Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # eliminateclubs_fixed.R
- # Εξάρτηση: install.packages(c("dplyr", "readr", "tidyr"))
- library(dplyr)
- library(readr)
- library(tidyr)
- # --- Ρυθμίσεις ---
- min_threshold <- 10L
- responses_file <- "responses.csv"
- clubs_file <- "clubs.csv"
- output_prefix <- "responses_round"
- # --- Διαβάζουμε δεδομένα ---
- responses <- read_csv(responses_file, show_col_types = FALSE)
- clubs <- read_csv(clubs_file, show_col_types = FALSE)
- # --- Καθαρισμός και εναρμόνιση (όπως πριν) ---
- colnames(clubs) <- tolower(trimws(colnames(clubs)))
- clubs$club_id <- trimws(tolower(clubs$club_id))
- if("club_name" %in% colnames(clubs)) {
- clubs$club_name <- trimws(clubs$club_name)
- } else if("clubname" %in% colnames(clubs)) {
- clubs$club_name <- trimws(clubs$clubname)
- } else {
- clubs$club_name <- clubs$club_id
- }
- student_col <- colnames(responses)[1]
- initial_club_cols <- trimws(tolower(colnames(responses)[-1]))
- colnames(responses) <- c(student_col, initial_club_cols)
- # Μετατροπή σε 'long' μορφή για ευκολότερη διαχείριση προτιμήσεων
- responses_long_master <- responses |>
- pivot_longer(cols = -all_of(student_col),
- names_to = "ClubID", values_to = "Rank") |>
- mutate(
- ClubID = trimws(tolower(ClubID)),
- # Εξασφάλιση ότι το Rank είναι ακέραιος
- Rank = as.integer(Rank)
- ) |>
- # Φιλτράρουμε μόνο τις καταγεγραμμένες προτιμήσεις
- filter(!is.na(Rank))
- round <- 1L
- elimination_log <- data.frame(Round=integer(), ClubID=character(), ClubName=character(), FirstPrefCount=integer(), stringsAsFactors = FALSE)
- active_clubs <- initial_club_cols
- repeat {
- # --- Βήμα 1: Υπολογισμός Πρώτων Προτιμήσεων (Τρέχουσα κατάσταση) ---
- # Βρίσκουμε την τρέχουσα υψηλότερη προτίμηση (το χαμηλότερο Rank) για κάθε μαθητή
- current_prefs <- responses_long_master |>
- # Φιλτράρουμε μόνο τους ενεργούς Ομίλους
- filter(ClubID %in% active_clubs) |>
- # Βρίσκουμε το ελάχιστο Rank (την πρώτη προτίμηση)
- group_by(across(all_of(student_col))) |>
- filter(Rank == min(Rank, na.rm = TRUE)) |>
- ungroup()
- # Μετράμε τις πρώτες προτιμήσεις
- counts <- current_prefs |>
- count(ClubID, name = "FirstPrefCount") |>
- right_join(data.frame(ClubID = active_clubs), by = "ClubID") |>
- replace_na(list(FirstPrefCount = 0)) |>
- # Μετατροπή σε named vector για εύκολη χρήση
- tibble::deframe()
- cat(sprintf("\n--- Γύρος %d ---\n", round))
- cat("Όμιλοι και πρώτες προτιμήσεις:\n")
- print(data.frame(ClubID=names(counts), FirstPref=as.integer(counts)), row.names = FALSE)
- # --- Βήμα 2: Έλεγχος Τερματισμού ---
- if(length(active_clubs) == 0) {
- cat("\nΤερματισμός: Δεν έμεινε κανένας Όμιλος.\n")
- break
- }
- if(all(counts >= min_threshold)) {
- cat("\nΤερματισμός: όλοι οι ενεργοί Όμιλοι έχουν τουλάχιστον ", min_threshold, " πρώτες προτιμήσεις.\n", sep = "")
- # Αναδημιουργία του τελικού responses_wide για αποθήκευση
- responses_final_wide <- responses_long_master |>
- filter(ClubID %in% active_clubs) |>
- pivot_wider(id_cols = all_of(student_col),
- names_from = ClubID, values_from = Rank)
- write_csv(responses_final_wide, "responses_final.csv")
- break
- }
- # --- Βήμα 3: Εξάλειψη ---
- counts_df <- data.frame(ClubID=names(counts), FirstPrefCount=as.integer(counts)) |>
- filter(FirstPrefCount < min_threshold)
- if(nrow(counts_df) == 0) {
- # Αυτό δεν θα έπρεπε να συμβεί λόγω του προηγούμενου ελέγχου,
- # αλλά εξασφαλίζει τη συνέχεια αν το all(counts >= min_threshold) δεν πιάσει την περίπτωση.
- cat("\nΤερματισμός: Όλοι οι Όμιλοι άνω του ορίου.\n")
- next
- }
- min_count <- min(counts_df$FirstPrefCount)
- elim_candidates <- counts_df |> filter(FirstPrefCount == min_count)
- # Λογική Ισοπαλίας: επιλέγουμε αλφαβητικά
- club_to_elim <- sort(elim_candidates$ClubID)[1]
- match_idx <- match(club_to_elim, clubs$club_id)
- club_name <- if(!is.na(match_idx)) clubs$club_name[match_idx] else club_to_elim
- cat(sprintf("Εξαλείφεται ο Όμιλος: %s (%s) με %d πρώτες προτιμήσεις.\n",
- club_to_elim, club_name, min_count))
- elimination_log <- rbind(elimination_log,
- data.frame(Round=round,
- ClubID=club_to_elim,
- ClubName=club_name,
- FirstPrefCount=min_count,
- stringsAsFactors = FALSE))
- # --- Βήμα 4: Μεταφορά Ψήφων (Αναβάθμιση Προτιμήσεων) ---
- # 1. Απενεργοποίηση του εξαλειφθέντος Ομίλου
- active_clubs <- setdiff(active_clubs, club_to_elim)
- # 2. Ακύρωση του club_to_elim (θέτουμε το Rank του σε NA)
- responses_long_master <- responses_long_master |>
- mutate(Rank = ifelse(ClubID == club_to_elim, NA_integer_, Rank)) |>
- # Αφαιρούμε πλέον τα NA rank, καθώς ο Όμιλος δεν μετράει
- filter(!is.na(Rank))
- # 3. Αναβαθμίζουμε τα Ranks για κάθε μαθητή
- responses_long_master <- responses_long_master |>
- group_by(across(all_of(student_col))) |>
- # Αναβαθμίζουμε τα Ranks (1, 3, 4, 5... γίνεται 1, 2, 3, 4...)
- # Επανα-αριθμούμε τις προτιμήσεις με βάση την τρέχουσα σειρά τους
- mutate(Rank = rank(Rank, ties.method = "min")) |>
- ungroup()
- # --- Αποθήκευση Ενδιάμεσου Αρχείου (responses_wide) ---
- round_file <- sprintf("%s%d.csv", output_prefix, round)
- responses_round_wide <- responses_long_master |>
- pivot_wider(id_cols = all_of(student_col),
- names_from = ClubID, values_from = Rank) |>
- # Συμπληρώνουμε με NA τους Όμιλους που έχουν ήδη εξαλειφθεί (αν υπάρχουν)
- select(all_of(student_col), all_of(active_clubs))
- write_csv(responses_round_wide, round_file)
- cat("Αποθηκεύτηκε ενδιάμεσο αρχείο: ", round_file, "\n")
- round <- round + 1L
- }
- if(nrow(elimination_log)>0) write_csv(elimination_log, "elimination_log.csv")
- cat("\nΟλοκληρώθηκε η διαδικασία εξάλειψης. Δες το elimination_log.csv.\n")
Advertisement
Add Comment
Please, Sign In to add comment