---
title: "Omogenizarea repartiției pe zile a lecțiilor"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Omogenizarea repartiției pe zile a lecțiilor}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)
```

```{r setup}
library(recastlessons)
```

Într-o școală avem trei categorii de profesori: cei care au numai "ore proprii", cei angajați și în "cuplaje", respectiv cei constituiți și în "tuplaje". În **`R123`** avem o repartiție pe zile a *tuturor* lecțiilor, iar în **`TPL`** sunt specificate tuplajele asociate acestei repartiții:
```{r}
dplyr::glimpse(R123)
str(TPL)
```
Profesorii sunt numiți după șablonul: disciplină, abreviată pe două litere, plus un număr de ordine între cei încadrați pe o aceeași disciplină; un *cuplaj* este reprezentat printr-un "profesor fictiv", cu numele rezultat prin alipirea codurilor de câte 3 caractere ale membrilor (iar cei câțiva profesori fictivi apar și ei, între cele 66 niveluri din `R123$prof`).\
Mai sus, `glimpse()` ne-a arătat că `Rl2`, `En3`, etc., fac lecțiile la `10A` respectiv în zilele `Lu`, `Jo`, `Ma`, etc.

`"Gr3 Gr4"/"10E 10F"` este un *tuplaj*, însemnând că lecțiile "`Gr3 10E`" și "`Gr4 10F`" trebuie să fie plasate într-o aceeași zi, anume în ziua `Mi` (și apoi, într-o aceeași oră a zilei), unde "`10E`" și "`10F`" au fost formate ad-hoc partiționând după criterii specifice școlii, ansamblul elevilor celor două clase inițiale.

**`R123`** este un exemplu de repartiție relativ *echilibrată* (care ne-a rezultat, plecând de la încadrarea `prof|cls` dintr-o anumită școală, prin https://cran.r-project.org/package=days2lessons); o bună parte a distribuțiilor individuale (pe profesori și pe clase) a numărului de ore/zi sunt distribuții *omogene* (uniforme), dar există altele care sunt doar *cvasi*-omogene (cu diferență de două ore ---dar nu mai mult--- de la o zi la alta).\
Prezentăm (parțial, aici) un set de funcții care depistează și expun în diverse formate (sau grupări), distribuțiile individuale "defectuoase", permițând prin corelare, omogenizarea treptată a acestora.

Să vedem întâi la care clase au rămas distribuții cvasi-omogene (dar aici, listăm doar trei):
```{r}
cls_quasihom(R123) %>% head(3)
```
Pentru a omogeniza distribuția la clasa `10A` ar trebui să mutăm o lecție fie din ziua `Ma`, fie din ziua `Vi`, în ziua `Mi` (ar rezulta 4 zile cu câte 6 ore și o zi cu 7 ore, deci o distribuție omogenă). Să vedem ce lecții sunt în ziua `Vi` la `10A` și *nu* sunt în ziua `Mi` (evităm să apară la clasă într-o aceeași zi, *două* lecții identice):
```{r}
prof_2days(R123, "10A", "Vi", "Mi")
```
Să lăsăm în pace deocamdată, pe `Is3` și pe `Gr2` (distribuția lui `Is3` ar deveni omogenă aducându-i încă o lecție nu în ziua `Mi`, ci în ziua `Lu`; iar lecția `Gr2 10A` trebuie să rămână `Vi`, fiindcă apare în tuplajul `"Gr2 Gr1"/"10A 10B"/"Vi Jo"`). La `Tc2` avem distribuție omogenă (dacă nu cumva este implicat și în cuplaje); ne rămâne `In2In1`, dar acesta este un cuplaj --- să vedem cum ar fi afectați membrii săi, dacă am muta lecția respectivă din ziua `Vi` în ziua `Mi`: 
```{r}
coupled_dis(R123)
```
Constatăm că `In2` are (singur sau în cuplaj) 3 ore `Mi` și 3 ore `Vi`, iar `In1` are 3 și respectiv, 5 ore --- distribuții care, după mutarea intenționată, ar deveni 2/4 și respectiv 4/4 și deocamdată, le putem accepta:
```{r eval=FALSE}
> DZ <- change_day(R123, "In2In1", "10A", "Vi", "Mi")
```
`DZ` diferă de `R123` numai prin faptul că `In2In1` apare `Mi` și nu `Vi`; în `DZ`, clasa `10A` a căpătat o distribuție omogenă a numărului de ore/zi. N-avem dacât să continuăm, operând cam ca mai sus, dar asupra repartiției curente `DZ`, pentru clasele rămase cu distribuții cvasi-omogene.

Dar pentru a echilibra distribuțiile orare ale celor implicați în cuplaje este mai bine să folosim funcția `coupled_list()`, care listează matricea distribuțiilor în care este implicat un profesor care are și ore proprii (pe clase neimplicate în cuplaje):
```{r}
coupled_list(R123)[["In1"]]
```
Pe matricea afișată vedem că pe `Vi`, `In1` cumulează 5 ore, dintre care două sunt ore proprii; deci (în loc de a muta cuplajul `In2In1`, cum am făcut mai sus) am putea muta una dintre aceste două ore proprii, din ziua `Vi` în ziua `Mi`, ceea ce i-ar omogeniza distribuția cumulată a orelor sale. 

Cândva... lucrând cu atenție și fără grabă, `cls_quasihom(DZ)` va returna `NULL` --- însemnând că în acel moment toate clasele au căpătat (în repartiția curentă `DZ`) distribuții omogene pentru numărul de ore/zi; se poate întâmpla (fiindcă... am lucrat într-adevăr, cu mare atenție, mai și inspectând una-alta, din când în când), se poate întâmpla ca și distribuția pe zile a totalului orelor, să fi devenit omogenă:
```{r eval=FALSE}
> addmargins(table(DZ[c('cls','zl')]))["Sum", ]
```
```{verbatim}
 Lu  Ma  Mi  Jo  Vi Sum 
