funifier-mcp 0.2.24 → 0.2.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cursor/rules/funifier.mdc +1 -0
- package/.github/copilot-instructions.md +1 -0
- package/AGENTS.md +1 -0
- package/datasource-funifier-docs/knowledge/guides/trigger-examples.md +511 -0
- package/datasource-funifier-docs/knowledge/guides/triggers-guide.md +1 -1
- package/datasource-funifier-docs/knowledge/index.md +1 -1
- package/datasource-funifier-docs/knowledge/modules/action.md +96 -39
- package/datasource-funifier-docs/knowledge/modules/challenge.md +285 -48
- package/datasource-funifier-docs/knowledge/modules/folder.md +347 -68
- package/datasource-funifier-docs/knowledge/modules/leaderboard.md +173 -71
- package/datasource-funifier-docs/knowledge/modules/point.md +108 -37
- package/datasource-funifier-docs/knowledge/modules/trigger.md +1 -1
- package/dist/cli/init.d.ts +1 -1
- package/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +11 -4
- package/dist/cli/init.js.map +1 -1
- package/dist/core/api-client.d.ts +21 -1
- package/dist/core/api-client.d.ts.map +1 -1
- package/dist/core/api-client.js +155 -2
- package/dist/core/api-client.js.map +1 -1
- package/dist/core/constants.d.ts +15 -0
- package/dist/core/constants.d.ts.map +1 -1
- package/dist/core/constants.js +15 -0
- package/dist/core/constants.js.map +1 -1
- package/dist/core/types/Folder.d.ts +16 -0
- package/dist/core/types/Folder.d.ts.map +1 -0
- package/dist/core/types/Folder.js +3 -0
- package/dist/core/types/Folder.js.map +1 -0
- package/dist/core/types/FolderContent.d.ts +10 -0
- package/dist/core/types/FolderContent.d.ts.map +1 -0
- package/dist/core/types/FolderContent.js +3 -0
- package/dist/core/types/FolderContent.js.map +1 -0
- package/dist/core/types/FolderContentType.d.ts +10 -0
- package/dist/core/types/FolderContentType.d.ts.map +1 -0
- package/dist/core/types/FolderContentType.js +3 -0
- package/dist/core/types/FolderContentType.js.map +1 -0
- package/dist/core/types/FolderLog.d.ts +11 -0
- package/dist/core/types/FolderLog.d.ts.map +1 -0
- package/dist/core/types/FolderLog.js +3 -0
- package/dist/core/types/FolderLog.js.map +1 -0
- package/dist/core/types/index.d.ts +4 -0
- package/dist/core/types/index.d.ts.map +1 -1
- package/dist/core/types/index.js +4 -0
- package/dist/core/types/index.js.map +1 -1
- package/dist/mcp/bundle.js +101 -92
- package/dist/mcp/check-update.d.ts +2 -0
- package/dist/mcp/check-update.d.ts.map +1 -0
- package/dist/mcp/check-update.js +44 -0
- package/dist/mcp/check-update.js.map +1 -0
- package/dist/mcp/index.js +5 -1
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/tools/_char-guard.js +1 -1
- package/dist/mcp/tools/_char-guard.js.map +1 -1
- package/dist/mcp/tools/_fetch-current.d.ts +1 -1
- package/dist/mcp/tools/_fetch-current.d.ts.map +1 -1
- package/dist/mcp/tools/_fetch-current.js +12 -0
- package/dist/mcp/tools/_fetch-current.js.map +1 -1
- package/dist/mcp/tools/delete.d.ts.map +1 -1
- package/dist/mcp/tools/delete.js +20 -0
- package/dist/mcp/tools/delete.js.map +1 -1
- package/dist/mcp/tools/folder.d.ts +4 -0
- package/dist/mcp/tools/folder.d.ts.map +1 -0
- package/dist/mcp/tools/folder.js +58 -0
- package/dist/mcp/tools/folder.js.map +1 -0
- package/dist/mcp/tools/get.d.ts.map +1 -1
- package/dist/mcp/tools/get.js +22 -8
- package/dist/mcp/tools/get.js.map +1 -1
- package/dist/mcp/tools/index.d.ts.map +1 -1
- package/dist/mcp/tools/index.js +2 -0
- package/dist/mcp/tools/index.js.map +1 -1
- package/dist/mcp/tools/list.d.ts.map +1 -1
- package/dist/mcp/tools/list.js +9 -2
- package/dist/mcp/tools/list.js.map +1 -1
- package/dist/mcp/tools/save.d.ts.map +1 -1
- package/dist/mcp/tools/save.js +100 -7
- package/dist/mcp/tools/save.js.map +1 -1
- package/dist/mcp/tools/save.test.js +191 -0
- package/dist/mcp/tools/save.test.js.map +1 -1
- package/package.json +3 -2
- package/skills/funifier-create-action/SKILL.md +58 -18
- package/skills/funifier-create-aggregate/SKILL.md +1 -0
- package/skills/funifier-create-challenge/SKILL.md +1 -0
- package/skills/funifier-create-custom-page/SKILL.md +1 -0
- package/skills/funifier-create-leaderboard/SKILL.md +90 -18
- package/skills/funifier-create-level/SKILL.md +1 -0
- package/skills/funifier-create-point/SKILL.md +60 -18
- package/skills/funifier-create-quiz/SKILL.md +1 -0
- package/skills/funifier-create-scheduler/SKILL.md +1 -0
- package/skills/funifier-create-trigger/SKILL.md +110 -19
- package/skills/funifier-create-virtual-good/SKILL.md +1 -0
- package/skills/funifier-debug/SKILL.md +2 -0
- package/skills/funifier-help/SKILL.md +1 -0
- package/skills/funifier-implement-frontend/SKILL.md +1 -0
- package/skills/funifier-index/SKILL.md +9 -1
- package/datasource-funifier-docs/.search-index.json +0 -16205
- package/datasource-funifier-docs/.skills-map.json +0 -71
|
@@ -5,55 +5,103 @@
|
|
|
5
5
|
|
|
6
6
|
## O que é
|
|
7
7
|
|
|
8
|
-
Cadastro das diferentes ações que os jogadores podem realizar na gamificação.
|
|
8
|
+
Cadastro das diferentes ações que os jogadores podem realizar na gamificação. As ações são a base da estratégia de engajamento — definem o que pode ser feito e servem para disparar desafios e recompensas. É possível adicionar atributos extras para detalhar o contexto (ex: `produto`, `valor` numa ação de venda).
|
|
9
9
|
|
|
10
10
|
## Quando usar
|
|
11
11
|
|
|
12
12
|
- Em todo projeto de gamificação (obrigatório)
|
|
13
13
|
- Para definir os comportamentos que serão rastreados
|
|
14
|
-
- Para criar a base de eventos que disparam
|
|
14
|
+
- Para criar a base de eventos que disparam challenges e recompensas
|
|
15
15
|
|
|
16
|
-
##
|
|
16
|
+
## Ação simples vs ação com atributos
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
**Ação simples** — sem atributos. Use quando o contexto não importa, só o fato de ter ocorrido:
|
|
19
|
+
|
|
20
|
+
```json
|
|
21
|
+
{
|
|
22
|
+
"_id": "watch_video",
|
|
23
|
+
"action": "Watch Video",
|
|
24
|
+
"active": true,
|
|
25
|
+
"attributes": []
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Exemplos típicos: `login`, `acessar_feed`, `assistir_video`, `jogar_mini`, `compartilhar`.
|
|
30
|
+
|
|
31
|
+
**Ação com atributos** — adicione atributos quando precisar filtrar ou acumular valores dentro de um challenge. Tipos disponíveis: `String`, `Number`, `Boolean`.
|
|
32
|
+
|
|
33
|
+
```json
|
|
34
|
+
{
|
|
35
|
+
"_id": "sell",
|
|
36
|
+
"action": "Sell",
|
|
37
|
+
"active": true,
|
|
38
|
+
"attributes": [
|
|
39
|
+
{ "name": "product", "type": "String" },
|
|
40
|
+
{ "name": "price", "type": "Number" }
|
|
41
|
+
]
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Use atributos quando quiser criar challenges como "vender 10 livros" (filtro por `product = "book"`) ou "vender R$500 em eletrônicos" (soma de `price`).
|
|
46
|
+
|
|
47
|
+
## Imagem
|
|
48
|
+
|
|
49
|
+
Actions podem ter uma imagem associada via campo `image` com três tamanhos:
|
|
50
|
+
|
|
51
|
+
```json
|
|
52
|
+
"image": {
|
|
53
|
+
"small": { "url": "https://...", "size": 0, "width": 0, "height": 0, "depth": 0 },
|
|
54
|
+
"medium": { "url": "https://...", "size": 0, "width": 0, "height": 0, "depth": 0 },
|
|
55
|
+
"original": { "url": "https://...", "size": 0, "width": 0, "height": 0, "depth": 0 }
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Na prática basta preencher `url` nos três tamanhos com a mesma URL se não houver versões distintas.
|
|
60
|
+
|
|
61
|
+
## Comportamento de `_id` duplicado (upsert)
|
|
62
|
+
|
|
63
|
+
O endpoint POST faz **upsert**: se o `_id` já existir, a ação é **atualizada**; se não existir, é **criada**. Não retorna erro em caso de duplicata.
|
|
64
|
+
|
|
65
|
+
Isso significa que é seguro reenviar a mesma ação para atualizar atributos ou o nome — os challenges existentes que referenciam esse `_id` continuam funcionando.
|
|
66
|
+
|
|
67
|
+
## Boas Práticas
|
|
68
|
+
|
|
69
|
+
- `_id`: letras minúsculas, sem espaços ou acentos — use `_` como separador (`watch_video`, não `Watch Video`)
|
|
70
|
+
- Crie ações **genéricas** e use atributos para detalhar: prefira `comprar` com atributo `produto` a criar `comprar_sapato` e `comprar_camisa`
|
|
71
|
+
- Omita `attributes` (ou envie `[]`) quando o contexto não for necessário para nenhum challenge
|
|
23
72
|
|
|
24
73
|
## API Endpoints
|
|
25
74
|
|
|
26
75
|
### Listar Ações
|
|
27
|
-
**Método:** GET
|
|
76
|
+
**Método:** GET
|
|
28
77
|
**Endpoint:** `/v3/action`
|
|
29
|
-
**Descrição:** Retorna a lista de ações configuradas na gamificação.
|
|
30
78
|
|
|
31
|
-
**
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
{
|
|
35
|
-
"action": "Sell",
|
|
36
|
-
"attributes": [
|
|
37
|
-
{ "name": "product", "type": "String" },
|
|
38
|
-
{ "name": "price", "type": "Number" }
|
|
39
|
-
],
|
|
40
|
-
"active": true,
|
|
41
|
-
"_id": "sell"
|
|
42
|
-
}
|
|
43
|
-
]
|
|
79
|
+
**Busca múltipla com funifier_list:** o parâmetro `search` aceita termos separados por vírgula (OR):
|
|
80
|
+
```
|
|
81
|
+
funifier_list type=action search="assistir video, jogar mini, acessar feed"
|
|
44
82
|
```
|
|
45
83
|
|
|
46
|
-
### Criar Ação
|
|
47
|
-
**Método:** POST
|
|
84
|
+
### Criar / Atualizar Ação
|
|
85
|
+
**Método:** POST
|
|
48
86
|
**Endpoint:** `/v3/action`
|
|
49
|
-
**Descrição:** Cria uma nova ação com nome, atributos e status de ativação.
|
|
50
87
|
|
|
51
|
-
|
|
88
|
+
POST com `_id` existente = update (upsert). POST sem `_id` = cria com ID gerado.
|
|
89
|
+
|
|
90
|
+
**Ação simples:**
|
|
91
|
+
```json
|
|
92
|
+
{
|
|
93
|
+
"_id": "watch_video",
|
|
94
|
+
"action": "Watch Video",
|
|
95
|
+
"active": true
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**Ação com atributos:**
|
|
52
100
|
```json
|
|
53
101
|
{
|
|
54
102
|
"_id": "sell",
|
|
55
|
-
"active": true,
|
|
56
103
|
"action": "Sell",
|
|
104
|
+
"active": true,
|
|
57
105
|
"attributes": [
|
|
58
106
|
{ "name": "product", "type": "String" },
|
|
59
107
|
{ "name": "price", "type": "Number" }
|
|
@@ -62,19 +110,28 @@ Cadastro das diferentes ações que os jogadores podem realizar na gamificação
|
|
|
62
110
|
```
|
|
63
111
|
|
|
64
112
|
### Excluir Ação
|
|
65
|
-
**Método:** DELETE
|
|
113
|
+
**Método:** DELETE
|
|
66
114
|
**Endpoint:** `/v3/action/:id`
|
|
67
|
-
**Descrição:** Remove uma ação da gamificação.
|
|
68
115
|
|
|
69
|
-
|
|
116
|
+
> ⚠ Deletar uma ação que é referenciada em challenges ativos pode causar inconsistências. Verifique antes quais challenges usam essa ação:
|
|
117
|
+
> ```
|
|
118
|
+
> funifier_database action=aggregate collection=challenge pipeline='[{"$match": {"rules.actionId": "<action_id>"}}]'
|
|
119
|
+
> ```
|
|
120
|
+
|
|
121
|
+
## Validação após criar
|
|
122
|
+
|
|
123
|
+
Use `funifier_list` para confirmar que a ação foi criada:
|
|
124
|
+
|
|
125
|
+
```
|
|
126
|
+
funifier_list type=action search=<_id ou nome>
|
|
127
|
+
```
|
|
70
128
|
|
|
71
|
-
|
|
72
|
-
- Use os atributos para detalhar o contexto da ação (ex: produto, local, valor)
|
|
73
|
-
- Evite criar uma ação diferente para cada variação. Exemplo errado: "comprar sapato", "comprar camisa". Exemplo certo: ação "comprar" com atributo "produto"
|
|
129
|
+
Não use `funifier_logs` para validar actions — esse comando é específico para triggers e schedulers.
|
|
74
130
|
|
|
75
|
-
##
|
|
131
|
+
## Checklist
|
|
76
132
|
|
|
77
|
-
- [ ]
|
|
78
|
-
- [ ]
|
|
79
|
-
- [ ]
|
|
80
|
-
- [ ]
|
|
133
|
+
- [ ] `_id` definido: minúsculas, sem espaços (`watch_video`, não `Watch Video`)
|
|
134
|
+
- [ ] `action` (nome amigável) preenchido
|
|
135
|
+
- [ ] `active: true`
|
|
136
|
+
- [ ] Atributos com tipos corretos: `String`, `Number` ou `Boolean`
|
|
137
|
+
- [ ] Confirmado com `funifier_list type=action search=<_id>`
|
|
@@ -19,73 +19,310 @@ Configuração de desafios a serem completados por jogadores ou equipes. Permite
|
|
|
19
19
|
- **Point**: tipos de ponto devem existir antes de criar challenges que os recompensam
|
|
20
20
|
- **Action**: ações devem existir antes de criar challenges que as referenciam
|
|
21
21
|
|
|
22
|
-
##
|
|
22
|
+
## Campos Obrigatórios vs Opcionais
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
24
|
+
| Campo | Obrigatório | Descrição |
|
|
25
|
+
|---|---|---|
|
|
26
|
+
| `challenge` | sim | Nome/título do desafio |
|
|
27
|
+
| `techniques` | sim | Array com pelo menos um código GT (ex: `["GT35"]`) |
|
|
28
|
+
| `rules` | sim | Regras que definem o que o jogador deve fazer |
|
|
29
|
+
| `points` | recomendado | Recompensas em pontos ao completar |
|
|
30
|
+
| `description` | não | Descrição exibida ao jogador |
|
|
31
|
+
| `active` | não | `true` por padrão |
|
|
32
|
+
| `_id` | não | Gerado automaticamente se omitido |
|
|
33
|
+
| `range` | não | Obrigatório quando há múltiplas rules; padrão `0` |
|
|
34
|
+
| `teamChallenge` | não | `true` para desafios de equipe |
|
|
35
|
+
| `limitTotal` | não | Limite de vezes que pode ser completado |
|
|
36
|
+
| `limitPerType` | não | A quem se aplica o limite |
|
|
37
|
+
| `limitTimeAmount` | não | Número de períodos para o limite |
|
|
38
|
+
| `limitTimeScale` | não | Escala de tempo do limite |
|
|
39
|
+
| `notifications` | não | Notificações ao completar/criar/alterar |
|
|
40
|
+
| `requirements` | não | Pré-requisitos para desbloquear |
|
|
41
|
+
| `rewards` | não | Recompensas adicionais (itens de catálogo) |
|
|
42
|
+
| `when` | não | Restrição de data/hora de disponibilidade |
|
|
43
|
+
| `principals` | não | Restringe o desafio a jogadores/equipes específicos |
|
|
44
|
+
| `trackFullProgress` | não | Rastrear progresso completo de cada rule |
|
|
45
|
+
| `extra` | não | Campos customizados livres |
|
|
46
|
+
| `i18n` | não | Traduções do título/descrição |
|
|
47
|
+
|
|
48
|
+
## Imagem (badge)
|
|
49
|
+
|
|
50
|
+
Challenges usam o campo `badge` (não `image`) para a imagem do desafio:
|
|
51
|
+
|
|
52
|
+
```json
|
|
53
|
+
"badge": {
|
|
54
|
+
"small": { "url": "https://...", "size": 0, "width": 0, "height": 0, "depth": 0 },
|
|
55
|
+
"medium": { "url": "https://...", "size": 0, "width": 0, "height": 0, "depth": 0 },
|
|
56
|
+
"original": { "url": "https://...", "size": 0, "width": 0, "height": 0, "depth": 0 }
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Na prática basta preencher `url` nos três tamanhos com a mesma URL se não houver versões distintas.
|
|
61
|
+
|
|
62
|
+
## Técnicas de Jogo (techniques)
|
|
63
|
+
|
|
64
|
+
`techniques` é **obrigatório**. Cada código GT representa uma mecânica de gamificação. Para challenges, os códigos válidos são:
|
|
65
|
+
|
|
66
|
+
`GT35`, `GT22`, `GT02`, `GT07`, `GT17`, `GT14`, `GT48`, `GT12`, `GT40`, `GT89`, `GT68`, `GT66`, `GT67`, `GT21`, `GT30`, `GT86`
|
|
67
|
+
|
|
68
|
+
O mais comum para challenges é **`GT35` (Quest List)** — exibe uma lista de tarefas/missões para o jogador cumprir.
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
"techniques": ["GT35"]
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Tabela de Referência dos Enums
|
|
75
|
+
|
|
76
|
+
### `range` — como as rules são avaliadas
|
|
77
|
+
|
|
78
|
+
| Valor | Label |
|
|
79
|
+
|---|---|
|
|
80
|
+
| `0` | Complete All (completar todas as rules) |
|
|
81
|
+
| `1` | Complete Any (completar qualquer uma) |
|
|
82
|
+
| `2` | Complete All in Order (completar todas em ordem) |
|
|
83
|
+
|
|
84
|
+
Padrão: `0` (Complete All). Necessário quando há mais de uma rule.
|
|
85
|
+
|
|
86
|
+
### `rules[].operator` — critério de contagem da rule
|
|
87
|
+
|
|
88
|
+
| Valor | Label | Uso |
|
|
89
|
+
|---|---|---|
|
|
90
|
+
| `5` | `>=` (Greater Than or Equal) | Padrão — contar N ou mais vezes |
|
|
91
|
+
| `1` | `=` (Equal) | Exatamente N vezes |
|
|
92
|
+
| `40` | `%` (Percentage) | Percentual |
|
|
93
|
+
|
|
94
|
+
Exemplo: `operator: 5, total: 3` = executar a ação 3 ou mais vezes.
|
|
95
|
+
|
|
96
|
+
### `rules[].filters[].operator` — operador dos filtros de atributo
|
|
97
|
+
|
|
98
|
+
| Valor | Label |
|
|
99
|
+
|---|---|
|
|
100
|
+
| `1` | Is (igual a) |
|
|
101
|
+
| `3` | Contains (contém) |
|
|
102
|
+
| `4` | Greater Than (maior que) |
|
|
103
|
+
| `5` | Greater Than or Equal To |
|
|
104
|
+
| `6` | Less Than (menor que) |
|
|
105
|
+
| `7` | Less Than or Equal To |
|
|
106
|
+
| `8` | Is Not (diferente de) |
|
|
107
|
+
| `9` | Exists (campo existe) |
|
|
108
|
+
| `10` | Does Not Exist (campo não existe) |
|
|
109
|
+
| `20` | Near in Meters (geolocalização) |
|
|
110
|
+
|
|
111
|
+
### `points[].operation` — operação sobre atributo numérico da ação
|
|
112
|
+
|
|
113
|
+
| Valor | Label | Uso |
|
|
114
|
+
|---|---|---|
|
|
115
|
+
| `0` | None | Pontos fixos (padrão) |
|
|
116
|
+
| `1` | Multiply By | Multiplica `total` pelo valor do atributo da ação |
|
|
117
|
+
| `2` | Divide By | Divide `total` pelo valor do atributo da ação |
|
|
118
|
+
|
|
119
|
+
`operation > 0` só faz sentido quando a rule tem exatamente 1 action com atributo numérico. Nesse caso, `points[].value` deve conter o nome do atributo.
|
|
120
|
+
|
|
121
|
+
### `limitPerType` — a quem o limite se aplica
|
|
122
|
+
|
|
123
|
+
| Valor | Label |
|
|
124
|
+
|---|---|
|
|
125
|
+
| `0` | Player |
|
|
126
|
+
| `1` | Team |
|
|
127
|
+
| `2` | Gamification (global) |
|
|
128
|
+
|
|
129
|
+
### `limitTimeScale` — escala de tempo do limite
|
|
130
|
+
|
|
131
|
+
| Valor | Label |
|
|
132
|
+
|---|---|
|
|
133
|
+
| `0` | None (sem janela de tempo) |
|
|
134
|
+
| `2` | Second |
|
|
135
|
+
| `3` | Minute |
|
|
136
|
+
| `4` | Hour |
|
|
137
|
+
| `5` | Day |
|
|
138
|
+
| `6` | Week |
|
|
139
|
+
| `7` | Month |
|
|
140
|
+
| `8` | Year |
|
|
141
|
+
|
|
142
|
+
### `notifications[].event`
|
|
143
|
+
|
|
144
|
+
| Valor | Label |
|
|
145
|
+
|---|---|
|
|
146
|
+
| `0` | On Win (ao completar o desafio) |
|
|
147
|
+
| `1` | On Create (ao criar o progresso) |
|
|
148
|
+
| `2` | On Change (ao avançar no progresso) |
|
|
149
|
+
|
|
150
|
+
### `notifications[].scope`
|
|
151
|
+
|
|
152
|
+
| Valor | Label |
|
|
153
|
+
|---|---|
|
|
154
|
+
| `0` | Private (apenas o jogador) |
|
|
155
|
+
| `1` | Newsfeed (visível no feed) |
|
|
156
|
+
| `99` | Custom |
|
|
157
|
+
|
|
158
|
+
### `requirements[].type` / `rewards[].type`
|
|
159
|
+
|
|
160
|
+
| Valor | Label |
|
|
161
|
+
|---|---|
|
|
162
|
+
| `0` | Point |
|
|
163
|
+
| `1` | Challenge |
|
|
164
|
+
| `2` | Catalog Item |
|
|
165
|
+
| `3` | Level |
|
|
166
|
+
| `5` | Lottery |
|
|
167
|
+
| `9` | Competition |
|
|
168
|
+
| `50` | Lottery Ticket (apenas em rewards) |
|
|
31
169
|
|
|
32
170
|
## API Endpoints
|
|
33
171
|
|
|
34
172
|
### Listar Desafios
|
|
35
|
-
**Método:** GET
|
|
173
|
+
**Método:** GET
|
|
36
174
|
**Endpoint:** `/v3/challenge`
|
|
37
175
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
{
|
|
42
|
-
"challenge": "Sell 10 books",
|
|
43
|
-
"description": "Sell 10 books to earn 25 xp and 5 coins",
|
|
44
|
-
"rules": [
|
|
45
|
-
{
|
|
46
|
-
"actionId": "sell",
|
|
47
|
-
"filters": [
|
|
48
|
-
{ "value": "book", "operator": 1, "param": "product" }
|
|
49
|
-
],
|
|
50
|
-
"total": 10
|
|
51
|
-
}
|
|
52
|
-
],
|
|
53
|
-
"points": [
|
|
54
|
-
{ "total": 25, "category": "xp" },
|
|
55
|
-
{ "total": 5, "category": "coin" }
|
|
56
|
-
],
|
|
57
|
-
"_id": "DTkhJHV"
|
|
58
|
-
}
|
|
59
|
-
]
|
|
60
|
-
```
|
|
176
|
+
### Buscar por ID
|
|
177
|
+
**Método:** GET
|
|
178
|
+
**Endpoint:** `/v3/challenge/:id`
|
|
61
179
|
|
|
62
|
-
### Criar Desafio
|
|
63
|
-
**Método:** POST
|
|
180
|
+
### Criar / Atualizar Desafio
|
|
181
|
+
**Método:** POST
|
|
64
182
|
**Endpoint:** `/v3/challenge`
|
|
65
183
|
|
|
66
|
-
|
|
184
|
+
Criar e atualizar usam o mesmo endpoint POST. Se `_id` for enviado e o documento existir, é atualizado.
|
|
185
|
+
|
|
186
|
+
### Excluir Desafio
|
|
187
|
+
**Método:** DELETE
|
|
188
|
+
**Endpoint:** `/v3/challenge/:id`
|
|
189
|
+
|
|
190
|
+
## Exemplos
|
|
191
|
+
|
|
192
|
+
### Challenge simples — executar uma ação N vezes
|
|
193
|
+
|
|
67
194
|
```json
|
|
68
195
|
{
|
|
69
196
|
"challenge": "Watch Video",
|
|
70
|
-
"description": "
|
|
197
|
+
"description": "Watch a video to earn 10 xp",
|
|
198
|
+
"techniques": ["GT35"],
|
|
199
|
+
"rules": [
|
|
200
|
+
{ "actionId": "watch_video", "operator": 5, "total": 1 }
|
|
201
|
+
],
|
|
202
|
+
"points": [
|
|
203
|
+
{ "total": 10, "category": "xp", "operation": 0 }
|
|
204
|
+
]
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Challenge com filtro de atributo
|
|
209
|
+
|
|
210
|
+
```json
|
|
211
|
+
{
|
|
212
|
+
"challenge": "Sell 10 Books",
|
|
213
|
+
"description": "Sell 10 books to earn 25 xp",
|
|
214
|
+
"techniques": ["GT35"],
|
|
215
|
+
"rules": [
|
|
216
|
+
{
|
|
217
|
+
"actionId": "sell",
|
|
218
|
+
"operator": 5,
|
|
219
|
+
"total": 10,
|
|
220
|
+
"filters": [
|
|
221
|
+
{ "param": "product", "operator": 1, "value": "book" }
|
|
222
|
+
]
|
|
223
|
+
}
|
|
224
|
+
],
|
|
225
|
+
"points": [
|
|
226
|
+
{ "total": 25, "category": "xp", "operation": 0 }
|
|
227
|
+
]
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### Challenge com múltiplas rules (completar todas)
|
|
232
|
+
|
|
233
|
+
```json
|
|
234
|
+
{
|
|
235
|
+
"challenge": "Daily Routine",
|
|
236
|
+
"techniques": ["GT35"],
|
|
237
|
+
"range": 0,
|
|
71
238
|
"rules": [
|
|
72
|
-
{ "actionId": "
|
|
239
|
+
{ "actionId": "login", "operator": 5, "total": 1 },
|
|
240
|
+
{ "actionId": "comment", "operator": 5, "total": 3 }
|
|
73
241
|
],
|
|
74
242
|
"points": [
|
|
75
|
-
{ "total":
|
|
243
|
+
{ "total": 50, "category": "xp", "operation": 0 }
|
|
244
|
+
]
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### Challenge com limite de frequência (1x por dia por jogador)
|
|
249
|
+
|
|
250
|
+
```json
|
|
251
|
+
{
|
|
252
|
+
"challenge": "Daily Check-in",
|
|
253
|
+
"techniques": ["GT35"],
|
|
254
|
+
"rules": [
|
|
255
|
+
{ "actionId": "checkin", "operator": 5, "total": 1 }
|
|
76
256
|
],
|
|
77
|
-
"
|
|
257
|
+
"points": [{ "total": 5, "category": "xp", "operation": 0 }],
|
|
258
|
+
"limitTotal": 1,
|
|
259
|
+
"limitPerType": 0,
|
|
260
|
+
"limitTimeAmount": 1,
|
|
261
|
+
"limitTimeScale": 5
|
|
78
262
|
}
|
|
79
263
|
```
|
|
80
264
|
|
|
81
|
-
###
|
|
82
|
-
|
|
83
|
-
|
|
265
|
+
### Challenge com notificação ao completar
|
|
266
|
+
|
|
267
|
+
```json
|
|
268
|
+
{
|
|
269
|
+
"challenge": "First Comment",
|
|
270
|
+
"techniques": ["GT35"],
|
|
271
|
+
"rules": [{ "actionId": "comment", "operator": 5, "total": 1 }],
|
|
272
|
+
"points": [{ "total": 10, "category": "xp", "operation": 0 }],
|
|
273
|
+
"notifications": [
|
|
274
|
+
{
|
|
275
|
+
"event": 0,
|
|
276
|
+
"type": 0,
|
|
277
|
+
"scope": 0,
|
|
278
|
+
"content": "{{player.name}} completed {{item.name}}"
|
|
279
|
+
}
|
|
280
|
+
]
|
|
281
|
+
}
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
### Challenge com pré-requisito (desbloqueia após completar outro desafio)
|
|
285
|
+
|
|
286
|
+
```json
|
|
287
|
+
{
|
|
288
|
+
"challenge": "Advanced Task",
|
|
289
|
+
"techniques": ["GT35"],
|
|
290
|
+
"rules": [{ "actionId": "upload", "operator": 5, "total": 5 }],
|
|
291
|
+
"points": [{ "total": 100, "category": "xp", "operation": 0 }],
|
|
292
|
+
"requirements": [
|
|
293
|
+
{ "type": 1, "total": 1, "item": "first_comment_challenge_id" }
|
|
294
|
+
]
|
|
295
|
+
}
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
## Como Validar se foi Criado Corretamente
|
|
299
|
+
|
|
300
|
+
Após salvar com `funifier_save`, confirme com `funifier_get`:
|
|
301
|
+
|
|
302
|
+
```
|
|
303
|
+
funifier_get type=challenge id=<id_retornado>
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
Ou liste e filtre:
|
|
307
|
+
|
|
308
|
+
```
|
|
309
|
+
funifier_list type=challenge search=<nome_do_challenge>
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
Para testar se o challenge está funcionando, registre a ação e verifique o progresso do jogador:
|
|
313
|
+
|
|
314
|
+
```
|
|
315
|
+
POST /v3/action/log { "actionId": "...", "player": "player_id" }
|
|
316
|
+
GET /v3/challenge/progress?player=player_id
|
|
317
|
+
```
|
|
84
318
|
|
|
85
|
-
##
|
|
319
|
+
## Checklist de Configuração
|
|
86
320
|
|
|
87
|
-
- [ ]
|
|
88
|
-
- [ ]
|
|
89
|
-
- [ ]
|
|
90
|
-
- [ ]
|
|
91
|
-
- [ ]
|
|
321
|
+
- [ ] `challenge` (nome) preenchido
|
|
322
|
+
- [ ] `techniques` com pelo menos um código GT (ex: `["GT35"]`)
|
|
323
|
+
- [ ] `rules` com `actionId` existente, `operator` e `total` definidos
|
|
324
|
+
- [ ] `range` definido quando há mais de uma rule
|
|
325
|
+
- [ ] `points` com `category` existente
|
|
326
|
+
- [ ] Ações referenciadas nas rules existem (`funifier_list type=action`)
|
|
327
|
+
- [ ] Pontos referenciados existem (`funifier_list type=point`)
|
|
328
|
+
- [ ] Validado com `funifier_get` após salvar
|