début plotting, pour l'instant ça marche pas

This commit is contained in:
jfelderh
2024-10-28 15:43:30 +01:00
parent 33de1a4778
commit fe470cf1c1
5 changed files with 92 additions and 9 deletions

16
Cargo.lock generated
View File

@@ -60,6 +60,12 @@ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "either"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
[[package]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.2.10" version = "0.2.10"
@@ -71,6 +77,15 @@ dependencies = [
"wasi", "wasi",
] ]
[[package]]
name = "itertools"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
dependencies = [
"either",
]
[[package]] [[package]]
name = "itoa" name = "itoa"
version = "1.0.9" version = "1.0.9"
@@ -149,6 +164,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"argh", "argh",
"csv", "csv",
"itertools",
"rand", "rand",
"rand_chacha", "rand_chacha",
"serde", "serde",

View File

@@ -8,6 +8,7 @@ edition = "2021"
[dependencies] [dependencies]
argh = "0.1.12" argh = "0.1.12"
csv = "1.2.2" csv = "1.2.2"
itertools = "0.13.0"
rand = "0.8.5" rand = "0.8.5"
rand_chacha = "0.3.1" rand_chacha = "0.3.1"
serde = "1.0.188" serde = "1.0.188"

View File

@@ -1,20 +1,66 @@
use super::repartition::*; use std::fs;
use std::process::Command;
const FORMAT_TEXT: &'static str = "<html> use super::repartition::*;
use itertools::Itertools;
impl Repartition {
pub fn to_json(&self) -> String {
let participants = self
.0
.iter()
.flat_map(|t| vec![t.from.clone(), t.to.clone()])
.dedup()
.collect_vec();
let mut str_nodes = String::new();
for p in participants {
str_nodes += &format!(
"{{
\"data\": {{
\"id\":\"{}\",
\"label\":\"{}\"
}},
}},",
p.name, p.name
);
}
let mut str_edges = String::new();
for t in &self.0 {
str_edges += &format!(
"{{
\"data\": {{
\"id\":\"{}-{}\",
\"label\":\"{}\",
\"source\":\"{}\",
\"target\":\"{}\",
}}
}},",
t.from.name,
t.to.name,
t.amount as f32 / 100.,
t.from.name,
t.to.name,
)
}
"[".to_owned() + &str_nodes + "," + &str_edges + "]"
}
}
const FORMAT_STRING: &'static str = "<html>
<head> <head>
<script src=\"/home/jfelderh/Prog/Repartition Alpes/cytoscape.min.js\"></script> <script src=\"/home/jfelderh/Prog/Repartition Alpes/cytoscape.min.js\"></script>
</head> </head>
<body> <body>
<div id=\"graph\" style=\"width: auto;height: 500px;\"></div> <div id=\"graph\" style=\"width: auto;height: 500px;\"></div>
<h3>Balance totale (doit être égal à zéro) : {}€</h3> <h3>Balance totale (doit être égal à zéro) : TOTAL_BALANCE €</h3>
<script type=\"text/javascript\"> <script type=\"text/javascript\">
var cy = cytoscape({ var cy = cytoscape({
container: document.getElementById('graph'), // container to render in container: document.getElementById('graph'), // container to render in
elements:{}, elements:ELEMENTS,
style: [ // the stylesheet for the graph style: [ // the stylesheet for the graph
{ {
@@ -48,3 +94,15 @@ style: [ // the stylesheet for the graph
</body> </body>
"; ";
use super::repartition::*;
pub fn plot_repartition(rep: &Repartition) {
let text_html = FORMAT_STRING
.to_string()
.replace("TOTAL_BALANCE", &rep.total_balance().to_string())
.replace("ELEMENTS", &rep.to_json());
fs::write("/tmp/repartition.html", text_html).expect("Could not write into /tmp/");
Command::new("firefox")
.arg("/tmp/repartition.html")
.output()
.expect("Could not run firefox");
}

View File

@@ -37,12 +37,16 @@ fn main() {
let repartition_file = fs::File::open(filename).expect("not able to read file"); let repartition_file = fs::File::open(filename).expect("not able to read file");
let mut csv_reader = csv::ReaderBuilder::new() let mut csv_reader = csv::ReaderBuilder::new()
.has_headers(false) .has_headers(false)
.delimiter(b';') .delimiter(b',')
.from_reader(repartition_file); .from_reader(repartition_file);
let user_list = csv_reader let user_list = csv_reader
.records() .records()
.map(Result::unwrap) .map(Result::unwrap)
.map(|r| {
dbg!(&r);
r
})
.map(|record| User { .map(|record| User {
name: record[0].parse::<String>().unwrap().trim_end().to_string(), name: record[0].parse::<String>().unwrap().trim_end().to_string(),
balance_cents: (record[1].parse::<f64>().unwrap() * 100.) as i32, balance_cents: (record[1].parse::<f64>().unwrap() * 100.) as i32,
@@ -67,9 +71,11 @@ fn main() {
serde_json::to_string_pretty(&best_repartition).unwrap() serde_json::to_string_pretty(&best_repartition).unwrap()
); );
} else if let Some(filename) = args.transfert_list_filename { } else if let Some(filename) = args.transfert_list_filename {
dbg!(&filename);
let repart: Repartition = let repart: Repartition =
serde_json::from_reader(fs::File::open(filename).expect("not able to read file")) serde_json::from_reader(fs::File::open(filename).expect("not able to read file"))
.expect("unable to read file"); .expect("unable to read file");
io::plot_repartition(&repart);
} else { } else {
println!("No parameter given, exiting"); println!("No parameter given, exiting");
} }

View File

@@ -1,10 +1,10 @@
use std::cmp::min; use std::{cmp::min, collections::HashSet};
use rand::prelude::*; use rand::prelude::*;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Deserialize, Serialize)] #[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
pub struct User { pub struct User {
pub name: String, pub name: String,
pub email: String, pub email: String,
@@ -85,11 +85,13 @@ pub struct Transfer {
} }
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize)]
pub struct Repartition(Vec<Transfer>); pub struct Repartition(pub Vec<Transfer>);
type Evaluation = (usize); type Evaluation = (usize);
impl Repartition { impl Repartition {
pub fn total_balance(&self) -> i32 {
self.0.iter().map(|t| t.amount as i32).sum()
}
pub fn evaluate(&self) -> Evaluation { pub fn evaluate(&self) -> Evaluation {
self.0.len() self.0.len()
} }