Relatório Acadêmico Tecnológico:
Otimização de Dados e Automação em Ambientes Dinâmicos

Delean Mafra - Profile Picture

CDADOS - Projeto de Extensão I - Delean Mafra

Descrição do Projeto

Este projeto tem como objetivo automatizar a conferência de recibos de pagamentos de eventos beneficentes da Igreja Renascer em Cristo. Com a implementação deste sistema, busca-se:

Descrição da 1° parte do Projeto: Base de Dados e Automação Core

Criei um plano de ação com os seguintes objetivos:

Com esses objetivos, o projeto visa não apenas a eficiência operacional, mas também um suporte adequado às atividades da Igreja Renascer em Cristo.

Descrição da 2ª parte do Projeto: Arquitetura de Dados Flexível

A atualização no código permite ler automaticamente o caminho da pasta a partir de um arquivo de configuração (pex.lic), trazendo uma melhoria significativa em termos de usabilidade e eficiência. O sistema não exige que o usuário insira manualmente o caminho da pasta a cada execução, minimizando o tempo necessário para configurar e executar o script. Esse aprimoramento torna o processo mais ágil, reduz a chance de erros de digitação ao informar o caminho e permite que a equipe execute a verificação de duplicados com um clique. Além disso, essa modificação facilita a integração do sistema com outros processos automatizados e garante uma experiência mais prática e acessível para a equipe da igreja.

Observação: Desafios na Integração de Tecnologias

Inicialmente, optei por utilizar a biblioteca "kivy" para criar uma interface mais agradável, combinada com a biblioteca "cryptography" para criar um registro de licença criptografado, evitando que o programa fosse compartilhado com outras pessoas além do pastor Julian e do Bispo Gabriel. Infelizmente, tive diversos problemas com as duas bibliotecas, pois o código funcionava perfeitamente no meu ambiente de teste, porém, quando era compilado para um executável, ele não conseguia ler corretamente o registro de licença criado. Outro problema foi que a compilação do programa utilizando a biblioteca "kivy" era muito longa, levando aproximadamente 30 minutos para concluir cada compilação. Foram compiladas 47 versões (1.0.0.47) desse projeto inicial, totalizando aproximadamente 23 horas de programação e compilação do programa.

3ª Parte do Projeto: Redesenho da Interface do Usuário com Tkinter

Removi do código a biblioteca “kivy” e "cryptography” e adicionei a biblioteca “Tkinter” no lugar da “kivy”.

A implementação da biblioteca “Tkinter” no projeto permitiu criar uma interface gráfica amigável e visualmente agradável, oferecendo várias vantagens:

4ª Parte do Projeto: Versionamento de Código (Database Snapshots)

A implementação de um sistema de controle de versão utilizando o arquivo “version.txt” permite acompanhar e documentar as diferentes versões do software, garantindo um histórico claro das alterações e evoluções do projeto.

5ª Parte do Projeto: Compilador de Software (Automated Build System)

Na quinta parte do projeto, foi desenvolvido um compilador em Python com o objetivo de transformar o código em um executável (.exe), utilizando as bibliotecas “pyinstaller” e “subprocess”. Esta etapa é fundamental para a distribuição do software, permitindo que ele seja executado no ambiente dos usuários sem a necessidade de um interpretador Python instalado.

Linha do Tempo para Conclusão do Projeto: Framework Evolutivo

1° parte do projeto: Identificação de Necessidade e Solução em Python (Data Processing Core)

import os
import hashlib

def calcular_hash(arquivo):
    """Calcula o hash SHA-256 de um arquivo para identificar duplicados."""
    hash_sha256 = hashlib.sha256()
    with open(arquivo, 'rb') as f:
        for chunk in iter(lambda: f.read(4096), b""):
            hash_sha256.update(chunk)
    return hash_sha256.hexdigest()

def verificar_duplicados(caminho_pasta):
    """Verifica e exclui arquivos duplicados na pasta especificada."""
    arquivos_verificados = {}
    log_exclusao = []

    for root, _, arquivos in os.walk(caminho_pasta):
        for nome_arquivo in arquivos:
            if nome_arquivo.lower().endswith(('.pdf', '.png', '.jpeg', '.jpg')):
                caminho_completo = os.path.join(root, nome_arquivo)
                hash_arquivo = calcular_hash(caminho_completo)

                if hash_arquivo in arquivos_verificados:
                    # Excluir o arquivo duplicado
                    os.remove(caminho_completo)
                    log_exclusao.append(caminho_completo)
                else:
                    # Armazenar o hash para comparação futura
                    arquivos_verificados[hash_arquivo] = caminho_completo

    # Salvar log dos arquivos excluídos
    with open('log_exclusao.txt', 'w') as log:
        for item in log_exclusao:
            log.write(f"{item}\n")
    print("Processo concluído. Log salvo em 'log_exclusao.txt'.")

# Solicita o caminho da pasta ao usuário e executa a verificação de duplicados
if __name__ == "__main__":
    caminho = input("Informe o caminho da pasta com os arquivos: ")
    verificar_duplicados(caminho)

2ª parte do projeto: Otimização de Entrada de Dados (Automated Data Pathways)

Foi adicionada uma função no código para que não seja necessário ter que sempre informar manualmente o caminho da pasta.

def obter_caminho_da_pasta():
"""Lê o caminho da pasta a partir de um arquivo de texto."""
with open('pex.lic', 'r') as arquivo: caminho_pasta = arquivo.readline().strip() return caminho_pasta

3ª parte do projeto: Interface Gráfica Avançada (Gaming-Inspired GUI)

Foi criada uma interface para que o programa não precisasse ser executado pelo terminal, melhorando a intuição e experiência do usuário

