How to implement a priority queue that still meets other requirements?

Asked

Viewed 629 times

1

I need to implement a priority queue, this queue in addition to the priority, needs to take into account some other requirements, such as switching between services and professionals, and of course respect the client’s order of arrival for that service and/or professional.

My complete (hypothetical) scenario:

In a hospital we have three services offered (this in any other company can be the same situation, a law firm finally.):

Appointments, exams that will be performed on the day and another service that is a scheduling of exams. The system needs to switch between services, like, called someone’s query, the next should be from any other service and so on. The system also needs to switch between professionals, the call earlier was professional 1, the next should be professional 2 and so on.

I’ve been researching about some lib or some algorithm and the closest I found was the Python heapq but I couldn’t adapt and assemble my solution.

I really need a help, I accept suggestions of implementations, indications of libs that solve this problem anyway.

I tried several solutions and none showed the desired result.

I stand by.

PS: I did several searches here in the OS and did not find any similar question, if repeated please indicate question link.

2 answers

1

I can think of some ways to solve this - but it’s complicated: a professional development task - it would be pretty long to answer here. And - suddenly time would be better engaged in creating a small Python package that could do that, instead of coming up with a working example here.

To give you some hints: Python’s "heapq" usually only compares the object itself (for example the "chip number") - a first step, if you choose to use the heapq, is to be able to pass a sort function that can have complex rules - just as we can pass the parameter "key" to the sorted. I have an answer in the S.O. in English that creates a small wrapper class of heapq that facilitates this: https://stackoverflow.com/a/8875823/108205

Now, your "key" function would have to take into account information that is outskirts to the element it is comparing - for example: what was the last sub-row called, and what was the last professional called - the function key Sorted only receives the element itself - without being able to look at the rest of the queue. In this case, you have to take advantage that you have a custom class, and instead accept the "key" as the __init__ as in the example I passed, do the function key within the class itself: and it will be able to look inside the elements that are already in the queue to take into account the other factors.

Another thing you can look at is the "redis" - it will allow you to keep a persistent queue between distinct HTTP requests - even if you have multiple machines serving requests to your application (or multiple processes and threads - which and normal in a production environment)

  • In terms of persistent queue (it doesn’t come ready, it needs some configuration, but it’s little) AP can also look at the Rabbitmq.

0

You can use the from itertools import cycle, in this case, you can make it stay permanently running over a list, using the function next(iter). So you can move on to a list of patients (for example) while alternating a (probably smaller) list of professionals.

It would be a code +- like this:

from itertools import cycle

class Filas:
    def __init__(self):
        self.dicio_filas = {
            "fila_um" : ["Fulano A", "Fulano B", "Fulano C", "Fulano D"],
            "fila_dois" : ["Fulano E", "Fulano F", "Fulano G"],
            "fila_tres" : ["Fulano H", "Fulano I", "Fulano J", "Fulano K", "Fulano L"]
        }
        self.lista_filas = cycle(list(self.dicio_filas.keys()))
        self.lista_prof = cycle(["Prof A", "Prof B", "Prof C"])

    def verifica(self):
        for i in self.dicio_filas:
            if len(self.dicio_filas[i]) == 0:
                del self.dicio_filas[i]

    def chama_fila(self):
        while True:
            prox = next(self.lista_filas)
            if prox in self.dicio_filas:
                if len(self.dicio_filas[prox]) == 0:
                    self.verifica()
                else:
                    return self.dicio_filas[prox].pop(0)
            else:
                if len(self.dicio_filas) == 0:
                    return None

    def chama_prof(self):
        chamar = self.lista_prof
        chamar = next(chamar)
        return chamar

    def direcionador(self):
        fila = self.chama_fila()
        if fila == None:
            text = "Não há mais ninguém na fila de espera!"
            print(text)
            return text
        else:
            func = self.chama_prof()
            print(f"O próximo é {fila}, favor ir até o profissional {func}")
            return fila, func

Then you matter in another process (if it is in Jupyter, in another cell)

chamar = Filas()

And then, for every time we run chamar.direcionador() on the call:

chamar.direcionador()

It will call the first of each row, alternating between the lines and removing the person called from the queue, directing sequentially to each professional. Example:

O próximo é Fulano A, favor ir até o profissional Prof A
O próximo é Fulano E, favor ir até o profissional Prof B
O próximo é Fulano H, favor ir até o profissional Prof C
O próximo é Fulano B, favor ir até o profissional Prof A
...
Não há mais ninguém na fila de espera!

There your lists and dictionaries you customize/customize them.

I hope I’ve helped.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.