Ezequias Rocha, analista de sistemas e pesquisador

%1zsh~
ezequias@lsi ~ $ whoami
Foto de Ezequias Rocha

EzequiasRocha

Analista de Sistemas e Pesquisador no Laboratório de Sistemas de Informação (LSI/UFCG). Bacharel em Ciência da Computação pela UFCG, mestrando. Campina Grande, Paraíba.

%2nvim~/README.md
%3zsh~
ezequias@lsi ~ $ cat .perfil
github
ezequiasOR, desde out/2018
repos
50 públicos
seguidores
138
commits
~1.110 autorais em 22 repositórios próprios
org
EssentIA (@EssentIA-Agents), voltada a agentes de IA
shell
Pop!_OS, Neovim em Lua, tmux
/ buscar1–7 janelasj k rolar
2:

Pesquisa

Replicação em PyTorch de Aspect-oriented unsupervised social link inference on user trajectory data (Byun, Choi e Kim, Information Sciences, vol. 626, 2023). A pergunta do paper: dá para dizer quem é amigo de quem sem nenhum rótulo, olhando só para os check-ins?

%1replication-ANESarquitetura

Os dados são trajetórias do Foursquare em Nova York. Cada check-in deixa de ser um ponto no mapa e vira uma tripla aspecto-orientada: o usuário se relaciona com um POI através de um aspecto (quando, que tipo de lugar, onde). Cada aspecto tem o próprio espaço de embedding, e as relações são projetadas como em grafos de conhecimento.

 check-in  (usuário, POI, tempo, categoria, geo)
     │
     ├── usuário    ─┐
     ├── POI         │
     ├── tempo      ─┤  embeddings separados, 128 dim cada
     ├── categoria   │  tempo em 168 slots semanais
     └── geografia  ─┘
                   │
        projeção TransH / TransR / TransD
                   │   h⊥ + r ≈ t⊥ no hiperplano da relação
                   │
     margin loss + orthogonal loss + norm loss
                   │   r ortogonal ao hiperplano; normas contidas
                   ▼
        espaço de usuários → pares de amizade inferidos

Variantes implementadas: ANES, ANES_GEO, ANES_GEO_YELP, ANES_GEO_Others e LBGC_v4.

%2tempo168 slots

Uma semana em 168 posições

O tempo não entra como timestamp. Ele é discretizado em dia × hora, 7 × 24 = 168 slots, depois de corrigir o fuso pelo offset em minutos de cada check-in. Assim "terça às 22h" e "terça às 9h" viram vetores diferentes, e o modelo aprende ritmo, não data.

Passe o mouse ou o foco por uma célula. slot = dia × 24 + hora

%3amostragemO(log n)

Amostragem negativa por busca binária

Para treinar com margin loss é preciso sortear exemplos negativos muitas vezes por época, seguindo uma distribuição não uniforme. Em vez de varrer os pesos a cada sorteio, a implementação monta a CDF uma vez e encontra o índice por busca binária.

# esboço do mecanismo, não é o código do repositório
cdf = acumulada(pesos)        # O(n), uma vez só

def amostra_negativa():
    x = random() * cdf[-1]
    return busca_binaria(cdf, x)  # O(log n) por sorteio
%4tree~2.400 linhas, 8 módulos
preprocessing.pycheck-ins para triplas, slots de tempo, recortes
ANES.pylaço de treino
model.pyembeddings, projeções e variantes776
data.pycarregamento e amostragem
loss.pymargin, orthogonal e norm loss
projection.pyTransH / TransR / TransD
graphutils.pyutilidades de grafo
utils.pyauxiliares
dados
NYC_20, 40, 60, 80 e 100, com pares verdadeiros e falsos para treino, validação e teste
treino
lr 1e-4, distância L1, 1000 iterações
análise
t-SNE para inspecionar o espaço aprendido
3:

Open source

O turbo-whisper é um ditado por voz no estilo SuperWhisper: OpenAI Whisper, 99 idiomas, PyQt6, atalho global e waveform. Funcionava, menos para quem digita em teclado brasileiro.

%1buglayout ABNT

O apóstrofo saía como til

O texto transcrito era digitado via evdev, que injeta scancodes crus pensando em US-QWERTY. A tecla que no layout americano é o ' ocupa, no ABNT2, a posição do ~. O sistema lê a posição física com o layout brasileiro, e o caractere sai trocado.

'o que o evdev pretende mandar → ~o que o layout ABNT2 desenha nessa posição

A correção foi parar de depender de scancode quando existe uma ferramenta que digita caracteres de verdade. Wayland primeiro, X11 depois, e o caminho antigo fica como rede de segurança.

  1. wtype
  2. xdotool type
  3. evdev
  4. PyAutoGUI
  5. clipboard
