Android Open Source - Mapyst Interpreter






From Project

Back to project page Mapyst.

License

The source code is released under:

Apache License

If you think the Android project Mapyst listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * Copyright (C) 2013 Mapyst//from  w  ww  . j  a  va2 s.  c o m
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.mapyst.route;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map.Entry;

import com.mapyst.campus.Campus;

//interprets text to decide which point(s) (if any) in the graph it represents 
public class Interpreter {

  private Campus campus;
  private HashMap<WaypointID, GraphNode<Waypoint2D>> loadedNodes;

  private static final int STATE_BUILDING = 0;
  private static final int STATE_FLOOR_OR_ROOM = 1;
  private static final int STATE_ROOM = 2;

  public Interpreter(Campus campus) {
    this.campus = campus;
    clean();
  }

  public void clean() {
    loadedNodes = new HashMap<WaypointID, GraphNode<Waypoint2D>>();
  }

  //example input for CMU: lat=40441885, lng=-79942778
  public InterpretedInfo interpretLatLng(int lat, int lng) {
    RouteFinder.loadOutsideBuildings(campus, loadedNodes);
    
    InterpretResult result = new InterpretResult();
    result.addWaypoint(pointFromLoc(lat, lng));
    result.setText("Lat: " + ((double)lat)/1e6 + ", " + "Long: " + ((double)lng)/1e6);
    
    InterpretedInfo info = new InterpretedInfo();
    info.addSuggestion(result);
    
    return info;
  }

  public InterpretedInfo interpret(String input, boolean type) {
    InterpretedInfo info = new InterpretedInfo();
    info.setInput(input);
    preprocessInput(info);
    info.type = type;
    
    //DEBUG visualizer
    if (input.matches("#\\d+,\\d+,\\d+")) {
      input = input.substring(1);
      String[] indexStrings = input.split(",");
      int buildingIndex = Integer.parseInt(indexStrings[0]);
      int floorIndex = Integer.parseInt(indexStrings[1]);
      int roomIndex = Integer.parseInt(indexStrings[2]);
      
      info.addSuggestion(new InterpretResult(new WaypointID(buildingIndex, floorIndex, roomIndex)));
      return info;
    }
    
    if (input.startsWith("lat:")) {
      int lngStringIndex = input.indexOf(" lng:");
      int lat = (int)(Double.parseDouble(input.substring(4, lngStringIndex)) * 1E6);
      int lng = (int)(Double.parseDouble(input.substring(lngStringIndex + 5)) * 1E6);
      return interpretLatLng(lat, lng);
    }
    
    //match input to a building, floor, and room
    ArrayList<InterpretedInfo> infoList = parse(info, STATE_BUILDING);
    for(int i = 0; i < infoList.size(); i++) {
      info.addSuggestions(infoList.get(i).getSuggestions());
    }
    
    //match the input to a location
    if (infoList.size() == 0)
      matchCampusLocations(info);
    
    //combineMultiples(info);
    checkForExactMatch(info);
    
    return info;
  }
  
  private void preprocessInput(InterpretedInfo info) {
    String input = info.getInput().toLowerCase().trim();
    
    String[] stringsToRemove = {"hall", "room", "#", "floor", " "};
    
    //TODO: Examine if important to have spaces
    for (int i = 0; i < stringsToRemove.length; i++) {
      input = input.replace(stringsToRemove[i], "");
    }
    
//    int startParenthesis = input.indexOf("(");
//    int endParenthesis = input.indexOf(")");
//    if (startParenthesis > -1 && endParenthesis > -1) {
//      input = input.substring(0, startParenthesis) + input.substring(endParenthesis + 1, input.length());
//    }
    
    info.setInput(input);
  }
  
//  private void combineMultiples(InterpretedInfo info) {
//    ArrayList<InterpretResult> suggestions = info.getSuggestions();
//    //The runtime complexity of this is not great, but the size of the collection is tiny
//    for (int i = 0; i < suggestions.size(); i++) {
//      InterpretResult s1 = suggestions.get(i);
//      for (int j = i + 1; j < suggestions.size(); j++) {
//        InterpretResult s2 = suggestions.get(j);
//        if (s1.getText().equals(s2.getText())) {
//          s1.addWaypoints(s2.getWaypoints());
//          suggestions.remove(j);
//          j--;
//        }
//      }
//    }
//  }
  
