我有一个团体实体。这个群体实体有一个" nombre"字段是该组的所需大小," jour1"和" horaire1"这是该组考试的第一个DateTime和" jour2"和" horaire2"这是该小组考试的第二个DateTime。
大约有40组,只有4对不同的DateTime(星期一17:30 - 星期三18:30,星期一18:30 - 星期三17:30,星期二17:30 - 星期四18:30,星期二18:30 - 星期四17:30)。
我有另一个实体,DemandeGroupe。该实体允许用户询问特定的考试日期时间和/或与该组中的另一个特定用户。用户可以要求多个用户。
我希望在某些条件下将所有用户划分为这些组:
1)要求与其他用户在一起并询问特定日期时间的用户必须与所询问的日期时间属于同一组。
2)仅询问特定用户的用户必须与该用户在同一组中。
3)只询问特定DateTime的用户必须在此DateTime的一组中。
4)没有提出任何要求的用户必须随机分组。
5)组的大小不同,因此所有组都必须遵守" nombre"中定义的大小。因此,每组中的用户数必须低于或等于" nombre"并且所有群组都必须在同一时间填写(如果用户数量少于群组中的空间,我不希望最后一个群体填充较少的用户。)
我无法在同一时间找到符合所有这些条件的方法。
GroupeComposition实体:
/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\Column(name="nom", type="string")
*/
private $nom;
/**
* @ORM\Column(name="salle_composition", type="string")
*/
private $salleComposition;
/**
* @ORM\Column(name="salle_correction", type="string")
*/
private $salleCorrection;
/**
* @ORM\Column(name="nombre", type="integer")
*/
private $nombre;
/**
* @ORM\Column(name="jour1", type="string")
*/
private $jour1;
/**
* @ORM\Column(name="horaire_jour1", type="string")
*/
private $horaireJour1;
/**
* @ORM\Column(name="jour2", type="string")
*/
private $jour2;
/**
* @ORM\Column(name="horaire_jour2", type="string")
*/
private $horaireJour2;
/**
* @ORM\Column(name="type_tutore", type="string")
*/
private $typeTutore;
/**
* @ORM\Column(name="specialite", type="string", nullable=true)
*/
private $specialite;
/**
* @ORM\OneToMany(targetEntity="\PACES\UserBundle\Entity\Tutore", mappedBy="groupeComposition")
*/
protected $tutores;
DemandeGroupe实体:
**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\ManyToOne(targetEntity="PACES\UserBundle\Entity\Tutore", cascade={"persist"})
*/
protected $tutoreSource;
/**
* @ORM\ManyToOne(targetEntity="PACES\UserBundle\Entity\Tutore", cascade={"persist"})
*/
protected $tutoreDemande;
/**
* @ORM\Column(name="jour", type="string", nullable=true)
*/
private $jour;
/**
* @ORM\Column(name="horaire", type="string", nullable=true)
*/
private $horaire;
/**
* @ORM\Column(name="raison", type="string")
*/
private $raison;
/**
* @ORM\Column(name="acceptee", type="boolean", nullable=true, options={"default":null})
*/
private $acceptee;
答案 0 :(得分:0)
我用这段代码解决了它:
$demandes = $em->getRepository(DemandeGroupe::class)->findBy(['acceptee' => true, 'semestre' => $semestre]);
$groupes = $em->getRepository(GroupeComposition::class)->findAll();
$groupesOfCompo = [];
foreach ($groupes as $groupe) {
$groupesOfCompo[] = ['objet' => $groupe,
'nombre' => $groupe->getNombre(),
'jour1' => $groupe->getJour1(). ' '. $groupe->getHoraireJour1(),
'jour2' => $groupe->getJour2(). ' '. $groupe->getHoraireJour2()];
}
// Array to exclude these users afterwards
$tutoresWithDemande = [];
shuffle($demandes);
foreach ($demandes as $demande) {
$tutore1 = $demande->getTutoreSource();
$tutoresWithDemande[] = $tutore1->getId();
$tutore2 = null;
if ($demande->getTutoreDemande()) {
$tutore2 = $demande->getTutoreDemande();
$tutoresWithDemande[] = $tutore2->getId();
}
$dateDemande = null;
if ($demande->getJour() && $demande->getHoraire()) {
$dateDemande = $demande->getJour() . ' ' . $demande->getHoraire();
}
if ($dateDemande) {
// Array of possible groups for current user
$groupes = [];
foreach ($groupesOfCompo as $groupe) {
if ($groupe['jour1'] == $dateDemande || $groupe['jour2'] == $dateDemande) {
// Check if there's enough space left in group && if group is possible for this user
if ((($tutore2 && 0 <= $groupe['nombre'] - 2) ||
(!$tutore2 && 0 <= $groupe['nombre'] - 1))
&& $tutore1->getSituation() === $groupe['objet']->getTypeTutore()
) {
$groupes[] = $groupe;
}
}
}
// Get size of each group
$effectifs = array_column($groupes, 'nombre');
// Get max group size
$max = max($effectifs);
// Get group with max group size
$max_array = $groupes[array_search($max, $effectifs)];
$tutore1->setGroupeComposition($max_array['objet']);
$em->persist($tutore1);
if ($tutore2) {
$tutore2->setGroupeComposition($max_array['objet']);
$em->persist($tutore2);
}
// Get back group from initial array to decrease space left in group
foreach ($groupesOfCompo as &$a) {
if ($a['objet'] === $max_array['objet']) {
if ($tutore2) {
$a['nombre'] -= 2;
}
else {
$a['nombre']--;
}
}
}
}
else {
$groupes = [];
foreach ($groupesOfCompo as $groupe) {
if ((($tutore2 && 0 <= $groupe['nombre'] - 2) ||
(!$tutore2 && 0 <= $groupe['nombre'] - 1))
&& $tutore1->getSituation() === $groupe['objet']->getTypeTutore())
{
$groupes[] = $groupe;
}
}
$effectifs = array_column($groupes, 'nombre');
$max = max($effectifs);
$max_array = $groupes[array_search($max, $effectifs)];
$tutore1->setGroupeComposition($max_array['objet']);
$em->persist($tutore1);
if ($tutore2) {
$tutore2->setGroupeComposition($max_array['objet']);
$em->persist($tutore2);
}
foreach ($groupesOfCompo as &$a) {
if ($a['objet'] === $max_array['objet']) {
if ($tutore2) {
$a['nombre'] -= 2;
}
else {
$a['nombre']--;
}
}
}
}
}
// Get users without DemandeGroupe
$groupeSalle = $em->getRepository(Groupe::class)->findOneBy(['nom' => 'Salle']);
$tutoresWithoutDemande = $em->getRepository(Tutore::class)->findAllExceptExcluded($groupeSalle, $tutoresWithDemande);
shuffle($tutoresWithoutDemande);
foreach ($tutoresWithoutDemande as $tutore) {
// Pour chaque groupe de composition
foreach ($groupesOfCompo as $groupe) {
if (0 <= $groupe['nombre'] - 1 && $tutore->getSituation() === $groupe['objet']->getTypeTutore()) {
$groupes[] = $groupe;
}
}
$effectifs = array_column($groupes, 'nombre');
$max = max($effectifs);
$max_array = $groupes[array_search($max, $effectifs)];
$tutore->setGroupeComposition($max_array['objet']);
$em->persist($tutore);
foreach ($groupesOfCompo as &$a) {
if ($a['objet'] === $max_array['objet']) {
$a['nombre']--;
}
}
}
$em->flush();