Commit 868542ed authored by Adam Blank's avatar Adam Blank
Browse files

Initial commit

parents
No related merge requests found
Showing with 1259 additions and 0 deletions
+1259 -0
package edu.caltech.cs2.interfaces;
public interface IDictionary<K, V> extends Iterable<K> {
public static class Entry<K, V> {
public final K key;
public V value;
public Entry(K key) {
this(key, null);
}
public Entry(K key, V value) {
this.key = key;
this.value = value;
}
}
/**
* Returns the value to which the specified key is mapped,
* or {@code null} if this map contains no mapping for the key.
*/
public V get(K key);
/**
* Removes the mapping for the specified key from this map if present.
*
* @param key key whose mapping is to be removed from the map
* @return the previous value associated with {@code key}, or
* {@code null} if there was no mapping for {@code key}.
*/
public V remove(K key);
/**
* Associates the specified value with the specified key in this map.
* If the map previously contained a mapping for the key, the old
* value is replaced.
*
* @param key key with which the specified value is to be associated
* @param value value to be associated with the specified key
* @return the previous value associated with {@code key}, or
* {@code null} if there was no mapping for {@code key}.
*/
public V put(K key, V value);
/**
* Returns {@code true} if this map contains a mapping for the
* specified key.
*
* @param key The key whose presence in this map is to be tested
* @return {@code true} if this map contains a mapping for the specified
* key.
*/
public boolean containsKey(K key);
/**
* Returns {@code true} if this map maps one or more keys to the
* specified value.
*
* @param value value whose presence in this map is to be tested
* @return {@code true} if this map maps one or more keys to the
* specified value
*/
public boolean containsValue(V value);
/**
* Returns the number of key-value mappings in this map.
*
* @return the number of key-value mappings in this map
*/
public int size();
/**
* Returns {@code true} if this map contains no key-value mappings.
*
* @return {@code true} if this map contains no key-value mappings
*/
default public boolean isEmpty() {
return this.size() == 0;
}
/**
* Returns a {@link ICollection} of the keys contained in this map.
*
* @return a collection of the keys contained in this map
*/
public ICollection<K> keys();
/**
* Returns a {@link ICollection} of the values contained in this map
* which does not contain duplicates.
*
* @return a collection of the values contained in this map
*/
public ICollection<V> values();
default public ICollection<Entry<K, V>> entrySet() {
IDeque<Entry<K, V>> entries = new LinkedDeque<>();
for (K key : keySet()) {
entries.add(new Entry(key, this.get(key)));
}
return entries;
}
@SuppressWarnings("unchecked cast")
default ISet<K> keySet() {
return ISet.getBackingSet((IDictionary<K, Object>)this);
}
}
package edu.caltech.cs2.interfaces;
/**
* This interface represents a fixed-size queue - a queue with a constant and finite capacity.
* @param <E> Element type
*/
public interface IFixedSizeQueue<E> extends IQueue<E> {
/**
* Checks whether the fixed-size queue is full.
* @return True if full, false otherwise
*/
public boolean isFull();
/**
* Calculates the maximum capacity of the queue.
* @return Maximum capacity of the queue
*/
public int capacity();
}
\ No newline at end of file
package edu.caltech.cs2.interfaces;
public abstract class IGraph<V, E> {
/**
* Add a vertex to the graph.
* @param vertex The vertex to add
* @return true if vertex was not present already.
*/
public abstract boolean addVertex(V vertex);
/**
* Adds edge e to the graph.
*
* @param e The edge to add.
* @throws IllegalArgumentException
* If e is not a valid edge (eg. refers to vertices not in the graph).
* @return true If e was not already present; false if it was (in which case the graph is not updated).
*/
public abstract boolean addEdge(V src, V dest, E e);
/**
* Adds edge e to the graph in both directionns.
*
* @param e The edge to add.
* @throws IllegalArgumentException
* If e is not a valid edge (eg. refers to vertices not in the graph).
* @return true If e was not already present in either direction; false if it was (in which case the graph is not updated).
*/
public abstract boolean addUndirectedEdge(V src, V dest, E e);
/**
* Remove an edge from src to dest from the graph.
*
* @throws IllegalArgumentException if src or dest is not in the graph.
* @return true if an edge from src to dest edge was present.
*/
public abstract boolean removeEdge(V src, V dest);
/**
* Returns the set of vertices in the graph.
* @return The set of all vertices in the graph.
*/
public abstract ISet<V> vertices();
/**
* Tests if vertices i and j are adjacent, returning the edge between
* them if so.
*
* @throws IllegalArgumentException if i or j are not vertices in the graph.
* @return The edge from i to j if it exists in the graph;
* null otherwise.
*/
public abstract E adjacent(V i, V j);
/**
* Return the neighbours of a given vertex when this graph is treated as
* DIRECTED; that is, vertices to which vertex has an outgoing edge.
*
* @param vertex The vertex the neighbours of which to return.
* @throws IllegalArgumentException if vertex is not in the graph.
* @return The set of neighbors of vertex.
*/
public abstract ISet<V> neighbors(V vertex);
}
\ No newline at end of file
package edu.caltech.cs2.interfaces;
/**
* This interface represents a Priority Queue - a data structure that is very similar to a queue but
* stores values in ascending order.
* @param <E> Element type
*/
public interface IPriorityQueue<E> extends IQueue<IPriorityQueue.PQElement<E>> {
public static class PQElement<E> {
public final E data;
public final double priority;
public PQElement(E data, double priority) {
this.data = data;
this.priority = priority;
}
public int hashCode() {
return this.data.hashCode();
}
public boolean equals(Object o) {
if (!(o instanceof PQElement)) {
return false;
}
return this.data.equals(((PQElement)o).data);
}
public String toString() {
return "(" + this.data + ", " + this.priority + ")";
}
}
/**
* Increase the priority of the key at idx
* @param key - the new key with the new priority
*/
public void increaseKey(PQElement<E> key);
/**
* Decrease the priority of the key at idx
* @param key - the new key with the new priority
*/
public void decreaseKey(PQElement<E> key);
}
\ No newline at end of file
package edu.caltech.cs2.interfaces;
/**
* This interface represents a queue - a data structure that can add elements at one end and remove them from the other.
* @param <E> Element type
*/
public interface IQueue<E> extends Iterable<E> {
/**
* Adds an element to the back of the queue.
* @param e Element to add
* @return True if successful, false otherwise (i.e. fixed data structure is full)
*/
public boolean enqueue(E e);
/**
* Removes and returns the element at the front of the queue. Returns null if queue is empty.
* @return Element at front of queue, if one exists; null otherwise
*/
public E dequeue();
/**
* Returns (but does not remove) the element at the front of the queue. Returns null if queue is empty.
* @return Element at front of queue, if one exists; null otherwise
*/
public E peek();
/**
* Calculates the size of the queue.
* @return Number of elements in the queue
*/
public int size();
}
package edu.caltech.cs2.interfaces;
import java.util.Iterator;
public class ISet<E> implements Iterable<E> {
private IDictionary<E, Object> internalDictionary;
protected ISet(IDictionary<E, Object> dict) {
this.internalDictionary = dict;
}
public static <E> ISet<E> getBackingSet(IDictionary<E, Object> dict) {
return new ISet<E>(dict);
}
/**
* Returns the number of elements in this set (its cardinality). If this
* set contains more than {@code Integer.MAX_VALUE} elements, returns
* {@code Integer.MAX_VALUE}.
*
* @return the number of elements in this set (its cardinality)
*/
public int size() {
return this.internalDictionary.size();
}
/**
* Returns {@code true} if this set contains no elements.
*
* @return {@code true} if this set contains no elements
*/
public boolean isEmpty() {
return this.internalDictionary.isEmpty();
}
/**
* Returns {@code true} if this set contains the specified element.
* More formally, returns {@code true} if and only if this set
* contains an element {@code e} such that
* {@code Objects.equals(o, e)}.
*
* @param e element whose presence in this set is to be tested
* @return {@code true} if this set contains the specified element
*/
public boolean contains(E e) {
return this.internalDictionary.containsKey(e);
}
/**
* Returns an iterator over the elements in this set. The elements are
* returned in no particular order (unless this set is an instance of some
* class that provides a guarantee).
*
* @return an iterator over the elements in this set
*/
public Iterator<E> iterator() {
return this.internalDictionary.iterator();
}
// Modification Operations
/**
* Adds the specified element to this set if it is not already present
* (optional operation). More formally, adds the specified element
* {@code e} to this set if the set contains no element {@code e2}
* such that
* {@code Objects.equals(e, e2)}.
* If this set already contains the element, the call leaves the set
* unchanged and returns {@code false}. In combination with the
* restriction on constructors, this ensures that sets never contain
* duplicate elements.
*
* @param e element to be added to this set
* @return {@code true} if this set did not already contain the specified
* element
*/
public boolean add(E e) {
return this.internalDictionary.put(e, new Object()) != null;
}
/**
* Removes the specified element from this set if it is present
* (optional operation). More formally, removes an element {@code e}
* such that
* {@code Objects.equals(o, e)}, if
* this set contains such an element. Returns {@code true} if this set
* contained the element (or equivalently, if this set changed as a
* result of the call). (This set will not contain the element once the
* call returns.)
*
* @param e object to be removed from this set, if present
* @return {@code true} if this set contained the specified element
*/
public boolean remove(E e) {
return this.internalDictionary.remove(e) != null;
}
/**
* Removes all of the elements from this set (optional operation).
* The set will be empty after this call returns.
*
* @throws UnsupportedOperationException if the {@code clear} method
* is not supported by this set
*/
public void clear() {
throw new UnsupportedOperationException();
}
@Override
public String toString() {
StringBuilder b = new StringBuilder();
for (E e : this) {
b.append(e + ", ");
}
if (b.length() > 0) {
b.delete(b.length() - 2, b.length());
}
return "[" + b.toString() + "]";
}
}
package edu.caltech.cs2.interfaces;
/**
* This interface represents a stack - a data structure that can add elements remove elements from a single end.
* @param <E> Element type
*/
public interface IStack<E> extends Iterable<E> {
/**
* Adds an element to the top of the stack.
* @param e Element to add
* @return True if successful, false otherwise (i.e. fixed data structure is full)
*/
public boolean push(E e);
/**
* Removes and returns the element at the top of the stack. Returns null if stack is empty.
* @return Element at top of the stack, if one exists; null otherwise
*/
public E pop();
/**
* Returns (but does not remove) the element at the top of the stack. Returns null if stack is empty.
* @return Element at top of the stack, if one exists; null otherwise
*/
public E peek();
/**
* Calculates the size of the stack.
* @return Number of elements in the stack
*/
public int size();
}
package edu.caltech.cs2.interfaces;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
public abstract class ITrieMap<A, K extends Iterable<A>, V> implements IDictionary<K, V> {
protected TrieNode<A, V> root;
protected Function<IDeque<A>, K> collector;
protected int size;
public ITrieMap(Function<IDeque<A>, K> collector) {
this.collector = collector;
this.size = 0;
this.root = new TrieNode<>();
}
public abstract boolean isPrefix(K key);
public abstract IDeque<V> getCompletions(K prefix);
public void clear() {
this.size = 0;
this.root = new TrieNode<>();
}
protected static class TrieNode<A, V> {
public final Map<A, TrieNode<A, V>> pointers;
public V value;
public TrieNode() {
this(null);
}
public TrieNode(V value) {
this.pointers = new HashMap<>();//new ChainingHashDictionary<>(() -> new MoveToFrontDictionary());
this.value = value;
}
@Override
public String toString() {
StringBuilder b = new StringBuilder();
if (this.value != null) {
b.append("[" + this.value + "]-> {\n");
this.toString(b, 1);
b.append("}");
}
else {
this.toString(b, 0);
}
return b.toString();
}
private String spaces(int i) {
StringBuilder sp = new StringBuilder();
for (int x = 0; x < i; x++) {
sp.append(" ");
}
return sp.toString();
}
protected boolean toString(StringBuilder s, int indent) {
Set<A> keySet = this.pointers.keySet();
boolean isSmall = keySet.isEmpty();
for (A idx : keySet){
TrieNode<A, V> node = this.pointers.get(idx);
if (node == null) {
continue;
}
V value = node.value;
s.append(spaces(indent) + idx + (value != null ? "[" + value + "]" : ""));
s.append("-> {\n");
boolean bc = node.toString(s, indent + 2);
if (!bc) {
s.append(spaces(indent) + "},\n");
}
else if (s.charAt(s.length() - 5) == '-') {
s.delete(s.length() - 5, s.length());
s.append(",\n");
}
}
if (!isSmall) {
s.deleteCharAt(s.length() - 2);
}
return isSmall;
}
}
@Override
public String toString() {
return this.root.toString();
}
}
package edu.caltech.cs2.project07;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import edu.caltech.cs2.datastructures.BeaverMapsGraph;
import edu.caltech.cs2.datastructures.Location;
import edu.caltech.cs2.interfaces.IDeque;
import edu.caltech.cs2.interfaces.ISet;
import java.awt.*;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Stream;
public class BeaverMaps {
public static final int PORT = 8001;
public static final int NUMBER_OF_OPTIONS = 15;
private static BeaverMapsGraph graph;
private static MapsAutoCompleter COMPLETER;
static class LocalFile implements HttpHandler {
private String name;
public LocalFile(String name) {
this.name = name;
}
@Override
public void handle(HttpExchange t) throws IOException {
String response = new String(Files.readAllBytes(Paths.get(this.name)), StandardCharsets.UTF_8);
t.sendResponseHeaders(200, 0);
OutputStream os = t.getResponseBody();
os.write(response.getBytes());
os.close();
}
}
public static void main(String[] args) throws Exception {
long start = System.currentTimeMillis();
graph = new BeaverMapsGraph("data/pasadena.buildings", "data/pasadena.waypoints", "data/pasadena.roads");
long end = System.currentTimeMillis();
System.out.println("Reading data took " + (end - start) + " millis.");
System.out.println("Populating autocomplete");
COMPLETER.populateLocations(graph.getBuildings());
System.out.println("Done populating autocomplete");
HttpServer server = HttpServer.create(new InetSocketAddress(PORT), 0);
server.createContext("/", new LocalFile("map.html"));
server.createContext("/css/map.css", new LocalFile("css/map.css"));
server.createContext("/js/map.js", new LocalFile("js/map.js"));
server.createContext("/js/autocomplete.js", new LocalFile("js/autocomplete.js"));
server.createContext("/js/typeahead.js", new LocalFile("js/typeahead.js"));
server.createContext("/byname", new AllWithNameSearch());
server.createContext("/nearby", new LocationSearch());
server.createContext("/pathfinder", new PathFinder());
server.createContext("/autocomplete", new Autocomplete());
server.createContext("/nearest", new NearestSearch());
server.setExecutor(null); // creates a default executor
server.start();
System.out.println("Server started!");
if (Desktop.isDesktopSupported()) {
Desktop.getDesktop().browse(new URI("http://localhost:" + PORT + "/"));
}
}
static class PathFinder implements HttpHandler {
@Override
public void handle(HttpExchange t) throws IOException {
Optional<String> start = Stream.of(t.getRequestURI().getQuery().split("\\&")).filter(x -> x.startsWith("start=")).map(x -> x.split("=")[1]).findAny();
Optional<String> start_id = Stream.of(t.getRequestURI().getQuery().split("\\&")).filter(x -> x.startsWith("start-id=")).map(x -> x.split("=")[1]).findAny();
Optional<String> end = Stream.of(t.getRequestURI().getQuery().split("\\&")).filter(x -> x.startsWith("end=")).map(x -> x.split("=")[1]).findAny();
Optional<String> end_id = Stream.of(t.getRequestURI().getQuery().split("\\&")).filter(x -> x.startsWith("end-id=")).map(x -> x.split("=")[1]).findAny();
String response = "[]";
if (start.isPresent() && end.isPresent()) {
String startL = start.get();
String endL = end.get();
String startID = start_id.orElse(null);
String endID = end_id.orElse(null);
Location startLocation = startID != null ?
graph.getLocationByID(Long.parseLong(startID)) :
graph.getLocationByName(startL).peek();
Location endLocation = endID != null ?
graph.getLocationByID(Long.parseLong(endID)) :
graph.getLocationByName(endL).peek();
if (startLocation != null && endLocation != null) {
IDeque<Location> locs = graph.dijkstra(startLocation, endLocation);
IDeque<String> path = new LinkedDeque<>();
int i = 0;
for (Location loc : locs) {
String locStr = loc.lat + "::" + loc.lon + "::" + ("" + i + ":" + (loc.name != null ? " " + loc.name : "") + "::" + loc.id);
path.add(locStr);
i++;
}
response = path.toString();
}
}
t.sendResponseHeaders(200, 0);
OutputStream os = t.getResponseBody();
os.write(response.getBytes());
os.close();
}
}
static class NearestSearch implements HttpHandler {
@Override
public void handle(HttpExchange t) throws IOException {
Optional<String> lat = Stream.of(t.getRequestURI().getQuery().split("\\&")).filter(x -> x.startsWith("lat=")).map(x -> x.split("=")[1]).findAny();
Optional<String> lon = Stream.of(t.getRequestURI().getQuery().split("\\&")).filter(x -> x.startsWith("lon=")).map(x -> x.split("=")[1]).findAny();
String response = "";
if (lat.isPresent() && lon.isPresent()) {
String latS = lat.get();
String lonS = lon.get();
Location l = graph.getClosestBuilding(Double.parseDouble(latS), Double.parseDouble(lonS));
if (l != null) {
response = "{\"id\": " + l.id + ", \"name\": \"" + l.name + "\"" + ", \"lat\":" + l.lat + ", \"lon\": " + l.lon + "}";
}
}
t.sendResponseHeaders(200, 0);
OutputStream os = t.getResponseBody();
os.write(response.getBytes());
os.close();
}
}
static class AllWithNameSearch implements HttpHandler {
@Override
public void handle(HttpExchange t) throws IOException {
Optional<String> query = Stream.of(t.getRequestURI().getQuery().split("\\&")).filter(x -> x.startsWith("query=")).map(x -> x.split("=")[1]).findAny();
String response = "[]";
if (query.isPresent()) {
String location = query.get();
IDeque<Location> locs = graph.getLocationByName(location);
if (!locs.isEmpty()) {
IDeque<String> locList = new LinkedDeque<>();
for (Location loc : locs) {
if (loc.type == Location.Type.BUILDING) {
String locStr = loc.lat + "::" + loc.lon + "::" + loc.name + "::" + loc.id;
locList.add(locStr);
}
}
response = locList.toString();
}
}
t.sendResponseHeaders(200, 0);
OutputStream os = t.getResponseBody();
os.write(response.getBytes());
os.close();
}
}
static class LocationSearch implements HttpHandler {
@Override
public void handle(HttpExchange t) throws IOException {
Optional<String> name = Stream.of(t.getRequestURI().getQuery().split("\\&")).filter(x -> x.startsWith("name=")).map(x -> x.split("=")[1]).findAny();
Optional<String> id = Stream.of(t.getRequestURI().getQuery().split("\\&")).filter(x -> x.startsWith("id=")).map(x -> x.split("=")[1]).findAny();
Optional<String> distance = Stream.of(t.getRequestURI().getQuery().split("\\&")).filter(x -> x.startsWith("distance=")).map(x -> x.split("=")[1]).findAny();
String response = "[]";
if (name.isPresent()) {
String nameS = name.get();
String idS = id.orElse(null);
Location l = idS != null ?
graph.getLocationByID(Long.parseLong(idS)) :
graph.getLocationByName(nameS).peek();
if (l != null) {
IDeque<String> locList = new LinkedDeque<>();
double dist = Double.parseDouble(distance.orElse("200"));
ISet<Location> closeLocs = graph.dfs(l, dist * 2);
closeLocs.remove(l);
for (Location loc : closeLocs) {
if (l.getDistance(loc) < dist && loc.type == Location.Type.BUILDING) {
String locStr = loc.lat + "::" + loc.lon + "::" + loc.name + "::" + loc.id;
locList.add(locStr);
}
}
locList.addFront(l.lat + "::" + l.lon + "::" + l.name);
response = locList.toString();
}
}
t.sendResponseHeaders(200, 0);
OutputStream os = t.getResponseBody();
os.write(response.getBytes());
os.close();
}
}
static class Autocomplete implements HttpHandler {
@Override
public void handle(HttpExchange t) throws IOException {
Optional<String> query = Stream.of(t.getRequestURI().getQuery().split("\\&")).filter(x -> x.startsWith("query=")).map(x -> x.split("=")[1]).findAny();
String response = "[]";
if (query.isPresent()) {
long before = System.currentTimeMillis();
IDeque<Long> options = COMPLETER.complete(query.get());
String[] opts = new String[options.size()];
Long[] ids = new Long[options.size()];
for (int i = 0; i < opts.length; i++) {
long id = options.removeFront();
ids[i] = id;
opts[i] = graph.getLocationByID(id).displayString();
}
long after = System.currentTimeMillis();
StringBuilder result = new StringBuilder();
for (int i = 0; i < opts.length && i < NUMBER_OF_OPTIONS; i++) {
result.append("{\"value\": \"" + opts[i].replace("\"", "\\\"") + "\", \"id\": " + ids[i] + "}, ");
}
System.out.println("\"" + query.get() + "\" took " + (after - before) + " milliseconds!");
if (result.length() > 0) {
response = result.toString();
response = "[" + response.substring(0, response.length() - 2) + "]";
}
}
System.out.println(response);
t.sendResponseHeaders(200, 0);
OutputStream os = t.getResponseBody();
os.write(response.getBytes());
os.close();
}
}
}
package edu.caltech.cs2.project07;
import edu.caltech.cs2.datastructures.Location;
import edu.caltech.cs2.interfaces.IDeque;
import edu.caltech.cs2.interfaces.ISet;
import edu.caltech.cs2.interfaces.ITrieMap;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public class MapsAutoCompleter {
private static ITrieMap<String, IDeque<String>, IDeque<Location>> locs = new TrieMap<>((IDeque<String> s) -> s);
public static void populateLocations(ISet<Location> locations) {
locs.clear();
for (Location l : locations) {
if (l.name == null) {
continue;
}
String[] words = l.name.toLowerCase().split(" ");
char[] charArr = l.name.toLowerCase().toCharArray();
String[] strCharArr = new String[charArr.length];
for (int i = 0; i < charArr.length; i++) {
strCharArr[i] = Character.toString(charArr[i]);
}
for (int i = 1; i <= l.name.length(); i++) {
String[] subarr = Arrays.copyOfRange(strCharArr, 0, i);
IDeque<String> iterableSubarr = listFromArray(subarr);
if (!locs.containsKey(iterableSubarr)) {
locs.put(iterableSubarr, new LinkedDeque<>());
}
locs.get(iterableSubarr).add(l);
}
for (int i = 0; i < words.length; i++) {
String[] subarr = Arrays.copyOfRange(words, i, words.length);
IDeque<String> iterableSubarr = listFromArray(subarr);
if (!locs.containsKey(iterableSubarr)) {
locs.put(iterableSubarr, new LinkedDeque<>());
}
locs.get(iterableSubarr).add(l);
}
if (l.address == null) {
continue;
}
words = l.address.toLowerCase().split(" ");
for (int i = 0; i < words.length; i++) {
String[] subarr = Arrays.copyOfRange(words, i, words.length);
IDeque<String> iterableSubarr = listFromArray(subarr);
if (!locs.containsKey(iterableSubarr)) {
locs.put(iterableSubarr, new LinkedDeque<>());
}
locs.get(iterableSubarr).add(l);
}
}
}
private static IDeque<String> listFromArray(String[] arr) {
IDeque<String> lst = new LinkedDeque<>();
for (String s: arr) {
lst.addBack(s);
}
return lst;
}
public static IDeque<String> charArrToStringIterable(char[] ca) {
IDeque<String> d = new LinkedDeque<>();
for (int i = 0; i < ca.length; i++) {
d.addBack(Character.toString(ca[i]));
}
return d;
}
public static IDeque<Long> complete(String term) {
String[] keyPath = term.strip().toLowerCase().split("\\s");
IDeque<String> kpIterable = listFromArray(keyPath);
IDeque<IDeque<Location>> options = locs.getCompletions(kpIterable);
options.addAll(locs.getCompletions(charArrToStringIterable(term.toLowerCase().toCharArray())));
Set<Long> opts = new HashSet<>();
for (IDeque<Location> val : options) {
for (Location o : val) {
opts.add(o.id);
}
}
IDeque<Long> completions = new LinkedDeque<>();
for (Long o : opts) {
completions.add(o);
}
return completions;
}
}
package edu.caltech.cs2.project07;
import edu.caltech.cs2.datastructures.*;
import edu.caltech.cs2.interfaces.IDeque;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;
import java.io.File;
import java.io.FileReader;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class OSMToJSON {
public static final QName NODE_ID = new QName("id");
public static final QName NODE_LAT = new QName("lat");
public static final QName NODE_LON = new QName("lon");
public static final QName TAG_TYPE = new QName("k");
public static final QName TAG_VAL = new QName("v");
public static final QName ND_REF = new QName("ref");
private static Map<Long, Location> tempNodes;
private static Map<Long, Boolean> addedNodes;
private static PrintWriter outbuilds;
private static PrintWriter outways;
private static PrintWriter outroads;
public static void readTags(IDeque<String> tagNames, IDeque<String> tagValues, XMLEventReader reader) {
try {
while (reader.peek().isStartElement()) {
StartElement data = reader.nextEvent().asStartElement();
tagNames.addBack(getStringAttr(data, TAG_TYPE));
tagValues.addBack(getStringAttr(data, TAG_VAL));
// Self-closing tags are split into start and end
// So read end
reader.nextEvent();
readNewlineEvent(reader);
}
}
catch (Exception e) {
e.printStackTrace();
}
}
public static void readNewlineEvent(XMLEventReader reader) {
try {
if (reader.peek().isCharacters() &&
(reader.peek().asCharacters().toString().strip().length() == 0 ||
reader.peek().asCharacters().toString().strip().length() == 0)) {
reader.nextEvent();
}
}
catch (Exception e) {
e.printStackTrace();
}
}
public static String getStringAttr(StartElement se, QName name) {
Attribute a = se.getAttributeByName(name);
if (a == null) {
return null;
}
return a.getValue();
}
public static void buildJSON(String xmlFile) {
System.out.println("Starting...");
tempNodes = new HashMap<>();
addedNodes = new HashMap<>();
try {
outbuilds = new PrintWriter(new File("out.buildings"));
outbuilds.print("[");
outways = new PrintWriter(new File("out.waypoints"));
outways.print("[");
outroads = new PrintWriter(new File("out.roads"));
outroads.print("[");
} catch(Exception e) {
System.exit(1);
}
XMLInputFactory factory = XMLInputFactory.newInstance();
try {
XMLEventReader reader = factory.createXMLEventReader(new FileReader(xmlFile));
while (reader.hasNext()) {
XMLEvent next = reader.nextEvent();
if (next.isStartElement()) {
StartElement elem = next.asStartElement();
String elemType = elem.getName().getLocalPart();
// Parse single node
if (elemType.equals("node")) {
String id = getStringAttr(elem, NODE_ID);
double lat = Double.parseDouble(getStringAttr(elem, NODE_LAT));
double lon = Double.parseDouble(getStringAttr(elem, NODE_LON));
String name = null;
String amenity = null;
String shop = null;
IDeque<String> tagNames = new LinkedDeque<>();
IDeque<String> tagValues = new LinkedDeque<>();
readNewlineEvent(reader);
readTags(tagNames, tagValues, reader);
Location newNode = buildNode(Long.parseLong(id), lat, lon, tagNames, tagValues);
tempNodes.put(newNode.id, newNode);
if (newNode.type == Location.Type.BUILDING) {
outbuilds.println(newNode);
}
}
// Parse footpath / building shape / lots of things
// nd in ways always come after corresponding node tag
else if (elemType.equals("way")) {
IDeque<String> nodeIDs = new LinkedDeque<>();
IDeque<String> tagNames = new LinkedDeque<>();
IDeque<String> tagValues = new LinkedDeque<>();
readNewlineEvent(reader);
// XMLEvent tmp = reader.peek();
while (reader.peek().isStartElement() &&
reader.peek().asStartElement().getName().getLocalPart().equals("nd")) {
StartElement data = reader.nextEvent().asStartElement();
nodeIDs.addBack(getStringAttr(data, ND_REF));
// Read closing tag of self-closing
reader.nextEvent();
readNewlineEvent(reader);
// tmp = reader.peek();
}
readTags(tagNames, tagValues, reader);
addFootpath(nodeIDs, tagNames, tagValues, Long.parseLong(getStringAttr(elem, NODE_ID)));
}
}
}
outroads.print("]");
outroads.close();
outbuilds.print("]");
outbuilds.close();
outways.print("]");
outways.close();
}
catch (Exception e) {
e.printStackTrace();
}
System.out.println("Finished generating files...");
}
public static Location buildNode(long id, double lat, double lon, IDeque<String> tags, IDeque<String> tagValues) {
Iterator<String> tagIter = tags.iterator();
Iterator<String> valIter = tagValues.iterator();
String name = null;
String amenity = null;
String shop = null;
String addr_num = null;
String addr_street = null;
String addr_city = null;
while (tagIter.hasNext()) {
String tagType = tagIter.next();
String tagVal = valIter.next();
switch (tagType) {
case "name":
name = tagVal;
break;
case "amenity":
amenity = tagVal;
break;
case "shop":
shop = tagVal;
break;
case "addr:housenumber":
addr_num = tagVal;
break;
case "addr:street":
addr_street = tagVal;
break;
case "addr:city":
addr_city = tagVal;
break;
}
}
String addr = null;
if (addr_city != null && addr_num != null && addr_street != null) {
addr = addr_num + " " + addr_street + ", " + addr_city;
}
// Only considering buildings that sell... something.
if (name != null || amenity != null || shop != null || addr != null) {
return new Location(id, lat, lon, name, addr, amenity, shop, "building");
}
return new Location(id, lat, lon, name, null, null, null, "footpath");
}
public static void addFootpath(IDeque<String> nodes, IDeque<String> tags, IDeque<String> tagValues, long wayID) {
boolean isWalkable = false;
String name = null;
Iterator<String> tagIter = tags.iterator();
Iterator<String> valIter = tagValues.iterator();
while (tagIter.hasNext()) {
String tagType = tagIter.next();
String tagVal = valIter.next();
switch (tagType) {
case "name":
name = tagVal;
break;
case "foot":
isWalkable = tagVal.equals("yes");
break;
case "highway":
// Too many cases - just consider any road not the
// freeway to be "walkable"
isWalkable = true;//!tagVal.equals("motorway");
break;
}
}
// If it's walkable, build edges along the footpath
if (isWalkable) {
Location prevNode = null;
outroads.print("[");
for (String sid : nodes) {
long id = Long.parseLong(sid);
Location currNode = null;
currNode = tempNodes.get(id);
currNode.name = name;
if (addedNodes.put(id, true) == null && currNode.type != Location.Type.BUILDING) {
outways.println(currNode);
}
if (prevNode != null) {
double dist = prevNode.getDistance(currNode);
outroads.print("\"" + prevNode.id + "\", ");
}
prevNode = currNode;
}
outroads.println("\"" + prevNode.id + "\"]");
}
// If location we want to track, find center of building and add to buildingNodes
else if (name != null) {
double latSum = 0;
double lonSum = 0;
for (String id : nodes) {
Location currNode = tempNodes.get(Long.parseLong(id));
outways.println(currNode);
outroads.println("[\"" + wayID + "\", " + "\"" + currNode.id + "\"]");
latSum += currNode.lat;
lonSum += currNode.lon;
}
Location newNode = buildNode(wayID, latSum / nodes.size(), lonSum / nodes.size(), tags, tagValues);
if (newNode.type == Location.Type.BUILDING) {
outbuilds.println(newNode);
}
}
}
public static void main(String[] args){
OSMToJSON.buildJSON("data/old/pasadena.osm");
}
}
This diff is collapsed.
This diff is collapsed.
LUNATIK II
RED WOLF II
SHARKSKIN
CLUMSY FOULUP
RANDAK
MARVEL BOY II/MARTIN
CALLAHAN, DANNY
JOHNSON, LYNDON BAIN
SEA LEOPARD
DEATHCHARGE
GIURESCU, RADU
GERVASE, LADY ALYSSA
BERSERKER II
BLARE/
ZANTOR
FENRIS
KULL
RUNE
This diff is collapsed.
package edu.caltech.cs2.helpers;
import org.junit.jupiter.params.provider.ArgumentsSource;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@ArgumentsSource(FileSourceProvider.class)
public @interface FileSource {
String[] inputs();
String[] outputFiles();
}
package edu.caltech.cs2.helpers;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.ArgumentsProvider;
import org.junit.jupiter.params.support.AnnotationConsumer;
import org.junit.platform.commons.util.Preconditions;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
import java.util.stream.Stream;
import static org.junit.jupiter.api.Assertions.fail;
public class FileSourceProvider implements ArgumentsProvider, AnnotationConsumer<FileSource> {
private String[] inputs;
private String[] outputFiles;
@Override
public void accept(FileSource source) {
this.inputs = source.inputs();//Stream.of(source.inputs()).map((x) -> Arrays.asList(x.split("\\|"))).collect(Collectors.toList());
this.outputFiles = source.outputFiles();
}
@Override
public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
Arguments[] args = new Arguments[this.outputFiles.length];
for (int i = 0; i < this.outputFiles.length; i++) {
String inputArgs = this.inputs[i];
Scanner in = getScanner(this.outputFiles[i]);
String output = in.useDelimiter("\\Z").next();
args[i] = Arguments.arguments(inputArgs, output);
}
return Stream.of(args);
}
private Scanner getScanner(String resource) {
Preconditions.notBlank(resource, "Test file " + resource + " must not be null or blank");
try {
return new Scanner(new File("tests/data/" + resource));
} catch (FileNotFoundException e) {
fail("Test file " + resource + " does not exist");
}
return null;
}
}
package edu.caltech.cs2.helpers;
import org.junit.jupiter.params.provider.ArgumentsSource;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@ArgumentsSource(ImageFileSourceProvider.class)
public @interface ImageFileSource {
String[] inputs();
String[] outputFiles();
}
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment