<template>
    <div class="app-container simulation-report-desc" v-loading="loading">
        <div style="background-color: #fff;padding:20px;margin-bottom: 60px;" id="print_simulation_report_desc">
            <div class="report-name">{{ info.report.report_name }}</div>
            <div class="report-info">
                <el-row>
                    <el-col :span="12">
                        报告生成时间:{{ info.report.create_time }}
                    </el-col>
                    <el-col :span="12" style="text-align: right;" v-if="info.report.user_name">
                        报告创建人:{{ info.report.user_name }}
                    </el-col>
                </el-row>
                <div v-if="info.report.report_desc">
                    {{ info.report.report_desc }}
                </div>
            </div>

            <div class="div-line"></div>
            <div class="sub-title">推理任务列表</div>
            <el-table :data="info.taskList" stripe style="margin-top:10px;">
                <el-table-column label="任务名称" align="left" prop="task_name" />
                <el-table-column label="模型名称" align="left" prop="model_name" />
                <el-table-column label="网络类型" align="left" prop="modl_sub_type" />
                <el-table-column label="互联名称" align="left" prop="connection_name" />
                <el-table-column label="数据集名称" align="left" prop="dataset_name" />
                <el-table-column label="图片数量" align="left" prop="image_count" />
                <el-table-column label="设备名称" align="left" prop="device_name" />
                <el-table-column label="设备处理器" align="left" prop="hardware_chip" />
            </el-table>
            <template v-if="info.reportType == 'other'">
                <div class="task-lists" v-if="info.tasks && info.tasks.length > 0">
                    <div v-for="(it, idx) in info.tasks" :key="idx">
                        <div class="sub-title">{{ it.taskName|| info.report.report_name }}的测试报告</div>
                        <template v-if="info.reportType == 'other'">
                            <div v-if="info.thresholds" class="info-thresholds">
                                <span>置信度阈值：</span>
                                <span>{{ info.thresholds.score_threshold }}</span>
                                <span style="margin-left:10px;">nms阈值:</span>
                                <span>{{ info.thresholds.nms_threshold }}</span>
                            </div>

                            <el-table :data="it.classes" stripe style="margin-top:10px;">
                                <el-table-column label="类别名称" align="left" prop="class_name" />
                                <el-table-column label="Precision(精确度)" align="left" prop="precision" />
                                <el-table-column label="Recall(召回率)" align="left" prop="recall" />
                                <el-table-column label="F1-score" align="left" prop="f1_score" />
                                <el-table-column label="AP" align="left" prop="ap" />
                            </el-table>

                            <el-table :data="it.datas" stripe style="margin-top:20px;">
                                <el-table-column label="mAP" align="left" prop="map" />
                                <el-table-column label="Micro F1" align="left" prop="micro_f1" />
                                <el-table-column label="Macro F1" align="left" prop="macro_f1" />
                                <el-table-column label="加权F1-Scroe" align="left" prop="weight_f1" />
                                <el-table-column label="平均推理时间" align="left" prop="inference_time" />
                                <el-table-column label="系统延迟时间" align="left" prop="system_delay" />
                            </el-table>
                            <div class="print-page" v-if="false"></div>
                            <el-row class="report-chart1" style="margin-top:20px;" :key="info.elPrint"  v-if="false"
                                :style="info.isPrint ? 'width:18cm;' : ''">
                                <el-col :span="info.isPrint || it.classes.length > 20 ? 24 : 24">
                                    <charts :id="'reportChart2-' + idx" width="100%" :height="calcChartHeight(it)"
                                        :render="opt => renderChart1(it, 'rp')"></charts>
                                </el-col>
                            </el-row>
                        </template>
                        <template v-else>
                            <el-table :data="it.targets" stripe style="margin-top:10px;">
                                <el-table-column label="目标序号" align="left" prop="index" />
                                <el-table-column label="IDSW" align="left" prop="idsw" />
                                <el-table-column label="TM(跟踪轨迹)" align="left" prop="mt" />
                                <el-table-column label="ML(丢失轨迹)" align="left" prop="ml" />
                                <el-table-column label="FM(打断次数)" align="left" prop="fm" />
                            </el-table>
                            <div class="info-thresholds" style="margin-top: 10px;line-height: 24px;">
                                <div> <span>MOTA（跟踪准确度）</span>
                                    <span>{{ it.mota }}</span>
                                </div>
                                <div> <span>平均推理时间:</span>
                                    <span>{{ it.inference_time }}ms</span>
                                </div>
                                <div><span>系统延迟时间:</span>
                                    <span>{{ it.system_delay }}ms</span>
                                </div>
                            </div>
                        </template>
                    </div>
                </div>

                <template v-if="info.robustness && info.robustness.length > 0">
                    <div class="div-line"></div>
                    <div class="sub-title">推理结果比对报告</div>
                    <el-table :data="info.robustness" stripe style="margin-top:10px;">
                        <el-table-column type="index" width="80" label="序号" />
                        <el-table-column label="模型名称" align="left" prop="model_name" />
                        <el-table-column label="数据集名称" align="left" prop="database_name" />
                        <el-table-column label="Micro F1" align="left" prop="micro_f1" />
                        <el-table-column label="Macro F1" align="left" prop="macro_f1" />
                        <el-table-column label="加权F1-Score" align="left" prop="weight_f1" />
                        <el-table-column label="mAP" align="left" prop="map" />
                        <el-table-column label="平均推理时间" align="left" prop="inference_time" />
                        <el-table-column label="mAP变化率" align="left">
                            <template #default="scope">
                                {{ scope.$index == 0 ? '----' : info.robustnessMapDecrease + '%' }}
                            </template>
                        </el-table-column>
                    </el-table>
                    <div style="margin-top:20px;">
                        <charts id="reportChart3-robustness" width="100%" height="400px" :render="renderChar3">
                        </charts>
                    </div>
                </template>
                <template v-if="info.horizontal_comparison && info.horizontal_comparison.length > 0">
                    <div class="div-line"></div>
                    <div class="sub-title">硬件横向对比测试报告</div>
                    <el-table :data="info.horizontal_comparison" stripe style="margin-top:10px;">
                        <el-table-column type="index" width="80" label="序号" />
                        <el-table-column label="设备名称" align="left" prop="device_name" />
                        <el-table-column label="设备处理器" align="left" prop="device_cpu" />
                        <el-table-column label="Micro F1" align="left" prop="micro_f1" />
                        <el-table-column label="Macro F1" align="left" prop="macro_f1" />
                        <el-table-column label="加权F1-Score" align="left" prop="weight_f1" />
                        <el-table-column label="mAP" align="left" prop="mAP" />
                        <el-table-column label="平均推理时间" align="left" prop="inference_time" />
                        <el-table-column label="系统延迟时间" align="left" prop="system_delay" />
                        <el-table-column label="mAP变化率" align="left">
                            <template #default="scope">
                                {{ scope.row.map_ratio + "%" }}
                            </template>
                        </el-table-column>
                    </el-table>
                    <div style="margin-top:20px;">
                        <charts id="reportChart3-comparison" width="100%" height="400px" :render="renderChar4">
                        </charts>
                    </div>
                </template>
            </template>
            <template v-else>
                <div v-for="(it, idx) in info.tasks" :key="idx">
                    <div class="div-line"></div>
                    <div class="sub-title">{{ info.report.report_name }}的测试报告</div>
                    <el-table :data="[it]" stripe style="margin-top:10px;">
                        <el-table-column label="IDSW" align="left" prop="idsw" />
                        <el-table-column label="MT（跟踪轨迹）" align="left" prop="mt" />
                        <el-table-column label="ML（丢失轨迹）" align="left" prop="ml" />
                        <el-table-column label="FM（打断次数）" align="left" prop="fm" />
                        <el-table-column label="MOTA" align="left" prop="mota" />
                        <el-table-column label="平均推理时间" align="left" prop="inference_time" />
                        <el-table-column label="系统延迟时间" align="left" prop="system_delay" />
                    </el-table>
                </div>

                <template v-if="info.robustness && info.robustness.length > 0">
                    <div class="div-line"></div>
                    <div class="sub-title">推理结果比对报告</div>
                    <el-table :data="info.robustness" stripe style="margin-top:10px;">
                        <el-table-column type="index" width="80" label="序号" />
                        <el-table-column label="模型名称" align="left" prop="model_name" />
                        <el-table-column label="数据集名称" align="left" prop="database_name" />
                        <el-table-column label="IDSW" align="left" prop="idsw" />
                        <el-table-column label="MT（跟踪轨迹）" align="left" prop="mt" />
                        <el-table-column label="ML（丢失轨迹）" align="left" prop="ml" />
                        <el-table-column label="FM（打断次数）" align="left" prop="fm" />
                        <el-table-column label="MOTA" align="left" prop="mota" />
                        <el-table-column label="mAP变化率" align="left">
                            <template #default="scope">
                                {{ scope.$index == 0 ? '----' : info.robustnessMapDecrease + '%' }}
                            </template>
                        </el-table-column>
                    </el-table>
                    <div style="margin-top:20px;">
                        <charts id="reportChart3-robustness" width="100%" height="400px" :render="renderChar3">
                        </charts>
                    </div>
                </template>

                <template v-if="info.horizontal_comparison && info.horizontal_comparison.length > 0">
                    <div class="div-line"></div>
                    <div class="sub-title">硬件横向对比测试报告</div>
                    <el-table :data="info.horizontal_comparison" stripe style="margin-top:10px;">
                        <el-table-column type="index" width="80" label="序号" />
                        <el-table-column label="设备名称" align="left" prop="device_name" />
                        <el-table-column label="设备处理器" align="left" prop="device_cpu" />
                        <el-table-column label="IDSW" align="left" prop="idsw" />
                        <el-table-column label="MT（跟踪轨迹）" align="left" prop="mt" />
                        <el-table-column label="ML（丢失轨迹）" align="left" prop="ml" />
                        <el-table-column label="FM（打断次数）" align="left" prop="fm" />
                        <el-table-column label="MOTA" align="left" prop="mota" />
                        <el-table-column label="平均推理时间" align="left" prop="inference_time" />
                        <el-table-column label="系统延迟时间" align="left" prop="system_delay" />
                        <el-table-column label="mAP变化率" align="left">
                            <template #default="scope">
                                {{ scope.row.mota_ratio + "%" }}
                            </template>
                        </el-table-column>
                    </el-table>
                    <div style="margin-top:20px;">
                        <charts id="reportChart3-comparison" width="100%" height="400px" :render="renderChar4">
                        </charts>
                    </div>
                </template>

            </template>
        </div>

        <el-card class="card-footer">
            <el-button type="primary" @click="doPrint">打印</el-button>
            <el-button type="primary" @click="doExport">导出</el-button>
            <el-button type="primary" @click="doDelete">删除</el-button>
            <el-button @click="goBack">返回</el-button>
        </el-card>
    </div>
