1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
use std::{fmt::Display, str::FromStr};
use crate::ParseError;
#[derive(Debug)]
pub struct Event {
pub kind: EventKind,
pub params: Vec<String>,
pub text: Option<String>,
}
#[derive(Debug)]
pub enum EventKind {
/// Generic event.
Message,
/// Bookmarks are highlighted in the time line and in the event log. They are easy to spot and
/// handy to highlight parts of the flight, like a bombing run, or when the trainee was in her
/// final approach for landing.
Bookmark,
/// Debug events are highlighted and easy to spot in the timeline and event log. Because they
/// must be used for development purposes, they are displayed only when launching Tacview with
/// the command line argument /Debug:on
Debug,
/// This event is useful to specify when an aircraft (or any object) is cleanly removed from the
/// battlefield (not destroyed). This prevents Tacview from generating a Destroyed event by
/// error.
LeftArea,
/// When an object has been officially destroyed.
Destroyed,
/// Because Tacview may not always properly auto-detect take-off events, it can be useful to
/// manually inject this event in the flight recording.
TakenOff,
/// Because Tacview may not always properly auto-detect landing events, it can be useful to
/// manually inject this event in the flight recording.
Landed,
/// Mainly used for real-life training debriefing to specify when a weapon (typically a
/// missile) reaches or misses its target. Tacview will report in the shot log as well as in the
/// 3D view the result of the shot. Most parameters are optional. SourceId designates the object
/// which has fired the weapon, while TargetId designates the target. Even if the displayed
/// result may be in nautical miles, bullseye coordinates must be specified in meters. The
/// target must be explicitly (manually) destroyed or disabled using the appropriate properties
/// independently from this event.
Timeout,
/// Unknown event. This only exists for forward compatibility and using it is not recommended
/// as the event you are using could be move to the known event in a future release.
Unknown(String),
}
impl FromStr for Event {
type Err = ParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut parts = s.split('|');
let kind = parts.next().ok_or(ParseError::InvalidEvent)?;
let kind = match kind {
"Message" => EventKind::Message,
"Bookmark" => EventKind::Bookmark,
"Debug" => EventKind::Debug,
"LeftArea" => EventKind::LeftArea,
"Destroyed" => EventKind::Destroyed,
"TakenOff" => EventKind::TakenOff,
"Landed" => EventKind::Landed,
"Timeout" => EventKind::Timeout,
name => EventKind::Unknown(name.to_string()),
};
let mut params = parts.map(String::from).collect::<Vec<_>>();
let text = if params.is_empty() {
None
} else {
Some(params.remove(params.len() - 1)).filter(|s| !s.is_empty())
};
Ok(Event { kind, params, text })
}
}
impl Display for Event {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "0,Event={}", self.kind.as_str())?;
for param in &self.params {
write!(f, "|{}", param)?;
}
if let Some(text) = &self.text {
write!(f, "|{}", text)?;
}
Ok(())
}
}
impl EventKind {
fn as_str(&self) -> &str {
use EventKind::*;
match self {
Message => "Message",
Bookmark => "Bookmark",
Debug => "Debug",
LeftArea => "LeftArea",
Destroyed => "Destroyed",
TakenOff => "TakenOff",
Landed => "Landed",
Timeout => "Timeout",
Unknown(name) => name,
}
}
}