The grand country split. #326

City names are now disambiguated by a two-letter country code. This
commit handles almost everything needed to make this transition. Main
next steps are fixing up map edits automatically and making the city
picker UI understand the extra level of hierarchy.

A little bit of fallout: lakeslice gridlocks again; this regression is
actually from the recent traffic signal changes, but I'm just now
regenerating everything. Will fix soon.
This commit is contained in:
Dustin Carlino 2021-02-13 15:45:59 -08:00
parent 3685f7b18a
commit 39f5d50fcd
148 changed files with 2115 additions and 1883 deletions

74
.gitignore vendored
View File

@ -8,40 +8,40 @@ importer.json
data/input
data/system/allerton_bywater
data/system/ashton_park
data/system/aylesbury
data/system/aylesham
data/system/bailrigg
data/system/bath_riverside
data/system/bellevue
data/system/berlin
data/system/bicester
data/system/castlemead
data/system/chapelford
data/system/clackers_brook
data/system/culm
data/system/dickens_heath
data/system/didcot
data/system/detroit
data/system/dunton_hills
data/system/ebbsfleet
data/system/great_kneighton
data/system/hampton
data/system/handforth
data/system/kidbrooke_village
data/system/krakow
data/system/lcid
data/system/leeds
data/system/london
data/system/long_marston
data/system/micklefield
data/system/montreal
data/system/newcastle_great_park
data/system/nyc
data/system/paris
data/system/providence
data/system/salzburg
data/system/seattle
data/system/tel_aviv
data/system/warsaw
data/system/at/salzburg
data/system/ca/montreal
data/system/de/berlin
data/system/fr/paris
data/system/gb/allerton_bywater
data/system/gb/ashton_park
data/system/gb/aylesbury
data/system/gb/aylesham
data/system/gb/bailrigg
data/system/gb/bath_riverside
data/system/gb/bicester
data/system/gb/castlemead
data/system/gb/chapelford
data/system/gb/clackers_brook
data/system/gb/culm
data/system/gb/dickens_heath
data/system/gb/didcot
data/system/gb/dunton_hills
data/system/gb/ebbsfleet
data/system/gb/great_kneighton
data/system/gb/hampton
data/system/gb/handforth
data/system/gb/kidbrooke_village
data/system/gb/lcid
data/system/gb/leeds
data/system/gb/london
data/system/gb/long_marston
data/system/gb/micklefield
data/system/gb/newcastle_great_park
data/system/il/tel_aviv
data/system/pl/krakow
data/system/pl/warsaw
data/system/us/bellevue
data/system/us/detroit
data/system/us/nyc
data/system/us/providence
data/system/us/seattle

View File

