From 1e237021b1219d80f3fcf50512fc45c4588521d3 Mon Sep 17 00:00:00 2001 From: Anatolii Kurotych Date: Fri, 24 May 2024 12:08:46 +0300 Subject: [PATCH 1/6] Create hex_assignments --- Cargo.toml | 1 + hex_assignments/Cargo.toml | 18 ++ .../src}/assignment.rs | 1 - .../src}/footfall.rs | 27 +- .../src}/landtype.rs | 27 +- hex_assignments/src/lib.rs | 271 +++++++++++++++++ .../src}/urbanization.rs | 27 +- mobile_verifier/Cargo.toml | 1 + .../src/boosting_oracles/data_sets.rs | 79 ++++- mobile_verifier/src/boosting_oracles/mod.rs | 281 ------------------ mobile_verifier/src/cli/verify_disktree.rs | 7 +- mobile_verifier/src/coverage.rs | 2 +- mobile_verifier/src/reward_shares.rs | 3 +- .../tests/integrations/boosting_oracles.rs | 7 +- .../tests/integrations/common/mod.rs | 6 +- 15 files changed, 386 insertions(+), 372 deletions(-) create mode 100644 hex_assignments/Cargo.toml rename {mobile_verifier/src/boosting_oracles => hex_assignments/src}/assignment.rs (99%) rename {mobile_verifier/src/boosting_oracles => hex_assignments/src}/footfall.rs (65%) rename {mobile_verifier/src/boosting_oracles => hex_assignments/src}/landtype.rs (84%) create mode 100644 hex_assignments/src/lib.rs rename {mobile_verifier/src/boosting_oracles => hex_assignments/src}/urbanization.rs (62%) diff --git a/Cargo.toml b/Cargo.toml index 47649d3ef..a858438fa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,7 @@ members = [ "reward_scheduler", "solana", "task_manager", + "hex_assignments" ] resolver = "2" diff --git a/hex_assignments/Cargo.toml b/hex_assignments/Cargo.toml new file mode 100644 index 000000000..a76526058 --- /dev/null +++ b/hex_assignments/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "hex-assignments" +version = "0.1.0" +description = "Hex Assignments" +edition.workspace = true +authors.workspace = true +license.workspace = true + +[dependencies] +anyhow = { workspace = true } +hextree = { workspace = true } +sqlx = {version = "*", features = ["runtime-tokio-rustls"]} +rust_decimal = { workspace = true} +rust_decimal_macros = { workspace = true} +helium-proto = {workspace = true} +async-trait = { workspace = true } +chrono = { workspace = true } +derive_builder = { workspace = true } diff --git a/mobile_verifier/src/boosting_oracles/assignment.rs b/hex_assignments/src/assignment.rs similarity index 99% rename from mobile_verifier/src/boosting_oracles/assignment.rs rename to hex_assignments/src/assignment.rs index 8d8a37321..a067a72ff 100644 --- a/mobile_verifier/src/boosting_oracles/assignment.rs +++ b/hex_assignments/src/assignment.rs @@ -150,7 +150,6 @@ impl HexAssignmentsBuilder { } } -#[cfg(test)] impl HexAssignments { pub fn test_best() -> Self { Self { diff --git a/mobile_verifier/src/boosting_oracles/footfall.rs b/hex_assignments/src/footfall.rs similarity index 65% rename from mobile_verifier/src/boosting_oracles/footfall.rs rename to hex_assignments/src/footfall.rs index 4af2ebaf5..bd9ece9e0 100644 --- a/mobile_verifier/src/boosting_oracles/footfall.rs +++ b/hex_assignments/src/footfall.rs @@ -1,13 +1,11 @@ -use std::path::Path; - use chrono::{DateTime, Utc}; use hextree::disktree::DiskTreeMap; -use super::{Assignment, DataSet, DataSetType, HexAssignment}; +use super::{Assignment, HexAssignment}; pub struct Footfall { - footfall: Option, - timestamp: Option>, + pub footfall: Option, + pub timestamp: Option>, } impl Footfall { @@ -32,25 +30,6 @@ impl Default for Footfall { } } -#[async_trait::async_trait] -impl DataSet for Footfall { - const TYPE: DataSetType = DataSetType::Footfall; - - fn timestamp(&self) -> Option> { - self.timestamp - } - - fn update(&mut self, path: &Path, time_to_use: DateTime) -> anyhow::Result<()> { - self.footfall = Some(DiskTreeMap::open(path)?); - self.timestamp = Some(time_to_use); - Ok(()) - } - - fn is_ready(&self) -> bool { - self.footfall.is_some() - } -} - impl HexAssignment for Footfall { fn assignment(&self, cell: hextree::Cell) -> anyhow::Result { let Some(ref footfall) = self.footfall else { diff --git a/mobile_verifier/src/boosting_oracles/landtype.rs b/hex_assignments/src/landtype.rs similarity index 84% rename from mobile_verifier/src/boosting_oracles/landtype.rs rename to hex_assignments/src/landtype.rs index b6cda7aef..533bb6f21 100644 --- a/mobile_verifier/src/boosting_oracles/landtype.rs +++ b/hex_assignments/src/landtype.rs @@ -1,13 +1,11 @@ -use std::path::Path; - use chrono::{DateTime, Utc}; use hextree::disktree::DiskTreeMap; -use super::{Assignment, DataSet, DataSetType, HexAssignment}; +use super::{Assignment, HexAssignment}; pub struct Landtype { - landtype: Option, - timestamp: Option>, + pub landtype: Option, + pub timestamp: Option>, } impl Landtype { @@ -32,25 +30,6 @@ impl Default for Landtype { } } -#[async_trait::async_trait] -impl DataSet for Landtype { - const TYPE: DataSetType = DataSetType::Landtype; - - fn timestamp(&self) -> Option> { - self.timestamp - } - - fn update(&mut self, path: &Path, time_to_use: DateTime) -> anyhow::Result<()> { - self.landtype = Some(DiskTreeMap::open(path)?); - self.timestamp = Some(time_to_use); - Ok(()) - } - - fn is_ready(&self) -> bool { - self.landtype.is_some() - } -} - #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum LandtypeValue { Tree = 10, diff --git a/hex_assignments/src/lib.rs b/hex_assignments/src/lib.rs new file mode 100644 index 000000000..7c7c6f156 --- /dev/null +++ b/hex_assignments/src/lib.rs @@ -0,0 +1,271 @@ +pub mod assignment; +pub mod footfall; +pub mod landtype; +pub mod urbanization; + +use std::collections::HashMap; + +use assignment::HexAssignments; +pub use assignment::Assignment; + +pub trait HexAssignment: Send + Sync + 'static { + fn assignment(&self, cell: hextree::Cell) -> anyhow::Result; +} + +impl HexAssignment for HashMap { + fn assignment(&self, cell: hextree::Cell) -> anyhow::Result { + Ok(*self.get(&cell).unwrap()) + } +} + +impl HexAssignment for Assignment { + fn assignment(&self, _cell: hextree::Cell) -> anyhow::Result { + Ok(*self) + } +} + +#[derive(derive_builder::Builder)] +#[builder(pattern = "owned")] +pub struct HexBoostData { + pub footfall: Foot, + pub landtype: Land, + pub urbanization: Urban, +} +impl HexBoostData { + pub fn builder() -> HexBoostDataBuilder { + HexBoostDataBuilder::default() + } +} + +impl HexBoostData +where + Foot: HexAssignment, + Land: HexAssignment, + Urban: HexAssignment, +{ + pub fn assignments(&self, cell: hextree::Cell) -> anyhow::Result { + HexAssignments::builder(cell) + .footfall(&self.footfall) + .landtype(&self.landtype) + .urbanized(&self.urbanization) + .build() + } +} + +#[cfg(test)] +mod tests { + + use std::io::Cursor; + + use hextree::{disktree::DiskTreeMap, HexTreeMap}; + + use self::{footfall::Footfall, landtype::Landtype, urbanization::Urbanization}; + + use super::*; + + #[test] + fn test_hex_boost_data() -> anyhow::Result<()> { + // This test will break if any of the logic deriving Assignments from + // the underlying DiskTreeMap's changes. + + let unknown_cell = hextree::Cell::from_raw(0x8c2681a3064d9ff)?; + + // Types of Cells + // yellow - POI ≥ 1 Urbanized + let poi_built_urbanized = hextree::Cell::from_raw(0x8c2681a3064dbff)?; + let poi_grass_urbanized = hextree::Cell::from_raw(0x8c2681a3064ddff)?; + let poi_water_urbanized = hextree::Cell::from_raw(0x8c2681a3064e1ff)?; + // orange - POI ≥ 1 Not Urbanized + let poi_built_not_urbanized = hextree::Cell::from_raw(0x8c2681a3064e3ff)?; + let poi_grass_not_urbanized = hextree::Cell::from_raw(0x8c2681a3064e5ff)?; + let poi_water_not_urbanized = hextree::Cell::from_raw(0x8c2681a3064e7ff)?; + // light green - Point of Interest Urbanized + let poi_no_data_built_urbanized = hextree::Cell::from_raw(0x8c2681a3064e9ff)?; + let poi_no_data_grass_urbanized = hextree::Cell::from_raw(0x8c2681a3064ebff)?; + let poi_no_data_water_urbanized = hextree::Cell::from_raw(0x8c2681a3064edff)?; + // dark green - Point of Interest Not Urbanized + let poi_no_data_built_not_urbanized = hextree::Cell::from_raw(0x8c2681a306501ff)?; + let poi_no_data_grass_not_urbanized = hextree::Cell::from_raw(0x8c2681a306503ff)?; + let poi_no_data_water_not_urbanized = hextree::Cell::from_raw(0x8c2681a306505ff)?; + // light blue - No POI Urbanized + let no_poi_built_urbanized = hextree::Cell::from_raw(0x8c2681a306507ff)?; + let no_poi_grass_urbanized = hextree::Cell::from_raw(0x8c2681a306509ff)?; + let no_poi_water_urbanized = hextree::Cell::from_raw(0x8c2681a30650bff)?; + // dark blue - No POI Not Urbanized + let no_poi_built_not_urbanized = hextree::Cell::from_raw(0x8c2681a30650dff)?; + let no_poi_grass_not_urbanized = hextree::Cell::from_raw(0x8c2681a306511ff)?; + let no_poi_water_not_urbanized = hextree::Cell::from_raw(0x8c2681a306513ff)?; + // gray - Outside of USA + let poi_built_outside_us = hextree::Cell::from_raw(0x8c2681a306515ff)?; + let poi_grass_outside_us = hextree::Cell::from_raw(0x8c2681a306517ff)?; + let poi_water_outside_us = hextree::Cell::from_raw(0x8c2681a306519ff)?; + let poi_no_data_built_outside_us = hextree::Cell::from_raw(0x8c2681a30651bff)?; + let poi_no_data_grass_outside_us = hextree::Cell::from_raw(0x8c2681a30651dff)?; + let poi_no_data_water_outside_us = hextree::Cell::from_raw(0x8c2681a306521ff)?; + let no_poi_built_outside_us = hextree::Cell::from_raw(0x8c2681a306523ff)?; + let no_poi_grass_outside_us = hextree::Cell::from_raw(0x8c2681a306525ff)?; + let no_poi_water_outside_us = hextree::Cell::from_raw(0x8c2681a306527ff)?; + + // Footfall Data + // POI - footfalls > 1 for a POI across hexes + // POI No Data - No footfalls for a POI across any hexes + // NO POI - Does not exist + let mut footfall = HexTreeMap::::new(); + footfall.insert(poi_built_urbanized, 42); + footfall.insert(poi_grass_urbanized, 42); + footfall.insert(poi_water_urbanized, 42); + footfall.insert(poi_built_not_urbanized, 42); + footfall.insert(poi_grass_not_urbanized, 42); + footfall.insert(poi_water_not_urbanized, 42); + footfall.insert(poi_no_data_built_urbanized, 0); + footfall.insert(poi_no_data_grass_urbanized, 0); + footfall.insert(poi_no_data_water_urbanized, 0); + footfall.insert(poi_no_data_built_not_urbanized, 0); + footfall.insert(poi_no_data_grass_not_urbanized, 0); + footfall.insert(poi_no_data_water_not_urbanized, 0); + footfall.insert(poi_built_outside_us, 42); + footfall.insert(poi_grass_outside_us, 42); + footfall.insert(poi_water_outside_us, 42); + footfall.insert(poi_no_data_built_outside_us, 0); + footfall.insert(poi_no_data_grass_outside_us, 0); + footfall.insert(poi_no_data_water_outside_us, 0); + + // Landtype Data + // Map to enum values for Landtype + // An unknown cell is considered Assignment::C + let mut landtype = HexTreeMap::::new(); + landtype.insert(poi_built_urbanized, 50); + landtype.insert(poi_grass_urbanized, 30); + landtype.insert(poi_water_urbanized, 80); + landtype.insert(poi_built_not_urbanized, 50); + landtype.insert(poi_grass_not_urbanized, 30); + landtype.insert(poi_water_not_urbanized, 80); + landtype.insert(poi_no_data_built_urbanized, 50); + landtype.insert(poi_no_data_grass_urbanized, 30); + landtype.insert(poi_no_data_water_urbanized, 80); + landtype.insert(poi_no_data_built_not_urbanized, 50); + landtype.insert(poi_no_data_grass_not_urbanized, 30); + landtype.insert(poi_no_data_water_not_urbanized, 80); + landtype.insert(no_poi_built_urbanized, 50); + landtype.insert(no_poi_grass_urbanized, 30); + landtype.insert(no_poi_water_urbanized, 80); + landtype.insert(no_poi_built_not_urbanized, 50); + landtype.insert(no_poi_grass_not_urbanized, 30); + landtype.insert(no_poi_water_not_urbanized, 80); + landtype.insert(poi_built_outside_us, 50); + landtype.insert(poi_grass_outside_us, 30); + landtype.insert(poi_water_outside_us, 80); + landtype.insert(poi_no_data_built_outside_us, 50); + landtype.insert(poi_no_data_grass_outside_us, 30); + landtype.insert(poi_no_data_water_outside_us, 80); + landtype.insert(no_poi_built_outside_us, 50); + landtype.insert(no_poi_grass_outside_us, 30); + landtype.insert(no_poi_water_outside_us, 80); + + // Urbanized data + // Urban - something in the map, and in the geofence + // Not Urban - nothing in the map, but in the geofence + // Outside - not in the geofence, urbanized hex never considered + let mut urbanized = HexTreeMap::::new(); + urbanized.insert(poi_built_urbanized, 1); + urbanized.insert(poi_grass_urbanized, 1); + urbanized.insert(poi_water_urbanized, 1); + urbanized.insert(poi_no_data_built_urbanized, 1); + urbanized.insert(poi_no_data_grass_urbanized, 1); + urbanized.insert(poi_no_data_water_urbanized, 1); + urbanized.insert(no_poi_built_urbanized, 1); + urbanized.insert(no_poi_grass_urbanized, 1); + urbanized.insert(no_poi_water_urbanized, 1); + + let inside_usa = [ + poi_built_urbanized, + poi_grass_urbanized, + poi_water_urbanized, + poi_built_not_urbanized, + poi_grass_not_urbanized, + poi_water_not_urbanized, + poi_no_data_built_urbanized, + poi_no_data_grass_urbanized, + poi_no_data_water_urbanized, + poi_no_data_built_not_urbanized, + poi_no_data_grass_not_urbanized, + poi_no_data_water_not_urbanized, + no_poi_built_urbanized, + no_poi_grass_urbanized, + no_poi_water_urbanized, + no_poi_built_not_urbanized, + no_poi_grass_not_urbanized, + no_poi_water_not_urbanized, + ]; + for inside_usa in inside_usa.into_iter() { + urbanized.entry(inside_usa).or_insert(0); + } + // These vectors are a standin for the file system + let mut urbanized_buf = vec![]; + let mut footfall_buff = vec![]; + let mut landtype_buf = vec![]; + + // Turn the HexTrees into DiskTrees + urbanized.to_disktree(Cursor::new(&mut urbanized_buf), |w, v| w.write_all(&[*v]))?; + footfall.to_disktree(Cursor::new(&mut footfall_buff), |w, v| w.write_all(&[*v]))?; + landtype.to_disktree(Cursor::new(&mut landtype_buf), |w, v| w.write_all(&[*v]))?; + + let footfall = Footfall::new_mock(DiskTreeMap::with_buf(footfall_buff)?); + let landtype = Landtype::new_mock(DiskTreeMap::with_buf(landtype_buf)?); + let urbanization = Urbanization::new_mock(DiskTreeMap::with_buf(urbanized_buf)?); + + // Let the testing commence + let data = HexBoostData::builder() + .footfall(footfall) + .landtype(landtype) + .urbanization(urbanization) + .build()?; + + // NOTE(mj): formatting ignored to make it easier to see the expected change in assignments. + // NOTE(mj): The semicolon at the end of the block is there to keep rust from + // complaining about attributes on expression being experimental. + #[rustfmt::skip] + { + use Assignment::*; + // yellow + assert_eq!(HexAssignments { footfall: A, landtype: A, urbanized: A }, data.assignments(poi_built_urbanized)?); + assert_eq!(HexAssignments { footfall: A, landtype: B, urbanized: A }, data.assignments(poi_grass_urbanized)?); + assert_eq!(HexAssignments { footfall: A, landtype: C, urbanized: A }, data.assignments(poi_water_urbanized)?); + // orange + assert_eq!(HexAssignments { footfall: A, landtype: A, urbanized: B }, data.assignments(poi_built_not_urbanized)?); + assert_eq!(HexAssignments { footfall: A, landtype: B, urbanized: B }, data.assignments(poi_grass_not_urbanized)?); + assert_eq!(HexAssignments { footfall: A, landtype: C, urbanized: B }, data.assignments(poi_water_not_urbanized)?); + // light green + assert_eq!(HexAssignments { footfall: B, landtype: A, urbanized: A }, data.assignments(poi_no_data_built_urbanized)?); + assert_eq!(HexAssignments { footfall: B, landtype: B, urbanized: A }, data.assignments(poi_no_data_grass_urbanized)?); + assert_eq!(HexAssignments { footfall: B, landtype: C, urbanized: A }, data.assignments(poi_no_data_water_urbanized)?); + // green + assert_eq!(HexAssignments { footfall: B, landtype: A, urbanized: B }, data.assignments(poi_no_data_built_not_urbanized)?); + assert_eq!(HexAssignments { footfall: B, landtype: B, urbanized: B }, data.assignments(poi_no_data_grass_not_urbanized)?); + assert_eq!(HexAssignments { footfall: B, landtype: C, urbanized: B }, data.assignments(poi_no_data_water_not_urbanized)?); + // light blue + assert_eq!(HexAssignments { footfall: C, landtype: A, urbanized: A }, data.assignments(no_poi_built_urbanized)?); + assert_eq!(HexAssignments { footfall: C, landtype: B, urbanized: A }, data.assignments(no_poi_grass_urbanized)?); + assert_eq!(HexAssignments { footfall: C, landtype: C, urbanized: A }, data.assignments(no_poi_water_urbanized)?); + // dark blue + assert_eq!(HexAssignments { footfall: C, landtype: A, urbanized: B }, data.assignments(no_poi_built_not_urbanized)?); + assert_eq!(HexAssignments { footfall: C, landtype: B, urbanized: B }, data.assignments(no_poi_grass_not_urbanized)?); + assert_eq!(HexAssignments { footfall: C, landtype: C, urbanized: B }, data.assignments(no_poi_water_not_urbanized)?); + // gray + assert_eq!(HexAssignments { footfall: A, landtype: A, urbanized: C }, data.assignments(poi_built_outside_us)?); + assert_eq!(HexAssignments { footfall: A, landtype: B, urbanized: C }, data.assignments(poi_grass_outside_us)?); + assert_eq!(HexAssignments { footfall: A, landtype: C, urbanized: C }, data.assignments(poi_water_outside_us)?); + assert_eq!(HexAssignments { footfall: B, landtype: A, urbanized: C }, data.assignments(poi_no_data_built_outside_us)?); + assert_eq!(HexAssignments { footfall: B, landtype: B, urbanized: C }, data.assignments(poi_no_data_grass_outside_us)?); + assert_eq!(HexAssignments { footfall: B, landtype: C, urbanized: C }, data.assignments(poi_no_data_water_outside_us)?); + assert_eq!(HexAssignments { footfall: C, landtype: A, urbanized: C }, data.assignments(no_poi_built_outside_us)?); + assert_eq!(HexAssignments { footfall: C, landtype: B, urbanized: C }, data.assignments(no_poi_grass_outside_us)?); + assert_eq!(HexAssignments { footfall: C, landtype: C, urbanized: C }, data.assignments(no_poi_water_outside_us)?); + // never inserted + assert_eq!(HexAssignments { footfall: C, landtype: C, urbanized: C }, data.assignments(unknown_cell)?); + }; + + Ok(()) + } +} + diff --git a/mobile_verifier/src/boosting_oracles/urbanization.rs b/hex_assignments/src/urbanization.rs similarity index 62% rename from mobile_verifier/src/boosting_oracles/urbanization.rs rename to hex_assignments/src/urbanization.rs index 8070c445c..c4a2c0943 100644 --- a/mobile_verifier/src/boosting_oracles/urbanization.rs +++ b/hex_assignments/src/urbanization.rs @@ -1,13 +1,11 @@ -use std::path::Path; - use chrono::{DateTime, Utc}; use hextree::disktree::DiskTreeMap; -use super::{Assignment, DataSet, DataSetType, HexAssignment}; +use super::{Assignment, HexAssignment}; pub struct Urbanization { - urbanized: Option, - timestamp: Option>, + pub urbanized: Option, + pub timestamp: Option>, } impl Urbanization { @@ -32,25 +30,6 @@ impl Default for Urbanization { } } -#[async_trait::async_trait] -impl DataSet for Urbanization { - const TYPE: DataSetType = DataSetType::Urbanization; - - fn timestamp(&self) -> Option> { - self.timestamp - } - - fn update(&mut self, path: &Path, time_to_use: DateTime) -> anyhow::Result<()> { - self.urbanized = Some(DiskTreeMap::open(path)?); - self.timestamp = Some(time_to_use); - Ok(()) - } - - fn is_ready(&self) -> bool { - self.urbanized.is_some() - } -} - impl HexAssignment for Urbanization { fn assignment(&self, cell: hextree::Cell) -> anyhow::Result { let Some(ref urbanized) = self.urbanized else { diff --git a/mobile_verifier/Cargo.toml b/mobile_verifier/Cargo.toml index 044256d9d..5760b0459 100644 --- a/mobile_verifier/Cargo.toml +++ b/mobile_verifier/Cargo.toml @@ -57,6 +57,7 @@ derive_builder = { workspace = true } regex = "1" humantime-serde = { workspace = true } custom-tracing = { path = "../custom_tracing" } +hex-assignments = {path = "../hex_assignments"} [dev-dependencies] backon = "0" diff --git a/mobile_verifier/src/boosting_oracles/data_sets.rs b/mobile_verifier/src/boosting_oracles/data_sets.rs index 76eaec1a4..2a3034383 100644 --- a/mobile_verifier/src/boosting_oracles/data_sets.rs +++ b/mobile_verifier/src/boosting_oracles/data_sets.rs @@ -14,6 +14,7 @@ use file_store::{ }; use futures_util::{Stream, StreamExt, TryFutureExt, TryStreamExt}; use helium_proto::services::poc_mobile as proto; +use hextree::disktree::DiskTreeMap; use lazy_static::lazy_static; use regex::Regex; use rust_decimal::prelude::ToPrimitive; @@ -23,13 +24,13 @@ use task_manager::{ManagedTask, TaskManager}; use tokio::{fs::File, io::AsyncWriteExt, time::Instant}; use crate::{ - boosting_oracles::assignment::HexAssignments, coverage::{NewCoverageObjectNotification, SignalLevel}, Settings, }; -use super::{ - footfall::Footfall, landtype::Landtype, urbanization::Urbanization, HexAssignment, HexBoostData, +use hex_assignments::{ + assignment::HexAssignments, footfall::Footfall, landtype::Landtype, urbanization::Urbanization, + HexAssignment, HexBoostData, }; #[async_trait::async_trait] @@ -106,6 +107,72 @@ pub trait DataSet: HexAssignment + Send + Sync + 'static { } } +#[async_trait::async_trait] +impl DataSet for Footfall { + const TYPE: DataSetType = DataSetType::Footfall; + + fn timestamp(&self) -> Option> { + self.timestamp + } + + fn update(&mut self, path: &Path, time_to_use: DateTime) -> anyhow::Result<()> { + self.footfall = Some(DiskTreeMap::open(path)?); + self.timestamp = Some(time_to_use); + Ok(()) + } + + fn is_ready(&self) -> bool { + self.footfall.is_some() + } +} + +#[async_trait::async_trait] +impl DataSet for Landtype { + const TYPE: DataSetType = DataSetType::Landtype; + + fn timestamp(&self) -> Option> { + self.timestamp + } + + fn update(&mut self, path: &Path, time_to_use: DateTime) -> anyhow::Result<()> { + self.landtype = Some(DiskTreeMap::open(path)?); + self.timestamp = Some(time_to_use); + Ok(()) + } + + fn is_ready(&self) -> bool { + self.landtype.is_some() + } +} + +#[async_trait::async_trait] +impl DataSet for Urbanization { + const TYPE: DataSetType = DataSetType::Urbanization; + + fn timestamp(&self) -> Option> { + self.timestamp + } + + fn update(&mut self, path: &Path, time_to_use: DateTime) -> anyhow::Result<()> { + self.urbanized = Some(DiskTreeMap::open(path)?); + self.timestamp = Some(time_to_use); + Ok(()) + } + + fn is_ready(&self) -> bool { + self.urbanized.is_some() + } +} + +pub fn is_hex_boost_data_ready(h: &HexBoostData) -> bool +where + A: DataSet, + B: DataSet, + C: DataSet, +{ + h.urbanization.is_ready() && h.footfall.is_ready() && h.landtype.is_ready() +} + pub struct DataSetDownloaderDaemon { pool: PgPool, data_sets: HexBoostData, @@ -268,7 +335,7 @@ where // hex assignments: let new_data_set = new_urbanized.is_some() || new_footfall.is_some() || new_landtype.is_some(); - if self.data_sets.is_ready() && new_data_set { + if is_hex_boost_data_ready(&self.data_sets) && new_data_set { tracing::info!("Processing new data sets"); set_all_oracle_boosting_assignments( &self.pool, @@ -326,7 +393,7 @@ where // Attempt to fill in any unassigned hexes. This is for the edge case in // which we shutdown before a coverage object updates. - if self.data_sets.is_ready() { + if is_hex_boost_data_ready(&self.data_sets) { set_unassigned_oracle_boosting_assignments( &self.pool, &self.data_sets, @@ -342,7 +409,7 @@ where _ = self.new_coverage_object_notification.await_new_coverage_object() => { // If we see a new coverage object, we want to assign only those hexes // that don't have an assignment - if self.data_sets.is_ready() { + if is_hex_boost_data_ready(&self.data_sets) { set_unassigned_oracle_boosting_assignments( &self.pool, &self.data_sets, diff --git a/mobile_verifier/src/boosting_oracles/mod.rs b/mobile_verifier/src/boosting_oracles/mod.rs index 0f63845cb..e1a05b952 100644 --- a/mobile_verifier/src/boosting_oracles/mod.rs +++ b/mobile_verifier/src/boosting_oracles/mod.rs @@ -1,283 +1,2 @@ -pub mod assignment; pub mod data_sets; -pub mod footfall; -pub mod landtype; -pub mod urbanization; - -use std::collections::HashMap; - -use crate::boosting_oracles::assignment::HexAssignments; -pub use assignment::Assignment; pub use data_sets::*; - -pub trait HexAssignment: Send + Sync + 'static { - fn assignment(&self, cell: hextree::Cell) -> anyhow::Result; -} - -impl HexAssignment for HashMap { - fn assignment(&self, cell: hextree::Cell) -> anyhow::Result { - Ok(*self.get(&cell).unwrap()) - } -} - -impl HexAssignment for Assignment { - fn assignment(&self, _cell: hextree::Cell) -> anyhow::Result { - Ok(*self) - } -} - -#[derive(derive_builder::Builder)] -#[builder(pattern = "owned")] -pub struct HexBoostData { - pub footfall: Foot, - pub landtype: Land, - pub urbanization: Urban, -} -impl HexBoostData { - pub fn builder() -> HexBoostDataBuilder { - HexBoostDataBuilder::default() - } -} - -impl HexBoostData -where - Foot: DataSet, - Land: DataSet, - Urban: DataSet, -{ - pub fn is_ready(&self) -> bool { - self.urbanization.is_ready() && self.footfall.is_ready() && self.landtype.is_ready() - } -} - -impl HexBoostData -where - Foot: HexAssignment, - Land: HexAssignment, - Urban: HexAssignment, -{ - pub fn assignments(&self, cell: hextree::Cell) -> anyhow::Result { - HexAssignments::builder(cell) - .footfall(&self.footfall) - .landtype(&self.landtype) - .urbanized(&self.urbanization) - .build() - } -} - -#[cfg(test)] -mod tests { - - use std::io::Cursor; - - use hextree::{disktree::DiskTreeMap, HexTreeMap}; - - use self::{footfall::Footfall, landtype::Landtype, urbanization::Urbanization}; - - use super::*; - - #[test] - fn test_hex_boost_data() -> anyhow::Result<()> { - // This test will break if any of the logic deriving Assignments from - // the underlying DiskTreeMap's changes. - - let unknown_cell = hextree::Cell::from_raw(0x8c2681a3064d9ff)?; - - // Types of Cells - // yellow - POI ≥ 1 Urbanized - let poi_built_urbanized = hextree::Cell::from_raw(0x8c2681a3064dbff)?; - let poi_grass_urbanized = hextree::Cell::from_raw(0x8c2681a3064ddff)?; - let poi_water_urbanized = hextree::Cell::from_raw(0x8c2681a3064e1ff)?; - // orange - POI ≥ 1 Not Urbanized - let poi_built_not_urbanized = hextree::Cell::from_raw(0x8c2681a3064e3ff)?; - let poi_grass_not_urbanized = hextree::Cell::from_raw(0x8c2681a3064e5ff)?; - let poi_water_not_urbanized = hextree::Cell::from_raw(0x8c2681a3064e7ff)?; - // light green - Point of Interest Urbanized - let poi_no_data_built_urbanized = hextree::Cell::from_raw(0x8c2681a3064e9ff)?; - let poi_no_data_grass_urbanized = hextree::Cell::from_raw(0x8c2681a3064ebff)?; - let poi_no_data_water_urbanized = hextree::Cell::from_raw(0x8c2681a3064edff)?; - // dark green - Point of Interest Not Urbanized - let poi_no_data_built_not_urbanized = hextree::Cell::from_raw(0x8c2681a306501ff)?; - let poi_no_data_grass_not_urbanized = hextree::Cell::from_raw(0x8c2681a306503ff)?; - let poi_no_data_water_not_urbanized = hextree::Cell::from_raw(0x8c2681a306505ff)?; - // light blue - No POI Urbanized - let no_poi_built_urbanized = hextree::Cell::from_raw(0x8c2681a306507ff)?; - let no_poi_grass_urbanized = hextree::Cell::from_raw(0x8c2681a306509ff)?; - let no_poi_water_urbanized = hextree::Cell::from_raw(0x8c2681a30650bff)?; - // dark blue - No POI Not Urbanized - let no_poi_built_not_urbanized = hextree::Cell::from_raw(0x8c2681a30650dff)?; - let no_poi_grass_not_urbanized = hextree::Cell::from_raw(0x8c2681a306511ff)?; - let no_poi_water_not_urbanized = hextree::Cell::from_raw(0x8c2681a306513ff)?; - // gray - Outside of USA - let poi_built_outside_us = hextree::Cell::from_raw(0x8c2681a306515ff)?; - let poi_grass_outside_us = hextree::Cell::from_raw(0x8c2681a306517ff)?; - let poi_water_outside_us = hextree::Cell::from_raw(0x8c2681a306519ff)?; - let poi_no_data_built_outside_us = hextree::Cell::from_raw(0x8c2681a30651bff)?; - let poi_no_data_grass_outside_us = hextree::Cell::from_raw(0x8c2681a30651dff)?; - let poi_no_data_water_outside_us = hextree::Cell::from_raw(0x8c2681a306521ff)?; - let no_poi_built_outside_us = hextree::Cell::from_raw(0x8c2681a306523ff)?; - let no_poi_grass_outside_us = hextree::Cell::from_raw(0x8c2681a306525ff)?; - let no_poi_water_outside_us = hextree::Cell::from_raw(0x8c2681a306527ff)?; - - // Footfall Data - // POI - footfalls > 1 for a POI across hexes - // POI No Data - No footfalls for a POI across any hexes - // NO POI - Does not exist - let mut footfall = HexTreeMap::::new(); - footfall.insert(poi_built_urbanized, 42); - footfall.insert(poi_grass_urbanized, 42); - footfall.insert(poi_water_urbanized, 42); - footfall.insert(poi_built_not_urbanized, 42); - footfall.insert(poi_grass_not_urbanized, 42); - footfall.insert(poi_water_not_urbanized, 42); - footfall.insert(poi_no_data_built_urbanized, 0); - footfall.insert(poi_no_data_grass_urbanized, 0); - footfall.insert(poi_no_data_water_urbanized, 0); - footfall.insert(poi_no_data_built_not_urbanized, 0); - footfall.insert(poi_no_data_grass_not_urbanized, 0); - footfall.insert(poi_no_data_water_not_urbanized, 0); - footfall.insert(poi_built_outside_us, 42); - footfall.insert(poi_grass_outside_us, 42); - footfall.insert(poi_water_outside_us, 42); - footfall.insert(poi_no_data_built_outside_us, 0); - footfall.insert(poi_no_data_grass_outside_us, 0); - footfall.insert(poi_no_data_water_outside_us, 0); - - // Landtype Data - // Map to enum values for Landtype - // An unknown cell is considered Assignment::C - let mut landtype = HexTreeMap::::new(); - landtype.insert(poi_built_urbanized, 50); - landtype.insert(poi_grass_urbanized, 30); - landtype.insert(poi_water_urbanized, 80); - landtype.insert(poi_built_not_urbanized, 50); - landtype.insert(poi_grass_not_urbanized, 30); - landtype.insert(poi_water_not_urbanized, 80); - landtype.insert(poi_no_data_built_urbanized, 50); - landtype.insert(poi_no_data_grass_urbanized, 30); - landtype.insert(poi_no_data_water_urbanized, 80); - landtype.insert(poi_no_data_built_not_urbanized, 50); - landtype.insert(poi_no_data_grass_not_urbanized, 30); - landtype.insert(poi_no_data_water_not_urbanized, 80); - landtype.insert(no_poi_built_urbanized, 50); - landtype.insert(no_poi_grass_urbanized, 30); - landtype.insert(no_poi_water_urbanized, 80); - landtype.insert(no_poi_built_not_urbanized, 50); - landtype.insert(no_poi_grass_not_urbanized, 30); - landtype.insert(no_poi_water_not_urbanized, 80); - landtype.insert(poi_built_outside_us, 50); - landtype.insert(poi_grass_outside_us, 30); - landtype.insert(poi_water_outside_us, 80); - landtype.insert(poi_no_data_built_outside_us, 50); - landtype.insert(poi_no_data_grass_outside_us, 30); - landtype.insert(poi_no_data_water_outside_us, 80); - landtype.insert(no_poi_built_outside_us, 50); - landtype.insert(no_poi_grass_outside_us, 30); - landtype.insert(no_poi_water_outside_us, 80); - - // Urbanized data - // Urban - something in the map, and in the geofence - // Not Urban - nothing in the map, but in the geofence - // Outside - not in the geofence, urbanized hex never considered - let mut urbanized = HexTreeMap::::new(); - urbanized.insert(poi_built_urbanized, 1); - urbanized.insert(poi_grass_urbanized, 1); - urbanized.insert(poi_water_urbanized, 1); - urbanized.insert(poi_no_data_built_urbanized, 1); - urbanized.insert(poi_no_data_grass_urbanized, 1); - urbanized.insert(poi_no_data_water_urbanized, 1); - urbanized.insert(no_poi_built_urbanized, 1); - urbanized.insert(no_poi_grass_urbanized, 1); - urbanized.insert(no_poi_water_urbanized, 1); - - let inside_usa = [ - poi_built_urbanized, - poi_grass_urbanized, - poi_water_urbanized, - poi_built_not_urbanized, - poi_grass_not_urbanized, - poi_water_not_urbanized, - poi_no_data_built_urbanized, - poi_no_data_grass_urbanized, - poi_no_data_water_urbanized, - poi_no_data_built_not_urbanized, - poi_no_data_grass_not_urbanized, - poi_no_data_water_not_urbanized, - no_poi_built_urbanized, - no_poi_grass_urbanized, - no_poi_water_urbanized, - no_poi_built_not_urbanized, - no_poi_grass_not_urbanized, - no_poi_water_not_urbanized, - ]; - for inside_usa in inside_usa.into_iter() { - urbanized.entry(inside_usa).or_insert(0); - } - // These vectors are a standin for the file system - let mut urbanized_buf = vec![]; - let mut footfall_buff = vec![]; - let mut landtype_buf = vec![]; - - // Turn the HexTrees into DiskTrees - urbanized.to_disktree(Cursor::new(&mut urbanized_buf), |w, v| w.write_all(&[*v]))?; - footfall.to_disktree(Cursor::new(&mut footfall_buff), |w, v| w.write_all(&[*v]))?; - landtype.to_disktree(Cursor::new(&mut landtype_buf), |w, v| w.write_all(&[*v]))?; - - let footfall = Footfall::new_mock(DiskTreeMap::with_buf(footfall_buff)?); - let landtype = Landtype::new_mock(DiskTreeMap::with_buf(landtype_buf)?); - let urbanization = Urbanization::new_mock(DiskTreeMap::with_buf(urbanized_buf)?); - - // Let the testing commence - let data = HexBoostData::builder() - .footfall(footfall) - .landtype(landtype) - .urbanization(urbanization) - .build()?; - - // NOTE(mj): formatting ignored to make it easier to see the expected change in assignments. - // NOTE(mj): The semicolon at the end of the block is there to keep rust from - // complaining about attributes on expression being experimental. - #[rustfmt::skip] - { - use Assignment::*; - // yellow - assert_eq!(HexAssignments { footfall: A, landtype: A, urbanized: A }, data.assignments(poi_built_urbanized)?); - assert_eq!(HexAssignments { footfall: A, landtype: B, urbanized: A }, data.assignments(poi_grass_urbanized)?); - assert_eq!(HexAssignments { footfall: A, landtype: C, urbanized: A }, data.assignments(poi_water_urbanized)?); - // orange - assert_eq!(HexAssignments { footfall: A, landtype: A, urbanized: B }, data.assignments(poi_built_not_urbanized)?); - assert_eq!(HexAssignments { footfall: A, landtype: B, urbanized: B }, data.assignments(poi_grass_not_urbanized)?); - assert_eq!(HexAssignments { footfall: A, landtype: C, urbanized: B }, data.assignments(poi_water_not_urbanized)?); - // light green - assert_eq!(HexAssignments { footfall: B, landtype: A, urbanized: A }, data.assignments(poi_no_data_built_urbanized)?); - assert_eq!(HexAssignments { footfall: B, landtype: B, urbanized: A }, data.assignments(poi_no_data_grass_urbanized)?); - assert_eq!(HexAssignments { footfall: B, landtype: C, urbanized: A }, data.assignments(poi_no_data_water_urbanized)?); - // green - assert_eq!(HexAssignments { footfall: B, landtype: A, urbanized: B }, data.assignments(poi_no_data_built_not_urbanized)?); - assert_eq!(HexAssignments { footfall: B, landtype: B, urbanized: B }, data.assignments(poi_no_data_grass_not_urbanized)?); - assert_eq!(HexAssignments { footfall: B, landtype: C, urbanized: B }, data.assignments(poi_no_data_water_not_urbanized)?); - // light blue - assert_eq!(HexAssignments { footfall: C, landtype: A, urbanized: A }, data.assignments(no_poi_built_urbanized)?); - assert_eq!(HexAssignments { footfall: C, landtype: B, urbanized: A }, data.assignments(no_poi_grass_urbanized)?); - assert_eq!(HexAssignments { footfall: C, landtype: C, urbanized: A }, data.assignments(no_poi_water_urbanized)?); - // dark blue - assert_eq!(HexAssignments { footfall: C, landtype: A, urbanized: B }, data.assignments(no_poi_built_not_urbanized)?); - assert_eq!(HexAssignments { footfall: C, landtype: B, urbanized: B }, data.assignments(no_poi_grass_not_urbanized)?); - assert_eq!(HexAssignments { footfall: C, landtype: C, urbanized: B }, data.assignments(no_poi_water_not_urbanized)?); - // gray - assert_eq!(HexAssignments { footfall: A, landtype: A, urbanized: C }, data.assignments(poi_built_outside_us)?); - assert_eq!(HexAssignments { footfall: A, landtype: B, urbanized: C }, data.assignments(poi_grass_outside_us)?); - assert_eq!(HexAssignments { footfall: A, landtype: C, urbanized: C }, data.assignments(poi_water_outside_us)?); - assert_eq!(HexAssignments { footfall: B, landtype: A, urbanized: C }, data.assignments(poi_no_data_built_outside_us)?); - assert_eq!(HexAssignments { footfall: B, landtype: B, urbanized: C }, data.assignments(poi_no_data_grass_outside_us)?); - assert_eq!(HexAssignments { footfall: B, landtype: C, urbanized: C }, data.assignments(poi_no_data_water_outside_us)?); - assert_eq!(HexAssignments { footfall: C, landtype: A, urbanized: C }, data.assignments(no_poi_built_outside_us)?); - assert_eq!(HexAssignments { footfall: C, landtype: B, urbanized: C }, data.assignments(no_poi_grass_outside_us)?); - assert_eq!(HexAssignments { footfall: C, landtype: C, urbanized: C }, data.assignments(no_poi_water_outside_us)?); - // never inserted - assert_eq!(HexAssignments { footfall: C, landtype: C, urbanized: C }, data.assignments(unknown_cell)?); - }; - - Ok(()) - } -} diff --git a/mobile_verifier/src/cli/verify_disktree.rs b/mobile_verifier/src/cli/verify_disktree.rs index 621b24ad2..ae0204d40 100644 --- a/mobile_verifier/src/cli/verify_disktree.rs +++ b/mobile_verifier/src/cli/verify_disktree.rs @@ -2,10 +2,9 @@ use std::{collections::HashMap, path::PathBuf}; use hextree::disktree::DiskTreeMap; -use crate::{ - boosting_oracles::{landtype::LandtypeValue, Assignment}, - Settings, -}; +use hex_assignments::{landtype::LandtypeValue, Assignment}; + +use crate::Settings; #[derive(Debug, clap::Args)] pub struct Cmd { diff --git a/mobile_verifier/src/coverage.rs b/mobile_verifier/src/coverage.rs index 11dfe7d88..8489a441f 100644 --- a/mobile_verifier/src/coverage.rs +++ b/mobile_verifier/src/coverage.rs @@ -1,5 +1,4 @@ use crate::{ - boosting_oracles::assignment::HexAssignments, heartbeats::{HbType, KeyType, OwnedKeyType}, IsAuthorized, Settings, }; @@ -23,6 +22,7 @@ use helium_proto::services::{ mobile_config::NetworkKeyRole, poc_mobile::{self as proto, CoverageObjectValidity, SignalLevel as SignalLevelProto}, }; +use hex_assignments::assignment::HexAssignments; use hextree::Cell; use mobile_config::{ boosted_hex_info::{BoostedHex, BoostedHexes}, diff --git a/mobile_verifier/src/reward_shares.rs b/mobile_verifier/src/reward_shares.rs index b4ddcca62..0fab60ef8 100644 --- a/mobile_verifier/src/reward_shares.rs +++ b/mobile_verifier/src/reward_shares.rs @@ -696,8 +696,9 @@ pub fn get_scheduled_tokens_for_oracles(duration: Duration) -> Decimal { #[cfg(test)] mod test { use super::*; + use hex_assignments::assignment::HexAssignments; + use crate::{ - boosting_oracles::assignment::HexAssignments, cell_type::CellType, coverage::{CoveredHexStream, HexCoverage, Seniority}, data_session::{self, HotspotDataSession, HotspotReward}, diff --git a/mobile_verifier/tests/integrations/boosting_oracles.rs b/mobile_verifier/tests/integrations/boosting_oracles.rs index 3f791d2cc..e56a5afa9 100644 --- a/mobile_verifier/tests/integrations/boosting_oracles.rs +++ b/mobile_verifier/tests/integrations/boosting_oracles.rs @@ -11,9 +11,10 @@ use helium_crypto::PublicKeyBinary; use helium_proto::services::poc_mobile::{ CoverageObjectValidity, OracleBoostingHexAssignment, SignalLevel, }; +use hex_assignments::{Assignment, HexBoostData}; use mobile_config::boosted_hex_info::BoostedHexes; + use mobile_verifier::{ - boosting_oracles::{Assignment, HexBoostData}, coverage::{CoverageClaimTimeCache, CoverageObject, CoverageObjectCache, Seniority}, geofence::GeofenceValidator, heartbeats::{Heartbeat, HeartbeatReward, LocationCache, SeniorityUpdate, ValidatedHeartbeat}, @@ -140,7 +141,7 @@ async fn test_footfall_and_urbanization_report(pool: PgPool) -> anyhow::Result<( let hexes = { // NOTE(mj): Cell is mutated in constructor to keep elements aligned for readability let mut cell = CellIndex::try_from(0x8c2681a3064d9ff)?; - use Assignment::*; + use hex_assignments::Assignment::*; vec![ // yellow - POI ≥ 1 Urbanized new_hex_assingment(&mut cell, A, A, A, 1000), @@ -260,7 +261,7 @@ async fn test_footfall_and_urbanization_and_landtype(pool: PgPool) -> anyhow::Re let hexes = { // NOTE(mj): Cell is mutated in constructor to keep elements aligned for readability let mut cell = CellIndex::try_from(0x8c2681a3064d9ff)?; - use Assignment::*; + use hex_assignments::Assignment::*; vec![ // yellow - POI ≥ 1 Urbanized TestHex::new(&mut cell, A, A, A, 400), diff --git a/mobile_verifier/tests/integrations/common/mod.rs b/mobile_verifier/tests/integrations/common/mod.rs index 5722f6a7a..9195ad00a 100644 --- a/mobile_verifier/tests/integrations/common/mod.rs +++ b/mobile_verifier/tests/integrations/common/mod.rs @@ -12,13 +12,13 @@ use helium_proto::{ }, Message, }; +use hex_assignments::{Assignment, HexAssignment, HexBoostData}; use mobile_config::{ boosted_hex_info::{BoostedHexInfo, BoostedHexInfoStream}, client::{hex_boosting_client::HexBoostingInfoResolver, ClientError}, }; -use mobile_verifier::boosting_oracles::{ - AssignedCoverageObjects, Assignment, HexAssignment, HexBoostData, -}; + +use mobile_verifier::boosting_oracles::AssignedCoverageObjects; use rust_decimal::prelude::ToPrimitive; use rust_decimal_macros::dec; use sqlx::PgPool; From d6a02bf47e6e0d0904b126eab3ff359756796361 Mon Sep 17 00:00:00 2001 From: Anatolii Kurotych Date: Fri, 24 May 2024 12:14:46 +0300 Subject: [PATCH 2/6] Fix fmt --- hex_assignments/src/lib.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hex_assignments/src/lib.rs b/hex_assignments/src/lib.rs index 7c7c6f156..0eb2c4299 100644 --- a/hex_assignments/src/lib.rs +++ b/hex_assignments/src/lib.rs @@ -5,8 +5,8 @@ pub mod urbanization; use std::collections::HashMap; -use assignment::HexAssignments; pub use assignment::Assignment; +use assignment::HexAssignments; pub trait HexAssignment: Send + Sync + 'static { fn assignment(&self, cell: hextree::Cell) -> anyhow::Result; @@ -268,4 +268,3 @@ mod tests { Ok(()) } } - From 3054ebdeb2fc98d8dc00e86b1a1476341a1cd329 Mon Sep 17 00:00:00 2001 From: Anatolii Kurotych Date: Fri, 24 May 2024 12:35:40 +0300 Subject: [PATCH 3/6] Add HexBoostDataAssignments trait --- Cargo.lock | 16 ++++++++++++++++ hex_assignments/src/lib.rs | 8 ++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 35c5bea7c..43726fc94 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3495,6 +3495,21 @@ dependencies = [ "serde", ] +[[package]] +name = "hex-assignments" +version = "0.1.0" +dependencies = [ + "anyhow", + "async-trait", + "chrono", + "derive_builder", + "helium-proto", + "hextree", + "rust_decimal", + "rust_decimal_macros", + "sqlx", +] + [[package]] name = "hex-literal" version = "0.3.4" @@ -4712,6 +4727,7 @@ dependencies = [ "h3o", "helium-crypto", "helium-proto", + "hex-assignments", "hextree", "http-serde", "humantime", diff --git a/hex_assignments/src/lib.rs b/hex_assignments/src/lib.rs index 0eb2c4299..20d15b2b3 100644 --- a/hex_assignments/src/lib.rs +++ b/hex_assignments/src/lib.rs @@ -24,6 +24,10 @@ impl HexAssignment for Assignment { } } +pub trait HexBoostDataAssignments: Send + Sync + 'static { + fn assignments(&self, cell: hextree::Cell) -> anyhow::Result; +} + #[derive(derive_builder::Builder)] #[builder(pattern = "owned")] pub struct HexBoostData { @@ -37,13 +41,13 @@ impl HexBoostData { } } -impl HexBoostData +impl HexBoostDataAssignments for HexBoostData where Foot: HexAssignment, Land: HexAssignment, Urban: HexAssignment, { - pub fn assignments(&self, cell: hextree::Cell) -> anyhow::Result { + fn assignments(&self, cell: hextree::Cell) -> anyhow::Result { HexAssignments::builder(cell) .footfall(&self.footfall) .landtype(&self.landtype) From 86d651b57ac31be3a843e3eb705173aefb5b3646 Mon Sep 17 00:00:00 2001 From: Anatolii Kurotych Date: Fri, 24 May 2024 14:31:10 +0300 Subject: [PATCH 4/6] Remove HexAssignments::test_best --- hex_assignments/src/assignment.rs | 10 ---------- mobile_verifier/src/coverage.rs | 29 ++++++++++++++++++---------- mobile_verifier/src/reward_shares.rs | 14 +++++++++++--- 3 files changed, 30 insertions(+), 23 deletions(-) diff --git a/hex_assignments/src/assignment.rs b/hex_assignments/src/assignment.rs index a067a72ff..90a99d990 100644 --- a/hex_assignments/src/assignment.rs +++ b/hex_assignments/src/assignment.rs @@ -149,13 +149,3 @@ impl HexAssignmentsBuilder { }) } } - -impl HexAssignments { - pub fn test_best() -> Self { - Self { - footfall: Assignment::A, - urbanized: Assignment::A, - landtype: Assignment::A, - } - } -} diff --git a/mobile_verifier/src/coverage.rs b/mobile_verifier/src/coverage.rs index 8489a441f..3da4e98b4 100644 --- a/mobile_verifier/src/coverage.rs +++ b/mobile_verifier/src/coverage.rs @@ -962,8 +962,17 @@ mod test { use super::*; use chrono::NaiveDate; use futures::stream::iter; + use hex_assignments::Assignment; use hextree::Cell; + fn hex_assignments_mock() -> HexAssignments { + HexAssignments { + footfall: Assignment::A, + urbanized: Assignment::A, + landtype: Assignment::A, + } + } + /// Test to ensure that if there are multiple radios with different signal levels /// in a given hex, that the one with the highest signal level is chosen. #[tokio::test] @@ -997,7 +1006,7 @@ mod test { points: CoverageRewardPoints { coverage_points: dec!(100), boost_multiplier: NonZeroU32::new(1).unwrap(), - hex_assignments: HexAssignments::test_best(), + hex_assignments: hex_assignments_mock(), rank: None }, boosted_hex_info: BoostedHex { @@ -1031,7 +1040,7 @@ mod test { signal_power: 0, coverage_claim_time, inserted_at: DateTime::::MIN_UTC, - assignments: HexAssignments::test_best(), + assignments: hex_assignments_mock(), } } @@ -1113,7 +1122,7 @@ mod test { points: CoverageRewardPoints { coverage_points: dec!(100), boost_multiplier: NonZeroU32::new(1).unwrap(), - hex_assignments: HexAssignments::test_best(), + hex_assignments: hex_assignments_mock(), rank: None }, boosted_hex_info: BoostedHex { @@ -1157,7 +1166,7 @@ mod test { coverage_points: dec!(4), rank: Some(dec!(1.0)), boost_multiplier: NonZeroU32::new(1).unwrap(), - hex_assignments: HexAssignments::test_best(), + hex_assignments: hex_assignments_mock(), }, boosted_hex_info: BoostedHex { location: Cell::from_raw(0x8a1fb46622dffff).expect("valid h3 cell"), @@ -1171,7 +1180,7 @@ mod test { coverage_points: dec!(4), rank: Some(dec!(0.50)), boost_multiplier: NonZeroU32::new(1).unwrap(), - hex_assignments: HexAssignments::test_best(), + hex_assignments: hex_assignments_mock(), }, boosted_hex_info: BoostedHex { location: Cell::from_raw(0x8a1fb46622dffff).expect("valid h3 cell"), @@ -1185,7 +1194,7 @@ mod test { coverage_points: dec!(4), rank: Some(dec!(0.25)), boost_multiplier: NonZeroU32::new(1).unwrap(), - hex_assignments: HexAssignments::test_best(), + hex_assignments: hex_assignments_mock(), }, boosted_hex_info: BoostedHex { location: Cell::from_raw(0x8a1fb46622dffff).expect("valid h3 cell"), @@ -1456,7 +1465,7 @@ mod test { signal_power: 0, coverage_claim_time: coverage_claim_time.unwrap_or(DateTime::::MIN_UTC), inserted_at: DateTime::::MIN_UTC, - assignments: HexAssignments::test_best(), + assignments: hex_assignments_mock(), } } @@ -1474,7 +1483,7 @@ mod test { signal_level: SignalLevel::High, coverage_claim_time, inserted_at: DateTime::::MIN_UTC, - assignments: HexAssignments::test_best(), + assignments: hex_assignments_mock(), } } @@ -1492,7 +1501,7 @@ mod test { signal_level: SignalLevel::High, coverage_claim_time, inserted_at: DateTime::::MIN_UTC, - assignments: HexAssignments::test_best(), + assignments: hex_assignments_mock(), } } @@ -1510,7 +1519,7 @@ mod test { signal_level, coverage_claim_time, inserted_at: DateTime::::MIN_UTC, - assignments: HexAssignments::test_best(), + assignments: hex_assignments_mock(), } } } diff --git a/mobile_verifier/src/reward_shares.rs b/mobile_verifier/src/reward_shares.rs index 0fab60ef8..632df340e 100644 --- a/mobile_verifier/src/reward_shares.rs +++ b/mobile_verifier/src/reward_shares.rs @@ -696,7 +696,7 @@ pub fn get_scheduled_tokens_for_oracles(duration: Duration) -> Decimal { #[cfg(test)] mod test { use super::*; - use hex_assignments::assignment::HexAssignments; + use hex_assignments::{assignment::HexAssignments, Assignment}; use crate::{ cell_type::CellType, @@ -719,6 +719,14 @@ mod test { use std::collections::HashMap; use uuid::Uuid; + fn hex_assignments_mock() -> HexAssignments { + HexAssignments { + footfall: Assignment::A, + urbanized: Assignment::A, + landtype: Assignment::A, + } + } + #[test] fn ensure_correct_conversion_of_bytes_to_bones() { assert_eq!( @@ -1007,7 +1015,7 @@ mod test { signal_power: 0, coverage_claim_time: DateTime::::MIN_UTC, inserted_at: DateTime::::MIN_UTC, - assignments: HexAssignments::test_best(), + assignments: hex_assignments_mock(), }] } @@ -1890,7 +1898,7 @@ mod test { coverage_points: CoverageRewardPoints { boost_multiplier: NonZeroU32::new(1).unwrap(), coverage_points: dec!(10.0), - hex_assignments: HexAssignments::test_best(), + hex_assignments: hex_assignments_mock(), rank: None, }, boosted_hex: BoostedHex { From f2d3d72c334a06dbb8eea2dfc763904a4e24e90c Mon Sep 17 00:00:00 2001 From: Anatolii Kurotych Date: Fri, 24 May 2024 14:37:48 +0300 Subject: [PATCH 5/6] Remove new_mock use optional parameter in new --- hex_assignments/src/footfall.rs | 13 +++---------- hex_assignments/src/landtype.rs | 13 +++---------- hex_assignments/src/lib.rs | 6 +++--- hex_assignments/src/urbanization.rs | 13 +++---------- mobile_verifier/src/boosting_oracles/data_sets.rs | 6 +++--- 5 files changed, 15 insertions(+), 36 deletions(-) diff --git a/hex_assignments/src/footfall.rs b/hex_assignments/src/footfall.rs index bd9ece9e0..be092800e 100644 --- a/hex_assignments/src/footfall.rs +++ b/hex_assignments/src/footfall.rs @@ -9,16 +9,9 @@ pub struct Footfall { } impl Footfall { - pub fn new() -> Self { + pub fn new(footfall: Option) -> Self { Self { - footfall: None, - timestamp: None, - } - } - - pub fn new_mock(footfall: DiskTreeMap) -> Self { - Self { - footfall: Some(footfall), + footfall, timestamp: None, } } @@ -26,7 +19,7 @@ impl Footfall { impl Default for Footfall { fn default() -> Self { - Self::new() + Self::new(None) } } diff --git a/hex_assignments/src/landtype.rs b/hex_assignments/src/landtype.rs index 533bb6f21..29ba9b645 100644 --- a/hex_assignments/src/landtype.rs +++ b/hex_assignments/src/landtype.rs @@ -9,16 +9,9 @@ pub struct Landtype { } impl Landtype { - pub fn new() -> Self { + pub fn new(landtype: Option) -> Self { Self { - landtype: None, - timestamp: None, - } - } - - pub fn new_mock(landtype: DiskTreeMap) -> Self { - Self { - landtype: Some(landtype), + landtype, timestamp: None, } } @@ -26,7 +19,7 @@ impl Landtype { impl Default for Landtype { fn default() -> Self { - Self::new() + Self::new(None) } } diff --git a/hex_assignments/src/lib.rs b/hex_assignments/src/lib.rs index 20d15b2b3..da87d9e5d 100644 --- a/hex_assignments/src/lib.rs +++ b/hex_assignments/src/lib.rs @@ -214,9 +214,9 @@ mod tests { footfall.to_disktree(Cursor::new(&mut footfall_buff), |w, v| w.write_all(&[*v]))?; landtype.to_disktree(Cursor::new(&mut landtype_buf), |w, v| w.write_all(&[*v]))?; - let footfall = Footfall::new_mock(DiskTreeMap::with_buf(footfall_buff)?); - let landtype = Landtype::new_mock(DiskTreeMap::with_buf(landtype_buf)?); - let urbanization = Urbanization::new_mock(DiskTreeMap::with_buf(urbanized_buf)?); + let footfall = Footfall::new(Some(DiskTreeMap::with_buf(footfall_buff)?)); + let landtype = Landtype::new(Some(DiskTreeMap::with_buf(landtype_buf)?)); + let urbanization = Urbanization::new(Some(DiskTreeMap::with_buf(urbanized_buf)?)); // Let the testing commence let data = HexBoostData::builder() diff --git a/hex_assignments/src/urbanization.rs b/hex_assignments/src/urbanization.rs index c4a2c0943..2cc2ca79f 100644 --- a/hex_assignments/src/urbanization.rs +++ b/hex_assignments/src/urbanization.rs @@ -9,16 +9,9 @@ pub struct Urbanization { } impl Urbanization { - pub fn new() -> Self { + pub fn new(urbanized: Option) -> Self { Self { - urbanized: None, - timestamp: None, - } - } - - pub fn new_mock(urbanized: DiskTreeMap) -> Self { - Self { - urbanized: Some(urbanized), + urbanized, timestamp: None, } } @@ -26,7 +19,7 @@ impl Urbanization { impl Default for Urbanization { fn default() -> Self { - Self::new() + Self::new(None) } } diff --git a/mobile_verifier/src/boosting_oracles/data_sets.rs b/mobile_verifier/src/boosting_oracles/data_sets.rs index 2a3034383..e0065e055 100644 --- a/mobile_verifier/src/boosting_oracles/data_sets.rs +++ b/mobile_verifier/src/boosting_oracles/data_sets.rs @@ -262,9 +262,9 @@ impl DataSetDownloaderDaemon { .create() .await?; - let urbanization = Urbanization::new(); - let footfall = Footfall::new(); - let landtype = Landtype::new(); + let urbanization = Urbanization::new(None); + let footfall = Footfall::new(None); + let landtype = Landtype::new(None); let hex_boost_data = HexBoostData::builder() .footfall(footfall) .landtype(landtype) From e1cc722ee6df88876fcfc7ae311ac6293a2dc696 Mon Sep 17 00:00:00 2001 From: Anatolii Kurotych Date: Tue, 28 May 2024 19:47:38 +0300 Subject: [PATCH 6/6] Format Cargo.toml --- hex_assignments/Cargo.toml | 8 ++++---- mobile_verifier/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/hex_assignments/Cargo.toml b/hex_assignments/Cargo.toml index a76526058..a37e15b67 100644 --- a/hex_assignments/Cargo.toml +++ b/hex_assignments/Cargo.toml @@ -9,10 +9,10 @@ license.workspace = true [dependencies] anyhow = { workspace = true } hextree = { workspace = true } -sqlx = {version = "*", features = ["runtime-tokio-rustls"]} -rust_decimal = { workspace = true} -rust_decimal_macros = { workspace = true} -helium-proto = {workspace = true} +sqlx = { version = "*", features = ["runtime-tokio-rustls"] } +rust_decimal = { workspace = true } +rust_decimal_macros = { workspace = true } +helium-proto = { workspace = true } async-trait = { workspace = true } chrono = { workspace = true } derive_builder = { workspace = true } diff --git a/mobile_verifier/Cargo.toml b/mobile_verifier/Cargo.toml index 5760b0459..75d86b1ec 100644 --- a/mobile_verifier/Cargo.toml +++ b/mobile_verifier/Cargo.toml @@ -57,7 +57,7 @@ derive_builder = { workspace = true } regex = "1" humantime-serde = { workspace = true } custom-tracing = { path = "../custom_tracing" } -hex-assignments = {path = "../hex_assignments"} +hex-assignments = { path = "../hex_assignments" } [dev-dependencies] backon = "0"