Skip to content

Commit

Permalink
Graph support, no UI Graph, just the the logic (#93)
Browse files Browse the repository at this point in the history
* init

* multi win

* finish window multi

* cargo update
  • Loading branch information
wiiznokes authored Apr 7, 2024
1 parent ac5f85f commit 57d75b9
Show file tree
Hide file tree
Showing 19 changed files with 536 additions and 35 deletions.
2 changes: 1 addition & 1 deletion .config/settings.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
theme = "Light"
update_delay = 1500
current_config = "fake"
current_config = "test"
20 changes: 19 additions & 1 deletion .config/test.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,22 @@
Control = []
Fan = []
Temp = []
Flat = []
Linear = []
Target = []

[[CustomTemp]]
name = "CPU"
kind = "Average"
inputs = []
inputs = []

[[Graph]]
name = "Graph"

[[Graph.coord]]
temp = 50
percent = 30

[[Graph.coord]]
temp = 50
percent = 30
2 changes: 1 addition & 1 deletion DEV.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
[[Graph]]
name = "Graph"
input = "max"
cood = [
coord = [
{ temp = 50, percent = 30 },
{ temp = 50, percent = 30 },
{ temp = 50, percent = 30 },
Expand Down
5 changes: 5 additions & 0 deletions data/src/app_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,11 @@ impl AppGraph {
app_graph.insert_node(node);
}

for graph in config.graphs {
let node = graph.to_node(&mut app_graph.id_generator, &app_graph.nodes, hardware);
app_graph.insert_node(node);
}

for control in config.controls {
let node = control.to_node(&mut app_graph.id_generator, &app_graph.nodes, hardware);
app_graph.insert_node(node);
Expand Down
228 changes: 222 additions & 6 deletions data/src/config/graph.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,239 @@
use serde::{Deserialize, Serialize};
use std::vec;

use crate::node::IsValid;
use hardware::{Hardware, Value};
use serde::{Deserialize, Deserializer, Serialize};

#[derive(Serialize, Deserialize, Debug, Clone)]
use crate::{
app_graph::Nodes,
config::graph::affine::Affine,
id::IdGenerator,
node::{IsValid, Node, NodeType, ToNode},
update::UpdateError,
};

#[derive(Serialize, Deserialize, Debug, Clone, Eq)]
pub struct Coord {
pub temp: u8,
pub percent: u8,
}

#[derive(Serialize, Deserialize, Debug, Clone, Default)]
impl TryFrom<(&str, &str)> for Coord {
type Error = Box<dyn std::error::Error>;

fn try_from((temp, percent): (&str, &str)) -> Result<Self, Self::Error> {
let temp = temp.parse::<u8>()?;

let percent = percent.parse::<u8>()?;

if percent > 100 {
return Err("Percent > 100".into());
}

Ok(Coord { temp, percent })
}
}

impl PartialEq for Coord {
fn eq(&self, other: &Self) -> bool {
self.temp == other.temp
}
}

impl PartialOrd for Coord {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}

impl Ord for Coord {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.temp.cmp(&other.temp)
}
}

impl Coord {
pub fn exact_same(&self, other: &Self) -> bool {
self.percent == other.percent && self.temp == other.temp
}
}

// todo: better default + UI
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Graph {
pub name: String,
#[serde(rename = "coord")]
pub coords: Vec<Coord>,
pub coords: Coords,
pub input: Option<String>, // Temp or CustomTemp
}

impl Default for Graph {
fn default() -> Self {
Self {
name: Default::default(),
coords: Coords(vec![
Coord {
temp: 10,
percent: 10,
},
Coord {
temp: 70,
percent: 100,
},
]),
input: Default::default(),
}
}
}

impl ToNode for Graph {
fn to_node(self, id_generator: &mut IdGenerator, nodes: &Nodes, _hardware: &Hardware) -> Node {
Node::new(id_generator, NodeType::Graph(self), nodes)
}
}

impl IsValid for Graph {
fn is_valid(&self) -> bool {
self.input.is_some() //TODO: add conditions on coords
#[derive(PartialEq)]
enum DupState {
Init,
Prev { temp: u8 },
DuplicateFound,
}

self.input.is_some()
&& !self.coords.0.is_empty()
&& self
.coords
.0
.iter()
.fold(DupState::Init, |prev, coord| match prev {
DupState::Init => DupState::Prev { temp: coord.temp },
DupState::Prev { temp } => {
if temp == coord.temp {
DupState::DuplicateFound
} else {
DupState::Prev { temp: coord.temp }
}
}
DupState::DuplicateFound => DupState::DuplicateFound,
})
!= DupState::DuplicateFound
&& !self.coords.0.iter().any(|coord| coord.percent > 100)
}
}

#[derive(Serialize, Debug, Clone, Default)]
pub struct Coords(pub Vec<Coord>);

impl<'de> serde::Deserialize<'de> for Coords {
fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
let mut s: Vec<Coord> = Vec::deserialize(d)?;

s.sort();

Ok(Coords(s))
}
}

impl Graph {
pub fn get_value(&self, value: Value) -> Result<Value, UpdateError> {
let dummy_coord = Coord {
temp: value as u8,
percent: 0,
};

let res = match self.coords.0.binary_search(&dummy_coord) {
Ok(index) => self.coords.0[index].percent as Value,
Err(index) => {
if index == 0 {
self.coords.0[index].percent as Value
} else if index == self.coords.0.len() {
self.coords.0[index - 1].percent as Value
} else {
let coord1 = &self.coords.0[index - 1];
let coord2 = &self.coords.0[index];

Affine {
xa: coord1.temp.into(),
ya: coord1.percent.into(),
xb: coord2.temp.into(),
yb: coord2.percent.into(),
}
.calcule(value) as Value
}
}
};

Ok(res)
}
}

// todo: use it in linear
mod affine {
use hardware::Value;

#[derive(Debug)]
pub struct Affine {
pub xa: f32,
pub ya: f32,
pub xb: f32,
pub yb: f32,
}

impl Affine {
pub fn calcule(&self, value: Value) -> f32 {
let a = (self.yb - self.ya) / (self.xb - self.xa);
let b = self.ya - a * self.xa;

a * value as f32 + b
}
}
}

#[test]
fn test() {
let coord1 = Coord {
temp: 10,
percent: 10,
};

let coord2 = Coord {
temp: 20,
percent: 20,
};

let coord3 = Coord {
temp: 30,
percent: 30,
};

let coord4 = Coord {
temp: 40,
percent: 40,
};

let coords = Coords(vec![coord1, coord2, coord3, coord4]);

let dummy_coord = Coord {
temp: 50,
percent: 0,
};

let res = coords.0.binary_search(&dummy_coord);

match res {
Ok(index) => {
println!("use {}", index);
}
Err(index) => {
if index == 0 {
println!("use {}", index);
} else if index == coords.0.len() {
println!("use {}", index - 1);
} else {
println!("use {} and {}", index - 1, index);
}
}
}
dbg!(&res);
}
6 changes: 3 additions & 3 deletions data/src/config/serde_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use super::custom_temp::{CustomTemp, CustomTempKind};

use super::fan::Fan;
use super::flat::Flat;
use super::graph::{Coord, Graph};
use super::graph::{Coord, Coords, Graph};
use super::linear::Linear;
use super::target::Target;
use super::temp::Temp;
Expand Down Expand Up @@ -154,7 +154,7 @@ fn config1() -> Config {
)],
graphs: vec![Graph {
name: "Graph".into(),
coords: vec![
coords: Coords(vec![
Coord {
temp: 10,
percent: 10,
Expand All @@ -163,7 +163,7 @@ fn config1() -> Config {
temp: 50,
percent: 30,
},
],
]),
input: Some("max".into()),
}],
flats: vec![Flat {
Expand Down
11 changes: 2 additions & 9 deletions data/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -371,16 +371,9 @@ impl NodeType {
NodeType::Temp(_) => Ordering::Greater,
_ => Ordering::Less,
},
NodeType::Graph(_) => todo!(),
NodeType::Flat(_) => Ordering::Equal,
NodeType::Linear(..) => match other {
NodeType::Control(_) => Ordering::Less,
NodeType::Fan(_) => Ordering::Greater,
NodeType::Temp(_) => Ordering::Greater,
NodeType::CustomTemp(_) => Ordering::Greater,
_ => Ordering::Equal,
},
NodeType::Target(..) => match other {

NodeType::Graph(_) | NodeType::Linear(..) | NodeType::Target(..) => match other {
NodeType::Control(_) => Ordering::Less,
NodeType::Fan(_) => Ordering::Greater,
NodeType::Temp(_) => Ordering::Greater,
Expand Down
2 changes: 1 addition & 1 deletion data/src/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ impl Node {
crate::node::NodeType::Fan(fan) => fan.get_value(bridge),
crate::node::NodeType::Temp(temp) => temp.get_value(bridge),
crate::node::NodeType::CustomTemp(custom_temp) => custom_temp.get_value(input_values),
crate::node::NodeType::Graph(_) => todo!(),
crate::node::NodeType::Graph(graph) => graph.get_value(input_values[0]),
crate::node::NodeType::Flat(flat) => Ok(flat.value.into()),
crate::node::NodeType::Linear(linear, ..) => linear.get_value(input_values[0]),
crate::node::NodeType::Target(target, ..) => target.get_value(input_values[0]),
Expand Down
26 changes: 26 additions & 0 deletions data/src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::cmp::Ordering;

pub trait RemoveElem<T> {
fn remove_elem<F>(&mut self, predicate: F) -> Option<T>
where
Expand All @@ -22,3 +24,27 @@ pub fn init_test_logging() {
.is_test(true)
.try_init();
}

pub trait InsertSorted<T> {
fn insert_sorted<F>(&mut self, predicate: F, element: T) -> Option<T>
where
F: Fn(&T) -> Ordering;
}

impl<T> InsertSorted<T> for Vec<T> {
fn insert_sorted<F>(&mut self, predicate: F, element: T) -> Option<T>
where
F: Fn(&T) -> Ordering,
{
match self.binary_search_by(predicate) {
Ok(index) => {
let removed = std::mem::replace(&mut self[index], element);
Some(removed)
}
Err(index) => {
self.insert(index, element);
None
}
}
}
}
Loading

0 comments on commit 57d75b9

Please sign in to comment.