mirror of
https://github.com/linux-odyssey/linux-odyssey.git
synced 2026-11-05 19:20:12 +08:00
feat: rewrite map state handling
This commit is contained in:
1 parent
8f6914d46c
commit
1572b2ea06
2 files changed
+61
-29
No files matched your search
@@ -1,5 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, onMounted, computed } from 'vue'
|
import { ref, onMounted, watch } from 'vue'
|
||||||
|
import { IQuest } from '@linux-odyssey/models'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { useToast } from 'vue-toastification'
|
import { useToast } from 'vue-toastification'
|
||||||
import { DAG } from '@linux-odyssey/utils'
|
import { DAG } from '@linux-odyssey/utils'
|
||||||
@@ -10,50 +11,79 @@ const store = useUserProfile()
|
|||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const toast = useToast()
|
const toast = useToast()
|
||||||
|
|
||||||
const quests = ref([])
|
|
||||||
const svgWidth = ref(window.innerWidth)
|
const svgWidth = ref(window.innerWidth)
|
||||||
const svgHeight = ref(window.innerHeight)
|
const svgHeight = ref(window.innerHeight)
|
||||||
|
|
||||||
const marginX = 60
|
const marginX = 80
|
||||||
const marginY = 50
|
const marginY = 80
|
||||||
|
|
||||||
|
const nodeWidth = 150
|
||||||
|
const nodeHeight = 50
|
||||||
|
|
||||||
async function getQuests() {
|
async function getQuests() {
|
||||||
try {
|
try {
|
||||||
const res = await api.get('/quests')
|
const res = await api.get<IQuest[]>('/quests')
|
||||||
quests.value = res.data
|
return res.data
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
throw err
|
throw err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const graphData = computed(() => {
|
type Node = {
|
||||||
const dag = new DAG(quests.value)
|
id: string
|
||||||
|
title: string
|
||||||
|
x: number
|
||||||
|
y: number
|
||||||
|
completed: boolean
|
||||||
|
unlocked: boolean
|
||||||
|
}
|
||||||
|
|
||||||
console.log(store.progress)
|
type Edge = {
|
||||||
const nodes = dag.getNodes().map((node) => ({
|
source: Node
|
||||||
|
target: Node
|
||||||
|
}
|
||||||
|
|
||||||
|
const graphData = ref<{ nodes: Node[]; edges: Edge[] }>({
|
||||||
|
nodes: [],
|
||||||
|
edges: [],
|
||||||
|
})
|
||||||
|
|
||||||
|
async function computeGraphData() {
|
||||||
|
if (!store.progress) return
|
||||||
|
|
||||||
|
try {
|
||||||
|
const quests = await getQuests()
|
||||||
|
const dag = new DAG(quests)
|
||||||
|
const nodesValues = dag.getNodes()
|
||||||
|
|
||||||
|
const nodes = nodesValues.map((node) => ({
|
||||||
id: node._id,
|
id: node._id,
|
||||||
title: node.title,
|
title: node.title,
|
||||||
x: marginX * node.layer * 2,
|
x: marginX * node.layer * 2,
|
||||||
// y: marginX * node.index - (marginX * dag.getLayer(node._id)) / 2,
|
y:
|
||||||
y: marginY * node.index + svgHeight.value / 2,
|
marginY * node.index -
|
||||||
|
(marginX * dag.getLayer(node._id)) / 2 +
|
||||||
|
svgHeight.value / 2,
|
||||||
completed: store.progress[node._id]?.completed || false,
|
completed: store.progress[node._id]?.completed || false,
|
||||||
unlocked: node.requirements.every(
|
unlocked: node.requirements.every(
|
||||||
(req: string) => store.progress[req]?.completed
|
(req: string) => store.progress[req]?.completed
|
||||||
),
|
),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
console.log(nodes)
|
// const edges = dag.getEdgesArray().map((edge) => ({
|
||||||
|
// source: nodes.find((n) => n.id === edge[0]),
|
||||||
|
// target: nodes.find((n) => n.id === edge[1]),
|
||||||
|
// }))
|
||||||
|
|
||||||
const edges = dag.getEdgesArray().map((edge: any) => ({
|
graphData.value = { nodes, edges: [] }
|
||||||
source: nodes.find((n) => n.id === edge[0]),
|
} catch (error) {
|
||||||
target: nodes.find((n) => n.id === edge[1]),
|
console.error('Error computing graph data:', error)
|
||||||
}))
|
toast.error('Failed to load quest data')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return { nodes, edges }
|
function handleNodeClick(node: { id: string; unlocked: boolean }) {
|
||||||
})
|
|
||||||
|
|
||||||
function handleNodeClick(node: any) {
|
|
||||||
if (node.unlocked) {
|
if (node.unlocked) {
|
||||||
router.push({ name: 'game', params: { questId: node.id } })
|
router.push({ name: 'game', params: { questId: node.id } })
|
||||||
} else {
|
} else {
|
||||||
@@ -63,8 +93,10 @@ function handleNodeClick(node: any) {
|
|||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await store.loadUserProfile()
|
await store.loadUserProfile()
|
||||||
await getQuests()
|
await computeGraphData()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
watch(() => store.progress, computeGraphData, { deep: true })
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -101,14 +133,14 @@ onMounted(async () => {
|
|||||||
@click="handleNodeClick(node)"
|
@click="handleNodeClick(node)"
|
||||||
>
|
>
|
||||||
<rect
|
<rect
|
||||||
:x="node.x - 50"
|
:x="node.x - nodeWidth / 2"
|
||||||
:y="node.y - 25"
|
:y="node.y - nodeHeight / 2"
|
||||||
width="100"
|
:width="nodeWidth"
|
||||||
height="50"
|
:height="nodeHeight"
|
||||||
rx="10"
|
rx="10"
|
||||||
ry="10"
|
ry="10"
|
||||||
:fill="
|
:fill="
|
||||||
node.completed ? '#00ff00' : node.unlocked ? '#ADADB5' : '#505050'
|
node.completed ? '#00bb00' : node.unlocked ? '#ADADB5' : '#505050'
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
<text
|
<text
|
||||||
@@ -117,7 +149,7 @@ onMounted(async () => {
|
|||||||
text-anchor="middle"
|
text-anchor="middle"
|
||||||
alignment-baseline="middle"
|
alignment-baseline="middle"
|
||||||
fill="white"
|
fill="white"
|
||||||
font-size="12"
|
font-size="16"
|
||||||
>
|
>
|
||||||
{{ node.title }}
|
{{ node.title }}
|
||||||
</text>
|
</text>
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ export default class DAG {
|
|||||||
if (!node) {
|
if (!node) {
|
||||||
throw new Error(`Node ${id} not found`)
|
throw new Error(`Node ${id} not found`)
|
||||||
}
|
}
|
||||||
return this.layers[node.layer - 1]
|
return this.layers[node.layer - 1] || 0
|
||||||
}
|
}
|
||||||
|
|
||||||
private setLayer(id: string) {
|
private setLayer(id: string) {
|
||||||
|
|||||||
Reference in new issue
Block a user