Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # club_assignment_stv_hours_auto_v8_final_output.R
- library(dplyr)
- library(readr)
- library(tidyr)
- library(stringr)
- # --- Ρυθμίσεις ---
- required_hours <- 10L
- responses_file <- "responses.csv"
- clubs_file <- "clubs.csv"
- output_prefix_assignments <- "club_assignments"
- auto_select_count <- 15L
- min_pool_size <- 15L
- set.seed(42)
- # --- Διαβάζουμε δεδομένα ---
- responses <- read_csv(responses_file, show_col_types = FALSE)
- clubs <- read_csv(clubs_file, show_col_types = FALSE)
- # --- Καθαρισμός και εναρμόνιση Clubs ---
- colnames(clubs) <- tolower(trimws(colnames(clubs)))
- club_name_source <- if("club_name" %in% colnames(clubs)) "club_name" else "club_id"
- if("clubname" %in% colnames(clubs) & !("club_name" %in% colnames(clubs))) {
- club_name_source <- "clubname"
- }
- if("hours_per_week" %in% colnames(clubs)) {
- clubs <- clubs |> rename(hours = hours_per_week)
- } else if(!("hours" %in% colnames(clubs))) {
- hours_col_name <- setdiff(colnames(clubs), c("club_id", "club_name", "clubname"))[1]
- if (!is.na(hours_col_name)) {
- clubs <- clubs |> rename(hours = hours_col_name)
- }
- }
- clubs <- clubs |>
- mutate(
- club_id = trimws(tolower(club_id)),
- club_name = .data[[club_name_source]],
- club_name = trimws(club_name),
- hours = as.integer(hours),
- hours = if_else(is.na(hours), 2L, hours)
- ) |>
- select(club_id, club_name, hours)
- # --- Καθαρισμός και εναρμόνιση Responses ---
- student_col <- colnames(responses)[1]
- responses <- responses |>
- mutate(across(all_of(student_col), as.character))
- initial_club_cols <- trimws(tolower(colnames(responses)[-1]))
- colnames(responses) <- c(student_col, initial_club_cols)
- responses_long_master <- responses |>
- pivot_longer(cols = -all_of(student_col),
- names_to = "ClubID", values_to = "Rank") |>
- mutate(
- ClubID = trimws(tolower(ClubID)),
- Rank = as.integer(Rank)
- ) |>
- filter(!is.na(Rank))
- # --- Ενεργές Καταστάσεις ---
- active_clubs <- initial_club_cols
- student_hours <- data.frame(StudentID = unique(responses[[student_col]]),
- HoursAssigned = 0L,
- stringsAsFactors = FALSE)
- colnames(student_hours)[1] <- student_col
- club_assignments <- data.frame(StudentID = character(), ClubID = character(), ClubName = character(), stringsAsFactors = FALSE)
- colnames(club_assignments)[1] <- student_col
- round <- 1L
- cat(sprintf("--- Έναρξη Διαδικασίας Κατανομής Ομίλων (Στόχος: %d Ώρες/Μαθητή, Min Pool: %d) ---\n", required_hours, min_pool_size))
- repeat {
- # --- 1. Υπολογισμός Πρώτων Προτιμήσεων (Τρέχουσα κατάσταση) ---
- active_students <- student_hours |>
- filter(HoursAssigned < required_hours) |>
- pull(all_of(student_col))
- current_prefs <- responses_long_master |>
- filter(ClubID %in% active_clubs) |>
- filter(get(student_col) %in% active_students) |>
- 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))
- cat(sprintf("\n*** Γύρος %d ***\n", round))
- # Έλεγχος Τερματισμού
- if(length(active_clubs) == 0 || length(active_students) == 0) {
- students_not_reached_target <- student_hours |>
- filter(HoursAssigned < required_hours)
- if(length(active_clubs) == 0 && nrow(students_not_reached_target) > 0) {
- cat(sprintf("\nΤΕΡΜΑΤΙΣΜΟΣ ΛΟΓΩ ΕΞΑΝΤΛΗΣΗΣ ΟΜΙΛΩΝ: %d μαθητές δεν συμπλήρωσαν τις %d ώρες.\n",
- nrow(students_not_reached_target), required_hours))
- } else {
- cat("\nΤερματισμός: Όλοι οι μαθητές έχουν συμπληρώσει τις ώρες τους.\n")
- }
- break
- }
- # --- 2. Εντοπισμός Δημοφιλέστερου Ομίλου ---
- max_count <- max(counts$FirstPrefCount)
- if (max_count == 0) {
- cat("Δεν υπάρχουν πλέον πρώτες προτιμήσεις για ενεργούς Ομίλους. Τερματισμός.\n")
- break
- }
- pop_candidates <- counts |> filter(FirstPrefCount == max_count)
- club_to_select <- sort(pop_candidates$ClubID)[1]
- match_idx <- match(club_to_select, clubs$club_id)
- club_name <- clubs$club_name[match_idx]
- club_hours <- clubs$hours[match_idx]
- cat(sprintf("-> Δημοφιλέστερος Όμιλος: %s (%s) με %d **πρώτες** προτιμήσεις (Ώρες: %d).\n",
- club_to_select, club_name, max_count, club_hours))
- # --- 3. Διεύρυνση Pool Υποψηφίων (ΛΟΓΙΚΗ ΕΛΑΧΙΣΤΟΥ 15) ---
- students_for_club_pool <- current_prefs |>
- filter(ClubID == club_to_select) |>
- pull(all_of(student_col))
- if(length(students_for_club_pool) < min_pool_size) {
- cat(sprintf("-> Οι πρώτες προτιμήσεις (%d) είναι < %d. Αναζήτηση σε χαμηλότερα ranks...\n",
- length(students_for_club_pool), min_pool_size))
- club_rankings <- responses_long_master |>
- filter(ClubID == club_to_select) |>
- filter(get(student_col) %in% active_students) |>
- arrange(Rank) |>
- select(all_of(student_col), Rank)
- max_rank_to_include <- club_rankings$Rank[min(nrow(club_rankings), min_pool_size)]
- students_for_club_pool <- club_rankings |>
- filter(Rank <= max_rank_to_include) |>
- pull(all_of(student_col))
- cat(sprintf("-> Το pool διευρύνθηκε για να συμπεριλάβει μαθητές μέχρι την %dη προτίμηση (Συνολικά: %d υποψήφιοι).\n",
- max_rank_to_include, length(students_for_club_pool)))
- }
- # --- 4. Αυτόματη Επιλογή 15 Μαθητών (Προσομοίωση) ---
- if (length(students_for_club_pool) > 0) {
- num_to_select <- min(auto_select_count, length(students_for_club_pool))
- final_selected_students <- sample(students_for_club_pool, size = num_to_select, replace = FALSE)
- cat(sprintf("-> Επιλέγονται τυχαία %d μαθητές από το pool.\n", num_to_select))
- } else {
- final_selected_students <- character(0)
- }
- # --- 5. Καταχώρηση και Μεταφορά Ψήφων ---
- if(length(final_selected_students) > 0) {
- new_assignments <- data.frame(StudentID = final_selected_students,
- ClubID = club_to_select,
- ClubName = club_name,
- stringsAsFactors = FALSE)
- colnames(new_assignments)[1] <- student_col
- club_assignments <- bind_rows(club_assignments, new_assignments)
- for (sid in final_selected_students) {
- student_hours[student_hours[[student_col]] == sid, "HoursAssigned"] <-
- student_hours[student_hours[[student_col]] == sid, "HoursAssigned"] + club_hours
- }
- cat(sprintf("-> Καταχωρήθηκαν %d μαθητές στον Όμιλο %s.\n", length(final_selected_students), club_name))
- assignment_file <- sprintf("%s_%s.csv", output_prefix_assignments, club_to_select)
- write_csv(new_assignments, assignment_file)
- }
- # Αφαίρεση του Ομίλου από τη λίστα των ενεργών (Βάσει του Κανόνα του Χρήστη)
- active_clubs <- setdiff(active_clubs, club_to_select)
- # --- 6. Ενημέρωση Ranks (Μεταφορά Ψήφων) ---
- responses_long_master <- responses_long_master |>
- mutate(Rank = ifelse(ClubID == club_to_select, NA_integer_, Rank)) |>
- filter(!is.na(Rank))
- responses_long_master <- responses_long_master |>
- group_by(across(all_of(student_col))) |>
- mutate(Rank = rank(Rank, ties.method = "min")) |>
- ungroup()
- # --- 7. Αποθήκευση Ενδιάμεσων Αρχείων ---
- write_csv(student_hours, "student_hours_log.csv")
- round <- round + 1L
- }
- # --- Τελική Καταγραφή & Νέο Αρχείο (Student Club List) ---
- cat("\nΟλοκληρώθηκε η διαδικασία κατανομής.\n")
- write_csv(club_assignments, "club_assignments_final.csv")
- # --- ΒΗΜΑ 8: ΔΗΜΙΟΥΡΓΙΑ ΑΡΧΕΙΟΥ ΜΕ ΛΙΣΤΑ ΟΜΙΛΩΝ ΑΝΑ ΜΑΘΗΤΗ ---
- student_club_list <- club_assignments |>
- # Ομαδοποίηση ανά μαθητή
- group_by(across(all_of(student_col))) |>
- # Συνένωση των ClubName σε μία συμβολοσειρά, χωρισμένη με κόμμα
- summarise(
- Clubs_Assigned = paste(ClubName, collapse = ", "),
- .groups = 'drop'
- )
- # Ενσωμάτωση των συνολικών ωρών για πληρέστερη εικόνα
- student_club_list <- student_club_list |>
- left_join(student_hours, by = student_col) |>
- select(all_of(student_col), Clubs_Assigned, HoursAssigned)
- # Αποθήκευση του νέου αρχείου
- write_csv(student_club_list, "student_club_list.csv")
- cat("Δημιουργήθηκε το αρχείο: student_club_list.csv (Λίστα Ομίλων ανά Μαθητή)\n")
- # --- ΒΗΜΑ 9: ΕΥΡΕΣΗ ΟΜΙΛΩΝ ΜΕ ΛΙΓΟΤΕΡΟΥΣ ΑΠΟ 10 ΜΑΘΗΤΕΣ ---
- # Υπολογίζουμε τους μαθητές ανά Όμιλο
- clubs_less_than_10 <- club_assignments |>
- # Ομαδοποίηση ανά όνομα Ομίλου
- group_by(ClubName) |>
- # Καταμέτρηση των αναθέσεων (μαθητών)
- summarise(
- Students_Count = n(),
- .groups = 'drop'
- ) |>
- # Φιλτράρισμα μόνο για όσους έχουν λιγότερους από 10 μαθητές
- filter(Students_Count < 10) |>
- # Ταξινόμηση για ευκολότερη επισκόπηση
- arrange(Students_Count, ClubName)
- # Εκτύπωση αποτελεσμάτων στην κονσόλα
- cat("\n\n--- ΟΜΙΛΟΙ ΜΕ ΛΙΓΟΤΕΡΟΥΣ ΑΠΟ 10 ΜΑΘΗΤΕΣ ---\n")
- print(clubs_less_than_10)
- # Αποθήκευση του αποτελέσματος σε αρχείο CSV
- write_csv(clubs_less_than_10, "clubs_less_than_10_students.csv")
- cat("\nΑποθηκεύτηκαν τα αποτελέσματα στο: clubs_less_than_10_students.csv\n")
Advertisement
Add Comment
Please, Sign In to add comment