Initial commit - Added logic to look up world city locations via csv
All checks were successful
Locusworks Team/world-cities/pipeline/head This commit looks good

This commit is contained in:
2020-06-11 10:19:32 -05:00
commit 11a85370a9
10 changed files with 16121 additions and 0 deletions

View File

@@ -0,0 +1,43 @@
package net.locusworks.worldcities;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;
import net.locusworks.worldcities.csv.CityFileReader;
import net.locusworks.worldcities.entities.City;
public class WorldCities {
private static List<City> WORLD_CITY_LIST;
static {
try {
WORLD_CITY_LIST = CityFileReader.readCities();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static City findByCityName(String cityName) {
return WORLD_CITY_LIST.stream().filter(c -> c.getCityName().equalsIgnoreCase(cityName))
.findFirst().orElse(null);
}
public static City findByCityAndCountry(String cityName, String country) {
return WORLD_CITY_LIST.stream()
.filter(c -> c.getCityName().equalsIgnoreCase(cityName))
.filter(c -> c.getCountryName().equalsIgnoreCase(country))
.findFirst().orElse(null);
}
public static List<City> findByCityNameLike(String cityName) {
return WORLD_CITY_LIST.stream().filter(c -> c.getCityName().toLowerCase()
.contains(cityName.toLowerCase())).collect(Collectors.toList());
}
public static List<City> findCitiesByCountry(String countryName) {
return WORLD_CITY_LIST.stream().filter(c -> c.getCountryName()
.equalsIgnoreCase(countryName.toLowerCase())).collect(Collectors.toList());
}
}

View File

@@ -0,0 +1,52 @@
package net.locusworks.worldcities.csv;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVRecord;
import net.locusworks.worldcities.entities.City;
import net.locusworks.worldcities.entities.Location;
public class CityFileReader {
private static final String[] HEADERS = {"city","city_ascii","lat","lng","country","iso2","iso3","admin_name","capital","population","id"};
private static List<City> worldCities;
public static List<City> readCities() throws IOException {
if (worldCities != null && worldCities.size() > 0) return worldCities;
InputStream is = CityFileReader.class.getClassLoader().getResourceAsStream("worldcities.csv");
Iterable<CSVRecord> records = CSVFormat.DEFAULT
.withHeader(HEADERS)
.withFirstRecordAsHeader()
.parse(new InputStreamReader(is));
worldCities = StreamSupport.stream(records.spliterator(), false)
.map(r -> toCity(r))
.collect(Collectors.toList());
return worldCities;
}
private static City toCity(CSVRecord record) {
String city = record.get("city_ascii");
float lat = Float.valueOf(record.get("lat"));
float lng = Float.valueOf(record.get("lng"));;
String country = record.get("country");
String iso2 = record.get("iso2");
String iso3 = record.get("iso3");
long id = Long.valueOf(record.get("id"));
return new City(id, city, country, iso2, iso3, new Location(lat, lng));
}
}

View File

@@ -0,0 +1,132 @@
package net.locusworks.worldcities.entities;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class City {
private long id;
private String cityName;
private String countryName;
private String iso2;
private String iso3;
private Location location;
public City(long id, String cityName, String countryName, Location location) {
this(id, cityName, countryName, null, null, location);
}
/**
* @param id
* @param cityName
* @param countryName
* @param iso2
* @param iso3
* @param location
*/
public City(long id, String cityName, String countryName, String iso2, String iso3, Location location) {
this.id = id;
this.cityName = cityName;
this.countryName = countryName;
this.iso2 = iso2;
this.iso3 = iso3;
this.location = location;
}
/**
* @return the id
*/
public long getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(long id) {
this.id = id;
}
/**
* @return the cityName
*/
public String getCityName() {
return cityName;
}
/**
* @param cityName the cityName to set
*/
public void setCityName(String cityName) {
this.cityName = cityName;
}
/**
* @return the countryName
*/
public String getCountryName() {
return countryName;
}
/**
* @param countryName the countryName to set
*/
public void setCountryName(String countryName) {
this.countryName = countryName;
}
/**
* @return the iso2
*/
public String getIso2() {
return iso2;
}
/**
* @param iso2 the iso2 to set
*/
public void setIso2(String iso2) {
this.iso2 = iso2;
}
/**
* @return the iso3
*/
public String getIso3() {
return iso3;
}
/**
* @param iso3 the iso3 to set
*/
public void setIso3(String iso3) {
this.iso3 = iso3;
}
/**
* @return the location
*/
public Location getLocation() {
return location;
}
/**
* @param location the location to set
*/
public void setLocation(Location location) {
this.location = location;
}
@Override
public String toString() {
ObjectMapper mapper = new ObjectMapper();
try {
return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(this);
} catch (JsonProcessingException e) {
throw new IllegalArgumentException(e);
}
}
}

View File

@@ -0,0 +1,41 @@
package net.locusworks.worldcities.entities;
public class Location {
private float latitude;
private float longitude;
public Location(float latitude, float longitude) {
this.latitude = latitude;
this.longitude = longitude;
}
public float getLatitude() {
return this.latitude;
}
public float getLongitude() {
return this.longitude;
}
public String toDMS() {
String lat = toDegreesMinutesAndSeconds(this.latitude);
String latCardinal = this.latitude >= 0 ? "N" : "S";
String lng = toDegreesMinutesAndSeconds(this.longitude);
String lngiCardinal = this.longitude >= 0 ? "E" : "W";
return String.format("%s%s%s%s", lat, latCardinal, lng, lngiCardinal);
}
private String toDegreesMinutesAndSeconds(float coordinate) {
float absolute = Math.abs(coordinate);
double degrees = Math.floor(absolute);
double minutesNotTruncated = (absolute - degrees) * 60;
double minutes = Math.floor(minutesNotTruncated);
double seconds = Math.floor((minutesNotTruncated - minutes) * 60);
return String.format("%2s%2s%s", (long)degrees, (long)minutes, seconds);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,20 @@
package net.locusworks.worldcities.tests;
import static org.junit.jupiter.api.Assertions.*;
import java.io.IOException;
import org.junit.jupiter.api.Test;
import net.locusworks.worldcities.csv.CityFileReader;
class CityFileReaderTest {
@Test
void testReadCities() throws IOException {
assertTrue(CityFileReader.readCities().size() > 0);
CityFileReader.readCities().forEach(c -> System.out.println(c));
}
}

View File

@@ -0,0 +1,50 @@
package net.locusworks.worldcities.tests;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import org.junit.jupiter.api.Test;
import net.locusworks.worldcities.WorldCities;
import net.locusworks.worldcities.entities.City;
class WorldCitiesTest {
@Test
void testFindByCityName() {
City city = WorldCities.findByCityName("Cheremoshna");
assertNotNull(city);
assertEquals(city.getCityName(), "Cheremoshna");
}
@Test
void testFindByCityNameLike() {
List<City> cities = WorldCities.findByCityNameLike("Cher");
assertTrue(cities.size() == 33);
}
@Test
void testFindCitiesByCountry() throws IOException {
List<City> cities = WorldCities.findCitiesByCountry("Ukraine");
assertTrue(cities.size() == 51);
Path file = Paths.get("ukraine.txt");
try(BufferedWriter bos = new BufferedWriter(Files.newBufferedWriter(file))) {
for (City c : cities) {
bos.write(String.format("%s%n", c));
System.out.println(c.getLocation().toDMS());
}
}
}
}