bx-865-apps #1

Merged
ksenia_mikhailova merged 140 commits from bx-865-apps into main 2024-06-27 15:03:27 +03:00
8 changed files with 187 additions and 132 deletions
Showing only changes of commit ac66af1fd7 - Show all commits

View File

@ -8579,7 +8579,7 @@
"kind": 5, "kind": 5,
"importPath": "back.back.settings", "importPath": "back.back.settings",
"description": "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", "detail": "back.back.settings",
"documentation": {} "documentation": {}
}, },
@ -8588,7 +8588,7 @@
"kind": 5, "kind": 5,
"importPath": "back.back.settings", "importPath": "back.back.settings",
"description": "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", "detail": "back.back.settings",
"documentation": {} "documentation": {}
}, },
@ -8597,7 +8597,7 @@
"kind": 5, "kind": 5,
"importPath": "back.back.settings", "importPath": "back.back.settings",
"description": "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", "detail": "back.back.settings",
"documentation": {} "documentation": {}
}, },

View File

@ -44,17 +44,20 @@ CSRF_TRUSTED_ORIGINS = (
"https://demo.kustarshina.ru", "https://demo.kustarshina.ru",
"http://localhost", "http://localhost",
"http://localhost:3011", "http://localhost:3011",
"http://localhost:4173",
"http://localhost:5173",
"http://192.168.103.159:3011",
"http://192.168.103.159", "http://192.168.103.159",
) )
CORS_ORIGIN_ALLOW_ALL = False CORS_ORIGIN_ALLOW_ALL = False
CORS_ORIGIN_WHITELIST = [ CORS_ORIGIN_WHITELIST = [
"null", "null",
"http://localhost", "http://localhost",
"http://localhost:3000",
"http://localhost:3011", "http://localhost:3011",
"http://localhost:4173", "http://localhost:4173",
"http://localhost:5173", "http://localhost:5173",
"http://localhost:8000", "http://localhost:8000",
"http://192.168.103.159:3011",
"http://127.0.0.1", "http://127.0.0.1",
"http://192.168.103.159", "http://192.168.103.159",
"http://192.168.103.159:3000", "http://192.168.103.159:3000",

View File

@ -7,7 +7,9 @@ export {}
declare module 'vue' { declare module 'vue' {
export interface GlobalComponents { export interface GlobalComponents {
copy: typeof import('./src/components/Floorplan copy.vue')['default']
Floorplan: typeof import('./src/components/Floorplan.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'] Game: typeof import('./src/components/Game.vue')['default']
Home: typeof import('./src/components/Home.vue')['default'] Home: typeof import('./src/components/Home.vue')['default']
IMdiFile: typeof import('~icons/mdi/file')['default'] IMdiFile: typeof import('~icons/mdi/file')['default']

View File

@ -1,133 +1,25 @@
<style lang="scss" scoped></style> <style lang="scss" scoped></style>
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, ref } from 'vue'; import { onMounted, } from 'vue';
import PF, { Grid } from 'pathfinding'
import { useFloorplanStore } from '../stores/floorplan'; import { useFloorplanStore } from '../stores/floorplan';
type PathItem = { path: string, unwalkable: boolean, x: number, y: number }
const floorplan = useFloorplanStore() 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 () => { onMounted(async () => {
await floorplan.getData() await floorplan.getList()
newDraw()
}) })
const cw = 1920
const ch = 800
</script> </script>
<template> <template>
<div class="container" style="display: flex; justify-content: center; align-items: center; flex-direction: column;"> <div class="container">
<canvas ref="canvasElement" :width="cw" :height="ch"></canvas> <ul>
<svg ref="svgElement" :width="cw" :height="ch" style="position: absolute;"> <li v-for="item in floorplan.items">
<path v-for="item in paths" :d="item.path" @click="setPointSvg(item)" :class="[ <RouterLink :to="`/floorplan/${item.id}`">
{ 'unwalkable': item.unwalkable }, {{ item.title }}
{ 'endPoint': (endPoint && item.x == endPoint.x && item.y == endPoint.y) }, </RouterLink>
{ 'startPoint': (startPoint && item.x == startPoint.x && item.y == startPoint.y) }, </li>
{ 'pathPoint': (startToEndPath && startToEndPath.find((el: number[]) => el[0] == item.x && el[1] == item.y)) }, </ul>
]">
</path>
</svg>
</div> </div>
</template> </template>
<style scoped> <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> </style>

View File

@ -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>

View File

@ -9,12 +9,14 @@ import Home from './components/Home.vue'
import Projects from './components/Projects.vue' import Projects from './components/Projects.vue'
import Game from './components/Game.vue' import Game from './components/Game.vue'
import Floorplan from './components/Floorplan.vue' import Floorplan from './components/Floorplan.vue'
import FloorplanItem from './components/FloorplanItem.vue'
const routes = [ const routes = [
{ path: '/', component: Home }, { path: '/', component: Home },
{ path: '/projects', component: Projects }, { path: '/projects', component: Projects },
{ path: '/game', component: Game }, { path: '/game', component: Game },
{ path: '/floorplan', component: Floorplan }, { path: '/floorplan', component: Floorplan },
{ path: '/floorplan/:id', component: FloorplanItem },
] ]
const router = createRouter({ const router = createRouter({

View File

@ -5,34 +5,60 @@ import { chunks } from '../helpers'
export const useFloorplanStore = defineStore('floorplan', { export const useFloorplanStore = defineStore('floorplan', {
state: () => { state: () => {
return { return {
items: [] as { id: string, title: string }[],
title: undefined, title: undefined,
chunkSize: 7,
np_array: [] as number[][], np_array: [] as number[][],
prepared_array: [] as number[][] prepared_array: [] as number[][],
chunk_size: undefined as number | undefined,
threshold: undefined as number | undefined,
} }
}, },
actions: { actions: {
async getData() { async getList() {
try { 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() const data = await res.json()
this.title = data.title this.title = data.title
this.np_array = data.np_field 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[][] 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) => { item.map((one_line, k) => {
if (!line_data[k]) line_data[k] = [] if (!line_data[k]) line_data[k] = []
line_data[k].push(...one_line) line_data[k].push(...one_line)
}) })
}) })
return line_data.map(el => { 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) { } catch (error) {
// this.list = [] console.log(error)
}
} }
},
} }
}) })

View File

@ -27,5 +27,5 @@ build-backend = "poetry.core.masonry.api"
export_req = "poetry export --without-hashes --format=requirements.txt > back/requirements.txt" export_req = "poetry export --without-hashes --format=requirements.txt > back/requirements.txt"
server = "back/manage.py runserver 0.0.0.0:8000" server = "back/manage.py runserver 0.0.0.0:8000"
front = "cd front && npm run build && npm run preview" 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" admin_front_dev = "cd admin_front && npm run dev"