Пример #1
0
def treeview_sort_column(app, tv, col, rev):
    '''
        Ordena as linhas com base em uma coluna.
    '''
    entradas = tv.get_children()
    if len(entradas) == 0:
        return
    ctrl.update_action(app, 'sort')
    unsorted_entradas = entradas
    sorted_entradas = sorted(
        entradas,
        key=lambda i: move_to_beginning(SORTING_KEYS[tv.winfo_name()](i), col),
        reverse=rev)

    for i, item in enumerate(sorted_entradas):
        tv.move(item, '', i)

    ctrl.update_action(app, 'sort')
    historico_redo = monitoradas.historico_redo
    historico_undo = monitoradas.historico_undo
    historico_redo.clear()
    historico_undo.append(['sort', tv, unsorted_entradas])

    tv.heading(col,
               command=lambda coluna=col: treeview_sort_column(
                   app, tv, coluna, not rev))
Пример #2
0
    def undo_reserva(event):
        historico_undo = monitoradas.historico_undo
        historico_redo = monitoradas.historico_redo
        try:
            evento = chave, *dados = historico_undo.pop(-1)
            historico_redo.append(evento)
            actions = hst.desfazer[chave](app, *dados)
            try:
                close = dados[0][:-6] != onibus
            except (IndexError, TypeError):
                close = True
            if not close:
                info_reserva = decodificar_id_reserva(dados[0])
                assento = info_reserva.assento
                nonlocal selected
                if selected['text'] != 'None':
                    selected['style'] = 'available.TLabel'
                labels[assento]['style'] = 'selected.TLabel'
                labels[assento]['cursor'] = 'hand2'
                labels[assento].bind('<Button-1>', selecionar)
                selected = labels[assento]
                button_state()
                if len(estado.linhas_entradas[linha].onibus[onibus]) == 0:
                    shift = (sum(coordenadas_assento(assento)) + 1) % 2
                    assentos_invisiveis = {
                        assento_coordenadas(i, 2 * j + (i + shift) % 2)
                        for j in range(2) for i in range(num_fileiras)
                    }
                    for assento_indisponivel in assentos_invisiveis:
                        labels[assento_indisponivel] = labels.get(
                            assento_indisponivel,
                            ttk.Label(painel_assentos,
                                      text=assento_indisponivel,
                                      anchor='center',
                                      takefocus=True,
                                      width=4,
                                      style='available.TLabel',
                                      cursor='hand2'))
                        i, j = coordenadas_assento(assento_indisponivel)
                        labels[assento_indisponivel].grid(
                            row=i,
                            column=j,
                            padx=(0, 10) if j == 1 else
                            (10, 0) if j == 2 else 0)
                        painel_assentos.rowconfigure(i, weight=1)

            if actions == 0:
                hst.undo(app)
            else:
                ctrl.update_action(app,
                                   cte.ACOES_COMPLEMENTARES.get(chave, chave))
        except IndexError:
            close = False
        if close:
            monitoradas.janela_reservas.destroy()
Пример #3
0
def redo(app, evento=None):
    print('CTRL+SHIFT+Z')

    try:
        evento = chave, *dados = monitoradas.historico_redo.pop(-1)
        monitoradas.historico_undo.append(evento)
        actions = refazer[chave](app, *dados)
        if actions == 0:
            redo(app)
        else:
            print(cte.ACTIONS.get(chave, chave))
            ctrl.update_action(app, chave)
    except IndexError:
        print('Nothing to redo...')
Пример #4
0
def undo(app, evento=None):
    print('CTRL+Z')
    try:
        evento = chave, *dados = monitoradas.historico_undo.pop(-1)
        monitoradas.historico_redo.append(evento)
        actions = desfazer[chave](app, *dados)
        if actions == 0:
            undo(app)
        else:
            print(
                cte.ACOES_COMPLEMENTARES.get(chave,
                                             cte.ACTIONS.get(chave, chave)))
            ctrl.update_action(app, cte.ACOES_COMPLEMENTARES.get(chave, chave))
    except IndexError:
        print('Nothing to undo...')
