package me.osm.gazetteer.web.imp;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONArray;
import org.json.JSONObject;
public class DefaultWeightBuilder implements ObjectsWeightBuilder {
private static final Map<String, Integer> baseLevels = new HashMap<String, Integer>();
static {
baseLevels.put("poipnt", 1 * 100);
baseLevels.put("adrpnt", 2 * 100);
baseLevels.put("neighbour", 3 * 100);
//ignore hghways, use hghnets
baseLevels.put("hghway", 4 * 100 - 10);
baseLevels.put("hghnet", 4 * 100);
baseLevels.put("city", 5 * 100 + 50);
baseLevels.put("place:town", 5 * 100 + 40);
baseLevels.put("place:village", 5 * 100 + 30);
baseLevels.put("place:hamlet", 5 * 100 + 20);
//towns inside city like Zelenograd inside Moscow
baseLevels.put("place:district", 5 * 100);
baseLevels.put("district", 6 * 100);
baseLevels.put("state", 7 * 100);
baseLevels.put("country", 8 * 100);
}
@Override
public int weight(JSONObject obj) {
String type = obj.optString("type");
JSONObject address = obj.optJSONObject("address");
Map<String, JSONObject> levels = mapLevels(address);
String baseType = getBaseType(type, obj, levels, address);
Integer baseScore = baseLevels.get(baseType);
obj.put("weight_base_type", baseType);
if(baseScore != null) {
return baseScore;
}
return 0;
}
private String getBaseType(String type, JSONObject subj, Map<String, JSONObject> levels, JSONObject address) {
switch(type) {
case "poipnt": return type;
case "adrpnt": return type;
case "hghway": return type;
case "hghnet": return type;
case "nbhdln": return "neighbour";
}
//admbnd plcpnt plcdln
int alvl = -1;
String place = null;
JSONObject tags = subj.optJSONObject("tags");
if(tags != null) {
Object adminLevel = tags.opt("admin_level");
if(adminLevel != null) {
if(adminLevel instanceof Integer) {
alvl = (Integer) adminLevel;
}
if(adminLevel instanceof String) {
alvl = Integer.valueOf((String) adminLevel);
}
}
place = StringUtils.stripToNull(tags.optString("place"));
}
if(alvl == 8) {
return "city";
}
if(alvl == 6 || alvl == 7) {
return "district";
}
if(alvl == 4 || alvl == 5) {
return "state";
}
if(alvl == 2) {
return "country";
}
if("city".equals(place)) {
return "city";
}
if(alvl > 8) {
return "neighbour";
}
if("neighbourhood".equals(place) || "quarter".equals(place)) {
return "neighbour";
}
//остались города и деревни (place), но если они внутри более крупного города
//то классифицируем их как район.
//place: hamlet village town
if("town".equals(place)) {
if(levels.containsKey("boundary:8") || levels.containsKey("place:city")) {
return "place:district";
}
return "place:town";
}
if("village".equals(place)) {
if(levels.containsKey("boundary:8") || levels.containsKey("place:city") || levels.containsKey("place:town")) {
return "place:district";
}
return "place:village";
}
if("hamlet".equals(place)) {
if(levels.containsKey("boundary:8") || levels.containsKey("place:city")
|| levels.containsKey("place:town")) {
return "place:district";
}
return "place:hamlet";
}
return null;
}
private Map<String, JSONObject> mapLevels(JSONObject address) {
Map<String, JSONObject> levels = new HashMap<String, JSONObject>();
if(address != null) {
JSONArray parts = address.getJSONArray("parts");
for(int i = 0; i < parts.length(); i++) {
JSONObject part = parts.getJSONObject(i);
String lvl = part.optString("lvl");
if(lvl != null) {
levels.put(lvl, part);
}
}
}
return levels;
}
}