@prosopo/datasets 3.0.34 → 3.0.42
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.
- package/CHANGELOG.md +70 -0
- package/coverage/base.css +224 -0
- package/coverage/block-navigation.js +87 -0
- package/coverage/clover.xml +493 -0
- package/coverage/coverage-final.json +7 -0
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +131 -0
- package/coverage/prettify.css +1 -0
- package/coverage/prettify.js +2 -0
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +210 -0
- package/coverage/src/captcha/captcha.ts.html +1093 -0
- package/coverage/src/captcha/dataset.ts.html +490 -0
- package/coverage/src/captcha/index.html +176 -0
- package/coverage/src/captcha/index.ts.html +136 -0
- package/coverage/src/captcha/merkle.ts.html +610 -0
- package/coverage/src/captcha/util.ts.html +187 -0
- package/coverage/src/index.html +116 -0
- package/coverage/src/index.ts.html +139 -0
- package/dist/captcha/captcha.d.ts +21 -0
- package/dist/captcha/captcha.d.ts.map +1 -0
- package/dist/captcha/captcha.js +154 -173
- package/dist/captcha/captcha.js.map +1 -0
- package/dist/captcha/dataset.d.ts +8 -0
- package/dist/captcha/dataset.d.ts.map +1 -0
- package/dist/captcha/dataset.js +69 -83
- package/dist/captcha/dataset.js.map +1 -0
- package/dist/captcha/index.d.ts +5 -0
- package/dist/captcha/index.d.ts.map +1 -0
- package/dist/captcha/index.js +5 -27
- package/dist/captcha/index.js.map +1 -0
- package/dist/captcha/merkle.d.ts +20 -0
- package/dist/captcha/merkle.d.ts.map +1 -0
- package/dist/captcha/merkle.js +109 -112
- package/dist/captcha/merkle.js.map +1 -0
- package/dist/captcha/util.d.ts +2 -0
- package/dist/captcha/util.d.ts.map +1 -0
- package/dist/captcha/util.js +18 -19
- package/dist/captcha/util.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -31
- package/dist/index.js.map +1 -0
- package/dist/tests/captcha.unit.test.d.ts +2 -0
- package/dist/tests/captcha.unit.test.d.ts.map +1 -0
- package/dist/tests/captcha.unit.test.js +357 -0
- package/dist/tests/captcha.unit.test.js.map +1 -0
- package/dist/tests/dataset.unit.test.d.ts +2 -0
- package/dist/tests/dataset.unit.test.d.ts.map +1 -0
- package/dist/tests/dataset.unit.test.js +126 -0
- package/dist/tests/dataset.unit.test.js.map +1 -0
- package/dist/tests/merkle.unit.test.d.ts +2 -0
- package/dist/tests/merkle.unit.test.d.ts.map +1 -0
- package/dist/tests/merkle.unit.test.js +171 -0
- package/dist/tests/merkle.unit.test.js.map +1 -0
- package/dist/tests/mocks/data/captchas.d.ts +24 -0
- package/dist/tests/mocks/data/captchas.d.ts.map +1 -0
- package/dist/tests/mocks/data/captchas.js +1033 -1039
- package/dist/tests/mocks/data/captchas.js.map +1 -0
- package/dist/tests/mocks/data/captchas.json +886 -886
- package/dist/tests/mocks/data/captchas1.json +132 -132
- package/dist/tests/mocks/data/captchas2.json +175 -175
- package/dist/tests/mocks/data/captchas3.json +133 -133
- package/dist/tests/mocks/data/captchas4.json +132 -132
- package/package.json +13 -13
- package/dist/cjs/captcha/captcha.cjs +0 -195
- package/dist/cjs/captcha/dataset.cjs +0 -93
- package/dist/cjs/captcha/index.cjs +0 -27
- package/dist/cjs/captcha/merkle.cjs +0 -128
- package/dist/cjs/captcha/util.cjs +0 -23
- package/dist/cjs/index.cjs +0 -31
- package/dist/cjs/tests/mocks/data/captchas.cjs +0 -1044
|
@@ -0,0 +1,1093 @@
|
|
|
1
|
+
|
|
2
|
+
<!doctype html>
|
|
3
|
+
<html lang="en">
|
|
4
|
+
|
|
5
|
+
<head>
|
|
6
|
+
<title>Code coverage report for src/captcha/captcha.ts</title>
|
|
7
|
+
<meta charset="utf-8" />
|
|
8
|
+
<link rel="stylesheet" href="../../prettify.css" />
|
|
9
|
+
<link rel="stylesheet" href="../../base.css" />
|
|
10
|
+
<link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
|
|
11
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
12
|
+
<style type='text/css'>
|
|
13
|
+
.coverage-summary .sorter {
|
|
14
|
+
background-image: url(../../sort-arrow-sprite.png);
|
|
15
|
+
}
|
|
16
|
+
</style>
|
|
17
|
+
</head>
|
|
18
|
+
|
|
19
|
+
<body>
|
|
20
|
+
<div class='wrapper'>
|
|
21
|
+
<div class='pad1'>
|
|
22
|
+
<h1><a href="../../index.html">All files</a> / <a href="index.html">src/captcha</a> captcha.ts</h1>
|
|
23
|
+
<div class='clearfix'>
|
|
24
|
+
|
|
25
|
+
<div class='fl pad1y space-right2'>
|
|
26
|
+
<span class="strong">81.3% </span>
|
|
27
|
+
<span class="quiet">Statements</span>
|
|
28
|
+
<span class='fraction'>174/214</span>
|
|
29
|
+
</div>
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
<div class='fl pad1y space-right2'>
|
|
33
|
+
<span class="strong">69.81% </span>
|
|
34
|
+
<span class="quiet">Branches</span>
|
|
35
|
+
<span class='fraction'>37/53</span>
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
<div class='fl pad1y space-right2'>
|
|
40
|
+
<span class="strong">91.66% </span>
|
|
41
|
+
<span class="quiet">Functions</span>
|
|
42
|
+
<span class='fraction'>11/12</span>
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
<div class='fl pad1y space-right2'>
|
|
47
|
+
<span class="strong">81.3% </span>
|
|
48
|
+
<span class="quiet">Lines</span>
|
|
49
|
+
<span class='fraction'>174/214</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 high'></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></td><td class="line-coverage quiet"><span class="cline-any cline-neutral"> </span>
|
|
403
|
+
<span class="cline-any cline-neutral"> </span>
|
|
404
|
+
<span class="cline-any cline-neutral"> </span>
|
|
405
|
+
<span class="cline-any cline-neutral"> </span>
|
|
406
|
+
<span class="cline-any cline-neutral"> </span>
|
|
407
|
+
<span class="cline-any cline-neutral"> </span>
|
|
408
|
+
<span class="cline-any cline-neutral"> </span>
|
|
409
|
+
<span class="cline-any cline-neutral"> </span>
|
|
410
|
+
<span class="cline-any cline-neutral"> </span>
|
|
411
|
+
<span class="cline-any cline-neutral"> </span>
|
|
412
|
+
<span class="cline-any cline-neutral"> </span>
|
|
413
|
+
<span class="cline-any cline-neutral"> </span>
|
|
414
|
+
<span class="cline-any cline-neutral"> </span>
|
|
415
|
+
<span class="cline-any cline-neutral"> </span>
|
|
416
|
+
<span class="cline-any cline-yes">1x</span>
|
|
417
|
+
<span class="cline-any cline-yes">1x</span>
|
|
418
|
+
<span class="cline-any cline-yes">1x</span>
|
|
419
|
+
<span class="cline-any cline-neutral"> </span>
|
|
420
|
+
<span class="cline-any cline-neutral"> </span>
|
|
421
|
+
<span class="cline-any cline-neutral"> </span>
|
|
422
|
+
<span class="cline-any cline-neutral"> </span>
|
|
423
|
+
<span class="cline-any cline-neutral"> </span>
|
|
424
|
+
<span class="cline-any cline-neutral"> </span>
|
|
425
|
+
<span class="cline-any cline-neutral"> </span>
|
|
426
|
+
<span class="cline-any cline-neutral"> </span>
|
|
427
|
+
<span class="cline-any cline-neutral"> </span>
|
|
428
|
+
<span class="cline-any cline-neutral"> </span>
|
|
429
|
+
<span class="cline-any cline-neutral"> </span>
|
|
430
|
+
<span class="cline-any cline-neutral"> </span>
|
|
431
|
+
<span class="cline-any cline-neutral"> </span>
|
|
432
|
+
<span class="cline-any cline-yes">1x</span>
|
|
433
|
+
<span class="cline-any cline-yes">1x</span>
|
|
434
|
+
<span class="cline-any cline-yes">1x</span>
|
|
435
|
+
<span class="cline-any cline-neutral"> </span>
|
|
436
|
+
<span class="cline-any cline-yes">1x</span>
|
|
437
|
+
<span class="cline-any cline-neutral"> </span>
|
|
438
|
+
<span class="cline-any cline-neutral"> </span>
|
|
439
|
+
<span class="cline-any cline-neutral"> </span>
|
|
440
|
+
<span class="cline-any cline-neutral"> </span>
|
|
441
|
+
<span class="cline-any cline-neutral"> </span>
|
|
442
|
+
<span class="cline-any cline-neutral"> </span>
|
|
443
|
+
<span class="cline-any cline-yes">1x</span>
|
|
444
|
+
<span class="cline-any cline-yes">1x</span>
|
|
445
|
+
<span class="cline-any cline-yes">1x</span>
|
|
446
|
+
<span class="cline-any cline-neutral"> </span>
|
|
447
|
+
<span class="cline-any cline-yes">1x</span>
|
|
448
|
+
<span class="cline-any cline-yes">1x</span>
|
|
449
|
+
<span class="cline-any cline-yes">1x</span>
|
|
450
|
+
<span class="cline-any cline-yes">2x</span>
|
|
451
|
+
<span class="cline-any cline-yes">2x</span>
|
|
452
|
+
<span class="cline-any cline-yes">2x</span>
|
|
453
|
+
<span class="cline-any cline-yes">1x</span>
|
|
454
|
+
<span class="cline-any cline-yes">1x</span>
|
|
455
|
+
<span class="cline-any cline-yes">2x</span>
|
|
456
|
+
<span class="cline-any cline-no"> </span>
|
|
457
|
+
<span class="cline-any cline-yes">2x</span>
|
|
458
|
+
<span class="cline-any cline-yes">2x</span>
|
|
459
|
+
<span class="cline-any cline-yes">1x</span>
|
|
460
|
+
<span class="cline-any cline-yes">1x</span>
|
|
461
|
+
<span class="cline-any cline-yes">1x</span>
|
|
462
|
+
<span class="cline-any cline-yes">1x</span>
|
|
463
|
+
<span class="cline-any cline-yes">1x</span>
|
|
464
|
+
<span class="cline-any cline-yes">1x</span>
|
|
465
|
+
<span class="cline-any cline-yes">1x</span>
|
|
466
|
+
<span class="cline-any cline-yes">1x</span>
|
|
467
|
+
<span class="cline-any cline-yes">1x</span>
|
|
468
|
+
<span class="cline-any cline-yes">1x</span>
|
|
469
|
+
<span class="cline-any cline-yes">1x</span>
|
|
470
|
+
<span class="cline-any cline-no"> </span>
|
|
471
|
+
<span class="cline-any cline-no"> </span>
|
|
472
|
+
<span class="cline-any cline-no"> </span>
|
|
473
|
+
<span class="cline-any cline-no"> </span>
|
|
474
|
+
<span class="cline-any cline-yes">1x</span>
|
|
475
|
+
<span class="cline-any cline-neutral"> </span>
|
|
476
|
+
<span class="cline-any cline-neutral"> </span>
|
|
477
|
+
<span class="cline-any cline-neutral"> </span>
|
|
478
|
+
<span class="cline-any cline-neutral"> </span>
|
|
479
|
+
<span class="cline-any cline-neutral"> </span>
|
|
480
|
+
<span class="cline-any cline-neutral"> </span>
|
|
481
|
+
<span class="cline-any cline-yes">1x</span>
|
|
482
|
+
<span class="cline-any cline-yes">2x</span>
|
|
483
|
+
<span class="cline-any cline-yes">2x</span>
|
|
484
|
+
<span class="cline-any cline-yes">2x</span>
|
|
485
|
+
<span class="cline-any cline-yes">2x</span>
|
|
486
|
+
<span class="cline-any cline-yes">2x</span>
|
|
487
|
+
<span class="cline-any cline-yes">2x</span>
|
|
488
|
+
<span class="cline-any cline-yes">2x</span>
|
|
489
|
+
<span class="cline-any cline-yes">2x</span>
|
|
490
|
+
<span class="cline-any cline-yes">1x</span>
|
|
491
|
+
<span class="cline-any cline-yes">1x</span>
|
|
492
|
+
<span class="cline-any cline-yes">1x</span>
|
|
493
|
+
<span class="cline-any cline-yes">1x</span>
|
|
494
|
+
<span class="cline-any cline-yes">2x</span>
|
|
495
|
+
<span class="cline-any cline-neutral"> </span>
|
|
496
|
+
<span class="cline-any cline-yes">1x</span>
|
|
497
|
+
<span class="cline-any cline-yes">13x</span>
|
|
498
|
+
<span class="cline-any cline-yes">13x</span>
|
|
499
|
+
<span class="cline-any cline-neutral"> </span>
|
|
500
|
+
<span class="cline-any cline-yes">1x</span>
|
|
501
|
+
<span class="cline-any cline-yes">2x</span>
|
|
502
|
+
<span class="cline-any cline-yes">2x</span>
|
|
503
|
+
<span class="cline-any cline-yes">2x</span>
|
|
504
|
+
<span class="cline-any cline-yes">2x</span>
|
|
505
|
+
<span class="cline-any cline-yes">2x</span>
|
|
506
|
+
<span class="cline-any cline-neutral"> </span>
|
|
507
|
+
<span class="cline-any cline-yes">2x</span>
|
|
508
|
+
<span class="cline-any cline-yes">2x</span>
|
|
509
|
+
<span class="cline-any cline-yes">4x</span>
|
|
510
|
+
<span class="cline-any cline-yes">4x</span>
|
|
511
|
+
<span class="cline-any cline-no"> </span>
|
|
512
|
+
<span class="cline-any cline-no"> </span>
|
|
513
|
+
<span class="cline-any cline-neutral"> </span>
|
|
514
|
+
<span class="cline-any cline-yes">4x</span>
|
|
515
|
+
<span class="cline-any cline-yes">4x</span>
|
|
516
|
+
<span class="cline-any cline-yes">4x</span>
|
|
517
|
+
<span class="cline-any cline-yes">4x</span>
|
|
518
|
+
<span class="cline-any cline-yes">4x</span>
|
|
519
|
+
<span class="cline-any cline-yes">4x</span>
|
|
520
|
+
<span class="cline-any cline-yes">4x</span>
|
|
521
|
+
<span class="cline-any cline-yes">4x</span>
|
|
522
|
+
<span class="cline-any cline-yes">4x</span>
|
|
523
|
+
<span class="cline-any cline-yes">4x</span>
|
|
524
|
+
<span class="cline-any cline-yes">4x</span>
|
|
525
|
+
<span class="cline-any cline-yes">4x</span>
|
|
526
|
+
<span class="cline-any cline-yes">4x</span>
|
|
527
|
+
<span class="cline-any cline-yes">4x</span>
|
|
528
|
+
<span class="cline-any cline-yes">4x</span>
|
|
529
|
+
<span class="cline-any cline-yes">2x</span>
|
|
530
|
+
<span class="cline-any cline-yes">2x</span>
|
|
531
|
+
<span class="cline-any cline-neutral"> </span>
|
|
532
|
+
<span class="cline-any cline-neutral"> </span>
|
|
533
|
+
<span class="cline-any cline-neutral"> </span>
|
|
534
|
+
<span class="cline-any cline-neutral"> </span>
|
|
535
|
+
<span class="cline-any cline-neutral"> </span>
|
|
536
|
+
<span class="cline-any cline-neutral"> </span>
|
|
537
|
+
<span class="cline-any cline-neutral"> </span>
|
|
538
|
+
<span class="cline-any cline-neutral"> </span>
|
|
539
|
+
<span class="cline-any cline-neutral"> </span>
|
|
540
|
+
<span class="cline-any cline-yes">1x</span>
|
|
541
|
+
<span class="cline-any cline-yes">3x</span>
|
|
542
|
+
<span class="cline-any cline-yes">3x</span>
|
|
543
|
+
<span class="cline-any cline-yes">3x</span>
|
|
544
|
+
<span class="cline-any cline-yes">3x</span>
|
|
545
|
+
<span class="cline-any cline-yes">3x</span>
|
|
546
|
+
<span class="cline-any cline-neutral"> </span>
|
|
547
|
+
<span class="cline-any cline-yes">3x</span>
|
|
548
|
+
<span class="cline-any cline-yes">3x</span>
|
|
549
|
+
<span class="cline-any cline-neutral"> </span>
|
|
550
|
+
<span class="cline-any cline-neutral"> </span>
|
|
551
|
+
<span class="cline-any cline-yes">3x</span>
|
|
552
|
+
<span class="cline-any cline-yes">1x</span>
|
|
553
|
+
<span class="cline-any cline-yes">1x</span>
|
|
554
|
+
<span class="cline-any cline-neutral"> </span>
|
|
555
|
+
<span class="cline-any cline-yes">2x</span>
|
|
556
|
+
<span class="cline-any cline-yes">2x</span>
|
|
557
|
+
<span class="cline-any cline-yes">2x</span>
|
|
558
|
+
<span class="cline-any cline-yes">2x</span>
|
|
559
|
+
<span class="cline-any cline-yes">3x</span>
|
|
560
|
+
<span class="cline-any cline-neutral"> </span>
|
|
561
|
+
<span class="cline-any cline-yes">2x</span>
|
|
562
|
+
<span class="cline-any cline-yes">2x</span>
|
|
563
|
+
<span class="cline-any cline-yes">3x</span>
|
|
564
|
+
<span class="cline-any cline-yes">2x</span>
|
|
565
|
+
<span class="cline-any cline-yes">2x</span>
|
|
566
|
+
<span class="cline-any cline-yes">1x</span>
|
|
567
|
+
<span class="cline-any cline-yes">1x</span>
|
|
568
|
+
<span class="cline-any cline-yes">2x</span>
|
|
569
|
+
<span class="cline-any cline-neutral"> </span>
|
|
570
|
+
<span class="cline-any cline-neutral"> </span>
|
|
571
|
+
<span class="cline-any cline-yes">1x</span>
|
|
572
|
+
<span class="cline-any cline-yes">2x</span>
|
|
573
|
+
<span class="cline-any cline-yes">2x</span>
|
|
574
|
+
<span class="cline-any cline-neutral"> </span>
|
|
575
|
+
<span class="cline-any cline-neutral"> </span>
|
|
576
|
+
<span class="cline-any cline-yes">2x</span>
|
|
577
|
+
<span class="cline-any cline-no"> </span>
|
|
578
|
+
<span class="cline-any cline-no"> </span>
|
|
579
|
+
<span class="cline-any cline-neutral"> </span>
|
|
580
|
+
<span class="cline-any cline-neutral"> </span>
|
|
581
|
+
<span class="cline-any cline-yes">2x</span>
|
|
582
|
+
<span class="cline-any cline-yes">2x</span>
|
|
583
|
+
<span class="cline-any cline-yes">2x</span>
|
|
584
|
+
<span class="cline-any cline-yes">2x</span>
|
|
585
|
+
<span class="cline-any cline-yes">2x</span>
|
|
586
|
+
<span class="cline-any cline-yes">2x</span>
|
|
587
|
+
<span class="cline-any cline-neutral"> </span>
|
|
588
|
+
<span class="cline-any cline-neutral"> </span>
|
|
589
|
+
<span class="cline-any cline-yes">2x</span>
|
|
590
|
+
<span class="cline-any cline-yes">2x</span>
|
|
591
|
+
<span class="cline-any cline-neutral"> </span>
|
|
592
|
+
<span class="cline-any cline-neutral"> </span>
|
|
593
|
+
<span class="cline-any cline-yes">2x</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-neutral"> </span>
|
|
597
|
+
<span class="cline-any cline-neutral"> </span>
|
|
598
|
+
<span class="cline-any cline-neutral"> </span>
|
|
599
|
+
<span class="cline-any cline-neutral"> </span>
|
|
600
|
+
<span class="cline-any cline-neutral"> </span>
|
|
601
|
+
<span class="cline-any cline-neutral"> </span>
|
|
602
|
+
<span class="cline-any cline-neutral"> </span>
|
|
603
|
+
<span class="cline-any cline-neutral"> </span>
|
|
604
|
+
<span class="cline-any cline-neutral"> </span>
|
|
605
|
+
<span class="cline-any cline-yes">1x</span>
|
|
606
|
+
<span class="cline-any cline-yes">18x</span>
|
|
607
|
+
<span class="cline-any cline-yes">18x</span>
|
|
608
|
+
<span class="cline-any cline-yes">18x</span>
|
|
609
|
+
<span class="cline-any cline-yes">18x</span>
|
|
610
|
+
<span class="cline-any cline-yes">18x</span>
|
|
611
|
+
<span class="cline-any cline-yes">18x</span>
|
|
612
|
+
<span class="cline-any cline-yes">18x</span>
|
|
613
|
+
<span class="cline-any cline-yes">108x</span>
|
|
614
|
+
<span class="cline-any cline-yes">108x</span>
|
|
615
|
+
<span class="cline-any cline-yes">108x</span>
|
|
616
|
+
<span class="cline-any cline-no"> </span>
|
|
617
|
+
<span class="cline-any cline-no"> </span>
|
|
618
|
+
<span class="cline-any cline-no"> </span>
|
|
619
|
+
<span class="cline-any cline-no"> </span>
|
|
620
|
+
<span class="cline-any cline-no"> </span>
|
|
621
|
+
<span class="cline-any cline-no"> </span>
|
|
622
|
+
<span class="cline-any cline-yes">18x</span>
|
|
623
|
+
<span class="cline-any cline-yes">18x</span>
|
|
624
|
+
<span class="cline-any cline-yes">18x</span>
|
|
625
|
+
<span class="cline-any cline-neutral"> </span>
|
|
626
|
+
<span class="cline-any cline-neutral"> </span>
|
|
627
|
+
<span class="cline-any cline-yes">18x</span>
|
|
628
|
+
<span class="cline-any cline-yes">18x</span>
|
|
629
|
+
<span class="cline-any cline-yes">18x</span>
|
|
630
|
+
<span class="cline-any cline-yes">18x</span>
|
|
631
|
+
<span class="cline-any cline-yes">18x</span>
|
|
632
|
+
<span class="cline-any cline-no"> </span>
|
|
633
|
+
<span class="cline-any cline-no"> </span>
|
|
634
|
+
<span class="cline-any cline-no"> </span>
|
|
635
|
+
<span class="cline-any cline-no"> </span>
|
|
636
|
+
<span class="cline-any cline-yes">18x</span>
|
|
637
|
+
<span class="cline-any cline-neutral"> </span>
|
|
638
|
+
<span class="cline-any cline-neutral"> </span>
|
|
639
|
+
<span class="cline-any cline-neutral"> </span>
|
|
640
|
+
<span class="cline-any cline-neutral"> </span>
|
|
641
|
+
<span class="cline-any cline-neutral"> </span>
|
|
642
|
+
<span class="cline-any cline-yes">1x</span>
|
|
643
|
+
<span class="cline-any cline-yes">13x</span>
|
|
644
|
+
<span class="cline-any cline-yes">13x</span>
|
|
645
|
+
<span class="cline-any cline-yes">13x</span>
|
|
646
|
+
<span class="cline-any cline-yes">13x</span>
|
|
647
|
+
<span class="cline-any cline-neutral"> </span>
|
|
648
|
+
<span class="cline-any cline-neutral"> </span>
|
|
649
|
+
<span class="cline-any cline-neutral"> </span>
|
|
650
|
+
<span class="cline-any cline-neutral"> </span>
|
|
651
|
+
<span class="cline-any cline-neutral"> </span>
|
|
652
|
+
<span class="cline-any cline-yes">90045x</span>
|
|
653
|
+
<span class="cline-any cline-yes">90045x</span>
|
|
654
|
+
<span class="cline-any cline-yes">90045x</span>
|
|
655
|
+
<span class="cline-any cline-yes">90045x</span>
|
|
656
|
+
<span class="cline-any cline-no"> </span>
|
|
657
|
+
<span class="cline-any cline-no"> </span>
|
|
658
|
+
<span class="cline-any cline-no"> </span>
|
|
659
|
+
<span class="cline-any cline-no"> </span>
|
|
660
|
+
<span class="cline-any cline-no"> </span>
|
|
661
|
+
<span class="cline-any cline-neutral"> </span>
|
|
662
|
+
<span class="cline-any cline-neutral"> </span>
|
|
663
|
+
<span class="cline-any cline-neutral"> </span>
|
|
664
|
+
<span class="cline-any cline-neutral"> </span>
|
|
665
|
+
<span class="cline-any cline-neutral"> </span>
|
|
666
|
+
<span class="cline-any cline-neutral"> </span>
|
|
667
|
+
<span class="cline-any cline-neutral"> </span>
|
|
668
|
+
<span class="cline-any cline-yes">1x</span>
|
|
669
|
+
<span class="cline-any cline-yes">12x</span>
|
|
670
|
+
<span class="cline-any cline-yes">12x</span>
|
|
671
|
+
<span class="cline-any cline-yes">12x</span>
|
|
672
|
+
<span class="cline-any cline-yes">12x</span>
|
|
673
|
+
<span class="cline-any cline-no"> </span>
|
|
674
|
+
<span class="cline-any cline-no"> </span>
|
|
675
|
+
<span class="cline-any cline-yes">12x</span>
|
|
676
|
+
<span class="cline-any cline-yes">27x</span>
|
|
677
|
+
<span class="cline-any cline-neutral"> </span>
|
|
678
|
+
<span class="cline-any cline-neutral"> </span>
|
|
679
|
+
<span class="cline-any cline-no"> </span>
|
|
680
|
+
<span class="cline-any cline-no"> </span>
|
|
681
|
+
<span class="cline-any cline-no"> </span>
|
|
682
|
+
<span class="cline-any cline-no"> </span>
|
|
683
|
+
<span class="cline-any cline-no"> </span>
|
|
684
|
+
<span class="cline-any cline-yes">27x</span>
|
|
685
|
+
<span class="cline-any cline-neutral"> </span>
|
|
686
|
+
<span class="cline-any cline-neutral"> </span>
|
|
687
|
+
<span class="cline-any cline-yes">27x</span>
|
|
688
|
+
<span class="cline-any cline-neutral"> </span>
|
|
689
|
+
<span class="cline-any cline-yes">27x</span>
|
|
690
|
+
<span class="cline-any cline-yes">27x</span>
|
|
691
|
+
<span class="cline-any cline-no"> </span>
|
|
692
|
+
<span class="cline-any cline-yes">12x</span>
|
|
693
|
+
<span class="cline-any cline-yes">12x</span>
|
|
694
|
+
<span class="cline-any cline-neutral"> </span>
|
|
695
|
+
<span class="cline-any cline-neutral"> </span>
|
|
696
|
+
<span class="cline-any cline-neutral"> </span>
|
|
697
|
+
<span class="cline-any cline-neutral"> </span>
|
|
698
|
+
<span class="cline-any cline-neutral"> </span>
|
|
699
|
+
<span class="cline-any cline-neutral"> </span>
|
|
700
|
+
<span class="cline-any cline-yes">1x</span>
|
|
701
|
+
<span class="cline-any cline-yes">1x</span>
|
|
702
|
+
<span class="cline-any cline-yes">1x</span>
|
|
703
|
+
<span class="cline-any cline-yes">1x</span>
|
|
704
|
+
<span class="cline-any cline-yes">1x</span>
|
|
705
|
+
<span class="cline-any cline-yes">1x</span>
|
|
706
|
+
<span class="cline-any cline-yes">1x</span>
|
|
707
|
+
<span class="cline-any cline-yes">1x</span>
|
|
708
|
+
<span class="cline-any cline-neutral"> </span>
|
|
709
|
+
<span class="cline-any cline-neutral"> </span>
|
|
710
|
+
<span class="cline-any cline-neutral"> </span>
|
|
711
|
+
<span class="cline-any cline-neutral"> </span>
|
|
712
|
+
<span class="cline-any cline-neutral"> </span>
|
|
713
|
+
<span class="cline-any cline-neutral"> </span>
|
|
714
|
+
<span class="cline-any cline-neutral"> </span>
|
|
715
|
+
<span class="cline-any cline-neutral"> </span>
|
|
716
|
+
<span class="cline-any cline-yes">1x</span>
|
|
717
|
+
<span class="cline-any cline-yes">1x</span>
|
|
718
|
+
<span class="cline-any cline-yes">1x</span>
|
|
719
|
+
<span class="cline-any cline-yes">1x</span>
|
|
720
|
+
<span class="cline-any cline-yes">1x</span>
|
|
721
|
+
<span class="cline-any cline-yes">1x</span>
|
|
722
|
+
<span class="cline-any cline-yes">1x</span>
|
|
723
|
+
<span class="cline-any cline-neutral"> </span>
|
|
724
|
+
<span class="cline-any cline-neutral"> </span>
|
|
725
|
+
<span class="cline-any cline-neutral"> </span>
|
|
726
|
+
<span class="cline-any cline-neutral"> </span>
|
|
727
|
+
<span class="cline-any cline-neutral"> </span>
|
|
728
|
+
<span class="cline-any cline-neutral"> </span>
|
|
729
|
+
<span class="cline-any cline-yes">1x</span>
|
|
730
|
+
<span class="cline-any cline-no"> </span>
|
|
731
|
+
<span class="cline-any cline-no"> </span>
|
|
732
|
+
<span class="cline-any cline-no"> </span>
|
|
733
|
+
<span class="cline-any cline-no"> </span>
|
|
734
|
+
<span class="cline-any cline-no"> </span>
|
|
735
|
+
<span class="cline-any cline-no"> </span>
|
|
736
|
+
<span class="cline-any cline-no"> </span>
|
|
737
|
+
<span class="cline-any cline-no"> </span>
|
|
738
|
+
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">// Copyright 2021-2025 Prosopo (UK) Ltd.
|
|
739
|
+
//
|
|
740
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
741
|
+
// you may not use this file except in compliance with the License.
|
|
742
|
+
// You may obtain a copy of the License at
|
|
743
|
+
//
|
|
744
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
745
|
+
//
|
|
746
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
747
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
748
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
749
|
+
// See the License for the specific language governing permissions and
|
|
750
|
+
// limitations under the License.
|
|
751
|
+
|
|
752
|
+
import { isHex } from "@polkadot/util";
|
|
753
|
+
import { ProsopoDatasetError, ProsopoEnvError } from "@prosopo/common";
|
|
754
|
+
import {
|
|
755
|
+
type AssetsResolver,
|
|
756
|
+
type Captcha,
|
|
757
|
+
type CaptchaSolution,
|
|
758
|
+
CaptchaSolutionArraySchema,
|
|
759
|
+
type CaptchaWithoutId,
|
|
760
|
+
type DatasetRaw,
|
|
761
|
+
DatasetWithNumericSolutionSchema,
|
|
762
|
+
type HashedItem,
|
|
763
|
+
type HashedSolution,
|
|
764
|
+
type Item,
|
|
765
|
+
type RawSolution,
|
|
766
|
+
} from "@prosopo/types";
|
|
767
|
+
import type { SolutionRecord } from "@prosopo/types-database";
|
|
768
|
+
import { at } from "@prosopo/util";
|
|
769
|
+
import { hexHash, hexHashArray } from "@prosopo/util-crypto";
|
|
770
|
+
import { downloadImage } from "./util.js";
|
|
771
|
+
|
|
772
|
+
export const NO_SOLUTION_VALUE = "NO_SOLUTION";
|
|
773
|
+
|
|
774
|
+
/**
|
|
775
|
+
* Parse a dataset
|
|
776
|
+
* @return {JSON} captcha dataset, stored in JSON
|
|
777
|
+
* @param datasetJSON
|
|
778
|
+
*/
|
|
779
|
+
export function parseCaptchaDataset(datasetJSON: JSON): DatasetRaw {
|
|
780
|
+
try {
|
|
781
|
+
const result = DatasetWithNumericSolutionSchema.parse(datasetJSON);
|
|
782
|
+
|
|
783
|
+
const result2: DatasetRaw = {
|
|
784
|
+
format: result.format,
|
|
785
|
+
captchas: result.captchas.map((captcha) => {
|
|
786
|
+
return {
|
|
787
|
+
...captcha,
|
|
788
|
+
solution: captcha.solution
|
|
789
|
+
? matchItemsToSolutions(captcha.solution, captcha.items)
|
|
790
|
+
: [],
|
|
791
|
+
unlabelled: captcha.<span class="branch-0 cbranch-no" title="branch not covered" >unlabelled</span>
|
|
792
|
+
<span class="cstat-no" title="statement not covered" > ? matchItemsToSolutions(captcha.unlabelled, captcha.items)</span>
|
|
793
|
+
: [],
|
|
794
|
+
};
|
|
795
|
+
}),
|
|
796
|
+
};
|
|
797
|
+
if (result.datasetId !== undefined) <span class="branch-0 cbranch-no" title="branch not covered" >result2.datasetId = result.datasetId;</span>
|
|
798
|
+
if (result.contentTree !== undefined)
|
|
799
|
+
<span class="branch-0 cbranch-no" title="branch not covered" > result2.contentTree = result.contentTree;</span>
|
|
800
|
+
if (result.datasetContentId !== undefined)
|
|
801
|
+
<span class="branch-0 cbranch-no" title="branch not covered" > result2.datasetContentId = result.datasetContentId;</span>
|
|
802
|
+
if (result.solutionTree !== undefined)
|
|
803
|
+
<span class="branch-0 cbranch-no" title="branch not covered" > result2.solutionTree = result.solutionTree;</span>
|
|
804
|
+
return result2;
|
|
805
|
+
<span class="branch-0 cbranch-no" title="branch not covered" > } catch (err) {</span>
|
|
806
|
+
<span class="cstat-no" title="statement not covered" > throw new ProsopoDatasetError("DATASET.DATASET_PARSE_ERROR", {</span>
|
|
807
|
+
<span class="cstat-no" title="statement not covered" > context: { error: err },</span>
|
|
808
|
+
<span class="cstat-no" title="statement not covered" > });</span>
|
|
809
|
+
<span class="cstat-no" title="statement not covered" > }</span>
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
/**
|
|
813
|
+
* Make sure captcha solutions are in the correct format
|
|
814
|
+
* @param {JSON} captchaJSON captcha solutions received from the api
|
|
815
|
+
* @return {CaptchaSolution[]} an array of parsed and sorted captcha solutions
|
|
816
|
+
*/
|
|
817
|
+
export function parseAndSortCaptchaSolutions(
|
|
818
|
+
captchaJSON: CaptchaSolution[],
|
|
819
|
+
): CaptchaSolution[] {
|
|
820
|
+
try {
|
|
821
|
+
return CaptchaSolutionArraySchema.parse(captchaJSON).map((captcha) => ({
|
|
822
|
+
...captcha,
|
|
823
|
+
solution: captcha.solution.sort(),
|
|
824
|
+
}));
|
|
825
|
+
} catch (err) {
|
|
826
|
+
throw new ProsopoDatasetError("DATASET.SOLUTION_PARSE_ERROR", {
|
|
827
|
+
context: { error: err },
|
|
828
|
+
});
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
export function captchaSort<T extends { captchaId: string }>(a: T, b: T) {
|
|
833
|
+
return a.captchaId.localeCompare(b.captchaId);
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
export function sortAndComputeHashes(
|
|
837
|
+
received: CaptchaSolution[],
|
|
838
|
+
stored: Captcha[],
|
|
839
|
+
): { captchaId: string; hash: string }[] {
|
|
840
|
+
received.sort(captchaSort);
|
|
841
|
+
stored.sort(captchaSort);
|
|
842
|
+
|
|
843
|
+
return stored.map(
|
|
844
|
+
({ salt, items = [], target = "", captchaId, solved }, index) => {
|
|
845
|
+
const item = at(received, index);
|
|
846
|
+
if (captchaId !== item.captchaId) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
|
|
847
|
+
<span class="cstat-no" title="statement not covered" > throw new ProsopoEnvError("CAPTCHA.ID_MISMATCH");</span>
|
|
848
|
+
<span class="cstat-no" title="statement not covered" > }</span>
|
|
849
|
+
|
|
850
|
+
return {
|
|
851
|
+
hash: computeCaptchaHash(
|
|
852
|
+
{
|
|
853
|
+
solution: solved ? item.<span class="branch-0 cbranch-no" title="branch not covered" >solution : [],</span>
|
|
854
|
+
salt,
|
|
855
|
+
items,
|
|
856
|
+
target,
|
|
857
|
+
},
|
|
858
|
+
true,
|
|
859
|
+
true,
|
|
860
|
+
false,
|
|
861
|
+
),
|
|
862
|
+
captchaId,
|
|
863
|
+
};
|
|
864
|
+
},
|
|
865
|
+
);
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
/**
|
|
869
|
+
* Take an array of CaptchaSolutions and Captchas and check if the solutions are the same for each pair
|
|
870
|
+
* @param {CaptchaSolution[]} received
|
|
871
|
+
* @param solutions
|
|
872
|
+
* @param totalImages
|
|
873
|
+
* @param {number} threshold the percentage of captchas that must be correct to return true
|
|
874
|
+
* @return {boolean}
|
|
875
|
+
*/
|
|
876
|
+
export function compareCaptchaSolutions(
|
|
877
|
+
received: CaptchaSolution[],
|
|
878
|
+
solutions: SolutionRecord[],
|
|
879
|
+
totalImages: number,
|
|
880
|
+
threshold: number,
|
|
881
|
+
): boolean {
|
|
882
|
+
// Sort both arrays by captchaId
|
|
883
|
+
received.sort(captchaSort);
|
|
884
|
+
solutions.sort(captchaSort);
|
|
885
|
+
|
|
886
|
+
// Check if lengths match
|
|
887
|
+
if (received.length !== solutions.length) {
|
|
888
|
+
return false;
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
if (
|
|
892
|
+
received.length &&
|
|
893
|
+
solutions.length &&
|
|
894
|
+
received.length === solutions.length
|
|
895
|
+
) {
|
|
896
|
+
// make sure captchaId matches in each pair
|
|
897
|
+
const captchaIdMismatch = received.some(
|
|
898
|
+
(captcha, index) =>
|
|
899
|
+
solutions[index] && captcha.captchaId !== solutions[index].captchaId,
|
|
900
|
+
);
|
|
901
|
+
if (captchaIdMismatch) {
|
|
902
|
+
return false;
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
// Verify each captcha solution against expected solution
|
|
907
|
+
return received.every((captcha, index) => {
|
|
908
|
+
const sortedReceivedSolution = captcha.solution.sort();
|
|
909
|
+
const targetSolution = solutions[index]?.solution.sort();
|
|
910
|
+
|
|
911
|
+
// Ensure target solution exists
|
|
912
|
+
if (!targetSolution) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
|
|
913
|
+
<span class="cstat-no" title="statement not covered" > return false;</span>
|
|
914
|
+
<span class="cstat-no" title="statement not covered" > }</span>
|
|
915
|
+
|
|
916
|
+
// Count incorrect and missing solutions
|
|
917
|
+
const incorrectCount = sortedReceivedSolution.filter(
|
|
918
|
+
(solution) => !targetSolution.includes(solution),
|
|
919
|
+
).length;
|
|
920
|
+
const missingCount = targetSolution.filter(
|
|
921
|
+
(solution) => !sortedReceivedSolution.includes(solution),
|
|
922
|
+
).length;
|
|
923
|
+
|
|
924
|
+
// Calculate correctness percentage
|
|
925
|
+
const totalIncorrect = incorrectCount + missingCount;
|
|
926
|
+
const percentageCorrect = 1 - totalIncorrect / totalImages;
|
|
927
|
+
|
|
928
|
+
// Return whether solution meets threshold
|
|
929
|
+
return percentageCorrect >= threshold;
|
|
930
|
+
});
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
/**
|
|
934
|
+
* Compute the hash of various types of captcha
|
|
935
|
+
* @param {Captcha} captcha
|
|
936
|
+
* @param {boolean} includeSolution
|
|
937
|
+
* @param {boolean} includeSalt
|
|
938
|
+
* @param {boolean} sortItemHashes
|
|
939
|
+
* @return {string} the hex string hash
|
|
940
|
+
*/
|
|
941
|
+
export function computeCaptchaHash(
|
|
942
|
+
captcha: CaptchaWithoutId,
|
|
943
|
+
includeSolution: boolean,
|
|
944
|
+
includeSalt: boolean,
|
|
945
|
+
sortItemHashes: boolean,
|
|
946
|
+
): string {
|
|
947
|
+
try {
|
|
948
|
+
const itemHashes: string[] = captcha.items.map((item, index) => {
|
|
949
|
+
if (item.hash) {
|
|
950
|
+
return item.hash;
|
|
951
|
+
<span class="branch-0 cbranch-no" title="branch not covered" > }</span>
|
|
952
|
+
<span class="cstat-no" title="statement not covered" > throw new ProsopoDatasetError("CAPTCHA.MISSING_ITEM_HASH", {</span>
|
|
953
|
+
<span class="cstat-no" title="statement not covered" > context: {</span>
|
|
954
|
+
<span class="cstat-no" title="statement not covered" > computeCaptchaHashName: computeCaptchaHash.name,</span>
|
|
955
|
+
<span class="cstat-no" title="statement not covered" > index,</span>
|
|
956
|
+
<span class="cstat-no" title="statement not covered" > },</span>
|
|
957
|
+
<span class="cstat-no" title="statement not covered" > });</span>
|
|
958
|
+
});
|
|
959
|
+
return hexHashArray([
|
|
960
|
+
captcha.target,
|
|
961
|
+
// empty array hashes as empty string, undefined solution results in the array [`NO_SOLUTION`]
|
|
962
|
+
// [undefined] also hashes as empty string, which is why we don't use it
|
|
963
|
+
...(includeSolution ? getSolutionValueToHash(captcha.solution) : []),
|
|
964
|
+
includeSalt ? captcha.salt : "",
|
|
965
|
+
sortItemHashes ? itemHashes.sort() : itemHashes,
|
|
966
|
+
]);
|
|
967
|
+
<span class="branch-0 cbranch-no" title="branch not covered" > } catch (err) {</span>
|
|
968
|
+
<span class="cstat-no" title="statement not covered" > throw new ProsopoDatasetError("DATASET.HASH_ERROR", {</span>
|
|
969
|
+
<span class="cstat-no" title="statement not covered" > context: { error: err },</span>
|
|
970
|
+
<span class="cstat-no" title="statement not covered" > });</span>
|
|
971
|
+
<span class="cstat-no" title="statement not covered" > }</span>
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
/** Return the sorted solution value or ['NO_SOLUTION'] if there is no solution. Ensures that an empty array is a valid
|
|
975
|
+
* solution
|
|
976
|
+
* @param solution
|
|
977
|
+
*/
|
|
978
|
+
export function getSolutionValueToHash(
|
|
979
|
+
solution?: HashedSolution[] | RawSolution[],
|
|
980
|
+
) {
|
|
981
|
+
return solution !== undefined ? solution.sort() : [NO_SOLUTION_VALUE];
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
/** Compute the hash of a captcha item, downloading the image if necessary
|
|
985
|
+
* @param {Item} item
|
|
986
|
+
* @return {Promise<HashedItem>} the hex string hash of the item
|
|
987
|
+
*/
|
|
988
|
+
export async function computeItemHash(item: Item): Promise<HashedItem> {
|
|
989
|
+
if (item.type === "text") {
|
|
990
|
+
return { ...item, hash: hexHash(item.data) };
|
|
991
|
+
<span class="branch-0 cbranch-no" title="branch not covered" > }</span>
|
|
992
|
+
<span class="cstat-no" title="statement not covered" > if (item.type === "image") {</span>
|
|
993
|
+
<span class="cstat-no" title="statement not covered" > return { ...item, hash: hexHash(await downloadImage(item.data)) };</span>
|
|
994
|
+
<span class="cstat-no" title="statement not covered" > }</span>
|
|
995
|
+
<span class="cstat-no" title="statement not covered" > throw new ProsopoDatasetError("CAPTCHA.INVALID_ITEM_FORMAT");</span>
|
|
996
|
+
<span class="cstat-no" title="statement not covered" >}</span>
|
|
997
|
+
|
|
998
|
+
/**
|
|
999
|
+
* Converts an indexed captcha solution to a hashed captcha solution or simply returns the hash if it is already hashed
|
|
1000
|
+
* @return {HashedSolution[]}
|
|
1001
|
+
* @param {RawSolution[] | HashedSolution[]} solutions
|
|
1002
|
+
* @param {Item[]} items
|
|
1003
|
+
*/
|
|
1004
|
+
export function matchItemsToSolutions(
|
|
1005
|
+
solutions: RawSolution[] | HashedSolution[],
|
|
1006
|
+
items: HashedItem[] | undefined,
|
|
1007
|
+
): HashedSolution[] {
|
|
1008
|
+
if (!items) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
|
|
1009
|
+
<span class="cstat-no" title="statement not covered" > return [];</span>
|
|
1010
|
+
<span class="cstat-no" title="statement not covered" > }</span>
|
|
1011
|
+
return solutions.map((solution: string | number) => {
|
|
1012
|
+
if (typeof solution === <span class="branch-0 cbranch-no" title="branch not covered" >"string" && isHex(solution)) <span class="branch-0 cbranch-no" title="branch not covered" >{</span></span>
|
|
1013
|
+
// solution must already be a hash
|
|
1014
|
+
// check that solution is in items array
|
|
1015
|
+
<span class="cstat-no" title="statement not covered" > if (!items?.some((item) => item.hash === solution)) {</span>
|
|
1016
|
+
<span class="cstat-no" title="statement not covered" > throw new ProsopoDatasetError("CAPTCHA.INVALID_ITEM_HASH");</span>
|
|
1017
|
+
<span class="cstat-no" title="statement not covered" > }</span>
|
|
1018
|
+
<span class="cstat-no" title="statement not covered" > return solution;</span>
|
|
1019
|
+
<span class="cstat-no" title="statement not covered" > }</span>
|
|
1020
|
+
if (typeof solution === "number") {
|
|
1021
|
+
// else solution must be a number
|
|
1022
|
+
// so lookup the item at that index
|
|
1023
|
+
const item = at(items, solution);
|
|
1024
|
+
// get the hash of the item
|
|
1025
|
+
return item.hash;
|
|
1026
|
+
<span class="branch-0 cbranch-no" title="branch not covered" > }</span>
|
|
1027
|
+
<span class="cstat-no" title="statement not covered" > throw new ProsopoDatasetError("CAPTCHA.INVALID_SOLUTION_TYPE");</span>
|
|
1028
|
+
});
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
/**
|
|
1032
|
+
* Create a unique solution commitment
|
|
1033
|
+
* @param {CaptchaSolution} captcha
|
|
1034
|
+
* @return {string} the hex string hash
|
|
1035
|
+
*/
|
|
1036
|
+
export function computeCaptchaSolutionHash(captcha: CaptchaSolution): string {
|
|
1037
|
+
return hexHashArray([
|
|
1038
|
+
captcha.captchaId,
|
|
1039
|
+
captcha.captchaContentId,
|
|
1040
|
+
[...captcha.solution].sort(),
|
|
1041
|
+
captcha.salt,
|
|
1042
|
+
]);
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
/**
|
|
1046
|
+
* Compute hash for an array of captcha ids, userAccount, and salt, which serves as the identifier for a pending request
|
|
1047
|
+
* @param {string[]} captchaIds
|
|
1048
|
+
* @param {string} userAccount
|
|
1049
|
+
* @param {string} salt
|
|
1050
|
+
* @return {string}
|
|
1051
|
+
*/
|
|
1052
|
+
export function computePendingRequestHash(
|
|
1053
|
+
captchaIds: string[],
|
|
1054
|
+
userAccount: string | number[],
|
|
1055
|
+
salt: string,
|
|
1056
|
+
): string {
|
|
1057
|
+
return hexHashArray([...captchaIds.sort(), userAccount, salt]);
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
/**
|
|
1061
|
+
* Parse the image items in a captcha and pass back a URI if they exist
|
|
1062
|
+
* @param {Item} item
|
|
1063
|
+
* @param {AssetsResolver} assetsResolver
|
|
1064
|
+
*/
|
|
1065
|
+
export <span class="fstat-no" title="function not covered" >function parseCaptchaAssets(</span>
|
|
1066
|
+
<span class="cstat-no" title="statement not covered" > item: Item,</span>
|
|
1067
|
+
<span class="cstat-no" title="statement not covered" > assetsResolver: AssetsResolver | undefined,</span>
|
|
1068
|
+
<span class="cstat-no" title="statement not covered" >): Item {</span>
|
|
1069
|
+
<span class="cstat-no" title="statement not covered" > return {</span>
|
|
1070
|
+
<span class="cstat-no" title="statement not covered" > ...item,</span>
|
|
1071
|
+
<span class="cstat-no" title="statement not covered" > data: assetsResolver?.resolveAsset(item.data).getURL() || item.data,</span>
|
|
1072
|
+
<span class="cstat-no" title="statement not covered" > };</span>
|
|
1073
|
+
<span class="cstat-no" title="statement not covered" >}</span>
|
|
1074
|
+
</pre></td></tr></table></pre>
|
|
1075
|
+
|
|
1076
|
+
<div class='push'></div><!-- for sticky footer -->
|
|
1077
|
+
</div><!-- /wrapper -->
|
|
1078
|
+
<div class='footer quiet pad2 space-top1 center small'>
|
|
1079
|
+
Code coverage generated by
|
|
1080
|
+
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
1081
|
+
at 2025-09-01T13:35:10.030Z
|
|
1082
|
+
</div>
|
|
1083
|
+
<script src="../../prettify.js"></script>
|
|
1084
|
+
<script>
|
|
1085
|
+
window.onload = function () {
|
|
1086
|
+
prettyPrint();
|
|
1087
|
+
};
|
|
1088
|
+
</script>
|
|
1089
|
+
<script src="../../sorter.js"></script>
|
|
1090
|
+
<script src="../../block-navigation.js"></script>
|
|
1091
|
+
</body>
|
|
1092
|
+
</html>
|
|
1093
|
+
|