  //if there is an exact match then make that the only suggestion
  private void checkForExactMatch(InterpretedInfo info) {
    ArrayList<InterpretResult> suggestions = info.getSuggestions(); 
    for (int i = 0; i < suggestions.size(); i++) {
      InterpretResult result = suggestions.get(i);
      if (result.getText().toLowerCase().equals(info.getOriginalInput().toLowerCase())) {
        suggestions.clear();
        suggestions.add(result);
        return;
      }
    }
  }

  private ArrayList<InterpretedInfo> parse(InterpretedInfo info, int state) {
    ArrayList<InterpretedInfo> infoList = new ArrayList<InterpretedInfo>();
    if (info.getInput().equals("")) {
      return infoList;
    }
    else {
      int numFloors = -1;
      if (info.buildingIndex != -1)
        numFloors = campus.buildings[info.buildingIndex].floors.length;
      
      switch(state) {
      case STATE_BUILDING:
        infoList.addAll(parseBuilding(info));
        break;

      case STATE_FLOOR_OR_ROOM:
        if (numFloors < 10) {
          InterpretedInfo roomInfo = parseRoom(info);
          if (roomInfo.getSuggestions().size() > 0)
            infoList.add(roomInfo);
        }
        else {
          infoList.addAll(parseFloor(info, numFloors));
        }
        break;

      case STATE_ROOM:
        if (numFloors < 10) {
          return infoList;
        }
        else {
          InterpretedInfo roomInfo = parseRoom(info);
          if (roomInfo.getSuggestions().size() > 0)
            infoList.add(roomInfo);
        }
        break;
      }
    }

    return infoList;
  }

  private ArrayList<InterpretedInfo> parseBuilding(InterpretedInfo info) {
    InterpretedInfo newInfo = null;
    ArrayList<InterpretedInfo> infoList = new ArrayList<InterpretedInfo>();
    for (int i = 0; i < campus.buildings.length; i++) { 
      //TODO: MAKE AUTHORING TOOL MAKE ACRONYMS HAVE NO SPACES
      String acronym = campus.buildings[i].acronym.toLowerCase().replaceAll(" ", "");
      //cut the acronym off the start or the end
      newInfo = tryBuildingStartAndEnd(info, acronym, i);

      if (newInfo != null) {
        infoList.addAll(parse(newInfo, STATE_FLOOR_OR_ROOM));
      }

      for (int j = 0; j < campus.buildings[i].names.length; j++) {
        String name = campus.buildings[i].names[j].toLowerCase().trim().replaceAll(" ", "");
        newInfo = tryBuildingStartAndEnd(info, name, i);
        if (newInfo != null) {
          infoList.addAll(parse(newInfo, STATE_FLOOR_OR_ROOM));
        }
      }
    }

    //this returns all successful interprets
    return infoList;
  }

  private InterpretedInfo tryBuildingStartAndEnd(InterpretedInfo info, String name, int buildingIndex) {
    InterpretedInfo newInfo = null;
    if (info.getInput().startsWith(name) && !name.equals("")) {
      newInfo = 
        new InterpretedInfo(info, 
            info.getInput().substring(name.length()).trim(), //input string with acronym removed 
            buildingIndex, -1);
    }
    else if (info.getInput().endsWith(name) && !name.equals("")) {
      newInfo = 
        new InterpretedInfo(info, 
            info.getInput().substring(0, info.getInput().length() - name.length()).trim(), //input string with acronym removed 
            buildingIndex, -1);
    }
    return newInfo;
  }

  private InterpretedInfo tryFloorStart(InterpretedInfo info, String name, int floorIndex) {
    InterpretedInfo newInfo = null;
    if (info.getInput().startsWith(name) && !name.equals("")) {
      newInfo = 
        new InterpretedInfo(info, 
            info.getInput().substring(name.length()).trim(), //input string with acronym removed 
            info.buildingIndex, floorIndex);
    }
    return newInfo;
  }

