@euconform/core 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/.turbo/turbo-check-types.log +4 -0
  3. package/.turbo/turbo-test.log +364 -0
  4. package/CHANGELOG.md +7 -0
  5. package/README.md +109 -0
  6. package/coverage/base.css +224 -0
  7. package/coverage/block-navigation.js +87 -0
  8. package/coverage/clover.xml +3282 -0
  9. package/coverage/coverage-final.json +20 -0
  10. package/coverage/favicon.png +0 -0
  11. package/coverage/index.html +161 -0
  12. package/coverage/prettify.css +1 -0
  13. package/coverage/prettify.js +2 -0
  14. package/coverage/sort-arrow-sprite.png +0 -0
  15. package/coverage/sorter.js +210 -0
  16. package/coverage/src/fairness-metrics.ts.html +1579 -0
  17. package/coverage/src/index.html +161 -0
  18. package/coverage/src/index.ts.html +535 -0
  19. package/coverage/src/inference/browser-inference.ts.html +859 -0
  20. package/coverage/src/inference/capability-detection.ts.html +2227 -0
  21. package/coverage/src/inference/index.html +176 -0
  22. package/coverage/src/inference/index.ts.html +553 -0
  23. package/coverage/src/inference/inference-factory.ts.html +751 -0
  24. package/coverage/src/inference/ollama-client.ts.html +1627 -0
  25. package/coverage/src/legal-checks/annex-iv-report.ts.html +556 -0
  26. package/coverage/src/legal-checks/bias-metrics.ts.html +1855 -0
  27. package/coverage/src/legal-checks/data-governance.ts.html +529 -0
  28. package/coverage/src/legal-checks/human-oversight-logging.ts.html +490 -0
  29. package/coverage/src/legal-checks/index.html +206 -0
  30. package/coverage/src/legal-checks/index.ts.html +250 -0
  31. package/coverage/src/legal-checks/risk-classifier.ts.html +940 -0
  32. package/coverage/src/legal-checks/robustness-transparency.ts.html +571 -0
  33. package/coverage/src/metrics/crows-pairs-bias.ts.html +820 -0
  34. package/coverage/src/metrics/index.html +146 -0
  35. package/coverage/src/metrics/index.ts.html +151 -0
  36. package/coverage/src/metrics/stereotype-bias.ts.html +886 -0
  37. package/coverage/src/risk-engine.ts.html +1660 -0
  38. package/coverage/src/types.ts.html +547 -0
  39. package/dist/legal-checks/disclaimer.d.ts +2 -0
  40. package/dist/legal-checks/disclaimer.d.ts.map +1 -0
  41. package/dist/legal-checks/disclaimer.js +1 -0
  42. package/package.json +20 -1
