use crate::{helpers, io::SupportingFileExts};
use serde::Deserialize;
use std::{fmt, fmt::Display, path::Path};
mod raw;
#[derive(Debug, Deserialize)]
#[serde(from = "raw::Config")]
pub struct Config {
pub parser: parser::Config,
pub generator: Option<generator::Config>,
pub routing: Option<routing::Config>,
}
impl SupportingFileExts for Config {
fn supported_exts<'a>() -> &'a [&'a str] {
&["yaml"]
}
}
impl Config {
pub fn from_yaml<P: AsRef<Path> + ?Sized>(path: &P) -> Result<Config, String> {
let file = {
Config::find_supported_ext(path)?;
helpers::open_file(path)?
};
match serde_yaml::from_reader(file) {
Ok(cfg) => Ok(cfg),
Err(msg) => Err(format!("{}", msg)),
}
}
}
pub mod parser {
pub use edges::Category as EdgeCategory;
pub use nodes::Category as NodeCategory;
use std::path::PathBuf;
#[derive(Debug)]
pub struct Config {
pub map_file: PathBuf,
pub vehicles: vehicles::Config,
pub nodes: nodes::Config,
pub edges: edges::Config,
}
pub mod vehicles {
use crate::network::VehicleCategory;
#[derive(Debug)]
pub struct Config {
pub category: VehicleCategory,
pub are_drivers_picky: bool,
}
}
pub mod nodes {
use serde::Deserialize;
#[derive(Copy, Clone, Debug, Deserialize, Eq, PartialEq)]
pub enum Category {
NodeId,
Latitude,
Longitude,
Level,
Ignore,
}
#[derive(Debug)]
pub struct Config {
categories: Vec<Category>,
}
impl Config {
pub fn new(categories: Vec<Category>) -> Config {
Config { categories }
}
pub fn categories(&self) -> &Vec<Category> {
&self.categories
}
}
}
pub mod edges {
use crate::{configs::SimpleId, defaults::capacity::DimVec, network::MetricIdx};
use serde::Deserialize;
use smallvec::smallvec;
use std::{
collections::BTreeMap,
fmt::{self, Display},
};
#[derive(Debug)]
pub struct Config {
edge_categories: Vec<Category>,
edge_ids: Vec<SimpleId>,
metric_categories: DimVec<Category>,
are_metrics_provided: DimVec<bool>,
metric_ids: DimVec<SimpleId>,
metric_indices: BTreeMap<SimpleId, MetricIdx>,
calc_rules: DimVec<DimVec<(Category, MetricIdx)>>,
}
impl Config {
pub fn new(
edge_categories: Vec<Category>,
edge_ids: Vec<SimpleId>,
metric_categories: DimVec<Category>,
are_metrics_provided: DimVec<bool>,
metric_ids: DimVec<SimpleId>,
metric_indices: BTreeMap<SimpleId, MetricIdx>,
calc_rules: DimVec<DimVec<(Category, MetricIdx)>>,
) -> Config {
Config {
edge_categories,
edge_ids,
metric_categories,
are_metrics_provided,
metric_ids,
metric_indices,
calc_rules,
}
}
}
impl Config {
pub fn edge_categories(&self) -> &Vec<Category> {
&self.edge_categories
}
pub fn edge_category(&self, id: &SimpleId) -> &Category {
match self.edge_ids.iter().position(|i| i == id) {
Some(idx) => &self.edge_categories[idx],
None => {
if id == &SimpleId(format!("{}", Category::Ignore)) {
&Category::Ignore
} else {
panic!("Id {} not found in config.", id);
}
}
}
}
pub fn metric_category(&self, idx: MetricIdx) -> Category {
match self.metric_categories.get(*idx) {
Some(metric_category) => *metric_category,
None => {
panic!("Idx {} for metric-category not found in config.", idx);
}
}
}
pub fn dim(&self) -> usize {
self.metric_categories.len()
}
pub fn is_metric_provided(&self, idx: MetricIdx) -> bool {
match self.are_metrics_provided.get(*idx) {
Some(is_provided) => *is_provided,
None => {
panic!("Idx {} for info 'is-provided' not found in config.", idx);
}
}
}
pub fn metric_idx(&self, id: &SimpleId) -> MetricIdx {
match self.metric_indices.get(id) {
Some(idx) => *idx,
None => {
panic!("Id {} not found in config.", id);
}
}
}
pub fn calc_rules(&self, idx: MetricIdx) -> &DimVec<(Category, MetricIdx)> {
match self.calc_rules.get(*idx) {
Some(calc_rule) => calc_rule,
None => {
panic!("Idx {} for calc-rule not found in config.", idx);
}
}
}
}
#[derive(Copy, Clone, Debug, Deserialize, Eq, PartialEq)]
pub enum Category {
Meters,
KilometersPerHour,
Seconds,
LaneCount,
Custom,
ShortcutEdgeIdx,
SrcId,
#[serde(rename = "Ignore - SrcIdx")]
IgnoredSrcIdx,
DstId,
#[serde(rename = "Ignore - DstIdx")]
IgnoredDstIdx,
Ignore,
}
impl Display for Category {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(self, f)
}
}
impl Category {
pub fn must_be_positive(&self) -> bool {
match self {
Category::Meters
| Category::KilometersPerHour
| Category::Seconds
| Category::LaneCount => true,
Category::Custom
| Category::ShortcutEdgeIdx
| Category::SrcId
| Category::IgnoredSrcIdx
| Category::DstId
| Category::IgnoredDstIdx
| Category::Ignore => false,
}
}
pub fn is_metric(&self) -> bool {
match self {
Category::SrcId
| Category::DstId
| Category::IgnoredSrcIdx
| Category::IgnoredDstIdx
| Category::ShortcutEdgeIdx
| Category::Ignore => false,
Category::Meters
| Category::KilometersPerHour
| Category::Seconds
| Category::LaneCount
| Category::Custom => true,
}
}
pub fn expected_calc_rules(&self) -> DimVec<Category> {
match self {
Category::KilometersPerHour => smallvec![Category::Meters, Category::Seconds],
Category::Seconds => smallvec![Category::Meters, Category::KilometersPerHour],
Category::Meters
| Category::LaneCount
| Category::Custom
| Category::ShortcutEdgeIdx
| Category::SrcId
| Category::IgnoredSrcIdx
| Category::DstId
| Category::IgnoredDstIdx
| Category::Ignore => smallvec![],
}
}
}
}
}
pub mod generator {
use super::SimpleId;
pub use edges::Category as EdgeCategory;
pub use nodes::Category as NodeCategory;
use std::path::PathBuf;
pub mod nodes {
use serde::Deserialize;
#[derive(Copy, Clone, Debug, Deserialize, Eq, PartialEq)]
pub enum Category {
NodeId,
NodeIdx,
Latitude,
Longitude,
Level,
Ignore,
}
}
pub mod edges {
use serde::Deserialize;
#[derive(Copy, Clone, Debug, Deserialize, Eq, PartialEq)]
pub enum Category {
Meters,
KilometersPerHour,
Seconds,
LaneCount,
Custom,
SrcId,
SrcIdx,
DstId,
DstIdx,
Ignore,
}
}
#[derive(Debug)]
pub struct Config {
pub map_file: PathBuf,
pub nodes: Vec<NodeCategory>,
pub edges: Vec<SimpleId>,
}
}
pub mod routing {
use crate::{
defaults::{self, capacity::DimVec},
network::MetricIdx,
};
#[derive(Clone, Debug)]
pub struct Config {
is_ch_dijkstra: bool,
metric_indices: DimVec<MetricIdx>,
alphas: DimVec<f64>,
}
impl Config {
fn _push(&mut self, idx: MetricIdx, alpha: f64) {
self.metric_indices.push(idx);
self.alphas.push(alpha);
}
pub fn is_ch_dijkstra(&self) -> bool {
self.is_ch_dijkstra
}
pub fn set_ch_dijkstra(&mut self, is_ch_dijkstra: bool) {
self.is_ch_dijkstra = is_ch_dijkstra
}
pub fn alpha(&self, metric_idx: MetricIdx) -> f64 {
let idx = match self.metric_indices.iter().position(|i| i == &metric_idx) {
Some(idx) => idx,
None => {
panic!("Idx {} not found in config.", metric_idx);
}
};
self.alphas[idx]
}
pub fn alphas(&self) -> &DimVec<f64> {
&self.alphas
}
pub fn metric_indices(&self) -> &DimVec<MetricIdx> {
&self.metric_indices
}
pub fn dim(&self) -> usize {
self.metric_indices.len()
}
pub fn from_str(
yaml_str: &str,
cfg_graph: &super::parser::Config,
) -> Result<Config, String> {
let raw_cfg = super::raw::routing::Config::from_str(yaml_str)?;
Ok(Config::from_raw(raw_cfg, cfg_graph))
}
pub fn from_raw(
raw_cfg: super::raw::routing::Config,
cfg_parser: &super::parser::Config,
) -> Config {
let (metric_indices, alphas) = raw_cfg
.metrics
.into_iter()
.map(|entry| {
(
cfg_parser.edges.metric_idx(&entry.id),
entry.alpha.unwrap_or(defaults::routing::ALPHA),
)
})
.unzip();
Config {
is_ch_dijkstra: raw_cfg.is_ch_dijkstra.unwrap_or(false),
metric_indices,
alphas,
}
}
}
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Ord, PartialOrd)]
#[serde(from = "String")]
pub struct SimpleId(pub String);
impl From<String> for SimpleId {
fn from(id: String) -> SimpleId {
SimpleId(id)
}
}
impl From<&str> for SimpleId {
fn from(id: &str) -> SimpleId {
SimpleId(id.to_owned())
}
}
impl Display for SimpleId {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}