Skip to content

Commit

Permalink
Merge pull request #1145 from westnordost/#1131
Browse files Browse the repository at this point in the history
after upload, remove unanswered quests that are no longer applicable (#1131, #746)
  • Loading branch information
westnordost authored Jul 25, 2018
2 parents cf0414b + 8286cd8 commit 4b9fe82
Show file tree
Hide file tree
Showing 7 changed files with 203 additions and 126 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package de.westnordost.streetcomplete.data.osm;

import android.text.TextUtils;
import android.util.Log;

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

import javax.inject.Inject;
import javax.inject.Provider;

import de.westnordost.osmapi.map.data.BoundingBox;
import de.westnordost.osmapi.map.data.Element;
import de.westnordost.osmapi.map.data.LatLon;
import de.westnordost.streetcomplete.data.QuestStatus;
import de.westnordost.streetcomplete.data.QuestType;
import de.westnordost.streetcomplete.data.osm.persist.ElementGeometryDao;
import de.westnordost.streetcomplete.data.osm.persist.OsmQuestDao;
import de.westnordost.streetcomplete.data.osmnotes.OsmNoteQuestDao;

/** Manages creating new quests and removing quests that are no longer applicable for an OSM
* element locally */
public class OsmQuestGiver
{
private static final String TAG = "OsmQuestGiver";

private final OsmNoteQuestDao osmNoteQuestDb;
private final OsmQuestDao questDB;
private final ElementGeometryDao elementGeometryDB;
private final Provider<List<QuestType>> questTypesProvider;

@Inject public OsmQuestGiver(
OsmNoteQuestDao osmNoteQuestDb, OsmQuestDao questDB,
ElementGeometryDao elementGeometryDB, Provider<List<QuestType>> questTypesProvider)
{
this.osmNoteQuestDb = osmNoteQuestDb;
this.questDB = questDB;
this.elementGeometryDB = elementGeometryDB;
this.questTypesProvider = questTypesProvider;
}

public class QuestUpdates
{
public List<OsmQuest> createdQuests = new ArrayList<>();
public List<Long> removedQuestIds = new ArrayList<>();
}

public QuestUpdates updateQuests(Element element)
{
ElementGeometry geometry = elementGeometryDB.get(element.getType(), element.getId());
boolean hasNote = hasNoteAt(geometry.center);

QuestUpdates result = new QuestUpdates();

Map<QuestType, OsmQuest> currentQuests = getCurrentQuests(element);
List<String> createdQuestsLog = new ArrayList<>();
List<String> removedQuestsLog = new ArrayList<>();

for(QuestType questType : questTypesProvider.get())
{
if(!(questType instanceof OsmElementQuestType)) continue;
OsmElementQuestType osmQuestType = (OsmElementQuestType)questType;

Boolean appliesToElement = osmQuestType.isApplicableTo(element);
if(appliesToElement == null) continue;

boolean hasQuest = currentQuests.containsKey(osmQuestType);
if(appliesToElement && !hasQuest && !hasNote)
{
OsmQuest quest = new OsmQuest(osmQuestType, element.getType(), element.getId(), geometry);
result.createdQuests.add(quest);
createdQuestsLog.add(osmQuestType.getClass().getSimpleName());
}
if(!appliesToElement && hasQuest)
{
OsmQuest quest = currentQuests.get(osmQuestType);
// only remove "fresh" unanswered quests because answered/closed quests by definition
// do not apply to the element anymore. E.g. after adding the name to the street,
// there shan't be any AddRoadName quest for that street anymore
if(quest.getStatus() == QuestStatus.NEW)
{
result.removedQuestIds.add(quest.getId());
removedQuestsLog.add(osmQuestType.getClass().getSimpleName());
}
}
}

if(!result.createdQuests.isEmpty())
{
// Before new quests are unlocked, all reverted quests need to be removed for
// this element so that they can be created anew as the case may be
questDB.deleteAllReverted(element.getType(), element.getId());

questDB.addAll(result.createdQuests);

Log.d(TAG, "Created new quests for " + element.getType().name() + "#" + element.getId() + ": " +
TextUtils.join(", ", createdQuestsLog)
);
}
if(!result.removedQuestIds.isEmpty())
{
questDB.deleteAll(result.removedQuestIds);

Log.d(TAG, "Removed quests no longer applicable for " + element.getType().name() + "#" + element.getId() + ": " +
TextUtils.join(", ", removedQuestsLog)
);
}

return result;
}

private boolean hasNoteAt(LatLon pos)
{
BoundingBox bbox = new BoundingBox(pos, pos);
return !osmNoteQuestDb.getAllPositions(bbox).isEmpty();
}

private Map<QuestType, OsmQuest> getCurrentQuests(Element element)
{
List<OsmQuest> quests = questDB.getAll(null, null, null, element.getType(), element.getId());
Map<QuestType, OsmQuest> result = new HashMap<>(quests.size());
for (OsmQuest quest : quests)
{
if(quest.getStatus() == QuestStatus.REVERT) continue;
result.put(quest.getType(), quest);
}
return result;
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,13 @@
import de.westnordost.streetcomplete.Prefs;
import de.westnordost.streetcomplete.data.QuestGroup;
import de.westnordost.streetcomplete.data.QuestStatus;
import de.westnordost.streetcomplete.data.QuestType;
import de.westnordost.streetcomplete.data.VisibleQuestListener;
import de.westnordost.streetcomplete.data.changesets.OpenChangesetInfo;
import de.westnordost.streetcomplete.data.changesets.OpenChangesetKey;
import de.westnordost.streetcomplete.data.changesets.OpenChangesetsDao;
import de.westnordost.streetcomplete.data.osm.OsmElementQuestType;
import de.westnordost.streetcomplete.data.osm.OsmQuest;
import de.westnordost.streetcomplete.data.osm.OsmQuestUnlocker;
import de.westnordost.streetcomplete.data.osm.OsmQuestGiver;
import de.westnordost.streetcomplete.data.osm.changes.StringMapChanges;
import de.westnordost.streetcomplete.data.osm.persist.AOsmQuestDao;
import de.westnordost.streetcomplete.data.osm.persist.ElementGeometryDao;
Expand All @@ -58,9 +57,10 @@ public abstract class AOsmQuestChangesUpload
private final ChangesetsDao changesetsDao;
private final DownloadedTilesDao downloadedTilesDao;
private final SharedPreferences prefs;
private final OsmQuestUnlocker questUnlocker;
private final OsmQuestGiver questUnlocker;

private List<OsmQuest> unlockedQuests;
private List<OsmQuest> createdQuests;
private List<Long> removedQuestIds;
private VisibleQuestListener visibleQuestListener;

// The cache is just here so that uploading 500 quests of same quest type does not result in 500 DB requests.
Expand All @@ -71,7 +71,7 @@ public AOsmQuestChangesUpload(
ElementGeometryDao elementGeometryDB, QuestStatisticsDao statisticsDB,
OpenChangesetsDao openChangesetsDB, ChangesetsDao changesetsDao,
DownloadedTilesDao downloadedTilesDao, SharedPreferences prefs,
OsmQuestUnlocker questUnlocker)
OsmQuestGiver questUnlocker)
{
this.osmDao = osmDao;
this.questDB = questDB;
Expand All @@ -83,7 +83,8 @@ public AOsmQuestChangesUpload(
this.downloadedTilesDao = downloadedTilesDao;
this.prefs = prefs;
this.questUnlocker = questUnlocker;
unlockedQuests = new ArrayList<>();
createdQuests = new ArrayList<>();
removedQuestIds = new ArrayList<>();
}

public synchronized void setVisibleQuestListener(VisibleQuestListener visibleQuestListener)
Expand All @@ -95,7 +96,8 @@ public synchronized void upload(AtomicBoolean cancelState)
{
int commits = 0, obsolete = 0;
changesetIdsCache = new HashMap<>();
unlockedQuests = new ArrayList<>();
createdQuests.clear();
removedQuestIds.clear();

HashSet<OsmElementQuestType> uploadedQuestTypes = new HashSet<>();

Expand Down Expand Up @@ -127,14 +129,23 @@ public synchronized void upload(AtomicBoolean cancelState)

Log.i(TAG, logMsg);

if(!unlockedQuests.isEmpty())
if(!createdQuests.isEmpty())
{
int unlockedQuestsCount = unlockedQuests.size();
int createdQuestsCount = createdQuests.size();
if(visibleQuestListener != null)
{
visibleQuestListener.onQuestsCreated(unlockedQuests, QuestGroup.OSM);
visibleQuestListener.onQuestsCreated(createdQuests, QuestGroup.OSM);
}
Log.i(TAG, "Unlocked " + unlockedQuestsCount + " new quests");
Log.i(TAG, "Created " + createdQuestsCount + " new quests");
}
if(!removedQuestIds.isEmpty())
{
int removedQuestsCount = removedQuestIds.size();
if(visibleQuestListener != null)
{
visibleQuestListener.onQuestsRemoved(removedQuestIds, QuestGroup.OSM);
}
Log.i(TAG, "Removed " + removedQuestsCount + " quests which are no longer applicable");
}

closeOpenChangesets();
Expand Down Expand Up @@ -255,7 +266,9 @@ boolean uploadQuestChange(long changesetId, OsmQuest quest, Element element,
elementDB.put(updatedElement);
statisticsDB.addOne(quest.getType().getClass().getSimpleName());

unlockedQuests.addAll(questUnlocker.unlockNewQuests(updatedElement));
OsmQuestGiver.QuestUpdates questUpdates = questUnlocker.updateQuests(updatedElement);
createdQuests.addAll(questUpdates.createdQuests);
removedQuestIds.addAll(questUpdates.removedQuestIds);

return true;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
package de.westnordost.streetcomplete.data.osm.upload;

import android.content.SharedPreferences;
import android.util.Log;

import javax.inject.Inject;

import de.westnordost.osmapi.changesets.ChangesetsDao;
import de.westnordost.osmapi.map.data.Element;
import de.westnordost.streetcomplete.data.changesets.OpenChangesetsDao;
import de.westnordost.streetcomplete.data.osm.OsmQuest;
import de.westnordost.streetcomplete.data.osm.OsmQuestUnlocker;
import de.westnordost.streetcomplete.data.osm.OsmQuestGiver;
import de.westnordost.streetcomplete.data.osm.persist.ElementGeometryDao;
import de.westnordost.streetcomplete.data.osm.persist.MergedElementDao;
import de.westnordost.streetcomplete.data.osm.persist.OsmQuestDao;
Expand All @@ -24,7 +23,7 @@ public class OsmQuestChangesUpload extends AOsmQuestChangesUpload
ElementGeometryDao elementGeometryDB, QuestStatisticsDao statisticsDB,
OpenChangesetsDao openChangesetsDB, ChangesetsDao changesetsDao,
DownloadedTilesDao downloadedTilesDao, SharedPreferences prefs,
OsmQuestUnlocker questUnlocker)
OsmQuestGiver questUnlocker)
{
super(osmDao, questDB, elementDB, elementGeometryDB, statisticsDB, openChangesetsDB,
changesetsDao, downloadedTilesDao, prefs, questUnlocker);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import de.westnordost.osmapi.map.data.Element;
import de.westnordost.streetcomplete.data.changesets.OpenChangesetsDao;
import de.westnordost.streetcomplete.data.osm.OsmQuest;
import de.westnordost.streetcomplete.data.osm.OsmQuestUnlocker;
import de.westnordost.streetcomplete.data.osm.OsmQuestGiver;
import de.westnordost.streetcomplete.data.osm.persist.ElementGeometryDao;
import de.westnordost.streetcomplete.data.osm.persist.MergedElementDao;
import de.westnordost.streetcomplete.data.osm.persist.UndoOsmQuestDao;
Expand All @@ -23,7 +23,7 @@ public class UndoOsmQuestChangesUpload extends AOsmQuestChangesUpload
ElementGeometryDao elementGeometryDB, QuestStatisticsDao statisticsDB,
OpenChangesetsDao openChangesetsDB, ChangesetsDao changesetsDao,
DownloadedTilesDao downloadedTilesDao, SharedPreferences prefs,
OsmQuestUnlocker questUnlocker)
OsmQuestGiver questUnlocker)
{
super(osmDao, questDB, elementDB, elementGeometryDB, statisticsDB, openChangesetsDB,
changesetsDao, downloadedTilesDao, prefs, questUnlocker);
Expand Down
Loading

0 comments on commit 4b9fe82

Please sign in to comment.