Skip to content

Commit

Permalink
fix exportData format
Browse files Browse the repository at this point in the history
  • Loading branch information
tom1484 committed Feb 4, 2024
1 parent 77c8427 commit f067b96
Show file tree
Hide file tree
Showing 5 changed files with 312 additions and 374 deletions.
245 changes: 139 additions & 106 deletions editor-server/src/routes/api/export_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,92 @@ use crate::db::types::{
position_frame::PositionFrameData,
};
use crate::global;
use crate::types::global::{
LEDEffectData, LEDEffectFrame, PositionPos, TColorData, TControlData, TDancerData, TExportData,
TExportLEDFrame, TExportLEDFrameLED, TExportLEDPart, TPartControl, TPartData, TPartType,
TPositionData, LED,
};
use crate::types::global::PositionPos;
use crate::utils::data::{get_redis_control, get_redis_position};
use crate::utils::vector::partition_by_field;
use async_graphql::Enum;
use axum::{http::StatusCode, response::Json};
use http::header::CONTENT_TYPE;
use http::HeaderMap;
use itertools::Itertools;
use serde::{Deserialize, Serialize};
use sqlx::Type;
use std::collections::{HashMap, HashSet};

#[derive(Debug, Deserialize, Serialize)]
pub struct ExPositionData {
pub start: i32,
pub pos: Vec<PositionPos>,
}

#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct ExColorData(pub i32, pub i32, pub i32); // [r: number, g: number, b: number]

impl From<String> for ExPartType {
fn from(data: String) -> Self {
match data.as_str() {
"LED" => ExPartType::LED,
"FIBER" => ExPartType::FIBER,
_ => panic!("Invalid TPartType value: {}", data),
}
}
}

