{"version":3,"sources":["AuthLoading.tsx","AuthError.tsx","datasource/AnnotationServiceClient.ts","datasource/ServiceClient.ts","datasource/UserServiceClient.ts","datasource/AnalysisServiceClient.ts","datasource/InspectionServiceClient.ts","datasource/BlobImageServiceClient.ts","datasource/LabelMapServiceClient.ts","datasource/ServiceFactory.ts","AuthConfig.ts","components/AppContextProvider.tsx","components/Analyses.style.ts","datamodel/Constants.ts","components/Analyses.tsx","components/layout/Layout.style.ts","components/layout/Progress.tsx","components/layout/AppMenu.style.ts","components/layout/AppMenu.tsx","components/layout/Layout.tsx","components/Inspections.style.ts","components/Inspections.tsx","wgapp/WgAppInterface.js","datamodel/DamageMapping.ts","components/mltraininggrid/BitmapImage.ts","wgapp/wgApp.js","components/AnnotationDialog.style.ts","components/SelectedImage.style.tsx","components/mltraininggrid/Bitmap.ts","components/DialogController.tsx","datasource/model/Annotation.ts","util/annotationUtil.ts","components/ImageWithOverlay.style.ts","components/ImageWithOverlay.tsx","components/SelectedImage.tsx","components/CustomDialog.style.ts","components/CustomDialog.tsx","components/Thumbnail.style.ts","components/Thumbnail.tsx","components/LabelCategorySelect.tsx","components/mltraininggrid/MLTrainingGrid.tsx","components/EditImageDialog.tsx","components/AlertDialog.tsx","datamodel/ConditionMapping.ts","components/AnnotationDialog.tsx","reducers/annotationReducer.ts","components/OverlayFilters.style.tsx","components/OverlayFilters.tsx","datamodel/BlobDataModel.js","datamodel/DataModel.js","components/Analysis.style.ts","components/Analysis.tsx","components/report/Info.tsx","components/report/Annotation.style.ts","components/report/Annotation.tsx","components/report/Report.style.ts","components/report/Report.tsx","App.tsx","reportWebVitals.js","theme.ts","index.js"],"names":["authLoading","props","Box","m","inProgress","authError","error","BrowserAuthError","errorMessage","console","AnnotationServiceClient","client","userServiceClient","analysisServiceClient","imageIdMap","imageNameMap","batchToIdsCache","Map","this","analysisId","imageIds","getCurrentTenantId","tenantId","postRequest","toString","imageIdList","tagNameIdList","conditionRatingIdList","getRequest","damageId","undefined","Promise","resolve","reject","annotation","annotationId","imageName","getImageIdMap","get","toImageUuid","imageId","getImageNameMap","map","getImageBatchIdFor","imageBatchId","getImageIdsFrom","queryAnnotations","imageAnnotationDetails","annotations","forEach","details","concat","annotationDetails","filter","isUserCreated","getUserAnnotationsForAnalysis","userAnnotations","systemId","systemIdFrom","set","mapImageNameToImageId","length","Error","systemAnnotation","getUserAnnotationsFor","validAnnotations","updateImageMaps","imageBatch","images","idMap","image","imageBlobName","id","nameMap","cachedIds","push","substring","comment","tokens","split","PaiServiceClient","baseUrl","tokenProvider","apiKey","path","getRequestResponse","json","getToken","token","fetch","method","headers","API_KEY","RequestId","uuid","Authorization","body","JSON","stringify","response","byteLength","status","PaiUserServiceClient","userId","userInfo","AnalysisServiceClient","inspectionServiceClient","alexandraAnalysisId","analysisCache","cachedAnalysis","analysis","getAllInspectionIds","inspectionIds","allAnalysis","inspectionId","getAnalysisForInspection","getAnalysis","analysisDetails","imageBatchDetails","getAllAnalysis","onlyAlexandraAnalysis","a","isAlexandraAnalysis","cvsProjectId","InspectionServiceClient","getAllInspections","inspections","i","inspection","BlobImageServiceClient","twoFiftyPxEnding","highQualityEnding","getTenantId","restUrl","request","text","getImageUrl","link","file_response","blob","URL","getImage","createObjectURL","imageNames","all","getImageAsObjectUrl","convertImageNameToHq","convertImageNameTo250px","LabelMapServiceClient","damageShortName","getZipUrl","url","zippedBody","gzipSync","Uint8Array","buffer","postBinary","ServiceFactory","serviceClient","annotationServiceClient","imageServiceClient","labelMapServiceClient","process","log","getServiceClient","getUserServiceClient","getAnalysisServiceClient","getInspectionServiceClient","_serviceFactory","setTokenProvider","msalConfig","auth","clientId","authority","redirectUri","loginRequest","scopes","queryClient","PublicClientApplication","QueryClient","defaultOptions","queries","refetchOnWindowFocus","refetchIntervalInBackground","refetchOnMount","AppContext","createContext","useApp","useContext","AppContextProvider","useMsal","instance","accounts","account","useAccount","useState","wgApp","setWgApp","userAnnotationIds","setUserAnnotationIds","totalAnnotationCount","setTotalAnnotationCount","acquireTokenSilent","then","ar","catch","InteractionRequiredAuthError","acquireTokenRedirect","authresult","accessToken","serviceFactory","Provider","value","children","useStyles","makeStyles","theme","textDecoration","color","palette","primary","markedItem","paddingRight","spacing","paths","home","report","Analyses","classes","useParams","inspectionIdNumber","parseInt","analysesQuery","useQuery","enabled","onError","width","Card","CardContent","isSuccess","isFetching","data","List","dense","component","aria-label","to","className","ListItem","button","fontSize","ListItemText","title","userAnnotationsCount","secondary","description","appBar","display","linkAppBar","content","marginTop","progressContainer","position","right","Progress","Typography","variant","AppMenu","anchor","open","handleClose","handleLogout","anchorEl","anchorOrigin","vertical","horizontal","keepMounted","transformOrigin","onClose","MenuItem","onClick","Layout","margin","showProgress","showHighlightId","highlightId","setAnchorEl","Boolean","isReport","window","location","href","indexOf","AppBar","Toolbar","IconButton","event","currentTarget","edge","titleNode","documentTitle","document","renderTitle","mr","logout","mt","Inspections","inspectionsQuery","isError","ins","analysisCount","WgAppInterface","callback","dataModel","polygonId","damageCategoryString","overlayData","visibleCategories","annotationIds","damageCategories","damageCategoriesShort","DamageMappingError","mapFromBackendIdToModelName","damages","damagesWithCorrectId","d","damageName","damageNameLowerCase","toLowerCase","trim","includes","backendNameToModelName","mapFromModelNameToBackendId","modelName","backendName","modelNameToBackendName","damagesWithCorrectValue","ColorChannel","WgApp","canvas","gl","getContext","preserveDrawingBuffer","glContext_","wgContext","frameCount_","lastFps_","resourceCache_","wgResourceCache","cameraPosition_","vec3","fromValues","orbitCamera_","wOrbitCamera","setViewport","getCanvasWidth","getCanvasHeight","setOrbitPivot","setCameraPosition","setPerspective","setUpvector","setZoomSpeed","cameraActiveCounter_","primRender_","primRenderIdAsColor_","gizmo_","wGizmo","intersectionTolerance_","setGizmoMode","wGizmoMode","INACTIVE","readBackFbo_","readBackTexture_","readbackPixels_","height","selectedObject_","hoveredLabel_","maskFbo_","maskTexture_","transform_","mat4","create","primTransform_","vertexBuffer_","wgVertexBuffer","colorTexture_","wgTexture","labelTexture_","labelVisibiltyTexture_","create2D","R8","imageAnnotationTexture_","combinedOverlayFbo_","combinedLabelTexture_","shader_","wgShader","idshader_","maskShader_","combineOverlayShader_","meshUvMaskShader_","posDepthShader_","labelmapDamageCategoriesData_","damageOpacity_","visibleDamageCategories_","visibleDamageCategoriesBitmask_","cameraFeatures_","meshBuilder","wgMeshBuilder","quadVbo_","buildFullscreenQuad","vssrc","labelColors","getLabelColors","fssrc","createShaderProgram","Pos","Texcoord","onLeftClickCallback","onRightClickCallback","onDamageHoverCallback_","keyboardEventHandler_","KeyboardEventHandler","mouseEventHander_","MouseEventHandler","touchEventHandler_","TouchEventHandler","appInfo_","appName","appDeveloper","fps","pickingInfo_","object","_dataModel","init","scheduleRender_","lastTimeStamp","requestAnimationFrame","loop","timestamp","deltaTime","update","render","onComplete","loadMesh","opensfm","parse","gltfModel","GLTFLoader","worker","gltf","node","scene","nodes","transform","matrix","copy","translation","rotation","quat","scale","fromRotationTranslationScale","toZup","fromXRotation","Math","PI","multiply","mesh","material","primitives","vertexCount","attributes","POSITION","count","posAttr","normalAttr","NORMAL","uvAttr","TEXCOORD_0","desc","wgVertexDescriptor","VertexType","VT_VertexNormalUv3","vertexData","Float32Array","j","indices","indexType","wgIndexType","wgUnsignedShort","componentType","UNSIGNED_BYTE","wgUnsignedByte","UNSIGNED_INT","wgUnsignedInt","deleteVertexBuffer","createElementsVertexBuffer","STATIC_DRAW","getVertexLayout","getVertexSizeInBytes","pbrMetallicRoughness","baseColorTexture","deleteTexture","setActiveTexture","TEXTURE0","create2dFromImage","RGBA","Image","onload","colorMap","colormap","src","labelMaps","maps","textureInitialized","buf","view","DataView","hdrlen","getUint16","hdrStr","String","fromCharCode","getUint8","hdr","match","texSize","groups","TEXTURE1","create2DArray","RG8UI","pixeldata","Uint16Array","maxval","reduce","b","max","npyData","npyHdr","slice","nextAnnotationId","bind","texSubImage3D","TEXTURE_2D_ARRAY","RG_INTEGER","byteOffset","unbind","uploadDataToTexture","RED","fill","updateCombinedOverlayTexture","createFbo","wgPrimRender","addGridXZ","canvas_","addEventListener","getKeyboardEventHandler","keyDown","key","keyUp","getMouseEventHandler","onMouseDown","onMouseUp","mouseDownPos","offsetX","offsetY","onMouseMove","onMouseLeave","onMouseClick","onMouseDoubleClick","preventDefault","onMouseWheel","getTouchEventHandler","onTouchStart","onTouchEnd","onTouchCancel","onTouchMove","e","onMouseRightClick","wgFbo","RGBA8","attachTexture","createDepthStencilBuffer","posFbo_","posTexture_","RGBA32UI","imageOverlayFbo_","imageOverlayFboTexture_","isUpdated","fx","getNormX","fy","getNormY","pickingRay","getPickingRay","isLeftMouseDown","isDown","MouseButtons","LeftButton","prevHoverState","isHovering","prevDragState","isDragging","flush","updateFps","vp","getViewProjection","mvp","mvpprim","clearColor","clear","COLOR_BUFFER_BIT","DEPTH_BUFFER_BIT","enable","DEPTH_TEST","viewport","clearPrimitive","addGizmo","totalTransform","getOrientation","bindProgram","getTextureHandle","setTextureUniform","TEXTURE2","setUniformMat4fv","setUniform1f","setUniform1i","draw","TRIANGLES","unbindProgram","ev","pixels","readPixels","drawingBufferHeight","selectedObject","damageIndex","pickPosition","drawingBufferWidth","type","imagedata","labelValue","getDamageForMousePosition","timeSinceLastFpsMeasure","performance","now","round","getFov","gl_","resize","clearBufferuiv","COLOR","Uint32Array","pixelsPos","clientX_","clientY_","RGBA_INTEGER","posDepth","cameraFeature","instrument","acquisitioninfo","origin","georeference","perspectivecentre","coordinates","rot","exteriororientation","cameraMatrixWorld","cameraProj","perspective","focallength","pixelspacing","imagecolumns","imagerows","permute","invObliqueCameraMatrixWorld","invert","cameraMVP","damageCategoryIndex","imageData","renderImageOverlayOnMesh","pixeldataU8","labelmap","labelmapWidth","labelmapHeight","updateId","u","v","px","py","texData","computeWVPFromCamera","floor","TEXTURE3","resize2D","setUniform2f","Uint8ClampedArray","ImageData","feature","find","references","renderLabelmapFromCameraFeature","cameraFeatures","requestedWidth","requestedHeight","filteredFeatureNames","pixelCount","imageid","sort","sortedFeatureNames","getWidth","getHeight","catIndex","createElement","context","putImageData","pngdata","toDataURL","style","background","imageById","imageDataUrl","globalCompositeOperation","globalAlpha","drawImage","append","damageCategoryId","getAnnotaionImagesFromCameraFeatures","pos","invTransform","cameraPos","getPosition","cameraPosMeshFrame","vec4","transformMat4","approxNormal","sub","normalize","ndc","ndcDisplaced","wvp","depth","depthDisplaced","abs","depthDiff","renderLabelmapFromCameraImagename","createOrUpdateAnnotation","updateTexture","annotationsList","unique","Set","delete","damageCategory","size","opacity","showGizmo","ROTATE","getGizmoMode","visibleLabelsData","columns","main","flex","flexDirection","form","info","inputs","overflowY","boxSizing","loading","justifyContent","titleIcon","float","imgWithoutOverlay","imageContainer","imageControls","bottom","left","imageControl","marginRight","grey","alignItems","Bitmap","_size","_chunks","ceil","bit","chunkIndex","bitMask","totalWidth","grid","bitColumn","index","insideMap","isOutOfBounds","getGrid","unset","isSet","result","offset","mask","enabledIndices","AnnotationType","BitmapImage","bitmap","_width","_height","_bitmap","channel","All","x1","y1","x2","y2","minX","maxX","xPosition","factor","resultWidth","resultHeight","x","y","upperLeftX","upperLeftY","positionInOrig","newWidth","row","column","rowOffset","columnOffset","Placement","top","AnnotationBuilder","damageLevel","conditionRatingId","placement","damage","customCause","cause","setCauses","isCauseCustom","serviceId","created","Date","toISOString","standardCauseId","standardCause","userIdCreated","userIdModified","imageBatchName","imageDateTime","probabilityPctRounded","conditionRating","userCreated","placeId","tagId","probability","isCluster","oldAnnotation","finishNew","convertBoundingBoxToPlacement","boundingBox","imageWidth","imageHeight","decimals","parseFloat","toFixed","getDamageColor","wgLabelColors","replace","c","join","convertWgAppColorToRGBA","selected","border","ImageWithOverlay","overlay","scaleFactor","canvasRef","useRef","fullWidth","fullHeight","scaledHeight","scaledWidth","useEffect","changeColor","convertedColor","r","current","onLoaded","imageDataToImage","imageFromData","ref","SelectedImage","disableControls","disableSetPrimary","fetching","onEdit","onSetAsPrimary","isPrimary","CircularProgress","alt","p","Button","disabled","startIcon","closeButton","CustomDialog","maxWidth","scroll","Dialog","DialogTitle","container","primaryIcon","borderRadius","editIcon","backgroundColor","Thumbnail","onSelect","isMouseOver","setMouseOver","mb","onMouseOver","LabelCategorySelect","required","label","items","FormControl","InputLabel","Select","onChange","findIndex","target","MLTrainingGrid","backgroundImageUrl","mlMask","gridScale","uiScale","zoom","maxZoomFactor","zoomMax","drawMode","brushSize","overlayVisible","drawColor","setBitmapEmpty","backgroundImageRef","renderFlag","setRenderFlag","hoveredGridIndex","setHoveredGridIndex","gridWidth","gridHeight","selectedColor","uiHeight","uiWidth","shouldRender","setGridPoint","gridPointIndex","save","fillStyle","moveTo","beginPath","lineTo","closePath","restore","clearRect","zoomFactor","expVal","pow","zoomExp","xTranslation","yTranslation","bb","bbWidth","bbHeight","bbCenterX","bbCenterY","setTransform","enabledIndex","drawBoundingBox","drawGridLines","isEmpty","canvasWidth","canvasHeight","wSteps","hSteps","strokeStyle","lineWidth","stroke","onLoad","mousePosition","canvasRect","getBoundingClientRect","transformMatrix","getTransform","m11","m41","m42","clientX","clientY","getMousePosition","gridX","gridIndex","buttons","setGrid","unsetGrid","EditImageDialog","onSaved","onCancel","annotationType","saving","setSaving","setZoom","setMlMask","imageUrl","setImageUrl","setDrawMode","setBrushSize","isDrawingEmpty","setDrawingEmpty","isOverlayVisible","setOverlayVisible","setErrorMessage","storeAnnotation","newId","reset","updatedTextureNpy","getUVLabelmap","getLabelMapServiceClient","postLabelMap","stored","createOverlay","scaledBitmap","overlayScaleFactor","scaleUp","rgbaData","toRGBAData","getImageServiceClient","overlayImage","getAnnotationOverlay","bitmapImage","fromRGBAData","Red","scaleDown","code","increaseSlider","decreaseSlider","removeEventListener","setFunc","min","step","DialogContent","DialogActions","Tooltip","sizes","getBrushSizes","FormControlLabel","control","Checkbox","icon","checkedIcon","checked","name","Grid","item","xs","Slider","marks","newValue","New","overlayDataNew","createAnnotation","User","System","updateAnnotationInImage","Unknown","pr","pb","align","AlertDialog","onSetOpen","onYes","onNo","yesLabel","noLabel","aria-labelledby","aria-describedby","autoFocus","mapToBackendRatingId","ratings","validRatings","rating","commonQueryId","AnnotationDialog","state","dispatch","onDialogClose","onEditImage","alertDialogOpen","setAlertDialogOpen","handleDialogClosed","isReady","damagesQuery","conditionRatingsQuery","imageQuery","annotationQuery","onSaveClicked","selectedDamage","userIdQuery","tenantIdQuery","primaryImageId","payload","builder","getPlacement","causeCustom","causesQuery","selectedCause","buildAndSaveAnnotation","errorMsg","newAnnotation","buildNewAnnotation","saveAnnotation","finishUpdate","saveMutation","mutate","onSuccess","deleteAnnotationFromBackendAndModel","deleteMutation","success","deleteAnnotationFromModel","deleteAnnotation","getTotalAnnotationCount","editImage","damageType","stack","isPrimaryImage","selectedImageName","primaryImage","primaryImageName","calcPlacement","calcDamageColor","sliderMarks","getTitle","selectedImageQuery","selectedImage","toLocaleString","s","onSetDamageLevel","onDamageCategorySelect","onDamageCauseSelect","TextField","Switch","multiline","rows","pl","deleting","initialAnnotationState","annotationReducer","action","DialogController","annotationDialogOpen","onUpdateSelectedObject","onSetAnnotationDialogOpen","editDialogOpen","setEditDialogOpen","editImageName","setEditImageName","editAnalysisId","setEditAnalysisId","editAnnotationId","setEditAnnotationId","editDamageCategory","setEditDamageCategory","editAnnotationType","setEditAnnotationType","useReducer","setAnnotationType","resetStateAndQueries","revokeObjectURL","revokeImageUrls","invalidateQueries","getUserId","getAnnotationService","getDamages","getConditionRatings","primaryImageQuery","getUserAnnotationsMapForAnalysis","fetchedIds","Array","from","keys","isNew","primaryImageNameQuery","mapImageIdToImageName","getImagesAsObjectUrls","convertImageNamesTo250px","getCausesFor","useMutation","setEditImageState","filters","checkbox","toggle","labelColor","OverlayFilters","visibleDamages","setVisibleDamages","setOpacity","expanded","setExpanded","gizmoVisible","setGizmoVisible","reviewedVisible","setReviewedVisible","unreviewedVisible","setUnreviewedVisible","getDamageOpacity","getDamageCategoryVisibility","category","visible","setDamageOpacity","setGizmoVisibility","showAllAnnotations","hideAnnotations","showAnnotations","hideAllAnnotations","update3dModel","cats","splice","setDamageCategoryVisibility","updateUIState","iv","getLabel","toggleCategory","BlobDataModel","damageShort","getGltfModelUrl","resolvedLabelmaps","getZipLabelMapUrl","arrayBuffer","gunzipSync","getOpenSfmModelUrl","_convertBlobToBase64","fileReader","FileReader","onerror","readAsDataURL","model","Analysis","updateHighlightId","setSelectedObject","setImageData","setAnnotationDialogOpen","analysisIdNumber","useMemo","setHighlightId","oncontextmenu","fetchUserAnnotationIds","wgAppLocal","setDataModel","setLeftClickHandler","clickedObj","getAnnotationImages","setRightClickHandler","getImagesForNewAnnotation","setDamageHoverCallback","highlightedObj","resizeCanvas","innerWidth","innerHeight","Info","page","pageBreakAfter","card","boxShadow","header","padding","overview","mainImg","maxHeight","overviewImg","Annotation","CardHeader","subheader","subtitle","mainImgSrc","overviewImgSrc","hideForPrint","showForPrint","frontPage","selectedPages","Report","setLoading","setTimeout","print","App","interactionType","InteractionType","Redirect","errorComponent","loadingComponent","QueryClientProvider","exact","reportWebVitals","onPerfEntry","Function","getCLS","getFID","getFCP","getLCP","getTTFB","createMuiTheme","blue","teal","ReactDOM","StrictMode","ThemeProvider","getElementById"],"mappings":"iVAIMA,EAAgC,SAACC,GACrC,OACE,eAACC,EAAA,EAAD,CAAKC,EAAG,EAAR,yCAAwCF,EAAMG,e,QCD5CC,EAA0C,SAACJ,GAC/C,OAAIA,EAAMK,iBAAiBC,IAEvB,eAACL,EAAA,EAAD,CAAKC,EAAG,EAAR,2BAA0BF,EAAMK,MAAME,iBAGxCC,QAAQH,MAAML,EAAMK,OAElB,mF,gHCHOI,EAAb,WAQE,WAAaC,EAAuBC,EAAsCC,GAA+C,yBAPxGF,YAOuG,OANvGC,uBAMuG,OALvGC,2BAKuG,OAJhHC,WAAyC,KAIuE,KAHhHC,aAA2C,KAGqE,KAFhHC,gBAAyC,IAAIC,IAGnDC,KAAKP,OAASA,EACdO,KAAKN,kBAAoBA,EACzBM,KAAKL,sBAAwBA,EAXjC,2FAcE,WAA+BM,EAAoBC,GAAnD,uFACiCF,KAAKN,kBAAkBS,qBADxD,cACQC,EADR,gBAEeJ,KAAKP,OAAOY,YAAY,+CAAiDD,EAASE,WAAY,CACzGL,WAAYA,EACZM,YAAaL,EACbM,cAAe,GACfC,sBAAuB,KAN3B,wFAdF,wHAwBE,oGACyBT,KAAKI,WAD9B,cACQA,EADR,gBAEeJ,KAAKP,OAAOiB,WAAW,oCAAsCN,EAASE,YAFrF,wFAxBF,8HA6BE,oGACyBN,KAAKI,WAD9B,cACQA,EADR,gBAEeJ,KAAKP,OAAOiB,WAAW,oDAAsDN,EAASE,YAFrG,wFA7BF,uHAkCE,WAA2BK,GAA3B,+EACmBC,IAAbD,EADN,gCAEiB,IAAIE,SACf,SAACC,EAASC,GACRD,EAAQ,OAJhB,+DAQ2Bd,KAAKI,WARhC,cAQUA,EARV,yBASWJ,KAAKP,OAAOiB,WAAW,wCAA0CN,EAASE,WAAa,mBAAqBK,EAASL,aAThI,iDAlCF,6IAgDE,WAAgDL,GAAhD,uFACyBD,KAAKI,WAD9B,cACQA,EADR,gBAEeJ,KAAKP,OAAOiB,WAAW,+CAAiDN,EAASE,WAAa,aAAeL,EAAWK,YAFvI,wFAhDF,0HAqDE,WAA6BU,GAA7B,uFACiChB,KAAKI,WADtC,cACQA,EADR,gBAEeJ,KAAKP,OAAOY,YAAY,wCAA0CD,EAASE,WAAYU,GAFtG,wFArDF,4HA0DE,WAA+BC,GAA/B,uFACiCjB,KAAKI,WADtC,cACQA,EADR,gBAEeJ,KAAKP,OAAOY,YAAY,0CAA4CD,EAASE,WAAa,eAAiBW,EAAaX,WAAY,IAFnJ,wFA1DF,iIAgEE,WAAoCL,EAAoBiB,GAAxD,iFACgBlB,KAAKmB,cAAclB,GADnC,uCACgDmB,IAAIpB,KAAKqB,YAAYH,KADrE,gDAhEF,mIAsEE,WAAoCjB,EAAoBqB,GAAxD,uFACoBtB,KAAKuB,gBAAgBtB,GADzC,cACQuB,EADR,yBAESA,EAAIJ,IAAIE,IAFjB,gDAtEF,2IA2EE,WAA4CrB,GAA5C,6FAC6BD,KAAKL,sBAAsB8B,mBAAmBxB,GAD3E,cACQyB,EADR,gBAEyB1B,KAAK2B,gBAAgBD,GAF9C,cAEQxB,EAFR,gBAGuCF,KAAK4B,iBAAiB3B,EAAYC,GAHzE,cAGQ2B,EAHR,OAIMC,EAA4B,GAChCD,EAAuBE,SAAQ,SAAAC,GAAO,OAAIF,EAAcA,EAAYG,OAAOD,EAAQE,sBALrF,kBAMSJ,EAAYK,QAAO,SAACH,GAAD,OAAaA,EAAQI,kBANjD,iDA3EF,4IAoFE,WAA+CnC,GAA/C,gGACgCD,KAAKqC,8BAA8BpC,GADnE,cACQqC,EADR,OAEQd,EAAM,IAAIzB,IAChBuC,EAAgBP,SAAQ,SAAAf,GACtB,IAAMuB,EAAW,EAAKC,aAAaxB,GAClB,KAAbuB,GACFf,EAAIiB,IAAIF,EAAUvB,MANxB,kBASSQ,GATT,gDApFF,iIAiGE,WAAoCvB,EAAoBiB,GAAxD,2FACwBlB,KAAK0C,sBAAsBzC,EAAYiB,GAD/D,eAEkBN,KADVU,EADR,iDAGW,IAHX,uBAK4BtB,KAAK4B,iBAAiB3B,EAAY,CAACqB,IAL/D,UAM6B,KADrBQ,EALR,QAMkBa,OANlB,0CAOW,IAPX,WAS6B,IAAvBb,EAAYa,OATlB,uBAUU,IAAIC,MAAM,wDAVpB,eAYQ5B,EAAac,EAAY,GAZjC,kBAaSd,EAAWkB,kBAAkBC,QAAO,SAACH,GAAD,OAAaA,EAAQI,kBAblE,iDAjGF,kIAkHE,WAAmCnC,EAAoBiB,EAAmB2B,GAA1E,gGACgC7C,KAAK8C,sBAAsB7C,EAAYiB,GADvE,UACQoB,EADR,OAGkC,KAD1BS,EAAmBT,EAAgBH,QAAO,SAACH,GAAD,OAAa,EAAKQ,aAAaR,KAAa,GAAKa,MAC5EF,OAHvB,yCAIW,MAJX,YAMMI,EAAiBJ,OAAS,GANhC,sBAOU,IAAIC,MAAM,0CAPpB,gCAUSG,EAAiB,IAV1B,gDAlHF,+HA+HE,WAA+B9C,GAA/B,oEAC4B,OAAtBD,KAAKH,aADX,yCAEWG,KAAKH,cAFhB,uBAIQG,KAAKgD,gBAAgB/C,GAJ7B,UAM4B,OAAtBD,KAAKH,aANX,sBAOU+C,MAAM,0BAPhB,gCASS5C,KAAKH,cATd,gDA/HF,yHA2IE,WAA6BI,GAA7B,oEAC0B,OAApBD,KAAKJ,WADX,yCAEWI,KAAKJ,YAFhB,uBAIQI,KAAKgD,gBAAgB/C,GAJ7B,UAM0B,OAApBD,KAAKJ,WANX,sBAOUgD,MAAM,0BAPhB,gCASS5C,KAAKJ,YATd,gDA3IF,2HAuJE,WAA8BK,GAA9B,wGACiCD,KAAKI,WADtC,cACQA,EADR,gBAE6BJ,KAAKL,sBAAsB8B,mBAAmBxB,GAF3E,cAEQyB,EAFR,gBAK2B1B,KAAKP,OAAOiB,WAAW,qDAAuDN,EAASE,WAAa,IAAMoB,EAAapB,YALlJ,OAKQ2C,EALR,OAMQC,EAASD,EAAWC,OAEpBC,EAAQ,IAAIpD,IAClBmD,EAAOnB,SAAQ,SAAAqB,GACbD,EAAMV,IAAI,EAAKpB,YAAY+B,EAAMC,eAA0BD,EAAME,OAG7DC,EAAU,IAAIxD,IACpBmD,EAAOnB,SAAQ,SAAAqB,GACbG,EAAQd,IAAIW,EAAME,GAAc,EAAKjC,YAAY+B,EAAMC,mBAGzDrD,KAAKJ,WAAauD,EAClBnD,KAAKH,aAAe0D,EAnBtB,iDAvJF,2HA6KE,WAA8B7B,GAA9B,uFAEoBd,KADZ4C,EAAYxD,KAAKF,gBAAgBsB,IAAIM,IAD7C,yCAGW8B,GAHX,uBAKiCxD,KAAKI,WALtC,cAKQA,EALR,gBAO2BJ,KAAKP,OAAOiB,WAAW,qDAAuDN,EAASE,WAAa,IAAMoB,EAAapB,YAPlJ,cAOQ2C,EAPR,OAQQC,EAASD,EAAWC,OAEtBhD,EAAqB,GACzBgD,EAAOnB,SAAQ,SAAAqB,GACblD,EAASuD,KAAKL,EAAME,OAEtBtD,KAAKF,gBAAgB2C,IAAIf,EAAcxB,GAdzC,kBAeSA,GAfT,iDA7KF,oHA+LE,8FACeF,KAAKN,kBAAkBS,qBADtC,wFA/LF,+EAoME,SAAoBe,GAClB,OAAOA,EAAUwC,UAAU,EAAG,MArMlC,0BAwME,SAAsB1C,GACpB,GAA2B,OAAvBA,EAAW2C,QACb,MAAO,GAET,IAAMC,EAAS5C,EAAW2C,QAAQE,MAAM,KACxC,OAAsB,IAAlBD,EAAOjB,OACF,GAEFiB,EAAO,OAhNlB,K,SCAaE,EAAb,WAKE,WAAaC,EAAiBC,GAA+B,yBAJ5CD,aAI2C,OAH3CE,OAAS,uCAGkC,KAF3CD,mBAE2C,EAC1DhE,KAAK+D,QAAUA,EACf/D,KAAKgE,cAAgBA,EAPzB,qFAUE,WAAyBE,GAAzB,iFACgBlE,KAAKmE,mBAAmBD,GADxC,uCAC+CE,QAD/C,gDAVF,8HAcE,WAAgCF,GAAhC,uFAE8BlE,KAAKgE,cAAcK,WAFjD,cAEQC,EAFR,yBAGSC,MAAMvE,KAAK+D,QAAUG,EAAM,CAChCM,OAAQ,MACRC,QAAS,CACPC,QAAS1E,KAAKiE,OACdU,UAAWC,cACXC,cAAe,UAAYP,MARjC,gDAdF,uHA2BE,WAA0BJ,EAAcY,GAAxC,yFAE8B9E,KAAKgE,cAAcK,WAFjD,cAEQC,EAFR,gBAGmCC,MAAMvE,KAAK+D,QAAUG,EAAM,CAC1DM,OAAQ,OACRC,QAAS,CACP,eAAgB,kCAChBC,QAAS1E,KAAKiE,OACdU,UAAWC,cACXC,cAAe,UAAYP,GAE7BQ,KAAMC,KAAKC,UAAUF,KAXzB,cAGQG,EAHR,gBAaeA,EAASb,OAbxB,wFA3BF,wHA2CE,WAAyBF,EAAcY,GAAvC,yFAC8B9E,KAAKgE,cAAcK,WADjD,cACQC,EADR,gBAGmCC,MAAMvE,KAAK+D,QAAUG,EAAM,CAC1DM,OAAQ,OACRC,QAAS,CACP,eAAgB,2BAChB,mBAAoB,WACpB,iBAAkB,GAAKK,EAAKI,WAC5BR,QAAS1E,KAAKiE,OACdU,UAAWC,cACXC,cAAe,UAAYP,GAE7BQ,KAAMA,IAbV,cAGQG,EAHR,yBAgB6B,MAApBA,EAASE,QAAuC,MAArBF,EAASE,QAhB7C,gDA3CF,gECHaC,EAAb,WAKE,WAAa3F,GAAwB,yBAJpBA,YAImB,OAH5BW,UAAoB,EAGQ,KAF5BiF,QAAkB,EAGxBrF,KAAKP,OAASA,EANlB,6FASE,wFACyB,IAAnBO,KAAKI,SADX,gCAE2BJ,KAAKP,OAAOiB,WAAW,qBAFlD,OAEU4E,EAFV,OAGItF,KAAKI,SAAWkF,EAASlF,SACzBJ,KAAKqF,OAASC,EAAShC,GAJ3B,gCAMStD,KAAKI,UANd,gDATF,oHAkBE,wFACuB,IAAjBJ,KAAKqF,OADX,gCAE2BrF,KAAKP,OAAOiB,WAAW,qBAFlD,OAEU4E,EAFV,OAGItF,KAAKI,SAAWkF,EAASlF,SACzBJ,KAAKqF,OAASC,EAAShC,GAJ3B,gCAMStD,KAAKqF,QANd,gDAlBF,6D,SCFaE,EAAb,WAIE,WAA6B9F,EAAwCC,EAAuD8F,GAAmD,yBAAlJ/F,SAAiJ,KAAzGC,oBAAyG,KAAlD8F,0BAAkD,KAH7JC,oBAA8B,IAG+H,KAF7JC,cAA8C,IAAI3F,IAFrE,sFAME,WAAyBE,GAAzB,mFAEyBW,KADjB+E,EAAiB3F,KAAK0F,cAActE,IAAInB,IADhD,yCAGW0F,GAHX,uBAKyB3F,KAAKI,WAL9B,cAKQA,EALR,gBAMyBJ,KAAKP,OAAOiB,WAAW,uCAAyCN,EAASE,WAAa,IAAML,EAAWK,YANhI,cAMQsF,EANR,OAOE5F,KAAK0F,cAAcjD,IAAIxC,EAAY2F,GAPrC,kBAQSA,GART,iDANF,0HAiBE,4GAC8B5F,KAAKwF,wBAAwBK,sBAD3D,OACQC,EADR,OAGMC,EAAiC,GAHvC,cAI6BD,GAJ7B,gEAIaE,EAJb,aAKkBD,EALlB,UAK2C/F,KAAKiG,yBAAyBD,GALzE,oBAKID,EALJ,KAK8B9D,OAL9B,wLAOS8D,GAPT,gEAjBF,6HA2BE,WAAgC9F,GAAhC,uFACgCD,KAAKkG,YAAYjG,GADjD,cACQkG,EADR,yBAESA,EAAgBC,kBAAkB9C,IAF3C,gDA3BF,mIAgCE,0FACStD,KADT,SAC0CA,KAAKqG,iBAD/C,iDACcC,sBADd,iEAhCF,mIAoCE,WAAsCN,GAAtC,uFACyBhG,KAAKI,WAD9B,cACQA,EADR,gBAEeJ,KAAKP,OAAOiB,WAAW,2CAA6CN,EAASE,WAAa,IAAM0F,EAAa1F,YAF5H,wFApCF,6IAyCE,WAA+C0F,GAA/C,6EACShG,KADT,SAC0CA,KAAKiG,yBAAyBD,GADxE,iDACcM,sBADd,iEAzCF,0FA6CE,SAA8BV,GAAiD,IAAD,OAC5E,OAAOA,EAASzD,QAAO,SAAAoE,GAAC,OAAI,EAAKC,oBAAoBD,QA9CzD,iCAiDE,SAA2BX,GACzB,OAAOA,EAASa,eAAiBzG,KAAKyF,sBAlD1C,sBAqDE,WACE,OAAOzF,KAAKN,kBAAkBS,yBAtDlC,KCDauG,EAAb,WAII,WAAYjH,EAAuBC,GAAuC,yBAHzDD,YAGwD,OAFxDC,uBAEwD,EACrEM,KAAKP,OAASA,EACdO,KAAKN,kBAAoBA,EANjC,4FASI,oGAC2BM,KAAKI,WADhC,cACUA,EADV,yBAEWJ,KAAKP,OAAOiB,WAAW,kDAAoDN,EAASE,aAF/F,gDATJ,8HAcI,sGAC8BN,KAAK2G,oBADnC,cACUC,EADV,OAEUd,EAAgBc,EAAYzE,QAAO,SAAA0E,GAAC,OAAa,OAATA,EAAEvD,MAAa9B,KAAI,SAAAsF,GAC7D,OAAOA,EAAWxD,MAH1B,kBAKWwC,GALX,gDAdJ,mHAsBI,8FACiB9F,KAAKN,kBAAkBS,qBADxC,wFAtBJ,6DCEa4G,EAAb,WAME,WAAatH,EAAuBC,GAAuC,yBAL1DD,YAKyD,OAJzDC,uBAIyD,OAHzDsH,iBAAmB,aAGsC,KAFzDC,kBAAoB,mBAGnCjH,KAAKP,OAASA,EACdO,KAAKN,kBAAoBA,EAR7B,sFAWE,WAAmBO,EAAoBiB,GAAvC,mBAAAqF,EAAA,sEACyBvG,KAAKkH,cAD9B,cACQ9G,EADR,OAEQ+G,EAAU,0BAA4BlH,EAAa,UAAYiB,EAAY,WAAad,EAFhG,SAGwBJ,KAAKP,OAAO0E,mBAAmBgD,GAHvD,cAGQC,EAHR,yBAISA,EAAQC,QAJjB,gDAXF,yHAkBE,uGACSrH,KAAKN,kBAAkBS,sBADhC,gDAlBF,mHA0BE,WAAgBF,EAAoBoD,GAApC,iBAAAkD,EAAA,sEACqBvG,KAAKsH,YAAYrH,EAAYoD,GADlD,cACQkE,EADR,gBAE8BhD,MAAMgD,EAAM,CACtC/C,OAAQ,QAHZ,cAEQgD,EAFR,yBAKSA,EAAcC,QALvB,gDA1BF,iIAkCE,WAA2BxH,EAAoBoD,GAA/C,SAAAkD,EAAA,kEACSmB,IADT,SACmC1H,KAAK2H,SAAS1H,EAAYoD,GAD7D,iDACauE,gBADb,iEAlCF,mIAsCE,WAAoC3H,EAAoB4H,GAAxD,4FACehH,QAAQiH,IAAID,EAAWrG,IAAX,uCAAe,WAAMqF,GAAN,SAAAN,EAAA,sEAAiB,EAAKwB,oBAAoB9H,EAAY4G,GAAtD,mFAAf,wDAD3B,mFAtCF,2FA0CE,SAA4B3F,GAC1B,OAAOlB,KAAKqB,YAAYH,GAAalB,KAAKiH,oBA3C9C,mCA8CE,SAA6BY,GAAiC,IAAD,OAC3D,OAAOA,EAAWrG,KAAI,SAAAN,GAAS,OAAI,EAAK8G,qBAAqB9G,QA/CjE,qCAkDE,SAA+BA,GAC7B,OAAOlB,KAAKqB,YAAYH,GAAalB,KAAKgH,mBAnD9C,sCAsDE,SAAgCa,GAAiC,IAAD,OAC9D,OAAOA,EAAWrG,KAAI,SAAAN,GAAS,OAAI,EAAK+G,wBAAwB/G,QAvDpE,yBA0DE,SAAoBA,GAClB,OAAOA,EAAUwC,UAAU,EAAG,QA3DlC,K,SCCawE,EAAb,WAIE,WAAazI,EAAuBC,GAAuC,yBAH1DD,YAGyD,OAFzDC,uBAEyD,EACxEM,KAAKP,OAASA,EACdO,KAAKN,kBAAoBA,EAN7B,iFASE,WAAcO,EAAoBkI,GAAlC,eAAA5B,EAAA,sEACyBvG,KAAKkH,cAD9B,cACQ9G,EADR,yBAES,0BAA4BH,EAAa,oBAAsBkI,EAAkB,WAAa/H,GAFvG,gDATF,uHAcE,WAAiBH,EAAoBkI,GAArC,eAAA5B,EAAA,sEACyBvG,KAAKkH,cAD9B,cACQ9G,EADR,yBAES,0BAA4BH,EAAa,uBAAyBkI,EAAkB,WAAa/H,GAF1G,gDAdF,yHAmBE,uGACSJ,KAAKN,kBAAkBS,sBADhC,gDAnBF,uHAuBE,WAA0BF,EAAoBkI,EAAyBrD,GAAvE,yFACoB9E,KAAKoI,UAAUnI,EAAYkI,GAD/C,cACQE,EADR,OAEQC,EAAaC,YAAS,IAAIC,WAAW1D,IAAO2D,OAFpD,kBAGSzI,KAAKP,OAAOiJ,WAAWL,EAAKC,IAHrC,gDAvBF,kECEaK,EAAb,WAaE,aAAuB,yBAVN5E,aAUK,OATd6E,mBAAgChI,EASlB,KARdlB,uBAAwCkB,EAQ1B,KAPdiI,6BAAoDjI,EAOtC,KANdjB,2BAAgDiB,EAMlC,KALdoD,mBAAgCpD,EAKlB,KAJd4E,6BAAoD5E,EAItC,KAHdkI,wBAA8ClI,EAGhC,KAFdmI,2BAAgDnI,EAKtD,IACMmD,EAAUiF,8CAOhBzJ,QAAQ0J,IAAI,2BACZjJ,KAAK+D,QAAUA,EAzBnB,oDA4BE,SAAyBC,GACvBhE,KAAKgE,cAAgBA,IA7BzB,kCAgCE,WACE,QAA2BpD,IAAvBZ,KAAKgE,cACP,MAAM,IAAIpB,MAAM,4BAKlB,YAHqChC,IAAjCZ,KAAK6I,0BACP7I,KAAK6I,wBAA0B,IAAIrJ,EAAwBQ,KAAKkJ,mBAAoBlJ,KAAKmJ,uBAAwBnJ,KAAKoJ,6BAEjHpJ,KAAK6I,0BAvChB,8BA0CE,WACE,QAA2BjI,IAAvBZ,KAAKgE,cACP,MAAM,IAAIpB,MAAM,4BAKlB,YAH2BhC,IAAvBZ,KAAK4I,gBACP5I,KAAK4I,cAAgB,IAAI9E,EAAiB9D,KAAK+D,QAAS/D,KAAKgE,gBAExDhE,KAAK4I,gBAjDhB,kCAoDE,WACE,QAA2BhI,IAAvBZ,KAAKgE,cACP,MAAM,IAAIpB,MAAM,4BAKlB,YAH+BhC,IAA3BZ,KAAKN,oBACPM,KAAKN,kBAAoB,IAAI0F,EAAqBpF,KAAKkJ,qBAElDlJ,KAAKN,oBA3DhB,sCA8DE,WACE,QAA2BkB,IAAvBZ,KAAKgE,cACP,MAAM,IAAIpB,MAAM,4BAKlB,YAHmChC,IAA/BZ,KAAKL,wBACPK,KAAKL,sBAAwB,IAAI4F,EAAsBvF,KAAKkJ,mBAAoBlJ,KAAKmJ,uBAAwBnJ,KAAKqJ,+BAE7GrJ,KAAKL,wBArEhB,wCAwEE,WACE,QAA2BiB,IAAvBZ,KAAKgE,cACP,MAAM,IAAIpB,MAAM,4BAKlB,YAHqChC,IAAjCZ,KAAKwF,0BACPxF,KAAKwF,wBAA0B,IAAIkB,EAAwB1G,KAAKkJ,mBAAoBlJ,KAAKmJ,yBAEpFnJ,KAAKwF,0BA/EhB,mCAkFE,WACE,QAA2B5E,IAAvBZ,KAAKgE,cACP,MAAM,IAAIpB,MAAM,4BAKlB,YAHgChC,IAA5BZ,KAAK8I,qBACP9I,KAAK8I,mBAAqB,IAAI/B,EAAuB/G,KAAKkJ,mBAAoBlJ,KAAKmJ,yBAE9EnJ,KAAK8I,qBAzFhB,sCA4FE,WACE,QAA2BlI,IAAvBZ,KAAKgE,cACP,MAAM,IAAIpB,MAAM,4BAKlB,YAHmChC,IAA/BZ,KAAK+I,wBACP/I,KAAK+I,sBAAwB,IAAIb,EAAsBlI,KAAKkJ,mBAAoBlJ,KAAKmJ,yBAEhFnJ,KAAK+I,yBAnGhB,uBAsGE,SAAwB/E,GAItB,YAHsBpD,IAAlBoD,GACF2E,EAAeW,gBAAgBC,iBAAiBvF,GAE3C2E,EAAeW,oBA1G1B,KAAaX,EACaW,gBAAkB,IAAIX,E,aCRnCa,EAA4B,CACvCC,KAAM,CACJC,SAAU,uCACVC,UAAW,yEACXC,YAAa,MAIJC,EAAe,CAC1BC,OAAQ,CAAC,SAAU,0CCefC,GDZsB,IAAIC,IAAwBR,GCYpC,I,OAAIS,GAAY,CAClCC,eAAgB,CACdC,QAAS,CACPC,sBAAsB,EACtBC,6BAA6B,EAC7BC,gBAAgB,OAMTC,EAAaC,6BAA8B5J,GAE3C6J,EAAS,WACpB,OAAOC,qBAAWH,IAGPI,EAAqB,SAAC5L,GACjC,MAA+B6L,cAAvBC,EAAR,EAAQA,SAAUC,EAAlB,EAAkBA,SACZC,EAA8BC,iBAA2BpK,IAAhBkK,EAAS,GAAmBA,EAAS,GAAK,IACzF,EAA0BG,wBAA4BrK,GAAtD,mBAAOsK,EAAP,KAAcC,EAAd,KACA,EAAkDF,mBAAmB,IAArE,mBAAOG,EAAP,KAA0BC,EAA1B,KACA,EAAwDJ,mBAAiB,GAAzE,mBAAOK,EAAP,KAA6BC,EAA7B,KAEMvH,EAA+B,CACnCK,SAAS,WAAD,4BAAE,4BAAAkC,EAAA,yDACQ,OAAZwE,EADI,gCAEyC,IAAIlK,SAAQ,SAACC,EAASC,GACnE8J,EAASW,mBAAmB,CAAET,QAASA,EAASjB,OAAQD,EAAaC,SAClE2B,MAAK,SAACC,GAAD,OAA8B5K,EAAQ4K,MAC3CC,OAAM,SAACvM,IACFA,aAAiBwM,KAAgCxM,aAAiBC,MACpEwL,EAASgB,qBAAqB,CAAE/B,OAAQD,EAAaC,SAClD6B,OAAM,SAACvM,GACNG,QAAQH,MAAM,aAAcA,GAC5B2B,EAAO3B,YAVb,cAEA0M,EAFA,yBAeCA,EAAWC,aAfZ,aAiBF,IAAInJ,MAAM,qBAjBR,2CAAF,kDAAC,IAoBLoJ,EAAiCrD,EAAekC,SAAS7G,GAE/D,OACE,cAACuG,EAAW0B,SAAZ,CAAqBC,MAAO,CAAEnB,UAASF,WAAUmB,iBAAgBd,QAAOC,WAAUC,oBAAmBC,uBAAsBC,uBAAsBC,0BAAyBxB,eAA1K,SACGhL,EAAMoN,Y,yBC/DEC,EAVUC,aAAW,SAAAC,GAAK,MAAK,CAC5C/E,KAAM,CACJgF,eAAgB,OAChBC,MAAOF,EAAMG,QAAQpF,KAAKqF,SAE5BC,WAAY,CACVC,aAAcN,EAAMO,QAAQ,QCPnBC,EAAQ,CACnBC,KAAM,IACNnG,YAAa,eACboG,OAAQ,W,kBCUGC,EAAW,WAAO,IAAD,EAC5B,EAAoCxC,IAA5BM,EAAR,EAAQA,QAASiB,EAAjB,EAAiBA,eACXkB,EAAUd,IACRpG,EAAiBmH,cAAjBnH,aACFoH,EAA6BpH,EAAeqH,SAASrH,IAAiB,EAEtEsH,EAAgBC,YAA4B,CAAC,WAAYvH,GAAjC,sBAAgD,sBAAAO,EAAA,sEAAkByF,EAAe5C,2BAA2BnD,yBAAyBmH,GAArF,mFAC5E,CACEI,QAAqB,OAAZzC,IAA4C,IAAxBqC,EAC7BK,QAAS,WACPlO,QAAQ0J,IAAI,8BAIlB,OACE,cAACjK,EAAA,EAAD,CAAK0O,MAAO,IAAKzO,EAAG,EAApB,SACE,cAAC0O,EAAA,EAAD,UACE,cAACC,EAAA,EAAD,WACIN,EAAcO,WAAaP,EAAcQ,WACzC,sBAEA,qCACiC,IAA9BR,EAAcS,KAAKpL,OAAe,oBAAsB,WACzD,cAACqL,EAAA,EAAD,CAAMC,OAAK,EAACC,UAAU,MAAMC,aAAW,WAAvC,mBACGb,EAAcS,YADjB,aACG,EAAoBvM,KAAI,SAAC+E,EAAGM,GAAJ,aACvB,cAAC,IAAD,CAAMuH,GAAE,UAAKtB,EAAMlG,YAAX,YAA0BZ,EAA1B,YAA0CO,EAAEjD,IAAc+K,UAAWnB,EAAQ3F,KAArF,SACE,eAAC+G,EAAA,EAAD,CAAUC,QAAM,EAAhB,UACGvC,EAAe5C,2BAA2B5C,oBAAoBD,IAC7D,cAAC,IAAD,CACEiG,MAAM,UACN6B,UAAWnB,EAAQP,WACnB6B,SAAS,UAGb,cAACC,EAAA,EAAD,CAAc/B,QAAO,UAAKnG,EAAEmI,MAAP,aAAiBnI,EAAEjD,GAAnB,wBAA2BiD,EAAEoI,4BAA7B,aAA2B,EAAwBhM,OAAnD,KAA8DiM,UAAWrI,EAAEsI,kBATrChI,kB,4DCZlEuF,GAzBUC,aAAW,SAAAC,GAAK,MAAK,CAC5CwC,OAAQ,CACN,eAAgB,CACdC,QAAS,SAGbC,WAAY,CACVzC,eAAgB,OAChBC,MAAO,QACP,UAAW,CACTD,eAAgB,cAGpB0C,QAAS,CACP,eAAgB,CACdC,UAAW,IAGfC,kBAAmB,CACjBJ,QAAS,OACTK,SAAU,WACVC,MAAO/C,EAAMO,QAAQ,QCpBZyC,GAAW,WACtB,MAAoD7E,IAA5CW,EAAR,EAAQA,kBAAmBE,EAA3B,EAA2BA,qBAE3B,OACE,eAACiE,GAAA,EAAD,CAAYC,QAAQ,QAApB,uBACapE,EAAkBzI,OAAS,IAAM2I,M,oBCCnCc,GAPUC,aAAW,SAAAC,GAAK,MAAK,CAC5C/E,KAAM,CACJgF,eAAgB,OAChBC,MAAOF,EAAMG,QAAQpF,KAAKqF,aCOjB+C,GAAU,SAAC,GAAsE,IAApEC,EAAmE,EAAnEA,OAAQC,EAA2D,EAA3DA,KAAM7C,EAAqD,EAArDA,MAAO8C,EAA8C,EAA9CA,YAAaC,EAAiC,EAAjCA,aACpD3C,EAAUd,KAEhB,OACE,eAAC,KAAD,CACE9I,GAAG,cACHwM,SAAUJ,EACVK,aAAc,CACZC,SAAU,MACVC,WAAY,SAEdC,aAAW,EACXC,gBAAiB,CACfH,SAAU,MACVC,WAAY,SAEdN,KAAMA,EACNS,QAASR,EAbX,UAeE,cAACS,GAAA,EAAD,CAAUC,QAAS,kBAAMV,KAAzB,SACE,cAAC,IAAD,CAAMxB,GAAItB,EAAMlG,YAAayH,UAAWnB,EAAQ3F,KAAhD,2BAEF,cAAC8I,GAAA,EAAD,CAAUC,QAAS,kBAAMV,KAAzB,SACE,cAAC,IAAD,CAAMxB,GAAItB,EAAME,OAAQqB,UAAWnB,EAAQ3F,KAA3C,6BAEF,cAAC8I,GAAA,EAAD,CAAUC,QAAS,kBAAMT,KAAzB,SACE,cAAC,IAAD,CAAMzB,GAAItB,EAAMC,KAAMsB,UAAWnB,EAAQ3F,KAAzC,2BClBKgJ,GAAS,SAAC,GAAmF,IAAjFC,EAAgF,EAAhFA,OAAQC,EAAwE,EAAxEA,aAAcC,EAA0D,EAA1DA,gBAAiBC,EAAyC,EAAzCA,YAAaxE,EAA4B,EAA5BA,SACnEtB,EAAaJ,IAAbI,SACFqC,EAAUd,KAChB,EAAgCnB,mBAA6B,MAA7D,mBAAO6E,EAAP,KAAiBc,EAAjB,KACA,EAAqCzD,cAA7BnH,EAAR,EAAQA,aAAc/F,EAAtB,EAAsBA,WAChB0P,EAAOkB,QAAQf,GAMfF,EAAc,WAClBgB,EAAY,OASRE,GAAuD,IAA5CC,OAAOC,SAASC,KAAKC,QAAQ,UAoC9C,OACA,qCACE,cAACC,GAAA,EAAD,CAAQ/B,SAAS,QAAQf,UAAWnB,EAAQ4B,OAA5C,SACE,eAACsC,GAAA,EAAD,CAAS5B,QAAQ,QAAjB,UACE,cAAC6B,GAAA,EAAD,CACEf,QAvDW,SAACgB,GAClBV,EAAYU,EAAMC,gBAuDZC,KAAK,QACLhF,MAAM,UACN2B,aAAW,OAJb,SAME,cAAC,KAAD,MAEF,cAACoB,GAAA,EAAD,CAAYC,QAAQ,KAApB,SA9Cc,WAClB,IAAIiC,EAAuB,6BACvBC,EAAgB,GA6BpB,YA5BqB9Q,IAAjBoF,QAA6CpF,IAAfX,IAChCyR,EAAgB,cAChBD,EAAY,oBAEO7Q,IAAjBoF,QAA6CpF,IAAfX,IAChCyR,EAAgB,cAAgB1L,EAChCyL,EACE,qCACE,cAAC,IAAD,CAAMrD,GAAItB,EAAMlG,YAAayH,UAAWnB,EAAQ8B,WAAhD,yBACC,MAAQhJ,WAIMpF,IAAjBoF,QAA6CpF,IAAfX,IAChCyR,EAAgB,YAAczR,EAC9BwR,EACE,qCACE,cAAC,IAAD,CAAMrD,GAAE,UAAKtB,EAAMlG,YAAX,YAA0BZ,GAAgBqI,UAAWnB,EAAQ8B,WAArE,SAAkF,cAAgBhJ,IACjG,eAAiB/F,MAKpB6Q,IACFY,EAAgB,SAChBD,EAAY,iBAEdE,SAASjD,MAAQgD,EACVD,EAgBAG,KAEAnB,GACC,sBAAKpC,UAAWnB,EAAQiC,kBAAxB,UACGuB,GACC,cAAC1R,EAAA,EAAD,CAAK6S,GAAI,EAAT,SACE,cAACtC,GAAA,EAAD,CAAYC,QAAQ,QAApB,UACoB,IAAjBmB,EAAqB,OAASA,EAAc,OAInD,cAAC3R,EAAA,EAAD,UACE,cAAC,GAAD,SAIN,cAAC,GAAD,CACE0Q,OAAQI,EACRH,KAAMA,EACN7C,MAAOA,EACP8C,YAAa,kBAAMA,KACnBC,aAAc,kBA3EtBhF,EAASiH,cACTlC,YA8EA,cAAC5Q,EAAA,EAAD,CAAK+S,QAAenR,IAAX4P,EAAuB,EAAIA,EAApC,SACGrE,QC3GQC,GAPUC,aAAW,SAAAC,GAAK,MAAK,CAC5C/E,KAAM,CACJgF,eAAgB,OAChBC,MAAOF,EAAMG,QAAQpF,KAAKqF,aCOjBsF,GAAc,WAAO,IAAD,EAC/B,EAAoCvH,IAA5BM,EAAR,EAAQA,QAASiB,EAAjB,EAAiBA,eACXkB,EAAUd,KAEV6F,EAAmB1E,YAAqC,cAA7B,sBAA4C,sBAAAhH,EAAA,sEAAkByF,EAAe3C,6BAA6B1C,oBAA9D,mFAC7E,CACE6G,QAAqB,OAAZzC,EACT0C,QAAS,WACPlO,QAAQ0J,IAAI,iCAIhB,OACE,cAACjK,EAAA,EAAD,CAAK0O,MAAO,IAAKzO,EAAG,EAApB,SACE,cAAC0O,EAAA,EAAD,UACE,eAACC,EAAA,EAAD,WACKqE,EAAiBpE,WAAcoE,EAAiBC,UAAYD,EAAiBnE,WAG9E,cAACE,EAAA,EAAD,CAAMC,OAAK,EAACC,UAAU,MAAMC,aAAW,cAAvC,mBACG8D,EAAiBlE,YADpB,aACG,EAAuBvM,KAAI,SAAC2Q,EAAKtL,GAAN,OAC1B,cAAC,IAAD,CAAMuH,GAAE,UAAKtB,EAAMlG,YAAX,YAA0BuL,EAAI7O,IAAc+K,UAAWnB,EAAQ3F,KAAvE,SACE,cAAC+G,EAAA,EAAD,CAAUC,QAAM,EAAhB,SACE,cAACE,EAAA,EAAD,CAAc/B,QAAO,UAAKyF,EAAIzD,MAAT,aAAmByD,EAAI7O,GAAvB,cAA+B6O,EAAIC,cAAnC,KAAqDxD,UAAWuD,EAAItD,iBAF5ChI,QAJrD,0BAYCoL,EAAiBnE,YAAcmE,EAAiBC,SACjD,qC,8CC1CCG,GAAb,mGAQE,SAAqBC,GACnB,MAAM1P,MAAM,sBAThB,kCAkBE,SAAsB0P,GACpB,MAAM1P,MAAM,sBAnBhB,0BA2BE,SAAc2P,GACZ,MAAM3P,MAAM,sBA5BhB,6BAqCE,SAAiB4P,GACf,MAAM5P,MAAM,qBAtChB,kCA+CE,SAAsB3B,EAAcK,EAASmR,GAC3C,MAAM7P,MAAM,qBAhDhB,sCAyDE,SAA0B1B,EAAWuR,GACnC,MAAM7P,MAAM,qBA1DhB,qCAoEE,SAAyB1B,EAAWD,EAAcwR,EAAsBC,GACtE,MAAM9P,MAAM,qBArEhB,8BA+EE,SAAkB1B,EAAWuR,EAAsBC,GACjD,MAAM9P,MAAM,qBAhFhB,yCAuFE,SAA6B+P,GAC3B,MAAM/P,MAAM,qBAxFhB,6BAgGE,SAAiBgQ,GACf,MAAMhQ,MAAM,qBAjGhB,gCAuGE,WACE,MAAMA,MAAM,qBAxGhB,6BAgHE,SAAiBgQ,GACf,MAAMhQ,MAAM,qBAjHhB,gCAuHE,WACE,MAAMA,MAAM,qBAxHhB,8BAgIE,SAAkB3B,EAAcwR,GAC9B,MAAM7P,MAAM,qBAjIhB,8BAwIE,WACE,MAAMA,MAAM,qBAzIhB,qCAgJE,WACE,MAAMA,MAAM,uBAjJhB,K,UCEaiQ,GAAmB,CAAC,OAAQ,QAAS,2BAA4B,WAAY,SAC7EC,GAAwB,CAAC,OAAQ,OAAQ,OAAQ,OAAQ,QAGzDC,GAAb,2IAAwCnQ,QAgB3BoQ,GAA8B,SAACC,EAAmB3P,GAC3D,IAAM4P,EAAuBD,EAAQ9Q,QAAO,SAAAgR,GAAC,OAAI7P,IAAO6P,EAAE7P,MAC1D,GAAoC,IAAhC4P,EAAqBvQ,OACrB,MAAM,IAAIoQ,GAAmB,+BAAiCzP,EAAK,oCAAsC2P,GAE7G,GAAIC,EAAqBvQ,OAAS,EAC9B,MAAM,IAAIoQ,GAAmB,0CAA4CzP,EAAK,oCAAsC2P,GAExH,OAGJ,SAAgCG,GAC5B,IAAMC,EAAsBD,EAAWE,cAAcC,OACrD,GAA4B,SAAxBF,EACA,OAAOP,GAAsB,GAEjC,GAA4B,UAAxBO,EACA,OAAOP,GAAsB,GAEjC,GAAIO,EAAoBG,SAAS,UAC7BH,EAAoBG,SAAS,iBAC7B,OAAOV,GAAsB,GAEjC,GAA4B,aAAxBO,EACA,OAAOP,GAAsB,GAEjC,GAA4B,UAAxBO,EACA,OAAOP,GAAsB,GAEjC,MAAM,IAAIC,GAAmB,4CAA8CK,GArBpEK,CAAuBP,EAAqB,GAAGhH,QAoCnD,IAAMwH,GAA8B,SAACT,EAAmBU,GAC3D,IAAMC,EAWV,SAAgCR,GAC5B,GAAmB,SAAfA,EACA,OAAOP,GAAiB,GAE5B,GAAmB,SAAfO,EACA,OAAOP,GAAiB,GAE5B,GAAmB,SAAfO,EACA,OAAOP,GAAiB,GAE5B,GAAmB,SAAfO,EACA,OAAOP,GAAiB,GAE5B,GAAmB,SAAfO,EACA,OAAOP,GAAiB,GAE5B,MAAM,IAAIE,GAAmB,8CAAgDK,GA3BzDS,CAAuBF,GACrCG,EAA0Bb,EAAQ9Q,QAAO,SAAAgR,GAAC,OAAIS,EAAYN,gBAAkBH,EAAEjH,MAAMoH,iBAC1F,GAAuC,IAAnCQ,EAAwBnR,OACxB,MAAM,IAAIoQ,GAAmB,iCAAmCa,EAAc,oCAAsCX,GAExH,GAAIa,EAAwBnR,OAAS,EACjC,MAAM,IAAIoQ,GAAmB,4CAA8Ca,EAAc,oCAAsCX,GAEnI,OAAOa,EAAwB,GAAGxQ,I,IC7DjCyQ,G,mKCqBCC,G,oDACJ,WAAaC,GAAS,IAAD,sBACnB,eAEA,IAAMC,EAAKD,EAAOE,WAAW,SAAU,CAAEC,uBAAuB,IAEhE,EAAKC,WAAa,IAAIC,KAAUJ,EAAID,GACpC,EAAKC,GAAK,EAAKG,WAAWH,KAC1B,EAAKK,YAAc,EACnB,EAAKC,SAAW,EAChB,EAAKC,eAAiB,IAAIC,KAE1B,EAAKC,gBAAkBC,KAAKC,YAAY,GAAM,EAAK,IACnD,EAAKC,aAAe,IAAIC,KAAa,eACrC,EAAKD,aAAaE,YAAY,EAAKX,WAAWY,iBAAkB,EAAKZ,WAAWa,mBAChF,EAAKJ,aAAaK,cAAc,CAAC,GAAI,EAAG,IACxC,EAAKL,aAAaM,kBAAkB,EAAKT,iBACzC,EAAKG,aAAaO,eAAe,IACjC,EAAKP,aAAaQ,YAAYV,KAAKC,WAAW,EAAK,EAAK,IACxD,EAAKC,aAAaS,aAAa,GAC/B,EAAKC,qBAAuB,EAE5B,EAAKC,YAAc,KACnB,EAAKC,qBAAuB,KAC5B,EAAKC,OAAS,IAAIC,KAAO,IACzB,EAAKD,OAAOE,uBAAyB,GACrC,EAAKF,OAAOG,aAAaC,KAAWC,UAEpC,EAAKC,aAAe,KACpB,EAAKC,iBAAmB,KACxB,EAAKC,gBAAkB,IAAI3N,WAAWyL,EAAOvG,MAAQuG,EAAOmC,OAAS,GACrE,EAAKC,iBAAmB,EACxB,EAAKC,eAAiB,EAEtB,EAAKC,SAAW,KAChB,EAAKC,aAAe,KAEpB,EAAKC,WAAaC,KAAKC,SAEvB,EAAKC,eAAiBF,KAAKC,SAG3B,EAAKE,cAAgB,IAAIC,KAAe,MAAO,EAAKzC,YACpD,EAAK0C,cAAgB,IAAIC,KAAU,QAAS,EAAK3C,YACjD,EAAK4C,cAAgB,IAAID,KAAU,QAAS,EAAK3C,YACjD,EAAK6C,uBAAyB,IAAIF,KAAU,iBAAkB,EAAK3C,YACnE,EAAK6C,uBAAuBC,SAASjD,EAAGkD,GAAI,IAAK,KAAK,GAAM,GAE5D,EAAKC,wBAA0B,IAAIL,KAAU,aAAc,EAAK3C,YAChE,EAAKiD,oBAAsB,KAC3B,EAAKC,sBAAwB,KAE7B,EAAKC,QAAU,IAAIC,KAAS,SAAU,EAAKpD,YAC3C,EAAKqD,UAAY,IAAID,KAAS,WAAY,EAAKpD,YAC/C,EAAKsD,YAAc,IAAIF,KAAS,aAAc,EAAKpD,YACnD,EAAKuD,sBAAwB,IAAIH,KAAS,gBAAiB,EAAKpD,YAChE,EAAKwD,kBAAoB,IAAIJ,KAAS,eAAgB,EAAKpD,YAC3D,EAAKyD,gBAAkB,IAAIL,KAAS,iBAAkB,EAAKpD,YAE3D,EAAK0D,8BAAgC,GAErC,EAAKC,eAAiB,GACtB,EAAKC,yBAA2BnF,GAChC,EAAKoF,gCAAkC,IAEvC,EAAKC,gBAAkB,KAEvB,IAAMC,EAAc,IAAIC,KAAc,UAAW,EAAKhE,YACtD,EAAKiE,SAAWF,EAAYG,oBAAoB,QAEhD,IAmCMC,EAAK,4OAYLC,EAAc,EAAKC,iBAEnBC,EAAK,iUASOF,EAAY,GATnB,kCAUOA,EAAY,GAVnB,kCAWOA,EAAY,GAXnB,kCAYOA,EAAY,GAZnB,kCAaOA,EAAY,GAbnB,8sBAoJX,EAAKjB,QAAQoB,oBAAoBJ,EAAOG,EAAO,CAAEE,IAAK,EAAGC,SAAU,IACnE,EAAKpB,UAAUkB,oBAAoBJ,EA3FtB,yrCA2FsC,CAAEK,IAAK,EAAGC,SAAU,IACvE,EAAKnB,YAAYiB,oBAAoBJ,EAnDtB,szBAmDwC,CAAEK,IAAK,EAAGC,SAAU,IAC3E,EAAKlB,sBAAsBgB,oBAxMF,8GAMA,+9BAkMgE,CAAEC,IAAK,IAChG,EAAKhB,kBAAkBe,oBAAoBJ,EA1BhB,04BA0B8C,CAAEK,IAAK,EAAGC,SAAU,IAC7F,EAAKhB,gBAAgBc,oBArHL,mPAWA,yOA0GiD,CAAEC,IAAK,IAGxE,EAAKE,oBAAsB,KAC3B,EAAKC,qBAAuB,KAC5B,EAAKC,uBAAyB,KAE9B,EAAKC,sBAAwB,IAAIC,KACjC,EAAKC,kBAAoB,IAAIC,KAC7B,EAAKC,mBAAqB,IAAIC,KAE9B,EAAKC,SAAW,CACdC,QAAS,qBACTC,aAAc,mBACdC,IAAK,GAGP,EAAKC,aAAe,CAClBC,OAAQ,WAGV,EAAKC,WAAa,KAElB,EAAKC,OAEL,EAAKC,iBAAkB,EACvB,IAAIC,EAAgB,EAzSD,OAqTnBC,uBAXa,SAAPC,EAAQC,GACZ,IAAMC,EAAYD,EAAYH,GAC1B,EAAKK,OAAOD,EAAY,MAAU,EAAKL,mBACzC,EAAKO,OAAOH,GACZ,EAAKJ,iBAAkB,GAGzBC,EAAgBG,EAEhBF,sBAAsBC,MAnTL,E,2DAwTrB,WAA6B,OAAOna,KAAKkZ,wB,kCACzC,WAA0B,OAAOlZ,KAAKoZ,oB,kCACtC,WAA0B,OAAOpZ,KAAKsZ,qB,iEAEtC,WAAoB/G,GAApB,2BAAAhM,EAAA,6DAA+BiU,EAA/B,+BAA4C,aAC1Cxa,KAAK8Z,WAAavH,EADpB,SAEQvS,KAAKya,WAFb,OAGED,IAHF,gD,oHASA,2DAAAjU,EAAA,6DACQ2N,EAAKlU,KAAKqU,WAAWH,KAD7B,SAG+BlU,KAAK8Z,WAAWY,UAH/C,cAGE1a,KAAKmY,gBAHP,OAKEwC,aAAM3a,KAAK8Z,WAAWc,YAAaC,KAAY,CAAEC,QAAQ,IAASrP,MAAK,SAACsP,GACtE,IACIC,EADUD,EAAKE,MACFC,MAAM,GAEjBC,EAAYzE,KAAKC,SAEvB,GAAIqE,EAAKI,OACP1E,KAAK2E,KAAKF,EAAWH,EAAKI,YACrB,CACL,IAAME,EAAc1G,KAAK+B,SACnB4E,EAAWC,KAAK7E,SAChB8E,EAAQ7G,KAAKC,WAAW,EAAG,EAAG,GAChCmG,EAAKM,aACP1G,KAAKyG,KAAKC,EAAaN,EAAKM,aAE1BN,EAAKO,UACPC,KAAKH,KAAKE,EAAUP,EAAKO,UAEvBP,EAAKS,OACP7G,KAAKyG,KAAKI,EAAOT,EAAKS,OAExB/E,KAAKgF,6BAA6BP,EAAWI,EAAUD,EAAaG,GAGtE,IAAME,EAAQjF,KAAKC,SACnBD,KAAKkF,cAAcD,EAAOE,KAAKC,GAAK,GACpCpF,KAAKqF,SAAS,EAAKtF,WAAYkF,EAAOR,GAGtC,IADA,IAAIa,EAAOhB,EAAKgB,UACApb,IAATob,QACQpb,IAAToa,GAIJgB,GADAhB,EAAOA,EAAK7O,SAAS,IACT6P,KAWd,IATA,IAAMC,EAAWD,EAAKE,WAAW,GAAGD,SAE9BE,EAAcH,EAAKE,WAAW,GAAGE,WAAWC,SAASC,MACrDC,EAAUP,EAAKE,WAAW,GAAGE,WAAWC,SAASnQ,MACjDsQ,EAAaR,EAAKE,WAAW,GAAGE,WAAWK,OAAOvQ,MAClDwQ,EAASV,EAAKE,WAAW,GAAGE,WAAWO,WAAWzQ,MAElD0Q,EAAO,IAAIC,KAAmBC,KAAWC,mBAAoB,EAAK1I,WAAWH,MAC7E8I,EAAa,IAAIC,aAA2B,EAAdd,GAC3BtV,EAAI,EAAGA,EAAIsV,EAAatV,IAAK,CACpC,IAAK,IAAIqW,EAAI,EAAGA,EAAI,EAAGA,IACrBF,EAAW,EAAInW,EAAIqW,GAAKX,EAAQ,EAAI1V,EAAIqW,GAE1C,IAAK,IAAIA,EAAI,EAAGA,EAAI,EAAGA,IACrBF,EAAW,EAAInW,EAAI,EAAIqW,GAAKV,EAAW,EAAI3V,EAAIqW,GAEjD,IAAK,IAAIA,EAAI,EAAGA,EAAI,EAAGA,IACrBF,EAAW,EAAInW,EAAI,EAAIqW,GAAKR,EAAO,EAAI7V,EAAIqW,GAI/C,IAAMC,EAAUnB,EAAKE,WAAW,GAAGiB,QAE/BC,EAAYC,KAAYC,gBAU5B,GATIH,EAAQI,gBAAkBrJ,EAAGsJ,cAC/BJ,EAAYC,KAAYI,eACfN,EAAQI,gBAAkBrJ,EAAGwJ,eACtCN,EAAYC,KAAYM,eAG1B,EAAK9G,cAAc+G,qBACnB,EAAK/G,cAAcgH,2BAA2B3J,EAAG4J,YAAalB,EAAKmB,kBAAmB5B,EAAaS,EAAKoB,uBAAwBZ,EAAWD,EAAQjR,MAAO8Q,GAEtJf,EAASgC,qBAAqBC,iBAChC,EAAKnH,cAAcoH,gBACnB,EAAKpH,cAAcqH,iBAAiBlK,EAAGmK,UACvC,EAAKtH,cAAcuH,kBAAkBvD,EAAK7X,OAAO,GAAGE,MAAO8Q,EAAGqK,KAAMrK,EAAGqK,KAAMrK,EAAGsJ,eAAe,GAAO,OACjG,CACL,IAAMpa,EAAQ,IAAIob,MAClBpb,EAAMqb,OAAS,WACb,EAAK1H,cAAcoH,gBACnB,EAAKpH,cAAcqH,iBAAiBlK,EAAGmK,UACvC,EAAKtH,cAAcuH,kBAAkBlb,EAAO8Q,EAAGqK,KAAMrK,EAAGqK,KAAMrK,EAAGsJ,eAAe,GAAO,GACvF,EAAKjD,UAEP,IACE,EAAKT,WAAW4E,WAAWjT,MAAK,SAACkT,GAC/Bvb,EAAMwb,IAAMD,KAEd,MAAOvf,GACPG,QAAQH,MAAR,mCAA0CA,KAI9C,EAAK4a,iBAAkB,KA/F3B,SAkGqBha,KAAK8Z,WAAW+E,YAlGrC,OAwGE,IANMC,EAlGR,OAoGE9e,KAAK+X,8BAAgC,GACjCgH,GAAqB,EAGhBlY,EAAI,EAAGA,EAAIiM,GAAsBnQ,OAAQkE,IAEhD,GADMmY,EAAMF,EAAKhM,GAAsBjM,GAAGyM,eACjC,CAKP,IAJM2L,EAAO,IAAIC,SAASF,GACpBG,EAASF,EAAKG,UAAU,GAAG,GAE7BC,EAAS,GACJxY,EAAI,EAAGA,EAAIsY,EAAQtY,IAC1BwY,GAAUC,OAAOC,aAAaN,EAAKO,SAAS3Y,EAAI,KAG5C4Y,EAAMJ,EAAOK,MAAP,aAAa,kCAAb,qBACZC,EAAUF,EAAIG,OAETb,IACH/e,KAAKiX,cAAcmH,iBAAiBlK,EAAG2L,UACvC7f,KAAKiX,cAAckH,gBACnBne,KAAKiX,cAAc6I,cAAc5L,EAAG6L,MAAOJ,EAAQjS,MAAOiS,EAAQvJ,OAAQtD,GAAsBnQ,QAAQ,GACxGoc,GAAqB,GAGjBiB,EAAY,IAAIC,YAAYjB,EAAK,GAAKG,GACtCe,EAASF,EAAUG,QAAO,SAAC5Z,EAAG6Z,GAAQ,OAAOvE,KAAKwE,IAAI9Z,EAAG6Z,MAC/DpgB,KAAK+X,8BAA8BtU,KAAK,CAAE6c,QAAStB,EAAKuB,OAAQvB,EAAIwB,MAAM,EAAGrB,EAAS,IAAKzR,MAAOiS,EAAQjS,MAAO0I,OAAQuJ,EAAQvJ,OAAQ4J,UAAWA,EAAWS,iBAAkBP,EAAS,IAE1LlgB,KAAKiX,cAAcyJ,OACnBxM,EAAGyM,cAAczM,EAAG0M,iBAAkB,EAAG,EAAG,EAAG/Z,EAAG8Y,EAAQjS,MAAOiS,EAAQvJ,OAAQ,EAAGlC,EAAG2M,WAAY3M,EAAGsJ,cAAe,IAAIhV,WAAWwX,EAAUvX,OAAQuX,EAAUc,aAChK9gB,KAAKiX,cAAc8J,SAIvB/gB,KAAKkX,uBAAuB8J,oBAAoB9M,EAAG+M,IAAK/M,EAAGsJ,cAAe,IAAIhV,WAAW,OAAO0Y,KAAK,MAGrGlhB,KAAKmhB,6BAA6BnhB,KAAKiY,0BAEvCjY,KAAKga,iBAAkB,EA5IzB,iD,wEA+IA,WAAS,IAAD,OAENha,KAAKohB,YACLphB,KAAKyV,YAAc,IAAI4L,KAAa,kBAAmBrhB,KAAKqU,YAE5DrU,KAAKyV,YAAY6L,UAAU,GAAM,OAGjCthB,KAAKqU,WAAWkN,QAAQC,iBAAiB,WAAW,SAAClQ,GAAY,EAAKmQ,0BAA0BC,QAAQpQ,EAAMqQ,QAC9G3hB,KAAKqU,WAAWkN,QAAQC,iBAAiB,SAAS,SAAClQ,GAAY,EAAKmQ,0BAA0BG,MAAMtQ,EAAMqQ,QAE1G3hB,KAAKqU,WAAWkN,QAAQC,iBAAiB,aAAa,SAAClQ,GAAY,EAAKuQ,uBAAuBC,YAAYxQ,MAC3GtR,KAAKqU,WAAWkN,QAAQC,iBAAiB,WAAW,SAAClQ,GAAY,EAAKuQ,uBAAuBE,UAAUzQ,MAEvG,IAAM0Q,EAAe,EAAE,GAAI,GAC3BhiB,KAAKqU,WAAWkN,QAAQC,iBAAiB,aAAa,SAAClQ,GAAY0Q,EAAa,GAAK1Q,EAAM2Q,QAASD,EAAa,GAAK1Q,EAAM4Q,WAC5HliB,KAAKqU,WAAWkN,QAAQC,iBAAiB,WAAW,SAAClQ,GAAgB0Q,EAAa,KAAO1Q,EAAM2Q,SAAWD,EAAa,KAAO1Q,EAAM4Q,SAAW,EAAK5R,QAAQgB,MAE5JtR,KAAKqU,WAAWkN,QAAQC,iBAAiB,aAAa,SAAClQ,GAAY,EAAKuQ,uBAAuBM,YAAY7Q,MAC3GtR,KAAKqU,WAAWkN,QAAQC,iBAAiB,aAAa,SAAClQ,GAAY,EAAK6Q,YAAY7Q,MACpFtR,KAAKqU,WAAWkN,QAAQC,iBAAiB,cAAc,SAAClQ,GAAY,EAAKuQ,uBAAuBO,aAAa9Q,MAC7GtR,KAAKqU,WAAWkN,QAAQC,iBAAiB,SAAS,SAAClQ,GAAY,EAAKuQ,uBAAuBQ,aAAa/Q,MACxGtR,KAAKqU,WAAWkN,QAAQC,iBAAiB,YAAY,SAAClQ,GAAY,EAAKuQ,uBAAuBS,mBAAmBhR,MACjHtR,KAAKqU,WAAWkN,QAAQC,iBAAiB,SAAS,SAAClQ,GAAYA,EAAMiR,iBAAkB,EAAKV,uBAAuBW,aAAalR,MAEhItR,KAAKqU,WAAWkN,QAAQC,iBAAiB,cAAc,SAAClQ,GAAY,EAAKmR,uBAAuBC,aAAapR,MAC7GtR,KAAKqU,WAAWkN,QAAQC,iBAAiB,YAAY,SAAClQ,GAAY,EAAKmR,uBAAuBE,WAAWrR,MACzGtR,KAAKqU,WAAWkN,QAAQC,iBAAiB,eAAe,SAAClQ,GAAY,EAAKmR,uBAAuBG,cAActR,MAC/GtR,KAAKqU,WAAWkN,QAAQC,iBAAiB,aAAa,SAAClQ,GAAY,EAAKmR,uBAAuBI,YAAYvR,MAE3GtR,KAAKqU,WAAWkN,QAAQC,iBAAiB,eAAe,SAACsB,GAAQA,EAAEP,iBAAkB,EAAKV,uBAAuBkB,uBAAuB,K,uBAG1I,WACE,IAAM7O,EAAKlU,KAAKkU,GAChBlU,KAAKiW,aAAe,IAAI+M,KAAM,cAAehjB,KAAKqU,YAClDrU,KAAKkW,iBAAmB,IAAIc,KAAU,kBAAmBhX,KAAKqU,YAC9DrU,KAAKkW,iBAAiBkI,iBAAiBlK,EAAGmK,UAC1Cre,KAAKkW,iBAAiBiB,SAASjD,EAAG+O,MAAOjjB,KAAKqU,WAAWY,iBAAkBjV,KAAKqU,WAAWa,mBAAmB,GAAM,GACpHlV,KAAKiW,aAAaiN,cAAcljB,KAAKkW,kBACrClW,KAAKiW,aAAakN,yBAAyBnjB,KAAKqU,WAAWY,iBAAkBjV,KAAKqU,WAAWa,mBAC7FlV,KAAKiW,aAAa8K,SAElB/gB,KAAKojB,QAAU,IAAIJ,KAAM,SAAUhjB,KAAKqU,YACxCrU,KAAKqjB,YAAc,IAAIrM,KAAU,aAAchX,KAAKqU,YACpDrU,KAAKqjB,YAAYjF,iBAAiBlK,EAAGmK,UACrCre,KAAKqjB,YAAYlM,SAASjD,EAAGoP,SAAUtjB,KAAKqU,WAAWY,iBAAkBjV,KAAKqU,WAAWa,mBAAmB,GAAM,GAElHlV,KAAKojB,QAAQF,cAAcljB,KAAKqjB,aAChCrjB,KAAKojB,QAAQD,yBAAyBnjB,KAAKqU,WAAWY,iBAAkBjV,KAAKqU,WAAWa,mBACxFlV,KAAKojB,QAAQrC,SAEb/gB,KAAKuW,SAAW,IAAIyM,KAAM,UAAWhjB,KAAKqU,YAC1CrU,KAAKwW,aAAe,IAAIQ,KAAU,cAAehX,KAAKqU,YAEtDrU,KAAKwW,aAAa4H,iBAAiBlK,EAAGmK,UACtCre,KAAKwW,aAAaW,SAASjD,EAAG+O,MAAO,EAAG,GAAG,GAAM,GACjDjjB,KAAKuW,SAAS2M,cAAcljB,KAAKkW,kBACjClW,KAAKuW,SAAS4M,yBAAyB,EAAG,GAC1CnjB,KAAKuW,SAASwK,SAEd/gB,KAAKsX,oBAAsB,IAAI0L,KAAM,kBAAmBhjB,KAAKqU,YAC7DrU,KAAKuX,sBAAwB,IAAIP,KAAU,gBAAiBhX,KAAKqU,YACjErU,KAAKuX,sBAAsBJ,SAASjD,EAAG+O,MAAO,KAAM,MAAM,GAAM,GAEhEjjB,KAAKsX,oBAAoB4L,cAAcljB,KAAKuX,uBAC5CvX,KAAKsX,oBAAoByJ,SAEzB/gB,KAAKujB,iBAAmB,IAAIP,KAAM,kBAAmBhjB,KAAKqU,YAC1DrU,KAAKwjB,wBAA0B,IAAIxM,KAAU,qBAAsBhX,KAAKqU,YACxErU,KAAKwjB,wBAAwBrM,SAASjD,EAAG+O,MAAO,EAAG,GAAG,GAAM,GAC5DjjB,KAAKujB,iBAAiBL,cAAcljB,KAAKwjB,yBACzCxjB,KAAKujB,iBAAiBJ,yBAAyB,EAAG,GAClDnjB,KAAKujB,iBAAiBxC,W,oBAGxB,SAAQ1G,GACN,IAAIoJ,GAAY,EAEVC,EAAK1jB,KAAK6hB,uBAAuB8B,WACjCC,EAAK5jB,KAAK6hB,uBAAuBgC,WACjCC,EAAa9jB,KAAK8U,aAAaiP,cAAcL,EAAIE,GACjDI,EAAkBhkB,KAAK6hB,uBAAuBoC,OAAOC,KAAaC,YAElEC,EAAiBpkB,KAAK2V,OAAO0O,aAC7BC,EAAgBtkB,KAAK2V,OAAO4O,aA0BlC,OAxBkC,IAA9BvkB,KAAKwV,sBACPxV,KAAK2V,OAAO2E,OAAOwJ,EAAY,CAACJ,EAAIE,GAAKI,GAGvChkB,KAAK2V,OAAO0O,eAAiBD,GAAkBpkB,KAAK2V,OAAO4O,eAAiBD,IAC9Eb,GAAY,EACZzjB,KAAKga,iBAAkB,GAGrBha,KAAK2V,OAAO4O,cACdd,GAAY,EACZzjB,KAAKga,iBAAkB,GAEnBha,KAAK8U,aAAawF,OAAOD,EAAWra,KAAK6hB,uBAAwB7hB,KAAKyhB,0BAA2BzhB,KAAKyiB,yBACxGziB,KAAKwV,qBAAuB,EAC5BiO,GAAY,EACZzjB,KAAKga,iBAAkB,GAEvBha,KAAKwV,qBAAuB,EAIhCxV,KAAK6hB,uBAAuB2C,QAC5BxkB,KAAKyiB,uBAAuB+B,QACrBf,I,oBAGT,WACEzjB,KAAKykB,YAEL,IAAMC,EAAK1kB,KAAK8U,aAAa6P,oBACvBzQ,EAAKlU,KAAKkU,GAEV0Q,EAAMlO,KAAKC,SACXkO,EAAUnO,KAAKC,SAcrB,GAZAzC,EAAG4Q,WAAW,IAAM,IAAM,IAAM,GAEhC5Q,EAAG6Q,MAAM7Q,EAAG8Q,iBAAmB9Q,EAAG+Q,kBAClC/Q,EAAGgR,OAAOhR,EAAGiR,YAEbjR,EAAGkR,SAAS,EAAG,EAAGplB,KAAKqU,WAAWY,iBAAkBjV,KAAKqU,WAAWa,mBAEpEwB,KAAKqF,SAAS8I,EAASH,EAAI1kB,KAAK4W,gBAChC5W,KAAKyV,YAAY4P,iBACjBrlB,KAAKyV,YAAY6P,SAAStlB,KAAK2V,QAC/B3V,KAAKyV,YAAY8E,OAAOsK,GAEpB7kB,KAAK6W,cAAe,CACtB,IAAM0O,EAAiB7O,KAAKC,SAC5BD,KAAKqF,SAASwJ,EAAgBvlB,KAAK2V,OAAO6P,iBAAkBxlB,KAAKyW,YACjEC,KAAKqF,SAAS6I,EAAKF,EAAIa,GAGvBvlB,KAAKwX,QAAQiO,cAETzlB,KAAK+W,cAAc2O,qBACrB1lB,KAAK+W,cAAcqH,iBAAiBlK,EAAGmK,UACvCre,KAAK+W,cAAc2J,OACnB1gB,KAAKwX,QAAQmO,kBAAkB,eAAgB,IAE7C3lB,KAAKuX,sBAAsBmO,qBAC7B1lB,KAAKuX,sBAAsB6G,iBAAiBlK,EAAG0R,UAC/C5lB,KAAKuX,sBAAsBmJ,OAC3B1gB,KAAKwX,QAAQmO,kBAAkB,eAAgB,IAGjD3lB,KAAKwX,QAAQqO,iBAAiB,KAAMjB,GACpC5kB,KAAKwX,QAAQsO,aAAa,UAAW9lB,KAAKgY,gBAC1ChY,KAAKwX,QAAQuO,aAAa,mBAAoB/lB,KAAKsW,eACnDtW,KAAK6W,cAAcmP,KAAK9R,EAAG+R,WAC3BjmB,KAAKwX,QAAQ0O,gBAIblmB,KAAKiW,aAAayK,OAClBxM,EAAG4Q,WAAW,EAAK,EAAK,EAAK,GAC7B5Q,EAAG6Q,MAAM7Q,EAAG8Q,iBAAmB9Q,EAAG+Q,kBAElCjlB,KAAK0X,UAAU+N,cAEXzlB,KAAKiX,cAAcyO,qBACrB1lB,KAAKiX,cAAcmH,iBAAiBlK,EAAG2L,UACvC7f,KAAKiX,cAAcyJ,OACnB1gB,KAAK0X,UAAUiO,kBAAkB,eAAgB,IAE/C3lB,KAAKkX,uBAAuBwO,qBAC9B1lB,KAAKkX,uBAAuBkH,iBAAiBlK,EAAG0R,UAChD5lB,KAAKkX,uBAAuBwJ,OAC5B1gB,KAAK0X,UAAUiO,kBAAkB,0BAA2B,IAG9D3lB,KAAK0X,UAAUmO,iBAAiB,KAAMjB,GACtC5kB,KAAK0X,UAAUqO,aAAa,iBAAkB/lB,KAAKkY,iCACnDlY,KAAK6W,cAAcmP,KAAK9R,EAAG+R,WAC3BjmB,KAAK0X,UAAUwO,gBACflmB,KAAK6W,cAAckK,SACnB/gB,KAAKiW,aAAa8K,Y,uCAQtB,SAA2BoF,GACzB,IAAMjS,EAAKlU,KAAKqU,WAAWH,KAE3BlU,KAAKiW,aAAayK,OAClB,IAAM0F,EAAS,IAAI5d,WAAW,GAC9B0L,EAAGmS,WAAWF,EAAGlE,QAAS/N,EAAGoS,oBAAsB,EAAIH,EAAGjE,QAAS,EAAG,EAAGhO,EAAGqK,KAAMrK,EAAGsJ,cAAe4I,GACpGpmB,KAAKiW,aAAa8K,SAElB,IAAIwF,EAAiB,EAGfC,EAAcJ,EAAO,GAAK,EAQhC,OAPIA,EAAO,GAAK,GAAKI,EAAc1T,GAAsBnQ,SAA0F,IAA/E3C,KAAKiY,yBAAyB/G,QAAQ4B,GAAsB0T,KAC9HxmB,KAAK4Z,aAAaC,OAAS/G,GAAsB0T,GACjDD,EAAiBH,EAAO,IAAMA,EAAO,IAAM,IAAMA,EAAO,IAAM,MAE9DpmB,KAAK4Z,aAAaC,OAAS,iBAC3B0M,GAAkB,GAEbA,I,qBAOT,SAASJ,GACPnmB,KAAKymB,aAAaN,GAClB,IAAMjS,EAAKlU,KAAKqU,WAAWH,KAE3BlU,KAAKiW,aAAayK,OAClB,IAAM0F,EAAS,IAAI5d,WAAW,GAC9B0L,EAAGmS,WAAWF,EAAGlE,QAAS/N,EAAGoS,oBAAsB,EAAIH,EAAGjE,QAAS,EAAG,EAAGhO,EAAGqK,KAAMrK,EAAGsJ,cAAe4I,GACpGlS,EAAGmS,WAAW,EAAG,EAAGnS,EAAGwS,mBAAoBxS,EAAGoS,oBAAqBpS,EAAGqK,KAAMrK,EAAGsJ,cAAexd,KAAKmW,iBACnGnW,KAAKiW,aAAa8K,SAElB/gB,KAAKqW,gBAAkB,EAGvB,IAAMmQ,EAAcJ,EAAO,GAAK,EAC5BA,EAAO,GAAK,GAAKI,EAAc1T,GAAsBnQ,SAA0F,IAA/E3C,KAAKiY,yBAAyB/G,QAAQ4B,GAAsB0T,KAC9HxmB,KAAK4Z,aAAaC,OAAS/G,GAAsB0T,GACjDxmB,KAAKqW,gBAAkB+P,EAAO,IAAMA,EAAO,IAAM,IAAMA,EAAO,IAAM,MAEpEpmB,KAAK4Z,aAAaC,OAAS,iBAC3B7Z,KAAKqW,iBAAmB,GAIR,IAAd8P,EAAG5X,QAAgBvO,KAAK+Y,oBAC1B/Y,KAAK+Y,oBAAoB,CAAE4N,KAAM3mB,KAAK4Z,aAAaC,OAAQvW,GAAItD,KAAKqW,gBAAiBuQ,UAAW5mB,KAAKmW,kBAC9E,IAAdgQ,EAAG5X,QAAgBvO,KAAKgZ,sBACjChZ,KAAKgZ,qBAAqB,CAAE1V,GAAItD,KAAKqW,oB,yBAOzC,SAAa8P,GACX,IAAMU,EAAa7mB,KAAK8mB,0BAA0BX,GAC9CU,IAAe7mB,KAAKsW,gBACtBtW,KAAKsW,cAAgBuQ,EACrB7mB,KAAKga,iBAAkB,EACnBha,KAAKiZ,wBACPjZ,KAAKiZ,uBAAuB,CAAE3V,GAAIujB,O,uBAKxC,WACE7mB,KAAKuU,cACL,IAAMwS,GAA2BC,YAAYC,MAAQjnB,KAAKwU,UAAY,IACtE,GAAIuS,EAA0B,EAAK,CACjC,IAAMpN,EAAM3Z,KAAKuU,YAAcwS,EAC/B/mB,KAAKwU,SAAWwS,YAAYC,MAC5BjnB,KAAKuU,YAAc,EACnBvU,KAAKwZ,SAASG,IAAMkC,KAAKqL,MAAMvN,M,oBASnC,SAAQjM,EAAO0I,GACbpW,KAAKqU,WAAWkN,QAAQ7T,MAAQA,EAChC1N,KAAKqU,WAAWkN,QAAQnL,OAASA,EAEjCpW,KAAK8U,aAAaE,YAAYhV,KAAKqU,WAAWY,iBAAkBjV,KAAKqU,WAAWa,mBAChFlV,KAAK8U,aAAaO,eAAerV,KAAK8U,aAAaqS,UACnDnnB,KAAKqU,WAAW+S,IAAIhC,SAAS,EAAG,EAAG1X,EAAO0I,GAG1CpW,KAAKiW,aAAaoR,OAAO3Z,EAAO0I,GAChCpW,KAAKojB,QAAQiE,OAAO3Z,EAAO0I,GAE3BpW,KAAKmW,gBAAkB,IAAI3N,WAAWkF,EAAQ0I,EAAS,GAEvDpW,KAAKga,iBAAkB,I,0BAQzB,WACE,IAAM9F,EAAKlU,KAAKkU,GAGV0Q,EAAMlO,KAAKC,SACX4O,EAAiB7O,KAAKC,SAC5BD,KAAKqF,SAASwJ,EAAgBvlB,KAAK2V,OAAO6P,iBAAkBxlB,KAAKyW,YACjEC,KAAKqF,SAAS6I,EAAK5kB,KAAK8U,aAAa6P,oBAAqBY,GAG1DvlB,KAAKojB,QAAQ1C,OACbxM,EAAGoT,eAAepT,EAAGqT,MAAO,EAAG,IAAIC,YAAY,CAAC,EAAG,EAAG,EAAG,KACzDtT,EAAG6Q,MAAM7Q,EAAG+Q,kBACZ/Q,EAAGkR,SAAS,EAAG,EAAGplB,KAAKqU,WAAWY,iBAAkBjV,KAAKqU,WAAWa,mBAEpElV,KAAK8X,gBAAgB2N,cAErBzlB,KAAK8X,gBAAgB+N,iBAAiB,KAAMjB,GAC5C5kB,KAAK6W,cAAc6J,OACnB1gB,KAAK6W,cAAcmP,KAAK9R,EAAG+R,WAC3BjmB,KAAK8X,gBAAgBoO,gBACrBlmB,KAAK6W,cAAckK,SAEnB,IAAM0G,EAAY,IAAID,YAAY,GAElCtT,EAAGmS,WAAWrmB,KAAKoZ,kBAAkBsO,SAAUxT,EAAGoS,oBAAsB,EAAItmB,KAAKoZ,kBAAkBuO,SAAU,EAAG,EAAGzT,EAAG0T,aAAc1T,EAAGwJ,aAAc+J,GACrJznB,KAAKiW,aAAa8K,SAClB,IAAM8G,EAAW,IAAI5K,aAAawK,EAAUhf,QAE5C,OAAOmM,KAAKC,WAAWgT,EAAS,GAAIA,EAAS,GAAIA,EAAS,M,kCAO5D,SAAsBC,GAEpB,IAAMC,EAAaD,EAAcE,gBAAgBD,WAC3CE,EAASF,EAAWG,aAAaC,kBAAkBC,YACnDC,EAAMN,EAAWG,aAAaI,oBAE9BC,EAAoB7R,KAAKC,SACzB6R,EAAa9R,KAAKC,SAExBD,KAAK+R,YAAYD,EAAY,EAAK,EAAK,GAAK,KAC5CA,EAAW,GAAK,EAAIT,EAAWW,aAAeX,EAAWY,aAAeZ,EAAWa,cACnFJ,EAAW,IAAM,EAAIT,EAAWW,aAAeX,EAAWY,aAAeZ,EAAWc,WAEpF,IAAK,IAAIhiB,EAAI,EAAGA,EAAI,EAAGA,IACrB,IAAK,IAAIqW,EAAI,EAAGA,EAAI,EAAGA,IACrBqL,EAAkB,EAAI1hB,EAAIqW,GAAKmL,EAAI,EAAIxhB,EAAIqW,GAI/CqL,EAAkB,IAAMN,EAAO,GAC/BM,EAAkB,IAAMN,EAAO,GAC/BM,EAAkB,IAAMN,EAAO,GAG/B,IAAMa,EAAUpS,KAAK7B,WACnB,EAAG,EAAG,EAAG,EACT,GAAI,EAAG,EAAG,EACV,EAAG,GAAI,EAAG,EACV,EAAG,EAAG,EAAG,GAEX6B,KAAKqF,SAASwM,EAAmBA,EAAmBO,GAEpD,IAAMC,EAA8BrS,KAAKC,SACzCD,KAAKsS,OAAOD,EAA6BR,GASzC,IAAMU,EAAYvS,KAAKC,SAIvB,OAFAD,KAAKqF,SAASkN,EAAWT,EAAYO,GAE9BE,I,sCAYT,SAA0BnB,EAAe7mB,EAAcioB,EAAqBxW,GAAqC,IAAxB8H,EAAuB,uDAAV,aACpG,GAAI0O,EAAsB,GAAKA,GAAuBlpB,KAAK+X,8BAA8BpV,OACvF,OAAO,EAET,IAAMuR,EAAKlU,KAAKkU,GACViV,EAAYnpB,KAAKopB,yBAAyBtB,EAAepV,GACzDhF,EAAQyb,EAAUzb,MAClB0I,EAAS+S,EAAU/S,OACnBiT,EAAcF,EAAUpb,KAExBub,EAAWtpB,KAAK+X,8BAA8BmR,GAC9CK,EAAgBD,EAAS5b,MACzB8b,EAAiBF,EAASlT,OAE5BqT,EAAWxoB,EACf,GAAqB,OAAjBA,EACFwoB,EAAWH,EAAS7I,iBACpB6I,EAAS7I,wBAGT,IAAK,IAAI5Z,EAAI,EAAGA,EAAI2iB,EAAiBD,EAAe1iB,IAC9CyiB,EAAStJ,UAAUnZ,KAAO4iB,IAC5BH,EAAStJ,UAAUnZ,GAAK,GAI9B,IAAK,IAAIA,EAAI,EAAGA,EAAI6G,EAAQ0I,EAAQvP,IAAK,CACvC,IAAM6iB,GAA0B,IAArBL,EAAY,EAAIxiB,GAAWwiB,EAAY,EAAIxiB,EAAI,IAAM,MAC1D8iB,GAA8B,IAAzBN,EAAY,EAAIxiB,EAAI,GAAWwiB,EAAY,EAAIxiB,EAAI,IAAM,MAC9D+iB,EAAK/N,KAAKqL,MAAMwC,EAAIH,GACpBM,EAAKhO,KAAKqL,MAAMyC,EAAIH,GAGhB,IAANE,GAAmB,IAANC,IACfL,EAAStJ,UAAU6J,EAAKN,EAAgBK,GAAMH,GAKlD,IAAMK,EAAU,IAAIthB,WAAW8gB,EAAStJ,UAAUvX,OAAQ6gB,EAAStJ,UAAUc,YAU7E,OATA9gB,KAAKiX,cAAcyJ,OACnBxM,EAAGyM,cAAczM,EAAG0M,iBAAkB,EAAG,EAAG,EAAGsI,EAAqBK,EAAeC,EAAgB,EAAGtV,EAAG2M,WAAY3M,EAAGsJ,cAAesM,GACvI9pB,KAAKiX,cAAc8J,SACnB/gB,KAAKmhB,6BAA6BnhB,KAAKiY,0BAEvCjY,KAAKga,iBAAkB,EAEvBQ,IAEOiP,I,sCAST,SAA0B3B,EAAepV,GACvC,IAAMwB,EAAKlU,KAAKkU,GACV+U,EAAYjpB,KAAK+pB,qBAAqBjC,GACtCC,EAAaD,EAAcE,gBAAgBD,WAC3Cra,EAAQqa,EAAWa,aAAe,EAGlCxS,EAASyF,KAAKmO,MAAMjC,EAAWc,UAAY,GAEjD7oB,KAAKqX,wBAAwB+G,iBAAiBlK,EAAG+V,UAC5CjqB,KAAKqX,wBAAwBqO,mBAGhC1lB,KAAKqX,wBAAwB6S,SAASxX,EAAYhF,MAAOgF,EAAY0D,QAFrEpW,KAAKqX,wBAAwBF,SAASjD,EAAG+O,MAAOvQ,EAAYhF,MAAOgF,EAAY0D,QAAQ,GAAM,GAI/FpW,KAAKqX,wBAAwB2J,oBAAoB9M,EAAGqK,KAAMrK,EAAGsJ,cAAe9K,EAAY3E,MAExF/N,KAAKujB,iBAAiB8D,OAAO3Z,EAAO0I,GAEpCpW,KAAKujB,iBAAiB7C,OAEtBxM,EAAG4Q,WAAW,EAAG,EAAG,EAAG,GACvB5Q,EAAGkR,SAAS,EAAG,EAAG1X,EAAO0I,GACzBlC,EAAG6Q,MAAM7Q,EAAG8Q,iBAAmB9Q,EAAG+Q,kBAElCjlB,KAAK6X,kBAAkB4N,cAEvBzlB,KAAKqX,wBAAwB+G,iBAAiBlK,EAAG+V,UACjDjqB,KAAKqX,wBAAwBqJ,OAC7B1gB,KAAK6X,kBAAkB8N,kBAAkB,cAAe,GACxD3lB,KAAK6X,kBAAkBsS,aAAa,WAAYzc,EAAO0I,GACvDpW,KAAK6X,kBAAkBgO,iBAAiB,KAAMoD,GAE9CjpB,KAAK6W,cAAcmP,KAAK9R,EAAG+R,WAC3BjmB,KAAK6X,kBAAkBqO,gBAGvB,IAAMmD,EAAc,IAAIe,kBAAkB,EAAI1c,EAAQ0I,GAUtD,OANAlC,EAAGmS,WAAW,EAAG,EAAG3Y,EAAO0I,EAAQlC,EAAGqK,KAAMrK,EAAGsJ,cAAe6L,GAE9DrpB,KAAKujB,iBAAiBxC,SACtB/gB,KAAKqX,wBAAwB0J,SAEX,IAAIsJ,UAAUhB,EAAa3b,EAAO0I,K,+CAUtD,SAAmClV,EAAWgoB,EAAqBjoB,GACjE,IAAMqpB,EAAUtqB,KAAKmY,gBAAgBoS,MAAK,SAAAzH,GAAO,OAAgD,MAAxCA,EAAE0H,WAAW,GAAGniB,IAAIqX,MAAMxe,MACnF,QAAKopB,GAGEtqB,KAAKyqB,gCAAgCH,EAASpB,EAAqBjoB,K,2CAS5E,SAA+BK,EAAS4nB,EAAqBjoB,GAC3D,GAAIK,EAAUtB,KAAKmY,gBAAgBxV,OAAQ,CACzC,IAAM2nB,EAAUtqB,KAAKmY,gBAAgB7W,GACrC,OAAOtB,KAAKyqB,gCAAgCH,EAASpB,EAAqBjoB,M,6CAU9E,SAAiC6mB,EAAeoB,EAAqBjoB,GACnE,IAAMiT,EAAKlU,KAAKkU,GACV+U,EAAYjpB,KAAK+pB,qBAAqBjC,GAEtCC,EAAaD,EAAcE,gBAAgBD,WAC3Cra,EAAQmO,KAAKqL,MAAMa,EAAWa,aAAe,GAC7CxS,EAASyF,KAAKqL,MAAMa,EAAWc,UAAY,GACjD7oB,KAAKuW,SAAS8Q,OAAO3Z,EAAO0I,GAC5BpW,KAAKuW,SAASmK,OAEdxM,EAAG4Q,WAAW,EAAG,EAAG,EAAG,GACvB5Q,EAAG6Q,MAAM7Q,EAAG8Q,iBAAmB9Q,EAAG+Q,kBAClC/Q,EAAGkR,SAAS,EAAG,EAAG1X,EAAO0I,GACzBpW,KAAK2X,YAAY8N,cACbzlB,KAAKiX,cAAcyO,qBACrB1lB,KAAKiX,cAAcmH,iBAAiBlK,EAAG2L,UACvC7f,KAAKiX,cAAcyJ,OACnB1gB,KAAK2X,YAAYgO,kBAAkB,eAAgB,IAGrD3lB,KAAK2X,YAAYoO,aAAa,YAAamD,GACvCjoB,EACFjB,KAAK2X,YAAYoO,aAAa,uBAAwB9kB,GAEtDjB,KAAK2X,YAAYoO,aAAa,uBAAwB,GAExD/lB,KAAK2X,YAAYkO,iBAAiB,KAAMoD,GACxCjpB,KAAK6W,cAAcmP,KAAK9R,EAAG+R,WAC3BjmB,KAAK2X,YAAYuO,gBAEjB,IAAMlG,EAAY,IAAIoK,kBAAkB,EAAI1c,EAAQ0I,GACpDlC,EAAGmS,WAAW,EAAG,EAAG3Y,EAAO0I,EAAQlC,EAAGqK,KAAMrK,EAAGsJ,cAAewC,GAC9D,IAAMmJ,EAAY,IAAIkB,UAAUrK,EAAWtS,EAAO0I,GAElD,OADApW,KAAKuW,SAASwK,SACPoI,I,kDAWT,SAAsCuB,EAAgBxB,EAAqBjoB,EAAc0pB,EAAgBC,GAGvG,IAAM1W,EAAKlU,KAAKkU,GACZxG,EAAQ,GACR0I,EAAS,QACUxV,IAAnB+pB,IACFjd,EAAQid,QAEc/pB,IAApBgqB,IACFxU,EAASwU,GAGX,IAAM5K,EAAY,IAAIoK,kBAAkB,EAAI1c,EAAQ0I,GAEpDpW,KAAKuW,SAAS8Q,OAAO3Z,EAAO0I,GAC5BpW,KAAKuW,SAASmK,OAEdxM,EAAG4Q,WAAW,EAAG,EAAG,EAAG,GACvB5Q,EAAGkR,SAAS,EAAG,EAAG1X,EAAO0I,GACzBpW,KAAK2X,YAAY8N,cACbzlB,KAAKiX,cAAcyO,qBACrB1lB,KAAKiX,cAAcmH,iBAAiBlK,EAAG2L,UACvC7f,KAAKiX,cAAcyJ,OACnB1gB,KAAK2X,YAAYgO,kBAAkB,eAAgB,IAGrD3lB,KAAK2X,YAAYoO,aAAa,YAAamD,GAC3ClpB,KAAK2X,YAAYoO,aAAa,uBAAwB9kB,GAGtD,IADA,IAAM4pB,EAAuB,GACpBhkB,EAAI,EAAGA,EAAI6jB,EAAe/nB,OAAQkE,IAAK,CAC9CqN,EAAG6Q,MAAM7Q,EAAG8Q,iBAAmB9Q,EAAG+Q,kBAClC,IAAMgE,EAAYjpB,KAAK+pB,qBAAqBW,EAAe7jB,IAK3D,GAJA7G,KAAK2X,YAAYkO,iBAAiB,KAAMoD,GACxCjpB,KAAK6W,cAAcmP,KAAK9R,EAAG+R,WAC3B/R,EAAGmS,WAAW,EAAG,EAAG3Y,EAAO0I,EAAQlC,EAAGqK,KAAMrK,EAAGsJ,cAAewC,IAE9B,IAA5BA,EAAU9O,QAAQ,KAAa,CAEjC,IADA,IAAI4Z,EAAa,EACR5N,EAAI,EAAGA,EAAIxP,EAAQ0I,EAAQ8G,IACT,IAArB8C,EAAU,EAAI9C,IAChB4N,IAGJD,EAAqBpnB,KAAK,CAAEsnB,QAASL,EAAe7jB,GAAG2jB,WAAW,GAAGniB,IAAKyiB,WAAYA,KAG1F9qB,KAAK2X,YAAYuO,gBAEjBlmB,KAAKuW,SAASwK,SAEd8J,EAAqBG,MAAK,SAAUzkB,EAAG6Z,GAAK,OAAQA,EAAE0K,WAAavkB,EAAEukB,cAErE,IAAMG,EAAqB,GAK3B,OAJAJ,EAAqB9oB,SAAQ,SAACuoB,GAC5BW,EAAmBxnB,KAAK6mB,EAAQS,YAG3BE,I,0CAOT,SAA8BtY,GAC5B,IAAMuB,EAAKlU,KAAKkU,GAEVxG,EAAQ1N,KAAKiX,cAAciU,WAC3B9U,EAASpW,KAAKiX,cAAckU,YAElCnrB,KAAKkY,gCAAkC,EACvC,IAAK,IAAIrR,EAAI,EAAGA,EAAI8L,EAAkBhQ,OAAQkE,IAAK,CACjD,IAAMukB,EAAWtY,GAAsB5B,QAAQyB,EAAkB9L,IAC7DukB,GAAY,IACdprB,KAAKkY,iCAAoC,GAAKkT,GAIpC,IAAV1d,GAA0B,IAAX0I,IAInBpW,KAAKsX,oBAAoB+P,OAAO3Z,EAAO0I,GACvCpW,KAAKsX,oBAAoBoJ,OAEzBxM,EAAGkR,SAAS,EAAG,EAAG1X,EAAO0I,GAEzBlC,EAAG4Q,WAAW,EAAG,EAAG,EAAG,GACvB5Q,EAAG6Q,MAAM7Q,EAAG8Q,iBAAmB9Q,EAAG+Q,kBAClCjlB,KAAK4X,sBAAsB6N,cAEvBzlB,KAAKiX,cAAcyO,qBACrB1lB,KAAKiX,cAAcmH,iBAAiBlK,EAAG2L,UACvC7f,KAAKiX,cAAcyJ,OACnB1gB,KAAK4X,sBAAsB+N,kBAAkB,eAAgB,IAE3D3lB,KAAKkX,uBAAuBwO,qBAC9B1lB,KAAKkX,uBAAuBkH,iBAAiBlK,EAAG0R,UAChD5lB,KAAKkX,uBAAuBwJ,OAC5B1gB,KAAK4X,sBAAsB+N,kBAAkB,0BAA2B,IAG1E3lB,KAAK4X,sBAAsBmO,aAAa,iBAAkB/lB,KAAKkY,iCAC/DlY,KAAKsY,SAAS0N,KAAK9R,EAAG+R,WAEtBjmB,KAAK4X,sBAAsBsO,gBAC3BlmB,KAAKsX,oBAAoByJ,SAEzB/gB,KAAKga,iBAAkB,K,+BAQzB,SAAmBmP,EAAW7nB,GAC5B,IAAM2S,EAAStC,SAAS0Z,cAAc,UACtCpX,EAAOvG,MAAQyb,EAAUzb,MACzBuG,EAAOmC,OAAS+S,EAAU/S,OAC1B,IAAMkV,EAAUrX,EAAOE,WAAW,MAElCmX,EAAQC,aAAapC,EAAW,EAAG,GACnC,IAAMqC,EAAUvX,EAAOwX,UAAU,aAajC,OAXAxX,EAAOyX,MAAMC,WAAa,QAC1B3rB,KAAK8Z,WAAW8R,UAAUtqB,GAASmK,MAAK,SAACogB,GACvC,IAAMzoB,EAAQ,IAAIob,MAClBpb,EAAMqb,OAAS,WACb6M,EAAQQ,yBAA2B,cACnCR,EAAQS,YAAc,GACtBT,EAAQU,UAAU5oB,EAAO,EAAG,EAAG6Q,EAAOvG,MAAOuG,EAAOmC,QACpDzE,SAAS7M,KAAKmnB,OAAOhY,IAEvB7Q,EAAMwb,IAAMiN,KAEPL,I,iCAaT,SAAqBlZ,GACnBtS,KAAK+Y,oBAAsBzG,I,kCAS7B,SAAsBA,GACpBtS,KAAKgZ,qBAAuB1G,I,oCAS9B,SAAwBA,GACtBtS,KAAKiZ,uBAAyB3G,I,iCAQhC,SAAqBrR,EAAcwR,GACjC,IAAMyZ,EAAmBpZ,GAAsB5B,QAAQuB,GAEvD,OAAOzS,KAAKmsB,qCAAqCnsB,KAAKmY,gBAAiB+T,EAAkBjrB,K,uCAO3F,WAA8B,IAAD,OAErBmrB,EAAMpsB,KAAKymB,eAIXlB,EAAiB7O,KAAKC,SAC5BD,KAAKqF,SAASwJ,EAAgBvlB,KAAK2V,OAAO6P,iBAAkBxlB,KAAKyW,YAEjE,IAAM4V,EAAe3V,KAAKC,SACpB2V,EAAYtsB,KAAK8U,aAAayX,cAC9BC,EAAqBC,KAAK9V,SAEhCD,KAAKsS,OAAOqD,EAAc9G,GAE1BkH,KAAKC,cAAcF,EAAoB,CAACF,EAAU,GAAIA,EAAU,GAAIA,EAAU,GAAI,GAAMD,GAExFI,KAAKhR,MAAM+Q,EAAoBA,EAAoB,EAAMA,EAAmB,IAC5E,IAAMG,EAAe/X,KAAK+B,SAC1B/B,KAAKgY,IAAID,EAAcH,EAAoBJ,GAC3CxX,KAAKiY,UAAUF,EAAcA,GAI7B,IAAM9B,EAAuB,GAE7B7qB,KAAKmY,gBAAgBpW,SAAQ,SAAC+lB,GAC5B,IAAMgF,EAAML,KAAK9V,SACXoW,EAAeN,KAAK9V,SACpBqW,EAAM,EAAKjD,qBAAqBjC,GAEtC2E,KAAKC,cAAcI,EAAK,CAACV,EAAI,GAAIA,EAAI,GAAIA,EAAI,GAAI,GAAMY,GACvDP,KAAKhR,MAAMqR,EAAKA,EAAK,EAAMA,EAAI,IAC/B,IAAMG,EAAQH,EAAI,GAIlBL,KAAKC,cAAcK,EAAc,CAACX,EAAI,GAAKO,EAAa,GAAIP,EAAI,GAAKO,EAAa,GAAIP,EAAI,GAAKO,EAAa,GAAI,GAAMK,GACtHP,KAAKhR,MAAMsR,EAAcA,EAAc,EAAMA,EAAa,IAC1D,IAAMG,EAAiBH,EAAa,GAEhCG,EAAiBD,GAASpR,KAAKsR,IAAIL,EAAI,IAAM,IAAOjR,KAAKsR,IAAIL,EAAI,IAAM,IACzEjC,EAAqBpnB,KAAK,CAAEsnB,QAASjD,EAAc0C,WAAW,GAAGniB,IAAK+kB,UAAWH,EAAQC,OAI7FrC,EAAqBG,MAAK,SAAUzkB,EAAG6Z,GAAK,OAAQA,EAAEgN,UAAY7mB,EAAE6mB,aAEpE,IAAMnC,EAAqB,GAK3B,OAJAJ,EAAqB9oB,SAAQ,SAACuoB,GAC5BW,EAAmBxnB,KAAK6mB,EAAQS,YAG3BE,I,kCAST,SAAsBhqB,EAAcK,EAASmR,GAC3C,IAAMyZ,EAAmBpZ,GAAsB5B,QAAQuB,GACvD,IAA0B,IAAtByZ,EACF,MAAM,IAAItpB,MAAM,yBAA2B6P,GAG7C,OADkBzS,KAAKqtB,kCAAkC/rB,EAAS4qB,EAAkBjrB,K,sCAUtF,SAA0BC,EAAWuR,GACnC,IAAMyZ,EAAmBpZ,GAAsB5B,QAAQuB,GACvD,IAA0B,IAAtByZ,EACF,MAAM,IAAItpB,MAAM,yBAA2B6P,GAG7C,OADkBzS,KAAKqtB,kCAAkCnsB,EAAWgrB,K,qCAYtE,SAAyBhrB,EAAWD,EAAcwR,EAAsBC,GAAqC,IAAxB8H,EAAuB,uDAAV,aAE1F8P,EAAUtqB,KAAKmY,gBAAgBoS,MAAK,SAAAzH,GAAO,OAAgD,MAAxCA,EAAE0H,WAAW,GAAGniB,IAAIqX,MAAMxe,MAC7EgrB,EAAmBpZ,GAAsB5B,QAAQuB,GACvDzS,KAAKstB,yBAAyBhD,EAASrpB,EAAcirB,EAAkBxZ,EAAa8H,K,8BAWtF,SAAkBtZ,EAAWuR,EAAsBC,GAAqC,IAAxB8H,EAAuB,uDAAV,aAErE8P,EAAUtqB,KAAKmY,gBAAgBoS,MAAK,SAAAzH,GAAO,OAAgD,MAAxCA,EAAE0H,WAAW,GAAGniB,IAAIqX,MAAMxe,MAC7EgrB,EAAmBpZ,GAAsB5B,QAAQuB,GACvD,OAAOzS,KAAKstB,yBAAyBhD,EAAS,KAAM4B,EAAkBxZ,EAAa8H,K,8BAQrF,SAAkBvZ,EAAcwR,GAC9B,IAAMyB,EAAKlU,KAAKkU,GACVgV,EAAsBpW,GAAsB5B,QAAQuB,GAC1D,IAA6B,IAAzByW,EACF,MAAM,IAAItmB,MAAM,yBAA2B6P,GAS7C,IANA,IAAM6W,EAAWtpB,KAAK+X,8BAA8BmR,GAC9CK,EAAgBD,EAAS5b,MACzB8b,EAAiBF,EAASlT,OAE5BmX,GAAgB,EAEX1mB,EAAI,EAAGA,EAAI2iB,EAAiBD,EAAe1iB,IAC9CyiB,EAAStJ,UAAUnZ,KAAO5F,IAC5BqoB,EAAStJ,UAAUnZ,GAAK,EACxB0mB,GAAgB,GAIpB,GAAIA,EAAe,CAEjB,IAAMzD,EAAU,IAAIthB,WAAW8gB,EAAStJ,UAAUvX,OAAQ6gB,EAAStJ,UAAUc,YAC7E9gB,KAAKiX,cAAcyJ,OACnBxM,EAAGyM,cAAczM,EAAG0M,iBAAkB,EAAG,EAAG,EAAGsI,EAAqBK,EAAeC,EAAgB,EAAGtV,EAAG2M,WAAY3M,EAAGsJ,cAAesM,GACvI9pB,KAAKiX,cAAc8J,SACnB/gB,KAAKmhB,6BAA6BnhB,KAAKiY,6B,8BAQ3C,WAEE,IADA,IAAMuV,EAAkB,GACf3mB,EAAI,EAAGA,EAAIiM,GAAsBnQ,OAAQkE,IAAK,CACrD,IAAMyiB,EAAWtpB,KAAK+X,8BAA8BlR,GAC9C4mB,EAAS,IAAIC,IAAIpE,EAAStJ,WAEhCyN,EAAOE,OAAO,GACdH,EAAgB/pB,KAAK,CAAEmqB,eAAgB9a,GAAsBjM,GAAI+L,cAAc,aAAK6a,KAEtF,OAAOD,I,qCAOT,WACE,IAAIlR,EAAQ,EAOZ,OANAtc,KAAK+X,8BAA8BhW,SAAQ,SAACunB,GAC1C,IAAMmE,EAAS,IAAIC,IAAIpE,EAAStJ,WAEhCyN,EAAOE,OAAO,GACdrR,GAASmR,EAAOI,QAEXvR,I,8BAOT,WACE,OAAOtc,KAAKgY,iB,8BAOd,SAAkB8V,GAChB9tB,KAAKgY,eAAiB8V,EACtB9tB,KAAKga,iBAAkB,I,yCAOzB,SAA6BrH,GAC3B3S,KAAKiY,yBAA2BtF,EAChC3S,KAAKmhB,6BAA6BnhB,KAAKiY,0BACvCjY,KAAKga,iBAAkB,I,yCAOzB,WACE,OAAOha,KAAKiY,2B,2BAQd,SAAexF,GACb,IAAMyZ,EAAmBpZ,GAAsB5B,QAAQuB,GACvD,IAA0B,IAAtByZ,EACF,MAAM,IAAItpB,MAAM,yBAA2B6P,GAG7C,OAAOzS,KAAK+X,8BAA8BmU,GAAkB5L,U,gCAO9D,SAAoByN,IACA,IAAdA,EACF/tB,KAAK2V,OAAOG,aAAaC,KAAWiY,QAEpChuB,KAAK2V,OAAOG,aAAaC,KAAWC,UAEtChW,KAAKga,iBAAkB,I,gCAOzB,WACE,OAAOha,KAAK2V,OAAOsY,iBAAmBlY,KAAWC,W,6BAQnD,SAAiBpD,GAKf,IAJA,IAAMsB,EAAKlU,KAAKkU,GAEVga,EAAoB,IAAI1lB,WAAW,OAAO0Y,KAAK,KAE5Cra,EAAI,EAAGA,EAAI+L,EAAcjQ,OAAQkE,IAAK,CAC7C,IAAMvD,EAAK+J,SAASuF,EAAc/L,IAClC,GAAIvD,GAAM4qB,EAAkBvrB,OAC1B,MAAM,IAAIC,MAAM,8BAElBsrB,EAAkB5qB,GAAM,EAE1BtD,KAAKkX,uBAAuB8J,oBAAoB9M,EAAG+M,IAAK/M,EAAGsJ,cAAe0Q,GAG1EluB,KAAKmhB,6BAA6BnhB,KAAKiY,4B,gCAMzC,WACE,IAAM/D,EAAKlU,KAAKkU,GAEVga,EAAoB,IAAI1lB,WAAW,OACzCxI,KAAKkX,uBAAuB8J,oBAAoB9M,EAAG+M,IAAK/M,EAAGsJ,cAAe0Q,GAG1EluB,KAAKmhB,6BAA6BnhB,KAAKiY,4B,6BAQzC,SAAiBrF,GAIf,IAHA,IAAMsB,EAAKlU,KAAKkU,GAEVga,EAAoB,IAAI1lB,WAAW,OAChC3B,EAAI,EAAGA,EAAI+L,EAAcjQ,OAAQkE,IAAK,CAC7C,IAAMvD,EAAK+J,SAASuF,EAAc/L,IAClC,GAAIvD,GAAM4qB,EAAkBvrB,OAC1B,MAAM,IAAIC,MAAM,8BAElBsrB,EAAkB5qB,GAAM,IAE1BtD,KAAKkX,uBAAuB8J,oBAAoB9M,EAAG+M,IAAK/M,EAAGsJ,cAAe0Q,GAG1EluB,KAAKmhB,6BAA6BnhB,KAAKiY,4B,gCAMzC,WACE,IAAM/D,EAAKlU,KAAKkU,GAEVga,EAAoB,IAAI1lB,WAAW,OAAO0Y,KAAK,KACrDlhB,KAAKkX,uBAAuB8J,oBAAoB9M,EAAG+M,IAAK/M,EAAGsJ,cAAe0Q,GAG1EluB,KAAKmhB,6BAA6BnhB,KAAKiY,4B,4BAOzC,WACE,MAAO,CACL,oBACA,oBACA,oBACA,oBACA,yB,GApiDc5F,I,gFCKLjG,GApCUC,aAAW,SAAAC,GAAK,MAAK,CAC5C6hB,QAAS,CACPzgB,MAJU,KAKVqB,QAAS,QAEXqf,KAAM,CACJrf,QAAS,OACTsf,KAAM,EACNC,cAAe,UAEjBC,KAAM,CACJxf,QAAS,QAEXyf,KAAM,CACJH,KAAM,GAERI,OAAQ,CACNJ,KAAM,GAERnrB,OAAQ,CAENwrB,UAAW,OACXC,UAAW,cAEbC,QAAS,CACP7f,QAAS,OACT8f,eAAgB,SAChBnhB,MA7BU,KA8BV0I,OAAQ,KAEV0Y,UAAW,CACTC,MAAO,OACPniB,aAAcN,EAAMO,QAAQ,Q,UCTjBT,GAxBUC,aAAW,SAAAC,GAAK,MAAK,CAC5C0iB,kBAAmB,GAEnBC,eAAgB,CACd7f,SAAU,YAEZ8f,cAAe,CACbP,UAAW,aACXvf,SAAU,WACV+f,OAAQ,EACRC,KAAM,EACN1hB,MAAO,QAET2hB,aAAc,CACZC,YAAahjB,EAAMO,QAAQ,IAE7B+hB,QAAS,CACP7f,QAAS,OACT4c,WAAY4D,KAAK,KACjBV,eAAgB,SAChBW,WAAY,c,0CCpBVC,G,WAQJ,WAAa5B,GACX,GAD0B,yBAPnB6B,WAOkB,OANlBC,aAMkB,EACrB9B,GAAQ,EACV,MAAM,IAAIjrB,MAAM,uBAElB5C,KAAK0vB,MAAQ7B,EACb7tB,KAAK2vB,QAAU,IAAInnB,WAAWqT,KAAK+T,KAAK/B,EAAO,IAC/C,IAAK,IAAIhnB,EAAI,EAAGA,EAAI7G,KAAK2vB,QAAQhtB,OAAQkE,IACvC7G,KAAK2vB,QAAQ9oB,GAAK,E,sCAOtB,WACE,OAAO7G,KAAK0vB,Q,iBAOd,SAAKG,GACH,GAAIA,EAAM,GAAKA,GAAO7vB,KAAK0vB,MACzB,MAAM,IAAI9sB,MAAJ,yBAA4BitB,IAEpC,IAAMC,EAAajU,KAAKmO,MAAM6F,EAAM,GAC9BE,EAAO,SAAG,EAAMF,EAAM,GAC5B7vB,KAAK2vB,QAAQG,IAAeC,I,mBAO9B,SAAOF,GACL,GAAIA,EAAM,GAAKA,GAAO7vB,KAAK0vB,MACzB,MAAM,IAAI9sB,MAAJ,yBAA4BitB,IAEpC,IAAMC,EAAajU,KAAKmO,MAAM6F,EAAM,GAC9BE,EAAU,aAAO,EAAMF,EAAM,GACnC7vB,KAAK2vB,QAAQG,IAAeC,I,qBAU7B,SAAQF,EAAahC,EAAcmC,GAGlC,IAFA,IAAMC,EAAO,GACPC,EAAYL,EAAMG,EACfnpB,EAAI,EAAGA,EAAIgnB,EAAMhnB,IACxB,IAAK,IAAIqW,EAAI,EAAGA,EAAI2Q,EAAM3Q,IAAK,CAC7B,IAAMiT,EAAQN,EAAOhpB,EAAEmpB,EAAc9S,EAE/BkT,EAAYF,GADEC,EAAQH,GAEvBhwB,KAAKqwB,cAAcF,IAAUC,GAChCH,EAAKxsB,KAAK0sB,GAIhB,OAAOF,I,qBAST,SAAQJ,EAAahC,EAAcmC,GAAqB,IAAD,OACrDhwB,KAAKswB,QAAQT,EAAKhC,EAAMmC,GAAYjuB,SAAQ,SAAA8E,GAAC,OAC3C,EAAKpE,IAAIoE,Q,uBAUb,SAAUgpB,EAAahC,EAAcmC,GAAqB,IAAD,OACvDhwB,KAAKswB,QAAQT,EAAKhC,EAAMmC,GAAYjuB,SAAQ,SAAA8E,GAAC,OAC3C,EAAK0pB,MAAM1pB,Q,oBAQf,SAAQgpB,GACF7vB,KAAKwwB,MAAMX,GACb7vB,KAAKuwB,MAAMV,GAEX7vB,KAAKyC,IAAIotB,K,mBASb,SAAOA,GACL,GAAIA,EAAM,GAAKA,GAAO7vB,KAAK0vB,MACzB,MAAM,IAAI9sB,MAAJ,yBAA4BitB,IAEpC,IAAMC,EAAajU,KAAKmO,MAAM6F,EAAM,GAC9BE,EAAO,SAAG,EAAMF,EAAM,GAC5B,OAAgD,KAAxC7vB,KAAK2vB,QAAQG,GAAcC,K,sBAMrC,WACE,IAAK,IAAIlpB,EAAI,EAAGA,EAAI7G,KAAK2vB,QAAQhtB,OAAQkE,IACvC7G,KAAK2vB,QAAQ9oB,GAAK,I,oBAOtB,WACE,IAAK,IAAIA,EAAI,EAAGA,EAAI7G,KAAK2vB,QAAQhtB,OAAQkE,IACvC7G,KAAK2vB,QAAQ9oB,GAAK,M,4BAQtB,WAEE,IADA,IAAM4pB,EAAmB,GAChB5pB,EAAI,EAAGA,EAAI7G,KAAK2vB,QAAQhtB,OAAQkE,IACvC,GAAwB,IAApB7G,KAAK2vB,QAAQ9oB,GAGf,IADA,IAAM6pB,EAAa,EAAJ7pB,EACNqW,EAAI,EAAGA,EAAI,EAAGA,IAAK,CAC1B,IAAMyT,EAAI,SAAG,EAAKzT,GACdld,KAAK2vB,QAAQ9oB,GAAK8pB,GACpBF,EAAOhtB,KAAKitB,EAASxT,GAK7B,OAAOuT,I,qBAOT,WACE,OAAwC,IAAjCzwB,KAAK4wB,iBAAiBjuB,S,2BAO9B,SAAektB,GACd,OAAOA,EAAM,GAAKA,GAAO7vB,KAAK0vB,U,eJtK7B3b,O,aAAAA,I,iBAAAA,I,eAAAA,I,iBAAAA,I,cAAAA,Q,SKQO8c,GLGNC,G,WAeJ,WAAapjB,EAAe0I,GAAyD,IAAzC2a,EAAwC,4DAAXnwB,EACvE,GADkF,yBAdpFowB,YAcoF,OAbpFC,aAaoF,OAZpFC,aAYoF,OACnEtwB,IAAXmwB,GAAwBA,EAAOlD,OAASngB,EAAQ0I,EAClD,MAAM,IAAIxT,MAAM,mCAElB5C,KAAKgxB,OAAStjB,EACd1N,KAAKixB,QAAU7a,EACfpW,KAAKkxB,aAAqBtwB,IAAXmwB,EAAuBA,EAAS,IAAItB,GAAO/hB,EAAQ0I,G,6CAGpE,WACE,OAAOpW,KAAKixB,U,sBAGd,WACE,OAAOjxB,KAAKgxB,S,kBAGd,WAAwB,OAAOhxB,KAAKkxB,U,wBA4CpC,WAA0E,IAA9DC,EAA6D,uDAArCpd,GAAaqd,IACzCrjB,EAAO,IAAIqc,kBAAqC,EAAnBpqB,KAAK+wB,OAAOlD,MACzC+C,EAAiB5wB,KAAK+wB,OAAOH,iBAYnC,OAXAA,EAAe7uB,SAAQ,SAAAouB,GACrB,IAAMO,EAAiB,EAARP,EACXgB,IAAYpd,GAAaqd,KAC3BrjB,EAAK2iB,GAAU,IACf3iB,EAAK2iB,EAAS,GAAK,IACnB3iB,EAAK2iB,EAAS,GAAK,KAEnB3iB,EAAK2iB,EAASS,GAAW,IAE3BpjB,EAAK2iB,EAAS,GAAK,OAEd3iB,I,yBAST,WAA+C,IAAlCyC,EAAiC,uDAAhB,EACtBigB,EAAsB,CAAEY,GAAI,EAAGC,GAAI,EAAGC,GAAIvxB,KAAKgxB,OAAS,EAAGQ,GAAIxxB,KAAKixB,QAAU,GAM9EL,EAAiB5wB,KAAKkxB,QAAQN,iBACpCH,EAAOa,GAAKzV,KAAKmO,MAAM4G,EAAe,GAAK5wB,KAAKgxB,QAChDP,EAAOe,GAAK3V,KAAKmO,MAAM4G,EAAeA,EAAejuB,OAAS,GAAK3C,KAAKgxB,QAIxE,IAFA,IAAIS,EAAOzxB,KAAKgxB,OACZU,GAAQ,EACH7qB,EAAI,EAAGA,EAAI+pB,EAAejuB,OAAQkE,IAAK,CAC9C,IAAM8qB,EAAYf,EAAe/pB,GAAKgV,KAAKmO,MAAM4G,EAAe/pB,GAAK7G,KAAKgxB,QAAUhxB,KAAKgxB,OACrFW,EAAYF,IACdA,EAAOE,GAELA,EAAYD,IACdA,EAAOC,GAcX,OAXAlB,EAAOY,GAAKI,EACZhB,EAAOc,GAAKG,EAGG,IAAXlhB,IACFigB,EAAOY,GAAKZ,EAAOY,GAAK7gB,EAAS,EAAIigB,EAAOY,GAAK7gB,EAAS,EAC1DigB,EAAOa,GAAKb,EAAOa,GAAK9gB,EAAS,EAAIigB,EAAOa,GAAK9gB,EAAS,EAC1DigB,EAAOc,GAAKd,EAAOc,GAAK/gB,EAASxQ,KAAKgxB,OAASP,EAAOc,GAAK/gB,EAASxQ,KAAKgxB,OAAS,EAClFP,EAAOe,GAAKf,EAAOe,GAAKhhB,EAASxQ,KAAKixB,QAAUR,EAAOe,GAAKhhB,EAASxQ,KAAKixB,QAAU,GAG/ER,I,uBAQT,SAAWmB,GAKT,GAAI5xB,KAAKgxB,OAASY,IAAW,EAC3B,MAAM,IAAIhvB,MAAM,iCAQlB,IALA,IAAM6tB,EAAS,IAAIhB,GAAOzvB,KAAKkxB,QAAQrD,MAAQ+D,EAASA,IAClDC,EAAc7xB,KAAKgxB,OAASY,EAE5BE,EAAejW,KAAKmO,MAAMhqB,KAAKixB,QAAUW,GAEtCG,EAAI,EAAGA,EAAIF,EAAaE,IAC/B,IAAK,IAAIC,EAAI,EAAGA,EAAIF,EAAcE,IAAK,CAIrC,IAHA,IAAMC,EAAaF,EAAIH,EACjBM,EAAaF,EAAIJ,EACnBpB,GAAQ,EACHe,EAAKU,EAAYV,EAAKU,EAAaL,EAAQL,IAClD,IAAK,IAAIC,EAAKU,EAAYV,EAAKU,EAAaN,EAAQJ,IAAM,CACxD,IAAMW,EAAiBX,EAAKxxB,KAAKgxB,OAASO,EACtCvxB,KAAKkxB,QAAQV,MAAM2B,KACrB3B,GAAQ,GAIVA,GACFC,EAAOhuB,IAAIuvB,EAAIH,EAAcE,GAKnC/xB,KAAKkxB,QAAUT,EACfzwB,KAAKgxB,OAASa,EACd7xB,KAAKixB,QAAUa,I,qBAQjB,SAASF,GAAuB,IAAD,OAC7B,GAAIA,EAAS,EACX,MAAM,IAAIhvB,MAAM,yBAElBgvB,EAAS/V,KAAKmO,MAAM4H,GAEpB,IAAMnB,EAAS,IAAIhB,GAAOzvB,KAAK+wB,OAAOlD,KAAO+D,EAASA,GAChDQ,EAAWpyB,KAAKgxB,OAASY,EACR5xB,KAAK+wB,OAAOH,iBACpB7uB,SAAQ,SAAAouB,GAKrB,IAJA,IAAMkC,EAAMxW,KAAKmO,MAAMmG,EAAQ,EAAKa,QAC9BsB,EAASnC,EAAQ,EAAKa,OACtBuB,EAAYF,EAAMT,EAClBY,EAAeF,EAASV,EACrB/qB,EAAI0rB,EAAW1rB,EAAI0rB,EAAYX,EAAQ/qB,IAC9C,IAAK,IAAIqW,EAAIsV,EAActV,EAAIsV,EAAeZ,EAAQ1U,IACpDuT,EAAOhuB,IAAIoE,EAAIurB,EAAWlV,MAKhCld,KAAKkxB,QAAUT,EACfzwB,KAAKixB,QAAUjxB,KAAKixB,QAAUW,EAC9B5xB,KAAKgxB,OAAShxB,KAAKgxB,OAASY,K,2BApK9B,SAAqB7jB,EAAyBL,EAAe0I,GAAwE,IAAxD+a,EAAuD,uDAA/Bpd,GAAaqd,IAEhH,GAAIrjB,EAAKpL,OAAS,IAAM,EACtB,MAAM,IAAIC,MAAM,+CAElB,GAAImL,EAAKpL,SAAW+K,EAAQ0I,EAAS,EACnC,MAAM,IAAIxT,MAAM,mCAGlB,IAAMmuB,EAAS,IAAItB,GAAO/hB,EAAQ0I,GAGlC,GAAI+a,IAAYpd,GAAaqd,IAC3B,IAAK,IAAIvqB,EAAI,EAAGA,EAAIkH,EAAKpL,OAAQkE,IACf,IAAZkH,EAAKlH,IACPkqB,EAAOtuB,IAAIoZ,KAAKmO,MAAMnjB,EAAI,SAI9B,IAAK,IAAIA,EAAIsqB,EAAStqB,EAAIkH,EAAKpL,OAAQkE,GAAK,EAC1B,IAAZkH,EAAKlH,IACPkqB,EAAOtuB,IAAIoZ,KAAKmO,MAAMnjB,EAAI,IAIhC,OAAO,IAAIiqB,EAAYpjB,EAAO0I,EAAQ2a,O,KMpD7B0B,GAWX,WAAaC,EAAatD,EAAchZ,EAAgB1I,GAAgB,yBAVxDglB,SAUuD,OATvDtD,UASuD,OARvDhZ,YAQuD,OAPvD1I,WAOuD,EACrE1N,KAAK0yB,IAAMA,EACX1yB,KAAKovB,KAAOA,EACZpvB,KAAKoW,OAASA,EACdpW,KAAK0N,MAAQA,GAIJilB,GAAb,WAeE,WAAapwB,EAAkBtC,EAAoBqB,EAAiBsxB,EAAqBC,EAA2BxtB,EAAgBjF,EAAkB0yB,EAAsBC,EAAgBpvB,GAAkB,IAAD,gCAd5L1D,gBAc4L,OAb5LqB,aAa4L,OAZ5LsxB,iBAY4L,OAX5LC,uBAW4L,OAV5LxtB,YAU4L,OAT5LjF,cAS4L,OAR5L0yB,eAQ4L,OAP5LC,YAO4L,OAN5LxwB,cAM4L,OAL5LoB,aAK4L,OAHrMqvB,YAA6B,KAGwK,KAFrMC,MAAsB,KAE+K,KAatMC,UAAY,SAACC,EAAwBF,EAA0BD,GAUpE,OATIG,GAAiC,KAAhBH,GACnB,EAAKC,MAAQ,KACb,EAAKD,YAAcA,QAELpyB,IAAVqyB,IACF,EAAKD,YAAc,KACnB,EAAKC,MAAQA,GAGV,GAtBPjzB,KAAKuC,SAAWA,EAChBvC,KAAKC,WAAaA,EAClBD,KAAKsB,QAAUA,EACftB,KAAK4yB,YAAcA,EACnB5yB,KAAK6yB,kBAAoBA,EACzB7yB,KAAKqF,OAASA,EACdrF,KAAKI,SAAWA,EAChBJ,KAAK8yB,UAAYA,EACjB9yB,KAAK+yB,OAASA,EACd/yB,KAAK2D,QAAUA,EAzBnB,6CAyCE,WACE,MAAO,CACLyvB,UAAW,KACXC,SAAS,IAAIC,MAAOC,cACpBjwB,GAAI,EACJhC,QAAStB,KAAKsB,QACdrB,WAAYD,KAAKC,WACjB0D,QAAS3D,KAAKuC,SAAW,IAAMvC,KAAK2D,QAEpCivB,YAAa5yB,KAAK4yB,YAClBC,kBAAmB7yB,KAAK6yB,kBAExBW,gBAAgC,OAAfxzB,KAAKizB,MAAiB,KAAOjzB,KAAKizB,MAAM3vB,GACzDmwB,cAA8B,OAAfzzB,KAAKizB,MAAiB,KAAOjzB,KAAKizB,MAAM/mB,MACvD8mB,YAAahzB,KAAKgzB,YAElBpF,eAAgB5tB,KAAK+yB,OAAO7mB,MAC5BggB,iBAAkBlsB,KAAK+yB,OAAOzvB,GAE9BovB,IAAK1yB,KAAK8yB,UAAUJ,IACpBtD,KAAMpvB,KAAK8yB,UAAU1D,KACrBhZ,OAAQpW,KAAK8yB,UAAU1c,OACvB1I,MAAO1N,KAAK8yB,UAAUplB,MACtBgmB,cAAe1zB,KAAKqF,OACpBsuB,eAAgB3zB,KAAKqF,OAErB4tB,MAAO,KACP/xB,UAAW,KACX0yB,eAAgB,KAChBC,eAAe,IAAIP,MAAOC,cAC1BO,sBAAuB,KACvBC,gBAAiB,KACjBC,YAAa,KACb5zB,SAAUJ,KAAKI,SACf6zB,QAAS,EACT9nB,SAAU,GACV+nB,MAAO,KACPC,YAAa,KACb/xB,eAAe,EACfgyB,WAAW,KAhFjB,0BAoFE,SAAqBC,GACnB,OAAO,6BACFr0B,KAAKs0B,aADV,IAEEhxB,GAAI+wB,EAAc/wB,GAClBowB,cAAeW,EAAcX,cAC7BL,QAASgB,EAAchB,QACvBM,eAAgB3zB,KAAKqF,aA1F3B,KCzCakvB,GAAgC,SAACC,EAA0BC,EAAoBC,GAA0D,IAArCC,EAAoC,uDAAjB,EAC5HtD,EAAKmD,EAAYnD,GAAKoD,EACtBlD,EAAKiD,EAAYjD,GAAKkD,EACtBnD,EAAKkD,EAAYlD,GAAKoD,EACtBlD,EAAKgD,EAAYhD,GAAKkD,EAC5B,OAAO,IAAIjC,GACTmC,WAAWtD,EAAGuD,QAAQF,IACtBC,WAAWvD,EAAGwD,QAAQF,IACtBC,YAAYpD,EAAKF,GAAIuD,QAAQF,IAC7BC,YAAYrD,EAAKF,GAAIwD,QAAQF,MAsBpBG,GAAiB,SAAClH,EAAiDmH,GAC9E,QAAsBn0B,IAAlBm0B,QAAkDn0B,IAAnBgtB,EAA8B,CAC/D,IAAMuC,EAAQrd,GAAsB5B,QAAQ0c,GAC5C,IAAe,IAAXuC,EAEF,OAvBiC,SAAC3jB,GACtC,MAAM,QAAN,OAAeA,EACVwoB,QAAQ,IAAK,IACbA,QAAQ,IAAK,IACbnxB,MAAM,KACNrC,KAAI,SAACyzB,EAAGpuB,GAAJ,OAAgB,IAANA,EAAUouB,EAAoB,IAAhBL,WAAWK,MACvCC,KAAK,KALV,KAsBWC,CADOJ,EAAc5E,IAIhC,MAAO,uBChDM/jB,GAPUC,aAAW,SAAAC,GAAK,MAAK,CAC5C8oB,SAAU,CACRzG,UAAW,aACX0G,OAAQ,aAAe/oB,EAAMG,QAAQC,QAAQ0hB,UCQpCkH,GAAmB,SAAC,GAAoF,IAAlF1W,EAAiF,EAAjFA,IAAK2W,EAA4E,EAA5EA,QAASC,EAAmE,EAAnEA,YAAaJ,EAAsD,EAAtDA,SAAU5oB,EAA4C,EAA5CA,MAAO8D,EAAqC,EAArCA,QACvEpD,EAAUd,KACVqpB,EAAYC,iBAA0B,MACtCC,EAAYJ,EAAQ7nB,MACpBkoB,EAAaL,EAAQnf,OACrByf,EAAeha,KAAKmO,MAAMuL,EAAQnf,OAAOof,GACzCM,EAAcja,KAAKmO,MAAMuL,EAAQ7nB,MAAM8nB,GA6C7C,OA3CAO,qBAAU,WACR,IAaMC,EAAc,SAAC7M,GAGnB,IAFA,IAAM8M,EAAuCzpB,EFM9CwoB,QAAQ,OAAQ,IAChBA,QAAQ,IAAK,IACbA,QAAQ,IAAK,IACbnxB,MAAM,KACNrC,KAAI,SAACyzB,EAAGpuB,GAAJ,OAAgB,IAANA,EAA0B,IAAhB+tB,WAAWK,GAAW5nB,SAAS4nB,METhDlnB,EAA0Bob,EAAUpb,KACjClH,EAAI,EAAGA,EAAIkH,EAAKpL,OAAQkE,GAAK,EAAG,CACvC,IAAMqvB,EAAInoB,EAAKlH,EAAI,GACnBkH,EAAKlH,EAAI,GAAW,MAANqvB,EAAYD,EAAe,GAAK,EAC9CloB,EAAKlH,EAAI,GAAW,MAANqvB,EAAYD,EAAe,GAAK,EAC9CloB,EAAKlH,EAAI,GAAW,MAANqvB,EAAYD,EAAe,GAAK,EAC9CloB,EAAKlH,EAAI,GAAW,MAANqvB,EAAY,IAAM,EAElC,OAAO/M,GAGHlV,EAAmCwhB,EAAUU,QAC7C7K,EAAoD,OAAGrX,QAAH,IAAGA,OAAH,EAAGA,EAAQE,WAAW,MAChF,GAAe,OAAXF,GAA+B,OAAZqX,QAAgC1qB,IAAZ0qB,EAAuB,CAChE,IAAMloB,EAAQ,IAAIob,MAClBpb,EAAMqb,OAAS,WACb6M,EAAQU,UAAU5oB,EAAO,EAAG,EAAGuyB,EAAWC,IA/BrB,SAACzM,EAAsBiN,GAC9C,IAAMniB,EAA4BtC,SAAS0Z,cAAc,UACnDC,EAA2CrX,EAAOE,WAAW,MACnEF,EAAOvG,MAAQioB,EACf1hB,EAAOmC,OAASwf,EACT,OAAPtK,QAAO,IAAPA,KAASC,aAAapC,EAAW,EAAG,GACpC,IAAM/lB,EAAQ,IAAIob,MAClBpb,EAAMqb,OAAS,WACb2X,EAAShzB,IAEXA,EAAMwb,IAAM3K,EAAOwX,YA0BjB4K,CAJkCL,EAAYT,IAC7B,SAACe,GAChBhL,EAAQU,UAAUsK,EAAe,EAAG,EAAGX,EAAWC,OAItDxyB,EAAMwb,IAAMA,KAEb,CAAC2W,EAAS3W,EAAKgX,EAAYD,EAAWnpB,IAGvC,wBACElJ,GAAIsb,EACJ2X,IAAKd,EACLpnB,UAAW+mB,EAAWloB,EAAQkoB,SAAW,GACzC9kB,QAASA,EACT5C,MAAOioB,EACPvf,OAAQwf,EACRlK,MAAO,CAAEhe,MAAOooB,EAAa1f,OAAQyf,MCrD9BW,GAAwC,SAAC,GAAkI,IAAhIC,EAA+H,EAA/HA,gBAAiBC,EAA8G,EAA9GA,kBAAmB9X,EAA2F,EAA3FA,IAAK+X,EAAsF,EAAtFA,SAAUC,EAA4E,EAA5EA,OAAQC,EAAoE,EAApEA,eAAgBC,EAAoD,EAApDA,UAAWvB,EAAyC,EAAzCA,QAAS/oB,EAAgC,EAAhCA,MAC/IU,EAAUd,KAEhB,OACE,wCACWxL,IAARge,GAAsB+X,EAmDrB,qBAAKtoB,UAAWnB,EAAQ0hB,QAAxB,SACE,cAACmI,GAAA,EAAD,MAnDF,eAAC/3B,EAAA,EAAD,CAAKqP,UAAWnB,EAAQ+hB,eAAxB,eACeruB,IAAZ20B,EACC,cAAC,GAAD,CACE3W,IAAKA,EACL2W,QAASA,EACTC,YAAa,EACbhpB,MAAOA,IAGT,qBAAKoS,IAAKA,EAAKvQ,UAAWnB,EAAQ8hB,kBAAmBgI,IAAI,aAE3D,eAACh4B,EAAA,EAAD,CAAKqP,UAAWnB,EAAQgiB,cAAe+H,EAAG,EAA1C,UACE,cAACC,GAAA,EAAD,CACEC,SAAUV,EACVpoB,UAAWnB,EAAQmiB,aACnBxB,KAAK,QACLvd,QAASsmB,EACTpnB,QAAQ,YACRhD,MAAM,UACN4qB,UAAW,cAAC,KAAD,IAPb,kBAWCN,EACC,cAACI,GAAA,EAAD,CACErJ,KAAK,QACLre,QAAQ,YACRhD,MAAM,YACN4qB,UAAW,cAAC,KAAD,IAJb,qBASA,oCACIV,GACA,cAACQ,GAAA,EAAD,CACE5mB,QAASumB,EACThJ,KAAK,QACLre,QAAQ,YACRhD,MAAM,UACN4qB,UAAW,cAAC,KAAD,IALb,uC,yCClDHhrB,GARUC,aAAW,SAAAC,GAAK,MAAK,CAC5C+qB,YAAa,CACXjoB,SAAU,WACVC,MAAO/C,EAAMO,QAAQ,GACrB6lB,IAAKpmB,EAAMO,QAAQ,QCQVyqB,GAAe,SAAC,GAAqG,IAAnG5oB,EAAkG,EAAlGA,MAAkG,IAA3F6oB,gBAA2F,WAAhF32B,EAAgF,EAArEwP,EAAqE,EAArEA,QAAST,EAA4D,EAA5DA,KAA4D,IAAtD6nB,cAAsD,WAA7C52B,EAA6C,EAAlCuL,EAAkC,EAAlCA,SACvFe,EAAUd,KAEhB,OACE,eAACqrB,GAAA,EAAD,CACE9nB,KAAMA,EACNS,QAASA,EACTmnB,SAAUA,EACVC,OAAQA,EAJV,UAME,eAACE,GAAA,EAAD,WACGhpB,EACD,cAAC2C,GAAA,EAAD,CACElD,aAAW,QACXE,UAAWnB,EAAQmqB,YACnB/mB,QAASF,EACTyd,KAAK,QAJP,SAME,cAAC,KAAD,SAGH1hB,M,qBCNQC,GA3BUC,aAAW,SAAAC,GAAK,MAAK,CAC5C0iB,kBAAmB,CACjBthB,MAAO,KAET0nB,SAAU,CACRzG,UAAW,aACX0G,OAAQ,aAAe/oB,EAAMG,QAAQC,QAAQ0hB,MAE/CuJ,UAAW,CACTvoB,SAAU,YAEZwoB,YAAa,CACXppB,SAAU,GACVY,SAAU,WACV+f,OAAQ7iB,EAAMO,QAAQ,GACtBwC,MAAO/C,EAAMO,QAAQ,GACrB8e,WAAY,QACZkM,aAAc,OAEhBC,SAAU,CACRC,gBAAiB,QACjB3oB,SAAU,WACV+f,OAAQ7iB,EAAMO,QAAQ,GACtBuiB,KAAM9iB,EAAMO,QAAQ,QCPXmrB,GAAgC,SAACj5B,GAC5C,IAAQ6f,EAA+D7f,EAA/D6f,IAAK2W,EAA0Dx2B,EAA1Dw2B,QAASuB,EAAiD/3B,EAAjD+3B,UAAW1B,EAAsCr2B,EAAtCq2B,SAAU5oB,EAA4BzN,EAA5ByN,MAAOyrB,EAAqBl5B,EAArBk5B,SAAUrB,EAAW73B,EAAX63B,OACtD1pB,EAAUd,KAChB,EAAoCnB,oBAAkB,GAAtD,mBAAOitB,EAAP,KAAoBC,EAApB,KAEA,OACE,eAACn5B,EAAA,EAAD,CACEo5B,GAAI,EACJ/pB,UAAWnB,EAAQyqB,UACnBU,YAAa,SAACvV,GAAD,OAAgCqV,GAAa,IAC1D/V,aAAc,SAACU,GAAD,OAAgCqV,GAAa,IAJ7D,eAMev3B,IAAZ20B,EACC,cAAC,GAAD,CACI3W,IAAKA,EACL2W,QAASA,EACTC,YAAa,EACbJ,SAAUA,EACV9kB,QAAS2nB,EACTzrB,MAAOA,IAGX,qBAAKoS,IAAKA,EAAKvQ,UAAW,CAACnB,EAAQ8hB,kBAAmBoG,EAAWloB,EAAQkoB,SAAW,IAAIF,KAAK,KAAM5kB,QAAS2nB,EAAUjB,IAAI,cAE3HF,GAAa,cAAC,KAAD,CAAiBtqB,MAAM,YAAY6B,UAAWnB,EAAQ0qB,cACnEM,GACC,cAAC7mB,GAAA,EAAD,CACEf,QAASsmB,EACT/I,KAAK,QACLxf,UAAWnB,EAAQ4qB,SAHrB,SAIE,cAAC,KAAD,CAAUtrB,MAAM,kB,8BCpCb8rB,GAAoD,SAACv5B,GAChE,IAAQw5B,EAAsDx5B,EAAtDw5B,SAAUpB,EAA4Cp4B,EAA5Co4B,SAAUqB,EAAkCz5B,EAAlCy5B,MAAOC,EAA2B15B,EAA3B05B,MAAOvsB,EAAoBnN,EAApBmN,MAAO+rB,EAAal5B,EAAbk5B,SAMjD,OACE,eAACS,GAAA,EAAD,CACEH,SAAUA,EACV5C,WAAS,EACTnlB,OAAO,QAHT,UAKE,cAACmoB,GAAA,EAAD,CAAYr1B,GAAG,SAAf,SAAyBk1B,IACzB,cAACI,GAAA,EAAD,CACEzB,SAAUA,EACV0B,SAbe,SAACvnB,GACpB2mB,EAAQ,OAACQ,QAAD,IAACA,OAAD,EAACA,EAAOK,WAAU,SAAAjyB,GAAC,OAAIA,IAAMyK,EAAMynB,OAAO7sB,WAa9CA,WAAiBtL,IAAVsL,EAAsBA,EAAQ,GAHvC,gBAKGusB,QALH,IAKGA,OALH,EAKGA,EAAOj3B,KAAI,SAAC0K,EAAOikB,GAClB,OAAO,cAAC9f,GAAA,EAAD,CAAsBnE,MAAOA,EAA7B,SAAqCA,GAAtBikB,Y,8BCX1B6I,I,OAA0C,SAAC,GAepB,IAd3BC,EAc0B,EAd1BA,mBACAC,EAa0B,EAb1BA,OACAC,EAY0B,EAZ1BA,UACAzrB,EAW0B,EAX1BA,MACA0I,EAU0B,EAV1BA,OACAgjB,EAS0B,EAT1BA,QACAC,EAQ0B,EAR1BA,KACAC,EAO0B,EAP1BA,cACAC,EAM0B,EAN1BA,QACAC,EAK0B,EAL1BA,SACAC,EAI0B,EAJ1BA,UACAC,EAG0B,EAH1BA,eACAC,EAE0B,EAF1BA,UACAC,EAC0B,EAD1BA,eAEMC,EAAqBnE,iBAAyB,MAC9CD,EAAYC,iBAA0B,MAE5C,EAAoCzqB,oBAAkB,GAAtD,mBAAO6uB,EAAP,KAAmBC,EAAnB,KACA,EAAgD9uB,oBAAkB,GAAlE,mBAAO+uB,EAAP,KAAyBC,EAAzB,KAEMC,EAAYre,KAAK+T,KAAKliB,EAAQyrB,GAC9BgB,EAAate,KAAK+T,KAAKxZ,EAAS+iB,GAEhCiB,EAAgBT,EAEhBU,EAAWjkB,EAASgjB,EACpBkB,EAAU5sB,EAAQ0rB,EAElBmB,EAAe,WACnBR,GAAeD,IAIjB/D,qBAAU,WAER,IAAMyE,EAAe,SAAClP,EAAmC6N,EAAmBe,EAAmBO,EAAwBrB,EAAiB5sB,GACtI8e,EAAQoP,OACRpP,EAAQS,YAAc2N,EAAiB,GAAO,EAC9C,IAAMje,EAAQ0d,EAAYC,EACpBrH,EAAI0I,EAAiBP,EAAYze,EACjCuW,EAAInW,KAAKmO,MAAMyQ,EAAiBP,GAAaze,EACnD6P,EAAQqP,UAAYnuB,EACpB8e,EAAQsP,OAAO7I,EAAGC,GAClB1G,EAAQuP,YACRvP,EAAQwP,OAAO/I,EAAItW,EAAOuW,GAC1B1G,EAAQwP,OAAO/I,EAAItW,EAAOuW,EAAIvW,GAC9B6P,EAAQwP,OAAO/I,EAAGC,EAAIvW,GACtB6P,EAAQwP,OAAO/I,EAAGC,GAClB1G,EAAQyP,YACRzP,EAAQpK,OACRoK,EAAQ0P,gBAqEgBp6B,IAAtB60B,EAAUU,SAA+C,OAAtBV,EAAUU,cAChBv1B,IAA/Bi5B,EAAmB1D,SAAwD,OAA/B0D,EAAmB1D,SAnElD,WAEb,QAA0Bv1B,IAAtB60B,EAAUU,SAA+C,OAAtBV,EAAUU,cAChBv1B,IAA/Bi5B,EAAmB1D,SAAwD,OAA/B0D,EAAmB1D,QADjE,CAKA,IAAM7K,EAAUmK,EAAUU,QAAQhiB,WAAW,MAC7C,GAAgB,OAAZmX,EAAJ,CAMAA,EAAQ2P,UAAU,EAAG,EAAGvtB,EAAO0I,GAG/B,IAKI8kB,EALY,SAAC7B,GACf,IAAM8B,EAAStf,KAAKuf,IAAI9B,EAAe,EAAEC,GACzC,OAAO1d,KAAKuf,IAAID,EAAQ9B,GAGTgC,CAAQhC,GACrBiC,EAAe,EACfC,EAAe,EAEbC,EAAKtC,EAAO1E,YAAY,GACxBiH,GAAWD,EAAGjK,GAAKiK,EAAGnK,IAAM8H,EAC5BuC,GAAYF,EAAGhK,GAAKgK,EAAGlK,IAAM6H,EAGnC,GAAI+B,EAAa,EAAG,CAClB,IAAMS,EAAYH,EAAGnK,GAAK8H,EAAYsC,EAAU,EAC1CG,EAAYJ,EAAGlK,GAAK6H,EAAYuC,EAAW,EAKjDJ,IAFmBK,EAFCjuB,EAAQwtB,EAEiB,GAEhB9B,EAAU8B,EACvCK,IAFmBK,EAFExlB,EAAS8kB,EAEgB,GAEjB9B,EAAU8B,EAEzC5P,EAAQuQ,aAAaX,EAAY,EAAG,EAAGA,EAAYI,EAAcC,GAGjEjQ,EAAQU,UAAU6N,EAAmB1D,QAAS,EAAG,EAAGmE,EAASD,GAG7DnB,EAAOnI,OAAOH,iBAAiB7uB,SAAQ,SAAA+5B,GACrCtB,EAAalP,EAAS6N,EAAWe,EAAW4B,EAAc1C,EAASgB,OAI3C,IAAtBJ,GACFd,EAAOhI,QAAQZ,QAAQ0J,EAAkBP,EAAWS,GAAWn4B,SAAQ,SAAA8tB,GAAG,OACxE2K,EAAalP,EAAS6N,EAAWe,EAAWrK,EAAKuJ,EArFlC,8BA0FnB2C,EAAgBzQ,EAASkQ,EAAIrC,EAAWC,GAExC4C,EAAc1Q,EAAS5d,EAAO0I,EAAQ+iB,EAAWC,GAEjDQ,EAAeV,EAAOhI,QAAQ+K,gBAtD5B18B,QAAQH,MAAM,8CALdG,QAAQ0J,IAAI,0DAgEdsR,KAED,CAACuf,EAAYE,EAAkBX,EAAMK,EAAgBP,EAAWzrB,EAAO0I,EAAQqjB,EAC9EH,EAAeC,EAASH,EAASF,EAAQU,EAAgBM,EAAWG,EAAUC,EAASF,IAG3F,IAAM4B,EAAgB,SAAC1Q,EAAmC4Q,EAAqBC,EAAsBhD,EAAmBC,GACtH9N,EAAQoP,OACR,IAAMjf,EAAQ0d,EAAYC,EACpBgD,EAASvgB,KAAKmO,MAAMkS,EAAczgB,GAClC4gB,EAASxgB,KAAKmO,MAAMmS,EAAe1gB,GAGzC6P,EAAQgR,YAAc,QACtBhR,EAAQiR,UAAY,GACpBjR,EAAQS,YAAc,GAGtB,IAAK,IAAIllB,EAAI,EAAGA,EAAIw1B,EAAQx1B,IAC1BykB,EAAQsP,OAAO,EAAG/zB,EAAI4U,GACtB6P,EAAQwP,OAAOoB,EAAar1B,EAAI4U,GAIlC,IAAK,IAAI5U,EAAI,EAAGA,EAAIu1B,EAAQv1B,IAC1BykB,EAAQsP,OAAO/zB,EAAI4U,EAAO,GAC1B6P,EAAQwP,OAAOj0B,EAAI4U,EAAO0gB,GAG5B7Q,EAAQkR,SACRlR,EAAQ0P,WAGJe,EAAkB,SAACzQ,EAAmCkJ,EAA0B2E,EAAmBC,GACvG9N,EAAQoP,OAER,IAAMjf,EAAQ0d,EAAYC,EAEpB7yB,EAAI,CAAEwrB,EAAGyC,EAAYnD,GAAK5V,EAAOuW,EAAGwC,EAAYlD,GAAK7V,GACrD2E,EAAI,CAAE2R,EAAGyC,EAAYjD,GAAK9V,EAAQA,EAAOuW,EAAGwC,EAAYhD,GAAK/V,EAAQA,GAE3E6P,EAAQgR,YAAc,QACtBhR,EAAQiR,UAAY,GACpBjR,EAAQsP,OAAOr0B,EAAEwrB,EAAGxrB,EAAEyrB,GACtB1G,EAAQuP,YACRvP,EAAQwP,OAAO1a,EAAE2R,EAAGxrB,EAAEyrB,GACtB1G,EAAQwP,OAAO1a,EAAE2R,EAAG3R,EAAE4R,GACtB1G,EAAQwP,OAAOv0B,EAAEwrB,EAAG3R,EAAE4R,GACtB1G,EAAQwP,OAAOv0B,EAAEwrB,EAAGxrB,EAAEyrB,EAAKuK,KAC3BjR,EAAQyP,YACRzP,EAAQkR,SAERlR,EAAQ0P,WAkEV,OACE,sBACE3sB,UAAU,iBACVqd,MAAO,CACLhe,MAAO4sB,EACPlkB,OAAQikB,GAJZ,UAOE,qBACEhsB,UAAU,mBACVX,MAAO4sB,EACPlkB,OAAQikB,EACRzb,IAAKqa,EACL1C,IAAKsD,EACL4C,OAAQ,kBAAMlC,KACdvD,IAAI,eAEN,wBACET,IAAKd,EACLpnB,UAAU,cACVX,MAAO4sB,EACPlkB,OAAQikB,EACRlY,YA5DyD,SAAC7Q,GAC9D,IAAMmK,EAAQ0d,EAAYC,EACpBsD,EA1BiB,SAACprB,GACxB,QAA0B1Q,IAAtB60B,EAAUU,SAA+C,OAAtBV,EAAUU,QAC/C,MAAO,CAAEpE,GAAI,EAAGC,GAAI,GAEtB,IAAM1G,EAAUmK,EAAUU,QAAQhiB,WAAW,MAC7C,GAAgB,OAAZmX,EAEF,OADA/rB,QAAQH,MAAM,yCACP,CAAE2yB,GAAI,EAAGC,GAAI,GAGtB,IAAM2K,EAAalH,EAAUU,QAAQyG,wBAC/BC,EAAkBvR,EAAQwR,eAC1BrhB,EAAgB,EAAIohB,EAAgBE,IACpC9sB,EAAqB4sB,EAAgBG,IACrChtB,EAAmB6sB,EAAgBI,IAEzC,MAAO,CACLlL,GAAIzgB,EAAM4rB,QAAUP,EAAWvN,KAAOnf,GAAcwL,EACpDuW,GAAI1gB,EAAM6rB,QAAUR,EAAWjK,IAAM1iB,GAAYyL,GAQ7B2hB,CAAiB9rB,GACjC+rB,EAAQxhB,KAAKmO,MAAM0S,EAAc3K,EAAItW,GAErC6hB,EADQzhB,KAAKmO,MAAM0S,EAAc1K,EAAIvW,GACjBye,EAAYmD,EAGlCC,EAAY,GAAKA,EAAYpD,EAAYC,GAIzCmD,IAActD,IAGM,IAAlB1oB,EAAMisB,UACJ/D,EACFN,EAAOhI,QAAQsM,QAAQF,EAAW7D,EAAWS,GAE7ChB,EAAOhI,QAAQuM,UAAUH,EAAW7D,EAAWS,IAGnDD,EAAoBqD,KAuClBxb,YAlCyD,SAACxQ,IACpC,IAAtB0oB,IACER,EACFN,EAAOhI,QAAQsM,QAAQxD,EAAkBP,EAAWS,GAEpDhB,EAAOhI,QAAQuM,UAAUzD,EAAkBP,EAAWS,GAExDK,a,iJC/NOmD,GAA4C,SAAC,GAA4J,IAA1JC,EAAyJ,EAAzJA,QAASvtB,EAAgJ,EAAhJA,QAASwtB,EAAuI,EAAvIA,SAAUrX,EAA6H,EAA7HA,eAAgB5W,EAA6G,EAA7GA,KAAMjB,EAAuG,EAAvGA,MAAOxN,EAAgG,EAAhGA,UAAWD,EAAqF,EAArFA,aAAc2sB,EAAuE,EAAvEA,eAAgB3tB,EAAuD,EAAvDA,WAAY49B,EAA2C,EAA3CA,eAOxK,EAA4B5yB,oBAAkB,GAA9C,mBAAO6yB,EAAP,KAAeC,EAAf,KACA,EAAwB9yB,mBAPR,GAOhB,mBAAOouB,EAAP,KAAa2E,EAAb,KACA,EAAkCvzB,IAA1BS,EAAR,EAAQA,MAAOc,EAAf,EAAeA,eACf,EAA4Bf,qBAA5B,mBAAOiuB,EAAP,KAAe+E,EAAf,KACA,EAAgChzB,qBAAhC,mBAAOizB,EAAP,KAAiBC,EAAjB,KACA,EAAgClzB,oBAAkB,GAAlD,mBAAOuuB,EAAP,KAAiB4E,EAAjB,KACA,EAAkCnzB,mBAAiB,GAAnD,mBAAOwuB,EAAP,KAAkB4E,EAAlB,KACA,EAA0CpzB,oBAAkB,GAA5D,mBAAOqzB,EAAP,KAAuBC,EAAvB,KACA,EAA8CtzB,oBAAkB,GAAhE,mBAAOuzB,EAAP,KAAyBC,EAAzB,KACA,GAAwCxzB,mBAAiB,IAAzD,qBAAO3L,GAAP,MAAqBo/B,GAArB,MAuBMC,GAAe,uCAAG,WAAOC,GAAP,iBAAAr4B,EAAA,8DACP3F,IAAXs4B,QAAkCt4B,IAAVsK,EADN,uBAEpB6yB,GAAU,GACVc,KACMC,EAAoB5zB,EAAM6zB,cAAcnR,GAJ1B,SAKC5hB,EAAegzB,2BAA2BC,aAAah/B,EAAY2tB,EAAgBkR,GALpF,OAKdI,EALc,OAMpBnB,GAAU,GAENmB,EACFvB,EAAQpX,EAAgBqH,EAAgBgR,IAExCF,GAAgB,+CAChBn/B,QAAQH,MAAM,6CAZI,2CAAH,sDAiBf+/B,GAAgB,SAACC,EAA2BjG,EAAmBkG,GACnED,EAAaE,QAAQnG,EAAYkG,GACjC,IAAME,EAAWH,EAAaI,aAC9B,OAAO,IAAInV,UAAUkV,EAAUH,EAAapO,OAAQoO,EAAanO,UAQnE8E,qBAAU,WACR,GAAIpmB,QAAkB/O,IAAVsK,EAAqB,CAC/B6yB,GAAU,GACV/xB,EAAeyzB,wBAAwBn4B,YAAYrH,EAAYiB,GAAWuK,MAAK,SAAApD,GAAG,OAAI81B,EAAY91B,MAIlG,IAAMq3B,EAAex0B,EAAMy0B,qBAAqB1+B,EAAcC,EAAW0sB,GACnEgS,EAAc9O,GAAY+O,aAAaH,EAAa3xB,KACxD2xB,EAAahyB,MACbgyB,EAAatpB,OACbrC,GAAa+rB,KAGfF,EAAYG,UAAU5G,GAEtB8E,EAAU2B,MAEX,CAACjwB,EAAMzE,EAAOjL,EAAYgB,EAAc2sB,EAAgB1sB,EAAW8K,IAEtE+pB,qBAAU,WACJuI,GACFN,EAxFY,KA0Fb,CAACM,IAEJ,IAAMO,GAAQ,WACZH,GAAgB,IAChBV,EA9Fc,GA+FdK,EA7FmB,GA8FnBD,GAAY,GACZK,GAAkB,IAGpB1I,qBAAU,WACR,IAAMrU,EAAU,SAACoB,GACf,IAAiC,IAA7BA,EAAEkd,KAAK9uB,QAAQ,SAAiB,CAClC,IAAM2c,EAAOxgB,SAASyV,EAAEkd,KAAKn8B,MAAM,SAAS,IAC5Cw6B,EAAaxQ,GArGE,EAqGqBA,EArGrB,GAuGjB,OAAQ/K,EAAEkd,MACR,IAAK,OACH5B,GAAY,GACZ,MACF,IAAK,OACHA,GAAY,GACZ,MACF,IAAK,OACHK,GAAmBD,GACnB,MACF,IAAK,OACHyB,GAAejC,EAAS3E,EApHhB,GAoH+B,GACvC,MACF,IAAK,OACH6G,GAAelC,EAAS3E,EAxHhB,EAwH+B,KAK7C,OADA1nB,SAAS6P,iBAAiB,UAAWE,GAC9B,WACL/P,SAASwuB,oBAAoB,UAAWze,MAEzC,CAAC8c,EAAkBnF,IAEtB,IAQM6G,GAAiB,SAACE,EAAkDl0B,EAAem0B,EAAaC,GAA/E,OACrBF,EAAQl0B,EAAQo0B,EAAOD,EAAMA,EAAMn0B,EAAQo0B,IAEvCL,GAAiB,SAACG,EAAkDl0B,EAAemU,EAAaigB,GAA/E,OACrBF,EAAQl0B,EAAQo0B,EAAOjgB,EAAMA,EAAMnU,EAAQo0B,IAE7C,OACE,eAAC,GAAD,CACE3wB,KAAMA,EACNjB,MAAOA,EACP0B,QAAS,WACPyuB,KACAzuB,KAEFonB,OAAO,OACPD,SAAS,KARX,UAUE,eAACgJ,GAAA,EAAD,gBACc3/B,IAAXs4B,QAAqCt4B,IAAbs9B,IAA2BJ,GAClD,cAAC,GAAD,CACE7E,mBAAoBiF,EACpBhF,OAAQA,EACRxrB,MA5JQ,EA4JDwrB,EAAOhO,WACd9U,OA7JQ,EA6JA8iB,EAAO/N,YACfgO,UA9JQ,EA+JRC,QA9JM,EA+JNC,KAAMA,EACNC,cAAe,GACfC,QArKM,GAsKNC,SAAUA,EACVC,UAAWA,EACXG,eAAgB,SAACqC,GAAD,OAAsBsC,EAAgBtC,IACtDvC,eAAgB8E,EAChB7E,UAAW7E,GAAelH,EAAD,OAAiB1iB,QAAjB,IAAiBA,OAAjB,EAAiBA,EAAOwN,oBAGpDolB,GACC,eAGJ,eAAC0C,GAAA,EAAD,WACE,cAACxhC,EAAA,EAAD,CAAK6S,GAAI,EAAT,SACE,cAAC4uB,GAAA,EAAD,CAAS/xB,MAAK,2DAlDA,WAEpB,IADA,IAAIgyB,EAAQ,GACH75B,EAlIU,EAkIQA,GAjIR,EAiI2BA,IAC5C65B,EAAMj9B,KAAKoD,GAEb,OAAO65B,EAAMxL,KAAK,KA6CwDyL,GAAtD,8BAAd,SACE,cAAC,KAAD,CAAiBn0B,MAAM,gBAG3B,cAACo0B,GAAA,EAAD,CAEIC,QACE,cAACC,GAAA,EAAD,CACEC,KAAM,cAAC,KAAD,CAA0BvyB,SAAS,UACzCwyB,YAAa,cAAC,KAAD,CAAcxyB,SAAS,UACpCyyB,QAASzC,EACT3F,SAAU,kBAAM4F,GAAmBD,IACnC0C,KAAK,eACL/J,SAAU2G,EACVtxB,MAAM,YAGVgsB,MAAM,gBAZF,gBAcR,cAACx5B,EAAA,EAAD,CAAK0O,MAAO,IAAKmE,GAAI,EAArB,SACE,eAACsvB,GAAA,EAAD,CAAMxJ,WAAS,EAAC9qB,QAAS,EAAzB,UACE,cAACs0B,GAAA,EAAD,CAAMC,MAAI,EAAV,SACE,cAAC/vB,GAAA,EAAD,CAAYwc,KAAK,QAAQvd,QAAS,SAACwS,GAAD,OAAOod,GAAe7B,EAAc5E,EAxM7D,EAwMsF,IAA/F,SACE,cAAC,KAAD,CAAWjtB,MAAM,UAAUgC,SAAS,cAGxC,cAAC2yB,GAAA,EAAD,CAAMC,MAAI,EAACC,IAAE,EAAb,SACE,cAACC,GAAA,EAAD,CACEp1B,MAAOutB,EACP4G,IA/MO,EAgNPhgB,IA/MO,EAgNPkhB,OAAO,EACP1I,SAAU,SAACvnB,EAAwBkwB,GAAzB,OAAyDnD,EAAamD,QAGpF,cAACL,GAAA,EAAD,CAAMC,MAAI,EAAV,SACE,cAAC/vB,GAAA,EAAD,CAAYwc,KAAK,QAAQvd,QAAS,SAACwS,GAAD,OAAOmd,GAAe5B,EAAc5E,EArN7D,EAqNsF,IAA/F,SACE,cAAC,KAAD,CAAWjtB,MAAM,qBAKzB,eAACxN,EAAA,EAAD,CAAK6S,GAAI,EAAT,UACE,cAACqlB,GAAA,EAAD,CACE5mB,QAAS,kBAAM8tB,GAAY,IAC3B5xB,MAAM,UACNqhB,KAAK,QACLre,QAASgqB,EAAW,YAAc,WAClCrC,SAAU2G,EACV1G,UAAW,cAAC,KAAD,IANb,kBAUA,cAACF,GAAA,EAAD,CACE5mB,QAAS,kBAAM8tB,GAAY,IAC3B5xB,MAAM,UACNqhB,KAAK,QACLre,QAAUgqB,EAAyB,WAAd,YACrBrC,SAAU2G,EACV1G,UAAW,cAAC,KAAD,IANb,sBAWF,cAACp4B,EAAA,EAAD,CAAK0O,MAAO,IAAKmE,GAAI,EAArB,SACE,eAACsvB,GAAA,EAAD,CAAMxJ,WAAS,EAAC9qB,QAAS,EAAzB,UACE,cAACs0B,GAAA,EAAD,CAAMC,MAAI,EAAV,SACE,cAAC/vB,GAAA,EAAD,CAAYwc,KAAK,QAAQvd,QAAS,SAACwS,GAAD,OAAOod,GAAelC,EAAS3E,EAvP7D,EAuP4E,IAAhF,SACE,cAAC,KAAD,CAAa7sB,MAAM,gBAGvB,cAAC20B,GAAA,EAAD,CAAMC,MAAI,EAACC,IAAE,EAAb,SACE,cAACC,GAAA,EAAD,CACEp1B,MAAOmtB,EACPlC,SAAUmH,EACV+B,IA/PE,EAgQFhgB,IA/PE,GAgQFigB,KAAM,GACNzH,SAAU,SAACvnB,EAAwBkwB,GAAzB,OAAyDxD,EAAQwD,QAG/E,cAACL,GAAA,EAAD,CAAMC,MAAI,EAAV,SACE,cAAC/vB,GAAA,EAAD,CAAYwc,KAAK,QAAQvd,QAAS,SAACwS,GAAD,OAAOmd,GAAejC,EAAS3E,EArQ7D,GAqQ4E,IAAhF,SACE,cAAC,KAAD,CAAY7sB,MAAM,qBAK1B,eAACxN,EAAA,EAAD,CAAK6S,GAAI,EAAT,UACE,cAACqlB,GAAA,EAAD,CACE5mB,QAjNc,WACtBuuB,KACAjB,KAgNQpxB,MAAM,UACNqhB,KAAK,QACLre,QAAQ,WACR2nB,SAAU2G,EALZ,oBASA,cAAC5G,GAAA,EAAD,CACE5mB,QAtQY,WACpB,QAAe1P,IAAXs4B,QAAkCt4B,IAAVsK,EAC1B,OAAQ2yB,GACN,KAAKhN,GAAe4Q,IAClB,IAAMC,EAAiBvC,GAAcjG,EAjB3B,EAPc,GAyBlB0F,EAAQ1zB,EAAMy2B,iBAAiBzgC,EAAW0sB,EAAgB8T,GAChE/C,GAAgBC,GAChB,MACF,KAAK/N,GAAe+Q,KACpB,KAAK/Q,GAAegR,OAClB,IAAMnvB,EAAcysB,GAAcjG,EAvBxB,EAPc,GA+BxBhuB,EAAM42B,wBAAwB5gC,EAAWD,EAAc2sB,EAAgBlb,GACvEisB,KACA,MACF,KAAK9N,GAAekR,QAClBxiC,QAAQH,MAAM,6BAwPZoN,MAAM,UACNqhB,KAAK,QACLre,QAAQ,WACR2nB,SAAU2G,GAAUQ,EALtB,SAOGR,EAAS,YAAc,eAIZ,KAAjBx+B,IACC,cAACN,EAAA,EAAD,CAAKgjC,GAAI,EAAGC,GAAI,EAAhB,SACE,cAAC1yB,GAAA,EAAD,CAAY2yB,MAAM,QAAQ11B,MAAM,QAAhC,SACGlN,W,+DCvTA6iC,GAAc,SAACpjC,GAC1B,IAAQ4Q,EAAiE5Q,EAAjE4Q,KAAMyyB,EAA2DrjC,EAA3DqjC,UAAWC,EAAgDtjC,EAAhDsjC,MAAOC,EAAyCvjC,EAAzCujC,KAAM5zB,EAAmC3P,EAAnC2P,MAAO5J,EAA4B/F,EAA5B+F,KAAMy9B,EAAsBxjC,EAAtBwjC,SAAUC,EAAYzjC,EAAZyjC,QAkB7D,OACE,mCACE,eAAC/K,GAAA,EAAD,CACE9nB,KAAMA,EACNS,QApBc,WAClBgyB,GAAU,IAoBNK,kBAAiB/zB,EACjBg0B,mBAAkB59B,EAJpB,UAME,cAAC4yB,GAAA,EAAD,UAAchpB,IACd,cAAC6xB,GAAA,EAAD,UAAgBz7B,IAChB,eAAC07B,GAAA,EAAD,WACE,cAACtJ,GAAA,EAAD,CAAQ5mB,QAlBC,gBACF1P,IAAT0hC,GACFA,IAEFF,GAAU,IAcuB51B,MAAM,UAAjC,SAA4Cg2B,IAC5C,cAACtL,GAAA,EAAD,CAAQ5mB,QAxBE,WAChB+xB,IACAD,GAAU,IAsBwB51B,MAAM,UAAUm2B,WAAS,EAArD,SAAuDJ,aC9CpDK,GAAuB,SAAC12B,EAAe22B,GAChD,IAAMC,EAAeD,EAAQ1gC,QAAO,SAAA4gC,GAAM,OAAIA,EAAO72B,QAAUA,EAAQ,MACjEvJ,EAASmgC,EAAangC,OAC5B,GAAe,IAAXA,EACA,OAAOmgC,EAAa,GAExB,GAAe,IAAXngC,EACA,MAAM,IAAIC,MAAM,qDAAuDsJ,GAE3E,MAAM,IAAItJ,MAAM,gEAAkEsJ,IC+CzE82B,GAAgB,mBAEvBC,GAA8C,SAAC,GAWvB,IAAD,gBAV3B94B,EAU2B,EAV3BA,QACA0zB,EAS2B,EAT3BA,eACAqF,EAQ2B,EAR3BA,MACAC,EAO2B,EAP3BA,SACAljC,EAM2B,EAN3BA,WACA0P,EAK2B,EAL3BA,KACAyzB,EAI2B,EAJ3BA,cACAC,EAG2B,EAH3BA,YACAngC,EAE2B,EAF3BA,OACAqjB,EAC2B,EAD3BA,eAEMrZ,EAAUd,KAChB,EAA8CnB,oBAAkB,GAAhE,mBAAOq4B,EAAP,KAAwBC,EAAxB,KAEA,EAA2D94B,IAAnDS,EAAR,EAAQA,MAAOc,EAAf,EAAeA,eAAgBT,EAA/B,EAA+BA,wBAsBzBi4B,EAAqB,kBAAYJ,KAEjCK,EAAU,WACd,OAAO9zB,GAAQxF,EAAQu5B,aAAa71B,WAAa1D,EAAQw5B,sBAAsB91B,WAAa1D,EAAQy5B,WAAW/1B,WAAa1D,EAAQ05B,gBAAgBh2B,YAAc1D,EAAQ05B,gBAAgB/1B,YAGtLg2B,EAAa,uCAAG,sCAAAv9B,EAAA,2DAEL3F,KADTmyB,EADc,UACe5oB,EAAQu5B,aAAa31B,YADpC,aACe,EAA2Bwc,MAAK,SAAApX,GAAC,OAAIA,EAAE7P,KAAO4/B,EAAMa,oBACrC,KAAtBb,EAAMr0B,aAAsB1E,EAAQ65B,YAAYn2B,WAAa1D,EAAQw5B,sBAAsB91B,WAAa1D,EAAQ85B,cAAcp2B,gBAAsCjN,IAAzBsiC,EAAMgB,iBAAuD,IAAvB3d,EAAejjB,IAC1N6/B,EAAS,CAAExc,KAAM,kBAAmBwd,QAAS,KACvCpQ,EAAmC6O,GAAqBM,EAAMtQ,YAAazoB,EAAQw5B,sBAAsB51B,MACzGq2B,EAAU,IAAIzR,GAAkBpM,EAAejjB,GAAGhD,WAAYL,EAAYijC,EAAMgB,eAAgBhB,EAAMtQ,YAAamB,EAAgBzwB,GAAI6G,EAAQ65B,YAAYj2B,KAAM5D,EAAQ85B,cAAcl2B,KAAMs2B,IAAgBtR,EAAQmQ,EAAMr0B,aAC9NqkB,UAAUgQ,EAAMoB,YADH,UACgBn6B,EAAQo6B,YAAYx2B,YADpC,aACgB,EAA0Bwc,MAAK,SAAA0K,GAAC,OAAIA,EAAE3xB,KAAO4/B,EAAMsB,iBAAgBtB,EAAMlQ,aACzGyR,EAAuBL,KAEjBM,OAAoC9jC,IAAzBsiC,EAAMgB,eAA+B,yBAC5B,IAAvB3d,EAAejjB,GAAY,yBAA2B,gBACzD6/B,EAAS,CAAExc,KAAM,kBAAmBwd,QAASO,KAX3B,2CAAH,qDAebD,EAAyB,SAACL,GAC9B,IAAIO,EAAwCC,EAAmBR,QACzCxjC,IAAlB+jC,GACFxB,EAAS,CAAExc,KAAM,YAAawd,SAAS,IACvCU,EAAeF,IAEfxB,EAAS,CAAExc,KAAM,kBAAmBwd,QAAS,gCAI3CS,EAAqB,SAACR,GAC1B,IAAIO,EAUJ,OATI9G,IAAmBhN,GAAegR,QAAUhE,IAAmBhN,GAAe4Q,IAChFkD,EAAgBP,EAAQ9P,YACfuJ,IAAmBhN,GAAe+Q,YACNhhC,IAAjCuJ,EAAQ05B,gBAAgB91B,KAC1B42B,EAAgBP,EAAQU,aAAa36B,EAAQ05B,gBAAgB91B,MAE7Do1B,EAAS,CAAExc,KAAM,kBAAmBwd,QAAS,kBAG1CQ,GAGHE,EAAiB,SAACF,GACtBx6B,EAAQ46B,aAAaC,OAAOL,EAAe,CACzCl3B,QAAS,WACP01B,EAAS,CAAExc,KAAM,YAAawd,SAAS,IACvChB,EAAS,CAAExc,KAAM,kBAAmBwd,QAAS,kBAE/Cc,UAAW,WACT9B,EAAS,CAAExc,KAAM,YAAawd,SAAS,IACvCX,QAkBA0B,EAAsC,gBACLtkC,IAAjCuJ,EAAQ05B,gBAAgB91B,KAC1B5D,EAAQg7B,eAAeH,OAAO76B,EAAQ05B,gBAAgB91B,KAAKzK,GAAI,CAC7D2hC,UAAW,SAACG,GACVjC,EAAS,CAAExc,KAAM,cAAewd,SAAS,IACrCiB,GACFC,IACA7B,KAEAL,EAAS,CAAExc,KAAM,kBAAmBwd,QAAS,sBAGjD12B,QAAS,SAACqV,GACRqgB,EAAS,CAAExc,KAAM,cAAewd,SAAS,IACzChB,EAAS,CAAExc,KAAM,kBAAmBwd,QAAS,uBAIjDhB,EAAS,CAAExc,KAAM,cAAewd,SAAS,IACzChB,EAAS,CAAExc,KAAM,kBAAmBwd,QAAS,kBAI3CkB,EAAyB,uCAAG,gCAAA9+B,EAAA,8DAClB3F,IAAVsK,QAA+CtK,IAAxB2lB,EAAeI,KADV,uBAExBiH,EAAiBrH,EAAeI,KACtCzb,EAAMo6B,iBAAiB/e,EAAejjB,GAAIsqB,GACpCkR,EAAoB5zB,EAAM6zB,cAAcnR,GAJhB,SAKT5hB,EAAegzB,2BAA2BC,aAAah/B,EAAY2tB,EAAgBkR,GAL1E,OAKxBI,EALwB,OAM9B3zB,OAAkC3K,IAAVsK,EAAsBA,EAAMq6B,0BAA4B,GAC3ErG,GACHiE,EAAS,CAAExc,KAAM,kBAAmBwd,QAAS,2BARjB,2CAAH,qDAazBqB,EAAY,SAACvlC,EAAoBiB,EAAmBD,EAAsB2sB,GAC9E,QAAuBhtB,IAAnBgtB,EACF,QAA6BhtB,IAAzBsiC,EAAMa,eACRZ,EAAS,CAAExc,KAAM,kBAAmBwd,QAAS,4CACxC,QAAkCvjC,IAA9BuJ,EAAQu5B,aAAa31B,KAC9Bo1B,EAAS,CAAExc,KAAM,kBAAmBwd,QAAS,iCAG7C,IACE,IAAMsB,EAAazyB,GAA4B7I,EAAQu5B,aAAa31B,KAAMm1B,EAAMa,gBAChFV,EAAYpjC,EAAYiB,EAAWD,EAAcwkC,EAAY5H,GAC7D,MAAOz+B,GACP,KAAIA,aAAiB2T,IAInB,MAAM3T,EAHNG,QAAQH,MAAMA,EAAOA,EAAMsmC,OAC3BvC,EAAS,CAAExc,KAAM,kBAAmBwd,QAAS,uDAOnDhB,EAAS,CAAExc,KAAM,kBAAmBwd,QAAS,KAC7Cd,EAAYpjC,EAAYiB,EAAWD,EAAc2sB,EAAgBiQ,IAI/D8H,EAAiB,SAACzkC,EAA+B0kC,GACrD,YAA6BhlC,IAAtBglC,GAAkC1kC,IAAc0kC,EAAkBplB,MAAM,EAAG,KAgB9E6jB,EAAe,WACnB,IAAMwB,EAAe3iC,EAAOqnB,MAAK,SAAA1jB,GAAC,OAAI8+B,EAAezC,EAAM4C,iBAAkBj/B,MAC7E,QAAqBjG,IAAjBilC,QAAwCjlC,IAAVsK,QAA+CtK,IAAxB2lB,EAAeI,KAAoB,CAC1F,IAAM4O,EAAUrqB,EAAMy0B,qBAAqBpZ,EAAejjB,GAAIuiC,EAActf,EAAeI,MAC3F,ObvPuB,SAAC4O,EAAoB8J,EAA4B5K,EAAoBC,GAChG,IAAMkL,EAAc9O,GAAY+O,aAAatK,EAAQxnB,KAAM0mB,EAAW4K,EAAoB3K,EAAY2K,EAAoBtrB,GAAa+rB,KAEvI,OADAF,EAAYN,QAAQD,GACb9K,GAA8BqL,EAAYpL,YAAY,GAAIC,EAAYC,GaoPlEqR,CAAcxQ,EH1NO,IG0NsBA,EAAQ7nB,MH1N9B,EG0N0D6nB,EAAQnf,QAEhG,OAAO,IAAIqc,GAAU,EAAG,EAAG,EAAG,IAG1BuT,EAAkB,kBAAMlR,GAAevO,EAAeI,KAAhB,OAAsBzb,QAAtB,IAAsBA,OAAtB,EAAsBA,EAAOwN,mBAEnEutB,EAAc,CAClB,CAAE/5B,MAAO,EAAGssB,MAAO,KACnB,CAAEtsB,MAAO,GAAIssB,MAAO,KACpB,CAAEtsB,MAAO,GAAIssB,MAAO,KACpB,CAAEtsB,MAAO,GAAIssB,MAAO,KACpB,CAAEtsB,MAAO,GAAIssB,MAAO,KACpB,CAAEtsB,MAAO,GAAIssB,MAAO,MAGtB,OACE,qCACE,cAAC,GAAD,CACE7oB,KAAMA,EACNS,QAASozB,EACT90B,MAAQ+0B,IAtCG,WACf,OAAQ5F,GACN,KAAKhN,GAAe4Q,IAClB,OAAO,qCAAE,cAAC,KAAD,CAAYj1B,MAAM,YAAYgC,SAAS,QAAQH,UAAWnB,EAAQ4hB,YAApE,oBACT,KAAK+B,GAAegR,OAClB,OAAO,qCAAE,cAAC,KAAD,CAA0Br1B,MAAM,UAAUgC,SAAS,QAAQH,UAAWnB,EAAQ4hB,YAAhF,sBAAiHvI,EAAejjB,GAAhI,OACT,KAAKutB,GAAe+Q,KAClB,OAAO,qCAAE,cAAC,KAAD,CAAgBp1B,MAAM,UAAUgC,SAAS,QAAQH,UAAWnB,EAAQ4hB,YAAtE,oBAAqGvI,EAAejjB,GAApH,OACT,QACE,MAAO,IA6B4B4iC,GAAf,aACpB3O,SAAS,KAJX,SAMGkM,IACC,qCACE,cAAClD,GAAA,EAAD,UACE,eAACvhC,EAAA,EAAD,CAAKqP,UAAWnB,EAAQihB,QAAxB,UACE,eAACnvB,EAAA,EAAD,CAAKgjC,GAAI,EAAGC,GAAI,EAAG5zB,UAAWnB,EAAQkhB,KAAtC,eAEaxtB,IAAVsK,GACC,cAAC,GAAD,CACEwrB,kBAAmBmH,IAAmBhN,GAAe+Q,KACrDnL,gBAAiByM,EAAMpF,OACvBlf,IAAKzU,EAAQg8B,mBAAmBp4B,KAChC4oB,SAAUxsB,EAAQg8B,mBAAmBr4B,WACrC8oB,OAAQ,WACN4O,EAAUvlC,EAAYiD,EAAOggC,EAAMkD,eAAgB7f,EAAejjB,GAAIijB,EAAeI,OAEvFkQ,eAAgB,kBArMZ31B,EAqMiCgC,EAAOggC,EAAMkD,oBApMpEjD,EAAS,CAAExc,KAAM,sBAAuBwd,QAASjjC,IAD5B,IAACA,GAsMJ41B,UAAW6O,EAAezC,EAAM4C,iBAAkB5iC,EAAOggC,EAAMkD,gBAC/D7Q,aAAiC30B,IAAxB2lB,EAAeI,KAAqBzb,EAAMy0B,qBAAqBpZ,EAAejjB,GAAIJ,EAAOggC,EAAMkD,eAAgB7f,EAAeI,WAAQ/lB,EAC/I4L,MAAOw5B,MAGX,eAAChnC,EAAA,EAAD,CAAKqP,UAAWnB,EAAQqhB,KAAxB,UAEE,cAACvvB,EAAA,EAAD,CAAKi4B,EAAG,EAAG5oB,UAAWnB,EAAQshB,KAA9B,SACGqP,IAAmBhN,GAAe+Q,MACjC,mCACE,cAACryB,GAAA,EAAD,8BACe,UAAApF,EAAQ05B,gBAAgB91B,YAAxB,eAA8BslB,SAAU,IAAIC,KAAKnpB,EAAQ05B,gBAAgB91B,KAAKslB,SAASgT,iBAAmB,WAK/H,eAACrnC,EAAA,EAAD,CAAKi4B,EAAG,EAAG5oB,UAAWnB,EAAQuhB,OAA9B,UACE,cAAClf,GAAA,EAAD,iCAGA,cAAC+xB,GAAA,EAAD,CACEh+B,GAAG,mBACHg9B,KAAM,KACNiB,MAAO0E,EACP/5B,MAAO+5B,EAAY/C,EAAMtQ,aAAa1mB,MACtC2sB,SAAU,SAACvnB,EAAwBkwB,GAAzB,OAnOP,SAAClwB,EAAwBkwB,GAChD2B,EAAS,CAAExc,KAAM,iBAAkBwd,QAAS8B,EAAYnN,WAAU,SAAAwN,GAAC,OAAIA,EAAEp6B,QAAUs1B,OAkOI+E,CAAiBj1B,EAAOkwB,MAG7F,cAAC,GAAD,CACErK,SAAU0G,IAAmBhN,GAAe4Q,IAC5ClJ,UAAU,EACVC,MAAM,kBACNC,MAAK,UAAEtuB,EAAQu5B,aAAa31B,YAAvB,aAAE,EAA2BvM,KAAI,SAAA2R,GAAC,OAAIA,EAAEjH,SAC7CA,MAAK,UAAE/B,EAAQu5B,aAAa31B,YAAvB,iBAAE,EAA2Bwc,MAAK,SAAApX,GAAC,OAAIA,EAAE7P,KAAO4/B,EAAMa,yBAAtD,aAAE,EAAqE73B,MAC5E+rB,SAAU,SAAC7C,GAAD,OAxPD,SAACA,GAC9B+N,EAAS,CAAExc,KAAM,mBAAoBwd,aAASvjC,IAC9C,IAAMmyB,OAA2DnyB,IAA9BuJ,EAAQu5B,aAAa31B,KAAqB5D,EAAQu5B,aAAa31B,KAAKqnB,QAAYx0B,EACnHuiC,EAAS,CAAExc,KAAM,oBAAqBwd,QAAO,OAAEpR,QAAF,IAAEA,OAAF,EAAEA,EAAQzvB,KAqPHkjC,CAAuBpR,OAGvD8N,EAAMoB,aACN,cAAC,GAAD,CACE9L,MAAM,QACNC,MAAK,UAAEtuB,EAAQo6B,YAAYx2B,YAAtB,aAAE,EAA0BvM,KAAI,SAAAyzB,GAAC,OAAIA,EAAE/oB,SAC5CA,MAAK,UAAE/B,EAAQo6B,YAAYx2B,YAAtB,iBAAE,EAA0Bwc,MAAK,SAAA0K,GAAC,OAAIA,EAAE3xB,KAAO4/B,EAAMsB,wBAArD,aAAE,EAAmEt4B,MAC1E+rB,SAAU,SAAC7C,GAAD,OA1PN,SAACA,GAC3B+N,EAAS,CAAExc,KAAM,iBAAkBwd,QAAS,KAC5C,IAAMlR,OAAwDryB,IAA7BuJ,EAAQo6B,YAAYx2B,KAAqB5D,EAAQo6B,YAAYx2B,KAAKqnB,QAAYx0B,EAC/GuiC,EAAS,CAAExc,KAAM,mBAAoBwd,QAAO,OAAElR,QAAF,IAAEA,OAAF,EAAEA,EAAO3vB,KAuPCmjC,CAAoBrR,MAGvD8N,EAAMoB,aACL,cAACoC,GAAA,EAAD,CACEx6B,MAAOg3B,EAAMlQ,YACbxjB,QAAQ,WACRgB,OAAO,QACPlN,GAAG,kBACHk1B,MAAM,eACN7C,WAAS,EACTkD,SAAU,SAAC/V,GAAD,OAAyCqgB,EAAS,CAAExc,KAAM,iBAAkBwd,QAASrhB,EAAEvR,cAAcrF,WAGnH,cAAC00B,GAAA,EAAD,CACEC,QACE,cAAC8F,GAAA,EAAD,CACE1F,QAASiC,EAAMoB,YACfzL,SAAU,SAACvnB,EAAsC2vB,GAAvC,OAA4DkC,EAAS,CAAExc,KAAM,iBAAkBwd,QAASlD,KAClHC,KAAK,oBACL10B,MAAM,YAGVgsB,MAAM,iBAGR,cAACkO,GAAA,EAAD,CACEnO,UAAQ,EACR/oB,QAAQ,WACRgpB,MAAM,cACNhoB,OAAO,QACPlN,GAAG,wBACHqyB,WAAS,EACTiR,WAAS,EACTC,KAAK,IACL36B,MAAOg3B,EAAMr0B,YACbgqB,SAAU,SAAC/V,GAAD,OAAsCqgB,EAAS,CAAExc,KAAM,iBAAkBwd,QAASrhB,EAAEiW,OAAO7sB,oBAO7G,cAAClN,EAAA,EAAD,CAAKqP,UAAWnB,EAAQhK,OAAQ4jC,GAAI,EAAG9E,GAAI,EAAGC,GAAI,EAAlD,cACarhC,IAAVsK,IAAA,UAAuBf,EAAQy5B,WAAW71B,YAA1C,aAAuB,EAAyBvM,KAAI,SAAC4B,EAAOyD,GAAR,OACnD,cAAC,GAAD,CAEE+X,IAAKxb,EACLmyB,aAAiC30B,IAAxB2lB,EAAeI,KAAqBzb,EAAMy0B,qBAAqBpZ,EAAejjB,GAAIJ,EAAO2D,GAAI0f,EAAeI,WAAQ/lB,EAC7Hw0B,SAAUvuB,IAAMq8B,EAAMkD,cACtBtP,UAAW6O,EAAezC,EAAM4C,iBAAkB5iC,EAAO2D,IACzDoxB,SAAU,kBAAMkL,EAAS,CAAExc,KAAM,mBAAoBwd,QAASt9B,KAC9D+vB,OAAQ,WACN4O,EAAUvlC,EAAYiD,EAAO2D,GAAI0f,EAAejjB,GAAIijB,EAAeI,OAErEna,MAAOw5B,KATFn/B,cAgBf,eAAC25B,GAAA,EAAD,WACE,cAACjxB,GAAA,EAAD,CAAY/C,MAAM,QAAlB,SACG02B,EAAM5jC,eAET,cAAC43B,GAAA,EAAD,CACE5mB,QAASkzB,EACTh3B,MAAM,UACNgD,QAAQ,WACR2nB,SAAU+L,EAAMpF,OAJlB,oBAQA,cAAC5G,GAAA,EAAD,CACE5mB,QAAS,kBAAMizB,GAAmB,IAClC/2B,MAAM,UACNgD,QAAQ,WACR2nB,SAAU+L,EAAMpF,QAAUoF,EAAM6D,UAAYlJ,IAAmBhN,GAAe4Q,IAJhF,SAMGyB,EAAM6D,SAAW,cAAgB,WAEpC,cAAC7P,GAAA,EAAD,CACE5mB,QAASwzB,EACTt3B,MAAM,UACNgD,QAAQ,WACR2nB,SAAU+L,EAAMpF,OAJlB,SAMGoF,EAAMpF,OAAS,YAAc,eAKpC,cAAC9+B,EAAA,EAAD,CAAKqP,UAAWnB,EAAQ0hB,QAAxB,SACE,cAACmI,GAAA,EAAD,QAKN,cAAC,GAAD,CACEroB,MAAM,oBACN5J,KAAK,kDACL09B,QAAQ,KACRD,SAAS,MACTH,UAAW,SAACzyB,GAAD,OAAmB4zB,EAAmB5zB,IACjDA,KAAM2zB,EACNjB,MAAO,gBA3RGzhC,IAAVsK,IACE2yB,IAAmBhN,GAAegR,QACpCwD,IACA7B,KAEO3F,IAAmBhN,GAAe+Q,OACzCuB,EAAS,CAAExc,KAAM,cAAewd,SAAS,IACzCe,aC/FK8B,GAAgC,CAC3CjD,oBAAgBnjC,EAChBtB,aAAc,GACd0zB,YAAa,GACbsR,aAAa,EACbE,mBAAe5jC,EACfwlC,cAAe,EACflC,oBAAgBtjC,EAChBklC,sBAAkBllC,EAClBk9B,QAAQ,EACRiJ,UAAU,EACVnU,YAAa,EACb/jB,YAAa,IAGFo4B,GAAoB,SAAC/D,EAAcgE,GAC9C,OAAQA,EAAOvgB,MACb,IAAK,WACH,OAAO,gBAAKqgB,IACd,IAAK,oBACH,OAAO,6BAAK9D,GAAZ,IAAmBa,eAAgBmD,EAAO/C,UAC5C,IAAK,kBACH,OAAO,6BAAKjB,GAAZ,IAAmB5jC,aAAc4nC,EAAO/C,UAC1C,IAAK,iBACH,OAAO,6BAAKjB,GAAZ,IAAmBlQ,YAAakU,EAAO/C,UACzC,IAAK,iBACH,OAAO,6BAAKjB,GAAZ,IAAmBoB,YAAa4C,EAAO/C,UACzC,IAAK,mBACH,OAAO,6BAAKjB,GAAZ,IAAmBsB,cAAe0C,EAAO/C,UAC3C,IAAK,mBACH,OAAO,6BAAKjB,GAAZ,IAAmBkD,cAAec,EAAO/C,UAC3C,IAAK,oBACH,OAAO,6BAAKjB,GAAZ,IAAmBgB,eAAgBgD,EAAO/C,UAC5C,IAAK,sBACH,OAAO,6BAAKjB,GAAZ,IAAmB4C,iBAAkBoB,EAAO/C,UAC9C,IAAK,YACH,OAAO,6BAAKjB,GAAZ,IAAmBpF,OAAQoJ,EAAO/C,UACpC,IAAK,cACH,OAAO,6BAAKjB,GAAZ,IAAmB6D,SAAUG,EAAO/C,UACtC,IAAK,iBACH,OAAO,6BAAKjB,GAAZ,IAAmBtQ,YAAasU,EAAO/C,UACzC,IAAK,iBACH,OAAO,6BAAKjB,GAAZ,IAAmBr0B,YAAaq4B,EAAO/C,UACzC,QACE,OAAOjB,I,oBhB1FDrS,O,mBAAAA,I,aAAAA,I,eAAAA,I,sBAAAA,Q,KAOL,IAAMsW,GAA8C,SAAC,GAO9B,IAN5B5gB,EAM2B,EAN3BA,eACArjB,EAK2B,EAL3BA,OACAkkC,EAI2B,EAJ3BA,qBACAnnC,EAG2B,EAH3BA,WACAonC,EAE2B,EAF3BA,uBACAC,EAC2B,EAD3BA,0BAEA,EAA4Cr8B,oBAAkB,GAA9D,mBAAOs8B,EAAP,KAAuBC,EAAvB,KACA,EAAuG/8B,IAA/FV,EAAR,EAAQA,YAAaiC,EAArB,EAAqBA,eAAgBjB,EAArC,EAAqCA,QAASG,EAA9C,EAA8CA,MAAOG,EAArD,EAAqDA,qBAAsBE,EAA3E,EAA2EA,wBAG3E,EAA0CN,mBAAiB,IAA3D,mBAAOw8B,EAAP,KAAsBC,EAAtB,KACA,EAA4Cz8B,oBAAkB,GAA9D,mBAAO08B,EAAP,KAAuBC,EAAvB,KACA,EAAgD38B,oBAAkB,GAAlE,mBAAO48B,EAAP,KAAyBC,EAAzB,KACA,EAAoD78B,mBAAiB,IAArE,mBAAO88B,EAAP,KAA2BC,EAA3B,KACA,EAAoD/8B,mBAAyB4lB,GAAekR,SAA5F,mBAAOkG,EAAP,KAA2BC,EAA3B,KAUA,EAA0BC,qBAAWlB,GAAmBD,IAAxD,mBAAO9D,EAAP,KAAcC,EAAd,KACA,EAA4Cl4B,mBAAyB4lB,GAAekR,SAApF,mBAAOlE,EAAP,KAAuBuK,EAAvB,KASMC,EAAuB,YAPL,WAAO,IAAD,EAC5B,UAAAzE,GAAW71B,YAAX,SAAiBhM,SAAQ,SAAAsG,GAAG,OAAIX,IAAI4gC,gBAAgBjgC,WACpBzH,IAA5BulC,GAAmBp4B,MACrBrG,IAAI4gC,gBAAJ,OAAoBnC,SAApB,IAAoBA,QAApB,EAAoBA,GAAoBp4B,MAK1Cw6B,GACAx+B,EAAYy+B,kBAAkBxF,IAC9BG,EAAS,CAAExc,KAAM,cAGbqd,GAAcz2B,YAAiB,CAAC,SAAUy1B,IAApB,sBAAoC,sBAAAz8B,EAAA,sEAAkByF,EAAe7C,uBAAuBs/B,YAAxD,mFAAqE,CAAEj7B,QAAqB,OAAZzC,IAC1Ik5B,GAAgB12B,YAAiB,CAAC,WAAYy1B,IAAtB,sBAAsC,sBAAAz8B,EAAA,sEAAkByF,EAAe7C,uBAAuBhJ,qBAAxD,mFAA8E,CAAEqN,QAAqB,OAAZzC,IAEvJ24B,GAAen2B,YAAmB,CAAC,UAAWy1B,IAAvB,sBAAuC,sBAAAz8B,EAAA,sEAAkByF,EAAe08B,uBAAuBC,aAAxD,mFAClE,CACEn7B,QAAqB,OAAZzC,EACT0C,QAAS,SAACqV,GAAD,OAAOvjB,QAAQH,MAAM,yBAA0B0jB,MAGtD6gB,GAAwBp2B,YAA4B,CAAC,mBAAoBy1B,IAAzC,sBAAyD,sBAAAz8B,EAAA,sEAAkByF,EAAe08B,uBAAuBE,sBAAxD,mFAA+E,CAAEp7B,QAAqB,OAAZzC,IAEnL89B,GAAoBt7B,YAA6B,CAAC,iBAAkBy1B,GAAeE,EAAM4C,kBAA7D,sBAChC,sBAAAv/B,EAAA,sEAAkByF,EAAe08B,uBAAuBhmC,sBAAsBzC,EAAYijC,EAAM4C,kBAAhG,mFACA,CACEt4B,SAAU45B,GAAwBG,SAA8C3mC,IAA3BsiC,EAAM4C,iBAC3Db,UAAW,SAACl3B,GACVo1B,EAAS,CAAExc,KAAM,oBAAqBwd,QAASp2B,KAEjDN,QAAS,SAACqV,GAAD,OAAOvjB,QAAQH,MAAM,0BAA2B0jB,MAGvD+gB,GAAkBt2B,YAAiC,CAAC,aAAcy1B,IAAxC,sBAC9B,8BAAAz8B,EAAA,sEAC8CyF,EAAe08B,uBAAuBI,iCAAiC7oC,GADrH,cACQ8N,EADR,QAEQg7B,EAAaC,MAAMC,KAAKl7B,EAAKm7B,SACpBvmC,OAAS,GACtB0I,EAAqB09B,GAJzB,kBAMSh7B,EAAK3M,IAAI,GAAKmlB,EAAejjB,KANtC,2CAQA,CACEkK,SAAU45B,GAAwBG,SAAyC3mC,IAAtB2lB,EAAejjB,IAAgC,OAAZyH,GAAoB24B,GAAa71B,UACzHo3B,UAAW,SAACl3B,GACVxC,OAAkC3K,IAAVsK,EAAsBA,EAAMq6B,0BAA4B,QACnE3kC,IAATmN,EACEwY,EAAe4iB,MAEjBf,EAAkBvX,GAAe4Q,MAGjC2G,EAAkBvX,GAAegR,aACLjhC,IAAxB2lB,EAAeI,WAA4C/lB,IAAtB8iC,GAAa31B,MACpDo1B,EAAS,CAAExc,KAAM,oBAAqBwd,QAASzwB,GAA4BgwB,GAAa31B,KAAMwY,EAAeI,UAKjHyhB,EAAkBvX,GAAe+Q,MACR,OAArB7zB,EAAKilB,aAA6C,KAArBjlB,EAAKilB,cACpCmQ,EAAS,CAAExc,KAAM,iBAAkBwd,SAAS,IAC5ChB,EAAS,CAAExc,KAAM,iBAAkBwd,QAASp2B,EAAKilB,eAEnDmQ,EAAS,CAAExc,KAAM,oBAAqBwd,QAASp2B,EAAKme,mBACpDiX,EAAS,CAAExc,KAAM,mBAAoBwd,QAAkC,OAAzBp2B,EAAKylB,gBAA2BzlB,EAAKylB,qBAAkB5yB,IACrGuiC,EAAS,CAAExc,KAAM,iBAAkBwd,QAASp2B,EAAK6kB,cACjDuQ,EAAS,CAAExc,KAAM,iBAAkBwd,SAA2B,OAAjBp2B,EAAKpK,QAAmBoK,EAAKpK,QAA7B,UAA0C4iB,EAAejjB,GAAzD,MAAgEO,MAAM,KAAK,KACxHs/B,EAAS,CAAExc,KAAM,oBAAqBwd,QAASp2B,EAAKzM,YAGxDmM,QAAS,SAACqV,GAAD,OAAOvjB,QAAQH,MAAM,4BAA6B0jB,MAGzDsmB,GAAwB77B,YAA6B,CAAC,mBAAoBy1B,GAAeE,EAAMgB,gBAA/D,sBACpC,sBAAA39B,EAAA,sEAAkByF,EAAe08B,uBAAuBW,sBAAsBppC,EAAYijC,EAAMgB,gBAAhG,mFACA,CACE12B,SAAU45B,GAAwBG,IAAmB1D,GAAgBh2B,UACrEo3B,UAAW,SAACl3B,GACVo1B,EAAS,CAAExc,KAAM,sBAAuBwd,QAASp2B,KAEnDN,QAAS,SAACqV,GAAD,OAAOvjB,QAAQH,MAAM,4BAA6B0jB,MAGzD8gB,GAAar2B,YAAmB,CAAC,QAASy1B,IAArB,sBAAqC,sBAAAz8B,EAAA,sEAAkByF,EAC/EyzB,wBACA6J,sBAAsBrpC,EAAY+L,EAAeyzB,wBAAwB8J,yBAAyBrmC,IAFrC,mFAE+C,CAC3GsK,SAAU45B,GAAwBG,IAAmB6B,GAAsBv7B,WAAa3K,EAAOP,OAAS,EACxG8K,QAAS,SAACqV,GAAD,OAAOvjB,QAAQH,MAAM,wBAAyB0jB,MAGrDqjB,GAAqB54B,YAAiB,CAAC,gBAAiBy1B,GAAeE,EAAMkD,eAAhD,sBAAgE,sBAAA7/B,EAAA,sEAAkByF,EAAeyzB,wBAAwB13B,oBAAoB9H,EAAYiD,EAAOggC,EAAMkD,gBAAtG,mFACjG,CACE54B,SAAU45B,GAAwBG,IAAmBrkC,EAAOP,OAAS,EACrE8K,QAAS,SAACqV,GAAD,OAAOvjB,QAAQH,MAAM,gCAAiC0jB,MAG7DyhB,GAAch3B,YAAkB,CAAC,SAAUy1B,GAAeE,EAAMa,gBAA1C,sBAA2D,sBAAAx9B,EAAA,sEAAkByF,EAAe08B,uBAAuBc,aAAatG,EAAMa,gBAA3E,mFACrF,CACEv2B,aAAkC5M,IAAzBsiC,EAAMa,eACft2B,QAAS,SAACqV,GAAD,OAAOvjB,QAAQH,MAAM,wBAAyB0jB,MAGrDiiB,GAAe0E,aAAW,uCAAC,WAAOzoC,GAAP,SAAAuF,EAAA,sEAAwCyF,EAAe08B,uBAAuB7D,eAAe7jC,GAA7F,mFAAD,sDAC9B,CACEyM,QAAS,SAACqV,GAAD,OAAOvjB,QAAQH,MAAM,0BAA2B0jB,MAGvDqiB,GAAiBsE,aAAW,uCAAC,WAAOxoC,GAAP,SAAAsF,EAAA,sEAAsCyF,EAAe08B,uBAAuBpD,iBAAiBrkC,GAA7F,mFAAD,uDAElC,OACE,qCACE,cAAC,GAAD,CACEkJ,QAAS,CACP65B,eACAC,iBACAP,gBACAC,yBACAkF,qBACAhF,mBACAuF,yBACAxF,cACAuC,sBACA5B,eACAQ,gBACAI,mBAEFtH,eAAgBA,EAChBqF,MAAOA,EACPC,SAAUA,EACVljC,WAAYA,EACZ0P,KAAMy3B,EACNhE,cAAe,WACbkE,GAA0B,GAC1Be,KAEFhF,YAAa,SAACpjC,EAAoBiB,EAAmBD,EAAsB2sB,EAAqCiQ,IArJ5F,SAAC59B,EAAoBiB,EAAmBD,EAAsB2sB,EAAwBiQ,GAC9G+J,EAAkB3nC,GAClBynC,EAAiBxmC,GACjB4mC,EAAoB7mC,GACpB+mC,EAAsBpa,GACtBsa,EAAsBrK,GAiJhB6L,CAAkBzpC,EAAYiB,EAAWD,EAAc2sB,EAAgBiQ,GACvE2J,GAAkB,GAClBF,GAA0B,IAE5B/gB,eAAgBA,EAChBrjB,OAAQA,IAEV,cAAC,GAAD,CACEkN,QAAS,WACPo3B,GAAkB,GAClBa,KAEFzK,SAAU,WACR0J,GAA0B,GAC1BE,GAAkB,IAEpB7J,QAAS,SAACpX,EAAgCqH,EAAqCgR,QAC/Dh+B,IAAVg+B,GACFyI,EAAuB,6BAAK9gB,GAAN,IAAsBjjB,GAAIs7B,EAAOuK,OAAO,EAAOxiB,KAAMiH,KAE7E0Z,GAA0B,GAC1BE,GAAkB,IAEpBjhB,eAAgBA,EAChB5W,KAAM43B,EACN74B,MAAM,OACNxN,UAAWumC,EACXxmC,aAAc4mC,EACdja,eAAgBma,EAChB9nC,WAAY0nC,EACZ9J,eAAgBoK,QiBlMT77B,GA9BUC,aAAW,SAAAC,GAAK,MAAK,CAC7Cq9B,QAAS,CACRj8B,MAAO,IACPqqB,gBAAiB,4BACjBF,aAAc,EACdzoB,SAAU,WACVsjB,IAAKpmB,EAAMO,QAAQ,GAAK,EACxBuiB,KAAM,GAEPwa,SAAU,CACTl8B,MAAO,QAERogB,QAAS,CACRpgB,MAAO,QAERm8B,OAAQ,CACPz6B,SAAU,WACVsjB,IAAK,GACLrjB,MAAO,IAERy6B,WAAY,CACXp8B,MAAO,GACP0I,OAAQ,GACR2Y,MAAO,OACP7f,UAAW,EACXogB,YAAa,EACbuI,aAAc,W,0CCbHkS,GAAiB,WAC5B,IACM78B,EAAUd,KAChB,EAA4CnB,mBAA0B,IAAtE,mBAAO++B,EAAP,KAAuBC,EAAvB,KACA,EAA8Bh/B,mBAHP,IAGvB,mBAAO6iB,EAAP,KAAgBoc,EAAhB,KACA,EAAgCj/B,oBAAkB,GAAlD,mBAAOk/B,EAAP,KAAiBC,EAAjB,KACA,EAAwCn/B,oBAAkB,GAA1D,mBAAOo/B,EAAP,KAAqBC,EAArB,KACA,EAA8Cr/B,oBAAkB,GAAhE,mBAAOs/B,EAAP,KAAwBC,EAAxB,KACA,EAAkDv/B,oBAAkB,GAApE,mBAAOw/B,EAAP,KAA0BC,EAA1B,KACA,EAAqCjgC,IAA7BS,EAAR,EAAQA,MAAOE,EAAf,EAAeA,kBAEf2qB,qBAAU,gBACMn1B,IAAVsK,IACFg/B,EAAsC,IAA3Bh/B,EAAMy/B,oBACjBV,EAAkB/+B,EAAM0/B,8BAA8BppC,KAAI,SAAAqpC,GAAc,MAAO,CAAEA,WAAUC,SAAS,UAErG,CAAC5/B,IAEJ6qB,qBAAU,gBACMn1B,IAAVsK,GACFA,EAAM6/B,iBAA2B,IAAVjd,KAExB,CAAC5iB,EAAO4iB,IAEXiI,qBAAU,gBACMn1B,IAAVsK,GACFA,EAAM8/B,mBAAmBX,KAE1B,CAACn/B,EAAOm/B,IAEXtU,qBAAU,gBACMn1B,IAAVsK,IACEq/B,GAAmBE,EACrBv/B,EAAM+/B,sBAEEV,GAAmBE,EAE3Bv/B,EAAMggC,gBAAgB9/B,EAAkB5J,KAAI,SAAAshB,GAAC,OAAIzV,SAASyV,OAEnDynB,IAAoBE,EAE3Bv/B,EAAMigC,gBAAgB//B,EAAkB5J,KAAI,SAAAshB,GAAC,OAAIzV,SAASyV,OAG1D5X,EAAMkgC,wBAGT,CAAClgC,EAAOE,EAAmBm/B,EAAiBE,IAE/C,IAQMY,EAAgB,SAACpK,EAAkB4J,GACvC,QAAcjqC,IAAVsK,EAAqB,CACvB,IAAMogC,EAAc,aAAOpgC,EAAM0/B,+BACjC,GAAK3J,EAIHqK,EAAKC,OAAOD,EAAK3oC,OAAQ,EAAGkoC,OAJhB,CACZ,IAAIhkC,EAAYykC,EAAKp6B,QAAQ25B,GAC7BS,EAAKC,OAAO1kC,EAAG,GAIjBqE,EAAMsgC,4BAA4BF,KAIhCG,EAAgB,SAACxK,EAAkB4J,GACvC,IAAIa,EAAa1B,EAAelR,WAAU,SAAAnP,GAAC,OAAIA,EAAEkhB,WAAaA,KAC9Db,EAAe0B,GAAIZ,QAAU7J,EAC7BgJ,EAAkB,aAAID,KAclB2B,EAAW,SAACd,GAChB,IAAM1a,EAAQrd,GAAsB5B,QAAQ25B,GACtCr+B,EAAQsoB,GAAe+V,EAAD,OAAW3/B,QAAX,IAAWA,OAAX,EAAWA,EAAOwN,kBAE9C,OACE,gCACE,qBAAKgT,MAAO,CAAEC,WAAYnf,GAAS6B,UAAWnB,EAAQ48B,aACrDj3B,GAAiBsd,OAKxB,OACE,sBAAK9hB,UAAWnB,EAAQy8B,QAAxB,UACGQ,EACC,cAAC94B,GAAA,EAAD,CACEhD,UAAWnB,EAAQ28B,OACnBhc,KAAK,QACLvd,QAAS,kBAAM85B,GAAaD,IAH9B,SAIE,cAAC,KAAD,MAGF,cAAC94B,GAAA,EAAD,CACEhD,UAAWnB,EAAQ28B,OACnBhc,KAAK,QACLvd,QAAS,kBAAM85B,GAAaD,IAH9B,SAIE,cAAC,KAAD,MAGHA,EACC,eAACnrC,EAAA,EAAD,CAAKi4B,EAAG,EAAR,UACG+S,EAAexoC,KAAI,SAAC2R,EAAGtM,GAAJ,OAClB,cAAC+5B,GAAA,EAAD,CACEvyB,UAAWnB,EAAQ08B,SAEnB/I,QACE,cAACC,GAAA,EAAD,CACEC,KAAM,cAAC,KAAD,CAA0BvyB,SAAS,UACzCwyB,YAAa,cAAC,KAAD,CAAcxyB,SAAS,UACpCyyB,QAAS+I,EAAenjC,GAAGikC,QAC3BjS,SAAU,SAAC/V,GAAD,OA9EH,SAACA,EAAkC+nB,GACxD,IAAM5J,EAAmBne,EAAEiW,OAAOkI,aACpBrgC,IAAVsK,IACFmgC,EAAcpK,EAAS4J,GACvBY,EAAcxK,EAAS4J,IA0EqCe,CAAe9oB,EAAG3P,EAAE03B,WACpE3J,KAAK,SACL10B,MAAM,YAGVgsB,MAAOmT,EAASx4B,EAAE03B,WAXbhkC,MAcT,uBACA,eAAC0I,GAAA,EAAD,CAAYjM,GAAG,kBAAf,sBACYwqB,EADZ,QAGA,cAACwT,GAAA,EAAD,CACEh+B,GAAG,iBACH+K,UAAWnB,EAAQ4gB,QACnB5hB,MAAO4hB,EACPuS,IAAK,EACLhgB,IAAK,IACLwY,SAAU,SAACvnB,EAAwBkwB,GAAzB,OAAyD0I,EAAW1I,MAEhF,cAACZ,GAAA,EAAD,CACEvyB,UAAWnB,EAAQ08B,SAEnB/I,QACE,cAACC,GAAA,EAAD,CACEC,KAAM,cAAC,KAAD,CAA0BvyB,SAAS,UACzCwyB,YAAa,cAAC,KAAD,CAAcxyB,SAAS,UACpCyyB,QAASoJ,EACTxR,SAAU,SAAC/V,EAAoB0e,GAArB,OAA4C8I,EAAgB9I,IACtEN,KAAK,QACL10B,MAAM,YAGVgsB,MAAM,cAXF,SAaN,cAACoI,GAAA,EAAD,CACEvyB,UAAWnB,EAAQ08B,SAEnB/I,QACE,cAACC,GAAA,EAAD,CACEC,KAAM,cAAC,KAAD,CAA0BvyB,SAAS,UACzCwyB,YAAa,cAAC,KAAD,CAAcxyB,SAAS,UACpCyyB,QAASsJ,EACT1R,SAAU,SAAC/V,EAAoB0e,GAArB,OAA4CgJ,EAAmBhJ,IACzEN,KAAK,WACL10B,MAAM,YAGVgsB,MAAM,iBAXF,YAaN,cAACoI,GAAA,EAAD,CACEvyB,UAAWnB,EAAQ08B,SAEnB/I,QACE,cAACC,GAAA,EAAD,CACEC,KAAM,cAAC,KAAD,CAA0BvyB,SAAS,UACzCwyB,YAAa,cAAC,KAAD,CAAcxyB,SAAS,UACpCyyB,QAASwJ,EACT5R,SAAU,SAAC/V,EAAoB0e,GAArB,OAA4CkJ,EAAqBlJ,IAC3EN,KAAK,aACL10B,MAAM,YAGVgsB,MAAM,mBAXF,cAaN,cAACtB,GAAA,EAAD,CAAQrJ,KAAK,QAAQre,QAAQ,WAAWc,QAAS,gBAnHzC1P,IAAVsK,IACFA,EAAMsgC,4BAA4B14B,IAClCm3B,EAAkB/+B,EAAM0/B,8BAA8BppC,KAAI,SAAAqpC,GAAc,MAAO,CAAEA,WAAUC,SAAS,OACpGZ,EA/EmB,IAgFnBM,GAAmB,GACnBE,GAAqB,GACrBJ,GAAgB,KA6GZ,sBAGF,eAACtrC,EAAA,EAAD,CAAKi4B,EAAG,EAAR,UACG,aAAI+S,GAAgB7nC,QAAO,SAAAwnB,GAAC,OAAIA,EAAEmhB,WAASnoC,OAAS,gBADvD,MAC2EmrB,EAD3E,WC1MK+d,GAAb,oDAEE,WAAa5rC,EAAY+L,GAAiB,IAAD,8BACvC,gBACK/L,WAAaA,EAClB,EAAK2I,cAAgBoD,EAAe9C,mBACpC,EAAKxJ,kBAAoBsM,EAAe7C,uBACxC,EAAKL,mBAAqBkD,EAAeyzB,wBALF,EAF3C,0FAWE,4BAAAl5B,EAAA,sEACyBvG,KAAKkH,cAD9B,cACQ9G,EADR,yBAES,0BAA4BJ,KAAKC,WAAa,0BAA4BG,GAFnF,gDAXF,6HAgBE,4BAAAmG,EAAA,sEACyBvG,KAAKkH,cAD9B,cACQ9G,EADR,yBAES,0BAA4BJ,KAAKC,WAAa,oBAAsBG,GAF7E,gDAhBF,yHAqBE,WAAsB0rC,GAAtB,eAAAvlC,EAAA,sEACyBvG,KAAKkH,cAD9B,cACQ9G,EADR,yBAES,0BAA4BJ,KAAKC,WAAa,oBAAsB6rC,EAAc,WAAa1rC,GAFxG,gDArBF,6HA0BE,WAAyB0rC,GAAzB,eAAAvlC,EAAA,sEACyBvG,KAAKkH,cAD9B,cACQ9G,EADR,yBAES,0BAA4BJ,KAAKC,WAAa,uBAAyB6rC,EAAc,WAAa1rC,GAF3G,gDA1BF,gFA+BE,WACE,OAAOJ,KAAKN,kBAAkBS,uBAhClC,8DAsCE,kCAAAoG,EAAA,sEACoBvG,KAAK+rC,kBADzB,cACQ1jC,EADR,gBAEyBrI,KAAK4I,cAAczE,mBAAmBkE,GAF/D,cAEQpD,EAFR,gBAGqBA,EAASoC,OAH9B,cAGQE,EAHR,iBAI8BhD,MAAMgD,EAAM,CACtC/C,OAAQ,QALZ,eAIQgD,EAJR,yBAOSA,EAAcC,QAPvB,iDAtCF,oHAmDE,sCAAAlB,EAAA,sDACQylC,EAAoB,GACjBnlC,EAAI,EAFf,YAEkBA,EAAIiM,GAAsBnQ,QAF5C,6BAG2B3C,KAAK4I,cAHhC,SAGuE5I,KAAKisC,kBAAkBn5B,GAAsBjM,IAHpH,wCAG8C1C,mBAH9C,8BAGUc,EAHV,iBAIuBA,EAASoC,OAJhC,eAIUE,EAJV,iBAKgChD,MAAMgD,EAAM,CACtC/C,OAAQ,QANd,WASiC,OAJvBgD,EALV,QASsBrC,OATtB,kCAU2BqC,EAAc0kC,cAVzC,QAUYzjC,EAVZ,OAWMujC,EAAkBl5B,GAAsBjM,GAAGyM,eAAiB64B,YAAW,IAAI3jC,WAAWC,IAASA,OAXrG,QAEoD5B,IAFpD,gDAcSmlC,GAdT,iDAnDF,kHAuEE,oCAAAzlC,EAAA,sEACoBvG,KAAKosC,qBADzB,cACQ/jC,EADR,gBAEyBrI,KAAK4I,cAAczE,mBAAmBkE,GAF/D,cAEQpD,EAFR,gBAGqBA,EAASoC,OAH9B,cAGQE,EAHR,iBAI8BhD,MAAMgD,EAAM,CACtC/C,OAAQ,QALZ,eAIQgD,EAJR,iBAOqBA,EAAcpD,OAPnC,eAOQA,EAPR,yBAQSA,GART,iDAvEF,oHAwFE,WAAiBlD,GAAjB,eAAAqF,EAAA,sEACyBvG,KAAK8I,mBAAmBnB,SAAS3H,KAAKC,WAAYiB,GAD3E,cACQ+D,EADR,yBAESjF,KAAKqsC,qBAAqBpnC,IAFnC,gDAxFF,yFAoGE,SAAsBwC,GACpB,OAAO,IAAI5G,SAAQ,SAACC,EAASC,GAC3B,IAAMurC,EAAa,IAAIC,WACvBD,EAAWE,QAAU,WACnBzrC,EAAO,IAAI6B,MAAM,iCAEnB0pC,EAAW7tB,OAAS,WAClB3d,EAAQwrC,EAAW7b,SAErB6b,EAAWG,cAAchlC,UA7G/B,GCJA,gIAKE,sBAAAlB,EAAA,4DACQ,IAAI3D,MAAM,mBADlB,2CALF,oHAcE,sBAAA2D,EAAA,4DACQ,IAAI3D,MAAM,mBADlB,2CAdF,kHAsBE,sBAAA2D,EAAA,4DACQ,IAAI3D,MAAM,mBADlB,2CAtBF,mHAgCE,sBAAA2D,EAAA,4DACQ,IAAI3D,MAAM,mBADlB,2CAhCF,mHA0CE,sBAAA2D,EAAA,4DACQ,IAAI3D,MAAM,mBADlB,2CA1CF,mHAmDE,sBAAA2D,EAAA,4DACQ,IAAI3D,MAAM,mBADlB,2CAnDF,mHA2DE,sBAAA2D,EAAA,4DACQ,IAAI3D,MAAM,mBADlB,2CA3DF,oHAqEE,WAAiB1B,GAAjB,SAAAqF,EAAA,4DACQ,IAAI3D,MAAM,mBADlB,2CArEF,+DCFawJ,GAAYC,aAAW,SAAAC,GAAK,MAAK,CAC5CogC,MAAO,CACLt9B,SAAU,WACVgH,OAAQ,aCkBCu2B,GAAW,SAAC,GAA2C,IAAzCC,EAAwC,EAAxCA,kBACnB1/B,EAAUd,KACVqpB,EAAYC,iBAA0B,MAC5C,EAA4CzqB,wBAAqCrK,GAAjF,mBAAO2lB,EAAP,KAAuBsmB,EAAvB,KACA,EAAoGpiC,IAA5FS,EAAR,EAAQA,MAAOC,EAAf,EAAeA,SAAUJ,EAAzB,EAAyBA,QAASiB,EAAlC,EAAkCA,eAAgBX,EAAlD,EAAkDA,qBAAsBE,EAAxE,EAAwEA,wBACxE,EAAkCN,mBAAmB,IAArD,mBAAOke,EAAP,KAAkB2jB,EAAlB,KACA,EAAwD7hC,oBAAkB,GAA1E,mBAAOm8B,EAAP,KAA6B2F,EAA7B,KAEQ9sC,EAAekN,cAAflN,WACF+sC,EAAmBC,mBAAQ,WAAQ,OAAOhtC,EAAaoN,SAASpN,QAAcW,IAAY,CAACX,IACjG,EAAsCgL,oBAAU,GAAhD,mBAAO0F,EAAP,KAAoBu8B,EAApB,KA6EA,OA3EAnX,qBAAU,WACR,GAA0B,OAAtBN,EAAUU,QAAkB,CAC9BV,EAAUU,QAAQgX,cAAgB,SAACrqB,GAAD,OAAmBA,EAAEP,kBAC3B,uCAAG,4BAAAhc,EAAA,8DACJ3F,IAArBosC,EADyB,gCAEiBhhC,EAAe08B,uBAAuBI,iCAAiCkE,GAFxF,OAErBj/B,EAFqB,OAG3B1C,EAAqB29B,MAAMC,KAAKl7B,EAAKm7B,SAHV,2CAAH,oDAM5BkE,GAEA,IAAMC,EAAa,IAAIr5B,GAAMyhB,EAAUU,SACjC5jB,EAAY,IAAIs5B,GAAcmB,EAAkBhhC,GAEtD6gC,OAAkBjsC,GAElB2K,EAAwB,GACxB8hC,EAAWC,aAAa/6B,GAAW,WACjChH,EAAwB8hC,EAAW9H,8BAGrC8H,EAAWE,qBAAoB,SAACC,GAE9B,GADAV,EAAa,KACU,IAAnBU,EAAWlqC,GACbupC,OAAkBjsC,OACb,CACL,IAAM2lB,EAAiCinB,EACvCX,EAAkB,6BAAKtmB,GAAN,IAAsB4iB,OAAO,KAC9C,IAAMjmC,EAAmBmqC,EAAWI,oBAAoBD,EAAWlqC,GAAIkqC,EAAW7mB,WACnE/lB,IAAXsC,GAAwBA,EAAOP,OAAS,GAC1CmqC,EAAa5pC,EAAOsd,MAAM,EAnCV,KAoChBusB,GAAwB,IAExBxtC,QAAQH,MAAM,uBAMpBiuC,EAAWK,sBAAqB,SAACF,GAE/B,GADAV,EAAa,KACU,IAAnBU,EAAWlqC,GAAW,CACxB,IAAMijB,EAAiCinB,EACjCtqC,EAASmqC,EAAWM,iCACX/sC,IAAXsC,GAAwBA,EAAOP,OAAS,GAC1CmqC,EAAa5pC,EAAOsd,MAAM,EAlDV,KAmDhBqsB,EAAkB,6BAAKtmB,GAAN,IAAsB4iB,OAAO,KAC9C4D,GAAwB,IAExBxtC,QAAQH,MAAM,uBAKpBiuC,EAAWO,wBAAuB,SAACC,GAAD,OAAyBX,EAAeW,EAAevqC,OAEzF6H,EAASkiC,MAEV,CAACtiC,EAASiiC,EAAkBhhC,EAAgBX,EAAsBF,EAAUI,IAE/EwqB,qBAAU,WACR6W,EAAkBj8B,KACjB,CAACA,EAAai8B,IAEjB7W,qBAAU,WACR,IAAM+X,EAAc,gBACJltC,IAAVsK,GACFA,EAAMmc,OAAOtW,OAAOg9B,WAAYh9B,OAAOi9B,cAK3C,OAFAj9B,OAAOyQ,iBAAiB,SAAUssB,GAAc,GAChDA,IACO,kBAAM/8B,OAAOovB,oBAAoB,SAAU2N,GAAc,MAC/D,CAAC5iC,IAGF,wCACwBtK,IAArBosC,EACC,qCACE,sBAAK3+B,UAAWnB,EAAQw/B,MAAxB,UACE,wBAAQnW,IAAKd,IACb,cAAC,GAAD,YAEkB70B,IAAnB2lB,GACC,cAAC,GAAD,CACE+gB,0BAA2B,SAAC33B,GAAD,OAAmBo9B,EAAwBp9B,IACtE03B,uBAAwB,SAAC9gB,GAAD,OAAoCsmB,EAAkBtmB,IAC9E6gB,qBAAsBA,EACtBlkC,OAAQimB,EACR5C,eAAgBA,EAChBtmB,WAAY+sC,OAKlB,cAAChuC,EAAA,EAAD,CAAKC,EAAG,EAAR,wCC3HKgvC,GAAO,SAAClvC,GACnB,OACE,8BACE,eAACwQ,GAAA,EAAD,CAAYC,QAAQ,QAApB,UACE,8BAAIzQ,EAAMy5B,MAAV,OADF,IACyBz5B,EAAMmN,Y,UCoCtBE,GA7CUC,aAAW,SAAAC,GAAK,MAAK,CAC5C4hC,KAAM,CACJn/B,QAAS,OACTrB,MAAO,IACP,eAAgB,CACd8C,OAAQ,EACR29B,eAAgB,SAChBzgC,MAAO,QACP0I,OAAQ,UAGZg4B,KAAM,CACJ,eAAgB,CACdC,UAAW,SAGfC,OAAQ,CACNC,QAASjiC,EAAMO,QAAQ,IAEzB8qB,UAAW,CACT4W,QAAS,GAEXngB,KAAM,CACJ1gB,MAAO,OACP8C,OAAQlE,EAAMO,QAAQ,IAExB2hC,SAAU,CACR9gC,MAAO,OACP8C,OAAQlE,EAAMO,QAAQ,IAExB2hB,KAAM,CACJ9gB,MAAO,OACP8C,OAAQlE,EAAMO,QAAQ,IAExB4hC,QAAS,CACP/gC,MAAO,IACP,eAAgB,CACdghC,UAAW,UAGfC,YAAa,CACXjhC,MAAO,SC/BEkhC,GAAa,SAAC7vC,GACzB,IAAMmO,EAAUd,KAEhB,OACE,cAACpN,EAAA,EAAD,CAAKC,EAAG,EAAGoP,UAAWnB,EAAQghC,KAA9B,SACE,eAACvgC,EAAA,EAAD,CAAMU,UAAWnB,EAAQkhC,KAAzB,UACE,cAACS,GAAA,EAAD,CACExgC,UAAWnB,EAAQohC,OACnB5/B,MAAO3P,EAAM2P,MACbogC,UAAW/vC,EAAMgwC,WACnB,eAACnhC,EAAA,EAAD,CAAaS,UAAWnB,EAAQyqB,UAAhC,UACE,cAAC34B,EAAA,EAAD,CAAKqP,UAAWnB,EAAQkhB,KAAxB,SACE,qBAAK4I,IAAI,UAAU3oB,UAAWnB,EAAQuhC,QAAS7vB,IAAK7f,EAAMiwC,eAE5D,cAAChwC,EAAA,EAAD,CAAKqP,UAAWnB,EAAQshC,SAAxB,SACE,qBAAKxX,IAAI,WAAW3oB,UAAWnB,EAAQyhC,YAAa/vB,IAAK7f,EAAMkwC,mBAEjE,cAACjwC,EAAA,EAAD,CAAKqP,UAAWnB,EAAQshB,KAAxB,SACGzvB,EAAMyvB,gBCFJpiB,GA1BUC,aAAW,SAAAC,GAAK,MAAK,CAC5C4iC,aAAc,CACZ,eAAgB,CACdngC,QAAS,SAGbogC,aAAc,CACZpgC,QAAS,OACT,eAAgB,CACdA,QAAS,UAGbqgC,UAAW,CACT,eAAgB,CACdjB,eAAgB,WAGpBkB,cAAe,CACb9iC,eAAgB,YAChBC,MAAOF,EAAMG,QAAQC,QAAQ0hB,MAE/B7f,OAAQ,CACN+gB,YAAahjB,EAAMO,QAAQ,Q,0CCVlByiC,GAAS,WAAO,IAAD,EACpBpiC,EAAUd,KAChB,EAA8BnB,oBAAkB,GAAhD,mBAAO2jB,EAAP,KAAgB2gB,EAAhB,KASA,OACE,qCACE,eAACvwC,EAAA,EAAD,CAAKi4B,EAAG,EAAG5oB,UAAW,CAACnB,EAAQiiC,aAAcjiC,EAAQkiC,WAAWla,KAAK,KAArE,UACE,cAAC3lB,GAAA,EAAD,CAAYC,QAAQ,KAApB,yBACA,uBACA,uBACA,cAAC,GAAD,CAAMgpB,MAAM,aAAatsB,MAAM,eAC/B,cAAC,GAAD,CAAMssB,MAAM,aAAatsB,MAAM,eAC/B,cAAC,GAAD,CAAMssB,MAAM,aAAatsB,MAAM,uBAC/B,cAAC,GAAD,CAAMssB,MAAM,WAAWtsB,MAAM,gBAC7B,cAAC,GAAD,CAAMssB,MAAM,oBAAoBtsB,MAAM,YACtC,cAAC,GAAD,CAAMssB,MAAM,oBAAoBtsB,MAAO2G,GAAiB1Q,QAAO,SAAAgR,GAAC,MAAU,SAANA,KAAc+hB,KAAK,QACvF,cAAC,GAAD,CAAMsD,MAAM,QAAQtsB,MAAM,YAC1B,cAAC,GAAD,CAAMssB,MAAM,iBAAiBtsB,MAAM,SACnC,cAAC,GAAD,CAAMssB,MAAM,cAActsB,MAAM,UAGlC,cAAClN,EAAA,EAAD,CAAKC,EAAG,EAAGoP,UAAWnB,EAAQgiC,aAAcxhC,MAAO,IAAnD,SACE,cAACC,EAAA,EAAD,UACE,eAACC,EAAA,EAAD,WACE,cAAC5O,EAAA,EAAD,CAAKi4B,EAAG,EAAGvpB,MAAO,IAAlB,SACE,eAACgrB,GAAA,EAAD,CACE/C,WAAS,EACTnlB,OAAO,QAFT,UAIA,cAACmoB,GAAA,EAAD,CAAYr1B,GAAG,SAAf,6BACE,cAACs1B,GAAA,EAAD,CACAC,SAAU,aACR3sB,MAAO,cAFT,mBAIC,CAAC,cAAe,sBAJjB,aAIC,EAAgC1K,KAAI,SAAC0K,EAAOikB,GAC3C,OAAO,cAAC9f,GAAA,EAAD,CAAsBnE,MAAOA,EAA7B,SAAqCA,GAAtBikB,aAK5B,cAACnxB,EAAA,EAAD,CAAKi4B,EAAG,EAAR,SAEIpkB,GAAiB1Q,QAAO,SAAAgR,GAAC,MAAU,SAANA,KAAc3R,KAAI,SAAC2R,EAAGtM,GAAJ,OAC/C,cAAC+5B,GAAA,EAAD,CAEEC,QACE,cAACC,GAAA,EAAD,CACEC,KAAM,cAAC,KAAD,CAA0BvyB,SAAS,UACzCwyB,YAAa,cAAC,KAAD,CAAcxyB,SAAS,UACpCyyB,SAAS,EACTpI,SAAU,aACVqI,KAAK,SACL10B,MAAM,YAGVgsB,MAAO3lB,GAAiB1Q,QAAO,SAAAgR,GAAC,MAAU,SAANA,KAActM,IAX7CA,QAgBX,cAAC7H,EAAA,EAAD,CAAKi4B,EAAG,EAAR,SACE,eAAC1nB,GAAA,EAAD,CAAYC,QAAQ,QAApB,2BACgB,mBAAGnB,UAAWnB,EAAQmiC,cAAtB,kBADhB,wBAKF,eAACrwC,EAAA,EAAD,CAAKi4B,EAAG,EAAGllB,GAAI,EAAf,UACE,cAACmlB,GAAA,EAAD,CACE5mB,QAvEK,WACjBi/B,GAAW,GACXC,YAAW,WACTD,GAAW,KACV,MAoESlhC,UAAWnB,EAAQqB,OACnBiB,QAAQ,YACRhD,MAAM,UACN4qB,UAAW,cAAC,KAAD,IALb,6BAOA,cAACF,GAAA,EAAD,CACE5mB,QAAS,kBAAMS,OAAO0+B,SACtBphC,UAAWnB,EAAQqB,OACnBiB,QAAQ,YACRhD,MAAM,UACN4qB,UAAW,cAAC,KAAD,IALb,6BAYNxI,EAmGA,cAAC5vB,EAAA,EAAD,CAAKC,EAAG,EAAR,kCAlGA,qCACE,cAAC,GAAD,CACEyP,MAAM,4CACNqgC,SAAS,sBACTC,WAAW,4BACXC,eAAe,uBACfzgB,KACE,qCACE,cAAC,GAAD,CAAMgK,MAAM,kBAAkBtsB,MAAM,YACpC,cAAC,GAAD,CAAMssB,MAAM,WAAWtsB,MAAM,6CAC7B,cAAC,GAAD,CAAMssB,MAAM,qBAAqBtsB,MAAM,qBACvC,cAAC,GAAD,CAAMssB,MAAM,OAAOtsB,MAAM,gBACzB,cAAC,GAAD,CAAMssB,MAAM,mBAAmBtsB,MAAM,MACrC,cAAC,GAAD,CAAMssB,MAAM,QAAQtsB,MAAM,oBAC1B,cAAC,GAAD,CAAMssB,MAAM,cAActsB,MAAM,KAChC,cAAC,GAAD,CAAMssB,MAAM,QAAQtsB,MAAM,uCAC1B,cAAC,GAAD,CAAMssB,MAAM,cAActsB,MAAM,iBAItC,cAAC,GAAD,CACEwC,MAAM,wBACNqgC,SAAS,sBACTC,WAAW,4BACXC,eAAe,uBACfzgB,KACE,qCACE,cAAC,GAAD,CAAMgK,MAAM,kBAAkBtsB,MAAM,YACpC,cAAC,GAAD,CAAMssB,MAAM,WAAWtsB,MAAM,6CAC7B,cAAC,GAAD,CAAMssB,MAAM,qBAAqBtsB,MAAM,qBACvC,cAAC,GAAD,CAAMssB,MAAM,OAAOtsB,MAAM,KACzB,cAAC,GAAD,CAAMssB,MAAM,mBAAmBtsB,MAAM,MACrC,cAAC,GAAD,CAAMssB,MAAM,QAAQtsB,MAAM,aAC1B,cAAC,GAAD,CAAMssB,MAAM,cAActsB,MAAM,KAChC,cAAC,GAAD,CAAMssB,MAAM,QAAQtsB,MAAM,uCAC1B,cAAC,GAAD,CAAMssB,MAAM,cAActsB,MAAM,iBAItC,cAAC,GAAD,CACEwC,MAAM,4BACNqgC,SAAS,sBACTC,WAAW,4BACXC,eAAe,uBACfzgB,KACE,qCACE,cAAC,GAAD,CAAMgK,MAAM,kBAAkBtsB,MAAM,YACpC,cAAC,GAAD,CAAMssB,MAAM,WAAWtsB,MAAM,6CAC7B,cAAC,GAAD,CAAMssB,MAAM,qBAAqBtsB,MAAM,qBACvC,cAAC,GAAD,CAAMssB,MAAM,OAAOtsB,MAAM,KACzB,cAAC,GAAD,CAAMssB,MAAM,mBAAmBtsB,MAAM,MACrC,cAAC,GAAD,CAAMssB,MAAM,QAAQtsB,MAAM,qBAC1B,cAAC,GAAD,CAAMssB,MAAM,cAActsB,MAAM,KAChC,cAAC,GAAD,CAAMssB,MAAM,QAAQtsB,MAAM,uCAC1B,cAAC,GAAD,CAAMssB,MAAM,cAActsB,MAAM,iBAItC,cAAC,GAAD,CACEwC,MAAM,4BACNqgC,SAAS,sBACTC,WAAW,4BACXC,eAAe,uBACfzgB,KACE,qCACE,cAAC,GAAD,CAAMgK,MAAM,kBAAkBtsB,MAAM,YACpC,cAAC,GAAD,CAAMssB,MAAM,WAAWtsB,MAAM,6CAC7B,cAAC,GAAD,CAAMssB,MAAM,qBAAqBtsB,MAAM,qBACvC,cAAC,GAAD,CAAMssB,MAAM,OAAOtsB,MAAM,KACzB,cAAC,GAAD,CAAMssB,MAAM,mBAAmBtsB,MAAM,MACrC,cAAC,GAAD,CAAMssB,MAAM,QAAQtsB,MAAM,WAC1B,cAAC,GAAD,CAAMssB,MAAM,cAActsB,MAAM,KAChC,cAAC,GAAD,CAAMssB,MAAM,QAAQtsB,MAAM,uCAC1B,cAAC,GAAD,CAAMssB,MAAM,cAActsB,MAAM,iBAItC,cAAC,GAAD,CACEwC,MAAM,yBACNqgC,SAAS,sBACTC,WAAW,4BACXC,eAAe,uBACfzgB,KACE,qCACE,cAAC,GAAD,CAAMgK,MAAM,kBAAkBtsB,MAAM,YACpC,cAAC,GAAD,CAAMssB,MAAM,WAAWtsB,MAAM,6CAC7B,cAAC,GAAD,CAAMssB,MAAM,qBAAqBtsB,MAAM,qBACvC,cAAC,GAAD,CAAMssB,MAAM,OAAOtsB,MAAM,gBACzB,cAAC,GAAD,CAAMssB,MAAM,mBAAmBtsB,MAAM,MACrC,cAAC,GAAD,CAAMssB,MAAM,QAAQtsB,MAAM,iCAC1B,cAAC,GAAD,CAAMssB,MAAM,cAActsB,MAAM,KAChC,cAAC,GAAD,CAAMssB,MAAM,QAAQtsB,MAAM,uCAC1B,cAAC,GAAD,CAAMssB,MAAM,cAActsB,MAAM,wBClIjCwjC,GA5CO,WACpB,MAAsCzkC,oBAAU,GAAhD,mBAAO0F,EAAP,KAAoBu8B,EAApB,KACQnjC,EAAgBU,IAAhBV,YAER,OACE,qCACE,cAAC,IAAD,CAA4B4lC,gBAAiBC,IAAgBC,SAAUC,eAAgB3wC,EAAW4wC,iBAAkBjxC,EAApH,SAEE,cAACkxC,EAAA,EAAD,CAAqBvwC,OAAQsK,EAA7B,SACE,cAAC,IAAD,UACE,eAAC,IAAD,WACE,cAAC,IAAD,CAAOkmC,OAAK,EAAC/rC,KAAI,UAAK4I,EAAMlG,YAAX,8BAAjB,SACE,cAAC,GAAD,CAAQ4J,OAAQ,EAAGC,cAAY,EAACC,iBAAe,EAACC,YAAaA,EAA7D,SACE,cAAC,GAAD,CAAUi8B,kBAAmB,SAACtpC,GAAD,OAAQ4pC,EAAe5pC,UAGxD,cAAC,IAAD,CAAO2sC,OAAK,EAAC/rC,KAAI,UAAK4I,EAAMlG,YAAX,kBAAjB,SACE,cAAC,GAAD,UACE,cAAC,EAAD,QAGJ,cAAC,IAAD,CAAOqpC,OAAK,EAAC/rC,KAAM,CAAC4I,EAAMC,KAAMD,EAAMlG,aAAtC,SACE,cAAC,GAAD,UACE,cAAC,GAAD,QAGJ,cAAC,IAAD,CAAOqpC,OAAK,EAAC/rC,KAAM4I,EAAME,OAAzB,SACE,cAAC,GAAD,UACE,cAAC,GAAD,iBASZ,cAAC,IAAD,UACE,cAAChO,EAAA,EAAD,CAAKC,EAAG,EAAR,6DCpDOixC,GAZS,SAAAC,GAClBA,GAAeA,aAAuBC,UACxC,8BAAqB3kC,MAAK,YAAkD,IAA/C4kC,EAA8C,EAA9CA,OAAQC,EAAsC,EAAtCA,OAAQC,EAA8B,EAA9BA,OAAQC,EAAsB,EAAtBA,OAAQC,EAAc,EAAdA,QAC3DJ,EAAOF,GACPG,EAAOH,GACPI,EAAOJ,GACPK,EAAOL,GACPM,EAAQN,O,8DCHD7jC,GAAeokC,aAAe,CACzCjkC,QAAS,CACPC,QAAS,CACP0hB,KAAMuiB,KAAK,MAEb/hC,UAAW,CACTwf,KAAMwiB,KAAK,SCEjBC,IAASt2B,OACP,cAAC,IAAMu2B,WAAP,UACE,cAAC,IAAD,CAAcjmC,SAAU,IAAIb,IAAwBR,GAApD,SACE,cAAC,EAAD,UACE,cAACunC,GAAA,EAAD,CAAezkC,MAAOA,GAAtB,SACE,cAAC,GAAD,YAKRqF,SAASq/B,eAAe,SAM1Bd,O","file":"static/js/main.c2bdf319.chunk.js","sourcesContent":["import { IMsalContext } from '@azure/msal-react'\nimport { FC, ReactElement } from 'react'\nimport { Box } from '@material-ui/core'\n\nconst authLoading: FC = (props: IMsalContext): ReactElement => {\n return (\n Authentication in progress: {props.inProgress}\n )\n}\n\nexport { authLoading }\n","import { BrowserAuthError } from '@azure/msal-browser'\nimport { MsalAuthenticationResult } from '@azure/msal-react'\nimport { FC, ReactElement } from 'react'\nimport { Box } from '@material-ui/core'\n\nconst authError: FC = (props: MsalAuthenticationResult): ReactElement => {\n if (props.error instanceof BrowserAuthError) {\n return (\n Login failed: {props.error.errorMessage}\n )\n } else {\n console.error(props.error)\n return (\n

An unkonwn error Occurred, check log for details

\n )\n }\n}\n\nexport { authError }\n","import { Annotation } from 'src/datasource/model/Annotation'\nimport { UserServiceClient } from 'src/datasource/UserServiceClient'\nimport { ServiceClient } from 'src/datasource/ServiceClient'\nimport { ImageAnnotationsCount } from 'src/datasource/model/ImageAnnotationCount'\nimport { Damage } from 'src/datasource/model/Damage'\nimport { Cause } from 'src/datasource/model/Cause'\nimport { ImageAnnotationsDetails } from 'src/datasource/model/ImageAnnotationDetails'\nimport { AnalysisServiceClient } from 'src/datasource/AnalysisServiceClient'\nimport { ConditionRating } from 'src/datasource/model/ConditionRating'\n\nexport class AnnotationServiceClient {\n private readonly client: ServiceClient\n private readonly userServiceClient: UserServiceClient\n private readonly analysisServiceClient: AnalysisServiceClient\n private imageIdMap: Map | null = null\n private imageNameMap: Map | null = null\n private batchToIdsCache: Map = new Map()\n\n constructor (client: ServiceClient, userServiceClient: UserServiceClient, analysisServiceClient: AnalysisServiceClient) {\n this.client = client\n this.userServiceClient = userServiceClient\n this.analysisServiceClient = analysisServiceClient\n }\n\n public async queryAnnotations (analysisId: number, imageIds: number[]): Promise {\n const tenantId: number = await this.userServiceClient.getCurrentTenantId()\n return await this.client.postRequest('api/annotation/ImageAnnotationsBatch/tenant/' + tenantId.toString(), {\n analysisId: analysisId,\n imageIdList: imageIds,\n tagNameIdList: [],\n conditionRatingIdList: []\n })\n }\n\n public async getDamages (): Promise {\n const tenantId = await this.tenantId()\n return await this.client.getRequest('api/tagname/TagNameFilter/tenant/' + tenantId.toString())\n }\n\n public async getConditionRatings (): Promise {\n const tenantId = await this.tenantId()\n return await this.client.getRequest('api/conditionrating/ConditionRatingFilter/tenant/' + tenantId.toString())\n }\n\n public async getCausesFor (damageId: number | undefined): Promise {\n if (damageId === undefined) {\n return await new Promise(\n (resolve, reject) => {\n resolve([])\n }\n )\n } else {\n const tenantId = await this.tenantId()\n return this.client.getRequest('api/annotation/StandardCauses/tenant/' + tenantId.toString() + '/damageCategory/' + damageId.toString())\n }\n }\n\n // Returns an overview with info about the number of annotations for each image\n public async getUserAnnotationCountForAnalysis (analysisId: number): Promise {\n const tenantId = await this.tenantId()\n return await this.client.getRequest('api/annotation/ImageAnnotationsCount/tenant/' + tenantId.toString() + '/analysis/' + analysisId.toString())\n }\n\n public async saveAnnotation (annotation: Annotation): Promise {\n const tenantId: number = await this.tenantId()\n return await this.client.postRequest('api/annotation/SaveAnnotation/tenant/' + tenantId.toString(), annotation)\n }\n\n public async deleteAnnotation (annotationId: number): Promise {\n const tenantId: number = await this.tenantId()\n return await this.client.postRequest('api/annotation/DeleteAnnotation/tenant/' + tenantId.toString() + '/annotation/' + annotationId.toString(), {})\n }\n\n // Map the name of the image on disk \"2c02ea39-a4fe-4124-9fc6-633b6fcaa21d-High_quality.jpg\" to the id of the image, 1190 \n public async mapImageNameToImageId (analysisId: number, imageName: string): Promise {\n return (await this.getImageIdMap(analysisId)).get(this.toImageUuid(imageName))\n }\n\n // Map the image id (1190) to the UUID part of the image name on disk (2c02ea39-a4fe-4124-9fc6-633b6fcaa21d-High_quality.jpg)\n // So 1190 => 2c02ea39-a4fe-4124-9fc6-633b6fcaa21d\n public async mapImageIdToImageName (analysisId: number, imageId: number): Promise {\n const map = await this.getImageNameMap(analysisId)\n return map.get(imageId)\n }\n\n public async getUserAnnotationsForAnalysis (analysisId: number): Promise {\n const imageBatchId = await this.analysisServiceClient.getImageBatchIdFor(analysisId)\n const imageIds = await this.getImageIdsFrom(imageBatchId);\n const imageAnnotationDetails = await this.queryAnnotations(analysisId, imageIds)\n let annotations: Annotation[] = []\n imageAnnotationDetails.forEach(details => annotations = annotations.concat(details.annotationDetails))\n return annotations.filter((details) => details.isUserCreated)\n }\n\n public async getUserAnnotationsMapForAnalysis (analysisId: number): Promise> {\n const userAnnotations = await this.getUserAnnotationsForAnalysis(analysisId)\n const map = new Map()\n userAnnotations.forEach(annotation => {\n const systemId = this.systemIdFrom(annotation)\n if (systemId !== \"\") {\n map.set(systemId, annotation)\n }\n })\n return map\n }\n\n // Returns the user annotations that exists on the analysis and the image name\n public async getUserAnnotationsFor (analysisId: number, imageName: string): Promise {\n const imageId = await this.mapImageNameToImageId(analysisId, imageName)\n if (imageId === undefined) {\n return []\n }\n const annotations = await this.queryAnnotations(analysisId, [imageId])\n if (annotations.length === 0) {\n return []\n }\n if (annotations.length !== 1) {\n throw new Error('Image query returned results for more than one image')\n }\n const annotation = annotations[0]\n return annotation.annotationDetails.filter((details) => details.isUserCreated)\n }\n\n // Returns the user annotation that may exist given the 3 parameters\n public async getUserAnnotationFor (analysisId: number, imageName: string, systemAnnotation: string): Promise {\n const userAnnotations = await this.getUserAnnotationsFor(analysisId, imageName)\n const validAnnotations = userAnnotations.filter((details) => this.systemIdFrom(details) === '' + systemAnnotation)\n if (validAnnotations.length === 0) {\n return null\n }\n if (validAnnotations.length > 1) {\n throw new Error('More than one systemAnnotation present')\n }\n\n return validAnnotations[0]\n }\n\n private async getImageNameMap (analysisId: number): Promise> {\n if (this.imageNameMap !== null) {\n return this.imageNameMap\n }\n await this.updateImageMaps(analysisId)\n \n if (this.imageNameMap === null) {\n throw Error(\"Image maps not updated\")\n }\n return this.imageNameMap\n }\n\n private async getImageIdMap (analysisId: number): Promise> {\n if (this.imageIdMap !== null) {\n return this.imageIdMap\n }\n await this.updateImageMaps(analysisId)\n\n if (this.imageIdMap === null) {\n throw Error(\"Image maps not updated\")\n }\n return this.imageIdMap\n }\n\n private async updateImageMaps(analysisId: number): Promise {\n const tenantId: number = await this.tenantId()\n const imageBatchId = await this.analysisServiceClient.getImageBatchIdFor(analysisId)\n\n // This should be split into an ImageBatchServiceClient and typed\n const imageBatch = await this.client.getRequest('api/imageBatch/ImageBatchDetailsWithImages/tenant/' + tenantId.toString() + '/' + imageBatchId.toString())\n const images = imageBatch.images as any[]\n\n const idMap = new Map()\n images.forEach(image => {\n idMap.set(this.toImageUuid(image.imageBlobName as string), image.id as number)\n })\n\n const nameMap = new Map()\n images.forEach(image => {\n nameMap.set(image.id as number, this.toImageUuid(image.imageBlobName as string))\n })\n\n this.imageIdMap = idMap\n this.imageNameMap = nameMap\n }\n\n private async getImageIdsFrom(imageBatchId: number) {\n const cachedIds = this.batchToIdsCache.get(imageBatchId)\n if (cachedIds !== undefined) {\n return cachedIds\n }\n const tenantId: number = await this.tenantId()\n // TODO: This should be split into an ImageBatchServiceClient and typed\n const imageBatch = await this.client.getRequest('api/imageBatch/ImageBatchDetailsWithImages/tenant/' + tenantId.toString() + '/' + imageBatchId.toString())\n const images = imageBatch.images as any[]\n \n let imageIds: number[] = []\n images.forEach(image => {\n imageIds.push(image.id as number)\n })\n this.batchToIdsCache.set(imageBatchId, imageIds)\n return imageIds\n }\n\n private async tenantId (): Promise {\n return await this.userServiceClient.getCurrentTenantId()\n }\n\n // Used for storing and lookup of image name\n private toImageUuid(imageName: string): string {\n return imageName.substring(0, 36)\n }\n\n private systemIdFrom (annotation: Annotation): string {\n if (annotation.comment === null) {\n return \"\"\n }\n const tokens = annotation.comment.split(\"#\")\n if (tokens.length !== 2) {\n return \"\"\n }\n return tokens[0]\n }\n}\n","import { v4 as uuid } from 'uuid'\nimport { TokenProvider } from 'src/datasource/TokenProvider'\n\nexport interface ServiceClient {\n getRequest: (path: string) => Promise\n postRequest: (path: string, body: any) => Promise\n postBinary: (path: string, body: any) => Promise\n getRequestResponse(path: string): Promise\n}\n\nexport class PaiServiceClient implements ServiceClient {\n private readonly baseUrl: string\n private readonly apiKey = '2fb55734-3c56-4442-abb9-9b0af26f8624'\n private readonly tokenProvider: TokenProvider\n\n constructor (baseUrl: string, tokenProvider: TokenProvider) {\n this.baseUrl = baseUrl\n this.tokenProvider = tokenProvider\n }\n\n public async getRequest (path: string): Promise {\n return (await this.getRequestResponse(path)).json()\n }\n \n public async getRequestResponse(path: string): Promise {\n // TODO: error handling, consider creating a shared request method between get and post\n const token: string = await this.tokenProvider.getToken()\n return fetch(this.baseUrl + path, {\n method: 'GET',\n headers: {\n API_KEY: this.apiKey,\n RequestId: uuid(),\n Authorization: 'Bearer ' + token\n }\n })\n }\n\n public async postRequest (path: string, body: any): Promise {\n // TODO: error handling\n const token: string = await this.tokenProvider.getToken()\n const response: Response = await fetch(this.baseUrl + path, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json; charset=utf-8',\n API_KEY: this.apiKey,\n RequestId: uuid(),\n Authorization: 'Bearer ' + token\n },\n body: JSON.stringify(body)\n })\n return await response.json()\n }\n\n public async postBinary (path: string, body: ArrayBuffer): Promise {\n const token: string = await this.tokenProvider.getToken()\n \n const response: Response = await fetch(this.baseUrl + path, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/octet-stream',\n 'Content-Encoding': 'identity',\n 'Content-Length': '' + body.byteLength,\n API_KEY: this.apiKey,\n RequestId: uuid(),\n Authorization: 'Bearer ' + token\n },\n body: body\n })\n \n return response.status === 201 || response.status === 200\n }\n}\n","import { ServiceClient } from 'src/datasource/ServiceClient'\n\nexport interface UserServiceClient {\n getCurrentTenantId: () => Promise\n getUserId: () => Promise\n}\n\nexport class PaiUserServiceClient implements UserServiceClient {\n private readonly client: ServiceClient\n private tenantId: number = -1\n private userId: number = -1\n\n constructor (client: ServiceClient) {\n this.client = client\n }\n\n public async getCurrentTenantId (): Promise {\n if (this.tenantId === -1) {\n const userInfo = await this.client.getRequest('api/user/UserInfo')\n this.tenantId = userInfo.tenantId\n this.userId = userInfo.id\n }\n return this.tenantId\n }\n\n public async getUserId (): Promise {\n if (this.userId === -1) {\n const userInfo = await this.client.getRequest('api/user/UserInfo')\n this.tenantId = userInfo.tenantId\n this.userId = userInfo.id\n }\n return this.userId\n }\n}\n","import { InspectionServiceClient } from 'src/datasource/InspectionServiceClient'\nimport { AnalysisDetails } from 'src/datasource/model/analysisDetails'\nimport { ServiceClient } from 'src/datasource/ServiceClient'\nimport { UserServiceClient } from 'src/datasource/UserServiceClient'\n\nexport class AnalysisServiceClient {\n private readonly alexandraAnalysisId: number = 230\n private readonly analysisCache: Map = new Map()\n\n constructor(private readonly client: ServiceClient, private readonly userServiceClient: UserServiceClient, private readonly inspectionServiceClient: InspectionServiceClient) { }\n\n public async getAnalysis(analysisId: number): Promise {\n const cachedAnalysis = this.analysisCache.get(analysisId)\n if (cachedAnalysis !== undefined) {\n return cachedAnalysis\n }\n const tenantId = await this.tenantId()\n const analysis = await this.client.getRequest('api/analysis/AnalysisDetails/tenant/' + tenantId.toString() + '/' + analysisId.toString())\n this.analysisCache.set(analysisId, analysis)\n return analysis\n }\n\n public async getAllAnalysis(): Promise {\n const inspectionIds = await this.inspectionServiceClient.getAllInspectionIds()\n\n let allAnalysis: AnalysisDetails[] = []\n for (const inspectionId of inspectionIds) {\n allAnalysis = allAnalysis.concat(await this.getAnalysisForInspection(inspectionId))\n }\n return allAnalysis;\n }\n\n public async getImageBatchIdFor(analysisId: number): Promise {\n const analysisDetails = await this.getAnalysis(analysisId)\n return analysisDetails.imageBatchDetails.id\n }\n\n public async getAllAlexandraAnalysis(): Promise {\n return this.onlyAlexandraAnalysis(await this.getAllAnalysis())\n }\n\n public async getAnalysisForInspection(inspectionId: number): Promise {\n const tenantId = await this.tenantId()\n return await this.client.getRequest('api/analysis/AnalysisDetailsList/tenant/' + tenantId.toString() + '/' + inspectionId.toString())\n }\n\n public async getAlexandraAnalysisForInspection(inspectionId: number): Promise {\n return this.onlyAlexandraAnalysis(await this.getAnalysisForInspection(inspectionId))\n }\n\n private onlyAlexandraAnalysis(analysis: AnalysisDetails[]): AnalysisDetails[] {\n return analysis.filter(a => this.isAlexandraAnalysis(a))\n }\n\n public isAlexandraAnalysis(analysis: AnalysisDetails): boolean {\n return analysis.cvsProjectId === this.alexandraAnalysisId\n }\n\n private tenantId(): Promise {\n return this.userServiceClient.getCurrentTenantId()\n }\n}","import { InspectionAnalysisReport } from \"src/datasource/model/InspectionAnalysisReport\";\nimport { ServiceClient } from \"src/datasource/ServiceClient\";\nimport { UserServiceClient } from \"src/datasource/UserServiceClient\";\n\nexport class InspectionServiceClient {\n private readonly client: ServiceClient\n private readonly userServiceClient: UserServiceClient\n\n constructor(client: ServiceClient, userServiceClient: UserServiceClient) {\n this.client = client\n this.userServiceClient = userServiceClient\n }\n\n public async getAllInspections(): Promise {\n const tenantId = await this.tenantId()\n return this.client.getRequest('api/inspection/InspectionAnalysisReport/tenant/' + tenantId.toString())\n }\n\n public async getAllInspectionIds(): Promise {\n const inspections = await this.getAllInspections()\n const inspectionIds = inspections.filter(i => i.id !== null).map(inspection => {\n return inspection.id as number\n })\n return inspectionIds\n }\n\n private async tenantId(): Promise {\n return await this.userServiceClient.getCurrentTenantId()\n }\n}","import { ServiceClient } from \"src/datasource/ServiceClient\"\nimport { UserServiceClient } from \"src/datasource/UserServiceClient\";\n\n/*\n * Uses blob storage to fetch images \n */\nexport class BlobImageServiceClient {\n private readonly client: ServiceClient\n private readonly userServiceClient: UserServiceClient\n private readonly twoFiftyPxEnding = \"-250Px.jpg\"\n private readonly highQualityEnding = \"-HighQuality.jpg\"\n\n constructor (client: ServiceClient, userServiceClient: UserServiceClient) {\n this.client = client;\n this.userServiceClient = userServiceClient\n }\n \n async getImageUrl (analysisId: number, imageName: string): Promise {\n const tenantId = await this.getTenantId()\n const restUrl = 'api/modelblob/analysis/' + analysisId + '/image/' + imageName + '/tenant/' + tenantId\n const request = await this.client.getRequestResponse(restUrl)\n return request.text()\n }\n\n private async getTenantId (): Promise {\n return this.userServiceClient.getCurrentTenantId()\n }\n\n /*\n * An example:\n * getImageAsObjectUrl(105, 0a0cfe50-6b6f-4993-ae7f-0e881c83b859-HighQuality.jpg)\n */\n async getImage (analysisId: number, imageBlobName: string): Promise {\n const link = await this.getImageUrl(analysisId, imageBlobName)\n const file_response = await fetch(link, {\n method: 'GET'\n })\n return file_response.blob()\n }\n\n async getImageAsObjectUrl (analysisId: number, imageBlobName: string): Promise {\n return URL.createObjectURL(await this.getImage(analysisId, imageBlobName))\n }\n\n public async getImagesAsObjectUrls (analysisId: number, imageNames: string[]): Promise {\n return await Promise.all(imageNames.map(async i => await this.getImageAsObjectUrl(analysisId, i)))\n }\n\n public convertImageNameToHq(imageName: string): string {\n return this.toImageUuid(imageName) + this.highQualityEnding\n }\n\n public convertImageNamesToHq(imageNames: string[]): string[] {\n return imageNames.map(imageName => this.convertImageNameToHq(imageName))\n }\n\n public convertImageNameTo250px(imageName: string): string {\n return this.toImageUuid(imageName) + this.twoFiftyPxEnding\n }\n\n public convertImageNamesTo250px(imageNames: string[]): string[] {\n return imageNames.map(imageName => this.convertImageNameTo250px(imageName))\n }\n\n private toImageUuid(imageName: string): string {\n return imageName.substring(0, 36)\n }\n}\n","import { ServiceClient } from \"src/datasource/ServiceClient\"\nimport { UserServiceClient } from \"src/datasource/UserServiceClient\";\nimport { gzipSync } from 'fflate'\n\n/*\n * Uses blob storage to fetch images \n */\nexport class LabelMapServiceClient {\n private readonly client: ServiceClient\n private readonly userServiceClient: UserServiceClient\n\n constructor (client: ServiceClient, userServiceClient: UserServiceClient) {\n this.client = client;\n this.userServiceClient = userServiceClient\n }\n \n async getUrl (analysisId: number, damageShortName: string): Promise {\n const tenantId = await this.getTenantId()\n return 'api/modelblob/analysis/' + analysisId + '/consensus/label/' + damageShortName + '/tenant/' + tenantId\n }\n\n async getZipUrl (analysisId: number, damageShortName: string): Promise {\n const tenantId = await this.getTenantId()\n return 'api/modelblob/analysis/' + analysisId + '/consensus/ziplabel/' + damageShortName + '/tenant/' + tenantId\n }\n\n private async getTenantId (): Promise {\n return this.userServiceClient.getCurrentTenantId()\n }\n\n public async postLabelMap(analysisId: number, damageShortName: string, body: ArrayBuffer): Promise {\n const url = await this.getZipUrl(analysisId, damageShortName); \n const zippedBody = gzipSync(new Uint8Array(body)).buffer\n return this.client.postBinary(url, zippedBody)\n }\n}\n","import { AnnotationServiceClient } from 'src/datasource/AnnotationServiceClient'\nimport { PaiServiceClient, ServiceClient } from 'src/datasource/ServiceClient'\nimport { PaiUserServiceClient, UserServiceClient } from 'src/datasource/UserServiceClient'\nimport { TokenProvider } from 'src/datasource/TokenProvider'\nimport { AnalysisServiceClient } from 'src/datasource/AnalysisServiceClient'\nimport { InspectionServiceClient } from 'src/datasource/InspectionServiceClient'\nimport { BlobImageServiceClient } from 'src/datasource/BlobImageServiceClient'\nimport { LabelMapServiceClient } from 'src/datasource/LabelMapServiceClient'\n\nexport class ServiceFactory {\n private static readonly _serviceFactory = new ServiceFactory()\n\n private readonly baseUrl: string\n private serviceClient?: ServiceClient = undefined\n private userServiceClient?: UserServiceClient = undefined\n private annotationServiceClient?: AnnotationServiceClient = undefined\n private analysisServiceClient?: AnalysisServiceClient = undefined\n private tokenProvider?: TokenProvider = undefined\n private inspectionServiceClient?: InspectionServiceClient = undefined\n private imageServiceClient?: BlobImageServiceClient = undefined\n private labelMapServiceClient?: LabelMapServiceClient = undefined\n\n private constructor() {\n // Read environment, with the purpose of setting the baseUrl\n // for the backend.\n const env = process.env.REACT_APP_ENV\n const baseUrl = process.env.REACT_APP_BASE_URL\n if (env === undefined) {\n throw new Error(\"Variable ENV is not defined\")\n }\n if (baseUrl === undefined) {\n throw new Error(\"Variable BASE_URL is not defined\")\n }\n console.log(\"Using environment: \" + env)\n this.baseUrl = baseUrl\n }\n\n public setTokenProvider (tokenProvider: TokenProvider): void {\n this.tokenProvider = tokenProvider\n }\n\n public getAnnotationService (): AnnotationServiceClient {\n if (this.tokenProvider === undefined) {\n throw new Error('No token provider given.')\n }\n if (this.annotationServiceClient === undefined) {\n this.annotationServiceClient = new AnnotationServiceClient(this.getServiceClient(), this.getUserServiceClient(), this.getAnalysisServiceClient())\n }\n return this.annotationServiceClient\n }\n\n public getServiceClient (): ServiceClient {\n if (this.tokenProvider === undefined) {\n throw new Error('No token provider given.')\n }\n if (this.serviceClient === undefined) {\n this.serviceClient = new PaiServiceClient(this.baseUrl, this.tokenProvider)\n }\n return this.serviceClient\n }\n\n public getUserServiceClient (): UserServiceClient {\n if (this.tokenProvider === undefined) {\n throw new Error('No token provider given.')\n }\n if (this.userServiceClient === undefined) {\n this.userServiceClient = new PaiUserServiceClient(this.getServiceClient())\n }\n return this.userServiceClient\n }\n\n public getAnalysisServiceClient (): AnalysisServiceClient {\n if (this.tokenProvider === undefined) {\n throw new Error('No token provider given.')\n }\n if (this.analysisServiceClient === undefined) {\n this.analysisServiceClient = new AnalysisServiceClient(this.getServiceClient(), this.getUserServiceClient(), this.getInspectionServiceClient())\n }\n return this.analysisServiceClient\n }\n\n public getInspectionServiceClient (): InspectionServiceClient {\n if (this.tokenProvider === undefined) {\n throw new Error('No token provider given.')\n }\n if (this.inspectionServiceClient === undefined) {\n this.inspectionServiceClient = new InspectionServiceClient(this.getServiceClient(), this.getUserServiceClient())\n }\n return this.inspectionServiceClient\n }\n\n public getImageServiceClient (): BlobImageServiceClient {\n if (this.tokenProvider === undefined) {\n throw new Error('No token provider given.')\n }\n if (this.imageServiceClient === undefined) {\n this.imageServiceClient = new BlobImageServiceClient(this.getServiceClient(), this.getUserServiceClient())\n }\n return this.imageServiceClient\n }\n\n public getLabelMapServiceClient (): LabelMapServiceClient {\n if (this.tokenProvider === undefined) {\n throw new Error('No token provider given.')\n }\n if (this.labelMapServiceClient === undefined) {\n this.labelMapServiceClient = new LabelMapServiceClient(this.getServiceClient(), this.getUserServiceClient())\n }\n return this.labelMapServiceClient\n }\n\n public static instance (tokenProvider: TokenProvider | undefined): ServiceFactory {\n if (tokenProvider !== undefined) {\n ServiceFactory._serviceFactory.setTokenProvider(tokenProvider)\n }\n return ServiceFactory._serviceFactory\n }\n}","import { Configuration, PublicClientApplication } from '@azure/msal-browser'\n\nexport const msalConfig: Configuration = {\n auth: {\n clientId: 'a0b26464-d148-46b5-8920-35b3abdd5262',\n authority: 'https://login.microsoftonline.com/d30f3b0f-3583-4916-a703-1ad8ab1d1102',\n redirectUri: '/'\n }\n}\n\nexport const loginRequest = {\n scopes: ['openid', 'https://sbhpai.com/Data.ReadWrite.All']\n}\n\nexport const msalInstance = new PublicClientApplication(msalConfig)\n","import { createContext, Dispatch, ReactNode, SetStateAction, useContext, useState } from \"react\"\nimport { useMsal, useAccount } from '@azure/msal-react'\nimport { AccountInfo, AuthenticationResult, AuthError, BrowserAuthError, InteractionRequiredAuthError, IPublicClientApplication } from \"@azure/msal-browser\"\nimport { ServiceFactory } from \"src/datasource/ServiceFactory\"\nimport { TokenProvider } from \"src/datasource/TokenProvider\"\nimport { loginRequest } from \"src/AuthConfig\"\nimport { WgApp } from 'src/wgapp/wgApp'\nimport { QueryClient } from 'react-query'\n\nexport interface AppContextType {\n account: AccountInfo | null\n instance: IPublicClientApplication\n serviceFactory: ServiceFactory\n wgApp: WgApp | undefined\n setWgApp: Dispatch>\n userAnnotationIds: string[]\n setUserAnnotationIds: Dispatch>\n totalAnnotationCount: number\n setTotalAnnotationCount: Dispatch>\n queryClient: QueryClient\n}\n\ninterface AppContextProviderProps {\n children: ReactNode\n}\n\nconst queryClient = new QueryClient({\n defaultOptions: {\n queries: {\n refetchOnWindowFocus: false,\n refetchIntervalInBackground: false,\n refetchOnMount: false,\n },\n }\n})\n\n//Tell TypeScript that during runtime the parameter will not be null or undefined to avoid checks everywhere\nexport const AppContext = createContext(undefined!)\n\nexport const useApp = (): AppContextType => {\n return useContext(AppContext)\n}\n\nexport const AppContextProvider = (props: AppContextProviderProps) => {\n const { instance, accounts } = useMsal()\n const account: AccountInfo | null = useAccount(accounts[0] !== undefined ? accounts[0] : {})\n const [wgApp, setWgApp] = useState(undefined)\n const [userAnnotationIds, setUserAnnotationIds] = useState([])\n const [totalAnnotationCount, setTotalAnnotationCount] = useState(0)\n\n const tokenProvider: TokenProvider = {\n getToken: async () => {\n if (account !== null) {\n const authresult: AuthenticationResult = await new Promise((resolve, reject) => {\n instance.acquireTokenSilent({ account: account, scopes: loginRequest.scopes })\n .then((ar: AuthenticationResult) => resolve(ar))\n .catch((error: AuthError) => {\n if (error instanceof InteractionRequiredAuthError || error instanceof BrowserAuthError) {\n instance.acquireTokenRedirect({ scopes: loginRequest.scopes })\n .catch((error: AuthError) => {\n console.error('Auth error', error)\n reject(error)\n })\n }\n })\n })\n return authresult.accessToken\n }\n throw new Error('No active account')\n }\n }\n const serviceFactory: ServiceFactory = ServiceFactory.instance(tokenProvider)\n\n return (\n \n {props.children}\n \n )\n}","import { makeStyles } from '@material-ui/core'\n\nexport const useStyles = makeStyles(theme => ({\n link: {\n textDecoration: 'none',\n color: theme.palette.text.primary,\n },\n markedItem: {\n paddingRight: theme.spacing(2),\n },\n}))\n\nexport default useStyles\n","\nexport const paths = {\n home: '/',\n inspections: '/inspections',\n report: '/report',\n}\n","import { useQuery } from \"react-query\"\nimport { AnalysisDetails } from \"src/datasource/model/analysisDetails\"\nimport List from '@material-ui/core/List'\nimport ListItem from '@material-ui/core/ListItem'\nimport ListItemText from '@material-ui/core/ListItemText'\nimport { Card, CardContent } from '@material-ui/core'\nimport { Box } from \"@material-ui/core\"\nimport { useApp } from \"src/components/AppContextProvider\"\nimport { Link, useParams } from \"react-router-dom\"\nimport useStyles from \"src/components/Analyses.style\"\nimport { paths } from \"src/datamodel/Constants\"\nimport ThreeDRotationIcon from '@material-ui/icons/ThreeDRotation'\nimport { RouterParams } from \"src/App\"\n\nexport const Analyses = () => {\n const { account, serviceFactory } = useApp()\n const classes = useStyles()\n const { inspectionId } = useParams()\n const inspectionIdNumber: number = inspectionId ? parseInt(inspectionId) : -1\n\n const analysesQuery = useQuery(['analyses', inspectionId], async () => await serviceFactory.getAnalysisServiceClient().getAnalysisForInspection(inspectionIdNumber),\n {\n enabled: account !== null && inspectionIdNumber !== -1,\n onError: () => {\n console.log('Error fetching analyses')\n }\n })\n\n return (\n \n \n \n {!analysesQuery.isSuccess || analysesQuery.isFetching ?\n 'Loading analyses...'\n :\n <>\n {analysesQuery.data.length === 0 ? 'No analyses found' : 'Analyses'}\n \n {analysesQuery.data?.map((a, i) =>\n \n \n {serviceFactory.getAnalysisServiceClient().isAlexandraAnalysis(a) &&\n \n }\n \n \n \n )}\n \n \n }\n \n \n \n )\n}","import { makeStyles } from '@material-ui/core'\n\nexport const useStyles = makeStyles(theme => ({\n appBar: {\n '@media print': {\n display: 'none'\n },\n },\n linkAppBar: {\n textDecoration: 'none',\n color: 'white',\n '&:hover': {\n textDecoration: 'underline',\n },\n },\n content: {\n '@media print': {\n marginTop: 0,\n },\n },\n progressContainer: {\n display: 'flex',\n position: 'absolute',\n right: theme.spacing(3),\n },\n}))\n\nexport default useStyles\n","import { Typography } from '@material-ui/core'\nimport { useApp } from 'src/components/AppContextProvider'\n\nexport const Progress = () => {\n const { userAnnotationIds, totalAnnotationCount } = useApp()\n\n return (\n \n Progress: {userAnnotationIds.length + '/' + totalAnnotationCount}\n \n )\n}\n","import { makeStyles } from '@material-ui/core'\n\nexport const useStyles = makeStyles(theme => ({\n link: {\n textDecoration: 'none',\n color: theme.palette.text.primary,\n },\n}))\n\nexport default useStyles\n","import { Menu, MenuItem } from \"@material-ui/core\"\nimport { Link } from \"react-router-dom\"\nimport useStyles from \"src/components/layout/AppMenu.style\"\n\ninterface AppMenuProps {\n anchor: HTMLElement | null\n open: boolean\n paths: any\n handleClose: () => void\n handleLogout: () => void\n}\n\nexport const AppMenu = ({ anchor, open, paths, handleClose, handleLogout }: AppMenuProps) => {\n const classes = useStyles()\n\n return (\n \n handleClose()}>\n Inspections\n \n handleClose()}>\n Report (test)\n \n handleLogout()}>\n Log out\n \n \n )\n}","import { AppBar, Toolbar, Typography, IconButton, Box } from '@material-ui/core'\nimport { ReactNode, useState } from 'react'\nimport { useParams } from 'react-router-dom'\nimport MenuIcon from '@material-ui/icons/Menu'\nimport { Link } from \"react-router-dom\"\nimport { paths } from 'src/datamodel/Constants'\nimport useStyles from 'src/components/layout/Layout.style'\nimport { useApp } from 'src/components/AppContextProvider'\nimport { RouterParams } from 'src/App'\nimport { Progress } from 'src/components/layout/Progress'\nimport { AppMenu } from 'src/components/layout/AppMenu'\n\ninterface LayoutProps {\n margin?: number\n showProgress?: boolean\n showHighlightId?: boolean\n highlightId?: number\n children: ReactNode\n}\n\nexport const Layout = ({ margin, showProgress, showHighlightId, highlightId, children }: LayoutProps) => {\n const { instance } = useApp()\n const classes = useStyles()\n const [anchorEl, setAnchorEl] = useState(null)\n const { inspectionId, analysisId } = useParams()\n const open = Boolean(anchorEl)\n\n const handleMenu = (event: React.MouseEvent) => {\n setAnchorEl(event.currentTarget)\n }\n\n const handleClose = () => {\n setAnchorEl(null)\n }\n\n const handleLogout = () => {\n instance.logout()\n handleClose()\n }\n\n //TODO: Find a better way - maybe via passed prop?\n const isReport = window.location.href.indexOf(\"report\") !== -1\n\n const renderTitle = (): ReactNode => {\n let titleNode: ReactNode = <>\n let documentTitle = ''\n if (inspectionId === undefined && analysisId === undefined) {\n documentTitle = 'Inspections'\n titleNode = 'Inspections'\n }\n if (inspectionId !== undefined && analysisId === undefined) {\n documentTitle = 'Inspection ' + inspectionId\n titleNode = (\n <>\n Inspections\n {' | ' + inspectionId}\n \n )\n }\n if (inspectionId !== undefined && analysisId !== undefined) {\n documentTitle = 'Analysis ' + analysisId\n titleNode = (\n <>\n {'Inspection ' + inspectionId}\n {' | Analysis ' + analysisId}\n \n )\n }\n \n if (isReport) {\n documentTitle = 'Report'\n titleNode = 'Report (test)'\n }\n document.title = documentTitle\n return titleNode\n }\n\n return (\n <>\n \n \n \n \n \n \n {renderTitle()}\n \n {showProgress &&\n
\n {showHighlightId &&\n \n \n {highlightId !== -1 ? 'Id: ' + highlightId : ''}\n \n \n }\n \n \n \n
\n }\n handleClose()}\n handleLogout={() => handleLogout()}\n />\n
\n
\n \n {children}\n \n \n )\n}","import { makeStyles } from '@material-ui/core'\n\nexport const useStyles = makeStyles(theme => ({\n link: {\n textDecoration: 'none',\n color: theme.palette.text.primary,\n }\n}))\n\nexport default useStyles\n","import { useQuery } from \"react-query\"\nimport List from '@material-ui/core/List';\nimport ListItem from '@material-ui/core/ListItem';\nimport ListItemText from '@material-ui/core/ListItemText';\nimport { Card, CardContent } from '@material-ui/core'\nimport { Box } from \"@material-ui/core\";\nimport { useApp } from \"src/components/AppContextProvider\";\nimport { Link } from \"react-router-dom\";\nimport useStyles from \"src/components/Inspections.style\";\nimport { paths } from \"src/datamodel/Constants\";\nimport { InspectionAnalysisReport } from \"src/datasource/model/InspectionAnalysisReport\";\n\nexport const Inspections = () => {\n const { account, serviceFactory } = useApp()\n const classes = useStyles()\n\n const inspectionsQuery = useQuery('inspections', async () => await serviceFactory.getInspectionServiceClient().getAllInspections(),\n {\n enabled: account !== null,\n onError: () => {\n console.log('Error fetching inspections')\n }\n })\n\n return (\n \n \n \n {(!inspectionsQuery.isSuccess && !inspectionsQuery.isError) && inspectionsQuery.isFetching ? \n 'Loading inspections...'\n :\n \n {inspectionsQuery.data?.map((ins, i) => \n \n \n \n \n \n )}\n \n }\n {(!inspectionsQuery.isFetching && inspectionsQuery.isError) && \n 'Could not load inspections'\n }\n \n \n \n )\n}","export class WgAppInterface {\n /**\n * Set left click handler.\n * @param {function} callback The callback function to be invoked on left\n * clicks. This method must be given an object with the id of the polygon\n * clicked (set to -1 if no polygon is clicked) and the type of damage\n * the polygon represents according to the ML model.\n */\n setLeftClickHandler (callback) {\n throw Error('Not implemented.')\n }\n\n /**\n * Set right click handler.\n * @param {function} callback The callback function to be invoked on right\n * clicks. This method must be given an object with the id of the polygon\n * clicked (-1 if no polygon is clicked).\n */\n setRightClickHandler (callback) {\n throw Error('Not implemented.')\n }\n\n /**\n * Set the data model in use.\n * @param {DataModel} dataModel The data model to load the 3D model from.\n * @see DataModel\n */\n setDataModel (dataModel) {\n throw Error('Not implemented.')\n }\n\n /**\n * Get a list of images that have contributed points to the given polygon.\n * @param {number} polygonId The ID of the polygon.\n * @returns {list} A list of images (IDs or file names) that contain parts\n * of this polygon.\n */\n imagesInPolygon (polygonId) {\n throw Error('Not implemented')\n }\n\n /**\n * @param {number} annotationId The ID of the annotation to create overlay for\n * @param {string} imageId The ID or file name of the image to create overlay for\n * @param {string} damageCategoryString Short-string of a damage category\n * @returns {ImageData} Instance of RGBA pixelvalues of the overlay\n */\n getAnnotationOverlay (annotationId, imageId, damageCategoryString) {\n throw Error('Not implemented')\n }\n\n /**\n * Get an imagedata overlay\n * @param {string} imageName The file name of the image to create overlay for\n * @param {string} damageCategoryString Short-string of a damage category\n * @returns {ImageData} RGBA pixelvalues of the overlay\n */\n getDamageCategoryOverlay (imageName, damageCategoryString) {\n throw Error('Not implemented')\n }\n\n /**\n * Update an annotation from a mask drawn on top of an image\n * @param {string} imageName The file name of the image\n * @param {number} annotationId Id of the annotation to update\n * @param {string} damageCategoryString Short-string of a damage category\n * @param {ImageData} overlayData Instance of ImageData that contains the mask image\n */\n updateAnnotationInImage (imageName, annotationId, damageCategoryString, overlayData) {\n throw Error('Not implemented')\n }\n\n /**\n * Create an annotation from a mask drawn on top of an image\n * @param {string} imageName The file name of the image\n * @param {string} damageCategoryString Short-string of a damage category\n * @param {ImageData} overlayData Instance of ImageData that contains the mask image\n * @return {number} The Id of the new annotation\n */\n createAnnotation (imageName, damageCategoryString, overlayData) {\n throw Error('Not implemented')\n }\n\n /**\n * Set visible damage categories\n * @param {string[]} visibleCategories Short-strings of the damage categories to show\n */\n setDamageCategoryVisibility (visibleCategories) {\n throw Error('Not implemented')\n }\n\n /**\n * Hide a specific set of annotations\n * Overrides all previous calls to showAnnotations and hideAnnotations.\n * @param {number[]} annotationIds Array of ids to hide. Entries must be in [0,65535]\n */\n hideAnnotations (annotationIds) {\n throw Error('Not implemented')\n }\n\n /**\n * Hide all annotations\n */\n hideAllAnnotations () {\n throw Error('Not implemented')\n }\n\n /**\n * Show only a specific set of annotations.\n * Overrides all previous call to showAnnotations and hideAnnotations.\n * @param {number[]} annotationIds Array of ids to show. Entries must be in [0,65535]\n */\n showAnnotations (annotationIds) {\n throw Error('Not implemented')\n }\n\n /**\n * Show all annotations\n */\n showAllAnnotations () {\n throw Error('Not implemented')\n }\n\n /**\n * Delete an annotation\n * @param {number} annotationId Id of the annotation to delete\n * @param {string} damageCategoryString Short-string of a damage category\n */\n deleteAnnotation (annotationId, damageCategoryString) {\n throw Error('Not implemented')\n }\n\n /**\n * Get annotation IDs\n * @return {Array} Array of structs that contain damage category name and the corresponding list of annotation IDs\n */\n getAnnotationIds () {\n throw Error('Not implemented')\n }\n\n /*\n * Get total number of annotations for all damage categories\n * @return {number} Annotation count\n */\n getTotalAnnotationCount () {\n throw Error('Not implemented')\n }\n}\n","import { Damage } from 'src/datasource/model/Damage'\n\nexport const damageCategories = ['Rust', 'Crack', 'Crack with precipitation', 'Spalling', 'Algae']\nexport const damageCategoriesShort = ['RUST', 'CRAC', 'CRPR', 'SPAL', 'ALGA']\nexport type DamageCategory = typeof damageCategories[number]\nexport type DamageCategoryShort = typeof damageCategoriesShort[number]\nexport class DamageMappingError extends Error {}\n\n/**\n * Take the id of the current damage and find the corresponding Damage from all damages.\n * With that Damage look at the name and map it to a DamageCategoryShort.\n * If anything goes wrong, throw exceptions.\n * \n * Ex:\n * If the selected damage is 5, go through the damages and find damage with id = 5, and take \n * the value, could be \"Rust\".\n * Map \"Rust\" to the best DamageCategoryShort it can find, in this case RUST.\n * \n * @param damages The list of all damages that exist in the system for the given tenant\n * @param id The id of current damage\n * @returns The model name of the selected damage\n */\nexport const mapFromBackendIdToModelName = (damages: Damage[], id: number): string => {\n const damagesWithCorrectId = damages.filter(d => id === d.id)\n if (damagesWithCorrectId.length === 0) {\n throw new DamageMappingError(\"No damage had the given id: \" + id + \", the damages in the system are: \" + damages)\n }\n if (damagesWithCorrectId.length > 1) {\n throw new DamageMappingError(\"More than one damage had the given id: \" + id + \", the damages in the system are: \" + damages)\n }\n return backendNameToModelName(damagesWithCorrectId[0].value)\n}\n\nfunction backendNameToModelName(damageName: string): DamageCategoryShort {\n const damageNameLowerCase = damageName.toLowerCase().trim()\n if (damageNameLowerCase === \"rust\") {\n return damageCategoriesShort[0]\n }\n if (damageNameLowerCase === \"crack\") {\n return damageCategoriesShort[1]\n }\n if (damageNameLowerCase.includes(\"crack\") &&\n damageNameLowerCase.includes(\"precipitation\")) {\n return damageCategoriesShort[2]\n }\n if (damageNameLowerCase === \"spalling\") {\n return damageCategoriesShort[3]\n }\n if (damageNameLowerCase === \"algae\") {\n return damageCategoriesShort[4]\n }\n throw new DamageMappingError(\"No damage mapping exists for model name: \" + damageName)\n}\n\n/**\n * Convert the modelName of the damage into a DamageCategory, then find the damage from\n * all the damages in the system and return its id.\n * \n * Ex:\n * The \"CRPR\" backend name is converted into 'Crack with precipitation' and that damage is found\n * in the list of all damages and the id hereof is returned\n * \n * @param damages The list of all damages that exist in the system for the given tenant\n * @param modelName The name of the damage in the model\n * @returns The id of the damage in the backend\n */\nexport const mapFromModelNameToBackendId = (damages: Damage[], modelName: DamageCategoryShort): number => {\n const backendName = modelNameToBackendName(modelName)\n const damagesWithCorrectValue = damages.filter(d => backendName.toLowerCase() === d.value.toLowerCase())\n if (damagesWithCorrectValue.length === 0) {\n throw new DamageMappingError(\"No damage had the given name: \" + backendName + \", the damages in the system are: \" + damages)\n }\n if (damagesWithCorrectValue.length > 1) {\n throw new DamageMappingError(\"More than one damage had the given name: \" + backendName + \", the damages in the system are: \" + damages)\n }\n return damagesWithCorrectValue[0].id\n}\n\nfunction modelNameToBackendName(damageName: DamageCategoryShort): DamageCategory {\n if (damageName === \"RUST\") {\n return damageCategories[0]\n }\n if (damageName === \"CRAC\") {\n return damageCategories[1]\n }\n if (damageName === \"CRPR\") {\n return damageCategories[2]\n }\n if (damageName === \"SPAL\") {\n return damageCategories[3]\n }\n if (damageName === \"ALGA\") {\n return damageCategories[4]\n }\n throw new DamageMappingError(\"No damage mapping exists for backend name: \" + damageName)\n}","import { Bitmap } from './Bitmap'\n\n/**\n * Type for describing a bounding box defined by its top left\n * and bottom right corners. The top left corner is (x1,y1)\n * and the bottom right corner is (x2,y2).\n */\ninterface BoundingBox {\n x1: number\n y1: number\n x2: number\n y2: number\n}\n\nenum ColorChannel {\n Red = 0,\n Green = 1,\n Blue = 2,\n Alpha = 3,\n All = 4\n}\n\n/**\n * An image with only two color values - 0 and 1.\n */\nclass BitmapImage {\n _width: number\n _height: number\n _bitmap: Bitmap\n\n /**\n * Constructor. This constructor dows sanity checking of its input.\n * The size of the bitmap must be width * height. If no bitmap is given,\n * a new empty bitmap is created.\n * @param width The width of the image.\n * @param height The height of the image.\n * @param bitmap The bitmap representing the image data.\n * @throws An Error if the dimensions of the images doesn't match\n * the given bitmap.\n */\n constructor (width: number, height: number, bitmap: Bitmap | undefined = undefined) {\n if (bitmap !== undefined && bitmap.size !== width * height) {\n throw new Error('Invalid image dimensions given.')\n }\n this._width = width\n this._height = height\n this._bitmap = bitmap !== undefined ? bitmap : new Bitmap(width * height)\n }\n\n getHeight(): number {\n return this._height\n }\n\n getWidth(): number {\n return this._width\n }\n\n get bitmap (): Bitmap { return this._bitmap }\n\n /**\n * Factory method for creating a BitmapImage from an array of RGBA data.\n * @param data RGBA data array.\n * @param width The width of the image.\n * @param height The height of the image.\n * @param channel The color channel to look at when setting the bits.\n * @returns A new BitmapImage instance.\n */\n static fromRGBAData (data: Uint8ClampedArray, width: number, height: number, channel: ColorChannel = ColorChannel.All): BitmapImage {\n // Sanity check.\n if (data.length % 4 !== 0) {\n throw new Error('The RGBA data array must be divisible by 4.')\n }\n if (data.length !== width * height * 4) {\n throw new Error('Invalid image dimensions given.')\n }\n\n const bitmap = new Bitmap(width * height)\n\n // Convert RGBA data to a pure bitmap.\n if (channel === ColorChannel.All) {\n for (let i = 0; i < data.length; i++) {\n if (data[i] !== 0) {\n bitmap.set(Math.floor(i / 4))\n }\n }\n } else {\n for (let i = channel; i < data.length; i += 4) {\n if (data[i] !== 0) {\n bitmap.set(Math.floor(i / 4))\n }\n }\n }\n return new BitmapImage(width, height, bitmap)\n }\n\n /**\n * Write the bitmap image back to the RGBA format that it was\n * created from when using \\see fromRGBAData.\n * @param channel The color channel to write to.\n * @returns An array of RGBA tuples representing an image.\n */\n toRGBAData (channel: ColorChannel = ColorChannel.All): Uint8ClampedArray {\n const data = new Uint8ClampedArray(this.bitmap.size * 4)\n const enabledIndices = this.bitmap.enabledIndices()\n enabledIndices.forEach(index => {\n const offset = index * 4\n if (channel === ColorChannel.All) {\n data[offset] = 255\n data[offset + 1] = 255\n data[offset + 2] = 255\n } else {\n data[offset + channel] = 255\n }\n data[offset + 3] = 255 // Alpha is set regardless to avoid confusion ;-)\n })\n return data\n }\n\n /**\n * Get the minimum bounding box of the data within the bitmap image.\n * @param margin The margin to add to the bounding box. This margin is\n * added to the top, bottom, left and right og the box.\n * @returns The bounding box of the data within the bitmap image.\n */\n boundingBox (margin: number = 0): BoundingBox {\n const result: BoundingBox = { x1: 0, y1: 0, x2: this._width - 1, y2: this._height - 1 }\n\n // The bitmap is laid out in row-by-row fashion, so running through it's\n // selected indices is running through the image data line by line from\n // left to right. The first and the last enabled index must then define\n // y1 and y2.\n const enabledIndices = this._bitmap.enabledIndices()\n result.y1 = Math.floor(enabledIndices[0] / this._width)\n result.y2 = Math.floor(enabledIndices[enabledIndices.length - 1] / this._width)\n\n let minX = this._width\n let maxX = -1\n for (let i = 0; i < enabledIndices.length; i++) {\n const xPosition = enabledIndices[i] - Math.floor(enabledIndices[i] / this._width) * this._width\n if (xPosition < minX) {\n minX = xPosition\n }\n if (xPosition > maxX) {\n maxX = xPosition\n }\n }\n result.x1 = minX\n result.x2 = maxX\n\n // Apply margin if needed.\n if (margin !== 0) {\n result.x1 = result.x1 - margin > 0 ? result.x1 - margin : 0\n result.y1 = result.y1 - margin > 0 ? result.y1 - margin : 0\n result.x2 = result.x2 + margin < this._width ? result.x2 + margin : this._width - 1\n result.y2 = result.y2 + margin < this._height ? result.y2 + margin : this._height - 1\n }\n\n return result\n }\n\n /**\n * Scale the bitmap image down by the given factor.\n * @param factor The factor to scale the bitmap image down by.\n * @throws An Error if the image cannot be scaled by that factor.\n */\n scaleDown (factor: number): void {\n // This scaling only works if the dimensions can be divided evenly\n // into 'factor' pieces.\n // We do not check height that matches the factor, as we want to allow\n // images of \"weird\" resolution\n if (this._width % factor !== 0) {\n throw new Error('Invalid scaling factor given.')\n }\n\n const result = new Bitmap(this._bitmap.size / (factor * factor))\n const resultWidth = this._width / factor\n // Rounding as this may not be an integer\n const resultHeight = Math.floor(this._height / factor)\n\n for (let x = 0; x < resultWidth; x++) {\n for (let y = 0; y < resultHeight; y++) {\n const upperLeftX = x * factor\n const upperLeftY = y * factor\n let isSet = false\n for (let x2 = upperLeftX; x2 < upperLeftX + factor; x2++) {\n for (let y2 = upperLeftY; y2 < upperLeftY + factor; y2++) {\n const positionInOrig = y2 * this._width + x2\n if (this._bitmap.isSet(positionInOrig)) {\n isSet = true\n }\n }\n }\n if (isSet) {\n result.set(y * resultWidth + x)\n }\n }\n }\n\n this._bitmap = result\n this._width = resultWidth\n this._height = resultHeight\n }\n\n /**\n * Scale up the size of the bitmap image.\n * @param factor Scale up factor.\n * @throws An Error if the factor is invalid.\n */\n scaleUp (factor: number): void {\n if (factor < 1) {\n throw new Error('Invalid factor given.')\n }\n factor = Math.floor(factor)\n\n const result = new Bitmap(this.bitmap.size * factor * factor)\n const newWidth = this._width * factor\n const enabledIndices = this.bitmap.enabledIndices()\n enabledIndices.forEach(index => {\n const row = Math.floor(index / this._width)\n const column = index % this._width\n const rowOffset = row * factor\n const columnOffset = column * factor\n for (let i = rowOffset; i < rowOffset + factor; i++) {\n for (let j = columnOffset; j < columnOffset + factor; j++) {\n result.set(i * newWidth + j)\n }\n }\n })\n\n this._bitmap = result\n this._height = this._height * factor\n this._width = this._width * factor\n }\n}\n\nexport { BitmapImage, ColorChannel }\nexport type { BoundingBox }\n","// I have disabled the rule that all class names should start with\n// a capital letter. I think that should be enabled later on, to\n// make all the code adhere to StandardJS but that would entail\n// updating all the wg* classes.\n// See: https://eslint.org/docs/rules/new-cap\n/* eslint new-cap: 0 */\n\n// Interface definition.\nimport { WgAppInterface } from 'src/wgapp/WgAppInterface.js'\nimport { damageCategoriesShort } from 'src/datamodel/DamageMapping'\n\n// External ////////////////////////////////////////////////////////\nimport { quat, vec3, vec4, mat4 } from 'gl-matrix'\nimport { parse } from '@loaders.gl/core'\nimport { GLTFLoader } from '@loaders.gl/gltf'\n\n// wgtek ///////////////////////////////////////////////////////////\nimport { wgContext } from 'wgTek/wgContext'\nimport { wgResourceCache } from 'wgTek/wgResourceCache.js'\nimport { wgPrimRender } from 'wgTek/wgPrimRender.js'\nimport { wgTexture } from 'wgTek/wgTexture.js'\nimport { wgFbo } from 'wgTek/wgFbo.js'\nimport { VertexType, wgVertexDescriptor } from 'wgTek/wgVertexDescriptors.js'\nimport { wgVertexBuffer, wgIndexType } from 'wgTek/wgVertexBuffer.js'\nimport { wgShader } from 'wgTek/wgShader.js'\nimport { wgMeshBuilder } from 'wgTek/wgMeshBuilder.js'\n\n// wfun ////////////////////////////////////////////////////////////\nimport { MouseEventHandler, MouseButtons } from 'wFundament/MouseEventHandler.js'\nimport { KeyboardEventHandler } from 'wFundament/KeyboardEventHandler.js'\nimport { TouchEventHandler } from 'wFundament/TouchEventHandler.js'\nimport { wOrbitCamera } from 'wFundament/wOrbitCamera.js'\nimport { wGizmo, wGizmoMode } from 'wFundament/wGizmo.js'\n\n// app /////////////////////////////////////////////////////////////\nclass WgApp extends WgAppInterface {\n constructor (canvas) {\n super()\n\n const gl = canvas.getContext('webgl2', { preserveDrawingBuffer: true })\n\n this.glContext_ = new wgContext(gl, canvas)\n this.gl = this.glContext_.gl()\n this.frameCount_ = 0\n this.lastFps_ = 0\n this.resourceCache_ = new wgResourceCache() // a convenient way to share textures and other graphics resources.\n\n this.cameraPosition_ = vec3.fromValues(-15.0, 0.0, 10.0)\n this.orbitCamera_ = new wOrbitCamera('orbitCamera')\n this.orbitCamera_.setViewport(this.glContext_.getCanvasWidth(), this.glContext_.getCanvasHeight())\n this.orbitCamera_.setOrbitPivot([0, -5, 0])\n this.orbitCamera_.setCameraPosition(this.cameraPosition_)\n this.orbitCamera_.setPerspective(60.0)\n this.orbitCamera_.setUpvector(vec3.fromValues(0.0, 0.0, 1.0))\n this.orbitCamera_.setZoomSpeed(4.0)\n this.cameraActiveCounter_ = 0 // used to make sure that the active camera keeps the focus\n\n this.primRender_ = null\n this.primRenderIdAsColor_ = null\n this.gizmo_ = new wGizmo(15.0)\n this.gizmo_.intersectionTolerance_ = 0.5\n this.gizmo_.setGizmoMode(wGizmoMode.INACTIVE)\n\n this.readBackFbo_ = null\n this.readBackTexture_ = null\n this.readbackPixels_ = new Uint8Array(canvas.width * canvas.height * 4)\n this.selectedObject_ = -1\n this.hoveredLabel_ = -1\n\n this.maskFbo_ = null\n this.maskTexture_ = null\n\n this.transform_ = mat4.create()\n\n this.primTransform_ = mat4.create()\n // mat4.fromXRotation(this.primTransform_, Math.PI / 2.0)\n\n this.vertexBuffer_ = new wgVertexBuffer('vbo', this.glContext_)\n this.colorTexture_ = new wgTexture('color', this.glContext_)\n this.labelTexture_ = new wgTexture('label', this.glContext_) // texture array. Each layer is a damage type and texels are IDs\n this.labelVisibiltyTexture_ = new wgTexture('labelVisiblity', this.glContext_) // Lookup table for 16bit labels\n this.labelVisibiltyTexture_.create2D(gl.R8, 256, 256, true, false)\n\n this.imageAnnotationTexture_ = new wgTexture('annotation', this.glContext_)\n this.combinedOverlayFbo_ = null\n this.combinedLabelTexture_ = null // 2d texture. Texel value is the damage type\n\n this.shader_ = new wgShader('shader', this.glContext_)\n this.idshader_ = new wgShader('idshader', this.glContext_)\n this.maskShader_ = new wgShader('maskshader', this.glContext_)\n this.combineOverlayShader_ = new wgShader('combineShader', this.glContext_)\n this.meshUvMaskShader_ = new wgShader('meshUvShader', this.glContext_)\n this.posDepthShader_ = new wgShader('posDepthShader', this.glContext_)\n\n this.labelmapDamageCategoriesData_ = []\n\n this.damageOpacity_ = 0.5\n this.visibleDamageCategories_ = damageCategoriesShort\n this.visibleDamageCategoriesBitmask_ = 255\n\n this.cameraFeatures_ = null\n\n const meshBuilder = new wgMeshBuilder('builder', this.glContext_)\n this.quadVbo_ = meshBuilder.buildFullscreenQuad('quad')\n\n const fullScreenQuadVssrc = `#version 300 es\n in vec4 Pos;\n void main()\n {\n gl_Position = vec4(Pos.xy, 0.0, 1.0);\n }`\n const combineOverlayFsSrc = `#version 300 es\n precision mediump float;\n out vec4 outColor;\n uniform mediump usampler2DArray labelTexture;\n uniform mediump sampler2D visibilityLookupTexture;\n uniform int visibleBitmask;\n void main()\n {\n ivec2 pxpos = ivec2(gl_FragCoord.xy);\n int labelType = 0;\n\n outColor = vec4(0.0);\n for ( int i = 0; i < textureSize(labelTexture, 0).z; i++ )\n {\n if ( (( uint(visibleBitmask) >> uint(i) ) & 1u) != 0u )\n {\n uvec2 labelForType = texelFetch(labelTexture, ivec3(pxpos, i) , 0).rg;\n\n if ( (labelForType.x != 0u) || (labelForType.y != 0u)){\n float labelVisibilty = texelFetch(visibilityLookupTexture, ivec2(labelForType), 0).r;\n if ( labelVisibilty > 0.0 ){\n outColor = vec4(float(labelForType.r)/255.0, float(labelForType.g)/255.0, 0.0, float(i+1)/255.0);\n }\n }\n }\n }\n }\n `\n\n const vssrc = `#version 300 es\n in vec3 Pos;\n in vec2 Texcoord;\n uniform mat4 VP;\n out vec2 uv;\n void main()\n {\n uv = Texcoord;\n gl_Position = VP * vec4(Pos, 1.0);\n }\n `\n // Color texture with labels\n const labelColors = this.getLabelColors()\n\n const fssrc = `#version 300 es\n precision mediump float;\n uniform sampler2D colorTexture;\n uniform sampler2D labelTexture;\n uniform float opacity;\n uniform int highlightedLabel;\n out vec4 outColor;\n in vec2 uv;\n const vec4 lut[5] = vec4[5](\n vec4${labelColors[0]},\n vec4${labelColors[1]},\n vec4${labelColors[2]},\n vec4${labelColors[3]},\n vec4${labelColors[4]}\n );\n void main()\n {\n outColor = texture(colorTexture, vec2(uv.s, uv.t));\n vec4 labelColor = outColor;\n\n ivec4 labelTexel = ivec4(255.0*texture(labelTexture, uv));\n int label = labelTexel.a;\n if ( label > 0 && label < 6 ){\n labelColor = lut[label-1];\n\n if ( highlightedLabel > 0 && highlightedLabel == ( labelTexel.r + labelTexel.g * 256 ) )\n {\n outColor.rgb += 0.2;\n }\n else\n {\n outColor = (1.0-opacity)*outColor + opacity*labelColor;\n }\n }\n }\n `\n const depthVsSrc = `#version 300 es\n in vec3 Pos;\n uniform mat4 VP;\n out vec4 positionDepth;\n void main()\n {\n gl_Position = VP * vec4(Pos, 1.0);\n positionDepth = vec4(Pos, gl_Position.z);\n }\n `\n\n const depthFsSrc = `#version 300 es\n precision mediump float;\n in vec4 positionDepth;\n layout(location=0) out uvec4 outPos;\n void main()\n {\n outPos = floatBitsToUint(positionDepth);\n }\n `\n\n // Render Id in RG and damage type in A\n const idfssrc = `#version 300 es\n precision mediump float;\n uniform sampler2D colorTexture;\n uniform sampler2D visibilityLookupTexture;\n\n uniform int visibleBitmask;\n uniform mediump usampler2DArray labelTexture;\n\n\n out vec4 outColor;\n in vec2 uv;\n void main()\n {\n ivec3 uvPx;\n uvPx.xy = ivec2(vec2(textureSize(labelTexture, 0).xy) * uv);\n\n\n uvec2 labelRg = uvec2(0,0);\n int labelType = 0;\n for ( int i = 0; i < textureSize(labelTexture, 0).z; i++ )\n {\n\n if ( (( uint(visibleBitmask) >> uint(i) ) & 1u) != 0u )\n {\n uvPx.z = i;\n uvec2 labelForType = texelFetch(labelTexture, uvPx, 0).rg;\n\n if ( labelForType.x > 0u || labelForType.y > 0u )\n {\n float labelVisibilty = texelFetch(visibilityLookupTexture, ivec2(labelForType), 0).r;\n if ( labelVisibilty > 0.0 ){\n labelRg = labelForType;\n labelType = i+1;\n }\n }\n }\n }\n outColor = vec4(vec2(labelRg)/255.0, 0.0, float(labelType)/255.0);\n }\n `\n // Render binary image for labels of a specific type\n const maskFssrc = `#version 300 es\n precision mediump float;\n\n uniform mediump usampler2DArray labelTexture;\n uniform int labelType;\n uniform int selectedAnnotationId;\n\n out vec4 outColor;\n in vec2 uv;\n void main()\n {\n ivec3 uvPx;\n uvPx.xy = ivec2(vec2(textureSize(labelTexture, 0).xy) * uv);\n uvPx.z = labelType;\n\n uvec2 labelForType = texelFetch(labelTexture, uvPx, 0).rg;\n\n float mask = 0.0;\n int annotationId = 256*int(labelForType.y) + int(labelForType.x);\n if ( annotationId > 0 && ((annotationId == selectedAnnotationId) || selectedAnnotationId == 0) )\n {\n mask = 1.0;\n }\n outColor = vec4(mask);\n //outColor = vec4(1.0);\n }\n `\n const meshUvInsideMaskFsSrc = `#version 300 es\n precision mediump float;\n in vec2 uv;\n uniform mediump sampler2D maskTexture;\n uniform vec2 viewport;\n out vec4 outColor;\n void main()\n {\n // Screenspace uv\n //vec2 ssUv = gl_FragCoord.xy / vec2(textureSize(maskTexture, 0).xy);\n vec2 ssUv = gl_FragCoord.xy / viewport;\n outColor = vec4(0.0);\n // Lookup mask in screenspace\n float maskValue = texture(maskTexture, ssUv).r;\n // Output mesh uv if fragment is inside mask\n if ( maskValue > 0.0 ){\n highp uint pack = packUnorm2x16(uv); // Note uv.s is LSB, uv.t is MSB\n //outColor = unpackUnorm4x8( pack ); // Doesnt work?\n outColor = vec4((pack >> 8u)&0xFFu, pack&0xFFu, (pack >> 24u)&0xFFu,(pack >> 16u)&0xFFu) / 255.0;\n }\n }\n `\n this.shader_.createShaderProgram(vssrc, fssrc, { Pos: 0, Texcoord: 2 })\n this.idshader_.createShaderProgram(vssrc, idfssrc, { Pos: 0, Texcoord: 2 })\n this.maskShader_.createShaderProgram(vssrc, maskFssrc, { Pos: 0, Texcoord: 2 })\n this.combineOverlayShader_.createShaderProgram(fullScreenQuadVssrc, combineOverlayFsSrc, { Pos: 0 })\n this.meshUvMaskShader_.createShaderProgram(vssrc, meshUvInsideMaskFsSrc, { Pos: 0, Texcoord: 2 })\n this.posDepthShader_.createShaderProgram(depthVsSrc, depthFsSrc, { Pos: 0 })\n\n // event handlers\n this.onLeftClickCallback = null\n this.onRightClickCallback = null\n this.onDamageHoverCallback_ = null\n\n this.keyboardEventHandler_ = new KeyboardEventHandler()\n this.mouseEventHander_ = new MouseEventHandler()\n this.touchEventHandler_ = new TouchEventHandler()\n\n this.appInfo_ = {\n appName: 'Fbo read back Demo',\n appDeveloper: 'Trier & Kjeldsen',\n fps: 0\n }\n\n this.pickingInfo_ = {\n object: 'unknown'\n }\n\n this._dataModel = null\n\n this.init()\n\n this.scheduleRender_ = true\n let lastTimeStamp = 0\n const loop = (timestamp) => {\n const deltaTime = timestamp - lastTimeStamp\n if (this.update(deltaTime / 100.0) || this.scheduleRender_) {\n this.render(timestamp)\n this.scheduleRender_ = false\n }\n\n lastTimeStamp = timestamp\n\n requestAnimationFrame(loop)\n }\n requestAnimationFrame(loop)\n }\n\n getKeyboardEventHandler () { return this.keyboardEventHandler_ }\n getMouseEventHandler () { return this.mouseEventHander_ }\n getTouchEventHandler () { return this.touchEventHandler_ }\n\n async setDataModel (dataModel, onComplete = () => {}) {\n this._dataModel = dataModel\n await this.loadMesh()\n onComplete()\n }\n\n /*\n * Internal. Load mesh and textures from this.datamodel_\n */\n async loadMesh () {\n const gl = this.glContext_.gl()\n\n this.cameraFeatures_ = await this._dataModel.opensfm()\n\n parse(this._dataModel.gltfModel(), GLTFLoader, { worker: false }).then((gltf) => {\n const scene = gltf.scene\n let node = scene.nodes[0]\n\n const transform = mat4.create()\n\n if (node.matrix) {\n mat4.copy(transform, node.matrix)\n } else {\n const translation = vec3.create()\n const rotation = quat.create()\n const scale = vec3.fromValues(1, 1, 1)\n if (node.translation) {\n vec3.copy(translation, node.translation)\n }\n if (node.rotation) {\n quat.copy(rotation, node.rotation)\n }\n if (node.scale) {\n vec3.copy(scale, node.scale)\n }\n mat4.fromRotationTranslationScale(transform, rotation, translation, scale)\n }\n // GLTF is Y up as standard\n const toZup = mat4.create()\n mat4.fromXRotation(toZup, Math.PI / 2)\n mat4.multiply(this.transform_, toZup, transform)\n\n let mesh = node.mesh\n while (mesh === undefined) {\n if (node === undefined) {\n break\n }\n node = node.children[0]\n mesh = node.mesh\n }\n const material = mesh.primitives[0].material\n\n const vertexCount = mesh.primitives[0].attributes.POSITION.count\n const posAttr = mesh.primitives[0].attributes.POSITION.value\n const normalAttr = mesh.primitives[0].attributes.NORMAL.value\n const uvAttr = mesh.primitives[0].attributes.TEXCOORD_0.value\n\n const desc = new wgVertexDescriptor(VertexType.VT_VertexNormalUv3, this.glContext_.gl())\n const vertexData = new Float32Array(vertexCount * 8)\n for (let i = 0; i < vertexCount; i++) {\n for (let j = 0; j < 3; j++) {\n vertexData[8 * i + j] = posAttr[3 * i + j]\n }\n for (let j = 0; j < 3; j++) {\n vertexData[8 * i + 3 + j] = normalAttr[3 * i + j]\n }\n for (let j = 0; j < 2; j++) {\n vertexData[8 * i + 6 + j] = uvAttr[2 * i + j]\n }\n }\n\n const indices = mesh.primitives[0].indices\n\n let indexType = wgIndexType.wgUnsignedShort\n if (indices.componentType === gl.UNSIGNED_BYTE) {\n indexType = wgIndexType.wgUnsignedByte\n } else if (indices.componentType === gl.UNSIGNED_INT) {\n indexType = wgIndexType.wgUnsignedInt\n }\n\n this.vertexBuffer_.deleteVertexBuffer()\n this.vertexBuffer_.createElementsVertexBuffer(gl.STATIC_DRAW, desc.getVertexLayout(), vertexCount, desc.getVertexSizeInBytes(), indexType, indices.value, vertexData)\n\n if (material.pbrMetallicRoughness.baseColorTexture) {\n this.colorTexture_.deleteTexture()\n this.colorTexture_.setActiveTexture(gl.TEXTURE0)\n this.colorTexture_.create2dFromImage(gltf.images[0].image, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, false, true)\n } else {\n const image = new Image()\n image.onload = () => {\n this.colorTexture_.deleteTexture()\n this.colorTexture_.setActiveTexture(gl.TEXTURE0)\n this.colorTexture_.create2dFromImage(image, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, false, true)\n this.render()\n }\n try {\n this._dataModel.colorMap().then((colormap) => {\n image.src = colormap\n })\n } catch (error) {\n console.error(`Error loading color map: ${error}`)\n }\n }\n\n this.scheduleRender_ = true\n })\n\n const maps = await this._dataModel.labelMaps()\n\n this.labelmapDamageCategoriesData_ = []\n let textureInitialized = false\n let texSize\n // Parse NPY files. Data is assumed to be uint16_t\n for (let i = 0; i < damageCategoriesShort.length; i++) {\n const buf = maps[damageCategoriesShort[i].toLowerCase()]\n if (buf) {\n const view = new DataView(buf)\n const hdrlen = view.getUint16(8, true)\n\n let hdrStr = ''\n for (let i = 0; i < hdrlen; i++) {\n hdrStr += String.fromCharCode(view.getUint8(i + 10))\n }\n\n const hdr = hdrStr.match(/'shape': \\((?\\d+), (?\\d+)\\)/)\n texSize = hdr.groups\n\n if (!textureInitialized) {\n this.labelTexture_.setActiveTexture(gl.TEXTURE1)\n this.labelTexture_.deleteTexture()\n this.labelTexture_.create2DArray(gl.RG8UI, texSize.width, texSize.height, damageCategoriesShort.length, true)\n textureInitialized = true\n }\n\n const pixeldata = new Uint16Array(buf, 10 + hdrlen)\n const maxval = pixeldata.reduce((a, b) => { return Math.max(a, b) })\n this.labelmapDamageCategoriesData_.push({ npyData: buf, npyHdr: buf.slice(0, hdrlen + 10), width: texSize.width, height: texSize.height, pixeldata: pixeldata, nextAnnotationId: maxval + 1 })\n\n this.labelTexture_.bind()\n gl.texSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 0, 0, i, texSize.width, texSize.height, 1, gl.RG_INTEGER, gl.UNSIGNED_BYTE, new Uint8Array(pixeldata.buffer, pixeldata.byteOffset))\n this.labelTexture_.unbind()\n }\n }\n // Set all labels visible\n this.labelVisibiltyTexture_.uploadDataToTexture(gl.RED, gl.UNSIGNED_BYTE, new Uint8Array(65536).fill(255))\n\n // Create the combined texture\n this.updateCombinedOverlayTexture(this.visibleDamageCategories_)\n\n this.scheduleRender_ = true\n }\n\n init () {\n // create the swap chain\n this.createFbo()\n this.primRender_ = new wgPrimRender('primitiveRender', this.glContext_)\n\n this.primRender_.addGridXZ(24.0, 10.01)\n\n // event handling\n this.glContext_.canvas_.addEventListener('keydown', (event) => { this.getKeyboardEventHandler().keyDown(event.key) })\n this.glContext_.canvas_.addEventListener('keyup', (event) => { this.getKeyboardEventHandler().keyUp(event.key) })\n\n this.glContext_.canvas_.addEventListener('mousedown', (event) => { this.getMouseEventHandler().onMouseDown(event) })\n this.glContext_.canvas_.addEventListener('mouseup', (event) => { this.getMouseEventHandler().onMouseUp(event) })\n\n const mouseDownPos = [-1, -1]\n this.glContext_.canvas_.addEventListener('mousedown', (event) => { mouseDownPos[0] = event.offsetX; mouseDownPos[1] = event.offsetY })\n this.glContext_.canvas_.addEventListener('mouseup', (event) => { if (mouseDownPos[0] === event.offsetX && mouseDownPos[1] === event.offsetY) { this.onClick(event) } })\n\n this.glContext_.canvas_.addEventListener('mousemove', (event) => { this.getMouseEventHandler().onMouseMove(event) })\n this.glContext_.canvas_.addEventListener('mousemove', (event) => { this.onMouseMove(event) })\n this.glContext_.canvas_.addEventListener('mouseleave', (event) => { this.getMouseEventHandler().onMouseLeave(event) })\n this.glContext_.canvas_.addEventListener('click', (event) => { this.getMouseEventHandler().onMouseClick(event) })\n this.glContext_.canvas_.addEventListener('dblclick', (event) => { this.getMouseEventHandler().onMouseDoubleClick(event) })\n this.glContext_.canvas_.addEventListener('wheel', (event) => { event.preventDefault(); this.getMouseEventHandler().onMouseWheel(event) })\n\n this.glContext_.canvas_.addEventListener('touchstart', (event) => { this.getTouchEventHandler().onTouchStart(event) })\n this.glContext_.canvas_.addEventListener('touchend', (event) => { this.getTouchEventHandler().onTouchEnd(event) })\n this.glContext_.canvas_.addEventListener('touchcancel', (event) => { this.getTouchEventHandler().onTouchCancel(event) })\n this.glContext_.canvas_.addEventListener('touchmove', (event) => { this.getTouchEventHandler().onTouchMove(event) })\n\n this.glContext_.canvas_.addEventListener('contextmenu', (e) => { e.preventDefault(); this.getMouseEventHandler().onMouseRightClick() }, false)\n }\n\n createFbo () {\n const gl = this.gl\n this.readBackFbo_ = new wgFbo('ReadBackFbo', this.glContext_)\n this.readBackTexture_ = new wgTexture('readBackTexture', this.glContext_)\n this.readBackTexture_.setActiveTexture(gl.TEXTURE0)\n this.readBackTexture_.create2D(gl.RGBA8, this.glContext_.getCanvasWidth(), this.glContext_.getCanvasHeight(), true, false)\n this.readBackFbo_.attachTexture(this.readBackTexture_)\n this.readBackFbo_.createDepthStencilBuffer(this.glContext_.getCanvasWidth(), this.glContext_.getCanvasHeight())\n this.readBackFbo_.unbind()\n\n this.posFbo_ = new wgFbo('posFbo', this.glContext_)\n this.posTexture_ = new wgTexture('posTexture', this.glContext_)\n this.posTexture_.setActiveTexture(gl.TEXTURE0)\n this.posTexture_.create2D(gl.RGBA32UI, this.glContext_.getCanvasWidth(), this.glContext_.getCanvasHeight(), true, false)\n\n this.posFbo_.attachTexture(this.posTexture_)\n this.posFbo_.createDepthStencilBuffer(this.glContext_.getCanvasWidth(), this.glContext_.getCanvasHeight())\n this.posFbo_.unbind()\n\n this.maskFbo_ = new wgFbo('maskFbo', this.glContext_)\n this.maskTexture_ = new wgTexture('maskTexture', this.glContext_)\n\n this.maskTexture_.setActiveTexture(gl.TEXTURE0)\n this.maskTexture_.create2D(gl.RGBA8, 1, 1, true, false)\n this.maskFbo_.attachTexture(this.readBackTexture_)\n this.maskFbo_.createDepthStencilBuffer(1, 1)\n this.maskFbo_.unbind()\n\n this.combinedOverlayFbo_ = new wgFbo('combinedOverlay', this.glContext_)\n this.combinedLabelTexture_ = new wgTexture('combinedLabel', this.glContext_) // 2d texture. Texel value is the damage type\n this.combinedLabelTexture_.create2D(gl.RGBA8, 2048, 2048, true, false)\n\n this.combinedOverlayFbo_.attachTexture(this.combinedLabelTexture_)\n this.combinedOverlayFbo_.unbind()\n\n this.imageOverlayFbo_ = new wgFbo('imageOverlayFbo', this.glContext_)\n this.imageOverlayFboTexture_ = new wgTexture('imageOverlayFboTex', this.glContext_)\n this.imageOverlayFboTexture_.create2D(gl.RGBA8, 1, 1, true, false)\n this.imageOverlayFbo_.attachTexture(this.imageOverlayFboTexture_)\n this.imageOverlayFbo_.createDepthStencilBuffer(1, 1)\n this.imageOverlayFbo_.unbind()\n }\n\n update (deltaTime) {\n let isUpdated = false\n\n const fx = this.getMouseEventHandler().getNormX()\n const fy = this.getMouseEventHandler().getNormY()\n const pickingRay = this.orbitCamera_.getPickingRay(fx, fy)\n const isLeftMouseDown = this.getMouseEventHandler().isDown(MouseButtons.LeftButton)\n\n const prevHoverState = this.gizmo_.isHovering()\n const prevDragState = this.gizmo_.isDragging()\n\n if (this.cameraActiveCounter_ === 0) {\n this.gizmo_.update(pickingRay, [fx, fy], isLeftMouseDown)\n }\n\n if (this.gizmo_.isHovering() !== prevHoverState || this.gizmo_.isDragging() !== prevDragState) {\n isUpdated = true\n this.scheduleRender_ = true\n }\n\n if (this.gizmo_.isDragging()) {\n isUpdated = true\n this.scheduleRender_ = true\n } else {\n if (this.orbitCamera_.update(deltaTime, this.getMouseEventHandler(), this.getKeyboardEventHandler(), this.getTouchEventHandler())) {\n this.cameraActiveCounter_ = 1\n isUpdated = true\n this.scheduleRender_ = true\n } else {\n this.cameraActiveCounter_ = 0\n }\n }\n\n this.getMouseEventHandler().flush()\n this.getTouchEventHandler().flush()\n return isUpdated\n }\n\n render () {\n this.updateFps()\n\n const vp = this.orbitCamera_.getViewProjection()\n const gl = this.gl\n\n const mvp = mat4.create()\n const mvpprim = mat4.create()\n\n gl.clearColor(0.15, 0.15, 0.15, 1.0)\n\n gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)\n gl.enable(gl.DEPTH_TEST)\n\n gl.viewport(0, 0, this.glContext_.getCanvasWidth(), this.glContext_.getCanvasHeight())\n\n mat4.multiply(mvpprim, vp, this.primTransform_)\n this.primRender_.clearPrimitive()\n this.primRender_.addGizmo(this.gizmo_)\n this.primRender_.render(mvpprim)\n\n if (this.vertexBuffer_) {\n const totalTransform = mat4.create()\n mat4.multiply(totalTransform, this.gizmo_.getOrientation(), this.transform_)\n mat4.multiply(mvp, vp, totalTransform)\n\n // Main render to canvas\n this.shader_.bindProgram()\n\n if (this.colorTexture_.getTextureHandle()) {\n this.colorTexture_.setActiveTexture(gl.TEXTURE0)\n this.colorTexture_.bind()\n this.shader_.setTextureUniform('colorTexture', 0)\n }\n if (this.combinedLabelTexture_.getTextureHandle()) {\n this.combinedLabelTexture_.setActiveTexture(gl.TEXTURE2)\n this.combinedLabelTexture_.bind()\n this.shader_.setTextureUniform('labelTexture', 2)\n }\n\n this.shader_.setUniformMat4fv('VP', mvp)\n this.shader_.setUniform1f('opacity', this.damageOpacity_)\n this.shader_.setUniform1i('highlightedLabel', this.hoveredLabel_)\n this.vertexBuffer_.draw(gl.TRIANGLES)\n this.shader_.unbindProgram()\n\n // Render ID to fbo. Should be possible to do in a single draw with\n // multiple render targets.\n this.readBackFbo_.bind()\n gl.clearColor(0.0, 0.0, 0.0, 0.0)\n gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)\n\n this.idshader_.bindProgram()\n\n if (this.labelTexture_.getTextureHandle()) {\n this.labelTexture_.setActiveTexture(gl.TEXTURE1)\n this.labelTexture_.bind()\n this.idshader_.setTextureUniform('labelTexture', 1)\n }\n if (this.labelVisibiltyTexture_.getTextureHandle()) {\n this.labelVisibiltyTexture_.setActiveTexture(gl.TEXTURE2)\n this.labelVisibiltyTexture_.bind()\n this.idshader_.setTextureUniform('visibilityLookupTexture', 2)\n }\n\n this.idshader_.setUniformMat4fv('VP', mvp)\n this.idshader_.setUniform1i('visibleBitmask', this.visibleDamageCategoriesBitmask_)\n this.vertexBuffer_.draw(gl.TRIANGLES)\n this.idshader_.unbindProgram()\n this.vertexBuffer_.unbind()\n this.readBackFbo_.unbind()\n }\n }\n\n /**\n * Mouse click handler.\n * @param {Object} ev mouseevent\n */\n getDamageForMousePosition (ev) {\n const gl = this.glContext_.gl()\n\n this.readBackFbo_.bind()\n const pixels = new Uint8Array(4)\n gl.readPixels(ev.offsetX, gl.drawingBufferHeight - 1 - ev.offsetY, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels)\n this.readBackFbo_.unbind()\n\n let selectedObject = 0\n\n // pixels[3] == 0 : No damage\n const damageIndex = pixels[3] - 1\n if (pixels[3] > 0 && damageIndex < damageCategoriesShort.length && (this.visibleDamageCategories_.indexOf(damageCategoriesShort[damageIndex]) !== -1)) {\n this.pickingInfo_.object = damageCategoriesShort[damageIndex]\n selectedObject = pixels[0] + (pixels[1] << 8) + (pixels[2] << 16)\n } else {\n this.pickingInfo_.object = 'Unknown object'\n selectedObject = -1\n }\n return selectedObject\n }\n\n /**\n * Mouse click handler.\n * @param {Object} ev mouseevent\n */\n onClick (ev) {\n this.pickPosition(ev)\n const gl = this.glContext_.gl()\n\n this.readBackFbo_.bind()\n const pixels = new Uint8Array(4)\n gl.readPixels(ev.offsetX, gl.drawingBufferHeight - 1 - ev.offsetY, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels)\n gl.readPixels(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight, gl.RGBA, gl.UNSIGNED_BYTE, this.readbackPixels_)\n this.readBackFbo_.unbind()\n\n this.selectedObject_ = 0\n\n // pixels[3] == 0 : No damage\n const damageIndex = pixels[3] - 1\n if (pixels[3] > 0 && damageIndex < damageCategoriesShort.length && (this.visibleDamageCategories_.indexOf(damageCategoriesShort[damageIndex]) !== -1)) {\n this.pickingInfo_.object = damageCategoriesShort[damageIndex]\n this.selectedObject_ = pixels[0] + (pixels[1] << 8) + (pixels[2] << 16)\n } else {\n this.pickingInfo_.object = 'Unknown object'\n this.selectedObject_ = -1\n }\n\n // Event handlers.\n if (ev.button === 0 && this.onLeftClickCallback) {\n this.onLeftClickCallback({ type: this.pickingInfo_.object, id: this.selectedObject_, imagedata: this.readbackPixels_ })\n } else if (ev.button === 2 && this.onRightClickCallback) {\n this.onRightClickCallback({ id: this.selectedObject_ })\n }\n }\n\n /**\n * Mouse move handler\n */\n onMouseMove (ev) {\n const labelValue = this.getDamageForMousePosition(ev)\n if (labelValue !== this.hoveredLabel_) {\n this.hoveredLabel_ = labelValue\n this.scheduleRender_ = true\n if (this.onDamageHoverCallback_) {\n this.onDamageHoverCallback_({ id: labelValue })\n }\n }\n }\n\n updateFps () {\n this.frameCount_++\n const timeSinceLastFpsMeasure = (performance.now() - this.lastFps_) / 1000.0\n if (timeSinceLastFpsMeasure > 1.0) {\n const fps = this.frameCount_ / timeSinceLastFpsMeasure\n this.lastFps_ = performance.now()\n this.frameCount_ = 0\n this.appInfo_.fps = Math.round(fps)\n }\n }\n\n /**\n * Resize the canvas\n * @param {number} width new canvas width\n * @param {height} height new canvas height\n */\n resize (width, height) {\n this.glContext_.canvas_.width = width\n this.glContext_.canvas_.height = height\n // Update camera projection matrix with new aspect\n this.orbitCamera_.setViewport(this.glContext_.getCanvasWidth(), this.glContext_.getCanvasHeight())\n this.orbitCamera_.setPerspective(this.orbitCamera_.getFov())\n this.glContext_.gl_.viewport(0, 0, width, height)\n\n // Resize FBOs\n this.readBackFbo_.resize(width, height)\n this.posFbo_.resize(width, height)\n\n this.readbackPixels_ = new Uint8Array(width * height * 4)\n\n this.scheduleRender_ = true\n }\n\n /**\n * Get position of the current mouse position on the mesh before any\n * transformations, i.e. in the opensfm frame of reference.\n * @returns {vec3} position coordinates\n */\n pickPosition () {\n const gl = this.gl\n // let ray = this.orbitCamera_.getPickingRay(this.mouseEventHander_.getNormX(), this.mouseEventHander_.getNormY())\n // console.log(ray)\n const mvp = mat4.create()\n const totalTransform = mat4.create()\n mat4.multiply(totalTransform, this.gizmo_.getOrientation(), this.transform_)\n mat4.multiply(mvp, this.orbitCamera_.getViewProjection(), totalTransform)\n\n // Render ID to fbo\n this.posFbo_.bind()\n gl.clearBufferuiv(gl.COLOR, 0, new Uint32Array([0, 0, 0, 0]))\n gl.clear(gl.DEPTH_BUFFER_BIT)\n gl.viewport(0, 0, this.glContext_.getCanvasWidth(), this.glContext_.getCanvasHeight())\n\n this.posDepthShader_.bindProgram()\n\n this.posDepthShader_.setUniformMat4fv('VP', mvp)\n this.vertexBuffer_.bind()\n this.vertexBuffer_.draw(gl.TRIANGLES)\n this.posDepthShader_.unbindProgram()\n this.vertexBuffer_.unbind()\n\n const pixelsPos = new Uint32Array(4)\n\n gl.readPixels(this.mouseEventHander_.clientX_, gl.drawingBufferHeight - 1 - this.mouseEventHander_.clientY_, 1, 1, gl.RGBA_INTEGER, gl.UNSIGNED_INT, pixelsPos)\n this.readBackFbo_.unbind()\n const posDepth = new Float32Array(pixelsPos.buffer) // Raw untransformed position\n\n return vec3.fromValues(posDepth[0], posDepth[1], posDepth[2])\n }\n\n /* Compute world view projection matrix\n * @param {Object} cameraFeature\n * @returns {mat4} WVP matrix\n */\n computeWVPFromCamera (cameraFeature) {\n // Find camera parameters\n const instrument = cameraFeature.acquisitioninfo.instrument\n const origin = instrument.georeference.perspectivecentre.coordinates\n const rot = instrument.georeference.exteriororientation\n\n const cameraMatrixWorld = mat4.create()\n const cameraProj = mat4.create()\n\n mat4.perspective(cameraProj, 1.0, 1.0, 0.1, 1000.0)\n cameraProj[0] = 2 * instrument.focallength / (instrument.pixelspacing * instrument.imagecolumns)\n cameraProj[5] = -2 * instrument.focallength / (instrument.pixelspacing * instrument.imagerows)\n\n for (let i = 0; i < 3; i++) {\n for (let j = 0; j < 3; j++) {\n cameraMatrixWorld[4 * i + j] = rot[3 * i + j]\n }\n }\n\n cameraMatrixWorld[12] = origin[0]\n cameraMatrixWorld[13] = origin[1]\n cameraMatrixWorld[14] = origin[2]\n\n // Change to from OpenCV to OpenGL convention\n const permute = mat4.fromValues(\n 1, 0, 0, 0,\n 0, -1, 0, 0,\n 0, 0, -1, 0,\n 0, 0, 0, 1)\n\n mat4.multiply(cameraMatrixWorld, cameraMatrixWorld, permute)\n\n const invObliqueCameraMatrixWorld = mat4.create()\n mat4.invert(invObliqueCameraMatrixWorld, cameraMatrixWorld)\n\n // If the mesh has been transformed to Y up, the following camera\n // transformation is necessary to go back to the opensfm frame of reference.\n // const toZup = mat4.create()\n // mat4.fromXRotation(toZup, Math.PI / 2)\n // mat4.multiply(invObliqueCameraMatrixWorld, invObliqueCameraMatrixWorld, toZup)\n\n // Model view projection for mesh\n const cameraMVP = mat4.create()\n\n mat4.multiply(cameraMVP, cameraProj, invObliqueCameraMatrixWorld)\n\n return cameraMVP\n }\n\n /**\n * Create or update an annotation from a mask drawn on top of an image\n * @param {string} cameraFeature Camerafeature corresponding to the image\n * @param {number|null} annotationId Id of the annotation to update. Create a new annotation if annotationId is null\n * @param {number} damageCategoryIndex index of a damage category\n * @param {ImageData} overlayData Instance of ImageData that contains the mask image\n * @param {() => void} onComplete Callback when update is complete\n * @returns {number} Id of the updated or created annotation\n */\n createOrUpdateAnnotation (cameraFeature, annotationId, damageCategoryIndex, overlayData, onComplete = () => {}) {\n if (damageCategoryIndex < 0 || damageCategoryIndex >= this.labelmapDamageCategoriesData_.length) {\n return false\n }\n const gl = this.gl\n const imageData = this.renderImageOverlayOnMesh(cameraFeature, overlayData)\n const width = imageData.width\n const height = imageData.height\n const pixeldataU8 = imageData.data\n\n const labelmap = this.labelmapDamageCategoriesData_[damageCategoryIndex]\n const labelmapWidth = labelmap.width\n const labelmapHeight = labelmap.height\n\n let updateId = annotationId\n if (annotationId === null) {\n updateId = labelmap.nextAnnotationId\n labelmap.nextAnnotationId++\n } else {\n // Clear existing pixels of the same label value\n for (let i = 0; i < labelmapHeight * labelmapWidth; i++) {\n if (labelmap.pixeldata[i] === updateId) {\n labelmap.pixeldata[i] = 0\n }\n }\n }\n for (let i = 0; i < width * height; i++) {\n const u = (pixeldataU8[4 * i] * 256 + pixeldataU8[4 * i + 1]) / 65535.0\n const v = (pixeldataU8[4 * i + 2] * 256 + pixeldataU8[4 * i + 3]) / 65535.0\n const px = Math.round(u * labelmapWidth)\n const py = Math.round(v * labelmapHeight)\n\n // TODO: 0,0 is a valid value. Nodata mask should be handled better.\n if (u !== 0.0 || v !== 0.0) {\n labelmap.pixeldata[py * labelmapWidth + px] = updateId\n }\n }\n\n // Update textures\n const texData = new Uint8Array(labelmap.pixeldata.buffer, labelmap.pixeldata.byteOffset)\n this.labelTexture_.bind()\n gl.texSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 0, 0, damageCategoryIndex, labelmapWidth, labelmapHeight, 1, gl.RG_INTEGER, gl.UNSIGNED_BYTE, texData)\n this.labelTexture_.unbind()\n this.updateCombinedOverlayTexture(this.visibleDamageCategories_)\n\n this.scheduleRender_ = true\n\n onComplete()\n\n return updateId\n }\n\n /**\n * Render a binary mask as uv coordinates on a mesh\n * @param {Object} cameraFeature\n * @param {ImageData} overlayData ImageData containing pixelvalues of the mask\n * @returns {ImageData} Texturecoordinates of the masked pixels encoded in RGBA8 values\n */\n renderImageOverlayOnMesh (cameraFeature, overlayData) {\n const gl = this.gl\n const cameraMVP = this.computeWVPFromCamera(cameraFeature)\n const instrument = cameraFeature.acquisitioninfo.instrument\n const width = instrument.imagecolumns / 4\n // Rounding down has been applied to support more resolutions\n // it may cause the overlay to be \"moved\"\n const height = Math.floor(instrument.imagerows / 4)\n\n this.imageAnnotationTexture_.setActiveTexture(gl.TEXTURE3)\n if (!this.imageAnnotationTexture_.getTextureHandle()) {\n this.imageAnnotationTexture_.create2D(gl.RGBA8, overlayData.width, overlayData.height, true, false)\n } else {\n this.imageAnnotationTexture_.resize2D(overlayData.width, overlayData.height)\n }\n this.imageAnnotationTexture_.uploadDataToTexture(gl.RGBA, gl.UNSIGNED_BYTE, overlayData.data)\n\n this.imageOverlayFbo_.resize(width, height)\n\n this.imageOverlayFbo_.bind()\n\n gl.clearColor(0, 0, 0, 0)\n gl.viewport(0, 0, width, height)\n gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)\n\n this.meshUvMaskShader_.bindProgram()\n\n this.imageAnnotationTexture_.setActiveTexture(gl.TEXTURE3)\n this.imageAnnotationTexture_.bind()\n this.meshUvMaskShader_.setTextureUniform('maskTexture', 3)\n this.meshUvMaskShader_.setUniform2f('viewport', width, height)\n this.meshUvMaskShader_.setUniformMat4fv('VP', cameraMVP)\n\n this.vertexBuffer_.draw(gl.TRIANGLES)\n this.meshUvMaskShader_.unbindProgram()\n\n // const pixeldata = new Uint16Array(4 * width * height)\n const pixeldataU8 = new Uint8ClampedArray(4 * width * height)\n // Data is packed as :\n // u[i] = (pixeldataU8[4*i] * 256 + pixeldataU8[4*i+1]) / 65535\n // v[i] = (pixeldataU8[4*i+2] * 256 + pixeldataU8[4*i+3]) / 65535\n gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixeldataU8)\n\n this.imageOverlayFbo_.unbind()\n this.imageAnnotationTexture_.unbind()\n\n const imageData = new ImageData(pixeldataU8, width, height)\n return imageData\n }\n\n /* Render labelmap from camera corresponding to imageName\n * @param {string} imageName Image filename\n * @param {number} damageCategoryIndex Index of the damage in the damamageCategoriesShortString\n * @param {number} [annotationId] Index of a specific label to render. If undefined, render all annotations\n * @returns {ImageData} RGBA pixelvalues of the projected mask image\n */\n renderLabelmapFromCameraImagename (imageName, damageCategoryIndex, annotationId) {\n const feature = this.cameraFeatures_.find(e => { return (e.references[0].url.match(imageName) != null) })\n if (!feature) {\n return false\n }\n return this.renderLabelmapFromCameraFeature(feature, damageCategoryIndex, annotationId)\n }\n\n /* Render labelmap from camera corresponding to imageId index in this.cameraFeatures_\n * @param {number} imageId Index in this.cameraFeatures_\n * @param {number} damageCategoryIndex Index of the damage in the damamageCategoriesShortString\n * @param {number} [annotationId] Index of a specific label to render. If undefined, render all annotations\n * @returns {ImageData} RGBA pixelvalues of the projected mask image\n */\n renderLabelmapFromCameraIndex (imageId, damageCategoryIndex, annotationId) {\n if (imageId < this.cameraFeatures_.length) {\n const feature = this.cameraFeatures_[imageId]\n return this.renderLabelmapFromCameraFeature(feature, damageCategoryIndex, annotationId)\n }\n }\n\n /* Render labelmap from camera feature\n * @param {Object} cameraFeature Camerafeature defining the model-view-projection\n * @param {number} damageCategoryIndex Index of the damage in the damamageCategoriesShortString\n * @param {number} [annotationId] Index of a specific label to render. If undefined, render all annotations.\n * @returns {ImageData} RGBA pixelvalues of the projected mask image\n */\n renderLabelmapFromCameraFeature (cameraFeature, damageCategoryIndex, annotationId) {\n const gl = this.gl\n const cameraMVP = this.computeWVPFromCamera(cameraFeature)\n\n const instrument = cameraFeature.acquisitioninfo.instrument\n const width = Math.round(instrument.imagecolumns / 8)\n const height = Math.round(instrument.imagerows / 8)\n this.maskFbo_.resize(width, height)\n this.maskFbo_.bind()\n\n gl.clearColor(0, 0, 0, 0)\n gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)\n gl.viewport(0, 0, width, height)\n this.maskShader_.bindProgram()\n if (this.labelTexture_.getTextureHandle()) {\n this.labelTexture_.setActiveTexture(gl.TEXTURE1)\n this.labelTexture_.bind()\n this.maskShader_.setTextureUniform('labelTexture', 1)\n }\n\n this.maskShader_.setUniform1i('labelType', damageCategoryIndex)\n if (annotationId) {\n this.maskShader_.setUniform1i('selectedAnnotationId', annotationId)\n } else {\n this.maskShader_.setUniform1i('selectedAnnotationId', 0)\n }\n this.maskShader_.setUniformMat4fv('VP', cameraMVP)\n this.vertexBuffer_.draw(gl.TRIANGLES)\n this.maskShader_.unbindProgram()\n\n const pixeldata = new Uint8ClampedArray(4 * width * height)\n gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixeldata)\n const imageData = new ImageData(pixeldata, width, height)\n this.maskFbo_.unbind()\n return imageData\n }\n\n /* Get a list of images that contain annotationId for a damageCategory\n * @return array of strings\n * @param {Object[]} cameraFeatures Array of camerafeatures to filter\n * @param {number} damageCategoryIndex Index of the damage in the damamageCategoriesShortString\n * @param {number} annotationId Index of a specific label to render\n * @param {number} [requestedWidth=64] Width of framebuffer, default 64\n * @param {number} [requestedHeight=64] Height of framebuffer, default 64\n */\n getAnnotaionImagesFromCameraFeatures (cameraFeatures, damageCategoryIndex, annotationId, requestedWidth, requestedHeight) {\n // Setup common gl state\n\n const gl = this.gl\n let width = 64\n let height = 64\n if (requestedWidth !== undefined) {\n width = requestedWidth\n }\n if (requestedHeight !== undefined) {\n height = requestedHeight\n }\n\n const pixeldata = new Uint8ClampedArray(4 * width * height)\n\n this.maskFbo_.resize(width, height)\n this.maskFbo_.bind()\n\n gl.clearColor(0, 0, 0, 0)\n gl.viewport(0, 0, width, height)\n this.maskShader_.bindProgram()\n if (this.labelTexture_.getTextureHandle()) {\n this.labelTexture_.setActiveTexture(gl.TEXTURE1)\n this.labelTexture_.bind()\n this.maskShader_.setTextureUniform('labelTexture', 1)\n }\n\n this.maskShader_.setUniform1i('labelType', damageCategoryIndex)\n this.maskShader_.setUniform1i('selectedAnnotationId', annotationId)\n\n const filteredFeatureNames = []\n for (let i = 0; i < cameraFeatures.length; i++) {\n gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)\n const cameraMVP = this.computeWVPFromCamera(cameraFeatures[i])\n this.maskShader_.setUniformMat4fv('VP', cameraMVP)\n this.vertexBuffer_.draw(gl.TRIANGLES)\n gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixeldata)\n\n if (pixeldata.indexOf(255) !== -1) {\n let pixelCount = 0\n for (let j = 0; j < width * height; j++) {\n if (pixeldata[4 * j] !== 0) {\n pixelCount++\n }\n }\n filteredFeatureNames.push({ imageid: cameraFeatures[i].references[0].url, pixelCount: pixelCount })\n }\n }\n this.maskShader_.unbindProgram()\n\n this.maskFbo_.unbind()\n\n filteredFeatureNames.sort(function (a, b) { return (b.pixelCount - a.pixelCount) })\n\n const sortedFeatureNames = []\n filteredFeatureNames.forEach((feature) => {\n sortedFeatureNames.push(feature.imageid)\n })\n\n return sortedFeatureNames\n }\n\n /**\n * Update combined label texture\n * @param {string[]} visibleCategories Shortstring containing the categories to show\n */\n updateCombinedOverlayTexture (visibleCategories /* String array */) {\n const gl = this.gl\n\n const width = this.labelTexture_.getWidth()\n const height = this.labelTexture_.getHeight()\n\n this.visibleDamageCategoriesBitmask_ = 0\n for (let i = 0; i < visibleCategories.length; i++) {\n const catIndex = damageCategoriesShort.indexOf(visibleCategories[i])\n if (catIndex >= 0) {\n this.visibleDamageCategoriesBitmask_ |= (1 << catIndex)\n }\n }\n\n if (width === 0 && height === 0) {\n return\n }\n\n this.combinedOverlayFbo_.resize(width, height)\n this.combinedOverlayFbo_.bind()\n\n gl.viewport(0, 0, width, height)\n\n gl.clearColor(0, 0, 0, 0)\n gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)\n this.combineOverlayShader_.bindProgram()\n\n if (this.labelTexture_.getTextureHandle()) {\n this.labelTexture_.setActiveTexture(gl.TEXTURE1)\n this.labelTexture_.bind()\n this.combineOverlayShader_.setTextureUniform('labelTexture', 1)\n }\n if (this.labelVisibiltyTexture_.getTextureHandle()) {\n this.labelVisibiltyTexture_.setActiveTexture(gl.TEXTURE2)\n this.labelVisibiltyTexture_.bind()\n this.combineOverlayShader_.setTextureUniform('visibilityLookupTexture', 2)\n }\n\n this.combineOverlayShader_.setUniform1i('visibleBitmask', this.visibleDamageCategoriesBitmask_)\n this.quadVbo_.draw(gl.TRIANGLES)\n\n this.combineOverlayShader_.unbindProgram()\n this.combinedOverlayFbo_.unbind()\n\n this.scheduleRender_ = true\n }\n\n /**\n * Debug visualization\n * @param {string} imageId The ID or file name of the image to create overlay for\n * @param {string} damageCategoryString Short string of a damage category\n */\n createDebugCanvas (imageData, imageId) {\n const canvas = document.createElement('canvas')\n canvas.width = imageData.width\n canvas.height = imageData.height\n const context = canvas.getContext('2d')\n\n context.putImageData(imageData, 0, 0)\n const pngdata = canvas.toDataURL('image/png')\n\n canvas.style.background = 'black'\n this._dataModel.imageById(imageId).then((imageDataUrl) => {\n const image = new Image()\n image.onload = () => {\n context.globalCompositeOperation = 'source-over'\n context.globalAlpha = 0.5\n context.drawImage(image, 0, 0, canvas.width, canvas.height)\n document.body.append(canvas)\n }\n image.src = imageDataUrl\n })\n return pngdata\n }\n\n // WgAppInterface API\n //\n\n /**\n * Set left click handler.\n * @param {function} callback The callback function to be invoked on left\n * clicks. This method must be given an object with the id of the polygon\n * clicked (set to -1 if no polygon is clicked) and the type of damage\n * the polygon represents according to the ML model.\n */\n setLeftClickHandler (callback) {\n this.onLeftClickCallback = callback\n }\n\n /**\n * Set right click handler.\n * @param {function} callback The callback function to be invoked on right\n * clicks. This method must be given an object with the id of the polygon\n * clicked (-1 if no polygon is clicked).\n */\n setRightClickHandler (callback) {\n this.onRightClickCallback = callback\n }\n\n /**\n * Set damage hover callback\n * @param {function} callback The callback function to be invoked on mouse entering or leaving a damage.\n * This method must be given an object with the id of the polygon\n * (set to -1 if no polygon is highlighted)\n */\n setDamageHoverCallback (callback) {\n this.onDamageHoverCallback_ = callback\n }\n\n /**\n * @param {number} annotationId The ID of the annotation to create overlay for\n * @param {string} damageCategoryString Short-string of a damage category\n * @returns {string[]} imageIds that contain annotationId\n */\n getAnnotationImages (annotationId, damageCategoryString) {\n const damageCategoryId = damageCategoriesShort.indexOf(damageCategoryString)\n // Return a list of images\n return this.getAnnotaionImagesFromCameraFeatures(this.cameraFeatures_, damageCategoryId, annotationId)\n }\n\n /*\n * Get images that contain the pointed pixel in the current mouse state\n * @returns {string[]} imageIds that contain annotationId\n */\n getImagesForNewAnnotation () {\n // Find the position of the mouse on the mesh\n const pos = this.pickPosition()\n\n // Approximate the normal by the view vector\n // Transform the camera position to raw mesh frame\n const totalTransform = mat4.create()\n mat4.multiply(totalTransform, this.gizmo_.getOrientation(), this.transform_)\n\n const invTransform = mat4.create()\n const cameraPos = this.orbitCamera_.getPosition()\n const cameraPosMeshFrame = vec4.create()\n\n mat4.invert(invTransform, totalTransform)\n\n vec4.transformMat4(cameraPosMeshFrame, [cameraPos[0], cameraPos[1], cameraPos[2], 1.0], invTransform)\n\n vec4.scale(cameraPosMeshFrame, cameraPosMeshFrame, 1.0 / cameraPosMeshFrame[3])\n const approxNormal = vec3.create()\n vec3.sub(approxNormal, cameraPosMeshFrame, pos)\n vec3.normalize(approxNormal, approxNormal)\n\n // Find images where the picked point is in the view frustum and the\n // approximated normal points towards the camera.\n const filteredFeatureNames = []\n // Filter features\n this.cameraFeatures_.forEach((cameraFeature) => {\n const ndc = vec4.create()\n const ndcDisplaced = vec4.create()\n const wvp = this.computeWVPFromCamera(cameraFeature)\n\n vec4.transformMat4(ndc, [pos[0], pos[1], pos[2], 1.0], wvp)\n vec4.scale(ndc, ndc, 1.0 / ndc[3])\n const depth = ndc[2]\n\n // Offset a point along the normal. This should probably be scaled\n // by the scene size\n vec4.transformMat4(ndcDisplaced, [pos[0] + approxNormal[0], pos[1] + approxNormal[1], pos[2] + approxNormal[2], 1.0], wvp)\n vec4.scale(ndcDisplaced, ndcDisplaced, 1.0 / ndcDisplaced[3])\n const depthDisplaced = ndcDisplaced[2]\n\n if (depthDisplaced < depth && Math.abs(ndc[0]) < 0.8 && Math.abs(ndc[1]) < 0.8) {\n filteredFeatureNames.push({ imageid: cameraFeature.references[0].url, depthDiff: depth - depthDisplaced })\n }\n })\n // Sort by incidence angle\n filteredFeatureNames.sort(function (a, b) { return (b.depthDiff - a.depthDiff) })\n\n const sortedFeatureNames = []\n filteredFeatureNames.forEach((feature) => {\n sortedFeatureNames.push(feature.imageid)\n })\n\n return sortedFeatureNames\n }\n\n /**\n * @param {number} annotationId The ID of the annotation to create overlay for\n * @param {string} imageId The ID or file name of the image to create overlay for\n * @param {string} damageCategoryString Short-string of a damage category\n * @returns {ImageData} Instance of RGBA pixelvalues of the overlay\n */\n getAnnotationOverlay (annotationId, imageId, damageCategoryString) {\n const damageCategoryId = damageCategoriesShort.indexOf(damageCategoryString)\n if (damageCategoryId === -1) {\n throw new Error('Unknown damageCategory' + damageCategoryString)\n }\n const imageData = this.renderLabelmapFromCameraImagename(imageId, damageCategoryId, annotationId)\n return imageData\n }\n\n /**\n * Get an imagedata overlay\n * @param {string} imageName The file name of the image to create overlay for\n * @param {string} damageCategoryString Short-string of a damage category\n * @returns {ImageData} RGBA pixelvalues of the overlay\n */\n getDamageCategoryOverlay (imageName, damageCategoryString) {\n const damageCategoryId = damageCategoriesShort.indexOf(damageCategoryString)\n if (damageCategoryId === -1) {\n throw new Error('Unknown damageCategory' + damageCategoryString)\n }\n const imageData = this.renderLabelmapFromCameraImagename(imageName, damageCategoryId)\n return imageData\n }\n\n /**\n * Update an annotation from a mask drawn on top of an image\n * @param {string} imageName The file name of the image\n * @param {number} annotationId Id of the annotation to update\n * @param {string} damageCategoryString Short-string of a damage category\n * @param {ImageData} overlayData Instance of ImageData that contains the mask image\n * @param {() => void} onComplete Callback when update is complete\n */\n updateAnnotationInImage (imageName, annotationId, damageCategoryString, overlayData, onComplete = () => {}) {\n // Update labelmap\n const feature = this.cameraFeatures_.find(e => { return (e.references[0].url.match(imageName) != null) })\n const damageCategoryId = damageCategoriesShort.indexOf(damageCategoryString)\n this.createOrUpdateAnnotation(feature, annotationId, damageCategoryId, overlayData, onComplete)\n }\n\n /**\n * Create an annotation from a mask drawn on top of an image\n * @param {string} imageName The file name of the image\n * @param {string} damageCategoryString Short-string of a damage category\n * @param {ImageData} overlayData Instance of ImageData that contains the mask image\n * @param {() => void} onComplete Callback when creation is complete\n * @return {number} The Id of the new annotation\n */\n createAnnotation (imageName, damageCategoryString, overlayData, onComplete = () => {}) {\n // Update labelmap\n const feature = this.cameraFeatures_.find(e => { return (e.references[0].url.match(imageName) != null) })\n const damageCategoryId = damageCategoriesShort.indexOf(damageCategoryString)\n return this.createOrUpdateAnnotation(feature, null, damageCategoryId, overlayData, onComplete)\n }\n\n /**\n * Delete an annotation\n * @param {number} annotationId Id of the annotation to delete\n * @param {string} damageCategoryString Short-string of a damage category\n */\n deleteAnnotation (annotationId, damageCategoryString) {\n const gl = this.gl\n const damageCategoryIndex = damageCategoriesShort.indexOf(damageCategoryString)\n if (damageCategoryIndex === -1) {\n throw new Error('Unknown damageCategory' + damageCategoryString)\n }\n\n const labelmap = this.labelmapDamageCategoriesData_[damageCategoryIndex]\n const labelmapWidth = labelmap.width\n const labelmapHeight = labelmap.height\n\n let updateTexture = false\n // Clear existing pixels of the annotation value\n for (let i = 0; i < labelmapHeight * labelmapWidth; i++) {\n if (labelmap.pixeldata[i] === annotationId) {\n labelmap.pixeldata[i] = 0\n updateTexture = true\n }\n }\n\n if (updateTexture) {\n // Update textures\n const texData = new Uint8Array(labelmap.pixeldata.buffer, labelmap.pixeldata.byteOffset)\n this.labelTexture_.bind()\n gl.texSubImage3D(gl.TEXTURE_2D_ARRAY, 0, 0, 0, damageCategoryIndex, labelmapWidth, labelmapHeight, 1, gl.RG_INTEGER, gl.UNSIGNED_BYTE, texData)\n this.labelTexture_.unbind()\n this.updateCombinedOverlayTexture(this.visibleDamageCategories_)\n }\n }\n\n /**\n * Get annotation IDs\n * @return {Array} Array of structs that contain damage category name and the corresponding list of annotation IDs\n */\n getAnnotationIds () {\n const annotationsList = []\n for (let i = 0; i < damageCategoriesShort.length; i++) {\n const labelmap = this.labelmapDamageCategoriesData_[i]\n const unique = new Set(labelmap.pixeldata)\n // Remove the clear value from the unique labels\n unique.delete(0)\n annotationsList.push({ damageCategory: damageCategoriesShort[i], annotationIds: [...unique] })\n }\n return annotationsList\n }\n\n /**\n * Get total number of annotations for all damage categories\n * @return {number} Annotation count\n */\n getTotalAnnotationCount () {\n let count = 0\n this.labelmapDamageCategoriesData_.forEach((labelmap) => {\n const unique = new Set(labelmap.pixeldata)\n // Remove the clear value from the unique labels\n unique.delete(0)\n count += unique.size\n })\n return count\n }\n\n /**\n * Get damage opacity\n * @return {number} opacity\n */\n getDamageOpacity () {\n return this.damageOpacity_\n }\n\n /**\n * Set damage opacity\n * @param {number} opacity in the range [0,1]\n */\n setDamageOpacity (opacity) {\n this.damageOpacity_ = opacity\n this.scheduleRender_ = true\n }\n\n /**\n * Set visible damage categories\n * @param {string[]} visibleCategories Short-strings of the damage categories to show\n */\n setDamageCategoryVisibility (visibleCategories) {\n this.visibleDamageCategories_ = visibleCategories\n this.updateCombinedOverlayTexture(this.visibleDamageCategories_)\n this.scheduleRender_ = true\n }\n\n /**\n * Get visible damage categories\n * @returns {string[]} visibleCategories short-strings of the damage categories shown\n */\n getDamageCategoryVisibility () {\n return this.visibleDamageCategories_\n }\n\n /**\n * Get labelmap for a damage category\n * @param {string} damageCategoryString Short-string of a damage category\n * @return {ArrayBuffer} Bytedata for the labelmap in npy format\n */\n getUVLabelmap (damageCategoryString) {\n const damageCategoryId = damageCategoriesShort.indexOf(damageCategoryString)\n if (damageCategoryId === -1) {\n throw new Error('Unknown damageCategory' + damageCategoryString)\n }\n\n return this.labelmapDamageCategoriesData_[damageCategoryId].npyData\n }\n\n /**\n * Set visibility of rotation gizmo\n * @param {bool} showGizmo New gizmo visibility state\n */\n setGizmoVisibility (showGizmo) {\n if (showGizmo === true) {\n this.gizmo_.setGizmoMode(wGizmoMode.ROTATE)\n } else {\n this.gizmo_.setGizmoMode(wGizmoMode.INACTIVE)\n }\n this.scheduleRender_ = true\n }\n\n /**\n * Get visibility of rotation gizmo\n * @return {bool} Gizmo visibility state\n */\n getGizmoVisibility () {\n return this.gizmo_.getGizmoMode() !== wGizmoMode.INACTIVE\n }\n\n /**\n * Hide a specific set of annotations\n * Overrides all previous calls to showAnnotations and hideAnnotations.\n * @param {number[]} annotationIds Array of ids to hide. Entries must be in [0,65535]\n */\n hideAnnotations (annotationIds) {\n const gl = this.gl\n // Set all labels visible\n const visibleLabelsData = new Uint8Array(65536).fill(255)\n // Hide the subset\n for (let i = 0; i < annotationIds.length; i++) {\n const id = parseInt(annotationIds[i])\n if (id >= visibleLabelsData.length) {\n throw new Error('Annotation id out of range')\n }\n visibleLabelsData[id] = 0\n }\n this.labelVisibiltyTexture_.uploadDataToTexture(gl.RED, gl.UNSIGNED_BYTE, visibleLabelsData)\n\n // Update the combined texture\n this.updateCombinedOverlayTexture(this.visibleDamageCategories_)\n }\n\n /**\n * Hide all annotations\n */\n hideAllAnnotations () {\n const gl = this.gl\n // Set all invisible\n const visibleLabelsData = new Uint8Array(65536)\n this.labelVisibiltyTexture_.uploadDataToTexture(gl.RED, gl.UNSIGNED_BYTE, visibleLabelsData)\n\n // Update the combined texture\n this.updateCombinedOverlayTexture(this.visibleDamageCategories_)\n }\n\n /**\n * Show only a specific set of annotations.\n * Overrides all previous call to showAnnotations and hideAnnotations.\n * @param {number[]} annotationIds Array of ids to show. Entries must be in [0,65535]\n */\n showAnnotations (annotationIds) {\n const gl = this.gl\n // Set all labels visible\n const visibleLabelsData = new Uint8Array(65536)\n for (let i = 0; i < annotationIds.length; i++) {\n const id = parseInt(annotationIds[i])\n if (id >= visibleLabelsData.length) {\n throw new Error('Annotation id out of range')\n }\n visibleLabelsData[id] = 255\n }\n this.labelVisibiltyTexture_.uploadDataToTexture(gl.RED, gl.UNSIGNED_BYTE, visibleLabelsData)\n\n // Update the combined texture\n this.updateCombinedOverlayTexture(this.visibleDamageCategories_)\n }\n\n /**\n * Show all annotations\n */\n showAllAnnotations () {\n const gl = this.gl\n // Set all labels visible\n const visibleLabelsData = new Uint8Array(65536).fill(255)\n this.labelVisibiltyTexture_.uploadDataToTexture(gl.RED, gl.UNSIGNED_BYTE, visibleLabelsData)\n\n // Update the combined texture\n this.updateCombinedOverlayTexture(this.visibleDamageCategories_)\n }\n\n /**\n * Get label colours\n * @return {string[]} Colours in RGBA-format, e.g. '(1.0,0.0,1.0,1.0)'\n */\n getLabelColors () {\n return [\n '(1.0,0.0,1.0,1.0)',\n '(0.0,1.0,0.0,1.0)',\n '(0.0,0.0,1.0,1.0)',\n '(1.0,1.0,0.0,1.0)',\n '(1.0,0.0,0.0,1.0)'\n ]\n }\n}\nexport { WgApp }\n","import { makeStyles } from '@material-ui/core'\n\nconst width = 1032\n\nexport const useStyles = makeStyles(theme => ({\n columns: {\n width,\n display: 'flex'\n },\n main: {\n display: 'flex',\n flex: 1,\n flexDirection: 'column'\n },\n form: {\n display: 'flex',\n },\n info: {\n flex: 1\n },\n inputs: {\n flex: 1\n },\n images: {\n // TODO: Scroll images inside dialog\n overflowY: 'auto',\n boxSizing: 'border-box'\n },\n loading: {\n display: 'flex',\n justifyContent: 'center',\n width,\n height: 600,\n },\n titleIcon: {\n float: 'left',\n paddingRight: theme.spacing(1),\n },\n}))\n\nexport default useStyles\n","import { makeStyles } from '@material-ui/core'\nimport { grey } from '@material-ui/core/colors'\n\nexport const useStyles = makeStyles(theme => ({\n imgWithoutOverlay: {\n },\n imageContainer: {\n position: 'relative'\n },\n imageControls: {\n boxSizing: 'border-box',\n position: 'absolute',\n bottom: 0,\n left: 0,\n width: '100%'\n },\n imageControl: {\n marginRight: theme.spacing(1)\n },\n loading: {\n display: 'flex',\n background: grey[100],\n justifyContent: 'center',\n alignItems: 'center',\n },\n}))\n\nexport default useStyles\n","/**\n * Bitmap class for representing a pure JS bitmap.\n */\nclass Bitmap {\n readonly _size: number\n readonly _chunks: Uint8Array\n\n /**\n * Creates a bitmap of the given size.\n * @param size The size (in bits) of the bitmap\n */\n constructor (size: number) {\n if (size <= 0) {\n throw new Error('Invalid bitmap size')\n }\n this._size = size\n this._chunks = new Uint8Array(Math.ceil(size / 8))\n for (let i = 0; i < this._chunks.length; i++) {\n this._chunks[i] = 0\n }\n }\n\n /**\n * Getter for the bitmap size.\n */\n get size (): number {\n return this._size\n }\n\n /**\n * Set the given bit in the map.\n * @param bit The bit number to set to 1.\n */\n set (bit: number): void {\n if (bit < 0 || bit >= this._size) {\n throw new Error(`Out of bounds: ${bit}`)\n }\n const chunkIndex = Math.floor(bit / 8)\n const bitMask = 2 ** (bit % 8)\n this._chunks[chunkIndex] |= bitMask\n }\n\n /**\n * Unset the given bit in the map.\n * @param bit The bit number to set to 0.\n */\n unset (bit: number): void {\n if (bit < 0 || bit >= this._size) {\n throw new Error(`Out of bounds: ${bit}`)\n }\n const chunkIndex = Math.floor(bit / 8)\n const bitMask = 255 - (2 ** (bit % 8))\n this._chunks[chunkIndex] &= bitMask\n }\n\n /**\n * Get grid of bits of specific size at index.\n * @param bit The bit number\n * @param size The size of the grid\n * @param totalWidth The total width of the image/bitmap\n * @returns Grid of bits\n */\n getGrid(bit: number, size: number, totalWidth: number): number[] {\n const grid = []\n const bitColumn = bit % totalWidth\n for (let i = 0; i < size; i++) {\n for (let j = 0; j < size; j++) {\n const index = bit + (i*totalWidth) + j\n const indexColumn = index % totalWidth\n const insideMap = bitColumn <= indexColumn\n if (!this.isOutOfBounds(index) && insideMap) {\n grid.push(index)\n }\n }\n }\n return grid\n }\n\n /**\n * Set a grid of bits.\n * @param bit The bit number\n * @param size The size of the grid\n * @param totalWidth The total width of the image/bitmap\n */\n setGrid(bit: number, size: number, totalWidth: number) {\n this.getGrid(bit, size, totalWidth).forEach(i =>\n this.set(i)\n )\n }\n\n /**\n * Unset a grid of bits.\n * @param bit The bit number\n * @param size The size of the grid\n * @param totalWidth The total width of the image/bitmap\n */\n unsetGrid(bit: number, size: number, totalWidth: number) {\n this.getGrid(bit, size, totalWidth).forEach(i =>\n this.unset(i)\n )\n }\n\n /**\n * Toggle the value of the given bit.\n * @param bit The bit number to toggle the value of.\n */\n toggle (bit: number): void {\n if (this.isSet(bit)) {\n this.unset(bit)\n } else {\n this.set(bit)\n }\n }\n\n /**\n * Check whether the given bit is set.\n * @param bit The bit to check.\n * @returns True if the bit is set, false if not.\n */\n isSet (bit: number): boolean {\n if (bit < 0 || bit >= this._size) {\n throw new Error(`Out of bounds: ${bit}`)\n }\n const chunkIndex = Math.floor(bit / 8)\n const bitMask = 2 ** (bit % 8)\n return (this._chunks[chunkIndex] & bitMask) !== 0\n }\n\n /**\n * Unset all bits in the map.\n */\n unsetAll (): void {\n for (let i = 0; i < this._chunks.length; i++) {\n this._chunks[i] = 0\n }\n }\n\n /**\n * Set all bits in the map.\n */\n setAll (): void {\n for (let i = 0; i < this._chunks.length; i++) {\n this._chunks[i] = 255\n }\n }\n\n /**\n * Get a list of bit indices that are set.\n * @returns A list of all indices whise corresponding bit is set.\n */\n enabledIndices (): number[] {\n const result: number[] = []\n for (let i = 0; i < this._chunks.length; i++) {\n if (this._chunks[i] !== 0) {\n // Some bits are set here.\n const offset = i * 8\n for (let j = 0; j < 8; j++) {\n const mask = 2 ** j\n if (this._chunks[i] & mask) { // eslint-disable-line @typescript-eslint/strict-boolean-expressions\n result.push(offset + j)\n }\n }\n }\n }\n return result\n }\n\n /**\n * Check whether any bits are set\n * @returns True if no bits are set, false if one or more are\n */\n isEmpty (): boolean {\n return this.enabledIndices().length === 0\n }\n\n /**\n * Check whether any bits are out of bounds\n * @returns True if bit is out of bounds, false if not\n */\n isOutOfBounds (bit: number): boolean {\n return bit < 0 || bit >= this._size\n }\n}\n\nexport { Bitmap }\n","import { SelectedObject } from 'src/components/Analysis'\nimport { FC, useReducer, useState } from 'react'\nimport { AnnotationDialog, commonQueryId } from 'src/components/AnnotationDialog'\nimport { EditImageDialog } from 'src/components/EditImageDialog'\nimport { DamageCategoryShort, mapFromModelNameToBackendId } from 'src/datamodel/DamageMapping'\nimport { useApp } from 'src/components/AppContextProvider'\nimport { annotationReducer, initialAnnotationState } from 'src/reducers/annotationReducer'\nimport { useMutation, useQuery } from 'react-query'\nimport { Damage } from 'src/datasource/model/Damage'\nimport { Annotation } from 'src/datasource/model/Annotation'\nimport { Cause } from 'src/datasource/model/Cause'\nimport { ConditionRating } from 'src/datasource/model/ConditionRating'\n\ninterface DialogControllerProps {\n analysisId: number\n selectedObject: SelectedObject\n images: string[]\n annotationDialogOpen: boolean\n onSetAnnotationDialogOpen: (open: boolean) => void\n onUpdateSelectedObject: (selectedObject: SelectedObject) => void\n}\n\nexport enum AnnotationType {\n System,\n New,\n User,\n Unknown,\n}\n\nexport const DialogController: FC = ({ \n selectedObject,\n images,\n annotationDialogOpen,\n analysisId,\n onUpdateSelectedObject,\n onSetAnnotationDialogOpen \n}: DialogControllerProps) => {\n const [editDialogOpen, setEditDialogOpen] = useState(false)\n const { queryClient, serviceFactory, account, wgApp, setUserAnnotationIds, setTotalAnnotationCount } = useApp()\n \n // State for the edit image dialog\n const [editImageName, setEditImageName] = useState('')\n const [editAnalysisId, setEditAnalysisId] = useState(-1)\n const [editAnnotationId, setEditAnnotationId] = useState(-1)\n const [editDamageCategory, setEditDamageCategory] = useState('')\n const [editAnnotationType, setEditAnnotationType] = useState(AnnotationType.Unknown)\n const setEditImageState = (analysisId: number, imageName: string, annotationId: number, damageCategory: string, annotationType: AnnotationType): void => {\n setEditAnalysisId(analysisId)\n setEditImageName(imageName)\n setEditAnnotationId(annotationId)\n setEditDamageCategory(damageCategory)\n setEditAnnotationType(annotationType)\n }\n\n // State for annotation dialog\n const [state, dispatch] = useReducer(annotationReducer, initialAnnotationState)\n const [annotationType, setAnnotationType] = useState(AnnotationType.Unknown)\n \n const revokeImageUrls = () => {\n imageQuery.data?.forEach(url => URL.revokeObjectURL(url))\n if (selectedImageQuery.data !== undefined) {\n URL.revokeObjectURL(selectedImageQuery?.data)\n }\n }\n\n const resetStateAndQueries = () => {\n revokeImageUrls()\n queryClient.invalidateQueries(commonQueryId)\n dispatch({ type: 'resetAll' })\n }\n\n const userIdQuery = useQuery(['userId', commonQueryId], async () => await serviceFactory.getUserServiceClient().getUserId(), { enabled: account !== null })\n const tenantIdQuery = useQuery(['tenantId', commonQueryId], async () => await serviceFactory.getUserServiceClient().getCurrentTenantId(), { enabled: account !== null })\n\n const damagesQuery = useQuery(['damages', commonQueryId], async () => await serviceFactory.getAnnotationService().getDamages(),\n {\n enabled: account !== null,\n onError: (e) => console.error('Error fetching damages', e)\n })\n\n const conditionRatingsQuery = useQuery(['conditionratings', commonQueryId], async () => await serviceFactory.getAnnotationService().getConditionRatings(), { enabled: account !== null})\n \n const primaryImageQuery = useQuery(['primaryImageId', commonQueryId, state.primaryImageName], \n async () => await serviceFactory.getAnnotationService().mapImageNameToImageId(analysisId, state.primaryImageName!),\n {\n enabled: (annotationDialogOpen || editDialogOpen) && state.primaryImageName !== undefined,\n onSuccess: (data: number | undefined) => {\n dispatch({ type: 'setPrimaryImageId', payload: data })\n },\n onError: (e) => console.error('Error fetching image id', e)\n })\n \n const annotationQuery = useQuery(['annotation', commonQueryId],\n async () => { \n const data: Map = await serviceFactory.getAnnotationService().getUserAnnotationsMapForAnalysis(analysisId)\n const fetchedIds = Array.from(data.keys())\n if (fetchedIds.length > 0) {\n setUserAnnotationIds(fetchedIds)\n }\n return data.get('' + selectedObject.id)\n },\n {\n enabled: (annotationDialogOpen || editDialogOpen) && selectedObject.id !== undefined && account !== null && damagesQuery.isSuccess,\n onSuccess: (data: Annotation | undefined) => {\n setTotalAnnotationCount(wgApp !== undefined ? wgApp.getTotalAnnotationCount() : 0)\n if (data === undefined) {\n if (selectedObject.isNew) {\n //New unedited annotation\n setAnnotationType(AnnotationType.New)\n } else {\n //System annotation or new annotation that has been edited\n setAnnotationType(AnnotationType.System)\n if (selectedObject.type !== undefined && damagesQuery.data !== undefined) {\n dispatch({ type: 'setSelectedDamage', payload: mapFromModelNameToBackendId(damagesQuery.data, selectedObject.type) })\n }\n }\n } else {\n //User annotation\n setAnnotationType(AnnotationType.User)\n if (data.customCause !== null && data.customCause !== '') {\n dispatch({ type: 'setCauseCustom', payload: true })\n dispatch({ type: 'setCustomCause', payload: data.customCause })\n }\n dispatch({ type: 'setSelectedDamage', payload: data.damageCategoryId })\n dispatch({ type: 'setSelectedCause', payload: data.standardCauseId !== null ? data.standardCauseId : undefined })\n dispatch({ type: 'setDamageLevel', payload: data.damageLevel })\n dispatch({ type: 'setDescription', payload: (data.comment !== null ? data.comment : `${selectedObject.id}#`).split('#')[1] })\n dispatch({ type: 'setPrimaryImageId', payload: data.imageId })\n }\n },\n onError: (e) => console.error('Error fetching annotation', e),\n })\n\n const primaryImageNameQuery = useQuery(['primaryImageName', commonQueryId, state.primaryImageId], \n async () => await serviceFactory.getAnnotationService().mapImageIdToImageName(analysisId, state.primaryImageId!),\n {\n enabled: (annotationDialogOpen || editDialogOpen) && annotationQuery.isSuccess,\n onSuccess: (data: string | undefined) => {\n dispatch({ type: 'setPrimaryImageName', payload: data })\n },\n onError: (e) => console.error('Error fetching image name', e)\n })\n\n const imageQuery = useQuery(['image', commonQueryId], async () => await serviceFactory\n .getImageServiceClient()\n .getImagesAsObjectUrls(analysisId, serviceFactory.getImageServiceClient().convertImageNamesTo250px(images)), {\n enabled: (annotationDialogOpen || editDialogOpen) && primaryImageNameQuery.isSuccess && images.length > 0,\n onError: (e) => console.error('Error fetching images', e)\n })\n\n const selectedImageQuery = useQuery(['selectedImage', commonQueryId, state.selectedImage], async () => await serviceFactory.getImageServiceClient().getImageAsObjectUrl(analysisId, images[state.selectedImage]),\n {\n enabled: (annotationDialogOpen || editDialogOpen) && images.length > 0,\n onError: (e) => console.error('Error fetching selected image', e)\n })\n\n const causesQuery = useQuery(['causes', commonQueryId, state.selectedDamage], async () => await serviceFactory.getAnnotationService().getCausesFor(state.selectedDamage),\n {\n enabled: state.selectedDamage !== undefined,\n onError: (e) => console.error('Error fetching causes', e)\n })\n\n const saveMutation = useMutation(async (annotation: Annotation) => await serviceFactory.getAnnotationService().saveAnnotation(annotation),\n {\n onError: (e) => console.error('Error saving annotation', e)\n })\n\n const deleteMutation = useMutation(async (annotationId: number) => await serviceFactory.getAnnotationService().deleteAnnotation(annotationId))\n\n return (\n <>\n {\n onSetAnnotationDialogOpen(false)\n resetStateAndQueries()\n }}\n onEditImage={(analysisId: number, imageName: string, annotationId: number, damageCategory: DamageCategoryShort, annotationType: AnnotationType): void => {\n setEditImageState(analysisId, imageName, annotationId, damageCategory, annotationType)\n setEditDialogOpen(true)\n onSetAnnotationDialogOpen(false)\n }}\n selectedObject={selectedObject}\n images={images}\n />\n {\n setEditDialogOpen(false)\n resetStateAndQueries()\n }}\n onCancel={() => {\n onSetAnnotationDialogOpen(true)\n setEditDialogOpen(false)\n }}\n onSaved={(selectedObject: SelectedObject, damageCategory: DamageCategoryShort, newId?: number) => {\n if (newId !== undefined) {\n onUpdateSelectedObject({ ...selectedObject, id: newId, isNew: false, type: damageCategory })\n }\n onSetAnnotationDialogOpen(true)\n setEditDialogOpen(false)\n }}\n selectedObject={selectedObject}\n open={editDialogOpen}\n title='Edit'\n imageName={editImageName}\n annotationId={editAnnotationId}\n damageCategory={editDamageCategory}\n analysisId={editAnalysisId}\n annotationType={editAnnotationType}\n />\n \n )\n}\n","import { Cause } from './Cause'\nimport { Damage } from './Damage'\n\nexport interface Annotation {\n id: number\n imageId: number\n imageName: string | null\n imageBatchName: string | null\n imageDateTime: string\n analysisId: number\n tagId: string | null // Should be a UUID\n probability: number | null // Should be a double\n isUserCreated: boolean\n isCluster: boolean\n damageLevel: number\n comment: string | null\n cause: string | null\n standardCauseId: number | null\n standardCause: string | null\n customCause: string | null\n created: string\n modified?: string\n probabilityPctRounded: number | null\n serviceId: string | null // Should be a UUID\n damageCategory: string\n damageCategoryId: number\n conditionRating: string | null\n conditionRatingId: number | null\n userIdCreated: number\n userCreated: string | null\n userIdModified: number\n tenantId: number\n placeId: number\n children: Annotation[]\n top: number // Should be a double\n left: number // Should be a double\n height: number // Should be a double\n width: number // Should be a double\n}\n\nexport class Placement {\n public readonly top: number\n public readonly left: number\n public readonly height: number\n public readonly width: number\n\n //Top: Distance from top\n //Left: Distance from left\n //Height: Height of damage annotation\n //Width: Width of damage annotation\n //Should all be doubles from 0.0 to 1.0. Example: 0.74952545199193155\n constructor (top: number, left: number, height: number, width: number) {\n this.top = top\n this.left = left\n this.height = height\n this.width = width\n }\n}\n\nexport class AnnotationBuilder {\n private readonly analysisId: number\n private readonly imageId: number\n private readonly damageLevel: number\n private readonly conditionRatingId: number\n private readonly userId: number\n private readonly tenantId: number\n private readonly placement: Placement\n private readonly damage: Damage\n private readonly systemId: string\n private readonly comment: string\n \n private customCause: string | null = null\n private cause: Cause | null = null\n\n constructor (systemId: string, analysisId: number, imageId: number, damageLevel: number, conditionRatingId: number, userId: number, tenantId: number, placement: Placement, damage: Damage, comment: string) {\n this.systemId = systemId\n this.analysisId = analysisId\n this.imageId = imageId\n this.damageLevel = damageLevel\n this.conditionRatingId = conditionRatingId\n this.userId = userId\n this.tenantId = tenantId\n this.placement = placement\n this.damage = damage\n this.comment = comment\n }\n\n public setCauses = (isCauseCustom: boolean, cause: Cause | undefined, customCause: string): AnnotationBuilder => {\n if (isCauseCustom && customCause !== '') {\n this.cause = null\n this.customCause = customCause\n } else {\n if (cause !== undefined) {\n this.customCause = null\n this.cause = cause\n }\n }\n return this\n }\n\n public finishNew (): Annotation {\n return {\n serviceId: null, // Should be a UUID\n created: new Date().toISOString(),\n id: 0,\n imageId: this.imageId,\n analysisId: this.analysisId,\n comment: this.systemId + \"#\" + this.comment,\n\n damageLevel: this.damageLevel,\n conditionRatingId: this.conditionRatingId,\n\n standardCauseId: this.cause === null ? null : this.cause.id,\n standardCause: this.cause === null ? null : this.cause.value,\n customCause: this.customCause, // Consider validating\n\n damageCategory: this.damage.value,\n damageCategoryId: this.damage.id,\n\n top: this.placement.top, // Should be a double\n left: this.placement.left, // Should be a double\n height: this.placement.height, // Should be a double\n width: this.placement.width, // Should be a double\n userIdCreated: this.userId,\n userIdModified: this.userId,\n\n cause: null,\n imageName: null,\n imageBatchName: null,\n imageDateTime: new Date().toISOString(),\n probabilityPctRounded: null,\n conditionRating: null,\n userCreated: null,\n tenantId: this.tenantId,\n placeId: 0,\n children: [],\n tagId: null, // Should be a UUID\n probability: null, // Should be a double\n isUserCreated: true,\n isCluster: false\n }\n }\n\n public finishUpdate (oldAnnotation: Annotation): Annotation {\n return {\n ...this.finishNew(),\n id: oldAnnotation.id,\n userIdCreated: oldAnnotation.userIdCreated,\n created: oldAnnotation.created,\n userIdModified: this.userId\n }\n }\n}\n","import { BitmapImage, BoundingBox, ColorChannel } from \"src/components/mltraininggrid/BitmapImage\"\nimport { damageCategoriesShort, DamageCategoryShort } from \"src/datamodel/DamageMapping\"\nimport { Placement } from \"src/datasource/model/Annotation\"\n\nexport const calcPlacement = (overlay: ImageData, overlayScaleFactor: number, imageWidth: number, imageHeight: number): Placement => {\n const bitmapImage = BitmapImage.fromRGBAData(overlay.data, imageWidth/overlayScaleFactor, imageHeight/overlayScaleFactor, ColorChannel.Red)\n bitmapImage.scaleUp(overlayScaleFactor)\n return convertBoundingBoxToPlacement(bitmapImage.boundingBox(1), imageWidth, imageHeight)\n}\n\n/**\n * Converts a BoundingBox from a BitmapImage to a Placement\n * @param {BoundingBox} boundingBox Bounding box around damage annotation, calculated from BitmapImage\n * @param {number|null} imageWidth Image width\n * @param {number} imageHeight Image height\n * @param {ImageData} decimals Number of decimals included in result (default = 4)\n * @returns {Placement} Placement (top, left, width, and height scaled to 0;1)\n */\nexport const convertBoundingBoxToPlacement = (boundingBox: BoundingBox, imageWidth: number, imageHeight: number, decimals: number = 4): Placement => {\n const x1 = boundingBox.x1 / imageWidth\n const x2 = boundingBox.x2 / imageWidth\n const y1 = boundingBox.y1 / imageHeight\n const y2 = boundingBox.y2 / imageHeight\n return new Placement(\n parseFloat(y1.toFixed(decimals)), \n parseFloat(x1.toFixed(decimals)),\n parseFloat((y2 - y1).toFixed(decimals)), \n parseFloat((x2 - x1).toFixed(decimals))\n )\n}\n\nexport const convertWgAppColorToRGBA = (color: string) => {\n return `rgba(${color\n .replace('(', '')\n .replace(')', '')\n .split(',')\n .map((c, i) => i === 3 ? c : parseFloat(c) * 255)\n .join(',')})`\n}\n\nexport const convertRGBAToChannels = (rgba: string) => {\n return rgba\n .replace('rgba', '')\n .replace('(', '')\n .replace(')', '')\n .split(',')\n .map((c, i) => i === 3 ? parseFloat(c) * 255 : parseInt(c))\n}\n\nexport const getDamageColor = (damageCategory: DamageCategoryShort | undefined, wgLabelColors: string[] | undefined) => {\n if (wgLabelColors !== undefined && damageCategory !== undefined) {\n const index = damageCategoriesShort.indexOf(damageCategory)\n if (index !== -1) {\n const color = wgLabelColors[index]\n return convertWgAppColorToRGBA(color)\n }\n }\n return 'rgb(255, 0, 0, 128)'\n}","import { makeStyles } from '@material-ui/core'\n\nexport const useStyles = makeStyles(theme => ({\n selected: {\n boxSizing: 'border-box',\n border: 'solid 2px ' + theme.palette.primary.main,\n }\n}))\n\nexport default useStyles\n","import { useEffect, useRef } from \"react\"\nimport { convertRGBAToChannels } from \"src/util/annotationUtil\"\nimport useStyles from \"src/components/ImageWithOverlay.style\"\n\ninterface ImageWithOverlayProps {\n src: string\n overlay: ImageData\n scaleFactor: number\n selected?: boolean\n color: string\n onClick?: () => void\n}\n\nexport const ImageWithOverlay = ({ src, overlay, scaleFactor, selected, color, onClick }: ImageWithOverlayProps) => {\n const classes = useStyles()\n const canvasRef = useRef(null)\n const fullWidth = overlay.width\n const fullHeight = overlay.height\n const scaledHeight = Math.floor(overlay.height/scaleFactor)\n const scaledWidth = Math.floor(overlay.width/scaleFactor)\n\n useEffect(() => {\n const imageDataToImage = (imageData: ImageData, onLoaded: (image: HTMLImageElement) => void) => {\n const canvas: HTMLCanvasElement = document.createElement('canvas')\n const context: CanvasRenderingContext2D | null = canvas.getContext('2d')\n canvas.width = fullWidth\n canvas.height = fullHeight\n context?.putImageData(imageData, 0, 0)\n const image = new Image()\n image.onload = () => {\n onLoaded(image)\n }\n image.src = canvas.toDataURL()\n }\n\n const changeColor = (imageData: ImageData): ImageData => {\n const convertedColor = convertRGBAToChannels(color)\n const data: Uint8ClampedArray = imageData.data\n for (let i = 0; i < data.length; i += 4) {\n const r = data[i + 0]\n data[i + 0] = r === 255 ? convertedColor[0] : 0 //R\n data[i + 1] = r === 255 ? convertedColor[1] : 0 //G\n data[i + 2] = r === 255 ? convertedColor[2] : 0 //B\n data[i + 3] = r === 255 ? 100 : 0 //A\n }\n return imageData\n }\n\n const canvas: HTMLCanvasElement | null = canvasRef.current\n const context: CanvasRenderingContext2D | null | undefined = canvas?.getContext('2d')\n if (canvas !== null && context !== null && context !== undefined) {\n const image = new Image()\n image.onload = () => {\n context.drawImage(image, 0, 0, fullWidth, fullHeight)\n const colorImageData: ImageData = changeColor(overlay)\n const onLoaded = (imageFromData: HTMLImageElement) => {\n context.drawImage(imageFromData, 0, 0, fullWidth, fullHeight)\n }\n imageDataToImage(colorImageData, onLoaded)\n }\n image.src = src\n }\n }, [overlay, src, fullHeight, fullWidth, color])\n\n return (\n \n )\n}","import { Box, Button, CircularProgress } from '@material-ui/core'\nimport useStyles from './SelectedImage.style'\nimport EditIcon from '@material-ui/icons/Edit'\nimport CheckIcon from '@material-ui/icons/Check'\nimport { FC } from 'react'\nimport { ImageWithOverlay } from 'src/components/ImageWithOverlay'\n\ninterface SelectedImageProps {\n disableControls: boolean\n disableSetPrimary: boolean\n src: string | undefined\n fetching: boolean\n onEdit: () => void\n onSetAsPrimary: () => void\n isPrimary: boolean\n overlay: ImageData | undefined\n color: string\n}\n\nexport const SelectedImage: FC = ({ disableControls, disableSetPrimary, src, fetching, onEdit, onSetAsPrimary, isPrimary, overlay, color }: SelectedImageProps) => {\n const classes = useStyles()\n\n return (\n <>\n {src !== undefined && !fetching ?\n \n {overlay !== undefined ?\n \n :\n \"selected\"\n }\n \n }\n >\n Edit\n \n {isPrimary ?\n }\n >\n Primary\n \n : \n <>\n {!disableSetPrimary && \n }\n >\n Set as primary\n \n } \n \n }\n \n \n :\n
\n \n
\n }\n \n )\n}\n","import { makeStyles } from '@material-ui/core'\n\nexport const useStyles = makeStyles(theme => ({\n closeButton: {\n position: 'absolute',\n right: theme.spacing(2),\n top: theme.spacing(2)\n }\n}))\n\nexport default useStyles\n","import { Dialog, DialogTitle, IconButton } from '@material-ui/core'\nimport { ReactNode } from 'react'\nimport CloseIcon from '@material-ui/icons/Close'\nimport useStyles from 'src/components/CustomDialog.style'\n\ninterface CustomDialogProps {\n title: ReactNode\n maxWidth?: false | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | undefined\n onClose: () => void\n open: boolean\n scroll?: 'paper' | 'body' | undefined\n children?: ReactNode\n}\n\nexport const CustomDialog = ({ title, maxWidth = undefined, onClose, open, scroll = undefined, children }: CustomDialogProps) => {\n const classes = useStyles()\n\n return (\n \n \n {title}\n \n \n \n \n {children}\n \n )\n}\n","import { makeStyles } from '@material-ui/core'\n\nexport const useStyles = makeStyles(theme => ({\n imgWithoutOverlay: {\n width: 250,\n },\n selected: {\n boxSizing: 'border-box',\n border: 'solid 2px ' + theme.palette.primary.main,\n },\n container: {\n position: 'relative'\n },\n primaryIcon: {\n fontSize: 32,\n position: 'absolute',\n bottom: theme.spacing(1),\n right: theme.spacing(1),\n background: 'white',\n borderRadius: '50%',\n },\n editIcon: {\n backgroundColor: 'white',\n position: 'absolute',\n bottom: theme.spacing(1),\n left: theme.spacing(1),\n },\n}))\n\nexport default useStyles\n","import { Box } from '@material-ui/core'\nimport CheckCircleIcon from '@material-ui/icons/CheckCircle'\nimport useStyles from 'src/components/Thumbnail.style'\nimport { FC, MouseEvent, useState } from 'react'\nimport EditIcon from '@material-ui/icons/Edit'\nimport { IconButton } from '@material-ui/core'\nimport { ImageWithOverlay } from 'src/components/ImageWithOverlay'\n\ninterface ThumbnailProps {\n src: string\n overlay: ImageData | undefined\n isPrimary: boolean\n selected: boolean\n color: string\n onSelect: () => void\n onEdit: () => void\n}\n\nexport const Thumbnail: FC = (props: ThumbnailProps) => {\n const { src, overlay, isPrimary, selected, color, onSelect, onEdit } = props\n const classes = useStyles()\n const [isMouseOver, setMouseOver] = useState(false)\n\n return (\n ) => setMouseOver(true)} \n onMouseLeave={(e: MouseEvent) => setMouseOver(false)}\n >\n {overlay !== undefined ?\n \n :\n \"thumbnail\"\n }\n {isPrimary && }\n {isMouseOver && \n \n \n \n }\n \n )\n}\n","import Select from '@material-ui/core/Select'\nimport { FormControl, InputLabel, MenuItem } from '@material-ui/core'\nimport { ChangeEvent, FC } from 'react'\n\ninterface LabelCategorySelectProps {\n required?: boolean\n label: string\n items: string[] | undefined\n value: string | undefined\n disabled?: boolean\n onSelect: (selected: number) => void\n}\nexport const LabelCategorySelect: FC = (props: LabelCategorySelectProps) => {\n const { required, disabled, label, items, value, onSelect } = props\n\n const handleChange = (event: ChangeEvent<{ value: unknown }>): void => {\n onSelect(items?.findIndex(i => i === event.target.value) as number)\n }\n\n return (\n \n {label}\n \n {items?.map((value, index) => {\n return {value}\n })}\n \n \n )\n}\n","import React, { FC, useRef, useEffect, useState, MouseEventHandler } from 'react'\nimport './MLTrainingGrid.css'\nimport { BitmapImage, BoundingBox } from './BitmapImage'\n\ninterface MLTrainingGridProps {\n backgroundImageUrl: string\n mlMask: BitmapImage\n gridScale: number\n width: number\n height: number\n uiScale: number\n zoom: number\n maxZoomFactor: number\n zoomMax: number\n drawMode: boolean\n brushSize: number\n overlayVisible: boolean\n drawColor: string\n setBitmapEmpty: (isEmpty: boolean) => void\n}\n\nconst MLTrainingGrid: FC = ({ \n backgroundImageUrl,\n mlMask,\n gridScale,\n width,\n height,\n uiScale,\n zoom,\n maxZoomFactor,\n zoomMax,\n drawMode,\n brushSize,\n overlayVisible,\n drawColor,\n setBitmapEmpty,\n }: MLTrainingGridProps) => {\n const backgroundImageRef = useRef(null)\n const canvasRef = useRef(null)\n\n const [renderFlag, setRenderFlag] = useState(false)\n const [hoveredGridIndex, setHoveredGridIndex] = useState(-1)\n\n const gridWidth = Math.ceil(width / gridScale)\n const gridHeight = Math.ceil(height / gridScale)\n const highlightColor = 'rgb(255, 255, 255, 128)'\n const selectedColor = drawColor\n\n const uiHeight = height / uiScale\n const uiWidth = width / uiScale\n\n const shouldRender = (): void => {\n setRenderFlag(!renderFlag)\n }\n\n // Update canvas on bitmap state change.\n useEffect(() => {\n // Set a single grid point to the given color.\n const setGridPoint = (context: CanvasRenderingContext2D, gridScale: number, gridWidth: number, gridPointIndex: number, uiScale: number, color: string): void => {\n context.save()\n context.globalAlpha = overlayVisible ? 0.40 : 0\n const scale = gridScale / uiScale\n const x = gridPointIndex % gridWidth * scale\n const y = Math.floor(gridPointIndex / gridWidth) * scale\n context.fillStyle = color\n context.moveTo(x, y)\n context.beginPath()\n context.lineTo(x + scale, y)\n context.lineTo(x + scale, y + scale)\n context.lineTo(x, y + scale)\n context.lineTo(x, y)\n context.closePath()\n context.fill()\n context.restore()\n }\n\n const render = (): void => {\n // Get a context reference.\n if (canvasRef.current === undefined || canvasRef.current === null ||\n backgroundImageRef.current === undefined || backgroundImageRef.current === null) {\n console.log('Render called before canvas or image reference is set.')\n return\n }\n const context = canvasRef.current.getContext('2d')\n if (context === null) {\n console.error('Error getting 2D context from canvas.')\n return\n }\n \n // Clear the canvas.\n context.clearRect(0, 0, width, height)\n \n // Increase zoom level exponentially\n const zoomExp = (zoom: number) => {\n const expVal = Math.pow(maxZoomFactor, 1/zoomMax)\n return Math.pow(expVal, zoom)\n }\n \n let zoomFactor = zoomExp(zoom)\n let xTranslation = 0\n let yTranslation = 0\n \n const bb = mlMask.boundingBox(0)\n const bbWidth = (bb.x2 - bb.x1) * gridScale\n const bbHeight = (bb.y2 - bb.y1) * gridScale\n \n // Calculate the translation.\n if (zoomFactor > 1) {\n const bbCenterX = bb.x1 * gridScale + bbWidth / 2\n const bbCenterY = bb.y1 * gridScale + bbHeight / 2\n const scaledWidth = width / zoomFactor\n const scaledHeight = height / zoomFactor\n const bbTopLeftX = bbCenterX - scaledWidth / 2\n const bbTopLeftY = bbCenterY - scaledHeight / 2\n xTranslation = -bbTopLeftX / uiScale * zoomFactor\n yTranslation = -bbTopLeftY / uiScale * zoomFactor\n }\n context.setTransform(zoomFactor, 0, 0, zoomFactor, xTranslation, yTranslation)\n \n // Draw the image into the background.\n context.drawImage(backgroundImageRef.current, 0, 0, uiWidth, uiHeight)\n \n // Fill in squares.\n mlMask.bitmap.enabledIndices().forEach(enabledIndex => {\n setGridPoint(context, gridScale, gridWidth, enabledIndex, uiScale, selectedColor)\n })\n \n // Highlight hovered grid index.\n if (hoveredGridIndex !== -1) {\n mlMask._bitmap.getGrid(hoveredGridIndex, brushSize, gridWidth).forEach(bit => \n setGridPoint(context, gridScale, gridWidth, bit, uiScale, highlightColor)\n )\n }\n \n // Draw bounding box.\n drawBoundingBox(context, bb, gridScale, uiScale)\n // Draw grid lines.\n drawGridLines(context, width, height, gridScale, uiScale)\n \n setBitmapEmpty(mlMask._bitmap.isEmpty())\n }\n\n if (canvasRef.current !== undefined && canvasRef.current !== null &&\n backgroundImageRef.current !== undefined && backgroundImageRef.current !== null) {\n render()\n }\n }, [renderFlag, hoveredGridIndex, zoom, overlayVisible, gridScale, width, height, brushSize, \n maxZoomFactor, zoomMax, uiScale, mlMask, setBitmapEmpty, gridWidth, uiHeight, uiWidth, selectedColor])\n\n // Draw thin lines separating the grid indices.\n const drawGridLines = (context: CanvasRenderingContext2D, canvasWidth: number, canvasHeight: number, gridScale: number, uiScale: number): void => {\n context.save()\n const scale = gridScale / uiScale\n const wSteps = Math.floor(canvasWidth / scale)\n const hSteps = Math.floor(canvasHeight / scale)\n\n // Set drawing style.\n context.strokeStyle = 'white'\n context.lineWidth = 0.1\n context.globalAlpha = 0.2\n\n // Draw horizontal lines.\n for (let i = 0; i < hSteps; i++) {\n context.moveTo(0, i * scale)\n context.lineTo(canvasWidth, i * scale)\n }\n\n // Draw vertical lines.\n for (let i = 0; i < wSteps; i++) {\n context.moveTo(i * scale, 0)\n context.lineTo(i * scale, canvasHeight)\n }\n\n context.stroke()\n context.restore()\n }\n\n const drawBoundingBox = (context: CanvasRenderingContext2D, boundingBox: BoundingBox, gridScale: number, uiScale: number): void => {\n context.save()\n\n const scale = gridScale / uiScale\n const lineWidth = 0.5\n const a = { x: boundingBox.x1 * scale, y: boundingBox.y1 * scale }\n const b = { x: boundingBox.x2 * scale + scale, y: boundingBox.y2 * scale + scale } // Adding one 'scale' to draw on the other side of the data.\n\n context.strokeStyle = 'white'\n context.lineWidth = 0.5\n context.moveTo(a.x, a.y)\n context.beginPath()\n context.lineTo(b.x, a.y)\n context.lineTo(b.x, b.y)\n context.lineTo(a.x, b.y)\n context.lineTo(a.x, a.y - (lineWidth / 2)) // -(lineWidth/2) to close the corner properly.\n context.closePath()\n context.stroke()\n\n context.restore()\n }\n\n // Get mouse position in screen coordinates within the canvas element.\n const getMousePosition = (event: React.MouseEvent): { x: number, y: number } => {\n if (canvasRef.current === undefined || canvasRef.current === null) {\n return { x: -1, y: -1 }\n }\n const context = canvasRef.current.getContext('2d')\n if (context === null) {\n console.error('Error getting 2D context from canvas.')\n return { x: -1, y: -1 }\n }\n\n const canvasRect = canvasRef.current.getBoundingClientRect()\n const transformMatrix = context.getTransform()\n const scale: number = 1 / transformMatrix.m11\n const horizontal: number = transformMatrix.m41\n const vertical: number = transformMatrix.m42\n\n return {\n x: (event.clientX - canvasRect.left - horizontal) * scale,\n y: (event.clientY - canvasRect.top - vertical) * scale\n }\n }\n\n // Mouse move handler - used for setting the hovered index, so that\n // highlighting may occur.\n const mouseMoveHandler: MouseEventHandler = (event: React.MouseEvent) => {\n const scale = gridScale / uiScale\n const mousePosition = getMousePosition(event)\n const gridX = Math.floor(mousePosition.x / scale)\n const gridY = Math.floor(mousePosition.y / scale)\n const gridIndex = gridY * gridWidth + gridX\n\n // Sanity check the grid index.\n if (gridIndex < 0 || gridIndex > gridWidth * gridHeight) {\n return // Just bail here\n }\n\n if (gridIndex !== hoveredGridIndex) {\n // We have moved - to a new grid index. If the mouse button is pressed,\n // we should color in the position.\n if (event.buttons === 1) {\n if (drawMode) {\n mlMask._bitmap.setGrid(gridIndex, brushSize, gridWidth)\n } else {\n mlMask._bitmap.unsetGrid(gridIndex, brushSize, gridWidth)\n }\n }\n setHoveredGridIndex(gridIndex) // Asks for a re-render\n }\n }\n\n // Mouse click handler for selecting grid positions.\n const mouseDownHandler: MouseEventHandler = (event: React.MouseEvent): void => {\n if (hoveredGridIndex !== -1) {\n if (drawMode) {\n mlMask._bitmap.setGrid(hoveredGridIndex, brushSize, gridWidth)\n } else {\n mlMask._bitmap.unsetGrid(hoveredGridIndex, brushSize, gridWidth)\n }\n shouldRender()\n }\n }\n\n return (\n \n shouldRender()}\n alt=\"background\"\n />\n \n \n )\n}\n\nexport { MLTrainingGrid }\n","import { Button, DialogActions, DialogContent, Box, Slider, Grid, Typography, FormControlLabel, Checkbox, Tooltip, IconButton } from '@material-ui/core'\nimport { ChangeEvent, FC, SetStateAction, useEffect, useState } from 'react'\nimport { CustomDialog } from 'src/components/CustomDialog'\nimport { MLTrainingGrid } from 'src/components/mltraininggrid/MLTrainingGrid'\nimport { BitmapImage, ColorChannel } from 'src/components/mltraininggrid/BitmapImage'\nimport { useApp } from 'src/components/AppContextProvider'\nimport { AnnotationType } from 'src/components/DialogController'\nimport DeleteIcon from '@material-ui/icons/Delete'\nimport EditIcon from '@material-ui/icons/Edit'\nimport ZoomOutIcon from '@material-ui/icons/ZoomOut'\nimport ZoomInIcon from '@material-ui/icons/ZoomIn'\nimport BrushIcon from '@material-ui/icons/Brush';\nimport HelpOutlineIcon from '@material-ui/icons/HelpOutline';\nimport { SelectedObject } from 'src/components/Analysis'\nimport { DamageCategoryShort } from 'src/datamodel/DamageMapping'\nimport CheckBoxOutlineBlankIcon from '@material-ui/icons/CheckBoxOutlineBlank'\nimport CheckBoxIcon from '@material-ui/icons/CheckBox'\nimport { getDamageColor } from 'src/util/annotationUtil'\n\ninterface EditImageDialogProps {\n onSaved: (selectedObject: SelectedObject, damageCategory: DamageCategoryShort, newId?: number) => void\n onClose: () => void\n onCancel: () => void\n selectedObject: SelectedObject\n open: boolean\n title: string\n imageName: string\n damageCategory: DamageCategoryShort\n annotationId: number\n analysisId: number\n annotationType: AnnotationType\n}\n\nexport const overlayScaleFactor = 8\n\nexport const EditImageDialog: FC = ({ onSaved, onClose, onCancel, selectedObject, open, title, imageName, annotationId, damageCategory, analysisId, annotationType }: EditImageDialogProps) => {\n const zoomMin = 0\n const zoomMax = 10\n const brushSizeMin = 1\n const brushSizeMax = 6\n const gridScale = 8\n const uiScale = 4\n const [saving, setSaving] = useState(false)\n const [zoom, setZoom] = useState(zoomMin)\n const { wgApp, serviceFactory } = useApp()\n const [mlMask, setMlMask] = useState()\n const [imageUrl, setImageUrl] = useState()\n const [drawMode, setDrawMode] = useState(true)\n const [brushSize, setBrushSize] = useState(1)\n const [isDrawingEmpty, setDrawingEmpty] = useState(true)\n const [isOverlayVisible, setOverlayVisible] = useState(true)\n const [errorMessage, setErrorMessage] = useState('')\n\n const onSaveClicked = (): void => {\n if (mlMask !== undefined && wgApp !== undefined) {\n switch (annotationType) {\n case AnnotationType.New:\n const overlayDataNew = createOverlay(mlMask, gridScale, overlayScaleFactor)\n const newId = wgApp.createAnnotation(imageName, damageCategory, overlayDataNew)\n storeAnnotation(newId)\n break\n case AnnotationType.User:\n case AnnotationType.System:\n const overlayData = createOverlay(mlMask, gridScale, overlayScaleFactor)\n wgApp.updateAnnotationInImage(imageName, annotationId, damageCategory, overlayData)\n storeAnnotation()\n break\n case AnnotationType.Unknown:\n console.error('Annotation type unknown')\n break\n }\n }\n }\n\n const storeAnnotation = async (newId?: number) => {\n if (mlMask !== undefined && wgApp !== undefined) {\n setSaving(true)\n reset()\n const updatedTextureNpy = wgApp.getUVLabelmap(damageCategory)\n const stored = await serviceFactory.getLabelMapServiceClient().postLabelMap(analysisId, damageCategory, updatedTextureNpy)\n setSaving(false)\n\n if (stored) {\n onSaved(selectedObject, damageCategory, newId)\n } else {\n setErrorMessage('Error: Damage update not stored in backend.')\n console.error(\"Damage area update not stored in backend\")\n }\n }\n }\n\n const createOverlay = (scaledBitmap: BitmapImage, gridScale: number, overlayScaleFactor: number): ImageData => {\n scaledBitmap.scaleUp(gridScale / overlayScaleFactor)\n const rgbaData = scaledBitmap.toRGBAData()\n return new ImageData(rgbaData, scaledBitmap._width, scaledBitmap._height)\n }\n\n const onCancelClicked = (): void => {\n reset()\n onCancel()\n }\n\n useEffect(() => {\n if (open && wgApp !== undefined) {\n setSaving(false)\n serviceFactory.getImageServiceClient().getImageUrl(analysisId, imageName).then(url => setImageUrl(url))\n\n // The annotation overlay is given in a scaled down version (factor is 8).\n // So each pixel in the overlay we receive here represents 8x8 pixels in the original image.\n const overlayImage = wgApp.getAnnotationOverlay(annotationId, imageName, damageCategory)\n const bitmapImage = BitmapImage.fromRGBAData(overlayImage.data,\n overlayImage.width,\n overlayImage.height,\n ColorChannel.Red)\n \n // Scale bitmap down even further to get to grid scale.\n bitmapImage.scaleDown(gridScale / overlayScaleFactor)\n \n setMlMask(bitmapImage)\n }\n }, [open, wgApp, analysisId, annotationId, damageCategory, imageName, serviceFactory])\n\n useEffect(() => {\n if (isDrawingEmpty) {\n setZoom(zoomMin)\n }\n }, [isDrawingEmpty])\n\n const reset = () => {\n setErrorMessage('')\n setZoom(zoomMin)\n setBrushSize(brushSizeMin)\n setDrawMode(true)\n setOverlayVisible(true)\n }\n\n useEffect(() => {\n const keyDown = (e: KeyboardEvent) => {\n if (e.code.indexOf('Digit') !== -1) {\n const size = parseInt(e.code.split('Digit')[1])\n setBrushSize(size <= brushSizeMax ? size : brushSizeMax)\n }\n switch (e.code) {\n case 'KeyD':\n setDrawMode(true)\n break\n case 'KeyE':\n setDrawMode(false)\n break\n case 'KeyC':\n setOverlayVisible(!isOverlayVisible)\n break\n case 'KeyA':\n increaseSlider(setZoom, zoom, zoomMax, 1)\n break\n case 'KeyZ':\n decreaseSlider(setZoom, zoom, zoomMin, 1)\n break\n }\n }\n document.addEventListener('keydown', keyDown)\n return () => {\n document.removeEventListener('keydown', keyDown)\n }\n }, [isOverlayVisible, zoom])\n\n const getBrushSizes = () => {\n let sizes = []\n for (let i = brushSizeMin; i <= brushSizeMax; i++) {\n sizes.push(i)\n }\n return sizes.join(',')\n }\n \n const decreaseSlider = (setFunc: (value: SetStateAction) => void, value: number, min: number, step: number) => \n setFunc(value - step < min ? min : value - step)\n\n const increaseSlider = (setFunc: (value: SetStateAction) => void, value: number, max: number, step: number) => \n setFunc(value + step > max ? max : value + step)\n\n return (\n {\n reset()\n onClose()\n }}\n scroll='body'\n maxWidth='xl'\n >\n \n {mlMask !== undefined && imageUrl !== undefined && !saving &&\n setDrawingEmpty(isEmpty)}\n overlayVisible={isOverlayVisible}\n drawColor={getDamageColor(damageCategory, wgApp?.getLabelColors())}\n />\n }\n {saving && \n 'Saving...'\n }\n \n \n \n \n \n \n \n }\n checkedIcon={}\n checked={isOverlayVisible}\n onChange={() => setOverlayVisible(!isOverlayVisible)}\n name=\"show-overlay\"\n disabled={saving}\n color=\"primary\"\n />\n }\n label=\"Show overlay\"\n />\n \n \n \n decreaseSlider(setBrushSize, brushSize, brushSizeMin, 1)}>\n \n \n \n \n , newValue: number | number[]) => setBrushSize(newValue as number)}\n />\n \n \n increaseSlider(setBrushSize, brushSize, brushSizeMax, 1)}>\n \n \n \n \n \n \n setDrawMode(true) }\n color='primary'\n size='small'\n variant={drawMode ? 'contained' : 'outlined'}\n disabled={saving}\n startIcon={}\n >\n Draw\n \n setDrawMode(false) }\n color='primary'\n size='small'\n variant={!drawMode ? 'contained' : 'outlined'}\n disabled={saving}\n startIcon={}\n >\n Erase\n \n \n \n \n \n decreaseSlider(setZoom, zoom, zoomMin, 1)}>\n \n \n \n \n , newValue: number | number[]) => setZoom(newValue as number)}\n />\n \n \n increaseSlider(setZoom, zoom, zoomMax, 1)}>\n \n \n \n \n \n \n \n Cancel\n \n \n {saving ? 'Saving...' : 'Save'}\n \n \n \n {errorMessage !== '' && \n \n \n {errorMessage}\n \n \n }\n \n )\n}\n","import Button from '@material-ui/core/Button'\nimport Dialog from '@material-ui/core/Dialog'\nimport DialogActions from '@material-ui/core/DialogActions'\nimport DialogContent from '@material-ui/core/DialogContent'\nimport DialogTitle from '@material-ui/core/DialogTitle'\n\ninterface AlertDialogProps {\n open: boolean\n onSetOpen: (open: boolean) => void\n onYes: () => void\n onNo?: () => void\n title: string\n body: string\n yesLabel: string\n noLabel: string\n}\n\nexport const AlertDialog = (props: AlertDialogProps) => {\n const { open, onSetOpen, onYes, onNo, title, body, yesLabel, noLabel } = props\n\n const handleClose = () => {\n onSetOpen(false)\n }\n\n const handleYes = () => {\n onYes()\n onSetOpen(false)\n }\n\n const handleNo = () => {\n if (onNo !== undefined) {\n onNo()\n }\n onSetOpen(false)\n }\n\n return (\n <>\n \n {title}\n {body}\n \n \n \n \n \n \n )\n}","import { ConditionRating } from \"src/datasource/model/ConditionRating\";\n\nexport const mapToBackendRatingId = (value: number, ratings: ConditionRating[]): ConditionRating => {\n const validRatings = ratings.filter(rating => rating.value === value + \"\")\n const length = validRatings.length\n if (length === 1) {\n return validRatings[0];\n }\n if (length === 0) {\n throw new Error(\"No condition rating in the backend had the value: \" + value)\n }\n throw new Error(\"More than one condition rating in the backend had the value: \" + value)\n}\n","import { ChangeEvent, Dispatch, FC, ReactNode, useState } from 'react'\nimport Button from '@material-ui/core/Button'\nimport TextField from '@material-ui/core/TextField'\nimport DialogActions from '@material-ui/core/DialogActions'\nimport DialogContent from '@material-ui/core/DialogContent'\nimport Slider from '@material-ui/core/Slider'\nimport { Box, CircularProgress, FormControlLabel, Switch, Typography } from '@material-ui/core'\nimport useStyles from 'src/components/AnnotationDialog.style'\nimport { SelectedImage } from 'src/components/SelectedImage'\nimport { UseMutationResult, UseQueryResult } from 'react-query'\nimport { Cause } from 'src/datasource/model/Cause'\nimport { Damage } from 'src/datasource/model/Damage'\nimport { Annotation, AnnotationBuilder, Placement } from 'src/datasource/model/Annotation'\nimport { CustomDialog } from 'src/components/CustomDialog'\nimport { Thumbnail } from 'src/components/Thumbnail'\nimport { LabelCategorySelect } from 'src/components/LabelCategorySelect'\nimport { AnnotationAction, State } from 'src/reducers/annotationReducer'\nimport { useApp } from 'src/components/AppContextProvider'\nimport { DamageCategoryShort, DamageMappingError, mapFromBackendIdToModelName } from 'src/datamodel/DamageMapping'\nimport { SelectedObject } from 'src/components/Analysis'\nimport { overlayScaleFactor } from 'src/components/EditImageDialog'\nimport { calcPlacement, getDamageColor } from 'src/util/annotationUtil'\nimport SettingsApplicationsIcon from '@material-ui/icons/SettingsApplications'\nimport AccountBoxIcon from '@material-ui/icons/AccountBox'\nimport AddBoxIcon from '@material-ui/icons/AddBox'\nimport { AnnotationType } from 'src/components/DialogController'\nimport { AlertDialog } from 'src/components/AlertDialog'\nimport { ConditionRating } from 'src/datasource/model/ConditionRating'\nimport { mapToBackendRatingId } from 'src/datamodel/ConditionMapping'\n\ninterface AnnotationDialogProps {\n queries: AnnotationDialogQueries\n annotationType: AnnotationType\n state: State\n dispatch: Dispatch\n analysisId: number\n open: boolean\n images: string[]\n selectedObject: SelectedObject\n onDialogClose: () => void\n onEditImage: (analysisId: number, imageName: string, annotationId: number, damageCategory: string, annotationType: AnnotationType) => void\n}\n\ninterface AnnotationDialogQueries {\n userIdQuery: UseQueryResult\n tenantIdQuery: UseQueryResult\n damagesQuery: UseQueryResult\n conditionRatingsQuery: UseQueryResult\n primaryImageQuery: UseQueryResult\n annotationQuery: UseQueryResult\n primaryImageNameQuery: UseQueryResult\n imageQuery: UseQueryResult\n selectedImageQuery: UseQueryResult\n causesQuery: UseQueryResult\n saveMutation: UseMutationResult\n deleteMutation: UseMutationResult\n}\n\nexport const commonQueryId = 'annotationDialog'\n\nconst AnnotationDialog: FC = ({\n queries,\n annotationType,\n state,\n dispatch,\n analysisId,\n open,\n onDialogClose,\n onEditImage,\n images,\n selectedObject\n}: AnnotationDialogProps) => {\n const classes = useStyles()\n const [alertDialogOpen, setAlertDialogOpen] = useState(false)\n\n const { wgApp, serviceFactory, setTotalAnnotationCount } = useApp()\n\n const onDamageCategorySelect = (selected: number): void => {\n dispatch({ type: 'setSelectedCause', payload: undefined })\n const damage: Damage | undefined = queries.damagesQuery.data !== undefined ? queries.damagesQuery.data[selected] : undefined\n dispatch({ type: 'setSelectedDamage', payload: damage?.id })\n }\n\n const onDamageCauseSelect = (selected: number): void => {\n dispatch({ type: 'setCustomCause', payload: '' })\n const cause: Cause | undefined = queries.causesQuery.data !== undefined ? queries.causesQuery.data[selected] : undefined\n dispatch({ type: 'setSelectedCause', payload: cause?.id })\n }\n\n const onSetDamageLevel = (event: ChangeEvent<{}>, newValue: number | number[]): void => {\n dispatch({ type: 'setDamageLevel', payload: sliderMarks.findIndex(s => s.value === newValue as number) })\n }\n\n const onSetAsPrimary = (imageName: string): void => {\n dispatch({ type: 'setPrimaryImageName', payload: imageName })\n }\n\n const handleDialogClosed = (): void => onDialogClose()\n\n const isReady = (): boolean => {\n return open && queries.damagesQuery.isSuccess && queries.conditionRatingsQuery.isSuccess && queries.imageQuery.isSuccess && queries.annotationQuery.isSuccess && !queries.annotationQuery.isFetching\n }\n\n const onSaveClicked = async (): Promise => {\n const damage: Damage | undefined = queries.damagesQuery.data?.find(d => d.id === state.selectedDamage)\n if (damage !== undefined && state.description !== '' && queries.userIdQuery.isSuccess && queries.conditionRatingsQuery.isSuccess && queries.tenantIdQuery.isSuccess && state.primaryImageId !== undefined && selectedObject.id !== -1) {\n dispatch({ type: 'setErrorMessage', payload: '' })\n const conditionRating: ConditionRating = mapToBackendRatingId(state.damageLevel, queries.conditionRatingsQuery.data)\n const builder = new AnnotationBuilder(selectedObject.id.toString(), analysisId, state.primaryImageId, state.damageLevel, conditionRating.id, queries.userIdQuery.data, queries.tenantIdQuery.data, getPlacement(), damage, state.description)\n .setCauses(state.causeCustom, queries.causesQuery.data?.find(c => c.id === state.selectedCause), state.customCause)\n buildAndSaveAnnotation(builder)\n } else {\n const errorMsg = state.primaryImageId === undefined ? 'Missing primary image' :\n (selectedObject.id === -1 ? 'Missing damage drawing' : 'Missing input')\n dispatch({ type: 'setErrorMessage', payload: errorMsg })\n }\n }\n\n const buildAndSaveAnnotation = (builder: AnnotationBuilder) => {\n let newAnnotation: Annotation | undefined = buildNewAnnotation(builder)\n if (newAnnotation !== undefined) {\n dispatch({ type: 'setSaving', payload: true })\n saveAnnotation(newAnnotation)\n } else {\n dispatch({ type: 'setErrorMessage', payload: 'Annotation cannot be saved' })\n }\n }\n\n const buildNewAnnotation = (builder: AnnotationBuilder): Annotation | undefined => {\n let newAnnotation: Annotation | undefined\n if (annotationType === AnnotationType.System || annotationType === AnnotationType.New) {\n newAnnotation = builder.finishNew()\n } else if (annotationType === AnnotationType.User) {\n if (queries.annotationQuery.data !== undefined) {\n newAnnotation = builder.finishUpdate(queries.annotationQuery.data)\n } else {\n dispatch({ type: 'setErrorMessage', payload: 'Update error' })\n }\n }\n return newAnnotation\n }\n\n const saveAnnotation = (newAnnotation: Annotation) => {\n queries.saveMutation.mutate(newAnnotation, {\n onError: () => {\n dispatch({ type: 'setSaving', payload: false })\n dispatch({ type: 'setErrorMessage', payload: 'Error saving' })\n },\n onSuccess: () => {\n dispatch({ type: 'setSaving', payload: false })\n handleDialogClosed()\n }\n })\n }\n\n const onConfirmDelete = () => {\n if (wgApp !== undefined) {\n if (annotationType === AnnotationType.System) {\n deleteAnnotationFromModel()\n handleDialogClosed()\n }\n else if (annotationType === AnnotationType.User) {\n dispatch({ type: 'setDeleting', payload: true })\n deleteAnnotationFromBackendAndModel()\n }\n }\n }\n\n const deleteAnnotationFromBackendAndModel = () => {\n if (queries.annotationQuery.data !== undefined) {\n queries.deleteMutation.mutate(queries.annotationQuery.data.id, {\n onSuccess: (success: boolean) => {\n dispatch({ type: 'setDeleting', payload: false })\n if (success) {\n deleteAnnotationFromModel()\n handleDialogClosed()\n } else {\n dispatch({ type: 'setErrorMessage', payload: 'Could not delete' })\n }\n },\n onError: (e) => {\n dispatch({ type: 'setDeleting', payload: false })\n dispatch({ type: 'setErrorMessage', payload: 'Error deleting' })\n }\n })\n } else {\n dispatch({ type: 'setDeleting', payload: false })\n dispatch({ type: 'setErrorMessage', payload: 'No id found' })\n }\n }\n\n const deleteAnnotationFromModel = async () => {\n if (wgApp !== undefined && selectedObject.type !== undefined) {\n const damageCategory = selectedObject.type\n wgApp.deleteAnnotation(selectedObject.id, damageCategory)\n const updatedTextureNpy = wgApp.getUVLabelmap(damageCategory)\n const stored = await serviceFactory.getLabelMapServiceClient().postLabelMap(analysisId, damageCategory, updatedTextureNpy)\n setTotalAnnotationCount(wgApp !== undefined ? wgApp.getTotalAnnotationCount() : 0)\n if (!stored) {\n dispatch({ type: 'setErrorMessage', payload: 'Could not update model' })\n }\n }\n }\n\n const editImage = (analysisId: number, imageName: string, annotationId: number, damageCategory: DamageCategoryShort | undefined) => {\n if (damageCategory === undefined) {\n if (state.selectedDamage === undefined) {\n dispatch({ type: 'setErrorMessage', payload: 'Set damage category before editing' })\n } else if (queries.damagesQuery.data === undefined) {\n dispatch({ type: 'setErrorMessage', payload: 'Damages not fetched yet' })\n }\n else {\n try {\n const damageType = mapFromBackendIdToModelName(queries.damagesQuery.data, state.selectedDamage)\n onEditImage(analysisId, imageName, annotationId, damageType, annotationType)\n } catch (error) {\n if (error instanceof DamageMappingError) {\n console.error(error, error.stack)\n dispatch({ type: 'setErrorMessage', payload: 'Unable to find correct mapping for the damage' })\n } else {\n throw error\n }\n }\n }\n } else {\n dispatch({ type: 'setErrorMessage', payload: '' })\n onEditImage(analysisId, imageName, annotationId, damageCategory, annotationType)\n }\n }\n\n const isPrimaryImage = (imageName: string | undefined, selectedImageName: string): boolean => {\n return selectedImageName !== undefined ? imageName === selectedImageName.slice(0, 36) : false\n }\n\n const getTitle = (): ReactNode => {\n switch (annotationType) {\n case AnnotationType.New:\n return <>New annotation\n case AnnotationType.System:\n return <>System annotation ({selectedObject.id})\n case AnnotationType.User:\n return <>User annotation ({selectedObject.id})\n default:\n return \"\"\n }\n }\n\n const getPlacement = (): Placement => {\n const primaryImage = images.find(i => isPrimaryImage(state.primaryImageName, i))\n if (primaryImage !== undefined && wgApp !== undefined && selectedObject.type !== undefined) {\n const overlay = wgApp.getAnnotationOverlay(selectedObject.id, primaryImage, selectedObject.type)\n return calcPlacement(overlay, overlayScaleFactor, overlay.width * overlayScaleFactor, overlay.height * overlayScaleFactor);\n }\n return new Placement(0, 0, 0, 0)\n }\n\n const calcDamageColor = () => getDamageColor(selectedObject.type, wgApp?.getLabelColors())\n\n const sliderMarks = [\n { value: 5, label: '0' },\n { value: 23, label: '1' },\n { value: 41, label: '2' },\n { value: 59, label: '3' },\n { value: 77, label: '4' },\n { value: 95, label: '5' }\n ]\n\n return (\n <>\n \n {isReady() ?\n <>\n \n \n \n\n {wgApp !== undefined &&\n {\n editImage(analysisId, images[state.selectedImage], selectedObject.id, selectedObject.type)\n }}\n onSetAsPrimary={() => onSetAsPrimary(images[state.selectedImage])}\n isPrimary={isPrimaryImage(state.primaryImageName, images[state.selectedImage])}\n overlay={selectedObject.type !== undefined ? wgApp.getAnnotationOverlay(selectedObject.id, images[state.selectedImage], selectedObject.type) : undefined}\n color={calcDamageColor()}\n />}\n\n \n\n \n {annotationType === AnnotationType.User &&\n <>\n \n {`Created: ${queries.annotationQuery.data?.created ? new Date(queries.annotationQuery.data.created).toLocaleString() : '?'}`}\n \n }\n \n\n \n \n Condition rating *\n \n , newValue: number | number[]) => onSetDamageLevel(event, newValue)}\n />\n\n d.value)}\n value={queries.damagesQuery.data?.find(d => d.id === state.selectedDamage)?.value}\n onSelect={(selected: number) => onDamageCategorySelect(selected)}\n />\n\n {!state.causeCustom &&\n c.value)}\n value={queries.causesQuery.data?.find(c => c.id === state.selectedCause)?.value}\n onSelect={(selected: number) => onDamageCauseSelect(selected)}\n />}\n\n {state.causeCustom &&\n ) => dispatch({ type: 'setCustomCause', payload: e.currentTarget.value })}\n />}\n\n , checked: boolean) => dispatch({ type: 'setCauseCustom', payload: checked })}\n name='show-custom-cause'\n color='primary'\n />\n }\n label='Custom cause'\n />\n\n ) => dispatch({ type: 'setDescription', payload: e.target.value })}\n />\n \n\n \n \n\n \n {wgApp !== undefined && queries.imageQuery.data?.map((image, i) =>\n dispatch({ type: 'setSelectedImage', payload: i })}\n onEdit={() => {\n editImage(analysisId, images[i], selectedObject.id, selectedObject.type)\n }}\n color={calcDamageColor()}\n />)\n }\n \n \n \n\n \n \n {state.errorMessage}\n \n \n Cancel\n \n setAlertDialogOpen(true)}\n color='primary'\n variant='outlined'\n disabled={state.saving || state.deleting || annotationType === AnnotationType.New}\n >\n {state.deleting ? 'Deleting...' : 'Delete'}\n \n \n {state.saving ? 'Saving...' : 'Save'}\n \n \n \n :\n \n \n \n }\n \n\n setAlertDialogOpen(open)}\n open={alertDialogOpen}\n onYes={() => onConfirmDelete()}\n />\n \n )\n}\n\nexport { AnnotationDialog }","export type AnnotationAction =\n{\n type: 'resetAll'\n}\n| {\n type: 'setSelectedDamage'\n payload: number | undefined\n}\n| {\n type: 'setErrorMessage'\n payload: string\n}\n| {\n type: 'setCustomCause'\n payload: string\n}\n| {\n type: 'setCauseCustom'\n payload: boolean\n}\n| {\n type: 'setSelectedCause'\n payload: number | undefined\n}\n| {\n type: 'setSelectedImage'\n payload: number\n}\n| {\n type: 'setPrimaryImageId'\n payload: number | undefined\n}\n| {\n type: 'setPrimaryImageName'\n payload: string | undefined\n}\n| {\n type: 'setSaving'\n payload: boolean\n}\n| {\n type: 'setDeleting'\n payload: boolean\n}\n| {\n type: 'setDamageLevel'\n payload: number\n}\n| {\n type: 'setDescription'\n payload: string\n}\n\nexport interface State {\n selectedDamage: number | undefined\n errorMessage: string\n customCause: string\n causeCustom: boolean\n selectedCause: number | undefined\n selectedImage: number\n primaryImageId: number | undefined\n primaryImageName: string | undefined\n saving: boolean\n deleting: boolean\n damageLevel: number\n description: string\n}\n\nexport const initialAnnotationState: State = {\n selectedDamage: undefined,\n errorMessage: '',\n customCause: '',\n causeCustom: false,\n selectedCause: undefined,\n selectedImage: 0,\n primaryImageId: undefined,\n primaryImageName: undefined,\n saving: false,\n deleting: false,\n damageLevel: 0,\n description: ''\n}\n\nexport const annotationReducer = (state: State, action: AnnotationAction): State => {\n switch (action.type) {\n case 'resetAll':\n return { ...initialAnnotationState }\n case 'setSelectedDamage':\n return { ...state, selectedDamage: action.payload }\n case 'setErrorMessage':\n return { ...state, errorMessage: action.payload }\n case 'setCustomCause':\n return { ...state, customCause: action.payload }\n case 'setCauseCustom':\n return { ...state, causeCustom: action.payload }\n case 'setSelectedCause':\n return { ...state, selectedCause: action.payload }\n case 'setSelectedImage':\n return { ...state, selectedImage: action.payload }\n case 'setPrimaryImageId':\n return { ...state, primaryImageId: action.payload }\n case 'setPrimaryImageName':\n return { ...state, primaryImageName: action.payload }\n case 'setSaving':\n return { ...state, saving: action.payload }\n case 'setDeleting':\n return { ...state, deleting: action.payload }\n case 'setDamageLevel':\n return { ...state, damageLevel: action.payload }\n case 'setDescription':\n return { ...state, description: action.payload }\n default:\n return state\n }\n}\n","import { makeStyles } from '@material-ui/core'\n\nexport const useStyles = makeStyles(theme => ({\n filters: {\n width: 220,\n backgroundColor: 'rgba(255, 255, 255, 0.55)',\n borderRadius: 4,\n position: 'absolute',\n top: theme.spacing(6) + 8,\n left: 8,\n },\n checkbox: {\n width: '100%',\n },\n opacity: {\n width: '100%',\n },\n toggle: {\n position: 'absolute',\n top: 10,\n right: 10,\n },\n labelColor: {\n width: 10, \n height: 10, \n float: 'left', \n marginTop: 6, \n marginRight: 4, \n borderRadius: '50%',\n },\n}))\n\nexport default useStyles\n","import { Checkbox, FormControlLabel, Box, Button, Slider, Typography, IconButton } from \"@material-ui/core\"\nimport { ChangeEvent, useEffect, useState } from \"react\"\nimport useStyles from \"src/components/OverlayFilters.style\"\nimport CheckBoxOutlineBlankIcon from '@material-ui/icons/CheckBoxOutlineBlank'\nimport CheckBoxIcon from '@material-ui/icons/CheckBox'\nimport { damageCategories, damageCategoriesShort, DamageCategoryShort } from \"src/datamodel/DamageMapping\"\nimport { useApp } from \"src/components/AppContextProvider\"\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore'\nimport ExpandLessIcon from '@material-ui/icons/ExpandLess'\nimport { getDamageColor } from \"src/util/annotationUtil\"\ninterface VisibleDamage {\n category: string\n visible: boolean\n}\n\nexport const OverlayFilters = () => {\n const defaultOpacity = 50\n const classes = useStyles()\n const [visibleDamages, setVisibleDamages] = useState([])\n const [opacity, setOpacity] = useState(defaultOpacity)\n const [expanded, setExpanded] = useState(true)\n const [gizmoVisible, setGizmoVisible] = useState(false)\n const [reviewedVisible, setReviewedVisible] = useState(true)\n const [unreviewedVisible, setUnreviewedVisible] = useState(true)\n const { wgApp, userAnnotationIds } = useApp()\n \n useEffect(() => {\n if (wgApp !== undefined) {\n setOpacity(wgApp.getDamageOpacity() * 100)\n setVisibleDamages(wgApp.getDamageCategoryVisibility().map(category => { return { category, visible: true } }))\n }\n }, [wgApp])\n\n useEffect(() => {\n if (wgApp !== undefined) {\n wgApp.setDamageOpacity(opacity * 0.01)\n }\n }, [wgApp, opacity])\n\n useEffect(() => {\n if (wgApp !== undefined) {\n wgApp.setGizmoVisibility(gizmoVisible)\n }\n }, [wgApp, gizmoVisible])\n\n useEffect(() => {\n if (wgApp !== undefined) {\n if (reviewedVisible && unreviewedVisible) {\n wgApp.showAllAnnotations()\n }\n else if (!reviewedVisible && unreviewedVisible) {\n // Hide userAnnotationIds, show all others\n wgApp.hideAnnotations(userAnnotationIds.map(e => parseInt(e)))\n }\n else if (reviewedVisible && !unreviewedVisible) {\n // Show userAnnotationIds, hide all others\n wgApp.showAnnotations(userAnnotationIds.map(e => parseInt(e)))\n }\n else {\n wgApp.hideAllAnnotations()\n }\n }\n }, [wgApp, userAnnotationIds, reviewedVisible, unreviewedVisible])\n\n const toggleCategory = (e: ChangeEvent, category: string) => {\n const checked: boolean = e.target.checked\n if (wgApp !== undefined) {\n update3dModel(checked, category)\n updateUIState(checked, category)\n }\n }\n\n const update3dModel = (checked: boolean, category: string) => {\n if (wgApp !== undefined) {\n const cats: string[] = [...wgApp.getDamageCategoryVisibility()]\n if (!checked) {\n let i: number = cats.indexOf(category)\n cats.splice(i, 1)\n } else {\n cats.splice(cats.length, 0, category)\n }\n wgApp.setDamageCategoryVisibility(cats)\n }\n }\n\n const updateUIState = (checked: boolean, category: string) => {\n let iv: number = visibleDamages.findIndex(v => v.category === category)\n visibleDamages[iv].visible = checked\n setVisibleDamages([...visibleDamages])\n }\n\n const reset = () => {\n if (wgApp !== undefined) {\n wgApp.setDamageCategoryVisibility(damageCategoriesShort)\n setVisibleDamages(wgApp.getDamageCategoryVisibility().map(category => { return { category, visible: true } }))\n setOpacity(defaultOpacity)\n setReviewedVisible(true)\n setUnreviewedVisible(true)\n setGizmoVisible(false)\n }\n }\n\n const getLabel = (category: string) => {\n const index = damageCategoriesShort.indexOf(category as DamageCategoryShort)\n const color = getDamageColor(category, wgApp?.getLabelColors())\n\n return (\n
\n
\n {damageCategories[index]}\n
\n )\n }\n\n return (\n
\n {expanded ?\n setExpanded(!expanded)}>\n \n \n :\n setExpanded(!expanded)}>\n \n \n }\n {expanded ?\n \n {visibleDamages.map((d, i) => \n }\n checkedIcon={}\n checked={visibleDamages[i].visible}\n onChange={(e: ChangeEvent) => toggleCategory(e, d.category)}\n name=\"damage\"\n color=\"primary\"\n />\n }\n label={getLabel(d.category)}\n />\n )}\n
\n \n Opacity ({opacity}%)\n \n , newValue: number | number[]) => setOpacity(newValue as number)}\n />\n }\n checkedIcon={}\n checked={gizmoVisible}\n onChange={(e: ChangeEvent<{}>, newValue : boolean) => setGizmoVisible(newValue)}\n name=\"gizmo\"\n color=\"primary\"\n />\n }\n label=\"Show gizmo\"\n />\n }\n checkedIcon={}\n checked={reviewedVisible}\n onChange={(e: ChangeEvent<{}>, newValue : boolean) => setReviewedVisible(newValue)}\n name=\"reviewed\"\n color=\"primary\"\n />\n }\n label=\"Show reviewed\"\n />\n }\n checkedIcon={}\n checked={unreviewedVisible}\n onChange={(e: ChangeEvent<{}>, newValue : boolean) => setUnreviewedVisible(newValue)}\n name=\"unreviewed\"\n color=\"primary\"\n />\n }\n label=\"Show unreviewed\"\n />\n \n
\n :\n \n {[...visibleDamages].filter(v => v.visible).length + \"/4 categories\"} | {opacity}%\n \n }\n
\n)\n}\n","import { DataModel } from 'src/datamodel/DataModel'\nimport { damageCategoriesShort } from 'src/datamodel/DamageMapping'\nimport { gunzipSync } from 'fflate'\n\n/**\n * A simple dummy data model that loads data from three files\n * stored in the dummydata folder.\n */\nexport class BlobDataModel extends DataModel {\n \n constructor (analysisId, serviceFactory) {\n super()\n this.analysisId = analysisId\n this.serviceClient = serviceFactory.getServiceClient()\n this.userServiceClient = serviceFactory.getUserServiceClient()\n this.imageServiceClient = serviceFactory.getImageServiceClient()\n }\n\n\n async getGltfModelUrl () {\n const tenantId = await this.getTenantId()\n return 'api/modelblob/analysis/' + this.analysisId + '/retexturedmesh/tenant/' + tenantId\n }\n\n async getOpenSfmModelUrl () {\n const tenantId = await this.getTenantId()\n return 'api/modelblob/analysis/' + this.analysisId + '/features/tenant/' + tenantId\n }\n\n async getLabelMapUrl (damageShort) {\n const tenantId = await this.getTenantId()\n return 'api/modelblob/analysis/' + this.analysisId + '/consensus/label/' + damageShort + '/tenant/' + tenantId\n }\n\n async getZipLabelMapUrl (damageShort) {\n const tenantId = await this.getTenantId()\n return 'api/modelblob/analysis/' + this.analysisId + '/consensus/ziplabel/' + damageShort + '/tenant/' + tenantId\n }\n\n getTenantId() {\n return this.userServiceClient.getCurrentTenantId()\n }\n\n /**\n * @see DataModel.gltfModel\n */\n async gltfModel () {\n const url = await this.getGltfModelUrl()\n const response = await this.serviceClient.getRequestResponse(url)\n const link = await response.text()\n const file_response = await fetch(link, {\n method: 'GET'\n })\n return file_response.blob()\n }\n\n /**\n * @see DataModel.labelMaps\n */\n async labelMaps () {\n const resolvedLabelmaps = {}\n for (let i = 0; i < damageCategoriesShort.length; i++) {\n const response = await this.serviceClient.getRequestResponse(await this.getZipLabelMapUrl(damageCategoriesShort[i]))\n const link = await response.text()\n const file_response = await fetch(link, {\n method: 'GET'\n })\n // Check if the labelmap was fetched from blob storage\n if (file_response.status === 200) {\n const buffer = await file_response.arrayBuffer()\n resolvedLabelmaps[damageCategoriesShort[i].toLowerCase()] = gunzipSync(new Uint8Array(buffer)).buffer\n }\n }\n return resolvedLabelmaps\n }\n\n /**\n * @see DataModel.opensfm\n */\n async opensfm () {\n const url = await this.getOpenSfmModelUrl()\n const response = await this.serviceClient.getRequestResponse(url)\n const link = await response.text()\n const file_response = await fetch(link, {\n method: 'GET'\n })\n const json = await file_response.json()\n return json\n }\n\n /**\n * TODO: Rename this method to imageByName\n * \n * An example of an imagename:\n * 0a0cfe50-6b6f-4993-ae7f-0e881c83b859-HighQuality.jpg\n */\n async imageById (imageName) {\n const response = await this.imageServiceClient.getImage(this.analysisId, imageName)\n return this._convertBlobToBase64(response)\n }\n\n /**\n * Converter that accepts a blob and converts it to a base64 encoded\n * string with mime type ready for use in e.g. the src attribute of\n * an img tag.\n * @param {*} blob The blob to convert.\n * @returns A promise that resolves to a base64 encoded string with mime type.\n */\n _convertBlobToBase64 (blob) {\n return new Promise((resolve, reject) => {\n const fileReader = new FileReader()\n fileReader.onerror = () => {\n reject(new Error('Error in base64 conversion.'))\n }\n fileReader.onload = () => {\n resolve(fileReader.result)\n }\n fileReader.readAsDataURL(blob)\n })\n }\n}\n","/**\n * Data model \"interface\".\n * This is just a stub where all methods return rejected promises.\n */\nexport class DataModel {\n /**\n * Loader for the GLTF model.\n * @returns A promise carrying the blob data of the gltf file.\n */\n async gltfModel () {\n throw new Error('Not implemented')\n }\n\n /**\n * Loader for the label/consensus maps.\n * @returns A promise carrying an object with the keys alga, crac, crpr,\n * rust, spal, and position that contain the corresponding consensus maps.\n */\n async labelMaps () {\n throw new Error('Not implemented')\n }\n\n /**\n * Loader for the opensfm file.\n * @returns A promise carrying the JSON content of the opensfm file.\n */\n async opensfm () {\n throw new Error('Not implemented')\n }\n\n /**\n * Loader for the color map.\n * @returns A promise that resolves to a base64 encoded image\n * string that can be used for an .\n * @deprecated As of 15/06/21 this method is deprecated.\n */\n async colorMap () {\n throw new Error('Not implemented')\n }\n\n /**\n * Loader for the label map.\n * @returns A promise that resolves to a base64 encoded image\n * string that can be used for an .\n * @deprecated As of 15/06/21 this method is deprecated.\n */\n async labelMap () {\n throw new Error('Not implemented')\n }\n\n /**\n * Loader for the model meta data.\n * @returns The model meta data.\n * @deprecated As of 15/06/21 this method is deprecated.\n */\n async metaData () {\n throw new Error('Not implemented')\n }\n\n /**\n * Loader for the features (metadata).\n * @deprecated As of 15/06/21 this method is deprecated.\n */\n async features () {\n throw new Error('Not implemented')\n }\n\n /**\n * Loader for the 2D images that lie behind the 3D model.\n * This is needed for annotating the images to provide supervised learning\n * to the ML model.\n * @param {string} imageName The name of the image to load.\n */\n async imageById (imageName) {\n throw new Error('Not implemented')\n }\n}\n","import { makeStyles } from '@material-ui/core'\n\nexport const useStyles = makeStyles(theme => ({\n model: {\n position: 'relative', \n height: '100vh',\n },\n}))\n\nexport default useStyles\n","import { useEffect, useMemo, useRef, useState } from 'react'\nimport { useParams } from 'react-router-dom'\nimport { RouterParams } from 'src/App'\nimport { WgApp } from 'src/wgapp/wgApp'\nimport { useApp } from 'src/components/AppContextProvider'\nimport { DialogController } from 'src/components/DialogController'\nimport { OverlayFilters } from 'src/components/OverlayFilters'\nimport { Box } from '@material-ui/core'\nimport { BlobDataModel } from 'src/datamodel/BlobDataModel'\nimport { useStyles } from 'src/components/Analysis.style'\nimport { DamageCategoryShort } from 'src/datamodel/DamageMapping'\nimport { Annotation } from 'src/datasource/model/Annotation'\n\nexport interface SelectedObject {\n id: number\n isNew: boolean\n type?: DamageCategoryShort\n}\n\ninterface AnalysisProps {\n updateHighlightId: (highlightId: number) => void\n}\n\nexport const Analysis = ({ updateHighlightId }: AnalysisProps) => {\n const classes = useStyles()\n const canvasRef = useRef(null)\n const [selectedObject, setSelectedObject] = useState(undefined)\n const { wgApp, setWgApp, account, serviceFactory, setUserAnnotationIds, setTotalAnnotationCount } = useApp()\n const [imageData, setImageData] = useState([])\n const [annotationDialogOpen, setAnnotationDialogOpen] = useState(false)\n const maxImages: number = 20\n const { analysisId } = useParams()\n const analysisIdNumber = useMemo(() => { return analysisId ? parseInt(analysisId) : undefined}, [analysisId])\n const [highlightId, setHighlightId] = useState(-1)\n\n useEffect(() => {\n if (canvasRef.current !== null) {\n canvasRef.current.oncontextmenu = (e: MouseEvent) => e.preventDefault()\n const fetchUserAnnotationIds = async () => {\n if (analysisIdNumber !== undefined) {\n const data: Map = await serviceFactory.getAnnotationService().getUserAnnotationsMapForAnalysis(analysisIdNumber)\n setUserAnnotationIds(Array.from(data.keys()))\n }\n }\n fetchUserAnnotationIds()\n\n const wgAppLocal = new WgApp(canvasRef.current)\n const dataModel = new BlobDataModel(analysisIdNumber, serviceFactory)\n //const dataModel = new VmDummyDataModel(analysisId)\n setSelectedObject(undefined)\n\n setTotalAnnotationCount(0)\n wgAppLocal.setDataModel(dataModel, () => {\n setTotalAnnotationCount(wgAppLocal.getTotalAnnotationCount())\n })\n\n wgAppLocal.setLeftClickHandler((clickedObj: any) => {\n setImageData([])\n if (clickedObj.id === -1) {\n setSelectedObject(undefined)\n } else {\n const selectedObject: SelectedObject = clickedObj\n setSelectedObject({ ...selectedObject, isNew: false })\n const images: string[] = wgAppLocal.getAnnotationImages(clickedObj.id, clickedObj.type)\n if (images !== undefined && images.length > 0) {\n setImageData(images.slice(0, maxImages))\n setAnnotationDialogOpen(true)\n } else {\n console.error('No images found')\n }\n }\n })\n\n //TODO: Move content to alternative click\n wgAppLocal.setRightClickHandler((clickedObj: any) => {\n setImageData([])\n if (clickedObj.id === -1) {\n const selectedObject: SelectedObject = clickedObj\n const images = wgAppLocal.getImagesForNewAnnotation()\n if (images !== undefined && images.length > 0) {\n setImageData(images.slice(0, maxImages))\n setSelectedObject({ ...selectedObject, isNew: true })\n setAnnotationDialogOpen(true)\n } else {\n console.error('No images found')\n }\n }\n })\n \n wgAppLocal.setDamageHoverCallback((highlightedObj: any) => setHighlightId(highlightedObj.id))\n\n setWgApp(wgAppLocal)\n }\n }, [account, analysisIdNumber, serviceFactory, setUserAnnotationIds, setWgApp, setTotalAnnotationCount])\n\n useEffect(() => {\n updateHighlightId(highlightId)\n }, [highlightId, updateHighlightId])\n\n useEffect(() => {\n const resizeCanvas= () => {\n if (wgApp !== undefined) {\n wgApp.resize(window.innerWidth, window.innerHeight)\n }\n }\n window.addEventListener('resize', resizeCanvas, false)\n resizeCanvas()\n return () => window.removeEventListener('resize', resizeCanvas, false)\n }, [wgApp])\n\n return (\n <>\n {analysisIdNumber !== undefined ?\n <>\n
\n \n \n
\n {selectedObject !== undefined &&\n setAnnotationDialogOpen(open)}\n onUpdateSelectedObject={(selectedObject: SelectedObject) => setSelectedObject(selectedObject)}\n annotationDialogOpen={annotationDialogOpen}\n images={imageData}\n selectedObject={selectedObject}\n analysisId={analysisIdNumber}\n />\n }\n \n :\n Annotation id not found\n }\n \n )\n}\n","import { Typography } from \"@material-ui/core\"\n\ninterface InfoProps {\n label: string\n value: string\n}\n\nexport const Info = (props: InfoProps) => {\n return (\n
\n \n {props.label}: {props.value}\n \n
\n )\n}","import { makeStyles } from '@material-ui/core'\n\nexport const useStyles = makeStyles(theme => ({\n page: {\n display: 'flex',\n width: 1000,\n '@media print': {\n margin: 0,\n pageBreakAfter: 'always',\n width: '210mm',\n height: '260mm',\n },\n },\n card: {\n '@media print': {\n boxShadow: 'none',\n },\n },\n header: {\n padding: theme.spacing(1),\n },\n container: {\n padding: 0,\n },\n main: {\n width: '100%',\n margin: theme.spacing(1),\n },\n overview: {\n width: '100%',\n margin: theme.spacing(1),\n },\n info: {\n width: '100%',\n margin: theme.spacing(1),\n },\n mainImg: {\n width: 600,\n '@media print': {\n maxHeight: '140mm',\n },\n },\n overviewImg: {\n width: 400,\n },\n}))\n\nexport default useStyles\n","import { Box, Card, CardContent, CardHeader } from '@material-ui/core'\nimport useStyles from 'src/components/report/Annotation.style'\nimport { ReactNode } from 'react'\n\ninterface AnnotationProps {\n title: string\n subtitle: string\n mainImgSrc: string\n overviewImgSrc: string\n info: ReactNode\n}\n\nexport const Annotation = (props: AnnotationProps) => {\n const classes = useStyles()\n\n return (\n \n \n \n \n \n \"primary\" \n \n \n \"overview\"\n \n \n {props.info}\n \n \n \n \n )\n}","import { makeStyles } from '@material-ui/core'\n\nexport const useStyles = makeStyles(theme => ({\n hideForPrint: {\n '@media print': {\n display: 'none',\n },\n },\n showForPrint: {\n display: 'none',\n '@media print': {\n display: 'block',\n },\n },\n frontPage: {\n '@media print': {\n pageBreakAfter: 'always',\n },\n },\n selectedPages: {\n textDecoration: 'underline',\n color: theme.palette.primary.main,\n },\n button: {\n marginRight: theme.spacing(2)\n },\n}))\n\nexport default useStyles\n","\nimport { Info } from 'src/components/report/Info'\nimport { Annotation } from 'src/components/report/Annotation'\nimport Select from '@material-ui/core/Select'\nimport { FormControl, InputLabel, MenuItem, Box, FormControlLabel, Checkbox, Card, CardContent, Button } from '@material-ui/core'\nimport CheckBoxOutlineBlankIcon from '@material-ui/icons/CheckBoxOutlineBlank'\nimport CheckBoxIcon from '@material-ui/icons/CheckBox'\nimport { useState } from 'react'\nimport useStyles from 'src/components/report/Report.style'\nimport { damageCategories } from 'src/datamodel/DamageMapping'\nimport { Typography } from '@material-ui/core'\nimport PrintIcon from '@material-ui/icons/Print'\nimport MenuBookIcon from '@material-ui/icons/MenuBook'\n\nexport const Report = () => {\n const classes = useStyles()\n const [loading, setLoading] = useState(false)\n\n const onGenerate = (): void => {\n setLoading(true)\n setTimeout(() => {\n setLoading(false)\n }, 4000)\n }\n\n return (\n <>\n \n Analysis 83\n
\n
\n \n \n \n \n \n d !== 'None').join(', ')} />\n \n \n \n
\n \n \n \n \n \n \n Select analysis\n {}}\n value={'Analysis 83'}\n >\n {['Analysis 83', 'Analysis 84']?.map((value, index) => {\n return {value}\n })}\n \n \n \n \n {//TODO: How to get damages correctly?\n damageCategories.filter(d => d !== 'None').map((d, i) => \n }\n checkedIcon={}\n checked={true}\n onChange={() => {}}\n name=\"damage\"\n color=\"primary\"\n />\n }\n label={damageCategories.filter(d => d !== 'None')[i]}\n />\n )}\n \n\n \n \n Select pages: 1-20 | 21-40 | 41-58\n \n \n\n \n }\n >Generate report\n window.print()}\n className={classes.button}\n variant=\"contained\"\n color=\"primary\"\n startIcon={}\n >Print\n \n \n \n \n\n {!loading ?\n <>\n \n \n \n \n \n \n \n \n \n \n \n }\n />\n \n \n \n \n \n \n \n \n \n \n \n }\n />\n \n \n \n \n \n \n \n \n \n \n \n }\n />\n \n \n \n \n \n \n \n \n \n \n \n }\n />\n \n \n \n \n \n \n \n \n \n \n \n }\n />\n \n :\n \n Generating report...\n \n }\n \n )\n}","import { FC, useState } from 'react'\nimport './App.css'\nimport { MsalAuthenticationTemplate, UnauthenticatedTemplate } from '@azure/msal-react'\nimport { InteractionType } from '@azure/msal-browser'\nimport { authLoading } from './AuthLoading'\nimport { authError } from './AuthError'\nimport { QueryClientProvider } from 'react-query'\nimport { Box } from '@material-ui/core'\nimport { Analyses } from 'src/components/Analyses'\nimport { Layout } from 'src/components/layout/Layout'\nimport {\n BrowserRouter as Router,\n Switch,\n Route,\n} from \"react-router-dom\";\nimport { Inspections } from 'src/components/Inspections'\nimport { Analysis } from 'src/components/Analysis'\nimport { Report } from 'src/components/report/Report'\nimport { paths } from 'src/datamodel/Constants'\nimport { useApp } from 'src/components/AppContextProvider'\n\nexport interface RouterParams {\n inspectionId?: string | undefined\n analysisId?: string | undefined\n}\n\nconst App: FC = () => {\n const [highlightId, setHighlightId] = useState(-1)\n const { queryClient } = useApp()\n\n return (\n <>\n \n \n \n \n \n \n \n setHighlightId(id)} />\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n Not logged in. Refresh page to try again.\n \n \n )\n}\n\nexport default App","const reportWebVitals = onPerfEntry => {\n if (onPerfEntry && onPerfEntry instanceof Function) {\n import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {\n getCLS(onPerfEntry)\n getFID(onPerfEntry)\n getFCP(onPerfEntry)\n getLCP(onPerfEntry)\n getTTFB(onPerfEntry)\n })\n }\n}\n\nexport default reportWebVitals\n","import { createMuiTheme, Theme } from '@material-ui/core/styles';\nimport blue from '@material-ui/core/colors/blue';\nimport teal from '@material-ui/core/colors/teal';\n\nexport const theme: Theme = createMuiTheme({\n palette: {\n primary: {\n main: blue[800]\n },\n secondary: {\n main: teal[600]\n },\n }\n})","import React from 'react'\nimport ReactDOM from 'react-dom'\nimport 'src/index.css'\nimport App from 'src/App'\nimport reportWebVitals from 'src/reportWebVitals'\nimport { AppContextProvider } from 'src/components/AppContextProvider'\nimport { msalConfig } from 'src/AuthConfig'\nimport { MsalProvider } from '@azure/msal-react'\nimport { PublicClientApplication } from '@azure/msal-browser'\nimport { ThemeProvider } from '@material-ui/core'\nimport { theme } from 'src/theme'\n\nReactDOM.render(\n \n \n \n \n \n \n \n \n ,\n document.getElementById('root')\n)\n\n// If you want to start measuring performance in your app, pass a function\n// to log results (for example: reportWebVitals(console.log))\n// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals\nreportWebVitals()\n"],"sourceRoot":""}