Пример #5
0
def remover_selecao_del(app):
    '''
        Remove as linhas selecionadas.
    '''
    linhas = app.linhas
    itens = sorted(linhas.selection())
    if itens == []:
        # nenhuma linha selecionada
        return
    indices = []
    for item in itens.copy():
        if item in estado.linhas_visiveis:
            estado.linhas_visiveis.remove(item)
            onibus_filhos = estado.linhas_entradas[item].onibus.keys()
            monitoradas.onibus_visiveis -= onibus_filhos
            estado.onibus_invisiveis.update(onibus_filhos)
        elif item in monitoradas.onibus_visiveis:
            monitoradas.onibus_visiveis.remove(item)
            estado.onibus_invisiveis.add(item)
        else:
            itens.remove(item)
            continue
        ctrl.update_action(app, 'rmv')
        indices.append(linhas.index(item))
        linhas.detach(item)

    # atualiza os contadores, já que removemos algumas linhas
    app.contador_linhas['text'] = fm.form_cont_linhas(
        len(estado.linhas_visiveis))
    app.contador_onibus['text'] = fm.form_cont_onibus(
        len(monitoradas.onibus_visiveis))

    if len(indices) > 0:
        historico_undo = monitoradas.historico_undo
        historico_redo = monitoradas.historico_redo
        indices = indices[::-1]
        itens = itens[::-1]
        if len(historico_undo
               ) == 0 or historico_undo[-1] != ['rmv', indices, itens]:
            ctrl.update_action(app, 'rmv')
            historico_redo.clear()
            # adicionamos o evento da remoção no histórico, para permitir CTRL+Z
            historico_undo.append(['rmv', indices, itens])
Пример #6
0
def check_pressed_rmv(app, indices, itens):
    pressed = monitoradas.pressed

    if pressed:
        indices, itens = remover_selecao(app, indices, itens)

        app.root.after(20, lambda *_: check_pressed_rmv(app, indices, itens))
    else:
        if len(indices) > 0:
            historico_undo = monitoradas.historico_undo
            historico_redo = monitoradas.historico_redo
            historico_redo.clear()
            indices = indices[::-1]
            itens = itens[::-1]
            if len(historico_undo
                   ) == 0 or historico_undo[-1] != ['rmv', indices, itens]:
                ctrl.update_action(app, 'rmv')
                historico_redo.clear()
                historico_undo.append(['rmv', indices, itens])
Пример #7
0
    def finalizar():
        '''
            Realiza a reserva. Chamado quando o usuário clica no botão Reservar.
        '''
        nonlocal selected
        assento = int(selected['text'])
        if len(estado.linhas_entradas[linha].onibus[onibus]) == 0:
            shift = (sum(coordenadas_assento(assento)) + 1) % 2
            assentos_invisiveis = {
                assento_coordenadas(i, 2 * j + (i + shift) % 2)
                for j in range(2) for i in range(num_fileiras)
            }
            for assento_indisponivel in assentos_invisiveis:
                labels[assento_indisponivel].grid_remove()
        tipo = passagem.get()
        estado.linhas_entradas[linha].onibus[onibus][assento] = tipo
        reserva = gerar_id_reserva(onibus, assento, tipo)
        estado.reservas.add(reserva)
        # insere essa reserva na aba de reservas
        app.reservas.insert(parent='',
                            index=0,
                            values=campos_reserva_formatados(reserva),
                            iid=reserva)
        prev_values = linhas.set(onibus)
        prev_values['assentos livres'] = int(
            prev_values['assentos livres']) - 1
        linhas.item(onibus, values=tuple(prev_values.values()))
        labels[assento]['cursor'] = 'X_cursor'
        labels[assento]['style'] = estilo[tipo]
        labels[assento].unbind('<Button-1>')
        selected = ttk.Label(painel_assentos, text='None')

        historico_undo = monitoradas.historico_undo
        historico_redo = monitoradas.historico_redo
        historico_redo.clear()
        historico_undo.append(['book', reserva])
        button_state()
        app.contador_reservas['text'] = fm.form_cont_reservas(
            len(estado.reservas))
        ctrl.update_action(app, 'book')
