Exemple #1
0
def descadastrar_linhas(app, dados):
    actions = 0
    reservas_changed = False

    for dados_linha, reservas in dados:
        linha = gerar_id_linha(*dados_linha[:2])
        for reserva in reservas:
            estado.reservas.discard(reserva)
            app.reservas.delete(reserva)
            reservas_changed = True

        app.contador_reservas['text'] = fm.form_cont_reservas(
            len(estado.reservas))

        t = minutos_dia(dados_linha.horario)

        del estado.linhas_entradas[linha]
        estado.linhas_possiveis.add((dados_linha.destino.title(), t))
        estado.horarios_linhas[t].remove(linha)
        estado.linhas_visiveis.remove(linha)
        app.contador_linhas['text'] = fm.form_cont_linhas(
            len(estado.linhas_visiveis))
        onibus_filhos = dados_linha.onibus.keys()
        monitoradas.onibus_visiveis -= onibus_filhos
        estado.onibus_invisiveis -= onibus_filhos
        app.contador_onibus['text'] = fm.form_cont_onibus(
            len(monitoradas.onibus_visiveis))
        app.linhas.delete(linha)

        actions += 1

    if not reservas_changed:
        app.abas.select(app.aba_linhas)

    return actions
Exemple #2
0
def detach_linhas(app, indices, itens):
    actions = 0

    for item in itens:
        if item in estado.linhas_visiveis:
            estado.linhas_visiveis.remove(item)
            app.contador_linhas['text'] = fm.form_cont_linhas(
                len(estado.linhas_visiveis))
            onibus_filhos_visiveis = set(app.linhas.get_children(item))
            monitoradas.onibus_visiveis -= onibus_filhos_visiveis
            estado.onibus_invisiveis.update(onibus_filhos_visiveis)
            app.contador_onibus['text'] = fm.form_cont_onibus(
                len(monitoradas.onibus_visiveis))
        elif item in monitoradas.onibus_visiveis:
            monitoradas.onibus_visiveis.remove(item)
            estado.onibus_invisiveis.add(item)
            app.contador_onibus['text'] = fm.form_cont_onibus(
                len(monitoradas.onibus_visiveis))
        else:
            continue
        app.linhas.detach(item)
        actions += 1

    if actions > 0:
        app.abas.select(app.aba_linhas)

    return actions
Exemple #3
0
def reattach_linhas(app, indices, itens):
    '''
        Readiciona as linhas (itens) nos indices indicados.
    '''
    actions = 0

    for i, item in zip(indices, itens):
        # linhas são entidades dinâmicas, precisa checar se ônibus removidos não expiraram e inserir novos ônibus
        if item in estado.linhas_entradas and item not in estado.linhas_visiveis:
            app.linhas.reattach(item, '', i)
            estado.linhas_visiveis.add(item)
            app.contador_linhas['text'] = fm.form_cont_linhas(
                len(estado.linhas_visiveis))
            onibus_filhos_visiveis = set(app.linhas.get_children(item))
            estado.onibus_invisiveis -= onibus_filhos_visiveis
            monitoradas.onibus_visiveis.update(onibus_filhos_visiveis)
            app.contador_onibus['text'] = fm.form_cont_onibus(
                len(monitoradas.onibus_visiveis))

        elif item in estado.onibus_invisiveis:  # inserir apenas se estiver no intervalo válido
            estado.onibus_invisiveis.remove(item)
            monitoradas.onibus_visiveis.add(item)
            app.contador_onibus['text'] = fm.form_cont_onibus(
                len(monitoradas.onibus_visiveis))
            app.linhas.reattach(item, item[:-7], i)
            app.linhas.see(item)
        else:
            continue
        actions += 1

    if actions > 0:
        app.abas.select(app.aba_linhas)
        app.linhas.selection_set(itens)
    return actions
