Compare commits
No commits in common. "a4578c004fec9667df2372aaa115c827d229fd83" and "81be549ac9250387615a61e91d1b784ead0e1365" have entirely different histories.
a4578c004f
...
81be549ac9
2
browser/pkg/calories_browser.d.ts
vendored
2
browser/pkg/calories_browser.d.ts
vendored
@ -27,8 +27,8 @@ export interface InitOutput {
|
||||
readonly __wbindgen_malloc: (a: number, b: number) => number;
|
||||
readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
||||
readonly __wbindgen_export_2: WebAssembly.Table;
|
||||
readonly _dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__hda38a12a2a1c09dc: (a: number, b: number) => void;
|
||||
readonly _dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h3ee002e21c3855c9: (a: number, b: number, c: number) => void;
|
||||
readonly _dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__hda38a12a2a1c09dc: (a: number, b: number) => void;
|
||||
readonly _dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__ha7dc131e1b42f45e: (a: number, b: number, c: number) => void;
|
||||
readonly __wbindgen_add_to_stack_pointer: (a: number) => number;
|
||||
readonly __wbindgen_free: (a: number, b: number, c: number) => void;
|
||||
|
@ -211,12 +211,12 @@ function makeMutClosure(arg0, arg1, dtor, f) {
|
||||
CLOSURE_DTORS.register(real, state, state);
|
||||
return real;
|
||||
}
|
||||
function __wbg_adapter_36(arg0, arg1) {
|
||||
wasm._dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__hda38a12a2a1c09dc(arg0, arg1);
|
||||
function __wbg_adapter_36(arg0, arg1, arg2) {
|
||||
wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h3ee002e21c3855c9(arg0, arg1, addHeapObject(arg2));
|
||||
}
|
||||
|
||||
function __wbg_adapter_39(arg0, arg1, arg2) {
|
||||
wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h3ee002e21c3855c9(arg0, arg1, addHeapObject(arg2));
|
||||
function __wbg_adapter_39(arg0, arg1) {
|
||||
wasm._dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__hda38a12a2a1c09dc(arg0, arg1);
|
||||
}
|
||||
|
||||
function __wbg_adapter_42(arg0, arg1, arg2) {
|
||||
@ -275,7 +275,7 @@ function passArray8ToWasm0(arg, malloc) {
|
||||
WASM_VECTOR_LEN = arg.length;
|
||||
return ptr;
|
||||
}
|
||||
function __wbg_adapter_197(arg0, arg1, arg2, arg3) {
|
||||
function __wbg_adapter_205(arg0, arg1, arg2, arg3) {
|
||||
wasm.wasm_bindgen__convert__closures__invoke2_mut__h101e073056d1eef9(arg0, arg1, addHeapObject(arg2), addHeapObject(arg3));
|
||||
}
|
||||
|
||||
@ -551,6 +551,20 @@ function __wbg_get_imports() {
|
||||
const ret = result;
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbg_setwidth_7aa91c44601eed4e = function(arg0, arg1) {
|
||||
getObject(arg0).width = arg1 >>> 0;
|
||||
};
|
||||
imports.wbg.__wbg_setheight_e6f800ffbc3ea28e = function(arg0, arg1) {
|
||||
getObject(arg0).height = arg1 >>> 0;
|
||||
};
|
||||
imports.wbg.__wbg_videoWidth_5f4190ae93af0dd6 = function(arg0) {
|
||||
const ret = getObject(arg0).videoWidth;
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbg_videoHeight_4fb4bdd27e02263a = function(arg0) {
|
||||
const ret = getObject(arg0).videoHeight;
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbg_set_b3c7c6d2e5e783d6 = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) {
|
||||
getObject(arg0).set(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4));
|
||||
}, arguments) };
|
||||
@ -769,7 +783,7 @@ function __wbg_get_imports() {
|
||||
const a = state0.a;
|
||||
state0.a = 0;
|
||||
try {
|
||||
return __wbg_adapter_197(a, state0.b, arg0, arg1);
|
||||
return __wbg_adapter_205(a, state0.b, arg0, arg1);
|
||||
} finally {
|
||||
state0.a = a;
|
||||
}
|
||||
@ -839,16 +853,16 @@ function __wbg_get_imports() {
|
||||
const ret = wasm.memory;
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_closure_wrapper171 = function(arg0, arg1, arg2) {
|
||||
const ret = makeMutClosure(arg0, arg1, 27, __wbg_adapter_36);
|
||||
imports.wbg.__wbindgen_closure_wrapper199 = function(arg0, arg1, arg2) {
|
||||
const ret = makeMutClosure(arg0, arg1, 33, __wbg_adapter_36);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_closure_wrapper172 = function(arg0, arg1, arg2) {
|
||||
const ret = makeMutClosure(arg0, arg1, 27, __wbg_adapter_39);
|
||||
imports.wbg.__wbindgen_closure_wrapper200 = function(arg0, arg1, arg2) {
|
||||
const ret = makeMutClosure(arg0, arg1, 33, __wbg_adapter_39);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
imports.wbg.__wbindgen_closure_wrapper1787 = function(arg0, arg1, arg2) {
|
||||
const ret = makeMutClosure(arg0, arg1, 495, __wbg_adapter_42);
|
||||
imports.wbg.__wbindgen_closure_wrapper1797 = function(arg0, arg1, arg2) {
|
||||
const ret = makeMutClosure(arg0, arg1, 498, __wbg_adapter_42);
|
||||
return addHeapObject(ret);
|
||||
};
|
||||
|
||||
|
Binary file not shown.
2
browser/pkg/calories_browser_bg.wasm.d.ts
vendored
2
browser/pkg/calories_browser_bg.wasm.d.ts
vendored
@ -8,8 +8,8 @@ export function enable_panic_debug(): void;
|
||||
export function __wbindgen_malloc(a: number, b: number): number;
|
||||
export function __wbindgen_realloc(a: number, b: number, c: number, d: number): number;
|
||||
export const __wbindgen_export_2: WebAssembly.Table;
|
||||
export function _dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__hda38a12a2a1c09dc(a: number, b: number): void;
|
||||
export function _dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__h3ee002e21c3855c9(a: number, b: number, c: number): void;
|
||||
export function _dyn_core__ops__function__FnMut_____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__hda38a12a2a1c09dc(a: number, b: number): void;
|
||||
export function _dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__ha7dc131e1b42f45e(a: number, b: number, c: number): void;
|
||||
export function __wbindgen_add_to_stack_pointer(a: number): number;
|
||||
export function __wbindgen_free(a: number, b: number, c: number): void;
|
||||
|
@ -73,6 +73,7 @@ pub fn init_camera_feed(product_options_js: JsValue) -> Result<(), String> {
|
||||
};
|
||||
product_options.push(test);
|
||||
|
||||
let video: HtmlVideoElement = get_element_by_id(VIDEO_ID).unwrap();
|
||||
let canvas: HtmlCanvasElement = get_element_by_id(CANVAS_ID).unwrap();
|
||||
let button: HtmlButtonElement = get_element_by_id(SCAN_BUTTON_ID).unwrap();
|
||||
let search: HtmlInputElement = get_element_by_id(SEARCH_FIELD_ID).unwrap();
|
||||
@ -103,9 +104,23 @@ pub fn init_camera_feed(product_options_js: JsValue) -> Result<(), String> {
|
||||
succ.forget(); // Memory leak
|
||||
fail.forget(); // Memory leak
|
||||
|
||||
canvas.set_width(CANVAS_WIDTH);
|
||||
canvas.set_height(CANVAS_HEIGHT);
|
||||
let set_width_and_height: Closure<dyn FnMut()> = Closure::new(move || {
|
||||
let video: HtmlVideoElement = get_element_by_id(VIDEO_ID).unwrap();
|
||||
|
||||
let width: u32 = 1920;
|
||||
let height: u32 =
|
||||
((width as f32 / video.video_width() as f32) * video.video_height() as f32) as u32;
|
||||
|
||||
video.set_width(width);
|
||||
video.set_height(height);
|
||||
canvas.set_width(CANVAS_WIDTH);
|
||||
canvas.set_height(CANVAS_HEIGHT);
|
||||
});
|
||||
|
||||
let _ = video
|
||||
.add_event_listener_with_callback("canplay", set_width_and_height.as_ref().unchecked_ref());
|
||||
set_width_and_height.forget(); // Memory leak
|
||||
//
|
||||
let scan_barcode_wrapper: Closure<dyn FnMut()> = Closure::new(move || {
|
||||
match scan_barcode(product_options.clone()) {
|
||||
Ok(()) => {}
|
||||
|
@ -24,44 +24,17 @@
|
||||
grid-column: span 3;
|
||||
}
|
||||
|
||||
.col-4 {
|
||||
grid-column: span 4;
|
||||
}
|
||||
|
||||
.col-5 {
|
||||
grid-column: span 5;
|
||||
}
|
||||
|
||||
.col-6 {
|
||||
grid-column: span 6;
|
||||
}
|
||||
|
||||
.col-7 {
|
||||
grid-column: span 7;
|
||||
}
|
||||
|
||||
.col-8 {
|
||||
grid-column: span 8;
|
||||
}
|
||||
|
||||
.col-9 {
|
||||
grid-column: span 9;
|
||||
}
|
||||
|
||||
.col-10 {
|
||||
grid-column: span 10;
|
||||
}
|
||||
|
||||
.col-11 {
|
||||
grid-column: span 11;
|
||||
}
|
||||
|
||||
.col-12 {
|
||||
grid-column: span 12;
|
||||
}
|
||||
|
||||
#video {
|
||||
width: 100%;
|
||||
#video_container {
|
||||
width: 100%;
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* The search field */
|
||||
@ -70,22 +43,14 @@
|
||||
background-image: url('/assets/searchicon.png');
|
||||
background-position: 14px 12px;
|
||||
background-repeat: no-repeat;
|
||||
font-size: 1em;
|
||||
font-size: 16px;
|
||||
padding: 14px 20px 12px 45px;
|
||||
border: none;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
/* The search field when it gets focus/clicked on */
|
||||
#myInput:focus {
|
||||
outline: 3px solid #ddd;
|
||||
}
|
||||
|
||||
#amount {
|
||||
font-size: 1em;
|
||||
width: 3em;
|
||||
height: calc(100% - 4px);;
|
||||
}
|
||||
#myInput:focus {outline: 3px solid #ddd;}
|
||||
|
||||
/* The container <div> - needed to position the dropdown content */
|
||||
.dropdown {
|
||||
@ -98,19 +63,15 @@
|
||||
.dropdown-content {
|
||||
position: relative;
|
||||
background-color: #f6f6f6;
|
||||
width: calc(100% - 2px);
|
||||
min-width: 230px;
|
||||
border: 1px solid #ddd;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.dropdown-input {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.dropdown-options {
|
||||
position: absolute;
|
||||
background-color: #f6f6f6;
|
||||
width: calc(100% - 2px);
|
||||
min-width: 230px;
|
||||
border: 1px solid #ddd;
|
||||
z-index: 1;
|
||||
}
|
||||
|
@ -21,7 +21,6 @@ mod math;
|
||||
mod my_structs;
|
||||
use my_structs::MyError;
|
||||
use my_structs::Purchase;
|
||||
use my_structs::Weight;
|
||||
mod plotting;
|
||||
// use crate::plotting::Plotter;
|
||||
use std::{thread, time};
|
||||
@ -69,7 +68,6 @@ async fn main() {
|
||||
.route("/image.png", get(png_image))
|
||||
.route("/image.svg", get(svg_image))
|
||||
.route("/calorie_intake.svg", get(svg_calorie_intake))
|
||||
.route("/weight_loss.svg", get(svg_weight_loss))
|
||||
.route("/calorie_intake", get(calorie_intake))
|
||||
.route("/wasm_test", get(wasm_test))
|
||||
.route("/camera_test", get(camera_test))
|
||||
@ -141,21 +139,6 @@ async fn svg_calorie_intake(
|
||||
Ok(plotting::SVGPlotter::plot(640, 480, plotfun))
|
||||
}
|
||||
|
||||
async fn svg_weight_loss(State(state): State<Arc<AppState>>) -> Result<impl IntoResponse, MyError> {
|
||||
println!("Serving: svg_weight_loss");
|
||||
|
||||
let nutrition_val_promise = Nutrition::get_nutrition_hashmap(state.sql_pool.clone());
|
||||
let purchases_val_promise = Purchase::get_purchase_rows(state.sql_pool.clone());
|
||||
let weight_val_promise = Weight::get_weight_rows(state.sql_pool.clone());
|
||||
|
||||
let nutrition_val = nutrition_val_promise.await?;
|
||||
let purchases_val = purchases_val_promise.await?;
|
||||
let weight_val = weight_val_promise.await?;
|
||||
|
||||
let plotfun = math::plot_weight_loss(nutrition_val, purchases_val, weight_val);
|
||||
Ok(plotting::SVGPlotter::plot(640, 480, plotfun))
|
||||
}
|
||||
|
||||
async fn png_image(State(_state): State<Arc<AppState>>) -> impl IntoResponse {
|
||||
println!("Serving: png_image");
|
||||
let fun = plotting::BitMapPlotter::examplefun();
|
||||
@ -171,10 +154,7 @@ async fn html_plotter(State(_state): State<Arc<AppState>>) -> Html<String> {
|
||||
async fn calorie_intake(State(_state): State<Arc<AppState>>) -> Html<String> {
|
||||
println!("Serving: calorie_intake");
|
||||
|
||||
Html(
|
||||
"<body><img src=/calorie_intake.svg><br><img src=/weight_loss.svg></img></body>"
|
||||
.to_string(),
|
||||
)
|
||||
Html("<body><img src=/calorie_intake.svg></img></body>".to_string())
|
||||
}
|
||||
|
||||
fn construct_js(path: &str) -> Result<String, MyError> {
|
||||
|
@ -1,4 +1,3 @@
|
||||
// pub use self::calculations::calculate_calories_per_day;
|
||||
pub use self::calculations::plot_calories_per_day;
|
||||
pub use self::calculations::plot_weight_loss;
|
||||
mod calculations;
|
||||
|
@ -153,119 +153,3 @@ pub fn plot_calories_per_day(
|
||||
});
|
||||
plotfun
|
||||
}
|
||||
|
||||
pub fn plot_weight_loss(
|
||||
nutrition_map: HashMap<u32, Nutrition>,
|
||||
purchases: Vec<my_structs::Purchase>,
|
||||
weight: Vec<my_structs::Weight>,
|
||||
) -> plotting::SVGPlotFun {
|
||||
let (mindate, calorie_days) = calculate_calories_per_day(nutrition_map, purchases);
|
||||
let calories_burned_per_day: f32 = 2200.;
|
||||
let deficit_days: Vec<f32> = calorie_days
|
||||
.iter()
|
||||
.scan(0., |deficit, &calories| {
|
||||
*deficit += calories - calories_burned_per_day;
|
||||
Some(*deficit)
|
||||
})
|
||||
.collect();
|
||||
|
||||
let maxdate = mindate
|
||||
.checked_add(Duration::days(deficit_days.len().try_into().unwrap()))
|
||||
.unwrap();
|
||||
|
||||
let mindate_chrono = time_date_to_chrono_naive_date(mindate);
|
||||
let maxdate_chrono = time_date_to_chrono_naive_date(maxdate);
|
||||
let today_chrono = DateTime::<Utc>::from(SystemTime::now()).date_naive();
|
||||
|
||||
let max_weight = weight
|
||||
.iter()
|
||||
.map(|w| w.weight)
|
||||
.reduce(|a, b| a.max(b))
|
||||
.unwrap();
|
||||
|
||||
let min_weight = weight
|
||||
.iter()
|
||||
.map(|w| w.weight)
|
||||
.reduce(|a, b| a.min(b))
|
||||
.unwrap();
|
||||
|
||||
let plotfun = Box::new(move |root: plotting::SVGPlotRoot| {
|
||||
root.fill(&WHITE).unwrap();
|
||||
let mut chart = ChartBuilder::on(&root)
|
||||
.caption("Weight loss", ("sans-serif", 50).into_font())
|
||||
// .margin(20)
|
||||
.x_label_area_size(30)
|
||||
.y_label_area_size(50)
|
||||
.build_cartesian_2d(
|
||||
mindate_chrono..maxdate_chrono,
|
||||
(min_weight - 2.)..(max_weight + 2.),
|
||||
// 70_f32..90_f32,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
chart
|
||||
.configure_mesh()
|
||||
.y_desc("kg fat burned")
|
||||
.y_max_light_lines(4)
|
||||
.x_max_light_lines(6)
|
||||
.draw()
|
||||
.unwrap();
|
||||
|
||||
chart
|
||||
.draw_series(LineSeries::new(
|
||||
vec![
|
||||
(today_chrono, min_weight - 2.),
|
||||
(today_chrono, max_weight + 2.),
|
||||
],
|
||||
BLACK.stroke_width(2),
|
||||
))
|
||||
.unwrap()
|
||||
.label("today")
|
||||
.legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], BLACK));
|
||||
|
||||
chart
|
||||
.draw_series(LineSeries::new(
|
||||
deficit_days.iter().enumerate().map(|(i, cal)| {
|
||||
(
|
||||
mindate_chrono
|
||||
.checked_add_days(chrono::Days::new(i.try_into().unwrap()))
|
||||
.unwrap(),
|
||||
*cal / 7000. + weight[0].weight + 1.,
|
||||
)
|
||||
}),
|
||||
RED.stroke_width(3),
|
||||
))
|
||||
.unwrap()
|
||||
.label("kg burned")
|
||||
.legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], RED));
|
||||
|
||||
chart
|
||||
.draw_series(LineSeries::new(
|
||||
weight.iter().map(|w| {
|
||||
(
|
||||
time_date_to_chrono_naive_date(w.datetime.date()),
|
||||
// mindate_chrono
|
||||
// .checked_add_days(chrono::Days::new(i.try_into().unwrap()))
|
||||
// .unwrap(),
|
||||
w.weight,
|
||||
)
|
||||
}),
|
||||
BLUE.stroke_width(3),
|
||||
))
|
||||
.unwrap()
|
||||
.label("weight")
|
||||
.legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], BLUE));
|
||||
|
||||
// Show labels
|
||||
chart
|
||||
.configure_series_labels()
|
||||
.background_style(WHITE.mix(0.8))
|
||||
.border_style(BLACK)
|
||||
.position(SeriesLabelPosition::LowerRight)
|
||||
.draw()
|
||||
.unwrap();
|
||||
|
||||
root.present().unwrap();
|
||||
});
|
||||
plotfun
|
||||
}
|
||||
|
@ -1,6 +1,4 @@
|
||||
pub use self::myerror::MyError;
|
||||
pub use self::purchases::Purchase;
|
||||
pub use self::weight::Weight;
|
||||
mod myerror;
|
||||
mod purchases;
|
||||
mod weight;
|
||||
|
@ -1,54 +0,0 @@
|
||||
use mysql::prelude::*;
|
||||
use mysql::*;
|
||||
use mysql_common::frunk::{hlist_pat, HList};
|
||||
use struct_field_names_as_array::FieldNamesAsArray;
|
||||
use time::PrimitiveDateTime;
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
#[derive(Debug, PartialEq, FieldNamesAsArray)]
|
||||
pub struct Weight {
|
||||
id: u32,
|
||||
pub weight: f32,
|
||||
pub datetime: PrimitiveDateTime,
|
||||
}
|
||||
|
||||
type RowType = HList!(u32, f32, PrimitiveDateTime);
|
||||
|
||||
impl Weight {
|
||||
fn get_sql_fields() -> String {
|
||||
Weight::FIELD_NAMES_AS_ARRAY
|
||||
.iter()
|
||||
.cloned()
|
||||
.intersperse(", ")
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn query_map_helper() -> (String, impl Fn(RowType) -> Weight) {
|
||||
let sql_query = format!("SELECT {} from weight", Self::get_sql_fields());
|
||||
println!("{}", sql_query);
|
||||
|
||||
let construction_closure = |row: RowType| {
|
||||
let hlist_pat![id, weight, datetime] = row;
|
||||
Weight {
|
||||
id,
|
||||
weight,
|
||||
datetime,
|
||||
}
|
||||
};
|
||||
|
||||
(sql_query, construction_closure)
|
||||
}
|
||||
|
||||
pub async fn get_weight_rows(sql_pool: Pool) -> Result<Vec<Weight>> {
|
||||
let mut conn = sql_pool
|
||||
.get_conn()
|
||||
.expect("Cannot establish database connection");
|
||||
|
||||
let (weight_query, weight_closure) = Self::query_map_helper();
|
||||
let weight_val: Vec<Weight> = conn
|
||||
.query_map(weight_query, weight_closure)
|
||||
.expect("Data in database doesn't match the Weight class");
|
||||
|
||||
Ok(weight_val)
|
||||
}
|
||||
}
|
@ -3,15 +3,10 @@
|
||||
<video id="video">Camera not available.</video>
|
||||
<canvas id="canvas" hidden> </canvas>
|
||||
</div>
|
||||
<div class="subgrid col-12">
|
||||
<div class="dropdown col-11">
|
||||
<div id="myDropdown" class="dropdown-content">
|
||||
<input type="text" placeholder="Search.." id="myInput" class="dropdown-input">
|
||||
<div id="dropdownOptions" class="dropdown-options"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<input type="number" id="amount" name="amount" min="1" value="1"/>
|
||||
<div class="dropdown col-12">
|
||||
<div id="myDropdown" class="dropdown-content">
|
||||
<input type="text" placeholder="Search.." id="myInput">
|
||||
<div id="dropdownOptions" class="dropdown-options"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
|
Loading…
Reference in New Issue
Block a user