Add craft and office to import and add/reorg AmenityType (#638)

* Add craft and office to import and add/reorg AmenityType

* Remove bike rental/parking and rename BikeShop to Bike

* add in leisure and tourism tags, add more categories to AmenityType and remove lesser used tags

* add dependency on strum and strum_macros and removed some manual code for text display of Enum and Enum into string

* include lock file, fix color of buildings for amenity layer, fix formatting and use orders
This commit is contained in:
Trevor Nederlof 2021-05-06 11:43:52 -04:00 committed by GitHub
parent c6e4b6147f
commit 4080d0d130
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 192 additions and 128 deletions

24
Cargo.lock generated
View File

@ -2331,6 +2331,8 @@ dependencies = [
"rand_xorshift",
"serde",
"serde_json",
"strum 0.20.0",
"strum_macros 0.20.1",
"thread_local",
"traffic_signal_data",
]
@ -3836,6 +3838,12 @@ version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57bd81eb48f4c437cadc685403cad539345bf703d78e63707418431cecd4522b"
[[package]]
name = "strum"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7318c509b5ba57f18533982607f24070a55d353e90d4cae30c467cdb2ad5ac5c"
[[package]]
name = "strum_macros"
version = "0.18.0"
@ -3848,6 +3856,18 @@ dependencies = [
"syn",
]
[[package]]
name = "strum_macros"
version = "0.20.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee8bc6b87a5112aeeab1f4a9f7ab634fe6cbefc4850006df31267f4cfb9e3149"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "subprocess"
version = "0.2.6"
@ -3909,8 +3929,8 @@ checksum = "0f3ecc17269a19353b3558b313bba738b25d82993e30d62a18406a24aba4649b"
dependencies = [
"heck",
"pkg-config",
"strum",
"strum_macros",
"strum 0.18.0",
"strum_macros 0.18.0",
"thiserror",
"toml",
"version-compare",

View File

@ -539,7 +539,7 @@ fn is_bldg(tags: &Tags) -> bool {
fn get_bldg_amenities(tags: &Tags) -> Vec<Amenity> {
let mut amenities = Vec::new();
for key in vec!["amenity", "shop"] {
for key in vec!["amenity", "shop", "craft", "office", "tourism", "leisure"] {
if let Some(amenity) = tags.get(key) {
amenities.push(Amenity {
names: NamePerLanguage::new(tags).unwrap_or_else(NamePerLanguage::unnamed),

View File

@ -12,6 +12,7 @@ use map_gui::tools::{
use map_gui::ID;
use map_model::connectivity::WalkingOptions;
use map_model::{AmenityType, Building, BuildingID, LaneType};
use std::str::FromStr;
use widgetry::table::{Col, Filter, Table};
use widgetry::{
lctrl, Cached, Choice, Color, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Key,
@ -97,7 +98,7 @@ impl State<App> for Viewer {
.currently_hovering()
.and_then(|x| x.strip_prefix("businesses: "));
if let Some(category) = key {
let category = AmenityType::parse(category).unwrap();
let category = AmenityType::from_str(category).unwrap();
if self
.hovering_on_category
.as_ref()
@ -177,7 +178,7 @@ impl State<App> for Viewer {
ctx,
app,
&self.isochrone,
AmenityType::parse(category).unwrap(),
AmenityType::from_str(category).unwrap(),
));
} else {
unreachable!()

View File

@ -6,7 +6,7 @@ use map_gui::tools::{ColorDiscrete, ColorLegend, ColorNetwork};
use map_gui::ID;
use map_model::{AmenityType, LaneType};
use sim::AgentType;
use widgetry::{Color, Drawable, EventCtx, GfxCtx, Line, Panel, Text, TextExt, Widget};
use widgetry::{Color, Drawable, EventCtx, GeomBatch, GfxCtx, Line, Panel, Text, TextExt, Widget};
use crate::app::App;
use crate::layer::{header, Layer, LayerOutcome, PANEL_PLACEMENT};
@ -251,45 +251,50 @@ impl Static {
}
pub fn amenities(ctx: &mut EventCtx, app: &App) -> Static {
let mut colorer = ColorDiscrete::new(
app,
vec![
(AmenityType::Groceries.to_string(), Color::BLACK),
(AmenityType::Food.to_string(), Color::RED),
(AmenityType::Bar.to_string(), Color::BLUE),
(AmenityType::Medical.to_string(), Color::PURPLE),
(AmenityType::Religious.to_string(), Color::GREEN),
(AmenityType::Education.to_string(), Color::CYAN),
(AmenityType::Financial.to_string(), Color::YELLOW),
(AmenityType::PostOffice.to_string(), Color::YELLOW),
(AmenityType::Culture.to_string(), Color::PINK),
(AmenityType::Childcare.to_string(), Color::ORANGE),
(AmenityType::Shopping.to_string(), Color::WHITE),
("other".to_string(), Color::hex("#96322F")),
],
);
let food = Color::RED;
let school = Color::CYAN;
let shopping = Color::PURPLE;
let other = Color::GREEN;
let mut unzoomed = GeomBatch::new();
let mut zoomed = GeomBatch::new();
for b in app.primary.map.all_buildings() {
let mut other = false;
if b.amenities.is_empty() {
continue;
}
let mut color = None;
for a in &b.amenities {
if let Some(t) = AmenityType::categorize(&a.amenity_type) {
colorer.add_b(b.id, t.to_string());
} else {
other = true;
color = Some(match t {
AmenityType::Food => food,
AmenityType::School => school,
AmenityType::Shopping => shopping,
_ => other,
});
break;
}
}
if other {
colorer.add_b(b.id, "other");
}
let color = color.unwrap_or(other);
unzoomed.push(color, b.polygon.clone());
zoomed.push(color.alpha(0.4), b.polygon.clone());
}
Static::new(
ctx,
colorer,
"amenities",
"Amenities".to_string(),
Widget::nothing(),
)
let panel = Panel::new(Widget::col(vec![
header(ctx, "Amenities"),
ColorLegend::row(ctx, food, AmenityType::Food.to_string()),
ColorLegend::row(ctx, school, AmenityType::School.to_string()),
ColorLegend::row(ctx, shopping, AmenityType::Shopping.to_string()),
ColorLegend::row(ctx, other, "other".to_string()),
]))
.aligned_pair(PANEL_PLACEMENT)
.build(ctx);
Static {
panel,
unzoomed: ctx.upload(unzoomed),
zoomed: ctx.upload(zoomed),
name: "amenities",
}
}
pub fn no_sidewalks(ctx: &mut EventCtx, app: &App) -> Static {

View File

@ -18,5 +18,7 @@ rand = "0.8.3"
rand_xorshift = "0.3.0"
serde = "1.0.123"
serde_json = "1.0.61"
strum = "0.20"
strum_macros = "0.20"
thread_local = "1.1.2"
traffic_signal_data = { path = "../traffic_signal_data" }

View File

@ -2,6 +2,8 @@ use std::collections::{BTreeMap, HashSet, VecDeque};
use std::fmt;
use serde::{Deserialize, Serialize};
use strum_macros::Display;
use strum_macros::EnumString;
use abstutil::{
deserialize_btreemap, deserialize_usize, serialize_btreemap, serialize_usize, Tags,
@ -225,112 +227,185 @@ fn sidewalk_to_bike(sidewalk_pos: Position, map: &Map) -> Option<(Position, Posi
}
/// Businesses are categorized into one of these types.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, EnumString, Display)]
pub enum AmenityType {
Groceries,
Food,
Bank,
Bar,
Medical,
Religious,
Education,
Financial,
PostOffice,
Culture,
Beauty,
Bike,
Cafe,
CarRepair,
CarShare,
Childcare,
ConvenienceStore,
Culture,
Exercise,
FastFood,
Food,
GreenSpace,
Hotel,
Laundry,
Library,
Medical,
Pet,
Playground,
Pool,
PostOffice,
Religious,
School,
Shopping,
Supermarket,
Tourism,
University,
}
impl AmenityType {
fn types(self) -> Vec<&'static str> {
// TODO: create categories for:
// hairdresser beauty chemist
// car_repair
// laundry
match self {
AmenityType::Groceries => vec!["convenience", "supermarket"],
// TODO Sort
AmenityType::Bank => vec!["bank"],
AmenityType::Bar => vec!["bar", "pub", "nightclub", "biergarten"],
AmenityType::Beauty => vec!["hairdresser", "beauty", "chemist", "cosmetics"],
AmenityType::Bike => vec!["bicycle"],
AmenityType::Cafe => vec!["cafe", "pastry", "coffee", "tea", "bakery"],
AmenityType::CarRepair => vec!["car_repair"],
AmenityType::CarShare => vec!["car_sharing"],
AmenityType::Childcare => vec!["childcare", "kindergarten"],
AmenityType::ConvenienceStore => vec!["convenience"],
AmenityType::Culture => vec!["arts_centre", "art", "cinema", "theatre"],
AmenityType::Exercise => vec!["fitness_centre", "sports_centre", "track", "pitch"],
AmenityType::FastFood => vec!["fast_food", "food_court"],
AmenityType::Food => vec![
"restaurant",
"cafe",
"fast_food",
"food_court",
"farm",
"ice_cream",
"pastry",
"seafood",
"cheese",
"chocolate",
"deli",
"greengrocer",
"bakery",
"butcher",
"confectionery",
"beverages",
"alcohol",
],
AmenityType::Bar => vec!["bar", "lounge", "pub", "nightclub"],
AmenityType::GreenSpace => vec!["park", "garden", "nature_reserve"],
AmenityType::Hotel => vec!["hotel", "hostel", "guest_house", "motel"],
AmenityType::Laundry => vec!["dry_cleaning", "laundry", "tailor"],
AmenityType::Library => vec!["library"],
AmenityType::Medical => vec![
"chiropractor",
"clinic",
"dentist",
"hospital",
"pharmacy",
"optician",
"clinic", "dentist", "hospital", "pharmacy", "doctors", "optician",
],
AmenityType::Religious => vec!["place_of_worship"],
AmenityType::Education => vec!["college", "school", "university"],
AmenityType::Financial => vec!["bank"],
AmenityType::Pet => vec!["veterinary", "pet", "animal_boarding", "pet_grooming"],
AmenityType::Playground => vec!["playground"],
AmenityType::Pool => vec!["swimming_pool"],
AmenityType::PostOffice => vec!["post_office"],
AmenityType::Culture => vec![
"arts_centre",
"art_gallery",
"cinema",
"library",
"museum",
"theatre",
],
AmenityType::Childcare => vec!["childcare", "kindergarten"],
AmenityType::Religious => vec!["place_of_worship", "religion"],
AmenityType::School => vec!["school"],
AmenityType::Shopping => vec![
"wholesale",
"bag",
"marketplace",
"second_hand",
"charity",
"clothes",
"furniture",
"lottery",
"shoes",
"mall",
"department_store",
"car",
"tailor",
"nutrition_supplements",
"watches",
"craft",
"fabric",
"kiosk",
"antiques",
"shoemaker",
"hardware",
"houseware",
"mobile_phone",
"photo",
"toys",
"bed",
"florist",
"electronics",
"fishing",
"garden_centre",
"frame",
"watchmaker",
"boutique",
"mobile_phone",
"party",
"car_parts",
"video",
"video_games",
"musical_instrument",
"music",
"baby_goods",
"doityourself",
"jewelry",
"variety_store",
"gift",
"bicycle",
"carpet",
"perfumery",
"curtain",
"appliance",
"furniture",
"lighting",
"sewing",
"books",
"sports",
"travel_agency",
"interior_decoration",
"stationery",
"pet",
"computer",
"tyres",
"newsagent",
"general",
],
AmenityType::Supermarket => vec!["supermarket", "greengrocer"],
AmenityType::Tourism => vec![
"gallery",
"museum",
"zoo",
"attraction",
"theme_park",
"aquarium",
],
AmenityType::University => vec!["college", "university"],
}
}
/// All types of amenities, in an arbitrary order.
pub fn all() -> Vec<AmenityType> {
vec![
AmenityType::Groceries,
AmenityType::Food,
AmenityType::Bank,
AmenityType::Bar,
AmenityType::Medical,
AmenityType::Religious,
AmenityType::Education,
AmenityType::Financial,
AmenityType::PostOffice,
AmenityType::Culture,
AmenityType::Beauty,
AmenityType::Bike,
AmenityType::Cafe,
AmenityType::CarRepair,
AmenityType::CarShare,
AmenityType::Childcare,
AmenityType::ConvenienceStore,
AmenityType::Culture,
AmenityType::FastFood,
AmenityType::Food,
AmenityType::Exercise,
AmenityType::GreenSpace,
AmenityType::Hotel,
AmenityType::Laundry,
AmenityType::Library,
AmenityType::Medical,
AmenityType::Pet,
AmenityType::Playground,
AmenityType::Pool,
AmenityType::PostOffice,
AmenityType::Religious,
AmenityType::School,
AmenityType::Shopping,
AmenityType::Supermarket,
AmenityType::Tourism,
AmenityType::University,
]
}
@ -343,43 +418,4 @@ impl AmenityType {
}
None
}
pub fn parse(x: &str) -> Option<AmenityType> {
match x {
"groceries" => Some(AmenityType::Groceries),
"food" => Some(AmenityType::Food),
"bar" => Some(AmenityType::Bar),
"medical" => Some(AmenityType::Medical),
"religious" => Some(AmenityType::Religious),
"education" => Some(AmenityType::Education),
"financial" => Some(AmenityType::Financial),
"post office" => Some(AmenityType::PostOffice),
"culture" => Some(AmenityType::Culture),
"childcare" => Some(AmenityType::Childcare),
"shopping" => Some(AmenityType::Shopping),
_ => None,
}
}
}
impl fmt::Display for AmenityType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{}",
match self {
AmenityType::Groceries => "groceries",
AmenityType::Food => "food",
AmenityType::Bar => "bar",
AmenityType::Medical => "medical",
AmenityType::Religious => "religious",
AmenityType::Education => "education",
AmenityType::Financial => "financial",
AmenityType::PostOffice => "post office",
AmenityType::Culture => "culture",
AmenityType::Childcare => "childcare",
AmenityType::Shopping => "shopping",
}
)
}
}