render some circles
This commit is contained in:
parent
6050903c09
commit
936417a88d
14 changed files with 431 additions and 53 deletions
103
Cargo.lock
generated
103
Cargo.lock
generated
|
@ -74,6 +74,54 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
"anstyle-query",
|
||||
"anstyle-wincon",
|
||||
"colorchoice",
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87"
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-parse"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c"
|
||||
dependencies = [
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-query"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648"
|
||||
dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-wincon"
|
||||
version = "3.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.76"
|
||||
|
@ -203,9 +251,12 @@ dependencies = [
|
|||
"anyhow",
|
||||
"axum",
|
||||
"chrono",
|
||||
"clap",
|
||||
"prisma-client-rust",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
"triangle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -517,6 +568,46 @@ dependencies = [
|
|||
"libloading",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.4.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bfaff671f6b22ca62406885ece523383b9b64022e341e53e009a62ebc47a45f2"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.4.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a216b506622bb1d316cd51328dce24e07bdff4a6128a47c7e7fad11878d5adbb"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
"clap_lex",
|
||||
"strsim",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442"
|
||||
dependencies = [
|
||||
"heck 0.4.1",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.43",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
|
||||
|
||||
[[package]]
|
||||
name = "cmake"
|
||||
version = "0.1.50"
|
||||
|
@ -526,6 +617,12 @@ dependencies = [
|
|||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
|
||||
|
||||
[[package]]
|
||||
name = "colored"
|
||||
version = "2.1.0"
|
||||
|
@ -4993,6 +5090,12 @@ dependencies = [
|
|||
"user-facing-error-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "1.6.1"
|
||||
|
|
|
@ -4,9 +4,13 @@ version = "0.1.0"
|
|||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
triangle = { path = "../triangle" }
|
||||
|
||||
anyhow = "1.0.76"
|
||||
axum = { version = "0.7.2", features = ["http2"] }
|
||||
chrono = "0.4.31"
|
||||
clap = { version = "4.4.11", features = ["derive"] }
|
||||
prisma-client-rust = { git = "https://github.com/Brendonovich/prisma-client-rust", tag = "0.6.10" }
|
||||
serde = { version = "1.0.193", features = ["derive"] }
|
||||
tokio = { version = "1.35.1", features = ["full"] }
|
||||
serde_json = "1.0.108"
|
||||
|
|
|
@ -1,19 +1,105 @@
|
|||
#[macro_use]
|
||||
extern crate serde_json;
|
||||
|
||||
#[allow(unused_imports, dead_code)]
|
||||
pub mod prisma;
|
||||
mod routes;
|
||||
pub mod state;
|
||||
|
||||
use std::{f64::consts::PI, sync::Arc};
|
||||
|
||||
use anyhow::Result;
|
||||
use axum::{routing::get, Router};
|
||||
use clap::{Parser, Subcommand};
|
||||
use prisma::PrismaClient;
|
||||
use prisma_client_rust::serde_json::json;
|
||||
use routes::{universe_list, universe_map};
|
||||
use triangle::{triangulate, Point, TrianglulateOpts};
|
||||
|
||||
use crate::prisma::star_system;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
struct Opt {
|
||||
#[clap(subcommand)]
|
||||
command: Command,
|
||||
}
|
||||
|
||||
#[derive(Debug, Subcommand)]
|
||||
enum Command {
|
||||
Run,
|
||||
Seed,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct AppState {
|
||||
prisma: Arc<PrismaClient>,
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
let opt = Opt::parse();
|
||||
|
||||
let client = PrismaClient::_builder().build().await?;
|
||||
let client = Arc::new(client);
|
||||
let state = AppState {
|
||||
prisma: client.clone(),
|
||||
};
|
||||
|
||||
let app = Router::new().route("/", get(|| async { "Hello, World!" }));
|
||||
match opt.command {
|
||||
Command::Run => {
|
||||
let app = Router::new()
|
||||
.route("/", get(|| async { "Hello, World!" }))
|
||||
.route("/universe", get(universe_list))
|
||||
.route("/universe/:universe_id/map", get(universe_map))
|
||||
.with_state(state);
|
||||
let listener = tokio::net::TcpListener::bind("0.0.0.0:1440").await?;
|
||||
axum::serve(listener, app).await?;
|
||||
}
|
||||
|
||||
let listener = tokio::net::TcpListener::bind("0.0.0.0:1440").await?;
|
||||
axum::serve(listener, app).await?;
|
||||
Command::Seed => {
|
||||
// Generate a new triangulation
|
||||
let result = {
|
||||
// Generate a circle of points
|
||||
let radius = 50.0;
|
||||
const NUM_POINTS: usize = 30;
|
||||
let point_list = (0..NUM_POINTS)
|
||||
.map(|n| n as f64 * (2.0 * PI) / NUM_POINTS as f64)
|
||||
.map(|theta| Point {
|
||||
x: radius * theta.cos(),
|
||||
y: radius * theta.sin(),
|
||||
});
|
||||
|
||||
triangulate(
|
||||
TrianglulateOpts::builder().point_list(point_list).build()?,
|
||||
)?
|
||||
};
|
||||
|
||||
println!("Result: {result:?}");
|
||||
|
||||
// Insert into database
|
||||
let universe = client.universe().create(json!({}), vec![]).exec().await?;
|
||||
client
|
||||
.star_system()
|
||||
.create_many(
|
||||
result
|
||||
.point_list
|
||||
.into_iter()
|
||||
.map(|point| {
|
||||
star_system::create_unchecked(
|
||||
universe.id.clone(),
|
||||
point.x as i32,
|
||||
point.y as i32,
|
||||
vec![],
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
.exec()
|
||||
.await?;
|
||||
|
||||
println!("Done.");
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
40
backend/src/routes/mod.rs
Normal file
40
backend/src/routes/mod.rs
Normal file
|
@ -0,0 +1,40 @@
|
|||
use axum::{
|
||||
extract::{Path, State},
|
||||
Json,
|
||||
};
|
||||
use serde_json::Value;
|
||||
|
||||
use crate::{prisma::star_system, AppState};
|
||||
|
||||
pub async fn universe_list(state: State<AppState>) -> Json<Value> {
|
||||
let universes = state
|
||||
.prisma
|
||||
.universe()
|
||||
.find_many(vec![])
|
||||
.exec()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
Json(json!({
|
||||
"universes": universes,
|
||||
}))
|
||||
}
|
||||
|
||||
pub async fn universe_map(
|
||||
Path((universe_id,)): Path<(String,)>,
|
||||
state: State<AppState>,
|
||||
) -> Json<Value> {
|
||||
println!("universe id {universe_id}");
|
||||
|
||||
let points = state
|
||||
.prisma
|
||||
.star_system()
|
||||
.find_many(vec![star_system::universe_id::equals(universe_id.clone())])
|
||||
.exec()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
Json(json!({
|
||||
"points": points,
|
||||
}))
|
||||
}
|
|
@ -9,6 +9,9 @@
|
|||
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"prisma": {
|
||||
"seed": "cargo run -p seeder"
|
||||
},
|
||||
"dependencies": {
|
||||
"@blueprintjs/core": "^5.7.2",
|
||||
"@blueprintjs/icons": "^5.5.0",
|
||||
|
@ -18,6 +21,7 @@
|
|||
"normalize.css": "^8.0.1",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-query": "^3.39.3",
|
||||
"react-router-dom": "^6.21.1",
|
||||
"three": "^0.160.0"
|
||||
},
|
||||
|
|
|
@ -29,6 +29,9 @@ dependencies:
|
|||
react-dom:
|
||||
specifier: ^18.2.0
|
||||
version: 18.2.0(react@18.2.0)
|
||||
react-query:
|
||||
specifier: ^3.39.3
|
||||
version: 3.39.3(react-dom@18.2.0)(react@18.2.0)
|
||||
react-router-dom:
|
||||
specifier: ^6.21.1
|
||||
version: 6.21.1(react-dom@18.2.0)(react@18.2.0)
|
||||
|
@ -971,12 +974,16 @@ packages:
|
|||
|
||||
/balanced-match@1.0.2:
|
||||
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
|
||||
dev: true
|
||||
|
||||
/base64-js@1.5.1:
|
||||
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
|
||||
dev: false
|
||||
|
||||
/big-integer@1.6.52:
|
||||
resolution: {integrity: sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==}
|
||||
engines: {node: '>=0.6'}
|
||||
dev: false
|
||||
|
||||
/binary-extensions@2.2.0:
|
||||
resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
|
||||
engines: {node: '>=8'}
|
||||
|
@ -987,7 +994,6 @@ packages:
|
|||
dependencies:
|
||||
balanced-match: 1.0.2
|
||||
concat-map: 0.0.1
|
||||
dev: true
|
||||
|
||||
/brace-expansion@2.0.1:
|
||||
resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
|
||||
|
@ -1002,6 +1008,19 @@ packages:
|
|||
fill-range: 7.0.1
|
||||
dev: true
|
||||
|
||||
/broadcast-channel@3.7.0:
|
||||
resolution: {integrity: sha512-cIAKJXAxGJceNZGTZSBzMxzyOn72cVgPnKx4dc6LRjQgbaJUQqhy5rzL3zbMxkMWsGKkv2hSFkPRMEXfoMZ2Mg==}
|
||||
dependencies:
|
||||
'@babel/runtime': 7.23.7
|
||||
detect-node: 2.1.0
|
||||
js-sha3: 0.8.0
|
||||
microseconds: 0.2.0
|
||||
nano-time: 1.0.0
|
||||
oblivious-set: 1.0.0
|
||||
rimraf: 3.0.2
|
||||
unload: 2.2.0
|
||||
dev: false
|
||||
|
||||
/buffer@6.0.3:
|
||||
resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==}
|
||||
dependencies:
|
||||
|
@ -1086,7 +1105,6 @@ packages:
|
|||
|
||||
/concat-map@0.0.1:
|
||||
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
|
||||
dev: true
|
||||
|
||||
/constant-case@3.0.4:
|
||||
resolution: {integrity: sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==}
|
||||
|
@ -1128,6 +1146,10 @@ packages:
|
|||
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
|
||||
dev: true
|
||||
|
||||
/detect-node@2.1.0:
|
||||
resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==}
|
||||
dev: false
|
||||
|
||||
/dir-glob@3.0.1:
|
||||
resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
|
||||
engines: {node: '>=8'}
|
||||
|
@ -1372,7 +1394,6 @@ packages:
|
|||
|
||||
/fs.realpath@1.0.0:
|
||||
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
|
||||
dev: true
|
||||
|
||||
/fsevents@2.3.3:
|
||||
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
|
||||
|
@ -1405,7 +1426,6 @@ packages:
|
|||
minimatch: 3.1.2
|
||||
once: 1.4.0
|
||||
path-is-absolute: 1.0.1
|
||||
dev: true
|
||||
|
||||
/globals@13.24.0:
|
||||
resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==}
|
||||
|
@ -1473,11 +1493,9 @@ packages:
|
|||
dependencies:
|
||||
once: 1.4.0
|
||||
wrappy: 1.0.2
|
||||
dev: true
|
||||
|
||||
/inherits@2.0.4:
|
||||
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
|
||||
dev: true
|
||||
|
||||
/is-binary-path@2.1.0:
|
||||
resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
|
||||
|
@ -1521,6 +1539,10 @@ packages:
|
|||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/js-sha3@0.8.0:
|
||||
resolution: {integrity: sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==}
|
||||
dev: false
|
||||
|
||||
/js-tokens@4.0.0:
|
||||
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
|
||||
dev: false
|
||||
|
@ -1589,6 +1611,13 @@ packages:
|
|||
yallist: 4.0.0
|
||||
dev: true
|
||||
|
||||
/match-sorter@6.3.1:
|
||||
resolution: {integrity: sha512-mxybbo3pPNuA+ZuCUhm5bwNkXrJTbsk5VWbR5wiwz/GC6LIiegBGn2w3O08UG/jdbYLinw51fSQ5xNU1U3MgBw==}
|
||||
dependencies:
|
||||
'@babel/runtime': 7.23.7
|
||||
remove-accents: 0.4.2
|
||||
dev: false
|
||||
|
||||
/merge2@1.4.1:
|
||||
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
|
||||
engines: {node: '>= 8'}
|
||||
|
@ -1606,11 +1635,14 @@ packages:
|
|||
picomatch: 2.3.1
|
||||
dev: true
|
||||
|
||||
/microseconds@0.2.0:
|
||||
resolution: {integrity: sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA==}
|
||||
dev: false
|
||||
|
||||
/minimatch@3.1.2:
|
||||
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
|
||||
dependencies:
|
||||
brace-expansion: 1.1.11
|
||||
dev: true
|
||||
|
||||
/minimatch@9.0.3:
|
||||
resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==}
|
||||
|
@ -1623,6 +1655,12 @@ packages:
|
|||
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
|
||||
dev: true
|
||||
|
||||
/nano-time@1.0.0:
|
||||
resolution: {integrity: sha512-flnngywOoQ0lLQOTRNexn2gGSNuM9bKj9RZAWSzhQ+UJYaAFG9bac4DW9VHjUAzrOaIcajHybCTHe/bkvozQqA==}
|
||||
dependencies:
|
||||
big-integer: 1.6.52
|
||||
dev: false
|
||||
|
||||
/nanoid@3.3.7:
|
||||
resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==}
|
||||
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
|
||||
|
@ -1654,11 +1692,14 @@ packages:
|
|||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
/oblivious-set@1.0.0:
|
||||
resolution: {integrity: sha512-z+pI07qxo4c2CulUHCDf9lcqDlMSo72N/4rLUpRXf6fu+q8vjt8y0xS+Tlf8NTJDdTXHbdeO1n3MlbctwEoXZw==}
|
||||
dev: false
|
||||
|
||||
/once@1.4.0:
|
||||
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
|
||||
dependencies:
|
||||
wrappy: 1.0.2
|
||||
dev: true
|
||||
|
||||
/optionator@0.9.3:
|
||||
resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==}
|
||||
|
@ -1722,7 +1763,6 @@ packages:
|
|||
/path-is-absolute@1.0.1:
|
||||
resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/path-key@3.1.1:
|
||||
resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
|
||||
|
@ -1816,6 +1856,25 @@ packages:
|
|||
warning: 4.0.3
|
||||
dev: false
|
||||
|
||||
/react-query@3.39.3(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-nLfLz7GiohKTJDuT4us4X3h/8unOh+00MLb2yJoGTPjxKs2bc1iDhkNx2bd5MKklXnOD3NrVZ+J2UXujA5In4g==}
|
||||
peerDependencies:
|
||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0
|
||||
react-dom: '*'
|
||||
react-native: '*'
|
||||
peerDependenciesMeta:
|
||||
react-dom:
|
||||
optional: true
|
||||
react-native:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.23.7
|
||||
broadcast-channel: 3.7.0
|
||||
match-sorter: 6.3.1
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/react-reconciler@0.27.0(react@18.2.0):
|
||||
resolution: {integrity: sha512-HmMDKciQjYmBRGuuhIaKA1ba/7a+UsM5FzOZsMO2JYHt9Jh8reCb7j1eDC95NOyUlKM9KRyvdx0flBuDvYSBoA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
@ -1893,6 +1952,10 @@ packages:
|
|||
resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==}
|
||||
dev: false
|
||||
|
||||
/remove-accents@0.4.2:
|
||||
resolution: {integrity: sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA==}
|
||||
dev: false
|
||||
|
||||
/resolve-from@4.0.0:
|
||||
resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
|
||||
engines: {node: '>=4'}
|
||||
|
@ -1908,7 +1971,6 @@ packages:
|
|||
hasBin: true
|
||||
dependencies:
|
||||
glob: 7.2.3
|
||||
dev: true
|
||||
|
||||
/rollup@4.9.1:
|
||||
resolution: {integrity: sha512-pgPO9DWzLoW/vIhlSoDByCzcpX92bKEorbgXuZrqxByte3JFk2xSW2JEeAcyLc9Ru9pqcNNW+Ob7ntsk2oT/Xw==}
|
||||
|
@ -2077,6 +2139,13 @@ packages:
|
|||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/unload@2.2.0:
|
||||
resolution: {integrity: sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA==}
|
||||
dependencies:
|
||||
'@babel/runtime': 7.23.7
|
||||
detect-node: 2.1.0
|
||||
dev: false
|
||||
|
||||
/upper-case-first@2.0.2:
|
||||
resolution: {integrity: sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==}
|
||||
dependencies:
|
||||
|
@ -2147,7 +2216,6 @@ packages:
|
|||
|
||||
/wrappy@1.0.2:
|
||||
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
|
||||
dev: true
|
||||
|
||||
/yallist@4.0.0:
|
||||
resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
|
||||
|
|
|
@ -9,7 +9,7 @@ html,body,#root {
|
|||
}
|
||||
|
||||
#root > main {
|
||||
flex-shrink: 1;
|
||||
min-height: 0;
|
||||
flex-shrink: 1;
|
||||
flex-grow: 1;
|
||||
}
|
|
@ -1,11 +1,17 @@
|
|||
import "./App.css";
|
||||
import { createBrowserRouter, RouterProvider } from "react-router-dom";
|
||||
import { QueryClient, QueryClientProvider } from "react-query";
|
||||
import "./App.css";
|
||||
import routes from "./routes";
|
||||
|
||||
const router = createBrowserRouter(routes);
|
||||
const queryClient = new QueryClient();
|
||||
|
||||
function App() {
|
||||
return <RouterProvider router={router} />;
|
||||
return (
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<RouterProvider router={router} />
|
||||
</QueryClientProvider>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
|
|
|
@ -1,22 +1,37 @@
|
|||
import { Outlet, Link } from "react-router-dom";
|
||||
import { Outlet, Link, useParams } from "react-router-dom";
|
||||
import { Alignment, Icon, Navbar } from "@blueprintjs/core";
|
||||
|
||||
export default function Layout() {
|
||||
const { universeId } = useParams();
|
||||
return (
|
||||
<>
|
||||
<Navbar>
|
||||
<Navbar.Group align={Alignment.LEFT}>
|
||||
<Navbar.Heading>OpenStellaris</Navbar.Heading>
|
||||
<Navbar.Heading>
|
||||
<Link to="/">OpenStellaris</Link>
|
||||
</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>
|
||||
{universeId && (
|
||||
<>
|
||||
<Link
|
||||
className="bp5-button bp5-minimal"
|
||||
role="button"
|
||||
to={`/universe/${universeId}`}
|
||||
>
|
||||
<Icon icon="home" />
|
||||
{universeId}
|
||||
</Link>
|
||||
<Link
|
||||
className="bp5-button bp5-minimal"
|
||||
role="button"
|
||||
to={`/universe/${universeId}/planets`}
|
||||
>
|
||||
<Icon icon="panel-table" />
|
||||
Planets
|
||||
</Link>
|
||||
</>
|
||||
)}
|
||||
</Navbar.Group>
|
||||
</Navbar>
|
||||
|
||||
|
|
23
frontend/src/routes/HomeView.tsx
Normal file
23
frontend/src/routes/HomeView.tsx
Normal file
|
@ -0,0 +1,23 @@
|
|||
import { useQuery } from "react-query";
|
||||
import { Link } from "react-router-dom";
|
||||
|
||||
export default function HomeView() {
|
||||
const { isLoading, data } = useQuery("universe list", () =>
|
||||
fetch("/api/universe").then((res) => res.json()),
|
||||
);
|
||||
|
||||
if (isLoading) return <>...</>;
|
||||
|
||||
return (
|
||||
<>
|
||||
<ul>
|
||||
{data.universes.map((universe) => (
|
||||
<li key={universe.id}>
|
||||
<Link to={`/universe/${universe.id}`}>Go to universe</Link>{" "}
|
||||
{JSON.stringify(universe)}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -1,28 +1,46 @@
|
|||
import { useRef, useState } from "react";
|
||||
import { useQuery } from "react-query";
|
||||
import { Canvas, useFrame, type MeshProps } from "@react-three/fiber";
|
||||
import styles from "./MapView.module.scss";
|
||||
import { useParams } from "react-router-dom";
|
||||
|
||||
export default function MapView({}) {
|
||||
const { universeId } = useParams();
|
||||
const { isLoading, data } = useQuery(`universe ${universeId} points`, () =>
|
||||
fetch(`/api/universe/${universeId}/map`).then((res) => res.json()),
|
||||
);
|
||||
|
||||
if (isLoading) return <>...</>;
|
||||
console.log("data", data);
|
||||
|
||||
export default function MapView() {
|
||||
return (
|
||||
<main className={styles.main}>
|
||||
<Canvas>
|
||||
<Canvas camera={{ position: [0, 20, 0] }}>
|
||||
<ambientLight />
|
||||
<pointLight position={[10, 10, 10]} />
|
||||
<Box position={[-1.2, 0, 0]} />
|
||||
<Box position={[1.2, 0, 0]} />
|
||||
<pointLight position={[0, 0, 0]} />
|
||||
|
||||
{data.points.map((point) => {
|
||||
console.log("point", point);
|
||||
return (
|
||||
<Box
|
||||
key={JSON.stringify([point.coordX, point.coordY])}
|
||||
position={[point.coordX / 5.0, 0, point.coordY / 5.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));
|
||||
useFrame((_state, delta) => {
|
||||
meshRef.current.rotation.x += delta;
|
||||
});
|
||||
// Return view, these are regular three.js elements expressed in JSX
|
||||
return (
|
||||
<mesh
|
||||
|
@ -33,7 +51,7 @@ function Box(props: MeshProps) {
|
|||
onPointerOver={(_event) => setHover(true)}
|
||||
onPointerOut={(_event) => setHover(false)}
|
||||
>
|
||||
<boxGeometry args={[1, 1, 1]} />
|
||||
<sphereGeometry args={[0.5]} />
|
||||
<meshStandardMaterial color={hovered ? "hotpink" : "orange"} />
|
||||
</mesh>
|
||||
);
|
||||
|
|
|
@ -2,6 +2,7 @@ import type { RouteObject } from "react-router-dom";
|
|||
import Layout from "../Layout";
|
||||
import MapView from "./MapView";
|
||||
import PlanetsView from "./PlanetsView";
|
||||
import HomeView from "./HomeView";
|
||||
|
||||
const routes: RouteObject[] = [
|
||||
{
|
||||
|
@ -9,12 +10,21 @@ const routes: RouteObject[] = [
|
|||
element: <Layout />,
|
||||
children: [
|
||||
{
|
||||
path: "/",
|
||||
element: <MapView />,
|
||||
path: "",
|
||||
element: <HomeView />,
|
||||
},
|
||||
{
|
||||
path: "/planets",
|
||||
element: <PlanetsView />,
|
||||
path: "universe/:universeId",
|
||||
children: [
|
||||
{
|
||||
path: "",
|
||||
element: <MapView />,
|
||||
},
|
||||
{
|
||||
path: "planets",
|
||||
element: <PlanetsView />,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
|
@ -1,10 +1,5 @@
|
|||
// This is your Prisma schema file,
|
||||
// learn more about it in the docs: https://pris.ly/d/prisma-schema
|
||||
|
||||
generator client {
|
||||
// Corresponds to the cargo alias created earlier
|
||||
provider = "cargo prisma"
|
||||
// The location to generate the client. Is relative to the position of the schema
|
||||
output = "../backend/src/prisma.rs"
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ use std::{ffi::CString, mem::MaybeUninit, ptr};
|
|||
use anyhow::Result;
|
||||
|
||||
#[derive(Builder)]
|
||||
pub struct TrianglulateOpts<P> {
|
||||
pub struct TrianglulateOpts<P = Vec<Point>> {
|
||||
point_list: P,
|
||||
|
||||
/// Generates a Voronoi diagram
|
||||
|
@ -26,8 +26,8 @@ impl<P: Clone> TrianglulateOpts<P> {
|
|||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct Point {
|
||||
x: f64,
|
||||
y: f64,
|
||||
pub x: f64,
|
||||
pub y: f64,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -53,27 +53,33 @@ where
|
|||
.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 input = MaybeUninit::<sys::triangulateio>::zeroed();
|
||||
let output = MaybeUninit::<sys::triangulateio>::zeroed();
|
||||
let vorout = MaybeUninit::<sys::triangulateio>::zeroed();
|
||||
|
||||
let mut input = unsafe { input.assume_init() };
|
||||
let mut output = unsafe { output.assume_init() };
|
||||
let mut vorout = unsafe { vorout.assume_init() };
|
||||
|
||||
input.pointlist = flat_point_list.as_mut_ptr();
|
||||
input.numberofpoints = point_list.len() as i32;
|
||||
|
||||
// TODO: Implement point attributes
|
||||
input.numberofpointattributes = 0;
|
||||
|
||||
println!("Going to triangulate...");
|
||||
|
||||
unsafe {
|
||||
sys::triangulate(
|
||||
switches.as_ptr() as *mut _,
|
||||
&mut input as *mut _,
|
||||
&mut output as *mut _,
|
||||
vorout as *mut _,
|
||||
&mut vorout as *mut _,
|
||||
)
|
||||
};
|
||||
|
||||
println!("Triangulated.");
|
||||
|
||||
let flat_point_list = unsafe {
|
||||
Vec::from_raw_parts(
|
||||
output.pointlist,
|
||||
|
|
Loading…
Reference in a new issue