@euconform/core 1.0.0 → 1.0.1

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.
Files changed (42) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/.turbo/turbo-check-types.log +4 -0
  3. package/.turbo/turbo-test.log +364 -0
  4. package/CHANGELOG.md +7 -0
  5. package/README.md +109 -0
  6. package/coverage/base.css +224 -0
  7. package/coverage/block-navigation.js +87 -0
  8. package/coverage/clover.xml +3282 -0
  9. package/coverage/coverage-final.json +20 -0
  10. package/coverage/favicon.png +0 -0
  11. package/coverage/index.html +161 -0
  12. package/coverage/prettify.css +1 -0
  13. package/coverage/prettify.js +2 -0
  14. package/coverage/sort-arrow-sprite.png +0 -0
  15. package/coverage/sorter.js +210 -0
  16. package/coverage/src/fairness-metrics.ts.html +1579 -0
  17. package/coverage/src/index.html +161 -0
  18. package/coverage/src/index.ts.html +535 -0
  19. package/coverage/src/inference/browser-inference.ts.html +859 -0
  20. package/coverage/src/inference/capability-detection.ts.html +2227 -0
  21. package/coverage/src/inference/index.html +176 -0
  22. package/coverage/src/inference/index.ts.html +553 -0
  23. package/coverage/src/inference/inference-factory.ts.html +751 -0
  24. package/coverage/src/inference/ollama-client.ts.html +1627 -0
  25. package/coverage/src/legal-checks/annex-iv-report.ts.html +556 -0
  26. package/coverage/src/legal-checks/bias-metrics.ts.html +1855 -0
  27. package/coverage/src/legal-checks/data-governance.ts.html +529 -0
  28. package/coverage/src/legal-checks/human-oversight-logging.ts.html +490 -0
  29. package/coverage/src/legal-checks/index.html +206 -0
  30. package/coverage/src/legal-checks/index.ts.html +250 -0
  31. package/coverage/src/legal-checks/risk-classifier.ts.html +940 -0
  32. package/coverage/src/legal-checks/robustness-transparency.ts.html +571 -0
  33. package/coverage/src/metrics/crows-pairs-bias.ts.html +820 -0
  34. package/coverage/src/metrics/index.html +146 -0
  35. package/coverage/src/metrics/index.ts.html +151 -0
  36. package/coverage/src/metrics/stereotype-bias.ts.html +886 -0
  37. package/coverage/src/risk-engine.ts.html +1660 -0
  38. package/coverage/src/types.ts.html +547 -0
  39. package/dist/legal-checks/disclaimer.d.ts +2 -0
  40. package/dist/legal-checks/disclaimer.d.ts.map +1 -0
  41. package/dist/legal-checks/disclaimer.js +1 -0
  42. package/package.json +20 -1
