Je pense que c'est un travail pour les champs de bits. Malheureusement, cette solution reposera sur des nombres magiques, des aides à la conversion et une bonne partie de la logique binaire, donc ce ne sera pas joli. Mais cela fonctionnera et sera très efficace.
Voici comment j'aborder le problème:
Anéantissez vos jours dans des intervalles de temps raisonnables. Je vais suivre votre exemple et traiter chaque bloc de temps de 15 minutes comme étant considéré comme un morceau de temps (surtout parce qu'il garde l'exemple simple). Ensuite, représentez votre disponibilité par heure en tant que chiffre hexadécimal.
Exemple:
- 0xF = 0x1111 => disponible pour toute heure.
- 0xC = 0x1100 => disponible pour la première moitié de l'heure.
Chaîne de 24 ensemble pour représenter un jour. Ou moins si vous pouvez être sûr qu'aucun événement ne se produira en dehors de la plage. L'exemple continue en supposant 24 heures.
A partir de là, j'ai Fractionnement des nombres hexadécimaux en mots pour la lisibilité En supposant que le jour va 0h00-à-23h59 business_hours['monday'] = 0x0000 0000 FFFF 0FFF F000 0000
Pour busy_hours vous stocker des événements dans un format similaire, et juste & tous ensemble.
Exmample:
event_a = 0x0000 0000 00F0 0000 0000 0000 # 10:00 - 11:00
event_b = 0x0000 0000 0000 07F8 0000 0000 # 13:15 - 15:15
busy_hours = event_a & event_b
De busy_hours et Business_hours vous pouvez obtenir des heures disponibles:
available_hours = Business_hours & (busy_hours^0xFFFF FFFF FFFF FFFF FFFF FFFF)
XOR (^) essentialy traduit busy_hours en not_busy_hours. Anding (&) not_busy_hours avec business_hours nous donne les heures disponibles pour la journée.
Ce système facilite également la comparaison des heures disponibles pour de nombreuses personnes.
all_available_hours = person_a_available_hours & person_b_available_hours & person_c_available_hours
Puis de trouver un intervalle de temps qui correspond aux heures disponibles. Vous devez faire quelque chose comme ceci: Convertissez votre longueur de temps en un chiffre hexadécimal similaire à l'heure où les uns représentent tous les morceaux de temps de cette heure que l'intervalle de temps couvrira. Ensuite, déplacez le chiffre vers la droite pour qu'il n'y ait pas de 0 à la fin.
exemples sont mieux que des explications: 0x1 => 15 minutes, 0x3 => demi-heure, 0x7 => 45 minutes, 0xF => pleine heure, ... 0xFF => 2 heures, etc.
Une fois que vous avez fait cela, vous faites ceci:
acceptable_times =[]
(0 .. 24 * 4 - (#of time chunks time slot)).each do |i|
acceptable_times.unshift(time_slot_in_hex) if available_hours & (time_slot_in_hex << i) == time_slot_in_hex << i
end
Le haut de gamme est un peu en désordre. Alors regardons un peu plus là-dessus. Nous ne voulons pas changer trop souvent, sinon nous pourrions commencer à obtenir des faux positifs au tout début du spectre.
24 * 4
24 heures dans la journée, chacune représentée par 4 bits. Soustrayez 1 chèque toutes les 15 minutes dans le créneau horaire que nous recherchons.Cette valeur peut être trouvée par (Math.log(time_slot_in_hex)/Math.log(2)).floor + 1
Qui commence à la fin de la journée, en vérifiant chaque intervalle de temps, se déplaçant plus tôt par un morceau de temps (15 minutes dans cet exemple) à chaque itération. Si le créneau horaire est disponible, il est ajouté au début des heures acceptables. Ainsi, lorsque le processus termine acceptable_times est trié par ordre d'occurrence. Ce qui est cool, c'est que cette implémentation permet aux créneaux horaires qui intègrent pour que votre participant puisse avoir une période occupée dans leur journée qui divise l'intervalle de temps que vous cherchez avec une pause, où ils pourraient être autrement occupés. C'est à vous d'écrire des fonctions d'aide qui se traduisent par un tableau de plages (ie: [800..1200, 1300..1700]) et la représentation hexadécimale. Le meilleur moyen d'y parvenir est d'encapsuler le comportement dans un objet et d'utiliser des méthodes d'accès personnalisées. Ensuite, utilisez les mêmes objets pour représenter les jours, les événements, les heures de pointe, etc. La seule chose qui n'est pas intégrée dans ce schéma est la façon de planifier les événements afin qu'ils puissent s'étendre sur plusieurs jours.
ce problème est la raison pour laquelle le logiciel de planification coûte beaucoup d'argent :) – avguchenko
J'espérais pouvoir utiliser une bibliothèque existante mais je n'ai rien trouvé. J'espère que d'autres SOers pourront faire la lumière. – Alexandre
On dirait que vous pourriez étendre Range faire ce que vous voulez, mais le problème ici est que vous utilisez une représentation de base-10 d'une valeur de base-60. 900 - 830 = 70, pas 30. – tadman