some more changes
This commit is contained in:
parent
bbdeea5031
commit
6050903c09
55 changed files with 1394 additions and 5468 deletions
1
.npmrc
1
.npmrc
|
@ -1 +0,0 @@
|
||||||
engine-strict=true
|
|
75
Cargo.lock
generated
75
Cargo.lock
generated
|
@ -734,8 +734,18 @@ version = "0.13.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c"
|
checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"darling_core",
|
"darling_core 0.13.4",
|
||||||
"darling_macro",
|
"darling_macro 0.13.4",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "darling"
|
||||||
|
version = "0.14.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850"
|
||||||
|
dependencies = [
|
||||||
|
"darling_core 0.14.4",
|
||||||
|
"darling_macro 0.14.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -752,13 +762,38 @@ dependencies = [
|
||||||
"syn 1.0.109",
|
"syn 1.0.109",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "darling_core"
|
||||||
|
version = "0.14.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0"
|
||||||
|
dependencies = [
|
||||||
|
"fnv",
|
||||||
|
"ident_case",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"strsim",
|
||||||
|
"syn 1.0.109",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "darling_macro"
|
name = "darling_macro"
|
||||||
version = "0.13.4"
|
version = "0.13.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835"
|
checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"darling_core",
|
"darling_core 0.13.4",
|
||||||
|
"quote",
|
||||||
|
"syn 1.0.109",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "darling_macro"
|
||||||
|
version = "0.14.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e"
|
||||||
|
dependencies = [
|
||||||
|
"darling_core 0.14.4",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 1.0.109",
|
"syn 1.0.109",
|
||||||
]
|
]
|
||||||
|
@ -800,6 +835,37 @@ dependencies = [
|
||||||
"syn 1.0.109",
|
"syn 1.0.109",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "derive_builder"
|
||||||
|
version = "0.12.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8d67778784b508018359cbc8696edb3db78160bab2c2a28ba7f56ef6932997f8"
|
||||||
|
dependencies = [
|
||||||
|
"derive_builder_macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "derive_builder_core"
|
||||||
|
version = "0.12.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f"
|
||||||
|
dependencies = [
|
||||||
|
"darling 0.14.4",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 1.0.109",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "derive_builder_macro"
|
||||||
|
version = "0.12.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ebcda35c7a396850a55ffeac740804b40ffec779b98fffbb1738f4033f0ee79e"
|
||||||
|
dependencies = [
|
||||||
|
"derive_builder_core",
|
||||||
|
"syn 1.0.109",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "derive_more"
|
name = "derive_more"
|
||||||
version = "0.99.17"
|
version = "0.99.17"
|
||||||
|
@ -3957,7 +4023,7 @@ version = "1.5.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082"
|
checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"darling",
|
"darling 0.13.4",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 1.0.109",
|
"syn 1.0.109",
|
||||||
|
@ -4738,6 +4804,7 @@ name = "triangle"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
|
"derive_builder",
|
||||||
"triangle-sys",
|
"triangle-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
workspace.members = ["backend", "prisma-cli", "triangle", "triangle-sys"]
|
workspace.members = ["backend", "prisma-cli", "triangle", "triangle-sys"]
|
||||||
workspace.resolver = "2"
|
workspace.resolver = "2"
|
||||||
|
workspace.default-members = ["backend"]
|
||||||
|
|
|
@ -3,8 +3,6 @@ name = "backend"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.76"
|
anyhow = "1.0.76"
|
||||||
axum = { version = "0.7.2", features = ["http2"] }
|
axum = { version = "0.7.2", features = ["http2"] }
|
||||||
|
|
|
@ -12,7 +12,7 @@ async fn main() -> Result<()> {
|
||||||
|
|
||||||
let app = Router::new().route("/", get(|| async { "Hello, World!" }));
|
let app = Router::new().route("/", get(|| async { "Hello, World!" }));
|
||||||
|
|
||||||
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await?;
|
let listener = tokio::net::TcpListener::bind("0.0.0.0:1440").await?;
|
||||||
axum::serve(listener, app).await?;
|
axum::serve(listener, app).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
17
biome.json
Normal file
17
biome.json
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://biomejs.dev/schemas/1.4.1/schema.json",
|
||||||
|
"organizeImports": {
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
"linter": {
|
||||||
|
"enabled": true,
|
||||||
|
"rules": {
|
||||||
|
"recommended": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"formatter": {
|
||||||
|
"enabled": true,
|
||||||
|
"indentWidth": 2,
|
||||||
|
"indentStyle": "space"
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,17 +0,0 @@
|
||||||
{
|
|
||||||
"name": "your-project-name",
|
|
||||||
"sources": [
|
|
||||||
{
|
|
||||||
"dir": "rescript",
|
|
||||||
"subdirs": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"package-specs": [
|
|
||||||
{
|
|
||||||
"module": "es6",
|
|
||||||
"in-source": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"suffix": ".bs.js",
|
|
||||||
"bs-dependencies": []
|
|
||||||
}
|
|
18
frontend/.eslintrc.cjs
Normal file
18
frontend/.eslintrc.cjs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
module.exports = {
|
||||||
|
root: true,
|
||||||
|
env: { browser: true, es2020: true },
|
||||||
|
extends: [
|
||||||
|
'eslint:recommended',
|
||||||
|
'plugin:@typescript-eslint/recommended',
|
||||||
|
'plugin:react-hooks/recommended',
|
||||||
|
],
|
||||||
|
ignorePatterns: ['dist', '.eslintrc.cjs'],
|
||||||
|
parser: '@typescript-eslint/parser',
|
||||||
|
plugins: ['react-refresh'],
|
||||||
|
rules: {
|
||||||
|
'react-refresh/only-export-components': [
|
||||||
|
'warn',
|
||||||
|
{ allowConstantExport: true },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
24
frontend/.gitignore
vendored
Normal file
24
frontend/.gitignore
vendored
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
dist-ssr
|
||||||
|
*.local
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.idea
|
||||||
|
.DS_Store
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
30
frontend/README.md
Normal file
30
frontend/README.md
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
# React + TypeScript + Vite
|
||||||
|
|
||||||
|
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
|
||||||
|
|
||||||
|
Currently, two official plugins are available:
|
||||||
|
|
||||||
|
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
|
||||||
|
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
|
||||||
|
|
||||||
|
## Expanding the ESLint configuration
|
||||||
|
|
||||||
|
If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
|
||||||
|
|
||||||
|
- Configure the top-level `parserOptions` property like this:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export default {
|
||||||
|
// other rules...
|
||||||
|
parserOptions: {
|
||||||
|
ecmaVersion: 'latest',
|
||||||
|
sourceType: 'module',
|
||||||
|
project: ['./tsconfig.json', './tsconfig.node.json'],
|
||||||
|
tsconfigRootDir: __dirname,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked`
|
||||||
|
- Optionally add `plugin:@typescript-eslint/stylistic-type-checked`
|
||||||
|
- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list
|
13
frontend/index.html
Normal file
13
frontend/index.html
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Vite + React + TS</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="root"></div>
|
||||||
|
<script type="module" src="/src/main.tsx"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
37
frontend/package.json
Normal file
37
frontend/package.json
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
{
|
||||||
|
"name": "frontend",
|
||||||
|
"private": true,
|
||||||
|
"version": "0.0.0",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "tsc && vite build",
|
||||||
|
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
||||||
|
"preview": "vite preview"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@blueprintjs/core": "^5.7.2",
|
||||||
|
"@blueprintjs/icons": "^5.5.0",
|
||||||
|
"@blueprintjs/table": "^5.0.20",
|
||||||
|
"@react-three/fiber": "^8.15.12",
|
||||||
|
"@types/three": "^0.160.0",
|
||||||
|
"normalize.css": "^8.0.1",
|
||||||
|
"react": "^18.2.0",
|
||||||
|
"react-dom": "^18.2.0",
|
||||||
|
"react-router-dom": "^6.21.1",
|
||||||
|
"three": "^0.160.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/react": "^18.2.43",
|
||||||
|
"@types/react-dom": "^18.2.17",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^6.14.0",
|
||||||
|
"@typescript-eslint/parser": "^6.14.0",
|
||||||
|
"@vitejs/plugin-react-swc": "^3.5.0",
|
||||||
|
"eslint": "^8.55.0",
|
||||||
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
|
"eslint-plugin-react-refresh": "^0.4.5",
|
||||||
|
"sass": "^1.69.6",
|
||||||
|
"typescript": "^5.2.2",
|
||||||
|
"vite": "^5.0.8"
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load diff
1
frontend/public/vite.svg
Normal file
1
frontend/public/vite.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
After Width: | Height: | Size: 1.5 KiB |
15
frontend/src/App.css
Normal file
15
frontend/src/App.css
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
html,body,#root {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#root {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
#root > main {
|
||||||
|
flex-shrink: 1;
|
||||||
|
min-height: 0;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
11
frontend/src/App.tsx
Normal file
11
frontend/src/App.tsx
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import "./App.css";
|
||||||
|
import { createBrowserRouter, RouterProvider } from "react-router-dom";
|
||||||
|
import routes from "./routes";
|
||||||
|
|
||||||
|
const router = createBrowserRouter(routes);
|
||||||
|
|
||||||
|
function App() {
|
||||||
|
return <RouterProvider router={router} />;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default App;
|
26
frontend/src/Layout.tsx
Normal file
26
frontend/src/Layout.tsx
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
import { Outlet, Link } from "react-router-dom";
|
||||||
|
import { Alignment, Icon, Navbar } from "@blueprintjs/core";
|
||||||
|
|
||||||
|
export default function Layout() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Navbar>
|
||||||
|
<Navbar.Group align={Alignment.LEFT}>
|
||||||
|
<Navbar.Heading>OpenStellaris</Navbar.Heading>
|
||||||
|
<Navbar.Divider />
|
||||||
|
|
||||||
|
<Link className="bp5-button bp5-minimal" role="button" to="/">
|
||||||
|
<Icon icon="path-search" />
|
||||||
|
Map
|
||||||
|
</Link>
|
||||||
|
<Link className="bp5-button bp5-minimal" role="button" to="/planets">
|
||||||
|
<Icon icon="panel-table" />
|
||||||
|
Planets
|
||||||
|
</Link>
|
||||||
|
</Navbar.Group>
|
||||||
|
</Navbar>
|
||||||
|
|
||||||
|
<Outlet />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
16
frontend/src/main.tsx
Normal file
16
frontend/src/main.tsx
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import React from "react";
|
||||||
|
import ReactDOM from "react-dom/client";
|
||||||
|
import App from "./App.tsx";
|
||||||
|
|
||||||
|
import "normalize.css";
|
||||||
|
import "@blueprintjs/core/lib/css/blueprint.css";
|
||||||
|
import "@blueprintjs/icons/lib/css/blueprint-icons.css";
|
||||||
|
|
||||||
|
// biome-ignore lint/style/noNonNullAssertion: <explanation>
|
||||||
|
const el = document.getElementById("root")!;
|
||||||
|
|
||||||
|
ReactDOM.createRoot(el).render(
|
||||||
|
<React.StrictMode>
|
||||||
|
<App />
|
||||||
|
</React.StrictMode>,
|
||||||
|
);
|
40
frontend/src/routes/MapView.tsx
Normal file
40
frontend/src/routes/MapView.tsx
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
import { useRef, useState } from "react";
|
||||||
|
import { Canvas, useFrame, type MeshProps } from "@react-three/fiber";
|
||||||
|
import styles from "./MapView.module.scss";
|
||||||
|
|
||||||
|
export default function MapView() {
|
||||||
|
return (
|
||||||
|
<main className={styles.main}>
|
||||||
|
<Canvas>
|
||||||
|
<ambientLight />
|
||||||
|
<pointLight position={[10, 10, 10]} />
|
||||||
|
<Box position={[-1.2, 0, 0]} />
|
||||||
|
<Box position={[1.2, 0, 0]} />
|
||||||
|
</Canvas>
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function Box(props: MeshProps) {
|
||||||
|
// This reference will give us direct access to the mesh
|
||||||
|
const meshRef = useRef();
|
||||||
|
// Set up state for the hovered and active state
|
||||||
|
const [hovered, setHover] = useState(false);
|
||||||
|
const [active, setActive] = useState(false);
|
||||||
|
// Subscribe this component to the render-loop, rotate the mesh every frame
|
||||||
|
useFrame((_state, delta) => (meshRef.current.rotation.x += delta));
|
||||||
|
// Return view, these are regular three.js elements expressed in JSX
|
||||||
|
return (
|
||||||
|
<mesh
|
||||||
|
{...props}
|
||||||
|
ref={meshRef}
|
||||||
|
scale={active ? 1.5 : 1}
|
||||||
|
onClick={(_event) => setActive(!active)}
|
||||||
|
onPointerOver={(_event) => setHover(true)}
|
||||||
|
onPointerOut={(_event) => setHover(false)}
|
||||||
|
>
|
||||||
|
<boxGeometry args={[1, 1, 1]} />
|
||||||
|
<meshStandardMaterial color={hovered ? "hotpink" : "orange"} />
|
||||||
|
</mesh>
|
||||||
|
);
|
||||||
|
}
|
3
frontend/src/routes/PlanetsView.tsx
Normal file
3
frontend/src/routes/PlanetsView.tsx
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
export default function PlanetsView() {
|
||||||
|
return <main>Planets</main>;
|
||||||
|
}
|
23
frontend/src/routes/index.tsx
Normal file
23
frontend/src/routes/index.tsx
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
import type { RouteObject } from "react-router-dom";
|
||||||
|
import Layout from "../Layout";
|
||||||
|
import MapView from "./MapView";
|
||||||
|
import PlanetsView from "./PlanetsView";
|
||||||
|
|
||||||
|
const routes: RouteObject[] = [
|
||||||
|
{
|
||||||
|
path: "/",
|
||||||
|
element: <Layout />,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "/",
|
||||||
|
element: <MapView />,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/planets",
|
||||||
|
element: <PlanetsView />,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default routes;
|
1
frontend/src/vite-env.d.ts
vendored
Normal file
1
frontend/src/vite-env.d.ts
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/// <reference types="vite/client" />
|
25
frontend/tsconfig.json
Normal file
25
frontend/tsconfig.json
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ES2020",
|
||||||
|
"useDefineForClassFields": true,
|
||||||
|
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
||||||
|
"module": "ESNext",
|
||||||
|
"skipLibCheck": true,
|
||||||
|
|
||||||
|
/* Bundler mode */
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
|
||||||
|
/* Linting */
|
||||||
|
"strict": true,
|
||||||
|
"noUnusedLocals": true,
|
||||||
|
"noUnusedParameters": true,
|
||||||
|
"noFallthroughCasesInSwitch": true
|
||||||
|
},
|
||||||
|
"include": ["src"],
|
||||||
|
"references": [{ "path": "./tsconfig.node.json" }]
|
||||||
|
}
|
10
frontend/tsconfig.node.json
Normal file
10
frontend/tsconfig.node.json
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"composite": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"allowSyntheticDefaultImports": true
|
||||||
|
},
|
||||||
|
"include": ["vite.config.ts"]
|
||||||
|
}
|
16
frontend/vite.config.ts
Normal file
16
frontend/vite.config.ts
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import { defineConfig } from "vite";
|
||||||
|
import react from "@vitejs/plugin-react-swc";
|
||||||
|
|
||||||
|
// https://vitejs.dev/config/
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [react()],
|
||||||
|
server: {
|
||||||
|
proxy: {
|
||||||
|
"/api": {
|
||||||
|
target: "http://localhost:1440",
|
||||||
|
changeOrigin: true,
|
||||||
|
rewrite: (path) => path.replace(/^\/api/, ""),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
3779
package-lock.json
generated
3779
package-lock.json
generated
File diff suppressed because it is too large
Load diff
44
package.json
44
package.json
|
@ -1,44 +0,0 @@
|
||||||
{
|
|
||||||
"name": "openstellaris",
|
|
||||||
"version": "0.0.1",
|
|
||||||
"private": true,
|
|
||||||
"scripts": {
|
|
||||||
"dev": "vite dev",
|
|
||||||
"build": "vite build",
|
|
||||||
"preview": "vite preview",
|
|
||||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
|
||||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
|
||||||
"test": "vitest",
|
|
||||||
"lint": "prettier --check . && eslint .",
|
|
||||||
"format": "prettier --write ."
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@sveltejs/adapter-auto": "^2.0.0",
|
|
||||||
"@sveltejs/kit": "^1.27.4",
|
|
||||||
"@types/delaunator": "^5.0.2",
|
|
||||||
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
|
||||||
"@typescript-eslint/parser": "^6.0.0",
|
|
||||||
"eslint": "^8.28.0",
|
|
||||||
"eslint-config-prettier": "^9.0.0",
|
|
||||||
"eslint-plugin-svelte": "^2.30.0",
|
|
||||||
"prettier": "^3.0.0",
|
|
||||||
"prettier-plugin-svelte": "^3.0.0",
|
|
||||||
"prisma": "^5.7.0",
|
|
||||||
"rescript": "^10.1.4",
|
|
||||||
"svelte": "^4.2.7",
|
|
||||||
"svelte-check": "^3.6.0",
|
|
||||||
"tslib": "^2.4.1",
|
|
||||||
"typescript": "^5.0.0",
|
|
||||||
"vite": "^4.4.2",
|
|
||||||
"vitest": "^0.34.0"
|
|
||||||
},
|
|
||||||
"type": "module",
|
|
||||||
"dependencies": {
|
|
||||||
"@auth/core": "^0.18.4",
|
|
||||||
"@auth/prisma-adapter": "^1.0.9",
|
|
||||||
"@auth/sveltekit": "^0.3.15",
|
|
||||||
"@prisma/client": "5.7.0",
|
|
||||||
"delaunator": "^5.0.0",
|
|
||||||
"sass": "^1.69.5"
|
|
||||||
}
|
|
||||||
}
|
|
12
src/app.d.ts
vendored
12
src/app.d.ts
vendored
|
@ -1,12 +0,0 @@
|
||||||
// See https://kit.svelte.dev/docs/types#app
|
|
||||||
// for information about these interfaces
|
|
||||||
declare global {
|
|
||||||
namespace App {
|
|
||||||
// interface Error {}
|
|
||||||
// interface Locals {}
|
|
||||||
// interface PageData {}
|
|
||||||
// interface Platform {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export {};
|
|
12
src/app.html
12
src/app.html
|
@ -1,12 +0,0 @@
|
||||||
<!doctype html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
||||||
%sveltekit.head%
|
|
||||||
</head>
|
|
||||||
<body data-sveltekit-preload-data="hover">
|
|
||||||
<div style="display: contents">%sveltekit.body%</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,25 +0,0 @@
|
||||||
import {
|
|
||||||
AUTH_SECRET,
|
|
||||||
DISCORD_CLIENT_ID,
|
|
||||||
DISCORD_CLIENT_SECRET,
|
|
||||||
} from "$env/static/private";
|
|
||||||
import Discord from "@auth/core/providers/discord";
|
|
||||||
import { SvelteKitAuth } from "@auth/sveltekit";
|
|
||||||
import { PrismaAdapter } from "@auth/prisma-adapter";
|
|
||||||
import { PrismaClient } from "@prisma/client";
|
|
||||||
|
|
||||||
const prisma = new PrismaClient();
|
|
||||||
|
|
||||||
export const handle = SvelteKitAuth(async (event) => {
|
|
||||||
return {
|
|
||||||
secret: AUTH_SECRET,
|
|
||||||
trustHost: true,
|
|
||||||
adapter: PrismaAdapter(prisma),
|
|
||||||
providers: [
|
|
||||||
Discord({
|
|
||||||
clientId: DISCORD_CLIENT_ID,
|
|
||||||
clientSecret: DISCORD_CLIENT_SECRET,
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
};
|
|
||||||
});
|
|
|
@ -1,7 +0,0 @@
|
||||||
import { describe, it, expect } from "vitest";
|
|
||||||
|
|
||||||
describe("sum test", () => {
|
|
||||||
it("adds 1 + 2 to equal 3", () => {
|
|
||||||
expect(1 + 2).toBe(3);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1 +0,0 @@
|
||||||
// place files you want to import through the `$lib` alias in this folder.
|
|
|
@ -1,144 +0,0 @@
|
||||||
import Delaunator from "delaunator";
|
|
||||||
import { euclideanDistance, lawOfCosines } from "./math";
|
|
||||||
|
|
||||||
export interface MapGenOptions {
|
|
||||||
numSystems?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface MapGenResult {
|
|
||||||
nodes: { x: number; y: number }[];
|
|
||||||
adj: Map<number, Set<number>>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function mapGen(opts: MapGenOptions = {}): MapGenResult {
|
|
||||||
const nodes = [];
|
|
||||||
const adj = new Map<number, Set<number>>();
|
|
||||||
|
|
||||||
const numSystems = opts.numSystems ?? 1000;
|
|
||||||
for (let i = 0; i < numSystems; ++i) {
|
|
||||||
nodes.push({
|
|
||||||
x: Math.floor(Math.random() * 800),
|
|
||||||
y: Math.floor(Math.random() * 600),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove nodes that are too close
|
|
||||||
// eslint-disable-next-line no-constant-condition
|
|
||||||
while (true) {
|
|
||||||
let idx = null;
|
|
||||||
let ctr = 0;
|
|
||||||
for (const node of nodes) {
|
|
||||||
for (const otherNode of nodes) {
|
|
||||||
if (node == otherNode) continue;
|
|
||||||
|
|
||||||
const dist = euclideanDistance(
|
|
||||||
node.x,
|
|
||||||
node.y,
|
|
||||||
otherNode.x,
|
|
||||||
otherNode.y,
|
|
||||||
);
|
|
||||||
if (dist < 25) {
|
|
||||||
idx = ctr;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (idx !== null) break;
|
|
||||||
ctr += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (idx !== null) nodes.splice(idx, 1);
|
|
||||||
else break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate edges
|
|
||||||
const delaunay = new Delaunator(nodes.flatMap((node) => [node.x, node.y]));
|
|
||||||
console.log("result", delaunay);
|
|
||||||
|
|
||||||
for (let i = 0; i < delaunay.triangles.length; i += 3) {
|
|
||||||
const a = delaunay.triangles[i];
|
|
||||||
const b = delaunay.triangles[i + 1];
|
|
||||||
const c = delaunay.triangles[i + 2];
|
|
||||||
|
|
||||||
const an = nodes[a];
|
|
||||||
const bn = nodes[b];
|
|
||||||
const cn = nodes[c];
|
|
||||||
|
|
||||||
const ab = euclideanDistance(an.x, an.y, bn.x, bn.y);
|
|
||||||
const ac = euclideanDistance(an.x, an.y, cn.x, cn.y);
|
|
||||||
const bc = euclideanDistance(bn.x, bn.y, cn.x, cn.y);
|
|
||||||
|
|
||||||
const angA = lawOfCosines(bc, ab, ac);
|
|
||||||
const angB = lawOfCosines(ac, bc, ab);
|
|
||||||
const angC = lawOfCosines(ab, bc, ac);
|
|
||||||
|
|
||||||
const threshold = Math.PI / 6;
|
|
||||||
if (angA < threshold || angB < threshold || angC < threshold) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!adj.has(a)) adj.set(a, new Set());
|
|
||||||
if (!adj.has(b)) adj.set(b, new Set());
|
|
||||||
if (!adj.has(c)) adj.set(c, new Set());
|
|
||||||
|
|
||||||
adj.get(a)?.add(b);
|
|
||||||
adj.get(a)?.add(c);
|
|
||||||
|
|
||||||
adj.get(b)?.add(a);
|
|
||||||
adj.get(b)?.add(c);
|
|
||||||
|
|
||||||
adj.get(c)?.add(a);
|
|
||||||
adj.get(c)?.add(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove hull
|
|
||||||
const hull = new Set(delaunay.hull);
|
|
||||||
for (const [nodeIdx, neighborIdxs] of adj) {
|
|
||||||
if (!hull.has(nodeIdx)) continue;
|
|
||||||
|
|
||||||
for (const neighborIdx of neighborIdxs) {
|
|
||||||
if (hull.has(neighborIdx)) {
|
|
||||||
adj.get(nodeIdx)?.delete(neighborIdx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Randomly remove some edges
|
|
||||||
// for (const [nodeIdx, neighborIdxs] of adj) {
|
|
||||||
// const numNeighbors = neighborIdxs.size;
|
|
||||||
|
|
||||||
// // Reverse weight
|
|
||||||
// const weightSlices = ((numNeighbors + 1) * numNeighbors) / 2;
|
|
||||||
// const sliceWidth = 1 / weightSlices;
|
|
||||||
// const roll = Math.random();
|
|
||||||
// const whichSlice = Math.floor(roll / sliceWidth);
|
|
||||||
// const whichTriangleNum = Math.floor(
|
|
||||||
// (-1 + Math.sqrt(1 + 8 * whichSlice)) / 2,
|
|
||||||
// );
|
|
||||||
// const actualWeight = numNeighbors - whichTriangleNum;
|
|
||||||
// const toRemove = numNeighbors - actualWeight;
|
|
||||||
|
|
||||||
// const asArray = [...neighborIdxs];
|
|
||||||
// const toRemoveSet = new Set();
|
|
||||||
// while (toRemoveSet.size < toRemove) {
|
|
||||||
// const idx = Math.floor(Math.random() * asArray.length);
|
|
||||||
// toRemoveSet.add(idx);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const newArray = [];
|
|
||||||
// for (let i = 0; i < asArray.length; ++i) {
|
|
||||||
// if (toRemoveSet.has(i)) continue;
|
|
||||||
// newArray.push(asArray[i]);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// adj.set(nodeIdx, new Set(newArray));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Make sure each edge has a reverse edge
|
|
||||||
for (const [nodeIdx, neighborIdxs] of adj) {
|
|
||||||
for (const neighborIdx of neighborIdxs) {
|
|
||||||
adj.get(neighborIdx)?.add(nodeIdx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return { nodes, adj };
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
export function euclideanDistance(
|
|
||||||
x1: number,
|
|
||||||
y1: number,
|
|
||||||
x2: number,
|
|
||||||
y2: number,
|
|
||||||
): number {
|
|
||||||
return Math.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function lawOfCosines(
|
|
||||||
opposite: number,
|
|
||||||
other1: number,
|
|
||||||
other2: number,
|
|
||||||
): number {
|
|
||||||
return Math.acos(
|
|
||||||
(other1 ** 2 + other2 ** 2 - opposite ** 2) / (2 * other1 * other2),
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
type empireId = {id: string}
|
|
||||||
|
|
||||||
type coreState = {id: string}
|
|
||||||
|
|
||||||
type derivedState = {id: string, energy: number, minerals: number, food: number, alloys: number}
|
|
|
@ -1,10 +0,0 @@
|
||||||
type coreState = {
|
|
||||||
startTime: Js.Date.t,
|
|
||||||
decisionTime: Js.Date.t,
|
|
||||||
empires: Belt.Map.t<string, Empires.coreState, string>,
|
|
||||||
}
|
|
||||||
|
|
||||||
type derivedState = {
|
|
||||||
instant: Js.Date.t,
|
|
||||||
empires: Belt.Map.t<string, Empires.derivedState, string>,
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
type coreState = {}
|
|
|
@ -1 +0,0 @@
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
export const load = async (event) => {
|
|
||||||
return {
|
|
||||||
session: await event.locals.getSession(),
|
|
||||||
};
|
|
||||||
};
|
|
|
@ -1,16 +0,0 @@
|
||||||
<script lang="ts">
|
|
||||||
import { signIn, signOut } from "@auth/sveltekit/client";
|
|
||||||
import { page } from "$app/stores";
|
|
||||||
</script>
|
|
||||||
|
|
||||||
SHIET
|
|
||||||
|
|
||||||
{JSON.stringify($page.data.session)}
|
|
||||||
|
|
||||||
{#if $page.data.session}
|
|
||||||
<button on:click={() => signOut()}>Sign out</button>
|
|
||||||
{:else}
|
|
||||||
<button on:click={() => signIn()}>Sign In</button>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<slot />
|
|
|
@ -1,4 +0,0 @@
|
||||||
<h1>Welcome to SvelteKit</h1>
|
|
||||||
<p>
|
|
||||||
Visit <a href="https://kit.svelte.dev">kit.svelte.dev</a> to read the documentation
|
|
||||||
</p>
|
|
|
@ -1,55 +0,0 @@
|
||||||
import mapGen from "$lib/mapGen.js";
|
|
||||||
import { PrismaClient } from "@prisma/client";
|
|
||||||
import { redirect } from "@sveltejs/kit";
|
|
||||||
|
|
||||||
export const actions = {
|
|
||||||
default: async () => {
|
|
||||||
const prisma = new PrismaClient();
|
|
||||||
|
|
||||||
// Create everything in a transaction
|
|
||||||
const { universeId } = await prisma.$transaction(async (client) => {
|
|
||||||
const result = await client.universe.create({
|
|
||||||
data: { config: { hello: "world" } },
|
|
||||||
});
|
|
||||||
const universeId = result.id;
|
|
||||||
|
|
||||||
const generatedMap = mapGen();
|
|
||||||
await client.starSystem.createMany({
|
|
||||||
data: generatedMap.nodes.map(({ x, y }) => ({
|
|
||||||
universeId,
|
|
||||||
coordX: x,
|
|
||||||
coordY: y,
|
|
||||||
})),
|
|
||||||
});
|
|
||||||
|
|
||||||
await client.starSystemEdges.createMany({
|
|
||||||
data: [...generatedMap.adj.entries()]
|
|
||||||
.flatMap(([nodeIdx, neighbors]) =>
|
|
||||||
[...neighbors].map((neighbor) => [nodeIdx, neighbor]),
|
|
||||||
)
|
|
||||||
.filter(([aIdx, bIdx]) => {
|
|
||||||
const a = generatedMap.nodes[aIdx];
|
|
||||||
const b = generatedMap.nodes[bIdx];
|
|
||||||
|
|
||||||
return a.x <= b.x ? (a.x == b.x ? a.y <= b.y : true) : false;
|
|
||||||
})
|
|
||||||
.map(([aIdx, bIdx]) => {
|
|
||||||
const a = generatedMap.nodes[aIdx];
|
|
||||||
const b = generatedMap.nodes[bIdx];
|
|
||||||
|
|
||||||
return {
|
|
||||||
universeId,
|
|
||||||
fromX: a.x,
|
|
||||||
fromY: a.y,
|
|
||||||
toX: b.x,
|
|
||||||
toY: b.y,
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
return { universeId };
|
|
||||||
});
|
|
||||||
// console.log("Helloge", result.id);
|
|
||||||
throw redirect(301, `/game/${universeId}`);
|
|
||||||
},
|
|
||||||
};
|
|
|
@ -1,5 +0,0 @@
|
||||||
Helloge
|
|
||||||
|
|
||||||
<form method="POST">
|
|
||||||
<button type="submit">Create Game</button>
|
|
||||||
</form>
|
|
|
@ -1,6 +0,0 @@
|
||||||
import { redirect } from "@sveltejs/kit";
|
|
||||||
|
|
||||||
export function load({ params }) {
|
|
||||||
// console.log("params", params);
|
|
||||||
throw redirect(307, `/game/${params.id}/createEmpire`);
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
<h1>Create Empire</h1>
|
|
||||||
|
|
||||||
<form>
|
|
||||||
<p>
|
|
||||||
<label>
|
|
||||||
Empire Name
|
|
||||||
<input type="text" />
|
|
||||||
</label>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<button type="submit">Create Empire</button>
|
|
||||||
</form>
|
|
|
@ -1,57 +0,0 @@
|
||||||
<script lang="ts">
|
|
||||||
import mapGen from "$lib/mapGen";
|
|
||||||
import { onMount } from "svelte";
|
|
||||||
|
|
||||||
let canvas: HTMLCanvasElement;
|
|
||||||
|
|
||||||
function generate() {
|
|
||||||
console.log("helloge", canvas);
|
|
||||||
const ctx = canvas.getContext("2d")!;
|
|
||||||
ctx.clearRect(0, 0, 800, 600);
|
|
||||||
|
|
||||||
const generatedMap = mapGen();
|
|
||||||
|
|
||||||
ctx.strokeStyle = "lightgray";
|
|
||||||
for (const [nodeIdx, neighborIdxs] of generatedMap.adj.entries()) {
|
|
||||||
const node = generatedMap.nodes[nodeIdx];
|
|
||||||
for (const neighborIdx of neighborIdxs) {
|
|
||||||
const neighbor = generatedMap.nodes[neighborIdx];
|
|
||||||
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.moveTo(node.x, node.y);
|
|
||||||
ctx.lineTo(neighbor.x, neighbor.y);
|
|
||||||
ctx.stroke();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const size = 3;
|
|
||||||
let ctr = 0;
|
|
||||||
for (const node of generatedMap.nodes) {
|
|
||||||
const neighbors = generatedMap.adj.get(ctr);
|
|
||||||
if (neighbors?.size == 0) continue;
|
|
||||||
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.ellipse(node.x, node.y, size, size, 0, 0, 2 * Math.PI);
|
|
||||||
ctx.fill();
|
|
||||||
ctr += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onMount(() => {
|
|
||||||
generate();
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<button on:click={() => generate()}>Generate</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<canvas class="canvas" bind:this={canvas} width="800" height="600"></canvas>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.canvas {
|
|
||||||
border: 1px solid black;
|
|
||||||
}
|
|
||||||
</style>
|
|
Binary file not shown.
Before Width: | Height: | Size: 1.5 KiB |
|
@ -1,18 +0,0 @@
|
||||||
import adapter from "@sveltejs/adapter-auto";
|
|
||||||
import { vitePreprocess } from "@sveltejs/kit/vite";
|
|
||||||
|
|
||||||
/** @type {import('@sveltejs/kit').Config} */
|
|
||||||
const config = {
|
|
||||||
// Consult https://kit.svelte.dev/docs/integrations#preprocessors
|
|
||||||
// for more information about preprocessors
|
|
||||||
preprocess: vitePreprocess(),
|
|
||||||
|
|
||||||
kit: {
|
|
||||||
// adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
|
|
||||||
// If your environment is not supported or you settled on a specific environment, switch out the adapter.
|
|
||||||
// See https://kit.svelte.dev/docs/adapters for more information about adapters.
|
|
||||||
adapter: adapter(),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default config;
|
|
1
triangle/.gitignore
vendored
Normal file
1
triangle/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
src/tricall.c
|
|
@ -5,4 +5,5 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.76"
|
anyhow = "1.0.76"
|
||||||
|
derive_builder = "0.12.0"
|
||||||
triangle-sys = { path = "../triangle-sys" }
|
triangle-sys = { path = "../triangle-sys" }
|
||||||
|
|
|
@ -1,51 +1,92 @@
|
||||||
use anyhow::Result;
|
#[macro_use]
|
||||||
use std::{ffi::CString, mem::MaybeUninit, ptr};
|
extern crate derive_builder;
|
||||||
|
|
||||||
extern crate triangle_sys as sys;
|
extern crate triangle_sys as sys;
|
||||||
|
|
||||||
pub struct TrianglulateOptions {}
|
#[cfg(test)]
|
||||||
|
mod tests;
|
||||||
|
|
||||||
pub struct TriangulateResult {}
|
use std::{ffi::CString, mem::MaybeUninit, ptr};
|
||||||
|
|
||||||
pub fn triangulate(opts: TrianglulateOptions) -> Result<TriangulateResult> {
|
use anyhow::Result;
|
||||||
let switches = CString::new("")?;
|
|
||||||
|
|
||||||
let mut input = sys::triangulateio {
|
#[derive(Builder)]
|
||||||
pointlist: todo!(),
|
pub struct TrianglulateOpts<P> {
|
||||||
pointattributelist: todo!(),
|
point_list: P,
|
||||||
pointmarkerlist: todo!(),
|
|
||||||
numberofpoints: todo!(),
|
/// Generates a Voronoi diagram
|
||||||
numberofpointattributes: todo!(),
|
#[builder(default)]
|
||||||
trianglelist: todo!(),
|
voronoi: bool,
|
||||||
triangleattributelist: todo!(),
|
}
|
||||||
trianglearealist: todo!(),
|
|
||||||
neighborlist: todo!(),
|
impl<P: Clone> TrianglulateOpts<P> {
|
||||||
numberoftriangles: todo!(),
|
pub fn builder() -> TrianglulateOptsBuilder<P> {
|
||||||
numberofcorners: todo!(),
|
TrianglulateOptsBuilder::default()
|
||||||
numberoftriangleattributes: todo!(),
|
}
|
||||||
segmentlist: todo!(),
|
}
|
||||||
segmentmarkerlist: todo!(),
|
|
||||||
numberofsegments: todo!(),
|
#[derive(Clone, Copy, Debug)]
|
||||||
holelist: todo!(),
|
pub struct Point {
|
||||||
numberofholes: todo!(),
|
x: f64,
|
||||||
regionlist: todo!(),
|
y: f64,
|
||||||
numberofregions: todo!(),
|
}
|
||||||
edgelist: todo!(),
|
|
||||||
edgemarkerlist: todo!(),
|
#[derive(Debug)]
|
||||||
normlist: todo!(),
|
pub struct TriangulateResult {
|
||||||
numberofedges: todo!(),
|
pub point_list: Vec<Point>,
|
||||||
};
|
}
|
||||||
let mut output = MaybeUninit::<sys::triangulateio>::uninit();
|
|
||||||
|
pub fn triangulate<P>(opts: TrianglulateOpts<P>) -> Result<TriangulateResult>
|
||||||
|
where
|
||||||
|
P: IntoIterator<Item = Point>,
|
||||||
|
{
|
||||||
|
let mut switches = Vec::new();
|
||||||
|
if opts.voronoi {
|
||||||
|
switches.push("v");
|
||||||
|
}
|
||||||
|
|
||||||
|
let switches = CString::new(switches.join(""))?;
|
||||||
|
|
||||||
|
let point_list = opts.point_list.into_iter().collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let mut flat_point_list = point_list
|
||||||
|
.iter()
|
||||||
|
.flat_map(|point| [point.x, point.y])
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let input = MaybeUninit::<sys::triangulateio>::uninit();
|
||||||
|
let output = MaybeUninit::<sys::triangulateio>::uninit();
|
||||||
let mut vorout = ptr::null::<sys::triangulateio>();
|
let mut vorout = ptr::null::<sys::triangulateio>();
|
||||||
|
|
||||||
|
let mut input = unsafe { input.assume_init() };
|
||||||
|
let mut output = unsafe { output.assume_init() };
|
||||||
|
input.pointlist = flat_point_list.as_mut_ptr();
|
||||||
|
input.numberofpoints = point_list.len() as i32;
|
||||||
|
|
||||||
|
// TODO: Implement point attributes
|
||||||
|
input.numberofpointattributes = 0;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
sys::triangulate(
|
sys::triangulate(
|
||||||
switches.as_ptr() as *mut _,
|
switches.as_ptr() as *mut _,
|
||||||
&mut input as *mut _,
|
&mut input as *mut _,
|
||||||
output.as_mut_ptr(),
|
&mut output as *mut _,
|
||||||
vorout as *mut _,
|
vorout as *mut _,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(TriangulateResult {})
|
let flat_point_list = unsafe {
|
||||||
|
Vec::from_raw_parts(
|
||||||
|
output.pointlist,
|
||||||
|
output.numberofpoints as usize * 2,
|
||||||
|
output.numberofpoints as usize * 2,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
let point_list = flat_point_list
|
||||||
|
.chunks(2)
|
||||||
|
.map(|points| Point {
|
||||||
|
x: points[0],
|
||||||
|
y: points[1],
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
Ok(TriangulateResult { point_list })
|
||||||
}
|
}
|
||||||
|
|
17
triangle/src/tests.rs
Normal file
17
triangle/src/tests.rs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
use crate::{triangulate, Point, TrianglulateOpts};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_tricall() {
|
||||||
|
let opts = TrianglulateOpts::builder()
|
||||||
|
.point_list([
|
||||||
|
Point { x: 0.0, y: 0.0 },
|
||||||
|
Point { x: 1.0, y: 0.0 },
|
||||||
|
Point { x: 1.0, y: 10.0 },
|
||||||
|
Point { x: 0.0, y: 10.0 },
|
||||||
|
])
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let result = triangulate(opts).unwrap();
|
||||||
|
panic!("Result: {:?}", result);
|
||||||
|
}
|
|
@ -1,18 +0,0 @@
|
||||||
{
|
|
||||||
"extends": "./.svelte-kit/tsconfig.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"allowJs": true,
|
|
||||||
"checkJs": true,
|
|
||||||
"esModuleInterop": true,
|
|
||||||
"forceConsistentCasingInFileNames": true,
|
|
||||||
"resolveJsonModule": true,
|
|
||||||
"skipLibCheck": true,
|
|
||||||
"sourceMap": true,
|
|
||||||
"strict": true,
|
|
||||||
"moduleResolution": "bundler"
|
|
||||||
}
|
|
||||||
// Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
|
|
||||||
//
|
|
||||||
// If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
|
|
||||||
// from the referenced tsconfig.json - TypeScript does not merge them in
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
import { sveltekit } from "@sveltejs/kit/vite";
|
|
||||||
import { defineConfig } from "vitest/config";
|
|
||||||
|
|
||||||
export default defineConfig({
|
|
||||||
plugins: [sveltekit()],
|
|
||||||
test: {
|
|
||||||
include: ["src/**/*.{test,spec}.{js,ts}"],
|
|
||||||
},
|
|
||||||
});
|
|
Loading…
Reference in a new issue