Skip to content

Commit

Permalink
feat: simplify inspector
Browse files Browse the repository at this point in the history
  • Loading branch information
ts0yu authored Aug 28, 2024
1 parent ef4e71d commit dbad3d9
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 189 deletions.
9 changes: 3 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

247 changes: 65 additions & 182 deletions src/engine/inspector.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
use std::collections::HashMap;
use plotly::{Plot, Scatter};

use std::fs::File;
use std::io::prelude::*;
use std::path::Path;
use std::fs::OpenOptions;
use std::{error::Error, io, process};
use serde::{Serialize, Deserialize};
use serde_json::{Value, json};

use serde::{Deserialize, Serialize};

/// Trait allowing custom behavior to be defined for logging and inspecting values.
pub trait Inspector<V> {
Expand All @@ -18,185 +11,109 @@ pub trait Inspector<V> {
fn inspect(&self, step: usize) -> Option<V>;

/// Save the inspector state.
fn save(&self, save_type: Option<SaveData>);
}

pub enum SaveData {
ToCsv(String),
ToNewCsv(String),
ToJson(String),
ToNewJson(String),
fn save(&self);
}

/// Type that allows for logging indexed values to files on disc.
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct LogMessage {
id: usize, // Id of the log
name: String, // Name of the log
data: String, // The data being stored inside the log
/// Index of the log message.
pub id: usize,

/// Key of the log message.
pub name: String,

/// Data of the log message.
pub data: String,
}

impl LogMessage {
/// Public constructor function for a new [`LogMessage`].
pub fn new(name: String, data: String) -> Self {
LogMessage {
id: 0,
name: name,
data: data,
}
}

pub fn update_counter(&mut self, counter: usize) {
self.id = counter;
Self { id: 0, name, data }
}
}

#[derive(Debug)]
/// Custom implementation of an [`Inspector`] for logging values to a file (CSV or JSON).
pub struct Logger {
pub values: Vec<LogMessage>, // Stores all the messages
pub counter: usize, // Used for keeping position of the id tag
values: Vec<LogMessage>,
counter: usize,
file_path: String,
format: LogFormat,
}

#[derive(Debug)]
/// Enum to specify the logging format.
enum LogFormat {
Csv,
Json,
}

impl Logger {
pub fn new() -> Self {
Logger {
/// Public constructor function for a new [`Logger`] for CSV format.
pub fn new_csv(file_path: String) -> Self {
Self {
values: Vec::new(),
counter: 0,
file_path,
format: LogFormat::Csv,
}
}

fn append_to_csv(record: LogMessage, path: &Path) -> Result<(), csv::Error> {
let file = OpenOptions::new()
.append(true)
.create(true)
.open(path)?;

let mut writer = csv::Writer::from_writer(file);

writer.serialize((
record.id,
record.name,
record.data
))?;
writer.flush()?;

Ok(())
}

fn create_csv(file_location: &String) -> Result<(), csv::Error> {
let file = OpenOptions::new()
.write(true)
.create(true)
.truncate(true)
.open(file_location)?;

let mut writer = csv::Writer::from_writer(file);
writer.write_record(&["id", "name", "data"])?;
writer.flush()?;

Ok(())
/// Public constructor function for a new [`Logger`] for JSON format.
pub fn new_json(file_path: String) -> Self {
Self {
values: Vec::new(),
counter: 0,
file_path,
format: LogFormat::Json,
}
}

fn create_json(file_location: &String) -> Result<(), Box<dyn std::error::Error>> {
let file = OpenOptions::new()
.write(true)
.create(true)
.truncate(true)
.open(file_location)?;

let empty_array = json!([]);
serde_json::to_writer(file, &empty_array)?;

Ok(())
}

fn append_to_json(record: LogMessage, path: &Path) -> Result<(), Box<dyn std::error::Error>> {
let mut records = Self::read_json_file(&path.to_string_lossy().to_string())?;

records.push(record);

/// Append a log message to the appropriate file format.
fn append_to_file(&self, record: &LogMessage) -> Result<(), Box<dyn std::error::Error>> {
let file = OpenOptions::new()
.write(true)
.truncate(true)
.open(path)?;

serde_json::to_writer(file, &records)?;

Ok(())
}

fn read_json_file(file_loc: &String) -> Result<Vec<LogMessage>, Box<dyn std::error::Error>> {
let file = File::open(file_loc)?;
let records: Vec<LogMessage> = serde_json::from_reader(file)?;
Ok(records)
}

/*
fn read_csv_file(file_loc: &String) -> Result<Vec<LogMessage>, csv::Error> {
let mut records: Vec<LogMessage> = vec![];
let file = OpenOptions::new()
.write(true)
.append(true)
.create(true)
.truncate(true)
.open(file_loc)?;
.open(&self.file_path)?;

let mut reader = csv::Reader::from_reader(file);
for record in reader.deserialize() {
// println!("Line");
let record: Record = record?;
records.push(record);
match self.format {
LogFormat::Csv => {
let mut writer = csv::Writer::from_writer(file);
writer.serialize((record.id, &record.name, &record.data))?;
writer.flush()?;
}
LogFormat::Json => {
let mut records: Vec<LogMessage> =
serde_json::from_reader(&file).unwrap_or_default();
records.push(record.clone());
serde_json::to_writer(file, &records)?;
}
}
Ok(records)
Ok(())
}
*/
}

impl Inspector<LogMessage> for Logger {
fn log(&mut self, mut value: LogMessage) {
value.update_counter(self.counter);
value.id = self.counter;
self.counter += 1;
self.values.push(value);
self.values.push(value.clone());

if let Err(e) = self.append_to_file(&value) {
eprintln!("Failed to append to file: {}", e);
}
}

fn inspect(&self, step: usize) -> Option<LogMessage> {
Some(self.values[step].clone())
self.values.get(step).cloned()
}

fn save(&self, save_type: Option<SaveData>) {
let mut file_loc = String::new();
match save_type.unwrap() {
SaveData::ToNewCsv(file_location) => {
Logger::create_csv(&file_location);
for log in self.values.clone() {
let file_path = Path::new(&file_location);
Logger::append_to_csv(log, &file_path);
}
},
SaveData::ToCsv(file_location) => {
for log in self.values.clone() {
let file_path = Path::new(&file_location);
Logger::append_to_csv(log, &file_path);
}
},

SaveData::ToNewJson(file_location) => {
Logger::create_json(&file_location);
for log in self.values.clone() {
let file_path = Path::new(&file_location);
Logger::append_to_json(log, &file_path);
}
},

SaveData::ToJson(file_location) => {
for log in self.values.clone() {
let file_path = Path::new(&file_location);
Logger::append_to_json(log, &file_path);
}
}
}
}
fn save(&self) {}
}

/// No-op implementation of an [`Inspector`] for custom usecases.
/// No-op implementation of an [`Inspector`] for custom use cases.
pub struct EmptyInspector;

impl Inspector<f64> for EmptyInspector {
Expand All @@ -206,37 +123,3 @@ impl Inspector<f64> for EmptyInspector {
fn log(&mut self, _value: f64) {}
fn save(&self) {}
}

// pub struct Plotter {
// values: Vec<f64>,
// }

// impl Plotter {
// pub fn new() -> Self {
// Plotter {
// values: Vec::new(),
// }
// }
// }

// impl Inspector<f64> for Plotter {
// fn log(&mut self, value: f64) {
// self.values.push(value);
// }

// fn inspect(&self, step: usize) -> Option<f64> {
// Some(self.values[step])
// }

// fn save(&self, save_type: Option<SaveData>) {
// let mut plot = Plot::new();

// let timesteps: Vec<usize> = (0..self.values.len()).collect();
// let values: Vec<f64> = timesteps.iter().map(|v| v).collect();

// let trace = Scatter::new(timesteps, values).mode(plotly::common::Mode::Markers);

// plot.add_trace(trace);
// plot.show();
// }
// }
1 change: 0 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ use alloy::{
};

use crate::{engine::inspector::Inspector, types::PoolManager::PoolKey};
use crate::engine::inspector::SaveData;

/// Provider type that includes all necessary fillers to execute transactions on an [`Anvil`] node.
pub type AnvilProvider = FillProvider<
Expand Down

0 comments on commit dbad3d9

Please sign in to comment.