bx-865-apps #1
|
@ -8579,7 +8579,7 @@
|
|||
"kind": 5,
|
||||
"importPath": "back.back.settings",
|
||||
"description": "back.back.settings",
|
||||
"peekOfCode": "CSRF_TRUSTED_ORIGINS = (\n \"https://demo.kustarshina.ru\",\n \"http://localhost\",\n \"http://localhost:3011\",\n \"http://192.168.103.159\",\n)\nCORS_ORIGIN_ALLOW_ALL = False\nCORS_ORIGIN_WHITELIST = [\n \"null\",\n \"http://localhost\",",
|
||||
"peekOfCode": "CSRF_TRUSTED_ORIGINS = (\n \"https://demo.kustarshina.ru\",\n \"http://localhost\",\n \"http://localhost:3011\",\n \"http://localhost:4173\",\n \"http://localhost:5173\",\n \"http://192.168.103.159:3011\",\n \"http://192.168.103.159\",\n)\nCORS_ORIGIN_ALLOW_ALL = False",
|
||||
"detail": "back.back.settings",
|
||||
"documentation": {}
|
||||
},
|
||||
|
@ -8588,7 +8588,7 @@
|
|||
"kind": 5,
|
||||
"importPath": "back.back.settings",
|
||||
"description": "back.back.settings",
|
||||
"peekOfCode": "CORS_ORIGIN_ALLOW_ALL = False\nCORS_ORIGIN_WHITELIST = [\n \"null\",\n \"http://localhost\",\n \"http://localhost:3000\",\n \"http://localhost:3011\",\n \"http://localhost:4173\",\n \"http://localhost:5173\",\n \"http://localhost:8000\",\n \"http://127.0.0.1\",",
|
||||
"peekOfCode": "CORS_ORIGIN_ALLOW_ALL = False\nCORS_ORIGIN_WHITELIST = [\n \"null\",\n \"http://localhost\",\n \"http://localhost:3011\",\n \"http://localhost:4173\",\n \"http://localhost:5173\",\n \"http://localhost:8000\",\n \"http://192.168.103.159:3011\",\n \"http://127.0.0.1\",",
|
||||
"detail": "back.back.settings",
|
||||
"documentation": {}
|
||||
},
|
||||
|
@ -8597,7 +8597,7 @@
|
|||
"kind": 5,
|
||||
"importPath": "back.back.settings",
|
||||
"description": "back.back.settings",
|
||||
"peekOfCode": "CORS_ORIGIN_WHITELIST = [\n \"null\",\n \"http://localhost\",\n \"http://localhost:3000\",\n \"http://localhost:3011\",\n \"http://localhost:4173\",\n \"http://localhost:5173\",\n \"http://localhost:8000\",\n \"http://127.0.0.1\",\n \"http://192.168.103.159\",",
|
||||
"peekOfCode": "CORS_ORIGIN_WHITELIST = [\n \"null\",\n \"http://localhost\",\n \"http://localhost:3011\",\n \"http://localhost:4173\",\n \"http://localhost:5173\",\n \"http://localhost:8000\",\n \"http://192.168.103.159:3011\",\n \"http://127.0.0.1\",\n \"http://192.168.103.159\",",
|
||||
"detail": "back.back.settings",
|
||||
"documentation": {}
|
||||
},
|
||||
|
|
|
@ -44,17 +44,20 @@ CSRF_TRUSTED_ORIGINS = (
|
|||
"https://demo.kustarshina.ru",
|
||||
"http://localhost",
|
||||
"http://localhost:3011",
|
||||
"http://localhost:4173",
|
||||
"http://localhost:5173",
|
||||
"http://192.168.103.159:3011",
|
||||
"http://192.168.103.159",
|
||||
)
|
||||
CORS_ORIGIN_ALLOW_ALL = False
|
||||
CORS_ORIGIN_WHITELIST = [
|
||||
"null",
|
||||
"http://localhost",
|
||||
"http://localhost:3000",
|
||||
"http://localhost:3011",
|
||||
"http://localhost:4173",
|
||||
"http://localhost:5173",
|
||||
"http://localhost:8000",
|
||||
"http://192.168.103.159:3011",
|
||||
"http://127.0.0.1",
|
||||
"http://192.168.103.159",
|
||||
"http://192.168.103.159:3000",
|
||||
|
|
|
@ -7,7 +7,9 @@ export {}
|
|||
|
||||
declare module 'vue' {
|
||||
export interface GlobalComponents {
|
||||
copy: typeof import('./src/components/Floorplan copy.vue')['default']
|
||||
Floorplan: typeof import('./src/components/Floorplan.vue')['default']
|
||||
FloorplanItem: typeof import('./src/components/FloorplanItem.vue')['default']
|
||||
Game: typeof import('./src/components/Game.vue')['default']
|
||||
Home: typeof import('./src/components/Home.vue')['default']
|
||||
IMdiFile: typeof import('~icons/mdi/file')['default']
|
||||
|
|
|
@ -1,133 +1,25 @@
|
|||
<style lang="scss" scoped></style>
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref } from 'vue';
|
||||
import PF, { Grid } from 'pathfinding'
|
||||
|
||||
import { onMounted, } from 'vue';
|
||||
import { useFloorplanStore } from '../stores/floorplan';
|
||||
|
||||
type PathItem = { path: string, unwalkable: boolean, x: number, y: number }
|
||||
const floorplan = useFloorplanStore()
|
||||
|
||||
const canvasElement = ref();
|
||||
const context = ref();
|
||||
|
||||
const grid = ref<Grid>()
|
||||
const startPoint = ref<{ x: number, y: number }>({ x: 25, y: 40 })
|
||||
const endPoint = ref<{ x: number, y: number }>()
|
||||
const startToEndPath = ref()
|
||||
|
||||
const plan = useFloorplanStore()
|
||||
const paths = ref<PathItem[]>([])
|
||||
|
||||
const finder = new PF.AStarFinder();
|
||||
|
||||
const newDraw = () => {
|
||||
endPoint.value = undefined
|
||||
startToEndPath.value = undefined
|
||||
|
||||
context.value = canvasElement.value?.getContext('2d') || undefined;
|
||||
const lines = plan.np_array
|
||||
lines.forEach((line, indexY) => {
|
||||
line.forEach((point, indexX) => {
|
||||
if (canvasElement.value && context.value) {
|
||||
context.value.fillStyle = point > 0 ? 'purple' : 'WHITE'
|
||||
context.value.fillRect(indexX, indexY, 1, 1)
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
// if (canvasElement.value && context.value) {
|
||||
// context.value.clearRect(0, 0, canvasElement.value.width, canvasElement.value.height);
|
||||
// if (!plan.value.hasOwnProperty('paths')) return
|
||||
// (plan.value).paths.forEach((path: string) => {
|
||||
// if (!context.value) return
|
||||
// context.value.fillStyle = 'rgba(255, 0, 255, 0.25)'
|
||||
// context.value.fill(new Path2D(path));
|
||||
|
||||
// context.value.strokeStyle = 'blue'
|
||||
// context.value.stroke(new Path2D(path));
|
||||
// });
|
||||
// }
|
||||
|
||||
|
||||
const quantum_lines = plan.prepared_array
|
||||
quantum_lines.forEach((line, indexY) => {
|
||||
line.forEach((point, indexX) => {
|
||||
const targetX = indexX * plan.chunkSize
|
||||
const targetY = indexY * plan.chunkSize
|
||||
paths.value.push({
|
||||
path: `M${targetX} ${targetY} ${targetX + plan.chunkSize} ${targetY} ${targetX + plan.chunkSize} ${targetY + plan.chunkSize} ${targetX} ${targetY + plan.chunkSize}Z`,
|
||||
unwalkable: !!point,
|
||||
x: indexX,
|
||||
y: indexY,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
grid.value = new PF.Grid(plan.prepared_array.map(y => y.map(x => x > 0 ? 1 : 0)))
|
||||
}
|
||||
|
||||
const findPath = async () => {
|
||||
if (!endPoint.value) return
|
||||
const localPath = finder.findPath(
|
||||
Math.round(startPoint.value.x),
|
||||
Math.round(startPoint.value.y),
|
||||
Math.round(endPoint.value.x),
|
||||
Math.round(endPoint.value.y),
|
||||
(grid.value?.clone() as Grid)
|
||||
);
|
||||
startToEndPath.value = localPath
|
||||
}
|
||||
|
||||
const setPointSvg = (item: PathItem) => {
|
||||
// startToEndPath.value = []
|
||||
endPoint.value = { x: item.x, y: item.y }
|
||||
findPath()
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await floorplan.getData()
|
||||
newDraw()
|
||||
await floorplan.getList()
|
||||
})
|
||||
const cw = 1920
|
||||
const ch = 800
|
||||
</script>
|
||||
<template>
|
||||
<div class="container" style="display: flex; justify-content: center; align-items: center; flex-direction: column;">
|
||||
<canvas ref="canvasElement" :width="cw" :height="ch"></canvas>
|
||||
<svg ref="svgElement" :width="cw" :height="ch" style="position: absolute;">
|
||||
<path v-for="item in paths" :d="item.path" @click="setPointSvg(item)" :class="[
|
||||
{ 'unwalkable': item.unwalkable },
|
||||
{ 'endPoint': (endPoint && item.x == endPoint.x && item.y == endPoint.y) },
|
||||
{ 'startPoint': (startPoint && item.x == startPoint.x && item.y == startPoint.y) },
|
||||
{ 'pathPoint': (startToEndPath && startToEndPath.find((el: number[]) => el[0] == item.x && el[1] == item.y)) },
|
||||
]">
|
||||
</path>
|
||||
</svg>
|
||||
<div class="container">
|
||||
<ul>
|
||||
<li v-for="item in floorplan.items">
|
||||
<RouterLink :to="`/floorplan/${item.id}`">
|
||||
{{ item.title }}
|
||||
</RouterLink>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
<style scoped>
|
||||
svg path {
|
||||
fill: transparent
|
||||
}
|
||||
|
||||
svg path:hover {
|
||||
fill: red
|
||||
}
|
||||
|
||||
svg path.unwalkable {
|
||||
/* fill: rgba(0, 0, 0, 0.5); */
|
||||
}
|
||||
|
||||
svg path.endPoint {
|
||||
fill: blue;
|
||||
}
|
||||
|
||||
svg path.startPoint {
|
||||
fill: lawngreen;
|
||||
}
|
||||
|
||||
svg path.pathPoint {
|
||||
fill: gold;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,130 @@
|
|||
<style lang="scss" scoped></style>
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref } from 'vue';
|
||||
import PF, { Grid } from 'pathfinding'
|
||||
|
||||
import { useFloorplanStore } from '../stores/floorplan';
|
||||
import { useRoute } from 'vue-router';
|
||||
|
||||
type PathItem = { path: string, unwalkable: boolean, x: number, y: number }
|
||||
const floorplan = useFloorplanStore()
|
||||
|
||||
const canvasElement = ref();
|
||||
const context = ref();
|
||||
|
||||
const grid = ref<Grid>()
|
||||
const startPoint = ref<{ x: number, y: number }>({ x: 25, y: 40 })
|
||||
const endPoint = ref<{ x: number, y: number }>()
|
||||
const startToEndPath = ref()
|
||||
|
||||
const plan = useFloorplanStore()
|
||||
const paths = ref<PathItem[]>([])
|
||||
|
||||
const finder = new PF.AStarFinder();
|
||||
|
||||
const nextFrame = () => new Promise(resolve => requestAnimationFrame(resolve));
|
||||
const route = useRoute()
|
||||
|
||||
const newDraw = async () => {
|
||||
endPoint.value = undefined
|
||||
startToEndPath.value = undefined
|
||||
|
||||
context.value = canvasElement.value?.getContext('2d') || undefined;
|
||||
const lines = plan.np_array
|
||||
for (let indexY = 0; indexY < lines.length; indexY++) {
|
||||
const line = lines[indexY];
|
||||
for (let indexX = 0; indexX < line.length; indexX++) {
|
||||
const point = line[indexX];
|
||||
if (canvasElement.value && context.value && point > 0) {
|
||||
context.value.fillStyle = 'purple'
|
||||
context.value.fillRect(indexX, indexY, 1, 1)
|
||||
}
|
||||
}
|
||||
if (indexY % 4 == 0) {
|
||||
await nextFrame()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const quantum_lines = plan.prepared_array
|
||||
quantum_lines.forEach((line, indexY) => {
|
||||
line.forEach((point, indexX) => {
|
||||
const chunkSize = plan.chunk_size || 8
|
||||
const targetX = indexX * chunkSize
|
||||
const targetY = indexY * chunkSize
|
||||
paths.value.push({
|
||||
path: `M${targetX} ${targetY} ${targetX + chunkSize} ${targetY} ${targetX + chunkSize} ${targetY + chunkSize} ${targetX} ${targetY + chunkSize}Z`,
|
||||
unwalkable: !!point,
|
||||
x: indexX,
|
||||
y: indexY,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
grid.value = new PF.Grid(plan.prepared_array.map(y => y.map(x => x > 0 ? 1 : 0)))
|
||||
}
|
||||
|
||||
const findPath = async () => {
|
||||
if (!endPoint.value) return
|
||||
const localPath = finder.findPath(
|
||||
Math.round(startPoint.value.x),
|
||||
Math.round(startPoint.value.y),
|
||||
Math.round(endPoint.value.x),
|
||||
Math.round(endPoint.value.y),
|
||||
(grid.value?.clone() as Grid)
|
||||
);
|
||||
startToEndPath.value = localPath
|
||||
}
|
||||
|
||||
const setPointSvg = (item: PathItem) => {
|
||||
// startToEndPath.value = []
|
||||
endPoint.value = { x: item.x, y: item.y }
|
||||
findPath()
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
await floorplan.getData(parseInt(route.params.id as string))
|
||||
newDraw()
|
||||
})
|
||||
const cw = 1920
|
||||
const ch = 800
|
||||
</script>
|
||||
<template>
|
||||
<div class="container" style="display: flex; justify-content: center; align-items: center; flex-direction: column;">
|
||||
<canvas ref="canvasElement" :width="cw" :height="ch"></canvas>
|
||||
<svg ref="svgElement" :width="cw" :height="ch" style="position: absolute;">
|
||||
<path v-for="item in paths" :d="item.path" @click="setPointSvg(item)" :class="[
|
||||
{ 'unwalkable': item.unwalkable },
|
||||
{ 'endPoint': (endPoint && item.x == endPoint.x && item.y == endPoint.y) },
|
||||
{ 'startPoint': (startPoint && item.x == startPoint.x && item.y == startPoint.y) },
|
||||
{ 'pathPoint': (startToEndPath && startToEndPath.find((el: number[]) => el[0] == item.x && el[1] == item.y)) },
|
||||
]">
|
||||
</path>
|
||||
</svg>
|
||||
</div>
|
||||
</template>
|
||||
<style scoped>
|
||||
svg path {
|
||||
fill: transparent
|
||||
}
|
||||
|
||||
svg path:hover {
|
||||
fill: red
|
||||
}
|
||||
|
||||
svg path.unwalkable {
|
||||
/* fill: rgba(0, 0, 0, 0.5); */
|
||||
}
|
||||
|
||||
svg path.endPoint {
|
||||
fill: blue;
|
||||
}
|
||||
|
||||
svg path.startPoint {
|
||||
fill: lawngreen;
|
||||
}
|
||||
|
||||
svg path.pathPoint {
|
||||
fill: gold;
|
||||
}
|
||||
</style>
|
|
@ -9,12 +9,14 @@ import Home from './components/Home.vue'
|
|||
import Projects from './components/Projects.vue'
|
||||
import Game from './components/Game.vue'
|
||||
import Floorplan from './components/Floorplan.vue'
|
||||
import FloorplanItem from './components/FloorplanItem.vue'
|
||||
|
||||
const routes = [
|
||||
{ path: '/', component: Home },
|
||||
{ path: '/projects', component: Projects },
|
||||
{ path: '/game', component: Game },
|
||||
{ path: '/floorplan', component: Floorplan },
|
||||
{ path: '/floorplan/:id', component: FloorplanItem },
|
||||
]
|
||||
|
||||
const router = createRouter({
|
||||
|
|
|
@ -5,34 +5,60 @@ import { chunks } from '../helpers'
|
|||
export const useFloorplanStore = defineStore('floorplan', {
|
||||
state: () => {
|
||||
return {
|
||||
items: [] as { id: string, title: string }[],
|
||||
title: undefined,
|
||||
chunkSize: 7,
|
||||
np_array: [] as number[][],
|
||||
prepared_array: [] as number[][]
|
||||
prepared_array: [] as number[][],
|
||||
chunk_size: undefined as number | undefined,
|
||||
threshold: undefined as number | undefined,
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
async getData() {
|
||||
async getList() {
|
||||
try {
|
||||
const res = await fetch(`${SERVER_URL}/api/floorplan`)
|
||||
const res = await fetch(`${SERVER_URL}/api/floorplan/`, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json'
|
||||
},
|
||||
})
|
||||
const data = await res.json()
|
||||
this.items = data
|
||||
// this.title = data.title
|
||||
// this.np_array = data.np_field
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
}
|
||||
},
|
||||
async getData(id: number) {
|
||||
try {
|
||||
const res = await fetch(`${SERVER_URL}/api/floorplan/${id}`, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json'
|
||||
},
|
||||
})
|
||||
const data = await res.json()
|
||||
this.title = data.title
|
||||
this.np_array = data.np_field
|
||||
this.prepared_array = [...chunks(data.np_field, this.chunkSize)].map(line => {
|
||||
this.chunk_size = data.d_size || 8
|
||||
this.threshold = data.d_border || 20
|
||||
|
||||
this.prepared_array = [...chunks(data.np_field, this.chunk_size as number)].map(line => {
|
||||
const line_data = [] as any[][]
|
||||
line.map((item: any) => [...chunks(item, this.chunkSize)]).map((item) => {
|
||||
line.map((item: any) => [...chunks(item, this.chunk_size as number)]).map((item) => {
|
||||
item.map((one_line, k) => {
|
||||
if (!line_data[k]) line_data[k] = []
|
||||
line_data[k].push(...one_line)
|
||||
})
|
||||
})
|
||||
return line_data.map(el => {
|
||||
return el.filter(e => e > 0).length > 20 ? 1 : 0
|
||||
return el.filter(e => e > 0).length > (this.threshold as number) ? 1 : 0
|
||||
})
|
||||
});
|
||||
} catch (error) {
|
||||
// this.list = []
|
||||
console.log(error)
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
})
|
|
@ -27,5 +27,5 @@ build-backend = "poetry.core.masonry.api"
|
|||
export_req = "poetry export --without-hashes --format=requirements.txt > back/requirements.txt"
|
||||
server = "back/manage.py runserver 0.0.0.0:8000"
|
||||
front = "cd front && npm run build && npm run preview"
|
||||
front_dev = "cd front && npm run dev"
|
||||
front_dev = "cd front && npm run dev -- --host"
|
||||
admin_front_dev = "cd admin_front && npm run dev"
|
Loading…
Reference in New Issue