dalagiorgos

Selected Clubs

Oct 25th, 2025
1,267
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
R 10.50 KB | Source Code | 0 0
  1. # club_assignment_stv_hours_auto_v8_final_output.R
  2.  
  3. library(dplyr)
  4. library(readr)
  5. library(tidyr)
  6. library(stringr)
  7.  
  8. # --- Ρυθμίσεις ---
  9. required_hours <- 10L
  10. responses_file <- "responses.csv"
  11. clubs_file <- "clubs.csv"
  12. output_prefix_assignments <- "club_assignments"
  13. auto_select_count <- 15L
  14. min_pool_size <- 15L
  15. set.seed(42)
  16.  
  17. # --- Διαβάζουμε δεδομένα ---
  18. responses <- read_csv(responses_file, show_col_types = FALSE)
  19. clubs <- read_csv(clubs_file, show_col_types = FALSE)
  20.  
  21. # --- Καθαρισμός και εναρμόνιση Clubs ---
  22. colnames(clubs) <- tolower(trimws(colnames(clubs)))
  23. club_name_source <- if("club_name" %in% colnames(clubs)) "club_name" else "club_id"
  24. if("clubname" %in% colnames(clubs) & !("club_name" %in% colnames(clubs))) {
  25.   club_name_source <- "clubname"
  26. }
  27.  
  28. if("hours_per_week" %in% colnames(clubs)) {
  29.   clubs <- clubs |> rename(hours = hours_per_week)
  30. } else if(!("hours" %in% colnames(clubs))) {
  31.   hours_col_name <- setdiff(colnames(clubs), c("club_id", "club_name", "clubname"))[1]
  32.   if (!is.na(hours_col_name)) {
  33.     clubs <- clubs |> rename(hours = hours_col_name)
  34.   }
  35. }
  36.  
  37. clubs <- clubs |>
  38.   mutate(
  39.     club_id = trimws(tolower(club_id)),
  40.     club_name = .data[[club_name_source]],
  41.     club_name = trimws(club_name),
  42.     hours = as.integer(hours),
  43.     hours = if_else(is.na(hours), 2L, hours)
  44.   ) |>
  45.   select(club_id, club_name, hours)
  46.  
  47. # --- Καθαρισμός και εναρμόνιση Responses ---
  48. student_col <- colnames(responses)[1]
  49. responses <- responses |>
  50.   mutate(across(all_of(student_col), as.character))
  51.  
  52. initial_club_cols <- trimws(tolower(colnames(responses)[-1]))
  53. colnames(responses) <- c(student_col, initial_club_cols)
  54.  
  55. responses_long_master <- responses |>
  56.   pivot_longer(cols = -all_of(student_col),
  57.                names_to = "ClubID", values_to = "Rank") |>
  58.   mutate(
  59.     ClubID = trimws(tolower(ClubID)),
  60.     Rank = as.integer(Rank)
  61.   ) |>
  62.   filter(!is.na(Rank))
  63.  
  64. # --- Ενεργές Καταστάσεις ---
  65. active_clubs <- initial_club_cols
  66. student_hours <- data.frame(StudentID = unique(responses[[student_col]]),
  67.                             HoursAssigned = 0L,
  68.                             stringsAsFactors = FALSE)
  69. colnames(student_hours)[1] <- student_col
  70. club_assignments <- data.frame(StudentID = character(), ClubID = character(), ClubName = character(), stringsAsFactors = FALSE)
  71. colnames(club_assignments)[1] <- student_col
  72. round <- 1L
  73.  
  74. cat(sprintf("--- Έναρξη Διαδικασίας Κατανομής Ομίλων (Στόχος: %d Ώρες/Μαθητή, Min Pool: %d) ---\n", required_hours, min_pool_size))
  75.  
  76. repeat {
  77.   # --- 1. Υπολογισμός Πρώτων Προτιμήσεων (Τρέχουσα κατάσταση) ---
  78.  
  79.   active_students <- student_hours |>
  80.     filter(HoursAssigned < required_hours) |>
  81.     pull(all_of(student_col))
  82.  
  83.   current_prefs <- responses_long_master |>
  84.     filter(ClubID %in% active_clubs) |>
  85.     filter(get(student_col) %in% active_students) |>
  86.     group_by(across(all_of(student_col))) |>
  87.     filter(Rank == min(Rank, na.rm = TRUE)) |>
  88.     ungroup()
  89.  
  90.   counts <- current_prefs |>
  91.     count(ClubID, name = "FirstPrefCount") |>
  92.     right_join(data.frame(ClubID = active_clubs), by = "ClubID") |>
  93.     replace_na(list(FirstPrefCount = 0))
  94.  
  95.   cat(sprintf("\n*** Γύρος %d ***\n", round))
  96.  
  97.   # Έλεγχος Τερματισμού
  98.   if(length(active_clubs) == 0 || length(active_students) == 0) {
  99.     students_not_reached_target <- student_hours |>
  100.       filter(HoursAssigned < required_hours)
  101.    
  102.     if(length(active_clubs) == 0 && nrow(students_not_reached_target) > 0) {
  103.       cat(sprintf("\nΤΕΡΜΑΤΙΣΜΟΣ ΛΟΓΩ ΕΞΑΝΤΛΗΣΗΣ ΟΜΙΛΩΝ: %d μαθητές δεν συμπλήρωσαν τις %d ώρες.\n",
  104.                   nrow(students_not_reached_target), required_hours))
  105.     } else {
  106.       cat("\nΤερματισμός: Όλοι οι μαθητές έχουν συμπληρώσει τις ώρες τους.\n")
  107.     }
  108.     break
  109.   }
  110.  
  111.   # --- 2. Εντοπισμός Δημοφιλέστερου Ομίλου ---
  112.   max_count <- max(counts$FirstPrefCount)
  113.   if (max_count == 0) {
  114.     cat("Δεν υπάρχουν πλέον πρώτες προτιμήσεις για ενεργούς Ομίλους. Τερματισμός.\n")
  115.     break
  116.   }
  117.  
  118.   pop_candidates <- counts |> filter(FirstPrefCount == max_count)
  119.   club_to_select <- sort(pop_candidates$ClubID)[1]
  120.  
  121.   match_idx <- match(club_to_select, clubs$club_id)
  122.   club_name <- clubs$club_name[match_idx]
  123.   club_hours <- clubs$hours[match_idx]
  124.  
  125.   cat(sprintf("-> Δημοφιλέστερος Όμιλος: %s (%s) με %d **πρώτες** προτιμήσεις (Ώρες: %d).\n",
  126.               club_to_select, club_name, max_count, club_hours))
  127.  
  128.   # --- 3. Διεύρυνση Pool Υποψηφίων (ΛΟΓΙΚΗ ΕΛΑΧΙΣΤΟΥ 15) ---
  129.  
  130.   students_for_club_pool <- current_prefs |>
  131.     filter(ClubID == club_to_select) |>
  132.     pull(all_of(student_col))
  133.  
  134.   if(length(students_for_club_pool) < min_pool_size) {
  135.     cat(sprintf("-> Οι πρώτες προτιμήσεις (%d) είναι < %d. Αναζήτηση σε χαμηλότερα ranks...\n",
  136.                 length(students_for_club_pool), min_pool_size))
  137.    
  138.     club_rankings <- responses_long_master |>
  139.       filter(ClubID == club_to_select) |>
  140.       filter(get(student_col) %in% active_students) |>
  141.       arrange(Rank) |>
  142.       select(all_of(student_col), Rank)
  143.    
  144.     max_rank_to_include <- club_rankings$Rank[min(nrow(club_rankings), min_pool_size)]
  145.    
  146.     students_for_club_pool <- club_rankings |>
  147.       filter(Rank <= max_rank_to_include) |>
  148.       pull(all_of(student_col))
  149.    
  150.     cat(sprintf("-> Το pool διευρύνθηκε για να συμπεριλάβει μαθητές μέχρι την %dη προτίμηση (Συνολικά: %d υποψήφιοι).\n",
  151.                 max_rank_to_include, length(students_for_club_pool)))
  152.   }
  153.  
  154.   # --- 4. Αυτόματη Επιλογή 15 Μαθητών (Προσομοίωση) ---
  155.  
  156.   if (length(students_for_club_pool) > 0) {
  157.     num_to_select <- min(auto_select_count, length(students_for_club_pool))
  158.     final_selected_students <- sample(students_for_club_pool, size = num_to_select, replace = FALSE)
  159.    
  160.     cat(sprintf("-> Επιλέγονται τυχαία %d μαθητές από το pool.\n", num_to_select))
  161.   } else {
  162.     final_selected_students <- character(0)
  163.   }
  164.  
  165.  
  166.   # --- 5. Καταχώρηση και Μεταφορά Ψήφων ---
  167.  
  168.   if(length(final_selected_students) > 0) {
  169.     new_assignments <- data.frame(StudentID = final_selected_students,
  170.                                   ClubID = club_to_select,
  171.                                   ClubName = club_name,
  172.                                   stringsAsFactors = FALSE)
  173.     colnames(new_assignments)[1] <- student_col
  174.     club_assignments <- bind_rows(club_assignments, new_assignments)
  175.    
  176.     for (sid in final_selected_students) {
  177.       student_hours[student_hours[[student_col]] == sid, "HoursAssigned"] <-
  178.         student_hours[student_hours[[student_col]] == sid, "HoursAssigned"] + club_hours
  179.     }
  180.    
  181.     cat(sprintf("-> Καταχωρήθηκαν %d μαθητές στον Όμιλο %s.\n", length(final_selected_students), club_name))
  182.    
  183.     assignment_file <- sprintf("%s_%s.csv", output_prefix_assignments, club_to_select)
  184.     write_csv(new_assignments, assignment_file)
  185.   }
  186.  
  187.   # Αφαίρεση του Ομίλου από τη λίστα των ενεργών (Βάσει του Κανόνα του Χρήστη)
  188.   active_clubs <- setdiff(active_clubs, club_to_select)
  189.  
  190.   # --- 6. Ενημέρωση Ranks (Μεταφορά Ψήφων) ---
  191.  
  192.   responses_long_master <- responses_long_master |>
  193.     mutate(Rank = ifelse(ClubID == club_to_select, NA_integer_, Rank)) |>
  194.     filter(!is.na(Rank))
  195.  
  196.   responses_long_master <- responses_long_master |>
  197.     group_by(across(all_of(student_col))) |>
  198.     mutate(Rank = rank(Rank, ties.method = "min")) |>
  199.     ungroup()
  200.  
  201.   # --- 7. Αποθήκευση Ενδιάμεσων Αρχείων ---
  202.   write_csv(student_hours, "student_hours_log.csv")
  203.  
  204.   round <- round + 1L
  205. }
  206.  
  207. # --- Τελική Καταγραφή & Νέο Αρχείο (Student Club List) ---
  208. cat("\nΟλοκληρώθηκε η διαδικασία κατανομής.\n")
  209. write_csv(club_assignments, "club_assignments_final.csv")
  210.  
  211.  
  212. # --- ΒΗΜΑ 8: ΔΗΜΙΟΥΡΓΙΑ ΑΡΧΕΙΟΥ ΜΕ ΛΙΣΤΑ ΟΜΙΛΩΝ ΑΝΑ ΜΑΘΗΤΗ ---
  213.  
  214. student_club_list <- club_assignments |>
  215.   # Ομαδοποίηση ανά μαθητή
  216.   group_by(across(all_of(student_col))) |>
  217.   # Συνένωση των ClubName σε μία συμβολοσειρά, χωρισμένη με κόμμα
  218.   summarise(
  219.     Clubs_Assigned = paste(ClubName, collapse = ", "),
  220.     .groups = 'drop'
  221.   )
  222.  
  223. # Ενσωμάτωση των συνολικών ωρών για πληρέστερη εικόνα
  224. student_club_list <- student_club_list |>
  225.   left_join(student_hours, by = student_col) |>
  226.   select(all_of(student_col), Clubs_Assigned, HoursAssigned)
  227.  
  228. # Αποθήκευση του νέου αρχείου
  229. write_csv(student_club_list, "student_club_list.csv")
  230. cat("Δημιουργήθηκε το αρχείο: student_club_list.csv (Λίστα Ομίλων ανά Μαθητή)\n")
  231.  
  232. # --- ΒΗΜΑ 9: ΕΥΡΕΣΗ ΟΜΙΛΩΝ ΜΕ ΛΙΓΟΤΕΡΟΥΣ ΑΠΟ 10 ΜΑΘΗΤΕΣ ---
  233.  
  234. # Υπολογίζουμε τους μαθητές ανά Όμιλο
  235. clubs_less_than_10 <- club_assignments |>
  236.   # Ομαδοποίηση ανά όνομα Ομίλου
  237.   group_by(ClubName) |>
  238.   # Καταμέτρηση των αναθέσεων (μαθητών)
  239.   summarise(
  240.     Students_Count = n(),
  241.     .groups = 'drop'
  242.   ) |>
  243.   # Φιλτράρισμα μόνο για όσους έχουν λιγότερους από 10 μαθητές
  244.   filter(Students_Count < 10) |>
  245.   # Ταξινόμηση για ευκολότερη επισκόπηση
  246.   arrange(Students_Count, ClubName)
  247.  
  248. # Εκτύπωση αποτελεσμάτων στην κονσόλα
  249. cat("\n\n--- ΟΜΙΛΟΙ ΜΕ ΛΙΓΟΤΕΡΟΥΣ ΑΠΟ 10 ΜΑΘΗΤΕΣ ---\n")
  250. print(clubs_less_than_10)
  251.  
  252. # Αποθήκευση του αποτελέσματος σε αρχείο CSV
  253. write_csv(clubs_less_than_10, "clubs_less_than_10_students.csv")
  254. cat("\nΑποθηκεύτηκαν τα αποτελέσματα στο: clubs_less_than_10_students.csv\n")
Advertisement
Add Comment
Please, Sign In to add comment