186 186 186 185 185 928
```
(da!... este necesară oleacă de inspirație, sau experiență, pentru alegerea unor schimbări succesive de lecții dintr-o zi în alta, care "deodată", să omogenizeze distribuțiile pe clase și până la urmă și pe totalul orelor) 

Să vedem acum care profesori din afara cuplajelor, cu mai mult de câte 8 ore/săptămână, au rămas cu distribuții cvasi-omogene:
```{r eval=FALSE}
prof_bad_dis(DZ)
```
```{verbatim}
   Ch1 Ch2 En3 ET1 Fl1 Fz2 Gr1 Gr3 Gr4 Mt1 Mt3 Mz1 Ro2 Ro7 Sp1
Lu   3   5   3   1   4   4   4   5   3   5   4   4   4   4   4
Ma   4   3   4   3   4   3   4   3   4   6   5   2   4   2   4
Mi   3   3   4   2   4   2   3   4   5   4   3   4   3   3   5
Jo   3   4   3   1   4   4   5   3   4   4   5   3   5   3   3
Vi   5   3   5   3   2   4   5   4   5   4   4   4   3   4   5
```
Ne atrage atenția distribuția lui `ET1`: are numai 10 ore, dar are două zile cu câte o singură oră. Am putea să-i grupăm orele în 4 zile, dacă ora de `Lu` și cea de `Jo` sunt la clase *diferite*:
```{r eval=FALSE}
> cls2prof(DZ, "ET1")
```
```{verbatim}
   ET1       
Lu "8A"      
Ma "5A 5B 6A"
Mi "6B 7B"   
Jo "7A"      
Vi "5A 5B 8B"
```
Fiindcă ținem să *nu* modificăm distribuțiile, deja omogene, ale claselor și nici distribuția totalului de ore --- căutăm vreun profesor cu care `ET1` să *interschimbe* lecția de `Lu` (la `8A`) cu cea de `Jo` (la `7A`): 

```{r eval=FALSE}
> prof_swap(DZ, "ET1", "Lu", "Jo")
```
```{verbatim}
   Ro4          
Lu "7A 7B 8B"   
Ma "7A 7B 8A 8B"
Mi "7A 7B 8A 8B"
Jo "7A 7B 8A 8B"
Vi "7A 7B 8A 8B"
```
`8A` apare la `Ro4` în ziua `Jo` și *nu* apare în ziua `Lu`; pe de altă parte, mutarea acestei clase *păstrează omogenitatea* distribuției orelor lui `Ro4`, încât putem decide să facem interschimbarea respectivă:
```{r eval=FALSE}
> DZ <- change_day(DZ, "ET1", "8A", "Lu", "Jo")
> DZ <- change_day(DZ, "Ro4", "8A", "Jo", "Lu")
> saveRDS(DZ, "../adjR123.RDS")  # salvăm din când în când, repartiția curentă
```
Pentru încă un exemplu, să încercăm să omogenizăm distribuția (`3 4 3 3 5`) a lui `Ch1`:
```{verbatim}
> cls2prof(DZ, "Ch1")
   Ch1                 
Lu "10A 10C 12A"       
Ma "10B 11A 11D 12B"   
Mi "10C 10D 11D"       
Jo "10A 10D 9C"        
Vi "10B 10C 10D 11D 9C"
```
Trebuie să căutăm profesori cu care `Ch1` să interschimbe o clasă din ziua `Vi` într-una dintre zilele `Lu`, `Mi` sau `Jo`, fără a deteriora alte distribuții individuale. `prof_swap(DZ, "Ch1", "Vi", "Jo")` ne arată între altele, distribuția cvasi-omogenă (`4 4 3 5 3`):
```{verbatim}
   Ro2              
