use crate::dispatcher::Session2DispatcherRequest;
use crate::integrator::{Packed, ResultID, Results};
use crate::session::SessionID;
use crate::{dispatcher::IType, Params, Shutdown};
use actix::{Actor, ActorContext, Handler, Message, Running, SyncContext, System};
use serde;
use std::collections::HashMap;
use std::path::PathBuf;
use std::sync::Arc;
#[derive(serde::Serialize)]
pub struct ClientResponse {
running: bool,
path: String,
#[serde(rename = "imageFile")]
last_frame: Option<PathBuf>,
#[serde(rename = "chiFile")]
last_dat: Option<PathBuf>,
pattern: String,
#[serde(rename = "patternSize")]
pattern_size: usize,
timestamp: f64,
frame: String,
#[serde(rename = "frameSize")]
frame_size: usize,
#[serde(rename = "all")]
total: isize,
#[serde(rename = "total")]
done: usize,
transmission: f64,
}
#[derive(Message)]
#[rtype(result = "()")]
pub struct SessionResponse {
pub saxs: Option<ClientResponse>,
pub waxs: Option<ClientResponse>,
pub errors: Vec<String>,
pub warnings: Vec<String>,
}
pub struct ResultsActor {
itype: IType,
params: Arc<Params>,
last: Box<Results>,
total: isize,
done: usize,
sent: HashMap<SessionID, ResultID>,
}
impl ResultsActor {
pub fn new(params: Arc<Params>, itype: IType) -> ResultsActor {
ResultsActor {
itype,
params,
last: Box::new(Results::empty()),
total: 0,
done: 0,
sent: Default::default(),
}
}
}
impl Actor for ResultsActor {
type Context = SyncContext<Self>;
fn started(&mut self, _: &mut Self::Context) {
debug!("{} Results Actor has started", self.itype);
}
fn stopping(&mut self, _: &mut Self::Context) -> Running {
debug!("{} Results Actor is stopping", self.itype);
Running::Stop
}
fn stopped(&mut self, _: &mut Self::Context) {
debug!("{} Results actor has stopped", self.itype);
System::current().stop();
}
}
impl Handler<Shutdown> for ResultsActor {
type Result = ();
fn handle(&mut self, _: Shutdown, ctx: &mut Self::Context) -> Self::Result {
ctx.stop();
}
}
impl Handler<Box<Results>> for ResultsActor {
type Result = ();
fn handle(&mut self, msg: Box<Results>, _: &mut Self::Context) -> Self::Result {
self.done += 1;
self.last = msg
}
}
struct SubResponse {
pattern: String,
pattern_size: usize,
frame: String,
frame_size: usize,
last_frame: Option<PathBuf>,
last_dat: Option<PathBuf>,
timestamp: f64,
transmission: f64,
}
impl Handler<Session2DispatcherRequest> for ResultsActor {
type Result = ();
fn handle(&mut self, msg: Session2DispatcherRequest, _: &mut Self::Context) -> Self::Result {
if !msg.state_requested {
return;
}
let speed = { msg.state.integration.read().speed() };
let sr = {
let packed = {
let sent = self.sent.entry(msg.id).or_insert(Default::default());
if sent != &self.last.id {
self.sent.insert(msg.id, self.last.id);
self.last.pack(self.params.resize, speed)
} else {
Packed::new()
}
};
SubResponse {
pattern: packed.pattern,
pattern_size: packed.pattern_size,
frame: packed.frame,
frame_size: packed.frame_size,
last_frame: Some(self.last.path.as_ref().clone()),
last_dat: Some(self.last.name.clone()),
timestamp: self.last.timestamp,
transmission: self.last.transmission,
}
};
let (saxs, waxs) = {
let i = msg.state.integration.read();
let resp = ClientResponse {
running: i.is_running(),
path: i.path().to_owned(),
last_frame: sr.last_frame,
last_dat: sr.last_dat,
pattern: sr.pattern,
pattern_size: sr.pattern_size,
timestamp: sr.timestamp,
frame: sr.frame,
frame_size: sr.frame_size,
total: self.total,
done: self.done,
transmission: sr.transmission,
};
match i.itype() {
IType::SAXS => (Some(resp), None),
IType::WAXS => (None, Some(resp)),
}
};
msg.session.do_send(SessionResponse {
saxs,
waxs,
errors: msg.state.errors,
warnings: msg.state.warnings,
})
}
}
#[derive(Message)]
#[rtype(result = "()")]
pub struct TaskToDo(pub isize);
impl Handler<TaskToDo> for ResultsActor {
type Result = ();
fn handle(&mut self, msg: TaskToDo, _: &mut Self::Context) -> Self::Result {
self.total += msg.0;
}
}
#[derive(Message)]
#[rtype(result = "()")]
pub struct RestartIntegration;
impl Handler<RestartIntegration> for ResultsActor {
type Result = ();
fn handle(&mut self, _: RestartIntegration, _: &mut Self::Context) -> Self::Result {
self.total = 0;
self.done = 0;
}
}