Fix broken chart in victory status (#13454)

* fix broken chart

* update comment and minor optimization

* rename misleading variable
This commit is contained in:
metablaster 2025-06-21 22:50:00 +02:00 committed by GitHub
parent 1ff10700b9
commit 911c26e5d6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 28 additions and 15 deletions

View File

@ -20,7 +20,7 @@ class CivRankingHistory : HashMap<Int, Map<RankingType, Int>>(), IsPartOfGameInf
fun recordRankingStats(civilization: Civilization) {
this[civilization.gameInfo.turns] =
RankingType.entries.associateWith { civilization.getStatForRanking(it) }
RankingType.entries.associateWith { civilization.getStatForRanking(it) }
}
/** Implement Json.Serializable

View File

@ -31,7 +31,7 @@ class LineChart(
private val axisLabelColor = axisColor
private val axisToLabelPadding = 5f
private val chartLineWidth = 3f
private val orientationLineWidth = 0.5f
private val orientationLineWidth = 1f
private val orientationLineColor = Color.LIGHT_GRAY
/** This should not be changed lightly. There's code (e.g. for generating the labels) that
@ -167,7 +167,8 @@ class LineChart(
// We draw the y-axis labels first. They will take away some space on the left of the
// widget which we need to consider when drawing the rest of the graph.
var yAxisYPosition = 0f
var yAxisLowestOrientationLinePosition = 0f // Lowest orientation line in pixels
var zeroAxisYPosition = 0f // Pixel position of zero axis
yLabels.forEachIndexed { index, value ->
val label = yLabelsAsLabels[index] // we assume yLabels.size == yLabelsAsLabels.size
val yPos = yAxisLabelMinY + index * (yAxisLabelYRange / (yLabels.size - 1))
@ -176,16 +177,18 @@ class LineChart(
// Draw y-axis orientation lines and x-axis
val zeroIndex = value == 0
val labelAdjustedYPos = yPos + labelHeight / 2
drawLine(
widestYLabelWidth + axisToLabelPadding + axisLineWidth,
yPos + labelHeight / 2,
labelAdjustedYPos,
width,
yPos + labelHeight / 2,
labelAdjustedYPos,
if (zeroIndex) axisColor else orientationLineColor,
if (zeroIndex) axisLineWidth else orientationLineWidth
)
if (zeroIndex) {
yAxisYPosition = yPos + labelHeight / 2
if (value <= 0) {
if (zeroIndex) zeroAxisYPosition = labelAdjustedYPos
yAxisLowestOrientationLinePosition = min(yAxisLowestOrientationLinePosition, labelAdjustedYPos)
}
}
@ -214,14 +217,14 @@ class LineChart(
// Draw line charts for each color
val linesMinX = widestYLabelWidth + axisToLabelPadding + axisLineWidth
val linesMaxX = width - lastXAxisLabelWidth / 2
val linesMinY = yAxisYPosition
val linesMinY = yAxisLowestOrientationLinePosition + labelHeight + axisToLabelPadding + axisLineWidth
val linesMaxY = height - labelHeight / 2
val scaleX = (linesMaxX - linesMinX) / (xLabels.max() - xLabels.min())
val scaleY = (linesMaxY - linesMinY) / (yLabels.max() - yLabels.min())
val negativeOrientationLineYPosition = yAxisLabelMinY + labelHeight / 2
val minXLabel = xLabels.min()
val minYLabel = yLabels.min()
val negativeScaleY = (negativeOrientationLineYPosition - linesMinY) / if (minYLabel < 0) minYLabel else 1
val scaleX = (linesMaxX - linesMinX) / (xLabels.max() - minXLabel)
val scaleY = (linesMaxY - linesMinY) / (yLabels.max() - minYLabel)
val negativeOrientationLineYPosition = yAxisLabelMinY + labelHeight / 2
val negativeScaleY = (negativeOrientationLineYPosition - zeroAxisYPosition) / if (minYLabel < 0) minYLabel else 1
val sortedPoints = dataPoints.sortedBy { it.x }
val pointsByCiv = sortedPoints.groupBy { it.civ }
// We want the current player civ to be drawn last, so it is never overlapped by another player.
@ -239,7 +242,7 @@ class LineChart(
val points = pointsByCiv[civ]!!
val scaledPoints : List<DataPoint<Float>> = points.map {
if (it.y < 0f)
DataPoint(linesMinX + (it.x - minXLabel) * scaleX, linesMinY + it.y * negativeScaleY, it.civ)
DataPoint(linesMinX + (it.x - minXLabel) * scaleX, zeroAxisYPosition + it.y * negativeScaleY, it.civ)
else
DataPoint(linesMinX + (it.x - minXLabel) * scaleX, linesMinY + (it.y - minYLabel) * scaleY, it.civ)
}

View File

@ -97,7 +97,7 @@ class VictoryScreenCharts(
}
private fun getLineChartData(rankingType: RankingType): List<DataPoint<Int>> {
return gameInfo.civilizations.asSequence()
val dataPoints = gameInfo.civilizations.asSequence()
.filter { it.isMajorCiv() }
.flatMap { civ ->
civ.statsHistory
@ -109,7 +109,17 @@ class VictoryScreenCharts(
.mapValues { group -> group.value.toMap() }
.flatMap { turn ->
turn.value.map { (civ, value) -> DataPoint(turn.key, value, civ) }
}
}.toMutableList()
// Historical data does not include data for current turn for civs which haven't got their turn yet,
// so we append missing stat for current turn to the data for each such civ
val pointsByCiv = dataPoints.sortedBy { it.x }.groupBy { it.civ }
val actualTurn = dataPoints.maxOf { it.x }
for (civ in pointsByCiv.keys.filterNot { it.isDefeated() })
if (pointsByCiv[civ]!!.last().x != actualTurn)
dataPoints += DataPoint(actualTurn, civ.getStatForRanking(rankingType), civ)
return dataPoints
}
override fun activated(index: Int, caption: String, pager: TabbedPager) {