From ad7ab9392a2a8c84a82b8de4b61e4299081429f2 Mon Sep 17 00:00:00 2001 From: Frank Elsinga Date: Mon, 10 Apr 2023 15:21:01 +0200 Subject: [PATCH] implemented editing coordinates --- ...540x_chemie.yaml => 5400-5409_chemie.yaml} | 0 .../{550x-551x_mw.yaml => 5500-5519_mw.yaml} | 0 .../feedback/src/proposed_edits/coordinate.rs | 80 ++++++++++++++++++- 3 files changed, 79 insertions(+), 1 deletion(-) rename data/sources/coordinates/{540x_chemie.yaml => 5400-5409_chemie.yaml} (100%) rename data/sources/coordinates/{550x-551x_mw.yaml => 5500-5519_mw.yaml} (100%) diff --git a/data/sources/coordinates/540x_chemie.yaml b/data/sources/coordinates/5400-5409_chemie.yaml similarity index 100% rename from data/sources/coordinates/540x_chemie.yaml rename to data/sources/coordinates/5400-5409_chemie.yaml diff --git a/data/sources/coordinates/550x-551x_mw.yaml b/data/sources/coordinates/5500-5519_mw.yaml similarity index 100% rename from data/sources/coordinates/550x-551x_mw.yaml rename to data/sources/coordinates/5500-5519_mw.yaml diff --git a/server/feedback/src/proposed_edits/coordinate.rs b/server/feedback/src/proposed_edits/coordinate.rs index 3d800bc65..fb008522c 100644 --- a/server/feedback/src/proposed_edits/coordinate.rs +++ b/server/feedback/src/proposed_edits/coordinate.rs @@ -1,6 +1,34 @@ use crate::proposed_edits::AppliableEdit; use serde::Deserialize; -use std::path::Path; +use std::ops::Range; +use std::path::{Path, PathBuf}; + +struct CoordinateFile { + path: PathBuf, +} + +impl CoordinateFile { + fn from(path: PathBuf) -> Self { + Self { path } + } + fn matches(&self) -> Range { + let name = self.path.file_name().unwrap().to_str().unwrap(); + match name.split('_').next() { + Some(prefix) => { + let range = prefix + .split('-') + .map(|s| s.parse::().unwrap()) + .collect::>(); + match range.len() { + 1 => range[0]..range[0], + 2 => range[0]..range[1], + _ => panic!("Invalid range: {:?}", range), + } + } + None => 0..99999, + } + } +} #[derive(Deserialize, Clone)] pub struct Coordinate { @@ -8,8 +36,58 @@ pub struct Coordinate { lon: f64, } +impl Coordinate { + fn best_matching_file(&self, key: &str, base_dir: &Path) -> PathBuf { + let coord_dir = base_dir.join("data").join("sources").join("coordinate"); + let filenames = std::fs::read_dir(coord_dir) + .unwrap() + .map(|res| res.map(|e| e.path())) + .filter_map(|res| res.ok()) + .map(CoordinateFile::from); + let best_match = filenames + .filter(|co| co.matches().contains(&key.parse::().unwrap())) + .min_by_key(|f| { + let Range { start, end } = f.matches(); + end - start + }) + .expect("No matching file found"); + best_match.path + } +} impl AppliableEdit for Coordinate { fn apply(&self, key: &str, base_dir: &Path) -> String { + let file = self.best_matching_file(key, base_dir); + let content = std::fs::read_to_string(file.clone()).unwrap(); + let mut lines = content.lines().collect::>(); + let pos_of_line_to_edit = lines + .iter() + .position(|l| l.starts_with(&format!("\"{key}\": "))); + let mut new_line = format!( + "\"{key}\": {{ lat: {lat}, lon: {lon} }}", + lat = self.lat, + lon = self.lon, + ); + match pos_of_line_to_edit { + Some(pos) => { + if lines[pos].contains('#') { + new_line += " #"; + new_line += lines[pos].split('#').last().unwrap(); + } + lines[pos] = &new_line; + } + None => { + //we need to insert a new line at a fitting position + let pos_of_line_to_insert = lines + .iter() + .position(|l| { + let key_at_pos = l.split("\":").next().unwrap().strip_prefix('"').unwrap(); + key_at_pos > key + }) + .unwrap_or(lines.len()); + lines.insert(pos_of_line_to_insert, &new_line) + } + } + std::fs::write(file.as_path(), lines.join("\n")).unwrap(); format!( "https://nav.tum.de/api/preview_edit/{k}?to_lat={lat}&to_lon={lon}", k = key,