@@ -0,0 +1,2227 @@
1
+
2
+ <!doctype html>
3
+ <html lang="en">
4
+
5
+ <head>
6
+ <title>Code coverage report for src/inference/capability-detection.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/inference</a> capability-detection.ts</h1>
23
+ <div class='clearfix'>
24
+
25
+ <div class='fl pad1y space-right2'>
26
+ <span class="strong">0% </span>
27
+ <span class="quiet">Statements</span>
28
+ <span class='fraction'>0/421</span>
29
+ </div>
30
+
31
+
32
+ <div class='fl pad1y space-right2'>
33
+ <span class="strong">100% </span>
34
+ <span class="quiet">Branches</span>
35
+ <span class='fraction'>1/1</span>
36
+ </div>
37
+
38
+
39
+ <div class='fl pad1y space-right2'>
40
+ <span class="strong">100% </span>
41
+ <span class="quiet">Functions</span>
42
+ <span class='fraction'>1/1</span>
43
+ </div>
44
+
45
+
46
+ <div class='fl pad1y space-right2'>
47
+ <span class="strong">0% </span>
48
+ <span class="quiet">Lines</span>
49
+ <span class='fraction'>0/421</span>
50
+ </div>
51
+
52
+
53
+ </div>
54
+ <p class="quiet">
55
+ Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
56
+ </p>
57
+ <template id="filterTemplate">
58
+ <div class="quiet">
59
+ Filter:
60
+ <input type="search" id="fileSearch">
61
+ </div>
62
+ </template>
63
+ </div>
64
+ <div class='status-line low'></div>
65
+ <pre><table class="coverage">
66
+ <tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
67
+ <a name='L2'></a><a href='#L2'>2</a>
68
+ <a name='L3'></a><a href='#L3'>3</a>
69
+ <a name='L4'></a><a href='#L4'>4</a>
70
+ <a name='L5'></a><a href='#L5'>5</a>
71
+ <a name='L6'></a><a href='#L6'>6</a>
72
+ <a name='L7'></a><a href='#L7'>7</a>
73
+ <a name='L8'></a><a href='#L8'>8</a>
74
+ <a name='L9'></a><a href='#L9'>9</a>
75
+ <a name='L10'></a><a href='#L10'>10</a>
76
+ <a name='L11'></a><a href='#L11'>11</a>
77
+ <a name='L12'></a><a href='#L12'>12</a>
78
+ <a name='L13'></a><a href='#L13'>13</a>
79
+ <a name='L14'></a><a href='#L14'>14</a>
80
+ <a name='L15'></a><a href='#L15'>15</a>
81
+ <a name='L16'></a><a href='#L16'>16</a>
82
+ <a name='L17'></a><a href='#L17'>17</a>
83
+ <a name='L18'></a><a href='#L18'>18</a>
84
+ <a name='L19'></a><a href='#L19'>19</a>
85
+ <a name='L20'></a><a href='#L20'>20</a>
86
+ <a name='L21'></a><a href='#L21'>21</a>
87
+ <a name='L22'></a><a href='#L22'>22</a>
88
+ <a name='L23'></a><a href='#L23'>23</a>
89
+ <a name='L24'></a><a href='#L24'>24</a>
90
+ <a name='L25'></a><a href='#L25'>25</a>
91
+ <a name='L26'></a><a href='#L26'>26</a>
92
+ <a name='L27'></a><a href='#L27'>27</a>
93
+ <a name='L28'></a><a href='#L28'>28</a>
94
+ <a name='L29'></a><a href='#L29'>29</a>
95
+ <a name='L30'></a><a href='#L30'>30</a>
96
+ <a name='L31'></a><a href='#L31'>31</a>
97
+ <a name='L32'></a><a href='#L32'>32</a>
98
+ <a name='L33'></a><a href='#L33'>33</a>
99
+ <a name='L34'></a><a href='#L34'>34</a>
100
+ <a name='L35'></a><a href='#L35'>35</a>
101
+ <a name='L36'></a><a href='#L36'>36</a>
102
+ <a name='L37'></a><a href='#L37'>37</a>
103
+ <a name='L38'></a><a href='#L38'>38</a>
104
+ <a name='L39'></a><a href='#L39'>39</a>
105
+ <a name='L40'></a><a href='#L40'>40</a>
106
+ <a name='L41'></a><a href='#L41'>41</a>
107
+ <a name='L42'></a><a href='#L42'>42</a>
108
+ <a name='L43'></a><a href='#L43'>43</a>
109
+ <a name='L44'></a><a href='#L44'>44</a>
110
+ <a name='L45'></a><a href='#L45'>45</a>
111
+ <a name='L46'></a><a href='#L46'>46</a>
112
+ <a name='L47'></a><a href='#L47'>47</a>
113
+ <a name='L48'></a><a href='#L48'>48</a>
114
+ <a name='L49'></a><a href='#L49'>49</a>
115
+ <a name='L50'></a><a href='#L50'>50</a>
116
+ <a name='L51'></a><a href='#L51'>51</a>
117
+ <a name='L52'></a><a href='#L52'>52</a>
118
+ <a name='L53'></a><a href='#L53'>53</a>
119
+ <a name='L54'></a><a href='#L54'>54</a>
120
+ <a name='L55'></a><a href='#L55'>55</a>
121
+ <a name='L56'></a><a href='#L56'>56</a>
122
+ <a name='L57'></a><a href='#L57'>57</a>
123
+ <a name='L58'></a><a href='#L58'>58</a>
124
+ <a name='L59'></a><a href='#L59'>59</a>
125
+ <a name='L60'></a><a href='#L60'>60</a>
126
+ <a name='L61'></a><a href='#L61'>61</a>
127
+ <a name='L62'></a><a href='#L62'>62</a>
128
+ <a name='L63'></a><a href='#L63'>63</a>
129
+ <a name='L64'></a><a href='#L64'>64</a>
130
+ <a name='L65'></a><a href='#L65'>65</a>
131
+ <a name='L66'></a><a href='#L66'>66</a>
132
+ <a name='L67'></a><a href='#L67'>67</a>
133
+ <a name='L68'></a><a href='#L68'>68</a>
134
+ <a name='L69'></a><a href='#L69'>69</a>
135
+ <a name='L70'></a><a href='#L70'>70</a>
136
+ <a name='L71'></a><a href='#L71'>71</a>
137
+ <a name='L72'></a><a href='#L72'>72</a>
138
+ <a name='L73'></a><a href='#L73'>73</a>
139
+ <a name='L74'></a><a href='#L74'>74</a>
140
+ <a name='L75'></a><a href='#L75'>75</a>
141
+ <a name='L76'></a><a href='#L76'>76</a>
142
+ <a name='L77'></a><a href='#L77'>77</a>
143
+ <a name='L78'></a><a href='#L78'>78</a>
144
+ <a name='L79'></a><a href='#L79'>79</a>
145
+ <a name='L80'></a><a href='#L80'>80</a>
146
+ <a name='L81'></a><a href='#L81'>81</a>
147
+ <a name='L82'></a><a href='#L82'>82</a>
148
+ <a name='L83'></a><a href='#L83'>83</a>
149
+ <a name='L84'></a><a href='#L84'>84</a>
150
+ <a name='L85'></a><a href='#L85'>85</a>
151
+ <a name='L86'></a><a href='#L86'>86</a>
152
+ <a name='L87'></a><a href='#L87'>87</a>
153
+ <a name='L88'></a><a href='#L88'>88</a>
154
+ <a name='L89'></a><a href='#L89'>89</a>
155
+ <a name='L90'></a><a href='#L90'>90</a>
156
+ <a name='L91'></a><a href='#L91'>91</a>
157
+ <a name='L92'></a><a href='#L92'>92</a>
158
+ <a name='L93'></a><a href='#L93'>93</a>
159
+ <a name='L94'></a><a href='#L94'>94</a>
160
+ <a name='L95'></a><a href='#L95'>95</a>
161
+ <a name='L96'></a><a href='#L96'>96</a>
162
+ <a name='L97'></a><a href='#L97'>97</a>
163
+ <a name='L98'></a><a href='#L98'>98</a>
164
+ <a name='L99'></a><a href='#L99'>99</a>
165
+ <a name='L100'></a><a href='#L100'>100</a>
166
+ <a name='L101'></a><a href='#L101'>101</a>
167
+ <a name='L102'></a><a href='#L102'>102</a>
168
+ <a name='L103'></a><a href='#L103'>103</a>
169
+ <a name='L104'></a><a href='#L104'>104</a>
170
+ <a name='L105'></a><a href='#L105'>105</a>
171
+ <a name='L106'></a><a href='#L106'>106</a>
172
+ <a name='L107'></a><a href='#L107'>107</a>
173
+ <a name='L108'></a><a href='#L108'>108</a>
174
+ <a name='L109'></a><a href='#L109'>109</a>
175
+ <a name='L110'></a><a href='#L110'>110</a>
176
+ <a name='L111'></a><a href='#L111'>111</a>
177
+ <a name='L112'></a><a href='#L112'>112</a>
178
+ <a name='L113'></a><a href='#L113'>113</a>
179
+ <a name='L114'></a><a href='#L114'>114</a>
180
+ <a name='L115'></a><a href='#L115'>115</a>
181
+ <a name='L116'></a><a href='#L116'>116</a>
182
+ <a name='L117'></a><a href='#L117'>117</a>
183
+ <a name='L118'></a><a href='#L118'>118</a>
184
+ <a name='L119'></a><a href='#L119'>119</a>
185
+ <a name='L120'></a><a href='#L120'>120</a>
186
+ <a name='L121'></a><a href='#L121'>121</a>
187
+ <a name='L122'></a><a href='#L122'>122</a>
188
+ <a name='L123'></a><a href='#L123'>123</a>
189
+ <a name='L124'></a><a href='#L124'>124</a>
190
+ <a name='L125'></a><a href='#L125'>125</a>
191
+ <a name='L126'></a><a href='#L126'>126</a>
192
+ <a name='L127'></a><a href='#L127'>127</a>
193
+ <a name='L128'></a><a href='#L128'>128</a>
194
+ <a name='L129'></a><a href='#L129'>129</a>
195
+ <a name='L130'></a><a href='#L130'>130</a>
196
+ <a name='L131'></a><a href='#L131'>131</a>
197
+ <a name='L132'></a><a href='#L132'>132</a>
198
+ <a name='L133'></a><a href='#L133'>133</a>
199
+ <a name='L134'></a><a href='#L134'>134</a>
200
+ <a name='L135'></a><a href='#L135'>135</a>
201
+ <a name='L136'></a><a href='#L136'>136</a>
202
+ <a name='L137'></a><a href='#L137'>137</a>
203
+ <a name='L138'></a><a href='#L138'>138</a>
204
+ <a name='L139'></a><a href='#L139'>139</a>
205
+ <a name='L140'></a><a href='#L140'>140</a>
206
+ <a name='L141'></a><a href='#L141'>141</a>
207
+ <a name='L142'></a><a href='#L142'>142</a>
208
+ <a name='L143'></a><a href='#L143'>143</a>
209
+ <a name='L144'></a><a href='#L144'>144</a>
210
+ <a name='L145'></a><a href='#L145'>145</a>
211
+ <a name='L146'></a><a href='#L146'>146</a>
212
+ <a name='L147'></a><a href='#L147'>147</a>
213
+ <a name='L148'></a><a href='#L148'>148</a>
214
+ <a name='L149'></a><a href='#L149'>149</a>
215
+ <a name='L150'></a><a href='#L150'>150</a>
216
+ <a name='L151'></a><a href='#L151'>151</a>
217
+ <a name='L152'></a><a href='#L152'>152</a>
218
+ <a name='L153'></a><a href='#L153'>153</a>
219
+ <a name='L154'></a><a href='#L154'>154</a>
220
+ <a name='L155'></a><a href='#L155'>155</a>
221
+ <a name='L156'></a><a href='#L156'>156</a>
222
+ <a name='L157'></a><a href='#L157'>157</a>
223
+ <a name='L158'></a><a href='#L158'>158</a>
224
+ <a name='L159'></a><a href='#L159'>159</a>
225
+ <a name='L160'></a><a href='#L160'>160</a>
226
+ <a name='L161'></a><a href='#L161'>161</a>
227
+ <a name='L162'></a><a href='#L162'>162</a>
228
+ <a name='L163'></a><a href='#L163'>163</a>
229
+ <a name='L164'></a><a href='#L164'>164</a>
230
+ <a name='L165'></a><a href='#L165'>165</a>
231
+ <a name='L166'></a><a href='#L166'>166</a>
232
+ <a name='L167'></a><a href='#L167'>167</a>
233
+ <a name='L168'></a><a href='#L168'>168</a>
234
+ <a name='L169'></a><a href='#L169'>169</a>
235
+ <a name='L170'></a><a href='#L170'>170</a>
236
+ <a name='L171'></a><a href='#L171'>171</a>
237
+ <a name='L172'></a><a href='#L172'>172</a>
238
+ <a name='L173'></a><a href='#L173'>173</a>
239
+ <a name='L174'></a><a href='#L174'>174</a>
240
+ <a name='L175'></a><a href='#L175'>175</a>
241
+ <a name='L176'></a><a href='#L176'>176</a>
242
+ <a name='L177'></a><a href='#L177'>177</a>
243
+ <a name='L178'></a><a href='#L178'>178</a>
244
+ <a name='L179'></a><a href='#L179'>179</a>
245
+ <a name='L180'></a><a href='#L180'>180</a>
246
+ <a name='L181'></a><a href='#L181'>181</a>
247
+ <a name='L182'></a><a href='#L182'>182</a>
248
+ <a name='L183'></a><a href='#L183'>183</a>
249
+ <a name='L184'></a><a href='#L184'>184</a>
250
+ <a name='L185'></a><a href='#L185'>185</a>
251
+ <a name='L186'></a><a href='#L186'>186</a>
252
+ <a name='L187'></a><a href='#L187'>187</a>
253
+ <a name='L188'></a><a href='#L188'>188</a>
254
+ <a name='L189'></a><a href='#L189'>189</a>
255
+ <a name='L190'></a><a href='#L190'>190</a>
256
+ <a name='L191'></a><a href='#L191'>191</a>
257
+ <a name='L192'></a><a href='#L192'>192</a>
258
+ <a name='L193'></a><a href='#L193'>193</a>
259
+ <a name='L194'></a><a href='#L194'>194</a>
260
+ <a name='L195'></a><a href='#L195'>195</a>
261
+ <a name='L196'></a><a href='#L196'>196</a>
262
+ <a name='L197'></a><a href='#L197'>197</a>
263
+ <a name='L198'></a><a href='#L198'>198</a>
264
+ <a name='L199'></a><a href='#L199'>199</a>
265
+ <a name='L200'></a><a href='#L200'>200</a>
266
+ <a name='L201'></a><a href='#L201'>201</a>
267
+ <a name='L202'></a><a href='#L202'>202</a>
268
+ <a name='L203'></a><a href='#L203'>203</a>
269
+ <a name='L204'></a><a href='#L204'>204</a>
270
+ <a name='L205'></a><a href='#L205'>205</a>
271
+ <a name='L206'></a><a href='#L206'>206</a>
272
+ <a name='L207'></a><a href='#L207'>207</a>
273
+ <a name='L208'></a><a href='#L208'>208</a>
274
+ <a name='L209'></a><a href='#L209'>209</a>
275
+ <a name='L210'></a><a href='#L210'>210</a>
276
+ <a name='L211'></a><a href='#L211'>211</a>
277
+ <a name='L212'></a><a href='#L212'>212</a>
278
+ <a name='L213'></a><a href='#L213'>213</a>
279
+ <a name='L214'></a><a href='#L214'>214</a>
280
+ <a name='L215'></a><a href='#L215'>215</a>
281
+ <a name='L216'></a><a href='#L216'>216</a>
282
+ <a name='L217'></a><a href='#L217'>217</a>
283
+ <a name='L218'></a><a href='#L218'>218</a>
284
+ <a name='L219'></a><a href='#L219'>219</a>
285
+ <a name='L220'></a><a href='#L220'>220</a>
286
+ <a name='L221'></a><a href='#L221'>221</a>
287
+ <a name='L222'></a><a href='#L222'>222</a>
288
+ <a name='L223'></a><a href='#L223'>223</a>
289
+ <a name='L224'></a><a href='#L224'>224</a>
290
+ <a name='L225'></a><a href='#L225'>225</a>
291
+ <a name='L226'></a><a href='#L226'>226</a>
292
+ <a name='L227'></a><a href='#L227'>227</a>
293
+ <a name='L228'></a><a href='#L228'>228</a>
294
+ <a name='L229'></a><a href='#L229'>229</a>
295
+ <a name='L230'></a><a href='#L230'>230</a>
296
+ <a name='L231'></a><a href='#L231'>231</a>
297
+ <a name='L232'></a><a href='#L232'>232</a>
298
+ <a name='L233'></a><a href='#L233'>233</a>
299
+ <a name='L234'></a><a href='#L234'>234</a>
300
+ <a name='L235'></a><a href='#L235'>235</a>
301
+ <a name='L236'></a><a href='#L236'>236</a>
302
+ <a name='L237'></a><a href='#L237'>237</a>
303
+ <a name='L238'></a><a href='#L238'>238</a>
304
+ <a name='L239'></a><a href='#L239'>239</a>
305
+ <a name='L240'></a><a href='#L240'>240</a>
306
+ <a name='L241'></a><a href='#L241'>241</a>
307
+ <a name='L242'></a><a href='#L242'>242</a>
308
+ <a name='L243'></a><a href='#L243'>243</a>
309
+ <a name='L244'></a><a href='#L244'>244</a>
310
+ <a name='L245'></a><a href='#L245'>245</a>
311
+ <a name='L246'></a><a href='#L246'>246</a>
312
+ <a name='L247'></a><a href='#L247'>247</a>
313
+ <a name='L248'></a><a href='#L248'>248</a>
314
+ <a name='L249'></a><a href='#L249'>249</a>
315
+ <a name='L250'></a><a href='#L250'>250</a>
316
+ <a name='L251'></a><a href='#L251'>251</a>
317
+ <a name='L252'></a><a href='#L252'>252</a>
318
+ <a name='L253'></a><a href='#L253'>253</a>
319
+ <a name='L254'></a><a href='#L254'>254</a>
320
+ <a name='L255'></a><a href='#L255'>255</a>
321
+ <a name='L256'></a><a href='#L256'>256</a>
322
+ <a name='L257'></a><a href='#L257'>257</a>
323
+ <a name='L258'></a><a href='#L258'>258</a>
324
+ <a name='L259'></a><a href='#L259'>259</a>
325
+ <a name='L260'></a><a href='#L260'>260</a>
326
+ <a name='L261'></a><a href='#L261'>261</a>
327
+ <a name='L262'></a><a href='#L262'>262</a>
328
+ <a name='L263'></a><a href='#L263'>263</a>
329
+ <a name='L264'></a><a href='#L264'>264</a>
330
+ <a name='L265'></a><a href='#L265'>265</a>
331
+ <a name='L266'></a><a href='#L266'>266</a>
332
+ <a name='L267'></a><a href='#L267'>267</a>
333
+ <a name='L268'></a><a href='#L268'>268</a>
334
+ <a name='L269'></a><a href='#L269'>269</a>
335
+ <a name='L270'></a><a href='#L270'>270</a>
336
+ <a name='L271'></a><a href='#L271'>271</a>
337
+ <a name='L272'></a><a href='#L272'>272</a>
338
+ <a name='L273'></a><a href='#L273'>273</a>
339
+ <a name='L274'></a><a href='#L274'>274</a>
340
+ <a name='L275'></a><a href='#L275'>275</a>
341
+ <a name='L276'></a><a href='#L276'>276</a>
342
+ <a name='L277'></a><a href='#L277'>277</a>
343
+ <a name='L278'></a><a href='#L278'>278</a>
344
+ <a name='L279'></a><a href='#L279'>279</a>
345
+ <a name='L280'></a><a href='#L280'>280</a>
346
+ <a name='L281'></a><a href='#L281'>281</a>
347
+ <a name='L282'></a><a href='#L282'>282</a>
348
+ <a name='L283'></a><a href='#L283'>283</a>
349
+ <a name='L284'></a><a href='#L284'>284</a>
350
+ <a name='L285'></a><a href='#L285'>285</a>
351
+ <a name='L286'></a><a href='#L286'>286</a>
352
+ <a name='L287'></a><a href='#L287'>287</a>
353
+ <a name='L288'></a><a href='#L288'>288</a>
354
+ <a name='L289'></a><a href='#L289'>289</a>
355
+ <a name='L290'></a><a href='#L290'>290</a>
356
+ <a name='L291'></a><a href='#L291'>291</a>
357
+ <a name='L292'></a><a href='#L292'>292</a>
358
+ <a name='L293'></a><a href='#L293'>293</a>
359
+ <a name='L294'></a><a href='#L294'>294</a>
360
+ <a name='L295'></a><a href='#L295'>295</a>
361
+ <a name='L296'></a><a href='#L296'>296</a>
362
+ <a name='L297'></a><a href='#L297'>297</a>
363
+ <a name='L298'></a><a href='#L298'>298</a>
364
+ <a name='L299'></a><a href='#L299'>299</a>
365
+ <a name='L300'></a><a href='#L300'>300</a>
366
+ <a name='L301'></a><a href='#L301'>301</a>
367
+ <a name='L302'></a><a href='#L302'>302</a>
368
+ <a name='L303'></a><a href='#L303'>303</a>
369
+ <a name='L304'></a><a href='#L304'>304</a>
370
+ <a name='L305'></a><a href='#L305'>305</a>
371
+ <a name='L306'></a><a href='#L306'>306</a>
372
+ <a name='L307'></a><a href='#L307'>307</a>
373
+ <a name='L308'></a><a href='#L308'>308</a>
374
+ <a name='L309'></a><a href='#L309'>309</a>
375
+ <a name='L310'></a><a href='#L310'>310</a>
376
+ <a name='L311'></a><a href='#L311'>311</a>
377
+ <a name='L312'></a><a href='#L312'>312</a>
378
+ <a name='L313'></a><a href='#L313'>313</a>
379
+ <a name='L314'></a><a href='#L314'>314</a>
380
+ <a name='L315'></a><a href='#L315'>315</a>
381
+ <a name='L316'></a><a href='#L316'>316</a>
382
+ <a name='L317'></a><a href='#L317'>317</a>
383
+ <a name='L318'></a><a href='#L318'>318</a>
384
+ <a name='L319'></a><a href='#L319'>319</a>
385
+ <a name='L320'></a><a href='#L320'>320</a>
386
+ <a name='L321'></a><a href='#L321'>321</a>
387
+ <a name='L322'></a><a href='#L322'>322</a>
388
+ <a name='L323'></a><a href='#L323'>323</a>
389
+ <a name='L324'></a><a href='#L324'>324</a>
390
+ <a name='L325'></a><a href='#L325'>325</a>
391
+ <a name='L326'></a><a href='#L326'>326</a>
392
+ <a name='L327'></a><a href='#L327'>327</a>
393
+ <a name='L328'></a><a href='#L328'>328</a>
394
+ <a name='L329'></a><a href='#L329'>329</a>
395
+ <a name='L330'></a><a href='#L330'>330</a>
396
+ <a name='L331'></a><a href='#L331'>331</a>
397
+ <a name='L332'></a><a href='#L332'>332</a>
398
+ <a name='L333'></a><a href='#L333'>333</a>
399
+ <a name='L334'></a><a href='#L334'>334</a>
400
+ <a name='L335'></a><a href='#L335'>335</a>
401
+ <a name='L336'></a><a href='#L336'>336</a>
402
+ <a name='L337'></a><a href='#L337'>337</a>
403
+ <a name='L338'></a><a href='#L338'>338</a>
404
+ <a name='L339'></a><a href='#L339'>339</a>
405
+ <a name='L340'></a><a href='#L340'>340</a>
406
+ <a name='L341'></a><a href='#L341'>341</a>
407
+ <a name='L342'></a><a href='#L342'>342</a>
408
+ <a name='L343'></a><a href='#L343'>343</a>
409
+ <a name='L344'></a><a href='#L344'>344</a>
410
+ <a name='L345'></a><a href='#L345'>345</a>
411
+ <a name='L346'></a><a href='#L346'>346</a>
412
+ <a name='L347'></a><a href='#L347'>347</a>
413
+ <a name='L348'></a><a href='#L348'>348</a>
414
+ <a name='L349'></a><a href='#L349'>349</a>
415
+ <a name='L350'></a><a href='#L350'>350</a>
416
+ <a name='L351'></a><a href='#L351'>351</a>
417
+ <a name='L352'></a><a href='#L352'>352</a>
418
+ <a name='L353'></a><a href='#L353'>353</a>
419
+ <a name='L354'></a><a href='#L354'>354</a>
420
+ <a name='L355'></a><a href='#L355'>355</a>
421
+ <a name='L356'></a><a href='#L356'>356</a>
422
+ <a name='L357'></a><a href='#L357'>357</a>
423
+ <a name='L358'></a><a href='#L358'>358</a>
424
+ <a name='L359'></a><a href='#L359'>359</a>
425
+ <a name='L360'></a><a href='#L360'>360</a>
426
+ <a name='L361'></a><a href='#L361'>361</a>
427
+ <a name='L362'></a><a href='#L362'>362</a>
428
+ <a name='L363'></a><a href='#L363'>363</a>
429
+ <a name='L364'></a><a href='#L364'>364</a>
430
+ <a name='L365'></a><a href='#L365'>365</a>
431
+ <a name='L366'></a><a href='#L366'>366</a>
432
+ <a name='L367'></a><a href='#L367'>367</a>
433
+ <a name='L368'></a><a href='#L368'>368</a>
434
+ <a name='L369'></a><a href='#L369'>369</a>
435
+ <a name='L370'></a><a href='#L370'>370</a>
436
+ <a name='L371'></a><a href='#L371'>371</a>
437
+ <a name='L372'></a><a href='#L372'>372</a>
438
+ <a name='L373'></a><a href='#L373'>373</a>
439
+ <a name='L374'></a><a href='#L374'>374</a>
440
+ <a name='L375'></a><a href='#L375'>375</a>
441
+ <a name='L376'></a><a href='#L376'>376</a>
442
+ <a name='L377'></a><a href='#L377'>377</a>
443
+ <a name='L378'></a><a href='#L378'>378</a>
444
+ <a name='L379'></a><a href='#L379'>379</a>
445
+ <a name='L380'></a><a href='#L380'>380</a>
446
+ <a name='L381'></a><a href='#L381'>381</a>
447
+ <a name='L382'></a><a href='#L382'>382</a>
448
+ <a name='L383'></a><a href='#L383'>383</a>
449
+ <a name='L384'></a><a href='#L384'>384</a>
450
+ <a name='L385'></a><a href='#L385'>385</a>
451
+ <a name='L386'></a><a href='#L386'>386</a>
452
+ <a name='L387'></a><a href='#L387'>387</a>
453
+ <a name='L388'></a><a href='#L388'>388</a>
454
+ <a name='L389'></a><a href='#L389'>389</a>
455
+ <a name='L390'></a><a href='#L390'>390</a>
456
+ <a name='L391'></a><a href='#L391'>391</a>
457
+ <a name='L392'></a><a href='#L392'>392</a>
458
+ <a name='L393'></a><a href='#L393'>393</a>
459
+ <a name='L394'></a><a href='#L394'>394</a>
460
+ <a name='L395'></a><a href='#L395'>395</a>
461
+ <a name='L396'></a><a href='#L396'>396</a>
462
+ <a name='L397'></a><a href='#L397'>397</a>
463
+ <a name='L398'></a><a href='#L398'>398</a>
464
+ <a name='L399'></a><a href='#L399'>399</a>
465
+ <a name='L400'></a><a href='#L400'>400</a>
466
+ <a name='L401'></a><a href='#L401'>401</a>
467
+ <a name='L402'></a><a href='#L402'>402</a>
468
+ <a name='L403'></a><a href='#L403'>403</a>
469
+ <a name='L404'></a><a href='#L404'>404</a>
470
+ <a name='L405'></a><a href='#L405'>405</a>
471
+ <a name='L406'></a><a href='#L406'>406</a>
472
+ <a name='L407'></a><a href='#L407'>407</a>
473
+ <a name='L408'></a><a href='#L408'>408</a>
474
+ <a name='L409'></a><a href='#L409'>409</a>
475
+ <a name='L410'></a><a href='#L410'>410</a>
476
+ <a name='L411'></a><a href='#L411'>411</a>
477
+ <a name='L412'></a><a href='#L412'>412</a>
478
+ <a name='L413'></a><a href='#L413'>413</a>
479
+ <a name='L414'></a><a href='#L414'>414</a>
480
+ <a name='L415'></a><a href='#L415'>415</a>
481
+ <a name='L416'></a><a href='#L416'>416</a>
482
+ <a name='L417'></a><a href='#L417'>417</a>
483
+ <a name='L418'></a><a href='#L418'>418</a>
484
+ <a name='L419'></a><a href='#L419'>419</a>
485
+ <a name='L420'></a><a href='#L420'>420</a>
486
+ <a name='L421'></a><a href='#L421'>421</a>
487
+ <a name='L422'></a><a href='#L422'>422</a>
488
+ <a name='L423'></a><a href='#L423'>423</a>
489
+ <a name='L424'></a><a href='#L424'>424</a>
490
+ <a name='L425'></a><a href='#L425'>425</a>
491
+ <a name='L426'></a><a href='#L426'>426</a>
492
+ <a name='L427'></a><a href='#L427'>427</a>
493
+ <a name='L428'></a><a href='#L428'>428</a>
494
+ <a name='L429'></a><a href='#L429'>429</a>
495
+ <a name='L430'></a><a href='#L430'>430</a>
496
+ <a name='L431'></a><a href='#L431'>431</a>
497
+ <a name='L432'></a><a href='#L432'>432</a>
498
+ <a name='L433'></a><a href='#L433'>433</a>
499
+ <a name='L434'></a><a href='#L434'>434</a>
500
+ <a name='L435'></a><a href='#L435'>435</a>
501
+ <a name='L436'></a><a href='#L436'>436</a>
502
+ <a name='L437'></a><a href='#L437'>437</a>
503
+ <a name='L438'></a><a href='#L438'>438</a>
504
+ <a name='L439'></a><a href='#L439'>439</a>
505
+ <a name='L440'></a><a href='#L440'>440</a>
506
+ <a name='L441'></a><a href='#L441'>441</a>
507
+ <a name='L442'></a><a href='#L442'>442</a>
508
+ <a name='L443'></a><a href='#L443'>443</a>
509
+ <a name='L444'></a><a href='#L444'>444</a>
510
+ <a name='L445'></a><a href='#L445'>445</a>
511
+ <a name='L446'></a><a href='#L446'>446</a>
512
+ <a name='L447'></a><a href='#L447'>447</a>
513
+ <a name='L448'></a><a href='#L448'>448</a>
514
+ <a name='L449'></a><a href='#L449'>449</a>
515
+ <a name='L450'></a><a href='#L450'>450</a>
516
+ <a name='L451'></a><a href='#L451'>451</a>
517
+ <a name='L452'></a><a href='#L452'>452</a>
518
+ <a name='L453'></a><a href='#L453'>453</a>
519
+ <a name='L454'></a><a href='#L454'>454</a>
520
+ <a name='L455'></a><a href='#L455'>455</a>
521
+ <a name='L456'></a><a href='#L456'>456</a>
522
+ <a name='L457'></a><a href='#L457'>457</a>
523
+ <a name='L458'></a><a href='#L458'>458</a>
524
+ <a name='L459'></a><a href='#L459'>459</a>
525
+ <a name='L460'></a><a href='#L460'>460</a>
526
+ <a name='L461'></a><a href='#L461'>461</a>
527
+ <a name='L462'></a><a href='#L462'>462</a>
528
+ <a name='L463'></a><a href='#L463'>463</a>
529
+ <a name='L464'></a><a href='#L464'>464</a>
530
+ <a name='L465'></a><a href='#L465'>465</a>
531
+ <a name='L466'></a><a href='#L466'>466</a>
532
+ <a name='L467'></a><a href='#L467'>467</a>
533
+ <a name='L468'></a><a href='#L468'>468</a>
534
+ <a name='L469'></a><a href='#L469'>469</a>
535
+ <a name='L470'></a><a href='#L470'>470</a>
536
+ <a name='L471'></a><a href='#L471'>471</a>
537
+ <a name='L472'></a><a href='#L472'>472</a>
538
+ <a name='L473'></a><a href='#L473'>473</a>
539
+ <a name='L474'></a><a href='#L474'>474</a>
540
+ <a name='L475'></a><a href='#L475'>475</a>
541
+ <a name='L476'></a><a href='#L476'>476</a>
542
+ <a name='L477'></a><a href='#L477'>477</a>
543
+ <a name='L478'></a><a href='#L478'>478</a>
544
+ <a name='L479'></a><a href='#L479'>479</a>
545
+ <a name='L480'></a><a href='#L480'>480</a>
546
+ <a name='L481'></a><a href='#L481'>481</a>
547
+ <a name='L482'></a><a href='#L482'>482</a>
548
+ <a name='L483'></a><a href='#L483'>483</a>
549
+ <a name='L484'></a><a href='#L484'>484</a>
550
+ <a name='L485'></a><a href='#L485'>485</a>
551
+ <a name='L486'></a><a href='#L486'>486</a>
552
+ <a name='L487'></a><a href='#L487'>487</a>
553
+ <a name='L488'></a><a href='#L488'>488</a>
554
+ <a name='L489'></a><a href='#L489'>489</a>
555
+ <a name='L490'></a><a href='#L490'>490</a>
556
+ <a name='L491'></a><a href='#L491'>491</a>
557
+ <a name='L492'></a><a href='#L492'>492</a>
558
+ <a name='L493'></a><a href='#L493'>493</a>
559
+ <a name='L494'></a><a href='#L494'>494</a>
560
+ <a name='L495'></a><a href='#L495'>495</a>
561
+ <a name='L496'></a><a href='#L496'>496</a>
562
+ <a name='L497'></a><a href='#L497'>497</a>
563
+ <a name='L498'></a><a href='#L498'>498</a>
564
+ <a name='L499'></a><a href='#L499'>499</a>
565
+ <a name='L500'></a><a href='#L500'>500</a>
566
+ <a name='L501'></a><a href='#L501'>501</a>
567
+ <a name='L502'></a><a href='#L502'>502</a>
568
+ <a name='L503'></a><a href='#L503'>503</a>
569
+ <a name='L504'></a><a href='#L504'>504</a>
570
+ <a name='L505'></a><a href='#L505'>505</a>
571
+ <a name='L506'></a><a href='#L506'>506</a>
572
+ <a name='L507'></a><a href='#L507'>507</a>
573
+ <a name='L508'></a><a href='#L508'>508</a>
574
+ <a name='L509'></a><a href='#L509'>509</a>
575
+ <a name='L510'></a><a href='#L510'>510</a>
576
+ <a name='L511'></a><a href='#L511'>511</a>
577
+ <a name='L512'></a><a href='#L512'>512</a>
578
+ <a name='L513'></a><a href='#L513'>513</a>
579
+ <a name='L514'></a><a href='#L514'>514</a>
580
+ <a name='L515'></a><a href='#L515'>515</a>
581
+ <a name='L516'></a><a href='#L516'>516</a>
582
+ <a name='L517'></a><a href='#L517'>517</a>
583
+ <a name='L518'></a><a href='#L518'>518</a>
584
+ <a name='L519'></a><a href='#L519'>519</a>
585
+ <a name='L520'></a><a href='#L520'>520</a>
586
+ <a name='L521'></a><a href='#L521'>521</a>
587
+ <a name='L522'></a><a href='#L522'>522</a>
588
+ <a name='L523'></a><a href='#L523'>523</a>
589
+ <a name='L524'></a><a href='#L524'>524</a>
590
+ <a name='L525'></a><a href='#L525'>525</a>
591
+ <a name='L526'></a><a href='#L526'>526</a>
592
+ <a name='L527'></a><a href='#L527'>527</a>
593
+ <a name='L528'></a><a href='#L528'>528</a>
594
+ <a name='L529'></a><a href='#L529'>529</a>
595
+ <a name='L530'></a><a href='#L530'>530</a>
596
+ <a name='L531'></a><a href='#L531'>531</a>
597
+ <a name='L532'></a><a href='#L532'>532</a>
598
+ <a name='L533'></a><a href='#L533'>533</a>
599
+ <a name='L534'></a><a href='#L534'>534</a>
600
+ <a name='L535'></a><a href='#L535'>535</a>
601
+ <a name='L536'></a><a href='#L536'>536</a>
602
+ <a name='L537'></a><a href='#L537'>537</a>
603
+ <a name='L538'></a><a href='#L538'>538</a>
604
+ <a name='L539'></a><a href='#L539'>539</a>
605
+ <a name='L540'></a><a href='#L540'>540</a>
606
+ <a name='L541'></a><a href='#L541'>541</a>
607
+ <a name='L542'></a><a href='#L542'>542</a>
608
+ <a name='L543'></a><a href='#L543'>543</a>
609
+ <a name='L544'></a><a href='#L544'>544</a>
610
+ <a name='L545'></a><a href='#L545'>545</a>
611
+ <a name='L546'></a><a href='#L546'>546</a>
612
+ <a name='L547'></a><a href='#L547'>547</a>
613
+ <a name='L548'></a><a href='#L548'>548</a>
614
+ <a name='L549'></a><a href='#L549'>549</a>
615
+ <a name='L550'></a><a href='#L550'>550</a>
616
+ <a name='L551'></a><a href='#L551'>551</a>
617
+ <a name='L552'></a><a href='#L552'>552</a>
618
+ <a name='L553'></a><a href='#L553'>553</a>
619
+ <a name='L554'></a><a href='#L554'>554</a>
620
+ <a name='L555'></a><a href='#L555'>555</a>
621
+ <a name='L556'></a><a href='#L556'>556</a>
622
+ <a name='L557'></a><a href='#L557'>557</a>
623
+ <a name='L558'></a><a href='#L558'>558</a>
624
+ <a name='L559'></a><a href='#L559'>559</a>
625
+ <a name='L560'></a><a href='#L560'>560</a>
626
+ <a name='L561'></a><a href='#L561'>561</a>
627
+ <a name='L562'></a><a href='#L562'>562</a>
628
+ <a name='L563'></a><a href='#L563'>563</a>
629
+ <a name='L564'></a><a href='#L564'>564</a>
630
+ <a name='L565'></a><a href='#L565'>565</a>
631
+ <a name='L566'></a><a href='#L566'>566</a>
632
+ <a name='L567'></a><a href='#L567'>567</a>
633
+ <a name='L568'></a><a href='#L568'>568</a>
634
+ <a name='L569'></a><a href='#L569'>569</a>
635
+ <a name='L570'></a><a href='#L570'>570</a>
636
+ <a name='L571'></a><a href='#L571'>571</a>
637
+ <a name='L572'></a><a href='#L572'>572</a>
638
+ <a name='L573'></a><a href='#L573'>573</a>
639
+ <a name='L574'></a><a href='#L574'>574</a>
640
+ <a name='L575'></a><a href='#L575'>575</a>
641
+ <a name='L576'></a><a href='#L576'>576</a>
642
+ <a name='L577'></a><a href='#L577'>577</a>
643
+ <a name='L578'></a><a href='#L578'>578</a>
644
+ <a name='L579'></a><a href='#L579'>579</a>
645
+ <a name='L580'></a><a href='#L580'>580</a>
646
+ <a name='L581'></a><a href='#L581'>581</a>
647
+ <a name='L582'></a><a href='#L582'>582</a>
648
+ <a name='L583'></a><a href='#L583'>583</a>
649
+ <a name='L584'></a><a href='#L584'>584</a>
650
+ <a name='L585'></a><a href='#L585'>585</a>
651
+ <a name='L586'></a><a href='#L586'>586</a>
652
+ <a name='L587'></a><a href='#L587'>587</a>
653
+ <a name='L588'></a><a href='#L588'>588</a>
654
+ <a name='L589'></a><a href='#L589'>589</a>
655
+ <a name='L590'></a><a href='#L590'>590</a>
656
+ <a name='L591'></a><a href='#L591'>591</a>
657
+ <a name='L592'></a><a href='#L592'>592</a>
658
+ <a name='L593'></a><a href='#L593'>593</a>
659
+ <a name='L594'></a><a href='#L594'>594</a>
660
+ <a name='L595'></a><a href='#L595'>595</a>
661
+ <a name='L596'></a><a href='#L596'>596</a>
662
+ <a name='L597'></a><a href='#L597'>597</a>
663
+ <a name='L598'></a><a href='#L598'>598</a>
664
+ <a name='L599'></a><a href='#L599'>599</a>
665
+ <a name='L600'></a><a href='#L600'>600</a>
666
+ <a name='L601'></a><a href='#L601'>601</a>
667
+ <a name='L602'></a><a href='#L602'>602</a>
668
+ <a name='L603'></a><a href='#L603'>603</a>
669
+ <a name='L604'></a><a href='#L604'>604</a>
670
+ <a name='L605'></a><a href='#L605'>605</a>
671
+ <a name='L606'></a><a href='#L606'>606</a>
672
+ <a name='L607'></a><a href='#L607'>607</a>
673
+ <a name='L608'></a><a href='#L608'>608</a>
674
+ <a name='L609'></a><a href='#L609'>609</a>
675
+ <a name='L610'></a><a href='#L610'>610</a>
676
+ <a name='L611'></a><a href='#L611'>611</a>
677
+ <a name='L612'></a><a href='#L612'>612</a>
678
+ <a name='L613'></a><a href='#L613'>613</a>
679
+ <a name='L614'></a><a href='#L614'>614</a>
680
+ <a name='L615'></a><a href='#L615'>615</a>
681
+ <a name='L616'></a><a href='#L616'>616</a>
682
+ <a name='L617'></a><a href='#L617'>617</a>
683
+ <a name='L618'></a><a href='#L618'>618</a>
684
+ <a name='L619'></a><a href='#L619'>619</a>
685
+ <a name='L620'></a><a href='#L620'>620</a>
686
+ <a name='L621'></a><a href='#L621'>621</a>
687
+ <a name='L622'></a><a href='#L622'>622</a>
688
+ <a name='L623'></a><a href='#L623'>623</a>
689
+ <a name='L624'></a><a href='#L624'>624</a>
690
+ <a name='L625'></a><a href='#L625'>625</a>
691
+ <a name='L626'></a><a href='#L626'>626</a>
692
+ <a name='L627'></a><a href='#L627'>627</a>
693
+ <a name='L628'></a><a href='#L628'>628</a>
694
+ <a name='L629'></a><a href='#L629'>629</a>
695
+ <a name='L630'></a><a href='#L630'>630</a>
696
+ <a name='L631'></a><a href='#L631'>631</a>
697
+ <a name='L632'></a><a href='#L632'>632</a>
698
+ <a name='L633'></a><a href='#L633'>633</a>
699
+ <a name='L634'></a><a href='#L634'>634</a>
700
+ <a name='L635'></a><a href='#L635'>635</a>
701
+ <a name='L636'></a><a href='#L636'>636</a>
702
+ <a name='L637'></a><a href='#L637'>637</a>
703
+ <a name='L638'></a><a href='#L638'>638</a>
704
+ <a name='L639'></a><a href='#L639'>639</a>
705
+ <a name='L640'></a><a href='#L640'>640</a>
706
+ <a name='L641'></a><a href='#L641'>641</a>
707
+ <a name='L642'></a><a href='#L642'>642</a>
708
+ <a name='L643'></a><a href='#L643'>643</a>
709
+ <a name='L644'></a><a href='#L644'>644</a>
710
+ <a name='L645'></a><a href='#L645'>645</a>
711
+ <a name='L646'></a><a href='#L646'>646</a>
712
+ <a name='L647'></a><a href='#L647'>647</a>
713
+ <a name='L648'></a><a href='#L648'>648</a>
714
+ <a name='L649'></a><a href='#L649'>649</a>
715
+ <a name='L650'></a><a href='#L650'>650</a>
716
+ <a name='L651'></a><a href='#L651'>651</a>
717
+ <a name='L652'></a><a href='#L652'>652</a>
718
+ <a name='L653'></a><a href='#L653'>653</a>
719
+ <a name='L654'></a><a href='#L654'>654</a>
720
+ <a name='L655'></a><a href='#L655'>655</a>
721
+ <a name='L656'></a><a href='#L656'>656</a>
722
+ <a name='L657'></a><a href='#L657'>657</a>
723
+ <a name='L658'></a><a href='#L658'>658</a>
724
+ <a name='L659'></a><a href='#L659'>659</a>
725
+ <a name='L660'></a><a href='#L660'>660</a>
726
+ <a name='L661'></a><a href='#L661'>661</a>
727
+ <a name='L662'></a><a href='#L662'>662</a>
728
+ <a name='L663'></a><a href='#L663'>663</a>
729
+ <a name='L664'></a><a href='#L664'>664</a>
730
+ <a name='L665'></a><a href='#L665'>665</a>
731
+ <a name='L666'></a><a href='#L666'>666</a>
732
+ <a name='L667'></a><a href='#L667'>667</a>
733
+ <a name='L668'></a><a href='#L668'>668</a>
734
+ <a name='L669'></a><a href='#L669'>669</a>
735
+ <a name='L670'></a><a href='#L670'>670</a>
736
+ <a name='L671'></a><a href='#L671'>671</a>
737
+ <a name='L672'></a><a href='#L672'>672</a>
738
+ <a name='L673'></a><a href='#L673'>673</a>
739
+ <a name='L674'></a><a href='#L674'>674</a>
740
+ <a name='L675'></a><a href='#L675'>675</a>
741
+ <a name='L676'></a><a href='#L676'>676</a>
742
+ <a name='L677'></a><a href='#L677'>677</a>
743
+ <a name='L678'></a><a href='#L678'>678</a>
744
+ <a name='L679'></a><a href='#L679'>679</a>
745
+ <a name='L680'></a><a href='#L680'>680</a>
746
+ <a name='L681'></a><a href='#L681'>681</a>
747
+ <a name='L682'></a><a href='#L682'>682</a>
748
+ <a name='L683'></a><a href='#L683'>683</a>
749
+ <a name='L684'></a><a href='#L684'>684</a>
750
+ <a name='L685'></a><a href='#L685'>685</a>
751
+ <a name='L686'></a><a href='#L686'>686</a>
752
+ <a name='L687'></a><a href='#L687'>687</a>
753
+ <a name='L688'></a><a href='#L688'>688</a>
754
+ <a name='L689'></a><a href='#L689'>689</a>
755
+ <a name='L690'></a><a href='#L690'>690</a>
756
+ <a name='L691'></a><a href='#L691'>691</a>
757
+ <a name='L692'></a><a href='#L692'>692</a>
758
+ <a name='L693'></a><a href='#L693'>693</a>
759
+ <a name='L694'></a><a href='#L694'>694</a>
760
+ <a name='L695'></a><a href='#L695'>695</a>
761
+ <a name='L696'></a><a href='#L696'>696</a>
762
+ <a name='L697'></a><a href='#L697'>697</a>
763
+ <a name='L698'></a><a href='#L698'>698</a>
764
+ <a name='L699'></a><a href='#L699'>699</a>
765
+ <a name='L700'></a><a href='#L700'>700</a>
766
+ <a name='L701'></a><a href='#L701'>701</a>
767
+ <a name='L702'></a><a href='#L702'>702</a>
768
+ <a name='L703'></a><a href='#L703'>703</a>
769
+ <a name='L704'></a><a href='#L704'>704</a>
770
+ <a name='L705'></a><a href='#L705'>705</a>
771
+ <a name='L706'></a><a href='#L706'>706</a>
772
+ <a name='L707'></a><a href='#L707'>707</a>
773
+ <a name='L708'></a><a href='#L708'>708</a>
774
+ <a name='L709'></a><a href='#L709'>709</a>
775
+ <a name='L710'></a><a href='#L710'>710</a>
776
+ <a name='L711'></a><a href='#L711'>711</a>
777
+ <a name='L712'></a><a href='#L712'>712</a>
778
+ <a name='L713'></a><a href='#L713'>713</a>
779
+ <a name='L714'></a><a href='#L714'>714</a>
780
+ <a name='L715'></a><a href='#L715'>715</a></td><td class="line-coverage quiet"><span class="cline-any cline-neutral">&nbsp;</span>
781
+ <span class="cline-any cline-neutral">&nbsp;</span>
782
+ <span class="cline-any cline-neutral">&nbsp;</span>
783
+ <span class="cline-any cline-neutral">&nbsp;</span>
784
+ <span class="cline-any cline-neutral">&nbsp;</span>
785
+ <span class="cline-any cline-neutral">&nbsp;</span>
786
+ <span class="cline-any cline-neutral">&nbsp;</span>
787
+ <span class="cline-any cline-neutral">&nbsp;</span>
788
+ <span class="cline-any cline-neutral">&nbsp;</span>
789
+ <span class="cline-any cline-neutral">&nbsp;</span>
790
+ <span class="cline-any cline-neutral">&nbsp;</span>
791
+ <span class="cline-any cline-neutral">&nbsp;</span>
792
+ <span class="cline-any cline-neutral">&nbsp;</span>
793
+ <span class="cline-any cline-neutral">&nbsp;</span>
794
+ <span class="cline-any cline-neutral">&nbsp;</span>
795
+ <span class="cline-any cline-neutral">&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-neutral">&nbsp;</span>
799
+ <span class="cline-any cline-neutral">&nbsp;</span>
800
+ <span class="cline-any cline-neutral">&nbsp;</span>
801
+ <span class="cline-any cline-neutral">&nbsp;</span>
802
+ <span class="cline-any cline-neutral">&nbsp;</span>
803
+ <span class="cline-any cline-neutral">&nbsp;</span>
804
+ <span class="cline-any cline-neutral">&nbsp;</span>
805
+ <span class="cline-any cline-neutral">&nbsp;</span>
806
+ <span class="cline-any cline-neutral">&nbsp;</span>
807
+ <span class="cline-any cline-neutral">&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-neutral">&nbsp;</span>
814
+ <span class="cline-any cline-neutral">&nbsp;</span>
815
+ <span class="cline-any cline-neutral">&nbsp;</span>
816
+ <span class="cline-any cline-neutral">&nbsp;</span>
817
+ <span class="cline-any cline-neutral">&nbsp;</span>
818
+ <span class="cline-any cline-neutral">&nbsp;</span>
819
+ <span class="cline-any cline-neutral">&nbsp;</span>
820
+ <span class="cline-any cline-neutral">&nbsp;</span>
821
+ <span class="cline-any cline-neutral">&nbsp;</span>
822
+ <span class="cline-any cline-neutral">&nbsp;</span>
823
+ <span class="cline-any cline-neutral">&nbsp;</span>
824
+ <span class="cline-any cline-neutral">&nbsp;</span>
825
+ <span class="cline-any cline-neutral">&nbsp;</span>
826
+ <span class="cline-any cline-neutral">&nbsp;</span>
827
+ <span class="cline-any cline-neutral">&nbsp;</span>
828
+ <span class="cline-any cline-neutral">&nbsp;</span>
829
+ <span class="cline-any cline-neutral">&nbsp;</span>
830
+ <span class="cline-any cline-neutral">&nbsp;</span>
831
+ <span class="cline-any cline-neutral">&nbsp;</span>
832
+ <span class="cline-any cline-neutral">&nbsp;</span>
833
+ <span class="cline-any cline-neutral">&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-neutral">&nbsp;</span>
837
+ <span class="cline-any cline-neutral">&nbsp;</span>
838
+ <span class="cline-any cline-neutral">&nbsp;</span>
839
+ <span class="cline-any cline-neutral">&nbsp;</span>
840
+ <span class="cline-any cline-neutral">&nbsp;</span>
841
+ <span class="cline-any cline-neutral">&nbsp;</span>
842
+ <span class="cline-any cline-neutral">&nbsp;</span>
843
+ <span class="cline-any cline-neutral">&nbsp;</span>
844
+ <span class="cline-any cline-neutral">&nbsp;</span>
845
+ <span class="cline-any cline-neutral">&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-neutral">&nbsp;</span>
849
+ <span class="cline-any cline-neutral">&nbsp;</span>
850
+ <span class="cline-any cline-neutral">&nbsp;</span>
851
+ <span class="cline-any cline-neutral">&nbsp;</span>
852
+ <span class="cline-any cline-neutral">&nbsp;</span>
853
+ <span class="cline-any cline-neutral">&nbsp;</span>
854
+ <span class="cline-any cline-neutral">&nbsp;</span>
855
+ <span class="cline-any cline-neutral">&nbsp;</span>
856
+ <span class="cline-any cline-neutral">&nbsp;</span>
857
+ <span class="cline-any cline-neutral">&nbsp;</span>
858
+ <span class="cline-any cline-neutral">&nbsp;</span>
859
+ <span class="cline-any cline-neutral">&nbsp;</span>
860
+ <span class="cline-any cline-neutral">&nbsp;</span>
861
+ <span class="cline-any cline-neutral">&nbsp;</span>
862
+ <span class="cline-any cline-neutral">&nbsp;</span>
863
+ <span class="cline-any cline-neutral">&nbsp;</span>
864
+ <span class="cline-any cline-neutral">&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-no">&nbsp;</span>
868
+ <span class="cline-any cline-no">&nbsp;</span>
869
+ <span class="cline-any cline-no">&nbsp;</span>
870
+ <span class="cline-any cline-no">&nbsp;</span>
871
+ <span class="cline-any cline-neutral">&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-neutral">&nbsp;</span>
876
+ <span class="cline-any cline-neutral">&nbsp;</span>
877
+ <span class="cline-any cline-neutral">&nbsp;</span>
878
+ <span class="cline-any cline-neutral">&nbsp;</span>
879
+ <span class="cline-any cline-neutral">&nbsp;</span>
880
+ <span class="cline-any cline-no">&nbsp;</span>
881
+ <span class="cline-any cline-no">&nbsp;</span>
882
+ <span class="cline-any cline-neutral">&nbsp;</span>
883
+ <span class="cline-any cline-no">&nbsp;</span>
884
+ <span class="cline-any cline-neutral">&nbsp;</span>
885
+ <span class="cline-any cline-no">&nbsp;</span>
886
+ <span class="cline-any cline-neutral">&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-no">&nbsp;</span>
891
+ <span class="cline-any cline-no">&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-no">&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-neutral">&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-neutral">&nbsp;</span>
911
+ <span class="cline-any cline-no">&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-neutral">&nbsp;</span>
915
+ <span class="cline-any cline-neutral">&nbsp;</span>
916
+ <span class="cline-any cline-no">&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-neutral">&nbsp;</span>
920
+ <span class="cline-any cline-no">&nbsp;</span>
921
+ <span class="cline-any cline-neutral">&nbsp;</span>
922
+ <span class="cline-any cline-neutral">&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-neutral">&nbsp;</span>
927
+ <span class="cline-any cline-no">&nbsp;</span>
928
+ <span class="cline-any cline-neutral">&nbsp;</span>
929
+ <span class="cline-any cline-neutral">&nbsp;</span>
930
+ <span class="cline-any cline-no">&nbsp;</span>
931
+ <span class="cline-any cline-no">&nbsp;</span>
932
+ <span class="cline-any cline-no">&nbsp;</span>
933
+ <span class="cline-any cline-no">&nbsp;</span>
934
+ <span class="cline-any cline-neutral">&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-no">&nbsp;</span>
943
+ <span class="cline-any cline-no">&nbsp;</span>
944
+ <span class="cline-any cline-no">&nbsp;</span>
945
+ <span class="cline-any cline-no">&nbsp;</span>
946
+ <span class="cline-any cline-no">&nbsp;</span>
947
+ <span class="cline-any cline-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-neutral">&nbsp;</span>
953
+ <span class="cline-any cline-neutral">&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-neutral">&nbsp;</span>
959
+ <span class="cline-any cline-neutral">&nbsp;</span>
960
+ <span class="cline-any cline-neutral">&nbsp;</span>
961
+ <span class="cline-any cline-no">&nbsp;</span>
962
+ <span class="cline-any cline-no">&nbsp;</span>
963
+ <span class="cline-any cline-no">&nbsp;</span>
964
+ <span class="cline-any cline-no">&nbsp;</span>
965
+ <span class="cline-any cline-neutral">&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-neutral">&nbsp;</span>
971
+ <span class="cline-any cline-neutral">&nbsp;</span>
972
+ <span class="cline-any cline-no">&nbsp;</span>
973
+ <span class="cline-any cline-no">&nbsp;</span>
974
+ <span class="cline-any cline-no">&nbsp;</span>
975
+ <span class="cline-any cline-no">&nbsp;</span>
976
+ <span class="cline-any cline-no">&nbsp;</span>
977
+ <span class="cline-any cline-no">&nbsp;</span>
978
+ <span class="cline-any cline-no">&nbsp;</span>
979
+ <span class="cline-any cline-no">&nbsp;</span>
980
+ <span class="cline-any cline-no">&nbsp;</span>
981
+ <span class="cline-any cline-neutral">&nbsp;</span>
982
+ <span class="cline-any cline-no">&nbsp;</span>
983
+ <span class="cline-any cline-no">&nbsp;</span>
984
+ <span class="cline-any cline-no">&nbsp;</span>
985
+ <span class="cline-any cline-neutral">&nbsp;</span>
986
+ <span class="cline-any cline-neutral">&nbsp;</span>
987
+ <span class="cline-any cline-no">&nbsp;</span>
988
+ <span class="cline-any cline-no">&nbsp;</span>
989
+ <span class="cline-any cline-no">&nbsp;</span>
990
+ <span class="cline-any cline-neutral">&nbsp;</span>
991
+ <span class="cline-any cline-neutral">&nbsp;</span>
992
+ <span class="cline-any cline-no">&nbsp;</span>
993
+ <span class="cline-any cline-neutral">&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-neutral">&nbsp;</span>
1002
+ <span class="cline-any cline-no">&nbsp;</span>
1003
+ <span class="cline-any cline-no">&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-neutral">&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-neutral">&nbsp;</span>
1020
+ <span class="cline-any cline-neutral">&nbsp;</span>
1021
+ <span class="cline-any cline-neutral">&nbsp;</span>
1022
+ <span class="cline-any cline-neutral">&nbsp;</span>
1023
+ <span class="cline-any cline-no">&nbsp;</span>
1024
+ <span class="cline-any cline-no">&nbsp;</span>
1025
+ <span class="cline-any cline-no">&nbsp;</span>
1026
+ <span class="cline-any cline-no">&nbsp;</span>
1027
+ <span class="cline-any cline-no">&nbsp;</span>
1028
+ <span class="cline-any cline-no">&nbsp;</span>
1029
+ <span class="cline-any cline-no">&nbsp;</span>
1030
+ <span class="cline-any cline-neutral">&nbsp;</span>
1031
+ <span class="cline-any cline-neutral">&nbsp;</span>
1032
+ <span class="cline-any cline-neutral">&nbsp;</span>
1033
+ <span class="cline-any cline-neutral">&nbsp;</span>
1034
+ <span class="cline-any cline-no">&nbsp;</span>
1035
+ <span class="cline-any cline-no">&nbsp;</span>
1036
+ <span class="cline-any cline-no">&nbsp;</span>
1037
+ <span class="cline-any cline-no">&nbsp;</span>
1038
+ <span class="cline-any cline-neutral">&nbsp;</span>
1039
+ <span class="cline-any cline-no">&nbsp;</span>
1040
+ <span class="cline-any cline-no">&nbsp;</span>
1041
+ <span class="cline-any cline-no">&nbsp;</span>
1042
+ <span class="cline-any cline-no">&nbsp;</span>
1043
+ <span class="cline-any cline-no">&nbsp;</span>
1044
+ <span class="cline-any cline-no">&nbsp;</span>
1045
+ <span class="cline-any cline-neutral">&nbsp;</span>
1046
+ <span class="cline-any cline-neutral">&nbsp;</span>
1047
+ <span class="cline-any cline-no">&nbsp;</span>
1048
+ <span class="cline-any cline-neutral">&nbsp;</span>
1049
+ <span class="cline-any cline-neutral">&nbsp;</span>
1050
+ <span class="cline-any cline-no">&nbsp;</span>
1051
+ <span class="cline-any cline-no">&nbsp;</span>
1052
+ <span class="cline-any cline-neutral">&nbsp;</span>
1053
+ <span class="cline-any cline-neutral">&nbsp;</span>
1054
+ <span class="cline-any cline-neutral">&nbsp;</span>
1055
+ <span class="cline-any cline-neutral">&nbsp;</span>
1056
+ <span class="cline-any cline-no">&nbsp;</span>
1057
+ <span class="cline-any cline-no">&nbsp;</span>
1058
+ <span class="cline-any cline-neutral">&nbsp;</span>
1059
+ <span class="cline-any cline-neutral">&nbsp;</span>
1060
+ <span class="cline-any cline-no">&nbsp;</span>
1061
+ <span class="cline-any cline-no">&nbsp;</span>
1062
+ <span class="cline-any cline-no">&nbsp;</span>
1063
+ <span class="cline-any cline-no">&nbsp;</span>
1064
+ <span class="cline-any cline-no">&nbsp;</span>
1065
+ <span class="cline-any cline-no">&nbsp;</span>
1066
+ <span class="cline-any cline-no">&nbsp;</span>
1067
+ <span class="cline-any cline-no">&nbsp;</span>
1068
+ <span class="cline-any cline-no">&nbsp;</span>
1069
+ <span class="cline-any cline-no">&nbsp;</span>
1070
+ <span class="cline-any cline-no">&nbsp;</span>
1071
+ <span class="cline-any cline-neutral">&nbsp;</span>
1072
+ <span class="cline-any cline-neutral">&nbsp;</span>
1073
+ <span class="cline-any cline-neutral">&nbsp;</span>
1074
+ <span class="cline-any cline-neutral">&nbsp;</span>
1075
+ <span class="cline-any cline-no">&nbsp;</span>
1076
+ <span class="cline-any cline-no">&nbsp;</span>
1077
+ <span class="cline-any cline-no">&nbsp;</span>
1078
+ <span class="cline-any cline-no">&nbsp;</span>
1079
+ <span class="cline-any cline-neutral">&nbsp;</span>
1080
+ <span class="cline-any cline-neutral">&nbsp;</span>
1081
+ <span class="cline-any cline-neutral">&nbsp;</span>
1082
+ <span class="cline-any cline-neutral">&nbsp;</span>
1083
+ <span class="cline-any cline-no">&nbsp;</span>
1084
+ <span class="cline-any cline-no">&nbsp;</span>
1085
+ <span class="cline-any cline-no">&nbsp;</span>
1086
+ <span class="cline-any cline-no">&nbsp;</span>
1087
+ <span class="cline-any cline-no">&nbsp;</span>
1088
+ <span class="cline-any cline-neutral">&nbsp;</span>
1089
+ <span class="cline-any cline-neutral">&nbsp;</span>
1090
+ <span class="cline-any cline-neutral">&nbsp;</span>
1091
+ <span class="cline-any cline-neutral">&nbsp;</span>
1092
+ <span class="cline-any cline-no">&nbsp;</span>
1093
+ <span class="cline-any cline-no">&nbsp;</span>
1094
+ <span class="cline-any cline-no">&nbsp;</span>
1095
+ <span class="cline-any cline-no">&nbsp;</span>
1096
+ <span class="cline-any cline-no">&nbsp;</span>
1097
+ <span class="cline-any cline-no">&nbsp;</span>
1098
+ <span class="cline-any cline-no">&nbsp;</span>
1099
+ <span class="cline-any cline-no">&nbsp;</span>
1100
+ <span class="cline-any cline-no">&nbsp;</span>
1101
+ <span class="cline-any cline-no">&nbsp;</span>
1102
+ <span class="cline-any cline-no">&nbsp;</span>
1103
+ <span class="cline-any cline-no">&nbsp;</span>
1104
+ <span class="cline-any cline-neutral">&nbsp;</span>
1105
+ <span class="cline-any cline-no">&nbsp;</span>
1106
+ <span class="cline-any cline-no">&nbsp;</span>
1107
+ <span class="cline-any cline-no">&nbsp;</span>
1108
+ <span class="cline-any cline-no">&nbsp;</span>
1109
+ <span class="cline-any cline-no">&nbsp;</span>
1110
+ <span class="cline-any cline-no">&nbsp;</span>
1111
+ <span class="cline-any cline-no">&nbsp;</span>
1112
+ <span class="cline-any cline-no">&nbsp;</span>
1113
+ <span class="cline-any cline-no">&nbsp;</span>
1114
+ <span class="cline-any cline-neutral">&nbsp;</span>
1115
+ <span class="cline-any cline-neutral">&nbsp;</span>
1116
+ <span class="cline-any cline-neutral">&nbsp;</span>
1117
+ <span class="cline-any cline-neutral">&nbsp;</span>
1118
+ <span class="cline-any cline-no">&nbsp;</span>
1119
+ <span class="cline-any cline-no">&nbsp;</span>
1120
+ <span class="cline-any cline-no">&nbsp;</span>
1121
+ <span class="cline-any cline-no">&nbsp;</span>
1122
+ <span class="cline-any cline-no">&nbsp;</span>
1123
+ <span class="cline-any cline-no">&nbsp;</span>
1124
+ <span class="cline-any cline-no">&nbsp;</span>
1125
+ <span class="cline-any cline-no">&nbsp;</span>
1126
+ <span class="cline-any cline-neutral">&nbsp;</span>
1127
+ <span class="cline-any cline-neutral">&nbsp;</span>
1128
+ <span class="cline-any cline-neutral">&nbsp;</span>
1129
+ <span class="cline-any cline-neutral">&nbsp;</span>
1130
+ <span class="cline-any cline-no">&nbsp;</span>
1131
+ <span class="cline-any cline-no">&nbsp;</span>
1132
+ <span class="cline-any cline-no">&nbsp;</span>
1133
+ <span class="cline-any cline-no">&nbsp;</span>
1134
+ <span class="cline-any cline-no">&nbsp;</span>
1135
+ <span class="cline-any cline-no">&nbsp;</span>
1136
+ <span class="cline-any cline-no">&nbsp;</span>
1137
+ <span class="cline-any cline-neutral">&nbsp;</span>
1138
+ <span class="cline-any cline-neutral">&nbsp;</span>
1139
+ <span class="cline-any cline-neutral">&nbsp;</span>
1140
+ <span class="cline-any cline-neutral">&nbsp;</span>
1141
+ <span class="cline-any cline-no">&nbsp;</span>
1142
+ <span class="cline-any cline-no">&nbsp;</span>
1143
+ <span class="cline-any cline-neutral">&nbsp;</span>
1144
+ <span class="cline-any cline-no">&nbsp;</span>
1145
+ <span class="cline-any cline-neutral">&nbsp;</span>
1146
+ <span class="cline-any cline-neutral">&nbsp;</span>
1147
+ <span class="cline-any cline-no">&nbsp;</span>
1148
+ <span class="cline-any cline-neutral">&nbsp;</span>
1149
+ <span class="cline-any cline-neutral">&nbsp;</span>
1150
+ <span class="cline-any cline-no">&nbsp;</span>
1151
+ <span class="cline-any cline-neutral">&nbsp;</span>
1152
+ <span class="cline-any cline-neutral">&nbsp;</span>
1153
+ <span class="cline-any cline-no">&nbsp;</span>
1154
+ <span class="cline-any cline-neutral">&nbsp;</span>
1155
+ <span class="cline-any cline-no">&nbsp;</span>
1156
+ <span class="cline-any cline-no">&nbsp;</span>
1157
+ <span class="cline-any cline-no">&nbsp;</span>
1158
+ <span class="cline-any cline-neutral">&nbsp;</span>
1159
+ <span class="cline-any cline-neutral">&nbsp;</span>
1160
+ <span class="cline-any cline-neutral">&nbsp;</span>
1161
+ <span class="cline-any cline-neutral">&nbsp;</span>
1162
+ <span class="cline-any cline-no">&nbsp;</span>
1163
+ <span class="cline-any cline-no">&nbsp;</span>
1164
+ <span class="cline-any cline-no">&nbsp;</span>
1165
+ <span class="cline-any cline-no">&nbsp;</span>
1166
+ <span class="cline-any cline-neutral">&nbsp;</span>
1167
+ <span class="cline-any cline-neutral">&nbsp;</span>
1168
+ <span class="cline-any cline-neutral">&nbsp;</span>
1169
+ <span class="cline-any cline-neutral">&nbsp;</span>
1170
+ <span class="cline-any cline-no">&nbsp;</span>
1171
+ <span class="cline-any cline-no">&nbsp;</span>
1172
+ <span class="cline-any cline-no">&nbsp;</span>
1173
+ <span class="cline-any cline-no">&nbsp;</span>
1174
+ <span class="cline-any cline-neutral">&nbsp;</span>
1175
+ <span class="cline-any cline-no">&nbsp;</span>
1176
+ <span class="cline-any cline-no">&nbsp;</span>
1177
+ <span class="cline-any cline-no">&nbsp;</span>
1178
+ <span class="cline-any cline-no">&nbsp;</span>
1179
+ <span class="cline-any cline-neutral">&nbsp;</span>
1180
+ <span class="cline-any cline-neutral">&nbsp;</span>
1181
+ <span class="cline-any cline-no">&nbsp;</span>
1182
+ <span class="cline-any cline-no">&nbsp;</span>
1183
+ <span class="cline-any cline-no">&nbsp;</span>
1184
+ <span class="cline-any cline-no">&nbsp;</span>
1185
+ <span class="cline-any cline-no">&nbsp;</span>
1186
+ <span class="cline-any cline-no">&nbsp;</span>
1187
+ <span class="cline-any cline-no">&nbsp;</span>
1188
+ <span class="cline-any cline-no">&nbsp;</span>
1189
+ <span class="cline-any cline-no">&nbsp;</span>
1190
+ <span class="cline-any cline-neutral">&nbsp;</span>
1191
+ <span class="cline-any cline-no">&nbsp;</span>
1192
+ <span class="cline-any cline-no">&nbsp;</span>
1193
+ <span class="cline-any cline-no">&nbsp;</span>
1194
+ <span class="cline-any cline-neutral">&nbsp;</span>
1195
+ <span class="cline-any cline-neutral">&nbsp;</span>
1196
+ <span class="cline-any cline-no">&nbsp;</span>
1197
+ <span class="cline-any cline-no">&nbsp;</span>
1198
+ <span class="cline-any cline-neutral">&nbsp;</span>
1199
+ <span class="cline-any cline-neutral">&nbsp;</span>
1200
+ <span class="cline-any cline-neutral">&nbsp;</span>
1201
+ <span class="cline-any cline-neutral">&nbsp;</span>
1202
+ <span class="cline-any cline-no">&nbsp;</span>
1203
+ <span class="cline-any cline-no">&nbsp;</span>
1204
+ <span class="cline-any cline-neutral">&nbsp;</span>
1205
+ <span class="cline-any cline-no">&nbsp;</span>
1206
+ <span class="cline-any cline-no">&nbsp;</span>
1207
+ <span class="cline-any cline-no">&nbsp;</span>
1208
+ <span class="cline-any cline-no">&nbsp;</span>
1209
+ <span class="cline-any cline-no">&nbsp;</span>
1210
+ <span class="cline-any cline-neutral">&nbsp;</span>
1211
+ <span class="cline-any cline-neutral">&nbsp;</span>
1212
+ <span class="cline-any cline-no">&nbsp;</span>
1213
+ <span class="cline-any cline-no">&nbsp;</span>
1214
+ <span class="cline-any cline-no">&nbsp;</span>
1215
+ <span class="cline-any cline-neutral">&nbsp;</span>
1216
+ <span class="cline-any cline-neutral">&nbsp;</span>
1217
+ <span class="cline-any cline-no">&nbsp;</span>
1218
+ <span class="cline-any cline-no">&nbsp;</span>
1219
+ <span class="cline-any cline-no">&nbsp;</span>
1220
+ <span class="cline-any cline-no">&nbsp;</span>
1221
+ <span class="cline-any cline-no">&nbsp;</span>
1222
+ <span class="cline-any cline-no">&nbsp;</span>
1223
+ <span class="cline-any cline-neutral">&nbsp;</span>
1224
+ <span class="cline-any cline-neutral">&nbsp;</span>
1225
+ <span class="cline-any cline-no">&nbsp;</span>
1226
+ <span class="cline-any cline-no">&nbsp;</span>
1227
+ <span class="cline-any cline-no">&nbsp;</span>
1228
+ <span class="cline-any cline-no">&nbsp;</span>
1229
+ <span class="cline-any cline-no">&nbsp;</span>
1230
+ <span class="cline-any cline-no">&nbsp;</span>
1231
+ <span class="cline-any cline-no">&nbsp;</span>
1232
+ <span class="cline-any cline-no">&nbsp;</span>
1233
+ <span class="cline-any cline-no">&nbsp;</span>
1234
+ <span class="cline-any cline-neutral">&nbsp;</span>
1235
+ <span class="cline-any cline-neutral">&nbsp;</span>
1236
+ <span class="cline-any cline-no">&nbsp;</span>
1237
+ <span class="cline-any cline-no">&nbsp;</span>
1238
+ <span class="cline-any cline-no">&nbsp;</span>
1239
+ <span class="cline-any cline-neutral">&nbsp;</span>
1240
+ <span class="cline-any cline-neutral">&nbsp;</span>
1241
+ <span class="cline-any cline-neutral">&nbsp;</span>
1242
+ <span class="cline-any cline-neutral">&nbsp;</span>
1243
+ <span class="cline-any cline-no">&nbsp;</span>
1244
+ <span class="cline-any cline-no">&nbsp;</span>
1245
+ <span class="cline-any cline-neutral">&nbsp;</span>
1246
+ <span class="cline-any cline-no">&nbsp;</span>
1247
+ <span class="cline-any cline-no">&nbsp;</span>
1248
+ <span class="cline-any cline-no">&nbsp;</span>
1249
+ <span class="cline-any cline-no">&nbsp;</span>
1250
+ <span class="cline-any cline-no">&nbsp;</span>
1251
+ <span class="cline-any cline-neutral">&nbsp;</span>
1252
+ <span class="cline-any cline-no">&nbsp;</span>
1253
+ <span class="cline-any cline-no">&nbsp;</span>
1254
+ <span class="cline-any cline-neutral">&nbsp;</span>
1255
+ <span class="cline-any cline-neutral">&nbsp;</span>
1256
+ <span class="cline-any cline-no">&nbsp;</span>
1257
+ <span class="cline-any cline-no">&nbsp;</span>
1258
+ <span class="cline-any cline-no">&nbsp;</span>
1259
+ <span class="cline-any cline-no">&nbsp;</span>
1260
+ <span class="cline-any cline-neutral">&nbsp;</span>
1261
+ <span class="cline-any cline-no">&nbsp;</span>
1262
+ <span class="cline-any cline-neutral">&nbsp;</span>
1263
+ <span class="cline-any cline-neutral">&nbsp;</span>
1264
+ <span class="cline-any cline-no">&nbsp;</span>
1265
+ <span class="cline-any cline-neutral">&nbsp;</span>
1266
+ <span class="cline-any cline-no">&nbsp;</span>
1267
+ <span class="cline-any cline-no">&nbsp;</span>
1268
+ <span class="cline-any cline-no">&nbsp;</span>
1269
+ <span class="cline-any cline-no">&nbsp;</span>
1270
+ <span class="cline-any cline-no">&nbsp;</span>
1271
+ <span class="cline-any cline-no">&nbsp;</span>
1272
+ <span class="cline-any cline-no">&nbsp;</span>
1273
+ <span class="cline-any cline-neutral">&nbsp;</span>
1274
+ <span class="cline-any cline-no">&nbsp;</span>
1275
+ <span class="cline-any cline-no">&nbsp;</span>
1276
+ <span class="cline-any cline-no">&nbsp;</span>
1277
+ <span class="cline-any cline-neutral">&nbsp;</span>
1278
+ <span class="cline-any cline-no">&nbsp;</span>
1279
+ <span class="cline-any cline-no">&nbsp;</span>
1280
+ <span class="cline-any cline-no">&nbsp;</span>
1281
+ <span class="cline-any cline-no">&nbsp;</span>
1282
+ <span class="cline-any cline-no">&nbsp;</span>
1283
+ <span class="cline-any cline-no">&nbsp;</span>
1284
+ <span class="cline-any cline-neutral">&nbsp;</span>
1285
+ <span class="cline-any cline-neutral">&nbsp;</span>
1286
+ <span class="cline-any cline-neutral">&nbsp;</span>
1287
+ <span class="cline-any cline-neutral">&nbsp;</span>
1288
+ <span class="cline-any cline-no">&nbsp;</span>
1289
+ <span class="cline-any cline-no">&nbsp;</span>
1290
+ <span class="cline-any cline-neutral">&nbsp;</span>
1291
+ <span class="cline-any cline-neutral">&nbsp;</span>
1292
+ <span class="cline-any cline-no">&nbsp;</span>
1293
+ <span class="cline-any cline-no">&nbsp;</span>
1294
+ <span class="cline-any cline-neutral">&nbsp;</span>
1295
+ <span class="cline-any cline-no">&nbsp;</span>
1296
+ <span class="cline-any cline-no">&nbsp;</span>
1297
+ <span class="cline-any cline-no">&nbsp;</span>
1298
+ <span class="cline-any cline-no">&nbsp;</span>
1299
+ <span class="cline-any cline-no">&nbsp;</span>
1300
+ <span class="cline-any cline-no">&nbsp;</span>
1301
+ <span class="cline-any cline-no">&nbsp;</span>
1302
+ <span class="cline-any cline-no">&nbsp;</span>
1303
+ <span class="cline-any cline-no">&nbsp;</span>
1304
+ <span class="cline-any cline-no">&nbsp;</span>
1305
+ <span class="cline-any cline-no">&nbsp;</span>
1306
+ <span class="cline-any cline-no">&nbsp;</span>
1307
+ <span class="cline-any cline-no">&nbsp;</span>
1308
+ <span class="cline-any cline-neutral">&nbsp;</span>
1309
+ <span class="cline-any cline-no">&nbsp;</span>
1310
+ <span class="cline-any cline-no">&nbsp;</span>
1311
+ <span class="cline-any cline-no">&nbsp;</span>
1312
+ <span class="cline-any cline-no">&nbsp;</span>
1313
+ <span class="cline-any cline-no">&nbsp;</span>
1314
+ <span class="cline-any cline-no">&nbsp;</span>
1315
+ <span class="cline-any cline-no">&nbsp;</span>
1316
+ <span class="cline-any cline-no">&nbsp;</span>
1317
+ <span class="cline-any cline-no">&nbsp;</span>
1318
+ <span class="cline-any cline-neutral">&nbsp;</span>
1319
+ <span class="cline-any cline-no">&nbsp;</span>
1320
+ <span class="cline-any cline-neutral">&nbsp;</span>
1321
+ <span class="cline-any cline-no">&nbsp;</span>
1322
+ <span class="cline-any cline-neutral">&nbsp;</span>
1323
+ <span class="cline-any cline-neutral">&nbsp;</span>
1324
+ <span class="cline-any cline-no">&nbsp;</span>
1325
+ <span class="cline-any cline-no">&nbsp;</span>
1326
+ <span class="cline-any cline-no">&nbsp;</span>
1327
+ <span class="cline-any cline-no">&nbsp;</span>
1328
+ <span class="cline-any cline-no">&nbsp;</span>
1329
+ <span class="cline-any cline-neutral">&nbsp;</span>
1330
+ <span class="cline-any cline-no">&nbsp;</span>
1331
+ <span class="cline-any cline-neutral">&nbsp;</span>
1332
+ <span class="cline-any cline-no">&nbsp;</span>
1333
+ <span class="cline-any cline-no">&nbsp;</span>
1334
+ <span class="cline-any cline-no">&nbsp;</span>
1335
+ <span class="cline-any cline-no">&nbsp;</span>
1336
+ <span class="cline-any cline-no">&nbsp;</span>
1337
+ <span class="cline-any cline-neutral">&nbsp;</span>
1338
+ <span class="cline-any cline-no">&nbsp;</span>
1339
+ <span class="cline-any cline-no">&nbsp;</span>
1340
+ <span class="cline-any cline-no">&nbsp;</span>
1341
+ <span class="cline-any cline-no">&nbsp;</span>
1342
+ <span class="cline-any cline-neutral">&nbsp;</span>
1343
+ <span class="cline-any cline-neutral">&nbsp;</span>
1344
+ <span class="cline-any cline-no">&nbsp;</span>
1345
+ <span class="cline-any cline-no">&nbsp;</span>
1346
+ <span class="cline-any cline-no">&nbsp;</span>
1347
+ <span class="cline-any cline-neutral">&nbsp;</span>
1348
+ <span class="cline-any cline-no">&nbsp;</span>
1349
+ <span class="cline-any cline-neutral">&nbsp;</span>
1350
+ <span class="cline-any cline-neutral">&nbsp;</span>
1351
+ <span class="cline-any cline-no">&nbsp;</span>
1352
+ <span class="cline-any cline-no">&nbsp;</span>
1353
+ <span class="cline-any cline-no">&nbsp;</span>
1354
+ <span class="cline-any cline-no">&nbsp;</span>
1355
+ <span class="cline-any cline-neutral">&nbsp;</span>
1356
+ <span class="cline-any cline-no">&nbsp;</span>
1357
+ <span class="cline-any cline-no">&nbsp;</span>
1358
+ <span class="cline-any cline-no">&nbsp;</span>
1359
+ <span class="cline-any cline-no">&nbsp;</span>
1360
+ <span class="cline-any cline-no">&nbsp;</span>
1361
+ <span class="cline-any cline-no">&nbsp;</span>
1362
+ <span class="cline-any cline-no">&nbsp;</span>
1363
+ <span class="cline-any cline-no">&nbsp;</span>
1364
+ <span class="cline-any cline-no">&nbsp;</span>
1365
+ <span class="cline-any cline-no">&nbsp;</span>
1366
+ <span class="cline-any cline-no">&nbsp;</span>
1367
+ <span class="cline-any cline-no">&nbsp;</span>
1368
+ <span class="cline-any cline-no">&nbsp;</span>
1369
+ <span class="cline-any cline-no">&nbsp;</span>
1370
+ <span class="cline-any cline-no">&nbsp;</span>
1371
+ <span class="cline-any cline-no">&nbsp;</span>
1372
+ <span class="cline-any cline-no">&nbsp;</span>
1373
+ <span class="cline-any cline-no">&nbsp;</span>
1374
+ <span class="cline-any cline-no">&nbsp;</span>
1375
+ <span class="cline-any cline-neutral">&nbsp;</span>
1376
+ <span class="cline-any cline-no">&nbsp;</span>
1377
+ <span class="cline-any cline-neutral">&nbsp;</span>
1378
+ <span class="cline-any cline-neutral">&nbsp;</span>
1379
+ <span class="cline-any cline-no">&nbsp;</span>
1380
+ <span class="cline-any cline-no">&nbsp;</span>
1381
+ <span class="cline-any cline-neutral">&nbsp;</span>
1382
+ <span class="cline-any cline-neutral">&nbsp;</span>
1383
+ <span class="cline-any cline-neutral">&nbsp;</span>
1384
+ <span class="cline-any cline-neutral">&nbsp;</span>
1385
+ <span class="cline-any cline-no">&nbsp;</span>
1386
+ <span class="cline-any cline-no">&nbsp;</span>
1387
+ <span class="cline-any cline-no">&nbsp;</span>
1388
+ <span class="cline-any cline-no">&nbsp;</span>
1389
+ <span class="cline-any cline-no">&nbsp;</span>
1390
+ <span class="cline-any cline-neutral">&nbsp;</span>
1391
+ <span class="cline-any cline-no">&nbsp;</span>
1392
+ <span class="cline-any cline-no">&nbsp;</span>
1393
+ <span class="cline-any cline-no">&nbsp;</span>
1394
+ <span class="cline-any cline-no">&nbsp;</span>
1395
+ <span class="cline-any cline-no">&nbsp;</span>
1396
+ <span class="cline-any cline-no">&nbsp;</span>
1397
+ <span class="cline-any cline-no">&nbsp;</span>
1398
+ <span class="cline-any cline-no">&nbsp;</span>
1399
+ <span class="cline-any cline-no">&nbsp;</span>
1400
+ <span class="cline-any cline-no">&nbsp;</span>
1401
+ <span class="cline-any cline-no">&nbsp;</span>
1402
+ <span class="cline-any cline-neutral">&nbsp;</span>
1403
+ <span class="cline-any cline-neutral">&nbsp;</span>
1404
+ <span class="cline-any cline-neutral">&nbsp;</span>
1405
+ <span class="cline-any cline-neutral">&nbsp;</span>
1406
+ <span class="cline-any cline-no">&nbsp;</span>
1407
+ <span class="cline-any cline-no">&nbsp;</span>
1408
+ <span class="cline-any cline-no">&nbsp;</span>
1409
+ <span class="cline-any cline-neutral">&nbsp;</span>
1410
+ <span class="cline-any cline-neutral">&nbsp;</span>
1411
+ <span class="cline-any cline-neutral">&nbsp;</span>
1412
+ <span class="cline-any cline-neutral">&nbsp;</span>
1413
+ <span class="cline-any cline-no">&nbsp;</span>
1414
+ <span class="cline-any cline-no">&nbsp;</span>
1415
+ <span class="cline-any cline-no">&nbsp;</span>
1416
+ <span class="cline-any cline-no">&nbsp;</span>
1417
+ <span class="cline-any cline-no">&nbsp;</span>
1418
+ <span class="cline-any cline-no">&nbsp;</span>
1419
+ <span class="cline-any cline-no">&nbsp;</span>
1420
+ <span class="cline-any cline-neutral">&nbsp;</span>
1421
+ <span class="cline-any cline-no">&nbsp;</span>
1422
+ <span class="cline-any cline-neutral">&nbsp;</span>
1423
+ <span class="cline-any cline-neutral">&nbsp;</span>
1424
+ <span class="cline-any cline-neutral">&nbsp;</span>
1425
+ <span class="cline-any cline-neutral">&nbsp;</span>
1426
+ <span class="cline-any cline-no">&nbsp;</span>
1427
+ <span class="cline-any cline-no">&nbsp;</span>
1428
+ <span class="cline-any cline-no">&nbsp;</span>
1429
+ <span class="cline-any cline-no">&nbsp;</span>
1430
+ <span class="cline-any cline-no">&nbsp;</span>
1431
+ <span class="cline-any cline-no">&nbsp;</span>
1432
+ <span class="cline-any cline-no">&nbsp;</span>
1433
+ <span class="cline-any cline-no">&nbsp;</span>
1434
+ <span class="cline-any cline-neutral">&nbsp;</span>
1435
+ <span class="cline-any cline-no">&nbsp;</span>
1436
+ <span class="cline-any cline-neutral">&nbsp;</span>
1437
+ <span class="cline-any cline-neutral">&nbsp;</span>
1438
+ <span class="cline-any cline-neutral">&nbsp;</span>
1439
+ <span class="cline-any cline-neutral">&nbsp;</span>
1440
+ <span class="cline-any cline-no">&nbsp;</span>
1441
+ <span class="cline-any cline-no">&nbsp;</span>
1442
+ <span class="cline-any cline-neutral">&nbsp;</span>
1443
+ <span class="cline-any cline-no">&nbsp;</span>
1444
+ <span class="cline-any cline-neutral">&nbsp;</span>
1445
+ <span class="cline-any cline-neutral">&nbsp;</span>
1446
+ <span class="cline-any cline-no">&nbsp;</span>
1447
+ <span class="cline-any cline-no">&nbsp;</span>
1448
+ <span class="cline-any cline-no">&nbsp;</span>
1449
+ <span class="cline-any cline-neutral">&nbsp;</span>
1450
+ <span class="cline-any cline-neutral">&nbsp;</span>
1451
+ <span class="cline-any cline-no">&nbsp;</span>
1452
+ <span class="cline-any cline-no">&nbsp;</span>
1453
+ <span class="cline-any cline-no">&nbsp;</span>
1454
+ <span class="cline-any cline-neutral">&nbsp;</span>
1455
+ <span class="cline-any cline-neutral">&nbsp;</span>
1456
+ <span class="cline-any cline-no">&nbsp;</span>
1457
+ <span class="cline-any cline-no">&nbsp;</span>
1458
+ <span class="cline-any cline-no">&nbsp;</span>
1459
+ <span class="cline-any cline-neutral">&nbsp;</span>
1460
+ <span class="cline-any cline-neutral">&nbsp;</span>
1461
+ <span class="cline-any cline-no">&nbsp;</span>
1462
+ <span class="cline-any cline-no">&nbsp;</span>
1463
+ <span class="cline-any cline-no">&nbsp;</span>
1464
+ <span class="cline-any cline-neutral">&nbsp;</span>
1465
+ <span class="cline-any cline-neutral">&nbsp;</span>
1466
+ <span class="cline-any cline-no">&nbsp;</span>
1467
+ <span class="cline-any cline-no">&nbsp;</span>
1468
+ <span class="cline-any cline-neutral">&nbsp;</span>
1469
+ <span class="cline-any cline-neutral">&nbsp;</span>
1470
+ <span class="cline-any cline-neutral">&nbsp;</span>
1471
+ <span class="cline-any cline-neutral">&nbsp;</span>
1472
+ <span class="cline-any cline-no">&nbsp;</span>
1473
+ <span class="cline-any cline-no">&nbsp;</span>
1474
+ <span class="cline-any cline-no">&nbsp;</span>
1475
+ <span class="cline-any cline-neutral">&nbsp;</span>
1476
+ <span class="cline-any cline-neutral">&nbsp;</span>
1477
+ <span class="cline-any cline-no">&nbsp;</span>
1478
+ <span class="cline-any cline-no">&nbsp;</span>
1479
+ <span class="cline-any cline-no">&nbsp;</span>
1480
+ <span class="cline-any cline-neutral">&nbsp;</span>
1481
+ <span class="cline-any cline-neutral">&nbsp;</span>
1482
+ <span class="cline-any cline-neutral">&nbsp;</span>
1483
+ <span class="cline-any cline-neutral">&nbsp;</span>
1484
+ <span class="cline-any cline-no">&nbsp;</span>
1485
+ <span class="cline-any cline-no">&nbsp;</span>
1486
+ <span class="cline-any cline-no">&nbsp;</span>
1487
+ <span class="cline-any cline-neutral">&nbsp;</span>
1488
+ <span class="cline-any cline-neutral">&nbsp;</span>
1489
+ <span class="cline-any cline-neutral">&nbsp;</span>
1490
+ <span class="cline-any cline-neutral">&nbsp;</span>
1491
+ <span class="cline-any cline-no">&nbsp;</span>
1492
+ <span class="cline-any cline-no">&nbsp;</span>
1493
+ <span class="cline-any cline-no">&nbsp;</span>
1494
+ <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">/**
1495
+ * Model Capability Detection Service
1496
+ * Real-time detection of model capabilities with smart caching
1497
+ */
1498
+ &nbsp;
1499
+ import type { BiasCalculationMethod } from "../types";
1500
+ &nbsp;
1501
+ /**
1502
+ * Detection status for model capabilities
1503
+ */
1504
+ export type CapabilityDetectionStatus = "detecting" | "available" | "unavailable" | "error";
1505
+ &nbsp;
1506
+ /**
1507
+ * Model capability information
1508
+ */
1509
+ export interface ModelCapability {
1510
+ modelId: string;
1511
+ engine: "browser" | "ollama";
1512
+ method: BiasCalculationMethod;
1513
+ status: CapabilityDetectionStatus;
1514
+ lastTested?: string;
1515
+ error?: string;
1516
+ recommended?: boolean;
1517
+ }
1518
+ &nbsp;
1519
+ /**
1520
+ * Model selection state for UI components
1521
+ */
1522
+ export interface ModelSelectionState {
1523
+ models: ModelCapability[];
1524
+ selectedModel?: string;
1525
+ isLoading: boolean;
1526
+ showExplanations: boolean;
1527
+ }
1528
+ &nbsp;
1529
+ /**
1530
+ * Cache entry structure with expiration and version tracking
1531
+ */
1532
+ export interface CapabilityCacheEntry {
1533
+ modelId: string;
1534
+ capability: ModelCapability;
1535
+ cachedAt: string;
1536
+ expiresAt: string;
1537
+ ollamaVersion?: string;
1538
+ }
1539
+ &nbsp;
1540
+ /**
1541
+ * Detection progress tracking
1542
+ */
1543
+ export interface DetectionProgress {
1544
+ total: number;
1545
+ completed: number;
1546
+ inProgress: string[];
1547
+ }
1548
+ &nbsp;
1549
+ /**
1550
+ * User preferences for model selection
1551
+ */
1552
+ export interface UserPreferences {
1553
+ showExplanations: boolean;
1554
+ preferExactMethods: boolean;
1555
+ hideUnavailableModels: boolean;
1556
+ }
1557
+ &nbsp;
1558
+ /**
1559
+ * Enhanced model selection state with preferences
1560
+ */
1561
+ export interface EnhancedModelSelectionState extends ModelSelectionState {
1562
+ detectionProgress: DetectionProgress;
1563
+ userPreferences: UserPreferences;
1564
+ lastRefresh: string;
1565
+ }
1566
+ /**
1567
+ * Service interface for capability detection
1568
+ */
1569
+ export interface CapabilityDetectionService {
1570
+ detectAllCapabilities(): Promise&lt;ModelCapability[]&gt;;
1571
+ detectModelCapability(modelId: string, engine: "browser" | "ollama"): Promise&lt;ModelCapability&gt;;
1572
+ getCachedCapability(modelId: string): CapabilityCacheEntry | null;
1573
+ setCachedCapability(capability: ModelCapability): void;
1574
+ clearCache(): void;
1575
+ refreshCapabilities(): Promise&lt;ModelCapability[]&gt;;
1576
+ }
1577
+ &nbsp;
1578
+ /**
1579
+ * Implementation of capability detection service
1580
+ */
1581
+ <span class="cstat-no" title="statement not covered" >export class DefaultCapabilityDetectionService implements CapabilityDetectionService {</span>
1582
+ <span class="cstat-no" title="statement not covered" > private cache: Map&lt;string, CapabilityCacheEntry&gt; = new Map();</span>
1583
+ <span class="cstat-no" title="statement not covered" > private readonly CACHE_DURATION_MS = 24 * 60 * 60 * 1000; // 24 hours</span>
1584
+ <span class="cstat-no" title="statement not covered" > private readonly CACHE_KEY_PREFIX = "euconform_capability_";</span>
1585
+ &nbsp;
1586
+ <span class="cstat-no" title="statement not covered" > constructor() {</span>
1587
+ <span class="cstat-no" title="statement not covered" > this.loadCacheFromStorage();</span>
1588
+ <span class="cstat-no" title="statement not covered" > }</span>
1589
+ &nbsp;
1590
+ /**
1591
+ * Detect capabilities for all available models
1592
+ * Includes browser inference and parallel Ollama model testing
1593
+ */
1594
+ <span class="cstat-no" title="statement not covered" > async detectAllCapabilities(): Promise&lt;ModelCapability[]&gt; {</span>
1595
+ <span class="cstat-no" title="statement not covered" > const capabilities: ModelCapability[] = [];</span>
1596
+ &nbsp;
1597
+ <span class="cstat-no" title="statement not covered" > try {</span>
1598
+ // Import browser models dynamically
1599
+ <span class="cstat-no" title="statement not covered" > const { BROWSER_MODELS } = await import("./browser-inference");</span>
1600
+ &nbsp;
1601
+ <span class="cstat-no" title="statement not covered" > for (const model of BROWSER_MODELS) {</span>
1602
+ <span class="cstat-no" title="statement not covered" > if (!model.supported) continue;</span>
1603
+ <span class="cstat-no" title="statement not covered" > capabilities.push({</span>
1604
+ <span class="cstat-no" title="statement not covered" > modelId: model.id,</span>
1605
+ <span class="cstat-no" title="statement not covered" > engine: "browser",</span>
1606
+ <span class="cstat-no" title="statement not covered" > method: "logprobs_exact",</span>
1607
+ <span class="cstat-no" title="statement not covered" > status: "available",</span>
1608
+ <span class="cstat-no" title="statement not covered" > recommended: true,</span>
1609
+ <span class="cstat-no" title="statement not covered" > lastTested: new Date().toISOString(),</span>
1610
+ <span class="cstat-no" title="statement not covered" > });</span>
1611
+ <span class="cstat-no" title="statement not covered" > }</span>
1612
+ <span class="cstat-no" title="statement not covered" > } catch (error) {</span>
1613
+ <span class="cstat-no" title="statement not covered" > console.warn("Failed to load browser models:", error);</span>
1614
+ // Fallback if import fails
1615
+ <span class="cstat-no" title="statement not covered" > capabilities.push({</span>
1616
+ <span class="cstat-no" title="statement not covered" > modelId: "Xenova/distilgpt2",</span>
1617
+ <span class="cstat-no" title="statement not covered" > engine: "browser",</span>
1618
+ <span class="cstat-no" title="statement not covered" > method: "logprobs_exact",</span>
1619
+ <span class="cstat-no" title="statement not covered" > status: "available",</span>
1620
+ <span class="cstat-no" title="statement not covered" > recommended: true,</span>
1621
+ <span class="cstat-no" title="statement not covered" > lastTested: new Date().toISOString(),</span>
1622
+ <span class="cstat-no" title="statement not covered" > });</span>
1623
+ <span class="cstat-no" title="statement not covered" > }</span>
1624
+ &nbsp;
1625
+ <span class="cstat-no" title="statement not covered" > try {</span>
1626
+ // Import Ollama functions dynamically to avoid issues if not available
1627
+ <span class="cstat-no" title="statement not covered" > const { detectOllama, listOllamaModels } = await import("./ollama-client");</span>
1628
+ &nbsp;
1629
+ // Check if Ollama is available
1630
+ <span class="cstat-no" title="statement not covered" > const ollamaAvailable = await detectOllama();</span>
1631
+ &nbsp;
1632
+ <span class="cstat-no" title="statement not covered" > if (ollamaAvailable) {</span>
1633
+ // Get list of available Ollama models
1634
+ <span class="cstat-no" title="statement not covered" > const ollamaModels = await listOllamaModels();</span>
1635
+ &nbsp;
1636
+ // Detect capabilities for all Ollama models in parallel
1637
+ <span class="cstat-no" title="statement not covered" > const detectionPromises = ollamaModels.map((model) =&gt;</span>
1638
+ <span class="cstat-no" title="statement not covered" > this.detectModelCapability(model.name, "ollama")</span>
1639
+ <span class="cstat-no" title="statement not covered" > );</span>
1640
+ &nbsp;
1641
+ <span class="cstat-no" title="statement not covered" > const ollamaCapabilities = await Promise.allSettled(detectionPromises);</span>
1642
+ &nbsp;
1643
+ // Process results and add successful detections
1644
+ <span class="cstat-no" title="statement not covered" > ollamaCapabilities.forEach((result, index) =&gt; {</span>
1645
+ <span class="cstat-no" title="statement not covered" > if (result.status === "fulfilled") {</span>
1646
+ <span class="cstat-no" title="statement not covered" > capabilities.push(result.value);</span>
1647
+ <span class="cstat-no" title="statement not covered" > } else {</span>
1648
+ // Add error capability for failed detections
1649
+ <span class="cstat-no" title="statement not covered" > const model = ollamaModels[index];</span>
1650
+ <span class="cstat-no" title="statement not covered" > if (model) {</span>
1651
+ <span class="cstat-no" title="statement not covered" > capabilities.push({</span>
1652
+ <span class="cstat-no" title="statement not covered" > modelId: model.name,</span>
1653
+ <span class="cstat-no" title="statement not covered" > engine: "ollama",</span>
1654
+ <span class="cstat-no" title="statement not covered" > method: "logprobs_fallback_latency",</span>
1655
+ <span class="cstat-no" title="statement not covered" > status: "error",</span>
1656
+ <span class="cstat-no" title="statement not covered" > error: result.reason?.message || "Detection failed",</span>
1657
+ <span class="cstat-no" title="statement not covered" > lastTested: new Date().toISOString(),</span>
1658
+ <span class="cstat-no" title="statement not covered" > });</span>
1659
+ <span class="cstat-no" title="statement not covered" > }</span>
1660
+ <span class="cstat-no" title="statement not covered" > }</span>
1661
+ <span class="cstat-no" title="statement not covered" > });</span>
1662
+ <span class="cstat-no" title="statement not covered" > }</span>
1663
+ <span class="cstat-no" title="statement not covered" > } catch (error) {</span>
1664
+ <span class="cstat-no" title="statement not covered" > console.warn("Failed to detect Ollama capabilities:", error);</span>
1665
+ <span class="cstat-no" title="statement not covered" > }</span>
1666
+ &nbsp;
1667
+ // Sort capabilities by recommendation score
1668
+ <span class="cstat-no" title="statement not covered" > return this.sortByRecommendation(capabilities);</span>
1669
+ <span class="cstat-no" title="statement not covered" > }</span>
1670
+ &nbsp;
1671
+ /**
1672
+ * Detect capability for a specific model
1673
+ * Uses cache-first strategy with live fallback
1674
+ */
1675
+ <span class="cstat-no" title="statement not covered" > async detectModelCapability(</span>
1676
+ <span class="cstat-no" title="statement not covered" > modelId: string,</span>
1677
+ <span class="cstat-no" title="statement not covered" > engine: "browser" | "ollama"</span>
1678
+ <span class="cstat-no" title="statement not covered" > ): Promise&lt;ModelCapability&gt; {</span>
1679
+ // Check cache first
1680
+ <span class="cstat-no" title="statement not covered" > const cached = this.getCachedCapability(modelId);</span>
1681
+ <span class="cstat-no" title="statement not covered" > if (cached &amp;&amp; this.isCacheValid(cached)) {</span>
1682
+ <span class="cstat-no" title="statement not covered" > return cached.capability;</span>
1683
+ <span class="cstat-no" title="statement not covered" > }</span>
1684
+ &nbsp;
1685
+ // Browser inference always supports exact log-probabilities
1686
+ <span class="cstat-no" title="statement not covered" > if (engine === "browser") {</span>
1687
+ <span class="cstat-no" title="statement not covered" > const capability: ModelCapability = {</span>
1688
+ <span class="cstat-no" title="statement not covered" > modelId,</span>
1689
+ <span class="cstat-no" title="statement not covered" > engine: "browser",</span>
1690
+ <span class="cstat-no" title="statement not covered" > method: "logprobs_exact",</span>
1691
+ <span class="cstat-no" title="statement not covered" > status: "available",</span>
1692
+ <span class="cstat-no" title="statement not covered" > recommended: true,</span>
1693
+ <span class="cstat-no" title="statement not covered" > lastTested: new Date().toISOString(),</span>
1694
+ <span class="cstat-no" title="statement not covered" > };</span>
1695
+ &nbsp;
1696
+ <span class="cstat-no" title="statement not covered" > this.setCachedCapability(capability);</span>
1697
+ <span class="cstat-no" title="statement not covered" > return capability;</span>
1698
+ <span class="cstat-no" title="statement not covered" > }</span>
1699
+ &nbsp;
1700
+ // Detect Ollama model capability
1701
+ <span class="cstat-no" title="statement not covered" > try {</span>
1702
+ <span class="cstat-no" title="statement not covered" > const { OllamaClient } = await import("./ollama-client");</span>
1703
+ <span class="cstat-no" title="statement not covered" > const client = new OllamaClient(modelId);</span>
1704
+ &nbsp;
1705
+ // Test if model supports log-probabilities
1706
+ <span class="cstat-no" title="statement not covered" > const supportsLogProbs = await client.detectLogProbSupport();</span>
1707
+ &nbsp;
1708
+ <span class="cstat-no" title="statement not covered" > const capability: ModelCapability = {</span>
1709
+ <span class="cstat-no" title="statement not covered" > modelId,</span>
1710
+ <span class="cstat-no" title="statement not covered" > engine: "ollama",</span>
1711
+ <span class="cstat-no" title="statement not covered" > method: supportsLogProbs ? "logprobs_exact" : "logprobs_fallback_latency",</span>
1712
+ <span class="cstat-no" title="statement not covered" > status: "available",</span>
1713
+ <span class="cstat-no" title="statement not covered" > lastTested: new Date().toISOString(),</span>
1714
+ <span class="cstat-no" title="statement not covered" > };</span>
1715
+ &nbsp;
1716
+ <span class="cstat-no" title="statement not covered" > this.setCachedCapability(capability);</span>
1717
+ <span class="cstat-no" title="statement not covered" > return capability;</span>
1718
+ <span class="cstat-no" title="statement not covered" > } catch (error) {</span>
1719
+ <span class="cstat-no" title="statement not covered" > const capability: ModelCapability = {</span>
1720
+ <span class="cstat-no" title="statement not covered" > modelId,</span>
1721
+ <span class="cstat-no" title="statement not covered" > engine: "ollama",</span>
1722
+ <span class="cstat-no" title="statement not covered" > method: "logprobs_fallback_latency",</span>
1723
+ <span class="cstat-no" title="statement not covered" > status: "error",</span>
1724
+ <span class="cstat-no" title="statement not covered" > error: error instanceof Error ? error.message : "Unknown error",</span>
1725
+ <span class="cstat-no" title="statement not covered" > lastTested: new Date().toISOString(),</span>
1726
+ <span class="cstat-no" title="statement not covered" > };</span>
1727
+ &nbsp;
1728
+ // Cache error results for shorter duration to allow retry
1729
+ <span class="cstat-no" title="statement not covered" > this.setCachedCapability(capability, 5 * 60 * 1000); // 5 minutes for errors</span>
1730
+ <span class="cstat-no" title="statement not covered" > return capability;</span>
1731
+ <span class="cstat-no" title="statement not covered" > }</span>
1732
+ <span class="cstat-no" title="statement not covered" > }</span>
1733
+ &nbsp;
1734
+ /**
1735
+ * Get cached capability result
1736
+ */
1737
+ <span class="cstat-no" title="statement not covered" > getCachedCapability(modelId: string): CapabilityCacheEntry | null {</span>
1738
+ <span class="cstat-no" title="statement not covered" > const cached = this.cache.get(modelId);</span>
1739
+ <span class="cstat-no" title="statement not covered" > if (cached &amp;&amp; this.isCacheValid(cached)) {</span>
1740
+ <span class="cstat-no" title="statement not covered" > return cached;</span>
1741
+ <span class="cstat-no" title="statement not covered" > }</span>
1742
+ <span class="cstat-no" title="statement not covered" > return null;</span>
1743
+ <span class="cstat-no" title="statement not covered" > }</span>
1744
+ &nbsp;
1745
+ /**
1746
+ * Cache capability result with optional custom duration
1747
+ */
1748
+ <span class="cstat-no" title="statement not covered" > setCachedCapability(capability: ModelCapability, durationMs?: number): void {</span>
1749
+ <span class="cstat-no" title="statement not covered" > const duration = durationMs || this.CACHE_DURATION_MS;</span>
1750
+ <span class="cstat-no" title="statement not covered" > const now = new Date();</span>
1751
+ <span class="cstat-no" title="statement not covered" > const expiresAt = new Date(now.getTime() + duration);</span>
1752
+ &nbsp;
1753
+ <span class="cstat-no" title="statement not covered" > const cacheEntry: CapabilityCacheEntry = {</span>
1754
+ <span class="cstat-no" title="statement not covered" > modelId: capability.modelId,</span>
1755
+ <span class="cstat-no" title="statement not covered" > capability,</span>
1756
+ <span class="cstat-no" title="statement not covered" > cachedAt: now.toISOString(),</span>
1757
+ <span class="cstat-no" title="statement not covered" > expiresAt: expiresAt.toISOString(),</span>
1758
+ <span class="cstat-no" title="statement not covered" > };</span>
1759
+ &nbsp;
1760
+ // Store in memory cache
1761
+ <span class="cstat-no" title="statement not covered" > this.cache.set(capability.modelId, cacheEntry);</span>
1762
+ &nbsp;
1763
+ // Persist to localStorage
1764
+ <span class="cstat-no" title="statement not covered" > this.saveCacheToStorage(capability.modelId, cacheEntry);</span>
1765
+ <span class="cstat-no" title="statement not covered" > }</span>
1766
+ &nbsp;
1767
+ /**
1768
+ * Clear all cached capabilities
1769
+ */
1770
+ <span class="cstat-no" title="statement not covered" > clearCache(): void {</span>
1771
+ <span class="cstat-no" title="statement not covered" > this.cache.clear();</span>
1772
+ &nbsp;
1773
+ // Clear from localStorage
1774
+ <span class="cstat-no" title="statement not covered" > try {</span>
1775
+ <span class="cstat-no" title="statement not covered" > const keys = Object.keys(localStorage);</span>
1776
+ <span class="cstat-no" title="statement not covered" > for (const key of keys) {</span>
1777
+ <span class="cstat-no" title="statement not covered" > if (key.startsWith(this.CACHE_KEY_PREFIX)) {</span>
1778
+ <span class="cstat-no" title="statement not covered" > localStorage.removeItem(key);</span>
1779
+ <span class="cstat-no" title="statement not covered" > }</span>
1780
+ <span class="cstat-no" title="statement not covered" > }</span>
1781
+ <span class="cstat-no" title="statement not covered" > } catch (error) {</span>
1782
+ <span class="cstat-no" title="statement not covered" > console.warn("Failed to clear capability cache from localStorage:", error);</span>
1783
+ <span class="cstat-no" title="statement not covered" > }</span>
1784
+ <span class="cstat-no" title="statement not covered" > }</span>
1785
+ &nbsp;
1786
+ /**
1787
+ * Refresh all capabilities by clearing cache and re-detecting
1788
+ */
1789
+ <span class="cstat-no" title="statement not covered" > async refreshCapabilities(): Promise&lt;ModelCapability[]&gt; {</span>
1790
+ <span class="cstat-no" title="statement not covered" > this.clearCache();</span>
1791
+ <span class="cstat-no" title="statement not covered" > return this.detectAllCapabilities();</span>
1792
+ <span class="cstat-no" title="statement not covered" > }</span>
1793
+ &nbsp;
1794
+ /**
1795
+ * Check if cache entry is still valid
1796
+ */
1797
+ <span class="cstat-no" title="statement not covered" > protected isCacheValid(cacheEntry: CapabilityCacheEntry): boolean {</span>
1798
+ <span class="cstat-no" title="statement not covered" > const now = new Date();</span>
1799
+ <span class="cstat-no" title="statement not covered" > const expiresAt = new Date(cacheEntry.expiresAt);</span>
1800
+ <span class="cstat-no" title="statement not covered" > return now &lt; expiresAt;</span>
1801
+ <span class="cstat-no" title="statement not covered" > }</span>
1802
+ &nbsp;
1803
+ /**
1804
+ * Load cache from localStorage
1805
+ */
1806
+ <span class="cstat-no" title="statement not covered" > private loadCacheFromStorage(): void {</span>
1807
+ <span class="cstat-no" title="statement not covered" > try {</span>
1808
+ <span class="cstat-no" title="statement not covered" > const keys = Object.keys(localStorage);</span>
1809
+ <span class="cstat-no" title="statement not covered" > for (const key of keys) {</span>
1810
+ <span class="cstat-no" title="statement not covered" > if (key.startsWith(this.CACHE_KEY_PREFIX)) {</span>
1811
+ <span class="cstat-no" title="statement not covered" > const cached = localStorage.getItem(key);</span>
1812
+ <span class="cstat-no" title="statement not covered" > if (cached) {</span>
1813
+ <span class="cstat-no" title="statement not covered" > const cacheEntry: CapabilityCacheEntry = JSON.parse(cached);</span>
1814
+ <span class="cstat-no" title="statement not covered" > if (this.isCacheValid(cacheEntry)) {</span>
1815
+ <span class="cstat-no" title="statement not covered" > const modelId = key.replace(this.CACHE_KEY_PREFIX, "");</span>
1816
+ <span class="cstat-no" title="statement not covered" > this.cache.set(modelId, cacheEntry);</span>
1817
+ <span class="cstat-no" title="statement not covered" > } else {</span>
1818
+ // Remove expired cache entries
1819
+ <span class="cstat-no" title="statement not covered" > localStorage.removeItem(key);</span>
1820
+ <span class="cstat-no" title="statement not covered" > }</span>
1821
+ <span class="cstat-no" title="statement not covered" > }</span>
1822
+ <span class="cstat-no" title="statement not covered" > }</span>
1823
+ <span class="cstat-no" title="statement not covered" > }</span>
1824
+ <span class="cstat-no" title="statement not covered" > } catch (error) {</span>
1825
+ <span class="cstat-no" title="statement not covered" > console.warn("Failed to load capability cache from localStorage:", error);</span>
1826
+ <span class="cstat-no" title="statement not covered" > }</span>
1827
+ <span class="cstat-no" title="statement not covered" > }</span>
1828
+ &nbsp;
1829
+ /**
1830
+ * Save cache entry to localStorage
1831
+ */
1832
+ <span class="cstat-no" title="statement not covered" > private saveCacheToStorage(modelId: string, cacheEntry: CapabilityCacheEntry): void {</span>
1833
+ <span class="cstat-no" title="statement not covered" > try {</span>
1834
+ <span class="cstat-no" title="statement not covered" > const key = `${this.CACHE_KEY_PREFIX}${modelId}`;</span>
1835
+ <span class="cstat-no" title="statement not covered" > localStorage.setItem(key, JSON.stringify(cacheEntry));</span>
1836
+ <span class="cstat-no" title="statement not covered" > } catch (error) {</span>
1837
+ <span class="cstat-no" title="statement not covered" > console.warn("Failed to save capability cache to localStorage:", error);</span>
1838
+ <span class="cstat-no" title="statement not covered" > }</span>
1839
+ <span class="cstat-no" title="statement not covered" > }</span>
1840
+ &nbsp;
1841
+ /**
1842
+ * Sort capabilities by recommendation score
1843
+ */
1844
+ <span class="cstat-no" title="statement not covered" > protected sortByRecommendation(capabilities: ModelCapability[]): ModelCapability[] {</span>
1845
+ <span class="cstat-no" title="statement not covered" > return capabilities.sort((a, b) =&gt; {</span>
1846
+ <span class="cstat-no" title="statement not covered" > const scoreA = this.getRecommendationScore(a);</span>
1847
+ <span class="cstat-no" title="statement not covered" > const scoreB = this.getRecommendationScore(b);</span>
1848
+ <span class="cstat-no" title="statement not covered" > return scoreB - scoreA;</span>
1849
+ <span class="cstat-no" title="statement not covered" > });</span>
1850
+ <span class="cstat-no" title="statement not covered" > }</span>
1851
+ &nbsp;
1852
+ /**
1853
+ * Calculate recommendation score for a capability
1854
+ */
1855
+ <span class="cstat-no" title="statement not covered" > protected getRecommendationScore(capability: ModelCapability): number {</span>
1856
+ <span class="cstat-no" title="statement not covered" > if (capability.status !== "available") return 0;</span>
1857
+ &nbsp;
1858
+ <span class="cstat-no" title="statement not covered" > let score = 0;</span>
1859
+ &nbsp;
1860
+ // Browser inference gets highest score
1861
+ <span class="cstat-no" title="statement not covered" > if (capability.engine === "browser") score += 100;</span>
1862
+ &nbsp;
1863
+ // Exact methods get bonus
1864
+ <span class="cstat-no" title="statement not covered" > if (capability.method === "logprobs_exact") score += 50;</span>
1865
+ &nbsp;
1866
+ // Recommended models get bonus
1867
+ <span class="cstat-no" title="statement not covered" > if (capability.recommended) score += 25;</span>
1868
+ &nbsp;
1869
+ <span class="cstat-no" title="statement not covered" > return score;</span>
1870
+ <span class="cstat-no" title="statement not covered" > }</span>
1871
+ <span class="cstat-no" title="statement not covered" >}</span>
1872
+ &nbsp;
1873
+ /**
1874
+ * Enhanced capability detection service with timeout and retry logic
1875
+ */
1876
+ <span class="cstat-no" title="statement not covered" >export class EnhancedCapabilityDetectionService extends DefaultCapabilityDetectionService {</span>
1877
+ <span class="cstat-no" title="statement not covered" > private readonly DETECTION_TIMEOUT_MS = 5000; // 5 seconds</span>
1878
+ <span class="cstat-no" title="statement not covered" > private readonly MAX_RETRIES = 3;</span>
1879
+ <span class="cstat-no" title="statement not covered" > private readonly RETRY_DELAY_BASE_MS = 1000; // Base delay for exponential backoff</span>
1880
+ &nbsp;
1881
+ /**
1882
+ * Detect model capability with timeout and retry logic
1883
+ */
1884
+ <span class="cstat-no" title="statement not covered" > async detectModelCapability(</span>
1885
+ <span class="cstat-no" title="statement not covered" > modelId: string,</span>
1886
+ <span class="cstat-no" title="statement not covered" > engine: "browser" | "ollama"</span>
1887
+ <span class="cstat-no" title="statement not covered" > ): Promise&lt;ModelCapability&gt; {</span>
1888
+ // Check cache first
1889
+ <span class="cstat-no" title="statement not covered" > const cached = this.getCachedCapability(modelId);</span>
1890
+ <span class="cstat-no" title="statement not covered" > if (cached &amp;&amp; this.isCacheValid(cached)) {</span>
1891
+ <span class="cstat-no" title="statement not covered" > return cached.capability;</span>
1892
+ <span class="cstat-no" title="statement not covered" > }</span>
1893
+ &nbsp;
1894
+ // Browser inference always supports exact log-probabilities
1895
+ <span class="cstat-no" title="statement not covered" > if (engine === "browser") {</span>
1896
+ <span class="cstat-no" title="statement not covered" > const capability: ModelCapability = {</span>
1897
+ <span class="cstat-no" title="statement not covered" > modelId,</span>
1898
+ <span class="cstat-no" title="statement not covered" > engine: "browser",</span>
1899
+ <span class="cstat-no" title="statement not covered" > method: "logprobs_exact",</span>
1900
+ <span class="cstat-no" title="statement not covered" > status: "available",</span>
1901
+ <span class="cstat-no" title="statement not covered" > recommended: true,</span>
1902
+ <span class="cstat-no" title="statement not covered" > lastTested: new Date().toISOString(),</span>
1903
+ <span class="cstat-no" title="statement not covered" > };</span>
1904
+ &nbsp;
1905
+ <span class="cstat-no" title="statement not covered" > this.setCachedCapability(capability);</span>
1906
+ <span class="cstat-no" title="statement not covered" > return capability;</span>
1907
+ <span class="cstat-no" title="statement not covered" > }</span>
1908
+ &nbsp;
1909
+ // Detect Ollama model capability with timeout and retry
1910
+ <span class="cstat-no" title="statement not covered" > return this.detectOllamaCapabilityWithRetry(modelId);</span>
1911
+ <span class="cstat-no" title="statement not covered" > }</span>
1912
+ &nbsp;
1913
+ /**
1914
+ * Detect Ollama capability with retry logic and exponential backoff
1915
+ */
1916
+ <span class="cstat-no" title="statement not covered" > private async detectOllamaCapabilityWithRetry(modelId: string): Promise&lt;ModelCapability&gt; {</span>
1917
+ <span class="cstat-no" title="statement not covered" > let lastError: Error | null = null;</span>
1918
+ &nbsp;
1919
+ <span class="cstat-no" title="statement not covered" > for (let attempt = 0; attempt &lt; this.MAX_RETRIES; attempt++) {</span>
1920
+ <span class="cstat-no" title="statement not covered" > try {</span>
1921
+ <span class="cstat-no" title="statement not covered" > return await this.detectOllamaCapabilityWithTimeout(modelId);</span>
1922
+ <span class="cstat-no" title="statement not covered" > } catch (error) {</span>
1923
+ <span class="cstat-no" title="statement not covered" > lastError = error instanceof Error ? error : new Error("Unknown error");</span>
1924
+ &nbsp;
1925
+ // Don't retry on certain errors
1926
+ <span class="cstat-no" title="statement not covered" > if (this.isNonRetryableError(lastError)) {</span>
1927
+ <span class="cstat-no" title="statement not covered" > break;</span>
1928
+ <span class="cstat-no" title="statement not covered" > }</span>
1929
+ &nbsp;
1930
+ // Wait before retry with exponential backoff
1931
+ <span class="cstat-no" title="statement not covered" > if (attempt &lt; this.MAX_RETRIES - 1) {</span>
1932
+ <span class="cstat-no" title="statement not covered" > const delay = this.RETRY_DELAY_BASE_MS * 2 ** attempt;</span>
1933
+ <span class="cstat-no" title="statement not covered" > await this.sleep(delay);</span>
1934
+ <span class="cstat-no" title="statement not covered" > }</span>
1935
+ <span class="cstat-no" title="statement not covered" > }</span>
1936
+ <span class="cstat-no" title="statement not covered" > }</span>
1937
+ &nbsp;
1938
+ // All retries failed, return error capability
1939
+ <span class="cstat-no" title="statement not covered" > const errorMessage = this.getErrorMessage(lastError);</span>
1940
+ <span class="cstat-no" title="statement not covered" > const capability: ModelCapability = {</span>
1941
+ <span class="cstat-no" title="statement not covered" > modelId,</span>
1942
+ <span class="cstat-no" title="statement not covered" > engine: "ollama",</span>
1943
+ <span class="cstat-no" title="statement not covered" > method: "logprobs_fallback_latency",</span>
1944
+ <span class="cstat-no" title="statement not covered" > status: this.isOllamaUnavailableError(lastError) ? "unavailable" : "error",</span>
1945
+ <span class="cstat-no" title="statement not covered" > error: errorMessage,</span>
1946
+ <span class="cstat-no" title="statement not covered" > lastTested: new Date().toISOString(),</span>
1947
+ <span class="cstat-no" title="statement not covered" > };</span>
1948
+ &nbsp;
1949
+ // Cache error results for shorter duration
1950
+ <span class="cstat-no" title="statement not covered" > this.setCachedCapability(capability, 5 * 60 * 1000); // 5 minutes for errors</span>
1951
+ <span class="cstat-no" title="statement not covered" > return capability;</span>
1952
+ <span class="cstat-no" title="statement not covered" > }</span>
1953
+ &nbsp;
1954
+ /**
1955
+ * Detect Ollama capability with timeout
1956
+ */
1957
+ <span class="cstat-no" title="statement not covered" > private async detectOllamaCapabilityWithTimeout(modelId: string): Promise&lt;ModelCapability&gt; {</span>
1958
+ <span class="cstat-no" title="statement not covered" > let timeoutId: ReturnType&lt;typeof setTimeout&gt; | undefined;</span>
1959
+ &nbsp;
1960
+ <span class="cstat-no" title="statement not covered" > const timeoutPromise = new Promise&lt;never&gt;((_resolve, reject) =&gt; {</span>
1961
+ <span class="cstat-no" title="statement not covered" > timeoutId = setTimeout(() =&gt; {</span>
1962
+ <span class="cstat-no" title="statement not covered" > reject(new Error(`Detection timeout after ${this.DETECTION_TIMEOUT_MS}ms`));</span>
1963
+ <span class="cstat-no" title="statement not covered" > }, this.DETECTION_TIMEOUT_MS);</span>
1964
+ <span class="cstat-no" title="statement not covered" > });</span>
1965
+ &nbsp;
1966
+ <span class="cstat-no" title="statement not covered" > const detectionPromise = (async () =&gt; {</span>
1967
+ <span class="cstat-no" title="statement not covered" > const { OllamaClient, detectOllama } = await import("./ollama-client");</span>
1968
+ &nbsp;
1969
+ // First check if Ollama is available
1970
+ <span class="cstat-no" title="statement not covered" > const ollamaAvailable = await detectOllama();</span>
1971
+ <span class="cstat-no" title="statement not covered" > if (!ollamaAvailable) {</span>
1972
+ <span class="cstat-no" title="statement not covered" > throw new Error("Ollama service is not available");</span>
1973
+ <span class="cstat-no" title="statement not covered" > }</span>
1974
+ &nbsp;
1975
+ <span class="cstat-no" title="statement not covered" > const client = new OllamaClient(modelId);</span>
1976
+ &nbsp;
1977
+ // Test if model supports log-probabilities
1978
+ <span class="cstat-no" title="statement not covered" > const supportsLogProbs = await client.detectLogProbSupport();</span>
1979
+ &nbsp;
1980
+ <span class="cstat-no" title="statement not covered" > const capability: ModelCapability = {</span>
1981
+ <span class="cstat-no" title="statement not covered" > modelId,</span>
1982
+ <span class="cstat-no" title="statement not covered" > engine: "ollama",</span>
1983
+ <span class="cstat-no" title="statement not covered" > method: supportsLogProbs ? "logprobs_exact" : "logprobs_fallback_latency",</span>
1984
+ <span class="cstat-no" title="statement not covered" > status: "available",</span>
1985
+ <span class="cstat-no" title="statement not covered" > lastTested: new Date().toISOString(),</span>
1986
+ <span class="cstat-no" title="statement not covered" > };</span>
1987
+ &nbsp;
1988
+ <span class="cstat-no" title="statement not covered" > this.setCachedCapability(capability);</span>
1989
+ <span class="cstat-no" title="statement not covered" > return capability;</span>
1990
+ <span class="cstat-no" title="statement not covered" > })();</span>
1991
+ &nbsp;
1992
+ <span class="cstat-no" title="statement not covered" > try {</span>
1993
+ <span class="cstat-no" title="statement not covered" > return await Promise.race([detectionPromise, timeoutPromise]);</span>
1994
+ <span class="cstat-no" title="statement not covered" > } finally {</span>
1995
+ <span class="cstat-no" title="statement not covered" > if (timeoutId) clearTimeout(timeoutId);</span>
1996
+ <span class="cstat-no" title="statement not covered" > }</span>
1997
+ <span class="cstat-no" title="statement not covered" > }</span>
1998
+ &nbsp;
1999
+ /**
2000
+ * Enhanced detectAllCapabilities with better error handling
2001
+ */
2002
+ <span class="cstat-no" title="statement not covered" > async detectAllCapabilities(): Promise&lt;ModelCapability[]&gt; {</span>
2003
+ <span class="cstat-no" title="statement not covered" > const capabilities: ModelCapability[] = [];</span>
2004
+ &nbsp;
2005
+ // Add all supported browser models dynamically
2006
+ <span class="cstat-no" title="statement not covered" > try {</span>
2007
+ <span class="cstat-no" title="statement not covered" > const { BROWSER_MODELS } = await import("./browser-inference");</span>
2008
+ &nbsp;
2009
+ <span class="cstat-no" title="statement not covered" > for (const model of BROWSER_MODELS) {</span>
2010
+ <span class="cstat-no" title="statement not covered" > if (!model.supported) continue;</span>
2011
+ <span class="cstat-no" title="statement not covered" > capabilities.push({</span>
2012
+ <span class="cstat-no" title="statement not covered" > modelId: model.id,</span>
2013
+ <span class="cstat-no" title="statement not covered" > engine: "browser",</span>
2014
+ <span class="cstat-no" title="statement not covered" > method: "logprobs_exact",</span>
2015
+ <span class="cstat-no" title="statement not covered" > status: "available",</span>
2016
+ <span class="cstat-no" title="statement not covered" > recommended: true,</span>
2017
+ <span class="cstat-no" title="statement not covered" > lastTested: new Date().toISOString(),</span>
2018
+ <span class="cstat-no" title="statement not covered" > });</span>
2019
+ <span class="cstat-no" title="statement not covered" > }</span>
2020
+ <span class="cstat-no" title="statement not covered" > } catch (error) {</span>
2021
+ <span class="cstat-no" title="statement not covered" > console.warn("Failed to load browser models:", error);</span>
2022
+ // Fallback if import fails
2023
+ <span class="cstat-no" title="statement not covered" > capabilities.push({</span>
2024
+ <span class="cstat-no" title="statement not covered" > modelId: "Xenova/distilgpt2",</span>
2025
+ <span class="cstat-no" title="statement not covered" > engine: "browser",</span>
2026
+ <span class="cstat-no" title="statement not covered" > method: "logprobs_exact",</span>
2027
+ <span class="cstat-no" title="statement not covered" > status: "available",</span>
2028
+ <span class="cstat-no" title="statement not covered" > recommended: true,</span>
2029
+ <span class="cstat-no" title="statement not covered" > lastTested: new Date().toISOString(),</span>
2030
+ <span class="cstat-no" title="statement not covered" > });</span>
2031
+ <span class="cstat-no" title="statement not covered" > }</span>
2032
+ &nbsp;
2033
+ <span class="cstat-no" title="statement not covered" > try {</span>
2034
+ // Import Ollama functions dynamically
2035
+ <span class="cstat-no" title="statement not covered" > const { detectOllama, listOllamaModels } = await import("./ollama-client");</span>
2036
+ &nbsp;
2037
+ // Check if Ollama is available with timeout
2038
+ <span class="cstat-no" title="statement not covered" > const ollamaAvailable = await this.withTimeout(</span>
2039
+ <span class="cstat-no" title="statement not covered" > detectOllama(),</span>
2040
+ <span class="cstat-no" title="statement not covered" > 2000, // 2 second timeout for Ollama availability check</span>
2041
+ <span class="cstat-no" title="statement not covered" > "Ollama availability check timeout"</span>
2042
+ <span class="cstat-no" title="statement not covered" > );</span>
2043
+ &nbsp;
2044
+ <span class="cstat-no" title="statement not covered" > if (ollamaAvailable) {</span>
2045
+ // Get list of available Ollama models with timeout
2046
+ <span class="cstat-no" title="statement not covered" > const ollamaModels = await this.withTimeout(</span>
2047
+ <span class="cstat-no" title="statement not covered" > listOllamaModels(),</span>
2048
+ <span class="cstat-no" title="statement not covered" > 5000, // 5 second timeout for model listing</span>
2049
+ <span class="cstat-no" title="statement not covered" > "Ollama model listing timeout"</span>
2050
+ <span class="cstat-no" title="statement not covered" > );</span>
2051
+ &nbsp;
2052
+ <span class="cstat-no" title="statement not covered" > if (ollamaModels.length === 0) {</span>
2053
+ <span class="cstat-no" title="statement not covered" > console.warn("No Ollama models found");</span>
2054
+ <span class="cstat-no" title="statement not covered" > return capabilities;</span>
2055
+ <span class="cstat-no" title="statement not covered" > }</span>
2056
+ &nbsp;
2057
+ // Detect capabilities for all Ollama models in parallel
2058
+ <span class="cstat-no" title="statement not covered" > const detectionPromises = ollamaModels.map((model) =&gt;</span>
2059
+ <span class="cstat-no" title="statement not covered" > this.detectModelCapability(model.name, "ollama")</span>
2060
+ <span class="cstat-no" title="statement not covered" > );</span>
2061
+ &nbsp;
2062
+ <span class="cstat-no" title="statement not covered" > const ollamaCapabilities = await Promise.allSettled(detectionPromises);</span>
2063
+ &nbsp;
2064
+ // Process results and add all capabilities (including errors)
2065
+ <span class="cstat-no" title="statement not covered" > ollamaCapabilities.forEach((result, index) =&gt; {</span>
2066
+ <span class="cstat-no" title="statement not covered" > if (result.status === "fulfilled") {</span>
2067
+ <span class="cstat-no" title="statement not covered" > capabilities.push(result.value);</span>
2068
+ <span class="cstat-no" title="statement not covered" > } else {</span>
2069
+ // Add error capability for failed detections
2070
+ <span class="cstat-no" title="statement not covered" > const model = ollamaModels[index];</span>
2071
+ <span class="cstat-no" title="statement not covered" > if (model) {</span>
2072
+ <span class="cstat-no" title="statement not covered" > const errorMessage = result.reason?.message || "Detection failed";</span>
2073
+ <span class="cstat-no" title="statement not covered" > capabilities.push({</span>
2074
+ <span class="cstat-no" title="statement not covered" > modelId: model.name,</span>
2075
+ <span class="cstat-no" title="statement not covered" > engine: "ollama",</span>
2076
+ <span class="cstat-no" title="statement not covered" > method: "logprobs_fallback_latency",</span>
2077
+ <span class="cstat-no" title="statement not covered" > status: "error",</span>
2078
+ <span class="cstat-no" title="statement not covered" > error: errorMessage,</span>
2079
+ <span class="cstat-no" title="statement not covered" > lastTested: new Date().toISOString(),</span>
2080
+ <span class="cstat-no" title="statement not covered" > });</span>
2081
+ <span class="cstat-no" title="statement not covered" > }</span>
2082
+ <span class="cstat-no" title="statement not covered" > }</span>
2083
+ <span class="cstat-no" title="statement not covered" > });</span>
2084
+ <span class="cstat-no" title="statement not covered" > } else {</span>
2085
+ <span class="cstat-no" title="statement not covered" > console.info("Ollama is not available, only browser inference will be offered");</span>
2086
+ <span class="cstat-no" title="statement not covered" > }</span>
2087
+ <span class="cstat-no" title="statement not covered" > } catch (error) {</span>
2088
+ <span class="cstat-no" title="statement not covered" > console.warn("Failed to detect Ollama capabilities:", error);</span>
2089
+ // Don't throw - we still have browser inference available
2090
+ <span class="cstat-no" title="statement not covered" > }</span>
2091
+ &nbsp;
2092
+ // Sort capabilities by recommendation score
2093
+ <span class="cstat-no" title="statement not covered" > return this.sortByRecommendation(capabilities);</span>
2094
+ <span class="cstat-no" title="statement not covered" > }</span>
2095
+ &nbsp;
2096
+ /**
2097
+ * Utility function to add timeout to any promise
2098
+ */
2099
+ <span class="cstat-no" title="statement not covered" > private withTimeout&lt;T&gt;(promise: Promise&lt;T&gt;, timeoutMs: number, errorMessage: string): Promise&lt;T&gt; {</span>
2100
+ <span class="cstat-no" title="statement not covered" > return new Promise((resolve, reject) =&gt; {</span>
2101
+ <span class="cstat-no" title="statement not covered" > const timeoutId = setTimeout(() =&gt; {</span>
2102
+ <span class="cstat-no" title="statement not covered" > reject(new Error(errorMessage));</span>
2103
+ <span class="cstat-no" title="statement not covered" > }, timeoutMs);</span>
2104
+ &nbsp;
2105
+ <span class="cstat-no" title="statement not covered" > promise</span>
2106
+ <span class="cstat-no" title="statement not covered" > .then((result) =&gt; {</span>
2107
+ <span class="cstat-no" title="statement not covered" > clearTimeout(timeoutId);</span>
2108
+ <span class="cstat-no" title="statement not covered" > resolve(result);</span>
2109
+ <span class="cstat-no" title="statement not covered" > })</span>
2110
+ <span class="cstat-no" title="statement not covered" > .catch((error) =&gt; {</span>
2111
+ <span class="cstat-no" title="statement not covered" > clearTimeout(timeoutId);</span>
2112
+ <span class="cstat-no" title="statement not covered" > reject(error);</span>
2113
+ <span class="cstat-no" title="statement not covered" > });</span>
2114
+ <span class="cstat-no" title="statement not covered" > });</span>
2115
+ <span class="cstat-no" title="statement not covered" > }</span>
2116
+ &nbsp;
2117
+ /**
2118
+ * Sleep utility for retry delays
2119
+ */
2120
+ <span class="cstat-no" title="statement not covered" > private sleep(ms: number): Promise&lt;void&gt; {</span>
2121
+ <span class="cstat-no" title="statement not covered" > return new Promise((resolve) =&gt; setTimeout(resolve, ms));</span>
2122
+ <span class="cstat-no" title="statement not covered" > }</span>
2123
+ &nbsp;
2124
+ /**
2125
+ * Check if error should not be retried
2126
+ */
2127
+ <span class="cstat-no" title="statement not covered" > private isNonRetryableError(error: Error): boolean {</span>
2128
+ <span class="cstat-no" title="statement not covered" > const message = error.message.toLowerCase();</span>
2129
+ <span class="cstat-no" title="statement not covered" > return (</span>
2130
+ <span class="cstat-no" title="statement not covered" > message.includes("not found") ||</span>
2131
+ <span class="cstat-no" title="statement not covered" > (message.includes("model") &amp;&amp; message.includes("not available")) ||</span>
2132
+ <span class="cstat-no" title="statement not covered" > message.includes("permission denied") ||</span>
2133
+ <span class="cstat-no" title="statement not covered" > message.includes("unauthorized")</span>
2134
+ );
2135
+ <span class="cstat-no" title="statement not covered" > }</span>
2136
+ &nbsp;
2137
+ /**
2138
+ * Check if error indicates Ollama is unavailable
2139
+ */
2140
+ <span class="cstat-no" title="statement not covered" > private isOllamaUnavailableError(error: Error | null): boolean {</span>
2141
+ <span class="cstat-no" title="statement not covered" > if (!error) return false;</span>
2142
+ <span class="cstat-no" title="statement not covered" > const message = error.message.toLowerCase();</span>
2143
+ <span class="cstat-no" title="statement not covered" > return (</span>
2144
+ <span class="cstat-no" title="statement not covered" > message.includes("ollama service is not available") ||</span>
2145
+ <span class="cstat-no" title="statement not covered" > message.includes("connection refused") ||</span>
2146
+ <span class="cstat-no" title="statement not covered" > message.includes("network error") ||</span>
2147
+ <span class="cstat-no" title="statement not covered" > message.includes("fetch failed")</span>
2148
+ );
2149
+ <span class="cstat-no" title="statement not covered" > }</span>
2150
+ &nbsp;
2151
+ /**
2152
+ * Get user-friendly error message
2153
+ */
2154
+ <span class="cstat-no" title="statement not covered" > private getErrorMessage(error: Error | null): string {</span>
2155
+ <span class="cstat-no" title="statement not covered" > if (!error) return "Unknown error";</span>
2156
+ &nbsp;
2157
+ <span class="cstat-no" title="statement not covered" > const message = error.message;</span>
2158
+ &nbsp;
2159
+ // Timeout errors
2160
+ <span class="cstat-no" title="statement not covered" > if (message.includes("timeout")) {</span>
2161
+ <span class="cstat-no" title="statement not covered" > return "Model detection timed out. The model may be slow to respond.";</span>
2162
+ <span class="cstat-no" title="statement not covered" > }</span>
2163
+ &nbsp;
2164
+ // Ollama unavailable
2165
+ <span class="cstat-no" title="statement not covered" > if (this.isOllamaUnavailableError(error)) {</span>
2166
+ <span class="cstat-no" title="statement not covered" > return "Ollama service is not running. Please start Ollama to use local models.";</span>
2167
+ <span class="cstat-no" title="statement not covered" > }</span>
2168
+ &nbsp;
2169
+ // Model not found
2170
+ <span class="cstat-no" title="statement not covered" > if (message.includes("not found")) {</span>
2171
+ <span class="cstat-no" title="statement not covered" > return "Model not found. Please ensure the model is installed in Ollama.";</span>
2172
+ <span class="cstat-no" title="statement not covered" > }</span>
2173
+ &nbsp;
2174
+ // Network errors
2175
+ <span class="cstat-no" title="statement not covered" > if (message.includes("network") || message.includes("fetch")) {</span>
2176
+ <span class="cstat-no" title="statement not covered" > return "Network error. Please check your connection and try again.";</span>
2177
+ <span class="cstat-no" title="statement not covered" > }</span>
2178
+ &nbsp;
2179
+ // Generic error
2180
+ <span class="cstat-no" title="statement not covered" > return `Detection failed: ${message}`;</span>
2181
+ <span class="cstat-no" title="statement not covered" > }</span>
2182
+ &nbsp;
2183
+ /**
2184
+ * Check if cache entry is still valid (override to handle version tracking)
2185
+ */
2186
+ <span class="cstat-no" title="statement not covered" > protected isCacheValid(cacheEntry: CapabilityCacheEntry): boolean {</span>
2187
+ <span class="cstat-no" title="statement not covered" > const now = new Date();</span>
2188
+ <span class="cstat-no" title="statement not covered" > const expiresAt = new Date(cacheEntry.expiresAt);</span>
2189
+ &nbsp;
2190
+ // Check expiration
2191
+ <span class="cstat-no" title="statement not covered" > if (now &gt;= expiresAt) {</span>
2192
+ <span class="cstat-no" title="statement not covered" > return false;</span>
2193
+ <span class="cstat-no" title="statement not covered" > }</span>
2194
+ &nbsp;
2195
+ // TODO: Add Ollama version checking when available
2196
+ // For now, we rely on time-based expiration
2197
+ &nbsp;
2198
+ <span class="cstat-no" title="statement not covered" > return true;</span>
2199
+ <span class="cstat-no" title="statement not covered" > }</span>
2200
+ <span class="cstat-no" title="statement not covered" >}</span>
2201
+ &nbsp;
2202
+ /**
2203
+ * Create a capability detection service instance
2204
+ */
2205
+ <span class="cstat-no" title="statement not covered" >export function createCapabilityDetectionService(): CapabilityDetectionService {</span>
2206
+ <span class="cstat-no" title="statement not covered" > return new EnhancedCapabilityDetectionService();</span>
2207
+ <span class="cstat-no" title="statement not covered" >}</span>
2208
+ &nbsp;</pre></td></tr></table></pre>
2209
+
2210
+ <div class='push'></div><!-- for sticky footer -->
2211
+ </div><!-- /wrapper -->
2212
+ <div class='footer quiet pad2 space-top1 center small'>
2213
+ Code coverage generated by
2214
+ <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
2215
+ at 2026-01-07T00:09:13.255Z
2216
+ </div>
2217
+ <script src="../../prettify.js"></script>
2218
+ <script>
2219
+ window.onload = function () {
2220
+ prettyPrint();
2221
+ };
2222
+ </script>
2223
+ <script src="../../sorter.js"></script>
2224
+ <script src="../../block-navigation.js"></script>
2225
+ </body>
2226
+ </html>
2227
+