diff options
-rw-r--r-- | assets/index.html | 9 | ||||
-rw-r--r-- | assets/style.css | 9 | ||||
-rw-r--r-- | conf.json.sample | 4 | ||||
-rw-r--r-- | src/main.rs | 43 |
4 files changed, 55 insertions, 10 deletions
diff --git a/assets/index.html b/assets/index.html index 69f1958..9282726 100644 --- a/assets/index.html +++ b/assets/index.html @@ -38,9 +38,12 @@ fetch("rspace").then(resp => resp.text()).then(roomspace => { let roomspacenum = Number(roomspace); let e = document.getElementById('rspace'); - let t = document.createTextNode("room slots filled, if a room empties of active players it can be replaced by a new one"); + if (roomspacenum == 0) { + e.appendChild(document.createTextNode("all room slots filled, when a room empties it can be replaced by a new one")); + document.getElementById("createbtn").disabled = "disabled"; + } if (roomspacenum == 1) { - e.appendChild(document.createTextNode(`there is one available room slot`)); + e.appendChild(document.createTextNode(`there is 1 available room slot`)); } else if (roomspacenum > 1) { e.appendChild(document.createTextNode(`there are ${roomspacenum} available room slots`)); } @@ -61,7 +64,7 @@ <label>public, ie. shown in the lobby <input name="raccess" type="checkbox" checked></label><br> <label>safe first move (if possible)<input name="ralwayssafe1move" type="checkbox" checked></label><br> <label>player limit<input name="rlimit" type="number" value="32"></label><br> - <button>create</button> + <button id="createbtn">create</button> </fieldset> <form> </body> diff --git a/assets/style.css b/assets/style.css index 66130eb..58da34f 100644 --- a/assets/style.css +++ b/assets/style.css @@ -36,13 +36,18 @@ body { padding: 0.1em 0.1em; } -#rlist a, span { +#rlist a, #rlist span { text-decoration: none; - line-height: 0.4; color: #dfdfff; background-color: #3c3c3c; } +span, h1, h4 { + margin: 0 auto; +} + +h4 { margin-left: 1em; } + a :visited { color: inherit; } diff --git a/conf.json.sample b/conf.json.sample new file mode 100644 index 0000000..7ca5bec --- /dev/null +++ b/conf.json.sample @@ -0,0 +1,4 @@ +{ + "area_limit": 22500, + "room_limit": 16 +} diff --git a/src/main.rs b/src/main.rs index 9c9e5b1..d8c5122 100644 --- a/src/main.rs +++ b/src/main.rs @@ -15,8 +15,7 @@ use types::*; use tokio::sync::RwLock; const FONT_FILE: &[u8] = include_bytes!("../assets/VT323-Regular.ttf"); -const AREA_LIMIT: usize = 150*150; -const ROOM_LIMIT: usize = 8; +const CONF_FILE: &str = "./conf.json"; fn main() -> Result<(), Box<dyn Error>> { let conf = Config { @@ -34,6 +33,13 @@ fn main() -> Result<(), Box<dyn Error>> { #[tokio::main] async fn tokio_main(conf: Config) -> Result<(), Box<dyn Error>> { + let conf_file: serde_json::Value = serde_json::from_str(&tokio::fs::read_to_string(CONF_FILE).await?)?; + let area_limit: usize = conf_file.get("area_limit") + .expect("no area_limit field in the conf.json file") + .as_u64().expect("area_limit not a number") as usize; + let room_limit: usize = conf_file.get("room_limit") + .expect("no room_limit field in the conf.json file") + .as_u64().expect("room_limit not a number") as usize; let rooms: RoomMap = Arc::new(RwLock::new(HashMap::new())); let public_rooms = Arc::new(RwLock::new(HashMap::new())); use warp::*; @@ -75,7 +81,7 @@ async fn tokio_main(conf: Config) -> Result<(), Box<dyn Error>> { let r = rooms.clone(); async move { let empty_len = empty_rooms(r.clone()).await.len(); - let space = ROOM_LIMIT - r.read().await.len() + empty_len; + let space = room_limit - r.read().await.len() + empty_len; Ok::<_,std::convert::Infallible>( hyper::Response::builder() .status(hyper::StatusCode::OK) @@ -94,6 +100,16 @@ async fn tokio_main(conf: Config) -> Result<(), Box<dyn Error>> { let rooms = rooms.clone(); let pubs = pubs.clone(); async move { + let slots_available = room_limit - rooms.read().await.len(); + let empty = empty_rooms(rooms.clone()).await; + if slots_available < 1 { + if slots_available + empty.len() > 0 { + remove_room(rooms.clone(), pubs.clone(), empty[0].clone()).await; + } else { + return Err(reject::custom(NoRoomSlots)); + } + } + if let (Some(w),Some(h),Some(num),Some(denom),access,asfm,limit) = ( rinfo.get("rwidth").and_then(|wt| wt.parse::<NonZeroUsize>().ok()), rinfo.get("rheight").and_then(|ht| ht.parse::<NonZeroUsize>().ok()), @@ -103,14 +119,14 @@ async fn tokio_main(conf: Config) -> Result<(), Box<dyn Error>> { rinfo.get("ralwayssafe1move"), rinfo.get("rlimit").and_then(|l| l.parse::<usize>().ok()), ) { - if w.get()*h.get() > AREA_LIMIT { + if w.get()*h.get() > area_limit { return Err(reject::custom(BoardTooBig)) } let board_conf = minesweeper::BoardConf { w, h, mine_ratio: (num,denom), always_safe_first_move: asfm.is_some() }; let mut rooms = rooms.write().await; let uid = types::RoomId::new_in(&rooms); let name = { - let n = rinfo.get("rname").map(|r| r.to_owned()).unwrap(); + let n = rinfo.get("rname").unwrap().to_owned(); if n.is_empty() { uid.to_string() } else { n } }; let players = PlayerMap::default(); @@ -261,12 +277,18 @@ impl Reject for BadFormData {} struct BoardTooBig; impl Reject for BoardTooBig {} +#[derive(Debug)] +struct NoRoomSlots; +impl Reject for NoRoomSlots {} + async fn error_handler(err: Rejection) -> Result<impl Reply, std::convert::Infallible> { if err.is_not_found() { Ok(reply::with_status("No such file", StatusCode::NOT_FOUND)) } else if let Some(_e) = err.find::<BadFormData>() { Ok(reply::with_status("Bad form data", StatusCode::BAD_REQUEST)) } else if let Some(_e) = err.find::<BoardTooBig>() { Ok(reply::with_status("Board too big", StatusCode::BAD_REQUEST)) + } else if let Some(_e) = err.find::<NoRoomSlots>() { + Ok(reply::with_status("No more rooms slots", StatusCode::BAD_REQUEST)) } else { println!("unhandled rejection: {err:?}"); Ok(reply::with_status("Server error", StatusCode::INTERNAL_SERVER_ERROR)) @@ -284,3 +306,14 @@ async fn empty_rooms(rooms: RoomMap) -> Vec<RoomId> { .collect::<Vec<RoomId>>().await } +async fn remove_room<T>(rooms: RoomMap, pubs: Arc<RwLock<HashMap<RoomId,T>>>, id: RoomId) { + { + let mut rwl = rooms.write().await; + rwl.remove(&id); + } + { + let mut pwl = pubs.write().await; + pwl.remove(&id); + } +} + |