diff --git a/Cargo.lock b/Cargo.lock index bd239b8..60beb03 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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" diff --git a/backend/Cargo.toml b/backend/Cargo.toml index e7f3626..d112556 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -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" diff --git a/backend/src/main.rs b/backend/src/main.rs index 79f678f..2433329 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -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, +} #[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(()) } diff --git a/backend/src/routes/mod.rs b/backend/src/routes/mod.rs new file mode 100644 index 0000000..4ea2f10 --- /dev/null +++ b/backend/src/routes/mod.rs @@ -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) -> Json { + 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, +) -> Json { + 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, + })) +} diff --git a/frontend/package.json b/frontend/package.json index c7117a8..4a1cdb5 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -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" }, diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml index 2660443..0ea843a 100644 --- a/frontend/pnpm-lock.yaml +++ b/frontend/pnpm-lock.yaml @@ -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==} diff --git a/frontend/src/App.css b/frontend/src/App.css index 9778106..a98e59d 100644 --- a/frontend/src/App.css +++ b/frontend/src/App.css @@ -9,7 +9,7 @@ html,body,#root { } #root > main { - flex-shrink: 1; min-height: 0; + flex-shrink: 1; flex-grow: 1; } \ No newline at end of file diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index f38469a..ee04752 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -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 ; + return ( + + + + ); } export default App; diff --git a/frontend/src/Layout.tsx b/frontend/src/Layout.tsx index 11043ea..6c1ec00 100644 --- a/frontend/src/Layout.tsx +++ b/frontend/src/Layout.tsx @@ -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 ( <> - OpenStellaris + + OpenStellaris + - - - Map - - - - Planets - + {universeId && ( + <> + + + {universeId} + + + + Planets + + + )} diff --git a/frontend/src/routes/HomeView.tsx b/frontend/src/routes/HomeView.tsx new file mode 100644 index 0000000..49ac8b5 --- /dev/null +++ b/frontend/src/routes/HomeView.tsx @@ -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 ( + <> +
    + {data.universes.map((universe) => ( +
  • + Go to universe{" "} + {JSON.stringify(universe)} +
  • + ))} +
+ + ); +} diff --git a/frontend/src/routes/MapView.tsx b/frontend/src/routes/MapView.tsx index e82e2db..987e331 100644 --- a/frontend/src/routes/MapView.tsx +++ b/frontend/src/routes/MapView.tsx @@ -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 (
- + - - - + + + {data.points.map((point) => { + console.log("point", point); + return ( + + ); + })}
); } 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 ( setHover(true)} onPointerOut={(_event) => setHover(false)} > - + ); diff --git a/frontend/src/routes/index.tsx b/frontend/src/routes/index.tsx index 2c1512c..acb1cf8 100644 --- a/frontend/src/routes/index.tsx +++ b/frontend/src/routes/index.tsx @@ -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: , children: [ { - path: "/", - element: , + path: "", + element: , }, { - path: "/planets", - element: , + path: "universe/:universeId", + children: [ + { + path: "", + element: , + }, + { + path: "planets", + element: , + }, + ], }, ], }, diff --git a/prisma/schema.prisma b/prisma/schema.prisma index cdebaa2..b0c56b6 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -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" } diff --git a/triangle/src/lib.rs b/triangle/src/lib.rs index 9f1d732..ede7a62 100644 --- a/triangle/src/lib.rs +++ b/triangle/src/lib.rs @@ -10,7 +10,7 @@ use std::{ffi::CString, mem::MaybeUninit, ptr}; use anyhow::Result; #[derive(Builder)] -pub struct TrianglulateOpts

{ +pub struct TrianglulateOpts

> { point_list: P, /// Generates a Voronoi diagram @@ -26,8 +26,8 @@ impl TrianglulateOpts

{ #[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::>(); - let input = MaybeUninit::::uninit(); - let output = MaybeUninit::::uninit(); - let mut vorout = ptr::null::(); + let input = MaybeUninit::::zeroed(); + let output = MaybeUninit::::zeroed(); + let vorout = MaybeUninit::::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,