2024-08-13 20:11:12 +02:00
|
|
|
#![feature(iter_intersperse)]
|
|
|
|
|
|
|
|
use axum::{
|
|
|
|
extract::State,
|
2024-08-14 17:39:47 +02:00
|
|
|
http::{
|
|
|
|
// header,
|
|
|
|
StatusCode,
|
|
|
|
Uri,
|
|
|
|
},
|
2024-08-13 20:11:12 +02:00
|
|
|
response::{Html, IntoResponse},
|
2024-08-16 13:05:57 +02:00
|
|
|
routing::{get, get_service},
|
2024-08-13 20:11:12 +02:00
|
|
|
Router,
|
|
|
|
};
|
2024-08-14 17:39:47 +02:00
|
|
|
// use image::ImageFormat;
|
|
|
|
// use mysql::prelude::*;
|
2024-08-13 20:11:12 +02:00
|
|
|
use mysql::*;
|
2024-08-14 17:39:47 +02:00
|
|
|
// use plotters::prelude::*;
|
|
|
|
// use std::io::{BufWriter, Cursor};
|
2024-08-13 20:11:12 +02:00
|
|
|
use std::sync::Arc;
|
2024-08-14 17:39:47 +02:00
|
|
|
mod math;
|
2024-08-13 20:11:12 +02:00
|
|
|
mod my_structs;
|
|
|
|
mod plotting;
|
2024-08-14 17:39:47 +02:00
|
|
|
// use crate::my_structs::MyError;
|
|
|
|
// use crate::plotting::Plotter;
|
2024-08-13 21:50:17 +02:00
|
|
|
use std::{thread, time};
|
2024-08-16 13:05:57 +02:00
|
|
|
use tower_http::services::ServeDir;
|
2024-08-13 20:11:12 +02:00
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
struct AppState {
|
|
|
|
sql_pool: Pool,
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_sql_pool(url: &str) -> Pool {
|
|
|
|
loop {
|
|
|
|
let sql_pool_attempt = Pool::new(url);
|
|
|
|
if let Ok(sql_pool) = sql_pool_attempt {
|
|
|
|
return sql_pool;
|
2024-08-13 21:50:17 +02:00
|
|
|
} else {
|
|
|
|
println!("Cannot connect to SQL database. Retrying");
|
|
|
|
thread::sleep(time::Duration::from_millis(1000));
|
2024-08-13 20:11:12 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[tokio::main]
|
|
|
|
async fn main() {
|
|
|
|
//Initialize state
|
|
|
|
let sql_pool = get_sql_pool("mysql://root:hQqjjMa3JbpLrJvJo7FV@db.knyffen.dk:3306/Food");
|
|
|
|
let shared_state = Arc::new(AppState { sql_pool });
|
|
|
|
|
|
|
|
// build our application with a single route
|
|
|
|
let app = Router::new()
|
|
|
|
.route("/get_rows", get(get_rows))
|
|
|
|
.route("/html_demo", get(html_demo))
|
|
|
|
.route("/html_plotter", get(html_plotter))
|
|
|
|
.route("/image.png", get(png_image))
|
|
|
|
.route("/image.svg", get(svg_image))
|
2024-08-14 17:39:47 +02:00
|
|
|
.route("/calorie_intake.svg", get(svg_calorie_intake))
|
|
|
|
.route("/calorie_intake", get(calorie_intake))
|
2024-08-16 13:05:57 +02:00
|
|
|
.route("/wasm_test", get(wasm_test))
|
|
|
|
.nest_service("/pkg", get_service(ServeDir::new("../browser/pkg")))
|
2024-08-13 21:50:17 +02:00
|
|
|
.with_state(shared_state)
|
|
|
|
.fallback(not_found);
|
2024-08-13 20:11:12 +02:00
|
|
|
|
|
|
|
// run our app with hyper, listening globally on port 3000
|
|
|
|
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
|
|
|
|
axum::serve(listener, app).await.unwrap();
|
|
|
|
}
|
|
|
|
|
2024-08-13 21:50:17 +02:00
|
|
|
async fn not_found(uri: Uri) -> (StatusCode, String) {
|
2024-08-14 17:39:47 +02:00
|
|
|
(StatusCode::NOT_FOUND, format!("404 not found: {uri}"))
|
2024-08-13 21:50:17 +02:00
|
|
|
}
|
|
|
|
|
2024-08-14 17:39:47 +02:00
|
|
|
async fn get_rows(State(state): State<Arc<AppState>>) -> Result<String, my_structs::MyError> {
|
|
|
|
let nutrition_val_promise =
|
|
|
|
my_structs::Nutrition::get_nutrition_hashmap(state.sql_pool.clone());
|
|
|
|
let purchases_val_promise = my_structs::Purchase::get_purchase_rows(state.sql_pool.clone());
|
2024-08-13 21:50:17 +02:00
|
|
|
|
|
|
|
let nutrition_val = nutrition_val_promise.await?;
|
|
|
|
let purchases_val = purchases_val_promise.await?;
|
2024-08-13 20:11:12 +02:00
|
|
|
|
|
|
|
println!("Serving: get_rows");
|
2024-08-14 17:39:47 +02:00
|
|
|
// Ok("See print logs instead".to_string())
|
2024-08-13 21:50:17 +02:00
|
|
|
Ok(format!("{:#?} {:#?}", nutrition_val, purchases_val))
|
2024-08-13 20:11:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
async fn html_demo(State(_state): State<Arc<AppState>>) -> Html<String> {
|
|
|
|
println!("Serving: html_demo");
|
|
|
|
|
|
|
|
Html("<body><p>This is HTML</p></body>".to_string())
|
|
|
|
}
|
|
|
|
|
2024-08-14 17:39:47 +02:00
|
|
|
async fn svg_image(State(_state): State<Arc<AppState>>) -> impl IntoResponse {
|
|
|
|
println!("Serving: svg_image");
|
|
|
|
let fun = plotting::SVGPlotter::examplefun();
|
|
|
|
plotting::SVGPlotter::plot(640, 480, fun)
|
2024-08-13 20:11:12 +02:00
|
|
|
}
|
|
|
|
|
2024-08-14 17:39:47 +02:00
|
|
|
async fn svg_calorie_intake(
|
|
|
|
State(state): State<Arc<AppState>>,
|
|
|
|
) -> Result<impl IntoResponse, my_structs::MyError> {
|
|
|
|
println!("Serving: svg_calorie_intake");
|
2024-08-13 20:11:12 +02:00
|
|
|
|
2024-08-14 17:39:47 +02:00
|
|
|
let nutrition_val_promise =
|
|
|
|
my_structs::Nutrition::get_nutrition_hashmap(state.sql_pool.clone());
|
|
|
|
let purchases_val_promise = my_structs::Purchase::get_purchase_rows(state.sql_pool.clone());
|
2024-08-13 20:11:12 +02:00
|
|
|
|
2024-08-14 17:39:47 +02:00
|
|
|
let nutrition_val = nutrition_val_promise.await?;
|
|
|
|
let purchases_val = purchases_val_promise.await?;
|
2024-08-13 20:11:12 +02:00
|
|
|
|
2024-08-14 17:39:47 +02:00
|
|
|
let plotfun = math::plot_calories_per_day(nutrition_val, purchases_val);
|
|
|
|
Ok(plotting::SVGPlotter::plot(640, 480, plotfun))
|
2024-08-13 20:11:12 +02:00
|
|
|
}
|
|
|
|
|
2024-08-14 17:39:47 +02:00
|
|
|
async fn png_image(State(_state): State<Arc<AppState>>) -> impl IntoResponse {
|
|
|
|
println!("Serving: png_image");
|
|
|
|
let fun = plotting::BitMapPlotter::examplefun();
|
|
|
|
plotting::BitMapPlotter::plot(640, 480, fun, plotting::BitMapOutputFormat::PNG)
|
2024-08-13 20:11:12 +02:00
|
|
|
}
|
|
|
|
|
2024-08-14 17:39:47 +02:00
|
|
|
async fn html_plotter(State(_state): State<Arc<AppState>>) -> Html<String> {
|
|
|
|
println!("Serving: html_plotter");
|
2024-08-13 20:11:12 +02:00
|
|
|
|
2024-08-14 17:39:47 +02:00
|
|
|
Html("<body><img src=/image.svg></img><img src=/calorie_intake.svg></img></body>".to_string())
|
2024-08-13 20:11:12 +02:00
|
|
|
}
|
|
|
|
|
2024-08-14 17:39:47 +02:00
|
|
|
async fn calorie_intake(State(_state): State<Arc<AppState>>) -> Html<String> {
|
|
|
|
println!("Serving: calorie_intake");
|
2024-08-13 20:11:12 +02:00
|
|
|
|
2024-08-14 17:39:47 +02:00
|
|
|
Html("<body><img src=/calorie_intake.svg></img></body>".to_string())
|
2024-08-13 20:11:12 +02:00
|
|
|
}
|
2024-08-16 13:05:57 +02:00
|
|
|
|
|
|
|
async fn wasm_test(State(_state): State<Arc<AppState>>) -> Html<String> {
|
|
|
|
println!("Serving: wasm_test");
|
|
|
|
|
|
|
|
Html(
|
|
|
|
"<head><script type='module'>
|
|
|
|
import init, { greet } from '/pkg/calories_browser.js';
|
|
|
|
await init();
|
|
|
|
greet('You!');
|
|
|
|
</script></head><body>wasm_test</body>"
|
|
|
|
.to_string(),
|
|
|
|
)
|
|
|
|
}
|