@stream-io/video-client 0.0.1-alpha.10

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 (222) hide show
  1. package/LICENSE +219 -0
  2. package/README.md +14 -0
  3. package/coverage/lcov-report/base.css +224 -0
  4. package/coverage/lcov-report/block-navigation.js +87 -0
  5. package/coverage/lcov-report/favicon.png +0 -0
  6. package/coverage/lcov-report/index.html +296 -0
  7. package/coverage/lcov-report/prettify.css +1 -0
  8. package/coverage/lcov-report/prettify.js +2 -0
  9. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  10. package/coverage/lcov-report/sorter.js +196 -0
  11. package/coverage/lcov-report/src/Batcher.ts.html +214 -0
  12. package/coverage/lcov-report/src/CallDropScheduler.ts.html +661 -0
  13. package/coverage/lcov-report/src/StreamSfuClient.ts.html +640 -0
  14. package/coverage/lcov-report/src/StreamVideoClient.ts.html +1594 -0
  15. package/coverage/lcov-report/src/config/defaultConfigs.ts.html +130 -0
  16. package/coverage/lcov-report/src/config/index.html +116 -0
  17. package/coverage/lcov-report/src/coordinator/StreamCoordinatorClient.ts.html +430 -0
  18. package/coverage/lcov-report/src/coordinator/connection/base64.ts.html +325 -0
  19. package/coverage/lcov-report/src/coordinator/connection/client.ts.html +2527 -0
  20. package/coverage/lcov-report/src/coordinator/connection/connection.ts.html +2335 -0
  21. package/coverage/lcov-report/src/coordinator/connection/connection_fallback.ts.html +802 -0
  22. package/coverage/lcov-report/src/coordinator/connection/errors.ts.html +295 -0
  23. package/coverage/lcov-report/src/coordinator/connection/index.html +251 -0
  24. package/coverage/lcov-report/src/coordinator/connection/insights.ts.html +349 -0
  25. package/coverage/lcov-report/src/coordinator/connection/signing.ts.html +397 -0
  26. package/coverage/lcov-report/src/coordinator/connection/token_manager.ts.html +565 -0
  27. package/coverage/lcov-report/src/coordinator/connection/types.ts.html +418 -0
  28. package/coverage/lcov-report/src/coordinator/connection/utils.ts.html +529 -0
  29. package/coverage/lcov-report/src/coordinator/index.html +116 -0
  30. package/coverage/lcov-report/src/events/call.ts.html +583 -0
  31. package/coverage/lcov-report/src/events/index.html +161 -0
  32. package/coverage/lcov-report/src/events/internal.ts.html +226 -0
  33. package/coverage/lcov-report/src/events/participant.ts.html +376 -0
  34. package/coverage/lcov-report/src/events/speaker.ts.html +271 -0
  35. package/coverage/lcov-report/src/gen/google/protobuf/index.html +131 -0
  36. package/coverage/lcov-report/src/gen/google/protobuf/struct.ts.html +1528 -0
  37. package/coverage/lcov-report/src/gen/google/protobuf/timestamp.ts.html +958 -0
  38. package/coverage/lcov-report/src/gen/video/sfu/event/events.ts.html +5971 -0
  39. package/coverage/lcov-report/src/gen/video/sfu/event/index.html +116 -0
  40. package/coverage/lcov-report/src/gen/video/sfu/models/index.html +116 -0
  41. package/coverage/lcov-report/src/gen/video/sfu/models/models.ts.html +3271 -0
  42. package/coverage/lcov-report/src/index.html +161 -0
  43. package/coverage/lcov-report/src/rpc/index.html +131 -0
  44. package/coverage/lcov-report/src/rpc/index.ts.html +91 -0
  45. package/coverage/lcov-report/src/rpc/latency.ts.html +214 -0
  46. package/coverage/lcov-report/src/rtc/Call.ts.html +1840 -0
  47. package/coverage/lcov-report/src/rtc/CallMetadata.ts.html +157 -0
  48. package/coverage/lcov-report/src/rtc/Dispatcher.ts.html +223 -0
  49. package/coverage/lcov-report/src/rtc/IceTrickleBuffer.ts.html +148 -0
  50. package/coverage/lcov-report/src/rtc/callEventHandlers.ts.html +196 -0
  51. package/coverage/lcov-report/src/rtc/codecs.ts.html +268 -0
  52. package/coverage/lcov-report/src/rtc/helpers/iceCandidate.ts.html +133 -0
  53. package/coverage/lcov-report/src/rtc/helpers/index.html +131 -0
  54. package/coverage/lcov-report/src/rtc/helpers/tracks.ts.html +139 -0
  55. package/coverage/lcov-report/src/rtc/index.html +251 -0
  56. package/coverage/lcov-report/src/rtc/publisher.ts.html +1000 -0
  57. package/coverage/lcov-report/src/rtc/signal.ts.html +187 -0
  58. package/coverage/lcov-report/src/rtc/subscriber.ts.html +340 -0
  59. package/coverage/lcov-report/src/rtc/videoLayers.ts.html +394 -0
  60. package/coverage/lcov-report/src/stats/index.html +116 -0
  61. package/coverage/lcov-report/src/stats/state-store-stats-reporter.ts.html +1177 -0
  62. package/coverage/lcov-report/src/store/index.html +146 -0
  63. package/coverage/lcov-report/src/store/index.ts.html +91 -0
  64. package/coverage/lcov-report/src/store/rxUtils.ts.html +211 -0
  65. package/coverage/lcov-report/src/store/stateStore.ts.html +1108 -0
  66. package/coverage/lcov.info +11463 -0
  67. package/coverage/tmp/coverage-2131-1675959950516-2.json +1 -0
  68. package/dist/index.d.ts +18 -0
  69. package/dist/index.js +8636 -0
  70. package/dist/index.js.map +1 -0
  71. package/dist/src/Batcher.d.ts +12 -0
  72. package/dist/src/CallDropScheduler.d.ts +44 -0
  73. package/dist/src/StreamSfuClient.d.ts +25 -0
  74. package/dist/src/StreamVideoClient.d.ts +145 -0
  75. package/dist/src/__tests__/StreamVideoClient.test.d.ts +1 -0
  76. package/dist/src/config/defaultConfigs.d.ts +2 -0
  77. package/dist/src/config/types.d.ts +29 -0
  78. package/dist/src/coordinator/StreamCoordinatorClient.d.ts +19 -0
  79. package/dist/src/coordinator/connection/base64.d.ts +2 -0
  80. package/dist/src/coordinator/connection/client.d.ts +174 -0
  81. package/dist/src/coordinator/connection/connection.d.ts +139 -0
  82. package/dist/src/coordinator/connection/connection_fallback.d.ts +38 -0
  83. package/dist/src/coordinator/connection/errors.d.ts +16 -0
  84. package/dist/src/coordinator/connection/events.d.ts +10 -0
  85. package/dist/src/coordinator/connection/insights.d.ts +58 -0
  86. package/dist/src/coordinator/connection/signing.d.ts +30 -0
  87. package/dist/src/coordinator/connection/token_manager.d.ts +39 -0
  88. package/dist/src/coordinator/connection/types.d.ts +87 -0
  89. package/dist/src/coordinator/connection/utils.d.ts +25 -0
  90. package/dist/src/devices.d.ts +79 -0
  91. package/dist/src/events/call.d.ts +26 -0
  92. package/dist/src/events/internal.d.ts +8 -0
  93. package/dist/src/events/participant.d.ts +21 -0
  94. package/dist/src/events/speaker.d.ts +10 -0
  95. package/dist/src/gen/coordinator/index.d.ts +1973 -0
  96. package/dist/src/gen/google/protobuf/descriptor.d.ts +1650 -0
  97. package/dist/src/gen/google/protobuf/duration.d.ts +113 -0
  98. package/dist/src/gen/google/protobuf/struct.d.ts +184 -0
  99. package/dist/src/gen/google/protobuf/timestamp.d.ts +158 -0
  100. package/dist/src/gen/video/coordinator/broadcast_v1/broadcast.d.ts +66 -0
  101. package/dist/src/gen/video/coordinator/call_v1/call.d.ts +254 -0
  102. package/dist/src/gen/video/coordinator/client_v1_rpc/client_rpc.client.d.ts +351 -0
  103. package/dist/src/gen/video/coordinator/client_v1_rpc/client_rpc.d.ts +1488 -0
  104. package/dist/src/gen/video/coordinator/client_v1_rpc/envelopes.d.ts +143 -0
  105. package/dist/src/gen/video/coordinator/client_v1_rpc/websocket.d.ts +292 -0
  106. package/dist/src/gen/video/coordinator/edge_v1/edge.d.ts +183 -0
  107. package/dist/src/gen/video/coordinator/event_v1/event.d.ts +411 -0
  108. package/dist/src/gen/video/coordinator/geofence_v1/geofence.d.ts +63 -0
  109. package/dist/src/gen/video/coordinator/member_v1/member.d.ts +59 -0
  110. package/dist/src/gen/video/coordinator/participant_v1/participant.d.ts +103 -0
  111. package/dist/src/gen/video/coordinator/push_v1/push.d.ts +240 -0
  112. package/dist/src/gen/video/coordinator/stat_v1/stat.d.ts +308 -0
  113. package/dist/src/gen/video/coordinator/user_v1/user.d.ts +112 -0
  114. package/dist/src/gen/video/coordinator/utils_v1/utils.d.ts +47 -0
  115. package/dist/src/gen/video/sfu/event/events.d.ts +736 -0
  116. package/dist/src/gen/video/sfu/models/models.d.ts +460 -0
  117. package/dist/src/gen/video/sfu/signal_rpc/signal.client.d.ts +89 -0
  118. package/dist/src/gen/video/sfu/signal_rpc/signal.d.ts +320 -0
  119. package/dist/src/helpers/browsers.d.ts +8 -0
  120. package/dist/src/helpers/sound-detector.d.ts +34 -0
  121. package/dist/src/rpc/createClient.d.ts +10 -0
  122. package/dist/src/rpc/index.d.ts +2 -0
  123. package/dist/src/rpc/latency.d.ts +9 -0
  124. package/dist/src/rtc/Call.d.ts +180 -0
  125. package/dist/src/rtc/CallMetadata.d.ts +9 -0
  126. package/dist/src/rtc/Dispatcher.d.ts +9 -0
  127. package/dist/src/rtc/IceTrickleBuffer.d.ts +11 -0
  128. package/dist/src/rtc/callEventHandlers.d.ts +5 -0
  129. package/dist/src/rtc/codecs.d.ts +2 -0
  130. package/dist/src/rtc/helpers/iceCandidate.d.ts +2 -0
  131. package/dist/src/rtc/helpers/tracks.d.ts +3 -0
  132. package/dist/src/rtc/publisher.d.ts +53 -0
  133. package/dist/src/rtc/signal.d.ts +5 -0
  134. package/dist/src/rtc/subscriber.d.ts +7 -0
  135. package/dist/src/rtc/types.d.ts +84 -0
  136. package/dist/src/rtc/videoLayers.d.ts +17 -0
  137. package/dist/src/stats/coordinator-stats-reporter.d.ts +10 -0
  138. package/dist/src/stats/state-store-stats-reporter.d.ts +57 -0
  139. package/dist/src/stats/types.d.ts +42 -0
  140. package/dist/src/store/index.d.ts +2 -0
  141. package/dist/src/store/rxUtils.d.ts +18 -0
  142. package/dist/src/store/stateStore.d.ts +182 -0
  143. package/generate-openapi.sh +32 -0
  144. package/index.ts +31 -0
  145. package/openapitools.json +7 -0
  146. package/package.json +54 -0
  147. package/rollup.config.mjs +48 -0
  148. package/src/Batcher.ts +43 -0
  149. package/src/CallDropScheduler.ts +192 -0
  150. package/src/StreamSfuClient.ts +185 -0
  151. package/src/StreamVideoClient.ts +503 -0
  152. package/src/__tests__/StreamVideoClient.test.ts +83 -0
  153. package/src/config/defaultConfigs.ts +15 -0
  154. package/src/config/types.ts +30 -0
  155. package/src/coordinator/StreamCoordinatorClient.ts +115 -0
  156. package/src/coordinator/connection/base64.ts +80 -0
  157. package/src/coordinator/connection/client.ts +814 -0
  158. package/src/coordinator/connection/connection.ts +750 -0
  159. package/src/coordinator/connection/connection_fallback.ts +239 -0
  160. package/src/coordinator/connection/errors.ts +70 -0
  161. package/src/coordinator/connection/events.ts +13 -0
  162. package/src/coordinator/connection/insights.ts +88 -0
  163. package/src/coordinator/connection/signing.ts +104 -0
  164. package/src/coordinator/connection/token_manager.ts +160 -0
  165. package/src/coordinator/connection/types.ts +111 -0
  166. package/src/coordinator/connection/utils.ts +148 -0
  167. package/src/devices.ts +266 -0
  168. package/src/events/call.ts +166 -0
  169. package/src/events/internal.ts +47 -0
  170. package/src/events/participant.ts +97 -0
  171. package/src/events/speaker.ts +62 -0
  172. package/src/gen/coordinator/index.ts +1956 -0
  173. package/src/gen/google/protobuf/descriptor.ts +3466 -0
  174. package/src/gen/google/protobuf/duration.ts +232 -0
  175. package/src/gen/google/protobuf/struct.ts +481 -0
  176. package/src/gen/google/protobuf/timestamp.ts +291 -0
  177. package/src/gen/video/coordinator/broadcast_v1/broadcast.ts +154 -0
  178. package/src/gen/video/coordinator/call_v1/call.ts +651 -0
  179. package/src/gen/video/coordinator/client_v1_rpc/client_rpc.client.ts +463 -0
  180. package/src/gen/video/coordinator/client_v1_rpc/client_rpc.ts +3819 -0
  181. package/src/gen/video/coordinator/client_v1_rpc/envelopes.ts +424 -0
  182. package/src/gen/video/coordinator/client_v1_rpc/websocket.ts +719 -0
  183. package/src/gen/video/coordinator/edge_v1/edge.ts +532 -0
  184. package/src/gen/video/coordinator/event_v1/event.ts +1171 -0
  185. package/src/gen/video/coordinator/geofence_v1/geofence.ts +128 -0
  186. package/src/gen/video/coordinator/member_v1/member.ts +138 -0
  187. package/src/gen/video/coordinator/participant_v1/participant.ts +261 -0
  188. package/src/gen/video/coordinator/push_v1/push.ts +651 -0
  189. package/src/gen/video/coordinator/stat_v1/stat.ts +656 -0
  190. package/src/gen/video/coordinator/user_v1/user.ts +277 -0
  191. package/src/gen/video/coordinator/utils_v1/utils.ts +98 -0
  192. package/src/gen/video/sfu/event/events.ts +1962 -0
  193. package/src/gen/video/sfu/models/models.ts +1062 -0
  194. package/src/gen/video/sfu/signal_rpc/signal.client.ts +108 -0
  195. package/src/gen/video/sfu/signal_rpc/signal.ts +906 -0
  196. package/src/helpers/browsers.ts +13 -0
  197. package/src/helpers/sound-detector.ts +85 -0
  198. package/src/rpc/createClient.ts +50 -0
  199. package/src/rpc/index.ts +2 -0
  200. package/src/rpc/latency.ts +43 -0
  201. package/src/rtc/Call.ts +585 -0
  202. package/src/rtc/CallMetadata.ts +24 -0
  203. package/src/rtc/Dispatcher.ts +46 -0
  204. package/src/rtc/IceTrickleBuffer.ts +21 -0
  205. package/src/rtc/callEventHandlers.ts +37 -0
  206. package/src/rtc/codecs.ts +61 -0
  207. package/src/rtc/helpers/iceCandidate.ts +16 -0
  208. package/src/rtc/helpers/tracks.ts +18 -0
  209. package/src/rtc/publisher.ts +305 -0
  210. package/src/rtc/signal.ts +34 -0
  211. package/src/rtc/subscriber.ts +85 -0
  212. package/src/rtc/types.ts +105 -0
  213. package/src/rtc/videoLayers.ts +103 -0
  214. package/src/stats/coordinator-stats-reporter.ts +167 -0
  215. package/src/stats/state-store-stats-reporter.ts +364 -0
  216. package/src/stats/types.ts +46 -0
  217. package/src/store/index.ts +2 -0
  218. package/src/store/rxUtils.ts +42 -0
  219. package/src/store/stateStore.ts +341 -0
  220. package/tsconfig.json +25 -0
  221. package/typedoc.json +11 -0
  222. package/vite.config.ts +11 -0
