Skip to content

Commit

Permalink
EDITOR-NTUEELightDance#451 finish request handler for api/getDancerLE…
Browse files Browse the repository at this point in the history
…DData
  • Loading branch information
durant42040 committed Jan 14, 2024
1 parent ea21e95 commit b1e5050
Show file tree
Hide file tree
Showing 4 changed files with 162 additions and 1 deletion.
6 changes: 6 additions & 0 deletions controller-server/websocket/RPi/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ export function sendToRPi(dancers: string[], msg: ToRPi) {

export async function sendBoardInfoToRPi(dancer: string) {
// send pinMap, LED and OF to RPi
/*
TODO: the structure of LEDresult is changed from
{status: Record<string, [number, number, number, number]>, start: number, fade: boolean}[]
to Record<string, [number, number, number, number]>[]
since start and fade is no longer used.
*/
const [LEDresult, OFresult] = await Promise.allSettled([
getDancerLEDDataAPI(dancer),
getDancerFiberDataAPI(dancer),
Expand Down
1 change: 0 additions & 1 deletion editor-server/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ model LEDEffect {
id Int @id @default(autoincrement())
name String
part_name String
repeat Int
// relation => not in db
editing EditingLEDEffect?
Expand Down
152 changes: 152 additions & 0 deletions editor-server/src/routes/api/get_dancer_led_data.rs
Original file line number Diff line number Diff line change
@@ -1 +1,153 @@
use crate::global;
use axum::{
extract::Query,
headers::{HeaderMap, HeaderValue},
http::StatusCode,
response::Json,
};
use http::header::CONTENT_TYPE;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

pub type GetDataResponse = HashMap<String, Vec<Vec<i32>>>;

#[derive(Debug, Deserialize, Serialize)]
pub struct GetDataFailedResponse {
err: String,
}

#[derive(Debug)]
struct Part {
length: Option<i32>,
effect_id: Option<i32>,
}

#[derive(Debug)]
struct Color {
r: i32,
g: i32,
b: i32,
}

pub async fn get_dancer_led_data(
Query(query): Query<HashMap<String, String>>,
) -> Result<
(StatusCode, (HeaderMap, Json<GetDataResponse>)),
(StatusCode, Json<GetDataFailedResponse>),
> {
let dancer = match query.get("dancer") {
Some(dancer) => dancer,
None => {
return Err((
StatusCode::BAD_REQUEST,
Json(GetDataFailedResponse {
err: "Dancer name is required.".to_string(),
}),
))
}
};

let clients = global::clients::get();
let mysql_pool = clients.mysql_pool();

let colors = sqlx::query!(
r#"
SELECT Color.r, Color.g, Color.b, Color.id
FROM Color
"#,
)
.fetch_all(mysql_pool)
.await
.unwrap();

let mut color_map: HashMap<i32, Color> = HashMap::new();
for color in colors.iter() {
color_map.insert(
color.id,
Color {
r: color.r,
g: color.g,
b: color.b,
},
);
}

let dancer_data = sqlx::query!(
r#"
SELECT Part.name, Part.length, ControlData.effect_id
FROM Dancer
INNER JOIN Part ON Dancer.id = Part.dancer_id
INNER JOIN ControlData ON Part.id = ControlData.part_id
WHERE Dancer.name = ? AND Part.type = 'LED'
"#,
dancer
)
.fetch_all(mysql_pool)
.await
.unwrap();

if dancer_data.is_empty() {
return Err((
StatusCode::BAD_REQUEST,
Json(GetDataFailedResponse {
err: "Dancer not found.".to_string(),
}),
));
}

let mut parts: HashMap<String, Vec<Part>> = HashMap::new();

for data in dancer_data.iter() {
parts
.entry(data.name.clone())
.or_insert_with(Vec::new)
.push(Part {
effect_id: data.effect_id,
length: data.length,
});
}

let mut response: GetDataResponse = HashMap::new();

for (part_name, control_data) in parts.iter() {
let mut part_data = vec![vec![0, 0, 0, 0]; control_data[0].length.unwrap() as usize];

for data in control_data.iter() {
if data.effect_id.unwrap() == -1 {
continue;
}

let led_effect_states = sqlx::query!(
r#"
SELECT LEDEffectState.color_id, LEDEffectState.alpha, LEDEffectState.position
FROM LEDEffect
INNER JOIN LEDEffectState ON LEDEffect.id = LEDEffectState.effect_id
WHERE part_name = ? AND LEDEffect.id = ?
"#,
part_name,
data.effect_id.unwrap()
)
.fetch_all(mysql_pool)
.await
.unwrap();

for state in led_effect_states.iter() {
if state.color_id == 0 {
part_data[state.position as usize] = vec![0, 0, 0, state.alpha];
} else {
let color = color_map.get(&state.color_id).unwrap();

part_data[state.position as usize] =
vec![color.r, color.g, color.b, state.alpha];
}
}
}

response.insert(part_name.clone(), part_data);
}

let mut headers = HeaderMap::new();
headers.insert(CONTENT_TYPE, HeaderValue::from_static("application/json"));

Ok((StatusCode::OK, (HeaderMap::new(), Json(response))))
}
4 changes: 4 additions & 0 deletions editor-server/src/routes/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,8 @@ pub fn build_api_routes() -> Router {
.route("/login", post(login::login))
.route("/logout", post(logout::logout))
.route("/createUser", post(create_user::create_user))
.route(
"/getDancerLEDData",
get(get_dancer_led_data::get_dancer_led_data),
)
}

0 comments on commit b1e5050

Please sign in to comment.