Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multi download #1901

Merged
merged 66 commits into from
Oct 29, 2020
Merged
Show file tree
Hide file tree
Changes from 58 commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
8264eeb
performance improvement in TagFilterExpression
westnordost Jun 17, 2020
8b2d513
replace OsmApiElementGeometryCreator
westnordost Jun 17, 2020
be49de0
remove wrong isApplicableTo
westnordost Jun 17, 2020
e028bc0
add putAll function to DownloadedTilesDao
westnordost Jun 17, 2020
9cc0603
MapData implements Iterable
westnordost Jun 17, 2020
67f8103
change signature of OsmQuestController.replaceInBBox
westnordost Jun 17, 2020
d9058c2
generalize DownloadProgressListener
westnordost Jun 17, 2020
61e6f9f
generalize DownloadProgressListener (fix)
westnordost Jun 17, 2020
d18b77b
multi quest downloader WIP (see todos)
westnordost Jun 17, 2020
1c86f67
Merge branch 'master' into multi-download
westnordost Oct 15, 2020
e2be084
merge wip
westnordost Oct 16, 2020
6ee3c7d
rename extension functions on MapDataApi
westnordost Oct 16, 2020
819b151
fix tests
westnordost Oct 16, 2020
299aa39
use neutral icon
westnordost Oct 17, 2020
44487d2
correct location of AddRoadName...
westnordost Oct 17, 2020
fc96c40
finish implementing OsmApiQuestDownloader
westnordost Oct 17, 2020
41c06c1
refactor
westnordost Oct 17, 2020
918856e
added tests to refactor
westnordost Oct 19, 2020
96f0138
add tests
westnordost Oct 19, 2020
61a45d0
add comment
westnordost Oct 19, 2020
a998e1e
separate MapDataQuests from Downloader quests
westnordost Oct 21, 2020
f04131c
add tests
westnordost Oct 21, 2020
4214dee
AddHousenumber: analyze locally
westnordost Oct 21, 2020
934fd91
add tests for housenumber quest creation
westnordost Oct 21, 2020
cdb81b8
allow creation of incomplete element geometry (for relations)
westnordost Oct 22, 2020
218fbd7
don't require full relation geometry for quest analysis; multithreading
westnordost Oct 22, 2020
c37e6e6
delete unsolved quests after 14 days, mark downloaded data as old aft…
westnordost Oct 22, 2020
6a6cd31
make sure road suggestion data is deleted (together with the quests) …
westnordost Oct 22, 2020
2b7afd2
convert AddAddressStreet and AddRoadName
westnordost Oct 22, 2020
b8ab214
convert suspected oneway quest
westnordost Oct 22, 2020
6eeea69
fix nullpointer
westnordost Oct 23, 2020
e15d64d
remove unused code
westnordost Oct 23, 2020
eef42eb
Merge branch 'master' into multi-download
westnordost Oct 24, 2020
8f3e2cb
remove unused imports
westnordost Oct 24, 2020
ffbdbdd
convert AddRecyclingcontainerMaterials quest
westnordost Oct 24, 2020
767348b
getApplicableElements may be iterable
westnordost Oct 24, 2020
86eb095
fix tests
westnordost Oct 24, 2020
e72e167
add polygon area function
westnordost Oct 25, 2020
01de385
convert forest leaf type quest
westnordost Oct 25, 2020
2bf1c78
add functions to SphericalEarthMath
westnordost Oct 26, 2020
28346a9
convert sidewalk quest
westnordost Oct 26, 2020
b019327
convert cycleway quest
westnordost Oct 26, 2020
35a1f6e
remove Overpass-stuff that is unnecessary now
westnordost Oct 26, 2020
820c52f
use different solution than ResurveyIntervalsStore
westnordost Oct 26, 2020
612a78d
element filter expression parser can be a static function
westnordost Oct 26, 2020
6413787
update osmapi dependency
westnordost Oct 27, 2020
9dcba04
discard Changeset information on parsed elements right away
westnordost Oct 27, 2020
d9bbeff
remove QuestDownloader stuff
westnordost Oct 27, 2020
5d5451f
remove limiting number of quest types for download
westnordost Oct 27, 2020
3ea7104
put road name suggestions into DB in one transaction
westnordost Oct 27, 2020
48ff1d2
decrease download areas
westnordost Oct 27, 2020
54b1c9d
auto sync option now only controls the upload
westnordost Oct 28, 2020
1b14f9a
rework auto sync download strategies
westnordost Oct 28, 2020
1e4c769
rename auto-sync
westnordost Oct 28, 2020
0de9602
reduce debug level
westnordost Oct 28, 2020
d9bf598
reduce DownloadTilesDao functionality/complexity
westnordost Oct 28, 2020
d0a93ed
remove OsmMapDataQuestType again
westnordost Oct 28, 2020
6f8cf82
nicer logging
westnordost Oct 28, 2020
e458b3a
correct some comments
westnordost Oct 29, 2020
09a919d
fix possible division by zero
westnordost Oct 29, 2020
bc8ba7e
formatting
westnordost Oct 29, 2020
16c336e
eliminate ElementEligibleForOsmQuestChecker
westnordost Oct 29, 2020
43837d1
remove MIN_DOWNLOADABLE_RADIUS_IN_METERS
westnordost Oct 29, 2020
0d32768
shortcut: don't create geometry when not needed
westnordost Oct 29, 2020
0134cb2
fix test
westnordost Oct 29, 2020
d082015
Merge branch 'master' into multi-download
westnordost Oct 29, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/quest-suggestion.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ If you are not sure about how one condition applies to your suggestion or you ha
### Ideas for implementation
<!-- If you do not have any, just delete this part. ;) -->