#[derive(Type, Enum, Clone, Copy, Eq, PartialEq, Serialize, Deserialize, Debug, Default)]
pub enum ExPartType {
#[default]
LED,
FIBER,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct ExPartData {
pub name: String,
pub r#type: ExPartType,
#[serde(skip_serializing_if = "Option::is_none")]
pub length: Option<i32>,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct ExDancerData {
pub parts: Vec<ExPartData>,
pub name: String,
}

#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct ExLEDFrameLED(pub String, pub i32);

#[derive(Debug, Deserialize, Serialize)]
pub struct TExportLEDFrame {
#[serde(rename = "LEDs")]
pub leds: Vec<ExLEDFrameLED>,
pub start: i32,
pub fade: bool,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct ExLEDPart {
pub repeat: i32,
pub frames: Vec<TExportLEDFrame>,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct ExControlData {
pub fade: bool,
pub start: i32,
pub status: Vec<Vec<ExPartControl>>,
}

#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct ExPartControl(pub String, pub i32); // TLEDControl: [src: string, alpha: number] or TFiberControl: [color: string, alpha: number]

#[derive(Debug, Deserialize, Serialize)]
pub struct ExportDataResponse {
pub data: TExportData,
pub dancer: Vec<ExDancerData>,
pub color: HashMap<String, ExColorData>,
pub position: HashMap<String, ExPositionData>,
pub control: HashMap<String, ExControlData>,
#[serde(rename = "LEDEffects")]
pub led_effects: HashMap<String, HashMap<String, ExLEDPart>>,
}

#[derive(Debug, Deserialize, Serialize)]
Expand Down Expand Up @@ -67,16 +136,16 @@ pub async fn export_data() -> Result<
.await
.into_result()?;

let mut color = HashMap::<String, TColorData>::new();
let mut color_dict = HashMap::<String, String>::new();
let mut color = HashMap::<String, ExColorData>::new();
let mut color_dict = HashMap::new();

// IColor
for color_obj in color_data {
color.insert(
color_obj.name.to_string(),
TColorData(color_obj.r, color_obj.g, color_obj.b),
ExColorData(color_obj.r, color_obj.g, color_obj.b),
);
color_dict.insert(color_obj.id.to_string(), color_obj.name.to_string());
color_dict.insert(color_obj.id, color_obj.name.to_string());
}

// grab dancer data include parts (INNER JOIN)
Expand All @@ -91,22 +160,21 @@ pub async fn export_data() -> Result<
FROM Dancer
INNER JOIN Part ON Part.dancer_id = Dancer.id
ORDER BY Dancer.id ASC, Part.id ASC;
"#,
"#,
)
.fetch_all(mysql_pool)
.await
.into_result()?;

let dancer_data = partition_by_field(|row| row.id, result);

let dancer: Vec<TDancerData> = dancer_data
let dancer: Vec<ExDancerData> = dancer_data
.into_iter()
.map(|dancer_obj| TDancerData {
.map(|dancer_obj| ExDancerData {
name: dancer_obj[0].name.clone(),
position_data: None,
parts: dancer_obj
.into_iter()
.map(|part| TPartData {
.map(|part| ExPartData {
name: part.part_name,
r#type: part.part_type.into(),
length: part.part_length,
Expand All @@ -119,9 +187,9 @@ pub async fn export_data() -> Result<
let led_parts = sqlx::query_as!(
PartData,
r#"
SELECT * FROM Part
WHERE type = "LED";
"#,
SELECT * FROM Part
WHERE type = "LED";
"#,
)
.fetch_all(mysql_pool)
.await
Expand All @@ -139,16 +207,16 @@ pub async fn export_data() -> Result<
})
.collect::<Vec<String>>();

let mut led_effects = HashMap::<String, HashMap<String, TExportLEDPart>>::new();
let mut led_dict = HashMap::<String, String>::new();
let mut led_effects = HashMap::new();
let mut led_dict = HashMap::new();

for part_name in led_parts_name {
let mut led_part = HashMap::<String, TExportLEDPart>::new();
let mut led_part = HashMap::<String, ExLEDPart>::new();
// LEDEffectState
let result = {
let result = sqlx::query!(
r#"
SELECT
SELECT
LEDEffect.id,
LEDEffect.name,
LEDEffect.part_name,
Expand All @@ -157,97 +225,70 @@ pub async fn export_data() -> Result<
LEDEffectState.position
FROM LEDEffect
INNER JOIN LEDEffectState ON LEDEffect.id = LEDEffectState.effect_id
WHERE part_name = ?;
"#,
WHERE part_name = ?
ORDER BY LEDEffect.id ASC, LEDEffectState.position ASC;
"#,
part_name
)
.fetch_all(mysql_pool)
.await
.into_result()?;
partition_by_field(|row| row.id, result)
};
let led_part_effects = result
.iter()
.map(|led_effect_states| {
let leds = led_effect_states
.iter()
.map(|effect| LED(effect.color_id, effect.alpha))
.collect::<Vec<LED>>();

LEDEffectData {
id: led_effect_states[0].id,
name: led_effect_states[0].name.clone(),
part_name: led_effect_states[0].part_name.clone(),
repeat: 0,
frames: vec![LEDEffectFrame {
leds,
fade: false,
start: 0,
}],
}
})
.collect_vec();
let _: () = led_part_effects
.iter()
.map(|led_part_effect| {
let led_frames: Vec<TExportLEDFrame> = led_part_effect
.frames
.clone()
result.iter().for_each(|led_effect_states| {
let led_frames = vec![TExportLEDFrame {
leds: led_effect_states
.iter()
.map(|led_frame| {
let leds: Vec<TExportLEDFrameLED> = led_frame
.leds
.clone()
.into_iter()
.map(|led| {
vec![TExportLEDFrameLED(
color_dict[&led.0.to_string()].clone(),
led.1,
)]
})
.flatten()
.collect();
let led_frame_data = TExportLEDFrame {
leds,
start: led_frame.start,
fade: led_frame.fade,
};
led_frame_data
.map(|led_effect_state| {
ExLEDFrameLED(
color_dict[&led_effect_state.color_id].clone(),
led_effect_state.alpha,
)
})
.collect();
led_part.insert(
led_part_effect.name.clone(),
TExportLEDPart {
repeat: led_part_effect.repeat,
frames: led_frames,
},
);
led_dict.insert(led_part_effect.id.to_string(), led_part_effect.name.clone());
})
.collect();
.collect(),
start: 0,
fade: false,
}];

led_part.insert(
led_effect_states[0].name.clone(),
ExLEDPart {
repeat: 0,
frames: led_frames,
},
);
led_dict.insert(led_effect_states[0].id, led_effect_states[0].name.clone());
});

led_effects.insert(part_name, led_part);
}

// grab control data from redis
let control_frames = sqlx::query_as!(
ControlFrameData,
r#"
SELECT id, start, fade as "fade: bool"
SELECT
id,
start,
fade as "fade: bool",
meta_rev,
data_rev
FROM ControlFrame;
"#,
"#,
)
.fetch_all(mysql_pool)
.await
.into_result()?;
let mut control = HashMap::<String, TControlData>::new();
let mut control = HashMap::<String, ExControlData>::new();
for control_frame in control_frames {
let redis_contol = get_redis_control(redis, control_frame.id)
.await
.into_result()?;
let fade = redis_contol.fade;
let start = redis_contol.start;
let status = redis_contol.status;
let new_status: Vec<Vec<TPartControl>> = status
let new_status: Vec<Vec<ExPartControl>> = status
.into_iter()
.enumerate()
.map(|(dancer_idx, dancer_statue)| {
Expand All @@ -256,28 +297,22 @@ pub async fn export_data() -> Result<
.enumerate()
.map(|(part_idx, part_status)| {
let part_type = dancer[dancer_idx].parts[part_idx].r#type;
if part_type == TPartType::FIBER {
if part_type == ExPartType::FIBER {
if part_status.0 == -1 {
return TPartControl(String::new(), part_status.1);
return ExPartControl(String::new(), part_status.1);
}
return TPartControl(
color_dict[&part_status.0.to_string()].clone(),
part_status.1,
);
ExPartControl(color_dict[&part_status.0].clone(), part_status.1)
} else {
if part_status.0 == -1 {
return TPartControl(String::new(), part_status.1);
return ExPartControl(String::new(), part_status.1);
}
return TPartControl(
color_dict[&part_status.0.to_string()].clone(),
part_status.1,
);
ExPartControl(led_dict[&part_status.0].clone(), part_status.1)
}
})
.collect::<Vec<TPartControl>>()
.collect::<Vec<ExPartControl>>()
})
.collect();
let new_cache_obj = TControlData {
let new_cache_obj = ExControlData {
fade,
start,
status: new_status,
Expand All @@ -296,15 +331,15 @@ pub async fn export_data() -> Result<
.await
.into_result()?;

let mut position = HashMap::<String, TPositionData>::new();
let mut position = HashMap::<String, ExPositionData>::new();

for position_frame in position_frames {
let redis_position = get_redis_position(redis, position_frame.id)
.await
.into_result()?;
position.insert(
position_frame.id.to_string(),
TPositionData {
ExPositionData {
start: position_frame.start,
pos: redis_position.pos,
},
Expand All @@ -328,18 +363,16 @@ pub async fn export_data() -> Result<
}
}

let data = TExportData {
let mut header = HeaderMap::new();
header.insert(CONTENT_TYPE, "application/json".parse().unwrap());

let export_data_response = ExportDataResponse {
position,
control,
dancer,
color,
led_effects,
};

let mut header = HeaderMap::new();
header.insert(CONTENT_TYPE, "application/json".parse().unwrap());

let export_data_response = ExportDataResponse { data };

Ok((StatusCode::OK, (header, Json(export_data_response))))
}
Loading

0 comments on commit f067b96

Please sign in to comment.