use native_db::{native_db, ToKey};
use native_model::{native_model, Model};
use serde::{Deserialize, Serialize};
pub use super::v1::{
Action, AncestorLocal, Device, DevicePrettyLocation, DeviceType, Heartbeat, Herd, Layer,
MediaType, Plan, PlanInsert, PlanType, ResponseScout, ResponseScoutStatus, Session,
SessionLocal, Syncable, TagObservationType, Zone,
};
pub use super::v2::{Operator, OperatorLocal};
pub use super::v6::{Connectivity, ConnectivityLocal, Tag};
pub use super::v8::TagLocal;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[native_model(id = 16, version = 5)]
#[native_db]
pub struct EventLocal {
pub id: Option<i64>,
#[primary_key]
pub id_local: Option<String>,
pub message: Option<String>,
pub media_url: Option<String>,
pub file_path: Option<String>,
pub location: Option<String>,
pub altitude: f64,
pub heading: f64,
pub media_type: super::v1::MediaType,
pub device_id: i64,
pub earthranger_url: Option<String>,
pub timestamp_observation: String,
pub is_public: bool,
#[secondary_key]
pub session_id: Option<i64>,
#[secondary_key]
pub ancestor_id_local: Option<String>,
pub tagged_at: Option<String>,
pub embedded_at: Option<String>,
pub segmented_at: Option<String>,
pub tracked_at: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Event {
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<i64>,
pub message: Option<String>,
pub media_url: Option<String>,
pub file_path: Option<String>,
pub location: Option<String>,
pub altitude: f64,
pub heading: f64,
pub media_type: super::v1::MediaType,
pub device_id: i64,
pub earthranger_url: Option<String>,
pub timestamp_observation: String,
pub is_public: bool,
pub session_id: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tagged_at: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub embedded_at: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub segmented_at: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tracked_at: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[native_model(id = 19, version = 7)]
#[native_db]
pub struct ArtifactLocal {
pub id: Option<i64>,
#[primary_key]
pub id_local: Option<String>,
#[secondary_key]
pub ancestor_id_local: Option<String>,
pub created_at: Option<String>,
pub file_path: String,
#[secondary_key]
pub session_id: Option<i64>,
pub timestamp_observation: Option<String>,
pub modality: Option<String>,
pub device_id: i64,
pub updated_at: Option<String>,
pub timestamp_observation_end: String,
pub has_uploaded_file_to_storage: bool,
pub upload_url: Option<String>,
pub upload_url_generated_at: Option<String>,
pub file_size_bytes: Option<i64>,
pub tagged_at: Option<String>,
pub embedded_at: Option<String>,
pub segmented_at: Option<String>,
pub tracked_at: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Artifact {
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub created_at: Option<String>,
pub file_path: String,
pub session_id: Option<i64>,
pub timestamp_observation: Option<String>,
pub modality: Option<String>,
pub device_id: i64,
pub updated_at: Option<String>,
pub timestamp_observation_end: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub file_size_bytes: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tagged_at: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub embedded_at: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub segmented_at: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tracked_at: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SegmentationSam3 {
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub created_at: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub event_id: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub artifact_id: Option<i64>,
#[serde(default)]
pub frame_index: i64,
pub mask_rle: serde_json::Value,
#[serde(skip_serializing_if = "Option::is_none")]
pub conf: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub origin_location: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub origin_pitch: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub origin_heading: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub origin_roll: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sensor_pitch: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sensor_yaw: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sensor_roll: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub origin_height: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub timestamp_observation: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub subject_location: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub subject_height: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub subject_id: Option<i64>,
}
impl Default for EventLocal {
fn default() -> Self {
Self {
id: None,
id_local: None,
message: None,
media_url: None,
file_path: None,
location: None,
altitude: 0.0,
heading: 0.0,
media_type: super::v1::MediaType::Image,
device_id: 0,
earthranger_url: None,
timestamp_observation: String::new(),
is_public: false,
session_id: None,
ancestor_id_local: None,
tagged_at: None,
embedded_at: None,
segmented_at: None,
tracked_at: None,
}
}
}
impl Default for Event {
fn default() -> Self {
Self {
id: None,
message: None,
media_url: None,
file_path: None,
location: None,
altitude: 0.0,
heading: 0.0,
media_type: super::v1::MediaType::Image,
device_id: 0,
earthranger_url: None,
timestamp_observation: String::new(),
is_public: false,
session_id: None,
tagged_at: None,
embedded_at: None,
segmented_at: None,
tracked_at: None,
}
}
}
impl super::v1::AncestorLocal for EventLocal {
fn ancestor_id_local(&self) -> Option<String> {
self.ancestor_id_local.clone()
}
fn set_ancestor_id_local(&mut self, ancestor_id_local: String) {
self.ancestor_id_local = Some(ancestor_id_local);
}
}
impl super::v1::Syncable for EventLocal {
fn id(&self) -> Option<i64> {
self.id
}
fn set_id(&mut self, id: i64) {
self.id = Some(id);
}
fn id_local(&self) -> Option<String> {
self.id_local.clone()
}
fn set_id_local(&mut self, id_local: String) {
self.id_local = Some(id_local);
}
}
impl super::v1::Syncable for Event {
fn id(&self) -> Option<i64> {
self.id
}
fn set_id(&mut self, id: i64) {
self.id = Some(id);
}
fn id_local(&self) -> Option<String> {
None
}
fn set_id_local(&mut self, _: String) {}
}
impl From<EventLocal> for Event {
fn from(local: EventLocal) -> Self {
Self {
id: local.id,
message: local.message,
media_url: local.media_url,
file_path: local.file_path,
location: local.location,
altitude: local.altitude,
heading: local.heading,
media_type: local.media_type,
device_id: local.device_id,
earthranger_url: local.earthranger_url,
timestamp_observation: local.timestamp_observation,
is_public: local.is_public,
session_id: local.session_id,
tagged_at: local.tagged_at,
embedded_at: local.embedded_at,
segmented_at: local.segmented_at,
tracked_at: local.tracked_at,
}
}
}
impl From<Event> for EventLocal {
fn from(event: Event) -> Self {
Self {
id: event.id,
id_local: None,
message: event.message,
media_url: event.media_url,
file_path: event.file_path,
location: event.location,
altitude: event.altitude,
heading: event.heading,
media_type: event.media_type,
device_id: event.device_id,
earthranger_url: event.earthranger_url,
timestamp_observation: event.timestamp_observation,
is_public: event.is_public,
session_id: event.session_id,
ancestor_id_local: None,
tagged_at: event.tagged_at,
embedded_at: event.embedded_at,
segmented_at: event.segmented_at,
tracked_at: event.tracked_at,
}
}
}
impl From<super::v6::EventLocal> for EventLocal {
fn from(v6: super::v6::EventLocal) -> Self {
Self {
id: v6.id,
id_local: v6.id_local,
message: v6.message,
media_url: v6.media_url,
file_path: v6.file_path,
location: v6.location,
altitude: v6.altitude,
heading: v6.heading,
media_type: v6.media_type,
device_id: v6.device_id,
earthranger_url: v6.earthranger_url,
timestamp_observation: v6.timestamp_observation,
is_public: v6.is_public,
session_id: v6.session_id,
ancestor_id_local: v6.ancestor_id_local,
tagged_at: None,
embedded_at: None,
segmented_at: None,
tracked_at: None,
}
}
}
impl From<super::v6::Event> for Event {
fn from(v6: super::v6::Event) -> Self {
Self {
id: v6.id,
message: v6.message,
media_url: v6.media_url,
file_path: v6.file_path,
location: v6.location,
altitude: v6.altitude,
heading: v6.heading,
media_type: v6.media_type,
device_id: v6.device_id,
earthranger_url: v6.earthranger_url,
timestamp_observation: v6.timestamp_observation,
is_public: v6.is_public,
session_id: v6.session_id,
tagged_at: None,
embedded_at: None,
segmented_at: None,
tracked_at: None,
}
}
}
impl Event {
pub fn new(
message: Option<String>,
media_url: Option<String>,
file_path: Option<String>,
earthranger_url: Option<String>,
latitude: f64,
longitude: f64,
altitude: f64,
heading: f64,
media_type: super::v1::MediaType,
device_id: i64,
timestamp_observation: u64,
is_public: bool,
session_id: Option<i64>,
) -> Self {
use chrono::{DateTime, Utc};
let timestamp_observation_str = DateTime::from_timestamp(timestamp_observation as i64, 0)
.unwrap_or_else(|| DateTime::<Utc>::from_timestamp(0, 0).unwrap())
.to_rfc3339();
Self {
id: None,
message,
media_url,
file_path,
location: Some(Self::format_location(latitude, longitude)),
altitude,
heading,
media_type,
device_id,
earthranger_url,
timestamp_observation: timestamp_observation_str,
is_public,
session_id,
tagged_at: None,
embedded_at: None,
segmented_at: None,
tracked_at: None,
}
}
pub fn format_location(latitude: f64, longitude: f64) -> String {
format!("POINT({} {})", longitude, latitude)
}
}
impl EventLocal {
pub fn new(
message: Option<String>,
media_url: Option<String>,
file_path: Option<String>,
earthranger_url: Option<String>,
latitude: f64,
longitude: f64,
altitude: f64,
heading: f64,
media_type: super::v1::MediaType,
device_id: i64,
timestamp_observation: u64,
is_public: bool,
session_id: Option<i64>,
) -> Self {
use chrono::{DateTime, Utc};
let location = Self::format_location(latitude, longitude);
let timestamp_observation = DateTime::from_timestamp(timestamp_observation as i64, 0)
.unwrap_or_else(|| Utc::now())
.to_rfc3339();
Self {
id: None,
id_local: None,
message,
media_url,
file_path,
location: Some(location),
altitude,
heading,
media_type,
device_id,
earthranger_url,
timestamp_observation,
is_public,
session_id,
ancestor_id_local: None,
tagged_at: None,
embedded_at: None,
segmented_at: None,
tracked_at: None,
}
}
pub fn format_location(latitude: f64, longitude: f64) -> String {
format!("POINT({} {})", longitude, latitude)
}
}
impl Default for ArtifactLocal {
fn default() -> Self {
use chrono::Utc;
Self {
id: None,
id_local: None,
ancestor_id_local: None,
created_at: None,
file_path: String::new(),
session_id: None,
timestamp_observation: None,
modality: None,
device_id: 0,
updated_at: None,
timestamp_observation_end: Utc::now().to_rfc3339(),
has_uploaded_file_to_storage: false,
upload_url: None,
upload_url_generated_at: None,
file_size_bytes: None,
tagged_at: None,
embedded_at: None,
segmented_at: None,
tracked_at: None,
}
}
}
impl super::v1::Syncable for ArtifactLocal {
fn id(&self) -> Option<i64> {
self.id
}
fn set_id(&mut self, id: i64) {
self.id = Some(id);
}
fn id_local(&self) -> Option<String> {
self.id_local.clone()
}
fn set_id_local(&mut self, id_local: String) {
self.id_local = Some(id_local);
}
}
impl super::v1::AncestorLocal for ArtifactLocal {
fn ancestor_id_local(&self) -> Option<String> {
self.ancestor_id_local.clone()
}
fn set_ancestor_id_local(&mut self, ancestor_id_local: String) {
self.ancestor_id_local = Some(ancestor_id_local);
}
}
impl From<ArtifactLocal> for Artifact {
fn from(local: ArtifactLocal) -> Self {
Self {
id: local.id,
created_at: local.created_at,
file_path: local.file_path,
session_id: local.session_id,
timestamp_observation: local.timestamp_observation,
modality: local.modality,
device_id: local.device_id,
updated_at: local.updated_at,
timestamp_observation_end: local.timestamp_observation_end,
file_size_bytes: local.file_size_bytes,
tagged_at: local.tagged_at,
embedded_at: local.embedded_at,
segmented_at: local.segmented_at,
tracked_at: local.tracked_at,
}
}
}
impl From<Artifact> for ArtifactLocal {
fn from(a: Artifact) -> Self {
Self {
id: a.id,
id_local: None,
ancestor_id_local: None,
created_at: a.created_at,
file_path: a.file_path,
session_id: a.session_id,
timestamp_observation: a.timestamp_observation,
modality: a.modality,
device_id: a.device_id,
updated_at: a.updated_at,
timestamp_observation_end: a.timestamp_observation_end,
has_uploaded_file_to_storage: false,
upload_url: None,
upload_url_generated_at: None,
file_size_bytes: a.file_size_bytes,
tagged_at: a.tagged_at,
embedded_at: a.embedded_at,
segmented_at: a.segmented_at,
tracked_at: a.tracked_at,
}
}
}
impl From<super::v6::ArtifactLocal> for ArtifactLocal {
fn from(v6: super::v6::ArtifactLocal) -> Self {
Self {
id: v6.id,
id_local: v6.id_local,
ancestor_id_local: v6.ancestor_id_local,
created_at: v6.created_at,
file_path: v6.file_path,
session_id: v6.session_id,
timestamp_observation: v6.timestamp_observation,
modality: v6.modality,
device_id: v6.device_id,
updated_at: v6.updated_at,
timestamp_observation_end: v6.timestamp_observation_end,
has_uploaded_file_to_storage: v6.has_uploaded_file_to_storage,
upload_url: v6.upload_url,
upload_url_generated_at: v6.upload_url_generated_at,
file_size_bytes: v6.file_size_bytes,
tagged_at: v6.tagged_at,
embedded_at: None,
segmented_at: None,
tracked_at: None,
}
}
}
impl From<super::v6::Artifact> for Artifact {
fn from(v6: super::v6::Artifact) -> Self {
Self {
id: v6.id,
created_at: v6.created_at,
file_path: v6.file_path,
session_id: v6.session_id,
timestamp_observation: v6.timestamp_observation,
modality: v6.modality,
device_id: v6.device_id,
updated_at: v6.updated_at,
timestamp_observation_end: v6.timestamp_observation_end,
file_size_bytes: v6.file_size_bytes,
tagged_at: v6.tagged_at,
embedded_at: None,
segmented_at: None,
tracked_at: None,
}
}
}
impl Artifact {
pub fn new(
file_path: String,
session_id: Option<i64>,
device_id: i64,
modality: Option<String>,
timestamp_observation: Option<String>,
) -> Self {
use chrono::Utc;
Self {
id: None,
created_at: None,
file_path,
session_id,
timestamp_observation,
modality,
device_id,
updated_at: None,
timestamp_observation_end: Utc::now().to_rfc3339(),
file_size_bytes: None,
tagged_at: None,
embedded_at: None,
segmented_at: None,
tracked_at: None,
}
}
}
impl ArtifactLocal {
pub fn new(
file_path: String,
session_id: Option<i64>,
device_id: i64,
modality: Option<String>,
timestamp_observation: Option<String>,
) -> Self {
use chrono::Utc;
Self {
id: None,
id_local: None,
ancestor_id_local: None,
created_at: None,
file_path,
session_id,
timestamp_observation,
modality,
device_id,
updated_at: None,
timestamp_observation_end: Utc::now().to_rfc3339(),
has_uploaded_file_to_storage: false,
upload_url: None,
upload_url_generated_at: None,
file_size_bytes: None,
tagged_at: None,
embedded_at: None,
segmented_at: None,
tracked_at: None,
}
}
pub fn mark_file_uploaded(&mut self) {
self.has_uploaded_file_to_storage = true;
}
pub fn mark_file_not_uploaded(&mut self) {
self.has_uploaded_file_to_storage = false;
}
pub fn is_file_uploaded(&self) -> bool {
self.has_uploaded_file_to_storage
}
pub fn needs_file_upload(&self) -> bool {
!self.has_uploaded_file_to_storage
}
}