@euconform/core 1.0.1 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +12 -0
  3. package/dist/evidence/bundle.d.ts +23 -0
  4. package/dist/evidence/bundle.d.ts.map +1 -0
  5. package/dist/evidence/bundle.js +44 -0
  6. package/dist/evidence/compliance-evaluation.d.ts +12 -0
  7. package/dist/evidence/compliance-evaluation.d.ts.map +1 -0
  8. package/dist/evidence/compliance-evaluation.js +78 -0
  9. package/dist/evidence/hash.d.ts +2 -0
  10. package/dist/evidence/hash.d.ts.map +1 -0
  11. package/dist/evidence/hash.js +4 -0
  12. package/dist/evidence/index.d.ts +13 -0
  13. package/dist/evidence/index.d.ts.map +1 -0
  14. package/dist/evidence/index.js +11 -0
  15. package/dist/evidence/markdown.d.ts +9 -0
  16. package/dist/evidence/markdown.d.ts.map +1 -0
  17. package/dist/evidence/markdown.js +169 -0
  18. package/dist/evidence/output.d.ts +13 -0
  19. package/dist/evidence/output.d.ts.map +1 -0
  20. package/dist/evidence/output.js +547 -0
  21. package/dist/evidence/types.d.ts +230 -0
  22. package/dist/evidence/types.d.ts.map +1 -0
  23. package/dist/evidence/types.js +7 -0
  24. package/dist/evidence/validate.d.ts +8 -0
  25. package/dist/evidence/validate.d.ts.map +1 -0
  26. package/dist/evidence/validate.js +175 -0
  27. package/dist/index.d.ts +2 -2
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +1 -1
  30. package/dist/inference/ollama-client.d.ts +3 -0
  31. package/dist/inference/ollama-client.d.ts.map +1 -1
  32. package/dist/inference/ollama-client.js +69 -71
  33. package/dist/legal-checks/annex-iv-report.d.ts +3 -0
  34. package/dist/legal-checks/annex-iv-report.d.ts.map +1 -1
  35. package/dist/legal-checks/annex-iv-report.js +1 -0
  36. package/dist/legal-checks/deadline-timeline.d.ts +57 -0
  37. package/dist/legal-checks/deadline-timeline.d.ts.map +1 -0
  38. package/dist/legal-checks/deadline-timeline.js +265 -0
  39. package/dist/legal-checks/gap-analysis.d.ts +48 -0
  40. package/dist/legal-checks/gap-analysis.d.ts.map +1 -0
  41. package/dist/legal-checks/gap-analysis.js +397 -0
  42. package/dist/legal-checks/gpai-classifier.d.ts +49 -0
  43. package/dist/legal-checks/gpai-classifier.d.ts.map +1 -0
  44. package/dist/legal-checks/gpai-classifier.js +197 -0
  45. package/dist/legal-checks/index.d.ts +6 -0
  46. package/dist/legal-checks/index.d.ts.map +1 -1
  47. package/dist/legal-checks/index.js +3 -0
  48. package/dist/scanner/aggregator.d.ts +7 -0
  49. package/dist/scanner/aggregator.d.ts.map +1 -0
  50. package/dist/scanner/aggregator.js +200 -0
  51. package/dist/scanner/detectors/ai-framework-detector.d.ts +3 -0
  52. package/dist/scanner/detectors/ai-framework-detector.d.ts.map +1 -0
  53. package/dist/scanner/detectors/ai-framework-detector.js +74 -0
  54. package/dist/scanner/detectors/ai-provider-detector.d.ts +3 -0
  55. package/dist/scanner/detectors/ai-provider-detector.d.ts.map +1 -0
  56. package/dist/scanner/detectors/ai-provider-detector.js +100 -0
  57. package/dist/scanner/detectors/compliance-detector.d.ts +3 -0
  58. package/dist/scanner/detectors/compliance-detector.d.ts.map +1 -0
  59. package/dist/scanner/detectors/compliance-detector.js +201 -0
  60. package/dist/scanner/detectors/config-detector.d.ts +3 -0
  61. package/dist/scanner/detectors/config-detector.d.ts.map +1 -0
  62. package/dist/scanner/detectors/config-detector.js +248 -0
  63. package/dist/scanner/detectors/framework-detector.d.ts +3 -0
  64. package/dist/scanner/detectors/framework-detector.d.ts.map +1 -0
  65. package/dist/scanner/detectors/framework-detector.js +141 -0
  66. package/dist/scanner/detectors/index.d.ts +8 -0
  67. package/dist/scanner/detectors/index.d.ts.map +1 -0
  68. package/dist/scanner/detectors/index.js +37 -0
  69. package/dist/scanner/detectors/local-inference-detector.d.ts +3 -0
  70. package/dist/scanner/detectors/local-inference-detector.d.ts.map +1 -0
  71. package/dist/scanner/detectors/local-inference-detector.js +93 -0
  72. package/dist/scanner/detectors/markdown-detector.d.ts +3 -0
  73. package/dist/scanner/detectors/markdown-detector.d.ts.map +1 -0
  74. package/dist/scanner/detectors/markdown-detector.js +139 -0
  75. package/dist/scanner/detectors/package-json-detector.d.ts +3 -0
  76. package/dist/scanner/detectors/package-json-detector.d.ts.map +1 -0
  77. package/dist/scanner/detectors/package-json-detector.js +166 -0
  78. package/dist/scanner/detectors/rag-detector.d.ts +3 -0
  79. package/dist/scanner/detectors/rag-detector.d.ts.map +1 -0
  80. package/dist/scanner/detectors/rag-detector.js +132 -0
  81. package/dist/scanner/detectors/shared.d.ts +18 -0
  82. package/dist/scanner/detectors/shared.d.ts.map +1 -0
  83. package/dist/scanner/detectors/shared.js +36 -0
  84. package/dist/scanner/discovery.d.ts +14 -0
  85. package/dist/scanner/discovery.d.ts.map +1 -0
  86. package/dist/scanner/discovery.js +235 -0
  87. package/dist/scanner/index.d.ts +9 -0
  88. package/dist/scanner/index.d.ts.map +1 -0
  89. package/dist/scanner/index.js +8 -0
  90. package/package.json +6 -3
  91. package/src/evidence/bundle.ts +65 -0
  92. package/src/evidence/compliance-evaluation.ts +114 -0
  93. package/src/evidence/hash.ts +5 -0
  94. package/src/evidence/index.ts +51 -0
  95. package/src/evidence/markdown.ts +226 -0
  96. package/src/evidence/output.ts +717 -0
  97. package/src/evidence/types.ts +329 -0
  98. package/src/evidence/validate.ts +270 -0
  99. package/src/index.ts +25 -0
  100. package/src/inference/ollama-client.ts +93 -86
  101. package/src/legal-checks/annex-iv-report.ts +4 -0
  102. package/src/legal-checks/deadline-timeline.ts +313 -0
  103. package/src/legal-checks/gap-analysis.ts +454 -0
  104. package/src/legal-checks/gpai-classifier.ts +281 -0
  105. package/src/legal-checks/index.ts +33 -0
  106. package/src/scanner/aggregator.ts +258 -0
  107. package/src/scanner/detectors/ai-framework-detector.ts +94 -0
  108. package/src/scanner/detectors/ai-provider-detector.ts +135 -0
  109. package/src/scanner/detectors/compliance-detector.ts +232 -0
  110. package/src/scanner/detectors/config-detector.ts +316 -0
  111. package/src/scanner/detectors/framework-detector.ts +163 -0
  112. package/src/scanner/detectors/index.ts +40 -0
  113. package/src/scanner/detectors/local-inference-detector.ts +124 -0
  114. package/src/scanner/detectors/markdown-detector.ts +176 -0
  115. package/src/scanner/detectors/package-json-detector.ts +202 -0
  116. package/src/scanner/detectors/rag-detector.ts +162 -0
  117. package/src/scanner/detectors/shared.ts +45 -0
  118. package/src/scanner/discovery.ts +290 -0
  119. package/src/scanner/index.ts +9 -0
  120. package/tests/evidence/bundle.test.ts +128 -0
  121. package/tests/evidence/ecef-schemas.test.ts +316 -0
  122. package/tests/evidence/hash.test.ts +25 -0
  123. package/tests/evidence/markdown.test.ts +92 -0
  124. package/tests/evidence/output.test.ts +203 -0
  125. package/tests/fixtures/compliance-good/README.md +14 -0
  126. package/tests/fixtures/compliance-good/lib/ai-service.ts +17 -0
  127. package/tests/fixtures/compliance-good/lib/review-flow.ts +11 -0
  128. package/tests/fixtures/compliance-good/package.json +10 -0
  129. package/tests/fixtures/compliance-good/tests/bias-check.test.ts +13 -0
  130. package/tests/fixtures/nextjs-openai/README.md +5 -0
  131. package/tests/fixtures/nextjs-openai/app/page.tsx +11 -0
  132. package/tests/fixtures/nextjs-openai/package.json +9 -0
  133. package/tests/fixtures/ollama-rag/.env.example +2 -0
  134. package/tests/fixtures/ollama-rag/docker-compose.yml +9 -0
  135. package/tests/fixtures/ollama-rag/package.json +9 -0
  136. package/tests/fixtures/ollama-rag/server.ts +21 -0
  137. package/tests/fixtures/plain-webapp/README.md +3 -0
  138. package/tests/fixtures/plain-webapp/index.js +5 -0
  139. package/tests/fixtures/plain-webapp/package.json +8 -0
  140. package/tests/gpai-classifier.test.ts +125 -0
  141. package/tests/gpai-timeline.test.ts +55 -0
  142. package/tests/scanner/aggregator.test.ts +122 -0
  143. package/tests/scanner/detectors.test.ts +274 -0
  144. package/tests/scanner/discovery.test.ts +87 -0
  145. package/vitest.config.ts +1 -0
  146. package/.turbo/turbo-check-types.log +0 -4
  147. package/.turbo/turbo-test.log +0 -364
  148. package/coverage/base.css +0 -224
  149. package/coverage/block-navigation.js +0 -87
  150. package/coverage/clover.xml +0 -3282
  151. package/coverage/coverage-final.json +0 -20
  152. package/coverage/favicon.png +0 -0
  153. package/coverage/index.html +0 -161
  154. package/coverage/prettify.css +0 -1
  155. package/coverage/prettify.js +0 -2
  156. package/coverage/sort-arrow-sprite.png +0 -0
  157. package/coverage/sorter.js +0 -210
  158. package/coverage/src/fairness-metrics.ts.html +0 -1579
  159. package/coverage/src/index.html +0 -161
  160. package/coverage/src/index.ts.html +0 -535
  161. package/coverage/src/inference/browser-inference.ts.html +0 -859
  162. package/coverage/src/inference/capability-detection.ts.html +0 -2227
  163. package/coverage/src/inference/index.html +0 -176
  164. package/coverage/src/inference/index.ts.html +0 -553
  165. package/coverage/src/inference/inference-factory.ts.html +0 -751
  166. package/coverage/src/inference/ollama-client.ts.html +0 -1627
  167. package/coverage/src/legal-checks/annex-iv-report.ts.html +0 -556
  168. package/coverage/src/legal-checks/bias-metrics.ts.html +0 -1855
  169. package/coverage/src/legal-checks/data-governance.ts.html +0 -529
  170. package/coverage/src/legal-checks/human-oversight-logging.ts.html +0 -490
  171. package/coverage/src/legal-checks/index.html +0 -206
  172. package/coverage/src/legal-checks/index.ts.html +0 -250
  173. package/coverage/src/legal-checks/risk-classifier.ts.html +0 -940
  174. package/coverage/src/legal-checks/robustness-transparency.ts.html +0 -571
  175. package/coverage/src/metrics/crows-pairs-bias.ts.html +0 -820
  176. package/coverage/src/metrics/index.html +0 -146
  177. package/coverage/src/metrics/index.ts.html +0 -151
  178. package/coverage/src/metrics/stereotype-bias.ts.html +0 -886
  179. package/coverage/src/risk-engine.ts.html +0 -1660
  180. package/coverage/src/types.ts.html +0 -547
  181. package/dist/legal-checks/disclaimer.d.ts +0 -2
  182. package/dist/legal-checks/disclaimer.d.ts.map +0 -1
  183. package/dist/legal-checks/disclaimer.js +0 -1