Exemple #4
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])
Exemple #5
0
def povoar_treeviews(app):
    '''
        Inicializa a interface gráfica com os dados persistidos.
    '''
    onibus_invisiveis = set()
    for linha in estado.ordem_inicial_linhas:
        onibus_invisiveis.update(reinsert_linha(app, linha))
    estado.ordem_inicial_linhas = tuple()
    for linha in estado.linhas_entradas.keys() - estado.linhas_visiveis:
        onibus_invisiveis.update(reinsert_linha(app, linha, False))
    for reserva in estado.ordem_inicial_reservas:
        app.reservas.insert(parent='',
                            index=0,
                            values=campos_reserva_formatados(reserva),
                            iid=reserva)
    estado.onibus_invisiveis = onibus_invisiveis
    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))
    print('Dados persistentes carregados.')
Exemple #6
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
Exemple #7
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)
Exemple #8
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)
Exemple #9
0
def adicionar_linha(app, indice, linha, data_atual=monitoradas.data_atual):
    '''
        Altera o estado da aplicação (incluindo a interface gráfica) para incluir a linha especificada no argumento.
    '''
    destino = linha.campus.title()
    if destino not in estado.destinos:
        # adicionamos o destino da linha do argumento, caso ele não exista
        estado.destinos.append(destino)
        estado.linhas_possiveis.update({(destino, t) for t in range(1440)})
        estado.destinos.sort()  # mantemos a ordenação
        app.entrada_destino['values'] = estado.destinos
        monitoradas.destino.set(estado.destinos[0])
    t = minutos_dia(linha.horario)
    estado.horarios_linhas[t] = estado.horarios_linhas.get(
        t, set()).union({linha.id})
    # incluimos a linha na interface gráfica
    estado.linhas_possiveis.discard((destino, t))
    app.linhas.insert(parent='',
                      index=indice,
                      values=(destino, fm.form_tempo(linha.horario), 2 *
                              linha.fileiras, it.inteira_termo(linha.inteira)),
                      iid=linha.id)
    estado.linhas_visiveis.add(linha.id)
    app.contador_linhas['text'] = fm.form_cont_linhas(
        len(estado.linhas_visiveis))

    estado.linhas_entradas[linha.id] = cte.ESTRUTURA_LINHA(
        destino, linha.horario, linha.fileiras, linha.inteira, dict())

    minutos_atual = minutos_dia(data_atual)

    # 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)
                   ).replace(hour=linha.horario.hour, minute=linha.horario.minute)
        onibus = gerar_id_onibus(linha.id, partida)
        app.linhas.insert(parent=linha.id, index='end', values=(
            '-', fm.form_data(partida), 2*linha.fileiras, '-'), iid=onibus)
        monitoradas.onibus_visiveis.add(onibus)
        # todos os assentos estão livres
        estado.linhas_entradas[linha.id].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))
Exemple #10
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()
Exemple #11
0
def mudar(app, dados_anterior, dados_alterada, existia):
    app.abas.select(app.aba_linhas)
    linha_anterior = gerar_id_linha(*dados_anterior[:2])
    linha_alterada = gerar_id_linha(*dados_alterada[:2])
    if linha_anterior == linha_alterada:
        app.linhas.item(linha_anterior,
                        values=campos_linha_formatados(dados_alterada))
        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 1
    indice = app.linhas.index(linha_anterior)
    expanded = app.linhas.item(linha_anterior, 'open')
    t = minutos_dia(dados_anterior.horario)
    estado.horarios_linhas[t].remove(linha_anterior)
    estado.linhas_visiveis.remove(linha_anterior)
    onibus_filhos = dados_anterior.onibus.keys()
    monitoradas.onibus_visiveis -= onibus_filhos
    estado.onibus_invisiveis -= onibus_filhos
    del estado.linhas_entradas[linha_anterior]
    app.linhas.delete(linha_anterior)
    estado.linhas_possiveis.add((dados_anterior.destino.title(), t))

    if existia:
        app.linhas.reattach(linha_alterada, '', indice)
        app.linhas.item(linha_alterada, open=expanded)
        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)
    else:
        t = minutos_dia(dados_alterada.horario)
        assentos = dados_alterada.fileiras * 2
        estado.horarios_linhas[t] = estado.horarios_linhas.get(t, set()).union(
            {linha_alterada})
        app.linhas.insert(parent='',
                          index=indice,
                          values=campos_linha_formatados(dados_alterada),
                          iid=linha_alterada,
                          open=expanded)
        estado.linhas_visiveis.add(linha_alterada)
        estado.linhas_possiveis.remove((dados_alterada.destino.title(), t))

        estado.linhas_entradas[linha_alterada] = cte.ESTRUTURA_LINHA(
            *dados_alterada[:-1], 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=dados_alterada.horario.hour,
                minute=dados_alterada.horario.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), assentos,
                                          '-'),
                                  iid=onibus)
                monitoradas.onibus_visiveis.add(onibus)
                estado.linhas_entradas[linha_alterada].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.linhas.selection_set(linha_alterada)

    return 1
