Skip to content

Commit

Permalink
Refactor element issue pipeline
Browse files Browse the repository at this point in the history
  • Loading branch information
bubelov committed Aug 28, 2024
1 parent 3143b12 commit e085b63
Show file tree
Hide file tree
Showing 6 changed files with 176 additions and 253 deletions.
10 changes: 0 additions & 10 deletions src/command/lint.rs

This file was deleted.

1 change: 0 additions & 1 deletion src/command/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ pub mod generate_android_icons;
pub mod generate_element_categories;
pub mod generate_reports;
pub mod import_countries;
pub mod lint;
pub mod remove_areas_tag;
pub mod sync;
pub mod trending_areas;
Expand Down
5 changes: 2 additions & 3 deletions src/command/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use crate::discord;
use crate::element;
use crate::element::Element;
use crate::event::Event;
use crate::lint;
use crate::osm::osm;
use crate::osm::overpass::query_bitcoin_merchants;
use crate::osm::overpass::OverpassElement;
Expand Down Expand Up @@ -195,7 +194,7 @@ async fn process_elements(fresh_elements: Vec<OverpassElement>, mut db: Connecti
)?;
}

lint::generate_element_issues(&updated_element, &tx)?;
element::service::generate_issues(vec![&updated_element], &tx)?;
element::service::update_areas_tag(&vec![updated_element], &tx)?;
}

Expand Down Expand Up @@ -235,7 +234,7 @@ async fn process_elements(fresh_elements: Vec<OverpassElement>, mut db: Connecti

info!(category, android_icon);

lint::generate_element_issues(&element, &tx)?;
element::service::generate_issues(vec![&element], &tx)?;
element::service::update_areas_tag(&vec![element], &tx)?;

let message = format!("User {user_display_name} added https://www.openstreetmap.org/{element_type}/{osm_id}");
Expand Down
174 changes: 174 additions & 0 deletions src/element/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@ use geo::LineString;
use geo::MultiPolygon;
use geo::Polygon;
use rusqlite::Connection;
use serde::Deserialize;
use serde::Serialize;
use serde_json::json;
use serde_json::Value;
use time::macros::format_description;
use time::Date;
use tracing::info;

pub fn remove_areas_tag(area: &Area, conn: &mut Connection) -> Result<()> {
Expand Down Expand Up @@ -155,3 +159,173 @@ pub fn find_areas<'a>(element: &Element, areas: &'a Vec<Area>) -> Result<Vec<&'a

Ok(element_areas)
}

#[derive(Serialize, Deserialize)]
pub struct Issue {
pub r#type: String,
pub severity: i64,
pub description: String,
}

pub fn generate_issues(elements: Vec<&Element>, conn: &Connection) -> Result<()> {
for element in elements {
let issues = crate::element::service::get_issues(&element);
// No current issues, no saved issues, nothing to do here
if issues.is_empty() && !element.tags.contains_key("issues") {
return Ok(());
}
// No current issues found but an element has some old issues which need to be deleted
if issues.is_empty() && element.tags.contains_key("issues") {
Element::remove_tag(element.id, "issues", conn)?;
return Ok(());
}
let issues = serde_json::to_value(&issues)?;
// We should avoid toucing the elements if the issues didn't change
if element.tag("issues") != &issues {
Element::set_tag(element.id, "issues", &issues, conn)?;
}
}

Ok(())
}

fn get_issues(element: &Element) -> Vec<Issue> {
let mut res: Vec<Issue> = vec![];
res.append(&mut crate::element::service::get_date_format_issues(
element,
));
res.append(&mut crate::element::service::get_misspelled_tag_issues(
element,
));
if let Some(issue) = crate::element::service::get_missing_icon_issue(element) {
res.push(issue);
};
if let Some(issue) = crate::element::service::get_not_verified_issue(element) {
res.push(issue);
};
if let Some(issue) = crate::element::service::get_out_of_date_issue(element) {
res.push(issue);
} else {
if let Some(issue) = crate::element::service::get_soon_out_of_date_issue(element) {
res.push(issue);
};
};
res
}

fn get_date_format_issues(element: &Element) -> Vec<Issue> {
let mut res: Vec<Issue> = vec![];
let date_format = format_description!("[year]-[month]-[day]");
let survey_date = element.overpass_data.tag("survey:date");
if survey_date.len() > 0 && Date::parse(survey_date, &date_format).is_err() {
res.push(Issue {
r#type: "date_format".into(),
severity: 600,
description: "survey:date is not formatted properly".into(),
});
}
let check_date = element.overpass_data.tag("check_date");
if check_date.len() > 0 && Date::parse(check_date, &date_format).is_err() {
res.push(Issue {
r#type: "date_format".into(),
severity: 600,
description: "check_date is not formatted properly".into(),
});
}
let check_date_currency_xbt = element.overpass_data.tag("check_date:currency:XBT");
if check_date_currency_xbt.len() > 0
&& Date::parse(check_date_currency_xbt, &date_format).is_err()
{
res.push(Issue {
r#type: "date_format".into(),
severity: 600,
description: "check_date:currency:XBT is not formatted properly".into(),
});
}
res
}

fn get_misspelled_tag_issues(element: &Element) -> Vec<Issue> {
let mut res: Vec<Issue> = vec![];
let payment_lighting = element.overpass_data.tag("payment:lighting");
if payment_lighting.len() > 0 {
res.push(Issue {
r#type: "misspelled_tag".into(),
severity: 500,
description: "Spelling issue: payment:lighting".into(),
});
}
let payment_lightning_contacless = element.overpass_data.tag("payment:lightning_contacless");
if payment_lightning_contacless.len() > 0 {
res.push(Issue {
r#type: "misspelled_tag".into(),
severity: 500,
description: "Spelling issue: payment:lightning_contacless".into(),
});
}
let payment_lighting_contactless = element.overpass_data.tag("payment:lighting_contactless");
if payment_lighting_contactless.len() > 0 {
res.push(Issue {
r#type: "misspelled_tag".into(),
severity: 500,
description: "Spelling issue: payment:lighting_contactless".into(),
});
}
res
}

fn get_missing_icon_issue(element: &Element) -> Option<Issue> {
if element.tag("icon:android").as_str().unwrap_or_default() == ""
|| element.tag("icon:android").as_str().unwrap_or_default() == "question_mark"
{
return Some(Issue {
r#type: "missing_icon".into(),
severity: 400,
description: "Icon is missing".into(),
});
}

None
}

fn get_not_verified_issue(element: &Element) -> Option<Issue> {
if element.overpass_data.verification_date().is_none() {
return Some(Issue {
r#type: "not_verified".into(),
severity: 300,
description: "Not verified".into(),
});
}

None
}

fn get_out_of_date_issue(element: &Element) -> Option<Issue> {
if element.overpass_data.verification_date().is_some() && !element.overpass_data.up_to_date() {
return Some(Issue {
r#type: "out_of_date".into(),
severity: 200,
description: "Out of date".into(),
});
}

None
}

fn get_soon_out_of_date_issue(element: &Element) -> Option<Issue> {
if element.overpass_data.verification_date().is_some()
&& element
.overpass_data
.days_since_verified()
.map(|it| it > 365 - 90 && it < 365)
.is_some_and(|it| it)
{
return Some(Issue {
r#type: "out_of_date_soon".into(),
severity: 100,
description: "Soon to be outdated".into(),
});
}

None
}
Loading

0 comments on commit e085b63

Please sign in to comment.