@@ -1,1579 +0,0 @@
1
-
2
- <!doctype html>
3
- <html lang="en">
4
-
5
- <head>
6
- <title>Code coverage report for src/fairness-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</a> fairness-metrics.ts</h1>
23
- <div class='clearfix'>
24
-
25
- <div class='fl pad1y space-right2'>
26
- <span class="strong">46.4% </span>
27
- <span class="quiet">Statements</span>
28
- <span class='fraction'>168/362</span>
29
- </div>
30
-
31
-
32
- <div class='fl pad1y space-right2'>
33
- <span class="strong">96.07% </span>
34
- <span class="quiet">Branches</span>
35
- <span class='fraction'>49/51</span>
36
- </div>
37
-
38
-
39
- <div class='fl pad1y space-right2'>
40
- <span class="strong">63.63% </span>
41
- <span class="quiet">Functions</span>
42
- <span class='fraction'>7/11</span>
43
- </div>
44
-
45
-
46
- <div class='fl pad1y space-right2'>
47
- <span class="strong">46.4% </span>
48
- <span class="quiet">Lines</span>
49
- <span class='fraction'>168/362</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></td><td class="line-coverage quiet"><span class="cline-any cline-yes">1x</span>
565
- <span class="cline-any cline-neutral">&nbsp;</span>
566
- <span class="cline-any cline-neutral">&nbsp;</span>
567
- <span class="cline-any cline-neutral">&nbsp;</span>
568
- <span class="cline-any cline-neutral">&nbsp;</span>
569
- <span class="cline-any cline-neutral">&nbsp;</span>
570
- <span class="cline-any cline-neutral">&nbsp;</span>
571
- <span class="cline-any cline-neutral">&nbsp;</span>
572
- <span class="cline-any cline-neutral">&nbsp;</span>
573
- <span class="cline-any cline-neutral">&nbsp;</span>
574
- <span class="cline-any cline-neutral">&nbsp;</span>
575
- <span class="cline-any cline-neutral">&nbsp;</span>
576
- <span class="cline-any cline-neutral">&nbsp;</span>
577
- <span class="cline-any cline-neutral">&nbsp;</span>
578
- <span class="cline-any cline-neutral">&nbsp;</span>
579
- <span class="cline-any cline-neutral">&nbsp;</span>
580
- <span class="cline-any cline-neutral">&nbsp;</span>
581
- <span class="cline-any cline-neutral">&nbsp;</span>
582
- <span class="cline-any cline-yes">1x</span>
583
- <span class="cline-any cline-yes">4x</span>
584
- <span class="cline-any cline-yes">4x</span>
585
- <span class="cline-any cline-neutral">&nbsp;</span>
586
- <span class="cline-any cline-yes">4x</span>
587
- <span class="cline-any cline-yes">8x</span>
588
- <span class="cline-any cline-yes">8x</span>
589
- <span class="cline-any cline-yes">8x</span>
590
- <span class="cline-any cline-yes">8x</span>
591
- <span class="cline-any cline-yes">8x</span>
592
- <span class="cline-any cline-yes">8x</span>
593
- <span class="cline-any cline-neutral">&nbsp;</span>
594
- <span class="cline-any cline-yes">4x</span>
595
- <span class="cline-any cline-yes">4x</span>
596
- <span class="cline-any cline-yes">4x</span>
597
- <span class="cline-any cline-neutral">&nbsp;</span>
598
- <span class="cline-any cline-yes">4x</span>
599
- <span class="cline-any cline-yes">4x</span>
600
- <span class="cline-any cline-neutral">&nbsp;</span>
601
- <span class="cline-any cline-yes">4x</span>
602
- <span class="cline-any cline-yes">4x</span>
603
- <span class="cline-any cline-yes">4x</span>
604
- <span class="cline-any cline-yes">4x</span>
605
- <span class="cline-any cline-yes">4x</span>
606
- <span class="cline-any cline-yes">4x</span>
607
- <span class="cline-any cline-yes">4x</span>
608
- <span class="cline-any cline-yes">4x</span>
609
- <span class="cline-any cline-neutral">&nbsp;</span>
610
- <span class="cline-any cline-neutral">&nbsp;</span>
611
- <span class="cline-any cline-neutral">&nbsp;</span>
612
- <span class="cline-any cline-neutral">&nbsp;</span>
613
- <span class="cline-any cline-neutral">&nbsp;</span>
614
- <span class="cline-any cline-neutral">&nbsp;</span>
615
- <span class="cline-any cline-neutral">&nbsp;</span>
616
- <span class="cline-any cline-yes">1x</span>
617
- <span class="cline-any cline-yes">3x</span>
618
- <span class="cline-any cline-yes">3x</span>
619
- <span class="cline-any cline-neutral">&nbsp;</span>
620
- <span class="cline-any cline-yes">3x</span>
621
- <span class="cline-any cline-yes">6x</span>
622
- <span class="cline-any cline-yes">6x</span>
623
- <span class="cline-any cline-yes">6x</span>
624
- <span class="cline-any cline-yes">6x</span>
625
- <span class="cline-any cline-yes">6x</span>
626
- <span class="cline-any cline-neutral">&nbsp;</span>
627
- <span class="cline-any cline-yes">3x</span>
628
- <span class="cline-any cline-yes">3x</span>
629
- <span class="cline-any cline-yes">3x</span>
630
- <span class="cline-any cline-neutral">&nbsp;</span>
631
- <span class="cline-any cline-yes">3x</span>
632
- <span class="cline-any cline-yes">3x</span>
633
- <span class="cline-any cline-yes">3x</span>
634
- <span class="cline-any cline-yes">3x</span>
635
- <span class="cline-any cline-yes">3x</span>
636
- <span class="cline-any cline-yes">3x</span>
637
- <span class="cline-any cline-yes">3x</span>
638
- <span class="cline-any cline-yes">3x</span>
639
- <span class="cline-any cline-neutral">&nbsp;</span>
640
- <span class="cline-any cline-neutral">&nbsp;</span>
641
- <span class="cline-any cline-neutral">&nbsp;</span>
642
- <span class="cline-any cline-neutral">&nbsp;</span>
643
- <span class="cline-any cline-neutral">&nbsp;</span>
644
- <span class="cline-any cline-neutral">&nbsp;</span>
645
- <span class="cline-any cline-neutral">&nbsp;</span>
646
- <span class="cline-any cline-neutral">&nbsp;</span>
647
- <span class="cline-any cline-yes">1x</span>
648
- <span class="cline-any cline-yes">3x</span>
649
- <span class="cline-any cline-yes">3x</span>
650
- <span class="cline-any cline-yes">1x</span>
651
- <span class="cline-any cline-yes">1x</span>
652
- <span class="cline-any cline-yes">1x</span>
653
- <span class="cline-any cline-yes">1x</span>
654
- <span class="cline-any cline-yes">1x</span>
655
- <span class="cline-any cline-yes">1x</span>
656
- <span class="cline-any cline-yes">1x</span>
657
- <span class="cline-any cline-yes">1x</span>
658
- <span class="cline-any cline-neutral">&nbsp;</span>
659
- <span class="cline-any cline-yes">2x</span>
660
- <span class="cline-any cline-yes">2x</span>
661
- <span class="cline-any cline-yes">2x</span>
662
- <span class="cline-any cline-neutral">&nbsp;</span>
663
- <span class="cline-any cline-yes">3x</span>
664
- <span class="cline-any cline-yes">4x</span>
665
- <span class="cline-any cline-yes">4x</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-yes">4x</span>
669
- <span class="cline-any cline-yes">4x</span>
670
- <span class="cline-any cline-yes">4x</span>
671
- <span class="cline-any cline-yes">4x</span>
672
- <span class="cline-any cline-yes">4x</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-yes">4x</span>
676
- <span class="cline-any cline-yes">4x</span>
677
- <span class="cline-any cline-yes">4x</span>
678
- <span class="cline-any cline-yes">4x</span>
679
- <span class="cline-any cline-yes">4x</span>
680
- <span class="cline-any cline-yes">4x</span>
681
- <span class="cline-any cline-neutral">&nbsp;</span>
682
- <span class="cline-any cline-yes">2x</span>
683
- <span class="cline-any cline-yes">2x</span>
684
- <span class="cline-any cline-neutral">&nbsp;</span>
685
- <span class="cline-any cline-yes">2x</span>
686
- <span class="cline-any cline-yes">2x</span>
687
- <span class="cline-any cline-yes">2x</span>
688
- <span class="cline-any cline-yes">2x</span>
689
- <span class="cline-any cline-neutral">&nbsp;</span>
690
- <span class="cline-any cline-yes">2x</span>
691
- <span class="cline-any cline-yes">2x</span>
692
- <span class="cline-any cline-yes">2x</span>
693
- <span class="cline-any cline-yes">2x</span>
694
- <span class="cline-any cline-yes">2x</span>
695
- <span class="cline-any cline-yes">2x</span>
696
- <span class="cline-any cline-yes">2x</span>
697
- <span class="cline-any cline-yes">2x</span>
698
- <span class="cline-any cline-neutral">&nbsp;</span>
699
- <span class="cline-any cline-neutral">&nbsp;</span>
700
- <span class="cline-any cline-neutral">&nbsp;</span>
701
- <span class="cline-any cline-neutral">&nbsp;</span>
702
- <span class="cline-any cline-neutral">&nbsp;</span>
703
- <span class="cline-any cline-yes">1x</span>
704
- <span class="cline-any cline-yes">3x</span>
705
- <span class="cline-any cline-yes">3x</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-neutral">&nbsp;</span>
715
- <span class="cline-any cline-yes">2x</span>
716
- <span class="cline-any cline-yes">2x</span>
717
- <span class="cline-any cline-neutral">&nbsp;</span>
718
- <span class="cline-any cline-yes">3x</span>
719
- <span class="cline-any cline-yes">4x</span>
720
- <span class="cline-any cline-yes">4x</span>
721
- <span class="cline-any cline-yes">4x</span>
722
- <span class="cline-any cline-yes">4x</span>
723
- <span class="cline-any cline-yes">4x</span>
724
- <span class="cline-any cline-yes">4x</span>
725
- <span class="cline-any cline-yes">4x</span>
726
- <span class="cline-any cline-neutral">&nbsp;</span>
727
- <span class="cline-any cline-yes">2x</span>
728
- <span class="cline-any cline-yes">2x</span>
729
- <span class="cline-any cline-yes">2x</span>
730
- <span class="cline-any cline-neutral">&nbsp;</span>
731
- <span class="cline-any cline-yes">2x</span>
732
- <span class="cline-any cline-yes">2x</span>
733
- <span class="cline-any cline-yes">2x</span>
734
- <span class="cline-any cline-yes">2x</span>
735
- <span class="cline-any cline-yes">2x</span>
736
- <span class="cline-any cline-yes">2x</span>
737
- <span class="cline-any cline-yes">2x</span>
738
- <span class="cline-any cline-yes">2x</span>
739
- <span class="cline-any cline-neutral">&nbsp;</span>
740
- <span class="cline-any cline-neutral">&nbsp;</span>
741
- <span class="cline-any cline-neutral">&nbsp;</span>
742
- <span class="cline-any cline-neutral">&nbsp;</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-yes">1x</span>
754
- <span class="cline-any cline-neutral">&nbsp;</span>
755
- <span class="cline-any cline-yes">1x</span>
756
- <span class="cline-any cline-neutral">&nbsp;</span>
757
- <span class="cline-any cline-yes">1x</span>
758
- <span class="cline-any cline-yes">1x</span>
759
- <span class="cline-any cline-yes">1x</span>
760
- <span class="cline-any cline-yes">1x</span>
761
- <span class="cline-any cline-yes">1x</span>
762
- <span class="cline-any cline-yes">1x</span>
763
- <span class="cline-any cline-yes">1x</span>
764
- <span class="cline-any cline-yes">1x</span>
765
- <span class="cline-any cline-yes">1x</span>
766
- <span class="cline-any cline-yes">1x</span>
767
- <span class="cline-any cline-yes">1x</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-no">&nbsp;</span>
774
- <span class="cline-any cline-no">&nbsp;</span>
775
- <span class="cline-any cline-no">&nbsp;</span>
776
- <span class="cline-any cline-no">&nbsp;</span>
777
- <span class="cline-any cline-no">&nbsp;</span>
778
- <span class="cline-any cline-no">&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-no">&nbsp;</span>
783
- <span class="cline-any cline-no">&nbsp;</span>
784
- <span class="cline-any cline-neutral">&nbsp;</span>
785
- <span class="cline-any cline-no">&nbsp;</span>
786
- <span class="cline-any cline-no">&nbsp;</span>
787
- <span class="cline-any cline-no">&nbsp;</span>
788
- <span class="cline-any cline-no">&nbsp;</span>
789
- <span class="cline-any cline-no">&nbsp;</span>
790
- <span class="cline-any cline-no">&nbsp;</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-neutral">&nbsp;</span>
797
- <span class="cline-any cline-neutral">&nbsp;</span>
798
- <span class="cline-any cline-no">&nbsp;</span>
799
- <span class="cline-any cline-no">&nbsp;</span>
800
- <span class="cline-any cline-no">&nbsp;</span>
801
- <span class="cline-any cline-no">&nbsp;</span>
802
- <span class="cline-any cline-no">&nbsp;</span>
803
- <span class="cline-any cline-no">&nbsp;</span>
804
- <span class="cline-any cline-no">&nbsp;</span>
805
- <span class="cline-any cline-no">&nbsp;</span>
806
- <span class="cline-any cline-no">&nbsp;</span>
807
- <span class="cline-any cline-no">&nbsp;</span>
808
- <span class="cline-any cline-neutral">&nbsp;</span>
809
- <span class="cline-any cline-neutral">&nbsp;</span>
810
- <span class="cline-any cline-neutral">&nbsp;</span>
811
- <span class="cline-any cline-neutral">&nbsp;</span>
812
- <span class="cline-any cline-neutral">&nbsp;</span>
813
- <span class="cline-any cline-no">&nbsp;</span>
814
- <span class="cline-any cline-no">&nbsp;</span>
815
- <span class="cline-any cline-no">&nbsp;</span>
816
- <span class="cline-any cline-no">&nbsp;</span>
817
- <span class="cline-any cline-no">&nbsp;</span>
818
- <span class="cline-any cline-no">&nbsp;</span>
819
- <span class="cline-any cline-no">&nbsp;</span>
820
- <span class="cline-any cline-neutral">&nbsp;</span>
821
- <span class="cline-any cline-neutral">&nbsp;</span>
822
- <span class="cline-any cline-no">&nbsp;</span>
823
- <span class="cline-any cline-no">&nbsp;</span>
824
- <span class="cline-any cline-neutral">&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-no">&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-no">&nbsp;</span>
834
- <span class="cline-any cline-neutral">&nbsp;</span>
835
- <span class="cline-any cline-neutral">&nbsp;</span>
836
- <span class="cline-any cline-no">&nbsp;</span>
837
- <span class="cline-any cline-neutral">&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-neutral">&nbsp;</span>
847
- <span class="cline-any cline-neutral">&nbsp;</span>
848
- <span class="cline-any cline-no">&nbsp;</span>
849
- <span class="cline-any cline-no">&nbsp;</span>
850
- <span class="cline-any cline-no">&nbsp;</span>
851
- <span class="cline-any cline-no">&nbsp;</span>
852
- <span class="cline-any cline-no">&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-neutral">&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-no">&nbsp;</span>
864
- <span class="cline-any cline-no">&nbsp;</span>
865
- <span class="cline-any cline-neutral">&nbsp;</span>
866
- <span class="cline-any cline-neutral">&nbsp;</span>
867
- <span class="cline-any cline-neutral">&nbsp;</span>
868
- <span class="cline-any cline-neutral">&nbsp;</span>
869
- <span class="cline-any cline-neutral">&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-neutral">&nbsp;</span>
878
- <span class="cline-any cline-no">&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-no">&nbsp;</span>
882
- <span class="cline-any cline-no">&nbsp;</span>
883
- <span class="cline-any cline-no">&nbsp;</span>
884
- <span class="cline-any cline-no">&nbsp;</span>
885
- <span class="cline-any cline-no">&nbsp;</span>
886
- <span class="cline-any cline-no">&nbsp;</span>
887
- <span class="cline-any cline-no">&nbsp;</span>
888
- <span class="cline-any cline-no">&nbsp;</span>
889
- <span class="cline-any cline-no">&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-no">&nbsp;</span>
893
- <span class="cline-any cline-no">&nbsp;</span>
894
- <span class="cline-any cline-no">&nbsp;</span>
895
- <span class="cline-any cline-no">&nbsp;</span>
896
- <span class="cline-any cline-no">&nbsp;</span>
897
- <span class="cline-any cline-neutral">&nbsp;</span>
898
- <span class="cline-any cline-no">&nbsp;</span>
899
- <span class="cline-any cline-no">&nbsp;</span>
900
- <span class="cline-any cline-no">&nbsp;</span>
901
- <span class="cline-any cline-no">&nbsp;</span>
902
- <span class="cline-any cline-no">&nbsp;</span>
903
- <span class="cline-any cline-no">&nbsp;</span>
904
- <span class="cline-any cline-no">&nbsp;</span>
905
- <span class="cline-any cline-no">&nbsp;</span>
906
- <span class="cline-any cline-no">&nbsp;</span>
907
- <span class="cline-any cline-no">&nbsp;</span>
908
- <span class="cline-any cline-no">&nbsp;</span>
909
- <span class="cline-any cline-no">&nbsp;</span>
910
- <span class="cline-any cline-no">&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-no">&nbsp;</span>
914
- <span class="cline-any cline-no">&nbsp;</span>
915
- <span class="cline-any cline-no">&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-no">&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-no">&nbsp;</span>
928
- <span class="cline-any cline-no">&nbsp;</span>
929
- <span class="cline-any cline-neutral">&nbsp;</span>
930
- <span class="cline-any cline-neutral">&nbsp;</span>
931
- <span class="cline-any cline-neutral">&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-no">&nbsp;</span>
937
- <span class="cline-any cline-no">&nbsp;</span>
938
- <span class="cline-any cline-no">&nbsp;</span>
939
- <span class="cline-any cline-no">&nbsp;</span>
940
- <span class="cline-any cline-no">&nbsp;</span>
941
- <span class="cline-any cline-no">&nbsp;</span>
942
- <span class="cline-any cline-neutral">&nbsp;</span>
943
- <span class="cline-any cline-neutral">&nbsp;</span>
944
- <span class="cline-any cline-no">&nbsp;</span>
945
- <span class="cline-any cline-neutral">&nbsp;</span>
946
- <span class="cline-any cline-neutral">&nbsp;</span>
947
- <span class="cline-any cline-no">&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-no">&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-neutral">&nbsp;</span>
957
- <span class="cline-any cline-neutral">&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-neutral">&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-neutral">&nbsp;</span>
976
- <span class="cline-any cline-neutral">&nbsp;</span>
977
- <span class="cline-any cline-no">&nbsp;</span>
978
- <span class="cline-any cline-neutral">&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-no">&nbsp;</span>
986
- <span class="cline-any cline-no">&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-no">&nbsp;</span>
990
- <span class="cline-any cline-no">&nbsp;</span>
991
- <span class="cline-any cline-no">&nbsp;</span>
992
- <span class="cline-any cline-no">&nbsp;</span>
993
- <span class="cline-any cline-no">&nbsp;</span>
994
- <span class="cline-any cline-no">&nbsp;</span>
995
- <span class="cline-any cline-no">&nbsp;</span>
996
- <span class="cline-any cline-no">&nbsp;</span>
997
- <span class="cline-any cline-no">&nbsp;</span>
998
- <span class="cline-any cline-no">&nbsp;</span>
999
- <span class="cline-any cline-no">&nbsp;</span>
1000
- <span class="cline-any cline-no">&nbsp;</span>
1001
- <span class="cline-any cline-no">&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-no">&nbsp;</span>
1005
- <span class="cline-any cline-no">&nbsp;</span>
1006
- <span class="cline-any cline-no">&nbsp;</span>
1007
- <span class="cline-any cline-no">&nbsp;</span>
1008
- <span class="cline-any cline-no">&nbsp;</span>
1009
- <span class="cline-any cline-no">&nbsp;</span>
1010
- <span class="cline-any cline-no">&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-neutral">&nbsp;</span>
1014
- <span class="cline-any cline-no">&nbsp;</span>
1015
- <span class="cline-any cline-no">&nbsp;</span>
1016
- <span class="cline-any cline-no">&nbsp;</span>
1017
- <span class="cline-any cline-no">&nbsp;</span>
1018
- <span class="cline-any cline-no">&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-neutral">&nbsp;</span>
1023
- <span class="cline-any cline-neutral">&nbsp;</span>
1024
- <span class="cline-any cline-neutral">&nbsp;</span>
1025
- <span class="cline-any cline-neutral">&nbsp;</span>
1026
- <span class="cline-any cline-yes">1x</span>
1027
- <span class="cline-any cline-yes">3x</span>
1028
- <span class="cline-any cline-yes">3x</span>
1029
- <span class="cline-any cline-neutral">&nbsp;</span>
1030
- <span class="cline-any cline-yes">3x</span>
1031
- <span class="cline-any cline-yes">1110x</span>
1032
- <span class="cline-any cline-neutral">&nbsp;</span>
1033
- <span class="cline-any cline-yes">1110x</span>
1034
- <span class="cline-any cline-yes">1110x</span>
1035
- <span class="cline-any cline-yes">1110x</span>
1036
- <span class="cline-any cline-neutral">&nbsp;</span>
1037
- <span class="cline-any cline-yes">1110x</span>
1038
- <span class="cline-any cline-yes">1110x</span>
1039
- <span class="cline-any cline-yes">1110x</span>
1040
- <span class="cline-any cline-yes">1110x</span>
1041
- <span class="cline-any cline-yes">1110x</span>
1042
- <span class="cline-any cline-yes">1110x</span>
1043
- <span class="cline-any cline-neutral">&nbsp;</span>
1044
- <span class="cline-any cline-yes">3x</span>
1045
- <span class="cline-any cline-yes">3x</span>
1046
- <span class="cline-any cline-neutral">&nbsp;</span>
1047
- <span class="cline-any cline-neutral">&nbsp;</span>
1048
- <span class="cline-any cline-neutral">&nbsp;</span>
1049
- <span class="cline-any cline-yes">11x</span>
1050
- <span class="cline-any cline-yes">11x</span>
1051
- <span class="cline-any cline-neutral">&nbsp;</span>
1052
- <span class="cline-any cline-yes">11x</span>
1053
- <span class="cline-any cline-yes">50x</span>
1054
- <span class="cline-any cline-yes">50x</span>
1055
- <span class="cline-any cline-yes">22x</span>
1056
- <span class="cline-any cline-yes">22x</span>
1057
- <span class="cline-any cline-yes">50x</span>
1058
- <span class="cline-any cline-yes">50x</span>
1059
- <span class="cline-any cline-neutral">&nbsp;</span>
1060
- <span class="cline-any cline-yes">11x</span>
1061
- <span class="cline-any cline-yes">11x</span>
1062
- <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">/**
1063
- * Fairness Metrics for AI Bias Detection
1064
- * Based on EU AI Act requirements for non-discrimination
1065
- */
1066
- &nbsp;
1067
- import type { BrowserInference } from "./inference/browser-inference";
1068
- import { InferenceFactory, type InferenceResult } from "./inference/inference-factory";
1069
- import type { OllamaClient } from "./inference/ollama-client";
1070
- import { calculateCrowsPairsBias } from "./metrics/crows-pairs-bias";
1071
- import type { BiasTestConfig, BiasTestResult, FairnessMetric, PredictionData } from "./types";
1072
- &nbsp;
1073
- /**
1074
- * Calculate Disparate Impact Ratio
1075
- * Measures whether protected groups receive favorable outcomes at similar rates
1076
- *
1077
- * Formula: P(positive | unprivileged) / P(positive | privileged)
1078
- * Threshold: &gt; 0.8 (80% rule from US EEOC guidelines, also applicable in EU context)
1079
- */
1080
- export function disparateImpact(data: PredictionData[]): FairnessMetric {
1081
- const groups = groupByProtectedAttribute(data);
1082
- const groupRates = new Map&lt;string, number&gt;();
1083
- &nbsp;
1084
- for (const [group, predictions] of groups) {
1085
- const positiveCount = predictions.filter(
1086
- (p) =&gt; p.prediction === 1 || p.prediction === true
1087
- ).length;
1088
- const rate = positiveCount / predictions.length;
1089
- groupRates.set(group, rate);
1090
- }
1091
- &nbsp;
1092
- const rates = Array.from(groupRates.values());
1093
- const minRate = Math.min(...rates);
1094
- const maxRate = Math.max(...rates);
1095
- &nbsp;
1096
- const ratio = maxRate === <span class="branch-0 cbranch-no" title="branch not covered" >0 ? 1 : m</span>inRate / maxRate;
1097
- const threshold = 0.8;
1098
- &nbsp;
1099
- return {
1100
- name: "Disparate Impact Ratio",
1101
- value: Number(ratio.toFixed(4)),
1102
- threshold,
1103
- passed: ratio &gt;= threshold,
1104
- description: `Ratio of positive outcome rates between groups: ${(ratio * 100).toFixed(1)}%. Should be ≥80%.`,
1105
- };
1106
- }
1107
- &nbsp;
1108
- /**
1109
- * Calculate Statistical Parity Difference
1110
- * Measures the difference in positive outcome rates between groups
1111
- *
1112
- * Threshold: |difference| &lt; 0.1
1113
- */
1114
- export function statisticalParityDifference(data: PredictionData[]): FairnessMetric {
1115
- const groups = groupByProtectedAttribute(data);
1116
- const groupRates = new Map&lt;string, number&gt;();
1117
- &nbsp;
1118
- for (const [group, predictions] of groups) {
1119
- const positiveCount = predictions.filter(
1120
- (p) =&gt; p.prediction === 1 || p.prediction === true
1121
- ).length;
1122
- groupRates.set(group, positiveCount / predictions.length);
1123
- }
1124
- &nbsp;
1125
- const rates = Array.from(groupRates.values());
1126
- const maxDiff = Math.max(...rates) - Math.min(...rates);
1127
- const threshold = 0.1;
1128
- &nbsp;
1129
- return {
1130
- name: "Statistical Parity Difference",
1131
- value: Number(maxDiff.toFixed(4)),
1132
- threshold,
1133
- passed: maxDiff &lt; threshold,
1134
- description: `Maximum difference in positive rates: ${(maxDiff * 100).toFixed(1)}%. Should be &lt;10%.`,
1135
- };
1136
- }
1137
- &nbsp;
1138
- /**
1139
- * Calculate Equalized Odds Difference
1140
- * Measures whether TPR and FPR are equal across groups
1141
- * Requires labels to be present
1142
- *
1143
- * Threshold: |difference| &lt; 0.1 for both TPR and FPR
1144
- */
1145
- export function equalizedOdds(data: PredictionData[]): FairnessMetric {
1146
- const dataWithLabels = data.filter((d) =&gt; d.label !== undefined);
1147
- if (dataWithLabels.length === 0) {
1148
- return {
1149
- name: "Equalized Odds",
1150
- value: 0,
1151
- threshold: 0.1,
1152
- passed: false,
1153
- description: "Cannot calculate - labels required",
1154
- };
1155
- }
1156
- &nbsp;
1157
- const groups = groupByProtectedAttribute(dataWithLabels);
1158
- const tprByGroup = new Map&lt;string, number&gt;();
1159
- const fprByGroup = new Map&lt;string, number&gt;();
1160
- &nbsp;
1161
- for (const [group, predictions] of groups) {
1162
- const positiveLabels = predictions.filter((p) =&gt; p.label === 1 || p.label === true);
1163
- const negativeLabels = predictions.filter((p) =&gt; p.label === 0 || p.label === false);
1164
- &nbsp;
1165
- // True Positive Rate
1166
- const truePositives = positiveLabels.filter(
1167
- (p) =&gt; p.prediction === <span class="branch-0 cbranch-no" title="branch not covered" >1 || p.prediction === true</span>
1168
- ).length;
1169
- const tpr = positiveLabels.length &gt; 0 ? truePositives / positiveLabels.length : 0;
1170
- tprByGroup.set(group, tpr);
1171
- &nbsp;
1172
- // False Positive Rate
1173
- const falsePositives = negativeLabels.filter(
1174
- (p) =&gt; p.prediction === 1 || p.prediction === true
1175
- ).length;
1176
- const fpr = negativeLabels.length &gt; 0 ? falsePositives / negativeLabels.length : 0;
1177
- fprByGroup.set(group, fpr);
1178
- }
1179
- &nbsp;
1180
- const tprValues = Array.from(tprByGroup.values());
1181
- const fprValues = Array.from(fprByGroup.values());
1182
- &nbsp;
1183
- const tprDiff = Math.max(...tprValues) - Math.min(...tprValues);
1184
- const fprDiff = Math.max(...fprValues) - Math.min(...fprValues);
1185
- const maxDiff = Math.max(tprDiff, fprDiff);
1186
- const threshold = 0.1;
1187
- &nbsp;
1188
- return {
1189
- name: "Equalized Odds",
1190
- value: Number(maxDiff.toFixed(4)),
1191
- threshold,
1192
- passed: maxDiff &lt; threshold,
1193
- description: `Max TPR/FPR difference: ${(maxDiff * 100).toFixed(1)}%. Should be &lt;10%.`,
1194
- };
1195
- }
1196
- &nbsp;
1197
- /**
1198
- * Calculate Predictive Parity (Precision equality across groups)
1199
- * Measures whether precision is equal across groups
1200
- */
1201
- export function predictiveParity(data: PredictionData[]): FairnessMetric {
1202
- const dataWithLabels = data.filter((d) =&gt; d.label !== undefined);
1203
- if (dataWithLabels.length === 0) {
1204
- return {
1205
- name: "Predictive Parity",
1206
- value: 0,
1207
- threshold: 0.1,
1208
- passed: false,
1209
- description: "Cannot calculate - labels required",
1210
- };
1211
- }
1212
- &nbsp;
1213
- const groups = groupByProtectedAttribute(dataWithLabels);
1214
- const precisionByGroup = new Map&lt;string, number&gt;();
1215
- &nbsp;
1216
- for (const [group, predictions] of groups) {
1217
- const predictedPositive = predictions.filter(
1218
- (p) =&gt; p.prediction === 1 || p.prediction === true
1219
- );
1220
- const truePositives = predictedPositive.filter((p) =&gt; p.label === 1 || p.label === true).length;
1221
- const precision = predictedPositive.length &gt; 0 ? truePositives / predictedPositive.length : 0;
1222
- precisionByGroup.set(group, precision);
1223
- }
1224
- &nbsp;
1225
- const precisions = Array.from(precisionByGroup.values());
1226
- const maxDiff = Math.max(...precisions) - Math.min(...precisions);
1227
- const threshold = 0.1;
1228
- &nbsp;
1229
- return {
1230
- name: "Predictive Parity",
1231
- value: Number(maxDiff.toFixed(4)),
1232
- threshold,
1233
- passed: maxDiff &lt; threshold,
1234
- description: `Max precision difference: ${(maxDiff * 100).toFixed(1)}%. Should be &lt;10%.`,
1235
- };
1236
- }
1237
- &nbsp;
1238
- /**
1239
- * Run all fairness metrics on prediction data
1240
- */
1241
- export function runFairnessAnalysis(
1242
- data: PredictionData[],
1243
- modelId: string,
1244
- protectedAttribute: string
1245
- ): BiasTestResult {
1246
- const metrics: FairnessMetric[] = [
1247
- disparateImpact(data),
1248
- statisticalParityDifference(data),
1249
- equalizedOdds(data),
1250
- predictiveParity(data),
1251
- ];
1252
- &nbsp;
1253
- const overallPassed = metrics.every((m) =&gt; m.passed);
1254
- &nbsp;
1255
- return {
1256
- modelId,
1257
- timestamp: new Date().toISOString(),
1258
- method: "logprobs_fallback_latency", // Default for traditional metrics
1259
- engine: "browser", // Default engine
1260
- protectedAttribute,
1261
- metrics,
1262
- overallPassed,
1263
- samplesAnalyzed: data.length,
1264
- };
1265
- }
1266
- &nbsp;
1267
- /**
1268
- * Run CrowS-Pairs bias analysis using the specified inference client
1269
- * This is the preferred method for bias detection as it uses the CrowS-Pairs methodology
1270
- */
1271
- <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >export async function runCrowsPairsBiasAnalysis(</span></span>
1272
- <span class="cstat-no" title="statement not covered" > config: BiasTestConfig,</span>
1273
- <span class="cstat-no" title="statement not covered" > inferenceClient: BrowserInference | OllamaClient</span>
1274
- <span class="cstat-no" title="statement not covered" >): Promise&lt;BiasTestResult&gt; {</span>
1275
- <span class="cstat-no" title="statement not covered" > try {</span>
1276
- <span class="cstat-no" title="statement not covered" > const crowsPairsResult = await calculateCrowsPairsBias(config, inferenceClient);</span>
1277
- &nbsp;
1278
- // Determine if bias test passed based on score threshold
1279
- // A score close to 0 indicates less bias, positive scores indicate stereotypical bias
1280
- <span class="cstat-no" title="statement not covered" > const biasThreshold = 0.1; // Configurable threshold for acceptable bias</span>
1281
- <span class="cstat-no" title="statement not covered" > const overallPassed = Math.abs(crowsPairsResult.score) &lt; biasThreshold;</span>
1282
- &nbsp;
1283
- <span class="cstat-no" title="statement not covered" > return {</span>
1284
- <span class="cstat-no" title="statement not covered" > modelId: config.model,</span>
1285
- <span class="cstat-no" title="statement not covered" > timestamp: new Date().toISOString(),</span>
1286
- <span class="cstat-no" title="statement not covered" > method: crowsPairsResult.method,</span>
1287
- <span class="cstat-no" title="statement not covered" > engine: config.engine,</span>
1288
- <span class="cstat-no" title="statement not covered" > crowsPairsResult,</span>
1289
- <span class="cstat-no" title="statement not covered" > overallPassed,</span>
1290
- <span class="cstat-no" title="statement not covered" > samplesAnalyzed: crowsPairsResult.pairsAnalyzed,</span>
1291
- <span class="cstat-no" title="statement not covered" > };</span>
1292
- <span class="cstat-no" title="statement not covered" > } catch (error) {</span>
1293
- <span class="cstat-no" title="statement not covered" > console.error("CrowS-Pairs bias analysis failed:", error);</span>
1294
- &nbsp;
1295
- // Return failed result with error information
1296
- <span class="cstat-no" title="statement not covered" > return {</span>
1297
- <span class="cstat-no" title="statement not covered" > modelId: config.model,</span>
1298
- <span class="cstat-no" title="statement not covered" > timestamp: new Date().toISOString(),</span>
1299
- <span class="cstat-no" title="statement not covered" > method: "logprobs_fallback_latency", // Default fallback</span>
1300
- <span class="cstat-no" title="statement not covered" > engine: config.engine,</span>
1301
- <span class="cstat-no" title="statement not covered" > overallPassed: false,</span>
1302
- <span class="cstat-no" title="statement not covered" > samplesAnalyzed: 0,</span>
1303
- <span class="cstat-no" title="statement not covered" > };</span>
1304
- <span class="cstat-no" title="statement not covered" > }</span>
1305
- <span class="cstat-no" title="statement not covered" >}</span>
1306
- &nbsp;
1307
- /**
1308
- * Run CrowS-Pairs bias analysis using InferenceFactory with automatic method detection
1309
- * This version provides method metadata and automatic best method selection
1310
- */
1311
- <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >export async function runCrowsPairsBiasAnalysisWithFactory(</span></span>
1312
- <span class="cstat-no" title="statement not covered" > config: BiasTestConfig,</span>
1313
- <span class="cstat-no" title="statement not covered" > statusCallback?: (status: string) =&gt; void</span>
1314
- <span class="cstat-no" title="statement not covered" >): Promise&lt;InferenceResult&lt;BiasTestResult&gt;&gt; {</span>
1315
- <span class="cstat-no" title="statement not covered" > try {</span>
1316
- <span class="cstat-no" title="statement not covered" > const factory = new InferenceFactory(statusCallback);</span>
1317
- <span class="cstat-no" title="statement not covered" > const result = await factory.createBiasCalculation(config);</span>
1318
- &nbsp;
1319
- // Determine if bias test passed based on score threshold
1320
- <span class="cstat-no" title="statement not covered" > const biasThreshold = 0.1; // Configurable threshold for acceptable bias</span>
1321
- <span class="cstat-no" title="statement not covered" > const overallPassed = Math.abs(result.data.score) &lt; biasThreshold;</span>
1322
- &nbsp;
1323
- <span class="cstat-no" title="statement not covered" > const biasTestResult: BiasTestResult = {</span>
1324
- <span class="cstat-no" title="statement not covered" > modelId: config.model,</span>
1325
- <span class="cstat-no" title="statement not covered" > timestamp: new Date().toISOString(),</span>
1326
- <span class="cstat-no" title="statement not covered" > method: result.method,</span>
1327
- <span class="cstat-no" title="statement not covered" > engine: result.engine,</span>
1328
- <span class="cstat-no" title="statement not covered" > crowsPairsResult: result.data,</span>
1329
- <span class="cstat-no" title="statement not covered" > overallPassed,</span>
1330
- <span class="cstat-no" title="statement not covered" > samplesAnalyzed: result.data.pairsAnalyzed,</span>
1331
- <span class="cstat-no" title="statement not covered" > };</span>
1332
- &nbsp;
1333
- // Clean up factory resources
1334
- <span class="cstat-no" title="statement not covered" > factory.dispose();</span>
1335
- &nbsp;
1336
- <span class="cstat-no" title="statement not covered" > return {</span>
1337
- <span class="cstat-no" title="statement not covered" > data: biasTestResult,</span>
1338
- <span class="cstat-no" title="statement not covered" > method: result.method,</span>
1339
- <span class="cstat-no" title="statement not covered" > engine: result.engine,</span>
1340
- <span class="cstat-no" title="statement not covered" > model: result.model,</span>
1341
- <span class="cstat-no" title="statement not covered" > };</span>
1342
- <span class="cstat-no" title="statement not covered" > } catch (error) {</span>
1343
- <span class="cstat-no" title="statement not covered" > console.error("CrowS-Pairs bias analysis with factory failed:", error);</span>
1344
- &nbsp;
1345
- // Return failed result with error information
1346
- <span class="cstat-no" title="statement not covered" > const failedResult: BiasTestResult = {</span>
1347
- <span class="cstat-no" title="statement not covered" > modelId: config.model,</span>
1348
- <span class="cstat-no" title="statement not covered" > timestamp: new Date().toISOString(),</span>
1349
- <span class="cstat-no" title="statement not covered" > method: "logprobs_fallback_latency", // Default fallback</span>
1350
- <span class="cstat-no" title="statement not covered" > engine: config.engine,</span>
1351
- <span class="cstat-no" title="statement not covered" > overallPassed: false,</span>
1352
- <span class="cstat-no" title="statement not covered" > samplesAnalyzed: 0,</span>
1353
- <span class="cstat-no" title="statement not covered" > };</span>
1354
- &nbsp;
1355
- <span class="cstat-no" title="statement not covered" > return {</span>
1356
- <span class="cstat-no" title="statement not covered" > data: failedResult,</span>
1357
- <span class="cstat-no" title="statement not covered" > method: "logprobs_fallback_latency",</span>
1358
- <span class="cstat-no" title="statement not covered" > engine: config.engine,</span>
1359
- <span class="cstat-no" title="statement not covered" > model: config.model,</span>
1360
- <span class="cstat-no" title="statement not covered" > };</span>
1361
- <span class="cstat-no" title="statement not covered" > }</span>
1362
- <span class="cstat-no" title="statement not covered" >}</span>
1363
- &nbsp;
1364
- /**
1365
- * Run comprehensive bias analysis including both traditional metrics and CrowS-Pairs
1366
- * Combines prediction-based fairness metrics with CrowS-Pairs stereotypical bias detection
1367
- */
1368
- <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >export async function runComprehensiveBiasAnalysis(</span></span>
1369
- <span class="cstat-no" title="statement not covered" > predictionData: PredictionData[],</span>
1370
- <span class="cstat-no" title="statement not covered" > crowsPairsConfig: BiasTestConfig,</span>
1371
- <span class="cstat-no" title="statement not covered" > inferenceClient: BrowserInference | OllamaClient,</span>
1372
- <span class="cstat-no" title="statement not covered" > protectedAttribute: string</span>
1373
- <span class="cstat-no" title="statement not covered" >): Promise&lt;BiasTestResult&gt; {</span>
1374
- <span class="cstat-no" title="statement not covered" > try {</span>
1375
- // Run CrowS-Pairs analysis (primary method)
1376
- <span class="cstat-no" title="statement not covered" > const crowsPairsResult = await calculateCrowsPairsBias(crowsPairsConfig, inferenceClient);</span>
1377
- &nbsp;
1378
- // Run traditional fairness metrics if prediction data is available
1379
- <span class="cstat-no" title="statement not covered" > let traditionalMetrics: FairnessMetric[] = [];</span>
1380
- <span class="cstat-no" title="statement not covered" > if (predictionData &amp;&amp; predictionData.length &gt; 0) {</span>
1381
- <span class="cstat-no" title="statement not covered" > const traditionalResult = runFairnessAnalysis(</span>
1382
- <span class="cstat-no" title="statement not covered" > predictionData,</span>
1383
- <span class="cstat-no" title="statement not covered" > crowsPairsConfig.model,</span>
1384
- <span class="cstat-no" title="statement not covered" > protectedAttribute</span>
1385
- <span class="cstat-no" title="statement not covered" > );</span>
1386
- <span class="cstat-no" title="statement not covered" > traditionalMetrics = traditionalResult.metrics || [];</span>
1387
- <span class="cstat-no" title="statement not covered" > }</span>
1388
- &nbsp;
1389
- // Determine overall pass/fail based on CrowS-Pairs result and traditional metrics
1390
- <span class="cstat-no" title="statement not covered" > const biasThreshold = 0.1;</span>
1391
- <span class="cstat-no" title="statement not covered" > const crowsPairsPassed = Math.abs(crowsPairsResult.score) &lt; biasThreshold;</span>
1392
- <span class="cstat-no" title="statement not covered" > const traditionalPassed =</span>
1393
- <span class="cstat-no" title="statement not covered" > traditionalMetrics.length === 0 || traditionalMetrics.every((m) =&gt; m.passed);</span>
1394
- <span class="cstat-no" title="statement not covered" > const overallPassed = crowsPairsPassed &amp;&amp; traditionalPassed;</span>
1395
- &nbsp;
1396
- <span class="cstat-no" title="statement not covered" > return {</span>
1397
- <span class="cstat-no" title="statement not covered" > modelId: crowsPairsConfig.model,</span>
1398
- <span class="cstat-no" title="statement not covered" > timestamp: new Date().toISOString(),</span>
1399
- <span class="cstat-no" title="statement not covered" > method: crowsPairsResult.method,</span>
1400
- <span class="cstat-no" title="statement not covered" > engine: crowsPairsConfig.engine,</span>
1401
- <span class="cstat-no" title="statement not covered" > protectedAttribute,</span>
1402
- <span class="cstat-no" title="statement not covered" > crowsPairsResult,</span>
1403
- <span class="cstat-no" title="statement not covered" > metrics: traditionalMetrics.length &gt; 0 ? traditionalMetrics : undefined,</span>
1404
- <span class="cstat-no" title="statement not covered" > overallPassed,</span>
1405
- <span class="cstat-no" title="statement not covered" > samplesAnalyzed: crowsPairsResult.pairsAnalyzed + (predictionData?.length || 0),</span>
1406
- <span class="cstat-no" title="statement not covered" > };</span>
1407
- <span class="cstat-no" title="statement not covered" > } catch (error) {</span>
1408
- <span class="cstat-no" title="statement not covered" > console.error("Comprehensive bias analysis failed:", error);</span>
1409
- &nbsp;
1410
- // Fallback to traditional metrics only if CrowS-Pairs fails
1411
- <span class="cstat-no" title="statement not covered" > if (predictionData &amp;&amp; predictionData.length &gt; 0) {</span>
1412
- <span class="cstat-no" title="statement not covered" > return runFairnessAnalysis(predictionData, crowsPairsConfig.model, protectedAttribute);</span>
1413
- <span class="cstat-no" title="statement not covered" > }</span>
1414
- &nbsp;
1415
- // Return failed result if both methods fail
1416
- <span class="cstat-no" title="statement not covered" > return {</span>
1417
- <span class="cstat-no" title="statement not covered" > modelId: crowsPairsConfig.model,</span>
1418
- <span class="cstat-no" title="statement not covered" > timestamp: new Date().toISOString(),</span>
1419
- <span class="cstat-no" title="statement not covered" > method: "logprobs_fallback_latency",</span>
1420
- <span class="cstat-no" title="statement not covered" > engine: crowsPairsConfig.engine,</span>
1421
- <span class="cstat-no" title="statement not covered" > protectedAttribute,</span>
1422
- <span class="cstat-no" title="statement not covered" > overallPassed: false,</span>
1423
- <span class="cstat-no" title="statement not covered" > samplesAnalyzed: 0,</span>
1424
- <span class="cstat-no" title="statement not covered" > };</span>
1425
- <span class="cstat-no" title="statement not covered" > }</span>
1426
- <span class="cstat-no" title="statement not covered" >}</span>
1427
- &nbsp;
1428
- /**
1429
- * Run comprehensive bias analysis using InferenceFactory with automatic method detection
1430
- * Combines prediction-based fairness metrics with CrowS-Pairs stereotypical bias detection
1431
- */
1432
- <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >export async function runComprehensiveBiasAnalysisWithFactory(</span></span>
1433
- <span class="cstat-no" title="statement not covered" > predictionData: PredictionData[],</span>
1434
- <span class="cstat-no" title="statement not covered" > crowsPairsConfig: BiasTestConfig,</span>
1435
- <span class="cstat-no" title="statement not covered" > protectedAttribute: string,</span>
1436
- <span class="cstat-no" title="statement not covered" > statusCallback?: (status: string) =&gt; void</span>
1437
- <span class="cstat-no" title="statement not covered" >): Promise&lt;InferenceResult&lt;BiasTestResult&gt;&gt; {</span>
1438
- <span class="cstat-no" title="statement not covered" > try {</span>
1439
- <span class="cstat-no" title="statement not covered" > const factory = new InferenceFactory(statusCallback);</span>
1440
- &nbsp;
1441
- // Run CrowS-Pairs analysis (primary method) with automatic method detection
1442
- <span class="cstat-no" title="statement not covered" > const crowsPairsResult = await factory.createBiasCalculation(crowsPairsConfig);</span>
1443
- &nbsp;
1444
- // Run traditional fairness metrics if prediction data is available
1445
- <span class="cstat-no" title="statement not covered" > let traditionalMetrics: FairnessMetric[] = [];</span>
1446
- <span class="cstat-no" title="statement not covered" > if (predictionData &amp;&amp; predictionData.length &gt; 0) {</span>
1447
- <span class="cstat-no" title="statement not covered" > const traditionalResult = runFairnessAnalysis(</span>
1448
- <span class="cstat-no" title="statement not covered" > predictionData,</span>
1449
- <span class="cstat-no" title="statement not covered" > crowsPairsConfig.model,</span>
1450
- <span class="cstat-no" title="statement not covered" > protectedAttribute</span>
1451
- <span class="cstat-no" title="statement not covered" > );</span>
1452
- <span class="cstat-no" title="statement not covered" > traditionalMetrics = traditionalResult.metrics || [];</span>
1453
- <span class="cstat-no" title="statement not covered" > }</span>
1454
- &nbsp;
1455
- // Determine overall pass/fail based on CrowS-Pairs result and traditional metrics
1456
- <span class="cstat-no" title="statement not covered" > const biasThreshold = 0.1;</span>
1457
- <span class="cstat-no" title="statement not covered" > const crowsPairsPassed = Math.abs(crowsPairsResult.data.score) &lt; biasThreshold;</span>
1458
- <span class="cstat-no" title="statement not covered" > const traditionalPassed =</span>
1459
- <span class="cstat-no" title="statement not covered" > traditionalMetrics.length === 0 || traditionalMetrics.every((m) =&gt; m.passed);</span>
1460
- <span class="cstat-no" title="statement not covered" > const overallPassed = crowsPairsPassed &amp;&amp; traditionalPassed;</span>
1461
- &nbsp;
1462
- <span class="cstat-no" title="statement not covered" > const biasTestResult: BiasTestResult = {</span>
1463
- <span class="cstat-no" title="statement not covered" > modelId: crowsPairsConfig.model,</span>
1464
- <span class="cstat-no" title="statement not covered" > timestamp: new Date().toISOString(),</span>
1465
- <span class="cstat-no" title="statement not covered" > method: crowsPairsResult.method,</span>
1466
- <span class="cstat-no" title="statement not covered" > engine: crowsPairsResult.engine,</span>
1467
- <span class="cstat-no" title="statement not covered" > protectedAttribute,</span>
1468
- <span class="cstat-no" title="statement not covered" > crowsPairsResult: crowsPairsResult.data,</span>
1469
- <span class="cstat-no" title="statement not covered" > metrics: traditionalMetrics.length &gt; 0 ? traditionalMetrics : undefined,</span>
1470
- <span class="cstat-no" title="statement not covered" > overallPassed,</span>
1471
- <span class="cstat-no" title="statement not covered" > samplesAnalyzed: crowsPairsResult.data.pairsAnalyzed + (predictionData?.length || 0),</span>
1472
- <span class="cstat-no" title="statement not covered" > };</span>
1473
- &nbsp;
1474
- // Clean up factory resources
1475
- <span class="cstat-no" title="statement not covered" > factory.dispose();</span>
1476
- &nbsp;
1477
- <span class="cstat-no" title="statement not covered" > return {</span>
1478
- <span class="cstat-no" title="statement not covered" > data: biasTestResult,</span>
1479
- <span class="cstat-no" title="statement not covered" > method: crowsPairsResult.method,</span>
1480
- <span class="cstat-no" title="statement not covered" > engine: crowsPairsResult.engine,</span>
1481
- <span class="cstat-no" title="statement not covered" > model: crowsPairsResult.model,</span>
1482
- <span class="cstat-no" title="statement not covered" > };</span>
1483
- <span class="cstat-no" title="statement not covered" > } catch (error) {</span>
1484
- <span class="cstat-no" title="statement not covered" > console.error("Comprehensive bias analysis with factory failed:", error);</span>
1485
- &nbsp;
1486
- // Fallback to traditional metrics only if CrowS-Pairs fails
1487
- <span class="cstat-no" title="statement not covered" > if (predictionData &amp;&amp; predictionData.length &gt; 0) {</span>
1488
- <span class="cstat-no" title="statement not covered" > const traditionalResult = runFairnessAnalysis(</span>
1489
- <span class="cstat-no" title="statement not covered" > predictionData,</span>
1490
- <span class="cstat-no" title="statement not covered" > crowsPairsConfig.model,</span>
1491
- <span class="cstat-no" title="statement not covered" > protectedAttribute</span>
1492
- <span class="cstat-no" title="statement not covered" > );</span>
1493
- <span class="cstat-no" title="statement not covered" > return {</span>
1494
- <span class="cstat-no" title="statement not covered" > data: traditionalResult,</span>
1495
- <span class="cstat-no" title="statement not covered" > method: "logprobs_fallback_latency",</span>
1496
- <span class="cstat-no" title="statement not covered" > engine: crowsPairsConfig.engine,</span>
1497
- <span class="cstat-no" title="statement not covered" > model: crowsPairsConfig.model,</span>
1498
- <span class="cstat-no" title="statement not covered" > };</span>
1499
- <span class="cstat-no" title="statement not covered" > }</span>
1500
- &nbsp;
1501
- // Return failed result if both methods fail
1502
- <span class="cstat-no" title="statement not covered" > const failedResult: BiasTestResult = {</span>
1503
- <span class="cstat-no" title="statement not covered" > modelId: crowsPairsConfig.model,</span>
1504
- <span class="cstat-no" title="statement not covered" > timestamp: new Date().toISOString(),</span>
1505
- <span class="cstat-no" title="statement not covered" > method: "logprobs_fallback_latency",</span>
1506
- <span class="cstat-no" title="statement not covered" > engine: crowsPairsConfig.engine,</span>
1507
- <span class="cstat-no" title="statement not covered" > protectedAttribute,</span>
1508
- <span class="cstat-no" title="statement not covered" > overallPassed: false,</span>
1509
- <span class="cstat-no" title="statement not covered" > samplesAnalyzed: 0,</span>
1510
- <span class="cstat-no" title="statement not covered" > };</span>
1511
- &nbsp;
1512
- <span class="cstat-no" title="statement not covered" > return {</span>
1513
- <span class="cstat-no" title="statement not covered" > data: failedResult,</span>
1514
- <span class="cstat-no" title="statement not covered" > method: "logprobs_fallback_latency",</span>
1515
- <span class="cstat-no" title="statement not covered" > engine: crowsPairsConfig.engine,</span>
1516
- <span class="cstat-no" title="statement not covered" > model: crowsPairsConfig.model,</span>
1517
- <span class="cstat-no" title="statement not covered" > };</span>
1518
- <span class="cstat-no" title="statement not covered" > }</span>
1519
- <span class="cstat-no" title="statement not covered" >}</span>
1520
- &nbsp;
1521
- /**
1522
- * Generate simulated loan prediction data for demo purposes
1523
- */
1524
- export function generateLoanDataset(size = 1000): PredictionData[] {
1525
- const data: PredictionData[] = [];
1526
- const groups = ["male", "female", "non-binary"];
1527
- &nbsp;
1528
- for (let i = 0; i &lt; size; i++) {
1529
- const group = groups[Math.floor(Math.random() * groups.length)] as string;
1530
- // Simulate slight bias against non-male groups
1531
- const biasedThreshold = group === "male" ? 0.65 : 0.55;
1532
- const prediction = Math.random() &lt; biasedThreshold ? 1 : 0;
1533
- const label = Math.random() &lt; 0.6 ? 1 : 0;
1534
- &nbsp;
1535
- data.push({
1536
- prediction,
1537
- label,
1538
- protectedGroup: group,
1539
- });
1540
- }
1541
- &nbsp;
1542
- return data;
1543
- }
1544
- &nbsp;
1545
- // Helper functions
1546
- &nbsp;
1547
- function groupByProtectedAttribute(data: PredictionData[]): Map&lt;string, PredictionData[]&gt; {
1548
- const groups = new Map&lt;string, PredictionData[]&gt;();
1549
- &nbsp;
1550
- for (const item of data) {
1551
- const group = item.protectedGroup;
1552
- if (!groups.has(group)) {
1553
- groups.set(group, []);
1554
- }
1555
- groups.get(group)?.push(item);
1556
- }
1557
- &nbsp;
1558
- return groups;
1559
- }
1560
- &nbsp;</pre></td></tr></table></pre>
1561
-
1562
- <div class='push'></div><!-- for sticky footer -->
1563
- </div><!-- /wrapper -->
1564
- <div class='footer quiet pad2 space-top1 center small'>
1565
- Code coverage generated by
1566
- <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
1567
- at 2026-01-07T00:09:13.255Z
1568
- </div>
1569
- <script src="../prettify.js"></script>
1570
- <script>
1571
- window.onload = function () {
1572
- prettyPrint();
1573
- };
1574
- </script>
1575
- <script src="../sorter.js"></script>
1576
- <script src="../block-navigation.js"></script>
1577
- </body>
1578
- </html>
1579
-