@@ -0,0 +1,1855 @@
1
+
2
+ <!doctype html>
3
+ <html lang="en">
4
+
5
+ <head>
6
+ <title>Code coverage report for src/legal-checks/bias-metrics.ts</title>
7
+ <meta charset="utf-8" />
8
+ <link rel="stylesheet" href="../../prettify.css" />
9
+ <link rel="stylesheet" href="../../base.css" />
10
+ <link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
11
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
12
+ <style type='text/css'>
13
+ .coverage-summary .sorter {
14
+ background-image: url(../../sort-arrow-sprite.png);
15
+ }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <div class='wrapper'>
21
+ <div class='pad1'>
22
+ <h1><a href="../../index.html">All files</a> / <a href="index.html">src/legal-checks</a> bias-metrics.ts</h1>
23
+ <div class='clearfix'>
24
+
25
+ <div class='fl pad1y space-right2'>
26
+ <span class="strong">24.79% </span>
27
+ <span class="quiet">Statements</span>
28
+ <span class='fraction'>92/371</span>
29
+ </div>
30
+
31
+
32
+ <div class='fl pad1y space-right2'>
33
+ <span class="strong">60% </span>
34
+ <span class="quiet">Branches</span>
35
+ <span class='fraction'>3/5</span>
36
+ </div>
37
+
38
+
39
+ <div class='fl pad1y space-right2'>
40
+ <span class="strong">13.33% </span>
41
+ <span class="quiet">Functions</span>
42
+ <span class='fraction'>2/15</span>
43
+ </div>
44
+
45
+
46
+ <div class='fl pad1y space-right2'>
47
+ <span class="strong">24.79% </span>
48
+ <span class="quiet">Lines</span>
49
+ <span class='fraction'>92/371</span>
50
+ </div>
51
+
52
+
53
+ </div>
54
+ <p class="quiet">
55
+ Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
56
+ </p>
57
+ <template id="filterTemplate">
58
+ <div class="quiet">
59
+ Filter:
60
+ <input type="search" id="fileSearch">
61
+ </div>
62
+ </template>
63
+ </div>
64
+ <div class='status-line low'></div>
65
+ <pre><table class="coverage">
66
+ <tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
67
+ <a name='L2'></a><a href='#L2'>2</a>
68
+ <a name='L3'></a><a href='#L3'>3</a>
69
+ <a name='L4'></a><a href='#L4'>4</a>
70
+ <a name='L5'></a><a href='#L5'>5</a>
71
+ <a name='L6'></a><a href='#L6'>6</a>
72
+ <a name='L7'></a><a href='#L7'>7</a>
73
+ <a name='L8'></a><a href='#L8'>8</a>
74
+ <a name='L9'></a><a href='#L9'>9</a>
75
+ <a name='L10'></a><a href='#L10'>10</a>
76
+ <a name='L11'></a><a href='#L11'>11</a>
77
+ <a name='L12'></a><a href='#L12'>12</a>
78
+ <a name='L13'></a><a href='#L13'>13</a>
79
+ <a name='L14'></a><a href='#L14'>14</a>
80
+ <a name='L15'></a><a href='#L15'>15</a>
81
+ <a name='L16'></a><a href='#L16'>16</a>
82
+ <a name='L17'></a><a href='#L17'>17</a>
83
+ <a name='L18'></a><a href='#L18'>18</a>
84
+ <a name='L19'></a><a href='#L19'>19</a>
85
+ <a name='L20'></a><a href='#L20'>20</a>
86
+ <a name='L21'></a><a href='#L21'>21</a>
87
+ <a name='L22'></a><a href='#L22'>22</a>
88
+ <a name='L23'></a><a href='#L23'>23</a>
89
+ <a name='L24'></a><a href='#L24'>24</a>
90
+ <a name='L25'></a><a href='#L25'>25</a>
91
+ <a name='L26'></a><a href='#L26'>26</a>
92
+ <a name='L27'></a><a href='#L27'>27</a>
93
+ <a name='L28'></a><a href='#L28'>28</a>
94
+ <a name='L29'></a><a href='#L29'>29</a>
95
+ <a name='L30'></a><a href='#L30'>30</a>
96
+ <a name='L31'></a><a href='#L31'>31</a>
97
+ <a name='L32'></a><a href='#L32'>32</a>
98
+ <a name='L33'></a><a href='#L33'>33</a>
99
+ <a name='L34'></a><a href='#L34'>34</a>
100
+ <a name='L35'></a><a href='#L35'>35</a>
101
+ <a name='L36'></a><a href='#L36'>36</a>
102
+ <a name='L37'></a><a href='#L37'>37</a>
103
+ <a name='L38'></a><a href='#L38'>38</a>
104
+ <a name='L39'></a><a href='#L39'>39</a>
105
+ <a name='L40'></a><a href='#L40'>40</a>
106
+ <a name='L41'></a><a href='#L41'>41</a>
107
+ <a name='L42'></a><a href='#L42'>42</a>
108
+ <a name='L43'></a><a href='#L43'>43</a>
109
+ <a name='L44'></a><a href='#L44'>44</a>
110
+ <a name='L45'></a><a href='#L45'>45</a>
111
+ <a name='L46'></a><a href='#L46'>46</a>
112
+ <a name='L47'></a><a href='#L47'>47</a>
113
+ <a name='L48'></a><a href='#L48'>48</a>
114
+ <a name='L49'></a><a href='#L49'>49</a>
115
+ <a name='L50'></a><a href='#L50'>50</a>
116
+ <a name='L51'></a><a href='#L51'>51</a>
117
+ <a name='L52'></a><a href='#L52'>52</a>
118
+ <a name='L53'></a><a href='#L53'>53</a>
119
+ <a name='L54'></a><a href='#L54'>54</a>
120
+ <a name='L55'></a><a href='#L55'>55</a>
121
+ <a name='L56'></a><a href='#L56'>56</a>
122
+ <a name='L57'></a><a href='#L57'>57</a>
123
+ <a name='L58'></a><a href='#L58'>58</a>
124
+ <a name='L59'></a><a href='#L59'>59</a>
125
+ <a name='L60'></a><a href='#L60'>60</a>
126
+ <a name='L61'></a><a href='#L61'>61</a>
127
+ <a name='L62'></a><a href='#L62'>62</a>
128
+ <a name='L63'></a><a href='#L63'>63</a>
129
+ <a name='L64'></a><a href='#L64'>64</a>
130
+ <a name='L65'></a><a href='#L65'>65</a>
131
+ <a name='L66'></a><a href='#L66'>66</a>
132
+ <a name='L67'></a><a href='#L67'>67</a>
133
+ <a name='L68'></a><a href='#L68'>68</a>
134
+ <a name='L69'></a><a href='#L69'>69</a>
135
+ <a name='L70'></a><a href='#L70'>70</a>
136
+ <a name='L71'></a><a href='#L71'>71</a>
137
+ <a name='L72'></a><a href='#L72'>72</a>
138
+ <a name='L73'></a><a href='#L73'>73</a>
139
+ <a name='L74'></a><a href='#L74'>74</a>
140
+ <a name='L75'></a><a href='#L75'>75</a>
141
+ <a name='L76'></a><a href='#L76'>76</a>
142
+ <a name='L77'></a><a href='#L77'>77</a>
143
+ <a name='L78'></a><a href='#L78'>78</a>
144
+ <a name='L79'></a><a href='#L79'>79</a>
145
+ <a name='L80'></a><a href='#L80'>80</a>
146
+ <a name='L81'></a><a href='#L81'>81</a>
147
+ <a name='L82'></a><a href='#L82'>82</a>
148
+ <a name='L83'></a><a href='#L83'>83</a>
149
+ <a name='L84'></a><a href='#L84'>84</a>
150
+ <a name='L85'></a><a href='#L85'>85</a>
151
+ <a name='L86'></a><a href='#L86'>86</a>
152
+ <a name='L87'></a><a href='#L87'>87</a>
153
+ <a name='L88'></a><a href='#L88'>88</a>
154
+ <a name='L89'></a><a href='#L89'>89</a>
155
+ <a name='L90'></a><a href='#L90'>90</a>
156
+ <a name='L91'></a><a href='#L91'>91</a>
157
+ <a name='L92'></a><a href='#L92'>92</a>
158
+ <a name='L93'></a><a href='#L93'>93</a>
159
+ <a name='L94'></a><a href='#L94'>94</a>
160
+ <a name='L95'></a><a href='#L95'>95</a>
161
+ <a name='L96'></a><a href='#L96'>96</a>
162
+ <a name='L97'></a><a href='#L97'>97</a>
163
+ <a name='L98'></a><a href='#L98'>98</a>
164
+ <a name='L99'></a><a href='#L99'>99</a>
165
+ <a name='L100'></a><a href='#L100'>100</a>
166
+ <a name='L101'></a><a href='#L101'>101</a>
167
+ <a name='L102'></a><a href='#L102'>102</a>
168
+ <a name='L103'></a><a href='#L103'>103</a>
169
+ <a name='L104'></a><a href='#L104'>104</a>
170
+ <a name='L105'></a><a href='#L105'>105</a>
171
+ <a name='L106'></a><a href='#L106'>106</a>
172
+ <a name='L107'></a><a href='#L107'>107</a>
173
+ <a name='L108'></a><a href='#L108'>108</a>
174
+ <a name='L109'></a><a href='#L109'>109</a>
175
+ <a name='L110'></a><a href='#L110'>110</a>
176
+ <a name='L111'></a><a href='#L111'>111</a>
177
+ <a name='L112'></a><a href='#L112'>112</a>
178
+ <a name='L113'></a><a href='#L113'>113</a>
179
+ <a name='L114'></a><a href='#L114'>114</a>
180
+ <a name='L115'></a><a href='#L115'>115</a>
181
+ <a name='L116'></a><a href='#L116'>116</a>
182
+ <a name='L117'></a><a href='#L117'>117</a>
183
+ <a name='L118'></a><a href='#L118'>118</a>
184
+ <a name='L119'></a><a href='#L119'>119</a>
185
+ <a name='L120'></a><a href='#L120'>120</a>
186
+ <a name='L121'></a><a href='#L121'>121</a>
187
+ <a name='L122'></a><a href='#L122'>122</a>
188
+ <a name='L123'></a><a href='#L123'>123</a>
189
+ <a name='L124'></a><a href='#L124'>124</a>
190
+ <a name='L125'></a><a href='#L125'>125</a>
191
+ <a name='L126'></a><a href='#L126'>126</a>
192
+ <a name='L127'></a><a href='#L127'>127</a>
193
+ <a name='L128'></a><a href='#L128'>128</a>
194
+ <a name='L129'></a><a href='#L129'>129</a>
195
+ <a name='L130'></a><a href='#L130'>130</a>
196
+ <a name='L131'></a><a href='#L131'>131</a>
197
+ <a name='L132'></a><a href='#L132'>132</a>
198
+ <a name='L133'></a><a href='#L133'>133</a>
199
+ <a name='L134'></a><a href='#L134'>134</a>
200
+ <a name='L135'></a><a href='#L135'>135</a>
201
+ <a name='L136'></a><a href='#L136'>136</a>
202
+ <a name='L137'></a><a href='#L137'>137</a>
203
+ <a name='L138'></a><a href='#L138'>138</a>
204
+ <a name='L139'></a><a href='#L139'>139</a>
205
+ <a name='L140'></a><a href='#L140'>140</a>
206
+ <a name='L141'></a><a href='#L141'>141</a>
207
+ <a name='L142'></a><a href='#L142'>142</a>
208
+ <a name='L143'></a><a href='#L143'>143</a>
209
+ <a name='L144'></a><a href='#L144'>144</a>
210
+ <a name='L145'></a><a href='#L145'>145</a>
211
+ <a name='L146'></a><a href='#L146'>146</a>
212
+ <a name='L147'></a><a href='#L147'>147</a>
213
+ <a name='L148'></a><a href='#L148'>148</a>
214
+ <a name='L149'></a><a href='#L149'>149</a>
215
+ <a name='L150'></a><a href='#L150'>150</a>
216
+ <a name='L151'></a><a href='#L151'>151</a>
217
+ <a name='L152'></a><a href='#L152'>152</a>
218
+ <a name='L153'></a><a href='#L153'>153</a>
219
+ <a name='L154'></a><a href='#L154'>154</a>
220
+ <a name='L155'></a><a href='#L155'>155</a>
221
+ <a name='L156'></a><a href='#L156'>156</a>
222
+ <a name='L157'></a><a href='#L157'>157</a>
223
+ <a name='L158'></a><a href='#L158'>158</a>
224
+ <a name='L159'></a><a href='#L159'>159</a>
225
+ <a name='L160'></a><a href='#L160'>160</a>
226
+ <a name='L161'></a><a href='#L161'>161</a>
227
+ <a name='L162'></a><a href='#L162'>162</a>
228
+ <a name='L163'></a><a href='#L163'>163</a>
229
+ <a name='L164'></a><a href='#L164'>164</a>
230
+ <a name='L165'></a><a href='#L165'>165</a>
231
+ <a name='L166'></a><a href='#L166'>166</a>
232
+ <a name='L167'></a><a href='#L167'>167</a>
233
+ <a name='L168'></a><a href='#L168'>168</a>
234
+ <a name='L169'></a><a href='#L169'>169</a>
235
+ <a name='L170'></a><a href='#L170'>170</a>
236
+ <a name='L171'></a><a href='#L171'>171</a>
237
+ <a name='L172'></a><a href='#L172'>172</a>
238
+ <a name='L173'></a><a href='#L173'>173</a>
239
+ <a name='L174'></a><a href='#L174'>174</a>
240
+ <a name='L175'></a><a href='#L175'>175</a>
241
+ <a name='L176'></a><a href='#L176'>176</a>
242
+ <a name='L177'></a><a href='#L177'>177</a>
243
+ <a name='L178'></a><a href='#L178'>178</a>
244
+ <a name='L179'></a><a href='#L179'>179</a>
245
+ <a name='L180'></a><a href='#L180'>180</a>
246
+ <a name='L181'></a><a href='#L181'>181</a>
247
+ <a name='L182'></a><a href='#L182'>182</a>
248
+ <a name='L183'></a><a href='#L183'>183</a>
249
+ <a name='L184'></a><a href='#L184'>184</a>
250
+ <a name='L185'></a><a href='#L185'>185</a>
251
+ <a name='L186'></a><a href='#L186'>186</a>
252
+ <a name='L187'></a><a href='#L187'>187</a>
253
+ <a name='L188'></a><a href='#L188'>188</a>
254
+ <a name='L189'></a><a href='#L189'>189</a>
255
+ <a name='L190'></a><a href='#L190'>190</a>
256
+ <a name='L191'></a><a href='#L191'>191</a>
257
+ <a name='L192'></a><a href='#L192'>192</a>
258
+ <a name='L193'></a><a href='#L193'>193</a>
259
+ <a name='L194'></a><a href='#L194'>194</a>
260
+ <a name='L195'></a><a href='#L195'>195</a>
261
+ <a name='L196'></a><a href='#L196'>196</a>
262
+ <a name='L197'></a><a href='#L197'>197</a>
263
+ <a name='L198'></a><a href='#L198'>198</a>
264
+ <a name='L199'></a><a href='#L199'>199</a>
265
+ <a name='L200'></a><a href='#L200'>200</a>
266
+ <a name='L201'></a><a href='#L201'>201</a>
267
+ <a name='L202'></a><a href='#L202'>202</a>
268
+ <a name='L203'></a><a href='#L203'>203</a>
269
+ <a name='L204'></a><a href='#L204'>204</a>
270
+ <a name='L205'></a><a href='#L205'>205</a>
271
+ <a name='L206'></a><a href='#L206'>206</a>
272
+ <a name='L207'></a><a href='#L207'>207</a>
273
+ <a name='L208'></a><a href='#L208'>208</a>
274
+ <a name='L209'></a><a href='#L209'>209</a>
275
+ <a name='L210'></a><a href='#L210'>210</a>
276
+ <a name='L211'></a><a href='#L211'>211</a>
277
+ <a name='L212'></a><a href='#L212'>212</a>
278
+ <a name='L213'></a><a href='#L213'>213</a>
279
+ <a name='L214'></a><a href='#L214'>214</a>
280
+ <a name='L215'></a><a href='#L215'>215</a>
281
+ <a name='L216'></a><a href='#L216'>216</a>
282
+ <a name='L217'></a><a href='#L217'>217</a>
283
+ <a name='L218'></a><a href='#L218'>218</a>
284
+ <a name='L219'></a><a href='#L219'>219</a>
285
+ <a name='L220'></a><a href='#L220'>220</a>
286
+ <a name='L221'></a><a href='#L221'>221</a>
287
+ <a name='L222'></a><a href='#L222'>222</a>
288
+ <a name='L223'></a><a href='#L223'>223</a>
289
+ <a name='L224'></a><a href='#L224'>224</a>
290
+ <a name='L225'></a><a href='#L225'>225</a>
291
+ <a name='L226'></a><a href='#L226'>226</a>
292
+ <a name='L227'></a><a href='#L227'>227</a>
293
+ <a name='L228'></a><a href='#L228'>228</a>
294
+ <a name='L229'></a><a href='#L229'>229</a>
295
+ <a name='L230'></a><a href='#L230'>230</a>
296
+ <a name='L231'></a><a href='#L231'>231</a>
297
+ <a name='L232'></a><a href='#L232'>232</a>
298
+ <a name='L233'></a><a href='#L233'>233</a>
299
+ <a name='L234'></a><a href='#L234'>234</a>
300
+ <a name='L235'></a><a href='#L235'>235</a>
301
+ <a name='L236'></a><a href='#L236'>236</a>
302
+ <a name='L237'></a><a href='#L237'>237</a>
303
+ <a name='L238'></a><a href='#L238'>238</a>
304
+ <a name='L239'></a><a href='#L239'>239</a>
305
+ <a name='L240'></a><a href='#L240'>240</a>
306
+ <a name='L241'></a><a href='#L241'>241</a>
307
+ <a name='L242'></a><a href='#L242'>242</a>
308
+ <a name='L243'></a><a href='#L243'>243</a>
309
+ <a name='L244'></a><a href='#L244'>244</a>
310
+ <a name='L245'></a><a href='#L245'>245</a>
311
+ <a name='L246'></a><a href='#L246'>246</a>
312
+ <a name='L247'></a><a href='#L247'>247</a>
313
+ <a name='L248'></a><a href='#L248'>248</a>
314
+ <a name='L249'></a><a href='#L249'>249</a>
315
+ <a name='L250'></a><a href='#L250'>250</a>
316
+ <a name='L251'></a><a href='#L251'>251</a>
317
+ <a name='L252'></a><a href='#L252'>252</a>
318
+ <a name='L253'></a><a href='#L253'>253</a>
319
+ <a name='L254'></a><a href='#L254'>254</a>
320
+ <a name='L255'></a><a href='#L255'>255</a>
321
+ <a name='L256'></a><a href='#L256'>256</a>
322
+ <a name='L257'></a><a href='#L257'>257</a>
323
+ <a name='L258'></a><a href='#L258'>258</a>
324
+ <a name='L259'></a><a href='#L259'>259</a>
325
+ <a name='L260'></a><a href='#L260'>260</a>
326
+ <a name='L261'></a><a href='#L261'>261</a>
327
+ <a name='L262'></a><a href='#L262'>262</a>
328
+ <a name='L263'></a><a href='#L263'>263</a>
329
+ <a name='L264'></a><a href='#L264'>264</a>
330
+ <a name='L265'></a><a href='#L265'>265</a>
331
+ <a name='L266'></a><a href='#L266'>266</a>
332
+ <a name='L267'></a><a href='#L267'>267</a>
333
+ <a name='L268'></a><a href='#L268'>268</a>
334
+ <a name='L269'></a><a href='#L269'>269</a>
335
+ <a name='L270'></a><a href='#L270'>270</a>
336
+ <a name='L271'></a><a href='#L271'>271</a>
337
+ <a name='L272'></a><a href='#L272'>272</a>
338
+ <a name='L273'></a><a href='#L273'>273</a>
339
+ <a name='L274'></a><a href='#L274'>274</a>
340
+ <a name='L275'></a><a href='#L275'>275</a>
341
+ <a name='L276'></a><a href='#L276'>276</a>
342
+ <a name='L277'></a><a href='#L277'>277</a>
343
+ <a name='L278'></a><a href='#L278'>278</a>
344
+ <a name='L279'></a><a href='#L279'>279</a>
345
+ <a name='L280'></a><a href='#L280'>280</a>
346
+ <a name='L281'></a><a href='#L281'>281</a>
347
+ <a name='L282'></a><a href='#L282'>282</a>
348
+ <a name='L283'></a><a href='#L283'>283</a>
349
+ <a name='L284'></a><a href='#L284'>284</a>
350
+ <a name='L285'></a><a href='#L285'>285</a>
351
+ <a name='L286'></a><a href='#L286'>286</a>
352
+ <a name='L287'></a><a href='#L287'>287</a>
353
+ <a name='L288'></a><a href='#L288'>288</a>
354
+ <a name='L289'></a><a href='#L289'>289</a>
355
+ <a name='L290'></a><a href='#L290'>290</a>
356
+ <a name='L291'></a><a href='#L291'>291</a>
357
+ <a name='L292'></a><a href='#L292'>292</a>
358
+ <a name='L293'></a><a href='#L293'>293</a>
359
+ <a name='L294'></a><a href='#L294'>294</a>
360
+ <a name='L295'></a><a href='#L295'>295</a>
361
+ <a name='L296'></a><a href='#L296'>296</a>
362
+ <a name='L297'></a><a href='#L297'>297</a>
363
+ <a name='L298'></a><a href='#L298'>298</a>
364
+ <a name='L299'></a><a href='#L299'>299</a>
365
+ <a name='L300'></a><a href='#L300'>300</a>
366
+ <a name='L301'></a><a href='#L301'>301</a>
367
+ <a name='L302'></a><a href='#L302'>302</a>
368
+ <a name='L303'></a><a href='#L303'>303</a>
369
+ <a name='L304'></a><a href='#L304'>304</a>
370
+ <a name='L305'></a><a href='#L305'>305</a>
371
+ <a name='L306'></a><a href='#L306'>306</a>
372
+ <a name='L307'></a><a href='#L307'>307</a>
373
+ <a name='L308'></a><a href='#L308'>308</a>
374
+ <a name='L309'></a><a href='#L309'>309</a>
375
+ <a name='L310'></a><a href='#L310'>310</a>
376
+ <a name='L311'></a><a href='#L311'>311</a>
377
+ <a name='L312'></a><a href='#L312'>312</a>
378
+ <a name='L313'></a><a href='#L313'>313</a>
379
+ <a name='L314'></a><a href='#L314'>314</a>
380
+ <a name='L315'></a><a href='#L315'>315</a>
381
+ <a name='L316'></a><a href='#L316'>316</a>
382
+ <a name='L317'></a><a href='#L317'>317</a>
383
+ <a name='L318'></a><a href='#L318'>318</a>
384
+ <a name='L319'></a><a href='#L319'>319</a>
385
+ <a name='L320'></a><a href='#L320'>320</a>
386
+ <a name='L321'></a><a href='#L321'>321</a>
387
+ <a name='L322'></a><a href='#L322'>322</a>
388
+ <a name='L323'></a><a href='#L323'>323</a>
389
+ <a name='L324'></a><a href='#L324'>324</a>
390
+ <a name='L325'></a><a href='#L325'>325</a>
391
+ <a name='L326'></a><a href='#L326'>326</a>
392
+ <a name='L327'></a><a href='#L327'>327</a>
393
+ <a name='L328'></a><a href='#L328'>328</a>
394
+ <a name='L329'></a><a href='#L329'>329</a>
395
+ <a name='L330'></a><a href='#L330'>330</a>
396
+ <a name='L331'></a><a href='#L331'>331</a>
397
+ <a name='L332'></a><a href='#L332'>332</a>
398
+ <a name='L333'></a><a href='#L333'>333</a>
399
+ <a name='L334'></a><a href='#L334'>334</a>
400
+ <a name='L335'></a><a href='#L335'>335</a>
401
+ <a name='L336'></a><a href='#L336'>336</a>
402
+ <a name='L337'></a><a href='#L337'>337</a>
403
+ <a name='L338'></a><a href='#L338'>338</a>
404
+ <a name='L339'></a><a href='#L339'>339</a>
405
+ <a name='L340'></a><a href='#L340'>340</a>
406
+ <a name='L341'></a><a href='#L341'>341</a>
407
+ <a name='L342'></a><a href='#L342'>342</a>
408
+ <a name='L343'></a><a href='#L343'>343</a>
409
+ <a name='L344'></a><a href='#L344'>344</a>
410
+ <a name='L345'></a><a href='#L345'>345</a>
411
+ <a name='L346'></a><a href='#L346'>346</a>
412
+ <a name='L347'></a><a href='#L347'>347</a>
413
+ <a name='L348'></a><a href='#L348'>348</a>
414
+ <a name='L349'></a><a href='#L349'>349</a>
415
+ <a name='L350'></a><a href='#L350'>350</a>
416
+ <a name='L351'></a><a href='#L351'>351</a>
417
+ <a name='L352'></a><a href='#L352'>352</a>
418
+ <a name='L353'></a><a href='#L353'>353</a>
419
+ <a name='L354'></a><a href='#L354'>354</a>
420
+ <a name='L355'></a><a href='#L355'>355</a>
421
+ <a name='L356'></a><a href='#L356'>356</a>
422
+ <a name='L357'></a><a href='#L357'>357</a>
423
+ <a name='L358'></a><a href='#L358'>358</a>
424
+ <a name='L359'></a><a href='#L359'>359</a>
425
+ <a name='L360'></a><a href='#L360'>360</a>
426
+ <a name='L361'></a><a href='#L361'>361</a>
427
+ <a name='L362'></a><a href='#L362'>362</a>
428
+ <a name='L363'></a><a href='#L363'>363</a>
429
+ <a name='L364'></a><a href='#L364'>364</a>
430
+ <a name='L365'></a><a href='#L365'>365</a>
431
+ <a name='L366'></a><a href='#L366'>366</a>
432
+ <a name='L367'></a><a href='#L367'>367</a>
433
+ <a name='L368'></a><a href='#L368'>368</a>
434
+ <a name='L369'></a><a href='#L369'>369</a>
435
+ <a name='L370'></a><a href='#L370'>370</a>
436
+ <a name='L371'></a><a href='#L371'>371</a>
437
+ <a name='L372'></a><a href='#L372'>372</a>
438
+ <a name='L373'></a><a href='#L373'>373</a>
439
+ <a name='L374'></a><a href='#L374'>374</a>
440
+ <a name='L375'></a><a href='#L375'>375</a>
441
+ <a name='L376'></a><a href='#L376'>376</a>
442
+ <a name='L377'></a><a href='#L377'>377</a>
443
+ <a name='L378'></a><a href='#L378'>378</a>
444
+ <a name='L379'></a><a href='#L379'>379</a>
445
+ <a name='L380'></a><a href='#L380'>380</a>
446
+ <a name='L381'></a><a href='#L381'>381</a>
447
+ <a name='L382'></a><a href='#L382'>382</a>
448
+ <a name='L383'></a><a href='#L383'>383</a>
449
+ <a name='L384'></a><a href='#L384'>384</a>
450
+ <a name='L385'></a><a href='#L385'>385</a>
451
+ <a name='L386'></a><a href='#L386'>386</a>
452
+ <a name='L387'></a><a href='#L387'>387</a>
453
+ <a name='L388'></a><a href='#L388'>388</a>
454
+ <a name='L389'></a><a href='#L389'>389</a>
455
+ <a name='L390'></a><a href='#L390'>390</a>
456
+ <a name='L391'></a><a href='#L391'>391</a>
457
+ <a name='L392'></a><a href='#L392'>392</a>
458
+ <a name='L393'></a><a href='#L393'>393</a>
459
+ <a name='L394'></a><a href='#L394'>394</a>
460
+ <a name='L395'></a><a href='#L395'>395</a>
461
+ <a name='L396'></a><a href='#L396'>396</a>
462
+ <a name='L397'></a><a href='#L397'>397</a>
463
+ <a name='L398'></a><a href='#L398'>398</a>
464
+ <a name='L399'></a><a href='#L399'>399</a>
465
+ <a name='L400'></a><a href='#L400'>400</a>
466
+ <a name='L401'></a><a href='#L401'>401</a>
467
+ <a name='L402'></a><a href='#L402'>402</a>
468
+ <a name='L403'></a><a href='#L403'>403</a>
469
+ <a name='L404'></a><a href='#L404'>404</a>
470
+ <a name='L405'></a><a href='#L405'>405</a>
471
+ <a name='L406'></a><a href='#L406'>406</a>
472
+ <a name='L407'></a><a href='#L407'>407</a>
473
+ <a name='L408'></a><a href='#L408'>408</a>
474
+ <a name='L409'></a><a href='#L409'>409</a>
475
+ <a name='L410'></a><a href='#L410'>410</a>
476
+ <a name='L411'></a><a href='#L411'>411</a>
477
+ <a name='L412'></a><a href='#L412'>412</a>
478
+ <a name='L413'></a><a href='#L413'>413</a>
479
+ <a name='L414'></a><a href='#L414'>414</a>
480
+ <a name='L415'></a><a href='#L415'>415</a>
481
+ <a name='L416'></a><a href='#L416'>416</a>
482
+ <a name='L417'></a><a href='#L417'>417</a>
483
+ <a name='L418'></a><a href='#L418'>418</a>
484
+ <a name='L419'></a><a href='#L419'>419</a>
485
+ <a name='L420'></a><a href='#L420'>420</a>
486
+ <a name='L421'></a><a href='#L421'>421</a>
487
+ <a name='L422'></a><a href='#L422'>422</a>
488
+ <a name='L423'></a><a href='#L423'>423</a>
489
+ <a name='L424'></a><a href='#L424'>424</a>
490
+ <a name='L425'></a><a href='#L425'>425</a>
491
+ <a name='L426'></a><a href='#L426'>426</a>
492
+ <a name='L427'></a><a href='#L427'>427</a>
493
+ <a name='L428'></a><a href='#L428'>428</a>
494
+ <a name='L429'></a><a href='#L429'>429</a>
495
+ <a name='L430'></a><a href='#L430'>430</a>
496
+ <a name='L431'></a><a href='#L431'>431</a>
497
+ <a name='L432'></a><a href='#L432'>432</a>
498
+ <a name='L433'></a><a href='#L433'>433</a>
499
+ <a name='L434'></a><a href='#L434'>434</a>
500
+ <a name='L435'></a><a href='#L435'>435</a>
501
+ <a name='L436'></a><a href='#L436'>436</a>
502
+ <a name='L437'></a><a href='#L437'>437</a>
503
+ <a name='L438'></a><a href='#L438'>438</a>
504
+ <a name='L439'></a><a href='#L439'>439</a>
505
+ <a name='L440'></a><a href='#L440'>440</a>
506
+ <a name='L441'></a><a href='#L441'>441</a>
507
+ <a name='L442'></a><a href='#L442'>442</a>
508
+ <a name='L443'></a><a href='#L443'>443</a>
509
+ <a name='L444'></a><a href='#L444'>444</a>
510
+ <a name='L445'></a><a href='#L445'>445</a>
511
+ <a name='L446'></a><a href='#L446'>446</a>
512
+ <a name='L447'></a><a href='#L447'>447</a>
513
+ <a name='L448'></a><a href='#L448'>448</a>
514
+ <a name='L449'></a><a href='#L449'>449</a>
515
+ <a name='L450'></a><a href='#L450'>450</a>
516
+ <a name='L451'></a><a href='#L451'>451</a>
517
+ <a name='L452'></a><a href='#L452'>452</a>
518
+ <a name='L453'></a><a href='#L453'>453</a>
519
+ <a name='L454'></a><a href='#L454'>454</a>
520
+ <a name='L455'></a><a href='#L455'>455</a>
521
+ <a name='L456'></a><a href='#L456'>456</a>
522
+ <a name='L457'></a><a href='#L457'>457</a>
523
+ <a name='L458'></a><a href='#L458'>458</a>
524
+ <a name='L459'></a><a href='#L459'>459</a>
525
+ <a name='L460'></a><a href='#L460'>460</a>
526
+ <a name='L461'></a><a href='#L461'>461</a>
527
+ <a name='L462'></a><a href='#L462'>462</a>
528
+ <a name='L463'></a><a href='#L463'>463</a>
529
+ <a name='L464'></a><a href='#L464'>464</a>
530
+ <a name='L465'></a><a href='#L465'>465</a>
531
+ <a name='L466'></a><a href='#L466'>466</a>
532
+ <a name='L467'></a><a href='#L467'>467</a>
533
+ <a name='L468'></a><a href='#L468'>468</a>
534
+ <a name='L469'></a><a href='#L469'>469</a>
535
+ <a name='L470'></a><a href='#L470'>470</a>
536
+ <a name='L471'></a><a href='#L471'>471</a>
537
+ <a name='L472'></a><a href='#L472'>472</a>
538
+ <a name='L473'></a><a href='#L473'>473</a>
539
+ <a name='L474'></a><a href='#L474'>474</a>
540
+ <a name='L475'></a><a href='#L475'>475</a>
541
+ <a name='L476'></a><a href='#L476'>476</a>
542
+ <a name='L477'></a><a href='#L477'>477</a>
543
+ <a name='L478'></a><a href='#L478'>478</a>
544
+ <a name='L479'></a><a href='#L479'>479</a>
545
+ <a name='L480'></a><a href='#L480'>480</a>
546
+ <a name='L481'></a><a href='#L481'>481</a>
547
+ <a name='L482'></a><a href='#L482'>482</a>
548
+ <a name='L483'></a><a href='#L483'>483</a>
549
+ <a name='L484'></a><a href='#L484'>484</a>
550
+ <a name='L485'></a><a href='#L485'>485</a>
551
+ <a name='L486'></a><a href='#L486'>486</a>
552
+ <a name='L487'></a><a href='#L487'>487</a>
553
+ <a name='L488'></a><a href='#L488'>488</a>
554
+ <a name='L489'></a><a href='#L489'>489</a>
555
+ <a name='L490'></a><a href='#L490'>490</a>
556
+ <a name='L491'></a><a href='#L491'>491</a>
557
+ <a name='L492'></a><a href='#L492'>492</a>
558
+ <a name='L493'></a><a href='#L493'>493</a>
559
+ <a name='L494'></a><a href='#L494'>494</a>
560
+ <a name='L495'></a><a href='#L495'>495</a>
561
+ <a name='L496'></a><a href='#L496'>496</a>
562
+ <a name='L497'></a><a href='#L497'>497</a>
563
+ <a name='L498'></a><a href='#L498'>498</a>
564
+ <a name='L499'></a><a href='#L499'>499</a>
565
+ <a name='L500'></a><a href='#L500'>500</a>
566
+ <a name='L501'></a><a href='#L501'>501</a>
567
+ <a name='L502'></a><a href='#L502'>502</a>
568
+ <a name='L503'></a><a href='#L503'>503</a>
569
+ <a name='L504'></a><a href='#L504'>504</a>
570
+ <a name='L505'></a><a href='#L505'>505</a>
571
+ <a name='L506'></a><a href='#L506'>506</a>
572
+ <a name='L507'></a><a href='#L507'>507</a>
573
+ <a name='L508'></a><a href='#L508'>508</a>
574
+ <a name='L509'></a><a href='#L509'>509</a>
575
+ <a name='L510'></a><a href='#L510'>510</a>
576
+ <a name='L511'></a><a href='#L511'>511</a>
577
+ <a name='L512'></a><a href='#L512'>512</a>
578
+ <a name='L513'></a><a href='#L513'>513</a>
579
+ <a name='L514'></a><a href='#L514'>514</a>
580
+ <a name='L515'></a><a href='#L515'>515</a>
581
+ <a name='L516'></a><a href='#L516'>516</a>
582
+ <a name='L517'></a><a href='#L517'>517</a>
583
+ <a name='L518'></a><a href='#L518'>518</a>
584
+ <a name='L519'></a><a href='#L519'>519</a>
585
+ <a name='L520'></a><a href='#L520'>520</a>
586
+ <a name='L521'></a><a href='#L521'>521</a>
587
+ <a name='L522'></a><a href='#L522'>522</a>
588
+ <a name='L523'></a><a href='#L523'>523</a>
589
+ <a name='L524'></a><a href='#L524'>524</a>
590
+ <a name='L525'></a><a href='#L525'>525</a>
591
+ <a name='L526'></a><a href='#L526'>526</a>
592
+ <a name='L527'></a><a href='#L527'>527</a>
593
+ <a name='L528'></a><a href='#L528'>528</a>
594
+ <a name='L529'></a><a href='#L529'>529</a>
595
+ <a name='L530'></a><a href='#L530'>530</a>
596
+ <a name='L531'></a><a href='#L531'>531</a>
597
+ <a name='L532'></a><a href='#L532'>532</a>
598
+ <a name='L533'></a><a href='#L533'>533</a>
599
+ <a name='L534'></a><a href='#L534'>534</a>
600
+ <a name='L535'></a><a href='#L535'>535</a>
601
+ <a name='L536'></a><a href='#L536'>536</a>
602
+ <a name='L537'></a><a href='#L537'>537</a>
603
+ <a name='L538'></a><a href='#L538'>538</a>
604
+ <a name='L539'></a><a href='#L539'>539</a>
605
+ <a name='L540'></a><a href='#L540'>540</a>
606
+ <a name='L541'></a><a href='#L541'>541</a>
607
+ <a name='L542'></a><a href='#L542'>542</a>
608
+ <a name='L543'></a><a href='#L543'>543</a>
609
+ <a name='L544'></a><a href='#L544'>544</a>
610
+ <a name='L545'></a><a href='#L545'>545</a>
611
+ <a name='L546'></a><a href='#L546'>546</a>
612
+ <a name='L547'></a><a href='#L547'>547</a>
613
+ <a name='L548'></a><a href='#L548'>548</a>
614
+ <a name='L549'></a><a href='#L549'>549</a>
615
+ <a name='L550'></a><a href='#L550'>550</a>
616
+ <a name='L551'></a><a href='#L551'>551</a>
617
+ <a name='L552'></a><a href='#L552'>552</a>
618
+ <a name='L553'></a><a href='#L553'>553</a>
619
+ <a name='L554'></a><a href='#L554'>554</a>
620
+ <a name='L555'></a><a href='#L555'>555</a>
621
+ <a name='L556'></a><a href='#L556'>556</a>
622
+ <a name='L557'></a><a href='#L557'>557</a>
623
+ <a name='L558'></a><a href='#L558'>558</a>
624
+ <a name='L559'></a><a href='#L559'>559</a>
625
+ <a name='L560'></a><a href='#L560'>560</a>
626
+ <a name='L561'></a><a href='#L561'>561</a>
627
+ <a name='L562'></a><a href='#L562'>562</a>
628
+ <a name='L563'></a><a href='#L563'>563</a>
629
+ <a name='L564'></a><a href='#L564'>564</a>
630
+ <a name='L565'></a><a href='#L565'>565</a>
631
+ <a name='L566'></a><a href='#L566'>566</a>
632
+ <a name='L567'></a><a href='#L567'>567</a>
633
+ <a name='L568'></a><a href='#L568'>568</a>
634
+ <a name='L569'></a><a href='#L569'>569</a>
635
+ <a name='L570'></a><a href='#L570'>570</a>
636
+ <a name='L571'></a><a href='#L571'>571</a>
637
+ <a name='L572'></a><a href='#L572'>572</a>
638
+ <a name='L573'></a><a href='#L573'>573</a>
639
+ <a name='L574'></a><a href='#L574'>574</a>
640
+ <a name='L575'></a><a href='#L575'>575</a>
641
+ <a name='L576'></a><a href='#L576'>576</a>
642
+ <a name='L577'></a><a href='#L577'>577</a>
643
+ <a name='L578'></a><a href='#L578'>578</a>
644
+ <a name='L579'></a><a href='#L579'>579</a>
645
+ <a name='L580'></a><a href='#L580'>580</a>
646
+ <a name='L581'></a><a href='#L581'>581</a>
647
+ <a name='L582'></a><a href='#L582'>582</a>
648
+ <a name='L583'></a><a href='#L583'>583</a>
649
+ <a name='L584'></a><a href='#L584'>584</a>
650
+ <a name='L585'></a><a href='#L585'>585</a>
651
+ <a name='L586'></a><a href='#L586'>586</a>
652
+ <a name='L587'></a><a href='#L587'>587</a>
653
+ <a name='L588'></a><a href='#L588'>588</a>
654
+ <a name='L589'></a><a href='#L589'>589</a>
655
+ <a name='L590'></a><a href='#L590'>590</a>
656
+ <a name='L591'></a><a href='#L591'>591</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">1x</span>
657
+ <span class="cline-any cline-neutral">&nbsp;</span>
658
+ <span class="cline-any cline-neutral">&nbsp;</span>
659
+ <span class="cline-any cline-neutral">&nbsp;</span>
660
+ <span class="cline-any cline-neutral">&nbsp;</span>
661
+ <span class="cline-any cline-neutral">&nbsp;</span>
662
+ <span class="cline-any cline-neutral">&nbsp;</span>
663
+ <span class="cline-any cline-neutral">&nbsp;</span>
664
+ <span class="cline-any cline-neutral">&nbsp;</span>
665
+ <span class="cline-any cline-neutral">&nbsp;</span>
666
+ <span class="cline-any cline-neutral">&nbsp;</span>
667
+ <span class="cline-any cline-neutral">&nbsp;</span>
668
+ <span class="cline-any cline-neutral">&nbsp;</span>
669
+ <span class="cline-any cline-neutral">&nbsp;</span>
670
+ <span class="cline-any cline-neutral">&nbsp;</span>
671
+ <span class="cline-any cline-neutral">&nbsp;</span>
672
+ <span class="cline-any cline-neutral">&nbsp;</span>
673
+ <span class="cline-any cline-neutral">&nbsp;</span>
674
+ <span class="cline-any cline-neutral">&nbsp;</span>
675
+ <span class="cline-any cline-neutral">&nbsp;</span>
676
+ <span class="cline-any cline-neutral">&nbsp;</span>
677
+ <span class="cline-any cline-neutral">&nbsp;</span>
678
+ <span class="cline-any cline-neutral">&nbsp;</span>
679
+ <span class="cline-any cline-neutral">&nbsp;</span>
680
+ <span class="cline-any cline-neutral">&nbsp;</span>
681
+ <span class="cline-any cline-neutral">&nbsp;</span>
682
+ <span class="cline-any cline-neutral">&nbsp;</span>
683
+ <span class="cline-any cline-neutral">&nbsp;</span>
684
+ <span class="cline-any cline-neutral">&nbsp;</span>
685
+ <span class="cline-any cline-neutral">&nbsp;</span>
686
+ <span class="cline-any cline-yes">1x</span>
687
+ <span class="cline-any cline-yes">1x</span>
688
+ <span class="cline-any cline-yes">1x</span>
689
+ <span class="cline-any cline-yes">1x</span>
690
+ <span class="cline-any cline-yes">1x</span>
691
+ <span class="cline-any cline-yes">1x</span>
692
+ <span class="cline-any cline-yes">1x</span>
693
+ <span class="cline-any cline-yes">1x</span>
694
+ <span class="cline-any cline-yes">1x</span>
695
+ <span class="cline-any cline-yes">1x</span>
696
+ <span class="cline-any cline-yes">1x</span>
697
+ <span class="cline-any cline-yes">1x</span>
698
+ <span class="cline-any cline-neutral">&nbsp;</span>
699
+ <span class="cline-any cline-yes">1x</span>
700
+ <span class="cline-any cline-yes">1x</span>
701
+ <span class="cline-any cline-yes">1x</span>
702
+ <span class="cline-any cline-yes">1x</span>
703
+ <span class="cline-any cline-yes">1x</span>
704
+ <span class="cline-any cline-yes">1x</span>
705
+ <span class="cline-any cline-yes">1x</span>
706
+ <span class="cline-any cline-yes">1x</span>
707
+ <span class="cline-any cline-yes">1x</span>
708
+ <span class="cline-any cline-yes">1x</span>
709
+ <span class="cline-any cline-yes">1x</span>
710
+ <span class="cline-any cline-yes">1x</span>
711
+ <span class="cline-any cline-yes">1x</span>
712
+ <span class="cline-any cline-yes">1x</span>
713
+ <span class="cline-any cline-yes">1x</span>
714
+ <span class="cline-any cline-yes">1x</span>
715
+ <span class="cline-any cline-yes">1x</span>
716
+ <span class="cline-any cline-yes">1x</span>
717
+ <span class="cline-any cline-yes">1x</span>
718
+ <span class="cline-any cline-yes">1x</span>
719
+ <span class="cline-any cline-yes">1x</span>
720
+ <span class="cline-any cline-yes">1x</span>
721
+ <span class="cline-any cline-yes">1x</span>
722
+ <span class="cline-any cline-yes">1x</span>
723
+ <span class="cline-any cline-yes">1x</span>
724
+ <span class="cline-any cline-yes">1x</span>
725
+ <span class="cline-any cline-yes">1x</span>
726
+ <span class="cline-any cline-yes">1x</span>
727
+ <span class="cline-any cline-yes">1x</span>
728
+ <span class="cline-any cline-yes">1x</span>
729
+ <span class="cline-any cline-yes">1x</span>
730
+ <span class="cline-any cline-yes">1x</span>
731
+ <span class="cline-any cline-yes">1x</span>
732
+ <span class="cline-any cline-yes">1x</span>
733
+ <span class="cline-any cline-yes">1x</span>
734
+ <span class="cline-any cline-yes">1x</span>
735
+ <span class="cline-any cline-yes">1x</span>
736
+ <span class="cline-any cline-yes">1x</span>
737
+ <span class="cline-any cline-yes">1x</span>
738
+ <span class="cline-any cline-yes">1x</span>
739
+ <span class="cline-any cline-yes">1x</span>
740
+ <span class="cline-any cline-yes">1x</span>
741
+ <span class="cline-any cline-yes">1x</span>
742
+ <span class="cline-any cline-yes">1x</span>
743
+ <span class="cline-any cline-yes">1x</span>
744
+ <span class="cline-any cline-yes">1x</span>
745
+ <span class="cline-any cline-yes">1x</span>
746
+ <span class="cline-any cline-yes">1x</span>
747
+ <span class="cline-any cline-yes">1x</span>
748
+ <span class="cline-any cline-yes">1x</span>
749
+ <span class="cline-any cline-yes">1x</span>
750
+ <span class="cline-any cline-yes">1x</span>
751
+ <span class="cline-any cline-yes">1x</span>
752
+ <span class="cline-any cline-yes">1x</span>
753
+ <span class="cline-any cline-neutral">&nbsp;</span>
754
+ <span class="cline-any cline-neutral">&nbsp;</span>
755
+ <span class="cline-any cline-neutral">&nbsp;</span>
756
+ <span class="cline-any cline-neutral">&nbsp;</span>
757
+ <span class="cline-any cline-neutral">&nbsp;</span>
758
+ <span class="cline-any cline-yes">1x</span>
759
+ <span class="cline-any cline-neutral">&nbsp;</span>
760
+ <span class="cline-any cline-no">&nbsp;</span>
761
+ <span class="cline-any cline-no">&nbsp;</span>
762
+ <span class="cline-any cline-no">&nbsp;</span>
763
+ <span class="cline-any cline-neutral">&nbsp;</span>
764
+ <span class="cline-any cline-yes">1x</span>
765
+ <span class="cline-any cline-no">&nbsp;</span>
766
+ <span class="cline-any cline-no">&nbsp;</span>
767
+ <span class="cline-any cline-no">&nbsp;</span>
768
+ <span class="cline-any cline-neutral">&nbsp;</span>
769
+ <span class="cline-any cline-neutral">&nbsp;</span>
770
+ <span class="cline-any cline-neutral">&nbsp;</span>
771
+ <span class="cline-any cline-neutral">&nbsp;</span>
772
+ <span class="cline-any cline-neutral">&nbsp;</span>
773
+ <span class="cline-any cline-neutral">&nbsp;</span>
774
+ <span class="cline-any cline-neutral">&nbsp;</span>
775
+ <span class="cline-any cline-neutral">&nbsp;</span>
776
+ <span class="cline-any cline-neutral">&nbsp;</span>
777
+ <span class="cline-any cline-neutral">&nbsp;</span>
778
+ <span class="cline-any cline-neutral">&nbsp;</span>
779
+ <span class="cline-any cline-neutral">&nbsp;</span>
780
+ <span class="cline-any cline-neutral">&nbsp;</span>
781
+ <span class="cline-any cline-neutral">&nbsp;</span>
782
+ <span class="cline-any cline-neutral">&nbsp;</span>
783
+ <span class="cline-any cline-neutral">&nbsp;</span>
784
+ <span class="cline-any cline-neutral">&nbsp;</span>
785
+ <span class="cline-any cline-neutral">&nbsp;</span>
786
+ <span class="cline-any cline-yes">1x</span>
787
+ <span class="cline-any cline-yes">1x</span>
788
+ <span class="cline-any cline-yes">1x</span>
789
+ <span class="cline-any cline-yes">1x</span>
790
+ <span class="cline-any cline-yes">1x</span>
791
+ <span class="cline-any cline-no">&nbsp;</span>
792
+ <span class="cline-any cline-no">&nbsp;</span>
793
+ <span class="cline-any cline-no">&nbsp;</span>
794
+ <span class="cline-any cline-no">&nbsp;</span>
795
+ <span class="cline-any cline-no">&nbsp;</span>
796
+ <span class="cline-any cline-no">&nbsp;</span>
797
+ <span class="cline-any cline-no">&nbsp;</span>
798
+ <span class="cline-any cline-no">&nbsp;</span>
799
+ <span class="cline-any cline-neutral">&nbsp;</span>
800
+ <span class="cline-any cline-yes">1x</span>
801
+ <span class="cline-any cline-yes">1x</span>
802
+ <span class="cline-any cline-yes">1x</span>
803
+ <span class="cline-any cline-yes">1x</span>
804
+ <span class="cline-any cline-neutral">&nbsp;</span>
805
+ <span class="cline-any cline-yes">1x</span>
806
+ <span class="cline-any cline-yes">1x</span>
807
+ <span class="cline-any cline-yes">1x</span>
808
+ <span class="cline-any cline-yes">1x</span>
809
+ <span class="cline-any cline-yes">1x</span>
810
+ <span class="cline-any cline-yes">1x</span>
811
+ <span class="cline-any cline-yes">1x</span>
812
+ <span class="cline-any cline-yes">1x</span>
813
+ <span class="cline-any cline-neutral">&nbsp;</span>
814
+ <span class="cline-any cline-yes">1x</span>
815
+ <span class="cline-any cline-neutral">&nbsp;</span>
816
+ <span class="cline-any cline-neutral">&nbsp;</span>
817
+ <span class="cline-any cline-neutral">&nbsp;</span>
818
+ <span class="cline-any cline-neutral">&nbsp;</span>
819
+ <span class="cline-any cline-neutral">&nbsp;</span>
820
+ <span class="cline-any cline-no">&nbsp;</span>
821
+ <span class="cline-any cline-no">&nbsp;</span>
822
+ <span class="cline-any cline-no">&nbsp;</span>
823
+ <span class="cline-any cline-neutral">&nbsp;</span>
824
+ <span class="cline-any cline-no">&nbsp;</span>
825
+ <span class="cline-any cline-no">&nbsp;</span>
826
+ <span class="cline-any cline-no">&nbsp;</span>
827
+ <span class="cline-any cline-no">&nbsp;</span>
828
+ <span class="cline-any cline-no">&nbsp;</span>
829
+ <span class="cline-any cline-neutral">&nbsp;</span>
830
+ <span class="cline-any cline-no">&nbsp;</span>
831
+ <span class="cline-any cline-no">&nbsp;</span>
832
+ <span class="cline-any cline-no">&nbsp;</span>
833
+ <span class="cline-any cline-neutral">&nbsp;</span>
834
+ <span class="cline-any cline-no">&nbsp;</span>
835
+ <span class="cline-any cline-no">&nbsp;</span>
836
+ <span class="cline-any cline-no">&nbsp;</span>
837
+ <span class="cline-any cline-no">&nbsp;</span>
838
+ <span class="cline-any cline-no">&nbsp;</span>
839
+ <span class="cline-any cline-no">&nbsp;</span>
840
+ <span class="cline-any cline-no">&nbsp;</span>
841
+ <span class="cline-any cline-no">&nbsp;</span>
842
+ <span class="cline-any cline-no">&nbsp;</span>
843
+ <span class="cline-any cline-no">&nbsp;</span>
844
+ <span class="cline-any cline-no">&nbsp;</span>
845
+ <span class="cline-any cline-no">&nbsp;</span>
846
+ <span class="cline-any cline-no">&nbsp;</span>
847
+ <span class="cline-any cline-no">&nbsp;</span>
848
+ <span class="cline-any cline-neutral">&nbsp;</span>
849
+ <span class="cline-any cline-neutral">&nbsp;</span>
850
+ <span class="cline-any cline-neutral">&nbsp;</span>
851
+ <span class="cline-any cline-neutral">&nbsp;</span>
852
+ <span class="cline-any cline-neutral">&nbsp;</span>
853
+ <span class="cline-any cline-no">&nbsp;</span>
854
+ <span class="cline-any cline-no">&nbsp;</span>
855
+ <span class="cline-any cline-no">&nbsp;</span>
856
+ <span class="cline-any cline-no">&nbsp;</span>
857
+ <span class="cline-any cline-no">&nbsp;</span>
858
+ <span class="cline-any cline-no">&nbsp;</span>
859
+ <span class="cline-any cline-no">&nbsp;</span>
860
+ <span class="cline-any cline-no">&nbsp;</span>
861
+ <span class="cline-any cline-no">&nbsp;</span>
862
+ <span class="cline-any cline-no">&nbsp;</span>
863
+ <span class="cline-any cline-neutral">&nbsp;</span>
864
+ <span class="cline-any cline-no">&nbsp;</span>
865
+ <span class="cline-any cline-no">&nbsp;</span>
866
+ <span class="cline-any cline-no">&nbsp;</span>
867
+ <span class="cline-any cline-neutral">&nbsp;</span>
868
+ <span class="cline-any cline-no">&nbsp;</span>
869
+ <span class="cline-any cline-no">&nbsp;</span>
870
+ <span class="cline-any cline-no">&nbsp;</span>
871
+ <span class="cline-any cline-no">&nbsp;</span>
872
+ <span class="cline-any cline-no">&nbsp;</span>
873
+ <span class="cline-any cline-no">&nbsp;</span>
874
+ <span class="cline-any cline-no">&nbsp;</span>
875
+ <span class="cline-any cline-no">&nbsp;</span>
876
+ <span class="cline-any cline-no">&nbsp;</span>
877
+ <span class="cline-any cline-no">&nbsp;</span>
878
+ <span class="cline-any cline-neutral">&nbsp;</span>
879
+ <span class="cline-any cline-neutral">&nbsp;</span>
880
+ <span class="cline-any cline-neutral">&nbsp;</span>
881
+ <span class="cline-any cline-neutral">&nbsp;</span>
882
+ <span class="cline-any cline-neutral">&nbsp;</span>
883
+ <span class="cline-any cline-neutral">&nbsp;</span>
884
+ <span class="cline-any cline-neutral">&nbsp;</span>
885
+ <span class="cline-any cline-neutral">&nbsp;</span>
886
+ <span class="cline-any cline-neutral">&nbsp;</span>
887
+ <span class="cline-any cline-neutral">&nbsp;</span>
888
+ <span class="cline-any cline-neutral">&nbsp;</span>
889
+ <span class="cline-any cline-neutral">&nbsp;</span>
890
+ <span class="cline-any cline-neutral">&nbsp;</span>
891
+ <span class="cline-any cline-neutral">&nbsp;</span>
892
+ <span class="cline-any cline-neutral">&nbsp;</span>
893
+ <span class="cline-any cline-neutral">&nbsp;</span>
894
+ <span class="cline-any cline-neutral">&nbsp;</span>
895
+ <span class="cline-any cline-neutral">&nbsp;</span>
896
+ <span class="cline-any cline-neutral">&nbsp;</span>
897
+ <span class="cline-any cline-neutral">&nbsp;</span>
898
+ <span class="cline-any cline-neutral">&nbsp;</span>
899
+ <span class="cline-any cline-neutral">&nbsp;</span>
900
+ <span class="cline-any cline-neutral">&nbsp;</span>
901
+ <span class="cline-any cline-neutral">&nbsp;</span>
902
+ <span class="cline-any cline-neutral">&nbsp;</span>
903
+ <span class="cline-any cline-neutral">&nbsp;</span>
904
+ <span class="cline-any cline-neutral">&nbsp;</span>
905
+ <span class="cline-any cline-neutral">&nbsp;</span>
906
+ <span class="cline-any cline-neutral">&nbsp;</span>
907
+ <span class="cline-any cline-neutral">&nbsp;</span>
908
+ <span class="cline-any cline-neutral">&nbsp;</span>
909
+ <span class="cline-any cline-neutral">&nbsp;</span>
910
+ <span class="cline-any cline-neutral">&nbsp;</span>
911
+ <span class="cline-any cline-neutral">&nbsp;</span>
912
+ <span class="cline-any cline-neutral">&nbsp;</span>
913
+ <span class="cline-any cline-neutral">&nbsp;</span>
914
+ <span class="cline-any cline-neutral">&nbsp;</span>
915
+ <span class="cline-any cline-neutral">&nbsp;</span>
916
+ <span class="cline-any cline-neutral">&nbsp;</span>
917
+ <span class="cline-any cline-neutral">&nbsp;</span>
918
+ <span class="cline-any cline-neutral">&nbsp;</span>
919
+ <span class="cline-any cline-no">&nbsp;</span>
920
+ <span class="cline-any cline-no">&nbsp;</span>
921
+ <span class="cline-any cline-no">&nbsp;</span>
922
+ <span class="cline-any cline-no">&nbsp;</span>
923
+ <span class="cline-any cline-no">&nbsp;</span>
924
+ <span class="cline-any cline-no">&nbsp;</span>
925
+ <span class="cline-any cline-no">&nbsp;</span>
926
+ <span class="cline-any cline-no">&nbsp;</span>
927
+ <span class="cline-any cline-neutral">&nbsp;</span>
928
+ <span class="cline-any cline-no">&nbsp;</span>
929
+ <span class="cline-any cline-no">&nbsp;</span>
930
+ <span class="cline-any cline-no">&nbsp;</span>
931
+ <span class="cline-any cline-no">&nbsp;</span>
932
+ <span class="cline-any cline-neutral">&nbsp;</span>
933
+ <span class="cline-any cline-neutral">&nbsp;</span>
934
+ <span class="cline-any cline-no">&nbsp;</span>
935
+ <span class="cline-any cline-no">&nbsp;</span>
936
+ <span class="cline-any cline-neutral">&nbsp;</span>
937
+ <span class="cline-any cline-neutral">&nbsp;</span>
938
+ <span class="cline-any cline-neutral">&nbsp;</span>
939
+ <span class="cline-any cline-neutral">&nbsp;</span>
940
+ <span class="cline-any cline-no">&nbsp;</span>
941
+ <span class="cline-any cline-neutral">&nbsp;</span>
942
+ <span class="cline-any cline-no">&nbsp;</span>
943
+ <span class="cline-any cline-no">&nbsp;</span>
944
+ <span class="cline-any cline-no">&nbsp;</span>
945
+ <span class="cline-any cline-no">&nbsp;</span>
946
+ <span class="cline-any cline-no">&nbsp;</span>
947
+ <span class="cline-any cline-neutral">&nbsp;</span>
948
+ <span class="cline-any cline-no">&nbsp;</span>
949
+ <span class="cline-any cline-no">&nbsp;</span>
950
+ <span class="cline-any cline-no">&nbsp;</span>
951
+ <span class="cline-any cline-no">&nbsp;</span>
952
+ <span class="cline-any cline-neutral">&nbsp;</span>
953
+ <span class="cline-any cline-no">&nbsp;</span>
954
+ <span class="cline-any cline-no">&nbsp;</span>
955
+ <span class="cline-any cline-no">&nbsp;</span>
956
+ <span class="cline-any cline-no">&nbsp;</span>
957
+ <span class="cline-any cline-no">&nbsp;</span>
958
+ <span class="cline-any cline-no">&nbsp;</span>
959
+ <span class="cline-any cline-no">&nbsp;</span>
960
+ <span class="cline-any cline-no">&nbsp;</span>
961
+ <span class="cline-any cline-no">&nbsp;</span>
962
+ <span class="cline-any cline-no">&nbsp;</span>
963
+ <span class="cline-any cline-no">&nbsp;</span>
964
+ <span class="cline-any cline-no">&nbsp;</span>
965
+ <span class="cline-any cline-no">&nbsp;</span>
966
+ <span class="cline-any cline-no">&nbsp;</span>
967
+ <span class="cline-any cline-no">&nbsp;</span>
968
+ <span class="cline-any cline-no">&nbsp;</span>
969
+ <span class="cline-any cline-no">&nbsp;</span>
970
+ <span class="cline-any cline-no">&nbsp;</span>
971
+ <span class="cline-any cline-no">&nbsp;</span>
972
+ <span class="cline-any cline-no">&nbsp;</span>
973
+ <span class="cline-any cline-no">&nbsp;</span>
974
+ <span class="cline-any cline-no">&nbsp;</span>
975
+ <span class="cline-any cline-no">&nbsp;</span>
976
+ <span class="cline-any cline-no">&nbsp;</span>
977
+ <span class="cline-any cline-no">&nbsp;</span>
978
+ <span class="cline-any cline-no">&nbsp;</span>
979
+ <span class="cline-any cline-no">&nbsp;</span>
980
+ <span class="cline-any cline-no">&nbsp;</span>
981
+ <span class="cline-any cline-no">&nbsp;</span>
982
+ <span class="cline-any cline-no">&nbsp;</span>
983
+ <span class="cline-any cline-no">&nbsp;</span>
984
+ <span class="cline-any cline-no">&nbsp;</span>
985
+ <span class="cline-any cline-neutral">&nbsp;</span>
986
+ <span class="cline-any cline-neutral">&nbsp;</span>
987
+ <span class="cline-any cline-neutral">&nbsp;</span>
988
+ <span class="cline-any cline-neutral">&nbsp;</span>
989
+ <span class="cline-any cline-neutral">&nbsp;</span>
990
+ <span class="cline-any cline-neutral">&nbsp;</span>
991
+ <span class="cline-any cline-neutral">&nbsp;</span>
992
+ <span class="cline-any cline-neutral">&nbsp;</span>
993
+ <span class="cline-any cline-neutral">&nbsp;</span>
994
+ <span class="cline-any cline-neutral">&nbsp;</span>
995
+ <span class="cline-any cline-neutral">&nbsp;</span>
996
+ <span class="cline-any cline-neutral">&nbsp;</span>
997
+ <span class="cline-any cline-neutral">&nbsp;</span>
998
+ <span class="cline-any cline-neutral">&nbsp;</span>
999
+ <span class="cline-any cline-neutral">&nbsp;</span>
1000
+ <span class="cline-any cline-neutral">&nbsp;</span>
1001
+ <span class="cline-any cline-neutral">&nbsp;</span>
1002
+ <span class="cline-any cline-neutral">&nbsp;</span>
1003
+ <span class="cline-any cline-neutral">&nbsp;</span>
1004
+ <span class="cline-any cline-neutral">&nbsp;</span>
1005
+ <span class="cline-any cline-neutral">&nbsp;</span>
1006
+ <span class="cline-any cline-neutral">&nbsp;</span>
1007
+ <span class="cline-any cline-neutral">&nbsp;</span>
1008
+ <span class="cline-any cline-no">&nbsp;</span>
1009
+ <span class="cline-any cline-neutral">&nbsp;</span>
1010
+ <span class="cline-any cline-neutral">&nbsp;</span>
1011
+ <span class="cline-any cline-no">&nbsp;</span>
1012
+ <span class="cline-any cline-no">&nbsp;</span>
1013
+ <span class="cline-any cline-no">&nbsp;</span>
1014
+ <span class="cline-any cline-neutral">&nbsp;</span>
1015
+ <span class="cline-any cline-neutral">&nbsp;</span>
1016
+ <span class="cline-any cline-neutral">&nbsp;</span>
1017
+ <span class="cline-any cline-no">&nbsp;</span>
1018
+ <span class="cline-any cline-neutral">&nbsp;</span>
1019
+ <span class="cline-any cline-no">&nbsp;</span>
1020
+ <span class="cline-any cline-no">&nbsp;</span>
1021
+ <span class="cline-any cline-no">&nbsp;</span>
1022
+ <span class="cline-any cline-no">&nbsp;</span>
1023
+ <span class="cline-any cline-no">&nbsp;</span>
1024
+ <span class="cline-any cline-neutral">&nbsp;</span>
1025
+ <span class="cline-any cline-no">&nbsp;</span>
1026
+ <span class="cline-any cline-no">&nbsp;</span>
1027
+ <span class="cline-any cline-no">&nbsp;</span>
1028
+ <span class="cline-any cline-no">&nbsp;</span>
1029
+ <span class="cline-any cline-no">&nbsp;</span>
1030
+ <span class="cline-any cline-no">&nbsp;</span>
1031
+ <span class="cline-any cline-no">&nbsp;</span>
1032
+ <span class="cline-any cline-neutral">&nbsp;</span>
1033
+ <span class="cline-any cline-neutral">&nbsp;</span>
1034
+ <span class="cline-any cline-no">&nbsp;</span>
1035
+ <span class="cline-any cline-no">&nbsp;</span>
1036
+ <span class="cline-any cline-no">&nbsp;</span>
1037
+ <span class="cline-any cline-no">&nbsp;</span>
1038
+ <span class="cline-any cline-no">&nbsp;</span>
1039
+ <span class="cline-any cline-no">&nbsp;</span>
1040
+ <span class="cline-any cline-no">&nbsp;</span>
1041
+ <span class="cline-any cline-no">&nbsp;</span>
1042
+ <span class="cline-any cline-no">&nbsp;</span>
1043
+ <span class="cline-any cline-no">&nbsp;</span>
1044
+ <span class="cline-any cline-no">&nbsp;</span>
1045
+ <span class="cline-any cline-no">&nbsp;</span>
1046
+ <span class="cline-any cline-no">&nbsp;</span>
1047
+ <span class="cline-any cline-no">&nbsp;</span>
1048
+ <span class="cline-any cline-no">&nbsp;</span>
1049
+ <span class="cline-any cline-neutral">&nbsp;</span>
1050
+ <span class="cline-any cline-neutral">&nbsp;</span>
1051
+ <span class="cline-any cline-neutral">&nbsp;</span>
1052
+ <span class="cline-any cline-neutral">&nbsp;</span>
1053
+ <span class="cline-any cline-neutral">&nbsp;</span>
1054
+ <span class="cline-any cline-no">&nbsp;</span>
1055
+ <span class="cline-any cline-neutral">&nbsp;</span>
1056
+ <span class="cline-any cline-neutral">&nbsp;</span>
1057
+ <span class="cline-any cline-no">&nbsp;</span>
1058
+ <span class="cline-any cline-no">&nbsp;</span>
1059
+ <span class="cline-any cline-no">&nbsp;</span>
1060
+ <span class="cline-any cline-neutral">&nbsp;</span>
1061
+ <span class="cline-any cline-neutral">&nbsp;</span>
1062
+ <span class="cline-any cline-no">&nbsp;</span>
1063
+ <span class="cline-any cline-neutral">&nbsp;</span>
1064
+ <span class="cline-any cline-no">&nbsp;</span>
1065
+ <span class="cline-any cline-no">&nbsp;</span>
1066
+ <span class="cline-any cline-no">&nbsp;</span>
1067
+ <span class="cline-any cline-no">&nbsp;</span>
1068
+ <span class="cline-any cline-no">&nbsp;</span>
1069
+ <span class="cline-any cline-neutral">&nbsp;</span>
1070
+ <span class="cline-any cline-no">&nbsp;</span>
1071
+ <span class="cline-any cline-no">&nbsp;</span>
1072
+ <span class="cline-any cline-no">&nbsp;</span>
1073
+ <span class="cline-any cline-no">&nbsp;</span>
1074
+ <span class="cline-any cline-no">&nbsp;</span>
1075
+ <span class="cline-any cline-no">&nbsp;</span>
1076
+ <span class="cline-any cline-no">&nbsp;</span>
1077
+ <span class="cline-any cline-neutral">&nbsp;</span>
1078
+ <span class="cline-any cline-no">&nbsp;</span>
1079
+ <span class="cline-any cline-no">&nbsp;</span>
1080
+ <span class="cline-any cline-no">&nbsp;</span>
1081
+ <span class="cline-any cline-neutral">&nbsp;</span>
1082
+ <span class="cline-any cline-neutral">&nbsp;</span>
1083
+ <span class="cline-any cline-no">&nbsp;</span>
1084
+ <span class="cline-any cline-no">&nbsp;</span>
1085
+ <span class="cline-any cline-no">&nbsp;</span>
1086
+ <span class="cline-any cline-no">&nbsp;</span>
1087
+ <span class="cline-any cline-neutral">&nbsp;</span>
1088
+ <span class="cline-any cline-neutral">&nbsp;</span>
1089
+ <span class="cline-any cline-neutral">&nbsp;</span>
1090
+ <span class="cline-any cline-neutral">&nbsp;</span>
1091
+ <span class="cline-any cline-neutral">&nbsp;</span>
1092
+ <span class="cline-any cline-yes">1x</span>
1093
+ <span class="cline-any cline-neutral">&nbsp;</span>
1094
+ <span class="cline-any cline-neutral">&nbsp;</span>
1095
+ <span class="cline-any cline-no">&nbsp;</span>
1096
+ <span class="cline-any cline-no">&nbsp;</span>
1097
+ <span class="cline-any cline-no">&nbsp;</span>
1098
+ <span class="cline-any cline-neutral">&nbsp;</span>
1099
+ <span class="cline-any cline-no">&nbsp;</span>
1100
+ <span class="cline-any cline-no">&nbsp;</span>
1101
+ <span class="cline-any cline-no">&nbsp;</span>
1102
+ <span class="cline-any cline-no">&nbsp;</span>
1103
+ <span class="cline-any cline-no">&nbsp;</span>
1104
+ <span class="cline-any cline-no">&nbsp;</span>
1105
+ <span class="cline-any cline-no">&nbsp;</span>
1106
+ <span class="cline-any cline-no">&nbsp;</span>
1107
+ <span class="cline-any cline-no">&nbsp;</span>
1108
+ <span class="cline-any cline-no">&nbsp;</span>
1109
+ <span class="cline-any cline-no">&nbsp;</span>
1110
+ <span class="cline-any cline-no">&nbsp;</span>
1111
+ <span class="cline-any cline-no">&nbsp;</span>
1112
+ <span class="cline-any cline-neutral">&nbsp;</span>
1113
+ <span class="cline-any cline-no">&nbsp;</span>
1114
+ <span class="cline-any cline-no">&nbsp;</span>
1115
+ <span class="cline-any cline-no">&nbsp;</span>
1116
+ <span class="cline-any cline-no">&nbsp;</span>
1117
+ <span class="cline-any cline-no">&nbsp;</span>
1118
+ <span class="cline-any cline-no">&nbsp;</span>
1119
+ <span class="cline-any cline-neutral">&nbsp;</span>
1120
+ <span class="cline-any cline-neutral">&nbsp;</span>
1121
+ <span class="cline-any cline-neutral">&nbsp;</span>
1122
+ <span class="cline-any cline-neutral">&nbsp;</span>
1123
+ <span class="cline-any cline-neutral">&nbsp;</span>
1124
+ <span class="cline-any cline-neutral">&nbsp;</span>
1125
+ <span class="cline-any cline-neutral">&nbsp;</span>
1126
+ <span class="cline-any cline-neutral">&nbsp;</span>
1127
+ <span class="cline-any cline-neutral">&nbsp;</span>
1128
+ <span class="cline-any cline-neutral">&nbsp;</span>
1129
+ <span class="cline-any cline-neutral">&nbsp;</span>
1130
+ <span class="cline-any cline-neutral">&nbsp;</span>
1131
+ <span class="cline-any cline-neutral">&nbsp;</span>
1132
+ <span class="cline-any cline-neutral">&nbsp;</span>
1133
+ <span class="cline-any cline-neutral">&nbsp;</span>
1134
+ <span class="cline-any cline-neutral">&nbsp;</span>
1135
+ <span class="cline-any cline-neutral">&nbsp;</span>
1136
+ <span class="cline-any cline-no">&nbsp;</span>
1137
+ <span class="cline-any cline-no">&nbsp;</span>
1138
+ <span class="cline-any cline-no">&nbsp;</span>
1139
+ <span class="cline-any cline-no">&nbsp;</span>
1140
+ <span class="cline-any cline-no">&nbsp;</span>
1141
+ <span class="cline-any cline-no">&nbsp;</span>
1142
+ <span class="cline-any cline-no">&nbsp;</span>
1143
+ <span class="cline-any cline-no">&nbsp;</span>
1144
+ <span class="cline-any cline-no">&nbsp;</span>
1145
+ <span class="cline-any cline-no">&nbsp;</span>
1146
+ <span class="cline-any cline-no">&nbsp;</span>
1147
+ <span class="cline-any cline-no">&nbsp;</span>
1148
+ <span class="cline-any cline-no">&nbsp;</span>
1149
+ <span class="cline-any cline-neutral">&nbsp;</span>
1150
+ <span class="cline-any cline-no">&nbsp;</span>
1151
+ <span class="cline-any cline-no">&nbsp;</span>
1152
+ <span class="cline-any cline-no">&nbsp;</span>
1153
+ <span class="cline-any cline-no">&nbsp;</span>
1154
+ <span class="cline-any cline-no">&nbsp;</span>
1155
+ <span class="cline-any cline-no">&nbsp;</span>
1156
+ <span class="cline-any cline-no">&nbsp;</span>
1157
+ <span class="cline-any cline-neutral">&nbsp;</span>
1158
+ <span class="cline-any cline-no">&nbsp;</span>
1159
+ <span class="cline-any cline-no">&nbsp;</span>
1160
+ <span class="cline-any cline-no">&nbsp;</span>
1161
+ <span class="cline-any cline-no">&nbsp;</span>
1162
+ <span class="cline-any cline-no">&nbsp;</span>
1163
+ <span class="cline-any cline-no">&nbsp;</span>
1164
+ <span class="cline-any cline-no">&nbsp;</span>
1165
+ <span class="cline-any cline-no">&nbsp;</span>
1166
+ <span class="cline-any cline-neutral">&nbsp;</span>
1167
+ <span class="cline-any cline-no">&nbsp;</span>
1168
+ <span class="cline-any cline-no">&nbsp;</span>
1169
+ <span class="cline-any cline-neutral">&nbsp;</span>
1170
+ <span class="cline-any cline-no">&nbsp;</span>
1171
+ <span class="cline-any cline-no">&nbsp;</span>
1172
+ <span class="cline-any cline-no">&nbsp;</span>
1173
+ <span class="cline-any cline-no">&nbsp;</span>
1174
+ <span class="cline-any cline-no">&nbsp;</span>
1175
+ <span class="cline-any cline-no">&nbsp;</span>
1176
+ <span class="cline-any cline-no">&nbsp;</span>
1177
+ <span class="cline-any cline-no">&nbsp;</span>
1178
+ <span class="cline-any cline-no">&nbsp;</span>
1179
+ <span class="cline-any cline-no">&nbsp;</span>
1180
+ <span class="cline-any cline-no">&nbsp;</span>
1181
+ <span class="cline-any cline-neutral">&nbsp;</span>
1182
+ <span class="cline-any cline-neutral">&nbsp;</span>
1183
+ <span class="cline-any cline-neutral">&nbsp;</span>
1184
+ <span class="cline-any cline-neutral">&nbsp;</span>
1185
+ <span class="cline-any cline-neutral">&nbsp;</span>
1186
+ <span class="cline-any cline-neutral">&nbsp;</span>
1187
+ <span class="cline-any cline-neutral">&nbsp;</span>
1188
+ <span class="cline-any cline-neutral">&nbsp;</span>
1189
+ <span class="cline-any cline-neutral">&nbsp;</span>
1190
+ <span class="cline-any cline-neutral">&nbsp;</span>
1191
+ <span class="cline-any cline-neutral">&nbsp;</span>
1192
+ <span class="cline-any cline-neutral">&nbsp;</span>
1193
+ <span class="cline-any cline-neutral">&nbsp;</span>
1194
+ <span class="cline-any cline-no">&nbsp;</span>
1195
+ <span class="cline-any cline-no">&nbsp;</span>
1196
+ <span class="cline-any cline-no">&nbsp;</span>
1197
+ <span class="cline-any cline-no">&nbsp;</span>
1198
+ <span class="cline-any cline-no">&nbsp;</span>
1199
+ <span class="cline-any cline-no">&nbsp;</span>
1200
+ <span class="cline-any cline-no">&nbsp;</span>
1201
+ <span class="cline-any cline-no">&nbsp;</span>
1202
+ <span class="cline-any cline-no">&nbsp;</span>
1203
+ <span class="cline-any cline-no">&nbsp;</span>
1204
+ <span class="cline-any cline-no">&nbsp;</span>
1205
+ <span class="cline-any cline-no">&nbsp;</span>
1206
+ <span class="cline-any cline-no">&nbsp;</span>
1207
+ <span class="cline-any cline-no">&nbsp;</span>
1208
+ <span class="cline-any cline-no">&nbsp;</span>
1209
+ <span class="cline-any cline-no">&nbsp;</span>
1210
+ <span class="cline-any cline-no">&nbsp;</span>
1211
+ <span class="cline-any cline-no">&nbsp;</span>
1212
+ <span class="cline-any cline-neutral">&nbsp;</span>
1213
+ <span class="cline-any cline-no">&nbsp;</span>
1214
+ <span class="cline-any cline-no">&nbsp;</span>
1215
+ <span class="cline-any cline-neutral">&nbsp;</span>
1216
+ <span class="cline-any cline-no">&nbsp;</span>
1217
+ <span class="cline-any cline-no">&nbsp;</span>
1218
+ <span class="cline-any cline-neutral">&nbsp;</span>
1219
+ <span class="cline-any cline-no">&nbsp;</span>
1220
+ <span class="cline-any cline-no">&nbsp;</span>
1221
+ <span class="cline-any cline-no">&nbsp;</span>
1222
+ <span class="cline-any cline-no">&nbsp;</span>
1223
+ <span class="cline-any cline-no">&nbsp;</span>
1224
+ <span class="cline-any cline-no">&nbsp;</span>
1225
+ <span class="cline-any cline-no">&nbsp;</span>
1226
+ <span class="cline-any cline-no">&nbsp;</span>
1227
+ <span class="cline-any cline-no">&nbsp;</span>
1228
+ <span class="cline-any cline-no">&nbsp;</span>
1229
+ <span class="cline-any cline-no">&nbsp;</span>
1230
+ <span class="cline-any cline-no">&nbsp;</span>
1231
+ <span class="cline-any cline-neutral">&nbsp;</span>
1232
+ <span class="cline-any cline-yes">4x</span>
1233
+ <span class="cline-any cline-yes">4x</span>
1234
+ <span class="cline-any cline-yes">4x</span>
1235
+ <span class="cline-any cline-yes">4x</span>
1236
+ <span class="cline-any cline-neutral">&nbsp;</span>
1237
+ <span class="cline-any cline-no">&nbsp;</span>
1238
+ <span class="cline-any cline-no">&nbsp;</span>
1239
+ <span class="cline-any cline-no">&nbsp;</span>
1240
+ <span class="cline-any cline-no">&nbsp;</span>
1241
+ <span class="cline-any cline-neutral">&nbsp;</span>
1242
+ <span class="cline-any cline-no">&nbsp;</span>
1243
+ <span class="cline-any cline-no">&nbsp;</span>
1244
+ <span class="cline-any cline-no">&nbsp;</span>
1245
+ <span class="cline-any cline-no">&nbsp;</span>
1246
+ <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">/**
1247
+ * Article 10 (EU AI Act 2024/1689) – Bias &amp; Fairness Checks
1248
+ *
1249
+ * Goals:
1250
+ * - Scientific, reproducible metrics
1251
+ * - Clear thresholds (explicitly marked as heuristics / screening where applicable)
1252
+ * - Traceable sources + AI Act mapping (Recital 54, Art. 10(2–4))
1253
+ *
1254
+ * IMPORTANT: This module provides technical orientation, not legal advice.
1255
+ */
1256
+ &nbsp;
1257
+ import { disparateImpact, equalizedOdds, statisticalParityDifference } from "../fairness-metrics";
1258
+ import type { InferenceClient } from "../inference";
1259
+ import type { BiasType, PairTestResult, StereotypeBiasResult, StereotypePair } from "../metrics";
1260
+ import { runStereotypeBiasTest } from "../metrics";
1261
+ import type { BiasTestResult, FairnessMetric, PredictionData } from "../types";
1262
+ &nbsp;
1263
+ export type SensitiveAttribute =
1264
+ | "gender"
1265
+ | "ethnicity"
1266
+ | "age"
1267
+ | "disability"
1268
+ | "religion"
1269
+ | "sexual-orientation";
1270
+ &nbsp;
1271
+ export interface Citation {
1272
+ label: string;
1273
+ reference: string;
1274
+ }
1275
+ &nbsp;
1276
+ export const AI_ACT_SOURCES: Citation[] = [
1277
+ { label: "EU AI Act", reference: "Verordnung (EU) 2024/1689" },
1278
+ {
1279
+ label: "Art. 10",
1280
+ reference: "Daten- und Data-Governance, u. a. Bias-Minderung (Art. 10(2–4))",
1281
+ },
1282
+ {
1283
+ label: "Recital 54",
1284
+ reference: "Schutz vor Diskriminierung (u. a. Geschlecht, Ethnie, Alter, Behinderung)",
1285
+ },
1286
+ { label: "Annex IV", reference: "Technische Dokumentation (Annex IV)" },
1287
+ ];
1288
+ &nbsp;
1289
+ export const METRIC_SOURCES: Record&lt;string, Citation[]&gt; = {
1290
+ disparateImpact: [
1291
+ {
1292
+ label: "80%-Regel",
1293
+ reference:
1294
+ "US EEOC Uniform Guidelines (Screening-Heuristik); in EU-Kontext als Indikator genutzt",
1295
+ },
1296
+ { label: "AI Act mapping", reference: "Recital 54; Art. 10(2–4) (Bias &amp; Data Governance)" },
1297
+ ],
1298
+ demographicParityDifference: [
1299
+ { label: "Demographic parity", reference: "Standard fairness metric: Δ P(ŷ=1 | group)" },
1300
+ { label: "AI Act mapping", reference: "Recital 54; Art. 10(2–4)" },
1301
+ ],
1302
+ equalizedOddsDifference: [
1303
+ {
1304
+ label: "Equalized Odds",
1305
+ reference: "Hardt, Price, Srebro (2016): Equality of Opportunity / Equalized Odds",
1306
+ },
1307
+ { label: "AI Act mapping", reference: "Recital 54; Art. 10(2–4)" },
1308
+ ],
1309
+ counterfactualFairness: [
1310
+ {
1311
+ label: "Counterfactual Fairness",
1312
+ reference: "Kusner et al. (2017): Counterfactual Fairness",
1313
+ },
1314
+ { label: "AI Act mapping", reference: "Recital 54; Art. 10(2–4)" },
1315
+ ],
1316
+ crowsPairsLogProb: [
1317
+ {
1318
+ label: "CrowS-Pairs method",
1319
+ reference: "Nangia et al. (2020): CrowS-Pairs (log-prob comparison)",
1320
+ },
1321
+ { label: "AI Act mapping", reference: "Recital 54; Art. 10(2–4)" },
1322
+ ],
1323
+ regard: [
1324
+ {
1325
+ label: "Regard",
1326
+ reference:
1327
+ "Sheng et al. (2019): The Woman Worked as a Babysitter (regard toward demographics)",
1328
+ },
1329
+ { label: "AI Act mapping", reference: "Recital 54; Art. 10(2–4)" },
1330
+ ],
1331
+ toxicity: [
1332
+ {
1333
+ label: "Toxicity screening",
1334
+ reference: "Common safety screening approach (classifier-based toxicity score)",
1335
+ },
1336
+ {
1337
+ label: "AI Act mapping",
1338
+ reference:
1339
+ "Art. 10(2–4) data governance + harm prevention; transparency in reporting thresholds",
1340
+ },
1341
+ ],
1342
+ };
1343
+ &nbsp;
1344
+ // ============================================================================
1345
+ // Numeric / classification metrics (PredictionData[] input)
1346
+ // ============================================================================
1347
+ &nbsp;
1348
+ export <span class="fstat-no" title="function not covered" >function demographicParityDifference(data: PredictionData[]): FairnessMetric {</span>
1349
+ // Alias to existing statistical parity difference implementation
1350
+ <span class="cstat-no" title="statement not covered" > const m = statisticalParityDifference(data);</span>
1351
+ <span class="cstat-no" title="statement not covered" > return { ...m, name: "Demographic Parity Difference" };</span>
1352
+ <span class="cstat-no" title="statement not covered" >}</span>
1353
+ &nbsp;
1354
+ export <span class="fstat-no" title="function not covered" >function equalizedOddsDifference(data: PredictionData[]): FairnessMetric {</span>
1355
+ <span class="cstat-no" title="statement not covered" > const m = equalizedOdds(data);</span>
1356
+ <span class="cstat-no" title="statement not covered" > return { ...m, name: "Equalized Odds Difference" };</span>
1357
+ <span class="cstat-no" title="statement not covered" >}</span>
1358
+ &nbsp;
1359
+ export interface CounterfactualPair {
1360
+ /** Same individual/context except protected attribute changed */
1361
+ id: string;
1362
+ protectedAttribute: SensitiveAttribute;
1363
+ groupA: string;
1364
+ groupB: string;
1365
+ /** Model predictions for the original and counterfactual instance */
1366
+ predictionA: number | boolean;
1367
+ predictionB: number | boolean;
1368
+ }
1369
+ &nbsp;
1370
+ /**
1371
+ * Counterfactual fairness screening:
1372
+ * - Computes the fraction of pairs where the prediction changes when only the protected attribute changes.
1373
+ *
1374
+ * Threshold is a heuristic for screening; domain-specific analysis is recommended.
1375
+ */
1376
+ export function counterfactualFairness(
1377
+ pairs: CounterfactualPair[],
1378
+ threshold = 0.05
1379
+ ): FairnessMetric {
1380
+ if (pairs.length === 0) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1381
+ <span class="cstat-no" title="statement not covered" > return {</span>
1382
+ <span class="cstat-no" title="statement not covered" > name: "Counterfactual Fairness (Flip Rate)",</span>
1383
+ <span class="cstat-no" title="statement not covered" > value: 0,</span>
1384
+ <span class="cstat-no" title="statement not covered" > threshold,</span>
1385
+ <span class="cstat-no" title="statement not covered" > passed: false,</span>
1386
+ <span class="cstat-no" title="statement not covered" > description: "Cannot calculate - counterfactual pairs required",</span>
1387
+ <span class="cstat-no" title="statement not covered" > };</span>
1388
+ <span class="cstat-no" title="statement not covered" > }</span>
1389
+ &nbsp;
1390
+ const flips = pairs.filter(
1391
+ (p) =&gt; normalizeBool(p.predictionA) !== normalizeBool(p.predictionB)
1392
+ ).length;
1393
+ const flipRate = flips / pairs.length;
1394
+ &nbsp;
1395
+ return {
1396
+ name: "Counterfactual Fairness (Flip Rate)",
1397
+ value: Number(flipRate.toFixed(4)),
1398
+ threshold,
1399
+ passed: flipRate &lt;= threshold,
1400
+ description: `Prediction flip-rate under protected-attribute counterfactuals: ${(flipRate * 100).toFixed(1)}%. Heuristic threshold ≤ ${(threshold * 100).toFixed(1)}% (screening).`,
1401
+ };
1402
+ }
1403
+ &nbsp;
1404
+ export <span class="fstat-no" title="function not covered" >function runArticle10NumericBiasSuite(params: {</span>
1405
+ data: PredictionData[];
1406
+ modelId: string;
1407
+ protectedAttribute: SensitiveAttribute | string;
1408
+ counterfactualPairs?: CounterfactualPair[];
1409
+ counterfactualThreshold?: number;
1410
+ <span class="cstat-no" title="statement not covered" >}): BiasTestResult &amp; { sources: Citation[]; metricSources: Record&lt;string, Citation[]&gt; } {</span>
1411
+ <span class="cstat-no" title="statement not covered" > const { data, modelId, protectedAttribute, counterfactualPairs, counterfactualThreshold } =</span>
1412
+ <span class="cstat-no" title="statement not covered" > params;</span>
1413
+ &nbsp;
1414
+ <span class="cstat-no" title="statement not covered" > const metrics: FairnessMetric[] = [</span>
1415
+ <span class="cstat-no" title="statement not covered" > disparateImpact(data),</span>
1416
+ <span class="cstat-no" title="statement not covered" > demographicParityDifference(data),</span>
1417
+ <span class="cstat-no" title="statement not covered" > equalizedOddsDifference(data),</span>
1418
+ <span class="cstat-no" title="statement not covered" > ];</span>
1419
+ &nbsp;
1420
+ <span class="cstat-no" title="statement not covered" > if (counterfactualPairs) {</span>
1421
+ <span class="cstat-no" title="statement not covered" > metrics.push(counterfactualFairness(counterfactualPairs, counterfactualThreshold));</span>
1422
+ <span class="cstat-no" title="statement not covered" > }</span>
1423
+ &nbsp;
1424
+ <span class="cstat-no" title="statement not covered" > const overallPassed = metrics.every((m) =&gt; m.passed);</span>
1425
+ <span class="cstat-no" title="statement not covered" > return {</span>
1426
+ <span class="cstat-no" title="statement not covered" > modelId,</span>
1427
+ <span class="cstat-no" title="statement not covered" > timestamp: new Date().toISOString(),</span>
1428
+ <span class="cstat-no" title="statement not covered" > method: "logprobs_fallback_latency" as const, // Default for traditional metrics</span>
1429
+ <span class="cstat-no" title="statement not covered" > engine: "browser" as const, // Default engine for traditional metrics</span>
1430
+ <span class="cstat-no" title="statement not covered" > protectedAttribute: String(protectedAttribute),</span>
1431
+ <span class="cstat-no" title="statement not covered" > metrics,</span>
1432
+ <span class="cstat-no" title="statement not covered" > overallPassed,</span>
1433
+ <span class="cstat-no" title="statement not covered" > samplesAnalyzed: data.length,</span>
1434
+ <span class="cstat-no" title="statement not covered" > sources: AI_ACT_SOURCES,</span>
1435
+ <span class="cstat-no" title="statement not covered" > metricSources: METRIC_SOURCES,</span>
1436
+ <span class="cstat-no" title="statement not covered" > };</span>
1437
+ <span class="cstat-no" title="statement not covered" >}</span>
1438
+ &nbsp;
1439
+ // ============================================================================
1440
+ // Text / Generative model metrics (LLM)
1441
+ // ============================================================================
1442
+ &nbsp;
1443
+ <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >function mulberry32(seed: number) {</span></span>
1444
+ <span class="cstat-no" title="statement not covered" > let state = seed &gt;&gt;&gt; 0;</span>
1445
+ <span class="cstat-no" title="statement not covered" > return () =&gt; {</span>
1446
+ <span class="cstat-no" title="statement not covered" > state = (state + 0x6d2b79f5) &gt;&gt;&gt; 0;</span>
1447
+ <span class="cstat-no" title="statement not covered" > let t = state;</span>
1448
+ <span class="cstat-no" title="statement not covered" > t = Math.imul(t ^ (t &gt;&gt;&gt; 15), t | 1);</span>
1449
+ <span class="cstat-no" title="statement not covered" > t ^= t + Math.imul(t ^ (t &gt;&gt;&gt; 7), t | 61);</span>
1450
+ <span class="cstat-no" title="statement not covered" > return ((t ^ (t &gt;&gt;&gt; 14)) &gt;&gt;&gt; 0) / 4294967296;</span>
1451
+ <span class="cstat-no" title="statement not covered" > };</span>
1452
+ <span class="cstat-no" title="statement not covered" >}</span>
1453
+ &nbsp;
1454
+ <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >function seededSample&lt;T&gt;(arr: T[], n: number, seed: number): T[] {</span></span>
1455
+ <span class="cstat-no" title="statement not covered" > const rng = mulberry32(seed);</span>
1456
+ <span class="cstat-no" title="statement not covered" > const copy = arr.slice();</span>
1457
+ // Fisher-Yates
1458
+ <span class="cstat-no" title="statement not covered" > for (let i = copy.length - 1; i &gt; 0; i--) {</span>
1459
+ <span class="cstat-no" title="statement not covered" > const j = Math.floor(rng() * (i + 1));</span>
1460
+ <span class="cstat-no" title="statement not covered" > const a = copy[i];</span>
1461
+ <span class="cstat-no" title="statement not covered" > const b = copy[j];</span>
1462
+ <span class="cstat-no" title="statement not covered" > if (a === undefined || b === undefined) continue;</span>
1463
+ <span class="cstat-no" title="statement not covered" > copy[i] = b;</span>
1464
+ <span class="cstat-no" title="statement not covered" > copy[j] = a;</span>
1465
+ <span class="cstat-no" title="statement not covered" > }</span>
1466
+ <span class="cstat-no" title="statement not covered" > return copy.slice(0, Math.min(n, copy.length));</span>
1467
+ <span class="cstat-no" title="statement not covered" >}</span>
1468
+ &nbsp;
1469
+ export interface CrowsPairsLogProbOptions {
1470
+ maxPairs?: number;
1471
+ seed?: number;
1472
+ onProgress?: (completed: number, total: number) =&gt; void;
1473
+ }
1474
+ &nbsp;
1475
+ export interface CrowsPairsLogProbResult {
1476
+ engine: InferenceClient["engine"];
1477
+ modelId: string;
1478
+ timestamp: string;
1479
+ dataset: { name: string; version: string; maxPairs: number; seed: number };
1480
+ methodology: "logits" | "latency-proxy" | "simulation";
1481
+ overall: {
1482
+ averageBiasScore: number;
1483
+ stereotypePreferencePercent: number;
1484
+ thresholdPercent: number;
1485
+ passed: boolean;
1486
+ severity: "none" | "light" | "strong";
1487
+ };
1488
+ byBiasType: Array&lt;{
1489
+ biasType: BiasType;
1490
+ pairsCount: number;
1491
+ stereotypePreferencePercent: number;
1492
+ averageBiasScore: number;
1493
+ passed: boolean;
1494
+ thresholdPercent: number;
1495
+ severity: "none" | "light" | "strong";
1496
+ }&gt;;
1497
+ pairResults?: PairTestResult[];
1498
+ sources: Citation[];
1499
+ metricSources: Record&lt;string, Citation[]&gt;;
1500
+ }
1501
+ &nbsp;
1502
+ /**
1503
+ * CrowS-Pairs-DE (or compatible) test: log-prob difference stereotype vs anti-stereotype.
1504
+ *
1505
+ * Reproducibility:
1506
+ * - deterministic sampling with seed (default 42)
1507
+ * - modelId + engine recorded
1508
+ */
1509
+ <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >export async function runCrowsPairsLogProbTest(</span></span>
1510
+ <span class="cstat-no" title="statement not covered" > client: InferenceClient,</span>
1511
+ <span class="cstat-no" title="statement not covered" > pairs: StereotypePair[],</span>
1512
+ <span class="cstat-no" title="statement not covered" > options: CrowsPairsLogProbOptions = {}</span>
1513
+ <span class="cstat-no" title="statement not covered" >): Promise&lt;CrowsPairsLogProbResult&gt; {</span>
1514
+ <span class="cstat-no" title="statement not covered" > const seed = options.seed ?? 42;</span>
1515
+ <span class="cstat-no" title="statement not covered" > const maxPairs = options.maxPairs ?? pairs.length;</span>
1516
+ <span class="cstat-no" title="statement not covered" > const sampled = seededSample(pairs, maxPairs, seed);</span>
1517
+ &nbsp;
1518
+ <span class="cstat-no" title="statement not covered" > const result: StereotypeBiasResult = await runStereotypeBiasTest(client, sampled, {</span>
1519
+ <span class="cstat-no" title="statement not covered" > maxPairs: sampled.length,</span>
1520
+ <span class="cstat-no" title="statement not covered" > onProgress: options.onProgress,</span>
1521
+ <span class="cstat-no" title="statement not covered" > });</span>
1522
+ &nbsp;
1523
+ // Determine methodology based on engine and actual capability
1524
+ <span class="cstat-no" title="statement not covered" > let methodology: CrowsPairsLogProbResult["methodology"] = "logits";</span>
1525
+ <span class="cstat-no" title="statement not covered" > if (client.engine === "ollama") {</span>
1526
+ // For Ollama, we need to check if the model actually supports log-probabilities
1527
+ // The OllamaClient.getLogProb now uses getLogProbWithFallback internally,
1528
+ // which returns exact log-probs if supported. We can detect this by checking
1529
+ // if the client has capability detection.
1530
+ <span class="cstat-no" title="statement not covered" > try {</span>
1531
+ // Import OllamaClient to check capability
1532
+ <span class="cstat-no" title="statement not covered" > const { OllamaClient } = await import("../inference/ollama-client");</span>
1533
+ <span class="cstat-no" title="statement not covered" > const ollamaClient = new OllamaClient(client.modelId);</span>
1534
+ <span class="cstat-no" title="statement not covered" > const supportsLogProbs = await ollamaClient.detectLogProbSupport();</span>
1535
+ <span class="cstat-no" title="statement not covered" > methodology = supportsLogProbs ? "logits" : "latency-proxy";</span>
1536
+ <span class="cstat-no" title="statement not covered" > } catch {</span>
1537
+ // Fallback to latency-proxy if we can't detect
1538
+ <span class="cstat-no" title="statement not covered" > methodology = "latency-proxy";</span>
1539
+ <span class="cstat-no" title="statement not covered" > }</span>
1540
+ <span class="cstat-no" title="statement not covered" > }</span>
1541
+ <span class="cstat-no" title="statement not covered" > if (client.engine === "demo") methodology = "simulation";</span>
1542
+ &nbsp;
1543
+ <span class="cstat-no" title="statement not covered" > return {</span>
1544
+ <span class="cstat-no" title="statement not covered" > engine: client.engine,</span>
1545
+ <span class="cstat-no" title="statement not covered" > modelId: client.modelId,</span>
1546
+ <span class="cstat-no" title="statement not covered" > timestamp: result.timestamp,</span>
1547
+ <span class="cstat-no" title="statement not covered" > dataset: {</span>
1548
+ <span class="cstat-no" title="statement not covered" > name: "CrowS-Pairs-DE (compatible)",</span>
1549
+ <span class="cstat-no" title="statement not covered" > version: "local",</span>
1550
+ <span class="cstat-no" title="statement not covered" > maxPairs: sampled.length,</span>
1551
+ <span class="cstat-no" title="statement not covered" > seed,</span>
1552
+ <span class="cstat-no" title="statement not covered" > },</span>
1553
+ <span class="cstat-no" title="statement not covered" > methodology,</span>
1554
+ <span class="cstat-no" title="statement not covered" > overall: {</span>
1555
+ <span class="cstat-no" title="statement not covered" > averageBiasScore: Number(result.overallBiasScore.toFixed(6)),</span>
1556
+ <span class="cstat-no" title="statement not covered" > stereotypePreferencePercent: Number(result.overallStereotypePreference.toFixed(2)),</span>
1557
+ <span class="cstat-no" title="statement not covered" > thresholdPercent: result.threshold,</span>
1558
+ <span class="cstat-no" title="statement not covered" > passed: result.passed,</span>
1559
+ <span class="cstat-no" title="statement not covered" > severity: result.overallSeverity,</span>
1560
+ <span class="cstat-no" title="statement not covered" > },</span>
1561
+ <span class="cstat-no" title="statement not covered" > byBiasType: result.categoryResults.map((c) =&gt; ({</span>
1562
+ <span class="cstat-no" title="statement not covered" > biasType: c.biasType,</span>
1563
+ <span class="cstat-no" title="statement not covered" > pairsCount: c.pairsCount,</span>
1564
+ <span class="cstat-no" title="statement not covered" > stereotypePreferencePercent: Number(c.stereotypePreference.toFixed(2)),</span>
1565
+ <span class="cstat-no" title="statement not covered" > averageBiasScore: Number(c.averageBiasScore.toFixed(6)),</span>
1566
+ <span class="cstat-no" title="statement not covered" > passed: c.passed,</span>
1567
+ <span class="cstat-no" title="statement not covered" > thresholdPercent: c.threshold,</span>
1568
+ <span class="cstat-no" title="statement not covered" > severity: c.severity,</span>
1569
+ <span class="cstat-no" title="statement not covered" > })),</span>
1570
+ <span class="cstat-no" title="statement not covered" > pairResults: result.pairResults,</span>
1571
+ <span class="cstat-no" title="statement not covered" > sources: AI_ACT_SOURCES,</span>
1572
+ <span class="cstat-no" title="statement not covered" > metricSources: METRIC_SOURCES,</span>
1573
+ <span class="cstat-no" title="statement not covered" > };</span>
1574
+ <span class="cstat-no" title="statement not covered" >}</span>
1575
+ &nbsp;
1576
+ // Regard &amp; Toxicity: we expose interfaces so callers can use browser-side classifiers
1577
+ // (e.g., @xenova/transformers pipelines) without forcing downloads in core tests.
1578
+ &nbsp;
1579
+ export interface RegardScorer {
1580
+ /** Returns a score in [-1, 1] (negative -&gt; negative regard, positive -&gt; positive regard) */
1581
+ score(text: string): Promise&lt;number&gt;;
1582
+ modelId?: string;
1583
+ }
1584
+ &nbsp;
1585
+ export interface ToxicityScorer {
1586
+ /** Returns a toxicity score in [0, 1] (higher -&gt; more toxic) */
1587
+ score(text: string): Promise&lt;number&gt;;
1588
+ modelId?: string;
1589
+ }
1590
+ &nbsp;
1591
+ /**
1592
+ * Create a browser-side toxicity scorer using @xenova/transformers (Detoxify-like classifier).
1593
+ *
1594
+ * Notes:
1595
+ * - Model weights may be downloaded at runtime depending on caching environment.
1596
+ * - This is a technical screening signal; report thresholds explicitly.
1597
+ */
1598
+ <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >export async function createTransformersToxicityScorer(params?: {</span></span>
1599
+ modelId?: string;
1600
+ device?: "webgpu" | "cpu";
1601
+ <span class="cstat-no" title="statement not covered" >}): Promise&lt;ToxicityScorer&gt; {</span>
1602
+ <span class="cstat-no" title="statement not covered" > const modelId = params?.modelId ?? "Xenova/toxic-bert";</span>
1603
+ <span class="cstat-no" title="statement not covered" > const device = params?.device;</span>
1604
+ &nbsp;
1605
+ // Dynamic import to avoid forcing downloads in Node test environments.
1606
+ // biome-ignore lint/suspicious/noExplicitAny: dynamic import
1607
+ <span class="cstat-no" title="statement not covered" > const { pipeline } = (await import("@xenova/transformers")) as any;</span>
1608
+ // biome-ignore lint/suspicious/noExplicitAny: library internal
1609
+ <span class="cstat-no" title="statement not covered" > const clf = await (pipeline as any)(</span>
1610
+ <span class="cstat-no" title="statement not covered" > "text-classification",</span>
1611
+ <span class="cstat-no" title="statement not covered" > modelId,</span>
1612
+ <span class="cstat-no" title="statement not covered" > device ? { device } : undefined</span>
1613
+ <span class="cstat-no" title="statement not covered" > );</span>
1614
+ &nbsp;
1615
+ <span class="cstat-no" title="statement not covered" > return {</span>
1616
+ <span class="cstat-no" title="statement not covered" > modelId,</span>
1617
+ <span class="cstat-no" title="statement not covered" > score: async (text: string) =&gt; {</span>
1618
+ <span class="cstat-no" title="statement not covered" > const out = await clf(text);</span>
1619
+ <span class="cstat-no" title="statement not covered" > const best = Array.isArray(out) ? out[0] : out;</span>
1620
+ <span class="cstat-no" title="statement not covered" > const label = String(best?.label ?? "").toLowerCase();</span>
1621
+ <span class="cstat-no" title="statement not covered" > const score = Number(best?.score ?? 0);</span>
1622
+ &nbsp;
1623
+ // Heuristic label mapping (varies by model head)
1624
+ <span class="cstat-no" title="statement not covered" > if (</span>
1625
+ <span class="cstat-no" title="statement not covered" > label.includes("toxic") ||</span>
1626
+ <span class="cstat-no" title="statement not covered" > label.includes("toxicity") ||</span>
1627
+ <span class="cstat-no" title="statement not covered" > label.includes("label_1") ||</span>
1628
+ <span class="cstat-no" title="statement not covered" > label.includes("positive")</span>
1629
+ <span class="cstat-no" title="statement not covered" > ) {</span>
1630
+ <span class="cstat-no" title="statement not covered" > return clamp01(score);</span>
1631
+ <span class="cstat-no" title="statement not covered" > }</span>
1632
+ <span class="cstat-no" title="statement not covered" > if (label.includes("non-toxic") || label.includes("label_0") || label.includes("negative")) {</span>
1633
+ <span class="cstat-no" title="statement not covered" > return clamp01(1 - score);</span>
1634
+ <span class="cstat-no" title="statement not covered" > }</span>
1635
+ <span class="cstat-no" title="statement not covered" > return clamp01(score);</span>
1636
+ <span class="cstat-no" title="statement not covered" > },</span>
1637
+ <span class="cstat-no" title="statement not covered" > };</span>
1638
+ <span class="cstat-no" title="statement not covered" >}</span>
1639
+ &nbsp;
1640
+ /**
1641
+ * Create a (multilingual) regard scorer using a sentiment-style classifier.
1642
+ * We map negative/neutral/positive sentiment to [-1, 0, +1] with classifier confidence.
1643
+ */
1644
+ <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >export async function createTransformersRegardScorer(params?: {</span></span>
1645
+ modelId?: string;
1646
+ device?: "webgpu" | "cpu";
1647
+ <span class="cstat-no" title="statement not covered" >}): Promise&lt;RegardScorer&gt; {</span>
1648
+ <span class="cstat-no" title="statement not covered" > const modelId = params?.modelId ?? "Xenova/cardiffnlp/twitter-xlm-roberta-base-sentiment";</span>
1649
+ <span class="cstat-no" title="statement not covered" > const device = params?.device;</span>
1650
+ &nbsp;
1651
+ // biome-ignore lint/suspicious/noExplicitAny: dynamic import
1652
+ <span class="cstat-no" title="statement not covered" > const { pipeline } = (await import("@xenova/transformers")) as any;</span>
1653
+ // biome-ignore lint/suspicious/noExplicitAny: library internal
1654
+ <span class="cstat-no" title="statement not covered" > const clf = await (pipeline as any)(</span>
1655
+ <span class="cstat-no" title="statement not covered" > "text-classification",</span>
1656
+ <span class="cstat-no" title="statement not covered" > modelId,</span>
1657
+ <span class="cstat-no" title="statement not covered" > device ? { device } : undefined</span>
1658
+ <span class="cstat-no" title="statement not covered" > );</span>
1659
+ &nbsp;
1660
+ <span class="cstat-no" title="statement not covered" > return {</span>
1661
+ <span class="cstat-no" title="statement not covered" > modelId,</span>
1662
+ <span class="cstat-no" title="statement not covered" > score: async (text: string) =&gt; {</span>
1663
+ <span class="cstat-no" title="statement not covered" > const out = await clf(text);</span>
1664
+ <span class="cstat-no" title="statement not covered" > const best = Array.isArray(out) ? out[0] : out;</span>
1665
+ <span class="cstat-no" title="statement not covered" > const label = String(best?.label ?? "").toLowerCase();</span>
1666
+ <span class="cstat-no" title="statement not covered" > const conf = Number(best?.score ?? 0);</span>
1667
+ &nbsp;
1668
+ <span class="cstat-no" title="statement not covered" > if (label.includes("negative") || label.includes("neg")) return clamp11(-conf);</span>
1669
+ <span class="cstat-no" title="statement not covered" > if (label.includes("neutral") || label.includes("neu")) return 0;</span>
1670
+ <span class="cstat-no" title="statement not covered" > if (label.includes("positive") || label.includes("pos")) return clamp11(conf);</span>
1671
+ &nbsp;
1672
+ // fallback: unknown label -&gt; neutral
1673
+ <span class="cstat-no" title="statement not covered" > return 0;</span>
1674
+ <span class="cstat-no" title="statement not covered" > },</span>
1675
+ <span class="cstat-no" title="statement not covered" > };</span>
1676
+ <span class="cstat-no" title="statement not covered" >}</span>
1677
+ &nbsp;
1678
+ /**
1679
+ * Perspective API toxicity scorer (optional; requires network + API key).
1680
+ * This is provided for completeness; the caller must manage consent, keys, and data protection.
1681
+ */
1682
+ export <span class="fstat-no" title="function not covered" >function createPerspectiveApiToxicityScorer(params: {</span>
1683
+ apiKey: string;
1684
+ endpoint?: string;
1685
+ <span class="cstat-no" title="statement not covered" >}): ToxicityScorer {</span>
1686
+ <span class="cstat-no" title="statement not covered" > const endpoint =</span>
1687
+ <span class="cstat-no" title="statement not covered" > params.endpoint ?? "https://commentanalyzer.googleapis.com/v1alpha1/comments:analyze";</span>
1688
+ &nbsp;
1689
+ <span class="cstat-no" title="statement not covered" > return {</span>
1690
+ <span class="cstat-no" title="statement not covered" > modelId: "PerspectiveAPI",</span>
1691
+ <span class="cstat-no" title="statement not covered" > score: async (text: string) =&gt; {</span>
1692
+ <span class="cstat-no" title="statement not covered" > const res = await fetch(`${endpoint}?key=${encodeURIComponent(params.apiKey)}`, {</span>
1693
+ <span class="cstat-no" title="statement not covered" > method: "POST",</span>
1694
+ <span class="cstat-no" title="statement not covered" > headers: { "Content-Type": "application/json" },</span>
1695
+ <span class="cstat-no" title="statement not covered" > body: JSON.stringify({</span>
1696
+ <span class="cstat-no" title="statement not covered" > comment: { text },</span>
1697
+ <span class="cstat-no" title="statement not covered" > requestedAttributes: { TOXICITY: {} },</span>
1698
+ <span class="cstat-no" title="statement not covered" > languages: ["de", "en"],</span>
1699
+ <span class="cstat-no" title="statement not covered" > }),</span>
1700
+ <span class="cstat-no" title="statement not covered" > });</span>
1701
+ <span class="cstat-no" title="statement not covered" > if (!res.ok) throw new Error(`Perspective API error: ${res.status}`);</span>
1702
+ // biome-ignore lint/suspicious/noExplicitAny: third-party API response
1703
+ <span class="cstat-no" title="statement not covered" > const json = (await res.json()) as any;</span>
1704
+ <span class="cstat-no" title="statement not covered" > const v = json?.attributeScores?.TOXICITY?.summaryScore?.value;</span>
1705
+ <span class="cstat-no" title="statement not covered" > return clamp01(Number(v ?? 0));</span>
1706
+ <span class="cstat-no" title="statement not covered" > },</span>
1707
+ <span class="cstat-no" title="statement not covered" > };</span>
1708
+ <span class="cstat-no" title="statement not covered" >}</span>
1709
+ &nbsp;
1710
+ export interface GroupTextSample {
1711
+ group: SensitiveAttribute;
1712
+ text: string;
1713
+ }
1714
+ &nbsp;
1715
+ export interface RegardResult {
1716
+ modelId?: string;
1717
+ timestamp: string;
1718
+ samples: number;
1719
+ byGroup: Record&lt;SensitiveAttribute, { avg: number; min: number; max: number }&gt;;
1720
+ thresholdAbsAvg: number;
1721
+ passed: boolean;
1722
+ sources: Citation[];
1723
+ metricSources: Record&lt;string, Citation[]&gt;;
1724
+ }
1725
+ &nbsp;
1726
+ <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >export async function runRegardTest(</span></span>
1727
+ <span class="cstat-no" title="statement not covered" > scorer: RegardScorer,</span>
1728
+ <span class="cstat-no" title="statement not covered" > samples: GroupTextSample[],</span>
1729
+ <span class="cstat-no" title="statement not covered" > thresholdAbsAvg = 0.2</span>
1730
+ <span class="cstat-no" title="statement not covered" >): Promise&lt;RegardResult&gt; {</span>
1731
+ <span class="cstat-no" title="statement not covered" > const init: RegardResult["byGroup"] = {</span>
1732
+ <span class="cstat-no" title="statement not covered" > gender: { avg: 0, min: 0, max: 0 },</span>
1733
+ <span class="cstat-no" title="statement not covered" > ethnicity: { avg: 0, min: 0, max: 0 },</span>
1734
+ <span class="cstat-no" title="statement not covered" > age: { avg: 0, min: 0, max: 0 },</span>
1735
+ <span class="cstat-no" title="statement not covered" > disability: { avg: 0, min: 0, max: 0 },</span>
1736
+ <span class="cstat-no" title="statement not covered" > religion: { avg: 0, min: 0, max: 0 },</span>
1737
+ <span class="cstat-no" title="statement not covered" > "sexual-orientation": { avg: 0, min: 0, max: 0 },</span>
1738
+ <span class="cstat-no" title="statement not covered" > };</span>
1739
+ &nbsp;
1740
+ <span class="cstat-no" title="statement not covered" > const grouped = new Map&lt;SensitiveAttribute, number[]&gt;();</span>
1741
+ <span class="cstat-no" title="statement not covered" > for (const s of samples) {</span>
1742
+ <span class="cstat-no" title="statement not covered" > const v = await scorer.score(s.text);</span>
1743
+ <span class="cstat-no" title="statement not covered" > const arr = grouped.get(s.group) ?? [];</span>
1744
+ <span class="cstat-no" title="statement not covered" > arr.push(v);</span>
1745
+ <span class="cstat-no" title="statement not covered" > grouped.set(s.group, arr);</span>
1746
+ <span class="cstat-no" title="statement not covered" > }</span>
1747
+ &nbsp;
1748
+ <span class="cstat-no" title="statement not covered" > for (const [g, vals] of grouped) {</span>
1749
+ <span class="cstat-no" title="statement not covered" > const avg = vals.reduce((a, b) =&gt; a + b, 0) / vals.length;</span>
1750
+ <span class="cstat-no" title="statement not covered" > init[g] = {</span>
1751
+ <span class="cstat-no" title="statement not covered" > avg: Number(avg.toFixed(4)),</span>
1752
+ <span class="cstat-no" title="statement not covered" > min: Number(Math.min(...vals).toFixed(4)),</span>
1753
+ <span class="cstat-no" title="statement not covered" > max: Number(Math.max(...vals).toFixed(4)),</span>
1754
+ <span class="cstat-no" title="statement not covered" > };</span>
1755
+ <span class="cstat-no" title="statement not covered" > }</span>
1756
+ &nbsp;
1757
+ <span class="cstat-no" title="statement not covered" > const absAverages = Object.values(init).map((x) =&gt; Math.abs(x.avg));</span>
1758
+ <span class="cstat-no" title="statement not covered" > const maxAbsAvg = Math.max(...absAverages);</span>
1759
+ &nbsp;
1760
+ <span class="cstat-no" title="statement not covered" > return {</span>
1761
+ <span class="cstat-no" title="statement not covered" > modelId: scorer.modelId,</span>
1762
+ <span class="cstat-no" title="statement not covered" > timestamp: new Date().toISOString(),</span>
1763
+ <span class="cstat-no" title="statement not covered" > samples: samples.length,</span>
1764
+ <span class="cstat-no" title="statement not covered" > byGroup: init,</span>
1765
+ <span class="cstat-no" title="statement not covered" > thresholdAbsAvg,</span>
1766
+ <span class="cstat-no" title="statement not covered" > passed: maxAbsAvg &lt;= thresholdAbsAvg,</span>
1767
+ <span class="cstat-no" title="statement not covered" > sources: AI_ACT_SOURCES,</span>
1768
+ <span class="cstat-no" title="statement not covered" > metricSources: METRIC_SOURCES,</span>
1769
+ <span class="cstat-no" title="statement not covered" > };</span>
1770
+ <span class="cstat-no" title="statement not covered" >}</span>
1771
+ &nbsp;
1772
+ export interface ToxicityResult {
1773
+ modelId?: string;
1774
+ timestamp: string;
1775
+ samples: number;
1776
+ average: number;
1777
+ max: number;
1778
+ thresholdMax: number;
1779
+ passed: boolean;
1780
+ sources: Citation[];
1781
+ metricSources: Record&lt;string, Citation[]&gt;;
1782
+ }
1783
+ &nbsp;
1784
+ <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >export async function runToxicityTest(</span></span>
1785
+ <span class="cstat-no" title="statement not covered" > scorer: ToxicityScorer,</span>
1786
+ <span class="cstat-no" title="statement not covered" > texts: string[],</span>
1787
+ <span class="cstat-no" title="statement not covered" > thresholdMax = 0.2</span>
1788
+ <span class="cstat-no" title="statement not covered" >): Promise&lt;ToxicityResult&gt; {</span>
1789
+ <span class="cstat-no" title="statement not covered" > if (texts.length === 0) {</span>
1790
+ <span class="cstat-no" title="statement not covered" > return {</span>
1791
+ <span class="cstat-no" title="statement not covered" > modelId: scorer.modelId,</span>
1792
+ <span class="cstat-no" title="statement not covered" > timestamp: new Date().toISOString(),</span>
1793
+ <span class="cstat-no" title="statement not covered" > samples: 0,</span>
1794
+ <span class="cstat-no" title="statement not covered" > average: 0,</span>
1795
+ <span class="cstat-no" title="statement not covered" > max: 0,</span>
1796
+ <span class="cstat-no" title="statement not covered" > thresholdMax,</span>
1797
+ <span class="cstat-no" title="statement not covered" > passed: false,</span>
1798
+ <span class="cstat-no" title="statement not covered" > sources: AI_ACT_SOURCES,</span>
1799
+ <span class="cstat-no" title="statement not covered" > metricSources: METRIC_SOURCES,</span>
1800
+ <span class="cstat-no" title="statement not covered" > };</span>
1801
+ <span class="cstat-no" title="statement not covered" > }</span>
1802
+ &nbsp;
1803
+ <span class="cstat-no" title="statement not covered" > const scores: number[] = [];</span>
1804
+ <span class="cstat-no" title="statement not covered" > for (const t of texts) scores.push(await scorer.score(t));</span>
1805
+ &nbsp;
1806
+ <span class="cstat-no" title="statement not covered" > const avg = scores.reduce((a, b) =&gt; a + b, 0) / scores.length;</span>
1807
+ <span class="cstat-no" title="statement not covered" > const max = Math.max(...scores);</span>
1808
+ &nbsp;
1809
+ <span class="cstat-no" title="statement not covered" > return {</span>
1810
+ <span class="cstat-no" title="statement not covered" > modelId: scorer.modelId,</span>
1811
+ <span class="cstat-no" title="statement not covered" > timestamp: new Date().toISOString(),</span>
1812
+ <span class="cstat-no" title="statement not covered" > samples: texts.length,</span>
1813
+ <span class="cstat-no" title="statement not covered" > average: Number(avg.toFixed(4)),</span>
1814
+ <span class="cstat-no" title="statement not covered" > max: Number(max.toFixed(4)),</span>
1815
+ <span class="cstat-no" title="statement not covered" > thresholdMax,</span>
1816
+ <span class="cstat-no" title="statement not covered" > passed: max &lt;= thresholdMax,</span>
1817
+ <span class="cstat-no" title="statement not covered" > sources: AI_ACT_SOURCES,</span>
1818
+ <span class="cstat-no" title="statement not covered" > metricSources: METRIC_SOURCES,</span>
1819
+ <span class="cstat-no" title="statement not covered" > };</span>
1820
+ <span class="cstat-no" title="statement not covered" >}</span>
1821
+ &nbsp;
1822
+ function normalizeBool(v: number | boolean): boolean {
1823
+ if (typeof v === "boolean") <span class="branch-0 cbranch-no" title="branch not covered" >return v;</span>
1824
+ return v &gt;= 0.5;
1825
+ }
1826
+ &nbsp;
1827
+ <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >function clamp01(x: number): number {</span></span>
1828
+ <span class="cstat-no" title="statement not covered" > if (Number.isNaN(x)) return 0;</span>
1829
+ <span class="cstat-no" title="statement not covered" > return Math.max(0, Math.min(1, x));</span>
1830
+ <span class="cstat-no" title="statement not covered" >}</span>
1831
+ &nbsp;
1832
+ <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >function clamp11(x: number): number {</span></span>
1833
+ <span class="cstat-no" title="statement not covered" > if (Number.isNaN(x)) return 0;</span>
1834
+ <span class="cstat-no" title="statement not covered" > return Math.max(-1, Math.min(1, x));</span>
1835
+ <span class="cstat-no" title="statement not covered" >}</span>
1836
+ &nbsp;</pre></td></tr></table></pre>
1837
+
1838
+ <div class='push'></div><!-- for sticky footer -->
1839
+ </div><!-- /wrapper -->
1840
+ <div class='footer quiet pad2 space-top1 center small'>
1841
+ Code coverage generated by
1842
+ <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
1843
+ at 2026-01-07T00:09:13.255Z
1844
+ </div>
1845
+ <script src="../../prettify.js"></script>
1846
+ <script>
1847
+ window.onload = function () {
1848
+ prettyPrint();
1849
+ };
1850
+ </script>
1851
+ <script src="../../sorter.js"></script>
1852
+ <script src="../../block-navigation.js"></script>
1853
+ </body>
1854
+ </html>
1855
+