calories/src/main.rs

129 lines
4.0 KiB
Rust
Raw Normal View History

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},
routing::get,
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-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-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
}