<!-- If you have any idea for how elements should be selected, add it here. Possibly include an overpass-api query if you are sure what you do. -->
<!-- If you have any idea for how elements should be selected, add it here. -->
**Element selection:**

<!-- If you have any idea whether metadata per country is needed, add it here. If you even have ideas, where to get this data from, you can of course also mention it! -->
Expand Down
17 changes: 0 additions & 17 deletions ARCHITECTURE.md

This file was deleted.

15 changes: 4 additions & 11 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,6 @@ configurations {
all {
exclude(group = "net.sf.kxml", module = "kxml2")
}

compile.configure {
exclude(group = "org.jetbrains", module = "annotations")
exclude(group = "com.intellij", module = "annotations")
exclude(group = "org.intellij", module = "annotations")
}
}

dependencies {
Expand Down Expand Up @@ -146,11 +140,10 @@ dependencies {
// finding a name for a feature without a name tag
implementation("de.westnordost:osmfeatures-android:1.1")
// talking with the OSM API
implementation("de.westnordost:osmapi-overpass:1.1")
implementation("de.westnordost:osmapi-map:1.2")
implementation("de.westnordost:osmapi-changesets:1.2")
implementation("de.westnordost:osmapi-notes:1.1")
implementation("de.westnordost:osmapi-user:1.1")
implementation("de.westnordost:osmapi-map:1.3")
implementation("de.westnordost:osmapi-changesets:1.3")
implementation("de.westnordost:osmapi-notes:1.2")
implementation("de.westnordost:osmapi-user:1.2")

// widgets
implementation("androidx.viewpager2:viewpager2:1.0.0")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import org.junit.Before
import org.junit.Test

import de.westnordost.streetcomplete.data.ApplicationDbTestCase
import de.westnordost.streetcomplete.ktx.containsExactlyInAnyOrder
import de.westnordost.streetcomplete.util.Tile
import de.westnordost.streetcomplete.util.TilesRect

Expand Down Expand Up @@ -76,6 +77,6 @@ class DownloadedTilesDaoTest : ApplicationDbTestCase() {
check = dao.get(r(0, 0, 6, 6), 0)
assertTrue(check.isEmpty())
}

private fun r(left: Int, top: Int, right: Int, bottom: Int) = TilesRect(left, top, right, bottom)
}
Original file line number Diff line number Diff line change
Expand Up @@ -204,13 +204,13 @@ private val TEST_QUEST_TYPE = TestQuestType()
private val TEST_QUEST_TYPE2 = TestQuestType2()

private fun create(
questType: OsmElementQuestType<*> = TEST_QUEST_TYPE,
elementType: Element.Type = Element.Type.NODE,
elementId: Long = 1,
status: QuestStatus = QuestStatus.NEW,
geometry: ElementGeometry = ElementPointGeometry(OsmLatLon(5.0, 5.0)),
changes: StringMapChanges? = null,
changesSource: String? = null
questType: OsmElementQuestType<*> = TEST_QUEST_TYPE,
elementType: Element.Type = Element.Type.NODE,
elementId: Long = 1,
status: QuestStatus = QuestStatus.NEW,
geometry: ElementGeometry = ElementPointGeometry(OsmLatLon(5.0, 5.0)),
changes: StringMapChanges? = null,
changesSource: String? = null
) = OsmQuest(
null, questType, elementType, elementId, status, changes, changesSource, Date(), geometry
)
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
package de.westnordost.streetcomplete.data.osm.osmquest

import de.westnordost.osmapi.map.data.BoundingBox
import de.westnordost.osmapi.map.MapDataWithGeometry
import de.westnordost.osmapi.map.data.Element
import de.westnordost.streetcomplete.data.osm.changes.StringMapChangesBuilder
import de.westnordost.streetcomplete.data.osm.elementgeometry.ElementGeometry
import de.westnordost.streetcomplete.quests.AbstractQuestAnswerFragment

open class TestQuestType : OsmElementQuestType<String> {

override fun getTitle(tags: Map<String, String>) = 0
override fun download(bbox: BoundingBox, handler: (element: Element, geometry: ElementGeometry?) -> Unit) = false
override fun isApplicableTo(element: Element):Boolean? = null
override fun applyAnswerTo(answer: String, changes: StringMapChangesBuilder) {}
override val icon = 0
override fun createForm(): AbstractQuestAnswerFragment<String> = object : AbstractQuestAnswerFragment<String>() {}
override val commitMessage = ""
override fun getApplicableElements(mapData: MapDataWithGeometry) = emptyList<Element>()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package de.westnordost.osmapi.map

import de.westnordost.osmapi.changesets.Changeset
import de.westnordost.osmapi.map.data.*
import java.util.*

/** Same as OsmMapDataFactory only that it throws away the Changeset data included in the OSM
* response */
class LightweightOsmMapDataFactory : MapDataFactory {
override fun createNode(
id: Long, version: Int, lat: Double, lon: Double, tags: MutableMap<String, String>?,
changeset: Changeset?, dateEdited: Date?
): Node = OsmNode(id, version, lat, lon, tags, null, dateEdited)

override fun createWay(
id: Long, version: Int, nodes: MutableList<Long>, tags: MutableMap<String, String>?,
changeset: Changeset?, dateEdited: Date?
): Way = OsmWay(id, version, nodes, tags, null, dateEdited)

override fun createRelation(
id: Long, version: Int, members: MutableList<RelationMember>,
tags: MutableMap<String, String>?, changeset: Changeset?, dateEdited: Date?
): Relation = OsmRelation(id, version, members, tags, null, dateEdited)

override fun createRelationMember(
ref: Long, role: String?, type: Element.Type
): RelationMember = OsmRelationMember(ref, role, type)
}
85 changes: 85 additions & 0 deletions app/src/main/java/de/westnordost/osmapi/map/MapData.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package de.westnordost.osmapi.map

import de.westnordost.osmapi.map.data.*
import de.westnordost.osmapi.map.handler.MapDataHandler
import de.westnordost.streetcomplete.data.osm.elementgeometry.ElementGeometry
import de.westnordost.streetcomplete.data.osm.elementgeometry.ElementPointGeometry
import de.westnordost.streetcomplete.util.MultiIterable

interface MapDataWithGeometry : MapData {
fun getNodeGeometry(id: Long): ElementPointGeometry?
fun getWayGeometry(id: Long): ElementGeometry?
fun getRelationGeometry(id: Long): ElementGeometry?

fun getGeometry(elementType: Element.Type, id: Long): ElementGeometry? = when(elementType) {
Element.Type.NODE -> getNodeGeometry(id)
Element.Type.WAY -> getWayGeometry(id)
Element.Type.RELATION -> getRelationGeometry(id)
}
}

interface MapData : Iterable<Element> {
val nodes: Collection<Node>
val ways: Collection<Way>
val relations: Collection<Relation>
val boundingBox: BoundingBox?

fun getNode(id: Long): Node?
fun getWay(id: Long): Way?
fun getRelation(id: Long): Relation?
}

open class MutableMapData : MapData, MapDataHandler {

protected val nodesById: MutableMap<Long, Node> = mutableMapOf()
protected val waysById: MutableMap<Long, Way> = mutableMapOf()
protected val relationsById: MutableMap<Long, Relation> = mutableMapOf()
override var boundingBox: BoundingBox? = null
protected set

override fun handle(bounds: BoundingBox) { boundingBox = bounds }
override fun handle(node: Node) { nodesById[node.id] = node }
override fun handle(way: Way) { waysById[way.id] = way }
override fun handle(relation: Relation) { relationsById[relation.id] = relation }

override val nodes get() = nodesById.values
override val ways get() = waysById.values
override val relations get() = relationsById.values

override fun getNode(id: Long) = nodesById[id]
override fun getWay(id: Long) = waysById[id]
override fun getRelation(id: Long) = relationsById[id]

fun addAll(elements: Iterable<Element>) {
for (element in elements) {
when(element) {
is Node -> nodesById[element.id] = element
is Way -> waysById[element.id] = element
is Relation -> relationsById[element.id] = element
}
}
}

override fun iterator(): Iterator<Element> {
val elements = MultiIterable<Element>()
elements.add(nodes)
elements.add(ways)
elements.add(relations)
return elements.iterator()
}
}

fun MapData.isRelationComplete(id: Long): Boolean =
getRelation(id)?.members?.all { member ->
when (member.type!!) {
Element.Type.NODE -> getNode(member.ref) != null
Element.Type.WAY -> getWay(member.ref) != null && isWayComplete(member.ref)
/* not being recursive here is deliberate. sub-relations are considered not relevant
for the element geometry in StreetComplete (and OSM API call to get a "complete"
relation also does not include sub-relations) */
Element.Type.RELATION -> getRelation(member.ref) != null
}
} ?: false

fun MapData.isWayComplete(id: Long): Boolean =
getWay(id)?.nodeIds?.all { getNode(it) != null } ?: false
22 changes: 22 additions & 0 deletions app/src/main/java/de/westnordost/osmapi/map/MapDataApi.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package de.westnordost.osmapi.map

import de.westnordost.osmapi.map.data.BoundingBox
import de.westnordost.streetcomplete.data.MapDataApi

fun MapDataApi.getMap(bounds: BoundingBox): MapData {
val result = MutableMapData()
getMap(bounds, result)
return result
}

fun MapDataApi.getWayComplete(id: Long): MapData {
val result = MutableMapData()
getWayComplete(id, result)
return result
}

fun MapDataApi.getRelationComplete(id: Long): MapData {
val result = MutableMapData()
getRelationComplete(id, result)
return result
}
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ interface ApplicationComponent {
fun inject(undoButtonFragment: UndoButtonFragment)
fun inject(uploadButtonFragment: UploadButtonFragment)
fun inject(answersCounterFragment: AnswersCounterFragment)
fun inject(questDownloadProgressFragment: QuestDownloadProgressFragment)
fun inject(downloadProgressFragment: DownloadProgressFragment)
fun inject(questStatisticsByCountryFragment: QuestStatisticsByCountryFragment)
fun inject(questStatisticsByQuestTypeFragment: QuestStatisticsByQuestTypeFragment)
fun inject(privacyStatementFragment: PrivacyStatementFragment)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,23 @@ public class ApplicationConstants
QUESTTYPE_TAG_KEY = NAME + ":quest_type";

public final static double
MAX_DOWNLOADABLE_AREA_IN_SQKM = 20,
MIN_DOWNLOADABLE_AREA_IN_SQKM = 1;
MAX_DOWNLOADABLE_AREA_IN_SQKM = 10,
MIN_DOWNLOADABLE_AREA_IN_SQKM = 0.1;

public final static double MIN_DOWNLOADABLE_RADIUS_IN_METERS = 600;

public final static String DATABASE_NAME = "streetcomplete.db";

public final static int QUEST_TILE_ZOOM = 14;
public final static int QUEST_TILE_ZOOM = 16;

public final static int NOTE_MIN_ZOOM = 15;

/** How many quests to download when pressing manually on "download quests" */
public final static int MANUAL_DOWNLOAD_QUEST_TYPE_COUNT = 10;

/** a "best before" duration for quests. Quests will not be downloaded again for any tile
* before the time expired */
public static final long REFRESH_QUESTS_AFTER = 7L*24*60*60*1000; // 1 week in ms
/** the duration after which quests will be deleted from the database if unsolved */
public static final long DELETE_UNSOLVED_QUESTS_AFTER = 1L*30*24*60*60*1000; // 1 months in ms
public static final long REFRESH_QUESTS_AFTER = 3L*24*60*60*1000; // 3 days in ms
/** the duration after which quests (and quest meta data) will be deleted from the database if
* unsolved and not refreshed in the meantime */
public static final long DELETE_UNSOLVED_QUESTS_AFTER = 14*24*60*60*1000; // 14 days in ms

/** the max age of the undo history - one cannot undo changes older than X */
public static final long MAX_QUEST_UNDO_HISTORY_AGE = 24*60*60*1000; // 1 day in ms
Expand Down
23 changes: 11 additions & 12 deletions app/src/main/java/de/westnordost/streetcomplete/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import android.os.Build;
import android.os.Bundle;
import androidx.annotation.AnyThread;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
Expand All @@ -28,9 +29,6 @@
import android.widget.TextView;
import android.widget.Toast;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.inject.Inject;

import de.westnordost.osmapi.common.errors.OsmApiException;
Expand All @@ -40,12 +38,13 @@
import de.westnordost.osmapi.map.data.LatLon;
import de.westnordost.osmapi.map.data.OsmLatLon;
import de.westnordost.streetcomplete.controls.NotificationButtonFragment;
import de.westnordost.streetcomplete.data.download.DownloadItem;
import de.westnordost.streetcomplete.data.notifications.Notification;
import de.westnordost.streetcomplete.data.notifications.NotificationsSource;
import de.westnordost.streetcomplete.data.quest.Quest;
import de.westnordost.streetcomplete.data.quest.QuestAutoSyncer;
import de.westnordost.streetcomplete.data.quest.QuestController;
import de.westnordost.streetcomplete.data.download.QuestDownloadProgressListener;
import de.westnordost.streetcomplete.data.download.DownloadProgressListener;
import de.westnordost.streetcomplete.data.download.QuestDownloadController;
import de.westnordost.streetcomplete.data.quest.QuestType;
import de.westnordost.streetcomplete.data.quest.UnsyncedChangesCountSource;
Expand Down Expand Up @@ -193,7 +192,7 @@ private void handleGeoUri()
questDownloadController.setShowNotification(false);

uploadController.addUploadProgressListener(uploadProgressListener);
questDownloadController.addQuestDownloadProgressListener(downloadProgressListener);
questDownloadController.addDownloadProgressListener(downloadProgressListener);

if(!hasAskedForLocation && !prefs.getBoolean(Prefs.LAST_LOCATION_REQUEST_DENIED, false))
{
Expand Down Expand Up @@ -253,7 +252,7 @@ public boolean dispatchKeyEvent(KeyEvent event) {
questDownloadController.setShowNotification(true);

uploadController.removeUploadProgressListener(uploadProgressListener);
questDownloadController.removeQuestDownloadProgressListener(downloadProgressListener);
questDownloadController.removeDownloadProgressListener(downloadProgressListener);
}

@Override public void onConfigurationChanged(@NonNull Configuration newConfig) {
Expand Down Expand Up @@ -346,14 +345,14 @@ else if(e instanceof OsmAuthorizationException)

/* ----------------------------- Download Progress listener -------------------------------- */

private final QuestDownloadProgressListener downloadProgressListener
= new QuestDownloadProgressListener()
private final DownloadProgressListener downloadProgressListener
= new DownloadProgressListener()
{
@AnyThread @Override public void onStarted() {}

@Override public void onFinished(@NotNull QuestType<?> questType) {}
@Override public void onFinished(@NonNull DownloadItem item) {}

@Override public void onStarted(@NotNull QuestType<?> questType) {}
@Override public void onStarted(@NonNull DownloadItem item) {}

@AnyThread @Override public void onError(@NonNull final Exception e)
{
Expand Down Expand Up @@ -386,7 +385,7 @@ else if(e instanceof OsmAuthorizationException)

/* --------------------------------- NotificationButtonFragment.Listener ---------------------------------- */

@Override public void onClickShowNotification(@NotNull Notification notification)
@Override public void onClickShowNotification(@NonNull Notification notification)
{
Fragment f = getSupportFragmentManager().findFragmentById(R.id.notifications_container_fragment);
((NotificationsContainerFragment) f).showNotification(notification);
Expand All @@ -399,7 +398,7 @@ else if(e instanceof OsmAuthorizationException)
ensureLoggedIn();
}

@Override public void onCreatedNote(@NotNull Point screenPosition)
@Override public void onCreatedNote(@NonNull Point screenPosition)
{
ensureLoggedIn();
}
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/java/de/westnordost/streetcomplete/Prefs.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ public class Prefs
KEEP_SCREEN_ON = "display.keepScreenOn",
UNGLUE_HINT_TIMES_SHOWN = "unglueHint.shown",
THEME_SELECT = "theme.select",
OVERPASS_URL = "overpass_url",
RESURVEY_INTERVALS = "quests.resurveyIntervals";


Expand All @@ -38,6 +37,7 @@ public class Prefs
LAST_PICKED_PREFIX = "imageListLastPicked.",
LAST_LOCATION_REQUEST_DENIED = "location.denied",
LAST_VERSION = "lastVersion",
LAST_VERSION_DATA = "lastVersion_data",
HAS_SHOWN_TUTORIAL = "hasShownTutorial";

public static final String HAS_SHOWN_UNDO_FUCKUP_WARNING = "alert.undo_fuckup_warning";
Expand Down
Loading