</template>

<script setup>
import ReportApi from '@/api/report'
import charts from './components/charts.vue'
import html2canvas from 'html2canvas';
import { useDateFormat } from "@vueuse/core";
const route = useRoute()
const router = useRouter();
const info = reactive({
    report: {},
    taskList: [],
    thresholds: null,
    extra_evaluation_type: '',
    tasks: [],
    reportType: '',
    robustness: [],
    robustnessMapDecrease: '',
    horizontal_comparison: [],
    isPrint: false,
    elPrint: 0,
})
const loading = ref(false)
const calcChartHeight = it => {
    let tmp = it.classes.length <= 20 ? '400px' : ((it.classes.length / 10 - 2) * 40 + 400 + 'px');
    if (info.isPrint) {
        tmp = it.classes.length <= 20 ? '400px' : ((it.classes.length / 5 - 2) * 30 + 400 + 'px');
    }
    return tmp;
}
const doExport = async () => {
    try {
        let dom = document.querySelector("#print_simulation_report_desc");
        const canvas = await html2canvas(dom, {
            allowTaint: true,
            useCORS: true,
        });
        const img = canvas.toDataURL('image/png');
        const link = document.createElement('a');
        link.href = img;
        link.setAttribute('download', info.report.report_name + useDateFormat(new Date(), "YYYYMMDDHHmmss").value + '.png');
        link.click();
    } catch (e) {
        ElMessage.error("导出图片失败!");
        console.error("导出图片失败!", e);
    }
}
function goBack() {
    router.push({ path: "/simulationEvaluation/reportList" });
}
function doPrint() {
    document.querySelector("html").classList.add("report-print");
    info.isPrint = true;
    info.elPrint++;
    loading.value = true;
    setTimeout(() => {
        loading.value = false;
        setTimeout(() => {
            window.print();
            document.querySelector("html").classList.remove("report-print");
            info.isPrint = false;
            info.elPrint++;
        }, 100);
    }, 2000);
}

