server.rs
1 use std::{collections::HashSet, fs, sync::Arc, time::Duration}; 2 3 use axum::{ 4 extract::{ws::Message, Path, State}, 5 response::{Html, IntoResponse}, 6 routing::{get, post}, 7 Json, Router, 8 }; 9 use base64::{prelude::BASE64_STANDARD, Engine}; 10 use rand::{thread_rng, Rng}; 11 use serde::Serialize; 12 use tokio::{ 13 sync::{broadcast, Mutex, RwLock}, 14 time, 15 }; 16 use tower_http::compression::CompressionLayer; 17 18 use crate::{ 19 fine_grained::Grid2, 20 grid::{Grid, SubRectInfo}, 21 state::AppState, 22 ws, 23 }; 24 25 /* 26 async fn get_grid( 27 Path((from_index, to_index)): Path<(usize, usize)>, 28 State(state): State<AppState>, 29 ) -> impl IntoResponse { 30 let grid = state.grid.read().await; 31 let item = grid.get_item(from_index); 32 if let Some(item) = item { 33 item.to_string() 34 } else { 35 "None".to_owned() 36 } 37 } 38 */ 39 40 async fn set_checkbox( 41 Path(index): Path<usize>, 42 State(state): State<AppState>, 43 ) -> impl IntoResponse { 44 let toggled = state.toggle(index).await; 45 46 if toggled { 47 "1" 48 } else { 49 "0" 50 } 51 } 52 53 async fn index() -> impl IntoResponse { 54 Html( 55 r#""" 56 <html> 57 <head><title>Grid shit</title></head> 58 <body> 59 <h1>Here'll be dynamic grid</h1> 60 </body> 61 </html> 62 """#, 63 ) 64 } 65 66 async fn full_grid(State(state): State<AppState>) -> impl IntoResponse { 67 let grid = state.grid.read().await; 68 let full = grid.get_full().await; 69 70 BASE64_STANDARD.encode(full) 71 } 72 73 async fn sub_grid(State(state): State<AppState>) -> impl IntoResponse { 74 let grid = state.grid.read().await; 75 let x_shift = rand::thread_rng().gen_range(0..(125 - 10)); 76 let y_shift = rand::thread_rng().gen_range(0..(1000 - 80)); 77 let subgrid = grid.get_rect(x_shift, y_shift, 10, 80).await; 78 let subgrid2 = SubRectInfoJson::from_info(&subgrid); 79 Json(subgrid2) 80 } 81 82 #[derive(Serialize)] 83 pub struct SubRectInfoJson { 84 pub data: String, 85 pub x_shift: usize, 86 pub y_shift: usize, 87 pub width: usize, 88 pub height: usize, 89 pub canvas_width: usize, 90 } 91 92 impl SubRectInfoJson { 93 fn from_info(info: &SubRectInfo) -> Self { 94 Self { 95 data: BASE64_STANDARD.encode(info.data.clone()), 96 x_shift: info.x_shift, 97 y_shift: info.y_shift, 98 width: info.width, 99 height: info.height, 100 canvas_width: info.canvas_width, 101 } 102 } 103 } 104 105 pub fn router(state: AppState) -> Router { 106 Router::new() 107 .route("/ws", get(ws::ws_grid)) 108 .route("/api/grid", get(full_grid)) 109 .route("/api/subgrid", get(sub_grid)) 110 .route("/set/:index", post(set_checkbox)) 111 //.route("/grid/:from/:to", get(get_grid)) 112 .route("/", get(index)) 113 .layer(CompressionLayer::new()) 114 .with_state(state) 115 } 116 117 #[cfg(test)] 118 mod tests { 119 use image::{buffer, GenericImage, GenericImageView}; 120 121 use crate::{ 122 bit_utils::{get_bit, set_bit}, 123 fine_grained::Grid2, 124 grid::{Grid, MAX_SIZE}, 125 state::PointQueue, 126 }; 127 128 #[test] 129 fn json_test() { 130 let mut pq = PointQueue::new(); 131 pq.off.insert(1111); 132 pq.on.insert(323123); 133 let result = serde_json::to_string(&pq); 134 dbg!(result); 135 } 136 137 #[tokio::test] 138 async fn create_png() { 139 let grid = Grid2::new(); 140 141 let buffer = grid.get_full().await; 142 143 let mut imgbuf = image::ImageBuffer::new(1000, 1000); 144 145 let filled_color = image::Rgb([255u8, 0u8, 0u8]); 146 let empty_color = image::Rgb([255u8, 255u8, 255u8]); 147 148 for i in 0..MAX_SIZE * 8 { 149 let bit_index = i % 8; 150 let byte_index = i / 8; 151 let byte = buffer[byte_index]; 152 let bit_value = get_bit(byte, bit_index); 153 154 let x = i % 1000; 155 let y = i / 1000; 156 imgbuf.put_pixel( 157 x as u32, 158 y as u32, 159 if bit_value { filled_color } else { empty_color }, 160 ); 161 } 162 163 imgbuf.save("dump.png").unwrap(); 164 } 165 166 #[tokio::test] 167 async fn load_png() { 168 let mut grid = Grid2::new(); 169 170 let empty_color = image::Rgba([255u8, 255u8, 255u8, 255u8]); 171 172 let img = image::open("dump.png").unwrap(); 173 174 let mut buffer: [u8; MAX_SIZE] = [0; MAX_SIZE]; 175 176 for i in 0..MAX_SIZE * 8 { 177 let bit_index = i % 8; 178 let byte_index = i / 8; 179 180 let x = (i % 1000) as u32; 181 let y = (i / 1000) as u32; 182 183 let byte = buffer[byte_index]; 184 185 //imgbuf.put_pixel(x as u32, y as u32, if bit_value { filled_color } else { empty_color }); 186 let color = img.get_pixel(x, y); 187 let byte = if color == empty_color { 188 set_bit(byte, bit_index, false) 189 } else { 190 set_bit(byte, bit_index, true) 191 }; 192 193 buffer[byte_index] = byte; 194 } 195 196 grid.set_full(buffer).await; 197 } 198 }