|
|
@@ -2,7 +2,7 @@
|
|
|
import { Page } from '@vben/common-ui';
|
|
|
import { requestClient } from '#/api/request';
|
|
|
import { Button, message } from 'ant-design-vue';
|
|
|
-import { ref, reactive, computed, onMounted, useTemplateRef } from 'vue';
|
|
|
+import { ref, reactive, computed, onMounted, onUnmounted, useTemplateRef } from 'vue';
|
|
|
import dayjs from 'dayjs';
|
|
|
|
|
|
import MatchCard from '../components/match_card.vue';
|
|
|
@@ -34,13 +34,143 @@ const getGamesEvents = async () => {
|
|
|
}
|
|
|
|
|
|
|
|
|
-const moveToFront = (arr, index) => {
|
|
|
- if (index <= 0 || index >= arr.length) {
|
|
|
- return arr;
|
|
|
+// const moveToFront = (arr, index) => {
|
|
|
+// if (index <= 0 || index >= arr.length) {
|
|
|
+// return arr;
|
|
|
+// }
|
|
|
+// const item = arr.splice(index, 1)[0];
|
|
|
+// arr.unshift(item);
|
|
|
+// return arr;
|
|
|
+// }
|
|
|
+
|
|
|
+const parseIorKey = (iorKey) => {
|
|
|
+ const [, type, accept, side, , ratioString] = iorKey.match(/^ior_(r|ou|m|wm|t)(a?)(h|c|n)?(_(\d+))?$/);
|
|
|
+ const ratio = ratioString ? `${ratioString[0]}.${ratioString.slice(1)}` * (accept ? 1 : -1) : 0;
|
|
|
+ return { type, side, ratio };
|
|
|
+}
|
|
|
+
|
|
|
+const formatJcEvents = (events) => {
|
|
|
+ const eventsMap = {};
|
|
|
+ Object.keys(events).forEach(key => {
|
|
|
+ const { type, side, ratio } = parseIorKey(key);
|
|
|
+ let ratioKey, index;
|
|
|
+ if (type === 'r') {
|
|
|
+ if (side === 'h') {
|
|
|
+ ratioKey = ratio + 0.5;
|
|
|
+ index = 0;
|
|
|
+ }
|
|
|
+ else if (side === 'c') {
|
|
|
+ ratioKey = -ratio - 0.5;
|
|
|
+ index = 2;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (type === 'm') {
|
|
|
+ ratioKey = 0;
|
|
|
+ index = 1;
|
|
|
+ }
|
|
|
+ else if (type === 'wm') {
|
|
|
+ if (side === 'h') {
|
|
|
+ ratioKey = ratio;
|
|
|
+ index = 1;
|
|
|
+ }
|
|
|
+ else if (side === 'c') {
|
|
|
+ ratioKey = -ratio;
|
|
|
+ index = 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ ratioKey = Math.round(ratioKey);
|
|
|
+
|
|
|
+ if (ratioKey > 0) {
|
|
|
+ ratioKey = `+${ratioKey}`;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ ratioKey = `${ratioKey}`;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!eventsMap[ratioKey]) {
|
|
|
+ eventsMap[ratioKey] = [];
|
|
|
+ }
|
|
|
+
|
|
|
+ const value = events[key] ?? 0;
|
|
|
+
|
|
|
+ eventsMap[ratioKey][index] = { key, value };
|
|
|
+
|
|
|
+ });
|
|
|
+ return Object.keys(eventsMap).sort((a, b) => b.localeCompare(a)).map(key => {
|
|
|
+ return [key, ...eventsMap[key]];
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+const rivalIor = (ior) => {
|
|
|
+ const map = {
|
|
|
+ "ior_rh": "ior_rac",
|
|
|
+ "ior_rc": "ior_rah",
|
|
|
+ "ior_rac": "ior_rh",
|
|
|
+ "ior_rah": "ior_rc",
|
|
|
+ "ior_ouc": "ior_ouh",
|
|
|
+ "ior_ouh": "ior_ouc",
|
|
|
+ };
|
|
|
+ const iorInfos = ior.split('_');
|
|
|
+ const iorStart = iorInfos.slice(0, 2).join('_');
|
|
|
+ if (!map[iorStart]) {
|
|
|
+ return ior;
|
|
|
}
|
|
|
- const item = arr.splice(index, 1)[0];
|
|
|
- arr.unshift(item);
|
|
|
- return arr;
|
|
|
+ return `${map[iorStart]}_${iorInfos[2]}`;
|
|
|
+}
|
|
|
+
|
|
|
+const formatEvents = (events, cprKeys) => {
|
|
|
+ const eventsMap = {};
|
|
|
+ cprKeys.forEach(key => {
|
|
|
+ const { type, side, ratio } = parseIorKey(key);
|
|
|
+ let ratioKey, values = [];
|
|
|
+ if (type === 'r') {
|
|
|
+ if (side === 'h') {
|
|
|
+ ratioKey = ratio;
|
|
|
+ values[0] = { key, value: events[key] ?? 0 };
|
|
|
+ values[2] = { key: rivalIor(key), value: events[rivalIor(key)] ?? 0 };
|
|
|
+ }
|
|
|
+ else if (side === 'c') {
|
|
|
+ ratioKey = -ratio;
|
|
|
+ values[0] = { key: rivalIor(key), value: events[rivalIor(key)] ?? 0 };
|
|
|
+ values[2] = { key, value: events[key] ?? 0 };
|
|
|
+ }
|
|
|
+ values[1] = { key: '', value: 0 };
|
|
|
+ }
|
|
|
+ else if (type === 'm') {
|
|
|
+ ratioKey = 'm';
|
|
|
+ values[0] = { key: 'ior_rh_05', value: events['ior_rh_05'] ?? 0 };
|
|
|
+ values[1] = { key, value: events[key] ?? 0 };
|
|
|
+ values[2] = { key: 'ior_rc_05', value: events['ior_rc_05'] ?? 0 };
|
|
|
+ }
|
|
|
+ else if (type === 'wm') {
|
|
|
+ ratioKey = `wm_${Math.abs(ratio)}`;
|
|
|
+ values[0] = { key: '', value: 0 };
|
|
|
+ values[1] = { key: '', value: 0 };
|
|
|
+ values[2] = { key: '', value: 0 };
|
|
|
+ if (side === 'h') {
|
|
|
+ values[0] = { key, value: events[key] ?? 0 };
|
|
|
+ }
|
|
|
+ else if (side === 'c') {
|
|
|
+ values[2] = { key, value: events[key] ?? 0 } ;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (typeof(ratioKey) == 'number') {
|
|
|
+ if (ratioKey > 0) {
|
|
|
+ ratioKey = `+${ratioKey}`;
|
|
|
+ }
|
|
|
+ else if (ratioKey === 0) {
|
|
|
+ ratioKey = '-0';
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ ratioKey = `${ratioKey}`;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ eventsMap[ratioKey] = values;
|
|
|
+ });
|
|
|
+ return Object.keys(eventsMap).sort((a, b) => a.localeCompare(b)).map(key => {
|
|
|
+ return [key, ...eventsMap[key]];
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
const updateSolutions = async () => {
|
|
|
@@ -48,42 +178,43 @@ const updateSolutions = async () => {
|
|
|
solutions.value = solutionsList.map(item => {
|
|
|
const { cpr, info, sol: { cross_type, jc_index, gold_side_a, gold_side_b, gold_side_m, win_side_a, win_side_b, win_side_m, win_average } } = item;
|
|
|
const cprKeys = cpr.map(item => item.k);
|
|
|
- const jcEvents = eventsList.jc[info.jc.eventId];
|
|
|
- const psEvents = eventsList.ps[info.ps.eventId];
|
|
|
- const obEvents = eventsList.ob[info.ob.eventId];
|
|
|
|
|
|
+ info.jc.events = formatJcEvents(eventsList.jc[info.jc.eventId]);
|
|
|
+ info.ps.events = formatEvents(eventsList.ps[info.ps.eventId], cprKeys);
|
|
|
+ info.ob.events = formatEvents(eventsList.ob[info.ob.eventId], cprKeys);
|
|
|
+
|
|
|
+ info.jc.dateTime = dayjs(info.jc.timestamp).format('YYYY-MM-DD HH:mm:ss');
|
|
|
+ info.ps.dateTime = dayjs(info.ps.timestamp).format('YYYY-MM-DD HH:mm:ss');
|
|
|
+ info.ob.dateTime = dayjs(info.ob.timestamp).format('YYYY-MM-DD HH:mm:ss');
|
|
|
|
|
|
+ cpr.forEach(item => {
|
|
|
+ const { k, p } = item;
|
|
|
+ if (!info[p]['selected']) {
|
|
|
+ info[p]['selected'] = [];
|
|
|
+ }
|
|
|
+ info[p]['selected'].push(k);
|
|
|
+ });
|
|
|
|
|
|
- cpr[0].g = gold_side_a;
|
|
|
- cpr[0].w = win_side_a;
|
|
|
- cpr[1].g = gold_side_b;
|
|
|
- cpr[1].w = win_side_b;
|
|
|
- cpr[2].g = gold_side_m;
|
|
|
- cpr[2].w = win_side_m;
|
|
|
- const newCpr = moveToFront(cpr, jc_index);
|
|
|
- return { ...item, cpr: newCpr, sol: { cross_type, jc_index, win_average }, events };
|
|
|
+ return item;
|
|
|
});
|
|
|
}
|
|
|
|
|
|
-const updateGamesEvents = async () => {
|
|
|
- const events = await getGamesEvents();
|
|
|
- gamesEvents.value = events;
|
|
|
-}
|
|
|
+let updateTimer = null;
|
|
|
|
|
|
onMounted(() => {
|
|
|
updateSolutions();
|
|
|
+ updateTimer = setInterval(() => {
|
|
|
+ updateSolutions();
|
|
|
+ }, 1000 * 10);
|
|
|
});
|
|
|
|
|
|
-</script>
|
|
|
+onUnmounted(() => {
|
|
|
+ console.log('unmounted');
|
|
|
+ clearInterval(updateTimer);
|
|
|
+});
|
|
|
|
|
|
-<!-- eventId
|
|
|
-platform
|
|
|
-leagueName
|
|
|
-teamHomeName
|
|
|
-teamAwayName
|
|
|
-dateTime
|
|
|
-eventInfo
|
|
|
-solutionKey -->
|
|
|
+
|
|
|
+</script>
|
|
|
|
|
|
<template>
|
|
|
<div class="solution-container">
|
|
|
@@ -94,27 +225,50 @@ solutionKey -->
|
|
|
<em>利润</em>
|
|
|
</div>
|
|
|
<div class="solution-list">
|
|
|
- <!-- <div class="solution-item" v-for="solution in solutions" :key="solution.sid">
|
|
|
- <MatchCard />
|
|
|
- <MatchCard />
|
|
|
- <MatchCard />
|
|
|
- <div class="solution-profit"></div>
|
|
|
- </div> -->
|
|
|
+ <div class="solution-item" v-for="{ sid, sol: {win_average}, info: {jc, ps, ob} } in solutions" :key="sid">
|
|
|
+ <MatchCard platform="jc"
|
|
|
+ :eventId="jc.eventId"
|
|
|
+ :leagueName="jc.leagueName"
|
|
|
+ :teamHomeName="jc.teamHomeName"
|
|
|
+ :teamAwayName="jc.teamAwayName"
|
|
|
+ :dateTime="jc.dateTime"
|
|
|
+ :eventInfo="jc.eventInfo"
|
|
|
+ :events="jc.events ?? []"
|
|
|
+ :selected="jc.selected ?? []"/>
|
|
|
+
|
|
|
+ <MatchCard platform="ps"
|
|
|
+ :eventId="ps.eventId"
|
|
|
+ :leagueName="ps.leagueName"
|
|
|
+ :teamHomeName="ps.teamHomeName"
|
|
|
+ :teamAwayName="ps.teamAwayName"
|
|
|
+ :dateTime="ps.dateTime"
|
|
|
+ :events="ps.events ?? []"
|
|
|
+ :selected="ps.selected ?? []"/>
|
|
|
+
|
|
|
+ <MatchCard platform="ob"
|
|
|
+ :eventId="ob.eventId"
|
|
|
+ :leagueName="ob.leagueName"
|
|
|
+ :teamHomeName="ob.teamHomeName"
|
|
|
+ :teamAwayName="ob.teamAwayName"
|
|
|
+ :dateTime="ob.dateTime"
|
|
|
+ :events="ob.events ?? []"
|
|
|
+ :selected="ob.selected ?? []"/>
|
|
|
+
|
|
|
+ <div class="solution-profit">{{ win_average }}</div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
-.solution-container {
|
|
|
- height: 100%;
|
|
|
- display: flex;
|
|
|
- flex-direction: column;
|
|
|
-}
|
|
|
.solution-header {
|
|
|
+ position: relative;
|
|
|
+ z-index: 11;
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
height: 40px;
|
|
|
- background: #fff;
|
|
|
+ padding: 0 20px;
|
|
|
+ background-color: hsl(var(--background));
|
|
|
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
|
|
|
span, em {
|
|
|
display: block;
|
|
|
@@ -128,4 +282,26 @@ solutionKey -->
|
|
|
font-style: normal;
|
|
|
}
|
|
|
}
|
|
|
+.solution-list {
|
|
|
+ padding: 20px;
|
|
|
+ overflow: hidden;
|
|
|
+}
|
|
|
+.solution-item {
|
|
|
+ display: flex;
|
|
|
+ border-radius: 10px;
|
|
|
+ background-color: hsl(var(--card));
|
|
|
+ &:not(:last-child) {
|
|
|
+ margin-bottom: 20px;
|
|
|
+ }
|
|
|
+ .match-card {
|
|
|
+ flex: 1;
|
|
|
+ border-right: 1px solid hsl(var(--border));
|
|
|
+ }
|
|
|
+ .solution-profit {
|
|
|
+ display: flex;
|
|
|
+ width: 80px;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ }
|
|
|
+}
|
|
|
</style>
|