#![feature(iter_intersperse)] use axum::{ extract::State, http::{ // header, StatusCode, Uri, }, response::{Html, IntoResponse}, routing::{get, get_service}, Router, }; // use image::ImageFormat; // use mysql::prelude::*; use mysql::*; // use plotters::prelude::*; // use std::io::{BufWriter, Cursor}; use std::sync::Arc; mod math; mod my_structs; mod plotting; // use crate::my_structs::MyError; // use crate::plotting::Plotter; use std::{thread, time}; use tower_http::services::ServeDir; #[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; } else { println!("Cannot connect to SQL database. Retrying"); thread::sleep(time::Duration::from_millis(1000)); } } } #[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)) .route("/calorie_intake.svg", get(svg_calorie_intake)) .route("/calorie_intake", get(calorie_intake)) .route("/wasm_test", get(wasm_test)) .route("/camera_test", get(camera_test)) .nest_service("/pkg", get_service(ServeDir::new("../browser/pkg"))) .with_state(shared_state) .fallback(not_found); // 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(); } async fn not_found(uri: Uri) -> (StatusCode, String) { (StatusCode::NOT_FOUND, format!("404 not found: {uri}")) } async fn get_rows(State(state): State>) -> Result { 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()); let nutrition_val = nutrition_val_promise.await?; let purchases_val = purchases_val_promise.await?; println!("Serving: get_rows"); // Ok("See print logs instead".to_string()) Ok(format!("{:#?} {:#?}", nutrition_val, purchases_val)) } async fn html_demo(State(_state): State>) -> Html { println!("Serving: html_demo"); Html("

This is HTML

".to_string()) } async fn svg_image(State(_state): State>) -> impl IntoResponse { println!("Serving: svg_image"); let fun = plotting::SVGPlotter::examplefun(); plotting::SVGPlotter::plot(640, 480, fun) } async fn svg_calorie_intake( State(state): State>, ) -> Result { println!("Serving: svg_calorie_intake"); 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()); let nutrition_val = nutrition_val_promise.await?; let purchases_val = purchases_val_promise.await?; let plotfun = math::plot_calories_per_day(nutrition_val, purchases_val); Ok(plotting::SVGPlotter::plot(640, 480, plotfun)) } async fn png_image(State(_state): State>) -> impl IntoResponse { println!("Serving: png_image"); let fun = plotting::BitMapPlotter::examplefun(); plotting::BitMapPlotter::plot(640, 480, fun, plotting::BitMapOutputFormat::PNG) } async fn html_plotter(State(_state): State>) -> Html { println!("Serving: html_plotter"); Html("".to_string()) } async fn calorie_intake(State(_state): State>) -> Html { println!("Serving: calorie_intake"); Html("".to_string()) } fn construct_js(path: &str) -> Result { let javascript = std::fs::read_to_string(format!("../javascript/{}", path))?; let module = format!( " ", javascript ); Ok(module) } fn construct_tmpl(path: &str) -> Result { Ok(std::fs::read_to_string(format!("../templates/{}", path))?) } fn construct_html( js_paths: Vec<&str>, tmpl_paths: Vec<&str>, ) -> Result { let js_modules: Vec = js_paths .into_iter() .map(construct_js) .collect::, my_structs::MyError>>()?; let tmpl_snippets: Vec = tmpl_paths .into_iter() .map(construct_tmpl) .collect::, my_structs::MyError>>()?; let html = format!( " {} {} ", js_modules.join(""), tmpl_snippets.join("") ); Ok(html) } fn get_template(path: &str) -> Result { Ok(std::fs::read_to_string(format!("../templates/{}", path))?) } async fn wasm_test( State(_state): State>, ) -> Result, my_structs::MyError> { println!("Serving: wasm_test"); let content = get_template("view_calories.html")?; Ok(Html(content)) } async fn camera_test( State(_state): State>, ) -> Result, my_structs::MyError> { println!("Serving: camera_test"); let html = construct_html(vec!["camera.js"], vec!["camera_test.html"])?; Ok(Html(html)) }