Пример #8
0
def remover_selecao(app, indices, itens):
    linhas = app.linhas
    # assim as linhas são acessadas primeiro, removendo possíveis ônibus filhos, já que o detach de uma linha desabilita junto os seus filhos (ônibus)
    cur_itens = sorted(linhas.selection())
    if cur_itens == []:
        try:
            cur_itens = [linhas.get_children()[0]]

        except IndexError:
            released(1)
            return indices, itens

    cur_indices = []
    for item in cur_itens.copy():
        if item in estado.linhas_visiveis:
            estado.linhas_visiveis.remove(item)
            onibus_filhos = estado.linhas_entradas[item].onibus.keys()
            monitoradas.onibus_visiveis -= onibus_filhos
            estado.onibus_invisiveis.update(onibus_filhos)
        elif item in monitoradas.onibus_visiveis:
            monitoradas.onibus_visiveis.remove(item)
            estado.onibus_invisiveis.add(item)
        else:
            # remove ônibus filhos caso sua linha haja sido selecionada
            cur_itens.remove(item)
            continue
        ctrl.update_action(app, 'rmv')
        cur_indices.append(linhas.index(item))
        linhas.detach(item)
    app.contador_linhas['text'] = fm.form_cont_linhas(
        len(estado.linhas_visiveis))
    app.contador_onibus['text'] = fm.form_cont_onibus(
        len(monitoradas.onibus_visiveis))

    indices.extend(cur_indices)
    itens.extend(cur_itens)

    return indices, itens
Пример #9
0
    def redo_reserva(event):
        historico_undo = monitoradas.historico_undo
        historico_redo = monitoradas.historico_redo
        try:
            evento = chave, *dados = historico_redo.pop(-1)
            historico_undo.append(evento)
            actions = hst.refazer[chave](app, *dados)
            try:
                close = dados[0][:-6] != onibus
            except (IndexError, TypeError):
                close = True
            if not close:
                info_reserva = decodificar_id_reserva(dados[0])
                assento, tipo = info_reserva.assento, info_reserva.passagem.tipo
                labels[assento]['cursor'] = 'X_cursor'
                labels[assento]['style'] = estilo[tipo]
                labels[assento].unbind('<Button-1>')
                nonlocal selected
                selected = ttk.Label(painel_assentos, text='None')
                button_state()
                if len(estado.linhas_entradas[linha].onibus[onibus]) == 1:
                    shift = (sum(coordenadas_assento(assento)) + 1) % 2
                    assentos_invisiveis = {
                        assento_coordenadas(i, 2 * j + (i + shift) % 2)
                        for j in range(2) for i in range(num_fileiras)
                    }
                    for assento_indisponivel in assentos_invisiveis:
                        labels[assento_indisponivel].grid_remove()

            if actions == 0:
                hst.redo(app)
            else:
                ctrl.update_action(app, chave)
        except IndexError:
            close = False
        if close:
            monitoradas.janela_reservas.destroy()