  /* This takes the info from the parseBuilding through the parse recursion */
  private ArrayList<InterpretedInfo> parseFloor(InterpretedInfo info, int numFloors) {
    InterpretedInfo newInfo = null;
    ArrayList<InterpretedInfo> infoList = new ArrayList<InterpretedInfo>();

    for (int i = 0; i < campus.buildings[info.buildingIndex].floors.length; i++) { 
      String floorName = campus.buildings[info.buildingIndex].floors[i].name.toLowerCase();
      //cut the floor name off the start of the input
      newInfo = tryFloorStart(info, floorName, i);
      
      if (newInfo != null) {
        infoList.addAll(parse(newInfo, STATE_ROOM));
      }
    }

    //this list is all possibilities for floors in a building (info.buildingIndex)
    return infoList;
  }  

  private InterpretedInfo parseRoom(InterpretedInfo info) {
    InterpretedInfo newInfo = new InterpretedInfo(info);
    int buildingIndex = info.buildingIndex;
    int floorIndex = info.floorIndex;
    
    if (loadedNodes.size() > 0)
      loadedNodes.clear();
    if (info.floorIndex == -1) {
      RouteFinder.loadBuilding(campus.buildings[buildingIndex], campus, loadedNodes);
    }
    else {
      DataParser.parseFile(campus.getFloorFile(buildingIndex, floorIndex, "ncmg"), loadedNodes, Campus.fileHandler);
    }
    
    StringBuilder inputRem = new StringBuilder(info.getInput());
    int originalLength = inputRem.length();
    boolean foundSome = false;

    //Start by removing no characters for the input (k=0)
    Outer: for (int k = 0; k < originalLength-1 && inputRem.length() >= 2; k++) {
      
      //For each of the points in loadedNodes
      for (Entry<WaypointID, GraphNode<Waypoint2D>> e : loadedNodes.entrySet()) {
        
        if (e.getValue().data.getLabel().toLowerCase().contains(inputRem.toString())){
            //&& e.getKey().getFloorIndex() == floorIndex
            //&& e.getKey().getBuildingIndex() == buildingIndex) {
          
          foundSome = true;

          //Construct end text and determine show dialog and modified additions
          for (String token : e.getValue().data.getLabel().toLowerCase().split(",")) {
            if (token.contains(inputRem.toString())) {
              int b = e.getKey().getBuildingIndex();
              
              InterpretResult result = new InterpretResult();
              
              result.addWaypoint(new WaypointID(buildingIndex, e.getKey().getFloorIndex(), e.getKey().getPointIndex()));
              
              String buildingAcronym = campus.buildings[b].acronym;
              result.setText(buildingAcronym + " " + token);
              
              newInfo.addSuggestion(result);
              
//              if (!info.getInput().toString().equals(token)) {
//                newInfo.addSuggestion(buildingAcronym + " " + token);  
//              }
            }
          }
          
          
        }
      }
      if (foundSome)
        break Outer;
      inputRem.deleteCharAt(inputRem.length() - 1); //remove a character (and then increment k in the for loop)
    }
    
    return newInfo;
  }  

  /*
   * Checks if the input can be associated with any campus locations
   * If so, it adds those locations to the info's suggestions
   */
  private void matchCampusLocations(InterpretedInfo info) {
    for (int i = 0; i < campus.location_types.length; i++) {
      for (int j = 0; j < campus.location_types[i].locations.length; j++) {
        for (int k = 0; k < campus.location_types[i].locations[j].names.length; k++) {
          String locationName = campus.location_types[i].locations[j].names[k];
          String locNameForComparison = locationName.toLowerCase().trim().replaceAll(" ", ""); 
          if (locNameForComparison.contains(info.getInput()) || info.getInput().contains(locNameForComparison)) {
            
            WaypointID[] locationWaypoints = campus.location_types[i].locations[j].waypoints;
            
            InterpretResult result = new InterpretResult();
            result.setText(locationName);
            if (info.type == InterpretedInfo.END) {
              for (int w = 0; w < locationWaypoints.length; w++) {
                result.addWaypoint(locationWaypoints[w]);
              }
            }
            else {
              result.addWaypoint(locationWaypoints[0]);
            }
            
            info.addSuggestion(result);
          }
        }
      }
    }
  }

