testilo 2.0.2 → 3.0.0
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/README.md +14 -77
- package/package.json +3 -4
- package/procs/score/tsp09.js +565 -0
- package/score.js +33 -0
- package/scoring/correlation.js +76 -0
- package/scoring/correlations.json +327 -0
- package/scoring/data.json +26021 -0
- package/scoring/dupCounts.js +39 -0
- package/scoring/dupCounts.json +112 -0
- package/scoring/duplications.json +253 -0
- package/scoring/issues.json +304 -0
- package/scoring/packageData.js +171 -0
- package/scoring/packageIssues.js +34 -0
- package/scoring/packageRules/aatt.js +543 -0
- package/scoring/rulesetData.json +15 -0
- package/aceconfig.js +0 -6
- package/index.js +0 -88
package/score.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/*
|
|
2
|
+
score.js
|
|
3
|
+
Testilo scoring script.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// ########## IMPORTS
|
|
7
|
+
|
|
8
|
+
// Module to keep secrets.
|
|
9
|
+
require('dotenv').config();
|
|
10
|
+
// Module to read and write files.
|
|
11
|
+
const fs = require('fs').promises;
|
|
12
|
+
|
|
13
|
+
// ########## CONSTANTS
|
|
14
|
+
|
|
15
|
+
const reportDir = process.env.REPORTDIR || 'reports';
|
|
16
|
+
const reportID = process.argv[2];
|
|
17
|
+
|
|
18
|
+
// ########## FUNCTIONS
|
|
19
|
+
|
|
20
|
+
const score = async () => {
|
|
21
|
+
const reportJSON = await fs.readFile(`${__dirname}/${reportDir}/${reportID}.json`, 'utf8');
|
|
22
|
+
const report = JSON.parse(reportJSON);
|
|
23
|
+
const scorerID = report.script.id;
|
|
24
|
+
const {scorer} = require(`./procs/score/${scorerID}`);
|
|
25
|
+
scorer(report);
|
|
26
|
+
const scoredReportJSON = JSON.stringify(report, null, 2);
|
|
27
|
+
await fs.writeFile(`${__dirname}/${reportDir}/${reportID}-scored.json`, scoredReportJSON);
|
|
28
|
+
console.log(`Report ${reportID} scored and saved`);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// ########## OPERATION
|
|
32
|
+
|
|
33
|
+
score();
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/*
|
|
2
|
+
correlation
|
|
3
|
+
Compiles a list of the correlations between distinct-package issue types and creates a file,
|
|
4
|
+
correlations.json, containing the list.
|
|
5
|
+
*/
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const compile = () => {
|
|
8
|
+
const issuesJSON = fs.readFileSync(`${__dirname}/package/issues.json`, 'utf8');
|
|
9
|
+
const issues = JSON.parse(issuesJSON);
|
|
10
|
+
const dataJSON = fs.readFileSync(`${__dirname}/package/data.json`, 'utf8');
|
|
11
|
+
const reportData = JSON.parse(dataJSON);
|
|
12
|
+
const reports = Object.values(reportData);
|
|
13
|
+
// Initialize the list.
|
|
14
|
+
const data = {
|
|
15
|
+
aatt_alfa: {},
|
|
16
|
+
aatt_axe: {},
|
|
17
|
+
aatt_ibm: {},
|
|
18
|
+
aatt_wave: {},
|
|
19
|
+
alfa_axe: {},
|
|
20
|
+
alfa_ibm: {},
|
|
21
|
+
alfa_wave: {},
|
|
22
|
+
axe_ibm: {},
|
|
23
|
+
axe_wave: {},
|
|
24
|
+
ibm_wave: {}
|
|
25
|
+
};
|
|
26
|
+
// For each pair of packages:
|
|
27
|
+
const packagePairs = Object.keys(data);
|
|
28
|
+
packagePairs.forEach(packagePair => {
|
|
29
|
+
console.log(`=== Starting package pair ${packagePair}`);
|
|
30
|
+
const packages = packagePair.split('_');
|
|
31
|
+
// Identify the reports containing results from both packages.
|
|
32
|
+
const pairReports = reports.filter(report => report[packages[0]] && report[packages[1]]);
|
|
33
|
+
// For each pair of issues:
|
|
34
|
+
issues[packages[0]].forEach(issueA => {
|
|
35
|
+
issues[packages[1]].forEach(issueB => {
|
|
36
|
+
// Initialize an array of score pairs.
|
|
37
|
+
const scorePairs = [];
|
|
38
|
+
// For each applicable report:
|
|
39
|
+
pairReports.forEach(report => {
|
|
40
|
+
// Add the scores for the issues to the array of score pairs.
|
|
41
|
+
const scorePair = [report[packages[0]][issueA] || 0, report[packages[1]][issueB] || 0];
|
|
42
|
+
scorePairs.push(scorePair);
|
|
43
|
+
});
|
|
44
|
+
// Get the correlation between the issues.
|
|
45
|
+
const aSum = scorePairs.reduce((sum, current) => sum + current[0], 0);
|
|
46
|
+
const bSum = scorePairs.reduce((sum, current) => sum + current[1], 0);
|
|
47
|
+
const abSum = scorePairs.reduce((sum, current) => sum + current[0] * current[1], 0);
|
|
48
|
+
const aSqSum = scorePairs.reduce((sum, current) => sum + current[0] ** 2, 0);
|
|
49
|
+
const bSqSum = scorePairs.reduce((sum, current) => sum + current[1] ** 2, 0);
|
|
50
|
+
const n = scorePairs.length;
|
|
51
|
+
const correlation
|
|
52
|
+
= (abSum - aSum * bSum / n) / n
|
|
53
|
+
/ (Math.sqrt(aSqSum / n - (aSum / n) ** 2) * Math.sqrt(bSqSum / n - (bSum / n) ** 2));
|
|
54
|
+
// If the correlation is large enough:
|
|
55
|
+
if (correlation > 0.7) {
|
|
56
|
+
const roundedCorr = correlation.toFixed(2);
|
|
57
|
+
// Record it and the count of non-zero scores.
|
|
58
|
+
const nonZero = scorePairs.reduce(
|
|
59
|
+
(count, current) => count + current.filter(score => score).length, 0
|
|
60
|
+
);
|
|
61
|
+
const corrPlusNZ = `${roundedCorr} (${nonZero})`;
|
|
62
|
+
if (data[packagePair][issueA]) {
|
|
63
|
+
data[packagePair][issueA][issueB] = corrPlusNZ;
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
data[packagePair][issueA] = {[issueB]: corrPlusNZ};
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
return data;
|
|
73
|
+
};
|
|
74
|
+
fs.writeFileSync(
|
|
75
|
+
`${__dirname}/package/correlations.json`, JSON.stringify(compile(), null, 2)
|
|
76
|
+
);
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
{
|
|
2
|
+
"aatt_alfa": {
|
|
3
|
+
"e:F77": {
|
|
4
|
+
"r3": "0.89 (253)"
|
|
5
|
+
},
|
|
6
|
+
"e:H36": {
|
|
7
|
+
"r28": "0.98 (6)"
|
|
8
|
+
},
|
|
9
|
+
"e:H37": {
|
|
10
|
+
"r2": "0.72 (221)"
|
|
11
|
+
},
|
|
12
|
+
"e:H57": {
|
|
13
|
+
"r4": "0.81 (66)"
|
|
14
|
+
},
|
|
15
|
+
"e:H58": {
|
|
16
|
+
"r7": "0.82 (5)"
|
|
17
|
+
},
|
|
18
|
+
"w:G141": {
|
|
19
|
+
"r53": "0.89 (427)"
|
|
20
|
+
},
|
|
21
|
+
"w:H98": {
|
|
22
|
+
"r10": "0.95 (3)"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"aatt_axe": {
|
|
26
|
+
"e:H36": {
|
|
27
|
+
"input-image-alt": "0.98 (6)"
|
|
28
|
+
},
|
|
29
|
+
"e:H57": {
|
|
30
|
+
"html-has-lang": "0.73 (75)"
|
|
31
|
+
},
|
|
32
|
+
"e:H58": {
|
|
33
|
+
"valid-lang": "0.82 (5)"
|
|
34
|
+
},
|
|
35
|
+
"w:G141": {
|
|
36
|
+
"heading-order": "0.79 (515)"
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"aatt_ibm": {
|
|
40
|
+
"e:ARIA4+F92": {
|
|
41
|
+
"v:Rpt_Aria_ValidRole": "0.96 (38)"
|
|
42
|
+
},
|
|
43
|
+
"e:ARIA6+H53": {
|
|
44
|
+
"v:WCAG20_Object_HasText": "1.00 (6)"
|
|
45
|
+
},
|
|
46
|
+
"e:H24": {
|
|
47
|
+
"v:WCAG20_Area_HasAlt": "0.79 (4)"
|
|
48
|
+
},
|
|
49
|
+
"e:H36": {
|
|
50
|
+
"v:WCAG20_Input_ExplicitLabelImage": "0.98 (6)"
|
|
51
|
+
},
|
|
52
|
+
"w:F10": {
|
|
53
|
+
"v:WCAG20_Object_HasText": "1.00 (6)"
|
|
54
|
+
},
|
|
55
|
+
"w:H65": {
|
|
56
|
+
"v:Rpt_Aria_ValidRole": "0.92 (16)"
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
"aatt_wave": {
|
|
60
|
+
"e:G1+G123+G124": {
|
|
61
|
+
"a:link_internal_broken": "0.94 (109)"
|
|
62
|
+
},
|
|
63
|
+
"e:H24": {
|
|
64
|
+
"e:alt_area_missing": "0.73 (5)"
|
|
65
|
+
},
|
|
66
|
+
"e:H36": {
|
|
67
|
+
"e:alt_input_missing": "0.91 (7)"
|
|
68
|
+
},
|
|
69
|
+
"e:H37": {
|
|
70
|
+
"e:alt_missing": "0.75 (274)"
|
|
71
|
+
},
|
|
72
|
+
"e:H57": {
|
|
73
|
+
"e:language_missing": "0.72 (85)"
|
|
74
|
+
},
|
|
75
|
+
"w:G141": {
|
|
76
|
+
"a:heading_skipped": "0.85 (535)"
|
|
77
|
+
},
|
|
78
|
+
"w:G90": {
|
|
79
|
+
"a:event_handler": "0.76 (109)"
|
|
80
|
+
},
|
|
81
|
+
"w:H44": {
|
|
82
|
+
"a:label_orphaned": "0.71 (67)"
|
|
83
|
+
},
|
|
84
|
+
"w:H49": {
|
|
85
|
+
"a:image_title": "0.70 (38)",
|
|
86
|
+
"e:alt_spacer_missing": "0.78 (36)",
|
|
87
|
+
"e:th_empty": "0.93 (13)"
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
"alfa_axe": {
|
|
91
|
+
"r11": {
|
|
92
|
+
"link-name": "0.71 (457)"
|
|
93
|
+
},
|
|
94
|
+
"r12": {
|
|
95
|
+
"aria-command-name": "0.93 (51)",
|
|
96
|
+
"dlitem": "0.93 (46)"
|
|
97
|
+
},
|
|
98
|
+
"r2": {
|
|
99
|
+
"image-alt": "0.70 (249)"
|
|
100
|
+
},
|
|
101
|
+
"r20": {
|
|
102
|
+
"aria-command-name": "0.93 (18)",
|
|
103
|
+
"dlitem": "0.93 (13)"
|
|
104
|
+
},
|
|
105
|
+
"r28": {
|
|
106
|
+
"input-image-alt": "1.00 (6)"
|
|
107
|
+
},
|
|
108
|
+
"r3": {
|
|
109
|
+
"duplicate-id": "0.75 (291)"
|
|
110
|
+
},
|
|
111
|
+
"r4": {
|
|
112
|
+
"html-has-lang": "0.80 (74)"
|
|
113
|
+
},
|
|
114
|
+
"r40": {
|
|
115
|
+
"aria-command-name": "0.89 (8)",
|
|
116
|
+
"dlitem": "0.89 (3)"
|
|
117
|
+
},
|
|
118
|
+
"r42": {
|
|
119
|
+
"aria-required-children": "0.91 (72)",
|
|
120
|
+
"aria-required-parent": "0.96 (51)",
|
|
121
|
+
"listitem": "0.73 (71)"
|
|
122
|
+
},
|
|
123
|
+
"r43": {
|
|
124
|
+
"svg-img-alt": "0.98 (4)"
|
|
125
|
+
},
|
|
126
|
+
"r47": {
|
|
127
|
+
"meta-viewport": "0.81 (157)"
|
|
128
|
+
},
|
|
129
|
+
"r5": {
|
|
130
|
+
"html-lang-valid": "1.00 (4)"
|
|
131
|
+
},
|
|
132
|
+
"r53": {
|
|
133
|
+
"heading-order": "0.92 (371)"
|
|
134
|
+
},
|
|
135
|
+
"r68": {
|
|
136
|
+
"aria-required-children": "0.73 (122)",
|
|
137
|
+
"aria-required-parent": "0.78 (101)"
|
|
138
|
+
},
|
|
139
|
+
"r7": {
|
|
140
|
+
"valid-lang": "1.00 (4)"
|
|
141
|
+
},
|
|
142
|
+
"r83": {
|
|
143
|
+
"definition-list": "0.89 (162)",
|
|
144
|
+
"landmark-main-is-top-level": "0.78 (167)"
|
|
145
|
+
},
|
|
146
|
+
"r93": {
|
|
147
|
+
"avoid-inline-spacing": "0.81 (6)"
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
"alfa_ibm": {
|
|
151
|
+
"r12": {
|
|
152
|
+
"v:Rpt_Aria_RequiredParent_Native_Host_Sematics": "0.84 (54)"
|
|
153
|
+
},
|
|
154
|
+
"r13": {
|
|
155
|
+
"v:WCAG20_Frame_HasTitle": "0.70 (116)"
|
|
156
|
+
},
|
|
157
|
+
"r20": {
|
|
158
|
+
"v:Rpt_Aria_RequiredParent_Native_Host_Sematics": "0.84 (20)"
|
|
159
|
+
},
|
|
160
|
+
"r28": {
|
|
161
|
+
"v:WCAG20_Input_ExplicitLabelImage": "0.93 (6)"
|
|
162
|
+
},
|
|
163
|
+
"r40": {
|
|
164
|
+
"v:Rpt_Aria_RequiredParent_Native_Host_Sematics": "0.81 (12)"
|
|
165
|
+
},
|
|
166
|
+
"r5": {
|
|
167
|
+
"v:WCAG20_Elem_Lang_Valid": "0.71 (6)"
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
"alfa_wave": {
|
|
171
|
+
"r28": {
|
|
172
|
+
"a:select_missing_label": "0.73 (39)",
|
|
173
|
+
"e:alt_input_missing": "0.92 (7)"
|
|
174
|
+
},
|
|
175
|
+
"r4": {
|
|
176
|
+
"e:language_missing": "0.71 (82)"
|
|
177
|
+
},
|
|
178
|
+
"r53": {
|
|
179
|
+
"a:heading_skipped": "0.90 (387)"
|
|
180
|
+
},
|
|
181
|
+
"r83": {
|
|
182
|
+
"a:youtube_video": "0.88 (232)"
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
"axe_ibm": {
|
|
186
|
+
"area-alt": {
|
|
187
|
+
"v:HAAC_Img_UsemapAlt": "0.89 (3)"
|
|
188
|
+
},
|
|
189
|
+
"aria-allowed-role": {
|
|
190
|
+
"v:aria_semantics_role": "0.74 (97)"
|
|
191
|
+
},
|
|
192
|
+
"aria-command-name": {
|
|
193
|
+
"v:Rpt_Aria_RequiredParent_Native_Host_Sematics": "0.78 (18)"
|
|
194
|
+
},
|
|
195
|
+
"aria-required-attr": {
|
|
196
|
+
"v:Rpt_Aria_RequiredProperties": "0.82 (5)"
|
|
197
|
+
},
|
|
198
|
+
"aria-valid-attr": {
|
|
199
|
+
"v:Rpt_Aria_ValidProperty": "0.94 (14)"
|
|
200
|
+
},
|
|
201
|
+
"autocomplete-valid": {
|
|
202
|
+
"v:WCAG21_Input_Autocomplete": "0.74 (19)"
|
|
203
|
+
},
|
|
204
|
+
"color-contrast": {
|
|
205
|
+
"v:IBMA_Color_Contrast_WCAG2AA": "0.76 (590)"
|
|
206
|
+
},
|
|
207
|
+
"dlitem": {
|
|
208
|
+
"v:Rpt_Aria_RequiredParent_Native_Host_Sematics": "0.78 (13)"
|
|
209
|
+
},
|
|
210
|
+
"duplicate-id-aria": {
|
|
211
|
+
"v:WCAG21_Label_Accessible": "0.73 (134)"
|
|
212
|
+
},
|
|
213
|
+
"empty-heading": {
|
|
214
|
+
"v:RPT_Header_HasContent": "0.86 (148)"
|
|
215
|
+
},
|
|
216
|
+
"frame-title": {
|
|
217
|
+
"v:WCAG20_Frame_HasTitle": "0.73 (128)"
|
|
218
|
+
},
|
|
219
|
+
"html-lang-valid": {
|
|
220
|
+
"v:WCAG20_Elem_Lang_Valid": "0.77 (8)"
|
|
221
|
+
},
|
|
222
|
+
"image-alt": {
|
|
223
|
+
"v:WCAG20_Img_HasAlt": "0.84 (305)"
|
|
224
|
+
},
|
|
225
|
+
"image-redundant-alt": {
|
|
226
|
+
"v:WCAG20_Img_LinkTextNotRedundant": "0.82 (57)"
|
|
227
|
+
},
|
|
228
|
+
"input-image-alt": {
|
|
229
|
+
"v:WCAG20_Input_ExplicitLabelImage": "0.93 (6)"
|
|
230
|
+
},
|
|
231
|
+
"landmark-complementary-is-top-level": {
|
|
232
|
+
"v:Rpt_Aria_ComplementaryRequiredLabel_Implicit": "0.82 (82)",
|
|
233
|
+
"v:Rpt_Aria_MultipleComplementaryLandmarks_Implicit": "0.83 (50)"
|
|
234
|
+
},
|
|
235
|
+
"landmark-contentinfo-is-top-level": {
|
|
236
|
+
"v:Rpt_Aria_MultipleContentinfoInSiblingSet_Implicit": "0.73 (30)",
|
|
237
|
+
"v:Rpt_Aria_MultipleContentinfoLandmarks_Implicit": "0.86 (49)"
|
|
238
|
+
},
|
|
239
|
+
"landmark-main-is-top-level": {
|
|
240
|
+
"r:Rpt_Aria_MultipleMainsVisibleLabel_Implicit": "0.71 (15)",
|
|
241
|
+
"v:Rpt_Aria_MultipleMainsRequireLabel_Implicit_2": "0.73 (15)"
|
|
242
|
+
},
|
|
243
|
+
"landmark-no-duplicate-banner": {
|
|
244
|
+
"v:Rpt_Aria_MultipleBannerLandmarks_Implicit": "0.73 (80)"
|
|
245
|
+
},
|
|
246
|
+
"landmark-no-duplicate-main": {
|
|
247
|
+
"r:Rpt_Aria_MultipleMainsVisibleLabel_Implicit": "1.00 (18)",
|
|
248
|
+
"v:Rpt_Aria_MultipleMainsRequireLabel_Implicit_2": "0.95 (18)"
|
|
249
|
+
},
|
|
250
|
+
"link-name": {
|
|
251
|
+
"v:WCAG20_A_HasText": "0.75 (492)"
|
|
252
|
+
}
|
|
253
|
+
},
|
|
254
|
+
"axe_wave": {
|
|
255
|
+
"area-alt": {
|
|
256
|
+
"e:alt_area_missing": "0.77 (5)"
|
|
257
|
+
},
|
|
258
|
+
"definition-list": {
|
|
259
|
+
"a:youtube_video": "0.98 (83)"
|
|
260
|
+
},
|
|
261
|
+
"document-title": {
|
|
262
|
+
"e:title_invalid": "0.71 (3)"
|
|
263
|
+
},
|
|
264
|
+
"empty-heading": {
|
|
265
|
+
"e:heading_empty": "0.74 (175)"
|
|
266
|
+
},
|
|
267
|
+
"heading-order": {
|
|
268
|
+
"a:heading_skipped": "0.90 (463)"
|
|
269
|
+
},
|
|
270
|
+
"html-has-lang": {
|
|
271
|
+
"e:language_missing": "0.87 (91)"
|
|
272
|
+
},
|
|
273
|
+
"input-image-alt": {
|
|
274
|
+
"e:alt_input_missing": "0.92 (7)"
|
|
275
|
+
},
|
|
276
|
+
"landmark-main-is-top-level": {
|
|
277
|
+
"a:youtube_video": "0.87 (88)"
|
|
278
|
+
},
|
|
279
|
+
"object-alt": {
|
|
280
|
+
"a:plugin": "1.00 (6)"
|
|
281
|
+
},
|
|
282
|
+
"page-has-heading-one": {
|
|
283
|
+
"a:h1_missing": "0.79 (206)"
|
|
284
|
+
},
|
|
285
|
+
"select-name": {
|
|
286
|
+
"a:select_missing_label": "0.79 (71)"
|
|
287
|
+
}
|
|
288
|
+
},
|
|
289
|
+
"ibm_wave": {
|
|
290
|
+
"v:HAAC_Aria_ImgAlt": {
|
|
291
|
+
"a:tabindex": "0.84 (57)"
|
|
292
|
+
},
|
|
293
|
+
"v:IBMA_Color_Contrast_WCAG2AA": {
|
|
294
|
+
"c:contrast": "0.73 (693)"
|
|
295
|
+
},
|
|
296
|
+
"v:RPT_Header_HasContent": {
|
|
297
|
+
"e:heading_empty": "0.84 (168)"
|
|
298
|
+
},
|
|
299
|
+
"v:RPT_Table_DataHeadingsAria": {
|
|
300
|
+
"a:table_layout": "0.73 (60)"
|
|
301
|
+
},
|
|
302
|
+
"v:Rpt_Aria_MultipleToolbarUniqueLabel": {
|
|
303
|
+
"a:tabindex": "0.89 (44)"
|
|
304
|
+
},
|
|
305
|
+
"v:Rpt_Aria_ValidIdRef": {
|
|
306
|
+
"e:aria_reference_broken": "0.81 (131)"
|
|
307
|
+
},
|
|
308
|
+
"v:WCAG20_Area_HasAlt": {
|
|
309
|
+
"e:alt_area_missing": "0.80 (5)"
|
|
310
|
+
},
|
|
311
|
+
"v:WCAG20_Elem_UniqueAccessKey": {
|
|
312
|
+
"a:accesskey": "0.78 (15)"
|
|
313
|
+
},
|
|
314
|
+
"v:WCAG20_Img_HasAlt": {
|
|
315
|
+
"e:alt_missing": "0.87 (296)"
|
|
316
|
+
},
|
|
317
|
+
"v:WCAG20_Img_PresentationImgHasNonNullAlt": {
|
|
318
|
+
"a:alt_redundant": "0.75 (75)"
|
|
319
|
+
},
|
|
320
|
+
"v:WCAG20_Input_ExplicitLabelImage": {
|
|
321
|
+
"e:alt_input_missing": "0.87 (7)"
|
|
322
|
+
},
|
|
323
|
+
"v:WCAG20_Input_RadioChkInFieldSet": {
|
|
324
|
+
"a:fieldset_missing": "0.71 (57)"
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|