@studious-lms/server 1.2.45 → 1.2.47

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 (241) hide show
  1. package/.env.example +45 -0
  2. package/.env.test.example +37 -0
  3. package/README.md +34 -7
  4. package/coverage/base.css +224 -0
  5. package/coverage/block-navigation.js +87 -0
  6. package/coverage/clover.xml +12110 -0
  7. package/coverage/coverage-final.json +44 -0
  8. package/coverage/favicon.png +0 -0
  9. package/coverage/index.html +221 -0
  10. package/coverage/prettify.css +1 -0
  11. package/coverage/prettify.js +2 -0
  12. package/coverage/server/index.html +116 -0
  13. package/coverage/server/src/exportType.ts.html +109 -0
  14. package/coverage/server/src/index.html +161 -0
  15. package/coverage/server/src/index.ts.html +1702 -0
  16. package/coverage/server/src/instrument.ts.html +130 -0
  17. package/coverage/server/src/lib/config/env.ts.html +448 -0
  18. package/coverage/server/src/lib/config/index.html +116 -0
  19. package/coverage/server/src/lib/fileUpload.ts.html +1138 -0
  20. package/coverage/server/src/lib/googleCloudStorage.ts.html +334 -0
  21. package/coverage/server/src/lib/index.html +206 -0
  22. package/coverage/server/src/lib/jsonConversion.ts.html +2323 -0
  23. package/coverage/server/src/lib/jsonStyles.ts.html +193 -0
  24. package/coverage/server/src/lib/notificationHandler.ts.html +193 -0
  25. package/coverage/server/src/lib/pusher.ts.html +121 -0
  26. package/coverage/server/src/lib/thumbnailGenerator.ts.html +592 -0
  27. package/coverage/server/src/middleware/auth.ts.html +646 -0
  28. package/coverage/server/src/middleware/index.html +146 -0
  29. package/coverage/server/src/middleware/logging.ts.html +244 -0
  30. package/coverage/server/src/middleware/security.ts.html +271 -0
  31. package/coverage/server/src/routers/_app.ts.html +232 -0
  32. package/coverage/server/src/routers/agenda.ts.html +319 -0
  33. package/coverage/server/src/routers/announcement.ts.html +3481 -0
  34. package/coverage/server/src/routers/assignment.ts.html +7633 -0
  35. package/coverage/server/src/routers/attendance.ts.html +1030 -0
  36. package/coverage/server/src/routers/auth.ts.html +1081 -0
  37. package/coverage/server/src/routers/class.ts.html +3535 -0
  38. package/coverage/server/src/routers/comment.ts.html +991 -0
  39. package/coverage/server/src/routers/conversation.ts.html +982 -0
  40. package/coverage/server/src/routers/event.ts.html +1609 -0
  41. package/coverage/server/src/routers/file.ts.html +1144 -0
  42. package/coverage/server/src/routers/folder.ts.html +2797 -0
  43. package/coverage/server/src/routers/index.html +386 -0
  44. package/coverage/server/src/routers/labChat.ts.html +3073 -0
  45. package/coverage/server/src/routers/marketing.ts.html +340 -0
  46. package/coverage/server/src/routers/message.ts.html +1912 -0
  47. package/coverage/server/src/routers/notifications.ts.html +364 -0
  48. package/coverage/server/src/routers/section.ts.html +1120 -0
  49. package/coverage/server/src/routers/user.ts.html +862 -0
  50. package/coverage/server/src/routers/worksheet.ts.html +1729 -0
  51. package/coverage/server/src/trpc.ts.html +397 -0
  52. package/coverage/server/src/types/index.html +116 -0
  53. package/coverage/server/src/types/trpc.ts.html +127 -0
  54. package/coverage/server/src/utils/aiUser.ts.html +280 -0
  55. package/coverage/server/src/utils/email.ts.html +121 -0
  56. package/coverage/server/src/utils/generateInviteCode.ts.html +106 -0
  57. package/coverage/server/src/utils/index.html +206 -0
  58. package/coverage/server/src/utils/inference.ts.html +709 -0
  59. package/coverage/server/src/utils/logger.ts.html +664 -0
  60. package/coverage/server/src/utils/prismaErrorHandler.ts.html +907 -0
  61. package/coverage/server/src/utils/prismaWrapper.ts.html +355 -0
  62. package/coverage/server/vitest.config.ts.html +196 -0
  63. package/coverage/sort-arrow-sprite.png +0 -0
  64. package/coverage/sorter.js +210 -0
  65. package/dist/index.d.ts.map +1 -1
  66. package/dist/index.js +83 -52
  67. package/dist/index.js.map +1 -1
  68. package/dist/instrument.js +15 -8
  69. package/dist/instrument.js.map +1 -1
  70. package/dist/lib/config/env.d.ts +169 -0
  71. package/dist/lib/config/env.d.ts.map +1 -0
  72. package/dist/lib/config/env.js +115 -0
  73. package/dist/lib/config/env.js.map +1 -0
  74. package/dist/lib/fileUpload.d.ts.map +1 -1
  75. package/dist/lib/fileUpload.js +5 -4
  76. package/dist/lib/fileUpload.js.map +1 -1
  77. package/dist/lib/googleCloudStorage.d.ts.map +1 -1
  78. package/dist/lib/googleCloudStorage.js +7 -8
  79. package/dist/lib/googleCloudStorage.js.map +1 -1
  80. package/dist/lib/jsonConversion.d.ts.map +1 -1
  81. package/dist/lib/jsonConversion.js +14 -16
  82. package/dist/lib/jsonConversion.js.map +1 -1
  83. package/dist/lib/notificationHandler.d.ts +2 -2
  84. package/dist/lib/prisma.d.ts +2 -2
  85. package/dist/lib/prisma.d.ts.map +1 -1
  86. package/dist/lib/prisma.js +22 -3
  87. package/dist/lib/prisma.js.map +1 -1
  88. package/dist/lib/pusher.d.ts.map +1 -1
  89. package/dist/lib/pusher.js +8 -7
  90. package/dist/lib/pusher.js.map +1 -1
  91. package/dist/middleware/auth.d.ts.map +1 -1
  92. package/dist/middleware/auth.js +7 -5
  93. package/dist/middleware/auth.js.map +1 -1
  94. package/dist/middleware/security.d.ts +5 -0
  95. package/dist/middleware/security.d.ts.map +1 -0
  96. package/dist/middleware/security.js +77 -0
  97. package/dist/middleware/security.js.map +1 -0
  98. package/dist/routers/_app.d.ts +368 -108
  99. package/dist/routers/_app.d.ts.map +1 -1
  100. package/dist/routers/_app.js +4 -2
  101. package/dist/routers/_app.js.map +1 -1
  102. package/dist/routers/agenda.d.ts.map +1 -1
  103. package/dist/routers/agenda.js +12 -9
  104. package/dist/routers/agenda.js.map +1 -1
  105. package/dist/routers/announcement.d.ts +8 -0
  106. package/dist/routers/announcement.d.ts.map +1 -1
  107. package/dist/routers/announcement.js +6 -4
  108. package/dist/routers/announcement.js.map +1 -1
  109. package/dist/routers/assignment.d.ts +17 -4
  110. package/dist/routers/assignment.d.ts.map +1 -1
  111. package/dist/routers/assignment.js +51 -19
  112. package/dist/routers/assignment.js.map +1 -1
  113. package/dist/routers/attendance.d.ts +1 -0
  114. package/dist/routers/attendance.d.ts.map +1 -1
  115. package/dist/routers/attendance.js +4 -4
  116. package/dist/routers/attendance.js.map +1 -1
  117. package/dist/routers/auth.d.ts +20 -0
  118. package/dist/routers/auth.d.ts.map +1 -1
  119. package/dist/routers/auth.js +132 -15
  120. package/dist/routers/auth.js.map +1 -1
  121. package/dist/routers/class.d.ts +10 -0
  122. package/dist/routers/class.d.ts.map +1 -1
  123. package/dist/routers/class.js +49 -5
  124. package/dist/routers/class.js.map +1 -1
  125. package/dist/routers/comment.d.ts +2 -0
  126. package/dist/routers/comment.d.ts.map +1 -1
  127. package/dist/routers/conversation.d.ts +2 -0
  128. package/dist/routers/conversation.d.ts.map +1 -1
  129. package/dist/routers/conversation.js +46 -31
  130. package/dist/routers/conversation.js.map +1 -1
  131. package/dist/routers/file.d.ts.map +1 -1
  132. package/dist/routers/file.js +30 -7
  133. package/dist/routers/file.js.map +1 -1
  134. package/dist/routers/labChat.d.ts +2 -0
  135. package/dist/routers/labChat.d.ts.map +1 -1
  136. package/dist/routers/labChat.js +5 -322
  137. package/dist/routers/labChat.js.map +1 -1
  138. package/dist/routers/marketing.d.ts +1 -1
  139. package/dist/routers/message.d.ts +1 -0
  140. package/dist/routers/message.d.ts.map +1 -1
  141. package/dist/routers/message.js +3 -2
  142. package/dist/routers/message.js.map +1 -1
  143. package/dist/routers/newtonChat.d.ts +55 -0
  144. package/dist/routers/newtonChat.d.ts.map +1 -0
  145. package/dist/routers/newtonChat.js +262 -0
  146. package/dist/routers/newtonChat.js.map +1 -0
  147. package/dist/routers/notifications.d.ts +4 -4
  148. package/dist/routers/section.d.ts +19 -4
  149. package/dist/routers/section.d.ts.map +1 -1
  150. package/dist/routers/section.js +26 -8
  151. package/dist/routers/section.js.map +1 -1
  152. package/dist/routers/user.d.ts.map +1 -1
  153. package/dist/routers/user.js +5 -4
  154. package/dist/routers/user.js.map +1 -1
  155. package/dist/routers/worksheet.d.ts +44 -41
  156. package/dist/routers/worksheet.d.ts.map +1 -1
  157. package/dist/routers/worksheet.js +25 -34
  158. package/dist/routers/worksheet.js.map +1 -1
  159. package/dist/seedDatabase.d.ts +1 -1
  160. package/dist/seedDatabase.js +275 -284
  161. package/dist/seedDatabase.js.map +1 -1
  162. package/dist/server/pipelines/aiLabChat.d.ts +21 -0
  163. package/dist/server/pipelines/aiLabChat.d.ts.map +1 -0
  164. package/dist/server/pipelines/aiLabChat.js +456 -0
  165. package/dist/server/pipelines/aiLabChat.js.map +1 -0
  166. package/dist/server/pipelines/aiNewtonChat.d.ts +30 -0
  167. package/dist/server/pipelines/aiNewtonChat.d.ts.map +1 -0
  168. package/dist/server/pipelines/aiNewtonChat.js +280 -0
  169. package/dist/server/pipelines/aiNewtonChat.js.map +1 -0
  170. package/dist/server/pipelines/gradeWorksheet.d.ts +15 -0
  171. package/dist/server/pipelines/gradeWorksheet.d.ts.map +1 -0
  172. package/dist/server/pipelines/gradeWorksheet.js +139 -0
  173. package/dist/server/pipelines/gradeWorksheet.js.map +1 -0
  174. package/dist/trpc.d.ts.map +1 -1
  175. package/dist/trpc.js +2 -2
  176. package/dist/trpc.js.map +1 -1
  177. package/dist/utils/email.d.ts +9 -1
  178. package/dist/utils/email.d.ts.map +1 -1
  179. package/dist/utils/email.js +20 -5
  180. package/dist/utils/email.js.map +1 -1
  181. package/dist/utils/inference.d.ts +5 -0
  182. package/dist/utils/inference.d.ts.map +1 -1
  183. package/dist/utils/inference.js +71 -7
  184. package/dist/utils/inference.js.map +1 -1
  185. package/dist/utils/logger.d.ts.map +1 -1
  186. package/dist/utils/logger.js +3 -3
  187. package/dist/utils/logger.js.map +1 -1
  188. package/docker-compose.yml +14 -0
  189. package/package.json +13 -4
  190. package/prisma/schema.prisma +34 -5
  191. package/scripts/test-pre-push.ts +14 -0
  192. package/src/index.ts +98 -54
  193. package/src/instrument.ts +13 -6
  194. package/src/lib/config/env.ts +126 -0
  195. package/src/lib/fileUpload.ts +3 -2
  196. package/src/lib/googleCloudStorage.ts +6 -6
  197. package/src/lib/jsonConversion.ts +12 -14
  198. package/src/lib/prisma.ts +23 -2
  199. package/src/lib/pusher.ts +6 -5
  200. package/src/middleware/auth.ts +5 -3
  201. package/src/middleware/security.ts +80 -0
  202. package/src/routers/_app.ts +2 -0
  203. package/src/routers/agenda.ts +10 -7
  204. package/src/routers/announcement.ts +4 -2
  205. package/src/routers/assignment.ts +74 -41
  206. package/src/routers/attendance.ts +2 -2
  207. package/src/routers/auth.ts +143 -14
  208. package/src/routers/class.ts +52 -3
  209. package/src/routers/conversation.ts +49 -29
  210. package/src/routers/file.ts +29 -5
  211. package/src/routers/labChat.ts +3 -367
  212. package/src/routers/message.ts +1 -1
  213. package/src/routers/newtonChat.ts +299 -0
  214. package/src/routers/section.ts +26 -6
  215. package/src/routers/user.ts +3 -2
  216. package/src/routers/worksheet.ts +26 -38
  217. package/src/seedDatabase.ts +290 -283
  218. package/src/server/pipelines/aiLabChat.ts +507 -0
  219. package/src/server/pipelines/aiNewtonChat.ts +338 -0
  220. package/src/server/pipelines/gradeWorksheet.ts +151 -0
  221. package/src/trpc.ts +2 -0
  222. package/src/utils/email.ts +30 -3
  223. package/src/utils/inference.ts +85 -5
  224. package/src/utils/logger.ts +2 -1
  225. package/tests/announcement.test.ts +164 -0
  226. package/tests/assignment.test.ts +296 -0
  227. package/tests/attendance.test.ts +168 -0
  228. package/tests/auth.test.ts +33 -10
  229. package/tests/class.test.ts +34 -9
  230. package/tests/event.test.ts +228 -0
  231. package/tests/section.test.ts +216 -0
  232. package/tests/setup.ts +70 -16
  233. package/tests/user.test.ts +158 -0
  234. package/vitest.config.ts +26 -0
  235. package/API_SPECIFICATION.md +0 -1597
  236. package/BASE64_REMOVAL_SUMMARY.md +0 -164
  237. package/CHAT_API_SPEC.md +0 -579
  238. package/LAB_CHAT_API_SPEC.md +0 -518
  239. package/dist/routers/school.d.ts +0 -208
  240. package/dist/routers/school.d.ts.map +0 -1
  241. package/dist/routers/school.js +0 -483
