PlayerCross

Atividade de palavras cruzadas por dedução para o Moodle — documentação completa.

English | Português

View on GitHub Download .zip

Moodle License Status Latest Release PlayerGames Ecosystem Game Activity Author

Moodle Plugin CI Last Commit Open Issues

O PlayerCross é uma atividade de palavras cruzadas por dedução para o Moodle. Cada rodada sorteia uma frase-mistério e um conjunto de termos montado a partir de conceitos relacionados do curso; resolver um termo revela as letras que ele compartilha com todo outro termo pendente e com a própria frase-mistério.

👈 Use a barra lateral para pular direto a qualquer seção desta página.


✨ Funcionalidades

🎓 Finalidade Educacional

O PlayerCross foi projetado para:

Adequado para:

🕹️ Ecossistema PlayerGames

O PlayerCross faz parte do ecossistema de gamificação PlayerGames para Moodle. Sua principal integração direta é com o bloco PlayerHUD:

Veja o hub do PlayerGames para a família completa de plugins.

🧩 Integração Opcional: Central de IA

A funcionalidade opcional de Geração de palavras por IA do PlayerCross pode usar o Central de IA (local_aihub, do mesmo autor, parte dos serviços compartilhados do ecossistema PlayerGames). Quando o Central de IA está instalado, qualquer chave pessoal ou do site que um professor ou administrador já tenha configurado lá fica automaticamente disponível para o PlayerCross — sem precisar reconfigurar a chave. O PlayerCross nunca contata um provedor de IA diretamente; sem o Central de IA instalado, ele recorre ao subsistema core_ai do próprio Moodle, roteando para o provedor que o administrador do site tiver configurado lá.

👉 https://github.com/jeanlucio/moodle-local_aihub

📦 Requisitos

Componente Versão
Moodle 4.5 – 5.2
PHP 8.1+
PlayerHUD (opcional) v1.7.1+

🛠️ Instalação e Configuração

  1. Baixe o arquivo .zip ou clone este repositório.
  2. Extraia na pasta mod/ do seu Moodle.
  3. Renomeie para playercross (se necessário). Caminho final: seu-moodle/mod/playercross/
  4. Acesse Administração do site > Notificações para concluir a instalação.
  5. Adicione uma atividade PlayerCross a qualquer curso.

Este plugin não tem configurações de nível de site para o administrador ajustar — toda configuração é feita pelo professor ao adicionar a atividade a um curso, conforme explicado em Como Usar logo abaixo. Se o block_playerhud não estiver instalado no site, a própria página de configurações do plugin em Administração do site → Plugins → Módulos de atividade → PlayerCross mostra um aviso informativo sobre isso — não há nada a configurar ali de qualquer forma.

📖 Como Usar

  1. Adicione uma atividade PlayerCross ao seu curso.
  2. Configure:
    • Intervalo de comprimento da frase-mistério (independente do intervalo das próprias palavras-termo) e número de termos por rodada
    • Condição de vitória (termos e frase-mistério obrigatórios, ou só o acerto da frase-mistério) e se letras não cobertas da frase-mistério são reveladas automaticamente
    • Máximo de tentativas por termo e para a frase-mistério, intervalo entre rodadas e limite de rodadas
    • Se dicas são permitidas, e se sim, o máximo de revelações por rodada (padrão 3, ou ilimitado)
    • Modo de palavra (aleatório ou sequência compartilhada)
    • Método de avaliação, modo de pontuação da nota e do ranking (Binário ou Linear), e configurações do diário de notas
    • Fontes de palavras (manual, Glossário, IA), glossário de origem, e uma lista de stopwords a ignorar ao dividir conceitos de glossário com várias palavras (todos opcionais)
    • Custos em itens do PlayerHUD e concessão por vitória (opcional, quando o bloco PlayerHUD está presente)
  3. Abra a página Gerenciar palavras para adicionar, gerar com IA, aprovar, editar ou excluir palavras.
  4. O estudante joga diretamente na página da atividade — resolvendo termos, chutando a frase-mistério, revelando dicas e desistindo de rodadas, sem recarregar a página. A própria barra de ferramentas da página dá acesso às regras (ajuda), ao histórico de tentativas e ao ranking.
  5. Notas e ranking são atualizados automaticamente após cada rodada.

🧮 Nota e Ranking

O PlayerCross 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.

Ambos são totalmente opcionais, e cada um é ligado ou desligado de forma independente:

Desligar um nunca afeta o outro: uma atividade pode ser avaliada sem ranking, ter ranking sem nota, ambos, 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 Modo de pontuação da nota / Modo de pontuação do ranking, ambas com padrão Binário). A nota usa a nota máxima configurada da atividade como base; o ranking sempre usa sua própria base fixa de 100 pontos, totalmente independente da nota — inclusive quando a atividade não tem nota nenhuma (Nota = Nenhuma, o padrão do formulário), o ranking continua funcionando normalmente:

