<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
    <title>QEC Playground</title>
    <link rel="icon" href="icon.svg">
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons" rel="stylesheet" type="text/css">
<link href="https://cdn.jsdelivr.net/npm/animate.css@^4.0.0/animate.min.css" rel="stylesheet" type="text/css">
<link href="https://cdn.jsdelivr.net/npm/quasar@2.6.6/dist/quasar.prod.css" rel="stylesheet" type="text/css">
<style>
body, html {
    margin: 0;
    overflow: hidden;
    height: 100%;
}
:root {
    --s: 1;  /* scale */
    --control-visibility: hidden;
}
.control-bar {
    position: fixed;
    width: calc(550px * var(--s));
    background-color: rgb(250, 250, 250);
    height: 100%;
    right: 0;
    overflow-y: hidden;
    overflow-x: hidden;
    visibility: var(--control-visibility);
}
.control-bar-inner {
    width: 550px;
    height: calc(100% / var(--s));
    transform: scale(var(--s));
    transform-origin: 0 0;
    font-size: 18px;
}
canvas {
    display: block;
}
.slider {
    margin-top: 0;
    margin-left: 35px;
    width: 480px;
}
.selector {
    margin-top: 20px;
    margin-left: 25px;
    width: 500px;
}
h1 {
    margin: 20px auto 0 auto;
    text-align: center;
    font-size: 40px;
    line-height: 40px;
}
h3 {
    margin: 0;
    font-size: 25px;
    line-height: 25px;
    font-weight: bold;
}
h5 {
    margin: 0;
    font-size: 20px;
    line-height: 20px;
    font-weight: bold;
}
.flex-center-div {
    width: 550px;
    margin-top: 10px;
    display: flex;
    justify-content: center;
    flex-direction: row;
}
.display-options-div {
    width: 550px;
    margin-top: 10px;
}
.display-options-row {
    width: 550px;
    margin-top: 0;
    display: flex;
    justify-content: center;
    flex-direction: row;
}
.display-options-row-left {
    width: 530px;
    margin-top: 0;
    margin-left: 20px;
    display: flex;
    justify-content: left;
    flex-direction: row;
}
.select-info-div-center {
    width: 530px;
    padding: 10px;
    margin: 10px;
    display: flex;
    justify-content: center;
    flex-direction: row;
}
.select-info-div {
    width: 530px;
    padding: 10px;
    margin: 10px;
}
.select-info-time {
    width: 190px;
    margin: 0 10px 0 10px;
}
.range-select {
    position: fixed;
    width: calc(50px * var(--s));
    background-color: rgb(250, 250, 250);
    height: 100%;
    right: calc(550px * var(--s));
    overflow-y: hidden;
    overflow-x: hidden;
    visibility: var(--control-visibility);
}
.range-select-inner {
    width: 50px;
    height: calc(100% / var(--s));
    transform: scale(var(--s));
    transform-origin: 0 0;
    font-size: 18px;
}
.range-select-qrange {
    height: 95%;
    margin-top: 30px;
}
.noise-model-row {
    width: 508px;
    margin-top: 0;
    display: flex;
    justify-content: center;
    flex-direction: row;
}
.noise-model-element {
    width: 120px;
    margin: 5px;
}
.noise-model-element-p {
    font-size: 80%;
}
.ref-position-btn {
    margin-left: 5px;
    margin-top: 2px;
    margin-bottom: 2px;
}
</style>
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/vue@3.2.33/dist/vue.global.prod.js"></script>
<script src="https://cdn.jsdelivr.net/npm/quasar@2.6.6/dist/quasar.umd.prod.js"></script>
<script id="MathJax-script" src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>