@ -42,21 +42,22 @@ impl Manifest {
let mut remove = Vec::new();
for path in self.entries.keys() {
// TODO Some hardcoded weird exceptions
if !data_packs.runtime.contains("huge_seattle")
&& (path == "data/system/seattle/maps/huge_seattle.bin"
|| path == "data/system/seattle/scenarios/huge_seattle/weekday.bin")
if !data_packs.runtime.contains("us/huge_seattle")
&& (path == "data/system/us/seattle/maps/huge_seattle.bin"
|| path == "data/system/us/seattle/scenarios/huge_seattle/weekday.bin")
{
remove.push(path.clone());
continue;
}
let parts = path.split("/").collect::<Vec<_>>();
let city = format!("{}/{}", parts[2], parts[3]);
if parts[1] == "input" {
if data_packs.input.contains(parts[2]) {
if data_packs.input.contains(&city) {
continue;
}
} else if parts[1] == "system" {
if data_packs.runtime.contains(parts[2]) {
if data_packs.runtime.contains(&city) {
continue;
}
} else {
@ -74,7 +75,8 @@ impl Manifest {
/// Player-chosen groups of files to opt into downloading
#[derive(Serialize, Deserialize)]
pub struct DataPacks {
/// A list of cities to download for using in A/B Street.
/// A list of cities to download for using in A/B Street. Expressed the same as
/// `CityName::to_path`, like "gb/london".
pub runtime: BTreeSet<String>,
/// A list of cities to download for running the map importer.
pub input: BTreeSet<String>,
@ -88,7 +90,7 @@ impl DataPacks {
match crate::maybe_read_json::<DataPacks>(path.clone(), &mut abstutil::Timer::throwaway()) {
Ok(mut cfg) => {
// The game breaks without this required data pack.
cfg.runtime.insert("seattle".to_string());
cfg.runtime.insert("us/seattle".to_string());
cfg
}
Err(err) => {
@ -97,7 +99,7 @@ impl DataPacks {
runtime: BTreeSet::new(),
input: BTreeSet::new(),
};
cfg.runtime.insert("seattle".to_string());
cfg.runtime.insert("us/seattle".to_string());
crate::write_json(path, &cfg);
cfg
}

View File

@ -1,5 +1,6 @@
//! Generate paths for different A/B Street files
use anyhow::Result;
use serde::{Deserialize, Serialize};
use abstutil::basename;
@ -56,84 +57,150 @@ pub fn path<I: Into<String>>(p: I) -> String {
}
}
/// A single map is identified using this. Using a struct makes refactoring later easier, to
/// organize cities hierarchially.
/// A single city is identified using this.
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct CityName {
/// A two letter lowercase country code, from https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2.
/// To represent imaginary/test cities, use the code `zz`.
pub country: String,
/// The name of the city, in filename-friendly form -- for example, "tel_aviv".
pub city: String,
}
impl CityName {
/// Create a CityName from a country code and city.
pub fn new(country: &str, city: &str) -> CityName {
assert_eq!(country.len(), 2);
CityName {
country: country.to_string(),
city: city.to_string(),
}
}
/// Returns all city names based on system data.
pub fn list_all_cities_from_system_data() -> Vec<CityName> {
let mut cities = Vec::new();
for country in list_all_objects(path("system")) {
if country == "assets" || country == "proposals" || country == "study_areas" {
continue;
}
for city in list_all_objects(path(format!("system/{}", country))) {
cities.push(CityName::new(&country, &city));
}
}
cities
}
/// Returns all city names based on importer config.
pub fn list_all_cities_from_importer_config() -> Vec<CityName> {
let mut cities = Vec::new();
for country in list_all_objects("importer/config".to_string()) {
for city in list_all_objects(format!("importer/config/{}", country)) {
cities.push(CityName::new(&country, &city));
}
}
cities
}
/// Parses a CityName from something like "gb/london"; the inverse of `to_path`.
pub fn parse(x: &str) -> Result<CityName> {
let parts = x.split("/").collect::<Vec<_>>();
if parts.len() != 2 || parts[0].len() != 2 {
bail!("Bad CityName {}", x);
}
Ok(CityName::new(parts[0], parts[1]))
}
/// Expresses the city as a path, like "gb/london"; the inverse of `parse`.
pub fn to_path(&self) -> String {
format!("{}/{}", self.country, self.city)
}
/// Stringify the city name for debug messages. Don't implement `std::fmt::Display`, to force
/// callers to explicitly opt into this description, which could change.
pub fn describe(&self) -> String {
format!("{} ({})", self.city, self.country)
}
}
/// A single map is identified using this.
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct MapName {
/// The name of the city, in filename-friendly form -- for example, "tel_aviv". In the future,
/// this field may change to express more geographic hierarchy.
pub city: String,
pub city: CityName,
/// The name of the map within the city, in filename-friendly form -- for example, "downtown"
pub map: String,
}
impl MapName {
/// Create a MapName from a simple city and map name.
pub fn new(city: &str, map: &str) -> MapName {
/// Create a MapName from a country code, city, and map name.
pub fn new(country: &str, city: &str, map: &str) -> MapName {
MapName {
city: city.to_string(),
city: CityName::new(country, city),
map: map.to_string(),
}
}
/// Create a MapName from a city and map within that city.
pub fn from_city(city: &CityName, map: &str) -> MapName {
MapName::new(&city.country, &city.city, map)
}
/// Convenient constructor for the main city of the game.
pub fn seattle(map: &str) -> MapName {
MapName::new("seattle", map)
MapName::new("us", "seattle", map)
}
/// Stringify the map name for debug messages. Don't implement `std::fmt::Display`, to force
/// callers to explicitly opt into this description, which could change.
pub fn describe(&self) -> String {
format!("{} (in {})", self.map, self.city)
format!(
"{} (in {} ({}))",
self.map, self.city.city, self.city.country
)
}
/// Stringify the map name for filenames.
pub fn as_filename(&self) -> String {
format!("{}_{}", self.city, self.map)
format!("{}_{}_{}", self.city.country, self.city.city, self.map)
}
/// Transforms a path to a map back to a MapName. Returns `None` if the input is strange.
pub fn from_path(path: &str) -> Option<MapName> {
// TODO regex
let parts = path.split("/").collect::<Vec<_>>();
if parts.len() < 3 {
if parts.len() < 4 {
return None;
}
let country = parts[parts.len() - 4];
let city = parts[parts.len() - 3];
let map = basename(parts[parts.len() - 1]);
Some(MapName::new(city, &map))
Some(MapName::new(country, city, &map))
}
/// Returns the filesystem path to this map.
pub fn path(&self) -> String {
path(format!("system/{}/maps/{}.bin", self.city, self.map))
}
/// Returns all city names.
pub fn list_all_cities() -> Vec<String> {
let mut cities = Vec::new();
for city in list_all_objects(path("system")) {
if city == "assets" || city == "proposals" || city == "study_areas" {
continue;
}
cities.push(city);
}
cities
path(format!(
"system/{}/{}/maps/{}.bin",
self.city.country, self.city.city, self.map
))
}
/// Returns all maps from one city.
pub fn list_all_maps_in_city(city: &str) -> Vec<MapName> {
pub fn list_all_maps_in_city(city: &CityName) -> Vec<MapName> {
let mut names = Vec::new();
for map in list_all_objects(path(format!("system/{}/maps", city))) {
names.push(MapName::new(&city, &map));
for map in list_all_objects(path(format!("system/{}/{}/maps", city.country, city.city))) {
names.push(MapName {
city: city.clone(),
map,
});
}
names
}
/// Returns all maps from all cities.
/// Returns all maps from all cities, using system data.
pub fn list_all_maps() -> Vec<MapName> {
let mut names = Vec::new();
for city in MapName::list_all_cities() {
for city in CityName::list_all_cities_from_system_data() {
names.extend(MapName::list_all_maps_in_city(&city));
}
names
@ -144,8 +211,8 @@ impl MapName {
pub fn path_prebaked_results(name: &MapName, scenario_name: &str) -> String {
path(format!(
"system/{}/prebaked_results/{}/{}.bin",
name.city, name.map, scenario_name
"system/{}/{}/prebaked_results/{}/{}.bin",
name.city.country, name.city.city, name.map, scenario_name
))
}
@ -153,12 +220,12 @@ pub fn path_scenario(name: &MapName, scenario_name: &str) -> String {
// TODO Getting complicated. Sometimes we're trying to load, so we should look for .bin, then
// .json. But when we're writing a custom scenario, we actually want to write a .bin.
let bin = path(format!(
"system/{}/scenarios/{}/{}.bin",
name.city, name.map, scenario_name
"system/{}/{}/scenarios/{}/{}.bin",
name.city.country, name.city.city, name.map, scenario_name
));
let json = path(format!(
"system/{}/scenarios/{}/{}.json",
name.city, name.map, scenario_name
"system/{}/{}/scenarios/{}/{}.json",
name.city.country, name.city.city, name.map, scenario_name
));
if file_exists(&bin) {
return bin;
@ -169,17 +236,21 @@ pub fn path_scenario(name: &MapName, scenario_name: &str) -> String {
bin
}
pub fn path_all_scenarios(name: &MapName) -> String {
path(format!("system/{}/scenarios/{}", name.city, name.map))
path(format!(
"system/{}/{}/scenarios/{}",
name.city.country, name.city.city, name.map
))
}
/// Extract the map and scenario name from a path. Crashes if the input is strange.
pub fn parse_scenario_path(path: &str) -> (MapName, String) {
// TODO regex
let parts = path.split("/").collect::<Vec<_>>();
let country = parts[parts.len() - 5];
let city = parts[parts.len() - 4];
let map = parts[parts.len() - 2];
let scenario = basename(parts[parts.len() - 1]);
let map_name = MapName::new(city, map);
let map_name = MapName::new(country, city, map);
(map_name, scenario)
}
@ -191,40 +262,46 @@ pub fn path_player<I: Into<String>>(p: I) -> String {
pub fn path_camera_state(name: &MapName) -> String {
path(format!(
"player/camera_state/{}/{}.json",
name.city, name.map
"player/camera_state/{}/{}/{}.json",
name.city.country, name.city.city, name.map
))
}
pub fn path_edits(name: &MapName, edits_name: &str) -> String {
path(format!(
"player/edits/{}/{}/{}.json",
name.city, name.map, edits_name
"player/edits/{}/{}/{}/{}.json",
name.city.country, name.city.city, name.map, edits_name
))
}
pub fn path_all_edits(name: &MapName) -> String {
path(format!("player/edits/{}/{}", name.city, name.map))
path(format!(
"player/edits/{}/{}/{}",
name.city.country, name.city.city, name.map
))
}
pub fn path_save(name: &MapName, edits_name: &str, run_name: &str, time: String) -> String {
path(format!(
"player/saves/{}/{}/{}_{}/{}.bin",
name.city, name.map, edits_name, run_name, time
"player/saves/{}/{}/{}/{}_{}/{}.bin",
name.city.country, name.city.city, name.map, edits_name, run_name, time
))
}
pub fn path_all_saves(name: &MapName, edits_name: &str, run_name: &str) -> String {
path(format!(
"player/saves/{}/{}/{}_{}",
name.city, name.map, edits_name, run_name
"player/saves/{}/{}/{}/{}_{}",
name.city.country, name.city.city, name.map, edits_name, run_name
))
}
// Input data (For developers to build maps, not needed at runtime)
pub fn path_popdat() -> String {
path("input/seattle/popdat.bin")
path("input/us/seattle/popdat.bin")
}
pub fn path_raw_map(name: &MapName) -> String {
path(format!("input/{}/raw_maps/{}.bin", name.city, name.map))
path(format!(
"input/{}/{}/raw_maps/{}.bin",
name.city.country, name.city.city, name.map
))
}

View File

@ -3,7 +3,7 @@
use std::collections::BTreeSet;
use anyhow::{anyhow, bail, Result};
use anyhow::Result;
use serde::de::DeserializeOwned;
use serde::Serialize;

View File

@ -2,6 +2,8 @@
//! way](https://a-b-street.github.io/docs/dev/data.html). This crate implements methods to
//! find files and (mostly) treat them the same way on native and web.
#[macro_use]
extern crate anyhow;
#[macro_use]
extern crate log;

View File

@ -176,11 +176,17 @@ pub fn extract_osm(map: &mut RawMap, opts: &Options, timer: &mut Timer) -> OsmEx
// city, but there's no way to express that right now.
if map.name == MapName::seattle("huge_seattle") {
abstio::write_binary(
abstio::path(format!("input/{}/footways.bin", map.name.city)),
abstio::path(format!(
"input/{}/{}/footways.bin",
map.name.city.country, map.name.city.city
)),
&extra_footways,
);
abstio::write_binary(
abstio::path(format!("input/{}/service_roads.bin", map.name.city)),
abstio::path(format!(
"input/{}/{}/service_roads.bin",
map.name.city.country, map.name.city.city
)),
&extra_service_roads,
);
}

View File

@ -19,7 +19,10 @@ pub fn snap_cycleways(map: &RawMap, timer: &mut Timer) {
let mut cycleways = BTreeMap::new();
for shape in abstio::read_binary::<ExtraShapes>(
abstio::path(format!("input/{}/footways.bin", map.name.city)),
abstio::path(format!(
"input/{}/{}/footways.bin",
map.name.city.country, map.name.city.city
)),
timer,
)
.shapes
@ -89,15 +92,15 @@ fn dump_output(
abstio::write_binary(
abstio::path(format!(
"input/{}/{}_separate_cycleways.bin",
map.name.city, map.name.map
"input/{}/{}/{}_separate_cycleways.bin",
map.name.city.country, map.name.city.city, map.name.map
)),
&separate_cycleways,
);
abstio::write_binary(
abstio::path(format!(
"input/{}/{}_snapped_cycleways.bin",
map.name.city, map.name.map
"input/{}/{}/{}_snapped_cycleways.bin",
map.name.city.country, map.name.city.city, map.name.map
)),
&snapped_cycleways,
);

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
set -e
rm -fv data/input/seattle/raw_maps/huge_seattle.bin data/system/seattle/maps/huge_seattle.bin data/input/raw_maps/huge_seattle.bin data/input/seattle/popdat.bin
rm -fv data/input/us/seattle/raw_maps/huge_seattle.bin data/system/us/seattle/maps/huge_seattle.bin data/input/us/seattle/raw_maps/huge_seattle.bin data/input/us/seattle/popdat.bin
./import.sh --regen_all

View File

@ -1,14 +1,15 @@
#!/bin/bash
city=$1;
map=$2;
country=$1
city=$2;
map=$3;
mkdir screens_before;
cd screens_before;
unzip ../../data/input/${city}/screenshots/${map}.zip;
unzip ../../data/input/${country}/${city}/screenshots/${map}.zip;
cd ..;
before=screens_before;
after=screenshots/${city}/${map};
after=screenshots/${country}/${city}/${map};
rm -rf diff
mkdir diff

View File

@ -1,12 +1,13 @@
#!/bin/bash
city=$1;
map=$2;
country=$1
city=$2;
map=$3;
rm -rf ../data/input/${city}/screenshots/${map}.zip diff screens_before;
cd screenshots/${city}/${map};
rm -rf ../data/input/${country}/${city}/screenshots/${map}.zip diff screens_before;
cd screenshots/${country}/${city}/${map};
zip ${map}.zip *;
mkdir -p ../../../../data/input/${city}/screenshots/;
mv ${map}.zip ../../../../data/input/${city}/screenshots/;
mkdir -p ../../../../data/input/${country}/${city}/screenshots/;
mv ${map}.zip ../../../../data/input/${country}/${city}/screenshots/;
cd ../../../;
rm -rf screenshots/${city}/${map};
rm -rf screenshots/${country}/${city}/${map};

View File

@ -28,7 +28,7 @@ pub fn prebake_all() {
}
for name in vec![
MapName::seattle("lakeslice"),
//MapName::seattle("lakeslice"), TODO Temporarily broken
MapName::seattle("rainier_valley"),
] {
let map = map_model::Map::new(name.path(), &mut timer);

View File

@ -273,10 +273,10 @@ impl State<App> for DebugMode {
app,
vec![
MapName::seattle("downtown"),
MapName::new("krakow", "center"),
MapName::new("pl", "krakow", "center"),
MapName::seattle("lakeslice"),
MapName::seattle("montlake"),
MapName::new("great_kneighton", "center"),
MapName::new("gb", "great_kneighton", "center"),
MapName::seattle("udistrict"),
],
));
@ -837,7 +837,10 @@ impl State<App> for ScreenshotTest {
self.screenshot_done = true;
let name = app.primary.map.get_name();
ctx.request_update(UpdateType::ScreenCaptureEverything {
dir: format!("screenshots/{}/{}", name.city, name.map),
dir: format!(
"screenshots/{}/{}/{}",
name.city.country, name.city.city, name.map
),
zoom: 3.0,
dims: ctx.canvas.get_window_dims(),
leaflet_naming: false,
@ -860,7 +863,10 @@ fn export_for_leaflet(ctx: &mut EventCtx, app: &App) {
// How do we fit the entire map_length into this many tiles?
let zoom = 256.0 * (num_tiles as f64) / map_length;
ctx.request_update(UpdateType::ScreenCaptureEverything {
dir: format!("screenshots/{}/{}/{}", name.city, name.map, zoom_level),
dir: format!(
"screenshots/{}/{}/{}/{}",
name.city.country, name.city.city, name.map, zoom_level
),
zoom,
dims: ScreenDims::new(256.0, 256.0),
leaflet_naming: true,

View File

@ -22,7 +22,11 @@ impl CollisionsViewer {
let map = &app.primary.map;
let data = ctx.loading_screen("load collision data", |_, mut timer| {
let mut all: CollisionDataset = abstio::read_binary(
abstio::path(format!("input/{}/collisions.bin", map.get_city_name())),
abstio::path(format!(
"input/{}/{}/collisions.bin",
map.get_city_name().country,
map.get_city_name().city
)),
&mut timer,
);
all.collisions.retain(|c| {

View File

@ -147,8 +147,9 @@ impl State<App> for ViewKML {
"Load file",
Choice::strings(
abstio::list_dir(abstio::path(format!(
"input/{}/",
app.primary.map.get_city_name()
"input/{}/{}/",
app.primary.map.get_city_name().country,
app.primary.map.get_city_name().city
)))
.into_iter()
.filter(|x| {

View File

@ -63,8 +63,9 @@ impl DevToolsMode {
.hotkey(Key::S)
.build_def(ctx),
if abstio::file_exists(abstio::path(format!(
"input/{}/collisions.bin",
app.primary.map.get_city_name()
"input/{}/{}/collisions.bin",
app.primary.map.get_city_name().country,
app.primary.map.get_city_name().city
))) {
ctx.style()
.btn_outline_light_text("collisions")
@ -97,8 +98,9 @@ impl State<App> for DevToolsMode {
// people building from source. Also, abstio::path is abused to find the
// importer/ directory.
abstio::list_dir(abstio::path(format!(
"../importer/config/{}",
app.primary.map.get_city_name()
"../importer/config/{}/{}",
app.primary.map.get_city_name().country,
app.primary.map.get_city_name().city
)))
.into_iter()
.filter(|path| path.ends_with(".poly"))

View File

@ -29,7 +29,10 @@ impl Favorites {
fn path(app: &App) -> String {
let name = app.primary.map.get_name();
abstio::path_player(format!("favorites/{}/{}.json", name.city, name.map))
abstio::path_player(format!(
"favorites/{}/{}/{}.json",
name.city.country, name.city.city, name.map
))
}
pub fn contains(app: &App, b: BuildingID) -> bool {

View File

@ -93,7 +93,7 @@ pub fn main() {
if let Some(site) = args.optional("--actdev") {
let city = site.replace("-", "_");
let name = MapName::new(&city, "center");
let name = MapName::new("gb", &city, "center");
flags.sim_flags.load = name.path();
flags.study_area = Some(site);
mode = Some(sandbox::GameplayMode::Blog(name));

View File

@ -19,7 +19,7 @@ def post(args, cmd, **kwargs):
# Returns Results
def run_sim(args, modifiers=[], edits=None):
post(args, '/sim/load', json={
'scenario': 'data/system/{}/scenarios/{}/weekday.bin'.format(args.city_name, args.map_name),
'scenario': 'data/system/{}/{}/scenarios/{}/weekday.bin'.format(args.country_code, args.city_name, args.map_name),
'modifiers': modifiers,
'edits': edits,
})

View File

@ -20,6 +20,7 @@ import time
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--api', default='http://localhost:1234')
parser.add_argument('--country_code', default='us')
parser.add_argument('--city_name', default='seattle')
parser.add_argument('--map_name', default='montlake')
parser.add_argument('--hours', type=int, default=24)
@ -29,8 +30,8 @@ def main():
if args.cmp1 and args.cmp2 and args.cmp1 > args.cmp2:
sys.exit(
'--cmp1={} --cmp2={} invalid, --cmp1 is the baseline'.format(args.cmp1, args.cmp2))
print('Simulating {} hours of data/system/{}/scenarios/{}/weekday.bin'.format(
args.hours, args.city_name, args.map_name))
print('Simulating {} hours of data/system/{}/{}/scenarios/{}/weekday.bin'.format(
args.hours, args.country_code, args.city_name, args.map_name))
print('')
num_succeeded_last = 0

View File

@ -20,6 +20,7 @@ import time
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--api', default='http://localhost:1234')
parser.add_argument('--country_code', default='us')
parser.add_argument('--city_name', default='seattle')
parser.add_argument('--map_name', default='montlake')
parser.add_argument('--hours', type=int, default=24)
@ -27,8 +28,8 @@ def main():
parser.add_argument('--rounds', type=int, default=10)
parser.add_argument('--cap_all_roads', type=bool, default=True)
args = parser.parse_args()
print('Simulating {} hours of data/system/{}/scenarios/{}/weekday.bin'.format(
args.hours, args.city_name, args.map_name))
print('Simulating {} hours of data/system/{}/{}/scenarios/{}/weekday.bin'.format(
args.hours, args.country_code, args.city_name, args.map_name))
baseline = abst_helpers.run_sim(args)
edits = get(args, '/map/get-edits').json()

View File

@ -2,10 +2,10 @@
# This example loads an exported JSON map, finds different buildings, and
# generates a simple travel demand model.
#
# 1) cargo run --bin dump_map data/system/seattle/maps/montlake.bin > montlake.json
# 1) cargo run --bin dump_map data/system/us/seattle/maps/montlake.bin > montlake.json
# 2) ./headless/examples/generate_traffic.py --map=montlake.json --out=traffic.json
# 3) cargo run --bin import_traffic -- --map=data/system/seattle/maps/montlake.bin --input=traffic.json
# 4) Use data/system/seattle/scenarios/montlake/monday.bin in the game or from the API.
# 3) cargo run --bin import_traffic -- --map=data/system/us/seattle/maps/montlake.bin --input=traffic.json
# 4) Use data/system/us/seattle/scenarios/montlake/monday.bin in the game or from the API.
#
# Keep this script formatted with autopep8 -i

View File

@ -26,7 +26,7 @@ const (
)
var (
cityName = flag.String("city", "seattle", "city of the map to simulate")
cityName = flag.String("city", "us/seattle", "city of the map to simulate")
mapName = flag.String("map", "montlake", "map name to simulate")
hoursToSimulate = flag.Int("hours", 24, "number of hours to simulate")
comparePct1 = flag.Int64("cmp1", -1, "the baseline percentage for indvidual comparison")

View File

@ -11,9 +11,9 @@ if [ "$CITY" == "" ]; then
exit 1;
fi
if cargo run --release --bin generate_houses -- --map=data/system/$CITY/maps/center.bin --num_required=1000 --rng_seed=42 --out=data/input/$CITY/procgen_houses.json; then
if cargo run --release --bin generate_houses -- --map=data/system/gb/$CITY/maps/center.bin --num_required=1000 --rng_seed=42 --out=data/input/gb/$CITY/procgen_houses.json; then
# Update the importer config, and import again
perl -pi -e "s#\"extra_buildings\": null#\"extra_buildings\": \"data/input/$CITY/procgen_houses.json\"#" importer/config/$CITY/cfg.json
perl -pi -e "s#\"extra_buildings\": null#\"extra_buildings\": \"data/input/gb/$CITY/procgen_houses.json\"#" importer/config/gb/$CITY/cfg.json
./import.sh --raw --map --city=$CITY
else
echo "$CITY already had enough houses"

View File

@ -13,20 +13,20 @@ if [ "$SITE" == "" ]; then
fi
CITY=`echo $SITE | sed -r 's/-/_/g'`
cp -Rv importer/config/leeds importer/config/$CITY
perl -pi -e "s#\"separate_cycleways\": false#\"separate_cycleways\": true#" importer/config/$CITY/cfg.json
rm -fv importer/config/$CITY/*.poly
cp -Rv importer/config/gb/leeds importer/config/gb/$CITY
perl -pi -e "s#\"separate_cycleways\": false#\"separate_cycleways\": true#" importer/config/gb/$CITY/cfg.json
rm -fv importer/config/gb/$CITY/*.poly
wget https://raw.githubusercontent.com/cyipt/actdev/main/data-small/$SITE/small-study-area.geojson
cargo run --bin geojson_to_osmosis < small-study-area.geojson
rm -fv small-study-area.geojson
mv boundary0.poly importer/config/$CITY/center.poly
GEOFABRIK=`cargo run --bin pick_geofabrik importer/config/$CITY/center.poly`
mv boundary0.poly importer/config/gb/$CITY/center.poly
GEOFABRIK=`cargo run --bin pick_geofabrik importer/config/gb/$CITY/center.poly`
echo "Geofabrik URL is $GEOFABRIK"
perl -pi -e "s#\"osm_url\": \".*\"#\"osm_url\": \"$GEOFABRIK\"#" importer/config/$CITY/cfg.json
perl -pi -e "s#\"osm_url\": \".*\"#\"osm_url\": \"$GEOFABRIK\"#" importer/config/gb/$CITY/cfg.json
wget https://raw.githubusercontent.com/cyipt/actdev/main/data-small/$SITE/site.geojson -O data/system/study_areas/$SITE.geojson
./import.sh --raw --map --city=$CITY
./import.sh --raw --map --city=gb/$CITY
echo "You have to manually update .gitignore, map_gui/src/tools/mod.rs, release/deploy_actdev.sh"
echo "You might need to procedurally generate houses."

View File

@ -14,5 +14,5 @@
},
"elevation": null,
"include_railroads": true,
"extra_buildings": "data/input/allerton_bywater/procgen_houses.json"
"extra_buildings": "data/input/gb/allerton_bywater/procgen_houses.json"
}

View File

@ -14,5 +14,5 @@
},
"elevation": null,
"include_railroads": true,
"extra_buildings": "data/input/clackers_brook/procgen_houses.json"
"extra_buildings": "data/input/gb/ashton_park/procgen_houses.json"
}

View File

@ -14,5 +14,5 @@
},
"elevation": null,
"include_railroads": true,
"extra_buildings": "data/input/aylesbury/procgen_houses.json"
"extra_buildings": "data/input/gb/aylesbury/procgen_houses.json"
}

View File

@ -14,5 +14,5 @@
},
"elevation": null,
"include_railroads": true,
"extra_buildings": "data/input/ebbsfleet/procgen_houses.json"
"extra_buildings": "data/input/gb/aylesham/procgen_houses.json"
}

View File

@ -14,5 +14,5 @@
},
"elevation": null,
"include_railroads": true,
"extra_buildings": "data/input/bailrigg/procgen_houses.json"
"extra_buildings": "data/input/gb/bailrigg/procgen_houses.json"
}

View File

@ -14,5 +14,5 @@
},
"elevation": null,
"include_railroads": true,
"extra_buildings": "data/input/bath_riverside/procgen_houses.json"
"extra_buildings": "data/input/gb/bath_riverside/procgen_houses.json"
}

View File

@ -14,5 +14,5 @@
},
"elevation": null,
"include_railroads": true,
"extra_buildings": "data/input/bicester/procgen_houses.json"
"extra_buildings": "data/input/gb/bicester/procgen_houses.json"
}

View File

@ -14,5 +14,5 @@
},
"elevation": null,
"include_railroads": true,
"extra_buildings": "data/input/castlemead/procgen_houses.json"
"extra_buildings": "data/input/gb/castlemead/procgen_houses.json"
}

View File

@ -14,5 +14,5 @@
},
"elevation": null,
"include_railroads": true,
"extra_buildings": "data/input/handforth/procgen_houses.json"
"extra_buildings": "data/input/gb/chapelford/procgen_houses.json"
}

View File

@ -14,5 +14,5 @@
},
"elevation": null,
"include_railroads": true,
"extra_buildings": "data/input/ashton_park/procgen_houses.json"
"extra_buildings": "data/input/gb/clackers_brook/procgen_houses.json"
}

View File

@ -14,5 +14,5 @@
},
"elevation": null,
"include_railroads": true,
"extra_buildings": "data/input/culm/procgen_houses.json"
"extra_buildings": "data/input/gb/culm/procgen_houses.json"
}

View File

@ -14,5 +14,5 @@
},
"elevation": null,
"include_railroads": true,
"extra_buildings": "data/input/didcot/procgen_houses.json"
"extra_buildings": "data/input/gb/didcot/procgen_houses.json"
}

View File

@ -14,5 +14,5 @@
},
"elevation": null,
"include_railroads": true,
"extra_buildings": "data/input/dunton_hills/procgen_houses.json"
"extra_buildings": "data/input/gb/dunton_hills/procgen_houses.json"
}

View File

@ -14,5 +14,5 @@
},
"elevation": null,
"include_railroads": true,
"extra_buildings": "data/input/aylesham/procgen_houses.json"
"extra_buildings": "data/input/gb/ebbsfleet/procgen_houses.json"
}

View File

@ -14,5 +14,5 @@
},
"elevation": null,
"include_railroads": true,
"extra_buildings": "data/input/hampton/procgen_houses.json"
"extra_buildings": "data/input/gb/hampton/procgen_houses.json"
}

View File

@ -14,5 +14,5 @@
},
"elevation": null,
"include_railroads": true,
"extra_buildings": "data/input/chapelford/procgen_houses.json"
"extra_buildings": "data/input/gb/handforth/procgen_houses.json"
}

View File

@ -14,5 +14,5 @@
},
"elevation": null,
"include_railroads": true,
"extra_buildings": "data/input/kidbrooke_village/procgen_houses.json"
"extra_buildings": "data/input/gb/kidbrooke_village/procgen_houses.json"
}

View File

@ -14,5 +14,5 @@
},
"elevation": null,
"include_railroads": true,
"extra_buildings": "data/input/micklefield/procgen_houses.json"
"extra_buildings": "data/input/gb/micklefield/procgen_houses.json"
}

View File

@ -14,5 +14,5 @@
},
"elevation": null,
"include_railroads": true,
"extra_buildings": "data/input/newcastle_great_park/procgen_houses.json"
"extra_buildings": "data/input/gb/newcastle_great_park/procgen_houses.json"
}

Some files were not shown because too many files have changed in this diff Show More