Modo Uma rodada vencida vale… Uma rodada perdida
Binário (padrão) A base cheia (nota da atividade, ou 100 pontos fixos no ranking) Zero
Linear Uma fração que diminui a cada palpite errado — em qualquer termo e na frase-mistério, contados juntos como um único conjunto Zero

Os termos não têm um valor de ponto próprio: todo palpite errado, seja em um termo ou na própria frase-mistério, consome o mesmo conjunto compartilhado de erros, e o tamanho desse conjunto determina a pontuação linear da rodada inteira:

max_errors = num_terms × (max_attempts_per_term − 1) + (max_attempts_final_guess − 1)
pontos (nota)    = nota × (max_errors − erros_usados + 1) / (max_errors + 1)
pontos (ranking) = 100  × (max_errors − erros_usados + 1) / (max_errors + 1)

O modo linear não tem nenhuma tolerância: o primeiro palpite errado já reduz a pontuação. Uma rodada sem nenhum erro continua sempre valendo exatamente a pontuação cheia, e a pontuação nunca chega a zero numa vitória genuinamente concluída — ela tem um piso de base / (max_errors + 1) mesmo no limite máximo de erros. Como max_errors depende das duas configurações de tentativas, escolher Linear para a nota ou para o ranking exige que “Máximo de tentativas por termo” e “Máximo de tentativas para a frase-mistério” sejam ambos um valor real, não ilimitado — o formulário de configurações bloqueia o salvamento caso contrário.

Exemplo prático com 5 termos, 3 tentativas por termo, 3 tentativas para a frase-mistério (max_errors = 5 × 2 + 2 = 12) — a coluna de nota assume uma nota máxima 100, mas a coluna de ranking vale exatamente assim em qualquer atividade, mesmo sem nota nenhuma configurada:

Erros Nota (base 100) Ranking (base 100, sempre) Erros Nota Ranking
0 100,00 100,00 7 46,15 46,15
1 92,31 92,31 8 38,46 38,46
2 84,62 84,62 9 30,77 30,77
3 76,92 76,92 10 23,08 23,08
4 69,23 69,23 11 15,38 15,38
5 61,54 61,54 12 7,69 7,69
6 53,85 53,85 Não concluída 0,00 0,00

Bônus de acerto antecipado: acertar a frase-mistério corretamente antes de resolver qualquer termo soma um bônus fixo de 10% em cima da pontuação base acima — 10% da nota da atividade, para a nota; 10% da base fixa de 100 (ou seja, sempre +10 pontos), para o ranking. Para a nota, isso tem um teto no máximo nominal da atividade — uma rodada perfeita já em 100% permanece em 100%. Para o ranking, não há teto — a mesma rodada perfeita tem seu total de ranking em 110, ultrapassando legitimamente a base nominal de 100, já que o ranking recompensa a dedução precoce eficiente além do que um valor de diário de notas consegue representar.

Combinar várias rodadas em uma nota final é uma configuração separada, Método de avaliação (maior nota, média das notas, primeira tentativa, última tentativa, ou média sobre todas as rodadas exigidas). Ela funciona da mesma forma independente de a pontuação por rodada acima ser Binária ou Linear: ela só agrega o que cada rodada já registrou.

O ranking é a soma dos pontos de ranking de cada rodada finalizada de um estudante (SUM), ordenada da maior para a menor; empates são desfeitos por menos tentativas usadas em média, depois menos tempo gasto em média. Só aparece quando o professor habilita “Mostrar ranking”, e nunca revela uma rodada ainda em andamento.

Só os 5 primeiros são mostrados — de propósito, não é um bug: tanto o widget de ranking no jogo quanto a página dedicada de ranking limitam a lista a 5 linhas, para evitar um ranking público de toda a turma. Um estudante em posição mais baixa ainda vê exatamente onde está: uma linha extra, separada por “…”, mostra sua posição e pontuação reais, sem expor a posição de ninguém abaixo do 5º lugar. Quem gerencia a atividade (editingteacher, manager) nunca aparece no ranking, mesmo que jogue a atividade — da mesma forma que suas próprias tentativas são excluídas do relatório de tentativas abaixo.

“Mostrar ranking” controla só a visibilidade, não a coleta de dados: os pontos de ranking são calculados e armazenados para toda rodada finalizada, independente de o ajuste estar ligado ou desligado no momento. Ativá-lo depois que estudantes já jogaram revela o total completo acumulado desde o início da atividade, não só os pontos ganhos a partir daquele momento — nada se perde, e nada precisa ser “recuperado” desligando e religando o ajuste.

