Implement ranking logic with SerieStandEntry, add support for streak results and binding types (Reiter+Pferd, Reiter, Pferd), update UI for detailed ranking display, and finalize Phase 10.
This commit is contained in:
+40
-7
@@ -1,5 +1,7 @@
|
||||
package at.mocode.series.service.application
|
||||
|
||||
import at.mocode.series.service.domain.Bindungstyp
|
||||
import at.mocode.series.service.domain.ReglementTyp
|
||||
import at.mocode.series.service.domain.Serie
|
||||
import at.mocode.series.service.domain.SeriePunkt
|
||||
import at.mocode.series.service.persistence.JpaSeriePunktRepository
|
||||
@@ -20,17 +22,48 @@ class SeriesService(
|
||||
@Transactional
|
||||
fun saveSerie(serie: Serie): Serie = serieRepository.save(serie)
|
||||
|
||||
fun getStand(serieId: String): Map<Pair<String, String>, Double> {
|
||||
fun getStand(serieId: String): List<SerieStandEntry> {
|
||||
val serie = getSeriesById(serieId) ?: return emptyList()
|
||||
val punkte = punkteRepository.findBySerieId(serieId)
|
||||
|
||||
// Aggregation pro Paar (Reiter, Pferd)
|
||||
return punkte.groupBy { it.reiterId to it.pferdId }
|
||||
.mapValues { (_, v) -> v.sumOf { it.punkte } }
|
||||
.toList()
|
||||
.sortedByDescending { it.second }
|
||||
.toMap()
|
||||
// Gruppierung nach Bindungstyp
|
||||
val groupedPunkte = when (serie.bindungstyp) {
|
||||
Bindungstyp.PAAR_BINDUNG -> punkte.groupBy { "${it.reiterId}_${it.pferdId}" }
|
||||
Bindungstyp.NUR_REITER -> punkte.groupBy { it.reiterId }
|
||||
Bindungstyp.NUR_PFERD -> punkte.groupBy { it.pferdId }
|
||||
}
|
||||
|
||||
return groupedPunkte.map { (_, v) ->
|
||||
val bewerbPunkte = v.map { it.punkte }.sortedDescending()
|
||||
|
||||
val gesamtPunkte = when (serie.reglementTyp) {
|
||||
ReglementTyp.ALLES_ZAEHLT -> bewerbPunkte.sum()
|
||||
ReglementTyp.STREICHER_NORMAL -> {
|
||||
// Berücksichtige Streichresultate: N-m gewertete Resultate (die besten N-m zählen)
|
||||
// Wenn wir m Streichresultate haben, zählen die besten (Total - m) Resultate.
|
||||
val countToSum = (bewerbPunkte.size - serie.streichresultateCount).coerceAtLeast(0)
|
||||
if (countToSum == 0 && bewerbPunkte.isNotEmpty()) bewerbPunkte.first() // Fallback: Zumindest eines zählt
|
||||
else bewerbPunkte.take(countToSum).sum()
|
||||
}
|
||||
ReglementTyp.MEISTERSCHAFT -> bewerbPunkte.sum() // TODO: Spezielle Gewichtung
|
||||
}
|
||||
|
||||
SerieStandEntry(
|
||||
reiterId = v.first().reiterId,
|
||||
pferdId = if (serie.bindungstyp == Bindungstyp.PAAR_BINDUNG) v.first().pferdId else null,
|
||||
punkte = gesamtPunkte,
|
||||
anzahlWertungen = v.size
|
||||
)
|
||||
}.sortedByDescending { it.punkte }
|
||||
}
|
||||
|
||||
@Transactional
|
||||
fun addPunkt(punkt: SeriePunkt): SeriePunkt = punkteRepository.save(punkt)
|
||||
}
|
||||
|
||||
data class SerieStandEntry(
|
||||
val reiterId: String,
|
||||
val pferdId: String?,
|
||||
val punkte: Double,
|
||||
val anzahlWertungen: Int
|
||||
)
|
||||
|
||||
+13
@@ -19,6 +19,13 @@ class Serie(
|
||||
@Column(nullable = false)
|
||||
val reglementTyp: ReglementTyp = ReglementTyp.STREICHER_NORMAL,
|
||||
|
||||
@Column(nullable = false)
|
||||
val streichresultateCount: Int = 1,
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(nullable = false)
|
||||
val bindungstyp: Bindungstyp = Bindungstyp.PAAR_BINDUNG,
|
||||
|
||||
@ElementCollection
|
||||
@CollectionTable(name = "serie_bewerbe", joinColumns = [JoinColumn(name = "serie_id")])
|
||||
@Column(name = "bewerb_id")
|
||||
@@ -31,6 +38,12 @@ enum class ReglementTyp {
|
||||
MEISTERSCHAFT // Spezielle Gewichtung (z.B. Finale doppelt)
|
||||
}
|
||||
|
||||
enum class Bindungstyp {
|
||||
PAAR_BINDUNG, // Reiter + Pferd (Standard)
|
||||
NUR_REITER, // Punkte zählen nur für den Reiter
|
||||
NUR_PFERD // Punkte zählen nur für das Pferd
|
||||
}
|
||||
|
||||
@Entity
|
||||
@Table(name = "serie_punkte")
|
||||
class SeriePunkt(
|
||||
|
||||
Reference in New Issue
Block a user