const doDelete = () => {
    let id = route.query.id;
    ElMessageBox.confirm("确认删除?", "警告", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
    }).then(function () {
        ReportApi.deleteReport(id).then(d => {
            if (d.data.code == 0) {
                ElMessage.success("删除成功!");
                goBack();
            } else {
                ElMessage.error("删除失败!");
            }
        });

    });
}
//硬件横向对比测试图
function renderChar4() {
    let datas = info.horizontal_comparison;
    let maxTime1 = 0;
    let maxTime2 = 0;
    let micro_f1 = 1;
    let maxIdsw=0;
    let maxFm=0;
    let seriesData = [];    
    datas.forEach((d, idx) => {
        if (d.inference_time > maxTime1) {
            maxTime1 = d.inference_time;
        }
        if (d.system_delay > maxTime2) {
            maxTime2 = d.system_delay;
        }
        if (d.micro_f1 > micro_f1) {
            micro_f1 = d.micro_f1;
        }
        if (d.idsw > maxIdsw) {
            maxIdsw = d.idsw;
        }
        if (d.fm > maxFm) {
            maxFm = d.fm;
        }
        if (info.reportType != 'tracking') {
            seriesData.push({
                name: idx + 1 + "-" + d.device_name,
                value: [d.micro_f1, d.macro_f1, d.weight_f1, d.mAP, d.inference_time, d.system_delay]
            }) 
        }else{
            seriesData.push({
                name: idx + 1 + "-" + d.device_name,
                value: [d.idsw, d.mt, d.ml, d.fm,d.mota, d.inference_time, d.system_delay]
            })
        }
    });
    let indicators = [
        { text: 'Micro F1', max: micro_f1 },
        { text: 'Macro F1', max: 1 },
        { text: '加权F1-Score', max: 1 },
        { text: 'mAP', max: 1 },
        { text: '平均推理时间', max: maxTime1 },
        { text: '系统延迟时间', max: maxTime2 }
    ];
    if (info.reportType == 'tracking') {
        indicators = [
        { text: 'IDSW', max: maxIdsw },
            { text: 'MT（跟踪轨迹）', max: 1 },
            { text: 'ML（丢失轨迹）', max: 1 },
            { text: 'FM（打断次数）', max: maxFm },
            { text: 'MOTA', max: 1 },
            { text: '平均推理时间', max: maxTime1 },
            { text: '系统延迟时间', max: maxTime2 }
        ];
    }
    let opt = {
        title: {
            text: '硬件横向对比测试图'
        },
        legend: {
            x: 'left',
            top: 40,
            orient: 'vertical',
            data: datas.map((d, idx) => idx + 1 + "-" + d.device_name)
        },
        tooltip: {
            trigger: 'axis'
        },
        calculable: true,
        radar: {
            indicator: indicators,
            radius: 130
        },
        series: [{
            type: 'radar',
            tooltip: {
                trigger: 'item'
            },
            label: {
                show: true,
            },
            itemStyle: {
                normal: {
                    areaStyle: {
                        type: 'default'
                    }
                }
            },
            data: seriesData
        }]
    }
    return opt;
}
//鲁棒性测试图
function renderChar3() {
    let datas = info.robustness;
    let maxTime = 0;
    let micro_f1 = 1;
    let seriesData = [];
    let maxIdsw = 0;
    let maxFm = 0;

    datas.forEach((d, idx) => {
        if (d.inference_time > maxTime) {
            maxTime = d.inference_time;
        }
        if (d.micro_f1 > micro_f1) {
            micro_f1 = d.micro_f1;
        }
        if (d.idsw > maxIdsw) {
            maxIdsw = d.idsw;
        }
        if (d.fm > maxFm) {
            maxFm = d.fm;
        }
    });
    datas.forEach((d, idx) => {
        if (info.reportType == "tracking") {
            seriesData.push({
                name: idx + 1 + '-' + d.database_name,
                value: [d.idsw, d.mt, d.ml, d.fm, d.mota]
            })
        } else {
            seriesData.push({
                name: idx + 1 + '-' + d.database_name,
                value: [d.micro_f1, d.macro_f1, d.weight_f1, d.map, d.inference_time]
            })
        }
    });
    let indicators = [
        { text: 'Micro F1', max: micro_f1 },
        { text: 'Macro F1', max: 1 },
        { text: '加权F1-Score', max: 1 },
        { text: 'mAP', max: 1 },
        { text: '平均推理时间', max: maxTime }
    ];
    if (info.reportType == "tracking") {
        indicators = [
            { text: 'IDSW', max: maxIdsw },
            { text: 'MT（跟踪轨迹）', max: 1 },
            { text: 'ML（丢失轨迹）', max: 1 },
            { text: 'FM（打断次数）', max: maxFm },
            { text: 'MOTA', max: 1 }
        ];
    }
    let legendDatas = datas.map((d, idx) => idx + 1 + '-' + d.database_name);
    if (info.reportType == "tracking") {
        legendDatas = datas.map((d, idx) => idx + 1 + '-' + d.database_name);
    }
    let toolTipFun = (p) => {
        let val = p.value;
        if (info.reportType == "tracking") {
            return `<b>${p.name}<b/><br/>IDSW:${maxIdsw - val[0]}<br>MT（跟踪轨迹）:${val[1]}<br/>ML（丢失轨迹）:${val[2]}<br/>FM（打断次数）:${maxFm - val[3]}<br/>MOTA:${val[4]}`
        } else {
            return `${p.name}<br/>`
        }
    }
    let opt = {
        title: {
            text: '推理结果比对图'
        },
        legend: {
            x: 'left',
            top: 40,
            orient: 'vertical',
            data: legendDatas
        },
        tooltip: {
            trigger: 'axis'
        },
        calculable: true,
        radar: {
            indicator: indicators,
            radius: 130
        },
        series: [{
            type: 'radar',
            tooltip: {
                trigger: 'item'
            },
            label: {
                show: true,
            },
            itemStyle: {
                normal: {
                    areaStyle: {
                        type: 'default'
                    }
                }
            },
            data: seriesData
        }]
    }
    return opt;
}

