library(dplyr)
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
Chess ELO Expected Score Calculator
# Chess ELO Expected Score Calculator
# Formula source: Solon, Nate. "How Elo Ratings Actually Work." Zwischenzug,
# https://zwischenzug.substack.com/p/how-elo-ratings-actually-work
# Expected Score = 1 / (1 + 10^((opponent_rating - player_rating)/400))
# Sample data structure - replace with your actual tournament data
chess_data <- data.frame(
player_name = c("Player A", "Player B", "Player C", "Player D", "Player E"),
player_rating = c(1800, 1650, 1900, 1750, 1600),
actual_score = c(4.0, 3.5, 4.5, 2.5, 3.0),
# Opponent ratings as lists (you'll need to format your data this way)
opponent_ratings = I(list(
c(1700, 1800, 1650, 1750, 1900), # Player A's opponents
c(1600, 1750, 1800, 1900, 1700), # Player B's opponents
c(1800, 1650, 1750, 1600, 1700), # Player C's opponents
c(1900, 1700, 1600, 1800, 1650), # Player D's opponents
c(1750, 1900, 1700, 1650, 1800) # Player E's opponents
))
)
Function to calculate expected score
calculate_expected_score <- function(player_rating, opponent_ratings) {
expected_scores <- sapply(opponent_ratings, function(opp_rating) {
1 / (1 + 10^((opp_rating - player_rating) / 400))
})
return(sum(expected_scores))
}
# Calculate expected scores and performance differences
results <- chess_data %>%
rowwise() %>%
mutate(
expected_score = calculate_expected_score(player_rating, opponent_ratings),
performance_diff = actual_score - expected_score,
over_under = ifelse(performance_diff > 0, "Overperformed", "Underperformed")
) %>%
ungroup()
Analyze and display results
print("Chess Tournament Performance Analysis:")
## [1] "Chess Tournament Performance Analysis:"
print(results[, c("player_name", "actual_score", "expected_score", "performance_diff")])
## # A tibble: 5 × 4
## player_name actual_score expected_score performance_diff
## <chr> <dbl> <dbl> <dbl>
## 1 Player A 4 2.77 1.23
## 2 Player B 3.5 1.85 1.65
## 3 Player C 4.5 3.76 0.739
## 4 Player D 2.5 2.64 -0.140
## 5 Player E 3 1.48 1.52
# Top 5 overperformers
top_over <- results %>%
arrange(desc(performance_diff)) %>%
head(5)
print("\nTop 5 Overperformers:")
## [1] "\nTop 5 Overperformers:"
print(top_over[, c("player_name", "performance_diff")])
## # A tibble: 5 × 2
## player_name performance_diff
## <chr> <dbl>
## 1 Player B 1.65
## 2 Player E 1.52
## 3 Player A 1.23
## 4 Player C 0.739
## 5 Player D -0.140
# Top 5 underperformers
top_under <- results %>%
arrange(performance_diff) %>%
head(5)
print("\nTop 5 Underperformers:")
## [1] "\nTop 5 Underperformers:"
print(top_under[, c("player_name", "performance_diff")])
## # A tibble: 5 × 2
## player_name performance_diff
## <chr> <dbl>
## 1 Player D -0.140
## 2 Player C 0.739
## 3 Player A 1.23
## 4 Player E 1.52
## 5 Player B 1.65