Exemple #12
0
def recadastrar_linhas(app, dados):
    actions = 0
    reservas_changed = False

    app.linhas.selection_set(*[])
    app.reservas.selection_set(*[])

    for dados_linha, reservas in dados:
        linha = gerar_id_linha(*dados_linha[:2])

        estado.linhas_entradas[linha] = cte.ESTRUTURA_LINHA(
            *dados_linha[:-1], dict())

        for reserva in reservas:
            estado.reservas.add(reserva)
            app.reservas.insert(parent='',
                                index=0,
                                values=campos_reserva_formatados(reserva),
                                iid=reserva)
            reservas_changed = True

        app.contador_reservas['text'] = fm.form_cont_reservas(
            len(estado.reservas))

        t = minutos_dia(dados_linha.horario)
        estado.linhas_possiveis.remove((dados_linha.destino.title(), t))

        estado.horarios_linhas[t] = estado.horarios_linhas.get(t, set()).union(
            {linha})
        estado.linhas_visiveis.add(linha)
        app.contador_linhas['text'] = fm.form_cont_linhas(
            len(estado.linhas_visiveis))

        app.linhas.insert(parent='',
                          index=0,
                          values=campos_linha_formatados(dados_linha),
                          iid=linha)

        data_atual = monitoradas.data_atual.replace(second=0, microsecond=0)
        minutos_atual = data_atual.hour * 60 + data_atual.minute

        if t == minutos_atual:
            periodo = range(cte.MAXIMO_NUMERO_DE_DIAS_ATE_RESERVA + 1)
        elif t < minutos_atual:
            periodo = range(1, cte.MAXIMO_NUMERO_DE_DIAS_ATE_RESERVA + 1)
        else:
            periodo = range(cte.MAXIMO_NUMERO_DE_DIAS_ATE_RESERVA)

        for d in periodo:
            partida = (data_atual + dt.timedelta(d)).replace(
                hour=dados_linha.horario.hour,
                minute=dados_linha.horario.minute)
            onibus = gerar_id_onibus(linha, partida)
            assentos = dados_linha.onibus.get(onibus, dict())
            app.linhas.insert(
                parent=linha,
                index='end',
                values=('-', fm.form_data(partida),
                        2 * int(dados_linha.fileiras) - len(assentos), '-'),
                iid=onibus)
            monitoradas.onibus_visiveis.add(onibus)
            app.contador_onibus['text'] = fm.form_cont_onibus(
                len(monitoradas.onibus_visiveis))
            estado.linhas_entradas[linha].onibus[onibus] = assentos

        app.linhas.selection_add(linha)
        app.reservas.selection_add(*reservas)

        actions += 1

    if not reservas_changed:
        app.abas.select(app.aba_linhas)

    return actions