@@ -0,0 +1,2527 @@
1
+
2
+ <!doctype html>
3
+ <html lang="en">
4
+
5
+ <head>
6
+ <title>Code coverage report for src/coordinator/connection/client.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/coordinator/connection</a> client.ts</h1>
23
+ <div class='clearfix'>
24
+
25
+ <div class='fl pad1y space-right2'>
26
+ <span class="strong">36.11% </span>
27
+ <span class="quiet">Statements</span>
28
+ <span class='fraction'>294/814</span>
29
+ </div>
30
+
31
+
32
+ <div class='fl pad1y space-right2'>
33
+ <span class="strong">33.33% </span>
34
+ <span class="quiet">Branches</span>
35
+ <span class='fraction'>5/15</span>
36
+ </div>
37
+
38
+
39
+ <div class='fl pad1y space-right2'>
40
+ <span class="strong">11.62% </span>
41
+ <span class="quiet">Functions</span>
42
+ <span class='fraction'>5/43</span>
43
+ </div>
44
+
45
+
46
+ <div class='fl pad1y space-right2'>
47
+ <span class="strong">36.11% </span>
48
+ <span class="quiet">Lines</span>
49
+ <span class='fraction'>294/814</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 oninput="onInput()" 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>
781
+ <a name='L716'></a><a href='#L716'>716</a>
782
+ <a name='L717'></a><a href='#L717'>717</a>
783
+ <a name='L718'></a><a href='#L718'>718</a>
784
+ <a name='L719'></a><a href='#L719'>719</a>
785
+ <a name='L720'></a><a href='#L720'>720</a>
786
+ <a name='L721'></a><a href='#L721'>721</a>
787
+ <a name='L722'></a><a href='#L722'>722</a>
788
+ <a name='L723'></a><a href='#L723'>723</a>
789
+ <a name='L724'></a><a href='#L724'>724</a>
790
+ <a name='L725'></a><a href='#L725'>725</a>
791
+ <a name='L726'></a><a href='#L726'>726</a>
792
+ <a name='L727'></a><a href='#L727'>727</a>
793
+ <a name='L728'></a><a href='#L728'>728</a>
794
+ <a name='L729'></a><a href='#L729'>729</a>
795
+ <a name='L730'></a><a href='#L730'>730</a>
796
+ <a name='L731'></a><a href='#L731'>731</a>
797
+ <a name='L732'></a><a href='#L732'>732</a>
798
+ <a name='L733'></a><a href='#L733'>733</a>
799
+ <a name='L734'></a><a href='#L734'>734</a>
800
+ <a name='L735'></a><a href='#L735'>735</a>
801
+ <a name='L736'></a><a href='#L736'>736</a>
802
+ <a name='L737'></a><a href='#L737'>737</a>
803
+ <a name='L738'></a><a href='#L738'>738</a>
804
+ <a name='L739'></a><a href='#L739'>739</a>
805
+ <a name='L740'></a><a href='#L740'>740</a>
806
+ <a name='L741'></a><a href='#L741'>741</a>
807
+ <a name='L742'></a><a href='#L742'>742</a>
808
+ <a name='L743'></a><a href='#L743'>743</a>
809
+ <a name='L744'></a><a href='#L744'>744</a>
810
+ <a name='L745'></a><a href='#L745'>745</a>
811
+ <a name='L746'></a><a href='#L746'>746</a>
812
+ <a name='L747'></a><a href='#L747'>747</a>
813
+ <a name='L748'></a><a href='#L748'>748</a>
814
+ <a name='L749'></a><a href='#L749'>749</a>
815
+ <a name='L750'></a><a href='#L750'>750</a>
816
+ <a name='L751'></a><a href='#L751'>751</a>
817
+ <a name='L752'></a><a href='#L752'>752</a>
818
+ <a name='L753'></a><a href='#L753'>753</a>
819
+ <a name='L754'></a><a href='#L754'>754</a>
820
+ <a name='L755'></a><a href='#L755'>755</a>
821
+ <a name='L756'></a><a href='#L756'>756</a>
822
+ <a name='L757'></a><a href='#L757'>757</a>
823
+ <a name='L758'></a><a href='#L758'>758</a>
824
+ <a name='L759'></a><a href='#L759'>759</a>
825
+ <a name='L760'></a><a href='#L760'>760</a>
826
+ <a name='L761'></a><a href='#L761'>761</a>
827
+ <a name='L762'></a><a href='#L762'>762</a>
828
+ <a name='L763'></a><a href='#L763'>763</a>
829
+ <a name='L764'></a><a href='#L764'>764</a>
830
+ <a name='L765'></a><a href='#L765'>765</a>
831
+ <a name='L766'></a><a href='#L766'>766</a>
832
+ <a name='L767'></a><a href='#L767'>767</a>
833
+ <a name='L768'></a><a href='#L768'>768</a>
834
+ <a name='L769'></a><a href='#L769'>769</a>
835
+ <a name='L770'></a><a href='#L770'>770</a>
836
+ <a name='L771'></a><a href='#L771'>771</a>
837
+ <a name='L772'></a><a href='#L772'>772</a>
838
+ <a name='L773'></a><a href='#L773'>773</a>
839
+ <a name='L774'></a><a href='#L774'>774</a>
840
+ <a name='L775'></a><a href='#L775'>775</a>
841
+ <a name='L776'></a><a href='#L776'>776</a>
842
+ <a name='L777'></a><a href='#L777'>777</a>
843
+ <a name='L778'></a><a href='#L778'>778</a>
844
+ <a name='L779'></a><a href='#L779'>779</a>
845
+ <a name='L780'></a><a href='#L780'>780</a>
846
+ <a name='L781'></a><a href='#L781'>781</a>
847
+ <a name='L782'></a><a href='#L782'>782</a>
848
+ <a name='L783'></a><a href='#L783'>783</a>
849
+ <a name='L784'></a><a href='#L784'>784</a>
850
+ <a name='L785'></a><a href='#L785'>785</a>
851
+ <a name='L786'></a><a href='#L786'>786</a>
852
+ <a name='L787'></a><a href='#L787'>787</a>
853
+ <a name='L788'></a><a href='#L788'>788</a>
854
+ <a name='L789'></a><a href='#L789'>789</a>
855
+ <a name='L790'></a><a href='#L790'>790</a>
856
+ <a name='L791'></a><a href='#L791'>791</a>
857
+ <a name='L792'></a><a href='#L792'>792</a>
858
+ <a name='L793'></a><a href='#L793'>793</a>
859
+ <a name='L794'></a><a href='#L794'>794</a>
860
+ <a name='L795'></a><a href='#L795'>795</a>
861
+ <a name='L796'></a><a href='#L796'>796</a>
862
+ <a name='L797'></a><a href='#L797'>797</a>
863
+ <a name='L798'></a><a href='#L798'>798</a>
864
+ <a name='L799'></a><a href='#L799'>799</a>
865
+ <a name='L800'></a><a href='#L800'>800</a>
866
+ <a name='L801'></a><a href='#L801'>801</a>
867
+ <a name='L802'></a><a href='#L802'>802</a>
868
+ <a name='L803'></a><a href='#L803'>803</a>
869
+ <a name='L804'></a><a href='#L804'>804</a>
870
+ <a name='L805'></a><a href='#L805'>805</a>
871
+ <a name='L806'></a><a href='#L806'>806</a>
872
+ <a name='L807'></a><a href='#L807'>807</a>
873
+ <a name='L808'></a><a href='#L808'>808</a>
874
+ <a name='L809'></a><a href='#L809'>809</a>
875
+ <a name='L810'></a><a href='#L810'>810</a>
876
+ <a name='L811'></a><a href='#L811'>811</a>
877
+ <a name='L812'></a><a href='#L812'>812</a>
878
+ <a name='L813'></a><a href='#L813'>813</a>
879
+ <a name='L814'></a><a href='#L814'>814</a>
880
+ <a name='L815'></a><a href='#L815'>815</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">1x</span>
881
+ <span class="cline-any cline-yes">1x</span>
882
+ <span class="cline-any cline-yes">1x</span>
883
+ <span class="cline-any cline-yes">1x</span>
884
+ <span class="cline-any cline-yes">1x</span>
885
+ <span class="cline-any cline-yes">1x</span>
886
+ <span class="cline-any cline-yes">1x</span>
887
+ <span class="cline-any cline-yes">1x</span>
888
+ <span class="cline-any cline-yes">1x</span>
889
+ <span class="cline-any cline-yes">1x</span>
890
+ <span class="cline-any cline-yes">1x</span>
891
+ <span class="cline-any cline-yes">1x</span>
892
+ <span class="cline-any cline-yes">1x</span>
893
+ <span class="cline-any cline-yes">1x</span>
894
+ <span class="cline-any cline-yes">1x</span>
895
+ <span class="cline-any cline-yes">1x</span>
896
+ <span class="cline-any cline-yes">1x</span>
897
+ <span class="cline-any cline-yes">1x</span>
898
+ <span class="cline-any cline-yes">1x</span>
899
+ <span class="cline-any cline-yes">1x</span>
900
+ <span class="cline-any cline-yes">1x</span>
901
+ <span class="cline-any cline-yes">1x</span>
902
+ <span class="cline-any cline-yes">1x</span>
903
+ <span class="cline-any cline-yes">1x</span>
904
+ <span class="cline-any cline-yes">1x</span>
905
+ <span class="cline-any cline-yes">1x</span>
906
+ <span class="cline-any cline-yes">1x</span>
907
+ <span class="cline-any cline-yes">1x</span>
908
+ <span class="cline-any cline-yes">1x</span>
909
+ <span class="cline-any cline-yes">1x</span>
910
+ <span class="cline-any cline-yes">1x</span>
911
+ <span class="cline-any cline-yes">1x</span>
912
+ <span class="cline-any cline-yes">1x</span>
913
+ <span class="cline-any cline-yes">1x</span>
914
+ <span class="cline-any cline-yes">1x</span>
915
+ <span class="cline-any cline-yes">1x</span>
916
+ <span class="cline-any cline-yes">4x</span>
917
+ <span class="cline-any cline-yes">4x</span>
918
+ <span class="cline-any cline-yes">4x</span>
919
+ <span class="cline-any cline-yes">4x</span>
920
+ <span class="cline-any cline-yes">1x</span>
921
+ <span class="cline-any cline-yes">2x</span>
922
+ <span class="cline-any cline-yes">2x</span>
923
+ <span class="cline-any cline-yes">2x</span>
924
+ <span class="cline-any cline-yes">2x</span>
925
+ <span class="cline-any cline-yes">2x</span>
926
+ <span class="cline-any cline-yes">2x</span>
927
+ <span class="cline-any cline-yes">2x</span>
928
+ <span class="cline-any cline-yes">2x</span>
929
+ <span class="cline-any cline-yes">2x</span>
930
+ <span class="cline-any cline-yes">2x</span>
931
+ <span class="cline-any cline-yes">2x</span>
932
+ <span class="cline-any cline-yes">2x</span>
933
+ <span class="cline-any cline-yes">2x</span>
934
+ <span class="cline-any cline-yes">2x</span>
935
+ <span class="cline-any cline-yes">2x</span>
936
+ <span class="cline-any cline-yes">2x</span>
937
+ <span class="cline-any cline-yes">2x</span>
938
+ <span class="cline-any cline-yes">2x</span>
939
+ <span class="cline-any cline-yes">2x</span>
940
+ <span class="cline-any cline-yes">2x</span>
941
+ <span class="cline-any cline-yes">2x</span>
942
+ <span class="cline-any cline-yes">2x</span>
943
+ <span class="cline-any cline-yes">2x</span>
944
+ <span class="cline-any cline-yes">2x</span>
945
+ <span class="cline-any cline-yes">2x</span>
946
+ <span class="cline-any cline-yes">2x</span>
947
+ <span class="cline-any cline-yes">2x</span>
948
+ <span class="cline-any cline-yes">2x</span>
949
+ <span class="cline-any cline-yes">2x</span>
950
+ <span class="cline-any cline-yes">2x</span>
951
+ <span class="cline-any cline-yes">2x</span>
952
+ <span class="cline-any cline-yes">2x</span>
953
+ <span class="cline-any cline-yes">2x</span>
954
+ <span class="cline-any cline-yes">2x</span>
955
+ <span class="cline-any cline-yes">2x</span>
956
+ <span class="cline-any cline-yes">2x</span>
957
+ <span class="cline-any cline-yes">2x</span>
958
+ <span class="cline-any cline-yes">2x</span>
959
+ <span class="cline-any cline-yes">2x</span>
960
+ <span class="cline-any cline-yes">2x</span>
961
+ <span class="cline-any cline-yes">2x</span>
962
+ <span class="cline-any cline-yes">2x</span>
963
+ <span class="cline-any cline-yes">2x</span>
964
+ <span class="cline-any cline-yes">2x</span>
965
+ <span class="cline-any cline-yes">2x</span>
966
+ <span class="cline-any cline-yes">2x</span>
967
+ <span class="cline-any cline-yes">2x</span>
968
+ <span class="cline-any cline-yes">2x</span>
969
+ <span class="cline-any cline-yes">2x</span>
970
+ <span class="cline-any cline-yes">2x</span>
971
+ <span class="cline-any cline-yes">2x</span>
972
+ <span class="cline-any cline-yes">2x</span>
973
+ <span class="cline-any cline-yes">2x</span>
974
+ <span class="cline-any cline-yes">2x</span>
975
+ <span class="cline-any cline-yes">2x</span>
976
+ <span class="cline-any cline-yes">2x</span>
977
+ <span class="cline-any cline-yes">2x</span>
978
+ <span class="cline-any cline-yes">2x</span>
979
+ <span class="cline-any cline-yes">2x</span>
980
+ <span class="cline-any cline-yes">2x</span>
981
+ <span class="cline-any cline-yes">2x</span>
982
+ <span class="cline-any cline-no">&nbsp;</span>
983
+ <span class="cline-any cline-no">&nbsp;</span>
984
+ <span class="cline-any cline-no">&nbsp;</span>
985
+ <span class="cline-any cline-no">&nbsp;</span>
986
+ <span class="cline-any cline-yes">2x</span>
987
+ <span class="cline-any cline-no">&nbsp;</span>
988
+ <span class="cline-any cline-yes">2x</span>
989
+ <span class="cline-any cline-yes">2x</span>
990
+ <span class="cline-any cline-no">&nbsp;</span>
991
+ <span class="cline-any cline-no">&nbsp;</span>
992
+ <span class="cline-any cline-no">&nbsp;</span>
993
+ <span class="cline-any cline-yes">2x</span>
994
+ <span class="cline-any cline-yes">2x</span>
995
+ <span class="cline-any cline-yes">2x</span>
996
+ <span class="cline-any cline-yes">2x</span>
997
+ <span class="cline-any cline-yes">2x</span>
998
+ <span class="cline-any cline-yes">2x</span>
999
+ <span class="cline-any cline-yes">2x</span>
1000
+ <span class="cline-any cline-yes">2x</span>
1001
+ <span class="cline-any cline-yes">2x</span>
1002
+ <span class="cline-any cline-yes">2x</span>
1003
+ <span class="cline-any cline-yes">2x</span>
1004
+ <span class="cline-any cline-yes">2x</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-yes">2x</span>
1012
+ <span class="cline-any cline-yes">2x</span>
1013
+ <span class="cline-any cline-yes">2x</span>
1014
+ <span class="cline-any cline-yes">2x</span>
1015
+ <span class="cline-any cline-yes">2x</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-yes">2x</span>
1020
+ <span class="cline-any cline-no">&nbsp;</span>
1021
+ <span class="cline-any cline-no">&nbsp;</span>
1022
+ <span class="cline-any cline-no">&nbsp;</span>
1023
+ <span class="cline-any cline-no">&nbsp;</span>
1024
+ <span class="cline-any cline-yes">2x</span>
1025
+ <span class="cline-any cline-yes">2x</span>
1026
+ <span class="cline-any cline-yes">2x</span>
1027
+ <span class="cline-any cline-yes">2x</span>
1028
+ <span class="cline-any cline-yes">2x</span>
1029
+ <span class="cline-any cline-yes">2x</span>
1030
+ <span class="cline-any cline-yes">2x</span>
1031
+ <span class="cline-any cline-yes">2x</span>
1032
+ <span class="cline-any cline-yes">2x</span>
1033
+ <span class="cline-any cline-yes">2x</span>
1034
+ <span class="cline-any cline-yes">2x</span>
1035
+ <span class="cline-any cline-yes">2x</span>
1036
+ <span class="cline-any cline-yes">2x</span>
1037
+ <span class="cline-any cline-yes">2x</span>
1038
+ <span class="cline-any cline-yes">2x</span>
1039
+ <span class="cline-any cline-yes">2x</span>
1040
+ <span class="cline-any cline-yes">2x</span>
1041
+ <span class="cline-any cline-yes">2x</span>
1042
+ <span class="cline-any cline-yes">2x</span>
1043
+ <span class="cline-any cline-no">&nbsp;</span>
1044
+ <span class="cline-any cline-yes">2x</span>
1045
+ <span class="cline-any cline-yes">2x</span>
1046
+ <span class="cline-any cline-yes">2x</span>
1047
+ <span class="cline-any cline-yes">2x</span>
1048
+ <span class="cline-any cline-no">&nbsp;</span>
1049
+ <span class="cline-any cline-no">&nbsp;</span>
1050
+ <span class="cline-any cline-yes">2x</span>
1051
+ <span class="cline-any cline-yes">2x</span>
1052
+ <span class="cline-any cline-no">&nbsp;</span>
1053
+ <span class="cline-any cline-no">&nbsp;</span>
1054
+ <span class="cline-any cline-yes">2x</span>
1055
+ <span class="cline-any cline-yes">2x</span>
1056
+ <span class="cline-any cline-yes">2x</span>
1057
+ <span class="cline-any cline-yes">2x</span>
1058
+ <span class="cline-any cline-yes">2x</span>
1059
+ <span class="cline-any cline-yes">2x</span>
1060
+ <span class="cline-any cline-yes">2x</span>
1061
+ <span class="cline-any cline-yes">2x</span>
1062
+ <span class="cline-any cline-yes">2x</span>
1063
+ <span class="cline-any cline-no">&nbsp;</span>
1064
+ <span class="cline-any cline-yes">2x</span>
1065
+ <span class="cline-any cline-yes">2x</span>
1066
+ <span class="cline-any cline-yes">2x</span>
1067
+ <span class="cline-any cline-yes">2x</span>
1068
+ <span class="cline-any cline-yes">2x</span>
1069
+ <span class="cline-any cline-yes">2x</span>
1070
+ <span class="cline-any cline-yes">2x</span>
1071
+ <span class="cline-any cline-yes">2x</span>
1072
+ <span class="cline-any cline-yes">2x</span>
1073
+ <span class="cline-any cline-yes">2x</span>
1074
+ <span class="cline-any cline-yes">2x</span>
1075
+ <span class="cline-any cline-yes">2x</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-no">&nbsp;</span>
1080
+ <span class="cline-any cline-no">&nbsp;</span>
1081
+ <span class="cline-any cline-no">&nbsp;</span>
1082
+ <span class="cline-any cline-no">&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-no">&nbsp;</span>
1089
+ <span class="cline-any cline-no">&nbsp;</span>
1090
+ <span class="cline-any cline-no">&nbsp;</span>
1091
+ <span class="cline-any cline-no">&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-no">&nbsp;</span>
1105
+ <span class="cline-any cline-no">&nbsp;</span>
1106
+ <span class="cline-any cline-no">&nbsp;</span>
1107
+ <span class="cline-any cline-no">&nbsp;</span>
1108
+ <span class="cline-any cline-no">&nbsp;</span>
1109
+ <span class="cline-any cline-no">&nbsp;</span>
1110
+ <span class="cline-any cline-no">&nbsp;</span>
1111
+ <span class="cline-any cline-no">&nbsp;</span>
1112
+ <span class="cline-any cline-no">&nbsp;</span>
1113
+ <span class="cline-any cline-no">&nbsp;</span>
1114
+ <span class="cline-any cline-no">&nbsp;</span>
1115
+ <span class="cline-any cline-no">&nbsp;</span>
1116
+ <span class="cline-any cline-no">&nbsp;</span>
1117
+ <span class="cline-any cline-no">&nbsp;</span>
1118
+ <span class="cline-any cline-no">&nbsp;</span>
1119
+ <span class="cline-any cline-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-no">&nbsp;</span>
1127
+ <span class="cline-any cline-no">&nbsp;</span>
1128
+ <span class="cline-any cline-no">&nbsp;</span>
1129
+ <span class="cline-any cline-no">&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-yes">2x</span>
1135
+ <span class="cline-any cline-yes">2x</span>
1136
+ <span class="cline-any cline-no">&nbsp;</span>
1137
+ <span class="cline-any cline-yes">2x</span>
1138
+ <span class="cline-any cline-yes">2x</span>
1139
+ <span class="cline-any cline-no">&nbsp;</span>
1140
+ <span class="cline-any cline-no">&nbsp;</span>
1141
+ <span class="cline-any cline-no">&nbsp;</span>
1142
+ <span class="cline-any cline-no">&nbsp;</span>
1143
+ <span class="cline-any cline-no">&nbsp;</span>
1144
+ <span class="cline-any cline-no">&nbsp;</span>
1145
+ <span class="cline-any cline-no">&nbsp;</span>
1146
+ <span class="cline-any cline-no">&nbsp;</span>
1147
+ <span class="cline-any cline-no">&nbsp;</span>
1148
+ <span class="cline-any cline-yes">2x</span>
1149
+ <span class="cline-any cline-yes">2x</span>
1150
+ <span class="cline-any cline-yes">2x</span>
1151
+ <span class="cline-any cline-yes">2x</span>
1152
+ <span class="cline-any cline-yes">2x</span>
1153
+ <span class="cline-any cline-yes">2x</span>
1154
+ <span class="cline-any cline-yes">2x</span>
1155
+ <span class="cline-any cline-yes">2x</span>
1156
+ <span class="cline-any cline-yes">2x</span>
1157
+ <span class="cline-any cline-yes">2x</span>
1158
+ <span class="cline-any cline-yes">2x</span>
1159
+ <span class="cline-any cline-yes">2x</span>
1160
+ <span class="cline-any cline-yes">2x</span>
1161
+ <span class="cline-any cline-yes">2x</span>
1162
+ <span class="cline-any cline-yes">2x</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-no">&nbsp;</span>
1167
+ <span class="cline-any cline-no">&nbsp;</span>
1168
+ <span class="cline-any cline-no">&nbsp;</span>
1169
+ <span class="cline-any cline-no">&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-yes">2x</span>
1175
+ <span class="cline-any cline-yes">2x</span>
1176
+ <span class="cline-any cline-yes">2x</span>
1177
+ <span class="cline-any cline-yes">2x</span>
1178
+ <span class="cline-any cline-yes">2x</span>
1179
+ <span class="cline-any cline-no">&nbsp;</span>
1180
+ <span class="cline-any cline-no">&nbsp;</span>
1181
+ <span class="cline-any cline-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-no">&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-no">&nbsp;</span>
1195
+ <span class="cline-any cline-no">&nbsp;</span>
1196
+ <span class="cline-any cline-no">&nbsp;</span>
1197
+ <span class="cline-any cline-no">&nbsp;</span>
1198
+ <span class="cline-any cline-no">&nbsp;</span>
1199
+ <span class="cline-any cline-no">&nbsp;</span>
1200
+ <span class="cline-any cline-no">&nbsp;</span>
1201
+ <span class="cline-any cline-no">&nbsp;</span>
1202
+ <span class="cline-any cline-no">&nbsp;</span>
1203
+ <span class="cline-any cline-no">&nbsp;</span>
1204
+ <span class="cline-any cline-no">&nbsp;</span>
1205
+ <span class="cline-any cline-no">&nbsp;</span>
1206
+ <span class="cline-any cline-no">&nbsp;</span>
1207
+ <span class="cline-any cline-no">&nbsp;</span>
1208
+ <span class="cline-any cline-no">&nbsp;</span>
1209
+ <span class="cline-any cline-no">&nbsp;</span>
1210
+ <span class="cline-any cline-no">&nbsp;</span>
1211
+ <span class="cline-any cline-no">&nbsp;</span>
1212
+ <span class="cline-any cline-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-yes">2x</span>
1216
+ <span class="cline-any cline-yes">2x</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-no">&nbsp;</span>
1224
+ <span class="cline-any cline-no">&nbsp;</span>
1225
+ <span class="cline-any cline-no">&nbsp;</span>
1226
+ <span class="cline-any cline-no">&nbsp;</span>
1227
+ <span class="cline-any cline-no">&nbsp;</span>
1228
+ <span class="cline-any cline-no">&nbsp;</span>
1229
+ <span class="cline-any cline-yes">2x</span>
1230
+ <span class="cline-any cline-yes">2x</span>
1231
+ <span class="cline-any cline-yes">2x</span>
1232
+ <span class="cline-any cline-yes">2x</span>
1233
+ <span class="cline-any cline-yes">2x</span>
1234
+ <span class="cline-any cline-yes">2x</span>
1235
+ <span class="cline-any cline-yes">2x</span>
1236
+ <span class="cline-any cline-yes">2x</span>
1237
+ <span class="cline-any cline-no">&nbsp;</span>
1238
+ <span class="cline-any cline-no">&nbsp;</span>
1239
+ <span class="cline-any cline-no">&nbsp;</span>
1240
+ <span class="cline-any cline-no">&nbsp;</span>
1241
+ <span class="cline-any cline-no">&nbsp;</span>
1242
+ <span class="cline-any cline-no">&nbsp;</span>
1243
+ <span class="cline-any cline-no">&nbsp;</span>
1244
+ <span class="cline-any cline-no">&nbsp;</span>
1245
+ <span class="cline-any cline-no">&nbsp;</span>
1246
+ <span class="cline-any cline-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-no">&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-no">&nbsp;</span>
1255
+ <span class="cline-any cline-yes">2x</span>
1256
+ <span class="cline-any cline-yes">2x</span>
1257
+ <span class="cline-any cline-yes">2x</span>
1258
+ <span class="cline-any cline-yes">2x</span>
1259
+ <span class="cline-any cline-yes">2x</span>
1260
+ <span class="cline-any cline-no">&nbsp;</span>
1261
+ <span class="cline-any cline-no">&nbsp;</span>
1262
+ <span class="cline-any cline-no">&nbsp;</span>
1263
+ <span class="cline-any cline-no">&nbsp;</span>
1264
+ <span class="cline-any cline-no">&nbsp;</span>
1265
+ <span class="cline-any cline-no">&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-no">&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-no">&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-yes">2x</span>
1282
+ <span class="cline-any cline-yes">2x</span>
1283
+ <span class="cline-any cline-yes">2x</span>
1284
+ <span class="cline-any cline-yes">2x</span>
1285
+ <span class="cline-any cline-yes">2x</span>
1286
+ <span class="cline-any cline-yes">2x</span>
1287
+ <span class="cline-any cline-yes">2x</span>
1288
+ <span class="cline-any cline-yes">2x</span>
1289
+ <span class="cline-any cline-yes">2x</span>
1290
+ <span class="cline-any cline-yes">2x</span>
1291
+ <span class="cline-any cline-yes">2x</span>
1292
+ <span class="cline-any cline-yes">2x</span>
1293
+ <span class="cline-any cline-yes">2x</span>
1294
+ <span class="cline-any cline-yes">2x</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-no">&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-yes">2x</span>
1315
+ <span class="cline-any cline-yes">2x</span>
1316
+ <span class="cline-any cline-yes">2x</span>
1317
+ <span class="cline-any cline-yes">2x</span>
1318
+ <span class="cline-any cline-yes">2x</span>
1319
+ <span class="cline-any cline-yes">2x</span>
1320
+ <span class="cline-any cline-no">&nbsp;</span>
1321
+ <span class="cline-any cline-no">&nbsp;</span>
1322
+ <span class="cline-any cline-no">&nbsp;</span>
1323
+ <span class="cline-any cline-no">&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-no">&nbsp;</span>
1330
+ <span class="cline-any cline-no">&nbsp;</span>
1331
+ <span class="cline-any cline-no">&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-no">&nbsp;</span>
1338
+ <span class="cline-any cline-yes">2x</span>
1339
+ <span class="cline-any cline-yes">2x</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-no">&nbsp;</span>
1343
+ <span class="cline-any cline-no">&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-no">&nbsp;</span>
1348
+ <span class="cline-any cline-no">&nbsp;</span>
1349
+ <span class="cline-any cline-no">&nbsp;</span>
1350
+ <span class="cline-any cline-no">&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-yes">2x</span>
1355
+ <span class="cline-any cline-yes">2x</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-yes">2x</span>
1367
+ <span class="cline-any cline-yes">2x</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-yes">2x</span>
1375
+ <span class="cline-any cline-yes">2x</span>
1376
+ <span class="cline-any cline-no">&nbsp;</span>
1377
+ <span class="cline-any cline-no">&nbsp;</span>
1378
+ <span class="cline-any cline-no">&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-no">&nbsp;</span>
1382
+ <span class="cline-any cline-no">&nbsp;</span>
1383
+ <span class="cline-any cline-no">&nbsp;</span>
1384
+ <span class="cline-any cline-no">&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-no">&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-no">&nbsp;</span>
1403
+ <span class="cline-any cline-no">&nbsp;</span>
1404
+ <span class="cline-any cline-no">&nbsp;</span>
1405
+ <span class="cline-any cline-no">&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-no">&nbsp;</span>
1410
+ <span class="cline-any cline-no">&nbsp;</span>
1411
+ <span class="cline-any cline-no">&nbsp;</span>
1412
+ <span class="cline-any cline-no">&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-no">&nbsp;</span>
1421
+ <span class="cline-any cline-no">&nbsp;</span>
1422
+ <span class="cline-any cline-no">&nbsp;</span>
1423
+ <span class="cline-any cline-no">&nbsp;</span>
1424
+ <span class="cline-any cline-no">&nbsp;</span>
1425
+ <span class="cline-any cline-no">&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-no">&nbsp;</span>
1435
+ <span class="cline-any cline-no">&nbsp;</span>
1436
+ <span class="cline-any cline-yes">2x</span>
1437
+ <span class="cline-any cline-yes">2x</span>
1438
+ <span class="cline-any cline-no">&nbsp;</span>
1439
+ <span class="cline-any cline-no">&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-yes">2x</span>
1443
+ <span class="cline-any cline-yes">2x</span>
1444
+ <span class="cline-any cline-no">&nbsp;</span>
1445
+ <span class="cline-any cline-no">&nbsp;</span>
1446
+ <span class="cline-any cline-yes">2x</span>
1447
+ <span class="cline-any cline-yes">2x</span>
1448
+ <span class="cline-any cline-no">&nbsp;</span>
1449
+ <span class="cline-any cline-no">&nbsp;</span>
1450
+ <span class="cline-any cline-yes">2x</span>
1451
+ <span class="cline-any cline-yes">2x</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-yes">2x</span>
1455
+ <span class="cline-any cline-yes">2x</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-no">&nbsp;</span>
1460
+ <span class="cline-any cline-yes">2x</span>
1461
+ <span class="cline-any cline-yes">2x</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-no">&nbsp;</span>
1465
+ <span class="cline-any cline-no">&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-no">&nbsp;</span>
1469
+ <span class="cline-any cline-no">&nbsp;</span>
1470
+ <span class="cline-any cline-no">&nbsp;</span>
1471
+ <span class="cline-any cline-no">&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-no">&nbsp;</span>
1476
+ <span class="cline-any cline-no">&nbsp;</span>
1477
+ <span class="cline-any cline-no">&nbsp;</span>
1478
+ <span class="cline-any cline-yes">2x</span>
1479
+ <span class="cline-any cline-yes">2x</span>
1480
+ <span class="cline-any cline-no">&nbsp;</span>
1481
+ <span class="cline-any cline-no">&nbsp;</span>
1482
+ <span class="cline-any cline-no">&nbsp;</span>
1483
+ <span class="cline-any cline-no">&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-yes">2x</span>
1487
+ <span class="cline-any cline-yes">2x</span>
1488
+ <span class="cline-any cline-no">&nbsp;</span>
1489
+ <span class="cline-any cline-no">&nbsp;</span>
1490
+ <span class="cline-any cline-no">&nbsp;</span>
1491
+ <span class="cline-any cline-no">&nbsp;</span>
1492
+ <span class="cline-any cline-yes">2x</span>
1493
+ <span class="cline-any cline-yes">2x</span>
1494
+ <span class="cline-any cline-no">&nbsp;</span>
1495
+ <span class="cline-any cline-no">&nbsp;</span>
1496
+ <span class="cline-any cline-no">&nbsp;</span>
1497
+ <span class="cline-any cline-no">&nbsp;</span>
1498
+ <span class="cline-any cline-no">&nbsp;</span>
1499
+ <span class="cline-any cline-yes">2x</span>
1500
+ <span class="cline-any cline-yes">2x</span>
1501
+ <span class="cline-any cline-no">&nbsp;</span>
1502
+ <span class="cline-any cline-no">&nbsp;</span>
1503
+ <span class="cline-any cline-no">&nbsp;</span>
1504
+ <span class="cline-any cline-no">&nbsp;</span>
1505
+ <span class="cline-any cline-no">&nbsp;</span>
1506
+ <span class="cline-any cline-no">&nbsp;</span>
1507
+ <span class="cline-any cline-no">&nbsp;</span>
1508
+ <span class="cline-any cline-no">&nbsp;</span>
1509
+ <span class="cline-any cline-no">&nbsp;</span>
1510
+ <span class="cline-any cline-no">&nbsp;</span>
1511
+ <span class="cline-any cline-no">&nbsp;</span>
1512
+ <span class="cline-any cline-no">&nbsp;</span>
1513
+ <span class="cline-any cline-no">&nbsp;</span>
1514
+ <span class="cline-any cline-no">&nbsp;</span>
1515
+ <span class="cline-any cline-no">&nbsp;</span>
1516
+ <span class="cline-any cline-yes">2x</span>
1517
+ <span class="cline-any cline-yes">2x</span>
1518
+ <span class="cline-any cline-yes">2x</span>
1519
+ <span class="cline-any cline-yes">2x</span>
1520
+ <span class="cline-any cline-yes">2x</span>
1521
+ <span class="cline-any cline-no">&nbsp;</span>
1522
+ <span class="cline-any cline-no">&nbsp;</span>
1523
+ <span class="cline-any cline-no">&nbsp;</span>
1524
+ <span class="cline-any cline-no">&nbsp;</span>
1525
+ <span class="cline-any cline-no">&nbsp;</span>
1526
+ <span class="cline-any cline-no">&nbsp;</span>
1527
+ <span class="cline-any cline-no">&nbsp;</span>
1528
+ <span class="cline-any cline-no">&nbsp;</span>
1529
+ <span class="cline-any cline-no">&nbsp;</span>
1530
+ <span class="cline-any cline-no">&nbsp;</span>
1531
+ <span class="cline-any cline-no">&nbsp;</span>
1532
+ <span class="cline-any cline-no">&nbsp;</span>
1533
+ <span class="cline-any cline-no">&nbsp;</span>
1534
+ <span class="cline-any cline-no">&nbsp;</span>
1535
+ <span class="cline-any cline-no">&nbsp;</span>
1536
+ <span class="cline-any cline-no">&nbsp;</span>
1537
+ <span class="cline-any cline-no">&nbsp;</span>
1538
+ <span class="cline-any cline-no">&nbsp;</span>
1539
+ <span class="cline-any cline-no">&nbsp;</span>
1540
+ <span class="cline-any cline-no">&nbsp;</span>
1541
+ <span class="cline-any cline-no">&nbsp;</span>
1542
+ <span class="cline-any cline-no">&nbsp;</span>
1543
+ <span class="cline-any cline-no">&nbsp;</span>
1544
+ <span class="cline-any cline-no">&nbsp;</span>
1545
+ <span class="cline-any cline-no">&nbsp;</span>
1546
+ <span class="cline-any cline-no">&nbsp;</span>
1547
+ <span class="cline-any cline-no">&nbsp;</span>
1548
+ <span class="cline-any cline-no">&nbsp;</span>
1549
+ <span class="cline-any cline-no">&nbsp;</span>
1550
+ <span class="cline-any cline-no">&nbsp;</span>
1551
+ <span class="cline-any cline-no">&nbsp;</span>
1552
+ <span class="cline-any cline-no">&nbsp;</span>
1553
+ <span class="cline-any cline-no">&nbsp;</span>
1554
+ <span class="cline-any cline-no">&nbsp;</span>
1555
+ <span class="cline-any cline-no">&nbsp;</span>
1556
+ <span class="cline-any cline-no">&nbsp;</span>
1557
+ <span class="cline-any cline-no">&nbsp;</span>
1558
+ <span class="cline-any cline-no">&nbsp;</span>
1559
+ <span class="cline-any cline-no">&nbsp;</span>
1560
+ <span class="cline-any cline-no">&nbsp;</span>
1561
+ <span class="cline-any cline-no">&nbsp;</span>
1562
+ <span class="cline-any cline-no">&nbsp;</span>
1563
+ <span class="cline-any cline-no">&nbsp;</span>
1564
+ <span class="cline-any cline-no">&nbsp;</span>
1565
+ <span class="cline-any cline-no">&nbsp;</span>
1566
+ <span class="cline-any cline-no">&nbsp;</span>
1567
+ <span class="cline-any cline-no">&nbsp;</span>
1568
+ <span class="cline-any cline-no">&nbsp;</span>
1569
+ <span class="cline-any cline-no">&nbsp;</span>
1570
+ <span class="cline-any cline-no">&nbsp;</span>
1571
+ <span class="cline-any cline-no">&nbsp;</span>
1572
+ <span class="cline-any cline-no">&nbsp;</span>
1573
+ <span class="cline-any cline-no">&nbsp;</span>
1574
+ <span class="cline-any cline-no">&nbsp;</span>
1575
+ <span class="cline-any cline-no">&nbsp;</span>
1576
+ <span class="cline-any cline-no">&nbsp;</span>
1577
+ <span class="cline-any cline-no">&nbsp;</span>
1578
+ <span class="cline-any cline-no">&nbsp;</span>
1579
+ <span class="cline-any cline-no">&nbsp;</span>
1580
+ <span class="cline-any cline-no">&nbsp;</span>
1581
+ <span class="cline-any cline-no">&nbsp;</span>
1582
+ <span class="cline-any cline-no">&nbsp;</span>
1583
+ <span class="cline-any cline-no">&nbsp;</span>
1584
+ <span class="cline-any cline-yes">2x</span>
1585
+ <span class="cline-any cline-yes">2x</span>
1586
+ <span class="cline-any cline-yes">2x</span>
1587
+ <span class="cline-any cline-yes">2x</span>
1588
+ <span class="cline-any cline-yes">2x</span>
1589
+ <span class="cline-any cline-yes">2x</span>
1590
+ <span class="cline-any cline-yes">2x</span>
1591
+ <span class="cline-any cline-no">&nbsp;</span>
1592
+ <span class="cline-any cline-no">&nbsp;</span>
1593
+ <span class="cline-any cline-no">&nbsp;</span>
1594
+ <span class="cline-any cline-no">&nbsp;</span>
1595
+ <span class="cline-any cline-no">&nbsp;</span>
1596
+ <span class="cline-any cline-no">&nbsp;</span>
1597
+ <span class="cline-any cline-no">&nbsp;</span>
1598
+ <span class="cline-any cline-no">&nbsp;</span>
1599
+ <span class="cline-any cline-no">&nbsp;</span>
1600
+ <span class="cline-any cline-no">&nbsp;</span>
1601
+ <span class="cline-any cline-no">&nbsp;</span>
1602
+ <span class="cline-any cline-no">&nbsp;</span>
1603
+ <span class="cline-any cline-no">&nbsp;</span>
1604
+ <span class="cline-any cline-no">&nbsp;</span>
1605
+ <span class="cline-any cline-no">&nbsp;</span>
1606
+ <span class="cline-any cline-no">&nbsp;</span>
1607
+ <span class="cline-any cline-yes">2x</span>
1608
+ <span class="cline-any cline-yes">2x</span>
1609
+ <span class="cline-any cline-no">&nbsp;</span>
1610
+ <span class="cline-any cline-no">&nbsp;</span>
1611
+ <span class="cline-any cline-no">&nbsp;</span>
1612
+ <span class="cline-any cline-no">&nbsp;</span>
1613
+ <span class="cline-any cline-no">&nbsp;</span>
1614
+ <span class="cline-any cline-no">&nbsp;</span>
1615
+ <span class="cline-any cline-no">&nbsp;</span>
1616
+ <span class="cline-any cline-yes">2x</span>
1617
+ <span class="cline-any cline-yes">2x</span>
1618
+ <span class="cline-any cline-no">&nbsp;</span>
1619
+ <span class="cline-any cline-no">&nbsp;</span>
1620
+ <span class="cline-any cline-yes">2x</span>
1621
+ <span class="cline-any cline-yes">2x</span>
1622
+ <span class="cline-any cline-yes">2x</span>
1623
+ <span class="cline-any cline-yes">2x</span>
1624
+ <span class="cline-any cline-yes">2x</span>
1625
+ <span class="cline-any cline-yes">2x</span>
1626
+ <span class="cline-any cline-yes">2x</span>
1627
+ <span class="cline-any cline-no">&nbsp;</span>
1628
+ <span class="cline-any cline-no">&nbsp;</span>
1629
+ <span class="cline-any cline-no">&nbsp;</span>
1630
+ <span class="cline-any cline-no">&nbsp;</span>
1631
+ <span class="cline-any cline-no">&nbsp;</span>
1632
+ <span class="cline-any cline-no">&nbsp;</span>
1633
+ <span class="cline-any cline-no">&nbsp;</span>
1634
+ <span class="cline-any cline-no">&nbsp;</span>
1635
+ <span class="cline-any cline-no">&nbsp;</span>
1636
+ <span class="cline-any cline-no">&nbsp;</span>
1637
+ <span class="cline-any cline-no">&nbsp;</span>
1638
+ <span class="cline-any cline-no">&nbsp;</span>
1639
+ <span class="cline-any cline-no">&nbsp;</span>
1640
+ <span class="cline-any cline-no">&nbsp;</span>
1641
+ <span class="cline-any cline-no">&nbsp;</span>
1642
+ <span class="cline-any cline-no">&nbsp;</span>
1643
+ <span class="cline-any cline-no">&nbsp;</span>
1644
+ <span class="cline-any cline-no">&nbsp;</span>
1645
+ <span class="cline-any cline-no">&nbsp;</span>
1646
+ <span class="cline-any cline-no">&nbsp;</span>
1647
+ <span class="cline-any cline-no">&nbsp;</span>
1648
+ <span class="cline-any cline-no">&nbsp;</span>
1649
+ <span class="cline-any cline-no">&nbsp;</span>
1650
+ <span class="cline-any cline-no">&nbsp;</span>
1651
+ <span class="cline-any cline-no">&nbsp;</span>
1652
+ <span class="cline-any cline-no">&nbsp;</span>
1653
+ <span class="cline-any cline-no">&nbsp;</span>
1654
+ <span class="cline-any cline-no">&nbsp;</span>
1655
+ <span class="cline-any cline-no">&nbsp;</span>
1656
+ <span class="cline-any cline-no">&nbsp;</span>
1657
+ <span class="cline-any cline-no">&nbsp;</span>
1658
+ <span class="cline-any cline-no">&nbsp;</span>
1659
+ <span class="cline-any cline-no">&nbsp;</span>
1660
+ <span class="cline-any cline-no">&nbsp;</span>
1661
+ <span class="cline-any cline-no">&nbsp;</span>
1662
+ <span class="cline-any cline-no">&nbsp;</span>
1663
+ <span class="cline-any cline-no">&nbsp;</span>
1664
+ <span class="cline-any cline-no">&nbsp;</span>
1665
+ <span class="cline-any cline-no">&nbsp;</span>
1666
+ <span class="cline-any cline-yes">2x</span>
1667
+ <span class="cline-any cline-yes">2x</span>
1668
+ <span class="cline-any cline-no">&nbsp;</span>
1669
+ <span class="cline-any cline-no">&nbsp;</span>
1670
+ <span class="cline-any cline-no">&nbsp;</span>
1671
+ <span class="cline-any cline-no">&nbsp;</span>
1672
+ <span class="cline-any cline-yes">2x</span>
1673
+ <span class="cline-any cline-yes">2x</span>
1674
+ <span class="cline-any cline-yes">2x</span>
1675
+ <span class="cline-any cline-yes">2x</span>
1676
+ <span class="cline-any cline-yes">2x</span>
1677
+ <span class="cline-any cline-yes">2x</span>
1678
+ <span class="cline-any cline-yes">2x</span>
1679
+ <span class="cline-any cline-no">&nbsp;</span>
1680
+ <span class="cline-any cline-no">&nbsp;</span>
1681
+ <span class="cline-any cline-no">&nbsp;</span>
1682
+ <span class="cline-any cline-no">&nbsp;</span>
1683
+ <span class="cline-any cline-no">&nbsp;</span>
1684
+ <span class="cline-any cline-no">&nbsp;</span>
1685
+ <span class="cline-any cline-no">&nbsp;</span>
1686
+ <span class="cline-any cline-yes">2x</span>
1687
+ <span class="cline-any cline-yes">2x</span>
1688
+ <span class="cline-any cline-yes">2x</span>
1689
+ <span class="cline-any cline-yes">2x</span>
1690
+ <span class="cline-any cline-yes">2x</span>
1691
+ <span class="cline-any cline-no">&nbsp;</span>
1692
+ <span class="cline-any cline-no">&nbsp;</span>
1693
+ <span class="cline-any cline-yes">2x</span>
1694
+ <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import axios, {
1695
+ AxiosError,
1696
+ AxiosHeaders,
1697
+ AxiosInstance,
1698
+ AxiosRequestConfig,
1699
+ AxiosResponse,
1700
+ } from 'axios';
1701
+ import https from 'https';
1702
+ import WebSocket from 'isomorphic-ws';
1703
+ import { StableWSConnection } from './connection';
1704
+ import { DevToken } from './signing';
1705
+ import { TokenManager } from './token_manager';
1706
+ import { WSConnectionFallback } from './connection_fallback';
1707
+ import { isErrorResponse, isWSFailure } from './errors';
1708
+ import {
1709
+ chatCodes,
1710
+ isFunction,
1711
+ isOnline,
1712
+ randomId,
1713
+ retryInterval,
1714
+ sleep,
1715
+ } from './utils';
1716
+ &nbsp;
1717
+ import {
1718
+ APIErrorResponse,
1719
+ ConnectAPIResponse,
1720
+ ErrorFromResponse,
1721
+ Event,
1722
+ EventHandler,
1723
+ Logger,
1724
+ OwnUserResponse,
1725
+ StreamClientOptions,
1726
+ TokenOrProvider,
1727
+ } from './types';
1728
+ import { InsightMetrics, postInsights } from './insights';
1729
+ &nbsp;
1730
+ function isString(x: unknown): x is string {
1731
+ return typeof x === 'string' || x instanceof String;
1732
+ }
1733
+ &nbsp;
1734
+ export class StreamClient {
1735
+ _user?: OwnUserResponse;
1736
+ anonymous: boolean;
1737
+ persistUserOnConnectionFailure?: boolean;
1738
+ axiosInstance: AxiosInstance;
1739
+ baseURL?: string;
1740
+ browser: boolean;
1741
+ cleaningIntervalRef?: NodeJS.Timeout;
1742
+ clientID?: string;
1743
+ key: string;
1744
+ listeners: Record&lt;string, Array&lt;(event: Event) =&gt; void&gt;&gt;;
1745
+ logger: Logger;
1746
+ &nbsp;
1747
+ node: boolean;
1748
+ options: StreamClientOptions;
1749
+ secret?: string;
1750
+ setUserPromise: ConnectAPIResponse | null;
1751
+ tokenManager: TokenManager;
1752
+ user?: OwnUserResponse;
1753
+ userAgent?: string;
1754
+ userID?: string;
1755
+ wsBaseURL?: string;
1756
+ wsConnection: StableWSConnection | null;
1757
+ wsFallback?: WSConnectionFallback;
1758
+ wsPromise: ConnectAPIResponse | null;
1759
+ consecutiveFailures: number;
1760
+ insightMetrics: InsightMetrics;
1761
+ defaultWSTimeoutWithFallback: number;
1762
+ defaultWSTimeout: number;
1763
+ private nextRequestAbortController: AbortController | null = null;
1764
+ &nbsp;
1765
+ /**
1766
+ * Initialize a client.
1767
+ *
1768
+ * @param {string} key - the api key
1769
+ * @param {string} [secret] - the api secret
1770
+ * @param {StreamClientOptions} [options] - additional options, here you can pass custom options to axios instance
1771
+ * @param {boolean} [options.browser] - enforce the client to be in browser mode
1772
+ * @param {boolean} [options.warmUp] - default to false, if true, client will open a connection as soon as possible to speed up following requests
1773
+ * @param {Logger} [options.Logger] - custom logger
1774
+ * @param {number} [options.timeout] - default to 3000
1775
+ * @param {httpsAgent} [options.httpsAgent] - custom httpsAgent, in node it's default to https.agent()
1776
+ * @example &lt;caption&gt;initialize the client in user mode&lt;/caption&gt;
1777
+ * new StreamChat('api_key')
1778
+ * @example &lt;caption&gt;initialize the client in user mode with options&lt;/caption&gt;
1779
+ * new StreamChat('api_key', { warmUp:true, timeout:5000 })
1780
+ * @example &lt;caption&gt;secret is optional and only used in server side mode&lt;/caption&gt;
1781
+ * new StreamChat('api_key', "secret", { httpsAgent: customAgent })
1782
+ */
1783
+ constructor(key: string, options?: StreamClientOptions);
1784
+ constructor(key: string, secret?: string, options?: StreamClientOptions);
1785
+ constructor(
1786
+ key: string,
1787
+ secretOrOptions?: StreamClientOptions | string,
1788
+ options?: StreamClientOptions,
1789
+ ) {
1790
+ // set the key
1791
+ this.key = key;
1792
+ this.listeners = {};
1793
+ &nbsp;
1794
+ // set the secret
1795
+ if (secretOrOptions &amp;&amp; isString(secretOrOptions)) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1796
+ <span class="cstat-no" title="statement not covered" > this.secret = secretOrOptions;</span>
1797
+ <span class="cstat-no" title="statement not covered" > }</span>
1798
+ <span class="cstat-no" title="statement not covered" ></span>
1799
+ <span class="cstat-no" title="statement not covered" > // set the options... and figure out defaults...</span>
1800
+ const inputOptions = <span class="branch-0 cbranch-no" title="branch not covered" >options</span>
1801
+ <span class="cstat-no" title="statement not covered" > ? options</span>
1802
+ : secretOrOptions &amp;&amp; !isString(secretOrOptions)
1803
+ ? <span class="branch-0 cbranch-no" title="branch not covered" >secretOrOptions</span>
1804
+ <span class="cstat-no" title="statement not covered" > : ({</span>
1805
+ <span class="cstat-no" title="statement not covered" > browser: typeof window !== 'undefined',</span>
1806
+ <span class="cstat-no" title="statement not covered" > } as Partial&lt;StreamClientOptions&gt;);</span>
1807
+ &nbsp;
1808
+ this.browser = inputOptions.<span class="branch-0 cbranch-no" title="branch not covered" >browser || typeof window !== 'undefined';</span>
1809
+ this.node = !this.browser;
1810
+ &nbsp;
1811
+ this.options = {
1812
+ timeout: 3000,
1813
+ withCredentials: false, // making sure cookies are not sent
1814
+ warmUp: false,
1815
+ ...inputOptions,
1816
+ };
1817
+ &nbsp;
1818
+ if (this.<span class="branch-0 cbranch-no" title="branch not covered" >node &amp;&amp; !this.options.httpsAgent) <span class="branch-0 cbranch-no" title="branch not covered" >{</span></span>
1819
+ <span class="cstat-no" title="statement not covered" > this.options.httpsAgent = new https.Agent({</span>
1820
+ <span class="cstat-no" title="statement not covered" > keepAlive: true,</span>
1821
+ <span class="cstat-no" title="statement not covered" > keepAliveMsecs: 3000,</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" ></span>
1825
+ this.axiosInstance = axios.create(this.options);
1826
+ &nbsp;
1827
+ this.setBaseURL(this.options.<span class="branch-0 cbranch-no" title="branch not covered" >baseURL || 'https://chat.stream-io-api.com');</span>
1828
+ &nbsp;
1829
+ if (typeof process !== 'undefined' &amp;&amp; process.env.STREAM_LOCAL_TEST_RUN) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1830
+ <span class="cstat-no" title="statement not covered" > this.setBaseURL('http://localhost:3030');</span>
1831
+ <span class="cstat-no" title="statement not covered" > }</span>
1832
+ <span class="cstat-no" title="statement not covered" ></span>
1833
+ if (typeof process !== 'undefined' &amp;&amp; process.env.STREAM_LOCAL_TEST_HOST) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1834
+ <span class="cstat-no" title="statement not covered" > this.setBaseURL('http://' + process.env.STREAM_LOCAL_TEST_HOST);</span>
1835
+ <span class="cstat-no" title="statement not covered" > }</span>
1836
+ <span class="cstat-no" title="statement not covered" ></span>
1837
+ <span class="cstat-no" title="statement not covered" > // WS connection is initialized when setUser is called</span>
1838
+ this.wsConnection = null;
1839
+ this.wsPromise = null;
1840
+ this.setUserPromise = null;
1841
+ &nbsp;
1842
+ // mapping between channel groups and configs
1843
+ this.anonymous = false;
1844
+ this.persistUserOnConnectionFailure =
1845
+ this.options?.persistUserOnConnectionFailure;
1846
+ &nbsp;
1847
+ // If its a server-side client, then lets initialize the tokenManager, since token will be
1848
+ // generated from secret.
1849
+ this.tokenManager = new TokenManager(this.secret);
1850
+ this.consecutiveFailures = 0;
1851
+ this.insightMetrics = new InsightMetrics();
1852
+ &nbsp;
1853
+ this.defaultWSTimeoutWithFallback = 6000;
1854
+ this.defaultWSTimeout = 15000;
1855
+ &nbsp;
1856
+ this.logger = isFunction(inputOptions.logger<span class="branch-0 cbranch-no" title="branch not covered" >)</span>
1857
+ <span class="cstat-no" title="statement not covered" > ? inputOptions.logger</span>
1858
+ : <span class="fstat-no" title="function not covered" >() =&gt; null;</span>
1859
+ }
1860
+ &nbsp;
1861
+ <span class="fstat-no" title="function not covered" > devToken(userID: string) {</span>
1862
+ <span class="cstat-no" title="statement not covered" > return DevToken(userID);</span>
1863
+ <span class="cstat-no" title="statement not covered" > }</span>
1864
+ &nbsp;
1865
+ <span class="fstat-no" title="function not covered" > getAuthType() {</span>
1866
+ <span class="cstat-no" title="statement not covered" > return this.anonymous ? 'anonymous' : 'jwt';</span>
1867
+ <span class="cstat-no" title="statement not covered" > }</span>
1868
+ &nbsp;
1869
+ setBaseURL(baseURL: string) {
1870
+ this.baseURL = baseURL;
1871
+ this.wsBaseURL = this.baseURL
1872
+ .replace('http', 'ws')
1873
+ .replace(':3030', ':8800');
1874
+ }
1875
+ &nbsp;
1876
+ _getConnectionID = <span class="fstat-no" title="function not covered" >() =&gt;</span>
1877
+ <span class="cstat-no" title="statement not covered" > this.wsConnection?.connectionID || this.wsFallback?.connectionID;</span>
1878
+ &nbsp;
1879
+ _hasConnectionID = <span class="fstat-no" title="function not covered" >() =&gt; Boolean(this._getConnectionID());</span>
1880
+ &nbsp;
1881
+ /**
1882
+ * connectUser - Set the current user and open a WebSocket connection
1883
+ *
1884
+ * @param {OwnUserResponse} user Data about this user. IE {name: "john"}
1885
+ * @param {TokenOrProvider} userTokenOrProvider Token or provider
1886
+ *
1887
+ * @return {ConnectAPIResponse} Returns a promise that resolves when the connection is setup
1888
+ */
1889
+ connectUser = <span class="fstat-no" title="function not covered" >async (</span>
1890
+ <span class="cstat-no" title="statement not covered" > user: OwnUserResponse,</span>
1891
+ <span class="cstat-no" title="statement not covered" > userTokenOrProvider: TokenOrProvider,</span>
1892
+ <span class="cstat-no" title="statement not covered" > ) =&gt; {</span>
1893
+ <span class="cstat-no" title="statement not covered" > if (!user.id) {</span>
1894
+ <span class="cstat-no" title="statement not covered" > throw new Error('The "id" field on the user is missing');</span>
1895
+ <span class="cstat-no" title="statement not covered" > }</span>
1896
+ <span class="cstat-no" title="statement not covered" ></span>
1897
+ <span class="cstat-no" title="statement not covered" > /**</span>
1898
+ <span class="cstat-no" title="statement not covered" > * Calling connectUser multiple times is potentially the result of a bad integration, however,</span>
1899
+ <span class="cstat-no" title="statement not covered" > * If the user id remains the same we don't throw error</span>
1900
+ <span class="cstat-no" title="statement not covered" > */</span>
1901
+ <span class="cstat-no" title="statement not covered" > if (this.userID === user.id &amp;&amp; this.setUserPromise) {</span>
1902
+ <span class="cstat-no" title="statement not covered" > console.warn(</span>
1903
+ <span class="cstat-no" title="statement not covered" > 'Consecutive calls to connectUser is detected, ideally you should only call this function once in your app.',</span>
1904
+ <span class="cstat-no" title="statement not covered" > );</span>
1905
+ <span class="cstat-no" title="statement not covered" > return this.setUserPromise;</span>
1906
+ <span class="cstat-no" title="statement not covered" > }</span>
1907
+ <span class="cstat-no" title="statement not covered" ></span>
1908
+ <span class="cstat-no" title="statement not covered" > if (this.userID) {</span>
1909
+ <span class="cstat-no" title="statement not covered" > throw new Error(</span>
1910
+ <span class="cstat-no" title="statement not covered" > 'Use client.disconnect() before trying to connect as a different user. connectUser was called twice.',</span>
1911
+ <span class="cstat-no" title="statement not covered" > );</span>
1912
+ <span class="cstat-no" title="statement not covered" > }</span>
1913
+ <span class="cstat-no" title="statement not covered" ></span>
1914
+ <span class="cstat-no" title="statement not covered" > if (</span>
1915
+ <span class="cstat-no" title="statement not covered" > (this._isUsingServerAuth() || this.node) &amp;&amp;</span>
1916
+ <span class="cstat-no" title="statement not covered" > !this.options.allowServerSideConnect</span>
1917
+ <span class="cstat-no" title="statement not covered" > ) {</span>
1918
+ <span class="cstat-no" title="statement not covered" > console.warn(</span>
1919
+ <span class="cstat-no" title="statement not covered" > 'Please do not use connectUser server side. connectUser impacts MAU and concurrent connection usage and thus your bill. If you have a valid use-case, add "allowServerSideConnect: true" to the client options to disable this warning.',</span>
1920
+ <span class="cstat-no" title="statement not covered" > );</span>
1921
+ <span class="cstat-no" title="statement not covered" > }</span>
1922
+ <span class="cstat-no" title="statement not covered" ></span>
1923
+ <span class="cstat-no" title="statement not covered" > // we generate the client id client side</span>
1924
+ <span class="cstat-no" title="statement not covered" > this.userID = user.id;</span>
1925
+ <span class="cstat-no" title="statement not covered" > this.anonymous = false;</span>
1926
+ <span class="cstat-no" title="statement not covered" ></span>
1927
+ <span class="cstat-no" title="statement not covered" > const setTokenPromise = this._setToken(user, userTokenOrProvider);</span>
1928
+ <span class="cstat-no" title="statement not covered" > this._setUser(user);</span>
1929
+ <span class="cstat-no" title="statement not covered" ></span>
1930
+ <span class="cstat-no" title="statement not covered" > const wsPromise = this.openConnection();</span>
1931
+ <span class="cstat-no" title="statement not covered" ></span>
1932
+ <span class="cstat-no" title="statement not covered" > this.setUserPromise = Promise.all([setTokenPromise, wsPromise]).then(</span>
1933
+ <span class="cstat-no" title="statement not covered" > (result) =&gt; result[1], // We only return connection promise;</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" > try {</span>
1937
+ <span class="cstat-no" title="statement not covered" > return await this.setUserPromise;</span>
1938
+ <span class="cstat-no" title="statement not covered" > } catch (err) {</span>
1939
+ <span class="cstat-no" title="statement not covered" > if (this.persistUserOnConnectionFailure) {</span>
1940
+ <span class="cstat-no" title="statement not covered" > // cleanup client to allow the user to retry connectUser again</span>
1941
+ <span class="cstat-no" title="statement not covered" > this.closeConnection();</span>
1942
+ <span class="cstat-no" title="statement not covered" > } else {</span>
1943
+ <span class="cstat-no" title="statement not covered" > this.disconnectUser();</span>
1944
+ <span class="cstat-no" title="statement not covered" > }</span>
1945
+ <span class="cstat-no" title="statement not covered" > throw err;</span>
1946
+ <span class="cstat-no" title="statement not covered" > }</span>
1947
+ <span class="cstat-no" title="statement not covered" > };</span>
1948
+ &nbsp;
1949
+ _setToken = (<span class="fstat-no" title="function not covered" >user: OwnUserResponse, userTokenOrProvider: TokenOrProvider) =&gt;</span>
1950
+ <span class="cstat-no" title="statement not covered" > this.tokenManager.setTokenOrProvider(userTokenOrProvider, user);</span>
1951
+ &nbsp;
1952
+ <span class="fstat-no" title="function not covered" > _setUser(user: OwnUserResponse) {</span>
1953
+ <span class="cstat-no" title="statement not covered" > /**</span>
1954
+ <span class="cstat-no" title="statement not covered" > * This one is used by the frontend. This is a copy of the current user object stored on backend.</span>
1955
+ <span class="cstat-no" title="statement not covered" > * It contains reserved properties and own user properties which are not present in `this._user`.</span>
1956
+ <span class="cstat-no" title="statement not covered" > */</span>
1957
+ <span class="cstat-no" title="statement not covered" > this.user = user;</span>
1958
+ <span class="cstat-no" title="statement not covered" > this.userID = user.id;</span>
1959
+ <span class="cstat-no" title="statement not covered" > // this one is actually used for requests. This is a copy of current user provided to `connectUser` function.</span>
1960
+ <span class="cstat-no" title="statement not covered" > this._user = { ...user };</span>
1961
+ <span class="cstat-no" title="statement not covered" > }</span>
1962
+ &nbsp;
1963
+ /**
1964
+ * Disconnects the websocket connection, without removing the user set on client.
1965
+ * client.closeConnection will not trigger default auto-retry mechanism for reconnection. You need
1966
+ * to call client.openConnection to reconnect to websocket.
1967
+ *
1968
+ * This is mainly useful on mobile side. You can only receive push notifications
1969
+ * if you don't have active websocket connection.
1970
+ * So when your app goes to background, you can call `client.closeConnection`.
1971
+ * And when app comes back to foreground, call `client.openConnection`.
1972
+ *
1973
+ * @param timeout Max number of ms, to wait for close event of websocket, before forcefully assuming succesful disconnection.
1974
+ * https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent
1975
+ */
1976
+ closeConnection = <span class="fstat-no" title="function not covered" >async (timeout?: number) =&gt; {</span>
1977
+ <span class="cstat-no" title="statement not covered" > if (this.cleaningIntervalRef != null) {</span>
1978
+ <span class="cstat-no" title="statement not covered" > clearInterval(this.cleaningIntervalRef);</span>
1979
+ <span class="cstat-no" title="statement not covered" > this.cleaningIntervalRef = undefined;</span>
1980
+ <span class="cstat-no" title="statement not covered" > }</span>
1981
+ <span class="cstat-no" title="statement not covered" ></span>
1982
+ <span class="cstat-no" title="statement not covered" > await Promise.all([</span>
1983
+ <span class="cstat-no" title="statement not covered" > this.wsConnection?.disconnect(timeout),</span>
1984
+ <span class="cstat-no" title="statement not covered" > this.wsFallback?.disconnect(timeout),</span>
1985
+ <span class="cstat-no" title="statement not covered" > ]);</span>
1986
+ <span class="cstat-no" title="statement not covered" > return Promise.resolve();</span>
1987
+ <span class="cstat-no" title="statement not covered" > };</span>
1988
+ &nbsp;
1989
+ /**
1990
+ * Creates a new WebSocket connection with the current user. Returns empty promise, if there is an active connection
1991
+ */
1992
+ openConnection = <span class="fstat-no" title="function not covered" >async () =&gt; {</span>
1993
+ <span class="cstat-no" title="statement not covered" > if (!this.userID) {</span>
1994
+ <span class="cstat-no" title="statement not covered" > throw Error(</span>
1995
+ <span class="cstat-no" title="statement not covered" > 'User is not set on client, use client.connectUser or client.connectAnonymousUser instead',</span>
1996
+ <span class="cstat-no" title="statement not covered" > );</span>
1997
+ <span class="cstat-no" title="statement not covered" > }</span>
1998
+ <span class="cstat-no" title="statement not covered" ></span>
1999
+ <span class="cstat-no" title="statement not covered" > if (this.wsConnection?.isConnecting &amp;&amp; this.wsPromise) {</span>
2000
+ <span class="cstat-no" title="statement not covered" > this.logger(</span>
2001
+ <span class="cstat-no" title="statement not covered" > 'info',</span>
2002
+ <span class="cstat-no" title="statement not covered" > 'client:openConnection() - connection already in progress',</span>
2003
+ <span class="cstat-no" title="statement not covered" > {</span>
2004
+ <span class="cstat-no" title="statement not covered" > tags: ['connection', 'client'],</span>
2005
+ <span class="cstat-no" title="statement not covered" > },</span>
2006
+ <span class="cstat-no" title="statement not covered" > );</span>
2007
+ <span class="cstat-no" title="statement not covered" > return this.wsPromise;</span>
2008
+ <span class="cstat-no" title="statement not covered" > }</span>
2009
+ <span class="cstat-no" title="statement not covered" ></span>
2010
+ <span class="cstat-no" title="statement not covered" > if (</span>
2011
+ <span class="cstat-no" title="statement not covered" > (this.wsConnection?.isHealthy || this.wsFallback?.isHealthy()) &amp;&amp;</span>
2012
+ <span class="cstat-no" title="statement not covered" > this._hasConnectionID()</span>
2013
+ <span class="cstat-no" title="statement not covered" > ) {</span>
2014
+ <span class="cstat-no" title="statement not covered" > this.logger(</span>
2015
+ <span class="cstat-no" title="statement not covered" > 'info',</span>
2016
+ <span class="cstat-no" title="statement not covered" > 'client:openConnection() - openConnection called twice, healthy connection already exists',</span>
2017
+ <span class="cstat-no" title="statement not covered" > {</span>
2018
+ <span class="cstat-no" title="statement not covered" > tags: ['connection', 'client'],</span>
2019
+ <span class="cstat-no" title="statement not covered" > },</span>
2020
+ <span class="cstat-no" title="statement not covered" > );</span>
2021
+ <span class="cstat-no" title="statement not covered" ></span>
2022
+ <span class="cstat-no" title="statement not covered" > return Promise.resolve();</span>
2023
+ <span class="cstat-no" title="statement not covered" > }</span>
2024
+ <span class="cstat-no" title="statement not covered" ></span>
2025
+ <span class="cstat-no" title="statement not covered" > this.clientID = `${this.userID}--${randomId()}`;</span>
2026
+ <span class="cstat-no" title="statement not covered" > this.wsPromise = this.connect();</span>
2027
+ <span class="cstat-no" title="statement not covered" > return this.wsPromise;</span>
2028
+ <span class="cstat-no" title="statement not covered" > };</span>
2029
+ &nbsp;
2030
+ _normalizeDate = (<span class="fstat-no" title="function not covered" >before: Date | string | null): string | null =&gt; {</span>
2031
+ <span class="cstat-no" title="statement not covered" > if (before instanceof Date) {</span>
2032
+ <span class="cstat-no" title="statement not covered" > before = before.toISOString();</span>
2033
+ <span class="cstat-no" title="statement not covered" > }</span>
2034
+ <span class="cstat-no" title="statement not covered" ></span>
2035
+ <span class="cstat-no" title="statement not covered" > if (before === '') {</span>
2036
+ <span class="cstat-no" title="statement not covered" > throw new Error(</span>
2037
+ <span class="cstat-no" title="statement not covered" > "Don't pass blank string for since, use null instead if resetting the token revoke",</span>
2038
+ <span class="cstat-no" title="statement not covered" > );</span>
2039
+ <span class="cstat-no" title="statement not covered" > }</span>
2040
+ <span class="cstat-no" title="statement not covered" ></span>
2041
+ <span class="cstat-no" title="statement not covered" > return before;</span>
2042
+ <span class="cstat-no" title="statement not covered" > };</span>
2043
+ &nbsp;
2044
+ /**
2045
+ * Disconnects the websocket and removes the user from client.
2046
+ *
2047
+ * @param timeout Max number of ms, to wait for close event of websocket, before forcefully assuming successful disconnection.
2048
+ * https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent
2049
+ */
2050
+ disconnectUser = <span class="fstat-no" title="function not covered" >async (timeout?: number) =&gt; {</span>
2051
+ <span class="cstat-no" title="statement not covered" > this.logger('info', 'client:disconnect() - Disconnecting the client', {</span>
2052
+ <span class="cstat-no" title="statement not covered" > tags: ['connection', 'client'],</span>
2053
+ <span class="cstat-no" title="statement not covered" > });</span>
2054
+ <span class="cstat-no" title="statement not covered" ></span>
2055
+ <span class="cstat-no" title="statement not covered" > // remove the user specific fields</span>
2056
+ <span class="cstat-no" title="statement not covered" > delete this.user;</span>
2057
+ <span class="cstat-no" title="statement not covered" > delete this._user;</span>
2058
+ <span class="cstat-no" title="statement not covered" > delete this.userID;</span>
2059
+ <span class="cstat-no" title="statement not covered" ></span>
2060
+ <span class="cstat-no" title="statement not covered" > this.anonymous = false;</span>
2061
+ <span class="cstat-no" title="statement not covered" ></span>
2062
+ <span class="cstat-no" title="statement not covered" > const closePromise = this.closeConnection(timeout);</span>
2063
+ <span class="cstat-no" title="statement not covered" > // reset token manager</span>
2064
+ <span class="cstat-no" title="statement not covered" > setTimeout(this.tokenManager.reset); // delay reseting to use token for disconnect calls</span>
2065
+ <span class="cstat-no" title="statement not covered" ></span>
2066
+ <span class="cstat-no" title="statement not covered" > // close the WS connection</span>
2067
+ <span class="cstat-no" title="statement not covered" > return closePromise;</span>
2068
+ <span class="cstat-no" title="statement not covered" > };</span>
2069
+ &nbsp;
2070
+ /**
2071
+ * connectAnonymousUser - Set an anonymous user and open a WebSocket connection
2072
+ */
2073
+ connectAnonymousUser = <span class="fstat-no" title="function not covered" >() =&gt; {</span>
2074
+ <span class="cstat-no" title="statement not covered" > if (</span>
2075
+ <span class="cstat-no" title="statement not covered" > (this._isUsingServerAuth() || this.node) &amp;&amp;</span>
2076
+ <span class="cstat-no" title="statement not covered" > !this.options.allowServerSideConnect</span>
2077
+ <span class="cstat-no" title="statement not covered" > ) {</span>
2078
+ <span class="cstat-no" title="statement not covered" > console.warn(</span>
2079
+ <span class="cstat-no" title="statement not covered" > 'Please do not use connectUser server side. connectUser impacts MAU and concurrent connection usage and thus your bill. If you have a valid use-case, add "allowServerSideConnect: true" to the client options to disable this warning.',</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" > this.anonymous = true;</span>
2084
+ <span class="cstat-no" title="statement not covered" > this.userID = randomId();</span>
2085
+ <span class="cstat-no" title="statement not covered" > const anonymousUser = {</span>
2086
+ <span class="cstat-no" title="statement not covered" > id: this.userID,</span>
2087
+ <span class="cstat-no" title="statement not covered" > anon: true,</span>
2088
+ <span class="cstat-no" title="statement not covered" > } as unknown as OwnUserResponse;</span>
2089
+ <span class="cstat-no" title="statement not covered" ></span>
2090
+ <span class="cstat-no" title="statement not covered" > this._setToken(anonymousUser, '');</span>
2091
+ <span class="cstat-no" title="statement not covered" > this._setUser(anonymousUser);</span>
2092
+ <span class="cstat-no" title="statement not covered" ></span>
2093
+ <span class="cstat-no" title="statement not covered" > return this.openConnection();</span>
2094
+ <span class="cstat-no" title="statement not covered" > };</span>
2095
+ &nbsp;
2096
+ /**
2097
+ * on - Listen to events on all channels and users your watching
2098
+ *
2099
+ * client.on('message.new', event =&gt; {console.log("my new message", event, channel.state.messages)})
2100
+ * or
2101
+ * client.on(event =&gt; {console.log(event.type)})
2102
+ *
2103
+ * @param {EventHandler | string} callbackOrEventName The event type to listen for (optional)
2104
+ * @param {EventHandler} [callbackOrNothing] The callback to call
2105
+ *
2106
+ * @return {Function} Returns a function which, when called, unsubscribes the event handler.
2107
+ */
2108
+ <span class="fstat-no" title="function not covered" > on(</span>
2109
+ <span class="cstat-no" title="statement not covered" > callbackOrEventName: EventHandler | string,</span>
2110
+ <span class="cstat-no" title="statement not covered" > callbackOrNothing?: EventHandler,</span>
2111
+ <span class="cstat-no" title="statement not covered" > ) {</span>
2112
+ <span class="cstat-no" title="statement not covered" > const key = callbackOrNothing ? (callbackOrEventName as string) : 'all';</span>
2113
+ <span class="cstat-no" title="statement not covered" > const callback = callbackOrNothing</span>
2114
+ <span class="cstat-no" title="statement not covered" > ? callbackOrNothing</span>
2115
+ <span class="cstat-no" title="statement not covered" > : (callbackOrEventName as EventHandler);</span>
2116
+ <span class="cstat-no" title="statement not covered" > if (!(key in this.listeners)) {</span>
2117
+ <span class="cstat-no" title="statement not covered" > this.listeners[key] = [];</span>
2118
+ <span class="cstat-no" title="statement not covered" > }</span>
2119
+ <span class="cstat-no" title="statement not covered" > this.logger('info', `Attaching listener for ${key} event`, {</span>
2120
+ <span class="cstat-no" title="statement not covered" > tags: ['event', 'client'],</span>
2121
+ <span class="cstat-no" title="statement not covered" > });</span>
2122
+ <span class="cstat-no" title="statement not covered" > this.listeners[key].push(callback);</span>
2123
+ <span class="cstat-no" title="statement not covered" ></span>
2124
+ <span class="cstat-no" title="statement not covered" > return () =&gt; {</span>
2125
+ <span class="cstat-no" title="statement not covered" > this.off(key, callback);</span>
2126
+ <span class="cstat-no" title="statement not covered" > };</span>
2127
+ <span class="cstat-no" title="statement not covered" > }</span>
2128
+ &nbsp;
2129
+ /**
2130
+ * off - Remove the event handler
2131
+ *
2132
+ */
2133
+ <span class="fstat-no" title="function not covered" > off(</span>
2134
+ <span class="cstat-no" title="statement not covered" > callbackOrEventName: EventHandler | string,</span>
2135
+ <span class="cstat-no" title="statement not covered" > callbackOrNothing?: EventHandler,</span>
2136
+ <span class="cstat-no" title="statement not covered" > ) {</span>
2137
+ <span class="cstat-no" title="statement not covered" > const key = callbackOrNothing ? (callbackOrEventName as string) : 'all';</span>
2138
+ <span class="cstat-no" title="statement not covered" > const callback = callbackOrNothing</span>
2139
+ <span class="cstat-no" title="statement not covered" > ? callbackOrNothing</span>
2140
+ <span class="cstat-no" title="statement not covered" > : (callbackOrEventName as EventHandler);</span>
2141
+ <span class="cstat-no" title="statement not covered" > if (!(key in this.listeners)) {</span>
2142
+ <span class="cstat-no" title="statement not covered" > this.listeners[key] = [];</span>
2143
+ <span class="cstat-no" title="statement not covered" > }</span>
2144
+ <span class="cstat-no" title="statement not covered" ></span>
2145
+ <span class="cstat-no" title="statement not covered" > this.logger('info', `Removing listener for ${key} event`, {</span>
2146
+ <span class="cstat-no" title="statement not covered" > tags: ['event', 'client'],</span>
2147
+ <span class="cstat-no" title="statement not covered" > });</span>
2148
+ <span class="cstat-no" title="statement not covered" > this.listeners[key] = this.listeners[key].filter(</span>
2149
+ <span class="cstat-no" title="statement not covered" > (value) =&gt; value !== callback,</span>
2150
+ <span class="cstat-no" title="statement not covered" > );</span>
2151
+ <span class="cstat-no" title="statement not covered" > }</span>
2152
+ &nbsp;
2153
+ <span class="fstat-no" title="function not covered" > _logApiRequest(</span>
2154
+ <span class="cstat-no" title="statement not covered" > type: string,</span>
2155
+ <span class="cstat-no" title="statement not covered" > url: string,</span>
2156
+ <span class="cstat-no" title="statement not covered" > data: unknown,</span>
2157
+ <span class="cstat-no" title="statement not covered" > config: AxiosRequestConfig &amp; {</span>
2158
+ <span class="cstat-no" title="statement not covered" > config?: AxiosRequestConfig &amp; { maxBodyLength?: number };</span>
2159
+ <span class="cstat-no" title="statement not covered" > },</span>
2160
+ <span class="cstat-no" title="statement not covered" > ) {</span>
2161
+ <span class="cstat-no" title="statement not covered" > this.logger('info', `client: ${type} - Request - ${url}`, {</span>
2162
+ <span class="cstat-no" title="statement not covered" > tags: ['api', 'api_request', 'client'],</span>
2163
+ <span class="cstat-no" title="statement not covered" > url,</span>
2164
+ <span class="cstat-no" title="statement not covered" > payload: data,</span>
2165
+ <span class="cstat-no" title="statement not covered" > config,</span>
2166
+ <span class="cstat-no" title="statement not covered" > });</span>
2167
+ <span class="cstat-no" title="statement not covered" > }</span>
2168
+ &nbsp;
2169
+ <span class="fstat-no" title="function not covered" > _logApiResponse&lt;T&gt;(type: string, url: string, response: AxiosResponse&lt;T&gt;) {</span>
2170
+ <span class="cstat-no" title="statement not covered" > this.logger(</span>
2171
+ <span class="cstat-no" title="statement not covered" > 'info',</span>
2172
+ <span class="cstat-no" title="statement not covered" > `client:${type} - Response - url: ${url} &gt; status ${response.status}`,</span>
2173
+ <span class="cstat-no" title="statement not covered" > {</span>
2174
+ <span class="cstat-no" title="statement not covered" > tags: ['api', 'api_response', 'client'],</span>
2175
+ <span class="cstat-no" title="statement not covered" > url,</span>
2176
+ <span class="cstat-no" title="statement not covered" > response,</span>
2177
+ <span class="cstat-no" title="statement not covered" > },</span>
2178
+ <span class="cstat-no" title="statement not covered" > );</span>
2179
+ <span class="cstat-no" title="statement not covered" > }</span>
2180
+ &nbsp;
2181
+ <span class="fstat-no" title="function not covered" > _logApiError(type: string, url: string, error: unknown) {</span>
2182
+ <span class="cstat-no" title="statement not covered" > this.logger('error', `client:${type} - Error - url: ${url}`, {</span>
2183
+ <span class="cstat-no" title="statement not covered" > tags: ['api', 'api_response', 'client'],</span>
2184
+ <span class="cstat-no" title="statement not covered" > url,</span>
2185
+ <span class="cstat-no" title="statement not covered" > error,</span>
2186
+ <span class="cstat-no" title="statement not covered" > });</span>
2187
+ <span class="cstat-no" title="statement not covered" > }</span>
2188
+ &nbsp;
2189
+ doAxiosRequest = <span class="fstat-no" title="function not covered" >async &lt;T&gt;(</span>
2190
+ <span class="cstat-no" title="statement not covered" > type: string,</span>
2191
+ <span class="cstat-no" title="statement not covered" > url: string,</span>
2192
+ <span class="cstat-no" title="statement not covered" > data?: unknown,</span>
2193
+ <span class="cstat-no" title="statement not covered" > options: AxiosRequestConfig &amp; {</span>
2194
+ <span class="cstat-no" title="statement not covered" > config?: AxiosRequestConfig &amp; { maxBodyLength?: number };</span>
2195
+ <span class="cstat-no" title="statement not covered" > } = {},</span>
2196
+ <span class="cstat-no" title="statement not covered" > ): Promise&lt;T&gt; =&gt; {</span>
2197
+ <span class="cstat-no" title="statement not covered" > await this.tokenManager.tokenReady();</span>
2198
+ <span class="cstat-no" title="statement not covered" > const requestConfig = this._enrichAxiosOptions(options);</span>
2199
+ <span class="cstat-no" title="statement not covered" > try {</span>
2200
+ <span class="cstat-no" title="statement not covered" > let response: AxiosResponse&lt;T&gt;;</span>
2201
+ <span class="cstat-no" title="statement not covered" > this._logApiRequest(type, url, data, requestConfig);</span>
2202
+ <span class="cstat-no" title="statement not covered" > switch (type) {</span>
2203
+ <span class="cstat-no" title="statement not covered" > case 'get':</span>
2204
+ <span class="cstat-no" title="statement not covered" > response = await this.axiosInstance.get(url, requestConfig);</span>
2205
+ <span class="cstat-no" title="statement not covered" > break;</span>
2206
+ <span class="cstat-no" title="statement not covered" > case 'delete':</span>
2207
+ <span class="cstat-no" title="statement not covered" > response = await this.axiosInstance.delete(url, requestConfig);</span>
2208
+ <span class="cstat-no" title="statement not covered" > break;</span>
2209
+ <span class="cstat-no" title="statement not covered" > case 'post':</span>
2210
+ <span class="cstat-no" title="statement not covered" > response = await this.axiosInstance.post(url, data, requestConfig);</span>
2211
+ <span class="cstat-no" title="statement not covered" > break;</span>
2212
+ <span class="cstat-no" title="statement not covered" > case 'put':</span>
2213
+ <span class="cstat-no" title="statement not covered" > response = await this.axiosInstance.put(url, data, requestConfig);</span>
2214
+ <span class="cstat-no" title="statement not covered" > break;</span>
2215
+ <span class="cstat-no" title="statement not covered" > case 'patch':</span>
2216
+ <span class="cstat-no" title="statement not covered" > response = await this.axiosInstance.patch(url, data, requestConfig);</span>
2217
+ <span class="cstat-no" title="statement not covered" > break;</span>
2218
+ <span class="cstat-no" title="statement not covered" > case 'options':</span>
2219
+ <span class="cstat-no" title="statement not covered" > response = await this.axiosInstance.options(url, requestConfig);</span>
2220
+ <span class="cstat-no" title="statement not covered" > break;</span>
2221
+ <span class="cstat-no" title="statement not covered" > default:</span>
2222
+ <span class="cstat-no" title="statement not covered" > throw new Error('Invalid request type');</span>
2223
+ <span class="cstat-no" title="statement not covered" > }</span>
2224
+ <span class="cstat-no" title="statement not covered" > this._logApiResponse&lt;T&gt;(type, url, response);</span>
2225
+ <span class="cstat-no" title="statement not covered" > this.consecutiveFailures = 0;</span>
2226
+ <span class="cstat-no" title="statement not covered" > return this.handleResponse(response);</span>
2227
+ <span class="cstat-no" title="statement not covered" > // eslint-disable-next-line @typescript-eslint/no-explicit-any</span>
2228
+ <span class="cstat-no" title="statement not covered" > } catch (e: any /**TODO: generalize error types */) {</span>
2229
+ <span class="cstat-no" title="statement not covered" > e.client_request_id = requestConfig.headers?.['x-client-request-id'];</span>
2230
+ <span class="cstat-no" title="statement not covered" > this._logApiError(type, url, e);</span>
2231
+ <span class="cstat-no" title="statement not covered" > this.consecutiveFailures += 1;</span>
2232
+ <span class="cstat-no" title="statement not covered" > if (e.response) {</span>
2233
+ <span class="cstat-no" title="statement not covered" > /** connection_fallback depends on this token expiration logic */</span>
2234
+ <span class="cstat-no" title="statement not covered" > if (</span>
2235
+ <span class="cstat-no" title="statement not covered" > e.response.data.code === chatCodes.TOKEN_EXPIRED &amp;&amp;</span>
2236
+ <span class="cstat-no" title="statement not covered" > !this.tokenManager.isStatic()</span>
2237
+ <span class="cstat-no" title="statement not covered" > ) {</span>
2238
+ <span class="cstat-no" title="statement not covered" > if (this.consecutiveFailures &gt; 1) {</span>
2239
+ <span class="cstat-no" title="statement not covered" > await sleep(retryInterval(this.consecutiveFailures));</span>
2240
+ <span class="cstat-no" title="statement not covered" > }</span>
2241
+ <span class="cstat-no" title="statement not covered" > await this.tokenManager.loadToken();</span>
2242
+ <span class="cstat-no" title="statement not covered" > return await this.doAxiosRequest&lt;T&gt;(type, url, data, options);</span>
2243
+ <span class="cstat-no" title="statement not covered" > }</span>
2244
+ <span class="cstat-no" title="statement not covered" > return this.handleResponse(e.response);</span>
2245
+ <span class="cstat-no" title="statement not covered" > } else {</span>
2246
+ <span class="cstat-no" title="statement not covered" > throw e as AxiosError&lt;APIErrorResponse&gt;;</span>
2247
+ <span class="cstat-no" title="statement not covered" > }</span>
2248
+ <span class="cstat-no" title="statement not covered" > }</span>
2249
+ <span class="cstat-no" title="statement not covered" > };</span>
2250
+ &nbsp;
2251
+ <span class="fstat-no" title="function not covered" > get&lt;T&gt;(url: string, params?: AxiosRequestConfig['params']) {</span>
2252
+ <span class="cstat-no" title="statement not covered" > return this.doAxiosRequest&lt;T&gt;('get', url, null, {</span>
2253
+ <span class="cstat-no" title="statement not covered" > params,</span>
2254
+ <span class="cstat-no" title="statement not covered" > });</span>
2255
+ <span class="cstat-no" title="statement not covered" > }</span>
2256
+ &nbsp;
2257
+ <span class="fstat-no" title="function not covered" > put&lt;T&gt;(url: string, data?: unknown) {</span>
2258
+ <span class="cstat-no" title="statement not covered" > return this.doAxiosRequest&lt;T&gt;('put', url, data);</span>
2259
+ <span class="cstat-no" title="statement not covered" > }</span>
2260
+ &nbsp;
2261
+ <span class="fstat-no" title="function not covered" > post&lt;T&gt;(url: string, data?: unknown) {</span>
2262
+ <span class="cstat-no" title="statement not covered" > return this.doAxiosRequest&lt;T&gt;('post', url, data);</span>
2263
+ <span class="cstat-no" title="statement not covered" > }</span>
2264
+ &nbsp;
2265
+ <span class="fstat-no" title="function not covered" > patch&lt;T&gt;(url: string, data?: unknown) {</span>
2266
+ <span class="cstat-no" title="statement not covered" > return this.doAxiosRequest&lt;T&gt;('patch', url, data);</span>
2267
+ <span class="cstat-no" title="statement not covered" > }</span>
2268
+ &nbsp;
2269
+ <span class="fstat-no" title="function not covered" > delete&lt;T&gt;(url: string, params?: AxiosRequestConfig['params']) {</span>
2270
+ <span class="cstat-no" title="statement not covered" > return this.doAxiosRequest&lt;T&gt;('delete', url, null, {</span>
2271
+ <span class="cstat-no" title="statement not covered" > params,</span>
2272
+ <span class="cstat-no" title="statement not covered" > });</span>
2273
+ <span class="cstat-no" title="statement not covered" > }</span>
2274
+ &nbsp;
2275
+ <span class="fstat-no" title="function not covered" > errorFromResponse(</span>
2276
+ <span class="cstat-no" title="statement not covered" > response: AxiosResponse&lt;APIErrorResponse&gt;,</span>
2277
+ <span class="cstat-no" title="statement not covered" > ): ErrorFromResponse&lt;APIErrorResponse&gt; {</span>
2278
+ <span class="cstat-no" title="statement not covered" > let err: ErrorFromResponse&lt;APIErrorResponse&gt;;</span>
2279
+ <span class="cstat-no" title="statement not covered" > err = new ErrorFromResponse(</span>
2280
+ <span class="cstat-no" title="statement not covered" > `StreamChat error HTTP code: ${response.status}`,</span>
2281
+ <span class="cstat-no" title="statement not covered" > );</span>
2282
+ <span class="cstat-no" title="statement not covered" > if (response.data &amp;&amp; response.data.code) {</span>
2283
+ <span class="cstat-no" title="statement not covered" > err = new Error(</span>
2284
+ <span class="cstat-no" title="statement not covered" > `StreamChat error code ${response.data.code}: ${response.data.message}`,</span>
2285
+ <span class="cstat-no" title="statement not covered" > );</span>
2286
+ <span class="cstat-no" title="statement not covered" > err.code = response.data.code;</span>
2287
+ <span class="cstat-no" title="statement not covered" > }</span>
2288
+ <span class="cstat-no" title="statement not covered" > err.response = response;</span>
2289
+ <span class="cstat-no" title="statement not covered" > err.status = response.status;</span>
2290
+ <span class="cstat-no" title="statement not covered" > return err;</span>
2291
+ <span class="cstat-no" title="statement not covered" > }</span>
2292
+ &nbsp;
2293
+ <span class="fstat-no" title="function not covered" > handleResponse&lt;T&gt;(response: AxiosResponse&lt;T&gt;) {</span>
2294
+ <span class="cstat-no" title="statement not covered" > const data = response.data;</span>
2295
+ <span class="cstat-no" title="statement not covered" > if (isErrorResponse(response)) {</span>
2296
+ <span class="cstat-no" title="statement not covered" > throw this.errorFromResponse(response);</span>
2297
+ <span class="cstat-no" title="statement not covered" > }</span>
2298
+ <span class="cstat-no" title="statement not covered" > return data;</span>
2299
+ <span class="cstat-no" title="statement not covered" > }</span>
2300
+ &nbsp;
2301
+ dispatchEvent = (<span class="fstat-no" title="function not covered" >event: Event) =&gt; {</span>
2302
+ <span class="cstat-no" title="statement not covered" > if (!event.received_at) event.received_at = new Date();</span>
2303
+ <span class="cstat-no" title="statement not covered" ></span>
2304
+ <span class="cstat-no" title="statement not covered" > this._callClientListeners(event);</span>
2305
+ <span class="cstat-no" title="statement not covered" > };</span>
2306
+ &nbsp;
2307
+ handleEvent = (<span class="fstat-no" title="function not covered" >messageEvent: WebSocket.MessageEvent) =&gt; {</span>
2308
+ <span class="cstat-no" title="statement not covered" > // dispatch the event to the channel listeners</span>
2309
+ <span class="cstat-no" title="statement not covered" > const jsonString = messageEvent.data as string;</span>
2310
+ <span class="cstat-no" title="statement not covered" > const event = JSON.parse(jsonString) as Event;</span>
2311
+ <span class="cstat-no" title="statement not covered" > this.dispatchEvent(event);</span>
2312
+ <span class="cstat-no" title="statement not covered" > };</span>
2313
+ &nbsp;
2314
+ _callClientListeners = (<span class="fstat-no" title="function not covered" >event: Event) =&gt; {</span>
2315
+ <span class="cstat-no" title="statement not covered" > const client = this;</span>
2316
+ <span class="cstat-no" title="statement not covered" > // gather and call the listeners</span>
2317
+ <span class="cstat-no" title="statement not covered" > const listeners: Array&lt;(e: Event) =&gt; void&gt; = [];</span>
2318
+ <span class="cstat-no" title="statement not covered" > if (client.listeners.all) {</span>
2319
+ <span class="cstat-no" title="statement not covered" > listeners.push(...client.listeners.all);</span>
2320
+ <span class="cstat-no" title="statement not covered" > }</span>
2321
+ <span class="cstat-no" title="statement not covered" > if (client.listeners[event.type]) {</span>
2322
+ <span class="cstat-no" title="statement not covered" > listeners.push(...client.listeners[event.type]);</span>
2323
+ <span class="cstat-no" title="statement not covered" > }</span>
2324
+ <span class="cstat-no" title="statement not covered" ></span>
2325
+ <span class="cstat-no" title="statement not covered" > // call the event and send it to the listeners</span>
2326
+ <span class="cstat-no" title="statement not covered" > for (const listener of listeners) {</span>
2327
+ <span class="cstat-no" title="statement not covered" > listener(event);</span>
2328
+ <span class="cstat-no" title="statement not covered" > }</span>
2329
+ <span class="cstat-no" title="statement not covered" > };</span>
2330
+ &nbsp;
2331
+ /**
2332
+ * @private
2333
+ */
2334
+ <span class="fstat-no" title="function not covered" > async connect() {</span>
2335
+ <span class="cstat-no" title="statement not covered" > if (!this.userID || !this._user) {</span>
2336
+ <span class="cstat-no" title="statement not covered" > throw Error(</span>
2337
+ <span class="cstat-no" title="statement not covered" > 'Call connectUser or connectAnonymousUser before starting the connection',</span>
2338
+ <span class="cstat-no" title="statement not covered" > );</span>
2339
+ <span class="cstat-no" title="statement not covered" > }</span>
2340
+ <span class="cstat-no" title="statement not covered" > if (!this.wsBaseURL) {</span>
2341
+ <span class="cstat-no" title="statement not covered" > throw Error('Websocket base url not set');</span>
2342
+ <span class="cstat-no" title="statement not covered" > }</span>
2343
+ <span class="cstat-no" title="statement not covered" > if (!this.clientID) {</span>
2344
+ <span class="cstat-no" title="statement not covered" > throw Error('clientID is not set');</span>
2345
+ <span class="cstat-no" title="statement not covered" > }</span>
2346
+ <span class="cstat-no" title="statement not covered" ></span>
2347
+ <span class="cstat-no" title="statement not covered" > if (</span>
2348
+ <span class="cstat-no" title="statement not covered" > !this.wsConnection &amp;&amp;</span>
2349
+ <span class="cstat-no" title="statement not covered" > (this.options.warmUp || this.options.enableInsights)</span>
2350
+ <span class="cstat-no" title="statement not covered" > ) {</span>
2351
+ <span class="cstat-no" title="statement not covered" > this._sayHi();</span>
2352
+ <span class="cstat-no" title="statement not covered" > }</span>
2353
+ <span class="cstat-no" title="statement not covered" > // The StableWSConnection handles all the reconnection logic.</span>
2354
+ <span class="cstat-no" title="statement not covered" > if (this.options.wsConnection &amp;&amp; this.node) {</span>
2355
+ <span class="cstat-no" title="statement not covered" > // Intentionally avoiding adding ts generics on wsConnection in options since its only useful for unit test purpose.</span>
2356
+ <span class="cstat-no" title="statement not covered" > (this.options.wsConnection as unknown as StableWSConnection).setClient(</span>
2357
+ <span class="cstat-no" title="statement not covered" > this,</span>
2358
+ <span class="cstat-no" title="statement not covered" > );</span>
2359
+ <span class="cstat-no" title="statement not covered" > this.wsConnection = this.options</span>
2360
+ <span class="cstat-no" title="statement not covered" > .wsConnection as unknown as StableWSConnection;</span>
2361
+ <span class="cstat-no" title="statement not covered" > } else {</span>
2362
+ <span class="cstat-no" title="statement not covered" > this.wsConnection = new StableWSConnection(this);</span>
2363
+ <span class="cstat-no" title="statement not covered" > }</span>
2364
+ <span class="cstat-no" title="statement not covered" ></span>
2365
+ <span class="cstat-no" title="statement not covered" > try {</span>
2366
+ <span class="cstat-no" title="statement not covered" > // if fallback is used before, continue using it instead of waiting for WS to fail</span>
2367
+ <span class="cstat-no" title="statement not covered" > if (this.wsFallback) {</span>
2368
+ <span class="cstat-no" title="statement not covered" > return await this.wsFallback.connect();</span>
2369
+ <span class="cstat-no" title="statement not covered" > }</span>
2370
+ <span class="cstat-no" title="statement not covered" ></span>
2371
+ <span class="cstat-no" title="statement not covered" > // if WSFallback is enabled, ws connect should timeout faster so fallback can try</span>
2372
+ <span class="cstat-no" title="statement not covered" > return await this.wsConnection.connect(</span>
2373
+ <span class="cstat-no" title="statement not covered" > this.options.enableWSFallback</span>
2374
+ <span class="cstat-no" title="statement not covered" > ? this.defaultWSTimeoutWithFallback</span>
2375
+ <span class="cstat-no" title="statement not covered" > : this.defaultWSTimeout,</span>
2376
+ <span class="cstat-no" title="statement not covered" > );</span>
2377
+ <span class="cstat-no" title="statement not covered" > } catch (err) {</span>
2378
+ <span class="cstat-no" title="statement not covered" > // run fallback only if it's WS/Network error and not a normal API error</span>
2379
+ <span class="cstat-no" title="statement not covered" > // make sure browser is online before even trying the longpoll</span>
2380
+ <span class="cstat-no" title="statement not covered" > // @ts-ignore</span>
2381
+ <span class="cstat-no" title="statement not covered" > if (this.options.enableWSFallback &amp;&amp; isWSFailure(err) &amp;&amp; isOnline()) {</span>
2382
+ <span class="cstat-no" title="statement not covered" > this.logger(</span>
2383
+ <span class="cstat-no" title="statement not covered" > 'info',</span>
2384
+ <span class="cstat-no" title="statement not covered" > 'client:connect() - WS failed, fallback to longpoll',</span>
2385
+ <span class="cstat-no" title="statement not covered" > { tags: ['connection', 'client'] },</span>
2386
+ <span class="cstat-no" title="statement not covered" > );</span>
2387
+ <span class="cstat-no" title="statement not covered" > this.dispatchEvent({ type: 'transport.changed', mode: 'longpoll' });</span>
2388
+ <span class="cstat-no" title="statement not covered" ></span>
2389
+ <span class="cstat-no" title="statement not covered" > this.wsConnection._destroyCurrentWSConnection();</span>
2390
+ <span class="cstat-no" title="statement not covered" > this.wsConnection.disconnect().then(); // close WS so no retry</span>
2391
+ <span class="cstat-no" title="statement not covered" > this.wsFallback = new WSConnectionFallback(this);</span>
2392
+ <span class="cstat-no" title="statement not covered" > return await this.wsFallback.connect();</span>
2393
+ <span class="cstat-no" title="statement not covered" > }</span>
2394
+ <span class="cstat-no" title="statement not covered" ></span>
2395
+ <span class="cstat-no" title="statement not covered" > throw err;</span>
2396
+ <span class="cstat-no" title="statement not covered" > }</span>
2397
+ <span class="cstat-no" title="statement not covered" > }</span>
2398
+ &nbsp;
2399
+ /**
2400
+ * Check the connectivity with server for warmup purpose.
2401
+ *
2402
+ * @private
2403
+ */
2404
+ <span class="fstat-no" title="function not covered" > _sayHi() {</span>
2405
+ <span class="cstat-no" title="statement not covered" > const client_request_id = randomId();</span>
2406
+ <span class="cstat-no" title="statement not covered" > const opts = {</span>
2407
+ <span class="cstat-no" title="statement not covered" > headers: AxiosHeaders.from({</span>
2408
+ <span class="cstat-no" title="statement not covered" > 'x-client-request-id': client_request_id,</span>
2409
+ <span class="cstat-no" title="statement not covered" > }),</span>
2410
+ <span class="cstat-no" title="statement not covered" > };</span>
2411
+ <span class="cstat-no" title="statement not covered" > this.doAxiosRequest('get', this.baseURL + '/hi', null, opts).catch((e) =&gt; {</span>
2412
+ <span class="cstat-no" title="statement not covered" > if (this.options.enableInsights) {</span>
2413
+ <span class="cstat-no" title="statement not covered" > postInsights('http_hi_failed', {</span>
2414
+ <span class="cstat-no" title="statement not covered" > api_key: this.key,</span>
2415
+ <span class="cstat-no" title="statement not covered" > err: e,</span>
2416
+ <span class="cstat-no" title="statement not covered" > client_request_id,</span>
2417
+ <span class="cstat-no" title="statement not covered" > });</span>
2418
+ <span class="cstat-no" title="statement not covered" > }</span>
2419
+ <span class="cstat-no" title="statement not covered" > });</span>
2420
+ <span class="cstat-no" title="statement not covered" > }</span>
2421
+ &nbsp;
2422
+ <span class="fstat-no" title="function not covered" > getUserAgent() {</span>
2423
+ <span class="cstat-no" title="statement not covered" > return (</span>
2424
+ <span class="cstat-no" title="statement not covered" > this.userAgent ||</span>
2425
+ <span class="cstat-no" title="statement not covered" > `stream-video-javascript-client-${this.node ? 'node' : 'browser'}-${</span>
2426
+ <span class="cstat-no" title="statement not covered" > process.env.PKG_VERSION</span>
2427
+ <span class="cstat-no" title="statement not covered" > }`</span>
2428
+ <span class="cstat-no" title="statement not covered" > );</span>
2429
+ <span class="cstat-no" title="statement not covered" > }</span>
2430
+ &nbsp;
2431
+ <span class="fstat-no" title="function not covered" > setUserAgent(userAgent: string) {</span>
2432
+ <span class="cstat-no" title="statement not covered" > this.userAgent = userAgent;</span>
2433
+ <span class="cstat-no" title="statement not covered" > }</span>
2434
+ &nbsp;
2435
+ /**
2436
+ * _isUsingServerAuth - Returns true if we're using server side auth
2437
+ */
2438
+ _isUsingServerAuth = <span class="fstat-no" title="function not covered" >() =&gt; !!this.secret;</span>
2439
+ &nbsp;
2440
+ <span class="fstat-no" title="function not covered" > _enrichAxiosOptions(</span>
2441
+ <span class="cstat-no" title="statement not covered" > options: AxiosRequestConfig &amp; { config?: AxiosRequestConfig } = {</span>
2442
+ <span class="cstat-no" title="statement not covered" > params: {},</span>
2443
+ <span class="cstat-no" title="statement not covered" > headers: {},</span>
2444
+ <span class="cstat-no" title="statement not covered" > config: {},</span>
2445
+ <span class="cstat-no" title="statement not covered" > },</span>
2446
+ <span class="cstat-no" title="statement not covered" > ): AxiosRequestConfig {</span>
2447
+ <span class="cstat-no" title="statement not covered" > const token = this._getToken();</span>
2448
+ <span class="cstat-no" title="statement not covered" > const authorization = token ? { Authorization: token } : undefined;</span>
2449
+ <span class="cstat-no" title="statement not covered" > let signal: AbortSignal | null = null;</span>
2450
+ <span class="cstat-no" title="statement not covered" > if (this.nextRequestAbortController !== null) {</span>
2451
+ <span class="cstat-no" title="statement not covered" > signal = this.nextRequestAbortController.signal;</span>
2452
+ <span class="cstat-no" title="statement not covered" > this.nextRequestAbortController = null;</span>
2453
+ <span class="cstat-no" title="statement not covered" > }</span>
2454
+ <span class="cstat-no" title="statement not covered" ></span>
2455
+ <span class="cstat-no" title="statement not covered" > if (!options.headers?.['x-client-request-id']) {</span>
2456
+ <span class="cstat-no" title="statement not covered" > options.headers = {</span>
2457
+ <span class="cstat-no" title="statement not covered" > ...options.headers,</span>
2458
+ <span class="cstat-no" title="statement not covered" > 'x-client-request-id': randomId(),</span>
2459
+ <span class="cstat-no" title="statement not covered" > };</span>
2460
+ <span class="cstat-no" title="statement not covered" > }</span>
2461
+ <span class="cstat-no" title="statement not covered" ></span>
2462
+ <span class="cstat-no" title="statement not covered" > return {</span>
2463
+ <span class="cstat-no" title="statement not covered" > params: {</span>
2464
+ <span class="cstat-no" title="statement not covered" > user_id: this.userID,</span>
2465
+ <span class="cstat-no" title="statement not covered" > connection_id: this._getConnectionID(),</span>
2466
+ <span class="cstat-no" title="statement not covered" > api_key: this.key,</span>
2467
+ <span class="cstat-no" title="statement not covered" > ...options.params,</span>
2468
+ <span class="cstat-no" title="statement not covered" > },</span>
2469
+ <span class="cstat-no" title="statement not covered" > headers: {</span>
2470
+ <span class="cstat-no" title="statement not covered" > ...authorization,</span>
2471
+ <span class="cstat-no" title="statement not covered" > 'stream-auth-type': this.getAuthType(),</span>
2472
+ <span class="cstat-no" title="statement not covered" > 'X-Stream-Client': this.getUserAgent(),</span>
2473
+ <span class="cstat-no" title="statement not covered" > ...options.headers,</span>
2474
+ <span class="cstat-no" title="statement not covered" > },</span>
2475
+ <span class="cstat-no" title="statement not covered" > ...(signal ? { signal } : {}),</span>
2476
+ <span class="cstat-no" title="statement not covered" > ...options.config,</span>
2477
+ <span class="cstat-no" title="statement not covered" > ...this.options.axiosRequestConfig,</span>
2478
+ <span class="cstat-no" title="statement not covered" > };</span>
2479
+ <span class="cstat-no" title="statement not covered" > }</span>
2480
+ &nbsp;
2481
+ <span class="fstat-no" title="function not covered" > _getToken() {</span>
2482
+ <span class="cstat-no" title="statement not covered" > if (!this.tokenManager || this.anonymous) return null;</span>
2483
+ <span class="cstat-no" title="statement not covered" ></span>
2484
+ <span class="cstat-no" title="statement not covered" > return this.tokenManager.getToken();</span>
2485
+ <span class="cstat-no" title="statement not covered" > }</span>
2486
+ &nbsp;
2487
+ /**
2488
+ * encode ws url payload
2489
+ * @private
2490
+ * @returns json string
2491
+ */
2492
+ _buildWSPayload = (<span class="fstat-no" title="function not covered" >client_request_id?: string) =&gt; {</span>
2493
+ <span class="cstat-no" title="statement not covered" > return JSON.stringify({</span>
2494
+ <span class="cstat-no" title="statement not covered" > user_id: this.userID,</span>
2495
+ <span class="cstat-no" title="statement not covered" > user_details: this._user,</span>
2496
+ <span class="cstat-no" title="statement not covered" > // device: this.options.device,</span>
2497
+ <span class="cstat-no" title="statement not covered" > client_request_id,</span>
2498
+ <span class="cstat-no" title="statement not covered" > });</span>
2499
+ <span class="cstat-no" title="statement not covered" > };</span>
2500
+ &nbsp;
2501
+ /**
2502
+ * creates an abort controller that will be used by the next HTTP Request.
2503
+ */
2504
+ <span class="fstat-no" title="function not covered" > createAbortControllerForNextRequest() {</span>
2505
+ <span class="cstat-no" title="statement not covered" > return (this.nextRequestAbortController = new AbortController());</span>
2506
+ <span class="cstat-no" title="statement not covered" > }</span>
2507
+ }
2508
+ &nbsp;</pre></td></tr></table></pre>
2509
+
2510
+ <div class='push'></div><!-- for sticky footer -->
2511
+ </div><!-- /wrapper -->
2512
+ <div class='footer quiet pad2 space-top1 center small'>
2513
+ Code coverage generated by
2514
+ <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
2515
+ at 2023-02-09T16:25:50.250Z
2516
+ </div>
2517
+ <script src="../../../prettify.js"></script>
2518
+ <script>
2519
+ window.onload = function () {
2520
+ prettyPrint();
2521
+ };
2522
+ </script>
2523
+ <script src="../../../sorter.js"></script>
2524
+ <script src="../../../block-navigation.js"></script>
2525
+ </body>
2526
+ </html>
2527
+