//! Minimal web GUI for entering a cube state and solving it. use anyhow::Result; use axum::{ extract::Json, response::Html, routing::{get, post}, Router, }; use serde::{Deserialize, Serialize}; use std::net::SocketAddr; const HTML: &str = r#" Rubik's Cube Solver

Rubik's Cube Solver

How to enter: Drag to rotate the cube. Click any sticker to cycle its color (U R F D L B). Start from a solved cube and set colors to match your cube, holding U on top and F in front as you rotate. Click Solve.

State:

Paste state:

"#; #[derive(Deserialize)] struct SolveReq { state: String, } #[derive(Serialize)] struct SolveRes { solution: String, } #[derive(Serialize)] struct ErrRes { error: String, } pub async fn run(port: u16) -> Result<()> { let app = Router::new() .route("/", get(|| async { Html(HTML) })) .route("/solve", post(solve_handler)); let addr = SocketAddr::from(([127, 0, 0, 1], port)); println!("GUI running at http://{}", addr); let listener = tokio::net::TcpListener::bind(addr).await?; axum::serve(listener, app).await?; Ok(()) } async fn solve_handler(Json(req): Json) -> Result, Json> { let state = req.state; let sol = tokio::task::spawn_blocking(move || { crate::solver::solve_facelet(&state, 20, 5.0) }) .await .map_err(|e| Json(ErrRes { error: e.to_string() }))? .map_err(|e| Json(ErrRes { error: e.to_string() }))?; Ok(Json(SolveRes { solution: crate::notation::format_moves(&sol), })) }