<div id="app">
<div class="control-bar">
    <q-scroll-area class="control-bar-inner" :vertical-thumb-style="vertical_thumb_style" :horizontal-thumb-style="horizontal_thumb_style"
            :vertical-bar-style="vertical_bar_style" :horizontal-bar-style="horizontal_bar_style">
        <div class="flex-center-div"><h1>QEC Playground</h1></div>
        <q-banner inline-actions class="text-white bg-yellow-10" v-if="!is_browser_supported" style="margin-top: 20px;">
            Please use Chrome or Firefox browser (It has known issue in Safari)
            <template v-slot:action>
                <q-btn flat color="white" label="Dismiss" @click="is_browser_supported = true" />
            </template>
        </q-banner>
        <q-banner inline-actions class="text-white bg-red" v-if="error_message != null" style="margin-top: 20px;">
            {{ error_message }}
        </q-banner>
        <q-banner inline-actions class="text-black bg-yellow" v-if="warning_message != null" style="margin-top: 20px;">
            {{ warning_message }}
        </q-banner>
        <div class="selector">
            <q-select filled v-model="case_select_label" :options="case_labels" options-dense behavior="menu" rounded>
                <template v-slot:selected v-if="case_select_label && active_case">
                    {{ case_select_label }} &nbsp;
                    <q-badge color="blue" v-if="get_idx_from_label(case_select_label) == 0">noise model</q-badge>
                    <q-badge color="red" v-else-if="active_case.qec_failed">logical error</q-badge>
                    <q-badge color="green" v-else>success</q-badge>
                    <span v-if="get_idx_from_label(case_select_label) > 0">&nbsp; {{ Object.keys(active_case.error_pattern).length }} physical errors</span>
                </template>
                <template v-slot:option="scope">
                    <q-item v-bind="scope.itemProps" v-if="scope.opt">
                        {{ scope.opt }} &nbsp;
                        <q-badge style="height: 20px;" color="blue" v-if="get_idx_from_label(scope.opt) == 0">noise model</q-badge>
                        <q-badge style="height: 20px;" color="red" v-else-if="get_case(get_idx_from_label(scope.opt)).qec_failed">logical error</q-badge>
                        <q-badge style="height: 20px;" color="green" v-else>success</q-badge>
                        <span v-if="get_idx_from_label(scope.opt) > 0">
                            &nbsp; {{ Object.keys(get_case(get_idx_from_label(scope.opt)).error_pattern).length }} physical errors
                        </span>
                    </q-item>
                </template>
                <template v-slot:before>
                    <q-btn round flat icon="arrow_circle_left" :disabled="case_select == 0" @click="case_select -= 1" size="xl"/>
                </template>
                <template v-slot:after>
                    <q-btn round flat icon="arrow_circle_right" :disabled="case_select == case_num-1" @click="case_select += 1" size="xl"/>
                </template>
            </q-select>
        </div>
        <div class="slider">
            <q-slider v-model="case_select" :min="0" :max="case_num-1" :step="1" snap
                thumb-size="25px" track-size="8px"></q-slider>
        </div>
        <div class="flex-center-div">
            <q-btn-toggle v-model="use_perspective_camera" no-caps rounded unelevated toggle-color="primary" color="white" text-color="primary"
                :options="[ { label: 'orthogonal', value: false }, { label: 'perspective', value: true } ]" size="lg"
            ></q-btn-toggle>
            <span style="margin: 0 15px 0 15px; line-height: 52px; font-size: 25px;">camera</span>
            <q-btn-dropdown color="warning" label="reset" no-caps size="lg" rounded>
                <q-list>
                    <q-item clickable v-close-popup @click="reset_camera('top')">
                        <q-item-section>
                        <q-item-label>from top</q-item-label>
                        </q-item-section>
                    </q-item>
                    <q-item clickable v-close-popup @click="reset_camera('front')">
                        <q-item-section>
                        <q-item-label>from front</q-item-label>
                        </q-item-section>
                        </q-item>
                    <q-item clickable v-close-popup @click="reset_camera('left')">
                        <q-item-section>
                        <q-item-label>from left</q-item-label>
                        </q-item-section>
                    </q-item>
                </q-list>
            </q-btn-dropdown>
        </div>
        <div class="flex-center-div">
            <div><q-toggle v-model="show_config" label="render configs" size="md"/></div>
            <div><q-toggle v-model="show_stats" label="performance stats" size="md"/></div>
            <div><q-toggle v-model="lock_view" label="lock view" size="md"/></div>
            <!-- <q-toggle v-model="show_hover_effect" label="hover effect" size="md"/> -->
        </div>
        <div class="flex-center-div">
            <span style="margin: 0 5px 0 5px; line-height: 40px; font-size: 20px;">export image:</span>
            <q-select rounded outlined v-model="export_scale_selected" :options="export_resolution_options" label="resolution" style="width: 200px;"
                emit-value behavior="menu" map-options dense></q-select>
            <q-btn push color="brown-5" rounded label="preview" style="margin-left: 10px;" no-caps @click="preview_image"></q-btn>
            <q-btn push color="brown-5" rounded label="download" style="margin-left: 10px;" no-caps @click="download_image"></q-btn>
        </div>
        <q-card bordered class="select-info-div-center" v-if="active_case && active_case.elapsed">
            <q-card-section class="bg-cyan text-white select-info-time">
                <div class="text-h6">{{ Number.parseFloat(active_case.elapsed.simulate).toExponential(3) }} (s)</div>
                <div class="text-subtitle2">Simulate Time</div>
            </q-card-section>
            <q-card-section class="bg-cyan text-white select-info-time">
                <div class="text-h6">{{ Number.parseFloat(active_case.elapsed.decode).toExponential(3) }} (s)</div>
                <div class="text-subtitle2">Decode Time</div>
            </q-card-section>
            <q-card-section class="bg-cyan text-white select-info-time">
                <div class="text-h6">{{ Number.parseFloat(active_case.elapsed.validate).toExponential(3) }} (s)</div>
                <div class="text-subtitle2">Validate Time</div>
            </q-card-section>
        </q-card>
        <div class="display-options-div">
            <div class="display-options-row">
                <div><q-toggle v-model="display_qubits" label="qubits" size="md"/></div>
                <div><q-toggle v-model="display_idle_sticks" label="idle sticks" size="md"/></div>
                <div><q-toggle v-model="display_gates" label="gates" size="md"/></div>
                <div><q-toggle v-model="display_measurements" label="measurements" size="md"/></div>
            </div>
            <div class="display-options-row-left" v-if="existed_noise_model">
                <span style="line-height: 42px;">Noise Model: </span>
                <div><q-toggle v-model="display_noise_model_pauli" label="Pauli errors" size="md" color="red"/></div>
                <div><q-toggle v-model="display_noise_model_erasure" label="erasure errors" size="md" color="purple"/></div>
            </div>
            <div class="display-options-row-left" v-if="existed_model_graph">
                <div><q-toggle left-label v-model="display_model_graph" label="Model Graph: " size="md"/></div>
                <div style="margin-top: 3px;">
                    <q-option-group v-model="model_graph_region_display" :options="model_graph_region_options"
                        color="green" type="toggle" inline left-label dense/>
                </div>
            </div>
            <div class="display-options-row-left" v-if="existed_model_hypergraph">
                <div><q-toggle left-label v-model="display_model_hypergraph" label="Model Hypergraph: " size="md"/></div>
            </div>
            <div class="display-options-row-left" v-if="case_select > 0">
                <span style="line-height: 42px;">Case [{{ case_select }}]: </span>
                <div><q-toggle v-model="display_error_pattern" label="actual error" size="md"/></div>
                <div><q-toggle v-model="display_correction" label="correction" size="md"/></div>
                <q-btn size="md" style="margin-left: 20px;" push no-caps color="white" text-color="primary"
                    :label="display_error_pattern ? '&nbsp;→ Correction&nbsp;' : '→ Actual Error'" @click="toggle_error_correction"></q-btn>
            </div>
        </div>
        <q-card bordered class="select-info-div" v-if="current_selected != null && current_selected.type == 'qubit'">
            <q-card-section class="bg-teal text-white">
                <div class="text-h6">{{ qubit_type_name(current_selected.qubit_type) }} Qubit 
                    at [...][{{ current_selected.i }}][{{ current_selected.j }}]</div>
            </q-card-section>
        </q-card>
        <q-card bordered class="select-info-div" v-if="current_selected != null && is_error_position(current_selected.type)">
            <q-card-section class="bg-teal text-white">
                <div class="text-h6">Noise Model at [{{ current_selected.t }}][{{ current_selected.i }}][{{ current_selected.j }}]
                    <span v-if="current_selected.gate_peer != null">, Gate Peer: {{ current_selected.gate_peer }}</span>
                </div>
            </q-card-section>
            <q-separator inset v-if="noise_model_info != null"></q-separator>
            <q-card-section v-if="noise_model_info != null" style="padding: 0;">
                <div class="noise-model-row">
                    <span style="line-height: 30px; position: relative; top: 5px; width: 50px;">Pauli: </span>
                    <div class="noise-model-element" :style="{ color: noise_model_info.pp.px > 2e-300 ? non_zero_color : zero_color }">\( p_{\small X}\): 
                        <span class="noise-model-element-p">{{ Number.parseFloat(noise_model_info.pp.px).toExponential(2) }}</span></div>
                    <div class="noise-model-element" :style="{ color: noise_model_info.pp.py > 2e-300 ? non_zero_color : zero_color }">\( p_{\small Y}\): 
                        <span class="noise-model-element-p">{{ Number.parseFloat(noise_model_info.pp.py).toExponential(2) }}</span></div>
                    <div class="noise-model-element" :style="{ color: noise_model_info.pp.pz > 2e-300 ? non_zero_color : zero_color }">\( p_{\small Z}\): 
                        <span class="noise-model-element-p">{{ Number.parseFloat(noise_model_info.pp.pz).toExponential(2) }}</span></div>
                </div>
                <div class="noise-model-row">
                    <span style="line-height: 30px; position: relative; top: 5px; width: 70px;">Erasure: </span>
                    <div class="noise-model-element" :style="{ color: noise_model_info.pe > 2e-300 ? non_zero_color : zero_color }">\( p_{\small E}\): 
                        <span class="noise-model-element-p">{{ Number.parseFloat(noise_model_info.pe).toExponential(2) }}</span></div>
                    <div class="noise-model-element" :style="{ width: '220px', 'margin-left': '56px', color: noise_model_info.pp.sum > 6e-300 ? non_zero_color : zero_color }">\( p_{\small X} {\small+} p_{\small Y} {\small+} p_{\small Z} \):
                        <span class="noise-model-element-p">{{ Number.parseFloat(noise_model_info.pp.sum).toExponential(2) }}</span></div>
                </div>
                <div class="noise-model-row" v-if="noise_model_info.corr_pe != null" style="border: 1px dashed grey;">
                    <div class="noise-model-element" :style="{ color: noise_model_info.corr_pe.sum > 2e-300 ? non_zero_color : zero_color, 'background-color': 'lightgrey' }">\( \sum p_{\small ee}\): 
                        <span class="noise-model-element-p">{{ Number.parseFloat(noise_model_info.corr_pe.sum).toExponential(2) }}</div>
                    <div class="noise-model-element" :style="{ color: noise_model_info.corr_pe.pie > 2e-300 ? non_zero_color : zero_color }">\( p_{\small I\otimes E}\): 
                        <span class="noise-model-element-p">{{ Number.parseFloat(noise_model_info.corr_pe.pie).toExponential(2) }}</div>
                    <div class="noise-model-element" :style="{ color: noise_model_info.corr_pe.pei > 2e-300 ? non_zero_color : zero_color }">\( p_{\small E\otimes I}\): 
                        <span class="noise-model-element-p">{{ Number.parseFloat(noise_model_info.corr_pe.pei).toExponential(2) }}</div>
                    <div class="noise-model-element" :style="{ color: noise_model_info.corr_pe.pee > 2e-300 ? non_zero_color : zero_color }">\( p_{\small E\otimes E}\): 
                        <span class="noise-model-element-p">{{ Number.parseFloat(noise_model_info.corr_pe.pee).toExponential(2) }}</div>
                </div>
                <div v-if="noise_model_info.corr_pp != null" style="border: 1px dashed grey;">
                    <div class="noise-model-row">
                        <div class="noise-model-element" :style="{ color: noise_model_info.corr_pp.sum > 30e-300 ? non_zero_color : zero_color, 'background-color': 'lightgrey' }">\( \sum p_{\small pp}\): 
                            <span class="noise-model-element-p">{{ Number.parseFloat(noise_model_info.corr_pp.sum).toExponential(2) }}</div>
                        <div class="noise-model-element" :style="{ color: noise_model_info.corr_pp.pix > 30e-300 ? non_zero_color : zero_color }">\( p_{\small I\otimes X}\): 
                            <span class="noise-model-element-p">{{ Number.parseFloat(noise_model_info.corr_pp.pix).toExponential(2) }}</div>
                        <div class="noise-model-element" :style="{ color: noise_model_info.corr_pp.piy > 30e-300 ? non_zero_color : zero_color }">\( p_{\small I\otimes Y}\): 
                            <span class="noise-model-element-p">{{ Number.parseFloat(noise_model_info.corr_pp.piy).toExponential(2) }}</div>
                        <div class="noise-model-element" :style="{ color: noise_model_info.corr_pp.piz > 30e-300 ? non_zero_color : zero_color }">\( p_{\small I\otimes Z}\): 
                            <span class="noise-model-element-p">{{ Number.parseFloat(noise_model_info.corr_pp.piz).toExponential(2) }}</div>
                    </div>
                    <div class="noise-model-row">
                        <div class="noise-model-element" :style="{ color: noise_model_info.corr_pp.pxi > 30e-300 ? non_zero_color : zero_color }">\( p_{\small X\otimes I}\): 
                            <span class="noise-model-element-p">{{ Number.parseFloat(noise_model_info.corr_pp.pxi).toExponential(2) }}</div>
                        <div class="noise-model-element" :style="{ color: noise_model_info.corr_pp.pxx > 30e-300 ? non_zero_color : zero_color }">\( p_{\small X\otimes X}\): 
                            <span class="noise-model-element-p">{{ Number.parseFloat(noise_model_info.corr_pp.pxx).toExponential(2) }}</div>
                        <div class="noise-model-element" :style="{ color: noise_model_info.corr_pp.pxy > 30e-300 ? non_zero_color : zero_color }">\( p_{\small X\otimes Y}\): 
                            <span class="noise-model-element-p">{{ Number.parseFloat(noise_model_info.corr_pp.pxy).toExponential(2) }}</div>
                        <div class="noise-model-element" :style="{ color: noise_model_info.corr_pp.pxz > 30e-300 ? non_zero_color : zero_color }">\( p_{\small X\otimes Z}\): 
                            <span class="noise-model-element-p">{{ Number.parseFloat(noise_model_info.corr_pp.pxz).toExponential(2) }}</div>
                    </div>
                    <div class="noise-model-row">
                        <div class="noise-model-element" :style="{ color: noise_model_info.corr_pp.pyi > 30e-300 ? non_zero_color : zero_color }">\( p_{\small Y\otimes I}\): 
                            <span class="noise-model-element-p">{{ Number.parseFloat(noise_model_info.corr_pp.pyi).toExponential(2) }}</div>
                        <div class="noise-model-element" :style="{ color: noise_model_info.corr_pp.pyx > 30e-300 ? non_zero_color : zero_color }">\( p_{\small Y\otimes X}\): 
                            <span class="noise-model-element-p">{{ Number.parseFloat(noise_model_info.corr_pp.pyx).toExponential(2) }}</div>
                        <div class="noise-model-element" :style="{ color: noise_model_info.corr_pp.pyy > 30e-300 ? non_zero_color : zero_color }">\( p_{\small Y\otimes Y}\): 
                            <span class="noise-model-element-p">{{ Number.parseFloat(noise_model_info.corr_pp.pyy).toExponential(2) }}</div>
                        <div class="noise-model-element" :style="{ color: noise_model_info.corr_pp.pyz > 30e-300 ? non_zero_color : zero_color }">\( p_{\small Y\otimes Z}\): 
                            <span class="noise-model-element-p">{{ Number.parseFloat(noise_model_info.corr_pp.pyz).toExponential(2) }}</div>
                    </div>
                    <div class="noise-model-row">
                        <div class="noise-model-element" :style="{ color: noise_model_info.corr_pp.pzi > 30e-300 ? non_zero_color : zero_color }">\( p_{\small Z\otimes I}\): 
                            <span class="noise-model-element-p">{{ Number.parseFloat(noise_model_info.corr_pp.pzi).toExponential(2) }}</div>
                        <div class="noise-model-element" :style="{ color: noise_model_info.corr_pp.pzx > 30e-300 ? non_zero_color : zero_color }">\( p_{\small Z\otimes X}\): 
                            <span class="noise-model-element-p">{{ Number.parseFloat(noise_model_info.corr_pp.pzx).toExponential(2) }}</div>
                        <div class="noise-model-element" :style="{ color: noise_model_info.corr_pp.pzy > 30e-300 ? non_zero_color : zero_color }">\( p_{\small Z\otimes Y}\): 
                            <span class="noise-model-element-p">{{ Number.parseFloat(noise_model_info.corr_pp.pzy).toExponential(2) }}</div>
                        <div class="noise-model-element" :style="{ color: noise_model_info.corr_pp.pzz > 30e-300 ? non_zero_color : zero_color }">\( p_{\small Z\otimes Z}\): 
                            <span class="noise-model-element-p">{{ Number.parseFloat(noise_model_info.corr_pp.pzz).toExponential(2) }}</div>
                    </div>
                </div>
                <div v-if="noise_model_info.additional.length > 0" style="margin-top: 10px;">
                    <h5>Other Contributing Noise:</h5>
                    <div v-for="(ad, index) in noise_model_info.additional" style="margin-top: 5px;">
                        <span>> </span>
                        <span v-if="ad.source == 'corr_pp'">two-qubit Pauli from 
                            <q-btn class="ref-position-btn" size="md" dense :label="`[${ad.t}][${ad.i}][${ad.j}]`" color="red" glossy @mouseover="ref_btn_hover(`[${ad.t}][${ad.i}][${ad.j}]`)" @mouseleave="ref_btn_leave()" @click="ref_btn_click(`[${ad.t}][${ad.i}][${ad.j}]`)"/>
                        </span>
                        <span v-if="ad.source == 'corr_pe'">two-qubit erasure from 
                            <q-btn class="ref-position-btn" size="md" dense :label="`[${ad.t}][${ad.i}][${ad.j}]`" color="purple" glossy @mouseover="ref_btn_hover(`[${ad.t}][${ad.i}][${ad.j}]`)" @mouseleave="ref_btn_leave()" @click="ref_btn_click(`[${ad.t}][${ad.i}][${ad.j}]`)"></q-btn>
                        </span>
                        <span v-if="ad.source == 'add_p' || ad.source == 'add_e'">{{ ad.source == 'add_p' ? "Pauli": "erasure" }} from additional noise [{{ ad.add_idx }}], probability: <span :style="{ color: non_zero_color }">{{ Number.parseFloat(ad.noise.p).toExponential(2) }}</span>
                            <span v-if="Object.entries(ad.noise.pe).length > 0">
                                <br/><span style="margin-left: 20px;">Pauli: </span>
                                <q-btn v-for="(error, pos_str) in ad.noise.pe" class="ref-position-btn" size="md" dense :label="pos_str + ':' + error.toUpperCase()" color="red" glossy @mouseover="ref_btn_hover(pos_str)" @mouseleave="ref_btn_leave()" @click="ref_btn_click(pos_str)"></q-btn>
                            </span>
                            <span v-if="ad.noise.ee.length > 0">
                                <br/><span style="margin-left: 20px;">erasures: </span>
                                <q-btn v-for="pos_str in ad.noise.ee" class="ref-position-btn" size="md" dense :label="pos_str" color="purple" glossy @mouseover="ref_btn_hover(pos_str)" @mouseleave="ref_btn_leave()" @click="ref_btn_click(pos_str)"></q-btn>
                            </span>
                        </span>
                    </div>
                </div>
            </q-card-section>
        </q-card>
        <q-card bordered class="select-info-div" v-if="current_selected != null && current_selected.type == 'model_hypergraph_vertex'">
            <q-card-section class="bg-green text-white">
                <div class="text-h6">Vertex {{ current_selected.vertex_index }} at {{ selected_hypergraph_info.vertex_position }}</div>
            </q-card-section>
            <q-separator inset></q-separator>
            <q-card-section>
                <div v-for="edge of selected_hypergraph_info.neighbor_edges" style="margin-top: 15px;">
                    <q-btn color="teal" no-caps size="12px" rounded padding="none md" @mouseenter="ref_btn_hover_general('model_hypergraph_edge', { edge_index: edge.edge_index })" 
                            @mouseleave="ref_btn_leave()" @click="jump_to('model_hypergraph_edge', { edge_index: edge.edge_index })">
                        <div class="text-center">
                            Edge</span><br>{{ edge.edge_index }}
                        </div>
                    </q-btn>
                    &nbsp;&nbsp;p: {{ Number.parseFloat(edge.probability).toExponential(2) }},
                    <span class="bg-green-2" style="padding: 14px 5px; border-radius: 5px; line-height: 45px;">V = 
                        [<q-btn color="green" no-caps unelevated v-for="vertex of edge.defect_vertices" style="margin-left: 5px; position: relative; bottom: 2px;"
                            padding="2px 4px" size="12px" @mouseenter="ref_btn_hover_general('model_hypergraph_vertex', { vertex_index: vertex.vertex_index })" 
                            @mouseleave="ref_btn_leave()"
                            @click="jump_to('model_hypergraph_vertex', { vertex_index: vertex.vertex_index })">Vid: {{ vertex.vertex_index }}<br>{{ vertex.position_str }}</q-btn>
                    ]</span>
                </div>
            </q-card-section>
        </q-card>
        <q-card bordered class="select-info-div" v-if="current_selected != null && current_selected.type == 'model_hypergraph_edge'">
            <q-card-section class="bg-teal text-white">
                <div class="text-h6">Edge {{ current_selected.edge_index }}</div>
            </q-card-section>
            <q-separator inset></q-separator>
            <q-card-section>
                <div>
                    p: {{ Number.parseFloat(selected_hypergraph_info.probability).toExponential(2) }},
                    <span class="bg-green-2" style="padding: 14px 5px; border-radius: 5px; line-height: 45px;">V = 
                        [<q-btn color="green" no-caps unelevated v-for="vertex of selected_hypergraph_info.defect_vertices" style="margin-left: 5px; position: relative; bottom: 2px;"
                            padding="2px 4px" size="12px" @mouseenter="ref_btn_hover_general('model_hypergraph_vertex', { vertex_index: vertex.vertex_index })" 
                            @mouseleave="ref_btn_leave()"
                            @click="jump_to('model_hypergraph_vertex', { vertex_index: vertex.vertex_index })">Vid: {{ vertex.vertex_index }}<br>{{ vertex.position_str }}</q-btn>
                    ]</span>
                </div>
                <div class="text-h6">Contributing Independent Errors:</div>
                <div v-for="hyperedge of selected_hypergraph_info.all_hyperedges" style="margin-top: 15px;">
                    p: {{ Number.parseFloat(hyperedge.probability).toExponential(2) }},
                    <span class="bg-red-2" style="padding: 14px 5px; border-radius: 5px; line-height: 45px;">Error = 
                        [<q-btn color="red" no-caps unelevated v-for="error of hyperedge.error_pattern" style="margin-left: 5px; position: relative; bottom: 2px;"
                            padding="2px 4px" size="12px"
                            @mouseover="ref_btn_hover(error.position_str)" @mouseleave="ref_btn_leave()" @click="ref_btn_click(error.position_str)"
                            >{{ error.position_str }}<br>{{ error.type }}</q-btn>
                    ]</span>,
                    <span class="bg-orange-2" style="padding: 14px 5px; border-radius: 5px; line-height: 45px;">Correction = 
                        [<q-btn color="orange" no-caps unelevated v-for="correction of hyperedge.correction" style="margin-left: 5px; position: relative; bottom: 2px;"
                            padding="2px 4px" size="12px"
                            @mouseover="ref_btn_hover(correction.position_str)" @mouseleave="ref_btn_leave()" @click="ref_btn_click(correction.position_str)"
                            >{{ correction.position_str }}<br>{{ correction.type }}</q-btn>
                    ]</span>,
                </div>
            </q-card-section>
        </q-card>
        <q-card bordered class="select-info-div" v-if="current_selected != null && current_selected.type == 'model_graph_vertex'">
            <q-card-section class="bg-green text-white">
                <div class="text-h6">Vertex [{{ current_selected.t }}][{{ current_selected.i }}][{{ current_selected.j }}] (region {{ current_selected.region_idx }})</div>
            </q-card-section>
            <q-separator inset></q-separator>
            <q-card-section>
                <div v-for="(edge, peer_position_str) of selected_model_graph_info.edges" style="margin-top: 5px;">
                    <q-btn color="teal" no-caps size="12px" rounded padding="none md" @mouseenter="ref_btn_hover_general('model_graph_edge', edge.userData)" 
                            @mouseleave="ref_btn_leave()" @click="jump_to('model_graph_edge', edge.userData)">
                        <div class="text-center">
                            Edge</span><br>{{ peer_position_str }}
                        </div>
                    </q-btn>
                    <div class="text-center" style="display: inline-block; font-size: 15px; position: relative; top: 10px; margin-left: 10px;">
                        probability: {{ Number.parseFloat(edge.p).toExponential(3) }}<br>weight: {{ Number.parseFloat(edge.w).toExponential(3) }}
                    </div>,
                    <div style="display: inline-block; font-size: 15px; position: relative; top: 10px; margin-left: 10px;">
                        error pattern: <span v-for="(error_type, position_str) of edge.e" @mouseover="ref_btn_hover(position_str)" @mouseleave="ref_btn_leave()" @click="ref_btn_click(position_str)">
                            {{ error_type }}({{ position_str }})
                        </span><br>correction: <span v-for="(error_type, position_str) of edge.c" @mouseover="ref_btn_hover(position_str)" @mouseleave="ref_btn_leave()" @click="ref_btn_click(position_str)">
                            {{ error_type }}({{ position_str }})
                        </span>
                    </div>
                </div>
                <div style="margin-top: 5px;" v-if="selected_model_graph_info.boundary != null">
                    <q-btn color="teal-9" no-caps size="12px" rounded padding="none md">
                        <div class="text-center">
                            Boundary
                        </div>
                    </q-btn>
                    <div class="text-center" style="display: inline-block; font-size: 15px; position: relative; top: 10px; margin-left: 10px;">
                        probability: {{ Number.parseFloat(selected_model_graph_info.boundary.p).toExponential(3) }}<br>
                        weight: {{ Number.parseFloat(selected_model_graph_info.boundary.w).toExponential(3) }}
                    </div>,
                    <div style="display: inline-block; font-size: 15px; position: relative; top: 10px; margin-left: 10px;">
                        error pattern: <span v-for="(error_type, position_str) of selected_model_graph_info.boundary.e" @mouseover="ref_btn_hover(position_str)" @mouseleave="ref_btn_leave()" @click="ref_btn_click(position_str)">
                            {{ error_type }}({{ position_str }})
                        </span><br>correction: <span v-for="(error_type, position_str) of selected_model_graph_info.boundary.c" @mouseover="ref_btn_hover(position_str)" @mouseleave="ref_btn_leave()" @click="ref_btn_click(position_str)">
                            {{ error_type }}({{ position_str }})
                        </span>
                    </div>
                </div>
            </q-card-section>
        </q-card>
    </q-scroll-area>
