-
Notifications
You must be signed in to change notification settings - Fork 1k
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
New vectortile layer for Digitransit realtime stops #5743
New vectortile layer for Digitransit realtime stops #5743
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## dev-2.x #5743 +/- ##
===========================================
Coverage 67.78% 67.78%
- Complexity 16478 16527 +49
===========================================
Files 1901 1905 +4
Lines 72132 72293 +161
Branches 7430 7441 +11
===========================================
+ Hits 48892 49007 +115
- Misses 20727 20765 +38
- Partials 2513 2521 +8 ☔ View full report in Codecov by Sentry. |
|
||
@BeforeEach | ||
public void setUp() { | ||
public final void setUp() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not really necessary to mark methods as final especially if you don't plan to extend the class.
protected static DigitransitRealtimeStopPropertyMapper create( | ||
TransitService transitService, | ||
Locale locale | ||
) { | ||
return new DigitransitRealtimeStopPropertyMapper(transitService, locale); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need this or could you just use the normal constructor in tests as well?
.../org/opentripplanner/ext/vectortiles/layers/stops/DigitransitRealtimeStopPropertyMapper.java
Outdated
Show resolved
Hide resolved
new KeyValue("desc", i18NStringMapper.mapToApi(stop.getDescription())), | ||
new KeyValue( | ||
"parentStation", | ||
stop.getParentStation() != null ? stop.getParentStation().getId() : "null" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this "null" is a mistake we made in the old layer, you can just return null
import org.opentripplanner.inspector.vector.LayerParameters; | ||
import org.opentripplanner.transit.service.TransitService; | ||
|
||
public class StopsBaseLayerBuilder extends StopsLayerBuilder { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this class necessary? Could we just edit the existing StopsLayerBuilder since this is not really overriding anything.
alert.effect().equals(AlertEffect.NO_SERVICE) && | ||
( | ||
alert.getEffectiveStartDate() != null && | ||
alert.getEffectiveStartDate().isBefore(currentTime) | ||
) && | ||
(alert.getEffectiveEndDate() != null && alert.getEffectiveEndDate().isAfter(currentTime)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you move this into a method on TransitAlert
? Maybe call it noServiceOn(instant)
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also fixed the logic a little, as I realised that the end time doesn't need to be defined for the alert to be effective, it could be open ended.
|
||
@Override | ||
protected Collection<KeyValue> map(RegularStop stop) { | ||
Instant currentTime = ZonedDateTime.now(transitService.getTimeZone()).toInstant(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instant currentTime = ZonedDateTime.now(transitService.getTimeZone()).toInstant(); | |
Instant currentTime = Instant.now(); |
No need for the detour via the ZonedDateTime.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really? I thought the time zone might be important in this context to ensure the alert is actually valid according to local time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you call toInstant all timezone information is lost again. An instant is just a number of seconds since 1970-01-01 UTC.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This instant can be converted to many time zones but it remains the same number of seconds.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And since we only want to give an answer at the time of someone asking and not the future/past the time zone doesn't matter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Haha, you're right. Somehow tricked myself into thinking the instant is different in different places. 😂 Thanks!
new KeyValue("gtfsId", stop.getId().toString()), | ||
new KeyValue("name", i18NStringMapper.mapNonnullToApi(stop.getName())), | ||
new KeyValue("code", stop.getCode()), | ||
new KeyValue("platform", stop.getPlatformCode()), | ||
new KeyValue("desc", i18NStringMapper.mapToApi(stop.getDescription())), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you extract a method for these KeyValue
instances that are shared between the two mappers?
You can define two lists and use ListUtils.combine
to combine the two lists.
), | ||
new KeyValue("type", getType(transitService, stop)), | ||
new KeyValue("routes", getRoutes(transitService, stop)), | ||
new KeyValue("noServiceAlert", noServiceAlert) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you want to keep the boolean, you could use a property name like "closedByServiceAlert".
* @param instant | ||
* @return | ||
*/ | ||
public boolean noServiceOn(Instant instant) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I think in English "no service at instant" is more correct. Can you rename the method?
i18NStringMapper.mapNonnullToApi(stop.getName()), | ||
i18NStringMapper.mapToApi(stop.getDescription()), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These two calls can move to the method by passing the i18nstring mapper.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, passed the transitService as well.
.../org/opentripplanner/ext/vectortiles/layers/stops/DigitransitRealtimeStopPropertyMapper.java
Outdated
Show resolved
Hide resolved
...ext/java/org/opentripplanner/ext/vectortiles/layers/stops/DigitransitStopPropertyMapper.java
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only tiny requests left.
…DigitransitRealtimeStopPropertyMapper.java Co-authored-by: Leonard Ehrenfried <[email protected]>
One thing I forgot: you need to add documentation. |
You need to modify the md file in doc-templates and then run |
Sorry about the confusion with the files, can't believe I forgot about the templates. It should be ok now. |
"mapper": "DigitransitRealtime", | ||
"maxZoom": 20, | ||
"minZoom": 14, | ||
"cacheMaxSeconds": 600 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the other realtime layers, we have suggested 60 second cache time. Not sure what is actually optimal here but we could use the same.
new KeyValue("desc", i18NStringMapper.mapToApi(stop.getDescription())), | ||
new KeyValue( | ||
"parentStation", | ||
stop.getParentStation() != null ? stop.getParentStation().getId() : null |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a breaking change. This shouldn't be shared between the mappers as the old one always returned a string.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has been regenerated (although there wasn't really a need since the graphql schema has not been updated. There are just some duplicate imports here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above.
This reverts commit 89e82e9.
b4a0f8e
@leonardehrenfried seemingly our UI at least doesn't rely on the fact that the parentStation id would always be a string. Should we just return null instead of "null" for the old layer? |
Yes, you can. I'm not aware of anyone using this field. I think the null as string came from a time when we used |
Summary
A new Digitransit vectortile layer for stops which also includes realtime alert information.
Issue
The new layer allows showing information related to alerts affecting stops on the map. Alert information is only fetched when the map is zoomed in, hence the requirement for a new layer. The implementation follows the same structure as VehicleRental layers. The realtime stop mapper uses the code from the previously existing stop layer for the parts that are identical between the two layers.
Unit tests
Unit test for alerts added to StopsLayerTest.
Manual testing was also performed.