use super::pdb::{alt_field, atom_name_field, insertion_code};
use molframe_core::structure::{AtomRef, ResidueRef, Structure};
use num_traits::ToPrimitive;
use std::fmt;
pub(super) struct Record<'a> {
pub atom: &'a AtomRef<'a>,
pub structure: &'a Structure,
pub residue: &'a ResidueRef<'a>,
pub name: &'a str,
pub component: &'a str,
pub chain: &'a str,
pub seq: &'a str,
pub serial: &'a str,
pub u: &'a [f32; 6],
}
impl Record<'_> {
pub(super) fn write(&self, out: &mut impl fmt::Write) {
let units = self.u.map(field);
let name = atom_name_field(self.name);
let _ = writeln!(
out,
"ANISOU{serial}{name:<4}{alt:1}{comp:>3} {chain:>1}{seq}{ins:1} \
{u0:>7}{u1:>7}{u2:>7}{u3:>7}{u4:>7}{u5:>7} {element:>2}",
serial = self.serial,
alt = alt_field(self.structure, self.atom),
comp = self.component,
chain = self.chain,
seq = self.seq,
ins = insertion_code(*self.residue),
element = match self.atom.element() {
Some(element) => element.symbol(),
None => "",
},
u0 = units[0],
u1 = units[1],
u2 = units[2],
u3 = units[3],
u4 = units[4],
u5 = units[5],
);
}
}
fn field(value: f32) -> i64 {
let rounded = (f64::from(value) * 10_000.0).round();
match rounded.to_i64() {
Some(field) => field,
None if rounded.is_sign_positive() => 99_999_999,
None => -99_999_999,
}
}