You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
272 lines
11 KiB
272 lines
11 KiB
1 year ago
|
<template>
|
||
|
<w-dialog ref="dialogRef" :title="detailRef?.modelName + '(' + detailRef?.modelId + ')'" :can-maximize="false" :maximized="true">
|
||
|
<div class="px-2">
|
||
|
<q-tabs v-model="selectedTabRef" inline-label align="left" :breakpoint="0" no-caps @update:model-value="tabChanged">
|
||
|
<q-tab name="discrimination" icon="bi-people" :label="$t('io.sc.engine.mv.result.grid.entity.discrimination')" />
|
||
|
<q-tab name="stability" icon="bi-diagram-3" :label="$t('io.sc.engine.mv.result.grid.entity.stability')" />
|
||
|
<q-tab name="scaleValidate" icon="bi-diagram-3" :label="$t('io.sc.engine.mv.result.grid.entity.scaleValidate')" />
|
||
|
</q-tabs>
|
||
|
|
||
|
<q-tab-panels v-model="selectedTabRef" animated swipeable keep-alive>
|
||
|
<q-tab-panel name="discrimination" class="px-0">
|
||
|
<div style="height: 50px"></div>
|
||
|
<div class="row">
|
||
|
<div class="col-4">
|
||
|
<div id="rocEchart" style="width: 100%; height: 300px"></div>
|
||
|
<div class="row justify-center">
|
||
|
<q-btn color="primary" no-caps flat :label="$t('io.sc.engine.mv.result.curve.viewData', { type: 'ROC' })" @click="showData('ROC')" />
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="col-4">
|
||
|
<div id="capEchart" style="width: 100%; height: 300px"></div>
|
||
|
<div class="row justify-center">
|
||
|
<q-btn color="primary" no-caps flat :label="$t('io.sc.engine.mv.result.curve.viewData', { type: 'CAP' })" @click="showData('CAP')" />
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="col-4">
|
||
|
<div id="ksEchart" style="width: 100%; height: 300px"></div>
|
||
|
<div class="row justify-center">
|
||
|
<q-btn color="primary" no-caps flat :label="$t('io.sc.engine.mv.result.curve.viewData', { type: 'KS' })" @click="showData('KS')" />
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
<h3>{{ $t('io.sc.engine.mv.result.curve.references') }}:</h3>
|
||
|
<table width="100%" style="border-collapse: collapse">
|
||
|
<tr>
|
||
|
<th class="referenceTh">{{ $t('io.sc.engine.mv.performance') }}</th>
|
||
|
<th class="referenceTh">ROC (AUC = {{ detailRef.auc }})</th>
|
||
|
<th class="referenceTh">CAP (AR = {{ detailRef.ar }})</th>
|
||
|
<th class="referenceTh">KS (KS = {{ detailRef.ks }})</th>
|
||
|
</tr>
|
||
|
<tr v-for="(level, index) in referenceLevels" :key="index">
|
||
|
<td class="referenceTd">{{ level }}</td>
|
||
|
<td :class="valueInRange(detailRef.auc, referenceValues.auc[index]) ? 'referenceTd highlight' : 'referenceTd'">
|
||
|
{{ referenceValues.auc[index].label }}
|
||
|
</td>
|
||
|
<td :class="valueInRange(detailRef.ar, referenceValues.ar[index]) ? 'referenceTd highlight' : 'referenceTd'">
|
||
|
{{ referenceValues.ar[index].label }}
|
||
|
</td>
|
||
|
<td :class="valueInRange(detailRef.ks, referenceValues.ks[index]) ? 'referenceTd highlight' : 'referenceTd'">
|
||
|
{{ referenceValues.ks[index].label }}
|
||
|
</td>
|
||
|
</tr>
|
||
|
</table>
|
||
|
</q-tab-panel>
|
||
|
<q-tab-panel name="stability" class="px-0">
|
||
|
<div style="height: 50px"></div>
|
||
|
<div class="row">
|
||
|
<div class="col-4">
|
||
|
<div id="psiEchart" style="width: 100%; height: 300px"></div>
|
||
|
<div class="row justify-center">
|
||
|
<q-btn color="primary" no-caps flat :label="$t('io.sc.engine.mv.result.curve.viewData', { type: 'ROC' })" @click="showData('ROC')" />
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</q-tab-panel>
|
||
|
<q-tab-panel name="scaleValidate" class="px-0">
|
||
|
<div class="row">
|
||
|
<div class="col-5 pr-2">
|
||
|
<w-grid
|
||
|
:checkbox-selection="false"
|
||
|
:fetch-data-url="Environment.apiContextPath('/api/mv/sc/roc?modelId=' + detailRef.modelId + '&validateDate=' + detailRef.validateDate)"
|
||
|
:pageable="true"
|
||
|
:toolbar-actions="['refresh', 'separator', 'export']"
|
||
|
:columns="[
|
||
|
{ width: 100, name: 'level', label: $t('io.sc.engine.mv.result.chiSquare.level'), align: 'right' },
|
||
|
{ width: 100, name: 'pd', label: $t('io.sc.engine.mv.result.chiSquare.pd'), align: 'right' },
|
||
|
{ width: 100, name: 'count', label: $t('io.sc.engine.mv.result.chiSquare.count'), align: 'right' },
|
||
|
{ width: 100, name: 'defaultCount', label: $t('io.sc.engine.mv.result.chiSquare.defaultCount'), align: 'right' },
|
||
|
{ width: 100, name: 'chiSquare', label: $t('io.sc.engine.mv.result.chiSquare.chiSquare'), align: 'right' },
|
||
|
]"
|
||
|
></w-grid>
|
||
|
</div>
|
||
|
<div class="col-7 pl-2">
|
||
|
<w-grid
|
||
|
:checkbox-selection="false"
|
||
|
:fetch-data-url="Environment.apiContextPath('/api/mv/sc/roc?modelId=' + detailRef.modelId + '&validateDate=' + detailRef.validateDate)"
|
||
|
:pageable="true"
|
||
|
:toolbar-actions="['refresh', 'separator', 'export']"
|
||
|
:columns="[
|
||
|
{ width: 100, name: 'level', label: $t('io.sc.engine.mv.result.binomial.level'), align: 'right' },
|
||
|
{ width: 100, name: 'pd', label: $t('io.sc.engine.mv.result.binomial.pd'), align: 'right' },
|
||
|
{ width: 100, name: 'count', label: $t('io.sc.engine.mv.result.binomial.count'), align: 'right' },
|
||
|
{ width: 100, name: 'defaultCount', label: $t('io.sc.engine.mv.result.binomial.defaultCount'), align: 'right' },
|
||
|
{ width: 100, name: 'ndAvg', label: $t('io.sc.engine.mv.result.binomial.ndAvg'), align: 'right' },
|
||
|
{ width: 100, name: 'ndSd', label: $t('io.sc.engine.mv.result.binomial.ndSd'), align: 'right' },
|
||
|
{ width: 100, name: 'sl', label: $t('io.sc.engine.mv.result.binomial.sl'), align: 'right' },
|
||
|
{ width: 100, name: 'cl', label: $t('io.sc.engine.mv.result.binomial.cl'), align: 'right' },
|
||
|
{ width: 100, name: 'zUpper', label: $t('io.sc.engine.mv.result.binomial.zUpper'), align: 'right' },
|
||
|
{ width: 100, name: 'zLower', label: $t('io.sc.engine.mv.result.binomial.zLower'), align: 'right' },
|
||
|
{ width: 100, name: 'dUpper', label: $t('io.sc.engine.mv.result.binomial.dUpper'), align: 'right' },
|
||
|
{ width: 100, name: 'dLower', label: $t('io.sc.engine.mv.result.binomial.dLower'), align: 'right' },
|
||
|
{ width: 100, name: 'leUpper', label: $t('io.sc.engine.mv.result.binomial.leUpper'), align: 'right' },
|
||
|
{ width: 100, name: 'geLower', label: $t('io.sc.engine.mv.result.binomial.geLower'), align: 'right' },
|
||
|
]"
|
||
|
></w-grid>
|
||
|
</div>
|
||
|
</div>
|
||
|
</q-tab-panel>
|
||
|
</q-tab-panels>
|
||
|
</div>
|
||
|
<CurveDataDialog ref="curveDataDialogRef"></CurveDataDialog>
|
||
|
</w-dialog>
|
||
|
</template>
|
||
|
<script setup lang="ts">
|
||
|
import { ref, nextTick, computed } from 'vue';
|
||
|
import { useI18n } from 'vue-i18n';
|
||
|
import * as echarts from 'echarts';
|
||
|
import { axios, Environment } from 'platform-core';
|
||
|
import CurveDataDialog from './CurveDataDialog.vue';
|
||
|
|
||
|
const { t } = useI18n();
|
||
|
|
||
|
const referenceValues = {
|
||
|
auc: [
|
||
|
{ label: '[0.00 - 0.65)', from: 0, to: 0.65 },
|
||
|
{ label: '[0.65 - 0.75)', from: 0.65, to: 0.75 },
|
||
|
{ label: '[0.75 - 0.80)', from: 0.75, to: 0.8 },
|
||
|
{ label: '[0.80 - 0.85)', from: 0.8, to: 0.85 },
|
||
|
{ label: '[0.85 - 0.90)', from: 0.85, to: 0.9 },
|
||
|
{ label: '[0.90 - 1.00)', from: 0.9, to: 1 },
|
||
|
],
|
||
|
ar: [
|
||
|
{ label: '[0.0 - 0.3)', from: 0, to: 0.3 },
|
||
|
{ label: '[0.3 - 0.5)', from: 0.3, to: 0.5 },
|
||
|
{ label: '[0.5 - 0.6)', from: 0.5, to: 0.6 },
|
||
|
{ label: '[0.6 - 0.7)', from: 0.6, to: 0.7 },
|
||
|
{ label: '[0.7 - 0.8)', from: 0.7, to: 0.8 },
|
||
|
{ label: '[0.8 - 1.0)', from: 0.8, to: 1 },
|
||
|
],
|
||
|
ks: [
|
||
|
{ label: '[0.00 - 0.20)', from: 0, to: 0.2 },
|
||
|
{ label: '[0.20 - 0.40)', from: 0.2, to: 0.4 },
|
||
|
{ label: '[0.40 - 0.50)', from: 0.4, to: 0.5 },
|
||
|
{ label: '[0.50 - 0.60)', from: 0.5, to: 0.6 },
|
||
|
{ label: '[0.60 - 0.75)', from: 0.6, to: 0.75 },
|
||
|
{ label: '[0.75 - 1.00)', from: 0.75, to: 1 },
|
||
|
],
|
||
|
};
|
||
|
const referenceLevels = computed(() => {
|
||
|
return [
|
||
|
t('io.sc.platform.core.enums.GoodLevel.POOR'),
|
||
|
t('io.sc.platform.core.enums.GoodLevel.MEDIUM'),
|
||
|
t('io.sc.platform.core.enums.GoodLevel.GOOD'),
|
||
|
t('io.sc.platform.core.enums.GoodLevel.VERY_GOOD'),
|
||
|
t('io.sc.platform.core.enums.GoodLevel.EXCELLENT'),
|
||
|
t('io.sc.platform.core.enums.GoodLevel.PERFECT'),
|
||
|
];
|
||
|
});
|
||
|
|
||
|
const dialogRef = ref();
|
||
|
const detailRef = ref();
|
||
|
const selectedTabRef = ref('discrimination');
|
||
|
const curveDataDialogRef = ref();
|
||
|
|
||
|
let rocEchart;
|
||
|
let capEchart;
|
||
|
let ksEchart;
|
||
|
let psiEchart;
|
||
|
const open = (detail: any) => {
|
||
|
detailRef.value = detail;
|
||
|
dialogRef.value.show();
|
||
|
tabChanged();
|
||
|
};
|
||
|
|
||
|
const tabChanged = () => {
|
||
|
nextTick(() => {
|
||
|
if ('discrimination' === selectedTabRef.value) {
|
||
|
if (!rocEchart) {
|
||
|
rocEchart = echarts.init(document.getElementById('rocEchart'));
|
||
|
}
|
||
|
axios
|
||
|
.get(Environment.apiContextPath('/api/mv/sc/cap/option?modelId=' + detailRef.value.modelId + '&validateDate=' + detailRef.value.validateDate))
|
||
|
.then((response) => {
|
||
|
rocEchart?.setOption(response.data);
|
||
|
rocEchart?.resize();
|
||
|
});
|
||
|
|
||
|
if (!capEchart) {
|
||
|
capEchart = echarts.init(document.getElementById('capEchart'));
|
||
|
}
|
||
|
axios
|
||
|
.get(Environment.apiContextPath('/api/mv/sc/cap/option?modelId=' + detailRef.value.modelId + '&validateDate=' + detailRef.value.validateDate))
|
||
|
.then((response) => {
|
||
|
capEchart?.setOption(response.data);
|
||
|
capEchart?.resize();
|
||
|
});
|
||
|
|
||
|
if (!ksEchart) {
|
||
|
ksEchart = echarts.init(document.getElementById('ksEchart'));
|
||
|
}
|
||
|
axios
|
||
|
.get(Environment.apiContextPath('/api/mv/sc/ks/option?modelId=' + detailRef.value.modelId + '&validateDate=' + detailRef.value.validateDate))
|
||
|
.then((response) => {
|
||
|
ksEchart?.setOption(response.data);
|
||
|
ksEchart?.resize();
|
||
|
});
|
||
|
} else if ('stability' === selectedTabRef.value) {
|
||
|
if (!psiEchart) {
|
||
|
psiEchart = echarts.init(document.getElementById('psiEchart'));
|
||
|
}
|
||
|
axios
|
||
|
.get(Environment.apiContextPath('/api/mv/st/psi/option?modelId=' + detailRef.value.modelId + '&validateDate=' + detailRef.value.validateDate))
|
||
|
.then((response) => {
|
||
|
psiEchart?.setOption(response.data);
|
||
|
psiEchart?.resize();
|
||
|
});
|
||
|
}
|
||
|
});
|
||
|
};
|
||
|
|
||
|
const close = () => {
|
||
|
dialogRef.value.hide();
|
||
|
if (rocEchart) {
|
||
|
rocEchart.dispose();
|
||
|
}
|
||
|
if (capEchart) {
|
||
|
capEchart.dispose();
|
||
|
}
|
||
|
if (ksEchart) {
|
||
|
ksEchart.dispose();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
const valueInRange = (value, config) => {
|
||
|
if (value >= config.from && value < config.to) {
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
};
|
||
|
|
||
|
const showData = (type: string) => {
|
||
|
curveDataDialogRef.value.open(type, detailRef.value);
|
||
|
};
|
||
|
|
||
|
defineExpose({
|
||
|
open,
|
||
|
close,
|
||
|
});
|
||
|
</script>
|
||
|
|
||
|
<style>
|
||
|
.referenceTh {
|
||
|
border: 1px solid gray;
|
||
|
padding-top: 0px;
|
||
|
padding-right: 10px;
|
||
|
padding-bottom: 0px;
|
||
|
padding-left: 10px;
|
||
|
}
|
||
|
|
||
|
.referenceTd {
|
||
|
border: 1px solid gray;
|
||
|
padding-top: 0px;
|
||
|
padding-right: 10px;
|
||
|
padding-bottom: 0px;
|
||
|
padding-left: 10px;
|
||
|
}
|
||
|
|
||
|
.highlight {
|
||
|
background-color: bisque;
|
||
|
}
|
||
|
</style>
|