import os
import hashlib
import tkinter as tk
from tkinter import messagebox

def calcular_hash(arquivo):
    # Calcula o hash SHA-256 de um arquivo para identificar duplicados
    hash_sha256 = hashlib.sha256()
    with open(arquivo, 'rb') as f:
        for chunk in iter(lambda: f.read(4096), b""):
            hash_sha256.update(chunk)
    return hash_sha256.hexdigest()

def verificar_duplicados(caminho_pasta):
    # Verifica e exclui arquivos duplicados na pasta especificada
    arquivos_verificados = {}
    log_exclusao = []

    for root, _, arquivos in os.walk(caminho_pasta):
        for nome_arquivo in arquivos:
            if nome_arquivo.lower().endswith(('.pdf', '.png', '.jpeg', '.jpg')):
                caminho_completo = os.path.join(root, nome_arquivo)
                hash_arquivo = calcular_hash(caminho_completo)

                if hash_arquivo in arquivos_verificados:
                    os.remove(caminho_completo) # Excluir o arquivo duplicado
                    log_exclusao.append(caminho_completo)
                else:
                    arquivos_verificados[hash_arquivo] = caminho_completo

    # Salvar log dos arquivos excluídos
    with open('log_exclusao.txt', 'w') as log:
        for item in log_exclusao:
            log.write(f"{item}\n")
    return "Processo concluído. Log salvo em 'log_exclusao.txt'."

def obter_caminho_da_pasta():
    # Lê o caminho da pasta a partir de um arquivo de texto
    with open('pex.lic', 'r') as arquivo:
        caminho_pasta = arquivo.readline().strip()
    return caminho_pasta

def excluir_arquivos_duplicados():
    # Executa a função de exclusão de arquivos duplicados e exibe mensagem de conclusão
    caminho = obter_caminho_da_pasta()
    mensagem = verificar_duplicados(caminho)
    messagebox.showinfo("Resultado", f"{mensagem}\nTodos os arquivos duplicados foram excluídos.")

def main():
    root = tk.Tk()
    root.withdraw() # Oculta a janela principal inicialmente

    # Configuração da interface para executar a exclusão de arquivos duplicados
    root.deiconify() # Mostra a janela principal para o botão de execução
    root.title("Exclusão de Arquivos Duplicados")
    root.geometry("400x200")

    # Label de autoria
    label_copyright = tk.Label(root, text="©2024 Delean Mafra - Todos os direitos reservados")
    label_copyright.pack(pady=10)

    # Botão para iniciar o processo de exclusão
    btn_executar = tk.Button(
        root,
        text="Excluir Arquivos Duplicados",
        command=excluir_arquivos_duplicados
    )
    btn_executar.pack(pady=20)

    root.mainloop()

if __name__ == "__main__":
    main()

4ª Parte: Arquivo de Versão (Version Control Data Layer)

Foi criado arquivo de versão (version.txt)

# UTF-8
#
# Para mais detalhes sobre o 'ffi' veja:
# http://msdn.microsoft.com/en-us/library/ms646997.aspx

VSVersionInfo(
    ffi=FixedFileInfo(
        filevers=(2, 0, 0, 0),
        prodvers=(2, 0, 0, 0),
        mask=0x3f,
        flags=0x0,
        OS=0x4,
        fileType=0x1,
        subtype=0x0,
        date=(0, 0)
    ),
    kids=[
        StringFileInfo(
            [
                StringTable(
                    '041604B0',
                    [
                        StringStruct('CompanyName', 'Delean Mafra'),
                        StringStruct('FileDescription', 'Exclui Arquivos Duplicados'),
                        StringStruct('FileVersion', StringStruct('Exclui Arquivos Duplicados'),
                        StringStruct('Copyright ©2024 | Delean Mafra, todos os direitos reservados.'),
                        StringStruct('Exclui Arquivos Duplicados.exe'),
                        StringStruct('Exclui Arquivos Duplicados'),
                        StringStruct('2.0.0.2'),
                    ]
                )
            ]
        ),
        VarFileInfo([VarStruct('Translation', [1046, 1200])])
    ]
)

5ª parte: Ferramenta de Compilação (Cybernetic Deployment Tool)

Foi criado compilador:

import os
import subprocess

# Função para incrementar a versão
def incrementar_versao(versao):
    partes = versao.split('.')
    partes[-1] = str(int(partes[-1]) + 1)
    return '.'.join(partes)

# Caminho do arquivo de versão
version_file_path = 'D:/Python/Python_projcts/pex/version.txt'

# Ler o arquivo de versão
with open(version_file_path, 'r', encoding='utf-8') as file:
    linhas = file.readlines()

# Atualizar as linhas com a nova versão, sem tocar no filevers
for i, linha in enumerate(linhas):
    if "StringStruct('ProductVersion'," in linha:
        partes = linha.split("'")
        nova_versao = incrementar_versao(partes[3])
        partes[3] = nova_versao
        linhas[i] = "'".join(partes)

# Escrever as novas linhas de volta no arquivo de versão
with open(version_file_path, 'w', encoding=as file:
    file.writelines(linhas)

# Mudar para o drive D:
os.chdir('D:/')

# Mudar para o diretório do projeto
os.chdir('D:/Python/Python_projcts/pex')

# Caminho do ícone
icon_path = 'D:/Python/Python_projcts/pex/ico_lupa.ico'

# Caminho correto do arquivo de versão
correct_version_file_path = # Executar o comando do PyInstaller
subprocess.run(['pyinstaller', '--onefile',
                    f'--version-file={correct_version_file_path}', f'--icon={icon_path}',
                    'pex.py'])

# Pausar a execução (equivalente ao 'pause' no .bat)
input("Pressione Enter para continuar...")