From 03be0758bad63d21ddfa82a2c565d7617f2135f4 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 26 Mar 2026 16:46:31 +0000 Subject: [PATCH] Add Orioles pitcher Predict+ output to daily pipeline For MLB games, identifies Baltimore Orioles pitchers from yesterday's Statcast data (via home_team/away_team + inning_topbot) and outputs their Predict+ scores for anyone who threw >= 10 pitches. Results are printed to console, saved as orioles_{day}.csv alongside the main CSV, and rendered as a markdown table in the GitHub Actions step summary. https://claude.ai/code/session_01XnaxiNLWNzGJXwyftRiGxr --- .github/workflows/daily-analysis.yml | 29 ++++++++++++++ run_daily.R | 60 ++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) diff --git a/.github/workflows/daily-analysis.yml b/.github/workflows/daily-analysis.yml index 1fe526e..6afa717 100644 --- a/.github/workflows/daily-analysis.yml +++ b/.github/workflows/daily-analysis.yml @@ -249,6 +249,35 @@ jobs: echo "### Output Files" >> $GITHUB_STEP_SUMMARY echo "- CSV: \`${CSV}\`" >> $GITHUB_STEP_SUMMARY echo "- Visualizations: \`output/${{ steps.check_outputs.outputs.year }}/${{ steps.check_outputs.outputs.month }}/visualizations/\`" >> $GITHUB_STEP_SUMMARY + + # Orioles pitcher summary (MLB only) + if [ "${LEVEL}" == "MLB" ]; then + YEAR=${{ steps.check_outputs.outputs.year }} + MONTH=${{ steps.check_outputs.outputs.month }} + DAY=$(date -d "$DATE" '+%d') + ORIOLES_CSV="output/${YEAR}/${MONTH}/orioles_${DAY}.csv" + + echo "" >> $GITHUB_STEP_SUMMARY + echo "### Baltimore Orioles Pitcher Predict+ Scores (≥ 10 pitches)" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + if [ -f "$ORIOLES_CSV" ]; then + python3 - "$ORIOLES_CSV" >> $GITHUB_STEP_SUMMARY << 'PYEOF' +import csv, sys +rows = list(csv.DictReader(open(sys.argv[1]))) +if rows: + print("| Pitcher | Role | Pitches | Predict+ | Status |") + print("|---------|------|---------|----------|--------|") + for r in rows: + pplus = f"{float(r['predict_plus']):.1f}" if r.get('predict_plus') else "N/A" + print(f"| {r['pitcher_name']} | {r['role']} | {r['n_pitches_test']} | {pplus} | {r['status']} |") +else: + print("No Orioles pitchers threw ≥ 10 pitches.") +PYEOF + else + echo "No Orioles pitchers appeared (or no team data available)." >> $GITHUB_STEP_SUMMARY + fi + fi else echo "**Status:** No output generated" >> $GITHUB_STEP_SUMMARY fi diff --git a/run_daily.R b/run_daily.R index 6001350..4dd84d9 100644 --- a/run_daily.R +++ b/run_daily.R @@ -530,3 +530,63 @@ cat(" CSV: ", OUT_CSV, "\n") cat(" Model: ", OUT_MODEL, "\n") cat(" Visuals: ", viz_output, "/\n", sep = "") cat("============================================================\n\n") + +# ============================================================================ +# BALTIMORE ORIOLES PITCHER SUMMARY +# ============================================================================ + +if (LEVEL == "MLB") { + orioles_ppi <- NULL + + if (all(c("home_team", "away_team", "inning_topbot") %in% names(df_test))) { + # Determine each pitcher's team from test data: + # TOP of inning → home team is pitching; BOT of inning → away team is pitching + pitcher_team_map <- df_test %>% + dplyr::mutate( + pitcher_team = dplyr::if_else( + stringr::str_to_upper(.data$inning_topbot) == "TOP", + as.character(.data$home_team), + as.character(.data$away_team) + ) + ) %>% + dplyr::filter(!is.na(.data$pitcher_id), !is.na(.data$pitcher_team)) %>% + dplyr::distinct(.data$pitcher_id, .data$pitcher_team) %>% + dplyr::group_by(.data$pitcher_id) %>% + dplyr::slice(1) %>% + dplyr::ungroup() + + orioles_pitcher_ids <- pitcher_team_map %>% + dplyr::filter(.data$pitcher_team == "BAL") %>% + dplyr::pull(.data$pitcher_id) + + if (length(orioles_pitcher_ids) > 0) { + orioles_ppi <- pitcher_ppi %>% + dplyr::filter(.data$pitcher_id %in% orioles_pitcher_ids, + .data$n_pitches_test >= 10) %>% + dplyr::arrange(dplyr::desc(.data$predict_plus)) + } + } + + cat("============================================================\n") + cat(" Baltimore Orioles Pitchers (>= 10 pitches)\n") + cat("============================================================\n") + + if (!is.null(orioles_ppi) && nrow(orioles_ppi) > 0) { + orioles_display <- orioles_ppi %>% + dplyr::select( + .data$pitcher_name, .data$role, .data$n_pitches_test, + .data$predict_plus, .data$status + ) + print(as.data.frame(orioles_display), row.names = FALSE) + + OUT_ORIOLES_CSV <- file.path(output_base, paste0("orioles_", target_day, ".csv")) + readr::write_csv(orioles_ppi, OUT_ORIOLES_CSV) + cat("\nOrioles CSV saved: ", OUT_ORIOLES_CSV, "\n") + } else if (!all(c("home_team", "away_team") %in% names(df_test))) { + cat("Team data not available in Statcast download.\n") + } else { + cat("No Orioles pitchers threw >= 10 pitches.\n") + } + + cat("============================================================\n\n") +}