Trava assim que há avaliação: no momento em que a atividade registra uma nota real para qualquer estudante, Termos por rodada, Método de avaliação, Máximo de tentativas por termo, Máximo de tentativas para a frase-mistério e Modo de pontuação da nota travam todos — da mesma forma que o Moodle já trava o campo “Nota máxima” de uma atividade avaliada assim que notas reais existem. Como o orçamento de erros da fórmula linear é uma função direta do número de termos e das duas configurações de tentativas, mudar qualquer um deles depois que já existem pontuações reais faria rodadas anteriores e posteriores valerem coisas diferentes; travá-los garante que toda rodada já registrada permaneça internamente consistente durante toda a vida da atividade.

Modo de pontuação do ranking trava separadamente, assim que existe qualquer tentativa finalizada — não espera uma nota real, porque os pontos de ranking já são calculados e gravados em toda rodada terminada independente de Nota ou Mostrar ranking estarem ligados (ver acima). Uma atividade sem nota nenhuma, só com ranking, já acumula histórico real desde a primeira rodada; travar o modo de pontuação assim que esse histórico existe evita a mesma inconsistência de escala que a trava acima evita para a nota.

Histórico de tentativas: cada estudante pode revisar suas próprias rodadas passadas — frase-mistério, termos resolvidos, tentativas usadas, tempo, pontuação da nota e (quando o ranking está ativado) pontos de ranking — numa página dedicada da barra de ferramentas. Quem gerencia a atividade também vê essa mesma página, incluindo as suas próprias tentativas caso já tenha jogado a atividade. Já o relatório para todos os estudantes vive numa página separada, visível só para quem gerencia: uma tabela com todas as tentativas de todos os estudantes, ordenável clicando em qualquer cabeçalho de coluna e filtrável para um único estudante. Assim como o ranking, esse relatório nunca inclui as próprias tentativas de um gestor.

Excluir tentativas reverte essas travas quando elas deixam de se aplicar. No relatório com todos os estudantes, quem gerencia a atividade pode excluir tentativas de um estudante individualmente ou em lote. A exclusão realmente limpa a nota daquele estudante em vez de deixar um valor obsoleto para trás, então se todas as tentativas de todos os estudantes forem removidas, Termos por rodada, Método de avaliação, as duas configurações de máximo de tentativas e Modo de pontuação da nota destravam de novo exatamente como grade_item::has_grades() espera — do mesmo jeito que aconteceria numa atividade nunca jogada. Modo de pontuação do ranking segue a mesma lógica direto contra a tabela de tentativas, independente de a nota estar ligada.

🧪 Testes Automatizados

O PlayerCross inclui uma suíte PHPUnit cobrindo lógica de negócio, consultas ao repositório, web services e conformidade com a Privacy API, além de uma suíte Behat cobrindo o jogo, a integração com o PlayerHUD e os relatórios de ponta a ponta num navegador real. 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 8
cross_instance_security_test.php 4
lib_grant_potential_test.php 6
lib_reset_userdata_test.php 4
lib_supports_test.php 2
completion/custom_completion_test.php 6
privacy/provider_test.php 21
lib_update_grades_test.php 2
mod_form_test.php 4
Subtotal 57

Testes de Lógica de Negócio (tests/local/)

Arquivo de teste Casos
ai_word_generator_test.php 19
attempts_history_service_test.php 21
gameplay_service_test.php 16
hud_service_test.php 27
intro_service_test.php 5
puzzle_builder_test.php 9
ranking_service_test.php 9
round_presenter_test.php 60
round_service_test.php 67
view_page_service_test.php 40
word_normalizer_test.php 38
words_repository_test.php 67
Subtotal 378

Testes de Web Services (tests/external/)

Arquivo de teste Casos
count_eligible_theme_words_test.php 5
count_eligible_words_test.php 5
count_glossary_candidates_test.php 5
end_round_test.php 6
new_round_test.php 5
reveal_hint_test.php 8
start_round_test.php 7
submit_term_guess_test.php 8
submit_final_guess_test.php 7
Subtotal 56
Total Geral 491
vendor/bin/phpunit --testsuite mod_playercross

Cobertura de linhas geral (moodle-coverage, PHPUnit + Xdebug): 90%.

Behat — Testes de Ponta a Ponta

Arquivo de feature Cenários
mod_playercross_smoke.feature 1
mod_playercross_gameplay.feature 15
mod_playercross_playerhud.feature 4
mod_playercross_reports.feature 5
mod_playercross_settings.feature 5
mod_playercross_toolbar.feature 9
Subtotal 39

Detalhamento completo teste a teste e tabela de cobertura →

🔐 Segurança e Conformidade

🔒 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 Central de IA (local_aihub) — usando a chave BYOK própria 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 que o administrador do site configurou. O PlayerCross nunca contata um provedor de IA diretamente; a requisição e sua divulgação/consentimento são inteiramente de responsabilidade 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 demais funcionalidades continuam funcionando normalmente.

📄 Licença

Este projeto é licenciado sob a GNU General Public License v3 (GPLv3).

Copyright: 2026 Jean Lúcio