this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: move to civility/1.0.0

+692 -8070
+3 -3
deno.json
··· 39 39 }, 40 40 "imports": { 41 41 "$/": "./www/", 42 - "@civility/sync": "jsr:@civility/sync@^0.1.1", 43 - "@byojs/storage": "npm:@byojs/storage@^0.12.1", 44 - "@civility/store": "jsr:@civility/store@^0.3.1", 42 + "@civility/store": "jsr:@civility/store@^1.0.0-beta.5", 45 43 "@civility/ui": "jsr:@civility/ui@^0.2.9", 46 44 "@civility/workers": "jsr:@civility/workers@^0.2.5", 47 45 "@flashcard/core": "jsr:@flashcard/core@^0.1.0", 48 46 "@flashcard/schedulers": "jsr:@flashcard/schedulers@^0.1.0", 47 + "@byojs/storage": "npm:@byojs/storage@^0.12.1", 48 + "@byojs/storage/idb": "npm:@byojs/storage@^0.12.1/idb", 49 49 "@leeoniya/ufuzzy": "npm:@leeoniya/ufuzzy@^1.0.19", 50 50 "@std/assert": "jsr:@std/assert@^1.0.19", 51 51 "@std/async": "jsr:@std/async@^1.2.0",
+15 -157
deno.lock
··· 1 1 { 2 2 "version": "5", 3 3 "specifiers": { 4 - "jsr:@civility/store@0.3": "0.3.1", 4 + "jsr:@civility/store@^1.0.0-beta.5": "1.0.0-beta.5", 5 5 "jsr:@civility/store@~0.3.1": "0.3.1", 6 - "jsr:@civility/sync@~0.1.1": "0.1.1", 7 6 "jsr:@civility/ui@~0.2.9": "0.2.9", 8 7 "jsr:@civility/workers@~0.2.5": "0.2.5", 9 - "jsr:@cliffy/ansi@1": "1.0.0", 10 - "jsr:@cliffy/ansi@1.0.0": "1.0.0", 11 - "jsr:@cliffy/command@1": "1.0.0", 12 - "jsr:@cliffy/flags@1": "1.0.0", 13 - "jsr:@cliffy/flags@1.0.0": "1.0.0", 14 - "jsr:@cliffy/internal@1.0.0": "1.0.0", 15 - "jsr:@cliffy/keycode@1": "1.0.0", 16 - "jsr:@cliffy/keycode@1.0.0": "1.0.0", 17 - "jsr:@cliffy/keypress@1": "1.0.0", 18 - "jsr:@cliffy/prompt@1": "1.0.0", 19 - "jsr:@cliffy/table@1": "1.0.0", 20 - "jsr:@cliffy/table@1.0.0": "1.0.0", 21 - "jsr:@flashcard/core@*": "0.1.0", 22 8 "jsr:@flashcard/core@0.1": "0.1.0", 23 9 "jsr:@flashcard/schedulers@0.1": "0.1.0", 24 - "jsr:@flashcard/utils@~0.1.1": "0.1.1", 25 - "jsr:@paulmillr/qr@~0.5.5": "0.5.5", 26 - "jsr:@std/assert@^1.0.18": "1.0.19", 27 10 "jsr:@std/assert@^1.0.19": "1.0.19", 28 11 "jsr:@std/async@^1.2.0": "1.2.0", 29 - "jsr:@std/bytes@^1.0.6": "1.0.6", 30 12 "jsr:@std/collections@^1.1.6": "1.1.6", 31 13 "jsr:@std/csv@^1.0.6": "1.0.6", 32 14 "jsr:@std/dotenv@~0.225.6": "0.225.6", 33 - "jsr:@std/encoding@^1.0.10": "1.0.10", 34 - "jsr:@std/fmt@^1.0.9": "1.0.9", 35 - "jsr:@std/fs@^1.0.23": "1.0.23", 36 15 "jsr:@std/html@^1.0.5": "1.0.5", 37 16 "jsr:@std/internal@^1.0.12": "1.0.12", 38 - "jsr:@std/io@~0.225.3": "0.225.3", 39 - "jsr:@std/path@^1.1.4": "1.1.4", 40 17 "jsr:@std/semver@^1.0.8": "1.0.8", 41 18 "jsr:@std/streams@^1.0.9": "1.0.17", 42 - "jsr:@std/text@^1.0.17": "1.0.17", 19 + "jsr:@std/ulid@1": "1.0.0", 43 20 "jsr:@zod/zod@^4.3.6": "4.3.6", 44 21 "npm:@byojs/storage@~0.12.1": "0.12.1", 45 22 "npm:@leeoniya/ufuzzy@^1.0.19": "1.0.19", 46 23 "npm:cc-cedict@^1.1.1": "1.1.1", 47 24 "npm:chinese-to-pinyin@^1.3.1": "1.3.1", 25 + "npm:fast-json-patch@^3.1.1": "3.1.1", 48 26 "npm:hanzi@^2.1.5": "2.1.5", 49 27 "npm:howler@^2.2.4": "2.2.4", 50 28 "npm:json-stringify-pretty-compact@4": "4.0.0", 51 29 "npm:kuromoji@~0.1.2": "0.1.2", 52 30 "npm:lit@^3.3.2": "3.3.2", 53 - "npm:native-file-system-adapter@^3.0.1": "3.0.1", 54 31 "npm:opencc-js@^1.0.5": "1.0.5", 55 32 "npm:pinyin-to-zhuyin@^1.0.3": "1.0.3", 56 33 "npm:pinyin-tone-tool@^1.0.5": "1.0.5", 57 - "npm:signature_pad@^5.1.3": "5.1.3", 58 - "npm:ts-fsrs@^5.2.3": "5.2.3" 34 + "npm:signature_pad@^5.1.3": "5.1.3" 59 35 }, 60 36 "jsr": { 61 37 "@civility/store@0.3.1": { 62 38 "integrity": "0438f2cdb16145a61a97f5be509cd0b34e7cbd9f71dc657feffe2a4dd7dd0ec3", 63 39 "dependencies": [ 64 - "jsr:@std/fs", 65 40 "jsr:@std/semver" 66 41 ] 67 42 }, 68 - "@civility/sync@0.1.1": { 69 - "integrity": "9ef604671656316dffbeea4c0d8c01488c8a2f54269ddcc68c4d4731317174ad", 43 + "@civility/store@1.0.0-beta.5": { 44 + "integrity": "afb3c70da4d4242faf9ca07e54b269889f2b3bac4e23962272c1350a3062a54d", 70 45 "dependencies": [ 71 - "jsr:@civility/store@0.3", 72 - "jsr:@paulmillr/qr", 73 - "npm:native-file-system-adapter" 46 + "jsr:@std/semver", 47 + "jsr:@std/ulid", 48 + "npm:fast-json-patch" 74 49 ] 75 50 }, 76 51 "@civility/ui@0.2.9": { ··· 83 58 "@civility/workers@0.2.5": { 84 59 "integrity": "5a27340c55972cc71042d4b3ce9c6a8d508e31a77fe6133f94ccdb0d48db0e40" 85 60 }, 86 - "@cliffy/ansi@1.0.0": { 87 - "integrity": "987008f74e50aa72cc1517ffccc769711734a14927bc4599e052efe1b9a840e2", 88 - "dependencies": [ 89 - "jsr:@cliffy/internal", 90 - "jsr:@std/encoding", 91 - "jsr:@std/fmt" 92 - ] 93 - }, 94 - "@cliffy/command@1.0.0": { 95 - "integrity": "c52a241ea68857fcdaff4f3173eb404f8017d7bc35553b6f533c592b89dde7d2", 96 - "dependencies": [ 97 - "jsr:@cliffy/flags@1.0.0", 98 - "jsr:@cliffy/internal", 99 - "jsr:@cliffy/table@1.0.0", 100 - "jsr:@std/fmt", 101 - "jsr:@std/semver", 102 - "jsr:@std/text" 103 - ] 104 - }, 105 - "@cliffy/flags@1.0.0": { 106 - "integrity": "8b57698adc644da8f90422d58976362d41a4ebca39c312ca1c101585d0148feb", 107 - "dependencies": [ 108 - "jsr:@cliffy/internal", 109 - "jsr:@std/text" 110 - ] 111 - }, 112 - "@cliffy/internal@1.0.0": { 113 - "integrity": "1e17ccbcd5420093c0a93e5b3827bbdc9abac5195bacf187edc44665e54bdde6" 114 - }, 115 - "@cliffy/keycode@1.0.0": { 116 - "integrity": "755dbf007be110dcb5625f87eb61b362b6a0ca6835453af03ebd3b34d399cf14" 117 - }, 118 - "@cliffy/keypress@1.0.0": { 119 - "integrity": "dd2e33484bea5fedf9bad5ed4aa0248a53373427d70cb94de4aad3052f948cea", 120 - "dependencies": [ 121 - "jsr:@cliffy/internal", 122 - "jsr:@cliffy/keycode@1.0.0" 123 - ] 124 - }, 125 - "@cliffy/prompt@1.0.0": { 126 - "integrity": "48b4cd35199fda7832f35e1fe0a3e8bc2b1ea49ba57b4ec0e29e22db44e8ca9f", 127 - "dependencies": [ 128 - "jsr:@cliffy/ansi@1.0.0", 129 - "jsr:@cliffy/internal", 130 - "jsr:@cliffy/keycode@1.0.0", 131 - "jsr:@std/assert@^1.0.18", 132 - "jsr:@std/fmt", 133 - "jsr:@std/path", 134 - "jsr:@std/text" 135 - ] 136 - }, 137 - "@cliffy/table@1.0.0": { 138 - "integrity": "3fdaa9e1ef1ea62022108adabd826932bdea8dd05497079896febcd41322907f", 139 - "dependencies": [ 140 - "jsr:@std/fmt" 141 - ] 142 - }, 143 61 "@flashcard/core@0.1.0": { 144 62 "integrity": "8c1379f8738d28bdaaf6ab7f30d35913c22a9ba7e86c74e22cd93ee3d58d4e15", 145 63 "dependencies": [ ··· 150 68 "@flashcard/schedulers@0.1.0": { 151 69 "integrity": "adff86f591b34cb469bc7a08ef463eb9f557e45f3f0c9f45fc27c5bdd7264f5a", 152 70 "dependencies": [ 153 - "jsr:@flashcard/core@0.1", 154 - "npm:ts-fsrs" 71 + "jsr:@flashcard/core" 155 72 ] 156 73 }, 157 - "@flashcard/utils@0.1.1": { 158 - "integrity": "a22b83b8ef743c43e50366c405ce252eddb95bd9ee7b164a5cf0d0cd141747fb", 159 - "dependencies": [ 160 - "jsr:@std/io", 161 - "jsr:@std/path" 162 - ] 163 - }, 164 - "@paulmillr/qr@0.5.5": { 165 - "integrity": "2f8ff22c8d2194f2147eac1b3093f5e85f648c0a8005d5635a617fb72bf5ae38" 166 - }, 167 74 "@std/assert@1.0.19": { 168 75 "integrity": "eaada96ee120cb980bc47e040f82814d786fe8162ecc53c91d8df60b8755991e", 169 76 "dependencies": [ ··· 173 80 "@std/async@1.2.0": { 174 81 "integrity": "c059c6f6d95ca7cc012ae8e8d7164d1697113d54b0b679e4372b354b11c2dee5" 175 82 }, 176 - "@std/bytes@1.0.6": { 177 - "integrity": "f6ac6adbd8ccd99314045f5703e23af0a68d7f7e58364b47d2c7f408aeb5820a" 178 - }, 179 83 "@std/collections@1.1.6": { 180 84 "integrity": "b458160ce65ea5ad35da05d0a5cbee4b583677c8b443a10d7beb0c4ac63f2baa" 181 85 }, ··· 187 91 }, 188 92 "@std/dotenv@0.225.6": { 189 93 "integrity": "1d6f9db72f565bd26790fa034c26e45ecb260b5245417be76c2279e5734c421b" 190 - }, 191 - "@std/encoding@1.0.10": { 192 - "integrity": "8783c6384a2d13abd5e9e87a7ae0520a30e9f56aeeaa3bdf910a3eaaf5c811a1" 193 - }, 194 - "@std/fmt@1.0.9": { 195 - "integrity": "2487343e8899fb2be5d0e3d35013e54477ada198854e52dd05ed0422eddcabe0" 196 - }, 197 - "@std/fs@1.0.23": { 198 - "integrity": "3ecbae4ce4fee03b180fa710caff36bb5adb66631c46a6460aaad49515565a37", 199 - "dependencies": [ 200 - "jsr:@std/internal", 201 - "jsr:@std/path" 202 - ] 203 94 }, 204 95 "@std/html@1.0.5": { 205 96 "integrity": "4e2d693f474cae8c16a920fa5e15a3b72267b94b84667f11a50c6dd1cb18d35e" ··· 207 98 "@std/internal@1.0.12": { 208 99 "integrity": "972a634fd5bc34b242024402972cd5143eac68d8dffaca5eaa4dba30ce17b027" 209 100 }, 210 - "@std/io@0.225.3": { 211 - "integrity": "27b07b591384d12d7b568f39e61dff966b8230559122df1e9fd11cc068f7ddd1", 212 - "dependencies": [ 213 - "jsr:@std/bytes" 214 - ] 215 - }, 216 - "@std/path@1.1.4": { 217 - "integrity": "1d2d43f39efb1b42f0b1882a25486647cb851481862dc7313390b2bb044314b5", 218 - "dependencies": [ 219 - "jsr:@std/internal" 220 - ] 221 - }, 222 101 "@std/semver@1.0.8": { 223 102 "integrity": "dc830e8b8b6a380c895d53fbfd1258dc253704ca57bbe1629ac65fd7830179b7" 224 103 }, 225 104 "@std/streams@1.0.17": { 226 105 "integrity": "7859f3d9deed83cf4b41f19223d4a67661b3d3819e9fc117698f493bf5992140" 227 106 }, 228 - "@std/text@1.0.17": { 229 - "integrity": "4b2c4ef67ae5b6c1dfd447c81c83a43718f52e3c7e748d8b33f694aba9895f95" 107 + "@std/ulid@1.0.0": { 108 + "integrity": "d41c3d27a907714413649fee864b7cde8d42ee68437d22b79d5de4f81d808780" 230 109 }, 231 110 "@zod/zod@4.3.6": { 232 111 "integrity": "7144e5e11f8ffc3cf6e2fca624f6597a8762898aac9868cc8938e9398b96ffe4" ··· 286 165 "readable-stream" 287 166 ] 288 167 }, 289 - "fetch-blob@3.2.0": { 290 - "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", 291 - "dependencies": [ 292 - "node-domexception", 293 - "web-streams-polyfill" 294 - ] 168 + "fast-json-patch@3.1.1": { 169 + "integrity": "sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ==" 295 170 }, 296 171 "fs-extra@11.3.4": { 297 172 "integrity": "sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA==", ··· 364 239 "lodash@4.17.23": { 365 240 "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==" 366 241 }, 367 - "native-file-system-adapter@3.0.1": { 368 - "integrity": "sha512-ocuhsYk2SY0906LPc3QIMW+rCV3MdhqGiy7wV5Bf0e8/5TsMjDdyIwhNiVPiKxzTJLDrLT6h8BoV9ERfJscKhw==", 369 - "optionalDependencies": [ 370 - "fetch-blob" 371 - ] 372 - }, 373 - "node-domexception@1.0.0": { 374 - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", 375 - "deprecated": true 376 - }, 377 242 "node-int64@0.4.0": { 378 243 "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==" 379 244 }, ··· 415 280 "safe-buffer" 416 281 ] 417 282 }, 418 - "ts-fsrs@5.2.3": { 419 - "integrity": "sha512-R3IjceC9WfnvUin6Nx+DwqEzh3Qil6Gg2yEHqvocUcC7Nbi+xDrFg/1fKaYBT0tJedDnDAguXMSX0hijhi859w==" 420 - }, 421 283 "universalify@2.0.1": { 422 284 "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==" 423 285 }, ··· 434 296 "util-deprecate@1.0.2": { 435 297 "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" 436 298 }, 437 - "web-streams-polyfill@3.3.3": { 438 - "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==" 439 - }, 440 299 "zlibjs@0.3.1": { 441 300 "integrity": "sha512-+J9RrgTKOmlxFSDHo0pI1xM6BLVUv+o0ZT9ANtCxGkjIVCCUdx9alUF8Gm+dGLKbkkkidWIHFDZHDMpfITt4+w==" 442 301 } 443 302 }, 444 303 "workspace": { 445 304 "dependencies": [ 446 - "jsr:@civility/store@~0.3.1", 447 - "jsr:@civility/sync@~0.1.1", 305 + "jsr:@civility/store@^1.0.0-beta.5", 448 306 "jsr:@civility/ui@~0.2.9", 449 307 "jsr:@civility/workers@~0.2.5", 450 308 "jsr:@flashcard/core@0.1",
+5 -4
www/components/h-details-editor.ts
··· 29 29 auxMeanings: '', 30 30 } 31 31 #stateInitialized = false 32 + #overrides: Record<string, Override> = {} 32 33 33 34 #onUpdate = () => this.requestUpdate() 34 35 ··· 41 42 super.connectedCallback() 42 43 subjects.addEventListener(this.#onUpdate) 43 44 app.addEventListener(this.#onUpdate) 45 + this.#overrides = app.getAllOverrides() 44 46 } 45 47 46 48 override disconnectedCallback() { ··· 54 56 const subject = subjects.state.byId[this.subjectId] 55 57 if (!subject) return 56 58 const { data, id } = subject 57 - const o = app.state.overrides?.[id] 59 + const overrides = this.#overrides 60 + const o = overrides?.[id] 58 61 this.#state = { 59 62 subjectId: id, 60 63 meaningHint: o?.meaningHint ?? data.meaningHint ?? '', ··· 82 85 const colors = `${color} ${color}-bg ${color}-shadow` 83 86 84 87 const onSave = async () => { 85 - app.state.overrides[subject.id] = this.#state 86 - await app.persist() 87 - app.notify() 88 + await app.saveOverride(this.#state) 88 89 this.dispatchEvent(new CustomEvent('done', { bubbles: true })) 89 90 } 90 91
+6 -7
www/components/h-locale-select.ts
··· 47 47 name="locale" 48 48 @change="${async (e: Event) => { 49 49 const locale = (e.target as HTMLSelectElement).value 50 - app.state.settings.locale = locale 51 - if (locale === ja) app.state.settings.transliteration = Hiragana 52 - if (locale === zh_CN) app.state.settings.transliteration = Pinyin 53 - if (locale === zh_HK) app.state.settings.transliteration = Jyutping 54 - if (locale === zh_TW) app.state.settings.transliteration = Pinyin 55 - await app.persist() 56 - app.notify() 50 + let transliteration = app.settings?.transliteration 51 + if (locale === ja) transliteration = Hiragana 52 + if (locale === zh_CN) transliteration = Pinyin 53 + if (locale === zh_HK) transliteration = Jyutping 54 + if (locale === zh_TW) transliteration = Pinyin 55 + await app.updateSettings({ locale, transliteration }) 57 56 }}" 58 57 > 59 58 ${[zh_CN, zh_HK, zh_TW, ja].map(
+1 -1
www/components/h-streak.ts
··· 25 25 } 26 26 27 27 override render() { 28 - const { currStreak = 0, longestStreak = 0 } = app.state.stats ?? {} 28 + const { currStreak = 0, longestStreak = 0 } = app.stats ?? {} 29 29 return html` 30 30 <section class="streak tc pa1"> 31 31 <span class="streak-count">${getString(
+5 -5
www/components/h-transliteration-select.ts
··· 32 32 class="ba pa2 db purple-shadow" 33 33 name="transliteration" 34 34 @change="${async (e: Event) => { 35 - app.state.settings.transliteration = ( 36 - e.target as HTMLSelectElement 37 - ).value as Transliteration 38 - await app.persist() 39 - app.notify() 35 + await app.updateSettings({ 36 + transliteration: ( 37 + e.target as HTMLSelectElement 38 + ).value as Transliteration, 39 + }) 40 40 }}" 41 41 > 42 42 ${options.map(
+4 -4
www/components/h-user-lang-select.ts
··· 29 29 class="ba pa2 db purple-shadow" 30 30 name="userLang" 31 31 @change="${async (e: Event) => { 32 - app.state.settings.userLang = (e.target as HTMLSelectElement) 33 - .value as UserLang 34 - await app.persist() 35 - app.notify() 32 + await app.updateSettings({ 33 + userLang: (e.target as HTMLSelectElement) 34 + .value as UserLang, 35 + }) 36 36 }}" 37 37 > 38 38 ${USER_LANGS.map(
+33 -26
www/index.html
··· 1 1 <!DOCTYPE html> 2 2 <html lang="en"> 3 + <head> 4 + <meta charset="utf-8" /> 5 + <meta name="viewport" content="width=device-width"> 6 + <meta name="mobile-web-app-capable" content="yes"> 7 + <meta name="apple-mobile-web-app-capable" content="yes"> 8 + <meta name="description" content="An app for learning Hanzi and Kanji"> 3 9 4 - <head> 5 - <meta charset="utf-8" /> 6 - <meta name="viewport" content="width=device-width"> 7 - <meta name="mobile-web-app-capable" content="yes"> 8 - <meta name="apple-mobile-web-app-capable" content="yes"> 9 - <meta name="description" content="An app for learning Hanzi and Kanji"> 10 + <link rel="manifest" href="manifest.json" /> 11 + <link rel="icon" type="image/x-icon" href="/dist/icons/icon.ico" /> 12 + <link rel="apple-touch-icon" href="/dist/icons/icon.png"> 10 13 11 - <link rel="manifest" href="manifest.json" /> 12 - <link rel="icon" type="image/x-icon" href="/dist/icons/icon.ico" /> 13 - <link rel="apple-touch-icon" href="/dist/icons/icon.png"> 14 + <link rel="canonical" href="https://hanzi.bpev.me" /> 15 + <title>HanziApp</title> 14 16 15 - <link rel="canonical" href="https://hanzi.bpev.me" /> 16 - <title>HanziApp</title> 17 + <link 18 + rel="preload" 19 + href="https://bpev.me/civility.min.css" 20 + as="style" 21 + onload="this.onload=null;this.rel='stylesheet'" 22 + /> 23 + <link 24 + rel="preload" 25 + href="/static/styles/theme.css" 26 + as="style" 27 + onload="this.onload=null;this.rel='stylesheet'" 28 + /> 17 29 18 - <link rel="preload" href="https://bpev.me/civility.min.css" as="style" 19 - onload="this.onload=null;this.rel='stylesheet'" /> 20 - <link rel="preload" href="/static/styles/theme.css" as="style" onload="this.onload=null;this.rel='stylesheet'" /> 30 + <noscript> 31 + <link rel="stylesheet" href="https://bpev.me/civility.min.css" /> 32 + <link rel="stylesheet" href="/static/styles/theme.css" /> 33 + </noscript> 21 34 22 - <noscript> 23 - <link rel="stylesheet" href="https://bpev.me/civility.min.css" /> 24 - <link rel="stylesheet" href="/static/styles/theme.css" /> 25 - </noscript> 35 + <script src="/dist/index.js" type="module"></script> 36 + </head> 26 37 27 - <script src="/dist/index.js" type="module"></script> 28 - </head> 29 - 30 - <body style="margin: 0"> 31 - <header></header><ui-sub-header></ui-sub-header> 32 - <main></main> 33 - </body> 34 - 38 + <body style="margin: 0"> 39 + <header></header><ui-sub-header></ui-sub-header> 40 + <main></main> 41 + </body> 35 42 </html>
-164
www/models/__tests__/app.test.ts
··· 1 - import { assertEquals, assertExists } from '@std/assert' 2 - import { Locale } from '$/enums.ts' 3 - import { Store } from '../store.ts' 4 - 5 - let testCounter = 0 6 - 7 - Deno.test.beforeEach(() => { 8 - // Clear all localStorage to ensure clean state 9 - globalThis.localStorage.clear() 10 - testCounter++ 11 - }) 12 - 13 - Deno.test.afterEach(() => { 14 - // Clear localStorage again to remove any residual data 15 - globalThis.localStorage.clear() 16 - }) 17 - 18 - Deno.test('App - userLevel auto-initializes to 1 from clean slate', async () => { 19 - // This test simulates a fresh user with no localStorage data 20 - // The userLevel should automatically be set to 1 (not stay at 0) 21 - 22 - const store = new Store(`hanzi-test-app-${testCounter}`) 23 - 24 - try { 25 - // Get initial data - should be default state 26 - const initialData = await store.getAllData() 27 - 28 - // On a clean slate, userLevels should default to 0 29 - assertEquals( 30 - initialData.userLevels[Locale.zh_CN], 31 - 0, 32 - 'Fresh store should start with userLevel 0', 33 - ) 34 - 35 - // Now simulate what the App does on initialization 36 - // If userLevel is 0, it should be set to 1 37 - if (initialData.userLevels[Locale.zh_CN] === 0) { 38 - await store.setUserLevel(Locale.zh_CN, 1) 39 - } 40 - 41 - // Verify userLevel was set to 1 42 - const updatedData = await store.getAllData() 43 - assertEquals( 44 - updatedData.userLevels[Locale.zh_CN], 45 - 1, 46 - 'After initialization, userLevel should be 1', 47 - ) 48 - 49 - // Verify it persists in localStorage 50 - const persistedData = await store.getAllData() 51 - assertEquals( 52 - persistedData.userLevels[Locale.zh_CN], 53 - 1, 54 - 'UserLevel should persist across reads', 55 - ) 56 - } finally { 57 - await store.clearAllData() 58 - store.dispose() 59 - } 60 - }) 61 - 62 - Deno.test('App - userLevel stays unchanged if already set', async () => { 63 - // This test ensures we don't overwrite an existing userLevel 64 - 65 - const store = new Store(`hanzi-test-app-${testCounter}`) 66 - 67 - try { 68 - // Set userLevel to 5 (existing user) 69 - await store.setUserLevel(Locale.zh_CN, 5) 70 - 71 - const data = await store.getAllData() 72 - assertEquals( 73 - data.userLevels[Locale.zh_CN], 74 - 5, 75 - 'UserLevel should be set to 5', 76 - ) 77 - 78 - // Simulate App initialization logic - should NOT change userLevel 79 - // because it's already non-zero 80 - if (data.userLevels[Locale.zh_CN] === 0) { 81 - await store.setUserLevel(Locale.zh_CN, 1) 82 - } 83 - 84 - const finalData = await store.getAllData() 85 - assertEquals( 86 - finalData.userLevels[Locale.zh_CN], 87 - 5, 88 - 'UserLevel should remain 5 after initialization', 89 - ) 90 - } finally { 91 - await store.clearAllData() 92 - store.dispose() 93 - } 94 - }) 95 - 96 - Deno.test('App - data persists to localStorage', async () => { 97 - // This test verifies that Store actually writes to localStorage 98 - 99 - const storeName = `hanzi-test-app-${testCounter}` 100 - const store = new Store(storeName) 101 - 102 - try { 103 - // Set some data 104 - await store.setUserLevel(Locale.zh_CN, 3) 105 - await store.updateSettings({ playAudio: false }) 106 - 107 - // Give a moment for async operations to complete 108 - await new Promise((resolve) => setTimeout(resolve, 10)) 109 - 110 - // Verify via store API (more reliable than checking localStorage directly) 111 - const data = await store.getAllData() 112 - assertEquals( 113 - data.userLevels[Locale.zh_CN], 114 - 3, 115 - 'UserLevel should be persisted', 116 - ) 117 - assertEquals( 118 - data.settings.playAudio, 119 - false, 120 - 'Settings should be persisted', 121 - ) 122 - 123 - // Also verify localStorage has something 124 - const storedData = localStorage.getItem(storeName) 125 - assertExists(storedData, 'Data should be written to localStorage') 126 - } finally { 127 - await store.clearAllData() 128 - store.dispose() 129 - } 130 - }) 131 - 132 - Deno.test('App - initialization completes without errors', async () => { 133 - // This test ensures the Store can initialize from clean state 134 - 135 - const storeName = `hanzi-test-app-${testCounter}` 136 - // Explicitly clear before creating store 137 - localStorage.removeItem(storeName) 138 - 139 - const store = new Store(storeName) 140 - 141 - try { 142 - // Should be able to get data without errors 143 - const data = await store.getAllData() 144 - 145 - assertExists(data, 'Should get data object') 146 - assertExists(data.settings, 'Should have settings') 147 - assertExists(data.assignments, 'Should have assignments') 148 - assertExists(data.userLevels, 'Should have userLevels') 149 - assertExists(data.flags, 'Should have flags') 150 - assertExists(data.overrides, 'Should have overrides') 151 - 152 - // Check defaults are correct 153 - assertEquals(data.settings.locale, Locale.zh_CN, 'Default locale') 154 - assertEquals( 155 - typeof data.settings.playAudio, 156 - 'boolean', 157 - 'playAudio should be boolean', 158 - ) 159 - assertEquals(data.flags.isFirstLoad, true, 'Default isFirstLoad') 160 - } finally { 161 - await store.clearAllData() 162 - store.dispose() 163 - } 164 - })
-291
www/models/__tests__/schema.test.ts
··· 1 - import { assertEquals, assertExists } from '@std/assert' 2 - import { migrateFromV0 } from '../migrations/v1.ts' 3 - import { migrateFromV1 } from '../migrations/v2.ts' 4 - import { Locale } from '$/enums.ts' 5 - import { CardSortMethod } from '@flashcard/core' 6 - import type { StoreState as StoreStateV0 } from '../schema/v0.ts' 7 - import type { StoreState as StoreStateV1 } from '../schema/v1.ts' 8 - import { StoreState } from '../schema/v3.ts' 9 - 10 - Deno.test('Schema - migrate from v0 to v1 (add efactor)', () => { 11 - const v0Data: StoreStateV0 = { 12 - version: '1.0.0', 13 - assignments: { 14 - [Locale.zh_CN]: { 15 - 'subject-1': { 16 - subjectId: 'subject-1', 17 - difficulty: 0.3, 18 - stability: 0, 19 - interval: 0, 20 - repetition: 0, 21 - markedCompleted: false, 22 - startedAt: new Date('2024-01-01'), 23 - }, 24 - 'subject-2': { 25 - subjectId: 'subject-2', 26 - difficulty: 0.3, 27 - stability: 0, 28 - interval: 0, 29 - repetition: 0, 30 - markedCompleted: false, 31 - passedAt: new Date('2024-01-05'), 32 - }, 33 - 'subject-3': { 34 - subjectId: 'subject-3', 35 - difficulty: 0.3, 36 - stability: 0, 37 - interval: 0, 38 - repetition: 0, 39 - markedCompleted: false, 40 - completedAt: new Date('2024-01-10'), 41 - }, 42 - }, 43 - [Locale.zh_HK]: {}, 44 - [Locale.zh_TW]: {}, 45 - [Locale.ja]: {}, 46 - }, 47 - settings: { 48 - locale: Locale.zh_CN, 49 - playAudio: true, 50 - reviewLimit: null, 51 - learnLimit: 10, 52 - learnSessionSize: 10, 53 - reviewSessionSize: 20, 54 - cardSortMethod: CardSortMethod.Paired, 55 - cardSortOrder: null, 56 - }, 57 - overrides: {}, 58 - userLevels: { 59 - [Locale.zh_CN]: 5, 60 - [Locale.zh_HK]: 0, 61 - [Locale.zh_TW]: 0, 62 - [Locale.ja]: 0, 63 - }, 64 - flags: { 65 - isFirstLoad: false, 66 - isFirstPinyin: true, 67 - isFirstPinyinVocab: true, 68 - }, 69 - } 70 - 71 - const v1Data = migrateFromV0(v0Data) 72 - 73 - // Check efactor was added based on progress state 74 - assertEquals(v1Data.assignments[Locale.zh_CN]['subject-1'].efactor, 1) // startedAt 75 - assertEquals(v1Data.assignments[Locale.zh_CN]['subject-2'].efactor, 5) // passedAt 76 - assertEquals(v1Data.assignments[Locale.zh_CN]['subject-3'].efactor, 9) // completedAt 77 - 78 - // Check other fields preserved 79 - assertEquals(v1Data.settings.locale, Locale.zh_CN) 80 - assertEquals(v1Data.userLevels[Locale.zh_CN], 5) 81 - assertEquals(v1Data.flags.isFirstLoad, false) 82 - }) 83 - 84 - Deno.test('Schema - migrate from v1 to v2 (rename StoreState to StoreState)', () => { 85 - const v1Data: StoreStateV1 = { 86 - version: '2.0.0', 87 - assignments: { 88 - [Locale.zh_CN]: { 89 - 'subject-1': { 90 - subjectId: 'subject-1', 91 - difficulty: 0.3, 92 - stability: 0, 93 - interval: 0, 94 - repetition: 0, 95 - srsId: 1, 96 - efactor: 5, 97 - markedCompleted: false, 98 - }, 99 - }, 100 - [Locale.zh_HK]: {}, 101 - [Locale.zh_TW]: {}, 102 - [Locale.ja]: {}, 103 - }, 104 - settings: { 105 - locale: Locale.zh_CN, 106 - playAudio: true, 107 - reviewLimit: null, 108 - learnLimit: 10, 109 - learnSessionSize: 10, 110 - reviewSessionSize: 20, 111 - cardSortMethod: CardSortMethod.Paired, 112 - cardSortOrder: null, 113 - }, 114 - overrides: {}, 115 - userLevels: { 116 - [Locale.zh_CN]: 5, 117 - [Locale.zh_HK]: 0, 118 - [Locale.zh_TW]: 0, 119 - [Locale.ja]: 0, 120 - }, 121 - flags: { 122 - isFirstLoad: false, 123 - isFirstPinyin: true, 124 - isFirstPinyinVocab: true, 125 - }, 126 - } 127 - 128 - const v2Data = migrateFromV1(v1Data) 129 - 130 - // v1 -> v2 is just a rename, data should be identical 131 - assertEquals(v2Data.assignments[Locale.zh_CN]['subject-1'].efactor, 5) 132 - assertEquals(v2Data.settings.locale, Locale.zh_CN) 133 - assertEquals(v2Data.userLevels[Locale.zh_CN], 5) 134 - }) 135 - 136 - Deno.test('Schema - migrate <4.0.0 (passthrough): initializes games.journal when missing', () => { 137 - // Simulate v3 data that predates the games field 138 - const oldV3Data = { 139 - version: '3.5.0', 140 - assignments: { 141 - [Locale.zh_CN]: {}, 142 - [Locale.zh_HK]: {}, 143 - [Locale.zh_TW]: {}, 144 - [Locale.ja]: {}, 145 - }, 146 - settings: { 147 - locale: Locale.zh_CN, 148 - playAudio: true, 149 - reviewLimit: null, 150 - learnLimit: 10, 151 - learnSessionSize: 10, 152 - reviewSessionSize: 20, 153 - cardSortMethod: CardSortMethod.Paired, 154 - cardSortOrder: null, 155 - }, 156 - overrides: {}, 157 - userLevels: { 158 - [Locale.zh_CN]: 2, 159 - [Locale.zh_HK]: 0, 160 - [Locale.zh_TW]: 0, 161 - [Locale.ja]: 0, 162 - }, 163 - flags: { 164 - isFirstLoad: false, 165 - isFirstPinyin: true, 166 - isFirstPinyinVocab: true, 167 - }, 168 - // no games property 169 - } 170 - 171 - // The <4.0.0 migration spreads data; onMigrationComplete then parses with StoreState 172 - const migrated = StoreState.parse({ 173 - ...oldV3Data, 174 - version: globalThis.__APP_VERSION__, 175 - }) 176 - 177 - assertExists(migrated.games) 178 - assertEquals(Array.isArray(migrated.games.journal), true) 179 - assertEquals(migrated.games.journal.length, 0) 180 - // Existing data preserved 181 - assertEquals(migrated.settings.locale, Locale.zh_CN) 182 - assertEquals(migrated.userLevels[Locale.zh_CN], 2) 183 - }) 184 - 185 - Deno.test('Schema - migrate <4.0.0: preserves existing games.journal entries', () => { 186 - const dataWithJournal = { 187 - version: '3.8.0', 188 - assignments: { 189 - [Locale.zh_CN]: {}, 190 - [Locale.zh_HK]: {}, 191 - [Locale.zh_TW]: {}, 192 - [Locale.ja]: {}, 193 - }, 194 - settings: { 195 - locale: Locale.ja, 196 - playAudio: true, 197 - reviewLimit: null, 198 - learnLimit: 10, 199 - learnSessionSize: 10, 200 - reviewSessionSize: 20, 201 - cardSortMethod: CardSortMethod.Paired, 202 - cardSortOrder: null, 203 - }, 204 - overrides: {}, 205 - userLevels: { 206 - [Locale.zh_CN]: 0, 207 - [Locale.zh_HK]: 0, 208 - [Locale.zh_TW]: 0, 209 - [Locale.ja]: 1, 210 - }, 211 - flags: { 212 - isFirstLoad: false, 213 - isFirstPinyin: true, 214 - isFirstPinyinVocab: true, 215 - }, 216 - games: { 217 - journal: [ 218 - { 219 - date: '2025-01-15', 220 - text: '今日は晴れです。', 221 - wordIds: ['v-00001', 'v-00002'], 222 - }, 223 - ], 224 - }, 225 - } 226 - 227 - const migrated = StoreState.parse({ 228 - ...dataWithJournal, 229 - version: globalThis.__APP_VERSION__, 230 - }) 231 - 232 - assertEquals(migrated.games.journal.length, 1) 233 - assertEquals(migrated.games.journal[0].date, '2025-01-15') 234 - assertEquals(migrated.games.journal[0].text, '今日は晴れです。') 235 - assertEquals(migrated.games.journal[0].wordIds, ['v-00001', 'v-00002']) 236 - }) 237 - 238 - Deno.test('Schema - full migration chain v0 -> v1 -> v2', () => { 239 - const v0Data: StoreStateV0 = { 240 - version: '1.0.0', 241 - assignments: { 242 - [Locale.zh_CN]: { 243 - 'subject-1': { 244 - subjectId: 'subject-1', 245 - difficulty: 0.3, 246 - stability: 0, 247 - interval: 0, 248 - repetition: 0, 249 - markedCompleted: false, 250 - completedAt: new Date('2024-01-10'), 251 - }, 252 - }, 253 - [Locale.zh_HK]: {}, 254 - [Locale.zh_TW]: {}, 255 - [Locale.ja]: {}, 256 - }, 257 - settings: { 258 - locale: Locale.zh_CN, 259 - playAudio: true, 260 - reviewLimit: null, 261 - learnLimit: 10, 262 - learnSessionSize: 10, 263 - reviewSessionSize: 20, 264 - cardSortMethod: CardSortMethod.Paired, 265 - cardSortOrder: null, 266 - }, 267 - overrides: {}, 268 - userLevels: { 269 - [Locale.zh_CN]: 3, 270 - [Locale.zh_HK]: 0, 271 - [Locale.zh_TW]: 0, 272 - [Locale.ja]: 0, 273 - }, 274 - flags: { 275 - isFirstLoad: false, 276 - isFirstPinyin: false, 277 - isFirstPinyinVocab: false, 278 - }, 279 - } 280 - 281 - // Migrate through the chain 282 - const v1Data = migrateFromV0(v0Data) 283 - const v2Data = migrateFromV1(v1Data) 284 - 285 - // Verify final state 286 - assertExists(v2Data.assignments[Locale.zh_CN]['subject-1']) 287 - assertEquals(v2Data.assignments[Locale.zh_CN]['subject-1'].efactor, 9) 288 - assertEquals(v2Data.settings.locale, Locale.zh_CN) 289 - assertEquals(v2Data.userLevels[Locale.zh_CN], 3) 290 - assertEquals(v2Data.flags.isFirstLoad, false) 291 - })
-178
www/models/__tests__/store.test.ts
··· 1 - import { assertEquals, assertExists } from '@std/assert' 2 - import { Locale } from '$/enums.ts' 3 - import { Assignment } from '../schema.ts' 4 - import { Store } from '../store.ts' 5 - 6 - let store: Store | undefined 7 - let testCounter = 0 8 - 9 - Deno.test.beforeEach(() => { 10 - // Clear all localStorage to ensure clean state 11 - globalThis.localStorage.clear() 12 - testCounter++ 13 - }) 14 - 15 - Deno.test.afterEach(async () => { 16 - if (store) { 17 - // Clear the store's data before disposing 18 - await store.clearAllData() 19 - store.dispose() 20 - } 21 - store = undefined 22 - // Clear localStorage again to remove any residual data 23 - globalThis.localStorage.clear() 24 - // Small delay to ensure cleanup completes 25 - await new Promise((resolve) => setTimeout(resolve, 5)) 26 - }) 27 - 28 - Deno.test('Store - save and retrieve assignment', async () => { 29 - store = new Store(`hanzi-test-${testCounter}`) 30 - 31 - const assignment = Assignment.parse({ 32 - subjectId: 'test-subject-1', 33 - difficulty: 0.5, 34 - stability: 1.0, 35 - efactor: 5, 36 - }) 37 - 38 - const saved = await store.saveAssignment(Locale.zh_CN, assignment) 39 - assertEquals(saved, true, 'assignment should save') 40 - 41 - const retrieved = await store.getAssignment(Locale.zh_CN, 'test-subject-1') 42 - assertExists(retrieved, 'assignment should be retrievable') 43 - assertEquals(retrieved.subjectId, 'test-subject-1') 44 - assertEquals(retrieved.efactor, 5) 45 - }) 46 - 47 - // NOTE: This test may be flaky when run with other tests due to localStorage 48 - // persistence across test runs. It passes when run in isolation. 49 - Deno.test('Store - get assignments by locale', async () => { 50 - store = new Store(`hanzi-test-${testCounter}`) 51 - 52 - const assignment1 = Assignment.parse({ subjectId: 'subject-1' }) 53 - const assignment2 = Assignment.parse({ subjectId: 'subject-2' }) 54 - 55 - await store.saveAssignment(Locale.zh_CN, assignment1) 56 - await store.saveAssignment(Locale.zh_CN, assignment2) 57 - 58 - const assignments = await store.getAssignmentsByLocale(Locale.zh_CN) 59 - // Check that our assignments exist rather than exact count 60 - // (exact count may fail due to test isolation issues) 61 - assertExists(assignments['subject-1']) 62 - assertExists(assignments['subject-2']) 63 - assertEquals(Object.keys(assignments).length >= 2, true) 64 - }) 65 - 66 - Deno.test('Store - delete assignment', async () => { 67 - store = new Store(`hanzi-test-${testCounter}`) 68 - 69 - const assignment = Assignment.parse({ subjectId: 'delete-me' }) 70 - await store.saveAssignment(Locale.zh_CN, assignment) 71 - 72 - const beforeDelete = await store.getAssignment(Locale.zh_CN, 'delete-me') 73 - assertExists(beforeDelete, 'assignment should exist before delete') 74 - 75 - const deleted = await store.deleteAssignment(Locale.zh_CN, 'delete-me') 76 - assertEquals(deleted, true, 'delete should succeed') 77 - 78 - const afterDelete = await store.getAssignment(Locale.zh_CN, 'delete-me') 79 - assertEquals(afterDelete, null, 'assignment should not exist after delete') 80 - }) 81 - 82 - Deno.test('Store - save and retrieve override', async () => { 83 - store = new Store(`hanzi-test-${testCounter}`) 84 - 85 - const override = { 86 - subjectId: 'test-subject', 87 - meaningHint: 'Custom hint', 88 - auxMeanings: 'extra, meanings', 89 - } 90 - 91 - await store.saveOverride(override) 92 - const retrieved = await store.getOverride('test-subject') 93 - 94 - assertExists(retrieved) 95 - assertEquals(retrieved.subjectId, 'test-subject') 96 - assertEquals(retrieved.meaningHint, 'Custom hint') 97 - }) 98 - 99 - Deno.test('Store - update settings', async () => { 100 - store = new Store(`hanzi-test-${testCounter}`) 101 - 102 - await store.updateSettings({ 103 - locale: Locale.zh_TW, 104 - playAudio: false, 105 - learnLimit: 20, 106 - }) 107 - 108 - const data = await store.getAllData() 109 - assertEquals(data.settings.locale, Locale.zh_TW) 110 - assertEquals(data.settings.playAudio, false) 111 - assertEquals(data.settings.learnLimit, 20) 112 - }) 113 - 114 - Deno.test('Store - user levels', async () => { 115 - store = new Store(`hanzi-test-${testCounter}`) 116 - 117 - await store.setUserLevel(Locale.zh_CN, 5) 118 - const level = await store.getUserLevel(Locale.zh_CN) 119 - assertEquals(level, 5) 120 - }) 121 - 122 - Deno.test('Store - update flags', async () => { 123 - store = new Store(`hanzi-test-${testCounter}`) 124 - 125 - await store.updateFlags({ 126 - isFirstLoad: false, 127 - isFirstPinyin: false, 128 - }) 129 - 130 - const data = await store.getAllData() 131 - assertEquals(data.flags.isFirstLoad, false) 132 - assertEquals(data.flags.isFirstPinyin, false) 133 - assertEquals(data.flags.isFirstPinyinVocab, true) // unchanged 134 - }) 135 - 136 - // NOTE: This test may be flaky when run with other tests due to localStorage 137 - // persistence across test runs. It passes when run in isolation. 138 - Deno.test('Store - clear all data', async () => { 139 - store = new Store(`hanzi-test-${testCounter}`) 140 - 141 - // Add some data 142 - await store.saveAssignment( 143 - Locale.zh_CN, 144 - Assignment.parse({ subjectId: 'test' }), 145 - ) 146 - await store.setUserLevel(Locale.zh_CN, 5) 147 - 148 - const beforeClear = await store.getAllData() 149 - // Verify our test assignment exists 150 - assertExists(beforeClear.assignments[Locale.zh_CN]['test']) 151 - assertEquals(beforeClear.userLevels[Locale.zh_CN], 5) 152 - 153 - await store.clearAllData() 154 - 155 - const afterClear = await store.getAllData() 156 - // After clear, our test assignment should not exist 157 - assertEquals(afterClear.assignments[Locale.zh_CN]['test'], undefined) 158 - assertEquals(afterClear.userLevels[Locale.zh_CN], 0) 159 - }) 160 - 161 - Deno.test('Store - reactive state updates', async () => { 162 - store = new Store(`hanzi-test-${testCounter}`) 163 - 164 - let notified = false 165 - store.addEventListener(() => { 166 - notified = true 167 - }) 168 - 169 - await store.saveAssignment( 170 - Locale.zh_CN, 171 - Assignment.parse({ subjectId: 'test' }), 172 - ) 173 - 174 - // Give a moment for async notification 175 - await new Promise((resolve) => setTimeout(resolve, 10)) 176 - 177 - assertEquals(notified, true, 'should notify listeners on data change') 178 - })
+331 -164
www/models/app.ts
··· 2 2 * @module App 3 3 * 4 4 * The App is the single source of truth for ALL application data: 5 - * - Persistent user data (via Store/SyncLink) - assignments, settings, overrides, flags 6 - * - Local settings (via LocalStorage) - just syncLinkUrl 7 - * - Transient UI state - error (loading/initialized provided by State class) 5 + * - Persistent user data (via @civility/store) - assignments, settings, overrides, flags 6 + * - Local settings (via localStorage) - just syncLinkUrl 7 + * - Transient UI state - error 8 8 */ 9 - import useJSON from '@civility/sync/json' 10 - import State from '@civility/store/state' 11 - import type { Meaning, Subject } from './subjects.ts' 12 - import { Store } from './store.ts' 13 - import type { Assignment, Override, StoreState } from './schema.ts' 9 + import { Store } from '@civility/store' 10 + import { IDBStorage } from '@civility/store/idb' 11 + import type { 12 + Assignment, 13 + Flags, 14 + JournalEntry, 15 + Override, 16 + Settings, 17 + Stats, 18 + UserLevels, 19 + } from './schema.ts' 20 + import { defaultFlags, defaultSettings, defaultUserLevels } from './schema.ts' 14 21 import { Locale, Transliteration } from '$/enums.ts' 15 22 16 - export type { Assignment, Override, StoreState as AppState } 23 + const backend = new IDBStorage({ dbName: 'hanzi-store' }) 17 24 18 - /** 19 - * AppSettings - LOCAL only settings (not synced) 20 - * Just the SyncLink URL for connecting to remote storage 21 - */ 22 - interface AppSettings { 23 - syncLinkUrl?: string 25 + const defaultStats: Stats = { 26 + currStreak: 0, 27 + longestStreak: 0, 28 + lastStudiedDate: undefined, 24 29 } 25 30 26 - const defaultAppSettings: AppSettings = {} 31 + const store = new Store(backend, { 32 + documents: ['settings', 'flags', 'userLevels', 'stats', 'searchHistory'], 33 + collections: ['assignments', 'overrides', 'journal'], 34 + versions: [{ 35 + version: globalThis.__APP_VERSION__, 36 + schema: { 37 + type: 'object', 38 + properties: { 39 + settings: { type: 'object' }, 40 + flags: { type: 'object' }, 41 + userLevels: { type: 'object' }, 42 + stats: { type: 'object' }, 43 + searchHistory: { type: 'array' }, 44 + assignments: { type: 'object' }, 45 + overrides: { type: 'object' }, 46 + journal: { type: 'object' }, 47 + }, 48 + }, 49 + }], 50 + }) 27 51 28 - /** 29 - * AppState - transient state (errors) 30 - * Note: loading/initialized are provided by State class automatically 31 - */ 32 - interface AppState { 52 + const settingsDoc = store.document<Settings>('settings', defaultSettings) 53 + const flagsDoc = store.document<Flags>('flags', defaultFlags) 54 + const userLevelsDoc = store.document<UserLevels>( 55 + 'userLevels', 56 + defaultUserLevels(), 57 + ) 58 + const statsDoc = store.document<Stats>('stats', defaultStats) 59 + const searchHistoryDoc = store.document<string[]>('searchHistory', []) 60 + 61 + const assignmentsColl = store.collection<Assignment>('assignments') 62 + const overridesColl = store.collection<Override>('overrides') 63 + const journalColl = store.collection<JournalEntry>('journal') 64 + 65 + export type { Assignment, Override } 66 + 67 + export interface AppState { 33 68 error: string | null 34 69 } 35 70 36 - const createSettingsStorage = () => { 37 - return useJSON<AppSettings>( 38 - 'hanzi-settings', 39 - defaultAppSettings, 40 - {}, 41 - ) 42 - } 71 + const defaultAppState: AppState = { error: null } 43 72 44 - export class App extends State<AppState> { 45 - store: Store 46 - settings: State<AppSettings> 73 + export class App { 74 + #subscribers = new Set<() => void>() 75 + #state: AppState = { ...defaultAppState } 47 76 48 77 constructor() { 49 - super({ error: null }) 50 - this.store = new Store('hanzi-data') 51 - this.settings = new State(defaultAppSettings, { 52 - storage: createSettingsStorage(), 53 - }) 78 + store.subscribe(() => this.#notify()) 79 + this.#init() 80 + } 54 81 55 - this.settings.addEventListener(() => void this.notify()) 56 - this.store.addEventListener(() => void this.notify()) 57 - this.settings.waitUntilReady().then(() => void this.connectStore()) 82 + async #init(): Promise<void> { 83 + await Promise.all([ 84 + settingsDoc.preload(), 85 + flagsDoc.preload(), 86 + userLevelsDoc.preload(), 87 + statsDoc.preload(), 88 + searchHistoryDoc.preload(), 89 + assignmentsColl.preload(), 90 + overridesColl.preload(), 91 + journalColl.preload(), 92 + ]) 93 + this.#notify() 58 94 } 59 95 60 - async connectStore() { 61 - const syncUrl = this.settings.state.syncLinkUrl?.trim() 62 - if (syncUrl) { 63 - try { 64 - await this.store.connect(syncUrl) 65 - this.notify() 66 - } catch (error) { 67 - super.state.error = `Failed to connect: ${error}` 68 - this.notify() 69 - } 70 - } 96 + #notify(): void { 97 + for (const cb of this.#subscribers) cb() 71 98 } 72 99 73 - // ====== STATE ACCESS ====== 74 - // For backward compatibility, we expose store data via app.state 75 - // This matches the old API where everything was under app.state 76 - // IMPORTANT: Returns actual store.data reference so mutations persist 100 + addEventListener(fn: () => void): void { 101 + this.#subscribers.add(fn) 102 + } 103 + removeEventListener(fn: () => void): void { 104 + this.#subscribers.delete(fn) 105 + } 77 106 78 - override get state(): StoreState & AppState { 79 - // Return the actual store data with error mixed in 80 - // This allows direct mutations like app.state.assignments[locale] = {...} 81 - return Object.assign(this.store.data, { 82 - error: super.state.error, 83 - }) as StoreState & AppState 107 + #setError(error: string | null): void { 108 + this.#state.error = error 109 + this.#notify() 84 110 } 85 111 86 - // ====== COMPUTED PROPERTIES ====== 112 + notify(): void { 113 + this.#notify() 114 + } 115 + 116 + get store() { 117 + return { 118 + testConnection: () => { 119 + throw new Error('SyncLink is no longer supported') 120 + }, 121 + syncFromServer: () => { 122 + throw new Error('SyncLink is no longer supported') 123 + }, 124 + syncToServer: () => { 125 + throw new Error('SyncLink is no longer supported') 126 + }, 127 + } 128 + } 129 + 130 + // ====== STATE ACCESS ====== 87 131 88 132 get assignments(): Record<string, Assignment> { 89 - return this.store.data.assignments?.[this.locale] || {} 133 + const locale = this.locale 134 + const map = assignmentsColl.value 135 + if (!map) return {} 136 + const result: Record<string, Assignment> = {} 137 + for (const [_key, assignment] of map) { 138 + if (assignment.locale === locale) { 139 + result[assignment.subjectId] = assignment 140 + } 141 + } 142 + return result 90 143 } 91 144 92 145 get locale(): string { 93 - return this.store.data.settings?.locale || Locale.zh_CN 146 + return settingsDoc.value?.locale || Locale.zh_CN 94 147 } 95 148 96 149 get userLang(): string { 97 - return this.store.data.settings?.userLang || 'en' 150 + return settingsDoc.value?.userLang || 'en' 98 151 } 99 152 100 153 get transliteration(): Transliteration { 101 - return this.store.data.settings?.transliteration || Transliteration.Pinyin 154 + return settingsDoc.value?.transliteration || Transliteration.Pinyin 102 155 } 103 156 104 157 get remainingChars(): number { ··· 106 159 } 107 160 108 161 get userLevel(): number { 109 - return this.store.data.userLevels?.[this.locale] || 0 162 + return userLevelsDoc.value?.[this.locale] || 0 110 163 } 111 164 112 165 set userLevel(lvl: number) { 113 - // Synchronously update the store data to avoid race conditions 114 - if (!this.store.data.userLevels) { 115 - this.store.data.userLevels = {} as Record<Locale, number> 166 + const locale = this.locale 167 + const current = userLevelsDoc.value ?? {} 168 + const newLevels = { ...current, [locale]: Math.min(lvl, 56) } 169 + userLevelsDoc.set(newLevels).then(() => this.#notify()) 170 + this.#notify() 171 + } 172 + 173 + // ====== SETTINGS ====== 174 + 175 + get settings(): Settings | undefined { 176 + return settingsDoc.value 177 + } 178 + 179 + get flags(): Flags | undefined { 180 + return flagsDoc.value 181 + } 182 + 183 + async updateSettings(updates: Partial<Settings>): Promise<void> { 184 + const current = settingsDoc.value ?? defaultSettings 185 + await settingsDoc.set({ ...current, ...updates }) 186 + this.#notify() 187 + } 188 + 189 + async updateFlags(updates: Partial<Flags>): Promise<void> { 190 + const current = flagsDoc.value ?? defaultFlags 191 + await flagsDoc.set({ ...current, ...updates }) 192 + this.#notify() 193 + } 194 + 195 + // ====== ASSIGNMENT CRUD ====== 196 + 197 + getAssignment(subjectId: string): Promise<Assignment | null> { 198 + const locale = this.locale 199 + const key = `${locale}__${subjectId}` 200 + return assignmentsColl.get(key) ?? null 201 + } 202 + 203 + async saveAssignment(assignment: Assignment): Promise<boolean> { 204 + const key = `${assignment.locale ?? this.locale}__${assignment.subjectId}` 205 + try { 206 + await assignmentsColl.set(key, assignment) 207 + return true 208 + } catch { 209 + return false 210 + } 211 + } 212 + 213 + async deleteAssignment(subjectId: string): Promise<boolean> { 214 + const locale = this.locale 215 + const key = `${locale}__${subjectId}` 216 + try { 217 + await assignmentsColl.delete(key) 218 + return true 219 + } catch { 220 + return false 221 + } 222 + } 223 + 224 + // ====== OVERRIDE CRUD ====== 225 + 226 + getOverride(subjectId: string): Promise<Override | null> { 227 + return overridesColl.get(subjectId) ?? null 228 + } 229 + 230 + getAllOverrides(): Record<string, Override> { 231 + return Object.fromEntries(overridesColl.value ?? new Map()) 232 + } 233 + 234 + async saveOverride(override: Override): Promise<boolean> { 235 + try { 236 + await overridesColl.set(override.subjectId, override) 237 + return true 238 + } catch { 239 + return false 116 240 } 117 - this.store.data.userLevels[this.locale] = Math.min(lvl, 56) 118 - // Trigger store sync in background (don't await to keep setter synchronous) 119 - this.store.setUserLevel(this.locale as Locale, lvl) 120 - .catch((err) => console.error('Failed to sync userLevel:', err)) 121 - this.notify() 122 241 } 123 242 124 - // ====== SYNC-LINK CONNECTION ====== 243 + async deleteOverride(subjectId: string): Promise<boolean> { 244 + try { 245 + await overridesColl.delete(subjectId) 246 + return true 247 + } catch { 248 + return false 249 + } 250 + } 125 251 126 - async setSyncUrl(syncLinkUrl: string): Promise<void> { 127 - this.settings.state.syncLinkUrl = syncLinkUrl 128 - await this.connectStore() 252 + // ====== JOURNAL ====== 253 + 254 + getJournalEntries(): JournalEntry[] { 255 + const map = journalColl.value 256 + if (!map) return [] 257 + return Array.from(map.values()).sort((a, b) => a.date.localeCompare(b.date)) 258 + } 259 + 260 + async saveJournalEntry(entry: JournalEntry): Promise<boolean> { 261 + try { 262 + await journalColl.set(entry.date, entry) 263 + return true 264 + } catch { 265 + return false 266 + } 267 + } 268 + 269 + // ====== STATS ====== 270 + 271 + get stats(): Stats | undefined { 272 + return statsDoc.value 273 + } 274 + 275 + async updateStats(updates: Partial<Stats>): Promise<void> { 276 + const current = statsDoc.value ?? defaultStats 277 + await statsDoc.set({ ...current, ...updates }) 278 + this.#notify() 279 + } 280 + 281 + // ====== SEARCH HISTORY ====== 282 + 283 + get searchHistory(): string[] { 284 + return searchHistoryDoc.value ?? [] 285 + } 286 + 287 + async addSearchHistory(term: string): Promise<void> { 288 + const current = searchHistoryDoc.value ?? [] 289 + if (!current.includes(term)) { 290 + await searchHistoryDoc.set([term, ...current].slice(0, 100)) 291 + } 292 + } 293 + 294 + async clearSearchHistory(): Promise<void> { 295 + await searchHistoryDoc.set([]) 296 + } 297 + 298 + // ====== SYNC-LINK CONNECTION (REMOVED) ====== 299 + 300 + setSyncUrl(_syncLinkUrl: string): void { 301 + this.#setError( 302 + 'SyncLink is no longer supported. Use import/export instead.', 303 + ) 129 304 } 130 305 131 306 disconnectStore(): void { 132 - this.settings.state.syncLinkUrl = undefined 133 - if (this.store) this.store.disconnect() 134 - this.notify() 307 + // SyncLink is no longer supported 135 308 } 136 309 137 310 get isConnected(): boolean { 138 - return this.store?.isConnected || false 311 + return false 139 312 } 140 313 141 314 /** True once the Store's async init has resolved and real data is available */ 142 315 get storeReady(): boolean { 143 - return this.store.initialized 316 + return settingsDoc.value !== undefined 144 317 } 145 318 146 319 // ====== UTILITY METHODS ====== 147 320 148 - /** 149 - * Persist current state to storage 150 - * Call this after mutating app.state directly 151 - */ 152 - async persist(): Promise<boolean> { 153 - return await this.store.setAllData(this.store.data) 154 - } 155 - 156 - /** TODO: apply override to all locales; override by override-locale */ 157 - applyOverride(subject: Subject): Subject { 158 - const { data, id } = subject 159 - const o = this.store.data.overrides?.[id] 321 + // deno-lint-ignore no-explicit-any 322 + applyOverride(subject: any): any { 323 + const o = overridesColl.value?.get(subject.id) 160 324 if (!o) return subject 161 325 326 + const data = { ...subject.data } 162 327 if (o.meaningHint) data.meaningHint = o.meaningHint 163 328 if (o.readingHint) data.readingHint = o.readingHint 164 329 if (o.meaningMnemonic) data.meaningMnemonic = o.meaningMnemonic 165 330 if (o.readingMnemonic) data.readingMnemonic = o.readingMnemonic 166 331 167 332 if (o.auxMeanings) { 168 - const prevNames = new Set([...data.meanings.map(({ value }) => value)]) 333 + const prevNames = new Set([ 334 + ...data.meanings.map(({ value }: { value: string }) => value), 335 + ]) 169 336 data.meanings = data.meanings.concat( 170 337 o.auxMeanings 171 338 .split(',') 172 - .map((value: string) => 173 - ({ 174 - isAcceptedAnswer: true, 175 - isPrimary: false, 176 - locale: this.locale, 177 - value: value.trim(), 178 - }) as Meaning 179 - ) 339 + .map((value: string) => ({ 340 + isAcceptedAnswer: true, 341 + isPrimary: false, 342 + locale: this.locale, 343 + value: value.trim(), 344 + })) 180 345 .filter(({ value }: { value: string }) => !prevNames.has(value)), 181 346 ) 182 347 } 183 348 184 - return subject 185 - } 186 - 187 - /** 188 - * Load state from external source (used for imports) 189 - * @param loader Function that returns the new state 190 - */ 191 - async loadStore(loader: () => Promise<StoreState>): Promise<void> { 192 - const newState = await loader() 193 - if (this.store) { 194 - await this.store.setAllData(newState) 195 - this.notify() 196 - } 349 + return { ...subject, data } 197 350 } 198 351 199 352 /** Clear any error */ 200 353 clearError(): void { 201 - super.state.error = null 202 - this.notify() 354 + this.#setError(null) 203 355 } 204 356 205 357 /** Export store data */ ··· 209 361 error?: string 210 362 }> { 211 363 try { 212 - return await this.store.exportToFile( 213 - filename || `hanzi-export_${Date.now()}`, 214 - ) 364 + const data = await store.export() 365 + const name = filename ?? `hanzi-export_${Date.now()}` 366 + const blob = new Blob([JSON.stringify(data)], { 367 + type: 'application/json', 368 + }) 369 + const url = URL.createObjectURL(blob) 370 + const a = document.createElement('a') 371 + a.href = url 372 + a.download = `${name}.json` 373 + a.click() 374 + URL.revokeObjectURL(url) 375 + return { success: true, path: `${name}.json` } 215 376 } catch (error) { 216 377 return { 217 378 success: false, ··· 222 383 } 223 384 224 385 /** Import store data */ 225 - async importStore(): Promise<{ 386 + importStore(): Promise<{ 226 387 success: boolean 227 388 path: string 228 389 error?: string 229 390 }> { 230 - try { 231 - const importResult = await this.store.importFromFile() 232 - if (!importResult.success) return importResult 233 - 234 - this.notify() 235 - return importResult 236 - } catch (error) { 237 - return { 238 - success: false, 239 - path: '', 240 - error: error instanceof Error ? error.message : 'Import failed', 391 + return new Promise((resolve) => { 392 + const input = document.createElement('input') 393 + input.type = 'file' 394 + input.accept = '.json' 395 + input.onchange = async () => { 396 + const file = input.files?.[0] 397 + if (!file) { 398 + return resolve({ 399 + success: false, 400 + path: '', 401 + error: 'No file selected', 402 + }) 403 + } 404 + try { 405 + const data = JSON.parse(await file.text()) 406 + await store.import(data) 407 + this.#notify() 408 + resolve({ success: true, path: file.name }) 409 + } catch (error) { 410 + resolve({ 411 + success: false, 412 + path: '', 413 + error: error instanceof Error ? error.message : 'Import failed', 414 + }) 415 + } 241 416 } 242 - } 417 + input.click() 418 + }) 243 419 } 244 420 245 421 /** Reset app data to initial state */ ··· 249 425 error?: string 250 426 }> { 251 427 try { 252 - await this.store.clearAllData() 253 - super.state.error = null 254 - this.notify() 255 - 256 - return { 257 - success: true, 258 - path: '', 259 - } 428 + await store.deleteAll() 429 + this.#setError(null) 430 + this.#notify() 431 + return { success: true, path: '' } 260 432 } catch (error) { 261 433 return { 262 434 success: false, ··· 265 437 } 266 438 } 267 439 } 440 + 441 + /** For backward compatibility - load from external source */ 442 + loadStore(_loader: () => Promise<unknown>): Promise<void> { 443 + this.#setError('loadStore is no longer supported. Use importStore instead.') 444 + return Promise.resolve() 445 + } 446 + 447 + /** For backward compatibility - persist current state */ 448 + persist(): boolean { 449 + return true 450 + } 268 451 } 269 452 270 453 const app = new App() 271 454 272 - /** 273 - * Import state from a JSON file 274 - * @returns Object containing the file path and imported content 275 - */ 276 - export async function importState(): Promise< 277 - { path: string; content: StoreState } 455 + export function importState(): Promise< 456 + { path: string; content: unknown } 278 457 > { 279 - const result = await app.store.importFromFile({ dryRun: true }) 280 - if (!result.success || !result.data) { 281 - throw new Error(result.error || 'Import preview failed') 282 - } 283 - return { path: result.path, content: result.data } 458 + throw new Error( 459 + 'importState is no longer supported. Use app.importStore() instead.', 460 + ) 284 461 } 285 462 286 - /** 287 - * Export state to a JSON file 288 - * @param filename Name of the file (without extension) 289 - * @returns Path where the file was saved 290 - */ 291 463 export async function exportState( 292 464 filename = `hanzi-app-export_${Date.now()}`, 293 465 ): Promise<string> { 294 466 const result = await app.exportStore(filename) 295 - 296 467 if (!result.success) { 297 468 throw new Error(result.error || 'Export failed') 298 469 } 299 - 300 470 return result.path 301 471 } 302 472 303 - /** 304 - * Reset state to defaults 305 - */ 306 473 export async function resetState(): Promise<void> { 307 474 await app.resetAppData() 308 475 }
+31 -2
www/models/downloads.ts
··· 1 - import State from '@civility/store/state' 2 1 import { DownloadStatus, Locale } from '$/enums.ts' 3 2 import { listAudioFiles } from '$/utils/audio.ts' 4 3 ··· 13 12 14 13 export type Downloads = Record<string, Download> 15 14 16 - const downloads = new State<Downloads>({}) 15 + class DownloadState { 16 + #state: Downloads = {} 17 + #subscribers = new Set<() => void>() 18 + 19 + get state(): Downloads { 20 + return this.#state 21 + } 22 + 23 + set state(value: Downloads) { 24 + this.#state = value 25 + this.#notify() 26 + } 27 + 28 + #notify(): void { 29 + for (const cb of this.#subscribers) cb() 30 + } 31 + 32 + addEventListener(fn: () => void): void { 33 + this.#subscribers.add(fn) 34 + } 35 + removeEventListener(fn: () => void): void { 36 + this.#subscribers.delete(fn) 37 + } 17 38 39 + async load(loader: () => Promise<Downloads>): Promise<void> { 40 + const downloads = await loader() 41 + this.#state = downloads 42 + this.#notify() 43 + } 44 + } 45 + 46 + const downloads = new DownloadState() 18 47 downloads.load(listAudioFiles) 19 48 20 49 export default downloads
-51
www/models/migrations/v1.ts
··· 1 - import { Locale } from '$/enums.ts' 2 - import { 3 - type Assignment as AssignmentV0, 4 - type StoreState as StoreStateV0, 5 - } from '../schema/v0.ts' 6 - import { 7 - Assignment, 8 - defaultAssignments, 9 - defaultSettings, 10 - defaultUserLevels, 11 - StoreState, 12 - } from '../schema/v1.ts' 13 - 14 - export function migrateFromV0(input: StoreStateV0): StoreState { 15 - const output: StoreState = { 16 - ...input, 17 - version: '1.0.0', 18 - assignments: defaultAssignments(), 19 - settings: input.settings || defaultSettings, 20 - userLevels: input.userLevels || defaultUserLevels(), 21 - overrides: input.overrides || {}, 22 - } 23 - 24 - // Safely handle assignments that may be null or undefined 25 - if (input.assignments && typeof input.assignments === 'object') { 26 - Object.entries(input.assignments).forEach( 27 - ([locale, assignments]) => { 28 - if (assignments && typeof assignments === 'object') { 29 - output.assignments[locale as Locale] = {} 30 - Object.values(assignments).forEach((a) => { 31 - if (a && a.subjectId) { 32 - output.assignments[locale as Locale][a.subjectId] = 33 - migrateAssignment(a) 34 - } 35 - }) 36 - } 37 - }, 38 - ) 39 - } 40 - 41 - return StoreState.parse(output) 42 - } 43 - 44 - function migrateAssignment(v0: AssignmentV0): Assignment { 45 - let efactor = 0 46 - if (v0.startedAt) efactor = 1 47 - if (v0.passedAt) efactor = 5 48 - if (v0.completedAt) efactor = 9 49 - 50 - return Assignment.parse({ ...v0, efactor }) 51 - }
-7
www/models/migrations/v2.ts
··· 1 - import { type StoreState as StoreStateV1 } from '../schema/v0.ts' 2 - import { StoreState } from '../schema/v1.ts' 3 - 4 - // v2: No data structure changes from v1, just renaming StoreState -> StoreState 5 - export function migrateFromV1(input: StoreStateV1): StoreState { 6 - return StoreState.parse({ ...input, version: '2.0.0' }) 7 - }
-6013
www/models/migrations/v3.ts
··· 1 - // v3: Subject IDs migrated from old numeric strings ("1", "20001") to new 2 - // prefixed string IDs ("c-00001", "v-00001"). The mapping is in the generated 3 - // id-map.json file (v2 numeric ID → new prefixed ID). 4 - import { Locale } from '$/enums.ts' 5 - import { type StoreState } from '../schema/v2.ts' 6 - export * from './v2.ts' 7 - 8 - export function migrateFromV2(input: StoreState): StoreState { 9 - const assignments = {} as StoreState['assignments'] 10 - for (const locale of Object.values(Locale)) { 11 - const old = input.assignments[locale] ?? {} 12 - assignments[locale] = {} 13 - for (const [oldId, assignment] of Object.entries(old)) { 14 - const newId = idMap[oldId] ?? oldId 15 - assignments[locale][newId] = { ...assignment, subjectId: newId } 16 - } 17 - } 18 - 19 - const overrides = {} as StoreState['overrides'] 20 - for (const [oldId, override] of Object.entries(input.overrides ?? {})) { 21 - const newId = idMap[oldId] ?? oldId 22 - overrides[newId] = { ...override, subjectId: newId } 23 - } 24 - 25 - return { 26 - ...input, 27 - assignments, 28 - overrides, 29 - version: '3.0.0', 30 - } 31 - } 32 - 33 - export const idMap: Record<string, string> = { 34 - '1': 'c-00001', 35 - '2': 'c-00003', 36 - '3': 'c-00022', 37 - '4': 'c-00009', 38 - '5': 'c-00015', 39 - '6': 'c-00019', 40 - '7': 'c-00007', 41 - '8': 'c-00004', 42 - '9': 'c-00010', 43 - '10': 'c-00032', 44 - '11': 'c-00037', 45 - '12': 'c-00117', 46 - '13': 'c-00164', 47 - '14': 'c-00039', 48 - '15': 'c-00036', 49 - '16': 'c-00030', 50 - '17': 'c-00011', 51 - '18': 'c-00330', 52 - '19': 'c-00112', 53 - '20': 'c-00150', 54 - '21': 'c-00038', 55 - '22': 'c-00026', 56 - '23': 'c-00262', 57 - '24': 'c-00088', 58 - '25': 'c-00160', 59 - '26': 'c-00419', 60 - '27': 'c-00119', 61 - '28': 'c-00046', 62 - '29': 'c-00018', 63 - '30': 'c-00027', 64 - '31': 'c-00087', 65 - '32': 'c-00210', 66 - '33': 'c-01018', 67 - '34': 'c-02567', 68 - '35': 'c-01237', 69 - '36': 'c-00244', 70 - '37': 'c-00275', 71 - '38': 'c-00236', 72 - '39': 'c-00067', 73 - '40': 'c-00064', 74 - '41': 'c-00581', 75 - '42': 'c-00110', 76 - '43': 'c-00507', 77 - '44': 'c-00733', 78 - '45': 'c-00217', 79 - '46': 'c-00214', 80 - '47': 'c-01087', 81 - '48': 'c-00335', 82 - '49': 'c-00043', 83 - '50': 'c-00216', 84 - '51': 'c-00113', 85 - '52': 'c-00174', 86 - '53': 'c-00075', 87 - '54': 'c-00300', 88 - '55': 'c-20029', 89 - '56': 'c-00513', 90 - '57': 'c-01041', 91 - '58': 'c-00100', 92 - '59': 'c-00235', 93 - '60': 'c-00444', 94 - '61': 'c-00360', 95 - '62': 'c-00093', 96 - '63': 'c-00118', 97 - '64': 'c-00283', 98 - '65': 'c-00121', 99 - '66': 'c-00123', 100 - '67': 'c-00731', 101 - '68': 'c-00625', 102 - '69': 'c-00109', 103 - '70': 'c-00302', 104 - '71': 'c-00163', 105 - '72': 'c-00227', 106 - '73': 'c-00384', 107 - '74': 'c-00225', 108 - '75': 'c-01422', 109 - '76': 'c-00161', 110 - '77': 'c-00078', 111 - '78': 'c-00144', 112 - '79': 'c-00072', 113 - '80': 'c-00530', 114 - '81': 'c-00120', 115 - '82': 'c-02365', 116 - '83': 'c-00443', 117 - '84': 'c-00345', 118 - '85': 'c-00141', 119 - '86': 'c-01079', 120 - '87': 'c-00308', 121 - '88': 'c-00208', 122 - '89': 'c-00583', 123 - '90': 'c-01171', 124 - '91': 'c-01326', 125 - '92': 'c-01324', 126 - '93': 'c-00854', 127 - '94': 'c-01852', 128 - '95': 'c-20030', 129 - '96': 'c-00783', 130 - '97': 'c-00388', 131 - '98': 'c-00548', 132 - '99': 'c-00066', 133 - '100': 'c-00277', 134 - '101': 'c-00582', 135 - '102': 'c-00761', 136 - '103': 'c-00782', 137 - '104': 'c-20004', 138 - '105': 'c-00091', 139 - '106': 'c-00429', 140 - '107': 'c-00307', 141 - '108': 'c-00578', 142 - '109': 'c-00774', 143 - '110': 'c-00458', 144 - '111': 'c-00784', 145 - '112': 'c-00045', 146 - '113': 'c-00466', 147 - '114': 'c-00263', 148 - '115': 'c-00505', 149 - '116': 'c-00055', 150 - '117': 'c-00076', 151 - '118': 'c-00253', 152 - '119': 'c-00063', 153 - '120': 'c-20031', 154 - '121': 'c-00190', 155 - '122': 'c-01166', 156 - '123': 'c-00104', 157 - '124': 'c-00146', 158 - '125': 'c-00222', 159 - '126': 'c-02021', 160 - '127': 'c-00127', 161 - '128': 'c-01185', 162 - '129': 'c-00097', 163 - '130': 'c-01642', 164 - '131': 'c-01081', 165 - '132': 'c-02639', 166 - '133': 'c-02284', 167 - '134': 'c-00279', 168 - '135': 'c-00298', 169 - '136': 'c-20003', 170 - '137': 'c-00105', 171 - '138': 'c-00132', 172 - '139': 'c-20032', 173 - '140': 'c-01479', 174 - '141': 'c-00293', 175 - '142': 'c-00116', 176 - '143': 'c-00204', 177 - '144': 'c-02041', 178 - '145': 'c-20033', 179 - '146': 'c-00148', 180 - '147': 'c-00690', 181 - '148': 'c-00273', 182 - '149': 'c-00528', 183 - '150': 'c-00382', 184 - '151': 'c-00549', 185 - '152': 'c-00880', 186 - '153': 'c-00485', 187 - '154': 'c-00883', 188 - '155': 'c-01198', 189 - '156': 'c-02367', 190 - '157': 'c-01194', 191 - '158': 'c-00296', 192 - '159': 'c-00176', 193 - '160': 'c-00154', 194 - '161': 'c-00122', 195 - '162': 'c-00082', 196 - '163': 'c-00242', 197 - '164': 'c-02249', 198 - '165': 'c-02884', 199 - '166': 'c-00390', 200 - '167': 'c-00080', 201 - '168': 'c-00188', 202 - '169': 'c-00031', 203 - '170': 'c-00520', 204 - '171': 'c-01190', 205 - '172': 'c-00245', 206 - '173': 'c-02155', 207 - '174': 'c-02074', 208 - '175': 'c-01679', 209 - '176': 'c-00538', 210 - '177': 'c-01411', 211 - '178': 'c-00665', 212 - '179': 'c-01408', 213 - '180': 'c-02207', 214 - '181': 'c-01488', 215 - '182': 'c-01064', 216 - '183': 'c-00585', 217 - '184': 'c-01523', 218 - '185': 'c-00805', 219 - '186': 'c-00102', 220 - '187': 'c-01389', 221 - '188': 'c-00336', 222 - '189': 'c-00369', 223 - '190': 'c-00786', 224 - '191': 'c-00536', 225 - '192': 'c-00533', 226 - '193': 'c-00267', 227 - '194': 'c-00450', 228 - '195': 'c-01248', 229 - '196': 'c-01205', 230 - '197': 'c-00061', 231 - '198': 'c-01539', 232 - '199': 'c-00797', 233 - '200': 'c-02681', 234 - '201': 'c-02069', 235 - '202': 'c-00717', 236 - '203': 'c-00192', 237 - '204': 'c-00193', 238 - '205': 'c-00079', 239 - '206': 'c-00707', 240 - '207': 'c-01503', 241 - '208': 'c-01078', 242 - '209': 'c-00432', 243 - '210': 'c-01155', 244 - '211': 'c-00153', 245 - '212': 'c-00744', 246 - '213': 'c-00521', 247 - '214': 'c-00847', 248 - '215': 'c-00114', 249 - '216': 'c-00588', 250 - '217': 'c-01495', 251 - '218': 'c-01042', 252 - '219': 'c-00509', 253 - '220': 'c-00589', 254 - '221': 'c-02201', 255 - '222': 'c-02655', 256 - '223': 'c-01469', 257 - '224': 'c-00175', 258 - '225': 'c-01077', 259 - '226': 'c-02569', 260 - '227': 'c-01881', 261 - '228': 'c-20034', 262 - '229': 'c-00534', 263 - '230': 'c-01697', 264 - '231': 'c-00826', 265 - '232': 'c-01570', 266 - '233': 'c-01707', 267 - '234': 'c-00837', 268 - '235': 'c-00564', 269 - '236': 'c-01515', 270 - '237': 'c-20035', 271 - '238': 'c-20005', 272 - '239': 'c-01441', 273 - '240': 'c-02257', 274 - '241': 'c-01650', 275 - '242': 'c-00482', 276 - '243': 'c-00697', 277 - '244': 'c-02994', 278 - '245': 'c-01632', 279 - '246': 'c-00287', 280 - '247': 'c-01832', 281 - '248': 'c-01011', 282 - '249': 'c-01430', 283 - '250': 'c-01944', 284 - '251': 'c-02867', 285 - '252': 'c-01209', 286 - '253': 'c-00823', 287 - '254': 'c-02379', 288 - '255': 'c-03148', 289 - '256': 'c-02430', 290 - '257': 'c-03135', 291 - '258': 'c-01970', 292 - '259': 'c-02662', 293 - '260': 'c-00999', 294 - '261': 'c-00205', 295 - '262': 'c-02311', 296 - '263': 'c-00861', 297 - '264': 'c-01006', 298 - '265': 'c-00311', 299 - '266': 'c-00194', 300 - '267': 'c-00240', 301 - '268': 'c-01711', 302 - '269': 'c-00355', 303 - '270': 'c-00477', 304 - '271': 'c-00060', 305 - '272': 'c-01500', 306 - '273': 'c-00323', 307 - '274': 'c-01973', 308 - '275': 'c-01269', 309 - '276': 'c-01907', 310 - '277': 'c-02996', 311 - '278': 'c-02235', 312 - '279': 'c-01296', 313 - '280': 'c-20006', 314 - '281': 'c-20036', 315 - '282': 'c-02108', 316 - '283': 'c-01703', 317 - '284': 'c-00621', 318 - '285': 'c-00196', 319 - '286': 'c-00970', 320 - '287': 'c-02911', 321 - '288': 'c-00130', 322 - '289': 'c-00069', 323 - '290': 'c-00014', 324 - '291': 'c-03348', 325 - '292': 'c-00094', 326 - '293': 'c-01562', 327 - '294': 'c-01672', 328 - '295': 'c-01671', 329 - '296': 'c-02758', 330 - '297': 'c-01241', 331 - '298': 'c-01088', 332 - '299': 'c-00128', 333 - '300': 'c-00446', 334 - '301': 'c-00248', 335 - '302': 'c-00098', 336 - '303': 'c-00033', 337 - '304': 'c-00694', 338 - '305': 'c-00710', 339 - '306': 'c-00181', 340 - '307': 'c-00129', 341 - '308': 'c-00048', 342 - '309': 'c-00430', 343 - '310': 'c-00165', 344 - '311': 'c-00767', 345 - '312': 'c-01489', 346 - '313': 'c-00417', 347 - '314': 'c-03240', 348 - '315': 'c-00575', 349 - '316': 'c-00572', 350 - '317': 'c-01734', 351 - '318': 'c-03163', 352 - '319': 'c-01621', 353 - '320': 'c-00540', 354 - '321': 'c-00726', 355 - '322': 'c-02331', 356 - '323': 'c-02410', 357 - '324': 'c-00237', 358 - '325': 'c-00947', 359 - '326': 'c-00969', 360 - '327': 'c-00488', 361 - '328': 'c-00288', 362 - '329': 'c-00212', 363 - '330': 'c-20037', 364 - '331': 'c-00371', 365 - '332': 'c-00321', 366 - '333': 'c-00012', 367 - '334': 'c-00041', 368 - '335': 'c-00532', 369 - '336': 'c-01636', 370 - '337': 'c-00152', 371 - '338': 'c-01197', 372 - '339': 'c-01127', 373 - '340': 'c-00366', 374 - '341': 'c-01164', 375 - '342': 'c-20038', 376 - '343': 'c-00324', 377 - '344': 'c-00047', 378 - '345': 'c-00436', 379 - '346': 'c-00543', 380 - '347': 'c-00844', 381 - '348': 'c-02040', 382 - '349': 'c-00777', 383 - '350': 'c-00353', 384 - '351': 'c-02477', 385 - '352': 'c-20039', 386 - '353': 'c-00944', 387 - '354': 'c-01584', 388 - '355': 'c-01801', 389 - '356': 'c-00876', 390 - '357': 'c-01244', 391 - '358': 'c-02309', 392 - '359': 'c-01987', 393 - '360': 'c-02614', 394 - '361': 'c-02523', 395 - '362': 'c-00587', 396 - '363': 'c-01282', 397 - '364': 'c-01104', 398 - '365': 'c-01160', 399 - '366': 'c-01063', 400 - '367': 'c-02168', 401 - '368': 'c-03259', 402 - '369': 'c-01774', 403 - '370': 'c-03084', 404 - '371': 'c-00325', 405 - '372': 'c-01035', 406 - '373': 'c-01334', 407 - '374': 'c-00182', 408 - '375': 'c-00358', 409 - '376': 'c-02864', 410 - '377': 'c-20040', 411 - '378': 'c-20041', 412 - '379': 'c-00137', 413 - '380': 'c-00392', 414 - '381': 'c-00814', 415 - '382': 'c-00483', 416 - '383': 'c-00519', 417 - '384': 'c-00996', 418 - '385': 'c-00021', 419 - '386': 'c-00760', 420 - '387': 'c-00140', 421 - '388': 'c-00029', 422 - '389': 'c-20042', 423 - '390': 'c-01474', 424 - '391': 'c-00838', 425 - '392': 'c-00228', 426 - '393': 'c-00471', 427 - '394': 'c-02895', 428 - '395': 'c-00600', 429 - '396': 'c-02702', 430 - '397': 'c-01327', 431 - '398': 'c-02623', 432 - '399': 'c-00332', 433 - '400': 'c-02611', 434 - '401': 'c-01122', 435 - '402': 'c-02146', 436 - '403': 'c-00413', 437 - '404': 'c-00226', 438 - '405': 'c-01208', 439 - '406': 'c-00675', 440 - '407': 'c-02322', 441 - '408': 'c-02438', 442 - '409': 'c-00198', 443 - '410': 'c-00693', 444 - '411': 'c-00751', 445 - '412': 'c-00997', 446 - '413': 'c-00908', 447 - '414': 'c-00573', 448 - '415': 'c-01102', 449 - '416': 'c-00747', 450 - '417': 'c-20043', 451 - '418': 'c-01952', 452 - '419': 'c-03121', 453 - '420': 'c-02362', 454 - '421': 'c-01508', 455 - '422': 'c-00831', 456 - '423': 'c-00295', 457 - '424': 'c-00401', 458 - '425': 'c-01276', 459 - '426': 'c-00070', 460 - '427': 'c-00142', 461 - '428': 'c-00301', 462 - '429': 'c-20044', 463 - '430': 'c-01174', 464 - '431': 'c-00389', 465 - '432': 'c-01092', 466 - '433': 'c-00239', 467 - '434': 'c-00249', 468 - '435': 'c-00271', 469 - '436': 'c-00206', 470 - '437': 'c-00265', 471 - '438': 'c-00696', 472 - '439': 'c-02687', 473 - '440': 'c-01366', 474 - '441': 'c-00393', 475 - '442': 'c-20045', 476 - '443': 'c-01273', 477 - '444': 'c-01694', 478 - '445': 'c-00719', 479 - '446': 'c-00285', 480 - '447': 'c-01609', 481 - '448': 'c-01278', 482 - '449': 'c-00867', 483 - '450': 'c-01789', 484 - '451': 'c-01758', 485 - '452': 'c-02520', 486 - '453': 'c-00168', 487 - '454': 'c-02542', 488 - '455': 'c-01338', 489 - '456': 'c-01868', 490 - '457': 'c-00341', 491 - '458': 'c-02875', 492 - '459': 'c-01622', 493 - '460': 'c-01355', 494 - '461': 'c-06716', 495 - '462': 'c-02391', 496 - '463': 'c-01585', 497 - '464': 'c-02723', 498 - '465': 'c-00981', 499 - '466': 'c-01225', 500 - '467': 'c-00316', 501 - '468': 'c-00544', 502 - '469': 'c-01418', 503 - '470': 'c-02025', 504 - '471': 'c-03378', 505 - '472': 'c-01589', 506 - '473': 'c-01550', 507 - '474': 'c-02270', 508 - '475': 'c-01069', 509 - '476': 'c-00377', 510 - '477': 'c-01139', 511 - '478': 'c-02179', 512 - '479': 'c-20008', 513 - '480': 'c-02263', 514 - '481': 'c-01223', 515 - '482': 'c-02027', 516 - '483': 'c-03005', 517 - '484': 'c-01545', 518 - '485': 'c-01290', 519 - '486': 'c-01052', 520 - '487': 'c-01693', 521 - '488': 'c-00781', 522 - '489': 'c-01928', 523 - '490': 'c-02345', 524 - '491': 'c-01224', 525 - '492': 'c-00441', 526 - '493': 'c-01847', 527 - '494': 'c-02001', 528 - '495': 'c-01645', 529 - '496': 'c-03049', 530 - '497': 'c-02227', 531 - '498': 'c-02517', 532 - '499': 'c-02355', 533 - '500': 'c-01806', 534 - '501': 'c-00315', 535 - '502': 'c-02751', 536 - '503': 'c-20046', 537 - '504': 'c-00897', 538 - '505': 'c-00492', 539 - '506': 'c-00938', 540 - '507': 'c-00921', 541 - '508': 'c-01640', 542 - '509': 'c-02256', 543 - '510': 'c-01556', 544 - '511': 'c-02741', 545 - '512': 'c-00486', 546 - '513': 'c-00379', 547 - '514': 'c-20009', 548 - '515': 'c-02044', 549 - '516': 'c-01862', 550 - '517': 'c-02145', 551 - '518': 'c-01754', 552 - '519': 'c-01551', 553 - '520': 'c-00035', 554 - '521': 'c-01983', 555 - '522': 'c-01932', 556 - '523': 'c-00822', 557 - '524': 'c-00924', 558 - '525': 'c-01019', 559 - '526': 'c-02486', 560 - '527': 'c-03207', 561 - '528': 'c-01407', 562 - '529': 'c-00791', 563 - '530': 'c-02514', 564 - '531': 'c-02045', 565 - '532': 'c-02282', 566 - '533': 'c-01717', 567 - '534': 'c-02745', 568 - '535': 'c-01038', 569 - '536': 'c-01350', 570 - '537': 'c-00949', 571 - '538': 'c-00556', 572 - '539': 'c-02324', 573 - '540': 'c-00554', 574 - '541': 'c-00180', 575 - '542': 'c-00739', 576 - '543': 'c-01964', 577 - '544': 'c-00611', 578 - '545': 'c-01200', 579 - '546': 'c-01192', 580 - '547': 'c-00209', 581 - '548': 'c-01730', 582 - '549': 'c-00442', 583 - '550': 'c-02337', 584 - '551': 'c-01286', 585 - '552': 'c-01423', 586 - '553': 'c-02333', 587 - '554': 'c-00902', 588 - '555': 'c-01543', 589 - '556': 'c-00594', 590 - '557': 'c-01119', 591 - '558': 'c-01140', 592 - '559': 'c-02359', 593 - '560': 'c-01915', 594 - '561': 'c-01559', 595 - '562': 'c-01951', 596 - '563': 'c-01955', 597 - '564': 'c-03268', 598 - '565': 'c-01869', 599 - '566': 'c-03054', 600 - '567': 'c-01348', 601 - '568': 'c-01221', 602 - '569': 'c-02260', 603 - '570': 'c-02051', 604 - '571': 'c-02955', 605 - '572': 'c-20010', 606 - '573': 'c-00763', 607 - '574': 'c-01232', 608 - '575': 'c-01431', 609 - '576': 'c-01555', 610 - '577': 'c-00269', 611 - '578': 'c-00334', 612 - '579': 'c-00178', 613 - '580': 'c-00099', 614 - '581': 'c-02009', 615 - '582': 'c-00877', 616 - '583': 'c-02170', 617 - '584': 'c-02341', 618 - '585': 'c-00081', 619 - '586': 'c-00339', 620 - '587': 'c-01285', 621 - '588': 'c-00231', 622 - '589': 'c-00310', 623 - '590': 'c-01938', 624 - '591': 'c-00171', 625 - '592': 'c-02185', 626 - '593': 'c-00367', 627 - '594': 'c-02961', 628 - '595': 'c-01300', 629 - '596': 'c-00911', 630 - '597': 'c-01948', 631 - '598': 'c-01463', 632 - '599': 'c-02726', 633 - '600': 'c-00894', 634 - '601': 'c-01356', 635 - '602': 'c-02900', 636 - '603': 'c-01969', 637 - '604': 'c-01337', 638 - '605': 'c-02450', 639 - '606': 'c-02885', 640 - '607': 'c-20047', 641 - '608': 'c-02918', 642 - '609': 'c-02385', 643 - '610': 'c-03233', 644 - '611': 'c-00297', 645 - '612': 'c-02080', 646 - '613': 'c-02174', 647 - '614': 'c-00704', 648 - '615': 'c-00951', 649 - '616': 'c-00294', 650 - '617': 'c-02920', 651 - '618': 'c-01960', 652 - '619': 'c-02936', 653 - '620': 'c-00652', 654 - '621': 'c-02631', 655 - '622': 'c-02870', 656 - '623': 'c-02046', 657 - '624': 'c-02373', 658 - '625': 'c-03278', 659 - '626': 'c-00044', 660 - '627': 'c-02498', 661 - '628': 'c-02976', 662 - '629': 'c-02489', 663 - '630': 'c-03285', 664 - '631': 'c-01552', 665 - '632': 'c-00816', 666 - '633': 'c-00023', 667 - '634': 'c-00605', 668 - '635': 'c-02999', 669 - '636': 'c-02616', 670 - '637': 'c-00608', 671 - '638': 'c-00243', 672 - '639': 'c-01036', 673 - '640': 'c-01849', 674 - '641': 'c-02157', 675 - '642': 'c-00656', 676 - '643': 'c-00892', 677 - '644': 'c-20011', 678 - '645': 'c-02476', 679 - '646': 'c-01502', 680 - '647': 'c-00550', 681 - '648': 'c-03094', 682 - '649': 'c-01809', 683 - '650': 'c-02122', 684 - '651': 'c-01546', 685 - '652': 'c-01641', 686 - '653': 'c-02795', 687 - '654': 'c-03342', 688 - '655': 'c-02852', 689 - '656': 'c-02120', 690 - '657': 'c-01998', 691 - '658': 'c-02012', 692 - '659': 'c-03357', 693 - '660': 'c-01613', 694 - '661': 'c-01455', 695 - '662': 'c-20012', 696 - '663': 'c-00721', 697 - '664': 'c-00770', 698 - '665': 'c-02591', 699 - '666': 'c-01294', 700 - '667': 'c-20013', 701 - '668': 'c-20014', 702 - '669': 'c-01439', 703 - '670': 'c-02112', 704 - '671': 'c-00928', 705 - '672': 'c-03341', 706 - '673': 'c-01202', 707 - '674': 'c-00654', 708 - '675': 'c-02147', 709 - '676': 'c-00337', 710 - '677': 'c-00586', 711 - '678': 'c-01701', 712 - '679': 'c-03169', 713 - '680': 'c-02669', 714 - '681': 'c-01624', 715 - '682': 'c-02788', 716 - '683': 'c-02880', 717 - '684': 'c-02251', 718 - '685': 'c-01161', 719 - '686': 'c-02707', 720 - '687': 'c-01382', 721 - '688': 'c-02031', 722 - '689': 'c-02881', 723 - '690': 'c-02728', 724 - '691': 'c-01980', 725 - '692': 'c-00053', 726 - '693': 'c-00418', 727 - '694': 'c-00317', 728 - '695': 'c-03300', 729 - '696': 'c-00836', 730 - '697': 'c-01204', 731 - '698': 'c-00649', 732 - '699': 'c-00616', 733 - '700': 'c-02035', 734 - '701': 'c-20015', 735 - '702': 'c-00700', 736 - '703': 'c-01874', 737 - '704': 'c-02764', 738 - '705': 'c-00318', 739 - '706': 'c-01509', 740 - '707': 'c-20016', 741 - '708': 'c-03185', 742 - '709': 'c-02721', 743 - '710': 'c-02005', 744 - '711': 'c-00423', 745 - '712': 'c-00808', 746 - '713': 'c-02958', 747 - '714': 'c-01195', 748 - '715': 'c-02361', 749 - '716': 'c-02634', 750 - '717': 'c-02280', 751 - '718': 'c-01071', 752 - '719': 'c-01304', 753 - '720': 'c-00688', 754 - '721': 'c-00684', 755 - '722': 'c-20048', 756 - '723': 'c-00410', 757 - '724': 'c-01572', 758 - '725': 'c-00179', 759 - '726': 'c-00841', 760 - '727': 'c-20049', 761 - '728': 'c-01722', 762 - '729': 'c-00089', 763 - '730': 'c-00139', 764 - '731': 'c-00796', 765 - '732': 'c-00040', 766 - '733': 'c-00860', 767 - '734': 'c-00737', 768 - '735': 'c-00107', 769 - '736': 'c-01025', 770 - '737': 'c-20050', 771 - '738': 'c-02272', 772 - '739': 'c-00052', 773 - '740': 'c-00604', 774 - '741': 'c-00407', 775 - '742': 'c-01743', 776 - '743': 'c-01268', 777 - '744': 'c-00135', 778 - '745': 'c-00828', 779 - '746': 'c-01510', 780 - '747': 'c-02954', 781 - '748': 'c-00735', 782 - '749': 'c-03703', 783 - '750': 'c-00499', 784 - '751': 'c-00479', 785 - '752': 'c-00349', 786 - '753': 'c-01486', 787 - '754': 'c-00948', 788 - '755': 'c-00508', 789 - '756': 'c-00106', 790 - '757': 'c-03123', 791 - '758': 'c-00503', 792 - '759': 'c-01050', 793 - '760': 'c-00054', 794 - '761': 'c-00440', 795 - '762': 'c-00203', 796 - '763': 'c-00155', 797 - '764': 'c-01399', 798 - '765': 'c-20051', 799 - '766': 'c-01577', 800 - '767': 'c-20017', 801 - '768': 'c-00472', 802 - '769': 'c-00771', 803 - '770': 'c-01940', 804 - '771': 'c-01651', 805 - '772': 'c-00187', 806 - '773': 'c-03374', 807 - '774': 'c-01617', 808 - '775': 'c-00890', 809 - '776': 'c-01168', 810 - '777': 'c-02544', 811 - '778': 'c-00218', 812 - '779': 'c-00830', 813 - '780': 'c-00481', 814 - '781': 'c-00202', 815 - '782': 'c-02127', 816 - '783': 'c-00491', 817 - '784': 'c-00595', 818 - '785': 'c-00849', 819 - '786': 'c-01871', 820 - '787': 'c-00778', 821 - '788': 'c-00681', 822 - '789': 'c-02353', 823 - '790': 'c-01365', 824 - '791': 'c-01596', 825 - '792': 'c-02105', 826 - '793': 'c-00327', 827 - '794': 'c-20052', 828 - '795': 'c-01177', 829 - '796': 'c-00734', 830 - '797': 'c-00576', 831 - '798': 'c-01172', 832 - '799': 'c-02153', 833 - '800': 'c-01733', 834 - '801': 'c-00682', 835 - '802': 'c-02360', 836 - '803': 'c-00633', 837 - '804': 'c-01866', 838 - '805': 'c-00169', 839 - '806': 'c-03265', 840 - '807': 'c-01962', 841 - '808': 'c-00703', 842 - '809': 'c-00319', 843 - '810': 'c-00411', 844 - '811': 'c-02747', 845 - '812': 'c-00522', 846 - '813': 'c-01496', 847 - '814': 'c-00909', 848 - '815': 'c-01329', 849 - '816': 'c-02071', 850 - '817': 'c-00373', 851 - '818': 'c-00615', 852 - '819': 'c-01373', 853 - '820': 'c-02405', 854 - '821': 'c-03153', 855 - '822': 'c-01424', 856 - '823': 'c-20065', 857 - '824': 'c-02557', 858 - '825': 'c-01673', 859 - '826': 'c-02034', 860 - '827': 'c-01344', 861 - '828': 'c-00593', 862 - '829': 'c-20018', 863 - '830': 'c-01700', 864 - '831': 'c-00655', 865 - '832': 'c-01726', 866 - '833': 'c-01325', 867 - '834': 'c-00518', 868 - '835': 'c-02802', 869 - '836': 'c-01845', 870 - '837': 'c-01633', 871 - '838': 'c-00686', 872 - '839': 'c-00272', 873 - '840': 'c-01573', 874 - '841': 'c-20053', 875 - '842': 'c-20054', 876 - '843': 'c-02259', 877 - '844': 'c-01234', 878 - '845': 'c-01257', 879 - '846': 'c-04965', 880 - '847': 'c-01695', 881 - '848': 'c-00467', 882 - '849': 'c-02131', 883 - '850': 'c-00946', 884 - '851': 'c-02097', 885 - '852': 'c-00525', 886 - '853': 'c-01548', 887 - '854': 'c-00391', 888 - '855': 'c-00952', 889 - '856': 'c-02432', 890 - '857': 'c-02546', 891 - '858': 'c-01647', 892 - '859': 'c-00708', 893 - '860': 'c-00558', 894 - '861': 'c-02626', 895 - '862': 'c-20055', 896 - '863': 'c-00074', 897 - '864': 'c-02039', 898 - '865': 'c-02193', 899 - '866': 'c-01212', 900 - '867': 'c-00699', 901 - '868': 'c-02389', 902 - '869': 'c-02394', 903 - '870': 'c-00211', 904 - '871': 'c-02354', 905 - '872': 'c-01850', 906 - '873': 'c-02134', 907 - '874': 'c-02738', 908 - '875': 'c-02470', 909 - '876': 'c-01395', 910 - '877': 'c-01956', 911 - '878': 'c-01853', 912 - '879': 'c-01010', 913 - '880': 'c-01858', 914 - '881': 'c-01560', 915 - '882': 'c-01271', 916 - '883': 'c-20019', 917 - '884': 'c-02267', 918 - '885': 'c-02289', 919 - '886': 'c-01020', 920 - '887': 'c-01302', 921 - '888': 'c-00561', 922 - '889': 'c-03116', 923 - '890': 'c-02808', 924 - '891': 'c-02906', 925 - '892': 'c-20020', 926 - '893': 'c-01720', 927 - '894': 'c-00057', 928 - '895': 'c-01732', 929 - '896': 'c-00542', 930 - '897': 'c-00560', 931 - '898': 'c-02148', 932 - '899': 'c-01594', 933 - '900': 'c-02084', 934 - '901': 'c-02059', 935 - '902': 'c-00246', 936 - '903': 'c-02677', 937 - '904': 'c-01678', 938 - '905': 'c-01810', 939 - '906': 'c-02813', 940 - '907': 'c-02863', 941 - '908': 'c-00256', 942 - '909': 'c-01367', 943 - '910': 'c-01876', 944 - '911': 'c-01867', 945 - '912': 'c-00494', 946 - '913': 'c-01580', 947 - '914': 'c-01945', 948 - '915': 'c-02734', 949 - '916': 'c-02781', 950 - '917': 'c-00762', 951 - '918': 'c-00887', 952 - '919': 'c-01714', 953 - '920': 'c-03167', 954 - '921': 'c-02232', 955 - '922': 'c-01935', 956 - '923': 'c-02144', 957 - '924': 'c-01788', 958 - '925': 'c-00232', 959 - '926': 'c-02481', 960 - '927': 'c-00006', 961 - '928': 'c-03172', 962 - '929': 'c-00515', 963 - '930': 'c-01841', 964 - '931': 'c-02693', 965 - '932': 'c-00732', 966 - '933': 'c-01293', 967 - '934': 'c-05933', 968 - '935': 'c-03209', 969 - '936': 'c-02099', 970 - '937': 'c-02981', 971 - '938': 'c-00083', 972 - '939': 'c-03174', 973 - '940': 'c-00712', 974 - '941': 'c-00535', 975 - '942': 'c-00687', 976 - '943': 'c-00885', 977 - '944': 'c-02024', 978 - '945': 'c-02123', 979 - '946': 'c-01336', 980 - '947': 'c-03204', 981 - '948': 'c-01485', 982 - '949': 'c-02152', 983 - '950': 'c-00651', 984 - '951': 'c-01762', 985 - '952': 'c-03095', 986 - '953': 'c-00469', 987 - '954': 'c-20021', 988 - '955': 'c-00136', 989 - '956': 'c-00398', 990 - '957': 'c-02694', 991 - '958': 'c-02265', 992 - '959': 'c-00073', 993 - '960': 'c-02692', 994 - '961': 'c-00221', 995 - '962': 'c-01654', 996 - '963': 'c-00455', 997 - '964': 'c-00567', 998 - '965': 'c-02488', 999 - '966': 'c-03061', 1000 - '967': 'c-00945', 1001 - '968': 'c-03453', 1002 - '969': 'c-02766', 1003 - '970': 'c-00385', 1004 - '971': 'c-00328', 1005 - '972': 'c-02840', 1006 - '973': 'c-20056', 1007 - '974': 'c-02392', 1008 - '975': 'c-03242', 1009 - '976': 'c-01884', 1010 - '977': 'c-00728', 1011 - '978': 'c-02192', 1012 - '979': 'c-00468', 1013 - '980': 'c-00889', 1014 - '981': 'c-01877', 1015 - '982': 'c-02890', 1016 - '983': 'c-02915', 1017 - '984': 'c-02538', 1018 - '985': 'c-00584', 1019 - '986': 'c-00454', 1020 - '987': 'c-00134', 1021 - '988': 'c-02871', 1022 - '989': 'c-02132', 1023 - '990': 'c-02792', 1024 - '991': 'c-02118', 1025 - '992': 'c-01059', 1026 - '993': 'c-07841', 1027 - '994': 'c-03138', 1028 - '995': 'c-02800', 1029 - '996': 'c-01549', 1030 - '997': 'c-00825', 1031 - '998': 'c-03033', 1032 - '999': 'c-00498', 1033 - '1000': 'c-00888', 1034 - '1001': 'c-02791', 1035 - '1002': 'c-00086', 1036 - '1003': 'c-03499', 1037 - '1004': 'c-01528', 1038 - '1005': 'c-01292', 1039 - '1006': 'c-02559', 1040 - '1007': 'c-01175', 1041 - '1008': 'c-00523', 1042 - '1009': 'c-00400', 1043 - '1010': 'c-03199', 1044 - '1011': 'c-01712', 1045 - '1012': 'c-03427', 1046 - '1013': 'c-20000', 1047 - '1014': 'c-00425', 1048 - '1015': 'c-01121', 1049 - '1016': 'c-01646', 1050 - '1017': 'c-02189', 1051 - '1018': 'c-01631', 1052 - '1019': 'c-00320', 1053 - '1020': 'c-03333', 1054 - '1021': 'c-00977', 1055 - '1022': 'c-00461', 1056 - '1023': 'c-00002', 1057 - '1024': 'c-02043', 1058 - '1025': 'c-00422', 1059 - '1026': 'c-00606', 1060 - '1027': 'c-00282', 1061 - '1028': 'c-00108', 1062 - '1029': 'c-00903', 1063 - '1030': 'c-00738', 1064 - '1031': 'c-01002', 1065 - '1032': 'c-00250', 1066 - '1033': 'c-00402', 1067 - '1034': 'c-00810', 1068 - '1035': 'c-00552', 1069 - '1036': 'c-00028', 1070 - '1037': 'c-00768', 1071 - '1038': 'c-03144', 1072 - '1039': 'c-01386', 1073 - '1040': 'c-00636', 1074 - '1041': 'c-00201', 1075 - '1042': 'c-02558', 1076 - '1043': 'c-00601', 1077 - '1044': 'c-01053', 1078 - '1045': 'c-00280', 1079 - '1046': 'c-02053', 1080 - '1047': 'c-00372', 1081 - '1048': 'c-03272', 1082 - '1049': 'c-01281', 1083 - '1050': 'c-01680', 1084 - '1051': 'c-02932', 1085 - '1052': 'c-00383', 1086 - '1053': 'c-00493', 1087 - '1054': 'c-00101', 1088 - '1055': 'c-02832', 1089 - '1056': 'c-00290', 1090 - '1057': 'c-01135', 1091 - '1058': 'c-01524', 1092 - '1059': 'c-01240', 1093 - '1060': 'c-01963', 1094 - '1061': 'c-01082', 1095 - '1062': 'c-01482', 1096 - '1063': 'c-02847', 1097 - '1064': 'c-01013', 1098 - '1065': 'c-02501', 1099 - '1066': 'c-01735', 1100 - '1067': 'c-00233', 1101 - '1068': 'c-02196', 1102 - '1069': 'c-00495', 1103 - '1070': 'c-01275', 1104 - '1071': 'c-01206', 1105 - '1072': 'c-00546', 1106 - '1073': 'c-00722', 1107 - '1074': 'c-00848', 1108 - '1075': 'c-00527', 1109 - '1076': 'c-00529', 1110 - '1077': 'c-00305', 1111 - '1078': 'c-03522', 1112 - '1079': 'c-20001', 1113 - '1080': 'c-02048', 1114 - '1081': 'c-02081', 1115 - '1082': 'c-00421', 1116 - '1083': 'c-02285', 1117 - '1084': 'c-02506', 1118 - '1085': 'c-02603', 1119 - '1086': 'c-00357', 1120 - '1087': 'c-02244', 1121 - '1088': 'c-00343', 1122 - '1089': 'c-00713', 1123 - '1090': 'c-00356', 1124 - '1091': 'c-00438', 1125 - '1092': 'c-00095', 1126 - '1093': 'c-00292', 1127 - '1094': 'c-00125', 1128 - '1095': 'c-01099', 1129 - '1096': 'c-00431', 1130 - '1097': 'c-02529', 1131 - '1098': 'c-01520', 1132 - '1099': 'c-00512', 1133 - '1100': 'c-00685', 1134 - '1101': 'c-00773', 1135 - '1102': 'c-00399', 1136 - '1103': 'c-20022', 1137 - '1104': 'c-00346', 1138 - '1105': 'c-00397', 1139 - '1106': 'c-02413', 1140 - '1107': 'c-01251', 1141 - '1108': 'c-01239', 1142 - '1109': 'c-00856', 1143 - '1110': 'c-01605', 1144 - '1111': 'c-02364', 1145 - '1112': 'c-01892', 1146 - '1113': 'c-00881', 1147 - '1114': 'c-01446', 1148 - '1115': 'c-00490', 1149 - '1116': 'c-01138', 1150 - '1117': 'c-00756', 1151 - '1118': 'c-02683', 1152 - '1119': 'c-00871', 1153 - '1120': 'c-00789', 1154 - '1121': 'c-01467', 1155 - '1122': 'c-01829', 1156 - '1123': 'c-20057', 1157 - '1124': 'c-20058', 1158 - '1125': 'c-00840', 1159 - '1126': 'c-02221', 1160 - '1127': 'c-00988', 1161 - '1128': 'c-01415', 1162 - '1129': 'c-02420', 1163 - '1130': 'c-00775', 1164 - '1131': 'c-00915', 1165 - '1132': 'c-00966', 1166 - '1133': 'c-01822', 1167 - '1134': 'c-20023', 1168 - '1135': 'c-02953', 1169 - '1136': 'c-00785', 1170 - '1137': 'c-01487', 1171 - '1138': 'c-00769', 1172 - '1139': 'c-00620', 1173 - '1140': 'c-01228', 1174 - '1141': 'c-01568', 1175 - '1142': 'c-01093', 1176 - '1143': 'c-00034', 1177 - '1144': 'c-20059', 1178 - '1145': 'c-20060', 1179 - '1146': 'c-02602', 1180 - '1147': 'c-02516', 1181 - '1148': 'c-02449', 1182 - '1149': 'c-01512', 1183 - '1150': 'c-01639', 1184 - '1151': 'c-00965', 1185 - '1152': 'c-01267', 1186 - '1153': 'c-01393', 1187 - '1154': 'c-01908', 1188 - '1155': 'c-01037', 1189 - '1156': 'c-02000', 1190 - '1157': 'c-00626', 1191 - '1158': 'c-01454', 1192 - '1159': 'c-02547', 1193 - '1160': 'c-02076', 1194 - '1161': 'c-02317', 1195 - '1162': 'c-01753', 1196 - '1163': 'c-02613', 1197 - '1164': 'c-01514', 1198 - '1165': 'c-03951', 1199 - '1166': 'c-02213', 1200 - '1167': 'c-20002', 1201 - '1168': 'c-01308', 1202 - '1169': 'c-00531', 1203 - '1170': 'c-20062', 1204 - '1171': 'c-01358', 1205 - '1172': 'c-01996', 1206 - '1173': 'c-01889', 1207 - '1174': 'c-01686', 1208 - '1175': 'c-00896', 1209 - '1176': 'c-00415', 1210 - '1177': 'c-20063', 1211 - '1178': 'c-00612', 1212 - '1179': 'c-02214', 1213 - '1180': 'c-00497', 1214 - '1181': 'c-00913', 1215 - '1182': 'c-01775', 1216 - '1183': 'c-01303', 1217 - '1184': 'c-00348', 1218 - '1185': 'c-00478', 1219 - '1186': 'c-03853', 1220 - '1187': 'c-01941', 1221 - '1188': 'c-00157', 1222 - '1189': 'c-00905', 1223 - '1190': 'c-01289', 1224 - '1191': 'c-01048', 1225 - '1192': 'c-01264', 1226 - '1193': 'c-00658', 1227 - '1194': 'c-02316', 1228 - '1195': 'c-01362', 1229 - '1196': 'c-01669', 1230 - '1197': 'c-00925', 1231 - '1198': 'c-01538', 1232 - '1199': 'c-00276', 1233 - '1200': 'c-01608', 1234 - '1201': 'c-00904', 1235 - '1202': 'c-01107', 1236 - '1203': 'c-00787', 1237 - '1204': 'c-01403', 1238 - '1205': 'c-00884', 1239 - '1206': 'c-02055', 1240 - '1207': 'c-01513', 1241 - '1208': 'c-01033', 1242 - '1209': 'c-00643', 1243 - '1210': 'c-01075', 1244 - '1211': 'c-02387', 1245 - '1212': 'c-00506', 1246 - '1213': 'c-01157', 1247 - '1214': 'c-01315', 1248 - '1215': 'c-01186', 1249 - '1216': 'c-00574', 1250 - '1217': 'c-00571', 1251 - '1218': 'c-07519', 1252 - '1219': 'c-02164', 1253 - '1220': 'c-01383', 1254 - '1221': 'c-02375', 1255 - '1222': 'c-01113', 1256 - '1223': 'c-01798', 1257 - '1224': 'c-00729', 1258 - '1225': 'c-02177', 1259 - '1226': 'c-00470', 1260 - '1227': 'c-01105', 1261 - '1228': 'c-01156', 1262 - '1229': 'c-01231', 1263 - '1230': 'c-00962', 1264 - '1231': 'c-00766', 1265 - '1232': 'c-01062', 1266 - '1233': 'c-00565', 1267 - '1234': 'c-01786', 1268 - '1235': 'c-01922', 1269 - '1236': 'c-02162', 1270 - '1237': 'c-03317', 1271 - '1238': 'c-00937', 1272 - '1239': 'c-02321', 1273 - '1240': 'c-01449', 1274 - '1241': 'c-01676', 1275 - '1242': 'c-00832', 1276 - '1243': 'c-03279', 1277 - '1244': 'c-00959', 1278 - '1245': 'c-01189', 1279 - '1246': 'c-01590', 1280 - '1247': 'c-02301', 1281 - '1248': 'c-02092', 1282 - '1249': 'c-01091', 1283 - '1250': 'c-01521', 1284 - '1251': 'c-02526', 1285 - '1252': 'c-02439', 1286 - '1253': 'c-01309', 1287 - '1254': 'c-02528', 1288 - '1255': 'c-01557', 1289 - '1256': 'c-01126', 1290 - '1257': 'c-00755', 1291 - '1258': 'c-01558', 1292 - '1259': 'c-00447', 1293 - '1260': 'c-01744', 1294 - '1261': 'c-01820', 1295 - '1262': 'c-20024', 1296 - '1263': 'c-02649', 1297 - '1264': 'c-00942', 1298 - '1265': 'c-00939', 1299 - '1266': 'c-02511', 1300 - '1267': 'c-01394', 1301 - '1268': 'c-01391', 1302 - '1269': 'c-01913', 1303 - '1270': 'c-01994', 1304 - '1271': 'c-02651', 1305 - '1272': 'c-02548', 1306 - '1273': 'c-02348', 1307 - '1274': 'c-00624', 1308 - '1275': 'c-02515', 1309 - '1276': 'c-02161', 1310 - '1277': 'c-01218', 1311 - '1278': 'c-01405', 1312 - '1279': 'c-00197', 1313 - '1280': 'c-00983', 1314 - '1281': 'c-00170', 1315 - '1282': 'c-02057', 1316 - '1283': 'c-00362', 1317 - '1284': 'c-04380', 1318 - '1285': 'c-01901', 1319 - '1286': 'c-02100', 1320 - '1287': 'c-04500', 1321 - '1288': 'c-01725', 1322 - '1289': 'c-00456', 1323 - '1290': 'c-00457', 1324 - '1291': 'c-01400', 1325 - '1292': 'c-00314', 1326 - '1293': 'c-00474', 1327 - '1294': 'c-00286', 1328 - '1295': 'c-00765', 1329 - '1296': 'c-00452', 1330 - '1297': 'c-00632', 1331 - '1298': 'c-01494', 1332 - '1299': 'c-01579', 1333 - '1300': 'c-00811', 1334 - '1301': 'c-03065', 1335 - '1302': 'c-01444', 1336 - '1303': 'c-02023', 1337 - '1304': 'c-01039', 1338 - '1305': 'c-01158', 1339 - '1306': 'c-01310', 1340 - '1307': 'c-01406', 1341 - '1308': 'c-01067', 1342 - '1309': 'c-00971', 1343 - '1310': 'c-01330', 1344 - '1311': 'c-02253', 1345 - '1312': 'c-01802', 1346 - '1313': 'c-01761', 1347 - '1314': 'c-01675', 1348 - '1315': 'c-02113', 1349 - '1316': 'c-00537', 1350 - '1317': 'c-01068', 1351 - '1318': 'c-00464', 1352 - '1319': 'c-00427', 1353 - '1320': 'c-01468', 1354 - '1321': 'c-01133', 1355 - '1322': 'c-01363', 1356 - '1323': 'c-02054', 1357 - '1324': 'c-01153', 1358 - '1325': 'c-01340', 1359 - '1326': 'c-01323', 1360 - '1327': 'c-02931', 1361 - '1328': 'c-01396', 1362 - '1329': 'c-00820', 1363 - '1330': 'c-00359', 1364 - '1331': 'c-01151', 1365 - '1332': 'c-01471', 1366 - '1333': 'c-01670', 1367 - '1334': 'c-02376', 1368 - '1335': 'c-02670', 1369 - '1336': 'c-01949', 1370 - '1337': 'c-02188', 1371 - '1338': 'c-00916', 1372 - '1339': 'c-02111', 1373 - '1340': 'c-01656', 1374 - '1341': 'c-02247', 1375 - '1342': 'c-03147', 1376 - '1343': 'c-02094', 1377 - '1344': 'c-00807', 1378 - '1345': 'c-00933', 1379 - '1346': 'c-02933', 1380 - '1347': 'c-02777', 1381 - '1348': 'c-02643', 1382 - '1349': 'c-00812', 1383 - '1350': 'c-02842', 1384 - '1351': 'c-01872', 1385 - '1352': 'c-02060', 1386 - '1353': 'c-00322', 1387 - '1354': 'c-02163', 1388 - '1355': 'c-01162', 1389 - '1356': 'c-01692', 1390 - '1357': 'c-02780', 1391 - '1358': 'c-01387', 1392 - '1359': 'c-02854', 1393 - '1360': 'c-01165', 1394 - '1361': 'c-00926', 1395 - '1362': 'c-02833', 1396 - '1363': 'c-01456', 1397 - '1364': 'c-02403', 1398 - '1365': 'c-00794', 1399 - '1366': 'c-00365', 1400 - '1367': 'c-02675', 1401 - '1368': 'c-01505', 1402 - '1369': 'c-02609', 1403 - '1370': 'c-02761', 1404 - '1371': 'c-01755', 1405 - '1372': 'c-00968', 1406 - '1373': 'c-02453', 1407 - '1374': 'c-02139', 1408 - '1375': 'c-01691', 1409 - '1376': 'c-02618', 1410 - '1377': 'c-03006', 1411 - '1378': 'c-02052', 1412 - '1379': 'c-00623', 1413 - '1380': 'c-03087', 1414 - '1381': 'c-02756', 1415 - '1382': 'c-01352', 1416 - '1383': 'c-03013', 1417 - '1384': 'c-01888', 1418 - '1385': 'c-01738', 1419 - '1386': 'c-01124', 1420 - '1387': 'c-01547', 1421 - '1388': 'c-00990', 1422 - '1389': 'c-05467', 1423 - '1390': 'c-00972', 1424 - '1391': 'c-01916', 1425 - '1392': 'c-01328', 1426 - '1393': 'c-00827', 1427 - '1394': 'c-02810', 1428 - '1395': 'c-03488', 1429 - '1396': 'c-01737', 1430 - '1397': 'c-02957', 1431 - '1398': 'c-01115', 1432 - '1399': 'c-01516', 1433 - '1400': 'c-00980', 1434 - '1401': 'c-03142', 1435 - '1402': 'c-01398', 1436 - '1403': 'c-03103', 1437 - '1404': 'c-02968', 1438 - '1405': 'c-03000', 1439 - '1406': 'c-01047', 1440 - '1407': 'c-02083', 1441 - '1408': 'c-03686', 1442 - '1409': 'c-01436', 1443 - '1410': 'c-04433', 1444 - '1411': 'c-05017', 1445 - '1412': 'c-02062', 1446 - '1413': 'c-00886', 1447 - '1414': 'c-03328', 1448 - '1415': 'c-02406', 1449 - '1416': 'c-02709', 1450 - '1417': 'c-00568', 1451 - '1418': 'c-02553', 1452 - '1419': 'c-01065', 1453 - '1420': 'c-00901', 1454 - '1421': 'c-01261', 1455 - '1422': 'c-01024', 1456 - '1423': 'c-02239', 1457 - '1424': 'c-01971', 1458 - '1425': 'c-01211', 1459 - '1426': 'c-02351', 1460 - '1427': 'c-00058', 1461 - '1428': 'c-01032', 1462 - '1429': 'c-01851', 1463 - '1430': 'c-02610', 1464 - '1431': 'c-00640', 1465 - '1432': 'c-02110', 1466 - '1433': 'c-01132', 1467 - '1434': 'c-01918', 1468 - '1435': 'c-00914', 1469 - '1436': 'c-01583', 1470 - '1437': 'c-02458', 1471 - '1438': 'c-20064', 1472 - '1439': 'c-00238', 1473 - '1440': 'c-00347', 1474 - '1441': 'c-00978', 1475 - '1442': 'c-01746', 1476 - '1443': 'c-01967', 1477 - '1444': 'c-00405', 1478 - '1445': 'c-01705', 1479 - '1446': 'c-02564', 1480 - '1447': 'c-02695', 1481 - '1448': 'c-01765', 1482 - '1449': 'c-01376', 1483 - '1450': 'c-00566', 1484 - '1451': 'c-02107', 1485 - '1452': 'c-03035', 1486 - '1453': 'c-01370', 1487 - '1454': 'c-02473', 1488 - '1455': 'c-03008', 1489 - '1456': 'c-03078', 1490 - '1457': 'c-02277', 1491 - '1458': 'c-01981', 1492 - '1459': 'c-02187', 1493 - '1460': 'c-01143', 1494 - '1461': 'c-01848', 1495 - '1462': 'c-02909', 1496 - '1463': 'c-02822', 1497 - '1464': 'c-02749', 1498 - '1465': 'c-00579', 1499 - '1466': 'c-00340', 1500 - '1467': 'c-01787', 1501 - '1468': 'c-01588', 1502 - '1469': 'c-00368', 1503 - '1470': 'c-02288', 1504 - '1471': 'c-01061', 1505 - '1472': 'c-02332', 1506 - '1473': 'c-00757', 1507 - '1474': 'c-02566', 1508 - '1475': 'c-00931', 1509 - '1476': 'c-02184', 1510 - '1477': 'c-01291', 1511 - '1478': 'c-02098', 1512 - '1479': 'c-02956', 1513 - '1480': 'c-02589', 1514 - '1481': 'c-03355', 1515 - '1482': 'c-01246', 1516 - '1483': 'c-02109', 1517 - '1484': 'c-02330', 1518 - '1485': 'c-02325', 1519 - '1486': 'c-02805', 1520 - '1487': 'c-01046', 1521 - '1488': 'c-02328', 1522 - '1489': 'c-02889', 1523 - '1490': 'c-02302', 1524 - '1491': 'c-02765', 1525 - '1492': 'c-00637', 1526 - '1493': 'c-02879', 1527 - '1494': 'c-02496', 1528 - '1495': 'c-01301', 1529 - '1496': 'c-02648', 1530 - '1497': 'c-03164', 1531 - '1498': 'c-01341', 1532 - '1499': 'c-00989', 1533 - '1500': 'c-01332', 1534 - '1501': 'c-03270', 1535 - '1502': 'c-01299', 1536 - '1503': 'c-01476', 1537 - '1504': 'c-00386', 1538 - '1505': 'c-02771', 1539 - '1506': 'c-02229', 1540 - '1507': 'c-02654', 1541 - '1508': 'c-03003', 1542 - '1509': 'c-02086', 1543 - '1510': 'c-01844', 1544 - '1511': 'c-02273', 1545 - '1512': 'c-01519', 1546 - '1513': 'c-01682', 1547 - '1514': 'c-01128', 1548 - '1515': 'c-01563', 1549 - '1516': 'c-03155', 1550 - '1517': 'c-02356', 1551 - '1518': 'c-02782', 1552 - '1519': 'c-02713', 1553 - '1520': 'c-02241', 1554 - '1521': 'c-01752', 1555 - '1522': 'c-03195', 1556 - '1523': 'c-03053', 1557 - '1524': 'c-01429', 1558 - '1525': 'c-05715', 1559 - '1526': 'c-03655', 1560 - '1527': 'c-06306', 1561 - '1528': 'c-00475', 1562 - '1529': 'c-00147', 1563 - '1530': 'c-01287', 1564 - '1531': 'c-02580', 1565 - '1532': 'c-02390', 1566 - '1533': 'c-00409', 1567 - '1534': 'c-02471', 1568 - '1535': 'c-02541', 1569 - '1536': 'c-01056', 1570 - '1537': 'c-02455', 1571 - '1538': 'c-00306', 1572 - '1539': 'c-03131', 1573 - '1540': 'c-02508', 1574 - '1541': 'c-02757', 1575 - '1542': 'c-03392', 1576 - '1543': 'c-01870', 1577 - '1544': 'c-00570', 1578 - '1545': 'c-00215', 1579 - '1546': 'c-02676', 1580 - '1547': 'c-02167', 1581 - '1548': 'c-02908', 1582 - '1549': 'c-01274', 1583 - '1550': 'c-20025', 1584 - '1551': 'c-01252', 1585 - '1552': 'c-01602', 1586 - '1553': 'c-00912', 1587 - '1554': 'c-00963', 1588 - '1555': 'c-01321', 1589 - '1556': 'c-20026', 1590 - '1557': 'c-01027', 1591 - '1558': 'c-02622', 1592 - '1559': 'c-02701', 1593 - '1560': 'c-02459', 1594 - '1561': 'c-02400', 1595 - '1562': 'c-03194', 1596 - '1563': 'c-02786', 1597 - '1564': 'c-03336', 1598 - '1565': 'c-01950', 1599 - '1566': 'c-01982', 1600 - '1567': 'c-02838', 1601 - '1568': 'c-02532', 1602 - '1569': 'c-01618', 1603 - '1570': 'c-00603', 1604 - '1571': 'c-02026', 1605 - '1572': 'c-01773', 1606 - '1573': 'c-02327', 1607 - '1574': 'c-01593', 1608 - '1575': 'c-03287', 1609 - '1576': 'c-01148', 1610 - '1577': 'c-03192', 1611 - '1578': 'c-00159', 1612 - '1579': 'c-03244', 1613 - '1580': 'c-03015', 1614 - '1581': 'c-03376', 1615 - '1582': 'c-02582', 1616 - '1583': 'c-00824', 1617 - '1584': 'c-00868', 1618 - '1585': 'c-02962', 1619 - '1586': 'c-01392', 1620 - '1587': 'c-03140', 1621 - '1588': 'c-01361', 1622 - '1589': 'c-02347', 1623 - '1590': 'c-03041', 1624 - '1591': 'c-01933', 1625 - '1592': 'c-02834', 1626 - '1593': 'c-01880', 1627 - '1594': 'c-03001', 1628 - '1595': 'c-02951', 1629 - '1596': 'c-02125', 1630 - '1597': 'c-03351', 1631 - '1598': 'c-02552', 1632 - '1599': 'c-02128', 1633 - '1600': 'c-00553', 1634 - '1601': 'c-03112', 1635 - '1602': 'c-02208', 1636 - '1603': 'c-02990', 1637 - '1604': 'c-01665', 1638 - '1605': 'c-02562', 1639 - '1606': 'c-01120', 1640 - '1607': 'c-01262', 1641 - '1608': 'c-03375', 1642 - '1609': 'c-01283', 1643 - '1610': 'c-02018', 1644 - '1611': 'c-01887', 1645 - '1612': 'c-01934', 1646 - '1613': 'c-02003', 1647 - '1614': 'c-03090', 1648 - '1615': 'c-03295', 1649 - '1616': 'c-01794', 1650 - '1617': 'c-02604', 1651 - '1618': 'c-05161', 1652 - '1619': 'c-02554', 1653 - '1620': 'c-02313', 1654 - '1621': 'c-03222', 1655 - '1622': 'c-05473', 1656 - '1623': 'c-01629', 1657 - '1624': 'c-05794', 1658 - '1625': 'c-00017', 1659 - '1626': 'c-03390', 1660 - '1627': 'c-02743', 1661 - '1628': 'c-02746', 1662 - '1629': 'c-03128', 1663 - '1630': 'c-01721', 1664 - '1631': 'c-02729', 1665 - '1632': 'c-03141', 1666 - '1633': 'c-02395', 1667 - '1634': 'c-03136', 1668 - '1635': 'c-02102', 1669 - '1636': 'c-01553', 1670 - '1637': 'c-01634', 1671 - '1638': 'c-02323', 1672 - '1639': 'c-00671', 1673 - '1640': 'c-00563', 1674 - '1641': 'c-00312', 1675 - '1642': 'c-03025', 1676 - '1643': 'c-20061', 1677 - '1644': 'c-00487', 1678 - '1645': 'c-02633', 1679 - '1646': 'c-00882', 1680 - '1647': 'c-01029', 1681 - '1648': 'c-01942', 1682 - '1649': 'c-01342', 1683 - '1650': 'c-01419', 1684 - '1651': 'c-00720', 1685 - '1652': 'c-02659', 1686 - '1653': 'c-01288', 1687 - '1654': 'c-03151', 1688 - '1655': 'c-02841', 1689 - '1656': 'c-02466', 1690 - '1657': 'c-03445', 1691 - '1658': 'c-03352', 1692 - '1659': 'c-02480', 1693 - '1660': 'c-00364', 1694 - '1661': 'c-02596', 1695 - '1662': 'c-01117', 1696 - '1663': 'c-03229', 1697 - '1664': 'c-00842', 1698 - '1665': 'c-02682', 1699 - '1666': 'c-03484', 1700 - '1667': 'c-00090', 1701 - '1668': 'c-03292', 1702 - '1669': 'c-02599', 1703 - '1670': 'c-00865', 1704 - '1671': 'c-00167', 1705 - '1672': 'c-02435', 1706 - '1673': 'c-02830', 1707 - '1674': 'c-02173', 1708 - '1675': 'c-03152', 1709 - '1676': 'c-02428', 1710 - '1677': 'c-02969', 1711 - '1678': 'c-00702', 1712 - '1679': 'c-03255', 1713 - '1680': 'c-02821', 1714 - '1681': 'c-02893', 1715 - '1682': 'c-01626', 1716 - '1683': 'c-03402', 1717 - '1684': 'c-02848', 1718 - '1685': 'c-02844', 1719 - '1686': 'c-01448', 1720 - '1687': 'c-00408', 1721 - '1688': 'c-01660', 1722 - '1689': 'c-03224', 1723 - '1690': 'c-03428', 1724 - '1691': 'c-01379', 1725 - '1692': 'c-03313', 1726 - '1693': 'c-02960', 1727 - '1694': 'c-03062', 1728 - '1695': 'c-02250', 1729 - '1696': 'c-03168', 1730 - '1697': 'c-03042', 1731 - '1698': 'c-02571', 1732 - '1699': 'c-02461', 1733 - '1700': 'c-03380', 1734 - '1701': 'c-01129', 1735 - '1702': 'c-01614', 1736 - '1703': 'c-03241', 1737 - '1704': 'c-02228', 1738 - '1705': 'c-02570', 1739 - '1706': 'c-03332', 1740 - '1707': 'c-06225', 1741 - '1708': 'c-03394', 1742 - '1709': 'c-02837', 1743 - '1710': 'c-01883', 1744 - '1711': 'c-00363', 1745 - '1712': 'c-02965', 1746 - '1713': 'c-05529', 1747 - '1714': 'c-02492', 1748 - '1715': 'c-02417', 1749 - '1716': 'c-02818', 1750 - '1717': 'c-03310', 1751 - '1718': 'c-03022', 1752 - '1719': 'c-00800', 1753 - '1720': 'c-00907', 1754 - '1721': 'c-00900', 1755 - '1722': 'c-01279', 1756 - '1723': 'c-01026', 1757 - '1724': 'c-00234', 1758 - '1725': 'c-00834', 1759 - '1726': 'c-01263', 1760 - '1727': 'c-02521', 1761 - '1728': 'c-01710', 1762 - '1729': 'c-02343', 1763 - '1730': 'c-00609', 1764 - '1731': 'c-20027', 1765 - '1732': 'c-00309', 1766 - '1733': 'c-02980', 1767 - '1734': 'c-02735', 1768 - '1735': 'c-00792', 1769 - '1736': 'c-03471', 1770 - '1737': 'c-03188', 1771 - '1738': 'c-01045', 1772 - '1739': 'c-03089', 1773 - '1740': 'c-02660', 1774 - '1741': 'c-00186', 1775 - '1742': 'c-01270', 1776 - '1743': 'c-01529', 1777 - '1744': 'c-01335', 1778 - '1745': 'c-00801', 1779 - '1746': 'c-03206', 1780 - '1747': 'c-00730', 1781 - '1748': 'c-02075', 1782 - '1749': 'c-03389', 1783 - '1750': 'c-01838', 1784 - '1751': 'c-01180', 1785 - '1752': 'c-02691', 1786 - '1753': 'c-03051', 1787 - '1754': 'c-01022', 1788 - '1755': 'c-02946', 1789 - '1756': 'c-02587', 1790 - '1757': 'c-03063', 1791 - '1758': 'c-01531', 1792 - '1759': 'c-02948', 1793 - '1760': 'c-02087', 1794 - '1761': 'c-02986', 1795 - '1762': 'c-01885', 1796 - '1763': 'c-01882', 1797 - '1764': 'c-00992', 1798 - '1765': 'c-03388', 1799 - '1766': 'c-01201', 1800 - '1767': 'c-02551', 1801 - '1768': 'c-00378', 1802 - '1769': 'c-01879', 1803 - '1770': 'c-02445', 1804 - '1771': 'c-00065', 1805 - '1772': 'c-20028', 1806 - '1773': 'c-03379', 1807 - '1774': 'c-03385', 1808 - '1775': 'c-03256', 1809 - '1776': 'c-03118', 1810 - '1777': 'c-00906', 1811 - '1778': 'c-03384', 1812 - '1779': 'c-02876', 1813 - '1780': 'c-03100', 1814 - '1781': 'c-00618', 1815 - '1782': 'c-02064', 1816 - '1783': 'c-03288', 1817 - '1784': 'c-02789', 1818 - '1785': 'c-02465', 1819 - '1786': 'c-00177', 1820 - '1787': 'c-03139', 1821 - '1788': 'c-03114', 1822 - '1789': 'c-01089', 1823 - '1790': 'c-01438', 1824 - '1791': 'c-01655', 1825 - '1792': 'c-01159', 1826 - '1793': 'c-00599', 1827 - '1794': 'c-01108', 1828 - '1795': 'c-03326', 1829 - '1796': 'c-03262', 1830 - '1797': 'c-02892', 1831 - '1798': 'c-00195', 1832 - '1799': 'c-00795', 1833 - '1800': 'c-00873', 1834 - '1801': 'c-00974', 1835 - '1802': 'c-00898', 1836 - '1803': 'c-01051', 1837 - '1804': 'c-02016', 1838 - '1805': 'c-02947', 1839 - '1806': 'c-02943', 1840 - '1807': 'c-03202', 1841 - '1808': 'c-01616', 1842 - '1809': 'c-01207', 1843 - '1810': 'c-03362', 1844 - '1811': 'c-01472', 1845 - '1812': 'c-03325', 1846 - '1813': 'c-03211', 1847 - '1814': 'c-00480', 1848 - '1815': 'c-00993', 1849 - '1816': 'c-03419', 1850 - '1817': 'c-00342', 1851 - '1818': 'c-01827', 1852 - '1819': 'c-00511', 1853 - '1820': 'c-00025', 1854 - '1821': 'c-02641', 1855 - '1822': 'c-02115', 1856 - '1823': 'c-02861', 1857 - '1824': 'c-03490', 1858 - '1825': 'c-02998', 1859 - '1826': 'c-00424', 1860 - '1827': 'c-00071', 1861 - '1828': 'c-00166', 1862 - '1829': 'c-02710', 1863 - '1830': 'c-03354', 1864 - '1831': 'c-00674', 1865 - '1832': 'c-01607', 1866 - '1833': 'c-02398', 1867 - '1834': 'c-01790', 1868 - '1835': 'c-02464', 1869 - '1836': 'c-00677', 1870 - '1837': 'c-01770', 1871 - '1838': 'c-01295', 1872 - '1839': 'c-01443', 1873 - '1840': 'c-01297', 1874 - '1841': 'c-02295', 1875 - '1842': 'c-03482', 1876 - '1843': 'c-01498', 1877 - '1844': 'c-03372', 1878 - '1845': 'c-00622', 1879 - '20001': 'v-00001', 1880 - '20002': 'v-00002', 1881 - '20003': 'v-00003', 1882 - '20004': 'v-00004', 1883 - '20005': 'v-00005', 1884 - '20006': 'v-00006', 1885 - '20007': 'v-00007', 1886 - '20008': 'v-00008', 1887 - '20009': 'v-00009', 1888 - '20010': 'v-00010', 1889 - '20011': 'v-00011', 1890 - '20012': 'v-00012', 1891 - '20013': 'v-00013', 1892 - '20014': 'v-00014', 1893 - '20015': 'v-00015', 1894 - '20016': 'v-00016', 1895 - '20017': 'v-00017', 1896 - '20018': 'v-00018', 1897 - '20019': 'v-00019', 1898 - '20020': 'v-00020', 1899 - '20021': 'v-00021', 1900 - '20022': 'v-00022', 1901 - '20023': 'v-00023', 1902 - '20024': 'v-00024', 1903 - '20025': 'v-00025', 1904 - '20026': 'v-00026', 1905 - '20027': 'v-00027', 1906 - '20028': 'v-00028', 1907 - '20029': 'v-00029', 1908 - '20030': 'v-00030', 1909 - '20031': 'v-00031', 1910 - '20032': 'v-00032', 1911 - '20033': 'v-00033', 1912 - '20034': 'v-00034', 1913 - '20035': 'v-00035', 1914 - '20036': 'v-00036', 1915 - '20037': 'v-00037', 1916 - '20038': 'v-00038', 1917 - '20039': 'v-00039', 1918 - '20040': 'v-00040', 1919 - '20041': 'v-00041', 1920 - '20042': 'v-00042', 1921 - '20043': 'v-00043', 1922 - '20044': 'v-00044', 1923 - '20045': 'v-00045', 1924 - '20046': 'v-00046', 1925 - '20047': 'v-00047', 1926 - '20048': 'v-00048', 1927 - '20049': 'v-00049', 1928 - '20050': 'v-00050', 1929 - '20051': 'v-00051', 1930 - '20052': 'v-00052', 1931 - '20053': 'v-00053', 1932 - '20054': 'v-00054', 1933 - '20055': 'v-00055', 1934 - '20056': 'v-00056', 1935 - '20057': 'v-00057', 1936 - '20058': 'v-00058', 1937 - '20059': 'v-00059', 1938 - '20060': 'v-00060', 1939 - '20061': 'v-00061', 1940 - '20062': 'v-00062', 1941 - '20063': 'v-00063', 1942 - '20064': 'v-00064', 1943 - '20065': 'v-00065', 1944 - '20066': 'v-00066', 1945 - '20067': 'v-00067', 1946 - '20068': 'v-00068', 1947 - '20069': 'v-00069', 1948 - '20070': 'v-00070', 1949 - '20071': 'v-00071', 1950 - '20072': 'v-00072', 1951 - '20073': 'v-00073', 1952 - '20074': 'v-00074', 1953 - '20075': 'v-00075', 1954 - '20076': 'v-00076', 1955 - '20077': 'v-00077', 1956 - '20078': 'v-00078', 1957 - '20079': 'v-00079', 1958 - '20080': 'v-00080', 1959 - '20081': 'v-00081', 1960 - '20082': 'v-00082', 1961 - '20083': 'v-00083', 1962 - '20084': 'v-00084', 1963 - '20085': 'v-00085', 1964 - '20086': 'v-00086', 1965 - '20087': 'v-00087', 1966 - '20088': 'v-00088', 1967 - '20089': 'v-00089', 1968 - '20090': 'v-00090', 1969 - '20091': 'v-00091', 1970 - '20092': 'v-00092', 1971 - '20093': 'v-00093', 1972 - '20094': 'v-00094', 1973 - '20095': 'v-00095', 1974 - '20096': 'v-00096', 1975 - '20097': 'v-00097', 1976 - '20098': 'v-00098', 1977 - '20099': 'v-00099', 1978 - '20100': 'v-00100', 1979 - '20101': 'v-00101', 1980 - '20102': 'v-00102', 1981 - '20103': 'v-00103', 1982 - '20104': 'v-00104', 1983 - '20105': 'v-00105', 1984 - '20106': 'v-00106', 1985 - '20107': 'v-00107', 1986 - '20108': 'v-00108', 1987 - '20109': 'v-00109', 1988 - '20110': 'v-00110', 1989 - '20111': 'v-00111', 1990 - '20112': 'v-00112', 1991 - '20113': 'v-00113', 1992 - '20114': 'v-00114', 1993 - '20115': 'v-00115', 1994 - '20116': 'v-00116', 1995 - '20117': 'v-00117', 1996 - '20118': 'v-00118', 1997 - '20119': 'v-00119', 1998 - '20120': 'v-00120', 1999 - '20121': 'v-00121', 2000 - '20122': 'v-00122', 2001 - '20123': 'v-00123', 2002 - '20124': 'v-00124', 2003 - '20125': 'v-00125', 2004 - '20126': 'v-00126', 2005 - '20127': 'v-00127', 2006 - '20128': 'v-00128', 2007 - '20129': 'v-00129', 2008 - '20130': 'v-00130', 2009 - '20131': 'v-00131', 2010 - '20132': 'v-00132', 2011 - '20133': 'v-00133', 2012 - '20134': 'v-00134', 2013 - '20135': 'v-00135', 2014 - '20136': 'v-00136', 2015 - '20137': 'v-00137', 2016 - '20138': 'v-00138', 2017 - '20139': 'v-00139', 2018 - '20140': 'v-00140', 2019 - '20141': 'v-00141', 2020 - '20142': 'v-00142', 2021 - '20143': 'v-00143', 2022 - '20144': 'v-00144', 2023 - '20145': 'v-00145', 2024 - '20146': 'v-00146', 2025 - '20147': 'v-00147', 2026 - '20148': 'v-00148', 2027 - '20149': 'v-00149', 2028 - '20150': 'v-00150', 2029 - '20151': 'v-00151', 2030 - '20152': 'v-00152', 2031 - '20153': 'v-00153', 2032 - '20154': 'v-00154', 2033 - '20155': 'v-00155', 2034 - '20156': 'v-00156', 2035 - '20157': 'v-00157', 2036 - '20158': 'v-00158', 2037 - '20159': 'v-00159', 2038 - '20160': 'v-00160', 2039 - '20161': 'v-00161', 2040 - '20162': 'v-00162', 2041 - '20163': 'v-00163', 2042 - '20164': 'v-00164', 2043 - '20165': 'v-00165', 2044 - '20166': 'v-00166', 2045 - '20167': 'v-00167', 2046 - '20168': 'v-00168', 2047 - '20169': 'v-00169', 2048 - '20170': 'v-00170', 2049 - '20171': 'v-00171', 2050 - '20172': 'v-00172', 2051 - '20173': 'v-00173', 2052 - '20174': 'v-00174', 2053 - '20175': 'v-00175', 2054 - '20176': 'v-00176', 2055 - '20177': 'v-00177', 2056 - '20178': 'v-00178', 2057 - '20179': 'v-00179', 2058 - '20180': 'v-00180', 2059 - '20181': 'v-00181', 2060 - '20182': 'v-00182', 2061 - '20183': 'v-00183', 2062 - '20184': 'v-00184', 2063 - '20185': 'v-00185', 2064 - '20186': 'v-00186', 2065 - '20187': 'v-00187', 2066 - '20188': 'v-00188', 2067 - '20189': 'v-00189', 2068 - '20190': 'v-00190', 2069 - '20191': 'v-00191', 2070 - '20192': 'v-00192', 2071 - '20193': 'v-00193', 2072 - '20194': 'v-00194', 2073 - '20195': 'v-00195', 2074 - '20196': 'v-00196', 2075 - '20197': 'v-00197', 2076 - '20198': 'v-00198', 2077 - '20199': 'v-00199', 2078 - '20200': 'v-00200', 2079 - '20201': 'v-00201', 2080 - '20202': 'v-00202', 2081 - '20203': 'v-00203', 2082 - '20204': 'v-00204', 2083 - '20205': 'v-00205', 2084 - '20206': 'v-00206', 2085 - '20207': 'v-00207', 2086 - '20208': 'v-00208', 2087 - '20209': 'v-00209', 2088 - '20210': 'v-00210', 2089 - '20211': 'v-00211', 2090 - '20212': 'v-00212', 2091 - '20213': 'v-00213', 2092 - '20214': 'v-00214', 2093 - '20215': 'v-00215', 2094 - '20216': 'v-00216', 2095 - '20217': 'v-00217', 2096 - '20218': 'v-00218', 2097 - '20219': 'v-00219', 2098 - '20220': 'v-00220', 2099 - '20221': 'v-00221', 2100 - '20222': 'v-00222', 2101 - '20223': 'v-00223', 2102 - '20224': 'v-00224', 2103 - '20225': 'v-00225', 2104 - '20226': 'v-00226', 2105 - '20227': 'v-00227', 2106 - '20228': 'v-00228', 2107 - '20229': 'v-00229', 2108 - '20230': 'v-00230', 2109 - '20231': 'v-00231', 2110 - '20232': 'v-00232', 2111 - '20233': 'v-00233', 2112 - '20234': 'v-00234', 2113 - '20235': 'v-00235', 2114 - '20236': 'v-00236', 2115 - '20237': 'v-00237', 2116 - '20238': 'v-00238', 2117 - '20239': 'v-00239', 2118 - '20240': 'v-00240', 2119 - '20241': 'v-00241', 2120 - '20242': 'v-00242', 2121 - '20243': 'v-00243', 2122 - '20244': 'v-00244', 2123 - '20245': 'v-00245', 2124 - '20246': 'v-00246', 2125 - '20247': 'v-00247', 2126 - '20248': 'v-00248', 2127 - '20249': 'v-00249', 2128 - '20250': 'v-00250', 2129 - '20251': 'v-00251', 2130 - '20252': 'v-00252', 2131 - '20253': 'v-00253', 2132 - '20254': 'v-00254', 2133 - '20255': 'v-00255', 2134 - '20256': 'v-00256', 2135 - '20257': 'v-00257', 2136 - '20258': 'v-00258', 2137 - '20259': 'v-00259', 2138 - '20260': 'v-00260', 2139 - '20261': 'v-00261', 2140 - '20262': 'v-00262', 2141 - '20263': 'v-00263', 2142 - '20264': 'v-00264', 2143 - '20265': 'v-00265', 2144 - '20266': 'v-00266', 2145 - '20267': 'v-00267', 2146 - '20268': 'v-00268', 2147 - '20269': 'v-00269', 2148 - '20270': 'v-00270', 2149 - '20271': 'v-00271', 2150 - '20272': 'v-00272', 2151 - '20273': 'v-00273', 2152 - '20274': 'v-00274', 2153 - '20275': 'v-00275', 2154 - '20276': 'v-00276', 2155 - '20277': 'v-00277', 2156 - '20278': 'v-00278', 2157 - '20279': 'v-00279', 2158 - '20280': 'v-00280', 2159 - '20281': 'v-00281', 2160 - '20282': 'v-00282', 2161 - '20283': 'v-00283', 2162 - '20284': 'v-00284', 2163 - '20285': 'v-00285', 2164 - '20286': 'v-00286', 2165 - '20287': 'v-00287', 2166 - '20288': 'v-00288', 2167 - '20289': 'v-00289', 2168 - '20290': 'v-00290', 2169 - '20291': 'v-00291', 2170 - '20292': 'v-00292', 2171 - '20293': 'v-00293', 2172 - '20294': 'v-00294', 2173 - '20295': 'v-00295', 2174 - '20296': 'v-00296', 2175 - '20297': 'v-00297', 2176 - '20298': 'v-00298', 2177 - '20299': 'v-00299', 2178 - '20300': 'v-00300', 2179 - '20301': 'v-00301', 2180 - '20302': 'v-00302', 2181 - '20303': 'v-00303', 2182 - '20304': 'v-00304', 2183 - '20305': 'v-00305', 2184 - '20306': 'v-00306', 2185 - '20307': 'v-00307', 2186 - '20308': 'v-00308', 2187 - '20309': 'v-00309', 2188 - '20310': 'v-00310', 2189 - '20311': 'v-00311', 2190 - '20312': 'v-00312', 2191 - '20313': 'v-00313', 2192 - '20314': 'v-00314', 2193 - '20315': 'v-00315', 2194 - '20316': 'v-00316', 2195 - '20317': 'v-00317', 2196 - '20318': 'v-00318', 2197 - '20319': 'v-00319', 2198 - '20320': 'v-00320', 2199 - '20321': 'v-00321', 2200 - '20322': 'v-00322', 2201 - '20323': 'v-00323', 2202 - '20324': 'v-00324', 2203 - '20325': 'v-00325', 2204 - '20326': 'v-00326', 2205 - '20327': 'v-00327', 2206 - '20328': 'v-00328', 2207 - '20329': 'v-00329', 2208 - '20330': 'v-00330', 2209 - '20331': 'v-00331', 2210 - '20332': 'v-00332', 2211 - '20333': 'v-00333', 2212 - '20334': 'v-00334', 2213 - '20335': 'v-00335', 2214 - '20336': 'v-00336', 2215 - '20337': 'v-00337', 2216 - '20338': 'v-00338', 2217 - '20339': 'v-00339', 2218 - '20340': 'v-00340', 2219 - '20341': 'v-00341', 2220 - '20342': 'v-00342', 2221 - '20343': 'v-00343', 2222 - '20344': 'v-00344', 2223 - '20345': 'v-00345', 2224 - '20346': 'v-00346', 2225 - '20347': 'v-00347', 2226 - '20348': 'v-00348', 2227 - '20349': 'v-00349', 2228 - '20350': 'v-00350', 2229 - '20351': 'v-00351', 2230 - '20352': 'v-00352', 2231 - '20353': 'v-00353', 2232 - '20354': 'v-00354', 2233 - '20355': 'v-00355', 2234 - '20356': 'v-00356', 2235 - '20357': 'v-00357', 2236 - '20358': 'v-00358', 2237 - '20359': 'v-00359', 2238 - '20360': 'v-00360', 2239 - '20361': 'v-00361', 2240 - '20362': 'v-00362', 2241 - '20363': 'v-00363', 2242 - '20364': 'v-00364', 2243 - '20365': 'v-00365', 2244 - '20366': 'v-00366', 2245 - '20367': 'v-00367', 2246 - '20368': 'v-00368', 2247 - '20369': 'v-00369', 2248 - '20370': 'v-00370', 2249 - '20371': 'v-00371', 2250 - '20372': 'v-00372', 2251 - '20373': 'v-00373', 2252 - '20374': 'v-00374', 2253 - '20375': 'v-00375', 2254 - '20376': 'v-00376', 2255 - '20377': 'v-00377', 2256 - '20378': 'v-00378', 2257 - '20379': 'v-00379', 2258 - '20380': 'v-00380', 2259 - '20381': 'v-00381', 2260 - '20382': 'v-00382', 2261 - '20383': 'v-00383', 2262 - '20384': 'v-00384', 2263 - '20385': 'v-00385', 2264 - '20386': 'v-00386', 2265 - '20387': 'v-00387', 2266 - '20388': 'v-00388', 2267 - '20389': 'v-00389', 2268 - '20390': 'v-00390', 2269 - '20391': 'v-00391', 2270 - '20392': 'v-00392', 2271 - '20393': 'v-00393', 2272 - '20394': 'v-00394', 2273 - '20395': 'v-00395', 2274 - '20396': 'v-00396', 2275 - '20397': 'v-00397', 2276 - '20398': 'v-00398', 2277 - '20399': 'v-00399', 2278 - '20400': 'v-00400', 2279 - '20401': 'v-00401', 2280 - '20402': 'v-00402', 2281 - '20403': 'v-00403', 2282 - '20404': 'v-00404', 2283 - '20405': 'v-00405', 2284 - '20406': 'v-00406', 2285 - '20407': 'v-00407', 2286 - '20408': 'v-00408', 2287 - '20409': 'v-00409', 2288 - '20410': 'v-00410', 2289 - '20411': 'v-00411', 2290 - '20412': 'v-00412', 2291 - '20413': 'v-00413', 2292 - '20414': 'v-00414', 2293 - '20415': 'v-00415', 2294 - '20416': 'v-00416', 2295 - '20417': 'v-00417', 2296 - '20418': 'v-00418', 2297 - '20419': 'v-00419', 2298 - '20420': 'v-00420', 2299 - '20421': 'v-00421', 2300 - '20422': 'v-00422', 2301 - '20423': 'v-00423', 2302 - '20424': 'v-00424', 2303 - '20425': 'v-00425', 2304 - '20426': 'v-00426', 2305 - '20427': 'v-00427', 2306 - '20428': 'v-00428', 2307 - '20429': 'v-00429', 2308 - '20430': 'v-00430', 2309 - '20431': 'v-00431', 2310 - '20432': 'v-00432', 2311 - '20433': 'v-00433', 2312 - '20434': 'v-00434', 2313 - '20435': 'v-00435', 2314 - '20436': 'v-00436', 2315 - '20437': 'v-00437', 2316 - '20438': 'v-00438', 2317 - '20439': 'v-00439', 2318 - '20440': 'v-00440', 2319 - '20441': 'v-00441', 2320 - '20442': 'v-00442', 2321 - '20443': 'v-00443', 2322 - '20444': 'v-00444', 2323 - '20445': 'v-00445', 2324 - '20446': 'v-00446', 2325 - '20447': 'v-00447', 2326 - '20448': 'v-00448', 2327 - '20449': 'v-00449', 2328 - '20450': 'v-00450', 2329 - '20451': 'v-00451', 2330 - '20452': 'v-00452', 2331 - '20453': 'v-00453', 2332 - '20454': 'v-00454', 2333 - '20455': 'v-00455', 2334 - '20456': 'v-00456', 2335 - '20457': 'v-00457', 2336 - '20458': 'v-00458', 2337 - '20459': 'v-00459', 2338 - '20460': 'v-00460', 2339 - '20461': 'v-00461', 2340 - '20462': 'v-00462', 2341 - '20463': 'v-00463', 2342 - '20464': 'v-00464', 2343 - '20465': 'v-00465', 2344 - '20466': 'v-00466', 2345 - '20467': 'v-00467', 2346 - '20468': 'v-00468', 2347 - '20469': 'v-00469', 2348 - '20470': 'v-00470', 2349 - '20471': 'v-00471', 2350 - '20472': 'v-00472', 2351 - '20473': 'v-00473', 2352 - '20474': 'v-00474', 2353 - '20475': 'v-00475', 2354 - '20476': 'v-00476', 2355 - '20477': 'v-00477', 2356 - '20478': 'v-00478', 2357 - '20479': 'v-00479', 2358 - '20480': 'v-00480', 2359 - '20481': 'v-00481', 2360 - '20482': 'v-00482', 2361 - '20483': 'v-00483', 2362 - '20484': 'v-00484', 2363 - '20485': 'v-00485', 2364 - '20486': 'v-00486', 2365 - '20487': 'v-00487', 2366 - '20488': 'v-00488', 2367 - '20489': 'v-00489', 2368 - '20490': 'v-00490', 2369 - '20491': 'v-00491', 2370 - '20492': 'v-00492', 2371 - '20493': 'v-00493', 2372 - '20494': 'v-00494', 2373 - '20495': 'v-00495', 2374 - '20496': 'v-00496', 2375 - '20497': 'v-00497', 2376 - '20498': 'v-00498', 2377 - '20499': 'v-00499', 2378 - '20500': 'v-00500', 2379 - '20501': 'v-00501', 2380 - '20502': 'v-00502', 2381 - '20503': 'v-00503', 2382 - '20504': 'v-00504', 2383 - '20505': 'v-00505', 2384 - '20506': 'v-00506', 2385 - '20507': 'v-00507', 2386 - '20508': 'v-00508', 2387 - '20509': 'v-00509', 2388 - '20510': 'v-00510', 2389 - '20511': 'v-00511', 2390 - '20512': 'v-00512', 2391 - '20513': 'v-00513', 2392 - '20514': 'v-00514', 2393 - '20515': 'v-00515', 2394 - '20516': 'v-00516', 2395 - '20517': 'v-00517', 2396 - '20518': 'v-00518', 2397 - '20519': 'v-00519', 2398 - '20520': 'v-00520', 2399 - '20521': 'v-00521', 2400 - '20522': 'v-00522', 2401 - '20523': 'v-00523', 2402 - '20524': 'v-00524', 2403 - '20525': 'v-00525', 2404 - '20526': 'v-00526', 2405 - '20527': 'v-00527', 2406 - '20528': 'v-00528', 2407 - '20529': 'v-00529', 2408 - '20530': 'v-00530', 2409 - '20531': 'v-00531', 2410 - '20532': 'v-00532', 2411 - '20533': 'v-00533', 2412 - '20534': 'v-00534', 2413 - '20535': 'v-00535', 2414 - '20536': 'v-00536', 2415 - '20537': 'v-00537', 2416 - '20538': 'v-00538', 2417 - '20539': 'v-00539', 2418 - '20540': 'v-00540', 2419 - '20541': 'v-00541', 2420 - '20542': 'v-00542', 2421 - '20543': 'v-00543', 2422 - '20544': 'v-00544', 2423 - '20545': 'v-00545', 2424 - '20546': 'v-00546', 2425 - '20547': 'v-00547', 2426 - '20548': 'v-00548', 2427 - '20549': 'v-00549', 2428 - '20550': 'v-00550', 2429 - '20551': 'v-00551', 2430 - '20552': 'v-00552', 2431 - '20553': 'v-00553', 2432 - '20554': 'v-00554', 2433 - '20555': 'v-00555', 2434 - '20556': 'v-00556', 2435 - '20557': 'v-00557', 2436 - '20558': 'v-00558', 2437 - '20559': 'v-00559', 2438 - '20560': 'v-00560', 2439 - '20561': 'v-00561', 2440 - '20562': 'v-00562', 2441 - '20563': 'v-00563', 2442 - '20564': 'v-00564', 2443 - '20565': 'v-00565', 2444 - '20566': 'v-00566', 2445 - '20567': 'v-00567', 2446 - '20568': 'v-00568', 2447 - '20569': 'v-00569', 2448 - '20570': 'v-00570', 2449 - '20571': 'v-00571', 2450 - '20572': 'v-00572', 2451 - '20573': 'v-00573', 2452 - '20574': 'v-00574', 2453 - '20575': 'v-00575', 2454 - '20576': 'v-00576', 2455 - '20577': 'v-00577', 2456 - '20578': 'v-00578', 2457 - '20579': 'v-00579', 2458 - '20580': 'v-00580', 2459 - '20581': 'v-00581', 2460 - '20582': 'v-00582', 2461 - '20583': 'v-00583', 2462 - '20584': 'v-00584', 2463 - '20585': 'v-00585', 2464 - '20586': 'v-00586', 2465 - '20587': 'v-00587', 2466 - '20588': 'v-00588', 2467 - '20589': 'v-00589', 2468 - '20590': 'v-00590', 2469 - '20591': 'v-00591', 2470 - '20592': 'v-00592', 2471 - '20593': 'v-00593', 2472 - '20594': 'v-00594', 2473 - '20595': 'v-00595', 2474 - '20596': 'v-00596', 2475 - '20597': 'v-00597', 2476 - '20598': 'v-00598', 2477 - '20599': 'v-00599', 2478 - '20600': 'v-00600', 2479 - '20601': 'v-00601', 2480 - '20602': 'v-00602', 2481 - '20603': 'v-00603', 2482 - '20604': 'v-00604', 2483 - '20605': 'v-00605', 2484 - '20606': 'v-00606', 2485 - '20607': 'v-00607', 2486 - '20608': 'v-00608', 2487 - '20609': 'v-00609', 2488 - '20610': 'v-00610', 2489 - '20611': 'v-00611', 2490 - '20612': 'v-00612', 2491 - '20613': 'v-00613', 2492 - '20614': 'v-00614', 2493 - '20615': 'v-00615', 2494 - '20616': 'v-00616', 2495 - '20617': 'v-00617', 2496 - '20618': 'v-00618', 2497 - '20619': 'v-00619', 2498 - '20620': 'v-00620', 2499 - '20621': 'v-00621', 2500 - '20622': 'v-00622', 2501 - '20623': 'v-00623', 2502 - '20624': 'v-00624', 2503 - '20625': 'v-00625', 2504 - '20626': 'v-00626', 2505 - '20627': 'v-00627', 2506 - '20628': 'v-00628', 2507 - '20629': 'v-00629', 2508 - '20630': 'v-00630', 2509 - '20631': 'v-00631', 2510 - '20632': 'v-00632', 2511 - '20633': 'v-00633', 2512 - '20634': 'v-00634', 2513 - '20635': 'v-00635', 2514 - '20636': 'v-00636', 2515 - '20637': 'v-00637', 2516 - '20638': 'v-00638', 2517 - '20639': 'v-00639', 2518 - '20640': 'v-00640', 2519 - '20641': 'v-00641', 2520 - '20642': 'v-00642', 2521 - '20643': 'v-00643', 2522 - '20644': 'v-00644', 2523 - '20645': 'v-00645', 2524 - '20646': 'v-00646', 2525 - '20647': 'v-00647', 2526 - '20648': 'v-00648', 2527 - '20649': 'v-00649', 2528 - '20650': 'v-00650', 2529 - '20651': 'v-00651', 2530 - '20652': 'v-00652', 2531 - '20653': 'v-00653', 2532 - '20654': 'v-00654', 2533 - '20655': 'v-00655', 2534 - '20656': 'v-00656', 2535 - '20657': 'v-00657', 2536 - '20658': 'v-00658', 2537 - '20659': 'v-00659', 2538 - '20660': 'v-00660', 2539 - '20661': 'v-00661', 2540 - '20662': 'v-00662', 2541 - '20663': 'v-00663', 2542 - '20664': 'v-00664', 2543 - '20665': 'v-00665', 2544 - '20666': 'v-00666', 2545 - '20667': 'v-00667', 2546 - '20668': 'v-00668', 2547 - '20669': 'v-00669', 2548 - '20670': 'v-00670', 2549 - '20671': 'v-00671', 2550 - '20672': 'v-00672', 2551 - '20673': 'v-00673', 2552 - '20674': 'v-00674', 2553 - '20675': 'v-00675', 2554 - '20676': 'v-00676', 2555 - '20677': 'v-00677', 2556 - '20678': 'v-00678', 2557 - '20679': 'v-00679', 2558 - '20680': 'v-00680', 2559 - '20681': 'v-00681', 2560 - '20682': 'v-00682', 2561 - '20683': 'v-00683', 2562 - '20684': 'v-00684', 2563 - '20685': 'v-00685', 2564 - '20686': 'v-00686', 2565 - '20687': 'v-00687', 2566 - '20688': 'v-00688', 2567 - '20689': 'v-00689', 2568 - '20690': 'v-00690', 2569 - '20691': 'v-00691', 2570 - '20692': 'v-00692', 2571 - '20693': 'v-00693', 2572 - '20694': 'v-00694', 2573 - '20695': 'v-00695', 2574 - '20696': 'v-00696', 2575 - '20697': 'v-00697', 2576 - '20698': 'v-00698', 2577 - '20699': 'v-00699', 2578 - '20700': 'v-00700', 2579 - '20701': 'v-00701', 2580 - '20702': 'v-00702', 2581 - '20703': 'v-00703', 2582 - '20704': 'v-00704', 2583 - '20705': 'v-00705', 2584 - '20706': 'v-00706', 2585 - '20707': 'v-00707', 2586 - '20708': 'v-00708', 2587 - '20709': 'v-00709', 2588 - '20710': 'v-00710', 2589 - '20711': 'v-00711', 2590 - '20712': 'v-00712', 2591 - '20713': 'v-00713', 2592 - '20714': 'v-00714', 2593 - '20715': 'v-00715', 2594 - '20716': 'v-00716', 2595 - '20717': 'v-00717', 2596 - '20718': 'v-00718', 2597 - '20719': 'v-00719', 2598 - '20720': 'v-00720', 2599 - '20721': 'v-00721', 2600 - '20722': 'v-00722', 2601 - '20723': 'v-00723', 2602 - '20724': 'v-00724', 2603 - '20725': 'v-00725', 2604 - '20726': 'v-00726', 2605 - '20727': 'v-00727', 2606 - '20728': 'v-00728', 2607 - '20729': 'v-00729', 2608 - '20730': 'v-00730', 2609 - '20731': 'v-00731', 2610 - '20732': 'v-00732', 2611 - '20733': 'v-00733', 2612 - '20734': 'v-00734', 2613 - '20735': 'v-00735', 2614 - '20736': 'v-00736', 2615 - '20737': 'v-00737', 2616 - '20738': 'v-00738', 2617 - '20739': 'v-00739', 2618 - '20740': 'v-00740', 2619 - '20741': 'v-00741', 2620 - '20742': 'v-00742', 2621 - '20743': 'v-00743', 2622 - '20744': 'v-00744', 2623 - '20745': 'v-00745', 2624 - '20746': 'v-00746', 2625 - '20747': 'v-00747', 2626 - '20748': 'v-00748', 2627 - '20749': 'v-00749', 2628 - '20750': 'v-00750', 2629 - '20751': 'v-00751', 2630 - '20752': 'v-00752', 2631 - '20753': 'v-00753', 2632 - '20754': 'v-00754', 2633 - '20755': 'v-00755', 2634 - '20756': 'v-00756', 2635 - '20757': 'v-00757', 2636 - '20758': 'v-00758', 2637 - '20759': 'v-00759', 2638 - '20760': 'v-00760', 2639 - '20761': 'v-00761', 2640 - '20762': 'v-00762', 2641 - '20763': 'v-00763', 2642 - '20764': 'v-00764', 2643 - '20765': 'v-00765', 2644 - '20766': 'v-00766', 2645 - '20767': 'v-00767', 2646 - '20768': 'v-00768', 2647 - '20769': 'v-00769', 2648 - '20770': 'v-00770', 2649 - '20771': 'v-00771', 2650 - '20772': 'v-00772', 2651 - '20773': 'v-00773', 2652 - '20774': 'v-00774', 2653 - '20775': 'v-00775', 2654 - '20776': 'v-00776', 2655 - '20777': 'v-00777', 2656 - '20778': 'v-00778', 2657 - '20779': 'v-00779', 2658 - '20780': 'v-00780', 2659 - '20781': 'v-00781', 2660 - '20782': 'v-00782', 2661 - '20783': 'v-00783', 2662 - '20784': 'v-00784', 2663 - '20785': 'v-00785', 2664 - '20786': 'v-00786', 2665 - '20787': 'v-00787', 2666 - '20788': 'v-00788', 2667 - '20789': 'v-00789', 2668 - '20790': 'v-00790', 2669 - '20791': 'v-00791', 2670 - '20792': 'v-00792', 2671 - '20793': 'v-00793', 2672 - '20794': 'v-00794', 2673 - '20795': 'v-00795', 2674 - '20796': 'v-00796', 2675 - '20797': 'v-00797', 2676 - '20798': 'v-00798', 2677 - '20799': 'v-00799', 2678 - '20800': 'v-00800', 2679 - '20801': 'v-00801', 2680 - '20802': 'v-00802', 2681 - '20803': 'v-00803', 2682 - '20804': 'v-00804', 2683 - '20805': 'v-00805', 2684 - '20806': 'v-00806', 2685 - '20807': 'v-00807', 2686 - '20808': 'v-00808', 2687 - '20809': 'v-00809', 2688 - '20810': 'v-00810', 2689 - '20811': 'v-00811', 2690 - '20812': 'v-00812', 2691 - '20813': 'v-00813', 2692 - '20814': 'v-00814', 2693 - '20815': 'v-00815', 2694 - '20816': 'v-00816', 2695 - '20817': 'v-00817', 2696 - '20818': 'v-00818', 2697 - '20819': 'v-00819', 2698 - '20820': 'v-00820', 2699 - '20821': 'v-00821', 2700 - '20822': 'v-00822', 2701 - '20823': 'v-00823', 2702 - '20824': 'v-00824', 2703 - '20825': 'v-00825', 2704 - '20826': 'v-00826', 2705 - '20827': 'v-00827', 2706 - '20828': 'v-00828', 2707 - '20829': 'v-00829', 2708 - '20830': 'v-00830', 2709 - '20831': 'v-00831', 2710 - '20832': 'v-00832', 2711 - '20833': 'v-00833', 2712 - '20834': 'v-00834', 2713 - '20835': 'v-00835', 2714 - '20836': 'v-00836', 2715 - '20837': 'v-00837', 2716 - '20838': 'v-00838', 2717 - '20839': 'v-00839', 2718 - '20840': 'v-00840', 2719 - '20841': 'v-00841', 2720 - '20842': 'v-00842', 2721 - '20843': 'v-00843', 2722 - '20844': 'v-00844', 2723 - '20845': 'v-00845', 2724 - '20846': 'v-00846', 2725 - '20847': 'v-00847', 2726 - '20848': 'v-00848', 2727 - '20849': 'v-00849', 2728 - '20850': 'v-00850', 2729 - '20851': 'v-00851', 2730 - '20852': 'v-00852', 2731 - '20853': 'v-00853', 2732 - '20854': 'v-00854', 2733 - '20855': 'v-00855', 2734 - '20856': 'v-00856', 2735 - '20857': 'v-00857', 2736 - '20858': 'v-00858', 2737 - '20859': 'v-00859', 2738 - '20860': 'v-00860', 2739 - '20861': 'v-00861', 2740 - '20862': 'v-00862', 2741 - '20863': 'v-00863', 2742 - '20864': 'v-00864', 2743 - '20865': 'v-00865', 2744 - '20866': 'v-00866', 2745 - '20867': 'v-00867', 2746 - '20868': 'v-00868', 2747 - '20869': 'v-00869', 2748 - '20870': 'v-00870', 2749 - '20871': 'v-00871', 2750 - '20872': 'v-00872', 2751 - '20873': 'v-00873', 2752 - '20874': 'v-00874', 2753 - '20875': 'v-00875', 2754 - '20876': 'v-00876', 2755 - '20877': 'v-00877', 2756 - '20878': 'v-00878', 2757 - '20879': 'v-00879', 2758 - '20880': 'v-00880', 2759 - '20881': 'v-00881', 2760 - '20882': 'v-00882', 2761 - '20883': 'v-00883', 2762 - '20884': 'v-00884', 2763 - '20885': 'v-00885', 2764 - '20886': 'v-00886', 2765 - '20887': 'v-00887', 2766 - '20888': 'v-00888', 2767 - '20889': 'v-00889', 2768 - '20890': 'v-00890', 2769 - '20891': 'v-00891', 2770 - '20892': 'v-00892', 2771 - '20893': 'v-00893', 2772 - '20894': 'v-00894', 2773 - '20895': 'v-00895', 2774 - '20896': 'v-00896', 2775 - '20897': 'v-00897', 2776 - '20898': 'v-00898', 2777 - '20899': 'v-00899', 2778 - '20900': 'v-00900', 2779 - '20901': 'v-00901', 2780 - '20902': 'v-00902', 2781 - '20903': 'v-00903', 2782 - '20904': 'v-00904', 2783 - '20905': 'v-00905', 2784 - '20906': 'v-00906', 2785 - '20907': 'v-00907', 2786 - '20908': 'v-00908', 2787 - '20909': 'v-00909', 2788 - '20910': 'v-00910', 2789 - '20911': 'v-00911', 2790 - '20912': 'v-00912', 2791 - '20913': 'v-00913', 2792 - '20914': 'v-00914', 2793 - '20915': 'v-00915', 2794 - '20916': 'v-00916', 2795 - '20917': 'v-00917', 2796 - '20918': 'v-00918', 2797 - '20919': 'v-00919', 2798 - '20920': 'v-00920', 2799 - '20921': 'v-00921', 2800 - '20922': 'v-00922', 2801 - '20923': 'v-00923', 2802 - '20924': 'v-00924', 2803 - '20925': 'v-00925', 2804 - '20926': 'v-00926', 2805 - '20927': 'v-00927', 2806 - '20928': 'v-00928', 2807 - '20929': 'v-00929', 2808 - '20930': 'v-00930', 2809 - '20931': 'v-00931', 2810 - '20932': 'v-00932', 2811 - '20933': 'v-00933', 2812 - '20934': 'v-00934', 2813 - '20935': 'v-00935', 2814 - '20936': 'v-00936', 2815 - '20937': 'v-00937', 2816 - '20938': 'v-00938', 2817 - '20939': 'v-00939', 2818 - '20940': 'v-00940', 2819 - '20941': 'v-00941', 2820 - '20942': 'v-00942', 2821 - '20943': 'v-00943', 2822 - '20944': 'v-00944', 2823 - '20945': 'v-00945', 2824 - '20946': 'v-00946', 2825 - '20947': 'v-00947', 2826 - '20948': 'v-00948', 2827 - '20949': 'v-00949', 2828 - '20950': 'v-00950', 2829 - '20951': 'v-00951', 2830 - '20952': 'v-00952', 2831 - '20953': 'v-00953', 2832 - '20954': 'v-00954', 2833 - '20955': 'v-00955', 2834 - '20956': 'v-00956', 2835 - '20957': 'v-00957', 2836 - '20958': 'v-00958', 2837 - '20959': 'v-00959', 2838 - '20960': 'v-00960', 2839 - '20961': 'v-00961', 2840 - '20962': 'v-00962', 2841 - '20963': 'v-00963', 2842 - '20964': 'v-00964', 2843 - '20965': 'v-00965', 2844 - '20966': 'v-00966', 2845 - '20967': 'v-00967', 2846 - '20968': 'v-00968', 2847 - '20969': 'v-00969', 2848 - '20970': 'v-00970', 2849 - '20971': 'v-00971', 2850 - '20972': 'v-00972', 2851 - '20973': 'v-00973', 2852 - '20974': 'v-00974', 2853 - '20975': 'v-00975', 2854 - '20976': 'v-00976', 2855 - '20977': 'v-00977', 2856 - '20978': 'v-00978', 2857 - '20979': 'v-00979', 2858 - '20980': 'v-00980', 2859 - '20981': 'v-00981', 2860 - '20982': 'v-00982', 2861 - '20983': 'v-00983', 2862 - '20984': 'v-00984', 2863 - '20985': 'v-00985', 2864 - '20986': 'v-00986', 2865 - '20987': 'v-00987', 2866 - '20988': 'v-00988', 2867 - '20989': 'v-00989', 2868 - '20990': 'v-00990', 2869 - '20991': 'v-00991', 2870 - '20992': 'v-00992', 2871 - '20993': 'v-00993', 2872 - '20994': 'v-00994', 2873 - '20995': 'v-00995', 2874 - '20996': 'v-00996', 2875 - '20997': 'v-00997', 2876 - '20998': 'v-00998', 2877 - '20999': 'v-00999', 2878 - '21000': 'v-01000', 2879 - '21001': 'v-01001', 2880 - '21002': 'v-01002', 2881 - '21003': 'v-01003', 2882 - '21004': 'v-01004', 2883 - '21005': 'v-01005', 2884 - '21006': 'v-01006', 2885 - '21007': 'v-01007', 2886 - '21008': 'v-01008', 2887 - '21009': 'v-01009', 2888 - '21010': 'v-01010', 2889 - '21011': 'v-01011', 2890 - '21012': 'v-01012', 2891 - '21013': 'v-01013', 2892 - '21014': 'v-01014', 2893 - '21015': 'v-01015', 2894 - '21016': 'v-01016', 2895 - '21017': 'v-01017', 2896 - '21018': 'v-01018', 2897 - '21019': 'v-01019', 2898 - '21020': 'v-01020', 2899 - '21021': 'v-01021', 2900 - '21022': 'v-01022', 2901 - '21023': 'v-14071', 2902 - '21024': 'v-01023', 2903 - '21025': 'v-01024', 2904 - '21026': 'v-01025', 2905 - '21027': 'v-01026', 2906 - '21028': 'v-01027', 2907 - '21029': 'v-01028', 2908 - '21030': 'v-01029', 2909 - '21031': 'v-01030', 2910 - '21032': 'v-01031', 2911 - '21033': 'v-01032', 2912 - '21034': 'v-01033', 2913 - '21035': 'v-01034', 2914 - '21036': 'v-01035', 2915 - '21037': 'v-01036', 2916 - '21038': 'v-01037', 2917 - '21039': 'v-01038', 2918 - '21040': 'v-01039', 2919 - '21041': 'v-01040', 2920 - '21042': 'v-01041', 2921 - '21043': 'v-01042', 2922 - '21044': 'v-01043', 2923 - '21045': 'v-01044', 2924 - '21046': 'v-01045', 2925 - '21047': 'v-01046', 2926 - '21048': 'v-01047', 2927 - '21049': 'v-01048', 2928 - '21050': 'v-01049', 2929 - '21051': 'v-01050', 2930 - '21052': 'v-01051', 2931 - '21053': 'v-01052', 2932 - '21054': 'v-01053', 2933 - '21055': 'v-01054', 2934 - '21056': 'v-01055', 2935 - '21057': 'v-01056', 2936 - '21058': 'v-01057', 2937 - '21059': 'v-01058', 2938 - '21060': 'v-01059', 2939 - '21061': 'v-01060', 2940 - '21062': 'v-01061', 2941 - '21063': 'v-01062', 2942 - '21064': 'v-01063', 2943 - '21065': 'v-01064', 2944 - '21066': 'v-01065', 2945 - '21067': 'v-01066', 2946 - '21068': 'v-01067', 2947 - '21069': 'v-01068', 2948 - '21070': 'v-01069', 2949 - '21071': 'v-01070', 2950 - '21072': 'v-01071', 2951 - '21073': 'v-01072', 2952 - '21074': 'v-01073', 2953 - '21075': 'v-01074', 2954 - '21076': 'v-01075', 2955 - '21077': 'v-01076', 2956 - '21078': 'v-01077', 2957 - '21079': 'v-01078', 2958 - '21080': 'v-01079', 2959 - '21081': 'v-01080', 2960 - '21082': 'v-01081', 2961 - '21083': 'v-01082', 2962 - '21084': 'v-01083', 2963 - '21085': 'v-01084', 2964 - '21086': 'v-01085', 2965 - '21087': 'v-01086', 2966 - '21088': 'v-01087', 2967 - '21089': 'v-01088', 2968 - '21090': 'v-01089', 2969 - '21091': 'v-01090', 2970 - '21092': 'v-01091', 2971 - '21093': 'v-01092', 2972 - '21094': 'v-01093', 2973 - '21095': 'v-01094', 2974 - '21096': 'v-01095', 2975 - '21097': 'v-01096', 2976 - '21098': 'v-01097', 2977 - '21099': 'v-01098', 2978 - '21100': 'v-01099', 2979 - '21101': 'v-01100', 2980 - '21102': 'v-01101', 2981 - '21103': 'v-01102', 2982 - '21104': 'v-01103', 2983 - '21105': 'v-01104', 2984 - '21106': 'v-01105', 2985 - '21107': 'v-01106', 2986 - '21108': 'v-01107', 2987 - '21109': 'v-01108', 2988 - '21110': 'v-01109', 2989 - '21111': 'v-01110', 2990 - '21112': 'v-01111', 2991 - '21113': 'v-01112', 2992 - '21114': 'v-01113', 2993 - '21115': 'v-01114', 2994 - '21116': 'v-01115', 2995 - '21117': 'v-01116', 2996 - '21118': 'v-01117', 2997 - '21119': 'v-01118', 2998 - '21120': 'v-01119', 2999 - '21121': 'v-01120', 3000 - '21122': 'v-01121', 3001 - '21123': 'v-01122', 3002 - '21124': 'v-01123', 3003 - '21125': 'v-01124', 3004 - '21126': 'v-01125', 3005 - '21127': 'v-01126', 3006 - '21128': 'v-01127', 3007 - '21129': 'v-01128', 3008 - '21130': 'v-01129', 3009 - '21131': 'v-01130', 3010 - '21132': 'v-01131', 3011 - '21133': 'v-01132', 3012 - '21134': 'v-01133', 3013 - '21135': 'v-01134', 3014 - '21136': 'v-01135', 3015 - '21137': 'v-01136', 3016 - '21138': 'v-01137', 3017 - '21139': 'v-01138', 3018 - '21140': 'v-01139', 3019 - '21141': 'v-01140', 3020 - '21142': 'v-01141', 3021 - '21143': 'v-01142', 3022 - '21144': 'v-01143', 3023 - '21145': 'v-01144', 3024 - '21146': 'v-01145', 3025 - '21147': 'v-01146', 3026 - '21148': 'v-01147', 3027 - '21149': 'v-01148', 3028 - '21150': 'v-01149', 3029 - '21151': 'v-01150', 3030 - '21152': 'v-01151', 3031 - '21153': 'v-01152', 3032 - '21154': 'v-01153', 3033 - '21155': 'v-01154', 3034 - '21156': 'v-01155', 3035 - '21157': 'v-01156', 3036 - '21158': 'v-01157', 3037 - '21159': 'v-01158', 3038 - '21160': 'v-01159', 3039 - '21161': 'v-01160', 3040 - '21162': 'v-01161', 3041 - '21163': 'v-01162', 3042 - '21164': 'v-01163', 3043 - '21165': 'v-01164', 3044 - '21166': 'v-01165', 3045 - '21167': 'v-01166', 3046 - '21168': 'v-01167', 3047 - '21169': 'v-01168', 3048 - '21170': 'v-01169', 3049 - '21171': 'v-01170', 3050 - '21172': 'v-01171', 3051 - '21173': 'v-01172', 3052 - '21174': 'v-01173', 3053 - '21175': 'v-01174', 3054 - '21176': 'v-01175', 3055 - '21177': 'v-01176', 3056 - '21178': 'v-01177', 3057 - '21179': 'v-01178', 3058 - '21180': 'v-01179', 3059 - '21181': 'v-01180', 3060 - '21182': 'v-01181', 3061 - '21183': 'v-01182', 3062 - '21184': 'v-01183', 3063 - '21185': 'v-01184', 3064 - '21186': 'v-01185', 3065 - '21187': 'v-01186', 3066 - '21188': 'v-01187', 3067 - '21189': 'v-01188', 3068 - '21190': 'v-01189', 3069 - '21191': 'v-01190', 3070 - '21192': 'v-01191', 3071 - '21193': 'v-01192', 3072 - '21194': 'v-01193', 3073 - '21195': 'v-01194', 3074 - '21196': 'v-01195', 3075 - '21197': 'v-01196', 3076 - '21198': 'v-01197', 3077 - '21199': 'v-01198', 3078 - '21200': 'v-01199', 3079 - '21201': 'v-01200', 3080 - '21202': 'v-01201', 3081 - '21203': 'v-01202', 3082 - '21204': 'v-01203', 3083 - '21205': 'v-01204', 3084 - '21206': 'v-01205', 3085 - '21207': 'v-01206', 3086 - '21208': 'v-01207', 3087 - '21209': 'v-01208', 3088 - '21210': 'v-14058', 3089 - '21211': 'v-01209', 3090 - '21212': 'v-01210', 3091 - '21213': 'v-01211', 3092 - '21214': 'v-01212', 3093 - '21215': 'v-01213', 3094 - '21216': 'v-01214', 3095 - '21217': 'v-01215', 3096 - '21218': 'v-01216', 3097 - '21219': 'v-01217', 3098 - '21220': 'v-01218', 3099 - '21221': 'v-01219', 3100 - '21222': 'v-01220', 3101 - '21223': 'v-01221', 3102 - '21224': 'v-01222', 3103 - '21225': 'v-01223', 3104 - '21226': 'v-01224', 3105 - '21227': 'v-01225', 3106 - '21228': 'v-01226', 3107 - '21229': 'v-01227', 3108 - '21230': 'v-01228', 3109 - '21231': 'v-01229', 3110 - '21232': 'v-01230', 3111 - '21233': 'v-01231', 3112 - '21234': 'v-01232', 3113 - '21235': 'v-01233', 3114 - '21236': 'v-01234', 3115 - '21237': 'v-01235', 3116 - '21238': 'v-01236', 3117 - '21239': 'v-01237', 3118 - '21240': 'v-01238', 3119 - '21241': 'v-01239', 3120 - '21242': 'v-01240', 3121 - '21243': 'v-01241', 3122 - '21244': 'v-01242', 3123 - '21245': 'v-01243', 3124 - '21246': 'v-01244', 3125 - '21247': 'v-01245', 3126 - '21248': 'v-01246', 3127 - '21249': 'v-01247', 3128 - '21250': 'v-01248', 3129 - '21251': 'v-01249', 3130 - '21252': 'v-01250', 3131 - '21253': 'v-01251', 3132 - '21254': 'v-01252', 3133 - '21255': 'v-01253', 3134 - '21256': 'v-01254', 3135 - '21257': 'v-01255', 3136 - '21258': 'v-01256', 3137 - '21259': 'v-01257', 3138 - '21260': 'v-01258', 3139 - '21261': 'v-01259', 3140 - '21262': 'v-01260', 3141 - '21263': 'v-01261', 3142 - '21264': 'v-01262', 3143 - '21265': 'v-01263', 3144 - '21266': 'v-01264', 3145 - '21267': 'v-01265', 3146 - '21268': 'v-01266', 3147 - '21269': 'v-01267', 3148 - '21270': 'v-01268', 3149 - '21271': 'v-01269', 3150 - '21272': 'v-01270', 3151 - '21273': 'v-01271', 3152 - '21274': 'v-01272', 3153 - '21275': 'v-01273', 3154 - '21276': 'v-01274', 3155 - '21277': 'v-01275', 3156 - '21278': 'v-01276', 3157 - '21279': 'v-01277', 3158 - '21280': 'v-01278', 3159 - '21281': 'v-01279', 3160 - '21282': 'v-01280', 3161 - '21283': 'v-01281', 3162 - '21284': 'v-01282', 3163 - '21285': 'v-01283', 3164 - '21286': 'v-01284', 3165 - '21287': 'v-01285', 3166 - '21288': 'v-01286', 3167 - '21289': 'v-01287', 3168 - '21290': 'v-01288', 3169 - '21291': 'v-01289', 3170 - '21292': 'v-01290', 3171 - '21293': 'v-01291', 3172 - '21294': 'v-01292', 3173 - '21295': 'v-01293', 3174 - '21296': 'v-01294', 3175 - '21297': 'v-01295', 3176 - '21298': 'v-01296', 3177 - '21299': 'v-01297', 3178 - '21300': 'v-01298', 3179 - '21301': 'v-01299', 3180 - '21302': 'v-01300', 3181 - '21303': 'v-01301', 3182 - '21304': 'v-01302', 3183 - '21305': 'v-01303', 3184 - '21306': 'v-01304', 3185 - '21307': 'v-01305', 3186 - '21308': 'v-01306', 3187 - '21309': 'v-01307', 3188 - '21310': 'v-01308', 3189 - '21311': 'v-01309', 3190 - '21312': 'v-01310', 3191 - '21313': 'v-01311', 3192 - '21314': 'v-01312', 3193 - '21315': 'v-01313', 3194 - '21316': 'v-01314', 3195 - '21317': 'v-01315', 3196 - '21318': 'v-01316', 3197 - '21319': 'v-01317', 3198 - '21320': 'v-01318', 3199 - '21321': 'v-01319', 3200 - '21322': 'v-01320', 3201 - '21323': 'v-01321', 3202 - '21324': 'v-01322', 3203 - '21325': 'v-01323', 3204 - '21326': 'v-01324', 3205 - '21327': 'v-01325', 3206 - '21328': 'v-01326', 3207 - '21329': 'v-01327', 3208 - '21330': 'v-01328', 3209 - '21331': 'v-01329', 3210 - '21332': 'v-01330', 3211 - '21333': 'v-01331', 3212 - '21334': 'v-01332', 3213 - '21335': 'v-01333', 3214 - '21336': 'v-01334', 3215 - '21337': 'v-01335', 3216 - '21338': 'v-01336', 3217 - '21339': 'v-01337', 3218 - '21340': 'v-01338', 3219 - '21341': 'v-01339', 3220 - '21342': 'v-01340', 3221 - '21343': 'v-01341', 3222 - '21344': 'v-01342', 3223 - '21345': 'v-01343', 3224 - '21346': 'v-01344', 3225 - '21347': 'v-01345', 3226 - '21348': 'v-01346', 3227 - '21349': 'v-01347', 3228 - '21350': 'v-01348', 3229 - '21351': 'v-01349', 3230 - '21352': 'v-01350', 3231 - '21353': 'v-01351', 3232 - '21354': 'v-01352', 3233 - '21355': 'v-01353', 3234 - '21356': 'v-01354', 3235 - '21357': 'v-01355', 3236 - '21358': 'v-01356', 3237 - '21359': 'v-01357', 3238 - '21360': 'v-01358', 3239 - '21361': 'v-01359', 3240 - '21362': 'v-01360', 3241 - '21363': 'v-01361', 3242 - '21364': 'v-01362', 3243 - '21365': 'v-01363', 3244 - '21366': 'v-01364', 3245 - '21367': 'v-01365', 3246 - '21368': 'v-01366', 3247 - '21369': 'v-01367', 3248 - '21370': 'v-01368', 3249 - '21371': 'v-01369', 3250 - '21372': 'v-01370', 3251 - '21373': 'v-01371', 3252 - '21374': 'v-01372', 3253 - '21375': 'v-01373', 3254 - '21376': 'v-01374', 3255 - '21377': 'v-01375', 3256 - '21378': 'v-01376', 3257 - '21379': 'v-01377', 3258 - '21380': 'v-01378', 3259 - '21381': 'v-01379', 3260 - '21382': 'v-01380', 3261 - '21383': 'v-01381', 3262 - '21384': 'v-01382', 3263 - '21385': 'v-01383', 3264 - '21386': 'v-01384', 3265 - '21387': 'v-01385', 3266 - '21388': 'v-01386', 3267 - '21389': 'v-01387', 3268 - '21390': 'v-01388', 3269 - '21391': 'v-01389', 3270 - '21392': 'v-01390', 3271 - '21393': 'v-01391', 3272 - '21394': 'v-01392', 3273 - '21395': 'v-01393', 3274 - '21396': 'v-01394', 3275 - '21397': 'v-01395', 3276 - '21398': 'v-01396', 3277 - '21399': 'v-01397', 3278 - '21400': 'v-01398', 3279 - '21401': 'v-01399', 3280 - '21402': 'v-01400', 3281 - '21403': 'v-01401', 3282 - '21404': 'v-01402', 3283 - '21405': 'v-01403', 3284 - '21406': 'v-01404', 3285 - '21407': 'v-01405', 3286 - '21408': 'v-01406', 3287 - '21409': 'v-01407', 3288 - '21410': 'v-01408', 3289 - '21411': 'v-01409', 3290 - '21412': 'v-01410', 3291 - '21413': 'v-01411', 3292 - '21414': 'v-01412', 3293 - '21415': 'v-01413', 3294 - '21416': 'v-01414', 3295 - '21417': 'v-01415', 3296 - '21418': 'v-01416', 3297 - '21419': 'v-01417', 3298 - '21420': 'v-01418', 3299 - '21421': 'v-01419', 3300 - '21422': 'v-01420', 3301 - '21423': 'v-01421', 3302 - '21424': 'v-01422', 3303 - '21425': 'v-01423', 3304 - '21426': 'v-01424', 3305 - '21427': 'v-01425', 3306 - '21428': 'v-01426', 3307 - '21429': 'v-01427', 3308 - '21430': 'v-01428', 3309 - '21431': 'v-01429', 3310 - '21432': 'v-01430', 3311 - '21433': 'v-01431', 3312 - '21434': 'v-01432', 3313 - '21435': 'v-01433', 3314 - '21436': 'v-01434', 3315 - '21437': 'v-01435', 3316 - '21438': 'v-01436', 3317 - '21439': 'v-01437', 3318 - '21440': 'v-01438', 3319 - '21441': 'v-14059', 3320 - '21442': 'v-14060', 3321 - '21443': 'v-01439', 3322 - '21444': 'v-01440', 3323 - '21445': 'v-01441', 3324 - '21446': 'v-01442', 3325 - '21447': 'v-01443', 3326 - '21448': 'v-01444', 3327 - '21449': 'v-01445', 3328 - '21450': 'v-01446', 3329 - '21451': 'v-01447', 3330 - '21452': 'v-01448', 3331 - '21453': 'v-01449', 3332 - '21454': 'v-14061', 3333 - '21455': 'v-14062', 3334 - '21456': 'v-14063', 3335 - '21457': 'v-01450', 3336 - '21458': 'v-01451', 3337 - '21459': 'v-01452', 3338 - '21460': 'v-01453', 3339 - '21461': 'v-01454', 3340 - '21462': 'v-14064', 3341 - '21463': 'v-01455', 3342 - '21464': 'v-01456', 3343 - '21465': 'v-01457', 3344 - '21466': 'v-01458', 3345 - '21467': 'v-01459', 3346 - '21468': 'v-01460', 3347 - '21469': 'v-01461', 3348 - '21470': 'v-01462', 3349 - '21471': 'v-01463', 3350 - '21472': 'v-01464', 3351 - '21473': 'v-01465', 3352 - '21474': 'v-01466', 3353 - '21475': 'v-01467', 3354 - '21476': 'v-01468', 3355 - '21477': 'v-01469', 3356 - '21478': 'v-01470', 3357 - '21479': 'v-01471', 3358 - '21480': 'v-01472', 3359 - '21481': 'v-01473', 3360 - '21482': 'v-01474', 3361 - '21483': 'v-01475', 3362 - '21484': 'v-01476', 3363 - '21485': 'v-01477', 3364 - '21486': 'v-01478', 3365 - '21487': 'v-01479', 3366 - '21488': 'v-01480', 3367 - '21489': 'v-01481', 3368 - '21490': 'v-01482', 3369 - '21491': 'v-01483', 3370 - '21492': 'v-01484', 3371 - '21493': 'v-01485', 3372 - '21494': 'v-01486', 3373 - '21495': 'v-01487', 3374 - '21496': 'v-01488', 3375 - '21497': 'v-01489', 3376 - '21498': 'v-01490', 3377 - '21499': 'v-01491', 3378 - '21500': 'v-01492', 3379 - '21501': 'v-01493', 3380 - '21502': 'v-01494', 3381 - '21503': 'v-01495', 3382 - '21504': 'v-01496', 3383 - '21505': 'v-01497', 3384 - '21506': 'v-01498', 3385 - '21507': 'v-01499', 3386 - '21508': 'v-01500', 3387 - '21509': 'v-01501', 3388 - '21510': 'v-01502', 3389 - '21511': 'v-01503', 3390 - '21512': 'v-01504', 3391 - '21513': 'v-01505', 3392 - '21514': 'v-01506', 3393 - '21515': 'v-01507', 3394 - '21516': 'v-01508', 3395 - '21517': 'v-01509', 3396 - '21518': 'v-01510', 3397 - '21519': 'v-01511', 3398 - '21520': 'v-01512', 3399 - '21521': 'v-01513', 3400 - '21522': 'v-01514', 3401 - '21523': 'v-01515', 3402 - '21524': 'v-01516', 3403 - '21525': 'v-01517', 3404 - '21526': 'v-01518', 3405 - '21527': 'v-01519', 3406 - '21528': 'v-01520', 3407 - '21529': 'v-01521', 3408 - '21530': 'v-01522', 3409 - '21531': 'v-01523', 3410 - '21532': 'v-01524', 3411 - '21533': 'v-01525', 3412 - '21534': 'v-01526', 3413 - '21535': 'v-01527', 3414 - '21536': 'v-01528', 3415 - '21537': 'v-01529', 3416 - '21538': 'v-01530', 3417 - '21539': 'v-01531', 3418 - '21540': 'v-01532', 3419 - '21541': 'v-01533', 3420 - '21542': 'v-01534', 3421 - '21543': 'v-01535', 3422 - '21544': 'v-01536', 3423 - '21545': 'v-01537', 3424 - '21546': 'v-01538', 3425 - '21547': 'v-01539', 3426 - '21548': 'v-01540', 3427 - '21549': 'v-01541', 3428 - '21550': 'v-01542', 3429 - '21551': 'v-01543', 3430 - '21552': 'v-01544', 3431 - '21553': 'v-01545', 3432 - '21554': 'v-01546', 3433 - '21555': 'v-01547', 3434 - '21556': 'v-01548', 3435 - '21557': 'v-01549', 3436 - '21558': 'v-01550', 3437 - '21559': 'v-01551', 3438 - '21560': 'v-01552', 3439 - '21561': 'v-01553', 3440 - '21562': 'v-01554', 3441 - '21563': 'v-01555', 3442 - '21564': 'v-01556', 3443 - '21565': 'v-01557', 3444 - '21566': 'v-01558', 3445 - '21567': 'v-01559', 3446 - '21568': 'v-01560', 3447 - '21569': 'v-01561', 3448 - '21570': 'v-01562', 3449 - '21571': 'v-01563', 3450 - '21572': 'v-01564', 3451 - '21573': 'v-01565', 3452 - '21574': 'v-01566', 3453 - '21575': 'v-01567', 3454 - '21576': 'v-01568', 3455 - '21577': 'v-01569', 3456 - '21578': 'v-01570', 3457 - '21579': 'v-01571', 3458 - '21580': 'v-01572', 3459 - '21581': 'v-01573', 3460 - '21582': 'v-01574', 3461 - '21583': 'v-01575', 3462 - '21584': 'v-01576', 3463 - '21585': 'v-01577', 3464 - '21586': 'v-01578', 3465 - '21587': 'v-01579', 3466 - '21588': 'v-01580', 3467 - '21589': 'v-01581', 3468 - '21590': 'v-01582', 3469 - '21591': 'v-01583', 3470 - '21592': 'v-01584', 3471 - '21593': 'v-01585', 3472 - '21594': 'v-01586', 3473 - '21595': 'v-01587', 3474 - '21596': 'v-01588', 3475 - '21597': 'v-01589', 3476 - '21598': 'v-01590', 3477 - '21599': 'v-01591', 3478 - '21600': 'v-01592', 3479 - '21601': 'v-01593', 3480 - '21602': 'v-01594', 3481 - '21603': 'v-01595', 3482 - '21604': 'v-01596', 3483 - '21605': 'v-01597', 3484 - '21606': 'v-01598', 3485 - '21607': 'v-01599', 3486 - '21608': 'v-01600', 3487 - '21609': 'v-01601', 3488 - '21610': 'v-01602', 3489 - '21611': 'v-01603', 3490 - '21612': 'v-01604', 3491 - '21613': 'v-01605', 3492 - '21614': 'v-01606', 3493 - '21615': 'v-01607', 3494 - '21616': 'v-01608', 3495 - '21617': 'v-01609', 3496 - '21618': 'v-01610', 3497 - '21619': 'v-01611', 3498 - '21620': 'v-01612', 3499 - '21621': 'v-01613', 3500 - '21622': 'v-01614', 3501 - '21623': 'v-01615', 3502 - '21624': 'v-01616', 3503 - '21625': 'v-01617', 3504 - '21626': 'v-01618', 3505 - '21627': 'v-01619', 3506 - '21628': 'v-01620', 3507 - '21629': 'v-01621', 3508 - '21630': 'v-01622', 3509 - '21631': 'v-01623', 3510 - '21632': 'v-01624', 3511 - '21633': 'v-01625', 3512 - '21634': 'v-01626', 3513 - '21635': 'v-01627', 3514 - '21636': 'v-01628', 3515 - '21637': 'v-01629', 3516 - '21638': 'v-01630', 3517 - '21639': 'v-01631', 3518 - '21640': 'v-01632', 3519 - '21641': 'v-01633', 3520 - '21642': 'v-01634', 3521 - '21643': 'v-01635', 3522 - '21644': 'v-01636', 3523 - '21645': 'v-01637', 3524 - '21646': 'v-01638', 3525 - '21647': 'v-01639', 3526 - '21648': 'v-01640', 3527 - '21649': 'v-01641', 3528 - '21650': 'v-01642', 3529 - '21651': 'v-01643', 3530 - '21652': 'v-01644', 3531 - '21653': 'v-01645', 3532 - '21654': 'v-01646', 3533 - '21655': 'v-01647', 3534 - '21656': 'v-01648', 3535 - '21657': 'v-01649', 3536 - '21658': 'v-01650', 3537 - '21659': 'v-01651', 3538 - '21660': 'v-01652', 3539 - '21661': 'v-01653', 3540 - '21662': 'v-01654', 3541 - '21663': 'v-01655', 3542 - '21664': 'v-01656', 3543 - '21665': 'v-01657', 3544 - '21666': 'v-01658', 3545 - '21667': 'v-01659', 3546 - '21668': 'v-01660', 3547 - '21669': 'v-01661', 3548 - '21670': 'v-01662', 3549 - '21671': 'v-01663', 3550 - '21672': 'v-01664', 3551 - '21673': 'v-01665', 3552 - '21674': 'v-01666', 3553 - '21675': 'v-01667', 3554 - '21676': 'v-01668', 3555 - '21677': 'v-01669', 3556 - '21678': 'v-01670', 3557 - '21679': 'v-01671', 3558 - '21680': 'v-01672', 3559 - '21681': 'v-01673', 3560 - '21682': 'v-01674', 3561 - '21683': 'v-01675', 3562 - '21684': 'v-01676', 3563 - '21685': 'v-01677', 3564 - '21686': 'v-01678', 3565 - '21687': 'v-01679', 3566 - '21688': 'v-01680', 3567 - '21689': 'v-01681', 3568 - '21690': 'v-01682', 3569 - '21691': 'v-01683', 3570 - '21692': 'v-01684', 3571 - '21693': 'v-01685', 3572 - '21694': 'v-01686', 3573 - '21695': 'v-01687', 3574 - '21696': 'v-01688', 3575 - '21697': 'v-01689', 3576 - '21698': 'v-01690', 3577 - '21699': 'v-01691', 3578 - '21700': 'v-01692', 3579 - '21701': 'v-01693', 3580 - '21702': 'v-01694', 3581 - '21703': 'v-01695', 3582 - '21704': 'v-01696', 3583 - '21705': 'v-01697', 3584 - '21706': 'v-01698', 3585 - '21707': 'v-01699', 3586 - '21708': 'v-01700', 3587 - '21709': 'v-01701', 3588 - '21710': 'v-01702', 3589 - '21711': 'v-01703', 3590 - '21712': 'v-01704', 3591 - '21713': 'v-01705', 3592 - '21714': 'v-01706', 3593 - '21715': 'v-01707', 3594 - '21716': 'v-01708', 3595 - '21717': 'v-01709', 3596 - '21718': 'v-01710', 3597 - '21719': 'v-01711', 3598 - '21720': 'v-01712', 3599 - '21721': 'v-01713', 3600 - '21722': 'v-01714', 3601 - '21723': 'v-01715', 3602 - '21724': 'v-01716', 3603 - '21725': 'v-01717', 3604 - '21726': 'v-01718', 3605 - '21727': 'v-01719', 3606 - '21728': 'v-01720', 3607 - '21729': 'v-01721', 3608 - '21730': 'v-01722', 3609 - '21731': 'v-01723', 3610 - '21732': 'v-01724', 3611 - '21733': 'v-01725', 3612 - '21734': 'v-01726', 3613 - '21735': 'v-01727', 3614 - '21736': 'v-01728', 3615 - '21737': 'v-01729', 3616 - '21738': 'v-01730', 3617 - '21739': 'v-01731', 3618 - '21740': 'v-01732', 3619 - '21741': 'v-01733', 3620 - '21742': 'v-01734', 3621 - '21743': 'v-01735', 3622 - '21744': 'v-01736', 3623 - '21745': 'v-01737', 3624 - '21746': 'v-01738', 3625 - '21747': 'v-01739', 3626 - '21748': 'v-01740', 3627 - '21749': 'v-01741', 3628 - '21750': 'v-01742', 3629 - '21751': 'v-01743', 3630 - '21752': 'v-01744', 3631 - '21753': 'v-01745', 3632 - '21754': 'v-01746', 3633 - '21755': 'v-01747', 3634 - '21756': 'v-01748', 3635 - '21757': 'v-01749', 3636 - '21758': 'v-01750', 3637 - '21759': 'v-01751', 3638 - '21760': 'v-01752', 3639 - '21761': 'v-01753', 3640 - '21762': 'v-01754', 3641 - '21763': 'v-01755', 3642 - '21764': 'v-01756', 3643 - '21765': 'v-01757', 3644 - '21766': 'v-01758', 3645 - '21767': 'v-01759', 3646 - '21768': 'v-01760', 3647 - '21769': 'v-01761', 3648 - '21770': 'v-01762', 3649 - '21771': 'v-01763', 3650 - '21772': 'v-01764', 3651 - '21773': 'v-01765', 3652 - '21774': 'v-01766', 3653 - '21775': 'v-01767', 3654 - '21776': 'v-01768', 3655 - '21777': 'v-01769', 3656 - '21778': 'v-01770', 3657 - '21779': 'v-01771', 3658 - '21780': 'v-01772', 3659 - '21781': 'v-01773', 3660 - '21782': 'v-01774', 3661 - '21783': 'v-01775', 3662 - '21784': 'v-01776', 3663 - '21785': 'v-01777', 3664 - '21786': 'v-01778', 3665 - '21787': 'v-01779', 3666 - '21788': 'v-01780', 3667 - '21789': 'v-01781', 3668 - '21790': 'v-01782', 3669 - '21791': 'v-01783', 3670 - '21792': 'v-01784', 3671 - '21793': 'v-01785', 3672 - '21794': 'v-01786', 3673 - '21795': 'v-01787', 3674 - '21796': 'v-01788', 3675 - '21797': 'v-01789', 3676 - '21798': 'v-01790', 3677 - '21799': 'v-01791', 3678 - '21800': 'v-01792', 3679 - '21801': 'v-01793', 3680 - '21802': 'v-01794', 3681 - '21803': 'v-01795', 3682 - '21804': 'v-01796', 3683 - '21805': 'v-01797', 3684 - '21806': 'v-01798', 3685 - '21807': 'v-01799', 3686 - '21808': 'v-01800', 3687 - '21809': 'v-01801', 3688 - '21810': 'v-01802', 3689 - '21811': 'v-01803', 3690 - '21812': 'v-01804', 3691 - '21813': 'v-01805', 3692 - '21814': 'v-01806', 3693 - '21815': 'v-01807', 3694 - '21816': 'v-01808', 3695 - '21817': 'v-01809', 3696 - '21818': 'v-01810', 3697 - '21819': 'v-01811', 3698 - '21820': 'v-01812', 3699 - '21821': 'v-01813', 3700 - '21822': 'v-01814', 3701 - '21823': 'v-01815', 3702 - '21824': 'v-01816', 3703 - '21825': 'v-01817', 3704 - '21826': 'v-01818', 3705 - '21827': 'v-01819', 3706 - '21828': 'v-01820', 3707 - '21829': 'v-01821', 3708 - '21830': 'v-01822', 3709 - '21831': 'v-01823', 3710 - '21832': 'v-01824', 3711 - '21833': 'v-01825', 3712 - '21834': 'v-01826', 3713 - '21835': 'v-01827', 3714 - '21836': 'v-01828', 3715 - '21837': 'v-01829', 3716 - '21838': 'v-01830', 3717 - '21839': 'v-01831', 3718 - '21840': 'v-01832', 3719 - '21841': 'v-01833', 3720 - '21842': 'v-01834', 3721 - '21843': 'v-01835', 3722 - '21844': 'v-01836', 3723 - '21845': 'v-01837', 3724 - '21846': 'v-01838', 3725 - '21847': 'v-01839', 3726 - '21848': 'v-01840', 3727 - '21849': 'v-01841', 3728 - '21850': 'v-01842', 3729 - '21851': 'v-01843', 3730 - '21852': 'v-01844', 3731 - '21853': 'v-01845', 3732 - '21854': 'v-01846', 3733 - '21855': 'v-01847', 3734 - '21856': 'v-01848', 3735 - '21857': 'v-01849', 3736 - '21858': 'v-01850', 3737 - '21859': 'v-01851', 3738 - '21860': 'v-01852', 3739 - '21861': 'v-01853', 3740 - '21862': 'v-01854', 3741 - '21863': 'v-01855', 3742 - '21864': 'v-01856', 3743 - '21865': 'v-01857', 3744 - '21866': 'v-01858', 3745 - '21867': 'v-01859', 3746 - '21868': 'v-01860', 3747 - '21869': 'v-01861', 3748 - '21870': 'v-01862', 3749 - '21871': 'v-01863', 3750 - '21872': 'v-01864', 3751 - '21873': 'v-01865', 3752 - '21874': 'v-01866', 3753 - '21875': 'v-01867', 3754 - '21876': 'v-01868', 3755 - '21877': 'v-01869', 3756 - '21878': 'v-01870', 3757 - '21879': 'v-01871', 3758 - '21880': 'v-01872', 3759 - '21881': 'v-01873', 3760 - '21882': 'v-01874', 3761 - '21883': 'v-01875', 3762 - '21884': 'v-01876', 3763 - '21885': 'v-01877', 3764 - '21886': 'v-01878', 3765 - '21887': 'v-01879', 3766 - '21888': 'v-01880', 3767 - '21889': 'v-01881', 3768 - '21890': 'v-01882', 3769 - '21891': 'v-01883', 3770 - '21892': 'v-01884', 3771 - '21893': 'v-01885', 3772 - '21894': 'v-01886', 3773 - '21895': 'v-01887', 3774 - '21896': 'v-01888', 3775 - '21897': 'v-01889', 3776 - '21898': 'v-01890', 3777 - '21899': 'v-01891', 3778 - '21900': 'v-01892', 3779 - '21901': 'v-01893', 3780 - '21902': 'v-01894', 3781 - '21903': 'v-01895', 3782 - '21904': 'v-01896', 3783 - '21905': 'v-01897', 3784 - '21906': 'v-01898', 3785 - '21907': 'v-01899', 3786 - '21908': 'v-01900', 3787 - '21909': 'v-01901', 3788 - '21910': 'v-01902', 3789 - '21911': 'v-01903', 3790 - '21912': 'v-01904', 3791 - '21913': 'v-01905', 3792 - '21914': 'v-01906', 3793 - '21915': 'v-01907', 3794 - '21916': 'v-01908', 3795 - '21917': 'v-01909', 3796 - '21918': 'v-01910', 3797 - '21919': 'v-14065', 3798 - '21920': 'v-01911', 3799 - '21921': 'v-01912', 3800 - '21922': 'v-01913', 3801 - '21923': 'v-01914', 3802 - '21924': 'v-01915', 3803 - '21925': 'v-01916', 3804 - '21926': 'v-01917', 3805 - '21927': 'v-01918', 3806 - '21928': 'v-01919', 3807 - '21929': 'v-01920', 3808 - '21930': 'v-01921', 3809 - '21931': 'v-01922', 3810 - '21932': 'v-01923', 3811 - '21933': 'v-01924', 3812 - '21934': 'v-01925', 3813 - '21935': 'v-01926', 3814 - '21936': 'v-01927', 3815 - '21937': 'v-01928', 3816 - '21938': 'v-01929', 3817 - '21939': 'v-01930', 3818 - '21940': 'v-01931', 3819 - '21941': 'v-01932', 3820 - '21942': 'v-01933', 3821 - '21943': 'v-01934', 3822 - '21944': 'v-01935', 3823 - '21945': 'v-01936', 3824 - '21946': 'v-01937', 3825 - '21947': 'v-01938', 3826 - '21948': 'v-01939', 3827 - '21949': 'v-01940', 3828 - '21950': 'v-01941', 3829 - '21951': 'v-01942', 3830 - '21952': 'v-01943', 3831 - '21953': 'v-01944', 3832 - '21954': 'v-01945', 3833 - '21955': 'v-01946', 3834 - '21956': 'v-01947', 3835 - '21957': 'v-01948', 3836 - '21958': 'v-01949', 3837 - '21959': 'v-01950', 3838 - '21960': 'v-01951', 3839 - '21961': 'v-01952', 3840 - '21962': 'v-01953', 3841 - '21963': 'v-01954', 3842 - '21964': 'v-01955', 3843 - '21965': 'v-01956', 3844 - '21966': 'v-01957', 3845 - '21967': 'v-01958', 3846 - '21968': 'v-01959', 3847 - '21969': 'v-01960', 3848 - '21970': 'v-01961', 3849 - '21971': 'v-01962', 3850 - '21972': 'v-01963', 3851 - '21973': 'v-01964', 3852 - '21974': 'v-01965', 3853 - '21975': 'v-01966', 3854 - '21976': 'v-01967', 3855 - '21977': 'v-01968', 3856 - '21978': 'v-01969', 3857 - '21979': 'v-01970', 3858 - '21980': 'v-01971', 3859 - '21981': 'v-01972', 3860 - '21982': 'v-01973', 3861 - '21983': 'v-01974', 3862 - '21984': 'v-01975', 3863 - '21985': 'v-01976', 3864 - '21986': 'v-01977', 3865 - '21987': 'v-01978', 3866 - '21988': 'v-01979', 3867 - '21989': 'v-01980', 3868 - '21990': 'v-01981', 3869 - '21991': 'v-01982', 3870 - '21992': 'v-01983', 3871 - '21993': 'v-01984', 3872 - '21994': 'v-01985', 3873 - '21995': 'v-01986', 3874 - '21996': 'v-01987', 3875 - '21997': 'v-01988', 3876 - '21998': 'v-01989', 3877 - '21999': 'v-01990', 3878 - '22000': 'v-01991', 3879 - '22001': 'v-01992', 3880 - '22002': 'v-01993', 3881 - '22003': 'v-01994', 3882 - '22004': 'v-01995', 3883 - '22005': 'v-01996', 3884 - '22006': 'v-01997', 3885 - '22007': 'v-01998', 3886 - '22008': 'v-01999', 3887 - '22009': 'v-02000', 3888 - '22010': 'v-02001', 3889 - '22011': 'v-02002', 3890 - '22012': 'v-02003', 3891 - '22013': 'v-02004', 3892 - '22014': 'v-02005', 3893 - '22015': 'v-02006', 3894 - '22016': 'v-02007', 3895 - '22017': 'v-02008', 3896 - '22018': 'v-02009', 3897 - '22019': 'v-02010', 3898 - '22020': 'v-02011', 3899 - '22021': 'v-02012', 3900 - '22022': 'v-02013', 3901 - '22023': 'v-02014', 3902 - '22024': 'v-02015', 3903 - '22025': 'v-02016', 3904 - '22026': 'v-02017', 3905 - '22027': 'v-02018', 3906 - '22028': 'v-02019', 3907 - '22029': 'v-02020', 3908 - '22030': 'v-02021', 3909 - '22031': 'v-02022', 3910 - '22032': 'v-02023', 3911 - '22033': 'v-02024', 3912 - '22034': 'v-02025', 3913 - '22035': 'v-02026', 3914 - '22036': 'v-02027', 3915 - '22037': 'v-02028', 3916 - '22038': 'v-02029', 3917 - '22039': 'v-02030', 3918 - '22040': 'v-02031', 3919 - '22041': 'v-02032', 3920 - '22042': 'v-02033', 3921 - '22043': 'v-02034', 3922 - '22044': 'v-02035', 3923 - '22045': 'v-02036', 3924 - '22046': 'v-02037', 3925 - '22047': 'v-02038', 3926 - '22048': 'v-02039', 3927 - '22049': 'v-02040', 3928 - '22050': 'v-02041', 3929 - '22051': 'v-02042', 3930 - '22052': 'v-02043', 3931 - '22053': 'v-02044', 3932 - '22054': 'v-02045', 3933 - '22055': 'v-02046', 3934 - '22056': 'v-02047', 3935 - '22057': 'v-02048', 3936 - '22058': 'v-02049', 3937 - '22059': 'v-02050', 3938 - '22060': 'v-02051', 3939 - '22061': 'v-02052', 3940 - '22062': 'v-02053', 3941 - '22063': 'v-02054', 3942 - '22064': 'v-14066', 3943 - '22065': 'v-02055', 3944 - '22066': 'v-02056', 3945 - '22067': 'v-02057', 3946 - '22068': 'v-02058', 3947 - '22069': 'v-02059', 3948 - '22070': 'v-02060', 3949 - '22071': 'v-02061', 3950 - '22072': 'v-02062', 3951 - '22073': 'v-02063', 3952 - '22074': 'v-02064', 3953 - '22075': 'v-02065', 3954 - '22076': 'v-02066', 3955 - '22077': 'v-02067', 3956 - '22078': 'v-02068', 3957 - '22079': 'v-02069', 3958 - '22080': 'v-02070', 3959 - '22081': 'v-02071', 3960 - '22082': 'v-02072', 3961 - '22083': 'v-02073', 3962 - '22084': 'v-02074', 3963 - '22085': 'v-02075', 3964 - '22086': 'v-02076', 3965 - '22087': 'v-02077', 3966 - '22088': 'v-02078', 3967 - '22089': 'v-02079', 3968 - '22090': 'v-02080', 3969 - '22091': 'v-02081', 3970 - '22092': 'v-02082', 3971 - '22093': 'v-02083', 3972 - '22094': 'v-02084', 3973 - '22095': 'v-02085', 3974 - '22096': 'v-02086', 3975 - '22097': 'v-02087', 3976 - '22098': 'v-02088', 3977 - '22099': 'v-02089', 3978 - '22100': 'v-02090', 3979 - '22101': 'v-02091', 3980 - '22102': 'v-02092', 3981 - '22103': 'v-02093', 3982 - '22104': 'v-02094', 3983 - '22105': 'v-02095', 3984 - '22106': 'v-02096', 3985 - '22107': 'v-02097', 3986 - '22108': 'v-02098', 3987 - '22109': 'v-02099', 3988 - '22110': 'v-02100', 3989 - '22111': 'v-02101', 3990 - '22112': 'v-02102', 3991 - '22113': 'v-02103', 3992 - '22114': 'v-02104', 3993 - '22115': 'v-02105', 3994 - '22116': 'v-02106', 3995 - '22117': 'v-02107', 3996 - '22118': 'v-02108', 3997 - '22119': 'v-02109', 3998 - '22120': 'v-02110', 3999 - '22121': 'v-02111', 4000 - '22122': 'v-02112', 4001 - '22123': 'v-02113', 4002 - '22124': 'v-02114', 4003 - '22125': 'v-02115', 4004 - '22126': 'v-02116', 4005 - '22127': 'v-02117', 4006 - '22128': 'v-02118', 4007 - '22129': 'v-02119', 4008 - '22130': 'v-02120', 4009 - '22131': 'v-02121', 4010 - '22132': 'v-02122', 4011 - '22133': 'v-02123', 4012 - '22134': 'v-02124', 4013 - '22135': 'v-02125', 4014 - '22136': 'v-02126', 4015 - '22137': 'v-02127', 4016 - '22138': 'v-02128', 4017 - '22139': 'v-02129', 4018 - '22140': 'v-02130', 4019 - '22141': 'v-02131', 4020 - '22142': 'v-02132', 4021 - '22143': 'v-02133', 4022 - '22144': 'v-02134', 4023 - '22145': 'v-02135', 4024 - '22146': 'v-02136', 4025 - '22147': 'v-02137', 4026 - '22148': 'v-02138', 4027 - '22149': 'v-02139', 4028 - '22150': 'v-02140', 4029 - '22151': 'v-02141', 4030 - '22152': 'v-02142', 4031 - '22153': 'v-02143', 4032 - '22154': 'v-02144', 4033 - '22155': 'v-02145', 4034 - '22156': 'v-02146', 4035 - '22157': 'v-02147', 4036 - '22158': 'v-02148', 4037 - '22159': 'v-02149', 4038 - '22160': 'v-02150', 4039 - '22161': 'v-02151', 4040 - '22162': 'v-02152', 4041 - '22163': 'v-02153', 4042 - '22164': 'v-02154', 4043 - '22165': 'v-02155', 4044 - '22166': 'v-02156', 4045 - '22167': 'v-02157', 4046 - '22168': 'v-02158', 4047 - '22169': 'v-02159', 4048 - '22170': 'v-02160', 4049 - '22171': 'v-02161', 4050 - '22172': 'v-02162', 4051 - '22173': 'v-02163', 4052 - '22174': 'v-02164', 4053 - '22175': 'v-02165', 4054 - '22176': 'v-02166', 4055 - '22177': 'v-02167', 4056 - '22178': 'v-02168', 4057 - '22179': 'v-02169', 4058 - '22180': 'v-02170', 4059 - '22181': 'v-02171', 4060 - '22182': 'v-02172', 4061 - '22183': 'v-02173', 4062 - '22184': 'v-02174', 4063 - '22185': 'v-02175', 4064 - '22186': 'v-02176', 4065 - '22187': 'v-02177', 4066 - '22188': 'v-02178', 4067 - '22189': 'v-02179', 4068 - '22190': 'v-02180', 4069 - '22191': 'v-02181', 4070 - '22192': 'v-02182', 4071 - '22193': 'v-02183', 4072 - '22194': 'v-02184', 4073 - '22195': 'v-02185', 4074 - '22196': 'v-02186', 4075 - '22197': 'v-02187', 4076 - '22198': 'v-02188', 4077 - '22199': 'v-02189', 4078 - '22200': 'v-02190', 4079 - '22201': 'v-02191', 4080 - '22202': 'v-02192', 4081 - '22203': 'v-02193', 4082 - '22204': 'v-02194', 4083 - '22205': 'v-02195', 4084 - '22206': 'v-02196', 4085 - '22207': 'v-02197', 4086 - '22208': 'v-02198', 4087 - '22209': 'v-02199', 4088 - '22210': 'v-02200', 4089 - '22211': 'v-02201', 4090 - '22212': 'v-02202', 4091 - '22213': 'v-02203', 4092 - '22214': 'v-02204', 4093 - '22215': 'v-02205', 4094 - '22216': 'v-02206', 4095 - '22217': 'v-02207', 4096 - '22218': 'v-02208', 4097 - '22219': 'v-02209', 4098 - '22220': 'v-02210', 4099 - '22221': 'v-02211', 4100 - '22222': 'v-02212', 4101 - '22223': 'v-02213', 4102 - '22224': 'v-02214', 4103 - '22225': 'v-02215', 4104 - '22226': 'v-02216', 4105 - '22227': 'v-02217', 4106 - '22228': 'v-02218', 4107 - '22229': 'v-02219', 4108 - '22230': 'v-02220', 4109 - '22231': 'v-02221', 4110 - '22232': 'v-02222', 4111 - '22233': 'v-02223', 4112 - '22234': 'v-02224', 4113 - '22235': 'v-02225', 4114 - '22236': 'v-02226', 4115 - '22237': 'v-02227', 4116 - '22238': 'v-02228', 4117 - '22239': 'v-02229', 4118 - '22240': 'v-02230', 4119 - '22241': 'v-02231', 4120 - '22242': 'v-02232', 4121 - '22243': 'v-02233', 4122 - '22244': 'v-02234', 4123 - '22245': 'v-02235', 4124 - '22246': 'v-02236', 4125 - '22247': 'v-02237', 4126 - '22248': 'v-02238', 4127 - '22249': 'v-02239', 4128 - '22250': 'v-02240', 4129 - '22251': 'v-02241', 4130 - '22252': 'v-02242', 4131 - '22253': 'v-02243', 4132 - '22254': 'v-02244', 4133 - '22255': 'v-02245', 4134 - '22256': 'v-02246', 4135 - '22257': 'v-02247', 4136 - '22258': 'v-02248', 4137 - '22259': 'v-02249', 4138 - '22260': 'v-02250', 4139 - '22261': 'v-02251', 4140 - '22262': 'v-02252', 4141 - '22263': 'v-02253', 4142 - '22264': 'v-02254', 4143 - '22265': 'v-02255', 4144 - '22266': 'v-02256', 4145 - '22267': 'v-02257', 4146 - '22268': 'v-02258', 4147 - '22269': 'v-02259', 4148 - '22270': 'v-02260', 4149 - '22271': 'v-02261', 4150 - '22272': 'v-02262', 4151 - '22273': 'v-02263', 4152 - '22274': 'v-02264', 4153 - '22275': 'v-02265', 4154 - '22276': 'v-02266', 4155 - '22277': 'v-02267', 4156 - '22278': 'v-02268', 4157 - '22279': 'v-02269', 4158 - '22280': 'v-02270', 4159 - '22281': 'v-02271', 4160 - '22282': 'v-02272', 4161 - '22283': 'v-02273', 4162 - '22284': 'v-02274', 4163 - '22285': 'v-02275', 4164 - '22286': 'v-02276', 4165 - '22287': 'v-02277', 4166 - '22288': 'v-02278', 4167 - '22289': 'v-02279', 4168 - '22290': 'v-02280', 4169 - '22291': 'v-02281', 4170 - '22292': 'v-02282', 4171 - '22293': 'v-02283', 4172 - '22294': 'v-02284', 4173 - '22295': 'v-02285', 4174 - '22296': 'v-02286', 4175 - '22297': 'v-02287', 4176 - '22298': 'v-02288', 4177 - '22299': 'v-02289', 4178 - '22300': 'v-02290', 4179 - '22301': 'v-02291', 4180 - '22302': 'v-02292', 4181 - '22303': 'v-02293', 4182 - '22304': 'v-02294', 4183 - '22305': 'v-02295', 4184 - '22306': 'v-02296', 4185 - '22307': 'v-02297', 4186 - '22308': 'v-02298', 4187 - '22309': 'v-02299', 4188 - '22310': 'v-02300', 4189 - '22311': 'v-02301', 4190 - '22312': 'v-02302', 4191 - '22313': 'v-02303', 4192 - '22314': 'v-02304', 4193 - '22315': 'v-02305', 4194 - '22316': 'v-02306', 4195 - '22317': 'v-02307', 4196 - '22318': 'v-02308', 4197 - '22319': 'v-02309', 4198 - '22320': 'v-02310', 4199 - '22321': 'v-02311', 4200 - '22322': 'v-02312', 4201 - '22323': 'v-02313', 4202 - '22324': 'v-02314', 4203 - '22325': 'v-02315', 4204 - '22326': 'v-02316', 4205 - '22327': 'v-02317', 4206 - '22328': 'v-02318', 4207 - '22329': 'v-02319', 4208 - '22330': 'v-02320', 4209 - '22331': 'v-02321', 4210 - '22332': 'v-02322', 4211 - '22333': 'v-02323', 4212 - '22334': 'v-02324', 4213 - '22335': 'v-02325', 4214 - '22336': 'v-02326', 4215 - '22337': 'v-02327', 4216 - '22338': 'v-02328', 4217 - '22339': 'v-02329', 4218 - '22340': 'v-02330', 4219 - '22341': 'v-02331', 4220 - '22342': 'v-02332', 4221 - '22343': 'v-02333', 4222 - '22344': 'v-02334', 4223 - '22345': 'v-02335', 4224 - '22346': 'v-02336', 4225 - '22347': 'v-02337', 4226 - '22348': 'v-02338', 4227 - '22349': 'v-02339', 4228 - '22350': 'v-02340', 4229 - '22351': 'v-02341', 4230 - '22352': 'v-02342', 4231 - '22353': 'v-02343', 4232 - '22354': 'v-02344', 4233 - '22355': 'v-02345', 4234 - '22356': 'v-02346', 4235 - '22357': 'v-02347', 4236 - '22358': 'v-02348', 4237 - '22359': 'v-02349', 4238 - '22360': 'v-02350', 4239 - '22361': 'v-02351', 4240 - '22362': 'v-02352', 4241 - '22363': 'v-02353', 4242 - '22364': 'v-02354', 4243 - '22365': 'v-02355', 4244 - '22366': 'v-02356', 4245 - '22367': 'v-02357', 4246 - '22368': 'v-02358', 4247 - '22369': 'v-02359', 4248 - '22370': 'v-02360', 4249 - '22371': 'v-02361', 4250 - '22372': 'v-02362', 4251 - '22373': 'v-02363', 4252 - '22374': 'v-02364', 4253 - '22375': 'v-02365', 4254 - '22376': 'v-02366', 4255 - '22377': 'v-02367', 4256 - '22378': 'v-02368', 4257 - '22379': 'v-02369', 4258 - '22380': 'v-02370', 4259 - '22381': 'v-02371', 4260 - '22382': 'v-02372', 4261 - '22383': 'v-02373', 4262 - '22384': 'v-02374', 4263 - '22385': 'v-02375', 4264 - '22386': 'v-02376', 4265 - '22387': 'v-02377', 4266 - '22388': 'v-02378', 4267 - '22389': 'v-02379', 4268 - '22390': 'v-02380', 4269 - '22391': 'v-02381', 4270 - '22392': 'v-02382', 4271 - '22393': 'v-02383', 4272 - '22394': 'v-02384', 4273 - '22395': 'v-02385', 4274 - '22396': 'v-02386', 4275 - '22397': 'v-02387', 4276 - '22398': 'v-02388', 4277 - '22399': 'v-02389', 4278 - '22400': 'v-02390', 4279 - '22401': 'v-02391', 4280 - '22402': 'v-02392', 4281 - '22403': 'v-02393', 4282 - '22404': 'v-02394', 4283 - '22405': 'v-02395', 4284 - '22406': 'v-02396', 4285 - '22407': 'v-02397', 4286 - '22408': 'v-02398', 4287 - '22409': 'v-02399', 4288 - '22410': 'v-02400', 4289 - '22411': 'v-02401', 4290 - '22412': 'v-02402', 4291 - '22413': 'v-02403', 4292 - '22414': 'v-02404', 4293 - '22415': 'v-02405', 4294 - '22416': 'v-02406', 4295 - '22417': 'v-02407', 4296 - '22418': 'v-02408', 4297 - '22419': 'v-02409', 4298 - '22420': 'v-02410', 4299 - '22421': 'v-02411', 4300 - '22422': 'v-02412', 4301 - '22423': 'v-02413', 4302 - '22424': 'v-02414', 4303 - '22425': 'v-02415', 4304 - '22426': 'v-02416', 4305 - '22427': 'v-02417', 4306 - '22428': 'v-02418', 4307 - '22429': 'v-02419', 4308 - '22430': 'v-02420', 4309 - '22431': 'v-02421', 4310 - '22432': 'v-02422', 4311 - '22433': 'v-02423', 4312 - '22434': 'v-02424', 4313 - '22435': 'v-02425', 4314 - '22436': 'v-02426', 4315 - '22437': 'v-02427', 4316 - '22438': 'v-02428', 4317 - '22439': 'v-02429', 4318 - '22440': 'v-02430', 4319 - '22441': 'v-02431', 4320 - '22442': 'v-02432', 4321 - '22443': 'v-02433', 4322 - '22444': 'v-02434', 4323 - '22445': 'v-02435', 4324 - '22446': 'v-02436', 4325 - '22447': 'v-02437', 4326 - '22448': 'v-02438', 4327 - '22449': 'v-02439', 4328 - '22450': 'v-02440', 4329 - '22451': 'v-02441', 4330 - '22452': 'v-02442', 4331 - '22453': 'v-02443', 4332 - '22454': 'v-02444', 4333 - '22455': 'v-02445', 4334 - '22456': 'v-02446', 4335 - '22457': 'v-02447', 4336 - '22458': 'v-02448', 4337 - '22459': 'v-02449', 4338 - '22460': 'v-02450', 4339 - '22461': 'v-02451', 4340 - '22462': 'v-02452', 4341 - '22463': 'v-02453', 4342 - '22464': 'v-02454', 4343 - '22465': 'v-02455', 4344 - '22466': 'v-02456', 4345 - '22467': 'v-02457', 4346 - '22468': 'v-02458', 4347 - '22469': 'v-02459', 4348 - '22470': 'v-02460', 4349 - '22471': 'v-02461', 4350 - '22472': 'v-02462', 4351 - '22473': 'v-02463', 4352 - '22474': 'v-02464', 4353 - '22475': 'v-02465', 4354 - '22476': 'v-02466', 4355 - '22477': 'v-02467', 4356 - '22478': 'v-02468', 4357 - '22479': 'v-02469', 4358 - '22480': 'v-02470', 4359 - '22481': 'v-02471', 4360 - '22482': 'v-02472', 4361 - '22483': 'v-02473', 4362 - '22484': 'v-02474', 4363 - '22485': 'v-02475', 4364 - '22486': 'v-02476', 4365 - '22487': 'v-02477', 4366 - '22488': 'v-02478', 4367 - '22489': 'v-02479', 4368 - '22490': 'v-02480', 4369 - '22491': 'v-02481', 4370 - '22492': 'v-02482', 4371 - '22493': 'v-02483', 4372 - '22494': 'v-02484', 4373 - '22495': 'v-02485', 4374 - '22496': 'v-02486', 4375 - '22497': 'v-02487', 4376 - '22498': 'v-02488', 4377 - '22499': 'v-02489', 4378 - '22500': 'v-02490', 4379 - '22501': 'v-02491', 4380 - '22502': 'v-02492', 4381 - '22503': 'v-02493', 4382 - '22504': 'v-02494', 4383 - '22505': 'v-02495', 4384 - '22506': 'v-02496', 4385 - '22507': 'v-02497', 4386 - '22508': 'v-02498', 4387 - '22509': 'v-02499', 4388 - '22510': 'v-02500', 4389 - '22511': 'v-02501', 4390 - '22512': 'v-02502', 4391 - '22513': 'v-02503', 4392 - '22514': 'v-02504', 4393 - '22515': 'v-02505', 4394 - '22516': 'v-02506', 4395 - '22517': 'v-02507', 4396 - '22518': 'v-02508', 4397 - '22519': 'v-02509', 4398 - '22520': 'v-02510', 4399 - '22521': 'v-02511', 4400 - '22522': 'v-02512', 4401 - '22523': 'v-02513', 4402 - '22524': 'v-02514', 4403 - '22525': 'v-02515', 4404 - '22526': 'v-02516', 4405 - '22527': 'v-02517', 4406 - '22528': 'v-02518', 4407 - '22529': 'v-02519', 4408 - '22530': 'v-02520', 4409 - '22531': 'v-02521', 4410 - '22532': 'v-02522', 4411 - '22533': 'v-02523', 4412 - '22534': 'v-02524', 4413 - '22535': 'v-02525', 4414 - '22536': 'v-02526', 4415 - '22537': 'v-02527', 4416 - '22538': 'v-02528', 4417 - '22539': 'v-02529', 4418 - '22540': 'v-02530', 4419 - '22541': 'v-02531', 4420 - '22542': 'v-02532', 4421 - '22543': 'v-02533', 4422 - '22544': 'v-02534', 4423 - '22545': 'v-02535', 4424 - '22546': 'v-02536', 4425 - '22547': 'v-02537', 4426 - '22548': 'v-02538', 4427 - '22549': 'v-02539', 4428 - '22550': 'v-02540', 4429 - '22551': 'v-02541', 4430 - '22552': 'v-02542', 4431 - '22553': 'v-02543', 4432 - '22554': 'v-02544', 4433 - '22555': 'v-02545', 4434 - '22556': 'v-02546', 4435 - '22557': 'v-02547', 4436 - '22558': 'v-02548', 4437 - '22559': 'v-02549', 4438 - '22560': 'v-02550', 4439 - '22561': 'v-02551', 4440 - '22562': 'v-02552', 4441 - '22563': 'v-02553', 4442 - '22564': 'v-02554', 4443 - '22565': 'v-02555', 4444 - '22566': 'v-02556', 4445 - '22567': 'v-02557', 4446 - '22568': 'v-02558', 4447 - '22569': 'v-02559', 4448 - '22570': 'v-02560', 4449 - '22571': 'v-02561', 4450 - '22572': 'v-02562', 4451 - '22573': 'v-02563', 4452 - '22574': 'v-02564', 4453 - '22575': 'v-02565', 4454 - '22576': 'v-02566', 4455 - '22577': 'v-02567', 4456 - '22578': 'v-02568', 4457 - '22579': 'v-02569', 4458 - '22580': 'v-02570', 4459 - '22581': 'v-02571', 4460 - '22582': 'v-02572', 4461 - '22583': 'v-02573', 4462 - '22584': 'v-02574', 4463 - '22585': 'v-02575', 4464 - '22586': 'v-02576', 4465 - '22587': 'v-02577', 4466 - '22588': 'v-02578', 4467 - '22589': 'v-02579', 4468 - '22590': 'v-02580', 4469 - '22591': 'v-02581', 4470 - '22592': 'v-02582', 4471 - '22593': 'v-02583', 4472 - '22594': 'v-02584', 4473 - '22595': 'v-02585', 4474 - '22596': 'v-02586', 4475 - '22597': 'v-02587', 4476 - '22598': 'v-02588', 4477 - '22599': 'v-02589', 4478 - '22600': 'v-02590', 4479 - '22601': 'v-02591', 4480 - '22602': 'v-02592', 4481 - '22603': 'v-02593', 4482 - '22604': 'v-02594', 4483 - '22605': 'v-02595', 4484 - '22606': 'v-02596', 4485 - '22607': 'v-02597', 4486 - '22608': 'v-02598', 4487 - '22609': 'v-02599', 4488 - '22610': 'v-02600', 4489 - '22611': 'v-02601', 4490 - '22612': 'v-02602', 4491 - '22613': 'v-02603', 4492 - '22614': 'v-02604', 4493 - '22615': 'v-02605', 4494 - '22616': 'v-02606', 4495 - '22617': 'v-02607', 4496 - '22618': 'v-02608', 4497 - '22619': 'v-02609', 4498 - '22620': 'v-02610', 4499 - '22621': 'v-02611', 4500 - '22622': 'v-02612', 4501 - '22623': 'v-02613', 4502 - '22624': 'v-02614', 4503 - '22625': 'v-02615', 4504 - '22626': 'v-02616', 4505 - '22627': 'v-02617', 4506 - '22628': 'v-02618', 4507 - '22629': 'v-02619', 4508 - '22630': 'v-02620', 4509 - '22631': 'v-02621', 4510 - '22632': 'v-02622', 4511 - '22633': 'v-02623', 4512 - '22634': 'v-02624', 4513 - '22635': 'v-02625', 4514 - '22636': 'v-02626', 4515 - '22637': 'v-02627', 4516 - '22638': 'v-02628', 4517 - '22639': 'v-02629', 4518 - '22640': 'v-02630', 4519 - '22641': 'v-02631', 4520 - '22642': 'v-02632', 4521 - '22643': 'v-02633', 4522 - '22644': 'v-02634', 4523 - '22645': 'v-02635', 4524 - '22646': 'v-02636', 4525 - '22647': 'v-02637', 4526 - '22648': 'v-02638', 4527 - '22649': 'v-02639', 4528 - '22650': 'v-02640', 4529 - '22651': 'v-02641', 4530 - '22652': 'v-02642', 4531 - '22653': 'v-02643', 4532 - '22654': 'v-02644', 4533 - '22655': 'v-02645', 4534 - '22656': 'v-02646', 4535 - '22657': 'v-02647', 4536 - '22658': 'v-02648', 4537 - '22659': 'v-02649', 4538 - '22660': 'v-02650', 4539 - '22661': 'v-02651', 4540 - '22662': 'v-02652', 4541 - '22663': 'v-02653', 4542 - '22664': 'v-02654', 4543 - '22665': 'v-02655', 4544 - '22666': 'v-02656', 4545 - '22667': 'v-02657', 4546 - '22668': 'v-02658', 4547 - '22669': 'v-02659', 4548 - '22670': 'v-02660', 4549 - '22671': 'v-02661', 4550 - '22672': 'v-02662', 4551 - '22673': 'v-02663', 4552 - '22674': 'v-02664', 4553 - '22675': 'v-02665', 4554 - '22676': 'v-02666', 4555 - '22677': 'v-02667', 4556 - '22678': 'v-02668', 4557 - '22679': 'v-02669', 4558 - '22680': 'v-02670', 4559 - '22681': 'v-02671', 4560 - '22682': 'v-02672', 4561 - '22683': 'v-02673', 4562 - '22684': 'v-02674', 4563 - '22685': 'v-02675', 4564 - '22686': 'v-02676', 4565 - '22687': 'v-02677', 4566 - '22688': 'v-02678', 4567 - '22689': 'v-02679', 4568 - '22690': 'v-02680', 4569 - '22691': 'v-02681', 4570 - '22692': 'v-02682', 4571 - '22693': 'v-02683', 4572 - '22694': 'v-02684', 4573 - '22695': 'v-02685', 4574 - '22696': 'v-02686', 4575 - '22697': 'v-02687', 4576 - '22698': 'v-02688', 4577 - '22699': 'v-02689', 4578 - '22700': 'v-02690', 4579 - '22701': 'v-02691', 4580 - '22702': 'v-02692', 4581 - '22703': 'v-02693', 4582 - '22704': 'v-02694', 4583 - '22705': 'v-02695', 4584 - '22706': 'v-02696', 4585 - '22707': 'v-02697', 4586 - '22708': 'v-02698', 4587 - '22709': 'v-02699', 4588 - '22710': 'v-02700', 4589 - '22711': 'v-02701', 4590 - '22712': 'v-02702', 4591 - '22713': 'v-02703', 4592 - '22714': 'v-02704', 4593 - '22715': 'v-02705', 4594 - '22716': 'v-02706', 4595 - '22717': 'v-02707', 4596 - '22718': 'v-02708', 4597 - '22719': 'v-02709', 4598 - '22720': 'v-02710', 4599 - '22721': 'v-02711', 4600 - '22722': 'v-02712', 4601 - '22723': 'v-02713', 4602 - '22724': 'v-02714', 4603 - '22725': 'v-02715', 4604 - '22726': 'v-02716', 4605 - '22727': 'v-02717', 4606 - '22728': 'v-02718', 4607 - '22729': 'v-02719', 4608 - '22730': 'v-02720', 4609 - '22731': 'v-02721', 4610 - '22732': 'v-02722', 4611 - '22733': 'v-02723', 4612 - '22734': 'v-02724', 4613 - '22735': 'v-02725', 4614 - '22736': 'v-02726', 4615 - '22737': 'v-02727', 4616 - '22738': 'v-02728', 4617 - '22739': 'v-02729', 4618 - '22740': 'v-02730', 4619 - '22741': 'v-02731', 4620 - '22742': 'v-02732', 4621 - '22743': 'v-02733', 4622 - '22744': 'v-02734', 4623 - '22745': 'v-02735', 4624 - '22746': 'v-02736', 4625 - '22747': 'v-02737', 4626 - '22748': 'v-02738', 4627 - '22749': 'v-02739', 4628 - '22750': 'v-02740', 4629 - '22751': 'v-02741', 4630 - '22752': 'v-02742', 4631 - '22753': 'v-02743', 4632 - '22754': 'v-02744', 4633 - '22755': 'v-02745', 4634 - '22756': 'v-02746', 4635 - '22757': 'v-02747', 4636 - '22758': 'v-02748', 4637 - '22759': 'v-02749', 4638 - '22760': 'v-02750', 4639 - '22761': 'v-02751', 4640 - '22762': 'v-02752', 4641 - '22763': 'v-02753', 4642 - '22764': 'v-02754', 4643 - '22765': 'v-02755', 4644 - '22766': 'v-02756', 4645 - '22767': 'v-02757', 4646 - '22768': 'v-02758', 4647 - '22769': 'v-02759', 4648 - '22770': 'v-02760', 4649 - '22771': 'v-02761', 4650 - '22772': 'v-02762', 4651 - '22773': 'v-02763', 4652 - '22774': 'v-02764', 4653 - '22775': 'v-02765', 4654 - '22776': 'v-02766', 4655 - '22777': 'v-02767', 4656 - '22778': 'v-02768', 4657 - '22779': 'v-02769', 4658 - '22780': 'v-02770', 4659 - '22781': 'v-02771', 4660 - '22782': 'v-02772', 4661 - '22783': 'v-02773', 4662 - '22784': 'v-02774', 4663 - '22785': 'v-02775', 4664 - '22786': 'v-02776', 4665 - '22787': 'v-02777', 4666 - '22788': 'v-02778', 4667 - '22789': 'v-02779', 4668 - '22790': 'v-02780', 4669 - '22791': 'v-02781', 4670 - '22792': 'v-02782', 4671 - '22793': 'v-02783', 4672 - '22794': 'v-02784', 4673 - '22795': 'v-02785', 4674 - '22796': 'v-02786', 4675 - '22797': 'v-02787', 4676 - '22798': 'v-02788', 4677 - '22799': 'v-02789', 4678 - '22800': 'v-02790', 4679 - '22801': 'v-02791', 4680 - '22802': 'v-02792', 4681 - '22803': 'v-02793', 4682 - '22804': 'v-02794', 4683 - '22805': 'v-02795', 4684 - '22806': 'v-02796', 4685 - '22807': 'v-02797', 4686 - '22808': 'v-02798', 4687 - '22809': 'v-02799', 4688 - '22810': 'v-02800', 4689 - '22811': 'v-02801', 4690 - '22812': 'v-02802', 4691 - '22813': 'v-02803', 4692 - '22814': 'v-02804', 4693 - '22815': 'v-02805', 4694 - '22816': 'v-02806', 4695 - '22817': 'v-02807', 4696 - '22818': 'v-02808', 4697 - '22819': 'v-02809', 4698 - '22820': 'v-02810', 4699 - '22821': 'v-02811', 4700 - '22822': 'v-02812', 4701 - '22823': 'v-02813', 4702 - '22824': 'v-02814', 4703 - '22825': 'v-02815', 4704 - '22826': 'v-02816', 4705 - '22827': 'v-02817', 4706 - '22828': 'v-02818', 4707 - '22829': 'v-02819', 4708 - '22830': 'v-02820', 4709 - '22831': 'v-02821', 4710 - '22832': 'v-02822', 4711 - '22833': 'v-02823', 4712 - '22834': 'v-02824', 4713 - '22835': 'v-02825', 4714 - '22836': 'v-02826', 4715 - '22837': 'v-02827', 4716 - '22838': 'v-02828', 4717 - '22839': 'v-02829', 4718 - '22840': 'v-02830', 4719 - '22841': 'v-02831', 4720 - '22842': 'v-02832', 4721 - '22843': 'v-02833', 4722 - '22844': 'v-02834', 4723 - '22845': 'v-02835', 4724 - '22846': 'v-02836', 4725 - '22847': 'v-02837', 4726 - '22848': 'v-02838', 4727 - '22849': 'v-02839', 4728 - '22850': 'v-02840', 4729 - '22851': 'v-02841', 4730 - '22852': 'v-02842', 4731 - '22853': 'v-02843', 4732 - '22854': 'v-02844', 4733 - '22855': 'v-02845', 4734 - '22856': 'v-02846', 4735 - '22857': 'v-02847', 4736 - '22858': 'v-02848', 4737 - '22859': 'v-02849', 4738 - '22860': 'v-02850', 4739 - '22861': 'v-02851', 4740 - '22862': 'v-02852', 4741 - '22863': 'v-02853', 4742 - '22864': 'v-02854', 4743 - '22865': 'v-02855', 4744 - '22866': 'v-02856', 4745 - '22867': 'v-02857', 4746 - '22868': 'v-02858', 4747 - '22869': 'v-02859', 4748 - '22870': 'v-02860', 4749 - '22871': 'v-02861', 4750 - '22872': 'v-02862', 4751 - '22873': 'v-02863', 4752 - '22874': 'v-02864', 4753 - '22875': 'v-02865', 4754 - '22876': 'v-02866', 4755 - '22877': 'v-02867', 4756 - '22878': 'v-02868', 4757 - '22879': 'v-02869', 4758 - '22880': 'v-02870', 4759 - '22881': 'v-02871', 4760 - '22882': 'v-02872', 4761 - '22883': 'v-02873', 4762 - '22884': 'v-02874', 4763 - '22885': 'v-02875', 4764 - '22886': 'v-02876', 4765 - '22887': 'v-02877', 4766 - '22888': 'v-02878', 4767 - '22889': 'v-02879', 4768 - '22890': 'v-02880', 4769 - '22891': 'v-02881', 4770 - '22892': 'v-02882', 4771 - '22893': 'v-02883', 4772 - '22894': 'v-02884', 4773 - '22895': 'v-14067', 4774 - '22896': 'v-02885', 4775 - '22897': 'v-02886', 4776 - '22898': 'v-02887', 4777 - '22899': 'v-02888', 4778 - '22900': 'v-02889', 4779 - '22901': 'v-02890', 4780 - '22902': 'v-02891', 4781 - '22903': 'v-02892', 4782 - '22904': 'v-02893', 4783 - '22905': 'v-02894', 4784 - '22906': 'v-02895', 4785 - '22907': 'v-02896', 4786 - '22908': 'v-02897', 4787 - '22909': 'v-02898', 4788 - '22910': 'v-02899', 4789 - '22911': 'v-02900', 4790 - '22912': 'v-02901', 4791 - '22913': 'v-02902', 4792 - '22914': 'v-02903', 4793 - '22915': 'v-02904', 4794 - '22916': 'v-02905', 4795 - '22917': 'v-02906', 4796 - '22918': 'v-02907', 4797 - '22919': 'v-02908', 4798 - '22920': 'v-02909', 4799 - '22921': 'v-02910', 4800 - '22922': 'v-02911', 4801 - '22923': 'v-02912', 4802 - '22924': 'v-02913', 4803 - '22925': 'v-02914', 4804 - '22926': 'v-02915', 4805 - '22927': 'v-02916', 4806 - '22928': 'v-02917', 4807 - '22929': 'v-02918', 4808 - '22930': 'v-02919', 4809 - '22931': 'v-02920', 4810 - '22932': 'v-02921', 4811 - '22933': 'v-02922', 4812 - '22934': 'v-02923', 4813 - '22935': 'v-02924', 4814 - '22936': 'v-02925', 4815 - '22937': 'v-02926', 4816 - '22938': 'v-02927', 4817 - '22939': 'v-02928', 4818 - '22940': 'v-02929', 4819 - '22941': 'v-02930', 4820 - '22942': 'v-02931', 4821 - '22943': 'v-02932', 4822 - '22944': 'v-02933', 4823 - '22945': 'v-02934', 4824 - '22946': 'v-02935', 4825 - '22947': 'v-02936', 4826 - '22948': 'v-02937', 4827 - '22949': 'v-02938', 4828 - '22950': 'v-02939', 4829 - '22951': 'v-02940', 4830 - '22952': 'v-02941', 4831 - '22953': 'v-02942', 4832 - '22954': 'v-02943', 4833 - '22955': 'v-02944', 4834 - '22956': 'v-02945', 4835 - '22957': 'v-02946', 4836 - '22958': 'v-02947', 4837 - '22959': 'v-02948', 4838 - '22960': 'v-02949', 4839 - '22961': 'v-02950', 4840 - '22962': 'v-02951', 4841 - '22963': 'v-02952', 4842 - '22964': 'v-02953', 4843 - '22965': 'v-02954', 4844 - '22966': 'v-02955', 4845 - '22967': 'v-02956', 4846 - '22968': 'v-02957', 4847 - '22969': 'v-02958', 4848 - '22970': 'v-02959', 4849 - '22971': 'v-02960', 4850 - '22972': 'v-02961', 4851 - '22973': 'v-02962', 4852 - '22974': 'v-02963', 4853 - '22975': 'v-02964', 4854 - '22976': 'v-02965', 4855 - '22977': 'v-02966', 4856 - '22978': 'v-02967', 4857 - '22979': 'v-14068', 4858 - '22980': 'v-02968', 4859 - '22981': 'v-02969', 4860 - '22982': 'v-02970', 4861 - '22983': 'v-02971', 4862 - '22984': 'v-02972', 4863 - '22985': 'v-02973', 4864 - '22986': 'v-02974', 4865 - '22987': 'v-02975', 4866 - '22988': 'v-02976', 4867 - '22989': 'v-02977', 4868 - '22990': 'v-02978', 4869 - '22991': 'v-02979', 4870 - '22992': 'v-02980', 4871 - '22993': 'v-02981', 4872 - '22994': 'v-02982', 4873 - '22995': 'v-02983', 4874 - '22996': 'v-02984', 4875 - '22997': 'v-02985', 4876 - '22998': 'v-02986', 4877 - '22999': 'v-02987', 4878 - '23000': 'v-02988', 4879 - '23001': 'v-02989', 4880 - '23002': 'v-02990', 4881 - '23003': 'v-02991', 4882 - '23004': 'v-02992', 4883 - '23005': 'v-02993', 4884 - '23006': 'v-02994', 4885 - '23007': 'v-02995', 4886 - '23008': 'v-02996', 4887 - '23009': 'v-02997', 4888 - '23010': 'v-02998', 4889 - '23011': 'v-02999', 4890 - '23012': 'v-03000', 4891 - '23013': 'v-03001', 4892 - '23014': 'v-03002', 4893 - '23015': 'v-03003', 4894 - '23016': 'v-03004', 4895 - '23017': 'v-03005', 4896 - '23018': 'v-03006', 4897 - '23019': 'v-03007', 4898 - '23020': 'v-03008', 4899 - '23021': 'v-03009', 4900 - '23022': 'v-03010', 4901 - '23023': 'v-03011', 4902 - '23024': 'v-03012', 4903 - '23025': 'v-03013', 4904 - '23026': 'v-03014', 4905 - '23027': 'v-03015', 4906 - '23028': 'v-03016', 4907 - '23029': 'v-03017', 4908 - '23030': 'v-03018', 4909 - '23031': 'v-03019', 4910 - '23032': 'v-03020', 4911 - '23033': 'v-03021', 4912 - '23034': 'v-03022', 4913 - '23035': 'v-03023', 4914 - '23036': 'v-03024', 4915 - '23037': 'v-03025', 4916 - '23038': 'v-03026', 4917 - '23039': 'v-03027', 4918 - '23040': 'v-03028', 4919 - '23041': 'v-03029', 4920 - '23042': 'v-03030', 4921 - '23043': 'v-03031', 4922 - '23044': 'v-03032', 4923 - '23045': 'v-03033', 4924 - '23046': 'v-03034', 4925 - '23047': 'v-03035', 4926 - '23048': 'v-03036', 4927 - '23049': 'v-03037', 4928 - '23050': 'v-03038', 4929 - '23051': 'v-03039', 4930 - '23052': 'v-03040', 4931 - '23053': 'v-03041', 4932 - '23054': 'v-03042', 4933 - '23055': 'v-03043', 4934 - '23056': 'v-03044', 4935 - '23057': 'v-03045', 4936 - '23058': 'v-03046', 4937 - '23059': 'v-03047', 4938 - '23060': 'v-03048', 4939 - '23061': 'v-03049', 4940 - '23062': 'v-03050', 4941 - '23063': 'v-03051', 4942 - '23064': 'v-03052', 4943 - '23065': 'v-03053', 4944 - '23066': 'v-03054', 4945 - '23067': 'v-03055', 4946 - '23068': 'v-03056', 4947 - '23069': 'v-03057', 4948 - '23070': 'v-03058', 4949 - '23071': 'v-03059', 4950 - '23072': 'v-03060', 4951 - '23073': 'v-03061', 4952 - '23074': 'v-03062', 4953 - '23075': 'v-03063', 4954 - '23076': 'v-03064', 4955 - '23077': 'v-03065', 4956 - '23078': 'v-03066', 4957 - '23079': 'v-03067', 4958 - '23080': 'v-03068', 4959 - '23081': 'v-03069', 4960 - '23082': 'v-03070', 4961 - '23083': 'v-03071', 4962 - '23084': 'v-03072', 4963 - '23085': 'v-03073', 4964 - '23086': 'v-03074', 4965 - '23087': 'v-03075', 4966 - '23088': 'v-03076', 4967 - '23089': 'v-03077', 4968 - '23090': 'v-03078', 4969 - '23091': 'v-03079', 4970 - '23092': 'v-03080', 4971 - '23093': 'v-03081', 4972 - '23094': 'v-03082', 4973 - '23095': 'v-03083', 4974 - '23096': 'v-03084', 4975 - '23097': 'v-03085', 4976 - '23098': 'v-03086', 4977 - '23099': 'v-03087', 4978 - '23100': 'v-03088', 4979 - '23101': 'v-03089', 4980 - '23102': 'v-03090', 4981 - '23103': 'v-03091', 4982 - '23104': 'v-03092', 4983 - '23105': 'v-03093', 4984 - '23106': 'v-03094', 4985 - '23107': 'v-03095', 4986 - '23108': 'v-03096', 4987 - '23109': 'v-03097', 4988 - '23110': 'v-03098', 4989 - '23111': 'v-03099', 4990 - '23112': 'v-03100', 4991 - '23113': 'v-03101', 4992 - '23114': 'v-03102', 4993 - '23115': 'v-03103', 4994 - '23116': 'v-03104', 4995 - '23117': 'v-03105', 4996 - '23118': 'v-03106', 4997 - '23119': 'v-03107', 4998 - '23120': 'v-03108', 4999 - '23121': 'v-03109', 5000 - '23122': 'v-03110', 5001 - '23123': 'v-03111', 5002 - '23124': 'v-03112', 5003 - '23125': 'v-03113', 5004 - '23126': 'v-03114', 5005 - '23127': 'v-03115', 5006 - '23128': 'v-03116', 5007 - '23129': 'v-03117', 5008 - '23130': 'v-03118', 5009 - '23131': 'v-03119', 5010 - '23132': 'v-03120', 5011 - '23133': 'v-14069', 5012 - '23134': 'v-03121', 5013 - '23135': 'v-03122', 5014 - '23136': 'v-03123', 5015 - '23137': 'v-03124', 5016 - '23138': 'v-03125', 5017 - '23139': 'v-03126', 5018 - '23140': 'v-03127', 5019 - '23141': 'v-03128', 5020 - '23142': 'v-03129', 5021 - '23143': 'v-03130', 5022 - '23144': 'v-03131', 5023 - '23145': 'v-03132', 5024 - '23146': 'v-03133', 5025 - '23147': 'v-03134', 5026 - '23148': 'v-03135', 5027 - '23149': 'v-03136', 5028 - '23150': 'v-03137', 5029 - '23151': 'v-03138', 5030 - '23152': 'v-03139', 5031 - '23153': 'v-03140', 5032 - '23154': 'v-03141', 5033 - '23155': 'v-03142', 5034 - '23156': 'v-03143', 5035 - '23157': 'v-03144', 5036 - '23158': 'v-03145', 5037 - '23159': 'v-03146', 5038 - '23160': 'v-03147', 5039 - '23161': 'v-03148', 5040 - '23162': 'v-03149', 5041 - '23163': 'v-03150', 5042 - '23164': 'v-03151', 5043 - '23165': 'v-03152', 5044 - '23166': 'v-03153', 5045 - '23167': 'v-03154', 5046 - '23168': 'v-03155', 5047 - '23169': 'v-03156', 5048 - '23170': 'v-03157', 5049 - '23171': 'v-03158', 5050 - '23172': 'v-03159', 5051 - '23173': 'v-03160', 5052 - '23174': 'v-03161', 5053 - '23175': 'v-03162', 5054 - '23176': 'v-03163', 5055 - '23177': 'v-03164', 5056 - '23178': 'v-03165', 5057 - '23179': 'v-03166', 5058 - '23180': 'v-03167', 5059 - '23181': 'v-03168', 5060 - '23182': 'v-03169', 5061 - '23183': 'v-03170', 5062 - '23184': 'v-03171', 5063 - '23185': 'v-03172', 5064 - '23186': 'v-03173', 5065 - '23187': 'v-03174', 5066 - '23188': 'v-03175', 5067 - '23189': 'v-03176', 5068 - '23190': 'v-03177', 5069 - '23191': 'v-03178', 5070 - '23192': 'v-03179', 5071 - '23193': 'v-03180', 5072 - '23194': 'v-03181', 5073 - '23195': 'v-03182', 5074 - '23196': 'v-03183', 5075 - '23197': 'v-03184', 5076 - '23198': 'v-03185', 5077 - '23199': 'v-03186', 5078 - '23200': 'v-03187', 5079 - '23201': 'v-03188', 5080 - '23202': 'v-03189', 5081 - '23203': 'v-03190', 5082 - '23204': 'v-03191', 5083 - '23205': 'v-03192', 5084 - '23206': 'v-03193', 5085 - '23207': 'v-03194', 5086 - '23208': 'v-03195', 5087 - '23209': 'v-03196', 5088 - '23210': 'v-03197', 5089 - '23211': 'v-03198', 5090 - '23212': 'v-03199', 5091 - '23213': 'v-03200', 5092 - '23214': 'v-03201', 5093 - '23215': 'v-03202', 5094 - '23216': 'v-03203', 5095 - '23217': 'v-03204', 5096 - '23218': 'v-03205', 5097 - '23219': 'v-03206', 5098 - '23220': 'v-03207', 5099 - '23221': 'v-03208', 5100 - '23222': 'v-03209', 5101 - '23223': 'v-03210', 5102 - '23224': 'v-03211', 5103 - '23225': 'v-03212', 5104 - '23226': 'v-03213', 5105 - '23227': 'v-03214', 5106 - '23228': 'v-03215', 5107 - '23229': 'v-03216', 5108 - '23230': 'v-03217', 5109 - '23231': 'v-03218', 5110 - '23232': 'v-03219', 5111 - '23233': 'v-03220', 5112 - '23234': 'v-03221', 5113 - '23235': 'v-03222', 5114 - '23236': 'v-03223', 5115 - '23237': 'v-03224', 5116 - '23238': 'v-03225', 5117 - '23239': 'v-03226', 5118 - '23240': 'v-03227', 5119 - '23241': 'v-03228', 5120 - '23242': 'v-03229', 5121 - '23243': 'v-03230', 5122 - '23244': 'v-03231', 5123 - '23245': 'v-03232', 5124 - '23246': 'v-03233', 5125 - '23247': 'v-03234', 5126 - '23248': 'v-03235', 5127 - '23249': 'v-03236', 5128 - '23250': 'v-03237', 5129 - '23251': 'v-03238', 5130 - '23252': 'v-03239', 5131 - '23253': 'v-03240', 5132 - '23254': 'v-03241', 5133 - '23255': 'v-03242', 5134 - '23256': 'v-03243', 5135 - '23257': 'v-03244', 5136 - '23258': 'v-03245', 5137 - '23259': 'v-03246', 5138 - '23260': 'v-03247', 5139 - '23261': 'v-03248', 5140 - '23262': 'v-03249', 5141 - '23263': 'v-03250', 5142 - '23264': 'v-03251', 5143 - '23265': 'v-03252', 5144 - '23266': 'v-03253', 5145 - '23267': 'v-03254', 5146 - '23268': 'v-03255', 5147 - '23269': 'v-03256', 5148 - '23270': 'v-03257', 5149 - '23271': 'v-03258', 5150 - '23272': 'v-03259', 5151 - '23273': 'v-03260', 5152 - '23274': 'v-03261', 5153 - '23275': 'v-03262', 5154 - '23276': 'v-03263', 5155 - '23277': 'v-03264', 5156 - '23278': 'v-03265', 5157 - '23279': 'v-03266', 5158 - '23280': 'v-03267', 5159 - '23281': 'v-03268', 5160 - '23282': 'v-03269', 5161 - '23283': 'v-03270', 5162 - '23284': 'v-03271', 5163 - '23285': 'v-03272', 5164 - '23286': 'v-03273', 5165 - '23287': 'v-03274', 5166 - '23288': 'v-03275', 5167 - '23289': 'v-03276', 5168 - '23290': 'v-03277', 5169 - '23291': 'v-03278', 5170 - '23292': 'v-03279', 5171 - '23293': 'v-03280', 5172 - '23294': 'v-03281', 5173 - '23295': 'v-03282', 5174 - '23296': 'v-03283', 5175 - '23297': 'v-03284', 5176 - '23298': 'v-03285', 5177 - '23299': 'v-03286', 5178 - '23300': 'v-03287', 5179 - '23301': 'v-03288', 5180 - '23302': 'v-03289', 5181 - '23303': 'v-03290', 5182 - '23304': 'v-03291', 5183 - '23305': 'v-03292', 5184 - '23306': 'v-03293', 5185 - '23307': 'v-03294', 5186 - '23308': 'v-03295', 5187 - '23309': 'v-03296', 5188 - '23310': 'v-03297', 5189 - '23311': 'v-03298', 5190 - '23312': 'v-03299', 5191 - '23313': 'v-03300', 5192 - '23314': 'v-03301', 5193 - '23315': 'v-03302', 5194 - '23316': 'v-03303', 5195 - '23317': 'v-03304', 5196 - '23318': 'v-03305', 5197 - '23319': 'v-03306', 5198 - '23320': 'v-03307', 5199 - '23321': 'v-03308', 5200 - '23322': 'v-03309', 5201 - '23323': 'v-03310', 5202 - '23324': 'v-03311', 5203 - '23325': 'v-03312', 5204 - '23326': 'v-03313', 5205 - '23327': 'v-03314', 5206 - '23328': 'v-03315', 5207 - '23329': 'v-03316', 5208 - '23330': 'v-03317', 5209 - '23331': 'v-03318', 5210 - '23332': 'v-03319', 5211 - '23333': 'v-03320', 5212 - '23334': 'v-03321', 5213 - '23335': 'v-03322', 5214 - '23336': 'v-03323', 5215 - '23337': 'v-03324', 5216 - '23338': 'v-03325', 5217 - '23339': 'v-03326', 5218 - '23340': 'v-03327', 5219 - '23341': 'v-03328', 5220 - '23342': 'v-03329', 5221 - '23343': 'v-03330', 5222 - '23344': 'v-03331', 5223 - '23345': 'v-03332', 5224 - '23346': 'v-03333', 5225 - '23347': 'v-03334', 5226 - '23348': 'v-03335', 5227 - '23349': 'v-03336', 5228 - '23350': 'v-03337', 5229 - '23351': 'v-03338', 5230 - '23352': 'v-03339', 5231 - '23353': 'v-03340', 5232 - '23354': 'v-03341', 5233 - '23355': 'v-03342', 5234 - '23356': 'v-03343', 5235 - '23357': 'v-03344', 5236 - '23358': 'v-03345', 5237 - '23359': 'v-03346', 5238 - '23360': 'v-03347', 5239 - '23361': 'v-03348', 5240 - '23362': 'v-03349', 5241 - '23363': 'v-03350', 5242 - '23364': 'v-03351', 5243 - '23365': 'v-03352', 5244 - '23366': 'v-03353', 5245 - '23367': 'v-03354', 5246 - '23368': 'v-03355', 5247 - '23369': 'v-03356', 5248 - '23370': 'v-03357', 5249 - '23371': 'v-03358', 5250 - '23372': 'v-03359', 5251 - '23373': 'v-03360', 5252 - '23374': 'v-03361', 5253 - '23375': 'v-03362', 5254 - '23376': 'v-03363', 5255 - '23377': 'v-03364', 5256 - '23378': 'v-03365', 5257 - '23379': 'v-03366', 5258 - '23380': 'v-03367', 5259 - '23381': 'v-03368', 5260 - '23382': 'v-03369', 5261 - '23383': 'v-03370', 5262 - '23384': 'v-03371', 5263 - '23385': 'v-03372', 5264 - '23386': 'v-03373', 5265 - '23387': 'v-03374', 5266 - '23388': 'v-03375', 5267 - '23389': 'v-03376', 5268 - '23390': 'v-03377', 5269 - '23391': 'v-03378', 5270 - '23392': 'v-03379', 5271 - '23393': 'v-03380', 5272 - '23394': 'v-03381', 5273 - '23395': 'v-03382', 5274 - '23396': 'v-03383', 5275 - '23397': 'v-03384', 5276 - '23398': 'v-03385', 5277 - '23399': 'v-03386', 5278 - '23400': 'v-03387', 5279 - '23401': 'v-03388', 5280 - '23402': 'v-03389', 5281 - '23403': 'v-03390', 5282 - '23404': 'v-03391', 5283 - '23405': 'v-03392', 5284 - '23406': 'v-03393', 5285 - '23407': 'v-03394', 5286 - '23408': 'v-03395', 5287 - '23409': 'v-03396', 5288 - '23410': 'v-03397', 5289 - '23411': 'v-03398', 5290 - '23412': 'v-03399', 5291 - '23413': 'v-03400', 5292 - '23414': 'v-03401', 5293 - '23415': 'v-03402', 5294 - '23416': 'v-03403', 5295 - '23417': 'v-03404', 5296 - '23418': 'v-03405', 5297 - '23419': 'v-03406', 5298 - '23420': 'v-03407', 5299 - '23421': 'v-03408', 5300 - '23422': 'v-03409', 5301 - '23423': 'v-03410', 5302 - '23424': 'v-03411', 5303 - '23425': 'v-03412', 5304 - '23426': 'v-03413', 5305 - '23427': 'v-03414', 5306 - '23428': 'v-03415', 5307 - '23429': 'v-03416', 5308 - '23430': 'v-03417', 5309 - '23431': 'v-03418', 5310 - '23432': 'v-03419', 5311 - '23433': 'v-03420', 5312 - '23434': 'v-03421', 5313 - '23435': 'v-03422', 5314 - '23436': 'v-03423', 5315 - '23437': 'v-03424', 5316 - '23438': 'v-03425', 5317 - '23439': 'v-03426', 5318 - '23440': 'v-03427', 5319 - '23441': 'v-03428', 5320 - '23442': 'v-03429', 5321 - '23443': 'v-03430', 5322 - '23444': 'v-03431', 5323 - '23445': 'v-03432', 5324 - '23446': 'v-03433', 5325 - '23447': 'v-03434', 5326 - '23448': 'v-03435', 5327 - '23449': 'v-03436', 5328 - '23450': 'v-03437', 5329 - '23451': 'v-03438', 5330 - '23452': 'v-03439', 5331 - '23453': 'v-03440', 5332 - '23454': 'v-03441', 5333 - '23455': 'v-03442', 5334 - '23456': 'v-03443', 5335 - '23457': 'v-03444', 5336 - '23458': 'v-03445', 5337 - '23459': 'v-03446', 5338 - '23460': 'v-03447', 5339 - '23461': 'v-03448', 5340 - '23462': 'v-03449', 5341 - '23463': 'v-03450', 5342 - '23464': 'v-03451', 5343 - '23465': 'v-03452', 5344 - '23466': 'v-03453', 5345 - '23467': 'v-03454', 5346 - '23468': 'v-03455', 5347 - '23469': 'v-03456', 5348 - '23470': 'v-03457', 5349 - '23471': 'v-03458', 5350 - '23472': 'v-03459', 5351 - '23473': 'v-03460', 5352 - '23474': 'v-03461', 5353 - '23475': 'v-03462', 5354 - '23476': 'v-03463', 5355 - '23477': 'v-03464', 5356 - '23478': 'v-03465', 5357 - '23479': 'v-03466', 5358 - '23480': 'v-03467', 5359 - '23481': 'v-03468', 5360 - '23482': 'v-03469', 5361 - '23483': 'v-03470', 5362 - '23484': 'v-03471', 5363 - '23485': 'v-03472', 5364 - '23486': 'v-03473', 5365 - '23487': 'v-03474', 5366 - '23488': 'v-03475', 5367 - '23489': 'v-03476', 5368 - '23490': 'v-03477', 5369 - '23491': 'v-03478', 5370 - '23492': 'v-03479', 5371 - '23493': 'v-03480', 5372 - '23494': 'v-03481', 5373 - '23495': 'v-03482', 5374 - '23496': 'v-03483', 5375 - '23497': 'v-03484', 5376 - '23498': 'v-03485', 5377 - '23499': 'v-03486', 5378 - '23500': 'v-03487', 5379 - '23501': 'v-03488', 5380 - '23502': 'v-03489', 5381 - '23503': 'v-03490', 5382 - '23504': 'v-03491', 5383 - '23505': 'v-03492', 5384 - '23506': 'v-03493', 5385 - '23507': 'v-03494', 5386 - '23508': 'v-03495', 5387 - '23509': 'v-03496', 5388 - '23510': 'v-03497', 5389 - '23511': 'v-03498', 5390 - '23512': 'v-03499', 5391 - '23513': 'v-03500', 5392 - '23514': 'v-03501', 5393 - '23515': 'v-03502', 5394 - '23516': 'v-03503', 5395 - '23517': 'v-03504', 5396 - '23518': 'v-03505', 5397 - '23519': 'v-03506', 5398 - '23520': 'v-03507', 5399 - '23521': 'v-03508', 5400 - '23522': 'v-03509', 5401 - '23523': 'v-03510', 5402 - '23524': 'v-03511', 5403 - '23525': 'v-03512', 5404 - '23526': 'v-03513', 5405 - '23527': 'v-03514', 5406 - '23528': 'v-03515', 5407 - '23529': 'v-03516', 5408 - '23530': 'v-03517', 5409 - '23531': 'v-03518', 5410 - '23532': 'v-03519', 5411 - '23533': 'v-03520', 5412 - '23534': 'v-03521', 5413 - '23535': 'v-03522', 5414 - '23536': 'v-03523', 5415 - '23537': 'v-03524', 5416 - '23538': 'v-03525', 5417 - '23539': 'v-03526', 5418 - '23540': 'v-03527', 5419 - '23541': 'v-03528', 5420 - '23542': 'v-03529', 5421 - '23543': 'v-03530', 5422 - '23544': 'v-03531', 5423 - '23545': 'v-03532', 5424 - '23546': 'v-03533', 5425 - '23547': 'v-03534', 5426 - '23548': 'v-03535', 5427 - '23549': 'v-03536', 5428 - '23550': 'v-03537', 5429 - '23551': 'v-03538', 5430 - '23552': 'v-03539', 5431 - '23553': 'v-03540', 5432 - '23554': 'v-03541', 5433 - '23555': 'v-03542', 5434 - '23556': 'v-03543', 5435 - '23557': 'v-03544', 5436 - '23558': 'v-03545', 5437 - '23559': 'v-03546', 5438 - '23560': 'v-03547', 5439 - '23561': 'v-03548', 5440 - '23562': 'v-03549', 5441 - '23563': 'v-03550', 5442 - '23564': 'v-03551', 5443 - '23565': 'v-03552', 5444 - '23566': 'v-03553', 5445 - '23567': 'v-03554', 5446 - '23568': 'v-03555', 5447 - '23569': 'v-03556', 5448 - '23570': 'v-03557', 5449 - '23571': 'v-03558', 5450 - '23572': 'v-03559', 5451 - '23573': 'v-03560', 5452 - '23574': 'v-03561', 5453 - '23575': 'v-03562', 5454 - '23576': 'v-03563', 5455 - '23577': 'v-03564', 5456 - '23578': 'v-03565', 5457 - '23579': 'v-03566', 5458 - '23580': 'v-03567', 5459 - '23581': 'v-03568', 5460 - '23582': 'v-03569', 5461 - '23583': 'v-03570', 5462 - '23584': 'v-03571', 5463 - '23585': 'v-03572', 5464 - '23586': 'v-03573', 5465 - '23587': 'v-03574', 5466 - '23588': 'v-03575', 5467 - '23589': 'v-03576', 5468 - '23590': 'v-03577', 5469 - '23591': 'v-03578', 5470 - '23592': 'v-03579', 5471 - '23593': 'v-03580', 5472 - '23594': 'v-03581', 5473 - '23595': 'v-03582', 5474 - '23596': 'v-03583', 5475 - '23597': 'v-03584', 5476 - '23598': 'v-03585', 5477 - '23599': 'v-03586', 5478 - '23600': 'v-03587', 5479 - '23601': 'v-03588', 5480 - '23602': 'v-03589', 5481 - '23603': 'v-03590', 5482 - '23604': 'v-03591', 5483 - '23605': 'v-03592', 5484 - '23606': 'v-03593', 5485 - '23607': 'v-03594', 5486 - '23608': 'v-03595', 5487 - '23609': 'v-03596', 5488 - '23610': 'v-03597', 5489 - '23611': 'v-03598', 5490 - '23612': 'v-03599', 5491 - '23613': 'v-03600', 5492 - '23614': 'v-03601', 5493 - '23615': 'v-03602', 5494 - '23616': 'v-03603', 5495 - '23617': 'v-03604', 5496 - '23618': 'v-03605', 5497 - '23619': 'v-03606', 5498 - '23620': 'v-03607', 5499 - '23621': 'v-03608', 5500 - '23622': 'v-03609', 5501 - '23623': 'v-03610', 5502 - '23624': 'v-03611', 5503 - '23625': 'v-03612', 5504 - '23626': 'v-03613', 5505 - '23627': 'v-03614', 5506 - '23628': 'v-03615', 5507 - '23629': 'v-03616', 5508 - '23630': 'v-03617', 5509 - '23631': 'v-03618', 5510 - '23632': 'v-03619', 5511 - '23633': 'v-03620', 5512 - '23634': 'v-03621', 5513 - '23635': 'v-03622', 5514 - '23636': 'v-03623', 5515 - '23637': 'v-03624', 5516 - '23638': 'v-03625', 5517 - '23639': 'v-03626', 5518 - '23640': 'v-03627', 5519 - '23641': 'v-03628', 5520 - '23642': 'v-03629', 5521 - '23643': 'v-03630', 5522 - '23644': 'v-03631', 5523 - '23645': 'v-03632', 5524 - '23646': 'v-03633', 5525 - '23647': 'v-03634', 5526 - '23648': 'v-03635', 5527 - '23649': 'v-03636', 5528 - '23650': 'v-03637', 5529 - '23651': 'v-03638', 5530 - '23652': 'v-03639', 5531 - '23653': 'v-03640', 5532 - '23654': 'v-03641', 5533 - '23655': 'v-03642', 5534 - '23656': 'v-03643', 5535 - '23657': 'v-03644', 5536 - '23658': 'v-03645', 5537 - '23659': 'v-03646', 5538 - '23660': 'v-03647', 5539 - '23661': 'v-03648', 5540 - '23662': 'v-03649', 5541 - '23663': 'v-03650', 5542 - '23664': 'v-03651', 5543 - '23665': 'v-03652', 5544 - '23666': 'v-03653', 5545 - '23667': 'v-03654', 5546 - '23668': 'v-03655', 5547 - '23669': 'v-03656', 5548 - '23670': 'v-03657', 5549 - '23671': 'v-03658', 5550 - '23672': 'v-03659', 5551 - '23673': 'v-03660', 5552 - '23674': 'v-03661', 5553 - '23675': 'v-03662', 5554 - '23676': 'v-03663', 5555 - '23677': 'v-03664', 5556 - '23678': 'v-03665', 5557 - '23679': 'v-03666', 5558 - '23680': 'v-03667', 5559 - '23681': 'v-03668', 5560 - '23682': 'v-03669', 5561 - '23683': 'v-03670', 5562 - '23684': 'v-03671', 5563 - '23685': 'v-03672', 5564 - '23686': 'v-03673', 5565 - '23687': 'v-03674', 5566 - '23688': 'v-03675', 5567 - '23689': 'v-03676', 5568 - '23690': 'v-03677', 5569 - '23691': 'v-03678', 5570 - '23692': 'v-03679', 5571 - '23693': 'v-03680', 5572 - '23694': 'v-03681', 5573 - '23695': 'v-03682', 5574 - '23696': 'v-03683', 5575 - '23697': 'v-03684', 5576 - '23698': 'v-03685', 5577 - '23699': 'v-03686', 5578 - '23700': 'v-03687', 5579 - '23701': 'v-03688', 5580 - '23702': 'v-03689', 5581 - '23703': 'v-03690', 5582 - '23704': 'v-03691', 5583 - '23705': 'v-03692', 5584 - '23706': 'v-03693', 5585 - '23707': 'v-03694', 5586 - '23708': 'v-03695', 5587 - '23709': 'v-03696', 5588 - '23710': 'v-03697', 5589 - '23711': 'v-03698', 5590 - '23712': 'v-03699', 5591 - '23713': 'v-03700', 5592 - '23714': 'v-03701', 5593 - '23715': 'v-03702', 5594 - '23716': 'v-03703', 5595 - '23717': 'v-03704', 5596 - '23718': 'v-03705', 5597 - '23719': 'v-03706', 5598 - '23720': 'v-03707', 5599 - '23721': 'v-03708', 5600 - '23722': 'v-03709', 5601 - '23723': 'v-03710', 5602 - '23724': 'v-03711', 5603 - '23725': 'v-03712', 5604 - '23726': 'v-03713', 5605 - '23727': 'v-03714', 5606 - '23728': 'v-03715', 5607 - '23729': 'v-03716', 5608 - '23730': 'v-03717', 5609 - '23731': 'v-03718', 5610 - '23732': 'v-03719', 5611 - '23733': 'v-03720', 5612 - '23734': 'v-03721', 5613 - '23735': 'v-03722', 5614 - '23736': 'v-03723', 5615 - '23737': 'v-03724', 5616 - '23738': 'v-03725', 5617 - '23739': 'v-14070', 5618 - '23740': 'v-03726', 5619 - '23741': 'v-03727', 5620 - '23742': 'v-03728', 5621 - '23743': 'v-03729', 5622 - '23744': 'v-03730', 5623 - '23745': 'v-03731', 5624 - '23746': 'v-03732', 5625 - '23747': 'v-03733', 5626 - '23748': 'v-03734', 5627 - '23749': 'v-03735', 5628 - '23750': 'v-03736', 5629 - '23751': 'v-03737', 5630 - '23752': 'v-03738', 5631 - '23753': 'v-03739', 5632 - '23754': 'v-03740', 5633 - '23755': 'v-03741', 5634 - '23756': 'v-03742', 5635 - '23757': 'v-03743', 5636 - '23758': 'v-03744', 5637 - '23759': 'v-03745', 5638 - '23760': 'v-03746', 5639 - '23761': 'v-03747', 5640 - '23762': 'v-03748', 5641 - '23763': 'v-03749', 5642 - '23764': 'v-03750', 5643 - '23765': 'v-03751', 5644 - '23766': 'v-03752', 5645 - '23767': 'v-03753', 5646 - '23768': 'v-03754', 5647 - '23769': 'v-03755', 5648 - '23770': 'v-03756', 5649 - '23771': 'v-03757', 5650 - '23772': 'v-03758', 5651 - '23773': 'v-03759', 5652 - '23774': 'v-03760', 5653 - '23775': 'v-03761', 5654 - '23776': 'v-03762', 5655 - '23777': 'v-03763', 5656 - '23778': 'v-03764', 5657 - '23779': 'v-03765', 5658 - '23780': 'v-03766', 5659 - '23781': 'v-03767', 5660 - '23782': 'v-03768', 5661 - '23783': 'v-03769', 5662 - '23784': 'v-03770', 5663 - '23785': 'v-03771', 5664 - '23786': 'v-03772', 5665 - '23787': 'v-03773', 5666 - '23788': 'v-03774', 5667 - '23789': 'v-03775', 5668 - '23790': 'v-03776', 5669 - '23791': 'v-03777', 5670 - '23792': 'v-03778', 5671 - '23793': 'v-03779', 5672 - '23794': 'v-03780', 5673 - '23795': 'v-03781', 5674 - '23796': 'v-03782', 5675 - '23797': 'v-03783', 5676 - '23798': 'v-03784', 5677 - '23799': 'v-03785', 5678 - '23800': 'v-03786', 5679 - '23801': 'v-03787', 5680 - '23802': 'v-03788', 5681 - '23803': 'v-03789', 5682 - '23804': 'v-03790', 5683 - '23805': 'v-03791', 5684 - '23806': 'v-03792', 5685 - '23807': 'v-03793', 5686 - '23808': 'v-03794', 5687 - '23809': 'v-03795', 5688 - '23810': 'v-03796', 5689 - '23811': 'v-03797', 5690 - '23812': 'v-03798', 5691 - '23813': 'v-03799', 5692 - '23814': 'v-03800', 5693 - '23815': 'v-03801', 5694 - '23816': 'v-03802', 5695 - '23817': 'v-03803', 5696 - '23818': 'v-03804', 5697 - '23819': 'v-03805', 5698 - '23820': 'v-03806', 5699 - '23821': 'v-03807', 5700 - '23822': 'v-03808', 5701 - '23823': 'v-03809', 5702 - '23824': 'v-03810', 5703 - '23825': 'v-03811', 5704 - '23826': 'v-03812', 5705 - '23827': 'v-03813', 5706 - '23828': 'v-03814', 5707 - '23829': 'v-03815', 5708 - '23830': 'v-03816', 5709 - '23831': 'v-03817', 5710 - '23832': 'v-03818', 5711 - '23833': 'v-03819', 5712 - '23834': 'v-03820', 5713 - '23835': 'v-03821', 5714 - '23836': 'v-03822', 5715 - '23837': 'v-03823', 5716 - '23838': 'v-03824', 5717 - '23839': 'v-03825', 5718 - '23840': 'v-03826', 5719 - '23841': 'v-03827', 5720 - '23842': 'v-03828', 5721 - '23843': 'v-03829', 5722 - '23844': 'v-03830', 5723 - '23845': 'v-03831', 5724 - '23846': 'v-03832', 5725 - '23847': 'v-03833', 5726 - '23848': 'v-03834', 5727 - '23849': 'v-03835', 5728 - '23850': 'v-03836', 5729 - '23851': 'v-03837', 5730 - '23852': 'v-03838', 5731 - '23853': 'v-03839', 5732 - '23854': 'v-03840', 5733 - '23855': 'v-03841', 5734 - '23856': 'v-03842', 5735 - '23857': 'v-03843', 5736 - '23858': 'v-03844', 5737 - '23859': 'v-03845', 5738 - '23860': 'v-03846', 5739 - '23861': 'v-03847', 5740 - '23862': 'v-03848', 5741 - '23863': 'v-03849', 5742 - '23864': 'v-03850', 5743 - '23865': 'v-03851', 5744 - '23866': 'v-03852', 5745 - '23867': 'v-03853', 5746 - '23868': 'v-03854', 5747 - '23869': 'v-03855', 5748 - '23870': 'v-03856', 5749 - '23871': 'v-03857', 5750 - '23872': 'v-03858', 5751 - '23873': 'v-03859', 5752 - '23874': 'v-03860', 5753 - '23875': 'v-03861', 5754 - '23876': 'v-03862', 5755 - '23877': 'v-03863', 5756 - '23878': 'v-03864', 5757 - '23879': 'v-03865', 5758 - '23880': 'v-03866', 5759 - '23881': 'v-03867', 5760 - '23882': 'v-03868', 5761 - '23883': 'v-03869', 5762 - '23884': 'v-03870', 5763 - '23885': 'v-03871', 5764 - '23886': 'v-03872', 5765 - '23887': 'v-03873', 5766 - '23888': 'v-03874', 5767 - '23889': 'v-03875', 5768 - '23890': 'v-03876', 5769 - '23891': 'v-03877', 5770 - '23892': 'v-03878', 5771 - '23893': 'v-03879', 5772 - '23894': 'v-03880', 5773 - '23895': 'v-03881', 5774 - '23896': 'v-03882', 5775 - '23897': 'v-03883', 5776 - '23898': 'v-03884', 5777 - '23899': 'v-03885', 5778 - '23900': 'v-03886', 5779 - '23901': 'v-03887', 5780 - '23902': 'v-03888', 5781 - '23903': 'v-03889', 5782 - '23904': 'v-03890', 5783 - '23905': 'v-03891', 5784 - '23906': 'v-03892', 5785 - '23907': 'v-03893', 5786 - '23908': 'v-03894', 5787 - '23909': 'v-03895', 5788 - '23910': 'v-03896', 5789 - '23911': 'v-03897', 5790 - '23912': 'v-03898', 5791 - '23913': 'v-03899', 5792 - '23914': 'v-03900', 5793 - '23915': 'v-03901', 5794 - '23916': 'v-03902', 5795 - '23917': 'v-03903', 5796 - '23918': 'v-03904', 5797 - '23919': 'v-03905', 5798 - '23920': 'v-03906', 5799 - '23921': 'v-03907', 5800 - '23922': 'v-03908', 5801 - '23923': 'v-03909', 5802 - '23924': 'v-03910', 5803 - '23925': 'v-03911', 5804 - '23926': 'v-03912', 5805 - '23927': 'v-03913', 5806 - '23928': 'v-03914', 5807 - '23929': 'v-03915', 5808 - '23930': 'v-03916', 5809 - '23931': 'v-03917', 5810 - '23932': 'v-03918', 5811 - '23933': 'v-03919', 5812 - '23934': 'v-03920', 5813 - '23935': 'v-03921', 5814 - '23936': 'v-03922', 5815 - '23937': 'v-03923', 5816 - '23938': 'v-03924', 5817 - '23939': 'v-03925', 5818 - '23940': 'v-03926', 5819 - '23941': 'v-03927', 5820 - '23942': 'v-03928', 5821 - '23943': 'v-03929', 5822 - '23944': 'v-03930', 5823 - '23945': 'v-03931', 5824 - '23946': 'v-03932', 5825 - '23947': 'v-03933', 5826 - '23948': 'v-03934', 5827 - '23949': 'v-03935', 5828 - '23950': 'v-03936', 5829 - '23951': 'v-03937', 5830 - '23952': 'v-03938', 5831 - '23953': 'v-03939', 5832 - '23954': 'v-03940', 5833 - '23955': 'v-03941', 5834 - '23956': 'v-03942', 5835 - '23957': 'v-03943', 5836 - '23958': 'v-03944', 5837 - '23959': 'v-03945', 5838 - '23960': 'v-03946', 5839 - '23961': 'v-03947', 5840 - '23962': 'v-03948', 5841 - '23963': 'v-03949', 5842 - '23964': 'v-03950', 5843 - '23965': 'v-03951', 5844 - '23966': 'v-03952', 5845 - '23967': 'v-03953', 5846 - '23968': 'v-03954', 5847 - '23969': 'v-03955', 5848 - '23970': 'v-03956', 5849 - '23971': 'v-03957', 5850 - '23972': 'v-03958', 5851 - '23973': 'v-03959', 5852 - '23974': 'v-03960', 5853 - '23975': 'v-03961', 5854 - '23976': 'v-03962', 5855 - '23977': 'v-03963', 5856 - '23978': 'v-03964', 5857 - '23979': 'v-03965', 5858 - '23980': 'v-03966', 5859 - '23981': 'v-03967', 5860 - '23982': 'v-03968', 5861 - '23983': 'v-03969', 5862 - '23984': 'v-03970', 5863 - '23985': 'v-03971', 5864 - '23986': 'v-03972', 5865 - '23987': 'v-03973', 5866 - '23988': 'v-03974', 5867 - '23989': 'v-03975', 5868 - '23990': 'v-03976', 5869 - '23991': 'v-03977', 5870 - '23992': 'v-03978', 5871 - '23993': 'v-03979', 5872 - '23994': 'v-03980', 5873 - '23995': 'v-03981', 5874 - '23996': 'v-03982', 5875 - '23997': 'v-03983', 5876 - '23998': 'v-03984', 5877 - '23999': 'v-03985', 5878 - '24000': 'v-03986', 5879 - '24001': 'v-03987', 5880 - '24002': 'v-03988', 5881 - '24003': 'v-03989', 5882 - '24004': 'v-03990', 5883 - '24005': 'v-03991', 5884 - '24006': 'v-03992', 5885 - '24007': 'v-03993', 5886 - '24008': 'v-03994', 5887 - '24009': 'v-03995', 5888 - '24010': 'v-03996', 5889 - '24011': 'v-03997', 5890 - '24012': 'v-03998', 5891 - '24013': 'v-03999', 5892 - '24014': 'v-04000', 5893 - '24015': 'v-04001', 5894 - '24016': 'v-04002', 5895 - '24017': 'v-04003', 5896 - '24018': 'v-04004', 5897 - '24019': 'v-04005', 5898 - '24020': 'v-04006', 5899 - '24021': 'v-04007', 5900 - '24022': 'v-04008', 5901 - '24023': 'v-04009', 5902 - '24024': 'v-04010', 5903 - '24025': 'v-04011', 5904 - '24026': 'v-04012', 5905 - '24027': 'v-04013', 5906 - '24028': 'v-04014', 5907 - '24029': 'v-04015', 5908 - '24030': 'v-04016', 5909 - '24031': 'v-04017', 5910 - '24032': 'v-04018', 5911 - '24033': 'v-04019', 5912 - '24034': 'v-04020', 5913 - '24035': 'v-04021', 5914 - '24036': 'v-04022', 5915 - '24037': 'v-04023', 5916 - '24038': 'v-04024', 5917 - '24039': 'v-04025', 5918 - '24040': 'v-04026', 5919 - '24041': 'v-04027', 5920 - '24042': 'v-04028', 5921 - '24043': 'v-04029', 5922 - '24044': 'v-04030', 5923 - '24045': 'v-04031', 5924 - '24046': 'v-04032', 5925 - '24047': 'v-04033', 5926 - '24048': 'v-04034', 5927 - '24049': 'v-04035', 5928 - '24050': 'v-04036', 5929 - '24051': 'v-04037', 5930 - '24052': 'v-04038', 5931 - '24053': 'v-04039', 5932 - '24054': 'v-04040', 5933 - '24055': 'v-04041', 5934 - '24056': 'v-04042', 5935 - '24057': 'v-04043', 5936 - '24058': 'v-04044', 5937 - '24059': 'v-04045', 5938 - '24060': 'v-04046', 5939 - '24061': 'v-04047', 5940 - '24062': 'v-04048', 5941 - '24063': 'v-04049', 5942 - '24064': 'v-04050', 5943 - '24065': 'v-04051', 5944 - '24066': 'v-04052', 5945 - '24067': 'v-04053', 5946 - '24068': 'v-04054', 5947 - '24069': 'v-04055', 5948 - '24070': 'v-04056', 5949 - '24071': 'v-04057', 5950 - '24072': 'v-04058', 5951 - '24073': 'v-04059', 5952 - '24074': 'v-04060', 5953 - '24075': 'v-04061', 5954 - '24076': 'v-04062', 5955 - '24077': 'v-04063', 5956 - '24078': 'v-04064', 5957 - '24079': 'v-04065', 5958 - '24080': 'v-04066', 5959 - '24081': 'v-04067', 5960 - '24082': 'v-04068', 5961 - '24083': 'v-04069', 5962 - '24084': 'v-04070', 5963 - '24085': 'v-04071', 5964 - '24086': 'v-04072', 5965 - '24087': 'v-04073', 5966 - '24088': 'v-04074', 5967 - '24089': 'v-04075', 5968 - '24090': 'v-04076', 5969 - '24091': 'v-04077', 5970 - '24092': 'v-04078', 5971 - '24093': 'v-04079', 5972 - '24094': 'v-04080', 5973 - '24095': 'v-04081', 5974 - '24096': 'v-04082', 5975 - '24097': 'v-04083', 5976 - '24098': 'v-04084', 5977 - '24099': 'v-04085', 5978 - '24100': 'v-04086', 5979 - '24101': 'v-04087', 5980 - '24102': 'v-04088', 5981 - '24103': 'v-04089', 5982 - '24104': 'v-04090', 5983 - '24105': 'v-04091', 5984 - '24106': 'v-04092', 5985 - '24107': 'v-04093', 5986 - '24108': 'v-04094', 5987 - '24109': 'v-04095', 5988 - '24110': 'v-04096', 5989 - '24111': 'v-04097', 5990 - '24112': 'v-04098', 5991 - '24113': 'v-04099', 5992 - '24114': 'v-04100', 5993 - '24115': 'v-04101', 5994 - '24116': 'v-04102', 5995 - '24117': 'v-04103', 5996 - '24118': 'v-04104', 5997 - '24119': 'v-04105', 5998 - '24120': 'v-04106', 5999 - '24121': 'v-04107', 6000 - '24122': 'v-04108', 6001 - '24123': 'v-04109', 6002 - '24124': 'v-04110', 6003 - '24125': 'v-04111', 6004 - '24126': 'v-04112', 6005 - '24127': 'v-04113', 6006 - '24128': 'v-04114', 6007 - '24129': 'v-04115', 6008 - '24130': 'v-04116', 6009 - '24131': 'v-04117', 6010 - '24132': 'v-04118', 6011 - '24133': 'v-04119', 6012 - '24134': 'v-04120', 6013 - }
+8 -179
www/models/schema.ts
··· 1 - import { 2 - MigrationConfig, 3 - MigrationMismatchAction, 4 - } from '@civility/store/storage' 5 - import { 1 + export { 6 2 Assignment, 7 - defaultStoreState, 8 - type JournalEntry, 3 + defaultFlags, 4 + defaultSettings, 5 + defaultUserLevels, 6 + Flags, 7 + JournalEntry, 9 8 Override, 10 9 OverrideProps, 11 10 Settings, 12 - type Stats, 13 - StoreState, 11 + Stats, 14 12 USER_LANGS, 15 - type UserLang, 16 13 } from './schema/v3.ts' 17 - import type { StoreState as V0 } from './schema/v0.ts' 18 - import type { StoreState as V1 } from './schema/v1.ts' 19 - import type { StoreState as V2 } from './schema/v2.ts' 20 - 21 - const { Continue, UseDefault } = MigrationMismatchAction 22 - 23 - type VersionPart = number | 'X' 24 - 25 - const currentVersion = globalThis.__APP_VERSION__ 26 - 27 - /** Migration configuration for StoreState (all synced data) */ 28 - export const storeMigrationConfig: MigrationConfig<StoreState> = { 29 - currentVersion, 30 - extractVersion: (data: unknown) => 31 - (data && typeof data === 'object' && 'version' in data) 32 - ? (data as { version: string }).version 33 - : undefined, 34 - onMigrationComplete: (data: unknown, _wasMigrated: boolean) => { 35 - const state = StoreState.parse(data) 36 - state.version = currentVersion 37 - return state 38 - }, 39 - migrations: [ 40 - { 41 - fromVersion: '<1.0.0', 42 - toVersion: '1.0.0', 43 - migrate: async (data: unknown) => 44 - (await import('./migrations/v1.ts')).migrateFromV0(data as V0), 45 - }, 46 - { 47 - fromVersion: '<2.0.0', 48 - toVersion: '2.0.0', 49 - migrate: async (data: unknown) => 50 - (await import('./migrations/v2.ts')).migrateFromV1(data as V1), 51 - }, 52 - { 53 - fromVersion: '<3.0.0', 54 - toVersion: '3.0.0', 55 - migrate: async (data: unknown) => 56 - (await import('./migrations/v3.ts')).migrateFromV2(data as V2), 57 - }, 58 - { 59 - fromVersion: '<4.0.0', 60 - toVersion: currentVersion, 61 - migrate: (data: unknown) => ({ 62 - ...data as StoreState, 63 - version: globalThis.__APP_VERSION__, 64 - }), 65 - }, 66 - ], 67 - 68 - /** 69 - * Handle version mismatches with fallback strategy 70 - * If there's no specific migration for a newer patch/minor version, 71 - * treat it as compatible with the latest known migration in the same major version 72 - */ 73 - onVersionMismatch( 74 - dataVersion: string | number | undefined, 75 - currentVersion: string | number, 76 - data: unknown, 77 - ) { 78 - console.log( 79 - `Version mismatch detected - data: ${dataVersion}, current: ${currentVersion}`, 80 - ) 81 - 82 - if (!dataVersion) return Continue // No version in data 83 - 84 - const dataVer = String(dataVersion) 85 - const currentVer = String(currentVersion) 86 - 87 - const dataParsed = parseVersion(dataVer) 88 - const currentParsed = parseVersion(currentVer) 89 - 90 - // If data is from a newer app version (higher major version), 91 - if ( 92 - typeof dataParsed.major === 'number' && 93 - typeof currentParsed.major === 'number' 94 - ) { 95 - if (dataParsed.major > currentParsed.major) { 96 - console.warn( 97 - `Newer major version detected (${dataVer} > ${currentVer})`, 98 - ) 99 - 100 - if (typeof globalThis !== 'undefined' && 'location' in globalThis) { 101 - console.log('Triggering app refresh to handle newer data version') 102 - setTimeout(() => { 103 - globalThis.location.reload() 104 - }, 1000) 105 - } 106 - 107 - // Try to extract compatible data, falling back to schema defaults 108 - try { 109 - const futureData = data as Partial<StoreState> 110 - 111 - // Use schema's default state as base 112 - const compatibleData: StoreState = { 113 - ...defaultStoreState, 114 - version: currentVer, 115 - } 116 - 117 - // Safely extract compatible fields if they exist and are valid 118 - if (futureData && typeof futureData === 'object') { 119 - if ( 120 - futureData.assignments && 121 - typeof futureData.assignments === 'object' 122 - ) { 123 - compatibleData.assignments = futureData.assignments 124 - } 125 - if (futureData.flags && typeof futureData.flags === 'object') { 126 - compatibleData.flags = futureData.flags 127 - } 128 - if ( 129 - futureData.settings && typeof futureData.settings === 'object' 130 - ) { 131 - compatibleData.settings = futureData.settings 132 - } 133 - if ( 134 - futureData.overrides && typeof futureData.overrides === 'object' 135 - ) { 136 - compatibleData.overrides = futureData.overrides 137 - } 138 - if ( 139 - futureData.userLevels && typeof futureData.userLevels === 'object' 140 - ) { 141 - compatibleData.userLevels = futureData.userLevels 142 - } 143 - if (Array.isArray(futureData.searchHistory)) { 144 - compatibleData.searchHistory = futureData.searchHistory 145 - } 146 - } 147 - 148 - return compatibleData 149 - } catch (error) { 150 - console.error('Failed to extract compatible data:', error) 151 - return UseDefault 152 - } 153 - } 154 - } 155 - 156 - return Continue 157 - }, 158 - } 159 - 160 - function parseVersion(version: string): { 161 - major: VersionPart 162 - minor: VersionPart 163 - patch: VersionPart 164 - raw: string 165 - } { 166 - const parts = version.split('.') 167 - return { 168 - major: parts[0] === 'X' ? 'X' : parseInt(parts[0] || '0', 10), 169 - minor: parts[1] === 'X' ? 'X' : parseInt(parts[1] || '0', 10), 170 - patch: parts[2] === 'X' ? 'X' : parseInt(parts[2] || '0', 10), 171 - raw: version, 172 - } 173 - } 174 - 175 - export { 176 - Assignment, 177 - defaultStoreState, 178 - Override, 179 - OverrideProps, 180 - Settings, 181 - StoreState, 182 - USER_LANGS, 183 - UserLang, 184 - } 185 - export type { JournalEntry, Stats } 14 + export type { UserLang, UserLevels } from './schema/v3.ts'
-100
www/models/schema/v0.ts
··· 1 - import { z } from '@zod/zod/mini' 2 - import { Locale } from '$/enums.ts' 3 - import { CardSortMethod } from '@flashcard/core' 4 - 5 - export const threshold = z.optional(z.union([ 6 - z.date(), 7 - z.pipe(z.iso.datetime(), z.transform((s) => new Date(s))), 8 - ])) 9 - 10 - export const Assignment = z.object({ 11 - difficulty: z.number(), 12 - stability: z.number(), 13 - interval: z.number(), 14 - repetition: z.number(), 15 - subjectId: z.string(), 16 - markedCompleted: z._default(z.boolean(), false), 17 - lastStudiedAt: threshold, 18 - unlockedAt: threshold, 19 - availableAt: threshold, 20 - startedAt: threshold, 21 - passedAt: threshold, 22 - completedAt: threshold, 23 - }) 24 - 25 - export type Assignment = z.infer<typeof Assignment> 26 - 27 - export const OverrideProps = z.object({ 28 - subjectId: z.string(), 29 - primaryMeaning: z.optional(z.string()), 30 - auxMeanings: z.optional(z.string()), 31 - meaningHint: z.optional(z.string()), 32 - meaningMnemonic: z.optional(z.string()), 33 - readingHint: z.optional(z.string()), 34 - readingMnemonic: z.optional(z.string()), 35 - }) 36 - 37 - export type OverrideProps = z.infer<typeof OverrideProps> 38 - 39 - export const Override = z.object({ 40 - ...OverrideProps.shape, 41 - [Locale.zh_CN]: z.optional(OverrideProps), 42 - [Locale.zh_HK]: z.optional(OverrideProps), 43 - [Locale.zh_TW]: z.optional(OverrideProps), 44 - }) 45 - 46 - export type Override = z.infer<typeof Override> 47 - 48 - export const Settings = z.object({ 49 - locale: z._default(z.enum(Locale), Locale.zh_CN), 50 - playAudio: z._default(z.boolean(), true), 51 - reviewLimit: z._default(z.nullable(z.number()), null), 52 - learnLimit: z._default(z.nullable(z.number()), 10), 53 - learnSessionSize: z._default(z.nullable(z.number()), 10), 54 - reviewSessionSize: z._default(z.nullable(z.number()), 20), 55 - cardSortMethod: z._default(z.enum(CardSortMethod), CardSortMethod.Paired), 56 - cardSortOrder: z._default(z.nullable(z.array(z.string())), null), 57 - }) 58 - 59 - export type Settings = z.infer<typeof Settings> 60 - 61 - export const defaultSettings = Settings.parse({}) 62 - 63 - // Create default factory functions for nested schemas 64 - const defaultAssignments = () => ({ 65 - [Locale.zh_CN]: {}, 66 - [Locale.zh_HK]: {}, 67 - [Locale.zh_TW]: {}, 68 - [Locale.ja]: {}, 69 - }) 70 - 71 - export const Flags = z.object({ 72 - isFirstLoad: z._default(z.boolean(), true), 73 - isFirstPinyin: z._default(z.boolean(), true), 74 - isFirstPinyinVocab: z._default(z.boolean(), true), 75 - }) 76 - 77 - export const defaultFlags = Flags.parse({}) 78 - 79 - const defaultUserLevels = () => ({ 80 - [Locale.zh_CN]: 0, 81 - [Locale.zh_HK]: 0, 82 - [Locale.zh_TW]: 0, 83 - }) 84 - 85 - export const StoreState = z.object({ 86 - version: z._default(z.string(), globalThis.__APP_VERSION__), 87 - assignments: z._default( 88 - z.record(z.string(), z.record(z.string(), Assignment)), 89 - defaultAssignments, 90 - ), 91 - flags: z._default(Flags, () => defaultFlags), 92 - settings: z._default(Settings, () => defaultSettings), 93 - overrides: z._default(z.record(z.string(), Override), {}), 94 - userLevels: z._default(z.record(z.string(), z.number()), defaultUserLevels), 95 - }) 96 - 97 - export type StoreState = z.infer<typeof StoreState> 98 - 99 - // Get the default app state by parsing an empty object 100 - export const defaultStoreState = StoreState.parse({})
-105
www/models/schema/v1.ts
··· 1 - import { z } from '@zod/zod/mini' 2 - import { Locale } from '$/enums.ts' 3 - import { CardSortMethod } from '@flashcard/core' 4 - 5 - export const threshold = z.optional(z.union([ 6 - z.date(), 7 - z.pipe(z.string(), z.transform((s: string) => new Date(s))), 8 - ])) 9 - 10 - /** 11 - * Allows for either Static or FSRS 12 - * Added efactor, srsId fields and made some fields optional 13 - */ 14 - export const Assignment = z.object({ 15 - difficulty: z._default(z.optional(z.number()), 0.3), 16 - stability: z._default(z.optional(z.number()), 0), 17 - interval: z._default(z.optional(z.number()), 0), 18 - repetition: z._default(z.optional(z.number()), 0), 19 - srsId: z._default(z.optional(z.number()), 1), 20 - efactor: z._default(z.optional(z.number()), 0), 21 - subjectId: z.string(), 22 - markedCompleted: z._default(z.boolean(), false), 23 - lastStudiedAt: threshold, 24 - unlockedAt: threshold, 25 - availableAt: threshold, 26 - startedAt: threshold, 27 - passedAt: threshold, 28 - completedAt: threshold, 29 - }) 30 - 31 - export type Assignment = z.infer<typeof Assignment> 32 - 33 - export const OverrideProps = z.object({ 34 - subjectId: z.string(), 35 - primaryMeaning: z.optional(z.string()), 36 - auxMeanings: z.optional(z.string()), 37 - meaningHint: z.optional(z.string()), 38 - meaningMnemonic: z.optional(z.string()), 39 - readingHint: z.optional(z.string()), 40 - readingMnemonic: z.optional(z.string()), 41 - }) 42 - 43 - export type OverrideProps = z.infer<typeof OverrideProps> 44 - 45 - export const Override = z.object({ 46 - ...OverrideProps.shape, 47 - [Locale.zh_CN]: z.optional(OverrideProps), 48 - [Locale.zh_HK]: z.optional(OverrideProps), 49 - [Locale.zh_TW]: z.optional(OverrideProps), 50 - }) 51 - 52 - export type Override = z.infer<typeof Override> 53 - 54 - export const Settings = z.object({ 55 - locale: z._default(z.enum(Locale), Locale.zh_CN), 56 - playAudio: z._default(z.boolean(), true), 57 - reviewLimit: z._default(z.nullable(z.number()), null), 58 - learnLimit: z._default(z.nullable(z.number()), 10), 59 - learnSessionSize: z._default(z.nullable(z.number()), 10), 60 - reviewSessionSize: z._default(z.nullable(z.number()), 20), 61 - cardSortMethod: z._default(z.enum(CardSortMethod), CardSortMethod.Paired), 62 - cardSortOrder: z._default(z.nullable(z.array(z.string())), null), 63 - }) 64 - 65 - export type Settings = z.infer<typeof Settings> 66 - 67 - export const defaultSettings = Settings.parse({}) 68 - 69 - export const Flags = z.object({ 70 - isFirstLoad: z._default(z.boolean(), true), 71 - isFirstPinyin: z._default(z.boolean(), true), 72 - isFirstPinyinVocab: z._default(z.boolean(), true), 73 - }) 74 - 75 - export const defaultFlags = Flags.parse({}) 76 - 77 - export const defaultUserLevels = () => ({ 78 - [Locale.zh_CN]: 0, 79 - [Locale.zh_HK]: 0, 80 - [Locale.zh_TW]: 0, 81 - }) 82 - 83 - // Create default factory functions for nested schemas 84 - export const defaultAssignments = () => ({ 85 - [Locale.zh_CN]: {}, 86 - [Locale.zh_HK]: {}, 87 - [Locale.zh_TW]: {}, 88 - }) 89 - 90 - export const StoreState = z.object({ 91 - version: z._default(z.string(), globalThis.__APP_VERSION__), 92 - assignments: z._default( 93 - z.record(z.string(), z.record(z.string(), Assignment)), 94 - defaultAssignments, 95 - ), 96 - flags: z._default(Flags, () => defaultFlags), 97 - settings: z._default(Settings, () => defaultSettings), 98 - overrides: z._default(z.record(z.string(), Override), {}), 99 - userLevels: z._default(z.record(z.string(), z.number()), defaultUserLevels), 100 - }) 101 - 102 - export type StoreState = z.infer<typeof StoreState> 103 - 104 - // Get the default app state by parsing an empty object 105 - export const defaultStoreState = StoreState.parse({})
-121
www/models/schema/v2.ts
··· 1 - import { z } from '@zod/zod/mini' 2 - import { Locale, Transliteration } from '$/enums.ts' 3 - import { CardSortMethod } from '@flashcard/core' 4 - 5 - export const threshold = z.optional(z.union([ 6 - z.date(), 7 - z.pipe(z.string(), z.transform((s) => new Date(s))), 8 - ])) 9 - 10 - /** 11 - * Allows for either Static or FSRS 12 - */ 13 - export const Assignment = z.object({ 14 - difficulty: z._default(z.optional(z.number()), 0.3), 15 - stability: z._default(z.optional(z.number()), 0), 16 - interval: z._default(z.optional(z.number()), 0), 17 - repetition: z._default(z.optional(z.number()), 0), 18 - srsId: z._default(z.optional(z.number()), 1), 19 - efactor: z._default(z.optional(z.number()), 0), 20 - subjectId: z.string(), 21 - markedCompleted: z._default(z.boolean(), false), 22 - lastStudiedAt: threshold, 23 - unlockedAt: threshold, 24 - availableAt: threshold, 25 - startedAt: threshold, 26 - passedAt: threshold, 27 - completedAt: threshold, 28 - }) 29 - 30 - export type Assignment = z.infer<typeof Assignment> 31 - 32 - export const OverrideProps = z.object({ 33 - subjectId: z.string(), 34 - primaryMeaning: z.optional(z.string()), 35 - auxMeanings: z.optional(z.string()), 36 - meaningHint: z.optional(z.string()), 37 - meaningMnemonic: z.optional(z.string()), 38 - readingHint: z.optional(z.string()), 39 - readingMnemonic: z.optional(z.string()), 40 - }) 41 - 42 - export type OverrideProps = z.infer<typeof OverrideProps> 43 - 44 - export const Override = z.object({ 45 - ...OverrideProps.shape, 46 - [Locale.zh_CN]: z.optional(OverrideProps), 47 - [Locale.zh_HK]: z.optional(OverrideProps), 48 - [Locale.zh_TW]: z.optional(OverrideProps), 49 - }) 50 - 51 - export type Override = z.infer<typeof Override> 52 - 53 - export const USER_LANGS = ['en', 'es'] as const 54 - export type UserLang = typeof USER_LANGS[number] 55 - 56 - export const Settings = z.object({ 57 - locale: z._default(z.string(), Locale.zh_CN), 58 - userLang: z._default(z.enum(USER_LANGS), () => { 59 - const lang = (typeof navigator !== 'undefined' ? navigator.language : 'en') 60 - .split('-')[0].toLowerCase() 61 - return (USER_LANGS as readonly string[]).includes(lang) 62 - ? lang as UserLang 63 - : 'en' 64 - }), 65 - playAudio: z._default(z.boolean(), true), 66 - reviewLimit: z._default(z.nullable(z.number()), null), 67 - learnLimit: z._default(z.nullable(z.number()), 10), 68 - learnSessionSize: z._default(z.nullable(z.number()), 10), 69 - reviewSessionSize: z._default(z.nullable(z.number()), 20), 70 - transliteration: z._default(z.enum(Transliteration), Transliteration.Pinyin), 71 - cardSortMethod: z._default(z.enum(CardSortMethod), CardSortMethod.Paired), 72 - cardSortOrder: z._default(z.nullable(z.array(z.string())), null), 73 - }) 74 - 75 - export type Settings = z.infer<typeof Settings> 76 - 77 - export const defaultSettings = Settings.parse({}) 78 - 79 - export const Flags = z.object({ 80 - isFirstLoad: z._default(z.boolean(), true), 81 - isFirstPinyin: z._default(z.boolean(), true), 82 - isFirstPinyinVocab: z._default(z.boolean(), true), 83 - isFirstZhuyin: z._default(z.boolean(), true), 84 - isFirstHiragana: z._default(z.boolean(), true), 85 - }) 86 - 87 - export const defaultFlags = Flags.parse({}) 88 - 89 - export const defaultUserLevels = () => ({ 90 - [Locale.zh_CN]: 0, 91 - [Locale.zh_HK]: 0, 92 - [Locale.zh_TW]: 0, 93 - [Locale.ja]: 0, 94 - }) 95 - 96 - // Create default factory functions for nested schemas 97 - export const defaultAssignments = () => ({ 98 - [Locale.zh_CN]: {}, 99 - [Locale.zh_HK]: {}, 100 - [Locale.zh_TW]: {}, 101 - [Locale.ja]: {}, 102 - }) 103 - 104 - const appVersion: string = globalThis.__APP_VERSION__ 105 - 106 - export const StoreState = z.object({ 107 - version: z._default(z.string(), appVersion), 108 - assignments: z._default( 109 - z.record(z.string(), z.record(z.string(), Assignment)), 110 - defaultAssignments, 111 - ), 112 - flags: z._default(Flags, () => defaultFlags), 113 - settings: z._default(Settings, () => defaultSettings), 114 - overrides: z._default(z.record(z.string(), Override), {}), 115 - userLevels: z._default(z.record(z.string(), z.number()), defaultUserLevels), 116 - }) 117 - 118 - export type StoreState = z.infer<typeof StoreState> 119 - 120 - // Get the default store state by parsing an empty object 121 - export const defaultStoreState = StoreState.parse({})
+96 -30
www/models/schema/v3.ts
··· 1 1 import { z } from '@zod/zod/mini' 2 - export { 3 - Assignment, 4 - defaultAssignments, 5 - defaultFlags, 6 - defaultSettings, 7 - defaultUserLevels, 8 - Flags, 9 - Override, 10 - OverrideProps, 11 - Settings, 12 - threshold, 13 - USER_LANGS, 14 - } from './v2.ts' 15 - export type { UserLang } from './v2.ts' 16 - import { StoreState as V2StoreState } from './v2.ts' 2 + import { Locale, Transliteration } from '$/enums.ts' 3 + import { CardSortMethod } from '@flashcard/core' 4 + 5 + export const threshold = z.optional(z.union([ 6 + z.date(), 7 + z.pipe(z.string(), z.transform((s: string) => new Date(s))), 8 + ])) 9 + 10 + export const Assignment = z.object({ 11 + difficulty: z._default(z.optional(z.number()), 0.3), 12 + stability: z._default(z.optional(z.number()), 0), 13 + interval: z._default(z.optional(z.number()), 0), 14 + repetition: z._default(z.optional(z.number()), 0), 15 + srsId: z._default(z.optional(z.number()), 1), 16 + efactor: z._default(z.optional(z.number()), 0), 17 + subjectId: z.string(), 18 + locale: z.optional(z.string()), 19 + markedCompleted: z._default(z.boolean(), false), 20 + lastStudiedAt: threshold, 21 + unlockedAt: threshold, 22 + availableAt: threshold, 23 + startedAt: threshold, 24 + passedAt: threshold, 25 + completedAt: threshold, 26 + }) 27 + 28 + export type Assignment = z.infer<typeof Assignment> 29 + 30 + export const OverrideProps = z.object({ 31 + subjectId: z.string(), 32 + primaryMeaning: z.optional(z.string()), 33 + auxMeanings: z.optional(z.string()), 34 + meaningHint: z.optional(z.string()), 35 + meaningMnemonic: z.optional(z.string()), 36 + readingHint: z.optional(z.string()), 37 + readingMnemonic: z.optional(z.string()), 38 + }) 39 + 40 + export type OverrideProps = z.infer<typeof OverrideProps> 41 + 42 + export const Override = z.object({ 43 + ...OverrideProps.shape, 44 + [Locale.zh_CN]: z.optional(OverrideProps), 45 + [Locale.zh_HK]: z.optional(OverrideProps), 46 + [Locale.zh_TW]: z.optional(OverrideProps), 47 + }) 48 + 49 + export type Override = z.infer<typeof Override> 50 + 51 + export const USER_LANGS = ['en', 'es'] as const 52 + export type UserLang = typeof USER_LANGS[number] 53 + 54 + export const Settings = z.object({ 55 + locale: z._default(z.string(), Locale.zh_CN), 56 + userLang: z._default(z.enum(USER_LANGS), () => { 57 + const lang = (typeof navigator !== 'undefined' ? navigator.language : 'en') 58 + .split('-')[0].toLowerCase() 59 + return (USER_LANGS as readonly string[]).includes(lang) 60 + ? lang as UserLang 61 + : 'en' 62 + }), 63 + playAudio: z._default(z.boolean(), true), 64 + reviewLimit: z._default(z.nullable(z.number()), null), 65 + learnLimit: z._default(z.nullable(z.number()), 10), 66 + learnSessionSize: z._default(z.nullable(z.number()), 10), 67 + reviewSessionSize: z._default(z.nullable(z.number()), 20), 68 + transliteration: z._default(z.enum(Transliteration), Transliteration.Pinyin), 69 + cardSortMethod: z._default(z.enum(CardSortMethod), CardSortMethod.Paired), 70 + cardSortOrder: z._default(z.nullable(z.array(z.string())), null), 71 + }) 72 + 73 + export type Settings = z.infer<typeof Settings> 74 + 75 + export const defaultSettings = Settings.parse({}) 76 + 77 + export const Flags = z.object({ 78 + isFirstLoad: z._default(z.boolean(), true), 79 + isFirstPinyin: z._default(z.boolean(), true), 80 + isFirstPinyinVocab: z._default(z.boolean(), true), 81 + isFirstZhuyin: z._default(z.boolean(), true), 82 + isFirstHiragana: z._default(z.boolean(), true), 83 + }) 84 + 85 + export type Flags = z.infer<typeof Flags> 86 + 87 + export const defaultFlags = Flags.parse({}) 88 + 89 + export const defaultUserLevels = (): UserLevels => ({ 90 + [Locale.zh_CN]: 0, 91 + [Locale.zh_HK]: 0, 92 + [Locale.zh_TW]: 0, 93 + [Locale.ja]: 0, 94 + }) 95 + 96 + export type UserLevels = Record<string, number> 97 + export const UserLevels = z.record(z.string(), z.number()) 17 98 18 99 export const JournalEntry = z.object({ 19 100 date: z.string(), ··· 23 104 24 105 export type JournalEntry = z.infer<typeof JournalEntry> 25 106 26 - const Games = z.object({ 27 - journal: z._default(z.array(JournalEntry), []), 28 - }) 29 - 30 107 export const Stats = z.object({ 31 108 currStreak: z._default(z.number(), 0), 32 109 longestStreak: z._default(z.number(), 0), ··· 34 111 }) 35 112 36 113 export type Stats = z.infer<typeof Stats> 37 - 38 - export const StoreState = z.object({ 39 - ...V2StoreState.shape, 40 - games: z._default(Games, () => Games.parse({})), 41 - stats: z._default(Stats, () => Stats.parse({})), 42 - searchHistory: z._default(z.array(z.string()), []), 43 - }) 44 - 45 - export type StoreState = z.infer<typeof StoreState> 46 - 47 - export const defaultStoreState = StoreState.parse({})
-338
www/models/store.ts
··· 1 - /** 2 - * The Store is a thin wrapper around SyncLink that provides CRUD 3 - * operations for user progress data. It handles syncing of assignments, 4 - * overrides, settings, and user levels across devices. 5 - */ 6 - import SyncLink from '@civility/sync' 7 - import LocalStorage from '@civility/store/local-storage' 8 - import { 9 - type Assignment, 10 - defaultStoreState, 11 - type JournalEntry, 12 - type Override, 13 - type Settings, 14 - storeMigrationConfig, 15 - StoreState, 16 - } from './schema.ts' 17 - import { Locale } from '$/enums.ts' 18 - 19 - /** 20 - * Thin wrapper around SyncLink for user progress data with CRUD operations 21 - */ 22 - export class Store { 23 - #sync: SyncLink<StoreState> 24 - #initialized = false 25 - 26 - constructor(name: string, syncLinkUrl?: string) { 27 - const storage = new LocalStorage<StoreState>({ 28 - name, 29 - defaultValue: defaultStoreState, 30 - deserialize: (str: string) => StoreState.parse(JSON.parse(str)), 31 - serialize: (data: StoreState) => JSON.stringify(data), 32 - verify: (_data: unknown) => true, 33 - migrations: storeMigrationConfig, 34 - }) 35 - 36 - this.#sync = new SyncLink(storage) 37 - 38 - // Mark initialized on SyncLink's first notification (data loaded from storage). 39 - // Used by app.storeReady to guard against acting on defaultStoreState. 40 - const onFirstLoad = () => { 41 - this.#initialized = true 42 - } 43 - this.#sync.addEventListener(onFirstLoad) 44 - 45 - if (syncLinkUrl) { 46 - this.connect(syncLinkUrl).catch((error) => 47 - console.warn('Store: Failed to connect to SyncLink:', error) 48 - ) 49 - } 50 - } 51 - 52 - /** True once SyncLink has fired its first notification (real data loaded from storage) */ 53 - get initialized(): boolean { 54 - return this.#initialized 55 - } 56 - 57 - // ====== SYNCLINK CONNECTION ====== 58 - 59 - /** Connect to SyncLink server */ 60 - async connect(syncLinkUrl: string): Promise<void> { 61 - if (!syncLinkUrl.trim()) throw new Error('SyncLink URL is required') 62 - 63 - const { baseUrl, appId, token } = SyncLink.parseURL(syncLinkUrl) 64 - await this.#sync.connect(baseUrl, appId, token) 65 - } 66 - 67 - /** Disconnect from SyncLink server */ 68 - disconnect(): void { 69 - this.#sync.disconnect() 70 - } 71 - 72 - notify() { 73 - this.#sync.notify() 74 - } 75 - 76 - /** Check if connected to SyncLink */ 77 - get isConnected(): boolean { 78 - return this.#sync.isConnected 79 - } 80 - 81 - /** Force sync from server */ 82 - async syncFromServer(): Promise<void> { 83 - await this.#sync.forceSyncFromServer() 84 - } 85 - 86 - /** Force sync to server */ 87 - async syncToServer(): Promise<void> { 88 - await this.#sync.forceSyncToServer() 89 - } 90 - 91 - // ====== STATE ACCESS ====== 92 - 93 - get state() { 94 - return this.#sync.state 95 - } 96 - 97 - get data() { 98 - return this.#sync.state.data 99 - } 100 - 101 - get assignments() { 102 - return this.#sync.state.data.assignments 103 - } 104 - 105 - get settings() { 106 - return this.#sync.state.data.settings 107 - } 108 - 109 - get overrides() { 110 - return this.#sync.state.data.overrides 111 - } 112 - 113 - get userLevels() { 114 - return this.#sync.state.data.userLevels 115 - } 116 - 117 - get flags() { 118 - return this.#sync.state.data.flags 119 - } 120 - 121 - /** Subscribe to state changes */ 122 - addEventListener(fn: () => void): void { 123 - this.#sync.addEventListener(fn) 124 - // If data is already loaded, call fn immediately so late-connecting components 125 - // get current state rather than waiting for the next change. 126 - if (this.#initialized) fn() 127 - } 128 - 129 - /** Unsubscribe from state changes */ 130 - removeEventListener(fn: () => void): void { 131 - this.#sync.removeEventListener(fn) 132 - } 133 - 134 - // ====== ASSIGNMENT CRUD ====== 135 - 136 - /** Get an assignment by subject ID and locale */ 137 - async getAssignment( 138 - locale: Locale, 139 - subjectId: string, 140 - ): Promise<Assignment | null> { 141 - const data = await this.#sync.get() 142 - return data.assignments[locale]?.[subjectId] || null 143 - } 144 - 145 - /** Get all assignments for a locale */ 146 - async getAssignmentsByLocale( 147 - locale: Locale, 148 - ): Promise<Record<string, Assignment>> { 149 - const data = await this.#sync.get() 150 - return data.assignments[locale] || {} 151 - } 152 - 153 - /** Save an assignment */ 154 - async saveAssignment( 155 - locale: Locale, 156 - assignment: Assignment, 157 - ): Promise<boolean> { 158 - const data = await this.#sync.get() 159 - if (!data.assignments[locale]) { 160 - data.assignments[locale] = {} 161 - } 162 - data.assignments[locale][assignment.subjectId] = assignment 163 - return await this.#sync.set(data) 164 - } 165 - 166 - /** Delete an assignment */ 167 - async deleteAssignment(locale: Locale, subjectId: string): Promise<boolean> { 168 - const data = await this.#sync.get() 169 - if (!data.assignments[locale]?.[subjectId]) return false 170 - delete data.assignments[locale][subjectId] 171 - return await this.#sync.set(data) 172 - } 173 - 174 - // ====== OVERRIDE CRUD ====== 175 - 176 - /** Get an override by subject ID */ 177 - async getOverride(subjectId: string): Promise<Override | null> { 178 - const data = await this.#sync.get() 179 - return data.overrides[subjectId] || null 180 - } 181 - 182 - /** Get all overrides */ 183 - async getAllOverrides(): Promise<Record<string, Override>> { 184 - const data = await this.#sync.get() 185 - return data.overrides 186 - } 187 - 188 - /** Save an override */ 189 - async saveOverride(override: Override): Promise<boolean> { 190 - const data = await this.#sync.get() 191 - data.overrides[override.subjectId] = override 192 - return await this.#sync.set(data) 193 - } 194 - 195 - /** Delete an override */ 196 - async deleteOverride(subjectId: string): Promise<boolean> { 197 - const data = await this.#sync.get() 198 - if (!(subjectId in data.overrides)) return false 199 - delete data.overrides[subjectId] 200 - return await this.#sync.set(data) 201 - } 202 - 203 - // ====== SETTINGS ====== 204 - 205 - /** Update settings */ 206 - async updateSettings(updates: Partial<Settings>): Promise<boolean> { 207 - const data = await this.#sync.get() 208 - data.settings = { ...data.settings, ...updates } 209 - return await this.#sync.set(data) 210 - } 211 - 212 - // ====== USER LEVELS ====== 213 - 214 - /** Get user level for a locale */ 215 - async getUserLevel(locale: Locale): Promise<number> { 216 - const data = await this.#sync.get() 217 - return data.userLevels[locale] || 0 218 - } 219 - 220 - /** Set user level for a locale */ 221 - async setUserLevel(locale: Locale, level: number): Promise<boolean> { 222 - const data = await this.#sync.get() 223 - data.userLevels[locale] = level 224 - return await this.#sync.set(data) 225 - } 226 - 227 - // ====== FLAGS ====== 228 - 229 - /** Update flags */ 230 - async updateFlags( 231 - updates: Partial<StoreState['flags']>, 232 - ): Promise<boolean> { 233 - const data = await this.#sync.get() 234 - data.flags = { ...data.flags, ...updates } 235 - return await this.#sync.set(data) 236 - } 237 - 238 - // ====== JOURNAL ====== 239 - 240 - /** Get all journal entries */ 241 - getJournalEntries(): JournalEntry[] { 242 - return this.#sync.state.data.games?.journal ?? [] 243 - } 244 - 245 - /** Save (upsert) a journal entry by date */ 246 - async saveJournalEntry(entry: JournalEntry): Promise<boolean> { 247 - const data = await this.#sync.get() 248 - if (!data.games) data.games = { journal: [] } 249 - const idx = data.games.journal.findIndex((e) => e.date === entry.date) 250 - if (idx >= 0) data.games.journal[idx] = entry 251 - else data.games.journal.push(entry) 252 - return await this.#sync.set(data) 253 - } 254 - 255 - // ====== UTILITY ====== 256 - 257 - /** Get all data (for debugging or export) */ 258 - getAllData(): Promise<StoreState> { 259 - return this.#sync.get() 260 - } 261 - 262 - /** Set all data (for imports) */ 263 - async setAllData(data: StoreState): Promise<boolean> { 264 - return await this.#sync.set(data) 265 - } 266 - 267 - /** Clear all data */ 268 - async clearAllData(): Promise<void> { 269 - const freshDefault = StoreState.parse({}) 270 - await this.#sync.set(freshDefault) 271 - } 272 - 273 - /** Export data to file */ 274 - exportToFile(filename?: string): Promise<{ 275 - success: boolean 276 - path: string 277 - error?: string 278 - }> { 279 - try { 280 - return this.#sync.exportToFile(filename || 'hanzi-data') 281 - } catch (error) { 282 - return Promise.resolve({ 283 - success: false, 284 - path: '', 285 - error: error instanceof Error ? error.message : 'Export failed', 286 - }) 287 - } 288 - } 289 - 290 - /** Import data from file */ 291 - importFromFile(options: { dryRun?: boolean } = {}): Promise<{ 292 - success: boolean 293 - path: string 294 - data?: StoreState 295 - error?: string 296 - }> { 297 - try { 298 - return this.#sync.importFromFile(options) 299 - } catch (error) { 300 - return Promise.resolve({ 301 - success: false, 302 - path: '', 303 - error: error instanceof Error ? error.message : 'Import failed', 304 - }) 305 - } 306 - } 307 - 308 - /** Reset data to defaults */ 309 - resetData(): Promise<{ 310 - success: boolean 311 - path: string 312 - error?: string 313 - }> { 314 - try { 315 - return this.#sync.resetData() 316 - } catch (error) { 317 - return Promise.resolve({ 318 - success: false, 319 - path: '', 320 - error: error instanceof Error ? error.message : 'Reset failed', 321 - }) 322 - } 323 - } 324 - 325 - /** Test connection to SyncLink server */ 326 - async testConnection(): Promise<boolean> { 327 - if (!this.isConnected) { 328 - throw new Error('Not connected to SyncLink') 329 - } 330 - await this.#sync.get() 331 - return true 332 - } 333 - 334 - /** Dispose resources */ 335 - dispose(): void { 336 - this.#sync.dispose() 337 - } 338 - }
+50 -10
www/models/subjects.ts
··· 1 - import State from '@civility/store/state' 2 - import { Deck, type Subject as AnySubject } from '@flashcard/core' 1 + import { 2 + CardSortMethod, 3 + Deck, 4 + type Subject as AnySubject, 5 + } from '@flashcard/core' 3 6 import StaticScheduler from '@flashcard/schedulers/progress-static' 4 7 import { StaticQuality as Quality } from '@flashcard/schedulers/static' 5 8 import { Locale, SubjectType, Transliteration } from '../enums.ts' ··· 7 10 import { getCustomSetData } from '$/utils/custom_sets.ts' 8 11 import app from './app.ts' 9 12 13 + class State<T> { 14 + #state: T 15 + #subscribers = new Set<(state: T) => void>() 16 + initialized = false 17 + loading = false 18 + 19 + constructor(initialState: T) { 20 + this.#state = initialState 21 + } 22 + 23 + get state(): T { 24 + return this.#state 25 + } 26 + 27 + batch(fn: (state: T) => void): void { 28 + fn(this.#state) 29 + this.#notify() 30 + } 31 + 32 + addEventListener(fn: (state: T) => void): void { 33 + this.#subscribers.add(fn) 34 + } 35 + 36 + removeEventListener(fn: (state: T) => void): void { 37 + this.#subscribers.delete(fn) 38 + } 39 + 40 + #notify(): void { 41 + for (const cb of this.#subscribers) cb(this.#state) 42 + } 43 + 44 + notify(): void { 45 + this.#notify() 46 + } 47 + } 48 + 10 49 class Scheduler extends StaticScheduler { 11 50 constructor({ userLevel }: { userLevel: number }) { 12 51 super({ userLevel }) ··· 116 155 subjectsData = ((await getCustomSetData(locale)) as Subject[]) ?? [] 117 156 } else { 118 157 subjectsData = await fetch(`/static/gen/lang/${userLang}/${locale}.json`) 119 - .then((r) => r.json()) 158 + .then((r) => r.json() as unknown as Subject[]) 120 159 } 121 160 loadedKey = key 122 161 loadingKey = '' ··· 170 209 } 171 210 // else: fetch in progress for this key — wait for it to complete 172 211 212 + const settings = app.settings 173 213 deck.batch((state) => { 174 214 state.assignments = app.assignments 175 - state.learnLimit = app.state.settings.learnLimit 176 - state.reviewLimit = app.state.settings.reviewLimit 177 - state.learnSessionSize = app.state.settings.learnSessionSize 178 - state.reviewSessionSize = app.state.settings.reviewSessionSize 179 - state.cardSortMethod = app.state.settings.cardSortMethod 180 - state.cardSortOrder = app.state.settings.cardSortOrder 215 + state.learnLimit = settings?.learnLimit ?? 5 216 + state.reviewLimit = settings?.reviewLimit ?? 20 217 + state.learnSessionSize = settings?.learnSessionSize ?? 10 218 + state.reviewSessionSize = settings?.reviewSessionSize ?? 50 219 + state.cardSortMethod = settings?.cardSortMethod ?? CardSortMethod.Paired 220 + state.cardSortOrder = settings?.cardSortOrder ?? null 181 221 scheduler = new Scheduler({ userLevel: app.userLevel }) 182 222 183 223 deck.scheduler = scheduler ··· 201 241 let numRemaining: number | undefined = undefined 202 242 203 243 state.all = subjectsData.map((data: Subject) => { 204 - const subject = app.applyOverride(data) 244 + const subject = app.applyOverride(data) as Subject 205 245 206 246 state.byId[subject.id] = subject 207 247 state.byType[subject.data.type].push(subject)
+4 -7
www/routes/games/journal.ts
··· 46 46 #tryRefreshEntry() { 47 47 if (this.#entry.wordIds.length > 0) return 48 48 const dateString = getDateString(this.#currDate) 49 - const existing = app.store.getJournalEntries() 49 + const existing = app.getJournalEntries() 50 50 .find((e) => e.date === dateString) 51 51 if (existing) { 52 52 this.#entry = existing ··· 78 78 79 79 #loadEntry() { 80 80 const dateString = getDateString(this.#currDate) 81 - const existing = app.store.getJournalEntries().find((e) => 82 - e.date === dateString 83 - ) 81 + const existing = app.getJournalEntries().find((e) => e.date === dateString) 84 82 if (existing) { 85 83 this.#entry = existing 86 84 } else { ··· 94 92 } 95 93 96 94 async #save() { 97 - await app.store.saveJournalEntry(this.#entry) 98 - app.notify() 95 + await app.saveJournalEntry(this.#entry) 99 96 } 100 97 101 98 override render() { 102 99 const today = getDateString() 103 - const entries = app.store.getJournalEntries() 100 + const entries = app.getJournalEntries() 104 101 const dates = [...new Set(entries.map((e) => e.date).concat([today]))] 105 102 const { text, wordIds, date } = this.#entry 106 103 const wordSubjects = wordIds
+2 -2
www/routes/games/sentences.ts
··· 51 51 } 52 52 53 53 async #loadDeck() { 54 - if (!app.initialized) return 54 + if (!app.storeReady) return 55 55 const key = `${app.userLang}/${app.locale}/${app.userLevel}` 56 56 if (this.#loadedKey === key || this.#loading) return 57 57 this.#loading = true ··· 101 101 } 102 102 103 103 override render() { 104 - if (!app.initialized || this.#loading) { 104 + if (!app.storeReady || this.#loading) { 105 105 return html` 106 106 <ui-spinner></ui-spinner> 107 107 `
+2 -4
www/routes/main.ts
··· 30 30 } 31 31 32 32 #renderFirstLoad() { 33 - const isFirstLoad = app.storeReady && app.state.flags.isFirstLoad 33 + const isFirstLoad = app.storeReady && app.flags?.isFirstLoad 34 34 if (!isFirstLoad) return null 35 35 const dismiss = async () => { 36 - app.state.flags.isFirstLoad = false 37 - await app.persist() 38 - app.notify() 36 + await app.updateFlags({ isFirstLoad: false }) 39 37 } 40 38 return html` 41 39 <ui-dialog ?open="${isFirstLoad}" @dismiss="${dismiss}">
+3 -9
www/routes/search.ts
··· 77 77 } 78 78 79 79 #addToHistory(subjectId: string) { 80 - const history = app.state.searchHistory ?? [] 81 - app.state.searchHistory = [ 82 - subjectId, 83 - ...history.filter((id) => id !== subjectId), 84 - ].slice(0, 20) 85 - app.persist() 80 + app.addSearchHistory(subjectId) 86 81 } 87 82 88 83 #clearHistory() { 89 - app.state.searchHistory = [] 90 - app.persist() 84 + app.clearSearchHistory() 91 85 } 92 86 93 87 override firstUpdated() { ··· 114 108 115 109 override render() { 116 110 const isSearching = !!this.#text 117 - const historyIds = app.state.searchHistory ?? [] 111 + const historyIds = app.searchHistory 118 112 const historySubjects = !isSearching 119 113 ? historyIds 120 114 .map((id) => subjects.state.byId[id])
+53 -43
www/routes/settings.ts
··· 1 1 import { html, LitElement, TemplateResult } from 'lit' 2 2 import getString from '$/utils/get_string.ts' 3 - import app, { 4 - AppState, 5 - exportState, 6 - importState, 7 - resetState, 8 - } from '$/models/app.ts' 3 + import app, { exportState, importState, resetState } from '$/models/app.ts' 9 4 import { subjects } from '$/models/subjects.ts' 10 5 import { CardSortMethod } from '@flashcard/core' 11 6 7 + interface ImportedData { 8 + settings?: { locale?: string } 9 + assignments?: Record< 10 + string, 11 + Record<string, { 12 + subjectId: string 13 + unlockedAt?: number 14 + }> 15 + > 16 + userLevels?: Record<string, number> 17 + } 18 + 12 19 type NumInputKey = 13 20 | 'learnLimit' 14 21 | 'learnSessionSize' ··· 16 23 | 'reviewSessionSize' 17 24 18 25 export class SettingsRoute extends LitElement { 19 - #importProgress: AppState | undefined = undefined 26 + #importProgress: ImportedData | undefined = undefined 20 27 #importProgressName = '' 21 28 #syncLinkUrl = '' 22 29 #isSyncing = false ··· 91 98 type="number" 92 99 max="999" 93 100 min="0" 94 - .value="${String(app.state.settings[key] ?? 0)}" 101 + .value="${String(app.settings?.[key] ?? 0)}" 95 102 @change="${async (e: InputEvent) => { 96 - app.state.settings[key] = Number( 97 - (e.target as HTMLInputElement).value, 98 - ) 99 - await app.persist() 100 - app.notify() 103 + await app.updateSettings({ 104 + [key]: Number( 105 + (e.target as HTMLInputElement).value, 106 + ), 107 + }) 101 108 }}" 102 109 /> 103 110 </div> ··· 105 112 } 106 113 107 114 #renderCardSortSelect(): TemplateResult { 115 + const settings = app.settings 108 116 const getCurrentValue = () => { 109 - if (app.state.settings.cardSortMethod === CardSortMethod.Sequential) { 110 - if (!app.state.settings.cardSortOrder) { 111 - app.state.settings.cardSortOrder = ['readings', 'meanings'] 112 - } 113 - return app.state.settings.cardSortOrder[0] === 'meanings' 117 + if (settings?.cardSortMethod === CardSortMethod.Sequential) { 118 + return settings.cardSortOrder?.[0] === 'meanings' 114 119 ? 'meaning_first' 115 120 : 'reading_first' 116 121 } else { 117 - return app.state.settings.cardSortMethod?.toLowerCase() ?? 'paired' 122 + return settings?.cardSortMethod?.toLowerCase() ?? 'paired' 118 123 } 119 124 } 120 125 ··· 131 136 @change="${async (e: InputEvent) => { 132 137 const value = (e.target as HTMLSelectElement).value 133 138 if (value === 'paired') { 134 - app.state.settings.cardSortMethod = CardSortMethod.Paired 135 - app.state.settings.cardSortOrder = ['readings', 'meanings'] 139 + await app.updateSettings({ 140 + cardSortMethod: CardSortMethod.Paired, 141 + cardSortOrder: ['readings', 'meanings'], 142 + }) 136 143 } else if (value === 'random') { 137 - app.state.settings.cardSortMethod = CardSortMethod.Random 138 - app.state.settings.cardSortOrder = null 144 + await app.updateSettings({ 145 + cardSortMethod: CardSortMethod.Random, 146 + cardSortOrder: null, 147 + }) 139 148 } else if (value === 'meaning_first') { 140 - app.state.settings.cardSortMethod = CardSortMethod.Sequential 141 - app.state.settings.cardSortOrder = ['meanings', 'readings'] 149 + await app.updateSettings({ 150 + cardSortMethod: CardSortMethod.Sequential, 151 + cardSortOrder: ['meanings', 'readings'], 152 + }) 142 153 } else if (value === 'reading_first') { 143 - app.state.settings.cardSortMethod = CardSortMethod.Sequential 144 - app.state.settings.cardSortOrder = ['readings', 'meanings'] 154 + await app.updateSettings({ 155 + cardSortMethod: CardSortMethod.Sequential, 156 + cardSortOrder: ['readings', 'meanings'], 157 + }) 145 158 } 146 - await app.persist() 147 - app.notify() 148 159 }}" 149 160 > 150 161 <option value="paired">${getString('paired')}</option> ··· 188 199 return Number(b.unlockedAt) - Number(a.unlockedAt) 189 200 }) 190 201 .slice(0, 20) 191 - .map((assignment) => { 202 + .map((assignment: { subjectId: string; unlockedAt?: number }) => { 192 203 const subject = subjects.state.byId[assignment.subjectId] 193 204 const chars = subject?.data?.character 194 205 return html` ··· 262 273 name="playAudio" 263 274 type="checkbox" 264 275 style="height: 2.5em; width: 2.5em;" 265 - .checked="${!!app.state.settings.playAudio}" 276 + .checked="${!!app.settings?.playAudio}" 266 277 @change="${async (e: InputEvent) => { 267 - app.state.settings.playAudio = 268 - (e.target as HTMLInputElement).checked 269 - await app.persist() 270 - app.notify() 278 + await app.updateSettings({ 279 + playAudio: (e.target as HTMLInputElement).checked, 280 + }) 271 281 }}" 272 282 /> 273 283 </div> ··· 309 319 <button 310 320 @click="${async () => { 311 321 const { path, content } = await importState() 312 - this.#importProgress = content 322 + this.#importProgress = content as ImportedData 313 323 const splitName = path.split('/') 314 324 this.#importProgressName = splitName[splitName.length - 1] 315 325 this.requestUpdate() ··· 340 350 <div class="full-button"> 341 351 <button 342 352 @click="${async () => { 343 - app.state.flags.isFirstLoad = true 344 - app.state.flags.isFirstPinyin = true 345 - app.state.flags.isFirstPinyinVocab = true 346 - app.state.flags.isFirstZhuyin = true 347 - app.state.flags.isFirstHiragana = true 348 - await app.persist() 349 - app.notify() 353 + await app.updateFlags({ 354 + isFirstLoad: true, 355 + isFirstPinyin: true, 356 + isFirstPinyinVocab: true, 357 + isFirstZhuyin: true, 358 + isFirstHiragana: true, 359 + }) 350 360 }}" 351 361 > 352 362 ${getString('reset_help_dialogs')}
+4 -6
www/routes/settings/assignments.ts
··· 35 35 if (!subject) continue 36 36 37 37 if (currAssignment) { 38 - app.state.assignments[app.locale][subject.id] = { 38 + await app.saveAssignment({ 39 39 ...currAssignment, 40 40 markedCompleted: true, 41 - } 41 + }) 42 42 } else { 43 43 const now = new Date() 44 - app.state.assignments[app.locale][subject.id] = { 44 + await app.saveAssignment({ 45 45 ...scheduler.add(subject) as Assignment, 46 46 availableAt: now, 47 47 markedCompleted: true, ··· 49 49 subjectId: subject.id, 50 50 startedAt: now, 51 51 unlockedAt: now, 52 - } 52 + }) 53 53 } 54 54 } 55 - await app.persist() 56 - app.notify() 57 55 this.#selected = {} 58 56 this.requestUpdate() 59 57 }
+2 -4
www/routes/settings/custom-sets.ts
··· 63 63 64 64 async #onDelete(id: string) { 65 65 await deleteCustomSet(id) 66 - if (app.state.settings.locale === id) { 67 - app.state.settings.locale = Locale.zh_CN as string 68 - app.persist() 69 - app.notify() 66 + if (app.settings?.locale === id) { 67 + await app.updateSettings({ locale: Locale.zh_CN }) 70 68 } 71 69 globalThis.dispatchEvent(new Event('hanzi-custom-sets-changed')) 72 70 this.requestUpdate()
+1 -1
www/routes/settings/downloads.ts
··· 206 206 </div> 207 207 </div> 208 208 209 - <h4>${getString(app.state.settings.locale)}</h4> 209 + <h4>${getString(app.settings?.locale ?? 'zh_CN')}</h4> 210 210 211 211 ${Array.from({ length: 54 }, (_, i) => this.#renderLevel(i + 1))} 212 212
+21 -24
www/routes/study.ts
··· 71 71 // by card type only). Paired would re-sort by subject ID and lose it. 72 72 deck.batch((state) => { 73 73 state.cardSortMethod = CardSortMethod.Sequential 74 - state.cardSortOrder = app.state.settings.cardSortOrder ?? 74 + state.cardSortOrder = app.settings?.cardSortOrder ?? 75 75 ['readings', 'meanings'] 76 76 }) 77 77 } ··· 97 97 98 98 const isPending = deck.state.currCardState === Pending 99 99 deck.submit(answer) 100 - app.state.assignments[app.locale] = deck.state.assignments as Record< 101 - string, 102 - Assignment 103 - > 104 - await app.persist() 100 + for (const assignment of Object.values(deck.state.assignments)) { 101 + await app.saveAssignment({ ...assignment, srsId: 1 } as Assignment) 102 + } 105 103 await updateStreak() 106 104 107 105 const answerInputEl = this.querySelector('h-answer-input') as ··· 122 120 answerInputEl?.setDisplayed(displayed) 123 121 124 122 const audioURL = this.#currSubject?.data.audios?.[0]?.url 125 - if (audioURL && app.state.settings.playAudio) playAudio(audioURL) 123 + if (audioURL && app.settings?.playAudio) playAudio(audioURL) 126 124 } else { 127 125 answerInputEl?.clear() 128 126 } 129 127 130 - app.notify() 128 + this.requestUpdate() 131 129 this.requestUpdate() 132 130 } 133 131 ··· 156 154 157 155 ` 158 156 159 - if (t === Pinyin && app.state.flags.isFirstPinyin) { 157 + if (t === Pinyin && app.flags?.isFirstPinyin) { 160 158 isOpen = true 161 159 dismiss = async () => { 162 - app.state.flags.isFirstPinyin = false 163 - await app.persist() 164 - app.notify() 160 + await app.updateFlags({ isFirstPinyin: false }) 165 161 } 166 162 content = html` 167 163 <h1>${getString('pinyin_help_title')}</h1> ··· 197 193 </table> 198 194 <p>${getString('pinyin_help_u')}</p> 199 195 ` 200 - } else if (t === Zhuyin && app.state.flags.isFirstZhuyin) { 196 + } else if (t === Zhuyin && app.flags?.isFirstZhuyin) { 201 197 isOpen = true 202 198 dismiss = async () => { 203 - app.state.flags.isFirstZhuyin = false 204 - await app.persist() 205 - app.notify() 199 + await app.updateFlags({ isFirstZhuyin: false }) 206 200 } 207 201 content = html` 208 202 <h1>${getString('zhuyin_help_title')}</h1> ··· 211 205 <a href="#!/games/zhuyin">${getString('zhuyin_help_practice')}</a> 212 206 </p> 213 207 ` 214 - } else if (t === Hiragana && app.state.flags.isFirstHiragana) { 208 + } else if (t === Hiragana && app.flags?.isFirstHiragana) { 215 209 isOpen = true 216 210 dismiss = async () => { 217 - app.state.flags.isFirstHiragana = false 218 - await app.persist() 219 - app.notify() 211 + await app.updateFlags({ isFirstHiragana: false }) 220 212 } 221 213 content = html` 222 214 <h1>${getString('hiragana_help_title')}</h1> ··· 387 379 subject?.data.readings[0]?.value ?? '') 388 380 this.#isEditing = false 389 381 deck.submit(answer) 390 - app.state.assignments[app.locale] = deck.state 391 - .assignments as Record<string, Assignment> 392 - await app.persist() 393 - app.notify() 382 + for ( 383 + const assignment of Object.values( 384 + deck.state.assignments, 385 + ) 386 + ) { 387 + await app.saveAssignment( 388 + { ...assignment, srsId: 1 } as Assignment, 389 + ) 390 + } 394 391 this.requestUpdate() 395 392 }}">${getString('done')}</button> 396 393 `
+10 -8
www/utils/streak.ts
··· 10 10 */ 11 11 export async function updateStreak(): Promise<void> { 12 12 const today = toDateStr(new Date()) 13 - const stats = app.state.stats 14 - if (stats.lastStudiedDate === today) return 13 + const stats = app.stats 14 + if (stats?.lastStudiedDate === today) return 15 15 16 16 const yesterday = toDateStr(new Date(Date.now() - 864e5)) 17 - const prev = stats.currStreak ?? 0 17 + const prev = stats?.currStreak ?? 0 18 18 19 - stats.currStreak = stats.lastStudiedDate === yesterday ? prev + 1 : 1 20 - stats.longestStreak = Math.max(stats.longestStreak ?? 0, stats.currStreak) 21 - stats.lastStudiedDate = today 19 + const newCurrStreak = stats?.lastStudiedDate === yesterday ? prev + 1 : 1 20 + const newLongestStreak = Math.max(stats?.longestStreak ?? 0, newCurrStreak) 22 21 23 - await app.persist() 24 - app.notify() 22 + await app.updateStats({ 23 + currStreak: newCurrStreak, 24 + longestStreak: newLongestStreak, 25 + lastStudiedDate: today, 26 + }) 25 27 }
+2 -2
www/worker.ts
··· 10 10 init([ 11 11 withPrecache([ 12 12 '/', 13 - "https://bpev.me/civility.min.css", 14 - "https://bpev.me/utilities.min.css", 13 + 'https://bpev.me/civility.min.css', 14 + 'https://bpev.me/utilities.min.css', 15 15 '/dist/index.js', 16 16 '/dist/icons/128x128.png', 17 17 '/dist/icons/192x192.png',