Skip to content

Commit

Permalink
finish plot
Browse files Browse the repository at this point in the history
  • Loading branch information
jacob-pro committed Jan 18, 2024
1 parent 3a92e66 commit c1a9d46
Show file tree
Hide file tree
Showing 7 changed files with 133 additions and 21 deletions.
51 changes: 49 additions & 2 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ human-repr = "1.1.0"
image = "0.24.7"
itertools = "0.11.0"
log = "0.4.14"
num = "0.4.1"
png = "0.17.10"
pollster = "0.3.0"
serde = { version = "1.0.110", features = ["derive"] }
Expand Down
Binary file modified screenshots/brightness.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified screenshots/status.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 3 additions & 2 deletions src/event_watcher/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ impl EventWatcher {
DispatchMessageA(&message);
}
}
log::debug!("EventWatcher thread exiting");
log::info!("EventWatcher thread exiting");
});

let hwnd = rx.recv().unwrap();
Expand All @@ -99,7 +99,7 @@ impl EventWatcher {
impl Drop for EventWatcher {
fn drop(&mut self) {
log::info!("Stopping EventWatcher");
unsafe { SendMessageW(self.hwnd, EXIT_LOOP, None, None) };
unsafe { check_error(|| SendMessageW(self.hwnd, EXIT_LOOP, None, None)).unwrap() };
self.thread.take().unwrap().join().unwrap();
}
}
Expand All @@ -126,6 +126,7 @@ unsafe extern "system" fn wndproc(
.unwrap();
}
EXIT_LOOP => {
log::info!("Received EXIT_LOOP message");
PostQuitMessage(0);
}
WM_WTSSESSION_CHANGE => match wparam.0 as u32 {
Expand Down
95 changes: 79 additions & 16 deletions src/gui/brightness_settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ use crate::calculator::calculate_brightness;
use crate::config::{Location, SsbConfig};
use crate::controller::Message;
use crate::gui::app::{save_config, AppState, Page, SPACING};
use egui::plot::{uniform_grid_spacer, Line, PlotBounds};
use chrono::{Duration, DurationRound, TimeZone};
use egui::plot::{uniform_grid_spacer, GridInput, GridMark, Line, PlotBounds};
use egui::widgets::plot::Plot;
use std::mem::take;
use std::time::{Instant, SystemTime, UNIX_EPOCH};
Expand Down Expand Up @@ -112,6 +113,8 @@ impl Page for BrightnessSettingsPage {
}
}

const LINE_NAME: &str = "Brightness";

impl BrightnessSettingsPage {
fn render_plot(&mut self, ui: &mut egui::Ui, app_state: &mut AppState) {
let config = app_state.config.read().unwrap();
Expand All @@ -135,12 +138,30 @@ impl BrightnessSettingsPage {
}

if let Some(plot) = &self.plot {
ui.separator();
ui.add_space(SPACING);

let first = plot.points.first().unwrap()[0];
let last = plot.points.last().unwrap()[0];
let line = Line::new(plot.points.clone());
let line = Line::new(plot.points.clone())
.name(LINE_NAME)
.highlight(true);

Plot::new("brightness_curve")
.allow_drag(false)
.allow_zoom(false)
.allow_scroll(false)
.y_grid_spacer(uniform_grid_spacer(|_| [100.0, 20.0, 10.0]))
.y_axis_formatter(|val, _| format!("{}%", val))
.x_grid_spacer(x_grid_spacer)
.label_formatter(|name, point| {
if name == LINE_NAME {
format!("{}\nBrightness {}%", convert_time(point.x), point.y)
} else {
String::new()
}
})
.x_axis_formatter(|val, _| convert_time(val))
.show(ui, |plot_ui| {
plot_ui.set_plot_bounds(PlotBounds::from_min_max([first, -5.0], [last, 105.0]));
plot_ui.line(line)
Expand All @@ -149,6 +170,36 @@ impl BrightnessSettingsPage {
}
}

fn convert_time(time: f64) -> String {
let time = chrono::Local.timestamp_opt(time as i64, 0).unwrap();
time.format("%I:%M %P").to_string()
}

const HOURS: i64 = 6;

// spaces the x-axis hourly
fn x_grid_spacer(input: GridInput) -> Vec<GridMark> {
let min_unix = input.bounds.0 as i64;
let max_unix = input.bounds.1 as i64;
let min_local = chrono::Local.timestamp_opt(min_unix, 0).unwrap();
let lowest_whole_hour = min_local.duration_trunc(Duration::hours(HOURS)).unwrap();

let mut output = Vec::new();
let hours_unix = HOURS * 3600;

let mut rounded_unix = lowest_whole_hour.timestamp();
while rounded_unix < max_unix {
if rounded_unix >= min_unix {
output.push(GridMark {
value: rounded_unix as f64,
step_size: hours_unix as f64,
});
}
rounded_unix += hours_unix;
}
output
}

fn generate_plot_data(
location: Location,
brightness_day: u32,
Expand All @@ -159,41 +210,53 @@ fn generate_plot_data(
let timer_start = Instant::now();

let now = SystemTime::now();
let mut graph_start = (now - chrono::Duration::hours(2).to_std().unwrap())
let graph_start = (now - Duration::hours(2).to_std().unwrap())
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs() as i64;
let graph_end = (now + chrono::Duration::hours(22).to_std().unwrap())
let graph_end = (now + Duration::hours(22).to_std().unwrap())
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs() as i64;

let mut points = Vec::new();
let mut current = graph_start;

while graph_start <= graph_end {
let sun = SunriseSunsetParameters::new(graph_start, location.latitude, location.longitude)
while current <= graph_end {
let sun = SunriseSunsetParameters::new(current, location.latitude, location.longitude)
.calculate()
.unwrap();
let brightness = calculate_brightness(
brightness_day,
brightness_night,
transition_mins,
&sun,
graph_start,
current,
);
points.push([graph_start as f64, brightness.brightness as f64]);
if graph_start == graph_end {
break;
}
let expiry = brightness.expiry_time.unwrap_or(graph_end);
if expiry > graph_end {
graph_start = graph_end;
let next_time = brightness.expiry_time.unwrap_or(graph_end).min(graph_end);

// Add some extra points in the "flat" zone to allow cursor to snap to the line
// This is a bit of a hack, assuming if expiry is greater than 30 minutes,
// to be completely accurate we would need to look ahead at the next calculation.
if brightness.expiry_time.unwrap_or(i64::MAX) - current > 1800 {
for second in num::range_step(current, next_time, 240) {
points.push([second as f64, brightness.brightness as f64]);
}
} else {
graph_start = expiry;
points.push([current as f64, brightness.brightness as f64]);
}

if current == graph_end {
break;
}
current = next_time;
}

log::debug!("Plot took {:?}", timer_start.elapsed());
log::debug!(
"Plot took {:?} {} points",
timer_start.elapsed(),
points.len()
);

PlotData {
points,
Expand Down
2 changes: 1 addition & 1 deletion src/gui/status.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ impl Page for StatusPage {
}

fn display_apply_results(results: &ApplyResults, ui: &mut egui::Ui) {
let date_format = "%H:%M %P (%b %d)";
let date_format = "%I:%M %P (%b %d)";
let sunrise = Local
.timestamp_opt(results.sun.rise, 0)
.unwrap()
Expand Down

0 comments on commit c1a9d46

Please sign in to comment.