@the-bearded-bear/claude-craft 8.8.1 → 8.8.2
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/Dev/i18n/de/Angular/commands/check-compliance.md +218 -168
- package/Dev/i18n/de/Common/agents/refactoring-specialist.md +146 -69
- package/Dev/i18n/de/Common/commands/add-technology.md +166 -68
- package/Dev/i18n/de/Common/commands/setup-ci.md +216 -33
- package/Dev/i18n/de/Laravel/commands/check-compliance.md +223 -115
- package/Dev/i18n/de/Python/checklists/new-feature.md +319 -44
- package/Dev/i18n/de/React/rules/02-architecture.md +483 -322
- package/Dev/i18n/de/React/rules/03-coding-standards.md +584 -368
- package/Dev/i18n/de/Symfony/commands/check-compliance.md +186 -114
- package/Dev/i18n/de/Symfony/rules/07-testing-symfony.md +679 -10
- package/Dev/i18n/de/UIUX/commands/a11y-component.md +284 -26
- package/Dev/i18n/de/UIUX/commands/design-tokens.md +199 -35
- package/Dev/i18n/de/UIUX/commands/user-flow.md +179 -16
- package/Dev/i18n/de/VueJS/commands/check-compliance.md +227 -102
- package/Dev/i18n/es/Angular/commands/check-compliance.md +217 -167
- package/Dev/i18n/es/Common/commands/add-technology.md +158 -60
- package/Dev/i18n/es/Laravel/commands/check-compliance.md +223 -115
- package/Dev/i18n/es/React/commands/check-testing.md +263 -169
- package/Dev/i18n/es/ReactNative/commands/check-testing.md +256 -198
- package/Dev/i18n/es/Symfony/commands/check-compliance.md +189 -117
- package/Dev/i18n/es/Symfony/commands/check-testing.md +301 -102
- package/Dev/i18n/es/Symfony/commands/migration-plan.md +267 -34
- package/Dev/i18n/es/UIUX/commands/a11y-component.md +274 -16
- package/Dev/i18n/es/UIUX/commands/design-tokens.md +186 -22
- package/Dev/i18n/es/UIUX/commands/user-flow.md +173 -10
- package/Dev/i18n/es/VueJS/commands/check-compliance.md +227 -102
- package/Dev/i18n/fr/Angular/commands/check-compliance.md +217 -167
- package/Dev/i18n/fr/Common/commands/ralph-run.md +138 -60
- package/Dev/i18n/fr/Laravel/commands/check-compliance.md +223 -115
- package/Dev/i18n/fr/React/commands/check-architecture.md +370 -53
- package/Dev/i18n/fr/React/commands/check-code-quality.md +454 -64
- package/Dev/i18n/fr/React/commands/check-testing.md +476 -102
- package/Dev/i18n/fr/Symfony/commands/check-compliance.md +188 -116
- package/Dev/i18n/fr/VueJS/commands/check-compliance.md +227 -102
- package/Dev/i18n/pt/Angular/commands/check-compliance.md +225 -175
- package/Dev/i18n/pt/Common/agents/ralph-conductor.md +211 -30
- package/Dev/i18n/pt/Common/commands/add-technology.md +149 -51
- package/Dev/i18n/pt/Common/commands/ralph-run.md +239 -35
- package/Dev/i18n/pt/Flutter/commands/analyze-performance.md +331 -46
- package/Dev/i18n/pt/Flutter/commands/check-compliance.md +234 -29
- package/Dev/i18n/pt/Flutter/commands/generate-feature.md +526 -51
- package/Dev/i18n/pt/Flutter/commands/generate-widget.md +515 -27
- package/Dev/i18n/pt/Flutter/commands/golden-update.md +322 -46
- package/Dev/i18n/pt/Flutter/commands/localization-check.md +278 -37
- package/Dev/i18n/pt/Laravel/commands/check-compliance.md +212 -104
- package/Dev/i18n/pt/React/commands/accessibility-check.md +151 -42
- package/Dev/i18n/pt/React/commands/bundle-analyze.md +300 -25
- package/Dev/i18n/pt/React/commands/check-architecture.md +369 -34
- package/Dev/i18n/pt/React/commands/check-code-quality.md +440 -34
- package/Dev/i18n/pt/React/commands/check-compliance.md +232 -62
- package/Dev/i18n/pt/React/commands/check-security.md +370 -31
- package/Dev/i18n/pt/React/commands/check-testing.md +473 -43
- package/Dev/i18n/pt/React/commands/generate-component.md +454 -19
- package/Dev/i18n/pt/React/commands/generate-hook.md +425 -24
- package/Dev/i18n/pt/React/commands/storybook-story.md +520 -35
- package/Dev/i18n/pt/ReactNative/commands/app-size.md +358 -387
- package/Dev/i18n/pt/ReactNative/commands/check-code-quality.md +246 -75
- package/Dev/i18n/pt/ReactNative/commands/check-compliance.md +191 -85
- package/Dev/i18n/pt/ReactNative/commands/check-security.md +363 -115
- package/Dev/i18n/pt/ReactNative/commands/check-testing.md +269 -79
- package/Dev/i18n/pt/ReactNative/commands/generate-screen.md +491 -324
- package/Dev/i18n/pt/ReactNative/commands/native-module.md +539 -82
- package/Dev/i18n/pt/ReactNative/commands/store-prepare.md +429 -185
- package/Dev/i18n/pt/ReactNative/rules/02-architecture.md +1084 -31
- package/Dev/i18n/pt/Symfony/commands/check-compliance.md +195 -123
- package/Dev/i18n/pt/UIUX/commands/a11y-audit.md +208 -24
- package/Dev/i18n/pt/UIUX/commands/a11y-component.md +281 -23
- package/Dev/i18n/pt/UIUX/commands/design-tokens.md +197 -33
- package/Dev/i18n/pt/UIUX/commands/user-flow.md +183 -20
- package/Dev/i18n/pt/VueJS/commands/check-compliance.md +228 -103
- package/Dev/i18n/pt/Workflow/commands/analyze.md +147 -146
- package/Dev/i18n/pt/Workflow/commands/design.md +205 -204
- package/Dev/i18n/pt/Workflow/commands/implement.md +184 -184
- package/Project/i18n/de/Sprint/commands/dev.md +339 -86
- package/Project/i18n/es/Sprint/commands/dev.md +342 -91
- package/Project/i18n/pt/Sprint/commands/dev.md +343 -92
- package/bundles/cursor/.cursorrules +1 -1
- package/bundles/windsurf/.windsurfrules +1 -1
- package/package.json +1 -1
|
@@ -1,85 +1,361 @@
|
|
|
1
1
|
---
|
|
2
|
-
description:
|
|
2
|
+
description: Atualização dos Golden Tests
|
|
3
|
+
argument-hint: [arguments]
|
|
3
4
|
---
|
|
4
5
|
|
|
5
|
-
#
|
|
6
|
+
# Atualização dos Golden Tests
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
Você é um desenvolvedor Flutter sênior. Você deve gerenciar os golden tests do projeto, atualizá-los após mudanças visuais intencionais e verificar regressões.
|
|
8
9
|
|
|
9
|
-
##
|
|
10
|
+
## Argumentos
|
|
11
|
+
$ARGUMENTS
|
|
12
|
+
|
|
13
|
+
Argumentos:
|
|
14
|
+
- Ação: update, check, compare
|
|
15
|
+
- (Opcional) Caminho para um teste específico
|
|
16
|
+
|
|
17
|
+
Exemplo: `/flutter:golden-update update` ou `/flutter:golden-update check test/widgets/button_test.dart`
|
|
18
|
+
|
|
19
|
+
## Modo de Planejamento
|
|
20
|
+
|
|
21
|
+
> **O modo de planejamento é obrigatório.** Antes de executar, o Claude ativa o modo de planejamento para analisar o código impactado, propor um plano de implementação e aguardar a sua validação antes de realizar qualquer alteração.
|
|
22
|
+
|
|
23
|
+
## MISSÃO
|
|
24
|
+
|
|
25
|
+
### Etapa 1: Compreender os Golden Tests
|
|
26
|
+
|
|
27
|
+
Os golden tests comparam o renderizado visual de um widget com uma imagem de referência.
|
|
28
|
+
|
|
29
|
+
```dart
|
|
30
|
+
// test/widgets/my_button_test.dart
|
|
31
|
+
import 'package:flutter/material.dart';
|
|
32
|
+
import 'package:flutter_test/flutter_test.dart';
|
|
33
|
+
import 'package:my_app/widgets/my_button.dart';
|
|
34
|
+
|
|
35
|
+
void main() {
|
|
36
|
+
group('MyButton Golden Tests', () {
|
|
37
|
+
testWidgets('estado padrão', (tester) async {
|
|
38
|
+
await tester.pumpWidget(
|
|
39
|
+
const MaterialApp(
|
|
40
|
+
home: Scaffold(
|
|
41
|
+
body: Center(
|
|
42
|
+
child: MyButton(label: 'Clique aqui'),
|
|
43
|
+
),
|
|
44
|
+
),
|
|
45
|
+
),
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
await expectLater(
|
|
49
|
+
find.byType(MyButton),
|
|
50
|
+
matchesGoldenFile('goldens/my_button_default.png'),
|
|
51
|
+
);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
testWidgets('estado pressionado', (tester) async {
|
|
55
|
+
await tester.pumpWidget(
|
|
56
|
+
MaterialApp(
|
|
57
|
+
home: Scaffold(
|
|
58
|
+
body: Center(
|
|
59
|
+
child: MyButton(
|
|
60
|
+
label: 'Clique aqui',
|
|
61
|
+
isPressed: true,
|
|
62
|
+
),
|
|
63
|
+
),
|
|
64
|
+
),
|
|
65
|
+
),
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
await expectLater(
|
|
69
|
+
find.byType(MyButton),
|
|
70
|
+
matchesGoldenFile('goldens/my_button_pressed.png'),
|
|
71
|
+
);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
testWidgets('estado desabilitado', (tester) async {
|
|
75
|
+
await tester.pumpWidget(
|
|
76
|
+
const MaterialApp(
|
|
77
|
+
home: Scaffold(
|
|
78
|
+
body: Center(
|
|
79
|
+
child: MyButton(
|
|
80
|
+
label: 'Clique aqui',
|
|
81
|
+
isEnabled: false,
|
|
82
|
+
),
|
|
83
|
+
),
|
|
84
|
+
),
|
|
85
|
+
),
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
await expectLater(
|
|
89
|
+
find.byType(MyButton),
|
|
90
|
+
matchesGoldenFile('goldens/my_button_disabled.png'),
|
|
91
|
+
);
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Etapa 2: Comandos Básicos
|
|
10
98
|
|
|
11
99
|
```bash
|
|
12
|
-
#
|
|
100
|
+
# Verificar os golden tests (comparar com as referências)
|
|
101
|
+
flutter test --tags=golden
|
|
102
|
+
|
|
103
|
+
# Atualizar TODOS os golden tests
|
|
13
104
|
flutter test --update-goldens
|
|
14
105
|
|
|
15
|
-
# Atualizar
|
|
16
|
-
flutter test
|
|
106
|
+
# Atualizar um teste específico
|
|
107
|
+
flutter test --update-goldens test/widgets/my_button_test.dart
|
|
17
108
|
|
|
18
|
-
# Executar
|
|
19
|
-
flutter test --
|
|
20
|
-
```
|
|
109
|
+
# Executar com um device específico (importante para consistência)
|
|
110
|
+
flutter test --update-goldens --device-id=linux
|
|
21
111
|
|
|
22
|
-
|
|
112
|
+
# Ignorar os golden tests no CI (se necessário)
|
|
113
|
+
flutter test --exclude-tags=golden
|
|
114
|
+
```
|
|
23
115
|
|
|
24
|
-
|
|
116
|
+
### Etapa 3: Configuração Recomendada
|
|
25
117
|
|
|
26
|
-
|
|
118
|
+
#### flutter_test_config.dart
|
|
27
119
|
|
|
28
|
-
|
|
120
|
+
```dart
|
|
121
|
+
// test/flutter_test_config.dart
|
|
122
|
+
import 'dart:async';
|
|
123
|
+
import 'package:flutter/material.dart';
|
|
29
124
|
|
|
30
|
-
|
|
125
|
+
Future<void> testExecutable(FutureOr<void> Function() testMain) async {
|
|
126
|
+
// Configuração de fontes para consistência
|
|
127
|
+
TestWidgetsFlutterBinding.ensureInitialized();
|
|
31
128
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
129
|
+
// Configurar o comparador de golden files
|
|
130
|
+
if (goldenFileComparator is LocalFileComparator) {
|
|
131
|
+
final testUrl = (goldenFileComparator as LocalFileComparator).basedir;
|
|
132
|
+
goldenFileComparator = _CustomGoldenFileComparator(testUrl);
|
|
133
|
+
}
|
|
35
134
|
|
|
36
|
-
|
|
37
|
-
|
|
135
|
+
await testMain();
|
|
136
|
+
}
|
|
38
137
|
|
|
39
|
-
|
|
40
|
-
|
|
138
|
+
class _CustomGoldenFileComparator extends LocalFileComparator {
|
|
139
|
+
_CustomGoldenFileComparator(Uri basedir) : super(basedir);
|
|
41
140
|
|
|
42
|
-
|
|
43
|
-
|
|
141
|
+
@override
|
|
142
|
+
Future<bool> compare(Uint8List imageBytes, Uri golden) async {
|
|
143
|
+
final result = await super.compare(imageBytes, golden);
|
|
144
|
+
if (!result) {
|
|
145
|
+
// Log mais detalhado em caso de falha
|
|
146
|
+
print('Golden test falhou: $golden');
|
|
147
|
+
}
|
|
148
|
+
return result;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
44
151
|
```
|
|
45
152
|
|
|
46
|
-
|
|
153
|
+
#### Tags para os Golden Tests
|
|
47
154
|
|
|
48
155
|
```dart
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
);
|
|
156
|
+
// test/widgets/my_button_test.dart
|
|
157
|
+
@Tags(['golden'])
|
|
158
|
+
library;
|
|
53
159
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
matchesGoldenFile('goldens/my_widget_default.png'),
|
|
57
|
-
);
|
|
58
|
-
});
|
|
160
|
+
import 'package:flutter_test/flutter_test.dart';
|
|
161
|
+
// ...
|
|
59
162
|
```
|
|
60
163
|
|
|
61
|
-
###
|
|
164
|
+
### Etapa 4: Boas Práticas
|
|
165
|
+
|
|
166
|
+
#### Estrutura de Pastas
|
|
167
|
+
|
|
168
|
+
```
|
|
169
|
+
test/
|
|
170
|
+
├── goldens/
|
|
171
|
+
│ ├── widgets/
|
|
172
|
+
│ │ ├── my_button_default.png
|
|
173
|
+
│ │ ├── my_button_pressed.png
|
|
174
|
+
│ │ └── my_button_disabled.png
|
|
175
|
+
│ └── screens/
|
|
176
|
+
│ ├── home_screen.png
|
|
177
|
+
│ └── settings_screen.png
|
|
178
|
+
├── widgets/
|
|
179
|
+
│ └── my_button_test.dart
|
|
180
|
+
└── screens/
|
|
181
|
+
└── home_screen_test.dart
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
#### Wrapper para Golden Tests
|
|
62
185
|
|
|
63
186
|
```dart
|
|
64
|
-
//
|
|
65
|
-
|
|
187
|
+
// test/helpers/golden_test_wrapper.dart
|
|
188
|
+
import 'package:flutter/material.dart';
|
|
189
|
+
|
|
190
|
+
Widget goldenTestWrapper({
|
|
191
|
+
required Widget child,
|
|
192
|
+
ThemeData? theme,
|
|
193
|
+
Size size = const Size(400, 600),
|
|
194
|
+
}) {
|
|
195
|
+
return MaterialApp(
|
|
196
|
+
debugShowCheckedModeBanner: false,
|
|
197
|
+
theme: theme ?? ThemeData.light(),
|
|
198
|
+
home: Scaffold(
|
|
199
|
+
body: SizedBox(
|
|
200
|
+
width: size.width,
|
|
201
|
+
height: size.height,
|
|
202
|
+
child: Center(child: child),
|
|
203
|
+
),
|
|
204
|
+
),
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// Uso
|
|
209
|
+
testWidgets('golden do meu widget', (tester) async {
|
|
66
210
|
await tester.pumpWidget(
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
211
|
+
goldenTestWrapper(
|
|
212
|
+
child: const MyWidget(),
|
|
213
|
+
size: const Size(300, 200),
|
|
70
214
|
),
|
|
71
215
|
);
|
|
72
216
|
|
|
73
217
|
await expectLater(
|
|
74
218
|
find.byType(MyWidget),
|
|
75
|
-
matchesGoldenFile('goldens/
|
|
219
|
+
matchesGoldenFile('goldens/my_widget.png'),
|
|
76
220
|
);
|
|
77
221
|
});
|
|
78
222
|
```
|
|
79
223
|
|
|
80
|
-
|
|
224
|
+
#### Multi-Tema e Multi-Plataforma
|
|
225
|
+
|
|
226
|
+
```dart
|
|
227
|
+
void main() {
|
|
228
|
+
final themes = {
|
|
229
|
+
'light': ThemeData.light(),
|
|
230
|
+
'dark': ThemeData.dark(),
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
for (final entry in themes.entries) {
|
|
234
|
+
testWidgets('MyButton - tema ${entry.key}', (tester) async {
|
|
235
|
+
await tester.pumpWidget(
|
|
236
|
+
MaterialApp(
|
|
237
|
+
theme: entry.value,
|
|
238
|
+
home: const Scaffold(
|
|
239
|
+
body: Center(child: MyButton(label: 'Test')),
|
|
240
|
+
),
|
|
241
|
+
),
|
|
242
|
+
);
|
|
243
|
+
|
|
244
|
+
await expectLater(
|
|
245
|
+
find.byType(MyButton),
|
|
246
|
+
matchesGoldenFile('goldens/my_button_${entry.key}.png'),
|
|
247
|
+
);
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### Etapa 5: Workflow CI/CD
|
|
254
|
+
|
|
255
|
+
```yaml
|
|
256
|
+
# .github/workflows/flutter.yml
|
|
257
|
+
name: Flutter Tests
|
|
258
|
+
|
|
259
|
+
on: [push, pull_request]
|
|
260
|
+
|
|
261
|
+
jobs:
|
|
262
|
+
test:
|
|
263
|
+
runs-on: ubuntu-latest
|
|
264
|
+
steps:
|
|
265
|
+
- uses: actions/checkout@v4
|
|
266
|
+
|
|
267
|
+
- uses: subosito/flutter-action@v2
|
|
268
|
+
with:
|
|
269
|
+
flutter-version: '3.24.0'
|
|
270
|
+
|
|
271
|
+
- name: Instalar dependências
|
|
272
|
+
run: flutter pub get
|
|
273
|
+
|
|
274
|
+
- name: Executar testes unitários
|
|
275
|
+
run: flutter test --exclude-tags=golden
|
|
276
|
+
|
|
277
|
+
- name: Executar golden tests
|
|
278
|
+
run: flutter test --tags=golden
|
|
279
|
+
continue-on-error: true # Para visualizar as diferenças
|
|
280
|
+
|
|
281
|
+
- name: Fazer upload das falhas dos golden tests
|
|
282
|
+
if: failure()
|
|
283
|
+
uses: actions/upload-artifact@v4
|
|
284
|
+
with:
|
|
285
|
+
name: golden-failures
|
|
286
|
+
path: '**/failures/*.png'
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### Etapa 6: Resolver as Diferenças
|
|
290
|
+
|
|
291
|
+
```
|
|
292
|
+
══════════════════════════════════════════════════════════════
|
|
293
|
+
🖼️ GOLDEN TESTS - RESULTADO
|
|
294
|
+
══════════════════════════════════════════════════════════════
|
|
295
|
+
|
|
296
|
+
──────────────────────────────────────────────────────────────
|
|
297
|
+
📊 RESUMO
|
|
298
|
+
──────────────────────────────────────────────────────────────
|
|
299
|
+
|
|
300
|
+
| Categoria | Testes | Aprovados | Reprovados |
|
|
301
|
+
|-------------|--------|-----------|------------|
|
|
302
|
+
| Widgets | 15 | 12 | 3 |
|
|
303
|
+
| Screens | 8 | 8 | 0 |
|
|
304
|
+
| Components | 10 | 10 | 0 |
|
|
305
|
+
| **Total** | 33 | 30 | 3 |
|
|
306
|
+
|
|
307
|
+
──────────────────────────────────────────────────────────────
|
|
308
|
+
❌ TESTES REPROVADOS
|
|
309
|
+
──────────────────────────────────────────────────────────────
|
|
310
|
+
|
|
311
|
+
### 1. my_button_default.png
|
|
312
|
+
|
|
313
|
+
Diferença detectada: 2,3%
|
|
314
|
+
|
|
315
|
+
Causa provável:
|
|
316
|
+
- Mudança de padding
|
|
317
|
+
- Modificação da fonte
|
|
318
|
+
- Atualização do tema
|
|
319
|
+
|
|
320
|
+
Ações:
|
|
321
|
+
- [ ] Verificar se a mudança é intencional
|
|
322
|
+
- [ ] Se sim: `flutter test --update-goldens test/widgets/my_button_test.dart`
|
|
323
|
+
- [ ] Se não: reverter as mudanças
|
|
324
|
+
|
|
325
|
+
### 2. user_card_avatar.png
|
|
326
|
+
|
|
327
|
+
Diferença detectada: 15,7%
|
|
328
|
+
|
|
329
|
+
Causa provável:
|
|
330
|
+
- Novo design do avatar
|
|
331
|
+
- Mudança de border-radius
|
|
81
332
|
|
|
82
|
-
|
|
83
|
-
- [ ]
|
|
84
|
-
- [ ]
|
|
85
|
-
|
|
333
|
+
Ações:
|
|
334
|
+
- [ ] Revisar com o designer
|
|
335
|
+
- [ ] Atualizar se validado
|
|
336
|
+
|
|
337
|
+
──────────────────────────────────────────────────────────────
|
|
338
|
+
🔧 COMANDOS
|
|
339
|
+
──────────────────────────────────────────────────────────────
|
|
340
|
+
|
|
341
|
+
# Ver as diferenças
|
|
342
|
+
open test/goldens/failures/
|
|
343
|
+
|
|
344
|
+
# Atualizar os testes reprovados
|
|
345
|
+
flutter test --update-goldens test/widgets/my_button_test.dart
|
|
346
|
+
|
|
347
|
+
# Atualizar todos os golden tests
|
|
348
|
+
flutter test --update-goldens --tags=golden
|
|
349
|
+
|
|
350
|
+
# Executar somente os golden tests
|
|
351
|
+
flutter test --tags=golden
|
|
352
|
+
|
|
353
|
+
──────────────────────────────────────────────────────────────
|
|
354
|
+
⚠️ LEMBRETES
|
|
355
|
+
──────────────────────────────────────────────────────────────
|
|
356
|
+
|
|
357
|
+
1. Sempre verificar visualmente antes de atualizar
|
|
358
|
+
2. Commitar os novos .png junto com o código
|
|
359
|
+
3. Usar o mesmo ambiente para gerar os goldens
|
|
360
|
+
4. Documentar as mudanças visuais na PR
|
|
361
|
+
```
|