  private WaypointID pointFromLoc(int lat, int lng) {
    loadedNodes = new HashMap<WaypointID, GraphNode<Waypoint2D>>();
    LatLngPoint point = new LatLngPoint(lat, lng);


    double closest = Double.MAX_VALUE;
    WaypointID closestID = null;

    RouteFinder.loadOutsideBuildings(campus, loadedNodes);

    for (Entry<WaypointID, GraphNode<Waypoint2D>> e: loadedNodes.entrySet()) {
      Waypoint2D point2D = e.getValue().data;

      double dist = DistanceCalculator.distance(point, point2D.getPoint());
      if (dist < closest) {
        closest = dist;
        closestID = point2D.getId();
      }
    }

    return closestID;
  }

  public boolean startsWithRoom(String input) {
    return input.length() > 1 && Character.isDigit(input.charAt(1));
  }
}




Java Source Code List

com.mapyst.FileHandlerInterface.java
com.mapyst.android.AndroidFileHandler.java
com.mapyst.android.CampusLoader.java
com.mapyst.android.Compass.java
com.mapyst.android.DirectionsList.java
com.mapyst.android.Images.java
com.mapyst.android.LocationFinder.java
com.mapyst.android.MainScreen.java
com.mapyst.android.Mapyst.java
com.mapyst.android.Settings.java
com.mapyst.android.Splash.java
com.mapyst.android.asynctask.CampusLoaderTaskPrefs.java
com.mapyst.android.asynctask.CampusLoaderTask.java
com.mapyst.android.asynctask.RouteMakerTaskPrefs.java
com.mapyst.android.asynctask.RouteMakerTask.java
com.mapyst.android.ui.CenteredToastFactory.java
com.mapyst.android.ui.CompassOverlay.java
com.mapyst.android.ui.DirectionIcon.java
com.mapyst.android.ui.DirectionsListAdapter.java
com.mapyst.android.ui.DirectionsListItem.java
com.mapyst.android.ui.DrawingHelpers.java
com.mapyst.android.ui.Icon.java
com.mapyst.android.ui.LocationsAdapter.java
com.mapyst.android.ui.LocationsListView.java
com.mapyst.android.ui.RouteMapOverlay.java
com.mapyst.android.ui.SlidingScrollView.java
com.mapyst.android.ui.map.AnimatedMapZoomer.java
com.mapyst.android.ui.map.LocationBalloon.java
com.mapyst.android.ui.map.LocationChooserOverlay.java
com.mapyst.android.ui.map.MapUtils.java
com.mapyst.android.ui.map.MapViewLimiter.java
com.mapyst.android.ui.map.MapViewMover.java
com.mapyst.android.ui.map.OnMapTouchLimiterListener.java
com.mapyst.android.ui.map.PriorityMapView.java
com.mapyst.android.ui.map.ViewItemOverlay.java
com.mapyst.campus.Building.java
com.mapyst.campus.Campus.java
com.mapyst.campus.Floor.java
com.mapyst.campus.ListOfCampuses.java
com.mapyst.campus.Location_Type.java
com.mapyst.campus.Location.java
com.mapyst.route.Arc.java
com.mapyst.route.DataParser.java
com.mapyst.route.Direction.java
com.mapyst.route.DistanceCalculator.java
com.mapyst.route.GraphNode.java
com.mapyst.route.InterpretResult.java
com.mapyst.route.InterpretedInfo.java
com.mapyst.route.Interpreter.java
com.mapyst.route.LatLngPoint.java
com.mapyst.route.Prioritizable.java
com.mapyst.route.PriorityQ.java
com.mapyst.route.RouteFinder.java
com.mapyst.route.RoutePreferences.java
com.mapyst.route.Route.java
com.mapyst.route.ShortestPath.java
com.mapyst.route.Waypoint2D.java
com.mapyst.route.WaypointID.java
com.markupartist.android.widget.ActionBar.java
com.markupartist.android.widget.ScrollingTextView.java