diff options
author | Melody Horn <melody@boringcactus.com> | 2021-12-04 17:35:02 -0700 |
---|---|---|
committer | Melody Horn <melody@boringcactus.com> | 2021-12-04 17:35:02 -0700 |
commit | 874077bf87e15208ba4d7bfab0095c3a60e4be17 (patch) | |
tree | f0e9ca4d4e11b8a2b72d1ceb5af98e0fb26a8333 /src | |
parent | ce5be7f783ac7c6589b501433caafd717c6e119f (diff) | |
download | queue-go-brrr-874077bf87e15208ba4d7bfab0095c3a60e4be17.tar.gz queue-go-brrr-874077bf87e15208ba4d7bfab0095c3a60e4be17.zip |
cock
Diffstat (limited to 'src')
-rw-r--r-- | src/lib.rs | 21 | ||||
-rw-r--r-- | src/ocr.rs | 39 |
2 files changed, 40 insertions, 20 deletions
@@ -2,6 +2,8 @@ use image::{DynamicImage, ImageFormat}; use std::cell::{Cell, RefCell}; use std::rc::Rc; +use futures::channel::mpsc; +use futures::prelude::*; use wasm_bindgen::prelude::*; use wasm_bindgen::JsCast; use wasm_bindgen_futures::*; @@ -84,6 +86,8 @@ async fn do_boot() { let history = Rc::new(RefCell::new(history::History::default())); + let (manual_update_tx, manual_update_rx) = mpsc::channel::<()>(5); + let video: HtmlVideoElement = document .get_element_by_id("video") .unwrap() @@ -107,7 +111,9 @@ async fn do_boot() { let width = width.clone(); let height = height.clone(); let target_marker = target_marker.clone(); + let manual_update_tx = manual_update_tx.clone(); gloo::events::EventListener::new(&video, "click", move |event| { + let mut manual_update_tx = manual_update_tx.clone(); let video = also_video.clone(); let mouse_event: &MouseEvent = event.dyn_ref().unwrap(); let mouse_x = mouse_event.offset_x() as f64; @@ -120,6 +126,7 @@ async fn do_boot() { let real_y = mouse_y / fake_height * real_height - QUEUE_SIZE_HEIGHT as f64 / 2.0; queue_position.replace((real_x.round() as u32, real_y.round() as u32)); update_target_marker(&target_marker, &width, &height, &video, &queue_position); + spawn_local(async move { manual_update_tx.send(()).await.unwrap() }); }) }; video_click_listener.forget(); @@ -146,7 +153,9 @@ async fn do_boot() { let also_video = video.clone(); let canvas = canvas.clone(); let queue_position = queue_position.clone(); + let manual_update_tx = manual_update_tx.clone(); gloo::events::EventListener::new(&video, "canplay", move |_event| { + let mut manual_update_tx = manual_update_tx.clone(); let video = also_video.clone(); let _ = video.play().unwrap(); if !streaming.get() { @@ -156,16 +165,21 @@ async fn do_boot() { canvas.set_attribute("height", &format!("{}", height.get())); streaming.set(true); update_target_marker(&target_marker, &width, &height, &video, &queue_position); + spawn_local(async move { manual_update_tx.send(()).await.unwrap() }); } }) }; video_play_listener.forget(); - let update_interval = gloo::timers::callback::Interval::new(2_000, move || { + let update_stream = futures::stream_select!( + gloo::timers::future::IntervalStream::new(2_000), + manual_update_rx, + ); + let update_future = update_stream.for_each(move |_| { let history = history.clone(); let queue_position = queue_position.clone(); if !streaming.get() { - return; + return futures::future::ready(()); } let context = canvas.get_context("2d").unwrap().unwrap(); let context: CanvasRenderingContext2d = context.dyn_into().unwrap(); @@ -247,8 +261,9 @@ async fn do_boot() { .unwrap(), ) .unwrap(); + futures::future::ready(()) }); - update_interval.forget(); + spawn_local(update_future); } #[wasm_bindgen] @@ -1,18 +1,27 @@ use image::{DynamicImage, GrayImage, ImageFormat}; use imageproc::template_matching::MatchTemplateMethod; +use lazy_static::lazy_static; -const REFERENCE_PNGS: [&[u8]; 10] = [ - include_bytes!("../data/0.png"), - include_bytes!("../data/1.png"), - include_bytes!("../data/2.png"), - include_bytes!("../data/3.png"), - include_bytes!("../data/4.png"), - include_bytes!("../data/5.png"), - include_bytes!("../data/6.png"), - include_bytes!("../data/7.png"), - include_bytes!("../data/8.png"), - include_bytes!("../data/9.png"), -]; +lazy_static! { + static ref REFERENCES: [GrayImage; 10] = { + let parse = |data: &[u8]| { + let png = image::load_from_memory_with_format(data, ImageFormat::Png).unwrap(); + image::imageops::grayscale(&png) + }; + [ + parse(include_bytes!("../data/0.png")), + parse(include_bytes!("../data/1.png")), + parse(include_bytes!("../data/2.png")), + parse(include_bytes!("../data/3.png")), + parse(include_bytes!("../data/4.png")), + parse(include_bytes!("../data/5.png")), + parse(include_bytes!("../data/6.png")), + parse(include_bytes!("../data/7.png")), + parse(include_bytes!("../data/8.png")), + parse(include_bytes!("../data/9.png")), + ] + }; +} fn x_matches(image: &GrayImage, template: &GrayImage) -> Vec<u32> { let match_values = imageproc::template_matching::match_template( @@ -31,11 +40,7 @@ pub fn ocr(image: DynamicImage) -> Option<u32> { let grayscale_image = image::imageops::grayscale(&image); let mut digit_x_positions: Vec<(u8, u32)> = (0..10) .flat_map(|i| { - let png_i = - image::load_from_memory_with_format(REFERENCE_PNGS[i as usize], ImageFormat::Png) - .unwrap(); - let grey_png_i = image::imageops::grayscale(&png_i); - x_matches(&grayscale_image, &grey_png_i) + x_matches(&grayscale_image, &REFERENCES[i as usize]) .into_iter() .map(move |x| (i, x)) }) |