RatingHistoryService.kt
package delta.codecharacter.server.user.rating_history
import delta.codecharacter.dtos.RatingHistoryDto
import delta.codecharacter.server.logic.rating.GlickoRating
import delta.codecharacter.server.logic.rating.RatingAlgorithm
import delta.codecharacter.server.match.MatchVerdictEnum
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Service
import java.math.BigDecimal
import java.time.Instant
import java.util.UUID
@Service
class RatingHistoryService(
@Autowired private val ratingHistoryRepository: RatingHistoryRepository,
@Autowired private val ratingAlgorithm: RatingAlgorithm
) {
fun create(userId: UUID) {
val ratingHistory =
RatingHistoryEntity(
userId = userId, rating = 1500.0, ratingDeviation = 350.0, validFrom = Instant.now()
)
ratingHistoryRepository.save(ratingHistory)
}
fun getRatingHistory(userId: UUID): List<RatingHistoryDto> {
return ratingHistoryRepository.findAllByUserId(userId).map {
RatingHistoryDto(
rating = BigDecimal(it.rating),
ratingDeviation = BigDecimal(it.ratingDeviation),
validFrom = it.validFrom
)
}
}
private fun convertVerdictToMatchResult(verdict: MatchVerdictEnum): Double {
return when (verdict) {
MatchVerdictEnum.PLAYER1 -> 1.0
MatchVerdictEnum.PLAYER2 -> 0.0
MatchVerdictEnum.TIE -> 0.5
}
}
fun updateRating(
userId: UUID,
opponentId: UUID,
verdict: MatchVerdictEnum
): Pair<Double, Double> {
val (_, userRating, userRatingDeviation, userRatingValidFrom) =
ratingHistoryRepository.findFirstByUserIdOrderByValidFromDesc(userId)
val (_, opponentRating, opponentRatingDeviation, opponentRatingValidFrom) =
ratingHistoryRepository.findFirstByUserIdOrderByValidFromDesc(opponentId)
val userWeightedRatingDeviation =
ratingAlgorithm.getWeightedRatingDeviationSinceLastCompetition(
userRatingDeviation, userRatingValidFrom
)
val opponentWeightedRatingDeviation =
ratingAlgorithm.getWeightedRatingDeviationSinceLastCompetition(
opponentRatingDeviation, opponentRatingValidFrom
)
val newUserRating =
ratingAlgorithm.calculateNewRating(
GlickoRating(userRating, userWeightedRatingDeviation),
listOf(GlickoRating(opponentRating, opponentWeightedRatingDeviation)),
listOf(convertVerdictToMatchResult(verdict))
)
val newOpponentRating =
ratingAlgorithm.calculateNewRating(
GlickoRating(opponentRating, opponentWeightedRatingDeviation),
listOf(GlickoRating(userRating, userWeightedRatingDeviation)),
listOf(1.0 - convertVerdictToMatchResult(verdict))
)
val currentInstant = Instant.now()
ratingHistoryRepository.save(
RatingHistoryEntity(
userId = userId,
rating = newUserRating.rating,
ratingDeviation = newUserRating.ratingDeviation,
validFrom = currentInstant
)
)
ratingHistoryRepository.save(
RatingHistoryEntity(
userId = opponentId,
rating = newOpponentRating.rating,
ratingDeviation = newOpponentRating.ratingDeviation,
validFrom = currentInstant
)
)
return Pair(newUserRating.rating, newOpponentRating.rating)
}
}