use std::rc::Rc;
use sim_kernel::{Expr, Result, Symbol};
use sim_lib_stream_device::ModeledDeviceCapsSource;
use sim_lib_view_device::{
DeviceProfile, DeviceProfileParts, EncodedScene, LocalAdapter, RateClass,
};
use sim_value::build;
pub fn reference_rich_profile_symbol() -> Symbol {
Symbol::qualified("device/reference", "rich-profile")
}
pub fn reference_glance_profile_symbol() -> Symbol {
Symbol::qualified("device/reference", "glance-profile")
}
pub fn reference_rich_profile() -> DeviceProfile {
DeviceProfile::new(DeviceProfileParts {
kind: Symbol::qualified("device", "reference-device"),
display: symbols(&["stereo", "hud"]),
input: symbols(&["tap"]),
output: symbols(&["hud", "haptic"]),
links: symbols(&["local"]),
streams: symbols(&["pose"]),
rate: RateClass::stereo(),
policy: build::map(vec![
("consent", build::sym("required")),
("retention-ms", build::uint(100)),
]),
})
}
pub fn reference_glance_profile() -> DeviceProfile {
DeviceProfile::new(DeviceProfileParts {
kind: Symbol::qualified("device", "reference-glance"),
display: symbols(&["round"]),
input: symbols(&["tap"]),
output: symbols(&["haptic"]),
links: symbols(&["local"]),
streams: Vec::new(),
rate: RateClass::watch(),
policy: build::map(vec![
("consent", build::sym("visible")),
("retention-ms", build::uint(50)),
]),
})
}
pub fn reference_caps_source() -> ModeledDeviceCapsSource {
ModeledDeviceCapsSource::new(
Symbol::qualified("device", "reference-device"),
vec![Symbol::qualified("device/stream", "pose")],
vec![Symbol::qualified("device/input", "tap")],
vec![
Symbol::qualified("device/output", "hud"),
Symbol::qualified("device/output", "haptic"),
],
)
.with_seq_base(10)
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ReferencePose {
pub seq: u64,
pub yaw_mdeg: i32,
}
impl ReferencePose {
pub fn new(seq: u64, yaw_mdeg: i32) -> Self {
Self { seq, yaw_mdeg }
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct ReferenceRichAdapter;
impl LocalAdapter for ReferenceRichAdapter {
type State = ReferencePose;
fn adapt(
&self,
scene: &EncodedScene,
state: &Self::State,
profile: &DeviceProfile,
) -> Result<Rc<Expr>> {
Ok(Rc::new(build::map(vec![
("kind", build::qsym("device/reference", "rich-frame")),
("tier", Expr::Symbol(profile.tier.to_symbol())),
("pose-seq", build::uint(state.seq)),
("yaw-mdeg", build::int(i64::from(state.yaw_mdeg))),
("scene", scene.expr().clone()),
])))
}
}
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct ReferenceSceneEncoder {
calls: u64,
}
impl ReferenceSceneEncoder {
pub fn new() -> Self {
Self::default()
}
pub fn encode(&mut self) -> EncodedScene {
self.calls = self.calls.saturating_add(1);
EncodedScene::new(reference_scene())
}
pub fn calls(&self) -> u64 {
self.calls
}
}
pub fn reference_scene() -> Expr {
build::map(vec![
("kind", build::qsym("scene", "glance")),
("title", build::text("Reference pose")),
(
"metric",
build::map(vec![
("label", build::text("yaw")),
("value", build::text("12 deg")),
]),
),
(
"action",
build::map(vec![
("label", build::text("Acknowledge")),
("target", build::sym("tap")),
]),
),
("urgency", build::sym("info")),
("cells", build::uint(4)),
("bypass-budget", Expr::Bool(false)),
])
}
fn symbols(names: &[&str]) -> Vec<Symbol> {
names.iter().map(|name| Symbol::new(*name)).collect()
}