O PlayerWords é uma atividade de adivinhação de palavras para o Moodle. O estudante adivinha uma palavra oculta letra por letra dentro de um número configurável de tentativas, recebendo feedback visual em cores e símbolos a cada chute.
Use a barra lateral para pular direto a qualquer seção desta página.
Código-fonte: github.com/jeanlucio/moodle-mod_playerwords
✨ Funcionalidades
- 🟩 Jogo de adivinhação de palavras: Feedback por letra com código de cores + símbolos (posição correta, posição errada, ausente); o campo de palpite treme quando uma tecla — física ou do teclado virtual na tela — é rejeitada por ultrapassar o comprimento da palavra-alvo, em vez de falhar silenciosamente.
- 📖 Integração com Glossário: Importa conceitos de um ou todos os glossários do curso como pool de palavras, usando as definições como dicas.
- 🚧 Stopwords configuráveis: Uma lista de palavras separadas por vírgula, por atividade (ex.: “de, da, e”), para ignorar ao dividir um conceito de glossário com várias palavras em candidatas — assim um conceito como “Reino dos Países Baixos” ainda gera o termo relevante em vez de sortear “dos” como palavra isolada.
- 🤖 Geração de palavras por IA (Opcional): Gera candidatas a palavra e dica para um tópico livre via
local_aihub(chave própria) ou fallback para ocore_aido Moodle. A resposta é tratada como entrada não confiável — só termos de um único token, puramente alfabéticos e dentro do comprimento configurado são salvos, e entram no pool pendentes de aprovação do professor. - ✍️ Pool de palavras manual: O professor pode adicionar, editar, aprovar e excluir palavras diretamente na página de gerenciamento.
- 🔀 Modos de palavra: Palavra aleatória por rodada (padrão) ou sequência compartilhada — todos os estudantes recebem as mesmas palavras na mesma ordem.
- 🎲 Rotação de palavras: No modo aleatório, a mesma palavra nunca se repete na rodada seguinte para um estudante, a menos que seja a única palavra restante no pool.
- 🚫 Prevenção de duplicatas: O mesmo texto de palavra só pode existir uma vez no pool da atividade, não importa qual fonte a adicionou — uma palavra manual bloqueia uma importação do glossário que colida com ela (e vice-versa), então o sorteio nunca fica enviesado por uma palavra duplicada sem querer.
- 🔤 Validação de palavra manual: Uma palavra adicionada ou editada manualmente precisa conter só letras; o formulário rejeita números, espaços e caracteres especiais na hora, em vez de aceitar silenciosamente uma palavra que o jogo nunca conseguiria sortear de verdade.
- 🧩 Aviso de conceito fragmentado: Um conceito de glossário com várias palavras (ex.: “Segunda Guerra Mundial”) dividido em várias entradas de palavra única é sinalizado na tabela de gerenciamento de palavras, já que cada palavra irmã ainda carrega a definição inteira do conceito original como dica.
- 🔍 Contagem ao vivo de palavras elegíveis: O formulário de configurações mostra, ao vivo via AJAX, quantas palavras caem dentro do intervalo de comprimento configurado — contra o banco real ao editar uma atividade já existente, ou uma prévia do conteúdo do glossário selecionado ao criar uma atividade nova — então o professor nunca publica um intervalo que esvazia o banco silenciosamente.
- ⚠️ Aviso de palavras inativas: A tela do jogo avisa quem gerencia a atividade, pelo nome, quais palavras aprovadas estão atualmente fora de jogo — fora do intervalo de comprimento configurado, ou com caractere que o jogo não consegue usar — junto com uma contagem permanente de palavras ativas. Um estudante nunca vê isso.
- 🎯 Rastreio de vezes sorteada: A tabela de gerenciamento de palavras mostra quantas vezes cada palavra já foi sorteada numa rodada, contado ao vivo a partir do histórico de tentativas — sem nenhum passo de recálculo.
- 💡 Dica oculta: A dica é escondida por padrão; o estudante precisa clicar em “Revelar dica” (com custo opcional em itens via PlayerHUD).
- 🏳️ Desistir: O estudante pode abandonar a rodada a qualquer momento — a palavra correta é revelada imediatamente.
- ⏱️ Tempo de recarga configurável: Intervalo mínimo entre rodadas (minutos, horas ou dias), sempre recalculado a partir da configuração atual da atividade — uma mudança do professor vale imediatamente, mesmo para quem já está em cooldown.
- 🔢 Limite de rodadas: O professor pode limitar o total de rodadas por estudante (1–10 ou ilimitado). O estudante vê um contador de rodadas jogadas (ex.: “3 / 10” ou “3 / ∞”) no lobby e após cada rodada.
- 🛡️ Integridade do limite de rodadas: Uma rodada abandonada no meio (aba fechada, sessão perdida) continua contando para o limite — reservada assim que começa, não só quando termina, então nunca dá um reroll de graça.
- 🔡 Correspondência sem acentos: Acentuação é sempre ignorada ao comparar chute e palavra-alvo.
- ⌨️ Seleção de acento no teclado virtual: Segurar uma tecla de vogal (A, E, I, O, U) no teclado virtual abre um popup com as variantes acentuadas, igual ao padrão de teclado de celular — arrastar o dedo escolhe a variante, soltar confirma. Puramente estético: a correspondência do chute continua sempre insensível a acentos.
- ✅ Revelação com ortografia real: Ao vencer, perder ou desistir da rodada, a palavra é exibida com sua acentuação verdadeira do banco de palavras, mesmo que o chute vencedor tenha sido digitado sem acento.
- 📊 Métodos de nota: Maior nota, média, primeira tentativa, última tentativa ou média sobre todas as rodadas exigidas.
- ⚖️ Modo de pontuação configurável: Escolha Binária (tudo ou nada) ou Linear (proporcional às tentativas poupadas) de forma independente para a nota e para o ranking — veja Nota e Ranking. Trava assim que a atividade registra uma nota real, garantindo que toda rodada seja pontuada sob as mesmas regras.
- 🧮 Transparência de avaliação: O estudante vê o método de avaliação ativo antes de jogar e sua nota atual computada após cada rodada, do mesmo jeito que o Quiz do Moodle comunica seu método de avaliação.
- 📋 Integração com o livro de notas: Notas gravadas automaticamente ao final de cada rodada.
- ✅ Regra de conclusão personalizada: Número mínimo de tentativas realizadas, avaliada e aplicada imediatamente após cada rodada.
- 🔄 Suporte a “Redefinir curso”: Limpa as tentativas dos estudantes e reseta as notas da atividade, restrito ao curso alvo.
- 🏆 Ranking Top 5: Classificação por atividade, limitada de propósito aos 5 primeiros — nunca um ranking público da turma inteira — com uma linha extra (“outsider”) pra um estudante mais abaixo ver sua posição real. Respeita
SEPARATEGROUPS. - 📋 Registro de tentativas: O estudante pode conferir cada rodada já concluída — palavra, tentativas usadas, tempo, nota e data — além da sua nota atual computada, a qualquer momento pelo toolbar. Quem pode gerenciar a atividade vê o registro de todos os estudantes em vez do próprio, numa tabela paginada, ordenável e filtrável por estudante.
- ❓ Ajuda no jogo: Uma página de ajuda dedicada explica as cores do feedback das letras, tentativas, dicas, temporizador e o método de avaliação da atividade.
- 👋 Acolhimento na primeira visita: O modal “Como jogar” abre sozinho na primeiríssima vez que um usuário visita qualquer atividade PlayerWords no site — uma única vez, para sempre, valendo para o site inteiro em vez de por curso ou por atividade — e nunca mais se repete depois disso; o ícone de ajuda no toolbar sempre reabre sob demanda.
- ♿ Acessibilidade: Contraste WCAG AA em todos os estados da grade; indicadores não visuais (✓ correto, ~ presente);
aria-labelem cada célula; região viva anuncia mudanças de estado para leitor de tela. - ⚡ Powered por AJAX: Toda transição de rodada (chute, dica, desistência, timeout, iniciar, nova rodada) acontece sem recarregar a página.
- 🎮 Integração com PlayerHUD (Opcional): Exige itens do inventário para iniciar uma rodada ou revelar a dica, com consumo atômico em ordem FIFO. O saldo atual do estudante em relação à quantidade exigida é sempre mostrado antes da ação, e o botão fica desabilitado — não só rejeitado depois do clique — quando falta item; um custo que aponta pra um item excluído ou de outro curso é dispensado em vez de travar o estudante. Também pode conceder um item a cada rodada vencida; seguindo a mesma regra antifarm do próprio PlayerHUD, nenhum XP é concedido por esse item enquanto a atividade permitir rodadas ilimitadas — o item continua sendo entregue, só sem XP — e o XP potencial dessa concessão é refletido no “Total XP no jogo” do próprio PlayerHUD.
- 🛡️ Integração segura entre cursos: Toda referência a item do PlayerHUD é validada contra a instância do bloco do próprio curso, nunca um item obsoleto ou de outro curso — mesmo depois de backup/restauração ou duplicação de curso. As configurações preservam um item desabilitado ou excluído como uma opção claramente rotulada, em vez de zerar o campo silenciosamente.
- 🔔 Aviso de dependência do PlayerHUD: Quando o PlayerHUD está instalado no site mas ainda não foi adicionado ao curso atual, o formulário de configurações explica que a integração vai aparecer assim que o bloco for adicionado. Quando o plugin block_playerhud não está instalado em lugar nenhum do site, o administrador vê um aviso equivalente na própria página de configurações do plugin — mesmo espírito da divulgação que
filter_playerhudeavailability_playerhudjá fazem, sem tornar o PlayerHUD uma exigência obrigatória de instalação. - 📦 Backup & Restauração: Suporte completo ao backup Moodle 2, incluindo a ação “Duplicar atividade”, pool de palavras, tentativas, remapeamento de ids de usuário/glossário, e remapeamento seguro de itens do PlayerHUD (descartado, em vez de mantido apontando pro item de outro curso, quando não faz parte da mesma restauração).
- 🔐 Privacy API: Compatível com LGPD/GDPR — exportação e exclusão completas de dados pessoais armazenados.
🎓 Finalidade Educacional
O PlayerWords foi projetado para:
- Reforçar o aprendizado de conceitos trabalhados no curso ou disciplina
- Fomentar o aprendizado lúdico e baseado em jogos
- Simplificar e tornar mais intuitivos os processos de aprendizagem e avaliação
- Colaborar para o atingimento de objetivos educacionais em cursos e disciplinas
- Fomentar metodologias ativas como a utilização de games na educação e a gamificação
- Apoiar a prática de recuperação — o estudante precisa lembrar o conceito antes de ver qualquer resposta, uma das técnicas com maior evidência de eficácia para retenção de longo prazo
- Estimular a prática espaçada — o tempo de recarga configurável entre rodadas faz o estudante retornar ao conteúdo em sessões distintas, alinhando-se aos princípios da repetição espaçada
Indicado para:
- Qualquer curso que trabalhe com conceitos expressos em palavras ou termos
- Cursos gamificados com o ecossistema PlayerGames
- Avaliação formativa e reforço de autoestudo
- Estratégias de reforço de engajamento
🕹️ Ecossistema PlayerGames
O PlayerWords faz parte do ecossistema de gamificação PlayerGames para Moodle. Sua principal integração direta é com o bloco PlayerHUD:
-
Bloco PlayerHUD (Opcional): Configure custos em itens para iniciar uma rodada ou revelar a dica, e uma concessão de item por rodada vencida. 👉 https://github.com/jeanlucio/moodle-block_playerhud
-
PlayerGroup (Compatível): Grupos padrão do Moodle — criados manualmente ou pela atividade PlayerGroup — são respeitados pelo filtro
SEPARATEGROUPSdo ranking. 👉 https://github.com/jeanlucio/moodle-mod_playergroup
Veja o perfil do autor no Moodle Plugins Directory para a família PlayerGames completa.
📦 Requisitos
| Componente | Versão |
|---|---|
| Moodle | 4.5+ |
| PHP | 8.1+ |
🛠️ Instalação e Configuração
- Baixe o arquivo
.zipou clone este repositório. - Extraia na pasta
mod/do seu Moodle. - Renomeie para
playerwords(se necessário). Caminho final:seu-moodle/mod/playerwords/ - Acesse Administração do site > Notificações para concluir a instalação.
- Adicione uma atividade PlayerWords a qualquer curso.
Este plugin não tem configurações separadas em nível de site após a instalação — toda configuração é feita pelo professor ao adicionar a atividade a um curso, conforme explicado em Como Usar logo abaixo.
📖 Como Usar
- Adicione uma atividade PlayerWords ao seu curso.
- Configure:
- Faixa de comprimento de palavras e máximo de tentativas
- Tempo de recarga entre rodadas e limite de rodadas
- Modo de palavras (aleatório ou sequência compartilhada)
- Método de nota e configurações do livro de notas
- Fontes de palavras (manual, Glossário, IA), fonte de glossário e uma lista de stopwords para ignorar ao dividir conceitos com várias palavras (todos opcionais)
- Custos em itens do PlayerHUD e concessão por vitória (opcional, quando o bloco PlayerHUD está presente)
- Acesse Gerenciar palavras para adicionar, gerar com IA, aprovar, editar ou excluir palavras.
- Os estudantes jogam diretamente na página da atividade — chutando, revelando dicas e desistindo de rodadas, sem recarregar a página. O toolbar da própria página dá acesso às regras (ajuda), ao registro de tentativas e ao ranking.
- Notas e ranking são atualizados automaticamente após cada rodada.
🧮 Nota e Ranking
O PlayerWords calcula uma nota e um total de ranking a partir das mesmas rodadas terminadas, mas os dois são configurados de forma totalmente independente — o professor pode manter a nota simples e ainda assim recompensar jogadas eficientes no ranking, ou o contrário.
Os dois são totalmente opcionais, e cada um liga/desliga por conta própria:
- Nota: deixe o campo padrão
Notacomo Nenhuma pra rodar a atividade sem avaliação nenhuma — nenhuma nota é calculada ou gravada no livro de notas, e as configuraçõesMétodo de avaliação/Pontuação da notasomem do formulário. - Ranking: deixe
Mostrar rankingcomo Não pra esconder o ranking em todo lugar — no jogo, na página dedicada de ranking, e na coluna extra do registro de tentativas — e a configuraçãoPontuação do rankingsome do formulário também.
Desligar um nunca afeta o outro: uma atividade pode ter nota sem ranking, ranking sem nota, os dois, ou nenhum dos dois.
A pontuação por rodada decide quanto vale uma única rodada, escolhida separadamente para a
nota e para o ranking (configurações Pontuação da nota / Pontuação do ranking, ambas com
padrão Binária):
| Modo | Uma rodada vencida vale… | Uma rodada perdida, desistida ou com tempo esgotado |
|---|---|---|
| Binária (padrão) | A nota cheia da atividade | Zero |
| Linear | Nota cheia nas duas primeiras tentativas, depois uma fração proporcional às tentativas poupadas: nota × (max_attempts − tentativas_usadas + 1) / (max_attempts − 1) |
Zero |
O modo linear dá nota cheia nas duas primeiras tentativas — um segundo palpite certeiro não é tratado como menos merecedor que um acerto de primeira, já que este é um jogo educativo não punitivo, não uma disputa de sorte — e só a partir daí distribui as tentativas restantes proporcionalmente, nunca zerando totalmente uma vitória: até vencer na última tentativa permitida ainda rende uma fração positiva. Exemplo com nota máxima 100 e 6 tentativas:
| Tentativas usadas | Pontos (linear) |
|---|---|
| 1 | 100,00 |
| 2 | 100,00 |
| 3 | 80,00 |
| 4 | 60,00 |
| 5 | 40,00 |
| 6 | 20,00 |
| Não completou | 0,00 |
Com Máximo de tentativas igual a 2 ou menos, o modo Linear fica numericamente idêntico ao
Binário — toda tentativa permitida já cai dentro do platô de nota cheia.
Combinar várias rodadas numa nota final é uma configuração separada, Método de avaliação
(maior nota, média, primeira tentativa, última tentativa ou média sobre todas as rodadas
exigidas). Funciona igual independente de a pontuação por rodada acima ser Binária ou Linear: só
agrega o valor que cada rodada já registrou.
O ranking é a soma dos pontos de ranking de todas as rodadas terminadas de um estudante
(SUM), ordenado do maior para o menor; empates são desfeitos por menos tentativas usadas em
média, depois menos tempo gasto em média. Só aparece quando o professor liga “Mostrar ranking”, e
nunca revela uma rodada ainda em andamento.
Só os 5 primeiros aparecem — de propósito, não é bug: tanto o mini-ranking dentro do jogo quanto a página dedicada limitam a lista a 5 linhas, pra evitar expor o ranking da turma inteira publicamente. Um estudante mais abaixo continua vendo exatamente onde está: uma linha extra, separada por “…”, mostra sua posição e pontuação reais, sem revelar a colocação de mais ninguém abaixo do 5º lugar. Quem pode gerenciar a atividade (professor editor, gerente) nunca aparece no ranking, mesmo que jogue a atividade — a mesma regra que exclui suas próprias tentativas do registro de tentativas abaixo.
“Mostrar ranking” só controla a exibição, não a coleta de dados: os pontos de ranking são calculados e gravados em toda rodada terminada, esteja a configuração ligada ou desligada naquele momento. Ligá-la depois que os estudantes já jogaram revela o total acumulado desde o início da atividade, não só os pontos ganhos a partir da mudança — nada se perde, e não é preciso “recuperar” nada ao desligar e ligar de novo.
Trava ao registrar a nota: assim que a atividade registra uma nota real para qualquer
estudante, Máximo de tentativas, Pontuação da nota e Pontuação do ranking travam — do mesmo
jeito que o Moodle já trava o campo “Nota máxima” de uma atividade avaliada assim que existem
notas reais. Isso garante que toda rodada já registrada para aquela atividade foi pontuada sob
exatamente as mesmas regras, então a nota e o total do ranking permanecem consistentes durante
toda a vida da atividade.
Registro de tentativas: cada estudante pode conferir suas próprias rodadas passadas — palavra, tentativas usadas, tempo, nota da rodada e (quando o ranking está ligado) pontos no ranking — pela página de registro de tentativas do toolbar. Quem pode gerenciar a atividade vê essa mesma página virar um relatório de todos os estudantes: uma tabela só, 30 linhas por página, ordenável clicando em qualquer cabeçalho de coluna, e filtrável para um único estudante. Assim como no ranking, nunca inclui as próprias tentativas de quem gerencia, mesmo que essa pessoa tenha jogado a atividade.
🧪 Testes Automatizados
O PlayerWords inclui uma suíte PHPUnit cobrindo lógica de negócio, consultas ao repositório, web services e conformidade com a Privacy API. Todo push de CI executa a matriz completa (Moodle 4.5 → 5.x, PostgreSQL e MariaDB).
PHPUnit — Testes Centrais
| Arquivo de teste | Casos |
|---|---|
backup_restore_test.php |
5 |
cross_instance_security_test.php |
4 |
lib_grant_potential_test.php |
6 |
lib_reset_userdata_test.php |
4 |
completion/custom_completion_test.php |
7 |
privacy/provider_test.php |
14 |
| Subtotal | 40 |
Testes de Lógica de Negócio (tests/local/)
| Arquivo de teste | Casos |
|---|---|
ai_word_generator_test.php |
12 |
attempts_history_service_test.php |
14 |
gameplay_service_test.php |
19 |
hud_service_test.php |
22 |
intro_service_test.php |
5 |
ranking_service_test.php |
6 |
round_presenter_test.php |
35 |
round_service_test.php |
30 |
view_page_service_test.php |
16 |
word_normalizer_test.php |
16 |
words_repository_test.php |
56 |
| Subtotal | 231 |
Testes de Web Services (tests/external/)
| Arquivo de teste | Casos |
|---|---|
count_eligible_words_test.php |
5 |
count_glossary_candidates_test.php |
4 |
end_round_test.php |
4 |
new_round_test.php |
3 |
reveal_hint_test.php |
6 |
start_round_test.php |
5 |
submit_guess_test.php |
7 |
| Subtotal | 34 |
| Total Geral | 305 |
vendor/bin/phpunit --testsuite mod_playerwords
Cobertura de linhas geral (moodle-coverage, PHPUnit + Xdebug): 63%.
Ver o detalhamento completo de cada teste e a tabela de cobertura →
🔐 Segurança e Conformidade
- Controle de acesso por capabilities (
mod/playerwords:view,mod/playerwords:addinstance) - Proteção com
require_sesskey()em todas as ações POST; chamadas AJAX são validadas pelo dispatchercore/ajaxdo Moodle - Validação no servidor dos limites de rodadas e tempo de recarga, sempre recalculados a partir da configuração atual
- Timeout de rodada é revalidado contra o prazo real do servidor (com pequena tolerância de latência de rede), em vez de confiar apenas no cronômetro do cliente
- Validação de charset do chute — apenas letras Unicode aceitas
- Palavras geradas por IA são tratadas como entrada não confiável: só termos de um único token, alfabéticos e dentro do comprimento configurado são salvos, entrando pendentes de aprovação do professor
- O estado de sessão da rodada é isolado por instância de atividade e por usuário — um id de palavra ou chave de sessão de uma atividade nunca é aceito por outra
- Compatível com a API externa do Moodle
- Privacy API completamente implementada (LGPD/GDPR)
🔒 Divulgação de Serviço de Terceiros
A geração de palavras por IA é opcional e vem desativada por padrão. Quando um professor a
usa, o tema da atividade (nunca dados de estudante ou registros de tentativa) é enviado através
do local_aihub — usando a chave própria (BYOK) do usuário ou do site, se o plugin estiver
instalado — ou, como alternativa, através do subsistema de IA nativo do Moodle (core_ai), que
roteia para o provedor configurado pelo administrador do site. O PlayerWords nunca contata um
provedor de IA diretamente; a requisição e sua divulgação/consentimento são de responsabilidade
exclusiva do local_aihub ou do core_ai. Se nenhum dos dois estiver instalado ou configurado,
a fonte de palavras por IA fica indisponível e todas as outras funcionalidades continuam
funcionando normalmente.
- Custo: Nenhum é exigido pelo próprio PlayerWords. Se usada, qualquer custo é o que o
provedor cobrar através de uma chave BYOK no
local_aihub, ou nenhum custo via um provedorcore_aigratuito/institucional que o administrador do site já tenha configurado. - Chaves de API / credenciais: Não são configuradas no PlayerWords. Obtenha e configure uma
chave pessoal ou do site dentro do
local_aihub(veja a documentação própria dele), ou peça ao administrador do site para configurar um provedorcore_ai. - Credenciais de demonstração: Não aplicável — nenhuma credencial é exigida para instalar ou usar o PlayerWords; a geração por IA é totalmente opcional.
📄 Licença
Este projeto é licenciado sob a GNU General Public License v3 (GPLv3).
Copyright: 2026 Jean Lúcio