Пример #10
0
def adicionar_linha(app):
    '''
        Adiciona uma linha com base nos campos de texto.
    '''
    # lemos todos os campos de texto
    campos = [
        dest.atualizar_destino(),
        date.update(app),
        vg.atualizar_vagas(),
        it.atualizar_inteira()
    ]

    for campo in campos:
        if popup.campos_invalidos[campo]():
            return
    # aqui, todos os campos de texto possuem valores válidos, então vamos criar a linha

    linhas = app.linhas
    destino = monitoradas.destino.get()
    tempo_exibido = monitoradas.tempo_exibido
    vagas = monitoradas.vagas.get()
    inteira = monitoradas.inteira.get()
    linha = gerar_id_linha(destino, tempo_exibido)
    # antes de inseri-la graficamente, temos que verificar se ela já existe
    if linha in estado.linhas_entradas:
        # Linha desabilitada. Deseja reabilitá-la?
        if linha not in estado.linhas_visiveis:
            texto = 'Linha desabilitada, deseja reabilitá-la?.'
            resposta = messagebox.askyesno(title='Linha existe',
                                           message=texto,
                                           default='yes')
            if resposta:
                app.linhas.reattach(linha, '', 0)
                estado.linhas_visiveis.add(linha)
                onibus_filhos_visiveis = set(app.linhas.get_children(linha))
                estado.onibus_invisiveis -= onibus_filhos_visiveis
                monitoradas.onibus_visiveis.update(onibus_filhos_visiveis)
                ctrl.update_action(app, 'Restaurar')

                monitoradas.historico_redo.clear()
                monitoradas.historico_undo.append(['show', [0], [linha]])
                app.linhas.selection_set(linha)
                app.contador_linhas['text'] = fm.form_cont_linhas(
                    len(estado.linhas_visiveis))
                app.contador_onibus['text'] = fm.form_cont_onibus(
                    len(monitoradas.onibus_visiveis))
                # nova ação: reabilitar
        else:
            app.linhas.see(linha)
            app.linhas.selection_set(linha)
        return
    h = minutos_dia(tempo_exibido)
    estado.linhas_possiveis.discard((destino, h))
    estado.horarios_linhas[h] = estado.horarios_linhas.get(h, set()).union(
        {linha})

    dest.add_destino(app)
    ctrl.update_action(app, 'add')
    linhas.insert(parent='',
                  index=0,
                  values=(destino, fm.form_tempo(tempo_exibido), vagas,
                          inteira),
                  iid=linha)
    estado.linhas_visiveis.add(linha)
    app.contador_linhas['text'] = fm.form_cont_linhas(
        len(estado.linhas_visiveis))

    estado.linhas_entradas[linha] = cte.ESTRUTURA_LINHA(
        destino, tempo_exibido,
        int(vagas) // 2, round(float(inteira) * 100 - 300), dict())

    data_atual = monitoradas.data_atual.replace(second=0, microsecond=0)
    for d in range(cte.MAXIMO_NUMERO_DE_DIAS_ATE_RESERVA + 1):
        partida = (data_atual + dt.timedelta(d)).replace(
            hour=tempo_exibido.hour, minute=tempo_exibido.minute)
        if data_atual <= partida <= data_atual + dt.timedelta(
                cte.MAXIMO_NUMERO_DE_DIAS_ATE_RESERVA):
            onibus = gerar_id_onibus(linha, partida)
            linhas.insert(parent=linha,
                          index='end',
                          values=('-', fm.form_data(partida), vagas, '-'),
                          iid=onibus)
            monitoradas.onibus_visiveis.add(onibus)
            estado.linhas_entradas[linha].onibus[onibus] = dict()
            app.contador_onibus['text'] = fm.form_cont_onibus(
                len(monitoradas.onibus_visiveis))

    app.contador_linhas['text'] = fm.form_cont_linhas(
        len(estado.linhas_visiveis))
    app.contador_onibus['text'] = fm.form_cont_onibus(
        len(monitoradas.onibus_visiveis))

    historico_undo = monitoradas.historico_undo
    historico_redo = monitoradas.historico_redo
    historico_redo.clear()
    historico_undo.append(['add', [[estado.linhas_entradas[linha], list()]]])
    linhas.selection_set(linha)
Пример #11
0
def editar_linha(app):
    '''
        Edita informações sobre uma linha.
    '''
    selecao = app.linhas.selection()
    if len(selecao) != 1 or app.linhas.parent(selecao[0]) != '':
        texto = 'Selecione uma única linha.'
        messagebox.showwarning(title='Impossível Editar', message=texto)
        return
    [linha] = selecao
    dados_linha = estado.linhas_entradas[linha]
    # a condição a seguir é True sse existe algum ônibus com reservas na linha selecionada.
    if any(len(x) != 0 for x in dados_linha.onibus.values()):
        texto = 'Linha possui reservas.'
        messagebox.showwarning(title='Impossível Editar', message=texto)
        return

    campos = [
        dest.atualizar_destino(),
        date.update(app),
        vg.atualizar_vagas(),
        it.atualizar_inteira()
    ]

    for campo in campos:
        if popup.campos_invalidos[campo]():
            return

    destino_alterada = monitoradas.destino.get()
    tempo_exibido = monitoradas.tempo_exibido
    vagas_alterada = monitoradas.vagas.get()
    inteira_alterada = monitoradas.inteira.get()
    linha_alterada = gerar_id_linha(destino_alterada, tempo_exibido)

    h = minutos_dia(estado.linhas_entradas[linha].horario)

    if linha_alterada in estado.linhas_entradas:
        if linha_alterada in estado.linhas_visiveis:
            if linha != linha_alterada:
                texto = 'Linha já existe.'
                messagebox.showwarning(title='Impossível Editar',
                                       message=texto)
            elif dados_linha[2:4] != [
                    int(vagas_alterada) // 2,
                    round(float(inteira_alterada) * 100 - 300)
            ]:
                dados_linha_alterada = estado.linhas_entradas[
                    linha] = cte.ESTRUTURA_LINHA(
                        *dados_linha[:2],
                        int(vagas_alterada) // 2,
                        round(float(inteira_alterada) * 100 - 300),
                        dados_linha[-1])
                app.linhas.item(
                    linha,
                    values=campos_linha_formatados(dados_linha_alterada))

                app.linhas.selection_set(linha_alterada)
                monitoradas.historico_redo.clear()
                monitoradas.historico_undo.append(
                    ['change', dados_linha, dados_linha_alterada, False])
                app.contador_linhas['text'] = fm.form_cont_linhas(
                    len(estado.linhas_visiveis))
                app.contador_onibus['text'] = fm.form_cont_onibus(
                    len(monitoradas.onibus_visiveis))

        else:
            texto = 'Linha desabilitada, deseja reabilitá-la?'
            resposta = messagebox.askyesno(title='Impossível Editar',
                                           message=texto,
                                           default='no')
            if resposta:
                app.linhas.reattach(linha_alterada, '',
                                    app.linhas.index(linha))
                app.linhas.item(linha_alterada,
                                open=app.linhas.item(linha, 'open'))
                estado.linhas_visiveis.add(linha_alterada)
                onibus_filhos_visiveis = set(
                    app.linhas.get_children(linha_alterada))
                estado.onibus_invisiveis -= onibus_filhos_visiveis
                monitoradas.onibus_visiveis.update(onibus_filhos_visiveis)
                ctrl.update_action(app, 'Restaurar')
                estado.horarios_linhas[h].remove(linha)
                app.linhas.delete(linha)
                estado.linhas_visiveis.remove(linha)
                for onibus in estado.linhas_entradas[linha].onibus:
                    monitoradas.onibus_visiveis.discard(onibus)
                    estado.onibus_invisiveis.discard(onibus)

                monitoradas.historico_redo.clear()
                monitoradas.historico_undo.append([
                    'change', estado.linhas_entradas[linha],
                    estado.linhas_entradas[linha_alterada], True
                ])
                estado.linhas_possiveis.add((dados_linha.destino.title(), h))
                del estado.linhas_entradas[linha]
                app.linhas.selection_set(linha_alterada)
                app.contador_linhas['text'] = fm.form_cont_linhas(
                    len(estado.linhas_visiveis))
                app.contador_onibus['text'] = fm.form_cont_onibus(
                    len(monitoradas.onibus_visiveis))
        return
    h_alt = tempo_exibido.hour * 60 + tempo_exibido.minute
    estado.linhas_possiveis.remove((destino_alterada, h_alt))
    estado.linhas_possiveis.add((dados_linha.destino.title(), h))
    estado.horarios_linhas[h].remove(linha)
    estado.horarios_linhas[h_alt] = estado.horarios_linhas.get(
        h_alt, set()).union({linha_alterada})
    dest.add_destino(app)
    ctrl.update_action(app, 'change')
    indice = app.linhas.index(linha)
    app.linhas.insert(parent='',
                      index=indice,
                      values=(destino_alterada, fm.form_tempo(tempo_exibido),
                              vagas_alterada, inteira_alterada),
                      iid=linha_alterada,
                      open=app.linhas.item(linha, 'open'))
    app.linhas.delete(linha)
    estado.linhas_visiveis.remove(linha)
    estado.linhas_visiveis.add(linha_alterada)

    onibus_filhos = dict()

    data_atual = monitoradas.data_atual.replace(second=0, microsecond=0)
    for d in range(cte.MAXIMO_NUMERO_DE_DIAS_ATE_RESERVA + 1):
        partida = (data_atual + dt.timedelta(d)).replace(
            hour=tempo_exibido.hour, minute=tempo_exibido.minute)
        if data_atual <= partida <= data_atual + dt.timedelta(
                cte.MAXIMO_NUMERO_DE_DIAS_ATE_RESERVA):
            onibus = gerar_id_onibus(linha_alterada, partida)
            app.linhas.insert(parent=linha_alterada,
                              index='end',
                              values=('-', fm.form_data(partida),
                                      vagas_alterada, '-'),
                              iid=onibus)
            monitoradas.onibus_visiveis.add(onibus)
            onibus_filhos[onibus] = dict()

    estado.linhas_entradas[linha_alterada] = cte.ESTRUTURA_LINHA(
        destino_alterada, tempo_exibido,
        int(vagas_alterada) // 2, round(float(inteira_alterada) * 100 - 300),
        onibus_filhos)

    for onibus in estado.linhas_entradas[linha].onibus:
        monitoradas.onibus_visiveis.discard(onibus)
        estado.onibus_invisiveis.discard(onibus)

    monitoradas.historico_redo.clear()
    monitoradas.historico_undo.append([
        'change', estado.linhas_entradas[linha],
        estado.linhas_entradas[linha_alterada], False
    ])

    del estado.linhas_entradas[linha]
    app.contador_linhas['text'] = fm.form_cont_linhas(
        len(estado.linhas_visiveis))
    app.contador_onibus['text'] = fm.form_cont_onibus(
        len(monitoradas.onibus_visiveis))

    ctrl.update_action(app, 'change')
    app.linhas.selection_set(linha_alterada)
Пример #12
0
    def gerar(event=None):
        '''
            Gera as linhas conforme a quantidade indicada pelo spin_linhas.
            É executado quando o usuário clica no botão de gerar, ou aperta ENTER.
        '''
        if not atualizar_num():
            # aqui, atualizar_num retornou False, o que significa que a entrada é inválida
            messagebox.showwarning(title='Entrada Inválida',
                                   message='Valor inválido!',
                                   parent=configuracoes)
            return

        from random import choice, randrange, sample
        ocupar = monitoradas.ocupar_assentos.get()
        # Uma sequência em que o valor assento_coordenadas(i, j) indica o número do assento na linha i e coluna j.
        # Note que para cada linha, há 4 colunas (índice j varia de 0 a 3).
        # As colunas 0 e 3 são adjacentes à janela e as colunas 1 e 2 são adjacentes ao corredor.
        # Essa sequência pode ser vista ao tentar reservar um assento.
        def assento_coordenadas(i, j): return 2*i + j + \
            1 if j <= 1 else 2*(num_fileiras + i + 2) - j
        dados = []
        data_atual = monitoradas.data_atual
        minutos_atual = data_atual.hour*60 + data_atual.minute
        # termo(monitoradas.indice_linhas_geradas) é o número de linhas indicado pelo spin_linhas
        # note que minutes[:termo(monitoradas.indice_linhas_geradas)] seleciona
        # justamente a quantidade de linhas que queremos!
        # como minutes foi permutado aleatoriamente, os horários em minutes escolhidos
        # pelo slicing são aleatórios e diferentes entre si
        for destino, t in sample(estado.linhas_possiveis, termo(monitoradas.indice_linhas_geradas)):
            estado.linhas_possiveis.discard((destino, t))
            # t é uma quantidade de minutos da lista minutes, que usaremos para calcular o horário dessa linha que
            # iremos cadastrar!
            interval = dt.timedelta(minutes=t)
            horario = data_atual.replace(hour=0, minute=0) + interval
            if data_atual > horario:
                horario += dt.timedelta(1)
            linha = gerar_id_linha(destino, horario)

            indice_vagas = choice(range(cte.MAXIMO_NUMERO_DE_FILEIRAS))
            num_fileiras = indice_vagas + 1
            vagas = vg.vagas_termo(indice_vagas)
            indice_inteira = choice(range(301))
            inteira = it.inteira_termo(indice_inteira)

            estado.horarios_linhas[t] = estado.horarios_linhas.get(
                t, set()).union({linha})

            app.linhas.insert(parent='',
                              index=0,
                              values=(destino, fm.form_tempo(
                                  horario), vagas, inteira),
                              iid=linha)
            estado.linhas_entradas[linha] = cte.ESTRUTURA_LINHA(
                destino, horario, num_fileiras, indice_inteira, dict())
            estado.linhas_visiveis.add(linha)

            reservas = list()

            # calculamos o período de dias em que haverá ônibus partindo
            if t == minutos_atual:
                periodo = range(cte.MAXIMO_NUMERO_DE_DIAS_ATE_RESERVA + 1)
            elif t < minutos_atual:
                # aqui, o horário da linha é menor que o horário atual,
                # então não vamos criar um ônibus para o dia de hoje, pois ele já partiu
                periodo = range(1, cte.MAXIMO_NUMERO_DE_DIAS_ATE_RESERVA + 1)
            else:
                # aqui, o horário da linha é maior que o horário atual,
                # então vamos incluir o dia de hoje
                periodo = range(cte.MAXIMO_NUMERO_DE_DIAS_ATE_RESERVA)

            for d in periodo:
                # para cada dia no período calculado, vamos adicionar um ônibus
                # note que d = 0 representa o dia de hoje, d = 1 é amanhã, etc.
                partida = data_atual + dt.timedelta(d)
                onibus = gerar_id_onibus(linha, partida)
                assentos_disponiveis = randrange(vagas+1) if ocupar else vagas
                app.linhas.insert(parent=linha, index='end', values=(
                    '-', fm.form_data(partida), assentos_disponiveis, '-'), iid=onibus)
                estado.linhas_entradas[linha].onibus[onibus] = dict()
                if assentos_disponiveis < vagas:
                    # nesse caso, significa que o usuário pediu para "Ocupar assentos"
                    # e o valor aleatorio assentos disponíveis é menor que a quantidade de vagas
                    # então, devemos fazer algumas reservas aleatórias!
                    # primeiro, vamos escolher quais assentos serão escolhíveis
                    # (afinal, metade dos assentos serão disponíveis, então vamos escolher qual metade)
                    shift = choice(range(2))
                    # os assentos escolhíveis respeitam as condições impostas pela pandemia
                    # basicamente, selecionamos (i, (i + shift) % 2) e (i, 2 + (i + shift) % 2) para todo i
                    # por exemplo,
                    # i = 0, shift = 0 -> selecionamos (0, 0) e (0, 2)
                    # i = 1, shift = 0 -> selecionamos (1, 1) e (1, 3)
                    # i = 2, shift = 0 -> selecionamos (2, 0) e (2, 2)
                    # Note que a primeira posição é um assento da seção da esquerda
                    # e a segunda posição é um assento da seção da direita
                    # e selecionamos dois assentos por linha
                    assentos_visiveis = {assento_coordenadas(i, 2 * j + (i + shift) % 2) for j in range(2)
                                         for i in range(num_fileiras)}
                    # a função sample seleciona aleatoriamente números de assentos escolhíveis para
                    # fazermos reserva
                    for assento in sample(assentos_visiveis, vagas - assentos_disponiveis):
                        # a variável assento é um número de assento escolhível aleatório
                        # devemos reservar esse assento!
                        passagem = choice([2]*3+[1]*2+[0])
                        estado.linhas_entradas[linha].onibus[onibus][assento] = passagem
                        reserva = gerar_id_reserva(onibus, assento, passagem)
                        estado.reservas.add(reserva)
                        reservas.insert(0, reserva)
                        app.reservas.insert(parent='',
                                            index=0,
                                            values=campos_reserva_formatados(
                                                reserva),
                                            iid=reserva)
                monitoradas.onibus_visiveis.add(onibus)

            dados.append([estado.linhas_entradas[linha], reservas])

        ctrl.update_action(app, 'add')

        historico_undo = monitoradas.historico_undo
        historico_redo = monitoradas.historico_redo
        historico_redo.clear()
        historico_undo.append(['add', dados])

        app.contador_linhas['text'] = fm.form_cont_linhas(
            len(estado.linhas_visiveis))
        app.contador_onibus['text'] = fm.form_cont_onibus(
            len(monitoradas.onibus_visiveis))
        app.contador_reservas['text'] = fm.form_cont_reservas(
            len(estado.reservas))
        configuracoes.destroy()