bubbles 4.1.0

Bubble integration server for powder diffraction
use crate::dispatcher::Session2DispatcherRequest;
use crate::integrator::{Packed, ResultID, Results};
use crate::session::SessionID;
use crate::{IType, Params};
use actix::{Actor, Handler, Message, SyncContext};
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 {
    params: Arc<Params>,
    last: Box<Results>,
    total: isize,
    done: usize,
    sent: HashMap<SessionID, ResultID>,
}

impl ResultsActor {
    pub fn new(params: Arc<Params>) -> ResultsActor {
        ResultsActor {
            params,
            last: Box::new(Results::empty()),
            total: 0,
            done: 0,
            sent: Default::default(),
        }
    }
}

impl Actor for ResultsActor {
    type Context = SyncContext<Self>;
}

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 {
        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;
    }
}