</div>
<div class="range-select">
    <div class="range-select-inner">
        <q-range class="range-select-qrange" v-model="t_range" :min="0" :max="t_length" vertical label snap label-always dense markers color="teal-4"
            track-size="8px" style="margin-left: 37px;" switch-label-side thumb-size="30px" drag-range reverse/>
    </div>
</div>
</div>

<script type="importmap">
{
    "imports": {
        "three": "https://cdn.jsdelivr.net/npm/three@0.139.2/build/three.module.js",
        "./node_modules/three/examples/jsm/controls/OrbitControls.js": "https://cdn.jsdelivr.net/npm/three@0.139.2/examples/jsm/controls/OrbitControls.js",
        "./node_modules/three/examples/jsm/geometries/ConvexGeometry.js": "https://cdn.jsdelivr.net/npm/three@0.139.2/examples/jsm/geometries/ConvexGeometry.js",
        "./node_modules/three/examples/jsm/libs/stats.module.js": "https://cdn.jsdelivr.net/npm/three@0.139.2/examples/jsm/libs/stats.module.js",
        "./node_modules/three/examples/jsm/libs/lil-gui.module.min.js": "https://cdn.jsdelivr.net/npm/three@0.139.2/examples/jsm/libs/lil-gui.module.min.js"
    }
}
</script>
<script src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script>

<script type="module" src="./index.js"></script>
<!-- <script>
// always fetch the latest script and avoid caching
var index_script = document.createElement('script');
index_script.setAttribute('src','./index.js?v=' + Math.random());
index_script.setAttribute('type','module');
document.body.appendChild(index_script);
</script> -->

</body>
</html>