function renderChart1(data, type) {
    let chartInfo = data.chartsInfo
    let gridTop = info.isPrint ? 20 * (data.classes.length / 5) : 20 * (data.classes.length / 10);
    let opt = {
        legend: {
            left: '10%', right: '20%',
            data: chartInfo.names
        },
        grid: { top: gridTop, },
        xAxis: [{
            type: 'category',   // 还有其他的type，可以去官网喵两眼哦
            data: chartInfo.labels,   // x轴数据
        }],
        yAxis: [{
            type: 'value',
            name: type == 'roc' ? "ROC曲线" : "RP曲线"
        }],
        tooltip: {
            trigger: 'axis'
        },
        series: (type == "roc" ? chartInfo.rocs : chartInfo.rps).map(it => {
            return {
                name: it.name,
                type: it.type,
                data: it.data,
                label: {
                    show: false,
                    position: 'top'
                }
            }
        })
    }
    return opt;
}
function initTaskChart(it) {
    let rocs = [];
    let rps = [];
    let names = [];
    let labels = [];
    let classes = it.classes || [];
    labels = classes.length > 0 ? classes[0].pr.map(it => it[0]) : [];
    classes.forEach(d => {
        rocs.push({
            name: d.class_name, data: d.roc, type: 'line'
        });
        rps.push({
            name: d.class_name, data: d.pr.map(it => it[1]), type: 'line'
        });
        names.push(d.class_name)
    });
    return {
        rocs, rps, names, labels
    }
}
function loadData() {
    let id = route.query.id;
    ReportApi.getReport(id).then(d => {
        info.report = d.data.data || {};
        info.taskList = info.report.task_list || []
        info.thresholds = info.report.report_parameters?.report_parameters?.thresholds || null
        info.extra_evaluation_type = info.report.report_parameters?.report_parameters?.extra_evaluation_type || '';
        info.tasks = (info.report.report_data?.tasks || info.report.report_data?.report_data?.tasks || []).map(it => {
            it.datas = [{
                inference_time: it.inference_time, macro_f1: it.macro_f1, map: it.map, micro_f1: it.micro_f1,
                system_delay: it.system_delay, task_id: it.task_id, weight_f1: it.weight_f1
            }];
            it.chartsInfo = initTaskChart(it);
            let tmps=info.taskList.filter(task=>task.task_id==it.task_id);
            it.taskName=tmps.length>0?tmps[0].task_name||"":"";
            return it;
        });
        let obj = info.report?.report_data?.robustness?.tasks || null
        info.robustness = (obj ? obj : []);
        info.robustnessMapDecrease = info.report?.report_data?.robustness?.map_decrease;
        info.horizontal_comparison = info.report?.report_data?.horizontal_comparison
        if (info.report.report_data.Tasks) {
            info.reportType = "tracking";
            info.tasks = (info.report?.report_data?.Tasks || []).map(it => {
                let tasks = info.taskList.filter(item => item.task_id == it.task_id);
                let task = tasks.length > 0 ? tasks[0] : {};
                it.task_name = task.task_name || ''
                it.task = task;
                return it;
            });
            obj = info.report?.report_data?.Robustness?.Tasks || null
            info.robustness = (obj ? obj : []);
            info.robustnessMapDecrease = info.report?.report_data?.Robustness?.mota_decrease;
            info.horizontal_comparison = info.report?.report_data?.HorizontalComparison
        } else {
            info.reportType = "other"
        }
    });
}
onMounted(loadData);
</script>
<style lang='scss'>
.simulation-report-desc {

    font-size: 12px;

    .report-name {
        font-size: 20px;
        text-align: center;
        font-weight: bold;
    }

    .sub-title {
        font-size: 14px;
        font-weight: bold;
        text-align: center;
    }

    .div-line {
        margin: 10px 0px;
        height: 2px;
        background-color: #aaa;
    }

    .task-lists {
        margin-top: 20px;

        .info-thresholds {
            font-weight: bold;
        }
    }

    .print-page {
        page-break-after: always;
    }

    .card-footer {
        position: fixed;
        width: calc(100% - 215px);
        bottom: 0px;

        .el-card__body {
            padding: 10px;

            .el-pagination {
                justify-content: end;
            }
        }
    }
}

html.report-print {
    height: auto;

    body {
        #app {
            height: auto;
            min-height: unset;

            .main-container {
                min-height: unset;

                .center-container {
                    display: block;

                    .el-main {
                        .app-main {
                            min-height: unset;

                            .el-scrollbar {
                                height: unset;

                                .el-scrollbar__wrap {
                                    height: unset !important;

                                    .simulation-report-desc {

                                        .el-scrollbar__view {
                                            vertical-align: unset !important;
                                        }

                                        .el-table {
                                            table {
                                                width: unset !important;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        .el-header {
            display: none;
        }

        .el-aside {
            display: none;
        }

        .card-footer {
            display: none;
        }
    }
}

@page {
    margin: 20px;
}
</style>