Skip to content

Commit

Permalink
Seal differences
Browse files Browse the repository at this point in the history
  • Loading branch information
TWiStErRob committed Jan 13, 2024
1 parent 349dabb commit 4d5c7d7
Show file tree
Hide file tree
Showing 11 changed files with 285 additions and 258 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,10 @@ import io.micronaut.views.View
import net.twisterrob.blt.data.StaticData
import net.twisterrob.blt.io.feeds.trackernet.LineStatusFeed
import net.twisterrob.travel.domain.london.status.Feed
import net.twisterrob.travel.domain.london.status.api.StatusHistoryRepository
import net.twisterrob.travel.domain.london.status.api.ParsedStatusItem
import net.twisterrob.travel.domain.london.status.api.StatusHistoryRepository
import net.twisterrob.travel.statushistory.viewmodel.LineColor
import net.twisterrob.travel.statushistory.viewmodel.Result
import net.twisterrob.travel.statushistory.viewmodel.ResultChange
import net.twisterrob.travel.statushistory.viewmodel.ResultChangeCalculator
import net.twisterrob.travel.statushistory.viewmodel.ResultChangeModel
import net.twisterrob.travel.statushistory.viewmodel.ResultChangeModelMapper
Expand All @@ -39,7 +38,7 @@ class LineStatusHistoryController(
val results = history
.filter { displayErrors || it !is ParsedStatusItem.ParseFailed }
.map(ParsedStatusItem::toResult)
val differences = getDifferences(results)
val differences = ResultChangeCalculator().getDifferences(results)

return HttpResponse.ok(
LineStatusHistoryModel(
Expand Down Expand Up @@ -69,15 +68,3 @@ private fun ParsedStatusItem.toResult(): Result {
Result.ErrorResult(date, Result.ErrorResult.Error("Error while displaying loaded XML: ${this.error.stacktrace}"))
}
}

private fun getDifferences(results: List<Result>): List<ResultChange> {
val resultChanges: MutableList<ResultChange> = ArrayList(results.size)
var newResult: Result? = null
for (oldResult in results) { // We're going forward, but the list is backwards.
resultChanges.add(ResultChangeCalculator().diff(oldResult, newResult))
newResult = oldResult
}
resultChanges.add(ResultChangeCalculator().diff(null, newResult))
resultChanges.removeAt(0)
return resultChanges
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,33 @@ import net.twisterrob.blt.io.feeds.trackernet.model.DelayType
import net.twisterrob.blt.io.feeds.trackernet.model.LineStatus
import net.twisterrob.blt.model.Line

open class ResultChange(
val previous: Result?,
val current: Result?,
val error: ErrorChange, // STOPSHIP seal for error and changes
) {
sealed interface Difference {

interface HasDescriptionChange {
data object Nothing : Difference

val desc: DescriptionChange
}
data class NewStatus(
val current: Result,
) : Difference

data class LastStatus(
val previous: Result,
) : Difference

data class Changes(
val previous: Result,
val current: Result,
val changes: Map<Line, StatusChange>,
) : Difference

sealed class StatusChange {
data class Appeared(
val newDelay: DelayType,
) : StatusChange()

data class Disappeared(
val oldDelay: DelayType,
) : StatusChange()

data class Better(
val oldDelay: DelayType,
val newDelay: DelayType,
Expand All @@ -32,8 +47,11 @@ open class ResultChange(
val delay: DelayType,
override val desc: DescriptionChange,
) : StatusChange(), HasDescriptionChange
}

interface HasDescriptionChange {

data object Unknown : StatusChange()
val desc: DescriptionChange
}

sealed class DescriptionChange {
Expand Down Expand Up @@ -61,29 +79,24 @@ open class ResultChange(
) : DescriptionChange()
}

sealed interface ErrorChange {
sealed interface ErrorDifference : Difference {
data class Same(
val error: Result.ErrorResult.Error,
) : ErrorChange
val error: Result.ErrorResult,
) : ErrorDifference

data class Change(
val oldError: Result.ErrorResult.Error,
val newError: Result.ErrorResult.Error,
) : ErrorChange
val oldError: Result.ErrorResult,
val newError: Result.ErrorResult,
) : ErrorDifference

data class Failed(
val newError: Result.ErrorResult.Error,
) : ErrorChange
val oldResult: Result.ContentResult,
val newError: Result.ErrorResult,
) : ErrorDifference

data class Fixed(
val oldError: Result.ErrorResult.Error,
) : ErrorChange

data class NoErrors(
val changes: Map<Line, StatusChange>,
) : ErrorChange

data object NewStatus : ErrorChange
data object LastStatus : ErrorChange
val oldError: Result.ErrorResult,
val newResult: Result.ContentResult,
) : ErrorDifference
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ import java.util.Date

sealed interface Result {

@Suppress("detekt.VariableNaming")
val `when`: Date

class ContentResult(
val `when`: Date,
override val `when`: Date,
val content: LineStatusFeed,
) : Result

class ErrorResult(
val `when`: Date,
override val `when`: Date,
val error: Error,
) : Result {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,45 @@ package net.twisterrob.travel.statushistory.viewmodel

import net.twisterrob.blt.io.feeds.trackernet.model.LineStatus
import net.twisterrob.blt.model.Line
import net.twisterrob.travel.statushistory.viewmodel.ResultChange.DescriptionChange
import net.twisterrob.travel.statushistory.viewmodel.ResultChange.ErrorChange
import net.twisterrob.travel.statushistory.viewmodel.ResultChange.StatusChange
import net.twisterrob.travel.statushistory.viewmodel.Difference.DescriptionChange
import net.twisterrob.travel.statushistory.viewmodel.Difference.ErrorDifference
import net.twisterrob.travel.statushistory.viewmodel.Difference.StatusChange
import java.util.EnumMap

class ResultChangeCalculator {

fun diff(oldResult: Result?, newResult: Result?): ResultChange {
val errorChange = when {
oldResult != null && newResult != null -> diffError(oldResult, newResult)
oldResult == null && newResult != null -> ErrorChange.NewStatus
oldResult != null && newResult == null -> ErrorChange.LastStatus
else /* oldResult == null && newResult == null */ -> ErrorChange.NoErrors(emptyMap())
fun getDifferences(results: List<Result>): List<Difference> {
val changes: MutableList<Difference> = ArrayList(results.size)
var newResult: Result? = null
for (oldResult in results) { // We're going forward, but the list is backwards.
changes.add(diff(oldResult, newResult))
newResult = oldResult
}
return ResultChange(
oldResult,
newResult,
errorChange,
)
changes.add(diff(null, newResult))
changes.removeAt(0)
return changes
}

fun diff(oldResult: Result?, newResult: Result?): Difference =
when {
oldResult == null && newResult != null -> Difference.NewStatus(newResult)
oldResult != null && newResult == null -> Difference.LastStatus(oldResult)
oldResult != null && newResult != null -> diffResults(oldResult, newResult)
else /* oldResult == null && newResult == null */ -> Difference.Nothing
}

private fun diffResults(oldResult: Result, newResult: Result): Difference =
when {
oldResult is Result.ContentResult && newResult is Result.ContentResult ->
Difference.Changes(oldResult, newResult, diffContent(oldResult, newResult))

oldResult is Result.ErrorResult || newResult is Result.ErrorResult ->
diffError(oldResult, newResult)

else ->
error("Unknown combination of results: old=${oldResult}, new=${newResult}.")
}

private fun diffContent(oldResult: Result.ContentResult, newResult: Result.ContentResult): Map<Line, StatusChange> {
val statusChanges: MutableMap<Line, StatusChange> = EnumMap(Line::class.java)
val oldMap = oldResult.content.statusMap
Expand All @@ -36,18 +54,24 @@ class ResultChangeCalculator {
return statusChanges
}

private fun statusChange(oldStatus: LineStatus?, newStatus: LineStatus?): StatusChange {
if (oldStatus == null || newStatus == null) {
return StatusChange.Unknown
}
val statusDiff = oldStatus.type.compareTo(newStatus.type)
val desc = diffDesc(oldStatus, newStatus)
return when {
statusDiff < 0 -> StatusChange.Better(oldStatus.type, newStatus.type, desc)
statusDiff > 0 -> StatusChange.Worse(oldStatus.type, newStatus.type, desc)
else /* statusDiff == 0 */ -> StatusChange.Same(newStatus.type, desc)
private fun statusChange(oldStatus: LineStatus?, newStatus: LineStatus?): StatusChange =
when {
oldStatus == null && newStatus == null -> error("Missing statuses")
oldStatus == null && newStatus != null -> StatusChange.Appeared(newStatus.type)
oldStatus != null && newStatus == null -> StatusChange.Disappeared(oldStatus.type)

oldStatus != null && newStatus != null -> {
val statusDiff = oldStatus.type.compareTo(newStatus.type)
val desc = diffDesc(oldStatus, newStatus)
when {
statusDiff < 0 -> StatusChange.Better(oldStatus.type, newStatus.type, desc)
statusDiff > 0 -> StatusChange.Worse(oldStatus.type, newStatus.type, desc)
else /* statusDiff == 0 */ -> StatusChange.Same(newStatus.type, desc)
}
}

else -> error("Unknown combination of statuses: old=${oldStatus}, new=${newStatus}.")
}
}

private fun diffDesc(oldStatus: LineStatus, newStatus: LineStatus): DescriptionChange {
val oldDesc = oldStatus.description
Expand All @@ -67,41 +91,33 @@ class ResultChangeCalculator {
}
}

oldDesc == null && newDesc != null -> {
DescriptionChange.Added(newDesc)
}

oldDesc != null && newDesc == null -> {
DescriptionChange.Removed(oldDesc)
}

else /* oldDesc == null && newDesc == null */ -> {
DescriptionChange.Missing
}
oldDesc == null && newDesc != null -> DescriptionChange.Added(newDesc)
oldDesc != null && newDesc == null -> DescriptionChange.Removed(oldDesc)
else /* oldDesc == null && newDesc == null */ -> DescriptionChange.Missing
}
}

private fun diffError(oldResult: Result, newResult: Result): ErrorChange {
private fun diffError(oldResult: Result, newResult: Result): Difference {
val oldError = (oldResult as? Result.ErrorResult)?.error
val newError = (newResult as? Result.ErrorResult)?.error
return when {
oldError != null && newError != null -> {
if (oldError.header == newError.header)
ErrorChange.Same(newError)
ErrorDifference.Same(newResult)
else
ErrorChange.Change(oldError, newError)
ErrorDifference.Change(oldResult, newResult)
}

oldError == null && newError != null -> {
ErrorChange.Failed(newError)
ErrorDifference.Failed(oldResult as Result.ContentResult, newResult)
}

oldError != null && newError == null -> {
ErrorChange.Fixed(oldError)
ErrorDifference.Fixed(oldResult, newResult as Result.ContentResult)
}

else /* oldErrorHeader == null && newErrorHeader == null */ -> {
ErrorChange.NoErrors(diffContent(oldResult as Result.ContentResult, newResult as Result.ContentResult))
else /* oldError == null && newError == null */ -> {
error("Neither result has an error: ${oldResult}, ${newResult}")
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import net.twisterrob.blt.model.Line
open class ResultChangeModel(
val previous: Result?,
val current: Result?,
val error: ErrorChange,
val error: ErrorChange?,
val statuses: Map<Line, StatusChange>,
val descriptions: Map<Line, String>,
) {
Expand Down
Loading

0 comments on commit 4d5c7d7

Please sign in to comment.