%2nvimtyping.py
# a cadeia de fallback, resumida
def type_text(text):
    wayland = (os.environ.get("WAYLAND_DISPLAY")
               or os.environ.get("XDG_SESSION_TYPE") == "wayland")

    if wayland and shutil.which("wtype"):
        return run(["wtype", text])

    if shutil.which("xdotool"):
        return run(["xdotool", "type", "--clearmodifiers",
                    "--delay", delay, text])

    # evdev manda scancode US-QWERTY cru: no ABNT, ' vira ~
    return (evdev_type(text)
            or pyautogui_type(text)
            or clipboard_paste(text))

Reescrito para leitura; o comportamento é o do commit.

%3git log--author=ezequiasOR
  • fix: prefer xdotool/wtype over evdev for auto-typing o bug do ABNT
  • feat: language selection, headless recording, clearer offline error +143 linhas em api.py, config.py, main.py
  • docs: self-hosted setup notes for Pop!_OS

As notas de self-hosting documentam o setup no Pop!_OS: servidor faster-whisper em Docker com CUDA (--gpus all), modelo Systran/faster-whisper-small, porta publicada só em 127.0.0.1, cache do HuggingFace montado como volume para não baixar o modelo a cada subida, e áudio por PipeWire/PortAudio.

4:

Projetos

Do mais recente para o mais antigo. O que muda entre eles é menos a linguagem e mais quanto da engenharia em volta do código entrou junto: lint, teste, container, deploy.

%1fast_zero2025

API em FastAPI com o rigor no pyproject

CRUD REST de usuários com Pydantic v2: EmailStr na validação e schemas separados por papel (UserSchema de entrada, UserPublic de saída sem senha, UserDB, UserList). Respostas com HTTPStatus e 404 tratado. Python 3.14 com Poetry, TestClient em fixture.

# pyproject.toml (trecho)
[tool.ruff.lint]
preview = true
select = ['I', 'F', 'E', 'W', 'PL', 'PT']

[tool.taskipy.tasks]
lint      = 'ruff check'
pre_test  = 'task lint'
test      = 'pytest --cov=fast_zero'
post_test = 'coverage html'

PL traz as regras do pylint, PT as do estilo pytest. Rodar os testes passa antes pelo lint e termina com relatório HTML de cobertura.

%2clone-tabnews2023–24

Next.js com Postgres de verdade, desde o primeiro endpoint

Next.js 13 falando com Postgres pelo driver pg. O banco sobe por Docker Compose a partir de infra/compose.yaml, e o primeiro endpoint, /api/v1/status, já nasce com teste de integração em Jest contra o banco rodando.

  • Prettier, .editorconfig e .nvmrc para que o ambiente seja o mesmo em qualquer máquina
  • versão da API no caminho da rota
  • deploy contínuo na Vercel
%32020API, web e mobile

Três apps, cada um em três plataformas

Em 2020 fiz os projetos das Semanas Omnistack e da NLW indo até o fim em todas as frentes: API em Node, front em React e app em React Native com Expo, cada um com o próprio problema técnico.

projetoAPIwebmobilecommits
Ecoleta Express + Knex (migrations e seeds) + SQLite, validação com Celebrate/Joi, upload com Multer, CORS React + TypeScript, mapa com Leaflet/react-leaflet, upload drag-and-drop com react-dropzone Expo, react-native-maps, expo-location, expo-mail-composer, React Navigation 124
DevRadar Express + MongoDB/Mongoose com consultas geoespaciais, Socket.io avisando devs próximos em tempo real, API do GitHub via axios React Expo com mapas, localização, WebView e socket.io-client 123
be-the-hero Express + Knex + SQLite + Celebrate, testes com Jest e Supertest, cross-env React React Native com Expo 122

Ecoleta é um marketplace de pontos de coleta de resíduos por geolocalização; DevRadar encontra devs por proximidade e tecnologia.