@@ -0,0 +1,1609 @@
1
+
2
+ <!doctype html>
3
+ <html lang="en">
4
+
5
+ <head>
6
+ <title>Code coverage report for server/src/routers/event.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">server/src/routers</a> event.ts</h1>
23
+ <div class='clearfix'>
24
+
25
+ <div class='fl pad1y space-right2'>
26
+ <span class="strong">43.01% </span>
27
+ <span class="quiet">Statements</span>
28
+ <span class='fraction'>194/451</span>
29
+ </div>
30
+
31
+
32
+ <div class='fl pad1y space-right2'>
33
+ <span class="strong">61.9% </span>
34
+ <span class="quiet">Branches</span>
35
+ <span class='fraction'>13/21</span>
36
+ </div>
37
+
38
+
39
+ <div class='fl pad1y space-right2'>
40
+ <span class="strong">100% </span>
41
+ <span class="quiet">Functions</span>
42
+ <span class='fraction'>0/0</span>
43
+ </div>
44
+
45
+
46
+ <div class='fl pad1y space-right2'>
47
+ <span class="strong">43.01% </span>
48
+ <span class="quiet">Lines</span>
49
+ <span class='fraction'>194/451</span>
50
+ </div>
51
+
52
+
53
+ </div>
54
+ <p class="quiet">
55
+ Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
56
+ </p>
57
+ <template id="filterTemplate">
58
+ <div class="quiet">
59
+ Filter:
60
+ <input type="search" id="fileSearch">
61
+ </div>
62
+ </template>
63
+ </div>
64
+ <div class='status-line low'></div>
65
+ <pre><table class="coverage">
66
+ <tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
67
+ <a name='L2'></a><a href='#L2'>2</a>
68
+ <a name='L3'></a><a href='#L3'>3</a>
69
+ <a name='L4'></a><a href='#L4'>4</a>
70
+ <a name='L5'></a><a href='#L5'>5</a>
71
+ <a name='L6'></a><a href='#L6'>6</a>
72
+ <a name='L7'></a><a href='#L7'>7</a>
73
+ <a name='L8'></a><a href='#L8'>8</a>
74
+ <a name='L9'></a><a href='#L9'>9</a>
75
+ <a name='L10'></a><a href='#L10'>10</a>
76
+ <a name='L11'></a><a href='#L11'>11</a>
77
+ <a name='L12'></a><a href='#L12'>12</a>
78
+ <a name='L13'></a><a href='#L13'>13</a>
79
+ <a name='L14'></a><a href='#L14'>14</a>
80
+ <a name='L15'></a><a href='#L15'>15</a>
81
+ <a name='L16'></a><a href='#L16'>16</a>
82
+ <a name='L17'></a><a href='#L17'>17</a>
83
+ <a name='L18'></a><a href='#L18'>18</a>
84
+ <a name='L19'></a><a href='#L19'>19</a>
85
+ <a name='L20'></a><a href='#L20'>20</a>
86
+ <a name='L21'></a><a href='#L21'>21</a>
87
+ <a name='L22'></a><a href='#L22'>22</a>
88
+ <a name='L23'></a><a href='#L23'>23</a>
89
+ <a name='L24'></a><a href='#L24'>24</a>
90
+ <a name='L25'></a><a href='#L25'>25</a>
91
+ <a name='L26'></a><a href='#L26'>26</a>
92
+ <a name='L27'></a><a href='#L27'>27</a>
93
+ <a name='L28'></a><a href='#L28'>28</a>
94
+ <a name='L29'></a><a href='#L29'>29</a>
95
+ <a name='L30'></a><a href='#L30'>30</a>
96
+ <a name='L31'></a><a href='#L31'>31</a>
97
+ <a name='L32'></a><a href='#L32'>32</a>
98
+ <a name='L33'></a><a href='#L33'>33</a>
99
+ <a name='L34'></a><a href='#L34'>34</a>
100
+ <a name='L35'></a><a href='#L35'>35</a>
101
+ <a name='L36'></a><a href='#L36'>36</a>
102
+ <a name='L37'></a><a href='#L37'>37</a>
103
+ <a name='L38'></a><a href='#L38'>38</a>
104
+ <a name='L39'></a><a href='#L39'>39</a>
105
+ <a name='L40'></a><a href='#L40'>40</a>
106
+ <a name='L41'></a><a href='#L41'>41</a>
107
+ <a name='L42'></a><a href='#L42'>42</a>
108
+ <a name='L43'></a><a href='#L43'>43</a>
109
+ <a name='L44'></a><a href='#L44'>44</a>
110
+ <a name='L45'></a><a href='#L45'>45</a>
111
+ <a name='L46'></a><a href='#L46'>46</a>
112
+ <a name='L47'></a><a href='#L47'>47</a>
113
+ <a name='L48'></a><a href='#L48'>48</a>
114
+ <a name='L49'></a><a href='#L49'>49</a>
115
+ <a name='L50'></a><a href='#L50'>50</a>
116
+ <a name='L51'></a><a href='#L51'>51</a>
117
+ <a name='L52'></a><a href='#L52'>52</a>
118
+ <a name='L53'></a><a href='#L53'>53</a>
119
+ <a name='L54'></a><a href='#L54'>54</a>
120
+ <a name='L55'></a><a href='#L55'>55</a>
121
+ <a name='L56'></a><a href='#L56'>56</a>
122
+ <a name='L57'></a><a href='#L57'>57</a>
123
+ <a name='L58'></a><a href='#L58'>58</a>
124
+ <a name='L59'></a><a href='#L59'>59</a>
125
+ <a name='L60'></a><a href='#L60'>60</a>
126
+ <a name='L61'></a><a href='#L61'>61</a>
127
+ <a name='L62'></a><a href='#L62'>62</a>
128
+ <a name='L63'></a><a href='#L63'>63</a>
129
+ <a name='L64'></a><a href='#L64'>64</a>
130
+ <a name='L65'></a><a href='#L65'>65</a>
131
+ <a name='L66'></a><a href='#L66'>66</a>
132
+ <a name='L67'></a><a href='#L67'>67</a>
133
+ <a name='L68'></a><a href='#L68'>68</a>
134
+ <a name='L69'></a><a href='#L69'>69</a>
135
+ <a name='L70'></a><a href='#L70'>70</a>
136
+ <a name='L71'></a><a href='#L71'>71</a>
137
+ <a name='L72'></a><a href='#L72'>72</a>
138
+ <a name='L73'></a><a href='#L73'>73</a>
139
+ <a name='L74'></a><a href='#L74'>74</a>
140
+ <a name='L75'></a><a href='#L75'>75</a>
141
+ <a name='L76'></a><a href='#L76'>76</a>
142
+ <a name='L77'></a><a href='#L77'>77</a>
143
+ <a name='L78'></a><a href='#L78'>78</a>
144
+ <a name='L79'></a><a href='#L79'>79</a>
145
+ <a name='L80'></a><a href='#L80'>80</a>
146
+ <a name='L81'></a><a href='#L81'>81</a>
147
+ <a name='L82'></a><a href='#L82'>82</a>
148
+ <a name='L83'></a><a href='#L83'>83</a>
149
+ <a name='L84'></a><a href='#L84'>84</a>
150
+ <a name='L85'></a><a href='#L85'>85</a>
151
+ <a name='L86'></a><a href='#L86'>86</a>
152
+ <a name='L87'></a><a href='#L87'>87</a>
153
+ <a name='L88'></a><a href='#L88'>88</a>
154
+ <a name='L89'></a><a href='#L89'>89</a>
155
+ <a name='L90'></a><a href='#L90'>90</a>
156
+ <a name='L91'></a><a href='#L91'>91</a>
157
+ <a name='L92'></a><a href='#L92'>92</a>
158
+ <a name='L93'></a><a href='#L93'>93</a>
159
+ <a name='L94'></a><a href='#L94'>94</a>
160
+ <a name='L95'></a><a href='#L95'>95</a>
161
+ <a name='L96'></a><a href='#L96'>96</a>
162
+ <a name='L97'></a><a href='#L97'>97</a>
163
+ <a name='L98'></a><a href='#L98'>98</a>
164
+ <a name='L99'></a><a href='#L99'>99</a>
165
+ <a name='L100'></a><a href='#L100'>100</a>
166
+ <a name='L101'></a><a href='#L101'>101</a>
167
+ <a name='L102'></a><a href='#L102'>102</a>
168
+ <a name='L103'></a><a href='#L103'>103</a>
169
+ <a name='L104'></a><a href='#L104'>104</a>
170
+ <a name='L105'></a><a href='#L105'>105</a>
171
+ <a name='L106'></a><a href='#L106'>106</a>
172
+ <a name='L107'></a><a href='#L107'>107</a>
173
+ <a name='L108'></a><a href='#L108'>108</a>
174
+ <a name='L109'></a><a href='#L109'>109</a>
175
+ <a name='L110'></a><a href='#L110'>110</a>
176
+ <a name='L111'></a><a href='#L111'>111</a>
177
+ <a name='L112'></a><a href='#L112'>112</a>
178
+ <a name='L113'></a><a href='#L113'>113</a>
179
+ <a name='L114'></a><a href='#L114'>114</a>
180
+ <a name='L115'></a><a href='#L115'>115</a>
181
+ <a name='L116'></a><a href='#L116'>116</a>
182
+ <a name='L117'></a><a href='#L117'>117</a>
183
+ <a name='L118'></a><a href='#L118'>118</a>
184
+ <a name='L119'></a><a href='#L119'>119</a>
185
+ <a name='L120'></a><a href='#L120'>120</a>
186
+ <a name='L121'></a><a href='#L121'>121</a>
187
+ <a name='L122'></a><a href='#L122'>122</a>
188
+ <a name='L123'></a><a href='#L123'>123</a>
189
+ <a name='L124'></a><a href='#L124'>124</a>
190
+ <a name='L125'></a><a href='#L125'>125</a>
191
+ <a name='L126'></a><a href='#L126'>126</a>
192
+ <a name='L127'></a><a href='#L127'>127</a>
193
+ <a name='L128'></a><a href='#L128'>128</a>
194
+ <a name='L129'></a><a href='#L129'>129</a>
195
+ <a name='L130'></a><a href='#L130'>130</a>
196
+ <a name='L131'></a><a href='#L131'>131</a>
197
+ <a name='L132'></a><a href='#L132'>132</a>
198
+ <a name='L133'></a><a href='#L133'>133</a>
199
+ <a name='L134'></a><a href='#L134'>134</a>
200
+ <a name='L135'></a><a href='#L135'>135</a>
201
+ <a name='L136'></a><a href='#L136'>136</a>
202
+ <a name='L137'></a><a href='#L137'>137</a>
203
+ <a name='L138'></a><a href='#L138'>138</a>
204
+ <a name='L139'></a><a href='#L139'>139</a>
205
+ <a name='L140'></a><a href='#L140'>140</a>
206
+ <a name='L141'></a><a href='#L141'>141</a>
207
+ <a name='L142'></a><a href='#L142'>142</a>
208
+ <a name='L143'></a><a href='#L143'>143</a>
209
+ <a name='L144'></a><a href='#L144'>144</a>
210
+ <a name='L145'></a><a href='#L145'>145</a>
211
+ <a name='L146'></a><a href='#L146'>146</a>
212
+ <a name='L147'></a><a href='#L147'>147</a>
213
+ <a name='L148'></a><a href='#L148'>148</a>
214
+ <a name='L149'></a><a href='#L149'>149</a>
215
+ <a name='L150'></a><a href='#L150'>150</a>
216
+ <a name='L151'></a><a href='#L151'>151</a>
217
+ <a name='L152'></a><a href='#L152'>152</a>
218
+ <a name='L153'></a><a href='#L153'>153</a>
219
+ <a name='L154'></a><a href='#L154'>154</a>
220
+ <a name='L155'></a><a href='#L155'>155</a>
221
+ <a name='L156'></a><a href='#L156'>156</a>
222
+ <a name='L157'></a><a href='#L157'>157</a>
223
+ <a name='L158'></a><a href='#L158'>158</a>
224
+ <a name='L159'></a><a href='#L159'>159</a>
225
+ <a name='L160'></a><a href='#L160'>160</a>
226
+ <a name='L161'></a><a href='#L161'>161</a>
227
+ <a name='L162'></a><a href='#L162'>162</a>
228
+ <a name='L163'></a><a href='#L163'>163</a>
229
+ <a name='L164'></a><a href='#L164'>164</a>
230
+ <a name='L165'></a><a href='#L165'>165</a>
231
+ <a name='L166'></a><a href='#L166'>166</a>
232
+ <a name='L167'></a><a href='#L167'>167</a>
233
+ <a name='L168'></a><a href='#L168'>168</a>
234
+ <a name='L169'></a><a href='#L169'>169</a>
235
+ <a name='L170'></a><a href='#L170'>170</a>
236
+ <a name='L171'></a><a href='#L171'>171</a>
237
+ <a name='L172'></a><a href='#L172'>172</a>
238
+ <a name='L173'></a><a href='#L173'>173</a>
239
+ <a name='L174'></a><a href='#L174'>174</a>
240
+ <a name='L175'></a><a href='#L175'>175</a>
241
+ <a name='L176'></a><a href='#L176'>176</a>
242
+ <a name='L177'></a><a href='#L177'>177</a>
243
+ <a name='L178'></a><a href='#L178'>178</a>
244
+ <a name='L179'></a><a href='#L179'>179</a>
245
+ <a name='L180'></a><a href='#L180'>180</a>
246
+ <a name='L181'></a><a href='#L181'>181</a>
247
+ <a name='L182'></a><a href='#L182'>182</a>
248
+ <a name='L183'></a><a href='#L183'>183</a>
249
+ <a name='L184'></a><a href='#L184'>184</a>
250
+ <a name='L185'></a><a href='#L185'>185</a>
251
+ <a name='L186'></a><a href='#L186'>186</a>
252
+ <a name='L187'></a><a href='#L187'>187</a>
253
+ <a name='L188'></a><a href='#L188'>188</a>
254
+ <a name='L189'></a><a href='#L189'>189</a>
255
+ <a name='L190'></a><a href='#L190'>190</a>
256
+ <a name='L191'></a><a href='#L191'>191</a>
257
+ <a name='L192'></a><a href='#L192'>192</a>
258
+ <a name='L193'></a><a href='#L193'>193</a>
259
+ <a name='L194'></a><a href='#L194'>194</a>
260
+ <a name='L195'></a><a href='#L195'>195</a>
261
+ <a name='L196'></a><a href='#L196'>196</a>
262
+ <a name='L197'></a><a href='#L197'>197</a>
263
+ <a name='L198'></a><a href='#L198'>198</a>
264
+ <a name='L199'></a><a href='#L199'>199</a>
265
+ <a name='L200'></a><a href='#L200'>200</a>
266
+ <a name='L201'></a><a href='#L201'>201</a>
267
+ <a name='L202'></a><a href='#L202'>202</a>
268
+ <a name='L203'></a><a href='#L203'>203</a>
269
+ <a name='L204'></a><a href='#L204'>204</a>
270
+ <a name='L205'></a><a href='#L205'>205</a>
271
+ <a name='L206'></a><a href='#L206'>206</a>
272
+ <a name='L207'></a><a href='#L207'>207</a>
273
+ <a name='L208'></a><a href='#L208'>208</a>
274
+ <a name='L209'></a><a href='#L209'>209</a>
275
+ <a name='L210'></a><a href='#L210'>210</a>
276
+ <a name='L211'></a><a href='#L211'>211</a>
277
+ <a name='L212'></a><a href='#L212'>212</a>
278
+ <a name='L213'></a><a href='#L213'>213</a>
279
+ <a name='L214'></a><a href='#L214'>214</a>
280
+ <a name='L215'></a><a href='#L215'>215</a>
281
+ <a name='L216'></a><a href='#L216'>216</a>
282
+ <a name='L217'></a><a href='#L217'>217</a>
283
+ <a name='L218'></a><a href='#L218'>218</a>
284
+ <a name='L219'></a><a href='#L219'>219</a>
285
+ <a name='L220'></a><a href='#L220'>220</a>
286
+ <a name='L221'></a><a href='#L221'>221</a>
287
+ <a name='L222'></a><a href='#L222'>222</a>
288
+ <a name='L223'></a><a href='#L223'>223</a>
289
+ <a name='L224'></a><a href='#L224'>224</a>
290
+ <a name='L225'></a><a href='#L225'>225</a>
291
+ <a name='L226'></a><a href='#L226'>226</a>
292
+ <a name='L227'></a><a href='#L227'>227</a>
293
+ <a name='L228'></a><a href='#L228'>228</a>
294
+ <a name='L229'></a><a href='#L229'>229</a>
295
+ <a name='L230'></a><a href='#L230'>230</a>
296
+ <a name='L231'></a><a href='#L231'>231</a>
297
+ <a name='L232'></a><a href='#L232'>232</a>
298
+ <a name='L233'></a><a href='#L233'>233</a>
299
+ <a name='L234'></a><a href='#L234'>234</a>
300
+ <a name='L235'></a><a href='#L235'>235</a>
301
+ <a name='L236'></a><a href='#L236'>236</a>
302
+ <a name='L237'></a><a href='#L237'>237</a>
303
+ <a name='L238'></a><a href='#L238'>238</a>
304
+ <a name='L239'></a><a href='#L239'>239</a>
305
+ <a name='L240'></a><a href='#L240'>240</a>
306
+ <a name='L241'></a><a href='#L241'>241</a>
307
+ <a name='L242'></a><a href='#L242'>242</a>
308
+ <a name='L243'></a><a href='#L243'>243</a>
309
+ <a name='L244'></a><a href='#L244'>244</a>
310
+ <a name='L245'></a><a href='#L245'>245</a>
311
+ <a name='L246'></a><a href='#L246'>246</a>
312
+ <a name='L247'></a><a href='#L247'>247</a>
313
+ <a name='L248'></a><a href='#L248'>248</a>
314
+ <a name='L249'></a><a href='#L249'>249</a>
315
+ <a name='L250'></a><a href='#L250'>250</a>
316
+ <a name='L251'></a><a href='#L251'>251</a>
317
+ <a name='L252'></a><a href='#L252'>252</a>
318
+ <a name='L253'></a><a href='#L253'>253</a>
319
+ <a name='L254'></a><a href='#L254'>254</a>
320
+ <a name='L255'></a><a href='#L255'>255</a>
321
+ <a name='L256'></a><a href='#L256'>256</a>
322
+ <a name='L257'></a><a href='#L257'>257</a>
323
+ <a name='L258'></a><a href='#L258'>258</a>
324
+ <a name='L259'></a><a href='#L259'>259</a>
325
+ <a name='L260'></a><a href='#L260'>260</a>
326
+ <a name='L261'></a><a href='#L261'>261</a>
327
+ <a name='L262'></a><a href='#L262'>262</a>
328
+ <a name='L263'></a><a href='#L263'>263</a>
329
+ <a name='L264'></a><a href='#L264'>264</a>
330
+ <a name='L265'></a><a href='#L265'>265</a>
331
+ <a name='L266'></a><a href='#L266'>266</a>
332
+ <a name='L267'></a><a href='#L267'>267</a>
333
+ <a name='L268'></a><a href='#L268'>268</a>
334
+ <a name='L269'></a><a href='#L269'>269</a>
335
+ <a name='L270'></a><a href='#L270'>270</a>
336
+ <a name='L271'></a><a href='#L271'>271</a>
337
+ <a name='L272'></a><a href='#L272'>272</a>
338
+ <a name='L273'></a><a href='#L273'>273</a>
339
+ <a name='L274'></a><a href='#L274'>274</a>
340
+ <a name='L275'></a><a href='#L275'>275</a>
341
+ <a name='L276'></a><a href='#L276'>276</a>
342
+ <a name='L277'></a><a href='#L277'>277</a>
343
+ <a name='L278'></a><a href='#L278'>278</a>
344
+ <a name='L279'></a><a href='#L279'>279</a>
345
+ <a name='L280'></a><a href='#L280'>280</a>
346
+ <a name='L281'></a><a href='#L281'>281</a>
347
+ <a name='L282'></a><a href='#L282'>282</a>
348
+ <a name='L283'></a><a href='#L283'>283</a>
349
+ <a name='L284'></a><a href='#L284'>284</a>
350
+ <a name='L285'></a><a href='#L285'>285</a>
351
+ <a name='L286'></a><a href='#L286'>286</a>
352
+ <a name='L287'></a><a href='#L287'>287</a>
353
+ <a name='L288'></a><a href='#L288'>288</a>
354
+ <a name='L289'></a><a href='#L289'>289</a>
355
+ <a name='L290'></a><a href='#L290'>290</a>
356
+ <a name='L291'></a><a href='#L291'>291</a>
357
+ <a name='L292'></a><a href='#L292'>292</a>
358
+ <a name='L293'></a><a href='#L293'>293</a>
359
+ <a name='L294'></a><a href='#L294'>294</a>
360
+ <a name='L295'></a><a href='#L295'>295</a>
361
+ <a name='L296'></a><a href='#L296'>296</a>
362
+ <a name='L297'></a><a href='#L297'>297</a>
363
+ <a name='L298'></a><a href='#L298'>298</a>
364
+ <a name='L299'></a><a href='#L299'>299</a>
365
+ <a name='L300'></a><a href='#L300'>300</a>
366
+ <a name='L301'></a><a href='#L301'>301</a>
367
+ <a name='L302'></a><a href='#L302'>302</a>
368
+ <a name='L303'></a><a href='#L303'>303</a>
369
+ <a name='L304'></a><a href='#L304'>304</a>
370
+ <a name='L305'></a><a href='#L305'>305</a>
371
+ <a name='L306'></a><a href='#L306'>306</a>
372
+ <a name='L307'></a><a href='#L307'>307</a>
373
+ <a name='L308'></a><a href='#L308'>308</a>
374
+ <a name='L309'></a><a href='#L309'>309</a>
375
+ <a name='L310'></a><a href='#L310'>310</a>
376
+ <a name='L311'></a><a href='#L311'>311</a>
377
+ <a name='L312'></a><a href='#L312'>312</a>
378
+ <a name='L313'></a><a href='#L313'>313</a>
379
+ <a name='L314'></a><a href='#L314'>314</a>
380
+ <a name='L315'></a><a href='#L315'>315</a>
381
+ <a name='L316'></a><a href='#L316'>316</a>
382
+ <a name='L317'></a><a href='#L317'>317</a>
383
+ <a name='L318'></a><a href='#L318'>318</a>
384
+ <a name='L319'></a><a href='#L319'>319</a>
385
+ <a name='L320'></a><a href='#L320'>320</a>
386
+ <a name='L321'></a><a href='#L321'>321</a>
387
+ <a name='L322'></a><a href='#L322'>322</a>
388
+ <a name='L323'></a><a href='#L323'>323</a>
389
+ <a name='L324'></a><a href='#L324'>324</a>
390
+ <a name='L325'></a><a href='#L325'>325</a>
391
+ <a name='L326'></a><a href='#L326'>326</a>
392
+ <a name='L327'></a><a href='#L327'>327</a>
393
+ <a name='L328'></a><a href='#L328'>328</a>
394
+ <a name='L329'></a><a href='#L329'>329</a>
395
+ <a name='L330'></a><a href='#L330'>330</a>
396
+ <a name='L331'></a><a href='#L331'>331</a>
397
+ <a name='L332'></a><a href='#L332'>332</a>
398
+ <a name='L333'></a><a href='#L333'>333</a>
399
+ <a name='L334'></a><a href='#L334'>334</a>
400
+ <a name='L335'></a><a href='#L335'>335</a>
401
+ <a name='L336'></a><a href='#L336'>336</a>
402
+ <a name='L337'></a><a href='#L337'>337</a>
403
+ <a name='L338'></a><a href='#L338'>338</a>
404
+ <a name='L339'></a><a href='#L339'>339</a>
405
+ <a name='L340'></a><a href='#L340'>340</a>
406
+ <a name='L341'></a><a href='#L341'>341</a>
407
+ <a name='L342'></a><a href='#L342'>342</a>
408
+ <a name='L343'></a><a href='#L343'>343</a>
409
+ <a name='L344'></a><a href='#L344'>344</a>
410
+ <a name='L345'></a><a href='#L345'>345</a>
411
+ <a name='L346'></a><a href='#L346'>346</a>
412
+ <a name='L347'></a><a href='#L347'>347</a>
413
+ <a name='L348'></a><a href='#L348'>348</a>
414
+ <a name='L349'></a><a href='#L349'>349</a>
415
+ <a name='L350'></a><a href='#L350'>350</a>
416
+ <a name='L351'></a><a href='#L351'>351</a>
417
+ <a name='L352'></a><a href='#L352'>352</a>
418
+ <a name='L353'></a><a href='#L353'>353</a>
419
+ <a name='L354'></a><a href='#L354'>354</a>
420
+ <a name='L355'></a><a href='#L355'>355</a>
421
+ <a name='L356'></a><a href='#L356'>356</a>
422
+ <a name='L357'></a><a href='#L357'>357</a>
423
+ <a name='L358'></a><a href='#L358'>358</a>
424
+ <a name='L359'></a><a href='#L359'>359</a>
425
+ <a name='L360'></a><a href='#L360'>360</a>
426
+ <a name='L361'></a><a href='#L361'>361</a>
427
+ <a name='L362'></a><a href='#L362'>362</a>
428
+ <a name='L363'></a><a href='#L363'>363</a>
429
+ <a name='L364'></a><a href='#L364'>364</a>
430
+ <a name='L365'></a><a href='#L365'>365</a>
431
+ <a name='L366'></a><a href='#L366'>366</a>
432
+ <a name='L367'></a><a href='#L367'>367</a>
433
+ <a name='L368'></a><a href='#L368'>368</a>
434
+ <a name='L369'></a><a href='#L369'>369</a>
435
+ <a name='L370'></a><a href='#L370'>370</a>
436
+ <a name='L371'></a><a href='#L371'>371</a>
437
+ <a name='L372'></a><a href='#L372'>372</a>
438
+ <a name='L373'></a><a href='#L373'>373</a>
439
+ <a name='L374'></a><a href='#L374'>374</a>
440
+ <a name='L375'></a><a href='#L375'>375</a>
441
+ <a name='L376'></a><a href='#L376'>376</a>
442
+ <a name='L377'></a><a href='#L377'>377</a>
443
+ <a name='L378'></a><a href='#L378'>378</a>
444
+ <a name='L379'></a><a href='#L379'>379</a>
445
+ <a name='L380'></a><a href='#L380'>380</a>
446
+ <a name='L381'></a><a href='#L381'>381</a>
447
+ <a name='L382'></a><a href='#L382'>382</a>
448
+ <a name='L383'></a><a href='#L383'>383</a>
449
+ <a name='L384'></a><a href='#L384'>384</a>
450
+ <a name='L385'></a><a href='#L385'>385</a>
451
+ <a name='L386'></a><a href='#L386'>386</a>
452
+ <a name='L387'></a><a href='#L387'>387</a>
453
+ <a name='L388'></a><a href='#L388'>388</a>
454
+ <a name='L389'></a><a href='#L389'>389</a>
455
+ <a name='L390'></a><a href='#L390'>390</a>
456
+ <a name='L391'></a><a href='#L391'>391</a>
457
+ <a name='L392'></a><a href='#L392'>392</a>
458
+ <a name='L393'></a><a href='#L393'>393</a>
459
+ <a name='L394'></a><a href='#L394'>394</a>
460
+ <a name='L395'></a><a href='#L395'>395</a>
461
+ <a name='L396'></a><a href='#L396'>396</a>
462
+ <a name='L397'></a><a href='#L397'>397</a>
463
+ <a name='L398'></a><a href='#L398'>398</a>
464
+ <a name='L399'></a><a href='#L399'>399</a>
465
+ <a name='L400'></a><a href='#L400'>400</a>
466
+ <a name='L401'></a><a href='#L401'>401</a>
467
+ <a name='L402'></a><a href='#L402'>402</a>
468
+ <a name='L403'></a><a href='#L403'>403</a>
469
+ <a name='L404'></a><a href='#L404'>404</a>
470
+ <a name='L405'></a><a href='#L405'>405</a>
471
+ <a name='L406'></a><a href='#L406'>406</a>
472
+ <a name='L407'></a><a href='#L407'>407</a>
473
+ <a name='L408'></a><a href='#L408'>408</a>
474
+ <a name='L409'></a><a href='#L409'>409</a>
475
+ <a name='L410'></a><a href='#L410'>410</a>
476
+ <a name='L411'></a><a href='#L411'>411</a>
477
+ <a name='L412'></a><a href='#L412'>412</a>
478
+ <a name='L413'></a><a href='#L413'>413</a>
479
+ <a name='L414'></a><a href='#L414'>414</a>
480
+ <a name='L415'></a><a href='#L415'>415</a>
481
+ <a name='L416'></a><a href='#L416'>416</a>
482
+ <a name='L417'></a><a href='#L417'>417</a>
483
+ <a name='L418'></a><a href='#L418'>418</a>
484
+ <a name='L419'></a><a href='#L419'>419</a>
485
+ <a name='L420'></a><a href='#L420'>420</a>
486
+ <a name='L421'></a><a href='#L421'>421</a>
487
+ <a name='L422'></a><a href='#L422'>422</a>
488
+ <a name='L423'></a><a href='#L423'>423</a>
489
+ <a name='L424'></a><a href='#L424'>424</a>
490
+ <a name='L425'></a><a href='#L425'>425</a>
491
+ <a name='L426'></a><a href='#L426'>426</a>
492
+ <a name='L427'></a><a href='#L427'>427</a>
493
+ <a name='L428'></a><a href='#L428'>428</a>
494
+ <a name='L429'></a><a href='#L429'>429</a>
495
+ <a name='L430'></a><a href='#L430'>430</a>
496
+ <a name='L431'></a><a href='#L431'>431</a>
497
+ <a name='L432'></a><a href='#L432'>432</a>
498
+ <a name='L433'></a><a href='#L433'>433</a>
499
+ <a name='L434'></a><a href='#L434'>434</a>
500
+ <a name='L435'></a><a href='#L435'>435</a>
501
+ <a name='L436'></a><a href='#L436'>436</a>
502
+ <a name='L437'></a><a href='#L437'>437</a>
503
+ <a name='L438'></a><a href='#L438'>438</a>
504
+ <a name='L439'></a><a href='#L439'>439</a>
505
+ <a name='L440'></a><a href='#L440'>440</a>
506
+ <a name='L441'></a><a href='#L441'>441</a>
507
+ <a name='L442'></a><a href='#L442'>442</a>
508
+ <a name='L443'></a><a href='#L443'>443</a>
509
+ <a name='L444'></a><a href='#L444'>444</a>
510
+ <a name='L445'></a><a href='#L445'>445</a>
511
+ <a name='L446'></a><a href='#L446'>446</a>
512
+ <a name='L447'></a><a href='#L447'>447</a>
513
+ <a name='L448'></a><a href='#L448'>448</a>
514
+ <a name='L449'></a><a href='#L449'>449</a>
515
+ <a name='L450'></a><a href='#L450'>450</a>
516
+ <a name='L451'></a><a href='#L451'>451</a>
517
+ <a name='L452'></a><a href='#L452'>452</a>
518
+ <a name='L453'></a><a href='#L453'>453</a>
519
+ <a name='L454'></a><a href='#L454'>454</a>
520
+ <a name='L455'></a><a href='#L455'>455</a>
521
+ <a name='L456'></a><a href='#L456'>456</a>
522
+ <a name='L457'></a><a href='#L457'>457</a>
523
+ <a name='L458'></a><a href='#L458'>458</a>
524
+ <a name='L459'></a><a href='#L459'>459</a>
525
+ <a name='L460'></a><a href='#L460'>460</a>
526
+ <a name='L461'></a><a href='#L461'>461</a>
527
+ <a name='L462'></a><a href='#L462'>462</a>
528
+ <a name='L463'></a><a href='#L463'>463</a>
529
+ <a name='L464'></a><a href='#L464'>464</a>
530
+ <a name='L465'></a><a href='#L465'>465</a>
531
+ <a name='L466'></a><a href='#L466'>466</a>
532
+ <a name='L467'></a><a href='#L467'>467</a>
533
+ <a name='L468'></a><a href='#L468'>468</a>
534
+ <a name='L469'></a><a href='#L469'>469</a>
535
+ <a name='L470'></a><a href='#L470'>470</a>
536
+ <a name='L471'></a><a href='#L471'>471</a>
537
+ <a name='L472'></a><a href='#L472'>472</a>
538
+ <a name='L473'></a><a href='#L473'>473</a>
539
+ <a name='L474'></a><a href='#L474'>474</a>
540
+ <a name='L475'></a><a href='#L475'>475</a>
541
+ <a name='L476'></a><a href='#L476'>476</a>
542
+ <a name='L477'></a><a href='#L477'>477</a>
543
+ <a name='L478'></a><a href='#L478'>478</a>
544
+ <a name='L479'></a><a href='#L479'>479</a>
545
+ <a name='L480'></a><a href='#L480'>480</a>
546
+ <a name='L481'></a><a href='#L481'>481</a>
547
+ <a name='L482'></a><a href='#L482'>482</a>
548
+ <a name='L483'></a><a href='#L483'>483</a>
549
+ <a name='L484'></a><a href='#L484'>484</a>
550
+ <a name='L485'></a><a href='#L485'>485</a>
551
+ <a name='L486'></a><a href='#L486'>486</a>
552
+ <a name='L487'></a><a href='#L487'>487</a>
553
+ <a name='L488'></a><a href='#L488'>488</a>
554
+ <a name='L489'></a><a href='#L489'>489</a>
555
+ <a name='L490'></a><a href='#L490'>490</a>
556
+ <a name='L491'></a><a href='#L491'>491</a>
557
+ <a name='L492'></a><a href='#L492'>492</a>
558
+ <a name='L493'></a><a href='#L493'>493</a>
559
+ <a name='L494'></a><a href='#L494'>494</a>
560
+ <a name='L495'></a><a href='#L495'>495</a>
561
+ <a name='L496'></a><a href='#L496'>496</a>
562
+ <a name='L497'></a><a href='#L497'>497</a>
563
+ <a name='L498'></a><a href='#L498'>498</a>
564
+ <a name='L499'></a><a href='#L499'>499</a>
565
+ <a name='L500'></a><a href='#L500'>500</a>
566
+ <a name='L501'></a><a href='#L501'>501</a>
567
+ <a name='L502'></a><a href='#L502'>502</a>
568
+ <a name='L503'></a><a href='#L503'>503</a>
569
+ <a name='L504'></a><a href='#L504'>504</a>
570
+ <a name='L505'></a><a href='#L505'>505</a>
571
+ <a name='L506'></a><a href='#L506'>506</a>
572
+ <a name='L507'></a><a href='#L507'>507</a>
573
+ <a name='L508'></a><a href='#L508'>508</a>
574
+ <a name='L509'></a><a href='#L509'>509</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">1x</span>
575
+ <span class="cline-any cline-yes">1x</span>
576
+ <span class="cline-any cline-yes">1x</span>
577
+ <span class="cline-any cline-yes">1x</span>
578
+ <span class="cline-any cline-yes">1x</span>
579
+ <span class="cline-any cline-neutral">&nbsp;</span>
580
+ <span class="cline-any cline-yes">1x</span>
581
+ <span class="cline-any cline-yes">1x</span>
582
+ <span class="cline-any cline-yes">1x</span>
583
+ <span class="cline-any cline-yes">1x</span>
584
+ <span class="cline-any cline-yes">1x</span>
585
+ <span class="cline-any cline-yes">1x</span>
586
+ <span class="cline-any cline-yes">1x</span>
587
+ <span class="cline-any cline-yes">1x</span>
588
+ <span class="cline-any cline-yes">1x</span>
589
+ <span class="cline-any cline-neutral">&nbsp;</span>
590
+ <span class="cline-any cline-yes">1x</span>
591
+ <span class="cline-any cline-yes">1x</span>
592
+ <span class="cline-any cline-yes">1x</span>
593
+ <span class="cline-any cline-yes">1x</span>
594
+ <span class="cline-any cline-yes">1x</span>
595
+ <span class="cline-any cline-yes">1x</span>
596
+ <span class="cline-any cline-yes">4x</span>
597
+ <span class="cline-any cline-no">&nbsp;</span>
598
+ <span class="cline-any cline-no">&nbsp;</span>
599
+ <span class="cline-any cline-no">&nbsp;</span>
600
+ <span class="cline-any cline-no">&nbsp;</span>
601
+ <span class="cline-any cline-no">&nbsp;</span>
602
+ <span class="cline-any cline-neutral">&nbsp;</span>
603
+ <span class="cline-any cline-yes">4x</span>
604
+ <span class="cline-any cline-yes">4x</span>
605
+ <span class="cline-any cline-yes">4x</span>
606
+ <span class="cline-any cline-yes">4x</span>
607
+ <span class="cline-any cline-yes">4x</span>
608
+ <span class="cline-any cline-yes">4x</span>
609
+ <span class="cline-any cline-yes">4x</span>
610
+ <span class="cline-any cline-yes">4x</span>
611
+ <span class="cline-any cline-yes">4x</span>
612
+ <span class="cline-any cline-yes">4x</span>
613
+ <span class="cline-any cline-yes">4x</span>
614
+ <span class="cline-any cline-yes">4x</span>
615
+ <span class="cline-any cline-yes">4x</span>
616
+ <span class="cline-any cline-yes">4x</span>
617
+ <span class="cline-any cline-yes">4x</span>
618
+ <span class="cline-any cline-yes">4x</span>
619
+ <span class="cline-any cline-yes">4x</span>
620
+ <span class="cline-any cline-yes">4x</span>
621
+ <span class="cline-any cline-yes">4x</span>
622
+ <span class="cline-any cline-yes">4x</span>
623
+ <span class="cline-any cline-yes">4x</span>
624
+ <span class="cline-any cline-yes">4x</span>
625
+ <span class="cline-any cline-yes">4x</span>
626
+ <span class="cline-any cline-yes">4x</span>
627
+ <span class="cline-any cline-yes">4x</span>
628
+ <span class="cline-any cline-yes">4x</span>
629
+ <span class="cline-any cline-yes">4x</span>
630
+ <span class="cline-any cline-yes">4x</span>
631
+ <span class="cline-any cline-yes">4x</span>
632
+ <span class="cline-any cline-yes">4x</span>
633
+ <span class="cline-any cline-yes">4x</span>
634
+ <span class="cline-any cline-yes">4x</span>
635
+ <span class="cline-any cline-yes">4x</span>
636
+ <span class="cline-any cline-yes">4x</span>
637
+ <span class="cline-any cline-yes">4x</span>
638
+ <span class="cline-any cline-yes">4x</span>
639
+ <span class="cline-any cline-yes">4x</span>
640
+ <span class="cline-any cline-yes">4x</span>
641
+ <span class="cline-any cline-neutral">&nbsp;</span>
642
+ <span class="cline-any cline-yes">4x</span>
643
+ <span class="cline-any cline-yes">2x</span>
644
+ <span class="cline-any cline-yes">2x</span>
645
+ <span class="cline-any cline-yes">2x</span>
646
+ <span class="cline-any cline-yes">2x</span>
647
+ <span class="cline-any cline-yes">2x</span>
648
+ <span class="cline-any cline-neutral">&nbsp;</span>
649
+ <span class="cline-any cline-yes">4x</span>
650
+ <span class="cline-any cline-yes">1x</span>
651
+ <span class="cline-any cline-yes">1x</span>
652
+ <span class="cline-any cline-yes">1x</span>
653
+ <span class="cline-any cline-yes">1x</span>
654
+ <span class="cline-any cline-yes">1x</span>
655
+ <span class="cline-any cline-neutral">&nbsp;</span>
656
+ <span class="cline-any cline-yes">1x</span>
657
+ <span class="cline-any cline-yes">1x</span>
658
+ <span class="cline-any cline-neutral">&nbsp;</span>
659
+ <span class="cline-any cline-yes">1x</span>
660
+ <span class="cline-any cline-yes">1x</span>
661
+ <span class="cline-any cline-yes">1x</span>
662
+ <span class="cline-any cline-yes">24x</span>
663
+ <span class="cline-any cline-no">&nbsp;</span>
664
+ <span class="cline-any cline-no">&nbsp;</span>
665
+ <span class="cline-any cline-no">&nbsp;</span>
666
+ <span class="cline-any cline-no">&nbsp;</span>
667
+ <span class="cline-any cline-no">&nbsp;</span>
668
+ <span class="cline-any cline-neutral">&nbsp;</span>
669
+ <span class="cline-any cline-neutral">&nbsp;</span>
670
+ <span class="cline-any cline-yes">24x</span>
671
+ <span class="cline-any cline-yes">22x</span>
672
+ <span class="cline-any cline-yes">22x</span>
673
+ <span class="cline-any cline-yes">22x</span>
674
+ <span class="cline-any cline-yes">22x</span>
675
+ <span class="cline-any cline-yes">22x</span>
676
+ <span class="cline-any cline-yes">22x</span>
677
+ <span class="cline-any cline-yes">22x</span>
678
+ <span class="cline-any cline-yes">22x</span>
679
+ <span class="cline-any cline-yes">22x</span>
680
+ <span class="cline-any cline-yes">22x</span>
681
+ <span class="cline-any cline-neutral">&nbsp;</span>
682
+ <span class="cline-any cline-yes">22x</span>
683
+ <span class="cline-any cline-yes">1x</span>
684
+ <span class="cline-any cline-yes">1x</span>
685
+ <span class="cline-any cline-yes">1x</span>
686
+ <span class="cline-any cline-yes">1x</span>
687
+ <span class="cline-any cline-yes">1x</span>
688
+ <span class="cline-any cline-yes">22x</span>
689
+ <span class="cline-any cline-neutral">&nbsp;</span>
690
+ <span class="cline-any cline-yes">23x</span>
691
+ <span class="cline-any cline-yes">23x</span>
692
+ <span class="cline-any cline-yes">23x</span>
693
+ <span class="cline-any cline-yes">23x</span>
694
+ <span class="cline-any cline-yes">23x</span>
695
+ <span class="cline-any cline-yes">23x</span>
696
+ <span class="cline-any cline-yes">23x</span>
697
+ <span class="cline-any cline-yes">23x</span>
698
+ <span class="cline-any cline-yes">23x</span>
699
+ <span class="cline-any cline-yes">24x</span>
700
+ <span class="cline-any cline-yes">24x</span>
701
+ <span class="cline-any cline-yes">24x</span>
702
+ <span class="cline-any cline-yes">24x</span>
703
+ <span class="cline-any cline-yes">24x</span>
704
+ <span class="cline-any cline-yes">24x</span>
705
+ <span class="cline-any cline-yes">24x</span>
706
+ <span class="cline-any cline-yes">24x</span>
707
+ <span class="cline-any cline-yes">24x</span>
708
+ <span class="cline-any cline-yes">24x</span>
709
+ <span class="cline-any cline-yes">24x</span>
710
+ <span class="cline-any cline-yes">24x</span>
711
+ <span class="cline-any cline-yes">24x</span>
712
+ <span class="cline-any cline-yes">24x</span>
713
+ <span class="cline-any cline-yes">24x</span>
714
+ <span class="cline-any cline-yes">24x</span>
715
+ <span class="cline-any cline-yes">24x</span>
716
+ <span class="cline-any cline-yes">24x</span>
717
+ <span class="cline-any cline-yes">24x</span>
718
+ <span class="cline-any cline-yes">24x</span>
719
+ <span class="cline-any cline-neutral">&nbsp;</span>
720
+ <span class="cline-any cline-yes">23x</span>
721
+ <span class="cline-any cline-yes">1x</span>
722
+ <span class="cline-any cline-neutral">&nbsp;</span>
723
+ <span class="cline-any cline-yes">1x</span>
724
+ <span class="cline-any cline-yes">1x</span>
725
+ <span class="cline-any cline-yes">1x</span>
726
+ <span class="cline-any cline-yes">1x</span>
727
+ <span class="cline-any cline-yes">1x</span>
728
+ <span class="cline-any cline-yes">1x</span>
729
+ <span class="cline-any cline-yes">1x</span>
730
+ <span class="cline-any cline-no">&nbsp;</span>
731
+ <span class="cline-any cline-no">&nbsp;</span>
732
+ <span class="cline-any cline-no">&nbsp;</span>
733
+ <span class="cline-any cline-no">&nbsp;</span>
734
+ <span class="cline-any cline-no">&nbsp;</span>
735
+ <span class="cline-any cline-neutral">&nbsp;</span>
736
+ <span class="cline-any cline-yes">1x</span>
737
+ <span class="cline-any cline-yes">1x</span>
738
+ <span class="cline-any cline-yes">1x</span>
739
+ <span class="cline-any cline-neutral">&nbsp;</span>
740
+ <span class="cline-any cline-yes">1x</span>
741
+ <span class="cline-any cline-no">&nbsp;</span>
742
+ <span class="cline-any cline-no">&nbsp;</span>
743
+ <span class="cline-any cline-no">&nbsp;</span>
744
+ <span class="cline-any cline-no">&nbsp;</span>
745
+ <span class="cline-any cline-no">&nbsp;</span>
746
+ <span class="cline-any cline-neutral">&nbsp;</span>
747
+ <span class="cline-any cline-yes">1x</span>
748
+ <span class="cline-any cline-no">&nbsp;</span>
749
+ <span class="cline-any cline-no">&nbsp;</span>
750
+ <span class="cline-any cline-no">&nbsp;</span>
751
+ <span class="cline-any cline-no">&nbsp;</span>
752
+ <span class="cline-any cline-no">&nbsp;</span>
753
+ <span class="cline-any cline-neutral">&nbsp;</span>
754
+ <span class="cline-any cline-yes">1x</span>
755
+ <span class="cline-any cline-yes">1x</span>
756
+ <span class="cline-any cline-yes">1x</span>
757
+ <span class="cline-any cline-yes">1x</span>
758
+ <span class="cline-any cline-yes">1x</span>
759
+ <span class="cline-any cline-yes">1x</span>
760
+ <span class="cline-any cline-yes">1x</span>
761
+ <span class="cline-any cline-yes">1x</span>
762
+ <span class="cline-any cline-yes">1x</span>
763
+ <span class="cline-any cline-yes">1x</span>
764
+ <span class="cline-any cline-yes">1x</span>
765
+ <span class="cline-any cline-yes">1x</span>
766
+ <span class="cline-any cline-neutral">&nbsp;</span>
767
+ <span class="cline-any cline-yes">1x</span>
768
+ <span class="cline-any cline-yes">1x</span>
769
+ <span class="cline-any cline-neutral">&nbsp;</span>
770
+ <span class="cline-any cline-yes">1x</span>
771
+ <span class="cline-any cline-yes">1x</span>
772
+ <span class="cline-any cline-yes">1x</span>
773
+ <span class="cline-any cline-yes">1x</span>
774
+ <span class="cline-any cline-yes">1x</span>
775
+ <span class="cline-any cline-yes">2x</span>
776
+ <span class="cline-any cline-no">&nbsp;</span>
777
+ <span class="cline-any cline-no">&nbsp;</span>
778
+ <span class="cline-any cline-no">&nbsp;</span>
779
+ <span class="cline-any cline-no">&nbsp;</span>
780
+ <span class="cline-any cline-no">&nbsp;</span>
781
+ <span class="cline-any cline-neutral">&nbsp;</span>
782
+ <span class="cline-any cline-yes">2x</span>
783
+ <span class="cline-any cline-yes">2x</span>
784
+ <span class="cline-any cline-yes">2x</span>
785
+ <span class="cline-any cline-neutral">&nbsp;</span>
786
+ <span class="cline-any cline-yes">2x</span>
787
+ <span class="cline-any cline-no">&nbsp;</span>
788
+ <span class="cline-any cline-no">&nbsp;</span>
789
+ <span class="cline-any cline-no">&nbsp;</span>
790
+ <span class="cline-any cline-no">&nbsp;</span>
791
+ <span class="cline-any cline-no">&nbsp;</span>
792
+ <span class="cline-any cline-neutral">&nbsp;</span>
793
+ <span class="cline-any cline-yes">2x</span>
794
+ <span class="cline-any cline-yes">1x</span>
795
+ <span class="cline-any cline-yes">1x</span>
796
+ <span class="cline-any cline-yes">1x</span>
797
+ <span class="cline-any cline-yes">1x</span>
798
+ <span class="cline-any cline-yes">1x</span>
799
+ <span class="cline-any cline-neutral">&nbsp;</span>
800
+ <span class="cline-any cline-yes">1x</span>
801
+ <span class="cline-any cline-yes">1x</span>
802
+ <span class="cline-any cline-yes">1x</span>
803
+ <span class="cline-any cline-neutral">&nbsp;</span>
804
+ <span class="cline-any cline-yes">1x</span>
805
+ <span class="cline-any cline-yes">1x</span>
806
+ <span class="cline-any cline-neutral">&nbsp;</span>
807
+ <span class="cline-any cline-yes">1x</span>
808
+ <span class="cline-any cline-yes">1x</span>
809
+ <span class="cline-any cline-yes">1x</span>
810
+ <span class="cline-any cline-yes">1x</span>
811
+ <span class="cline-any cline-yes">1x</span>
812
+ <span class="cline-any cline-yes">1x</span>
813
+ <span class="cline-any cline-no">&nbsp;</span>
814
+ <span class="cline-any cline-no">&nbsp;</span>
815
+ <span class="cline-any cline-no">&nbsp;</span>
816
+ <span class="cline-any cline-no">&nbsp;</span>
817
+ <span class="cline-any cline-no">&nbsp;</span>
818
+ <span class="cline-any cline-no">&nbsp;</span>
819
+ <span class="cline-any cline-neutral">&nbsp;</span>
820
+ <span class="cline-any cline-neutral">&nbsp;</span>
821
+ <span class="cline-any cline-no">&nbsp;</span>
822
+ <span class="cline-any cline-no">&nbsp;</span>
823
+ <span class="cline-any cline-no">&nbsp;</span>
824
+ <span class="cline-any cline-no">&nbsp;</span>
825
+ <span class="cline-any cline-no">&nbsp;</span>
826
+ <span class="cline-any cline-no">&nbsp;</span>
827
+ <span class="cline-any cline-no">&nbsp;</span>
828
+ <span class="cline-any cline-no">&nbsp;</span>
829
+ <span class="cline-any cline-no">&nbsp;</span>
830
+ <span class="cline-any cline-no">&nbsp;</span>
831
+ <span class="cline-any cline-no">&nbsp;</span>
832
+ <span class="cline-any cline-no">&nbsp;</span>
833
+ <span class="cline-any cline-neutral">&nbsp;</span>
834
+ <span class="cline-any cline-no">&nbsp;</span>
835
+ <span class="cline-any cline-no">&nbsp;</span>
836
+ <span class="cline-any cline-no">&nbsp;</span>
837
+ <span class="cline-any cline-no">&nbsp;</span>
838
+ <span class="cline-any cline-no">&nbsp;</span>
839
+ <span class="cline-any cline-no">&nbsp;</span>
840
+ <span class="cline-any cline-neutral">&nbsp;</span>
841
+ <span class="cline-any cline-neutral">&nbsp;</span>
842
+ <span class="cline-any cline-no">&nbsp;</span>
843
+ <span class="cline-any cline-no">&nbsp;</span>
844
+ <span class="cline-any cline-no">&nbsp;</span>
845
+ <span class="cline-any cline-no">&nbsp;</span>
846
+ <span class="cline-any cline-no">&nbsp;</span>
847
+ <span class="cline-any cline-no">&nbsp;</span>
848
+ <span class="cline-any cline-no">&nbsp;</span>
849
+ <span class="cline-any cline-neutral">&nbsp;</span>
850
+ <span class="cline-any cline-neutral">&nbsp;</span>
851
+ <span class="cline-any cline-no">&nbsp;</span>
852
+ <span class="cline-any cline-no">&nbsp;</span>
853
+ <span class="cline-any cline-no">&nbsp;</span>
854
+ <span class="cline-any cline-no">&nbsp;</span>
855
+ <span class="cline-any cline-no">&nbsp;</span>
856
+ <span class="cline-any cline-no">&nbsp;</span>
857
+ <span class="cline-any cline-no">&nbsp;</span>
858
+ <span class="cline-any cline-no">&nbsp;</span>
859
+ <span class="cline-any cline-no">&nbsp;</span>
860
+ <span class="cline-any cline-no">&nbsp;</span>
861
+ <span class="cline-any cline-no">&nbsp;</span>
862
+ <span class="cline-any cline-no">&nbsp;</span>
863
+ <span class="cline-any cline-neutral">&nbsp;</span>
864
+ <span class="cline-any cline-no">&nbsp;</span>
865
+ <span class="cline-any cline-no">&nbsp;</span>
866
+ <span class="cline-any cline-no">&nbsp;</span>
867
+ <span class="cline-any cline-no">&nbsp;</span>
868
+ <span class="cline-any cline-no">&nbsp;</span>
869
+ <span class="cline-any cline-no">&nbsp;</span>
870
+ <span class="cline-any cline-neutral">&nbsp;</span>
871
+ <span class="cline-any cline-neutral">&nbsp;</span>
872
+ <span class="cline-any cline-no">&nbsp;</span>
873
+ <span class="cline-any cline-no">&nbsp;</span>
874
+ <span class="cline-any cline-no">&nbsp;</span>
875
+ <span class="cline-any cline-no">&nbsp;</span>
876
+ <span class="cline-any cline-no">&nbsp;</span>
877
+ <span class="cline-any cline-no">&nbsp;</span>
878
+ <span class="cline-any cline-neutral">&nbsp;</span>
879
+ <span class="cline-any cline-neutral">&nbsp;</span>
880
+ <span class="cline-any cline-no">&nbsp;</span>
881
+ <span class="cline-any cline-no">&nbsp;</span>
882
+ <span class="cline-any cline-no">&nbsp;</span>
883
+ <span class="cline-any cline-no">&nbsp;</span>
884
+ <span class="cline-any cline-no">&nbsp;</span>
885
+ <span class="cline-any cline-no">&nbsp;</span>
886
+ <span class="cline-any cline-neutral">&nbsp;</span>
887
+ <span class="cline-any cline-neutral">&nbsp;</span>
888
+ <span class="cline-any cline-no">&nbsp;</span>
889
+ <span class="cline-any cline-no">&nbsp;</span>
890
+ <span class="cline-any cline-no">&nbsp;</span>
891
+ <span class="cline-any cline-no">&nbsp;</span>
892
+ <span class="cline-any cline-no">&nbsp;</span>
893
+ <span class="cline-any cline-no">&nbsp;</span>
894
+ <span class="cline-any cline-no">&nbsp;</span>
895
+ <span class="cline-any cline-no">&nbsp;</span>
896
+ <span class="cline-any cline-no">&nbsp;</span>
897
+ <span class="cline-any cline-no">&nbsp;</span>
898
+ <span class="cline-any cline-no">&nbsp;</span>
899
+ <span class="cline-any cline-no">&nbsp;</span>
900
+ <span class="cline-any cline-no">&nbsp;</span>
901
+ <span class="cline-any cline-no">&nbsp;</span>
902
+ <span class="cline-any cline-no">&nbsp;</span>
903
+ <span class="cline-any cline-no">&nbsp;</span>
904
+ <span class="cline-any cline-no">&nbsp;</span>
905
+ <span class="cline-any cline-no">&nbsp;</span>
906
+ <span class="cline-any cline-no">&nbsp;</span>
907
+ <span class="cline-any cline-no">&nbsp;</span>
908
+ <span class="cline-any cline-no">&nbsp;</span>
909
+ <span class="cline-any cline-no">&nbsp;</span>
910
+ <span class="cline-any cline-no">&nbsp;</span>
911
+ <span class="cline-any cline-no">&nbsp;</span>
912
+ <span class="cline-any cline-no">&nbsp;</span>
913
+ <span class="cline-any cline-no">&nbsp;</span>
914
+ <span class="cline-any cline-no">&nbsp;</span>
915
+ <span class="cline-any cline-no">&nbsp;</span>
916
+ <span class="cline-any cline-no">&nbsp;</span>
917
+ <span class="cline-any cline-neutral">&nbsp;</span>
918
+ <span class="cline-any cline-no">&nbsp;</span>
919
+ <span class="cline-any cline-yes">1x</span>
920
+ <span class="cline-any cline-neutral">&nbsp;</span>
921
+ <span class="cline-any cline-yes">1x</span>
922
+ <span class="cline-any cline-yes">1x</span>
923
+ <span class="cline-any cline-yes">1x</span>
924
+ <span class="cline-any cline-yes">1x</span>
925
+ <span class="cline-any cline-yes">1x</span>
926
+ <span class="cline-any cline-yes">1x</span>
927
+ <span class="cline-any cline-no">&nbsp;</span>
928
+ <span class="cline-any cline-no">&nbsp;</span>
929
+ <span class="cline-any cline-no">&nbsp;</span>
930
+ <span class="cline-any cline-no">&nbsp;</span>
931
+ <span class="cline-any cline-no">&nbsp;</span>
932
+ <span class="cline-any cline-no">&nbsp;</span>
933
+ <span class="cline-any cline-neutral">&nbsp;</span>
934
+ <span class="cline-any cline-neutral">&nbsp;</span>
935
+ <span class="cline-any cline-no">&nbsp;</span>
936
+ <span class="cline-any cline-no">&nbsp;</span>
937
+ <span class="cline-any cline-no">&nbsp;</span>
938
+ <span class="cline-any cline-no">&nbsp;</span>
939
+ <span class="cline-any cline-no">&nbsp;</span>
940
+ <span class="cline-any cline-no">&nbsp;</span>
941
+ <span class="cline-any cline-no">&nbsp;</span>
942
+ <span class="cline-any cline-no">&nbsp;</span>
943
+ <span class="cline-any cline-no">&nbsp;</span>
944
+ <span class="cline-any cline-no">&nbsp;</span>
945
+ <span class="cline-any cline-no">&nbsp;</span>
946
+ <span class="cline-any cline-no">&nbsp;</span>
947
+ <span class="cline-any cline-neutral">&nbsp;</span>
948
+ <span class="cline-any cline-no">&nbsp;</span>
949
+ <span class="cline-any cline-no">&nbsp;</span>
950
+ <span class="cline-any cline-no">&nbsp;</span>
951
+ <span class="cline-any cline-no">&nbsp;</span>
952
+ <span class="cline-any cline-no">&nbsp;</span>
953
+ <span class="cline-any cline-no">&nbsp;</span>
954
+ <span class="cline-any cline-neutral">&nbsp;</span>
955
+ <span class="cline-any cline-neutral">&nbsp;</span>
956
+ <span class="cline-any cline-no">&nbsp;</span>
957
+ <span class="cline-any cline-no">&nbsp;</span>
958
+ <span class="cline-any cline-no">&nbsp;</span>
959
+ <span class="cline-any cline-no">&nbsp;</span>
960
+ <span class="cline-any cline-no">&nbsp;</span>
961
+ <span class="cline-any cline-no">&nbsp;</span>
962
+ <span class="cline-any cline-no">&nbsp;</span>
963
+ <span class="cline-any cline-neutral">&nbsp;</span>
964
+ <span class="cline-any cline-neutral">&nbsp;</span>
965
+ <span class="cline-any cline-no">&nbsp;</span>
966
+ <span class="cline-any cline-no">&nbsp;</span>
967
+ <span class="cline-any cline-no">&nbsp;</span>
968
+ <span class="cline-any cline-no">&nbsp;</span>
969
+ <span class="cline-any cline-no">&nbsp;</span>
970
+ <span class="cline-any cline-no">&nbsp;</span>
971
+ <span class="cline-any cline-no">&nbsp;</span>
972
+ <span class="cline-any cline-no">&nbsp;</span>
973
+ <span class="cline-any cline-no">&nbsp;</span>
974
+ <span class="cline-any cline-no">&nbsp;</span>
975
+ <span class="cline-any cline-no">&nbsp;</span>
976
+ <span class="cline-any cline-no">&nbsp;</span>
977
+ <span class="cline-any cline-no">&nbsp;</span>
978
+ <span class="cline-any cline-no">&nbsp;</span>
979
+ <span class="cline-any cline-no">&nbsp;</span>
980
+ <span class="cline-any cline-no">&nbsp;</span>
981
+ <span class="cline-any cline-no">&nbsp;</span>
982
+ <span class="cline-any cline-no">&nbsp;</span>
983
+ <span class="cline-any cline-no">&nbsp;</span>
984
+ <span class="cline-any cline-no">&nbsp;</span>
985
+ <span class="cline-any cline-no">&nbsp;</span>
986
+ <span class="cline-any cline-no">&nbsp;</span>
987
+ <span class="cline-any cline-no">&nbsp;</span>
988
+ <span class="cline-any cline-no">&nbsp;</span>
989
+ <span class="cline-any cline-no">&nbsp;</span>
990
+ <span class="cline-any cline-no">&nbsp;</span>
991
+ <span class="cline-any cline-no">&nbsp;</span>
992
+ <span class="cline-any cline-no">&nbsp;</span>
993
+ <span class="cline-any cline-no">&nbsp;</span>
994
+ <span class="cline-any cline-neutral">&nbsp;</span>
995
+ <span class="cline-any cline-no">&nbsp;</span>
996
+ <span class="cline-any cline-yes">1x</span>
997
+ <span class="cline-any cline-neutral">&nbsp;</span>
998
+ <span class="cline-any cline-yes">1x</span>
999
+ <span class="cline-any cline-yes">1x</span>
1000
+ <span class="cline-any cline-yes">1x</span>
1001
+ <span class="cline-any cline-yes">1x</span>
1002
+ <span class="cline-any cline-yes">1x</span>
1003
+ <span class="cline-any cline-no">&nbsp;</span>
1004
+ <span class="cline-any cline-no">&nbsp;</span>
1005
+ <span class="cline-any cline-no">&nbsp;</span>
1006
+ <span class="cline-any cline-no">&nbsp;</span>
1007
+ <span class="cline-any cline-no">&nbsp;</span>
1008
+ <span class="cline-any cline-no">&nbsp;</span>
1009
+ <span class="cline-any cline-neutral">&nbsp;</span>
1010
+ <span class="cline-any cline-neutral">&nbsp;</span>
1011
+ <span class="cline-any cline-no">&nbsp;</span>
1012
+ <span class="cline-any cline-no">&nbsp;</span>
1013
+ <span class="cline-any cline-no">&nbsp;</span>
1014
+ <span class="cline-any cline-no">&nbsp;</span>
1015
+ <span class="cline-any cline-no">&nbsp;</span>
1016
+ <span class="cline-any cline-no">&nbsp;</span>
1017
+ <span class="cline-any cline-no">&nbsp;</span>
1018
+ <span class="cline-any cline-no">&nbsp;</span>
1019
+ <span class="cline-any cline-no">&nbsp;</span>
1020
+ <span class="cline-any cline-no">&nbsp;</span>
1021
+ <span class="cline-any cline-no">&nbsp;</span>
1022
+ <span class="cline-any cline-no">&nbsp;</span>
1023
+ <span class="cline-any cline-neutral">&nbsp;</span>
1024
+ <span class="cline-any cline-no">&nbsp;</span>
1025
+ <span class="cline-any cline-no">&nbsp;</span>
1026
+ <span class="cline-any cline-no">&nbsp;</span>
1027
+ <span class="cline-any cline-no">&nbsp;</span>
1028
+ <span class="cline-any cline-no">&nbsp;</span>
1029
+ <span class="cline-any cline-no">&nbsp;</span>
1030
+ <span class="cline-any cline-neutral">&nbsp;</span>
1031
+ <span class="cline-any cline-neutral">&nbsp;</span>
1032
+ <span class="cline-any cline-no">&nbsp;</span>
1033
+ <span class="cline-any cline-no">&nbsp;</span>
1034
+ <span class="cline-any cline-no">&nbsp;</span>
1035
+ <span class="cline-any cline-no">&nbsp;</span>
1036
+ <span class="cline-any cline-no">&nbsp;</span>
1037
+ <span class="cline-any cline-no">&nbsp;</span>
1038
+ <span class="cline-any cline-no">&nbsp;</span>
1039
+ <span class="cline-any cline-neutral">&nbsp;</span>
1040
+ <span class="cline-any cline-neutral">&nbsp;</span>
1041
+ <span class="cline-any cline-no">&nbsp;</span>
1042
+ <span class="cline-any cline-no">&nbsp;</span>
1043
+ <span class="cline-any cline-no">&nbsp;</span>
1044
+ <span class="cline-any cline-no">&nbsp;</span>
1045
+ <span class="cline-any cline-no">&nbsp;</span>
1046
+ <span class="cline-any cline-no">&nbsp;</span>
1047
+ <span class="cline-any cline-no">&nbsp;</span>
1048
+ <span class="cline-any cline-no">&nbsp;</span>
1049
+ <span class="cline-any cline-no">&nbsp;</span>
1050
+ <span class="cline-any cline-no">&nbsp;</span>
1051
+ <span class="cline-any cline-no">&nbsp;</span>
1052
+ <span class="cline-any cline-no">&nbsp;</span>
1053
+ <span class="cline-any cline-no">&nbsp;</span>
1054
+ <span class="cline-any cline-no">&nbsp;</span>
1055
+ <span class="cline-any cline-no">&nbsp;</span>
1056
+ <span class="cline-any cline-no">&nbsp;</span>
1057
+ <span class="cline-any cline-no">&nbsp;</span>
1058
+ <span class="cline-any cline-no">&nbsp;</span>
1059
+ <span class="cline-any cline-no">&nbsp;</span>
1060
+ <span class="cline-any cline-no">&nbsp;</span>
1061
+ <span class="cline-any cline-no">&nbsp;</span>
1062
+ <span class="cline-any cline-no">&nbsp;</span>
1063
+ <span class="cline-any cline-no">&nbsp;</span>
1064
+ <span class="cline-any cline-no">&nbsp;</span>
1065
+ <span class="cline-any cline-no">&nbsp;</span>
1066
+ <span class="cline-any cline-no">&nbsp;</span>
1067
+ <span class="cline-any cline-no">&nbsp;</span>
1068
+ <span class="cline-any cline-no">&nbsp;</span>
1069
+ <span class="cline-any cline-no">&nbsp;</span>
1070
+ <span class="cline-any cline-no">&nbsp;</span>
1071
+ <span class="cline-any cline-no">&nbsp;</span>
1072
+ <span class="cline-any cline-no">&nbsp;</span>
1073
+ <span class="cline-any cline-no">&nbsp;</span>
1074
+ <span class="cline-any cline-no">&nbsp;</span>
1075
+ <span class="cline-any cline-no">&nbsp;</span>
1076
+ <span class="cline-any cline-no">&nbsp;</span>
1077
+ <span class="cline-any cline-no">&nbsp;</span>
1078
+ <span class="cline-any cline-no">&nbsp;</span>
1079
+ <span class="cline-any cline-neutral">&nbsp;</span>
1080
+ <span class="cline-any cline-no">&nbsp;</span>
1081
+ <span class="cline-any cline-yes">1x</span>
1082
+ <span class="cline-any cline-yes">1x</span></td><td class="text"><pre class="prettyprint lang-js">import { z } from "zod";
1083
+ import { createTRPCRouter, protectedProcedure } from "../trpc.js";
1084
+ import { TRPCError } from "@trpc/server";
1085
+ import { prisma } from "../lib/prisma.js";
1086
+ import { parseISO } from "date-fns";
1087
+ &nbsp;
1088
+ const eventSchema = z.object({
1089
+ name: z.string().optional(),
1090
+ location: z.string().optional(),
1091
+ remarks: z.string().optional(),
1092
+ startTime: z.string(),
1093
+ endTime: z.string(),
1094
+ classId: z.string().optional(),
1095
+ color: z.string().optional(),
1096
+ });
1097
+ &nbsp;
1098
+ export const eventRouter = createTRPCRouter({
1099
+ get: protectedProcedure
1100
+ .input(z.object({
1101
+ id: z.string(),
1102
+ }))
1103
+ .query(async ({ ctx, input }) =&gt; {
1104
+ if (!ctx.user) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1105
+ <span class="cstat-no" title="statement not covered" > throw new TRPCError({</span>
1106
+ <span class="cstat-no" title="statement not covered" > code: "UNAUTHORIZED",</span>
1107
+ <span class="cstat-no" title="statement not covered" > message: "You must be logged in to get an event",</span>
1108
+ <span class="cstat-no" title="statement not covered" > });</span>
1109
+ <span class="cstat-no" title="statement not covered" > }</span>
1110
+ &nbsp;
1111
+ const event = await prisma.event.findUnique({
1112
+ where: { id: input.id },
1113
+ include: {
1114
+ class: true,
1115
+ user: true,
1116
+ assignmentsAttached: {
1117
+ select: {
1118
+ id: true,
1119
+ title: true,
1120
+ instructions: true,
1121
+ dueDate: true,
1122
+ type: true,
1123
+ graded: true,
1124
+ maxGrade: true,
1125
+ weight: true,
1126
+ attachments: {
1127
+ select: {
1128
+ id: true,
1129
+ name: true,
1130
+ type: true,
1131
+ }
1132
+ },
1133
+ section: {
1134
+ select: {
1135
+ id: true,
1136
+ name: true
1137
+ }
1138
+ },
1139
+ teacher: {
1140
+ select: {
1141
+ id: true,
1142
+ username: true
1143
+ }
1144
+ }
1145
+ }
1146
+ }
1147
+ },
1148
+ });
1149
+ &nbsp;
1150
+ if (!event) {
1151
+ throw new TRPCError({
1152
+ code: "NOT_FOUND",
1153
+ message: "Event not found",
1154
+ });
1155
+ }
1156
+ &nbsp;
1157
+ if (event.userId !== ctx.user.id) {
1158
+ throw new TRPCError({
1159
+ code: "UNAUTHORIZED",
1160
+ message: "You are not authorized to view this event",
1161
+ });
1162
+ }
1163
+ &nbsp;
1164
+ return { event };
1165
+ }),
1166
+ &nbsp;
1167
+ create: protectedProcedure
1168
+ .input(eventSchema)
1169
+ .mutation(async ({ ctx, input }) =&gt; {
1170
+ if (!ctx.user) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1171
+ <span class="cstat-no" title="statement not covered" > throw new TRPCError({</span>
1172
+ <span class="cstat-no" title="statement not covered" > code: "UNAUTHORIZED",</span>
1173
+ <span class="cstat-no" title="statement not covered" > message: "You must be logged in to create an event",</span>
1174
+ <span class="cstat-no" title="statement not covered" > });</span>
1175
+ <span class="cstat-no" title="statement not covered" > }</span>
1176
+ &nbsp;
1177
+ // If classId is provided, check if user is a teacher of the class
1178
+ if (input.classId) {
1179
+ const classData = await prisma.class.findUnique({
1180
+ where: {
1181
+ id: input.classId,
1182
+ teachers: {
1183
+ some: {
1184
+ id: ctx.user.id,
1185
+ },
1186
+ },
1187
+ },
1188
+ });
1189
+ &nbsp;
1190
+ if (!classData) {
1191
+ throw new TRPCError({
1192
+ code: "UNAUTHORIZED",
1193
+ message: "You are not authorized to create events for this class",
1194
+ });
1195
+ }
1196
+ }
1197
+ &nbsp;
1198
+ const event = await prisma.event.create({
1199
+ data: {
1200
+ name: input.name,
1201
+ location: input.location,
1202
+ remarks: input.remarks,
1203
+ startTime: parseISO(input.startTime),
1204
+ endTime: parseISO(input.endTime),
1205
+ userId: ctx.user.id,
1206
+ color: input.color,
1207
+ ...(input.classId ? { classId: input.classId } : {}),
1208
+ },
1209
+ select: {
1210
+ id: true,
1211
+ name: true,
1212
+ location: true,
1213
+ remarks: true,
1214
+ startTime: true,
1215
+ endTime: true,
1216
+ color: true,
1217
+ classId: true,
1218
+ userId: true,
1219
+ class: {
1220
+ select: {
1221
+ id: true,
1222
+ name: true
1223
+ }
1224
+ },
1225
+ }
1226
+ });
1227
+ &nbsp;
1228
+ return { event };
1229
+ }),
1230
+ &nbsp;
1231
+ update: protectedProcedure
1232
+ .input(z.object({
1233
+ id: z.string(),
1234
+ data: eventSchema,
1235
+ }))
1236
+ .mutation(async ({ ctx, input }) =&gt; {
1237
+ if (!ctx.user) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1238
+ <span class="cstat-no" title="statement not covered" > throw new TRPCError({</span>
1239
+ <span class="cstat-no" title="statement not covered" > code: "UNAUTHORIZED",</span>
1240
+ <span class="cstat-no" title="statement not covered" > message: "You must be logged in to update an event",</span>
1241
+ <span class="cstat-no" title="statement not covered" > });</span>
1242
+ <span class="cstat-no" title="statement not covered" > }</span>
1243
+ &nbsp;
1244
+ const event = await prisma.event.findUnique({
1245
+ where: { id: input.id },
1246
+ });
1247
+ &nbsp;
1248
+ if (!event) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1249
+ <span class="cstat-no" title="statement not covered" > throw new TRPCError({</span>
1250
+ <span class="cstat-no" title="statement not covered" > code: "NOT_FOUND",</span>
1251
+ <span class="cstat-no" title="statement not covered" > message: "Event not found",</span>
1252
+ <span class="cstat-no" title="statement not covered" > });</span>
1253
+ <span class="cstat-no" title="statement not covered" > }</span>
1254
+ &nbsp;
1255
+ if (event.userId !== ctx.user.id) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1256
+ <span class="cstat-no" title="statement not covered" > throw new TRPCError({</span>
1257
+ <span class="cstat-no" title="statement not covered" > code: "UNAUTHORIZED",</span>
1258
+ <span class="cstat-no" title="statement not covered" > message: "You are not authorized to update this event",</span>
1259
+ <span class="cstat-no" title="statement not covered" > });</span>
1260
+ <span class="cstat-no" title="statement not covered" > }</span>
1261
+ &nbsp;
1262
+ const updatedEvent = await prisma.event.update({
1263
+ where: { id: input.id },
1264
+ data: {
1265
+ name: input.data.name,
1266
+ location: input.data.location,
1267
+ remarks: input.data.remarks,
1268
+ startTime: parseISO(input.data.startTime),
1269
+ endTime: parseISO(input.data.endTime),
1270
+ color: input.data.color,
1271
+ ...(input.data.<span class="branch-0 cbranch-no" title="branch not covered" >classId ? { classId: input.data.classId } : {</span>}),
1272
+ },
1273
+ });
1274
+ &nbsp;
1275
+ return { event: updatedEvent };
1276
+ }),
1277
+ &nbsp;
1278
+ delete: protectedProcedure
1279
+ .input(z.object({
1280
+ id: z.string(),
1281
+ }))
1282
+ .mutation(async ({ ctx, input }) =&gt; {
1283
+ if (!ctx.user) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1284
+ <span class="cstat-no" title="statement not covered" > throw new TRPCError({</span>
1285
+ <span class="cstat-no" title="statement not covered" > code: "UNAUTHORIZED",</span>
1286
+ <span class="cstat-no" title="statement not covered" > message: "You must be logged in to delete an event",</span>
1287
+ <span class="cstat-no" title="statement not covered" > });</span>
1288
+ <span class="cstat-no" title="statement not covered" > }</span>
1289
+ &nbsp;
1290
+ const event = await prisma.event.findUnique({
1291
+ where: { id: input.id },
1292
+ });
1293
+ &nbsp;
1294
+ if (!event) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1295
+ <span class="cstat-no" title="statement not covered" > throw new TRPCError({</span>
1296
+ <span class="cstat-no" title="statement not covered" > code: "NOT_FOUND",</span>
1297
+ <span class="cstat-no" title="statement not covered" > message: "Event not found",</span>
1298
+ <span class="cstat-no" title="statement not covered" > });</span>
1299
+ <span class="cstat-no" title="statement not covered" > }</span>
1300
+ &nbsp;
1301
+ if (event.userId !== ctx.user.id) {
1302
+ throw new TRPCError({
1303
+ code: "UNAUTHORIZED",
1304
+ message: "You are not authorized to delete this event",
1305
+ });
1306
+ }
1307
+ &nbsp;
1308
+ await prisma.event.delete({
1309
+ where: { id: input.id },
1310
+ });
1311
+ &nbsp;
1312
+ return { success: true };
1313
+ }),
1314
+ &nbsp;
1315
+ attachAssignment: protectedProcedure
1316
+ .input(z.object({
1317
+ eventId: z.string(),
1318
+ assignmentId: z.string(),
1319
+ }))
1320
+ .mutation(async ({ ctx, input }) =&gt; {
1321
+ <span class="cstat-no" title="statement not covered" > if (!ctx.user || !ctx.user.id) {</span>
1322
+ <span class="cstat-no" title="statement not covered" > throw new TRPCError({</span>
1323
+ <span class="cstat-no" title="statement not covered" > code: "UNAUTHORIZED",</span>
1324
+ <span class="cstat-no" title="statement not covered" > message: "You must be logged in to attach an assignment",</span>
1325
+ <span class="cstat-no" title="statement not covered" > });</span>
1326
+ <span class="cstat-no" title="statement not covered" > }</span>
1327
+ &nbsp;
1328
+ // Check if user owns the event
1329
+ <span class="cstat-no" title="statement not covered" > const event = await prisma.event.findUnique({</span>
1330
+ <span class="cstat-no" title="statement not covered" > where: { id: input.eventId },</span>
1331
+ <span class="cstat-no" title="statement not covered" > include: {</span>
1332
+ <span class="cstat-no" title="statement not covered" > class: {</span>
1333
+ <span class="cstat-no" title="statement not covered" > include: {</span>
1334
+ <span class="cstat-no" title="statement not covered" > teachers: {</span>
1335
+ <span class="cstat-no" title="statement not covered" > select: { id: true }</span>
1336
+ <span class="cstat-no" title="statement not covered" > }</span>
1337
+ <span class="cstat-no" title="statement not covered" > }</span>
1338
+ <span class="cstat-no" title="statement not covered" > }</span>
1339
+ <span class="cstat-no" title="statement not covered" > }</span>
1340
+ <span class="cstat-no" title="statement not covered" > });</span>
1341
+ &nbsp;
1342
+ <span class="cstat-no" title="statement not covered" > if (!event) {</span>
1343
+ <span class="cstat-no" title="statement not covered" > throw new TRPCError({</span>
1344
+ <span class="cstat-no" title="statement not covered" > code: "NOT_FOUND",</span>
1345
+ <span class="cstat-no" title="statement not covered" > message: "Event not found",</span>
1346
+ <span class="cstat-no" title="statement not covered" > });</span>
1347
+ <span class="cstat-no" title="statement not covered" > }</span>
1348
+ &nbsp;
1349
+ // Check if user is the event owner or a teacher of the class
1350
+ <span class="cstat-no" title="statement not covered" > if (event.userId !== ctx.user.id &amp;&amp; </span>
1351
+ <span class="cstat-no" title="statement not covered" > !event.class?.teachers.some(teacher =&gt; teacher.id === ctx.user!.id)) {</span>
1352
+ <span class="cstat-no" title="statement not covered" > throw new TRPCError({</span>
1353
+ <span class="cstat-no" title="statement not covered" > code: "UNAUTHORIZED",</span>
1354
+ <span class="cstat-no" title="statement not covered" > message: "You are not authorized to modify this event",</span>
1355
+ <span class="cstat-no" title="statement not covered" > });</span>
1356
+ <span class="cstat-no" title="statement not covered" > }</span>
1357
+ &nbsp;
1358
+ // Check if assignment exists and belongs to the same class
1359
+ <span class="cstat-no" title="statement not covered" > const assignment = await prisma.assignment.findUnique({</span>
1360
+ <span class="cstat-no" title="statement not covered" > where: { id: input.assignmentId },</span>
1361
+ <span class="cstat-no" title="statement not covered" > include: {</span>
1362
+ <span class="cstat-no" title="statement not covered" > class: {</span>
1363
+ <span class="cstat-no" title="statement not covered" > include: {</span>
1364
+ <span class="cstat-no" title="statement not covered" > teachers: {</span>
1365
+ <span class="cstat-no" title="statement not covered" > select: { id: true }</span>
1366
+ <span class="cstat-no" title="statement not covered" > }</span>
1367
+ <span class="cstat-no" title="statement not covered" > }</span>
1368
+ <span class="cstat-no" title="statement not covered" > }</span>
1369
+ <span class="cstat-no" title="statement not covered" > }</span>
1370
+ <span class="cstat-no" title="statement not covered" > });</span>
1371
+ &nbsp;
1372
+ <span class="cstat-no" title="statement not covered" > if (!assignment) {</span>
1373
+ <span class="cstat-no" title="statement not covered" > throw new TRPCError({</span>
1374
+ <span class="cstat-no" title="statement not covered" > code: "NOT_FOUND",</span>
1375
+ <span class="cstat-no" title="statement not covered" > message: "Assignment not found",</span>
1376
+ <span class="cstat-no" title="statement not covered" > });</span>
1377
+ <span class="cstat-no" title="statement not covered" > }</span>
1378
+ &nbsp;
1379
+ // Check if user is a teacher of the assignment's class
1380
+ <span class="cstat-no" title="statement not covered" > if (!assignment.class.teachers.some(teacher =&gt; teacher.id === ctx.user!.id)) {</span>
1381
+ <span class="cstat-no" title="statement not covered" > throw new TRPCError({</span>
1382
+ <span class="cstat-no" title="statement not covered" > code: "UNAUTHORIZED",</span>
1383
+ <span class="cstat-no" title="statement not covered" > message: "You are not authorized to modify this assignment",</span>
1384
+ <span class="cstat-no" title="statement not covered" > });</span>
1385
+ <span class="cstat-no" title="statement not covered" > }</span>
1386
+ &nbsp;
1387
+ // Check if event and assignment belong to the same class
1388
+ <span class="cstat-no" title="statement not covered" > if (event.classId !== assignment.classId) {</span>
1389
+ <span class="cstat-no" title="statement not covered" > throw new TRPCError({</span>
1390
+ <span class="cstat-no" title="statement not covered" > code: "BAD_REQUEST",</span>
1391
+ <span class="cstat-no" title="statement not covered" > message: "Event and assignment must belong to the same class",</span>
1392
+ <span class="cstat-no" title="statement not covered" > });</span>
1393
+ <span class="cstat-no" title="statement not covered" > }</span>
1394
+ &nbsp;
1395
+ // Attach assignment to event
1396
+ <span class="cstat-no" title="statement not covered" > const updatedAssignment = await prisma.assignment.update({</span>
1397
+ <span class="cstat-no" title="statement not covered" > where: { id: input.assignmentId },</span>
1398
+ <span class="cstat-no" title="statement not covered" > data: {</span>
1399
+ <span class="cstat-no" title="statement not covered" > eventAttached: {</span>
1400
+ <span class="cstat-no" title="statement not covered" > connect: { id: input.eventId }</span>
1401
+ <span class="cstat-no" title="statement not covered" > }</span>
1402
+ <span class="cstat-no" title="statement not covered" > },</span>
1403
+ <span class="cstat-no" title="statement not covered" > include: {</span>
1404
+ <span class="cstat-no" title="statement not covered" > attachments: {</span>
1405
+ <span class="cstat-no" title="statement not covered" > select: {</span>
1406
+ <span class="cstat-no" title="statement not covered" > id: true,</span>
1407
+ <span class="cstat-no" title="statement not covered" > name: true,</span>
1408
+ <span class="cstat-no" title="statement not covered" > type: true,</span>
1409
+ <span class="cstat-no" title="statement not covered" > }</span>
1410
+ <span class="cstat-no" title="statement not covered" > },</span>
1411
+ <span class="cstat-no" title="statement not covered" > section: {</span>
1412
+ <span class="cstat-no" title="statement not covered" > select: {</span>
1413
+ <span class="cstat-no" title="statement not covered" > id: true,</span>
1414
+ <span class="cstat-no" title="statement not covered" > name: true</span>
1415
+ <span class="cstat-no" title="statement not covered" > }</span>
1416
+ <span class="cstat-no" title="statement not covered" > },</span>
1417
+ <span class="cstat-no" title="statement not covered" > teacher: {</span>
1418
+ <span class="cstat-no" title="statement not covered" > select: {</span>
1419
+ <span class="cstat-no" title="statement not covered" > id: true,</span>
1420
+ <span class="cstat-no" title="statement not covered" > username: true</span>
1421
+ <span class="cstat-no" title="statement not covered" > }</span>
1422
+ <span class="cstat-no" title="statement not covered" > }</span>
1423
+ <span class="cstat-no" title="statement not covered" > }</span>
1424
+ <span class="cstat-no" title="statement not covered" > });</span>
1425
+ &nbsp;
1426
+ <span class="cstat-no" title="statement not covered" > return { assignment: updatedAssignment };</span>
1427
+ }),
1428
+ &nbsp;
1429
+ detachAssignment: protectedProcedure
1430
+ .input(z.object({
1431
+ eventId: z.string(),
1432
+ assignmentId: z.string(),
1433
+ }))
1434
+ .mutation(async ({ ctx, input }) =&gt; {
1435
+ <span class="cstat-no" title="statement not covered" > if (!ctx.user) {</span>
1436
+ <span class="cstat-no" title="statement not covered" > throw new TRPCError({</span>
1437
+ <span class="cstat-no" title="statement not covered" > code: "UNAUTHORIZED",</span>
1438
+ <span class="cstat-no" title="statement not covered" > message: "You must be logged in to detach an assignment",</span>
1439
+ <span class="cstat-no" title="statement not covered" > });</span>
1440
+ <span class="cstat-no" title="statement not covered" > }</span>
1441
+ &nbsp;
1442
+ // Check if user owns the event
1443
+ <span class="cstat-no" title="statement not covered" > const event = await prisma.event.findUnique({</span>
1444
+ <span class="cstat-no" title="statement not covered" > where: { id: input.eventId },</span>
1445
+ <span class="cstat-no" title="statement not covered" > include: {</span>
1446
+ <span class="cstat-no" title="statement not covered" > class: {</span>
1447
+ <span class="cstat-no" title="statement not covered" > include: {</span>
1448
+ <span class="cstat-no" title="statement not covered" > teachers: {</span>
1449
+ <span class="cstat-no" title="statement not covered" > select: { id: true }</span>
1450
+ <span class="cstat-no" title="statement not covered" > }</span>
1451
+ <span class="cstat-no" title="statement not covered" > }</span>
1452
+ <span class="cstat-no" title="statement not covered" > }</span>
1453
+ <span class="cstat-no" title="statement not covered" > }</span>
1454
+ <span class="cstat-no" title="statement not covered" > });</span>
1455
+ &nbsp;
1456
+ <span class="cstat-no" title="statement not covered" > if (!event) {</span>
1457
+ <span class="cstat-no" title="statement not covered" > throw new TRPCError({</span>
1458
+ <span class="cstat-no" title="statement not covered" > code: "NOT_FOUND",</span>
1459
+ <span class="cstat-no" title="statement not covered" > message: "Event not found",</span>
1460
+ <span class="cstat-no" title="statement not covered" > });</span>
1461
+ <span class="cstat-no" title="statement not covered" > }</span>
1462
+ &nbsp;
1463
+ // Check if user is the event owner or a teacher of the class
1464
+ <span class="cstat-no" title="statement not covered" > if (event.userId !== ctx.user.id &amp;&amp; </span>
1465
+ <span class="cstat-no" title="statement not covered" > !event.class?.teachers.some(teacher =&gt; teacher.id === ctx.user!.id)) {</span>
1466
+ <span class="cstat-no" title="statement not covered" > throw new TRPCError({</span>
1467
+ <span class="cstat-no" title="statement not covered" > code: "UNAUTHORIZED",</span>
1468
+ <span class="cstat-no" title="statement not covered" > message: "You are not authorized to modify this event",</span>
1469
+ <span class="cstat-no" title="statement not covered" > });</span>
1470
+ <span class="cstat-no" title="statement not covered" > }</span>
1471
+ &nbsp;
1472
+ // Detach assignment from event
1473
+ <span class="cstat-no" title="statement not covered" > const updatedAssignment = await prisma.assignment.update({</span>
1474
+ <span class="cstat-no" title="statement not covered" > where: { id: input.assignmentId },</span>
1475
+ <span class="cstat-no" title="statement not covered" > data: {</span>
1476
+ <span class="cstat-no" title="statement not covered" > eventAttached: {</span>
1477
+ <span class="cstat-no" title="statement not covered" > disconnect: true</span>
1478
+ <span class="cstat-no" title="statement not covered" > }</span>
1479
+ <span class="cstat-no" title="statement not covered" > },</span>
1480
+ <span class="cstat-no" title="statement not covered" > include: {</span>
1481
+ <span class="cstat-no" title="statement not covered" > attachments: {</span>
1482
+ <span class="cstat-no" title="statement not covered" > select: {</span>
1483
+ <span class="cstat-no" title="statement not covered" > id: true,</span>
1484
+ <span class="cstat-no" title="statement not covered" > name: true,</span>
1485
+ <span class="cstat-no" title="statement not covered" > type: true,</span>
1486
+ <span class="cstat-no" title="statement not covered" > }</span>
1487
+ <span class="cstat-no" title="statement not covered" > },</span>
1488
+ <span class="cstat-no" title="statement not covered" > section: {</span>
1489
+ <span class="cstat-no" title="statement not covered" > select: {</span>
1490
+ <span class="cstat-no" title="statement not covered" > id: true,</span>
1491
+ <span class="cstat-no" title="statement not covered" > name: true</span>
1492
+ <span class="cstat-no" title="statement not covered" > }</span>
1493
+ <span class="cstat-no" title="statement not covered" > },</span>
1494
+ <span class="cstat-no" title="statement not covered" > teacher: {</span>
1495
+ <span class="cstat-no" title="statement not covered" > select: {</span>
1496
+ <span class="cstat-no" title="statement not covered" > id: true,</span>
1497
+ <span class="cstat-no" title="statement not covered" > username: true</span>
1498
+ <span class="cstat-no" title="statement not covered" > }</span>
1499
+ <span class="cstat-no" title="statement not covered" > }</span>
1500
+ <span class="cstat-no" title="statement not covered" > }</span>
1501
+ <span class="cstat-no" title="statement not covered" > });</span>
1502
+ &nbsp;
1503
+ <span class="cstat-no" title="statement not covered" > return { assignment: updatedAssignment };</span>
1504
+ }),
1505
+ &nbsp;
1506
+ getAvailableAssignments: protectedProcedure
1507
+ .input(z.object({
1508
+ eventId: z.string(),
1509
+ }))
1510
+ .query(async ({ ctx, input }) =&gt; {
1511
+ <span class="cstat-no" title="statement not covered" > if (!ctx.user) {</span>
1512
+ <span class="cstat-no" title="statement not covered" > throw new TRPCError({</span>
1513
+ <span class="cstat-no" title="statement not covered" > code: "UNAUTHORIZED",</span>
1514
+ <span class="cstat-no" title="statement not covered" > message: "You must be logged in to get available assignments",</span>
1515
+ <span class="cstat-no" title="statement not covered" > });</span>
1516
+ <span class="cstat-no" title="statement not covered" > }</span>
1517
+ &nbsp;
1518
+ // Get the event to find the class
1519
+ <span class="cstat-no" title="statement not covered" > const event = await prisma.event.findUnique({</span>
1520
+ <span class="cstat-no" title="statement not covered" > where: { id: input.eventId },</span>
1521
+ <span class="cstat-no" title="statement not covered" > include: {</span>
1522
+ <span class="cstat-no" title="statement not covered" > class: {</span>
1523
+ <span class="cstat-no" title="statement not covered" > include: {</span>
1524
+ <span class="cstat-no" title="statement not covered" > teachers: {</span>
1525
+ <span class="cstat-no" title="statement not covered" > select: { id: true }</span>
1526
+ <span class="cstat-no" title="statement not covered" > }</span>
1527
+ <span class="cstat-no" title="statement not covered" > }</span>
1528
+ <span class="cstat-no" title="statement not covered" > }</span>
1529
+ <span class="cstat-no" title="statement not covered" > }</span>
1530
+ <span class="cstat-no" title="statement not covered" > });</span>
1531
+ &nbsp;
1532
+ <span class="cstat-no" title="statement not covered" > if (!event || !event.classId) {</span>
1533
+ <span class="cstat-no" title="statement not covered" > throw new TRPCError({</span>
1534
+ <span class="cstat-no" title="statement not covered" > code: "NOT_FOUND",</span>
1535
+ <span class="cstat-no" title="statement not covered" > message: "Event not found",</span>
1536
+ <span class="cstat-no" title="statement not covered" > });</span>
1537
+ <span class="cstat-no" title="statement not covered" > }</span>
1538
+ &nbsp;
1539
+ // Check if user is authorized to access this event/class
1540
+ <span class="cstat-no" title="statement not covered" > if (event.userId !== ctx.user.id &amp;&amp; </span>
1541
+ <span class="cstat-no" title="statement not covered" > !event.class?.teachers.some(teacher =&gt; teacher.id === ctx.user!.id)) {</span>
1542
+ <span class="cstat-no" title="statement not covered" > throw new TRPCError({</span>
1543
+ <span class="cstat-no" title="statement not covered" > code: "UNAUTHORIZED",</span>
1544
+ <span class="cstat-no" title="statement not covered" > message: "You are not authorized to access this event",</span>
1545
+ <span class="cstat-no" title="statement not covered" > });</span>
1546
+ <span class="cstat-no" title="statement not covered" > }</span>
1547
+ &nbsp;
1548
+ // Get all assignments for the class that are not already attached to an event
1549
+ <span class="cstat-no" title="statement not covered" > const assignments = await prisma.assignment.findMany({</span>
1550
+ <span class="cstat-no" title="statement not covered" > where: {</span>
1551
+ <span class="cstat-no" title="statement not covered" > classId: event.classId,</span>
1552
+ <span class="cstat-no" title="statement not covered" > eventId: null, // Not already attached to any event</span>
1553
+ <span class="cstat-no" title="statement not covered" > },</span>
1554
+ <span class="cstat-no" title="statement not covered" > select: {</span>
1555
+ <span class="cstat-no" title="statement not covered" > id: true,</span>
1556
+ <span class="cstat-no" title="statement not covered" > title: true,</span>
1557
+ <span class="cstat-no" title="statement not covered" > instructions: true,</span>
1558
+ <span class="cstat-no" title="statement not covered" > dueDate: true,</span>
1559
+ <span class="cstat-no" title="statement not covered" > type: true,</span>
1560
+ <span class="cstat-no" title="statement not covered" > graded: true,</span>
1561
+ <span class="cstat-no" title="statement not covered" > maxGrade: true,</span>
1562
+ <span class="cstat-no" title="statement not covered" > weight: true,</span>
1563
+ <span class="cstat-no" title="statement not covered" > section: {</span>
1564
+ <span class="cstat-no" title="statement not covered" > select: {</span>
1565
+ <span class="cstat-no" title="statement not covered" > id: true,</span>
1566
+ <span class="cstat-no" title="statement not covered" > name: true</span>
1567
+ <span class="cstat-no" title="statement not covered" > }</span>
1568
+ <span class="cstat-no" title="statement not covered" > },</span>
1569
+ <span class="cstat-no" title="statement not covered" > attachments: {</span>
1570
+ <span class="cstat-no" title="statement not covered" > select: {</span>
1571
+ <span class="cstat-no" title="statement not covered" > id: true,</span>
1572
+ <span class="cstat-no" title="statement not covered" > name: true,</span>
1573
+ <span class="cstat-no" title="statement not covered" > type: true,</span>
1574
+ <span class="cstat-no" title="statement not covered" > }</span>
1575
+ <span class="cstat-no" title="statement not covered" > },</span>
1576
+ <span class="cstat-no" title="statement not covered" > teacher: {</span>
1577
+ <span class="cstat-no" title="statement not covered" > select: {</span>
1578
+ <span class="cstat-no" title="statement not covered" > id: true,</span>
1579
+ <span class="cstat-no" title="statement not covered" > username: true</span>
1580
+ <span class="cstat-no" title="statement not covered" > }</span>
1581
+ <span class="cstat-no" title="statement not covered" > }</span>
1582
+ <span class="cstat-no" title="statement not covered" > },</span>
1583
+ <span class="cstat-no" title="statement not covered" > orderBy: {</span>
1584
+ <span class="cstat-no" title="statement not covered" > createdAt: 'desc'</span>
1585
+ <span class="cstat-no" title="statement not covered" > }</span>
1586
+ <span class="cstat-no" title="statement not covered" > });</span>
1587
+ &nbsp;
1588
+ <span class="cstat-no" title="statement not covered" > return { assignments };</span>
1589
+ }),
1590
+ }); </pre></td></tr></table></pre>
1591
+
1592
+ <div class='push'></div><!-- for sticky footer -->
1593
+ </div><!-- /wrapper -->
1594
+ <div class='footer quiet pad2 space-top1 center small'>
1595
+ Code coverage generated by
1596
+ <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
1597
+ at 2025-11-22T10:42:40.796Z
1598
+ </div>
1599
+ <script src="../../../prettify.js"></script>
1600
+ <script>
1601
+ window.onload = function () {
1602
+ prettyPrint();
1603
+ };
1604
+ </script>
1605
+ <script src="../../../sorter.js"></script>
1606
+ <script src="../../../block-navigation.js"></script>
1607
+ </body>
1608
+ </html>
1609
+