Lu "10B 5A 5B 6B"   
Ma "5A 5B 6B 9B"    
Mi "10B 5B 9B"      
Jo "10B 5A 5B 6B 9B"
Vi "5A 6B 9B"
```
Putem muta clasa `10B` de pe `Jo` pe `Vi` la `Ro2` și de pe `Vi` pe `Jo` la `Ch1`, folosind iarăși `change_day()`; ca urmare, devin omogene ambele distribuții (și la `Ch1` și la `Ro2`).

La fel, folosind succesiv `cls2prof()`, `prof_swap()` și apoi, după ce facem alegerile potrivite, `change_day()` --- omogenizăm pe rând și distribuțiile cvasi-omogene rămase profesorilor din afara tuplajelor.\
În final, `prof_bad_dis()` ne-a dat:

```{verbatim}
   ET1 Gr1 Gr3 Gr4 Mz1
Lu   0   4   5   3   4
Ma   3   4   3   4   2
Mi   2   3   4   5   4
Jo   2   5   3   4   3
Vi   3   5   4   5   4
```
Exceptând `ET1` (căruia mai sus, am voit să-i plasăm orele în 4 zile), cei 4 profesori rămași cu distribuții cvasi-omogene sunt membri ai unor tuplaje și preferăm să nu le modificăm distribuțiile (trebuie păstrată ziua alocată din start pentru fiecare clasă care este implicată în tuplaje, deci la cei 4 profesori am putea muta într-o altă zi numai clase ale lor care nu sunt printre cele existente în tuplaje --- ceea ce necesită o analiză care probabil că nu este prea grea, dar de care ne putem și lipsi).

Trebuie totuși să verificăm dacă, tot mutând lecții pe alte zile, am reușit să păstrăm în repartiția curentă `DZ`, alocările pe zile existente în setul inițial 'R123' pentru tuplaje: invocarea `keep_toupled(DZ, TPL)` ar trebui să returneze `TRUE`.\
De altfel, putem vizualiza (în format TSV) întreaga repartizare pe zile a lecțiilor vreunui subset de profesori, folosind funcția `tidy2tsv()`; de exemplu, chiar pentru cei din tuplaje:
```{r}
library(dplyr, warn.conflicts = FALSE)
Tpl_prof <- TPL %>% pull(prof) %>% unique() %>%
    sapply(function(P) strsplit(P, " ")[[1]]) %>% 
    unlist() %>% unique()
DZ %>% filter(prof %in% Tpl_prof) %>% 
    tidy2tsv() %>% select(1:5)  # câte coloane încap aici...
``` 
Putem verifica astfel, direct, că am respectat repartizarea pe zile din 'TPL'; vedem de exemplu, că `Gr3`, `Gr1` și `Gr4` intră la `12A`, `12B`, respectiv `12D` în zilele `Lu` și `Ma`, iar `Ds1` și `Mz1` intră la `9A` și `9B` în ziua `Jo` (exact cum precizează 'TPL'). Putem observa că la `Mz1` am putea muta `12F` (sau `6B`, sau `8B`, aflate și ele în afara tuplajelor) din ziua `Lu` în ziua `Ma` --- ceea ce ar omogeniza distribuția respectivă (la fel ne putem gândi să omogenizăm distribuțiile celorlalți profesori din tuplaje, folosind iarăși `prof_swap()` și `change_day()`).

În final... probabil că putem fi mulțumiți: repartiția pe zile din `DZ` este omogenă și pe clase și pe profesori --- exceptând unii membri ai cuplajelor și tuplajelor existente, pentru care a rămas totuși acceptabilă, fiind cvasi-omogenă (iar numărul total de lecții din DZ are o distribuție uniformă pe zile); desigur, ar mai fi de analizat și poate de corectat, distribuțiile celor cu mai puțin de 8 ore/săptămână (acestea pot fi depistate prin `prof_bad_dis(DZ, at_least = 1)`).\
Desigur, pentru aceasta ne-au fost necesare vreo două sesiuni de lucru în consola R, cam de câte o "oră" bună... Pentru o eventuală edificare, am adăugat în pachet și repartizarea finală **`DZ`**; dar bineînțeles că dacă am lua-o de la capăt, procedând cam cum am arătat mai sus asupra repartiției inițiale 'R123', am ajunge la o a doua repartiție `DZ`, probabil "mai bună" ca prima (am profita desigur, de experiența primeia).   



