Skip to content

Commit

Permalink
Merge pull request #3330 from finnishtransportagency/DROTH-4185_parti…
Browse files Browse the repository at this point in the history
…al_unknown_speed_limit

Droth 4185 partial unknown speed limit
  • Loading branch information
anttiahopeltositowise authored Oct 23, 2024
2 parents 71bffcb + 826aee6 commit 4affc04
Show file tree
Hide file tree
Showing 11 changed files with 131 additions and 41 deletions.
2 changes: 1 addition & 1 deletion UI/src/model/selectedSpeedLimit.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@
eventbus.trigger('speedLimit:saving');
var payloadContents = function() {
if (self.isUnknown()) {
return { newLimits: _.map(selection, function(s) { return _.pick(s, 'linkId', 'startMeasure', 'endMeasure'); }) };
return { newLimits: _.map(selection, function(s) { return _.pick(s, 'linkId', 'startMeasure', 'endMeasure', 'sideCode'); }) };
} else {
return { ids: _.map(selection, 'id') };
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1386,7 +1386,7 @@ class Digiroad2Api(val roadLinkService: RoadLinkService,
"track" -> extractIntValue(link.attributes, "TRACK"),
"startAddrMValue" -> extractLongValue(link.attributes, "START_ADDR"),
"endAddrMValue" -> extractLongValue(link.attributes, "END_ADDR"),
"administrativeClass" -> link.attributes.get("ROAD_ADMIN_CLASS"),
"administrativeClass" -> link.administrativeClass.value,
"municipalityCode" -> extractIntValue(link.attributes, "municipality"),
"constructionType" -> extractIntValue(link.attributes, "constructionType")
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -394,11 +394,12 @@ class AssetFiller {
dbAssets.map { dbAsset =>
val points = GeometryUtils.truncateGeometry3D(roadLink.geometry, dbAsset.startMeasure, dbAsset.endMeasure)
val endPoints = GeometryUtils.geometryEndpoints(points)
val attributesToUse = Map("municipality" -> roadLink.municipalityCode, "constructionType" -> roadLink.constructionType.value)
PieceWiseLinearAsset(
dbAsset.id, dbAsset.linkId, SideCode(dbAsset.sideCode), dbAsset.value, points, dbAsset.expired, dbAsset.startMeasure,
dbAsset.endMeasure, Set(endPoints._1, endPoints._2), dbAsset.modifiedBy, dbAsset.modifiedDateTime, dbAsset.createdBy,
dbAsset.createdDateTime, dbAsset.typeId, roadLink.trafficDirection, dbAsset.timeStamp, dbAsset.geomModifiedDate,
dbAsset.linkSource, roadLink.administrativeClass, verifiedBy = dbAsset.verifiedBy, verifiedDate = dbAsset.verifiedDate, informationSource = dbAsset.informationSource,
dbAsset.linkSource, roadLink.administrativeClass, attributes = attributesToUse, verifiedBy = dbAsset.verifiedBy, verifiedDate = dbAsset.verifiedDate, informationSource = dbAsset.informationSource,
oldId = dbAsset.oldId
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import fi.liikennevirasto.digiroad2.Point
import fi.liikennevirasto.digiroad2.asset._
import org.joda.time.DateTime

case class NewLimit(linkId: String, startMeasure: Double, endMeasure: Double)
case class NewLimit(linkId: String, startMeasure: Double, endMeasure: Double, sideCode: Int = 1)
case class UnknownSpeedLimit(linkId: String, municipalityCode: Int, administrativeClass: AdministrativeClass)

case class SpeedLimitRow(id: Long, linkId: String, sideCode: SideCode, value: Option[Int], startMeasure: Double, endMeasure: Double,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,6 @@ class PostGISSpeedLimitDao(val roadLinkService: RoadLinkService) extends Dynamic

def groupSpeedLimitsResultWithRoadInfo(speedLimitRows: Seq[SpeedLimitRowWithRoadInfo]) : (Seq[PieceWiseLinearAsset], Seq[RoadLinkForUnknownGeneration]) = {
val (assetRows, roadLinkRows) = speedLimitRows.partition(_.id != 0)
val emptyRoadLinkRows = roadLinkRows.filterNot(rlRow => assetRows.map(_.linkId).contains(rlRow.linkId))
val groupedSpeedLimit = assetRows.groupBy(_.id)
val speedLimitAssets = groupedSpeedLimit.keys.map { assetId =>
val rows = groupedSpeedLimit(assetId)
Expand All @@ -245,10 +244,10 @@ class PostGISSpeedLimitDao(val roadLinkService: RoadLinkService) extends Dynamic
administrativeClass = asset.administrativeClass, attributes = attributes, verifiedBy = None, verifiedDate = None, informationSource = None)
}.toSeq

val emptyRoadLinks = emptyRoadLinkRows.map(rl => {
val roadLinks = roadLinkRows.map(rl => {
RoadLinkForUnknownGeneration(rl.linkId, rl.municipalityCode, rl.constructionType, rl.roadLinkLength, rl.geometry, rl.trafficDirection, rl.administrativeClass, rl.linkSource)
})
(speedLimitAssets, emptyRoadLinks)
(speedLimitAssets, roadLinks)
}

private def fetchByLinkIds(linkIds: Seq[String], queryFilter: String) : Seq[PersistedLinearAsset] = {
Expand Down Expand Up @@ -603,9 +602,9 @@ class PostGISSpeedLimitDao(val roadLinkService: RoadLinkService) extends Dynamic
*/
def createSpeedLimit(creator: String, linkId: String, linkMeasures: Measures, sideCode: SideCode, value: SpeedLimitValue,
timeStamp: Long, municipalityValidation: (Int, AdministrativeClass) => Unit): Option[Long] = {
val roadLink = roadLinkService.fetchRoadlinkAndComplementary(linkId)
municipalityValidation(roadLink.get.municipalityCode, roadLink.get.administrativeClass)
createSpeedLimitWithoutDuplicates(creator, linkId, linkMeasures, sideCode, value, None, None, None, None, roadLink.get.linkSource)
val roadLink = roadLinkService.enrichFetchedRoadLinks(Seq(roadLinkService.fetchRoadlinkAndComplementary(linkId).get)).head
municipalityValidation(roadLink.municipalityCode, roadLink.administrativeClass)
createSpeedLimitWithoutDuplicates(creator, linkId, linkMeasures, sideCode, value, None, None, None, None, roadLink.linkSource)
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,15 @@ class SpeedLimitService(eventbus: DigiroadEventBus, roadLinkService: RoadLinkSer
}

def getSpeedLimitsByBbox(bbox: BoundingRectangle): Seq[Seq[PieceWiseLinearAsset]] = {
val (speedLimits, emptyRoadLinks) = withDynTransaction {
val (speedLimits, allRoadLinks) = withDynTransaction {
speedLimitDao.fetchByBBox(bbox)
}
val unknownSpeedLimits = emptyRoadLinkToUnknownSpeedLimit(emptyRoadLinks)
LinearAssetPartitioner.partition(speedLimits ++ unknownSpeedLimits)

val roadLinksFT = allRoadLinks.map(rl => RoadLinkForFillTopology(rl.linkId, rl.length, rl.trafficDirection,
rl.administrativeClass, rl.linkSource, UnknownLinkType, rl.constructionType, rl.geometry, rl.municipalityCode))
val speedLimitsWithUnknowns = assetFiller.generateUnknowns(roadLinksFT, speedLimits.groupBy(_.linkId), SpeedLimitAsset.typeId)._1

LinearAssetPartitioner.partition(speedLimitsWithUnknowns)
}

def emptyRoadLinkToUnknownSpeedLimit(emptyRoadLinks: Seq[RoadLinkForUnknownGeneration]): Seq[PieceWiseLinearAsset] = {
Expand Down Expand Up @@ -486,7 +490,7 @@ class SpeedLimitService(eventbus: DigiroadEventBus, roadLinkService: RoadLinkSer
def create(newLimits: Seq[NewLimit], value: SpeedLimitValue, username: String, municipalityValidation: (Int, AdministrativeClass) => Unit): Seq[Long] = {
withDynTransaction {
val createdIds = newLimits.flatMap { limit =>
speedLimitDao.createSpeedLimit(username, limit.linkId, Measures(limit.startMeasure, limit.endMeasure), SideCode.BothDirections, value, createTimeStamp(), municipalityValidation)
speedLimitDao.createSpeedLimit(username, limit.linkId, Measures(limit.startMeasure, limit.endMeasure), SideCode.apply(limit.sideCode), value, createTimeStamp(), municipalityValidation)
}
eventbus.publish("speedLimits:purgeUnknownLimits", (newLimits.map(_.linkId).toSet, Seq()))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,16 @@ class PostGISSpeedLimitDaoSpec extends FunSuite with Matchers {
test("speed limit creation fails if speed limit is already defined on link segment") {
runWithRollback {
val linkId = LinkIdGenerator.generateRandom()
val roadLink = RoadLinkFetched(linkId, 0, List(Point(0.0, 0.0), Point(0.0, 200.0)), Municipality, TrafficDirection.UnknownDirection, AllOthers)
when(mockRoadLinkService.fetchRoadlinkAndComplementary(linkId)).thenReturn(Some(roadLink))
val dao = daoWithRoadLinks(List(roadLink))
val roadLinkFetched = RoadLinkFetched(linkId, 0, List(Point(0.0, 0.0), Point(0.0, 200.0)), Municipality, TrafficDirection.UnknownDirection, AllOthers)
val roadLink = RoadLink(linkId = roadLinkFetched.linkId, geometry = roadLinkFetched.geometry, length = roadLinkFetched.length,
administrativeClass = roadLinkFetched.administrativeClass, functionalClass = FunctionalClass3.value,
trafficDirection = roadLinkFetched.trafficDirection, linkType = SingleCarriageway, modifiedAt = None,
modifiedBy = None, attributes = Map("MUNICIPALITYCODE" -> BigInt(99)), constructionType = roadLinkFetched.constructionType, linkSource = roadLinkFetched.linkSource)

when(mockRoadLinkService.fetchRoadlinkAndComplementary(linkId)).thenReturn(Some(roadLinkFetched))
when(mockRoadLinkService.enrichFetchedRoadLinks(Seq(roadLinkFetched))).thenReturn(Seq(roadLink))

val dao = daoWithRoadLinks(List(roadLinkFetched))
val id = simulateQuery {
dao.createSpeedLimit("test", linkId, Measures(0.0, 100.0), SideCode.BothDirections, SpeedLimitValue(40), 0, (_, _) => ())
}
Expand All @@ -105,9 +112,16 @@ class PostGISSpeedLimitDaoSpec extends FunSuite with Matchers {
test("speed limit creation succeeds when speed limit is already defined on segment iff speed limits have opposing sidecodes") {
runWithRollback {
val linkId = LinkIdGenerator.generateRandom()
val roadLink = RoadLinkFetched(linkId, 0, List(Point(0.0, 0.0), Point(0.0, 200.0)), Municipality, TrafficDirection.UnknownDirection, AllOthers)
when(mockRoadLinkService.fetchRoadlinkAndComplementary(linkId)).thenReturn(Some(roadLink))
val dao = daoWithRoadLinks(List(roadLink))
val roadLinkFetched = RoadLinkFetched(linkId, 0, List(Point(0.0, 0.0), Point(0.0, 200.0)), Municipality, TrafficDirection.UnknownDirection, AllOthers)
val roadLink = RoadLink(linkId = roadLinkFetched.linkId, geometry = roadLinkFetched.geometry, length = roadLinkFetched.length,
administrativeClass = roadLinkFetched.administrativeClass, functionalClass = FunctionalClass3.value,
trafficDirection = roadLinkFetched.trafficDirection, linkType = SingleCarriageway, modifiedAt = None,
modifiedBy = None, attributes = Map("MUNICIPALITYCODE" -> BigInt(99)), constructionType = roadLinkFetched.constructionType, linkSource = roadLinkFetched.linkSource)


when(mockRoadLinkService.fetchRoadlinkAndComplementary(linkId)).thenReturn(Some(roadLinkFetched))
when(mockRoadLinkService.enrichFetchedRoadLinks(Seq(roadLinkFetched))).thenReturn(Seq(roadLink))
val dao = daoWithRoadLinks(List(roadLinkFetched))
val id = simulateQuery {
dao.createSpeedLimit("test", linkId, Measures(0.0, 100.0), SideCode.TowardsDigitizing, SpeedLimitValue(40), 0, (_, _) => ())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,16 @@ class SpeedLimitServiceSpec extends FunSuite with Matchers {

test("create new speed limit") {
runWithRollback {
val roadLink = RoadLinkFetched(linkId1, 0, List(Point(0.0, 0.0), Point(0.0, 200.0)), Municipality, TrafficDirection.UnknownDirection, AllOthers)
when(mockRoadLinkService.fetchRoadlinkAndComplementary(linkId1)).thenReturn(Some(roadLink))
when(mockRoadLinkService.fetchRoadlinksAndComplementaries(Set(linkId1))).thenReturn(Seq(roadLink))
val roadLinkFetched = RoadLinkFetched(linkId1, 0, List(Point(0.0, 0.0), Point(0.0, 200.0)), Municipality, TrafficDirection.UnknownDirection, AllOthers)

val roadLink = RoadLink(linkId = roadLinkFetched.linkId, geometry = roadLinkFetched.geometry, length = roadLinkFetched.length,
administrativeClass = roadLinkFetched.administrativeClass, functionalClass = FunctionalClass3.value,
trafficDirection = roadLinkFetched.trafficDirection, linkType = SingleCarriageway, modifiedAt = None,
modifiedBy = None, attributes = Map("MUNICIPALITYCODE" -> BigInt(99)), constructionType = roadLinkFetched.constructionType, linkSource = roadLinkFetched.linkSource)

when(mockRoadLinkService.fetchRoadlinkAndComplementary(linkId1)).thenReturn(Some(roadLinkFetched))
when(mockRoadLinkService.fetchRoadlinksAndComplementaries(Set(linkId1))).thenReturn(Seq(roadLinkFetched))
when(mockRoadLinkService.enrichFetchedRoadLinks(Seq(roadLinkFetched))).thenReturn(Seq(roadLink))

val id = provider.create(Seq(NewLimit(linkId1, 0.0, 150.0)), SpeedLimitValue(30), "test", (_, _) => Unit)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ class ExpiredRoadLinkHandlingProcessSpec extends FunSuite with Matchers {
test("Persist links with assets, insert assets on work list"){
runWithRollback {
when(mockRoadLinkService.fetchRoadlinkAndComplementary(expiredLinkId)).thenReturn(Some(testRoadLinkFetched))
when(mockRoadLinkService.enrichFetchedRoadLinks(Seq(testRoadLinkFetched))).thenReturn(Seq(testRoadLink))

val createdSpeedLimitId = speedLimitService.create(Seq(NewLimit(expiredLinkId, 0.0, 131.683)), SpeedLimitValue(30), "test", (_, _) => Unit).head
val expiredLinks = roadLinkDAO.fetchExpiredRoadLinks()
Expand Down
Loading

0 comments on commit 4affc04

Please sign in to comment.