#![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)) .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()) } async fn wasm_test(State(_state): State>) -> Html { println!("Serving: wasm_test"); Html( "wasm_test" .to_string(), ) }