Exemple #13
0
    def __init__(self, root):
        '''
            Inicializa a interface gráfica e armazena as instâncias dos componentes
            nesse objeto (self).

            O argumento root é uma instância de Tk, a janela principal da aplicação.

            O manager grid é utilizado para o posicionamento dos componentes, sendo especificado
            posições de linhas e colunas para os filhos de um componente.


            ::: self.component.grid(row=1, column=2, sticky='n')
            significa que component será posicionado na LINHA 1 e COLUNA 2 em relação ao seu master
            e alinhado ao NORTE ('n'), ou seja, o componente "gruda" no topo.
            sticky='ns' significa que o componente "gruda" no NORTE e no SUL, se esticando verticalmente.
            Outros sticky possuem significado com lógica similar.

            ::: self.component.columnconfigure(0, weight=1)
            ::: self.component.columnconfigure(1, weight=1)
            ::: self.component.columnconfigure(2, weight=1)
            significa que os filhos de component nas colunas 0, 1 e 2 possuem o mesmo PESO, ou seja,
            ocupam a mesma quantidade de espaço

            ::: self.component.bind('<Evento>', funcao)
            significa que o event handler "funcao" será associado (bind) ao evento <Evento>.
            assim, sempre que <Evento> for recebido por component, funcao irá executar
        '''
        root.minsize(*cte.TAMANHO_DA_JANELA_PRINCIPAL
                     )  # tamanho mínimo da janela principal
        # título, aparece na porção superior do programa
        root.title(cte.TITULO)
        # permitimos o acesso por self.root (ou app.root, fora dessa função)
        self.root = root
        # ícone
        self.estilo = ttk.Style()
        self.estilo.configure('inteira.TLabel',
                              background='#e30000',
                              foreground='#fff')
        self.estilo.configure('meia.TLabel',
                              background='#eb7100',
                              foreground='#fff')
        self.estilo.configure('gratuita.TLabel',
                              background='#095f9c',
                              foreground='#fff')
        self.estilo.configure('available.TLabel',
                              background='#07de00',
                              foreground='#fff')
        self.estilo.configure('selected.TLabel',
                              background='#fff',
                              foreground='#005')

        self.frame = ttk.Frame()
        self.frame.pack(fill='both', expand=True)

        # crio um objeto Notebook em root (janela principal), que permite a divisão de uma janela em abas
        self.abas = ttk.Notebook(self.frame)

        # a primeira aba, onde o usuário poderá manipular as entradas de linhas de ônibus
        self.aba_linhas = ttk.Frame(self.abas, padding=12, name='aba_linhas')
        self.aba_linhas.pack(
        )  # peço ao módulo para exibir a aba usando o método pack

        self.linhas = ttk.Treeview(self.aba_linhas,
                                   columns=cte.COLUNAS_LINHAS,
                                   selectmode='extended',
                                   name='linhas')
        self.linhas.column('#0', width=20, stretch=0)
        for i, coluna in enumerate(cte.COLUNAS_LINHAS):
            self.linhas.heading(
                i,
                text=coluna.title(),
                command=lambda col=i: util.treeview_sort_column(
                    self, self.linhas, col, False))
            self.linhas.column(i,
                               width=0,
                               minwidth=len(coluna) * 15,
                               anchor='center')
        self.linhas.bind('<Motion>',
                         lambda ev: util.last_separator(ev, self.linhas))
        self.linhas.bind('<1>',
                         lambda ev: util.last_separator(ev, self.linhas))

        self.linhas_scroller_v = ttk.Scrollbar(self.aba_linhas,
                                               orient='vertical',
                                               command=self.linhas.yview)
        self.linhas_scroller_h = ttk.Scrollbar(self.aba_linhas,
                                               orient='horizontal',
                                               command=self.linhas.xview)

        self.linhas['yscrollcommand'] = self.linhas_scroller_v.set
        self.linhas['xscrollcommand'] = self.linhas_scroller_h.set

        # gridding - aba_linhas
        self.linhas.grid(row=0, column=0, sticky='nsew')
        self.linhas_scroller_v.grid(row=0, column=1, sticky='ens')
        self.linhas_scroller_h.grid(row=1, column=0, sticky='sew')

        self.aba_reservas = ttk.Frame(self.abas,
                                      padding=12,
                                      name='aba_reservas')
        self.aba_reservas.pack()

        self.reservas = ttk.Treeview(self.aba_reservas,
                                     columns=cte.COLUNAS_RESERVAS,
                                     show='headings',
                                     selectmode='extended',
                                     name='reservas')
        for i, coluna in enumerate(cte.COLUNAS_RESERVAS):
            self.reservas.heading(
                i,
                text=coluna.title(),
                command=lambda col=i: util.treeview_sort_column(
                    self, self.reservas, col, False))
            self.reservas.column(i,
                                 width=0,
                                 minwidth=len(coluna) * 15,
                                 anchor='center')
        self.reservas.bind('<Motion>',
                           lambda ev: util.last_separator(ev, self.reservas))
        self.reservas.bind('<1>',
                           lambda ev: util.last_separator(ev, self.reservas))

        self.reservas_scroller_v = ttk.Scrollbar(self.aba_reservas,
                                                 orient='vertical',
                                                 command=self.reservas.yview)
        self.reservas_scroller_h = ttk.Scrollbar(self.aba_reservas,
                                                 orient='horizontal',
                                                 command=self.reservas.xview)

        self.reservas['yscrollcommand'] = self.reservas_scroller_v.set
        self.reservas['xscrollcommand'] = self.reservas_scroller_h.set

        # gridding - aba_reservas
        self.reservas.grid(row=0, column=0, sticky='nsew')
        self.reservas_scroller_v.grid(row=0, column=1, sticky='ens')
        self.reservas_scroller_h.grid(row=1, column=0, sticky='new')

        self.painel_botoes_reservas = ttk.Frame(self.aba_reservas)
        self.painel_botoes_reservas.grid(row=2,
                                         column=0,
                                         columnspan=1,
                                         sticky='nesw',
                                         pady=(12, 6))

        self.botao_devolver = ttk.Button(self.painel_botoes_reservas,
                                         command=lambda: util.devolver(self),
                                         text='Devolver')
        self.botao_devolver.grid(row=0, column=0, sticky='we')

        self.botao_importar_reservas = ttk.Button(
            self.painel_botoes_reservas,
            command=lambda: arq.importar_reservas(self),
            text='Importar')
        self.botao_importar_reservas.grid(row=0, column=1, sticky='we')

        self.botao_exportar_reservas = ttk.Button(
            self.painel_botoes_reservas,
            command=lambda: arq.exportar_reservas(self),
            text='Exportar')
        self.botao_exportar_reservas.grid(row=0, column=2, sticky='we')

        for i in range(3):
            self.painel_botoes_reservas.columnconfigure(i, weight=1)

        self.painel_entrada = ttk.Frame(self.aba_linhas)
        self.painel_entrada.columnconfigure(0, weight=1)
        self.painel_entrada.columnconfigure(1, weight=1)
        self.painel_entrada.columnconfigure(2, weight=1)
        self.painel_entrada.columnconfigure(3, weight=1)

        self.painel_destino = ttk.Frame(self.painel_entrada)
        self.painel_destino.grid(row=0, column=0, sticky='w', padx=0)

        self.painel_partida = ttk.Frame(self.painel_entrada)
        self.painel_partida.grid(row=0, column=1, sticky='we', padx=0)

        self.entrada_destino = ttk.Combobox(self.painel_destino,
                                            justify='center',
                                            textvariable=monitoradas.destino,
                                            values=estado.destinos,
                                            width=15)
        self.entrada_destino.bind('<FocusOut>', dest.atualizar_destino)
        self.entrada_destino.bind('<Return>', dest.validar_destino)
        self.entrada_destino.grid(row=0, column=0, sticky='ew', padx=0)

        self.botao_add_destino = ttk.Button(
            self.painel_destino,
            command=lambda: dest.add_destino(self),
            text='+',
            width=2)
        self.botao_add_destino.grid(row=0, column=2, sticky='w')

        self.botao_rmv_destino = ttk.Button(
            self.painel_destino,
            command=lambda: dest.rmv_destino(self),
            text='-',
            width=2)
        self.botao_rmv_destino.grid(row=0, column=1, sticky='w')

        self.spin_hora = Spinbox(self.painel_entrada,
                                 textvariable=monitoradas.tempo_formatado,
                                 justify='center',
                                 width=6)
        self.spin_hora.bind('<<Increment>>',
                            lambda e: date.increment(self, cte.MIN))
        self.spin_hora.bind('<<Decrement>>',
                            lambda e: date.decrement(self, cte.MIN))
        self.spin_hora.bind('<Return>', lambda e: date.update(self))
        self.spin_hora.grid(row=0, column=1, sticky='', padx=(0, 30))

        self.spin_vagas = Spinbox(self.painel_entrada,
                                  textvariable=monitoradas.vagas,
                                  justify='center',
                                  width=4)
        self.spin_vagas.bind('<<Increment>>', vg.incrementar_vagas)
        self.spin_vagas.bind('<<Decrement>>', vg.decrementar_vagas)
        self.spin_vagas.bind('<Return>', vg.atualizar_vagas)
        self.spin_vagas.grid(row=0, column=2, sticky='', padx=(30, 0))

        self.painel_inteira = ttk.Frame(self.painel_entrada)
        self.painel_inteira.columnconfigure(0, weight=1)
        self.painel_inteira.columnconfigure(1, weight=1)
        self.painel_inteira.grid(row=0, column=3, sticky='e', padx=0)

        self.reais = ttk.Label(self.painel_inteira,
                               text='R$',
                               width=4,
                               anchor='center')
        self.reais.grid(row=0, column=0, sticky='e')

        self.spin_inteira = Spinbox(self.painel_inteira,
                                    textvariable=monitoradas.inteira,
                                    justify='center',
                                    width=5)
        self.spin_inteira.bind('<<Increment>>', it.incrementar_inteira)
        self.spin_inteira.bind('<<Decrement>>', it.decrementar_inteira)
        self.spin_inteira.bind('<Return>', it.atualizar_inteira)
        self.spin_inteira.grid(row=0, column=1, sticky='ew', padx=0)

        self.painel_botoes = ttk.Frame(self.painel_entrada)
        self.painel_botoes.columnconfigure(0, weight=1)
        self.painel_botoes.columnconfigure(1, weight=1)
        self.painel_botoes.columnconfigure(2, weight=1)
        self.painel_botoes.grid(row=1, column=0, columnspan=4, sticky='ew')

        self.root.bind('<Control-z>', lambda ev: hst.undo(self, ev))
        self.root.bind('<Control-Shift-KeyPress-Z>',
                       lambda ev: hst.redo(self, ev))
        self.root.bind('<Control-a>', lambda ev: util.select_all(self, ev))
        self.root.bind('<Delete>', lambda ev: util.del_selecao(self))
        self.root.bind('<Control-w>', lambda *_: quit())
        self.root.protocol("WM_DELETE_WINDOW", lambda: estado.persistir(self))

        self.botao_remover = ttk.Button(self.painel_botoes, text='Remover')
        self.botao_remover.bind('<ButtonPress>',
                                lambda ev: util.remover_linhas(self, ev))
        self.botao_remover.bind('<ButtonRelease>', util.released)
        self.botao_remover.grid(row=0, column=0, sticky='we')

        self.botao_editar = ttk.Button(self.painel_botoes,
                                       text='Editar',
                                       command=lambda: util.editar_linha(self))
        self.botao_editar.grid(row=0, column=1, sticky='we')

        self.botao_adicionar = ttk.Button(
            self.painel_botoes,
            text='Adicionar',
            command=lambda: util.adicionar_linha(self))
        self.botao_adicionar.grid(row=0, column=2, sticky='we')

        self.botao_reservar = ttk.Button(
            self.painel_botoes,
            text='Reservar',
            command=lambda: util.reservar_viagem(self))
        self.botao_reservar.grid(row=1, column=3, sticky='we', padx=(10, 0))
        self.painel_botoes.columnconfigure(3, weight=1)

        self.botao_gerar = ttk.Button(self.painel_botoes,
                                      text='Gerar',
                                      command=lambda: gerar.gerar_linhas(self))
        self.botao_gerar.grid(row=0, column=3, sticky='we', padx=(10, 0))

        self.botao_relatorio = ttk.Button(
            self.painel_botoes,
            text='Relatório',
            command=lambda: rel.exibir_relatorio(self))
        self.botao_relatorio.grid(row=1, column=0, sticky='we')

        self.botao_importar_linhas = ttk.Button(
            self.painel_botoes,
            text='Importar',
            command=lambda: arq.importar_linhas(self))
        self.botao_importar_linhas.grid(row=1, column=1, sticky='we')

        self.botao_exportar_linhas = ttk.Button(
            self.painel_botoes,
            text='Exportar',
            command=lambda: arq.exportar_linhas(self))
        self.botao_exportar_linhas.grid(row=1, column=2, sticky='we')

        self.painel_contadores = ttk.Frame(self.frame)

        self.contador_linhas = ttk.Label(self.painel_contadores,
                                         text=fm.form_cont_linhas(
                                             len(estado.linhas_visiveis)),
                                         anchor='sw')
        self.contador_linhas.grid(row=0, column=0, sticky='sw')

        self.contador_onibus = ttk.Label(self.painel_contadores,
                                         text=fm.form_cont_onibus(
                                             len(monitoradas.onibus_visiveis)),
                                         anchor='sw')
        self.contador_onibus.grid(row=0, column=1, sticky='s')

        self.contador_reservas = ttk.Label(self.painel_contadores,
                                           text=fm.form_cont_reservas(
                                               len(estado.reservas)),
                                           anchor='sw')
        self.contador_reservas.grid(row=0, column=2, sticky='s')

        self.label_action = ttk.Label(self.painel_contadores,
                                      textvariable=monitoradas.cur_action,
                                      anchor='w',
                                      width=10)
        self.label_action.grid(row=0, column=3, sticky='se')

        for j in range(4):
            self.painel_contadores.columnconfigure(j, weight=1)

        self.painel_entrada.rowconfigure(0, weight=1)
        self.painel_entrada.rowconfigure(1, weight=1)
        self.painel_entrada.rowconfigure(2, weight=1)
        self.painel_entrada.grid(row=2, column=0, sticky='nsew')

        self.aba_linhas.columnconfigure(0, weight=2000)
        self.aba_linhas.rowconfigure(0, weight=100)
        self.aba_linhas.columnconfigure(1, weight=1)
        self.aba_linhas.rowconfigure(1, weight=1)
        self.aba_linhas.rowconfigure(2, minsize=70, weight=0)

        self.aba_reservas.columnconfigure(0, weight=2000)
        self.aba_reservas.columnconfigure(1, weight=1)
        self.aba_reservas.rowconfigure(0, weight=1)

        self.abas.add(self.aba_linhas, text='Linhas')
        self.abas.add(self.aba_reservas, text='Reservas')
        self.abas.grid(row=0, column=0, sticky='nesw')

        self.painel_contadores.grid(row=1,
                                    column=0,
                                    sticky='we',
                                    pady=5,
                                    padx=15)

        self.frame.rowconfigure(0, weight=1)
        self.frame.columnconfigure(0, weight=1)
        if estado.data is not None:
            util.povoar_treeviews(self)