lights/src/animations.rs

394 lines
12 KiB
Rust
Raw Normal View History

2023-03-13 20:59:50 +00:00
use std::{u8, error::Error};
use rocket::{serde::{json::{Json, serde_json::json}, Deserialize, Serialize}, State};
use crate::{utils::ApiResponse, DBConn, ASender, Action};
use crate::DBPool;
#[derive(Debug, Deserialize, Serialize, Clone)]
#[serde(crate = "rocket::serde")]
#[serde(rename_all = "camelCase")]
pub struct LigthSetting {
start: Option<u32>,
end: Option<u32>,
tags: Option<String>,
r: u8,
b: u8,
g: u8,
}
impl LigthSetting {
pub fn get_start(&self) -> Option<u32>{
self.start
}
pub fn get_end(&self) -> Option<u32>{
self.end
}
pub fn get_tags(&self) -> Option<String>{
if self.tags.as_ref().is_some() {
return Some(self.tags.as_ref().unwrap().to_string());
}
None
}
pub fn get_r(&self) -> u8 {
self.r
}
pub fn get_b(&self) -> u8 {
self.b
}
pub fn get_g(&self) -> u8 {
self.g
}
}
#[derive(Debug, Deserialize, Serialize, Clone)]
#[serde(crate = "rocket::serde")]
#[serde(rename_all = "camelCase")]
pub struct KeyFrame {
duration: u32,
settings: Vec<LigthSetting>
}
impl KeyFrame {
pub fn get_settings(&self) -> Vec<LigthSetting> {
self.settings.clone()
}
pub fn get_duration(&self) -> u32 {
self.duration
}
}
#[derive(Debug, Deserialize, Serialize, Clone)]
#[serde(crate = "rocket::serde")]
#[serde(rename_all = "camelCase")]
pub struct Animation {
key_frames: Vec<KeyFrame>,
priority: Option<u32>,
name: String,
repeat: bool,
}
impl Animation {
pub fn get_frames(&self) -> Vec<KeyFrame> {
self.key_frames.clone()
}
pub fn get_name(&self) -> String {
self.name.to_string()
}
pub fn get_priority(&self) -> u32 {
if self.priority.is_none() { 0 } else {self.priority.unwrap()}
}
pub fn get_repeat(&self) -> bool {
self.repeat
}
}
#[post("/animation", data= "<data>")]
pub async fn animation(data: Json<Animation>, db: &State<DBPool>) -> String {
if data.key_frames.is_empty() {
return json!(ApiResponse {code: 400, message: "KeyFrame are nessesary".to_string()}).to_string();
}
if data.name.is_empty() {
return json!(ApiResponse {code: 400, message: "Name must not be empty".to_string()}).to_string();
}
for key_frame in data.key_frames.iter() {
if key_frame.settings.is_empty() {
return json!(ApiResponse {code: 400, message: "keyFrames.settings can not be empty".to_string()}).to_string();
}
if key_frame.duration == 0 {
return json!(ApiResponse {code: 400, message: "keyFrames.duration can not be 0".to_string()}).to_string();
}
for setting in key_frame.settings.iter() {
if setting.tags.is_none() && (setting.start.is_none() || setting.end.is_none()) {
return json!(ApiResponse {code: 400, message: "Either tags or start end pair is needed".to_string()}).to_string();
}
if !(setting.start.is_none() && setting.end.is_none()) && (setting.start.is_none() || setting.end.is_none()) {
return json!(ApiResponse {code: 400, message: "Both start and end need to be filled".to_string()}).to_string();
}
}
}
let db_status = add_animation_to_db(data, db);
if db_status.is_err() || db_status.as_ref().ok().is_none() {
return json!(ApiResponse {code: 500, message: format!("Error setting the animation. Err: {:?}", db_status.err()).to_string()}).to_string();
}
let db_status = db_status.ok().unwrap();
if !db_status.is_empty() {
return db_status;
}
json!(ApiResponse {code: 200, message: "Configuration was successful".to_string()}).to_string()
}
fn get_animation_from_name(conn: &DBConn, name: String) -> Result<Option<u32>, Box<dyn Error>> {
let mut stmt = conn.prepare("SELECT id FROM animation WHERE name=?1")?;
let next = stmt.query_map([name], |row| {
row.get(0)
})?.next();
if next.is_none() {
return Ok(None);
}
Ok(next.unwrap()?)
}
fn get_keyframe_from_index(conn: &DBConn, animation: u32, index: u32) -> Result<Option<u32>, Box<dyn Error>> {
let mut stmt = conn.prepare("SELECT id FROM keyframe WHERE animation=?1 AND i=?2")?;
let next = stmt.query_map([animation, index], |row| {
row.get(0)
})?.next();
if next.is_none() {
return Ok(None);
}
Ok(next.unwrap()?)
}
fn add_animation_to_db(data: Json<Animation>, pool: &State<DBPool>) -> Result<String, Box<dyn Error>>{
let priority = if data.priority.is_some() { data.priority.unwrap() } else { 0 };
let conn = pool.get()?;
println!("g: {}", data.name);
let name = get_animation_from_name(&conn, data.name.to_string())?;
println!("t: {:?}", name);
if name.is_some() {
return Ok(json!(ApiResponse {code: 500, message: "Animation with that name is already exists.".to_string()}).to_string());
}
conn.execute("INSERT INTO animation (priority, name, repeat) VALUES (?1, ?2, ?3);", (priority, data.name.to_string(), data.repeat ))?;
let name = get_animation_from_name(&conn, data.name.to_string())?;
if name.is_none() {
return Ok(json!(ApiResponse {code: 500, message: "Failed to create animation.".to_string()}).to_string());
}
let animation_id = name.unwrap();
let mut i = 0;
for key_frame in data.key_frames.clone() {
conn.execute("INSERT INTO keyframe (duration, animation, i) VALUES (?1, ?2, ?3);", (key_frame.duration, animation_id, i))?;
let keyframe = get_keyframe_from_index(&conn, animation_id, i)?;
if keyframe.is_none() {
return Ok(json!(ApiResponse {code: 500, message: "Failed to create animation.".to_string()}).to_string());
}
let keyframe = keyframe.unwrap();
for setting in key_frame.settings {
conn.execute("INSERT INTO lightsetting (start, end, tags, r, b, g, keyframe) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7);", (setting.start, setting.end, setting.tags, setting.r, setting.b, setting.g, keyframe))?;
}
i += 1;
}
Ok("".to_string())
}
/**
*
* Stop animations
*
*/
#[get("/stop/<name>")]
pub async fn stop_animation(name: &str, stop_sender: &State<ASender<String>>) -> String {
let r = stop_sender.lock().unwrap().send(name.to_string());
if r.is_err() || r.ok().is_none() {
return json!(ApiResponse {code: 500, message: "Something went wrong".to_string()}).to_string()
}
json!(ApiResponse {code: 200, message: "Configuration was successful".to_string()}).to_string()
}
/**
*
* Start animations
*
*/
#[get("/start/<name>")]
pub async fn start_animation(name: &str, start_sender: &State<ASender<Animation>>, db: &State<DBPool>) -> String {
let animation = get_animation(name, db);
if animation.is_err() || animation.as_ref().ok().is_none() {
return json!(ApiResponse {code: 500, message: format!("Probelms with the db: {:?}", animation.err()).to_string()}).to_string()
}
let animation = animation.ok().unwrap();
if animation.is_none() {
return json!(ApiResponse {code: 404, message: "Animation not found".to_string()}).to_string()
}
let animation = animation.unwrap();
let r = start_sender.lock().unwrap().send(animation);
if r.is_err() || r.as_ref().ok().is_none() {
return json!(ApiResponse {code: 500, message: "Probelms with the db".to_string()}).to_string()
}
json!(ApiResponse {code: 200, message: "Started animation".to_string()}).to_string()
}
/**
*
* Clear animations
*
*/
#[get("/clear/<name>")]
pub async fn clear(name: &str, start_sender: &State<ASender<Animation>>, db: &State<DBPool>, action: &State<ASender<Action>>) -> String {
let r = action.lock().unwrap().send(Action::Clear);
if r.is_err() || r.ok().is_none() {
return json!(ApiResponse {code: 500, message: "Something went wrong".to_string()}).to_string()
}
let animation = get_animation(name, db);
if animation.is_err() || animation.as_ref().ok().is_none() {
return json!(ApiResponse {code: 500, message: format!("Probelms with the db: {:?}", animation.err()).to_string()}).to_string()
}
let animation = animation.ok().unwrap();
if animation.is_none() {
return json!(ApiResponse {code: 404, message: "Animation not found".to_string()}).to_string()
}
let animation = animation.unwrap();
let r = start_sender.lock().unwrap().send(animation);
if r.is_err() || r.as_ref().ok().is_none() {
return json!(ApiResponse {code: 500, message: "Probelms with the db".to_string()}).to_string()
}
json!(ApiResponse {code: 200, message: "Started animation".to_string()}).to_string()
}
pub fn get_animation(name: &str, db: &State<DBPool>) -> Result<Option<Animation>, Box<dyn Error>> {
let conn = db.get()?;
let mut stmt = conn.prepare("SELECT id, priority, name, repeat FROM animation WHERE name=?1;")?;
struct AnimationId {
animation: Animation,
id: u8
Lerppppppp Squashed commit of the following: commit 11c776c2a9059cd073d376632c829e0c6156b085 Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 23:23:08 2023 +0000 update to have diff abs commit 92fb1478b73f0b226798b54fc0d4a58095cd6bf5 Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 23:21:40 2023 +0000 speed up commit 5418a139f29e7dbd4077bd502d5481b8592101e7 Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 23:20:09 2023 +0000 fix diff commit f96fc9b48d235f100aa1afc1015441bf95d689c5 Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 23:18:34 2023 +0000 update check commit 788b705c87893af901c0cacbc333635837394d6f Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 23:16:50 2023 +0000 update check commit 29efa6be830e711485bae44b905b151facc57ea6 Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 23:14:41 2023 +0000 change values to u128 commit 100f782aeaf281a27c2dd419552b3966ca29f549 Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 23:10:03 2023 +0000 addjust for diff values commit f31bc45947fff40125d259bd53282399509715dd Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 23:07:51 2023 +0000 account for 0 diff commit b31c967ca04fc41e876bb7cf3b545246866b4b1d Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 23:05:17 2023 +0000 update lerp functionn commit 81930f35ebeb2567218b429a58ce5b560a0a175b Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 23:03:51 2023 +0000 update lerp functionn commit cb9eb57a2c525827a1ef2f58199d0063e208059e Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 23:00:06 2023 +0000 update diff target commit 0bce36f41debff1046359e503c5120f5035ef45f Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 22:58:46 2023 +0000 update diff target commit be35ecb310bfd6b0d58d3c43de6b33ff9784898f Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 22:57:28 2023 +0000 fix render commit 0a721463629132b97080ba39ad2add5340f0cfcc Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 22:55:56 2023 +0000 update render commit 16ea28557e1c1ce76cfa6fe1236adac1c956c982 Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 22:52:45 2023 +0000 update delta diff commit 540af201742cbac04ea85fa8b7843d405dc58dd9 Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 22:51:15 2023 +0000 update delta diff commit 0fdba152d6402438cb893c115266e5d8b995a59b Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 22:49:41 2023 +0000 changed to render to f64 commit c49d3380b49e13d6be5c832679077b98b66c9ac7 Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 22:35:16 2023 +0000 added delta commit af2b8e55aedc6aea0d1fb4951f44d3c1b4502373 Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 22:28:55 2023 +0000 init last if empty commit 02f261a85a2112ed1f47ceae97d7ebb631b41275 Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 22:23:05 2023 +0000 added more logs to test commit b6d0cca501c21245738d80746ef81bbb5228d479 Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 22:21:53 2023 +0000 added more logs to test commit 81b4de369006513a1c95436a0735e80c9ccc19ec Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 22:19:48 2023 +0000 added more logs to test commit 8c4c736555ad653f02b4aee2ef527b2a478c2d13 Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 22:16:14 2023 +0000 added more logs commit d82df637e03d9e86849357b75f39ee88f23dfe5e Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 22:14:02 2023 +0000 added logs commit fbfbd232a9ed5b830706e5d24d0c8e89bc8ec4db Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 22:02:56 2023 +0000 finished lerp commit 8e615a31d161e09ff4f18af19f17dd9989feb84e Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Tue Mar 14 23:25:15 2023 +0000 started working
2023-03-15 23:27:37 +00:00
}
2023-03-13 20:59:50 +00:00
let next = stmt.query_map([name], |row| {
Ok(AnimationId {
animation: Animation {
key_frames: Vec::new(),
priority: Some(row.get(1)?),
name: row.get(2)?,
repeat: row.get(3)?
},
id: row.get(0)?
})
})?.next();
if next.is_none() {
return Ok(None);
}
let mut animation = next.unwrap()?;
struct KeyFrameId {
keyframe: KeyFrame,
id: u8,
}
let mut stmt = conn.prepare("SELECT id, duration from keyframe where animation=?1 order by i asc")?;
let mut map = stmt.query_map([animation.id], |row| {
Ok(KeyFrameId {
id: row.get(0)?,
keyframe: KeyFrame {
duration: row.get(1)?,
settings: Vec::new()
}
})
})?;
while let Some(key_frame_id) = map.next() {
let mut key_frame_id = key_frame_id?;
let mut stmt = conn.prepare("SELECT start, end, tags, r, b, g from lightsetting where keyframe=?1")?;
let mut light_setting_map = stmt.query_map([key_frame_id.id], |row| {
Ok(LigthSetting {
start: row.get(0)?,
end: row.get(1)?,
tags: row.get(2)?,
r: row.get(3)?,
b: row.get(4)?,
g: row.get(5)?
})
})?;
while let Some(light_setting) = light_setting_map.next() {
key_frame_id.keyframe.settings.push(light_setting?);
}
animation.animation.key_frames.push(key_frame_id.keyframe);
}
Ok(Some(animation.animation))
}
/**
*
* Delete animations
*
*/
#[get("/delete/<name>")]
Lerppppppp Squashed commit of the following: commit 11c776c2a9059cd073d376632c829e0c6156b085 Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 23:23:08 2023 +0000 update to have diff abs commit 92fb1478b73f0b226798b54fc0d4a58095cd6bf5 Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 23:21:40 2023 +0000 speed up commit 5418a139f29e7dbd4077bd502d5481b8592101e7 Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 23:20:09 2023 +0000 fix diff commit f96fc9b48d235f100aa1afc1015441bf95d689c5 Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 23:18:34 2023 +0000 update check commit 788b705c87893af901c0cacbc333635837394d6f Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 23:16:50 2023 +0000 update check commit 29efa6be830e711485bae44b905b151facc57ea6 Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 23:14:41 2023 +0000 change values to u128 commit 100f782aeaf281a27c2dd419552b3966ca29f549 Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 23:10:03 2023 +0000 addjust for diff values commit f31bc45947fff40125d259bd53282399509715dd Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 23:07:51 2023 +0000 account for 0 diff commit b31c967ca04fc41e876bb7cf3b545246866b4b1d Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 23:05:17 2023 +0000 update lerp functionn commit 81930f35ebeb2567218b429a58ce5b560a0a175b Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 23:03:51 2023 +0000 update lerp functionn commit cb9eb57a2c525827a1ef2f58199d0063e208059e Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 23:00:06 2023 +0000 update diff target commit 0bce36f41debff1046359e503c5120f5035ef45f Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 22:58:46 2023 +0000 update diff target commit be35ecb310bfd6b0d58d3c43de6b33ff9784898f Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 22:57:28 2023 +0000 fix render commit 0a721463629132b97080ba39ad2add5340f0cfcc Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 22:55:56 2023 +0000 update render commit 16ea28557e1c1ce76cfa6fe1236adac1c956c982 Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 22:52:45 2023 +0000 update delta diff commit 540af201742cbac04ea85fa8b7843d405dc58dd9 Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 22:51:15 2023 +0000 update delta diff commit 0fdba152d6402438cb893c115266e5d8b995a59b Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 22:49:41 2023 +0000 changed to render to f64 commit c49d3380b49e13d6be5c832679077b98b66c9ac7 Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 22:35:16 2023 +0000 added delta commit af2b8e55aedc6aea0d1fb4951f44d3c1b4502373 Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 22:28:55 2023 +0000 init last if empty commit 02f261a85a2112ed1f47ceae97d7ebb631b41275 Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 22:23:05 2023 +0000 added more logs to test commit b6d0cca501c21245738d80746ef81bbb5228d479 Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 22:21:53 2023 +0000 added more logs to test commit 81b4de369006513a1c95436a0735e80c9ccc19ec Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 22:19:48 2023 +0000 added more logs to test commit 8c4c736555ad653f02b4aee2ef527b2a478c2d13 Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 22:16:14 2023 +0000 added more logs commit d82df637e03d9e86849357b75f39ee88f23dfe5e Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 22:14:02 2023 +0000 added logs commit fbfbd232a9ed5b830706e5d24d0c8e89bc8ec4db Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Wed Mar 15 22:02:56 2023 +0000 finished lerp commit 8e615a31d161e09ff4f18af19f17dd9989feb84e Author: Andre Henriques <andr3h3nriqu3s@gmail.com> Date: Tue Mar 14 23:25:15 2023 +0000 started working
2023-03-15 23:27:37 +00:00
pub async fn delete(name: &str, db: &State<DBPool>) -> String {
2023-03-13 20:59:50 +00:00
let animation = remove_animation(name, db);
if animation.is_err() || animation.as_ref().ok().is_none() {
return json!(ApiResponse {code: 500, message: format!("Probelms with the db: {:?}", animation.err()).to_string()}).to_string()
}
json!(ApiResponse {code: 200, message: "Deleted animation".to_string()}).to_string()
}
pub fn remove_animation(name: &str, db: &State<DBPool>) -> Result<(), Box<dyn Error>> {
let conn = db.get()?;
conn.execute("delete from lightsetting where id in (select l.id from lightsetting as l left join keyframe as k on l.keyframe = k.id left join animation as a on k.animation = a.id where a.name=?1);", [name])?;
conn.execute("delete from keyframe where id in (select k.id from keyframe as k left join animation as a on k.animation = a.id where a.name=?1);", [name])?;
conn.execute("delete from animation where name=?1;", [name])?;
Ok(())
}