%4ls ~/estudos2019 em diante
  • Web-Estudos844 commits de 2019 a 2025, 479 meus. JavaScript do zero (map/filter/reduce, imperativo vs declarativo), AJAX com XHR, fetch, axios e jQuery, Express, Gulp, Webpack, Vue, React, SQL relacional com joins e agregação, MongoDB com lookup.
  • Python-Estudos105 commits meus. Banco de dados com consultas parametrizadas (inclusive "selecionar sem SQL injection"), CRUD, paginação com limit/offset.
  • ia-ufcgQuizzes de Inteligência Artificial em Jupyter, 2022–23.
  • ibdmdDatasets para BI: lojas, gerentes, vendas.
  • Java, 2020Primeiros sistemas na UFCG: coisa (Controle Institucional da Situação Acadêmica), agenda-de-contatos, controle-de-alunos.
  • audio-speed-controllerExtensão que acelera os áudios do WhatsApp Web (2020).
  • nvim, tmuxNeovim em Lua com LSP, Telescope, Treesitter, Harpoon, Fugitive, Undotree, Trouble, Zen Mode, refactoring e cloak. nvim e tmux.
  • bin2dec, casa-criativa, doeExercícios curtos, os dois últimos da MaratonaDev.
5:

Algoritmos

Montei trilhas semanais de Aprendizado de Algoritmos com listas no vJudge e gravei vídeos resolvendo as questões para os alunos. A trilha começa em ad hoc e termina em decomposição por raiz quadrada.

%1trilhaaa-iniciante → aa
  • Iniciante
  • ad hoc, two pointers, soma acumulada
  • busca binária
  • fila, heap, pilha, set, mapa
  • GCD/LCM, crivo
  • aritmética modular, exponenciação binária
  • Avançada
  • Segment Tree
  • Lazy Propagation
  • Square Root Decomposition, algoritmo de Mo

ATAL na UFCG

Em Análise e Técnicas de Algoritmos, soluções de Codeforces organizadas por paradigma: força bruta, backtracking, guloso, divisão e conquista, programação dinâmica e grafos com BFS e DFS.

%2segtreeconsulta de intervalo

A aula da segment tree, em miniatura

Clique em duas posições do vetor para escolher o intervalo. Os nós em âmbar cobrem o intervalo inteiro e são somados; os em ciano são visitados e divididos; o resto nem é tocado.

cobredividefora

6:

Log

Números contados nos 22 repositórios próprios, sem forks. Volume de código mede quanto foi escrito em cada linguagem, não quanto eu domino cada uma.

%1git shortlogcommits por ano
2019 ██▎                           21
2020 ██████████████████████▋      207
2021 █████████████████████▉       200
2022 ████████████████████████████ 256
2023 ██████████████████▊          172
2024 █████████████████████▏       193
2025 ██████▋                       61
2026 ▍                              3
     ──────────────────────────── ─────
     escala linear, 28 colunas = 256 1.113

2026 são os commits do turbo-whisper, que vivem num fork.

%2linguistvolume em KB
JavaScript ████████████████████████████ 828
CSS        █████████████▎               392
HTML       ███████████▏                 330
Jupyter    ██████████                   294
Python     ███████▌                     223
TypeScript █▉                            55
Java       █▎                            36
Lua        ▍                             11
Vue        ▍                             11
SQL        ▎                              6

JavaScript, CSS e HTML pesam pelos anos de Web-Estudos e pelos apps de 2020.

%3nvimstack.lua
local stack = {
  ia_e_dados = {
    "Python", "PyTorch", "scikit-learn", "Pandas",
    "NumPy", "Jupyter", "TransH/R/D",
    "Whisper", "faster-whisper",
  },
  backend = {
    "FastAPI", "Pydantic", "Node.js", "Express",
    "Next.js API routes", "Knex", "Mongoose", "Socket.io",
  },
  frontend_e_mobile = {
    "TypeScript", "React", "React Native", "Expo",
    "Next.js", "Leaflet", "Vue",
  },
  bancos = { "PostgreSQL", "SQLite", "MongoDB", "MySQL" },
  qualidade_e_infra = {
    "pytest", "Jest", "Supertest", "Ruff", "Prettier",
    "Poetry", "Docker", "Docker Compose", "CUDA",
    "Vercel", "Git",
  },
  ambiente = {
    "Pop!_OS", "Neovim/Lua", "tmux", "Wayland/X11",
  },
}

return stack
%4git log --graphlinha do tempo
  1. 2026

    Contribuição no turbo-whisper: o fix do ABNT.

  2. 2025

    fast_zero em FastAPI. Nova turma de algoritmos (aa).

  3. 2024

    Replicação do ANES na pesquisa. Config de tmux.

  4. 2022

    IA na UFCG até 2023. Neovim configurado em Lua.

  5. 2021

    ATAL: Codeforces por paradigma.

  6. 2020

    Java na UFCG. Semanas Omnistack (DevRadar, Be The Hero) e NLW (Ecoleta). Começo a ensinar algoritmos.

  7. 2019

    Começo Web-Estudos e Python-Estudos.

  8. 2018

    Conta no GitHub.

7:

Contato

Código no GitHub, trabalho no LinkedIn, o resto nos outros dois.