-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSQL_Dojo_Publications.html
More file actions
1732 lines (1647 loc) · 359 KB
/
Copy pathSQL_Dojo_Publications.html
File metadata and controls
1732 lines (1647 loc) · 359 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>SQL Dojo — Publications</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/codemirror.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/theme/dracula.min.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
:root{
/* Premium Obsidian Dark Mode */
--bg:#0a0a0d; --bg-alt:#0e0f13; --panel:#131419; --panel-2:#1a1b21;
--border:rgba(255,255,255,.07); --border-strong:rgba(255,255,255,.14);
--text:#f2f2f5; --text-dim:#a3a3ad; --text-faint:#6e6e78;
--accent:#7477d8; --accent-soft:rgba(116,119,216,.16); --accent-2:#e0a458;
--good:#22c55e; --bad:#ef4444; --warn:#e0a458;
--radius:10px;
--shadow-sm:0 1px 2px rgba(0,0,0,.5);
--shadow:0 6px 20px -6px rgba(0,0,0,.6), 0 1px 2px rgba(0,0,0,.4);
--font-mono:'SF Mono', 'Fira Code', 'JetBrains Mono', ui-monospace, Menlo, Monaco, Consolas, monospace;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto, sans-serif;
}
*{box-sizing:border-box;}
html,body{margin:0;padding:0;background:var(--bg);color:var(--text);}
body{min-height:100vh;}
#app{display:flex;flex-direction:column;min-height:100vh;}
/* ---------- header ---------- */
header{
display:flex;align-items:center;justify-content:space-between;
padding:16px 28px;background:var(--bg-alt);
border-bottom:1px solid var(--border);flex-wrap:wrap;gap:10px;
}
header h1{font-size:19px;margin:0;display:flex;align-items:center;gap:10px;letter-spacing:.2px;font-weight:600;color:var(--text);}
header h1 .logo{font-size:22px;}
header h1 small{font-weight:400;color:var(--text-faint);font-size:12px;display:block;margin-top:2px;letter-spacing:.1px;}
.hud{display:flex;gap:10px;align-items:center;flex-wrap:wrap;}
.hud .chip{
background:var(--panel-2);border:1px solid var(--border);border-radius:7px;
padding:6px 13px;font-size:13px;color:var(--text-dim);display:flex;align-items:center;gap:6px;
}
.hud .chip b{color:var(--text);font-weight:600;}
.hud .chip.streak{color:#ffb020;border-color:#ffb02040;}
button, select, input[type=text], input[type=number]{
font-family:inherit;font-size:14px;
}
button{
cursor:pointer;border:1px solid transparent;border-radius:8px;padding:10px 18px;font-weight:600;
background:var(--accent);color:#f5f5ff;box-shadow:var(--shadow-sm);
transition:filter .12s ease, transform .12s ease, box-shadow .12s ease;
}
button:hover{filter:brightness(1.12);transform:translateY(-1px);box-shadow:var(--shadow);}
button:active{filter:brightness(.95);transform:translateY(0);}
button.secondary{background:var(--panel-2);color:var(--text);border:1px solid var(--border);}
button.secondary:hover{border-color:var(--border-strong);}
button.ghost{background:transparent;color:var(--text-dim);border:1px solid var(--border);box-shadow:none;}
button.ghost:hover{color:var(--text);border-color:var(--border-strong);box-shadow:none;transform:none;}
button.good{background:var(--good);color:#08170d;}
button.small{padding:6px 12px;font-size:12.5px;border-radius:6px;}
button:disabled{opacity:.4;cursor:not-allowed;}
/* ---------- layout ---------- */
.layout{display:flex;flex:1;min-height:0;}
aside#sidebar{
width:280px;flex-shrink:0;background:var(--bg-alt);border-right:1px solid var(--border);
padding:20px 14px;overflow-y:auto;
}
aside#sidebar h2{font-size:11px;text-transform:uppercase;letter-spacing:.1em;color:var(--text-faint);margin:4px 8px 12px;font-weight:700;}
.schema-filter{
width:100%;padding:8px 11px;margin-bottom:12px;background:var(--panel);border:1px solid var(--border);
border-radius:7px;color:var(--text);font-size:12.5px;
}
.schema-filter::placeholder{color:var(--text-faint);}
.table-card{background:transparent;border:none;border-radius:6px;margin-bottom:2px;overflow:hidden;}
.table-head{
display:flex;align-items:center;justify-content:space-between;padding:7px 9px;cursor:pointer;user-select:none;
border-radius:6px;transition:background .12s ease;
}
.table-head:hover{background:var(--panel-2);}
.table-card.open > .table-head{background:var(--accent-soft);}
.table-card.open > .table-head .tname{color:var(--text);}
.table-head .tname{font-family:var(--font-mono);font-size:13px;color:var(--text);font-weight:500;}
.table-head .tname::before{content:"▤ ";color:var(--text-faint);}
.table-head .arrow{color:var(--text-faint);font-size:10px;transition:transform .15s;}
.table-card.open .arrow{transform:rotate(90deg);}
.table-card.open .table-head .arrow{color:var(--accent);}
.table-desc{padding:0 9px 7px 25px;font-size:11px;color:var(--text-faint);}
.table-cols{display:none;padding:3px 9px 9px 25px;font-family:var(--font-mono);font-size:12px;border-left:1px solid var(--border);margin-left:13px;}
.table-card.open .table-cols{display:block;}
.col-row{display:flex;justify-content:space-between;padding:2.5px 0;color:var(--text-dim);}
.col-row .ctype{color:var(--text-faint);font-size:10.5px;}
.col-row.pk{color:var(--accent-2);}
.preview-btn{
margin:5px 9px 11px 25px;font-size:11px;padding:5px 9px;width:calc(100% - 34px);
}
/* ---------- main ---------- */
main{flex:1;min-width:0;overflow-y:auto;padding:32px;display:flex;justify-content:center;}
.screen{width:100%;max-width:900px;}
/* setup screen */
.setup-card{background:var(--panel);border:1px solid var(--border);border-radius:var(--radius);padding:32px;box-shadow:var(--shadow);}
.setup-card h2{margin-top:0;font-weight:600;letter-spacing:.1px;}
.field{margin-bottom:26px;}
.field label{display:block;font-size:13px;color:var(--text-dim);margin-bottom:9px;font-weight:600;}
.topic-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:9px;}
.topic-pill{
display:flex;align-items:center;gap:8px;padding:11px 13px;border-radius:10px;border:1px solid var(--border);
cursor:pointer;background:var(--panel-2);transition:.15s ease;
}
.topic-pill:hover{border-color:var(--border-strong);}
.topic-pill.active{border-color:var(--tc);background:color-mix(in srgb, var(--tc) 14%, var(--panel-2));box-shadow:var(--shadow-sm);}
.topic-pill .dot{width:10px;height:10px;border-radius:50%;background:var(--tc);flex-shrink:0;}
.topic-pill .tt{font-size:13px;color:var(--text);}
.topic-pill .tt small{display:block;color:var(--text-faint);font-size:10.5px;}
.row-inline{display:flex;gap:10px;flex-wrap:wrap;}
.count-btn{padding:9px 16px;border-radius:9px;border:1px solid var(--border);background:var(--panel-2);color:var(--text-dim);transition:.15s ease;}
.count-btn:hover{border-color:var(--border-strong);color:var(--text);}
.count-btn.active{border-color:var(--accent);background:var(--accent-soft);color:var(--text);}
.start-row{display:flex;justify-content:center;gap:10px;margin-top:10px;}
.mix-note{background:rgba(239,68,68,.08);border:1px solid rgba(239,68,68,.25);border-radius:10px;padding:14px 16px;margin-top:12px;font-size:12.5px;color:var(--text-dim);line-height:1.6;}
.mix-note b{color:#f87171;}
.setup-card + .setup-card{margin-top:22px;}
.freeplay-card{background:linear-gradient(135deg,rgba(116,119,216,.08),var(--panel) 60%);border-color:rgba(116,119,216,.25);}
.roundrobin-card{background:linear-gradient(135deg,rgba(16,185,129,.07),var(--panel) 60%);border-color:rgba(16,185,129,.25);}
/* lesson screen */
.lesson-card{background:var(--panel);border:1px solid var(--border);border-radius:var(--radius);padding:32px;margin-bottom:18px;box-shadow:var(--shadow);}
.lesson-card h2{margin-top:0;display:flex;align-items:center;gap:10px;font-weight:600;color:var(--accent);}
.lesson-intro{background:color-mix(in srgb, var(--tc,var(--accent)) 8%, var(--panel-2));border:1px solid color-mix(in srgb, var(--tc,var(--accent)) 30%, transparent);border-radius:12px;padding:18px 20px;margin-bottom:22px;font-size:14.5px;line-height:1.7;color:var(--text);}
.lesson-intro b{color:var(--tc,var(--accent));}
.worked-wrap{margin-bottom:24px;}
.worked-note{font-size:12.5px;color:var(--text-faint);margin-bottom:9px;}
.worked-table{width:100%;border-collapse:collapse;font-family:var(--font-mono);font-size:13px;background:rgba(0,0,0,.22);border:1px solid var(--border);border-radius:10px;overflow:hidden;}
.worked-table th{background:rgba(0,0,0,.28);text-align:left;padding:8px 13px;color:var(--text-dim);font-weight:600;font-size:11.5px;text-transform:uppercase;letter-spacing:.03em;}
.worked-table td{padding:8px 13px;border-top:1px solid var(--border);color:var(--text);}
.worked-table td.hl{background:color-mix(in srgb, var(--tc,var(--accent)) 18%, transparent);color:var(--tc,var(--accent));font-weight:700;}
.lesson-step{border-left:2px solid var(--tc,var(--accent));padding:4px 0 4px 18px;margin-bottom:20px;position:relative;}
.lesson-step h4{margin:0 0 7px;font-size:15px;font-weight:600;color:var(--tc,var(--accent));display:flex;align-items:center;gap:9px;}
.lesson-step .step-num{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;border-radius:50%;background:var(--tc,var(--accent));color:#0a0a0d;font-size:11.5px;font-weight:800;flex-shrink:0;}
.lesson-step p{margin:0 0 9px;font-size:14px;line-height:1.65;color:var(--text-dim);}
.lesson-step .lex{background:rgba(0,0,0,.22);border:1px solid var(--border);border-radius:8px;padding:10px 13px;font-family:var(--font-mono);font-size:12.5px;color:var(--text);white-space:pre-wrap;}
.lex .tok-kw{color:var(--accent);font-weight:700;}
.lex .tok-str{color:#9dc76e;}
.lex .tok-num{color:#c9a0dc;}
.lex .tok-id{color:var(--text);}
.merk-box{background:color-mix(in srgb, var(--tc,var(--accent)) 14%, transparent);border-left:3px solid var(--tc,var(--accent));border-radius:0 8px 8px 0;padding:8px 13px;margin:2px 0 11px;font-weight:700;font-size:13.5px;color:var(--text);}
.detail-heading{font-size:12px;text-transform:uppercase;letter-spacing:.05em;color:var(--text-faint);margin:24px 0 13px;padding-top:16px;border-top:1px dashed var(--border);}
.lesson-step.detail{border-left:2px dashed color-mix(in srgb, var(--tc,var(--accent)) 55%, var(--border));opacity:.92;}
.lesson-step.detail h4{font-size:13.5px;}
.lesson-step.detail .step-num{background:transparent;border:1.5px solid var(--tc,var(--accent));color:var(--tc,var(--accent));}
.lesson-condensed{display:flex;align-items:flex-start;gap:12px;padding:15px 4px;border-bottom:1px solid var(--border);}
.lesson-condensed:last-child{border-bottom:none;}
.lesson-condensed b{color:var(--tc,var(--accent));}
.lesson-condensed .lc-icon{font-size:22px;width:34px;height:34px;flex-shrink:0;border-radius:9px;display:flex;align-items:center;justify-content:center;background:color-mix(in srgb, var(--tc) 16%, var(--panel-2));}
.lesson-condensed .lex{margin-top:9px;background:rgba(0,0,0,.22);border:1px solid var(--border);border-radius:8px;padding:9px 12px;font-family:var(--font-mono);font-size:12px;color:var(--accent-2);}
/* inline code chips inside prose */
.lesson-intro code, .lesson-step code, .ns-note code{background:color-mix(in srgb, var(--accent) 16%, transparent);color:var(--accent);font-family:var(--font-mono);padding:1px 6px;border-radius:5px;font-size:.92em;}
.ns-intro-title{font-size:15px;font-weight:700;color:var(--tc,var(--accent));margin-bottom:8px;}
/* fixed 4-part lesson format: Was macht der Befehl? / Einfach erklärt / Bauanleitung / Beispiel */
.ns-block{margin-bottom:14px;}
.ns-block:last-child{margin-bottom:0;}
.ns-label{font-size:11px;text-transform:uppercase;letter-spacing:.06em;color:var(--tc,var(--accent));font-weight:700;margin-bottom:6px;}
.ns-was{font-size:14.5px;font-weight:600;color:var(--text);margin:0;line-height:1.55;}
.ns-tip{margin-top:8px;background:color-mix(in srgb, var(--tc,var(--accent)) 12%, transparent);border:1px solid color-mix(in srgb, var(--tc,var(--accent)) 30%, transparent);border-radius:8px;padding:9px 12px;font-size:12.5px;color:var(--text-dim);line-height:1.5;}
.ns-sublabel{font-size:12px;color:var(--text-faint);margin:10px 0 5px;font-weight:600;}
.ns-sublabel:first-child{margin-top:0;}
.ns-note{font-size:13px;color:var(--text-faint);margin:6px 0 0;font-style:italic;}
/* hints */
.hint-row{display:flex;gap:10px;margin-bottom:13px;flex-wrap:wrap;}
.hint-box{background:rgba(116,119,216,.08);border:1px solid rgba(116,119,216,.25);border-radius:10px;padding:13px 15px;margin-bottom:13px;font-size:13.5px;color:var(--text-dim);}
.hint-box .hb-tier{color:#9a9cec;font-weight:700;font-size:11.5px;text-transform:uppercase;letter-spacing:.05em;margin-bottom:5px;}
.hint-box code{display:block;margin-top:7px;background:rgba(0,0,0,.3);border:1px solid var(--border);padding:9px 11px;border-radius:7px;font-family:var(--font-mono);color:#9ff5c6;white-space:pre-wrap;}
.alt-box{margin-top:13px;background:rgba(20,184,166,.07);border:1px solid rgba(20,184,166,.25);border-radius:11px;padding:13px 15px;font-size:13px;color:var(--text-dim);}
.alt-box .ab-title{color:#5eead4;font-weight:700;margin-bottom:7px;}
.alt-box code{display:block;margin:7px 0;background:rgba(0,0,0,.3);border:1px solid var(--border);padding:9px 11px;border-radius:7px;font-family:var(--font-mono);color:#9ff5c6;white-space:pre-wrap;font-size:12px;}
/* explorer-style data browser */
.modal-box.wide{min-width:min(900px,90vw);}
.modal-header{display:flex;justify-content:space-between;align-items:center;gap:14px;margin-bottom:10px;flex-wrap:wrap;}
.search-box{padding:8px 12px;border-radius:8px;border:1px solid var(--border);background:var(--panel-2);color:var(--text);min-width:200px;}
.refcard{background:var(--panel);border:1px solid var(--border);border-radius:11px;margin-bottom:15px;overflow:hidden;box-shadow:var(--shadow-sm);}
.refcard summary{padding:11px 13px;cursor:pointer;font-size:12.5px;color:var(--text-dim);font-weight:600;list-style:none;display:flex;justify-content:space-between;align-items:center;}
.refcard summary::-webkit-details-marker{display:none;}
.refcard .refbody{padding:0 13px 13px;font-size:11.5px;color:var(--text-faint);}
.refcard table{width:100%;border-collapse:collapse;margin-top:7px;}
.refcard td{padding:4px 5px;border-bottom:1px solid var(--border);}
.refcard td.k{color:var(--accent-2);font-family:var(--font-mono);}
/* question screen */
.q-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:16px;flex-wrap:wrap;gap:8px;}
.topic-badge{
display:inline-flex;align-items:center;gap:7px;padding:5px 12px;border-radius:7px;font-size:12.5px;font-weight:700;
background:color-mix(in srgb, var(--tc) 18%, transparent);color:var(--tc);border:1px solid color-mix(in srgb, var(--tc) 40%, transparent);
}
.stars{color:#ffd166;font-size:13px;letter-spacing:1px;}
.progress-track{flex:1;height:6px;background:var(--panel-2);border-radius:99px;margin:0 14px;overflow:hidden;min-width:100px;}
.progress-fill{height:100%;background:linear-gradient(90deg,var(--accent),var(--accent-2));border-radius:99px;transition:width .3s;}
.q-card{background:var(--panel);border:1px solid var(--border);border-radius:var(--radius);padding:24px 26px;margin-bottom:18px;box-shadow:var(--shadow);}
.q-card p{margin:0;font-size:15.5px;line-height:1.6;color:var(--text);}
.editor-wrap{background:#101116;border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;margin-bottom:14px;box-shadow:var(--shadow);}
.editor-toolbar{
display:flex;justify-content:space-between;align-items:center;padding:9px 14px;background:#16171d;
border-bottom:1px solid var(--border);font-size:11.5px;color:var(--text-faint);
}
.editor-toolbar .kbd{background:var(--panel-2);border:1px solid var(--border);padding:2px 7px;border-radius:5px;font-family:var(--font-mono);color:var(--text);}
.CodeMirror{height:150px;font-family:var(--font-mono);font-size:14px;line-height:1.5;}
/* ---- MySQL-Workbench-artiges Syntax-Highlighting (auf dracula-Basis umgefärbt) ---- */
.cm-s-dracula.CodeMirror{background:#101116 !important;color:#f2f2f5 !important;}
.cm-s-dracula .CodeMirror-gutters{background:#101116 !important;border-right:1px solid var(--border) !important;}
.cm-s-dracula .CodeMirror-linenumber{color:#4d4f5a !important;}
.cm-s-dracula .cm-keyword{color:#e0a458 !important;font-weight:600;}
.cm-s-dracula .cm-atom{color:#e0a458 !important;}
.cm-s-dracula .cm-builtin{color:#6fa8dc !important;}
.cm-s-dracula .cm-def{color:#f2f2f5 !important;}
.cm-s-dracula .cm-variable, .cm-s-dracula .cm-variable-2, .cm-s-dracula .cm-property{color:#f2f2f5 !important;}
.cm-s-dracula .cm-string{color:#9dc76e !important;}
.cm-s-dracula .cm-number{color:#c9a0dc !important;}
.cm-s-dracula .cm-comment{color:#6fa8dc !important;font-style:italic;}
.cm-s-dracula .cm-operator{color:#f2f2f5 !important;}
.cm-s-dracula .CodeMirror-selected{background:rgba(116,119,216,.28) !important;}
.cm-s-dracula .CodeMirror-cursor{border-left:1.5px solid #f2f2f5 !important;}
.cm-s-dracula .CodeMirror-matchingbracket{color:#e0a458 !important;background:rgba(116,119,216,.22);}
.run-row{display:flex;justify-content:center;align-items:center;margin-bottom:18px;}
.topic-refcard{margin-bottom:15px;}
.topic-refcard summary{font-weight:600;color:var(--text);}
.topic-syntax{background:rgba(0,0,0,.28);border:1px solid var(--border);border-radius:8px;padding:11px 13px;font-family:var(--font-mono);font-size:12.5px;color:var(--accent-2);white-space:pre-wrap;margin-bottom:7px;line-height:1.5;}
.results-panel{background:var(--panel);border:1px solid var(--border);border-radius:var(--radius);padding:0;margin-bottom:18px;overflow:hidden;min-height:60px;box-shadow:var(--shadow);}
.results-panel .rp-head{padding:11px 17px;font-size:12px;color:var(--text-faint);border-bottom:1px solid var(--border);}
.results-panel .rp-body{overflow:auto;max-height:260px;}
table.result-table{border-collapse:collapse;width:100%;font-size:13px;}
table.result-table th{
position:sticky;top:0;background:var(--panel-2);text-align:left;padding:9px 13px;color:var(--accent-2);
font-family:var(--font-mono);border-bottom:1px solid var(--border);white-space:nowrap;
}
table.result-table td{padding:8px 13px;border-bottom:1px solid var(--border);color:var(--text-dim);white-space:nowrap;font-family:var(--font-mono);}
table.result-table tr:hover td{background:var(--panel-2);}
.empty-note, .error-note{padding:17px;font-size:13.5px;color:var(--text-faint);}
.error-note{color:#ff8080;font-family:var(--font-mono);white-space:pre-wrap;}
/* mini-dashboard under multi-row aggregate results */
.mini-chart{border-top:1px solid var(--border);padding:15px 17px;}
.mini-chart .mc-head{font-size:11.5px;color:var(--text-faint);text-transform:uppercase;letter-spacing:.06em;margin-bottom:11px;font-weight:700;}
.chart-row{display:flex;align-items:center;gap:10px;margin-bottom:8px;}
.chart-row .chart-label{width:150px;flex-shrink:0;font-size:12px;color:var(--text-dim);font-family:var(--font-mono);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.chart-row .chart-track{flex:1;height:14px;background:var(--panel-2);border-radius:4px;overflow:hidden;}
.chart-row .chart-fill{height:100%;background:var(--accent);border-radius:4px;}
.chart-row .chart-val{width:60px;text-align:right;font-size:12px;color:var(--text);font-family:var(--font-mono);flex-shrink:0;}
.feedback{border-radius:var(--radius);padding:19px 21px;margin-bottom:18px;border:1px solid;box-shadow:var(--shadow);}
.feedback.ok{background:rgba(34,197,94,.08);border-color:rgba(34,197,94,.3);}
.feedback.bad{background:rgba(239,68,68,.08);border-color:rgba(239,68,68,.3);}
.feedback h3{margin:0 0 9px;font-size:16px;font-weight:600;display:flex;align-items:center;gap:8px;}
.feedback.ok h3{color:#4ade80;}
.feedback.bad h3{color:#fb7185;}
.feedback .body{font-size:14px;line-height:1.6;color:var(--text-dim);}
.feedback .example-box{
margin-top:11px;background:rgba(0,0,0,.22);border-radius:10px;padding:13px 15px;font-size:13px;color:var(--text-dim);
border-left:3px solid var(--accent);
}
.feedback .actions{display:flex;gap:10px;margin-top:15px;flex-wrap:wrap;}
.solution-box{margin-top:13px;background:rgba(0,0,0,.35);border-radius:10px;padding:13px 15px;font-family:var(--font-mono);font-size:12.5px;color:#9ff5c6;white-space:pre-wrap;border:1px solid rgba(34,197,94,.25);}
/* summary screen */
.summary-card{background:var(--panel);border:1px solid var(--border);border-radius:var(--radius);padding:36px;text-align:center;box-shadow:var(--shadow);}
.summary-card .big-score{font-size:48px;font-weight:800;background:linear-gradient(90deg,var(--accent),var(--accent-2));-webkit-background-clip:text;background-clip:text;color:transparent;}
.summary-card .sub{color:var(--text-dim);margin-top:5px;}
.crown{font-size:34px;}
.topic-bars{margin-top:28px;text-align:left;}
.tb-row{display:flex;align-items:center;gap:10px;margin-bottom:11px;}
.tb-row .tb-label{width:200px;font-size:12.5px;color:var(--text-dim);flex-shrink:0;}
.tb-row .tb-track{flex:1;height:9px;background:var(--panel-2);border-radius:99px;overflow:hidden;}
.tb-row .tb-fill{height:100%;border-radius:99px;}
.tb-row .tb-pct{width:40px;text-align:right;font-size:12px;color:var(--text-faint);}
.confetti{position:fixed;inset:0;pointer-events:none;overflow:hidden;z-index:999;}
.confetti span{
position:absolute;top:-20px;width:8px;height:14px;border-radius:2px;
animation:fall 2.6s linear forwards;
}
@keyframes fall{to{transform:translateY(110vh) rotate(360deg);opacity:.3;}}
/* preview modal */
.modal-backdrop{position:fixed;inset:0;background:rgba(0,0,0,.72);display:flex;align-items:center;justify-content:center;z-index:500;}
.modal-box{background:var(--panel);border:1px solid var(--border);border-radius:var(--radius);max-width:90vw;max-height:80vh;overflow:auto;padding:20px;box-shadow:var(--shadow);}
.modal-box h3{margin-top:0;font-family:var(--font-mono);color:var(--accent-2);}
.app-footer{text-align:center;padding:12px;font-size:11.5px;color:var(--text-faint);border-top:1px solid var(--border);background:var(--bg-alt);}
.app-footer a{color:var(--text-faint);}
.hidden{display:none !important;}
.text-faint{color:var(--text-faint);}
@media (max-width:800px){
aside#sidebar{display:none;}
}
</style>
</head>
<body>
<div id="app">
<header>
<h1><span class="logo">🐢</span>SQL Dojo <small>Publications-Datenbank · von Beginner zu Advanced</small></h1>
<div class="hud" id="hud"></div>
</header>
<div class="layout">
<aside id="sidebar">
<h2>Schema</h2>
<input class="schema-filter" id="schema-filter" placeholder="🔍 Tabellen filtern…" oninput="filterSchema(this.value)">
<div id="schema-tree"></div>
</aside>
<main>
<div class="screen" id="screen-setup"></div>
<div class="screen hidden" id="screen-lesson"></div>
<div class="screen hidden" id="screen-question"></div>
<div class="screen hidden" id="screen-summary"></div>
</main>
</div>
<footer class="app-footer">Gebaut von Andreas Kunz · <a href="https://github.com/Agentic-Content/sql-dojo" target="_blank" rel="noopener">GitHub</a></footer>
</div>
<div id="modal-root"></div>
<div id="confetti-root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/codemirror.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/mode/sql/sql.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.16/addon/edit/matchbrackets.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/sql.js/1.10.3/sql-wasm.js"></script>
<script>
/* =========================================================================
SQL DOJO — Lern-Tool für die Publications-Datenbank
========================================================================= */
const DB_B64 = "U1FMaXRlIGZvcm1hdCAzABAAAQEAQCAgAAAADAAAACMAAAAAAAAAAAAAAAsAAAAEAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAC5XSg0AAAALCZEAD0IOqQ3yDX4NGwySDBELgArwCmgJkQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIFUCwcXGRkBgwN0YWJsZXRpdGxlc3RpdGxlcwxDUkVBVEUgVEFCTEUgInRpdGxlcyIgKCJ0aXRsZV9pZCIgVEVYVCwgInRpdGxlIiBURVhULCAidHlwZSIgVEVYVCwgInB1Yl9pZCIgVEVYVCwgInByaWNlIiBOVU1FUklDLCAiYWR2YW5jZSIgTlVNRVJJQywgInJveWFsdHkiIElOVEVHRVIsICJ5dGRfc2FsZXMiIElOVEVHRVIsICJub3RlcyIgVEVYVCwgInB1YmRhdGUiIFRFWFQpgQUKBxcjIwGBUXRhYmxldGl0bGVhdXRob3J0aXRsZWF1dGhvcgtDUkVBVEUgVEFCTEUgInRpdGxlYXV0aG9yIiAoImF1X2lkIiBURVhULCAidGl0bGVfaWQiIFRFWFQsICJhdV9vcmQiIElOVEVHRVIsICJyb3lhbHR5cGVyIiBJTlRFR0VSKYENCQcXGRkBgXV0YWJsZXN0b3Jlc3N0b3JlcwpDUkVBVEUgVEFCTEUgInN0b3JlcyIgKCJzdG9yX2lkIiBURVhULCAic3Rvcl9uYW1lIiBURVhULCAic3Rvcl9hZGRyZXNzIiBURVhULCAiY2l0eSIgVEVYVCwgInN0YXRlIiBURVhULCAiemlwIiBURVhUKYEOCAcXFxcBgXt0YWJsZXNhbGVzc2FsZXMJQ1JFQVRFIFRBQkxFICJzYWxlcyIgKCJzdG9yX2lkIiBURVhULCAib3JkX251bSIgVEVYVCwgIm9yZF9kYXRlIiBURVhULCAicXR5IiBJTlRFR0VSLCAicGF5dGVybXMiIFRFWFQsICJ0aXRsZV9pZCIgVEVYVCl/BwcXHR0BgVF0YWJsZXJveXNjaGVkcm95c2NoZWQIQ1JFQVRFIFRBQkxFICJyb3lzY2hlZCIgKCJ0aXRsZV9pZCIgVEVYVCwgImxvcmFuZ2UiIElOVEVHRVIsICJoaXJhbmdlIiBJTlRFR0VSLCAicm95YWx0eSIgSU5URUdFUimBBgYHFyEhAYFXdGFibGVwdWJsaXNoZXJzcHVibGlzaGVycwdDUkVBVEUgVEFCTEUgInB1Ymxpc2hlcnMiICgicHViX2lkIiBURVhULCAicHViX25hbWUiIFRFWFQsICJjaXR5IiBURVhULCAic3RhdGUiIFRFWFQsICJjb3VudHJ5IiBURVhUKWEFBxcdHQGBFXRhYmxlcHViX2luZm9wdWJfaW5mbwZDUkVBVEUgVEFCTEUgInB1Yl9pbmZvIiAoInB1Yl9pZCIgVEVYVCwgImxvZ28iIEJMT0IsICJwcl9pbmZvIiBURVhUKXIEBxcVFQGBR3RhYmxlam9ic2pvYnMFQ1JFQVRFIFRBQkxFICJqb2JzIiAoImpvYl9pZCIgSU5URUdFUiwgImpvYl9kZXNjIiBURVhULCAibWluX2x2bCIgSU5URUdFUiwgIm1heF9sdmwiIElOVEVHRVIpgTQDBxcdHQGCO3RhYmxlZW1wbG95ZWVlbXBsb3llZQRDUkVBVEUgVEFCTEUgImVtcGxveWVlIiAoImVtcF9pZCIgVEVYVCwgImZuYW1lIiBURVhULCAibWluaXQiIFRFWFQsICJsbmFtZSIgVEVYVCwgImpvYl9pZCIgSU5URUdFUiwgImpvYl9sdmwiIElOVEVHRVIsICJwdWJfaWQiIFRFWFQsICJoaXJlX2RhdGUiIFRFWFQpgRYCBxcfHwGBe3RhYmxlZGlzY291bnRzZGlzY291bnRzA0NSRUFURSBUQUJMRSAiZGlzY291bnRzIiAoImRpc2NvdW50dHlwZSIgVEVYVCwgInN0b3JfaWQiIFRFWFQsICJsb3dxdHkiIElOVEVHRVIsICJoaWdocXR5IiBJTlRFR0VSLCAiZGlzY291bnQiIE5VTUVSSUMpgTsBBxcbGwGCTXRhYmxlYXV0aG9yc2F1dGhvcnMCQ1JFQVRFIFRBQkxFICJhdXRob3JzIiAoImF1X2lkIiBURVhULCAiYXVfbG5hbWUiIFRFWFQsICJhdV9mbmFtZSIgVEVYVCwgInBob25lIiBURVhULCAiYWRkcmVzcyIgVEVYVCwgImNpdHkiIFRFWFQsICJzdGF0ZSIgVEVYVCwgInppcCIgVEVYVCwgImNvbnRyYWN0IiBJTlRFR0VSKQ0AAAAXCNcAD7EPYg8WDsIOdQ4lDdYNjQ1FDO8Mlww+C+8LmgtRCwIKsgpmChMJxQl5CSkI1wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQFwojGRklKSkRFwk5OTgtNzItMzU2N1JpbmdlckFsYmVydDgwMSA4MjYtMDc1MjY3IFNldmVudGggQXYuU2FsdCBMYWtlIENpdHlVVDg0MTUyThYKIxkVJSkpERcJODk5LTQ2LTIwMzVSaW5nZXJBbm5lODAxIDgyNi0wNzUyNjcgU2V2ZW50aCBBdi5TYWx0IExha2UgQ2l0eVVUODQxNTJKFQojHRslIR8RFwg4OTMtNzItMTE1OE1jQmFkZGVuSGVhdGhlcjcwNyA0NDgtNDk4MjMwMSBQdXRuYW1WYWNhdmlsbGVDQTk1Njg4TBQKIxkZJSsfERcJODQ2LTkyLTcxODZIdW50ZXJTaGVyeWw0MTUgODM2LTcxMjgzNDEwIEJsb25kZSBTdC5QYWxvIEFsdG9DQTk0MzAxURMKIx0ZJTEfERcJODA3LTkxLTY2NTRQYW50ZWxleVN5bHZpYTMwMSA5NDYtODg1MzE5NTYgQXJsaW5ndG9uIFBsLlJvY2t2aWxsZU1EMjA4NTNKEgojGRclLRsRFwk3NTYtMzAtNzM5MUthcnNlbkxpdmlhNDE1IDUzNC05MjE5NTcyMCBNY0F1bGV5IFN0Lk9ha2xhbmRDQTk0NjA5ThEKIyEbJSkbERcJNzI0LTgwLTkzOTFNYWNGZWF0aGVyU3RlYXJuczQxNSAzNTQtNzEyODQ0IFVwbGFuZCBIdHMuT2FrbGFuZENBOTQ2MTJNEAojHRUlMRsRFwg3MjQtMDgtOTkzMVN0cmluZ2VyRGlyazQxNSA4NDMtMjk5MTU0MjAgVGVsZWdyYXBoIEF2Lk9ha2xhbmRDQTk0NjA5Rw8KIx0ZJScVERcJNzIyLTUxLTU0NTREZUZyYW5jZU1pY2hlbDIxOSA1NDctOTk4MjMgQmFsZGluZyBQbC5HYXJ5SU40NjQwM1MOCiMlFyUvHxEXCTcxMi00NS0xODY3ZGVsIENhc3RpbGxvSW5uZXM2MTUgOTk2LTgyNzUyMjg2IENyYW0gUGwuICM4NkFubiBBcmJvck1JNDgxMDVNDQojHRclJSURFwk2NzItNzEtMzI0OVlva29tb3RvQWtpa280MTUgOTM1LTQyMjgzIFNpbHZlciBDdC5XYWxudXQgQ3JlZWtDQTk0NTk1VwwKIykdJS0fERcJNjQ4LTkyLTE4NzJCbG90Y2hldC1IYWxsc1JlZ2luYWxkNTAzIDc0NS02NDAyNTUgSGlsbHNkYWxlIEJsLkNvcnZhbGxpc09SOTczMzBWCwojGSMlNR8RFwg1MjctNzItMzI0NkdyZWVuZU1vcm5pbmdzdGFyNjE1IDI5Ny0yNzIzMjIgR3JheWJhciBIb3VzZSBSZC5OYXNodmlsbGVUTjM3MjE1VAoKIx0dJSsnERcJNDg2LTI5LTE3ODZMb2Nrc2xleUNoYXJsZW5lNDE1IDU4NS00NjIwMTggQnJvYWR3YXkgQXYuU2FuIEZyYW5jaXNjb0NBOTQxMzBGCQojIRUlIRkRFwk0NzItMjctMjM0OUdyaW5nbGVzYnlCdXJ0NzA3IDkzOC02NDQ1UE8gQm94IDc5MkNvdmVsb0NBOTU0MjhHCAojFRMlKx8RFwk0MjctMTctMjMxOUR1bGxBbm40MTUgODM2LTcxMjgzNDEwIEJsb25kZSBTdC5QYWxvIEFsdG9DQTk0MzAxTQcKIxkbJS0dERcJNDA5LTU2LTcwMDhCZW5uZXRBYnJhaGFtNDE1IDY1OC05OTMyNjIyMyBCYXRlbWFuIFN0LkJlcmtlbGV5Q0E5NDcwNU4GCiMXGyUxHREXCDM0MS0yMi0xNzgyU21pdGhNZWFuZGVyOTEzIDg0My0wNDYyMTAgTWlzc2lzc2lwcGkgRHIuTGF3cmVuY2VLUzY2MDQ0SwUKIx0VJS0bERcJMjc0LTgwLTkzOTFTdHJhaWdodERlYW40MTUgODM0LTI5MTk1NDIwIENvbGxlZ2UgQXYuT2FrbGFuZENBOTQ2MDlSBAojGxslNR0RFwkyNjctNDEtMjM5NE8nTGVhcnlNaWNoYWVsNDA4IDI4Ni0yNDI4MjIgQ2xldmVsYW5kIEF2LiAjMTRTYW4gSm9zZUNBOTUxMjhKAwojGRklKR0RFwkyMzgtOTUtNzc2NkNhcnNvbkNoZXJ5bDQxNSA1NDgtNzcyMzU4OSBEYXJ3aW4gTG4uQmVya2VsZXlDQTk0NzA1TQIKIxcdJS8bERcJMjEzLTQ2LTg5MTVHcmVlbk1hcmpvcmllNDE1IDk4Ni03MDIwMzA5IDYzcmQgU3QuICM0MTFPYWtsYW5kQ0E5NDYxOE0BCiMXGyUrIREXCTE3Mi0zMi0xMTc2V2hpdGVKb2huc29uNDA4IDQ5Ni03MjIzMTA5MzIgQmlnZ2UgUmQuTWVubG8gUGFya0NBOTQwMjUNAAAAAw+gAA/gD74PoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAMGLxUAAAFDdXN0b21lciBEaXNjb3VudDgwNDIFIAIGKwABAgdWb2x1bWUgRGlzY291bnRkA+hAGszMzMzMzR4BBi0AAAAHSW5pdGlhbCBDdXN0b21lckAlAAAAAAAADQAAACsGJgAPyw+QD1kPGw7eDqMOaQ4xDfMNtw1+DUUNCgzQDJQMWgwdC+ULpwttCzMK+gq/CoQKSQoMCdIJmAlaCSEI5witCHAINwf9B8IHiAdOBxUG2waeBl8GJgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3KwkfFw0bAQEVM1ktTDc3OTUzTVlvc2hpTGF0aW1lcgwgMTM4OTE5ODktMDYtMTEgMDA6MDA6MDA9KgkfHQ8dAQIVM1ZQQTMwODkwRlZpY3RvcmlhUEFzaHdvcnRoBgCMMDg3NzE5OTAtMDktMTMgMDA6MDA6MDA7KQkfGw8dAQEVM1RQTzU1MDkzTVRpbW90aHlQTydSb3Vya2UNZDA3MzYxOTg4LTA2LTE5IDAwOjAwOjAwOCgJHxUPGwECFTNTS08yMjQxMk1TdmVuS090dGxpZWIFAJYxMzg5MTk5MS0wNC0wNSAwMDowMDowMDcnCR8VDxkBAhUzUkJNMjMwNjFGUml0YUJNdWxsZXIFAMYxNjIyMTk5My0xMC0wOSAwMDowMDowMDgmCR8ZDRkBAhUzUi1NNTM1NTBNUm9sYW5kTWVuZGVsCwCWMDczNjE5OTEtMDktMDUgMDA6MDA6MDA4JQkfFQ8bAQIVM1BYSDIyMjUwTVBhdWxYSGVucmlvdAUAnzA4NzcxOTkzLTA4LTE5IDAwOjAwOjAwOSQJHxkPGQECFTNQVEMxMTk2Mk1QaGlsaXBUQ3JhbWVyAgDXOTk1MjE5ODktMTEtMTEgMDA6MDA6MDA4IwkfFw8bAQEVM1BTUDY4NjYxRlBhdWxhU1BhcmVudGUIfTEzODkxOTk0LTAxLTE5IDAwOjAwOjAwNyIJHxcPGQEBFTNQU0E4OTA4Nk1QZWRyb1NBZm9uc28OWTEzODkxOTkwLTEyLTI0IDAwOjAwOjAwOyEJHxkPHwEBFTNQT0s5MzAyOE1QaXJra29PS29za2l0YWxvClA5OTk5MTk5My0xMS0yOSAwMDowMDowMDggCR8XDxsBARUzUE1BNDI2MjhNUGFvbG9NQWNjb3J0aQ0jMDg3NzE5OTItMDgtMjcgMDA6MDA6MDA4HwkfFw8bAQEVM1BIRjM4ODk5TVBldGVySEZyYW5rZW4KSzA4NzcxOTkyLTA1LTE3IDAwOjAwOjAwNx4JHxcPFwECFTNQREk0NzQ3ME1QYWxsZURJYnNlbgcAwzA3MzYxOTkzLTA1LTA5IDAwOjAwOjAwPB0JHx0PGwECFTNQQ005ODUwOUZQYXRyaWNpYUNNY0tlbm5hCwCWOTk5OTE5ODktMDgtMDEgMDA6MDA6MDA4HAkfFQ8bAQIVM01NUzQ5NjQ5Rk1hcnlNU2F2ZWxleQgArzA3MzYxOTkzLTA2LTI5IDAwOjAwOjAwOBsJHxcPGQECFTNNSlAyNTkzOU1NYXJpYUpQb250ZXMFAPYxNzU2MTk4OS0wMy0wMSAwMDowMDowMDsaCR8XDx8BAhUzTUdLNDQ2MDVNTWF0dGlHS2FydHR1bmVuBgDcMDczNjE5OTQtMDUtMDEgMDA6MDA6MDA5GQkfGQ8ZAQIVM01GUzUyMzQ3TU1hcnRpbkZTb21tZXIKAKUwNzM2MTk5MC0wNC0xMyAwMDowMDowMDkYCR8dDxcBARUzTUFTNzA0NzRGTWFyZ2FyZXRBU21pdGgJTjEzODkxOTg4LTA5LTI5IDAwOjAwOjAwORcJHxkPGwEBFTNNQVA3NzE4M01NaWd1ZWxBUGFvbGlubwtwMTM4OTE5OTItMTItMDcgMDA6MDA6MDA3FgkfGw0XAQEVM00tUjM4ODM0Rk1hcnRpbmVSYW5jZQlLMDg3NzE5OTItMDItMDUgMDA6MDA6MDA4FQkfGQ0bAQEVM00tUDkxMjA5TU1hbnVlbFBlcmVpcmEIZTk5OTkxOTg5LTAxLTA5IDAwOjAwOjAwOBQJHxcNGwECFTNNLUw2Nzk1OEZNYXJpYUxhcnNzb24HAIcxMzg5MTk5Mi0wMy0yNyAwMDowMDowMDwTCR8dDxsBAhUzTEFMMjE0NDdNTGF1cmVuY2VB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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAOBQEdAQEORGVzaWduZXIZZBwNBQE1AQENU2FsZXMgUmVwcmVzZW50YXRpdmUZZA4MBQEZAQEMRWRpdG9yGWQbCwUBMQECC09wZXJhdGlvbnMgTWFuYWdlcksAlhwKBQEzAQIKUHJvZHVjdGlvbnMgTWFuYWdlcksApR0JBQE1AQIJQWNxdWlzaXRpb25zIE1hbmFnZXJLAK8hCAUBPQECCFB1YmxpYyBSZWxhdGlvbnMgTWFuYWdlcmQArxoHBQEvAQIHTWFya2V0aW5nIE1hbmFnZXJ4AMgZBgUBKwICBk1hbmFnaW5nIEVkaXRvcgCMAOETBQUBHwICBVB1Ymxpc2hlcgCWAPoiBAUBPQICBENoaWVmIEZpbmFuY2lhbCBPZmZpY2llcgCvAPolAwUBQwICA0J1c2luZXNzIE9wZXJhdGlvbnMgTWFuYWdlcgCvAOEhAgUBOwICAkNoaWVmIEV4ZWN1dGl2ZSBPZmZpY2VyAMgA+iMBBQlFAQFOZXcgSGlyZSAtIEpvYiBub3Qgc3BlY2lmaWVkCgoFAAAAAg/2AAAAACMP+w/2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiBAAAACEDDQAAAAgOvgAP2w+wD4MPVg8uDw4O5w6+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJwgGFTEXABk5OTk5THVjZXJuZSBQdWJsaXNoaW5nUGFyaXNGcmFuY2UlBwYVKR0REzk5NTJTY29vdG5leSBCb29rc05ldyBZb3JrTllVU0EeBgYVFx0AGzk5MDFHR0cmR03CgW5jaGVuR2VybWFueSYFBhUvGRETMTc1NlJhbW9uYSBQdWJsaXNoZXJzRGFsbGFzVFhVU0ErBAYVNxsREzE2MjJGaXZlIExha2VzIFB1Ymxpc2hpbmdDaGljYWdvSUxVU0ErAwYVNR0REzEzODlBbGdvZGF0YSBJbmZvc3lzdGVtc0JlcmtlbGV5Q0FVU0EpAgYVLSEREzA4NzdCaW5uZXQgJiBIYXJkbGV5V2FzaGluZ3RvbkRDVVNBIwEGFSkZERMwNzM2TmV3IE1vb24gQm9va3NCb3N0b25NQVVTQQ0AAABWCf4AD/AP3Q/ND7sPqQ+XD4QPdA9iD1APPg8sDxoPCA71DuUO0w7BDq4Ong6MDnoOZw5XDkUOMw4hDg8N/Q3rDdgNyA22DaQNkg2ADW4NXA1JDTkNJw0VDQIM8gzfDM8MvQyrDJgMiAx2DGQMUgxADC4MHAwJC/kL5wvVC8MLsQueC44LfAtpC1kLRws1CyMLEQr+CuoK2grICrYKpAqSCoAKbQpZCkkKNwolChIJ/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAGBxUdKR0RFzgwNDJCb29rYmVhdDY3OSBDYXJzb24gU3QuUG9ydGxhbmRPUjg5MDc2OQUHFTEpGxEXNzg5NkZyaWNhdGl2ZSBCb29rc2hvcDg5IE1hZGlzb24gU3QuRnJlbW9udENBOTAwMTlPBAcVVS8dERc3MTMxRG9jLVUtTWF0OiBRdWFsaXR5IExhdW5kcnkgYW5kIEJvb2tzMjQtQSBBdm9nYWRybyBXYXlSZW11bGFkZVdBOTgwMTQ0AwcVJScfERc3MDY3TmV3cyAmIEJyZXdzNTc3IEZpcnN0IFN0LkxvcyBHYXRvc0NBOTY3NDUxAgcVHS8ZERc3MDY2QmFybnVtJ3M1NjcgUGFzYWRlbmEgQXZlLlR1c3RpbkNBOTI3ODk/AQcVMzMbERc2MzgwRXJpYyB0aGUgUmVhZCBCb29rczc4OCBDYXRhbWF1Z3VzIEF2ZS5TZWF0dGxlV0E5ODA1Ng0AAAAZDYcAD+cPzQ+0D5sPgQ9nD04PNQ8cDwIO6Q7QDrcOng6FDmwOUw45DiAOBw3tDdMNuQ2gDYcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA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ZS4xOTkxLTA2LTEyIDAwOjAwOjAwgWMRDBlfHxUHAgECggMzVEM0MjAzRmlmdHkgWWVhcnMgaW4gQnVja2luZ2hhbSBQYWxhY2UgS2l0Y2hlbnN0cmFkX2Nvb2swODc3QCfmZmZmZmYPoA46+E1vcmUgYW5lY2RvdGVzIGZyb20gdGhlIFF1ZWVuJ3MgZmF2b3JpdGUgY29vayBkZXNjcmliaW5nIGxpZmUgYW1vbmcgRW5nbGlzaCByb3lhbHR5LiBSZWNpcGVzLCB0ZWNobmlxdWVzLCB0ZW5kZXIgdmlnbmV0dGVzLjE5OTEtMDYtMTIgMDA6MDA6MDCBXhANGYELHxUHAgECgUszVEMzMjE4T25pb25zLCBMZWVrcywgYW5kIEdhcmxpYzogQ29va2luZyBTZWNyZXRzIG9mIHRoZSBNZWRpdGVycmFuZWFudHJhZF9jb29rMDg3N0A08zMzMzMzG1gKAXdQcm9mdXNlbHkgaWxsdXN0cmF0ZWQgaW4gY29sb3IsIHRoaXMgbWFrZXMgYSB3b25kZXJmdWwgZ2lmdCBib29rIGZvciBhIGN1aXNpbmUtb3JpZW50ZWQgZnJpZW5kLjE5OTEtMTAtMjEgMDA6MDA6MDCBbA8MGVMhFQcCAQKCHzNQUzc3NzdFbW90aW9uYWwgU2VjdXJpdHk6IEEgTmV3IEFsZ29yaXRobXBzeWNob2xvZ3kwNzM2QB/1wo9cKPYPoAoNCFByb3RlY3RpbmcgeW91cnNlbGYgYW5kIHlvdXIgbG92ZWQgb25lcyBmcm9tIHVuZHVlIGVtb3Rpb25hbCBzdHJlc3MgaW4gdGhlIG1vZGVybiB3b3JsZC4gVXNlIG9mIGNvbXB1dGVyIGFuZCBudXRyaXRpb25hbCBhaWRzIGVtcGhhc2l6ZWQuMTk5MS0wNi0xMiAwMDowMDowMIFJDgwZZyEVBwIBAoFFM1BTMzMzM1Byb2xvbmdlZCBEYXRhIERlcHJpdmF0aW9uOiBGb3VyIENhc2UgU3R1ZGllc3BzeWNob2xvZ3kwNzM2QDP9cKPXCj0H0AoP6FdoYXQgaGFwcGVucyB3aGVuIHRoZSBkYXRhIHJ1bnMgZHJ5PyAgU2VhcmNoaW5nIGV2YWx1YXRpb25zIG9mIGluZm9ybWF0aW9uLXNob3J0YWdlIGVmZmVjdHMuMTk5MS0wNi0xMiAwMDowMDowMIF8DQwZLyEVAQIBAYJzM1BTMjEwNkxpZmUgV2l0aG91dCBGZWFycHN5Y2hvbG9neTA3MzYHF3AKb05ldyBleGVyY2lzZSwgbWVkaXRhdGlvbiwgYW5kIG51dHJpdGlvbmFsIHRlY2huaXF1ZXMgdGhhdCBjYW4gcmVkdWNlIHRoZSBzaG9jayBvZiBkYWlseSBpbnRlcmFjdGlvbnMuIFBvcHVsYXIgYXVkaWVuY2UuIFNhbXBsZSBtZW51cyBpbmNsdWRlZCwgZXhlcmNpc2UgdmlkZW8gYXZhaWxhYmxlIHNlcGFyYXRlbHkuMTk5MS0xMC0wNSAwMDowMDowMIE3DAwZMyEVBwIBAoFVM1BTMjA5MUlzIEFuZ2VyIHRoZSBFbmVteT9wc3ljaG9sb2d5MDczNkAl5mZmZmZmCOMMB/1DYXJlZnVsbHkgcmVzZWFyY2hlZCBzdHVkeSBvZiB0aGUgZWZmZWN0cyBvZiBzdHJvbmcgZW1vdGlvbnMgb24gdGhlIGJvZHkuIE1ldGFib2xpYyBjaGFydHMgaW5jbHVkZWQuMTk5MS0wNi0xNSAwMDowMDowMIF7Cw0ZgQshFQcCAQKCAzNQUzEzNzJDb21wdXRlciBQaG9iaWMgQU5EIE5vbi1QaG9iaWMgSW5kaXZpZHVhbHM6IEJlaGF2aW9yIFZhcmlhdGlvbnNwc3ljaG9sb2d5MDg3N0A1lwo9cKPXG1gKAXdBIG11c3QgZm9yIHRoZSBzcGVjaWFsaXN0LCB0aGlzIGJvb2sgZXhhbWluZXMgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aG9zZSB3aG8gaGF0ZSBhbmQgZmVhciBjb21wdXRlcnMgYW5kIHRob3NlIHdobyBkb24ndC4xOTkxLTEwLTIxIDAwOjAwOjAwZwoLGSclFQAAAABZM1BDOTk5OU5ldCBFdGlxdWV0dGVwb3B1bGFyX2NvbXAxMzg5QSBtdXN0LXJlYWQgZm9yIGNvbXB1dGVyIGNvbmZlcmVuY2luZy4yMDE0LTExLTA3IDEwOjM5OjM3gS0JDBk/JRUBAgECgT8zUEM4ODg4U2VjcmV0cyBvZiBTaWxpY29uIFZhbGxleXBvcHVsYXJfY29tcDEzODkUH0AKD/9NdWNrcmFraW5nIHJlcG9ydGluZyBvbiB0aGUgd29ybGQncyBsYXJnZXN0IGNvbXB1dGVyIGhhcmR3YXJlIGFuZCBzb2Z0d2FyZSBtYW51ZmFjdHVyZXJzLjE5OTQtMDYtMTIgMDA6MDA6MDCBKggMGT0lFQcCAQKBLTNQQzEwMzVCdXQgSXMgSXQgVXNlciBGcmllbmRseT9wb3B1bGFyX2NvbXAxMzg5QDbzMzMzMzMbWBAiTEEgc3VydmV5IG9mIHNvZnR3YXJlIGZvciB0aGUgbmFpdmUgdXNlciwgZm9jdXNpbmcgb24gdGhlICdmcmllbmRsaW5lc3MnIG9mIGVhY2guMTk5MS0wNi0zMCAwMDowMDowMFMHCxlRHxUAAAAAADNNQzMwMjZUaGUgUHN5Y2hvbG9neSBvZiBDb21wdXRlciBDb29raW5nVU5ERUNJREVEMDg3NzIwMTQtMTEtMDcgMTA6Mzk6MzeBGwYMGTcdFQcCAQKBHTNNQzMwMjFUaGUgR291cm1ldCBNaWNyb3dhdmVtb2RfY29vazA4NzdAB+uFHrhR7DqYGFbmVHJhZGl0aW9uYWwgRnJlbmNoIGdvdXJtZXQgcmVjaXBlcyBhZGFwdGVkIGZvciBtb2Rlcm4gbWljcm93YXZlIGNvb2tpbmcuMTk5MS0wNi0xOCAwMDowMDowMIEQBQsZTx0VBwgBAnUzTUMyMjIyU2lsaWNvbiBWYWxsZXkgR2FzdHJvbm9taWMgVHJlYXRzbW9kX2Nvb2swODc3QDP9cKPXCj0MB/BGYXZvcml0ZSByZWNpcGVzIGZvciBxdWljaywgZWFzeSwgYW5kIGVsZWdhbnQgbWVhbHMuMTk5MS0wNi0wOSAwMDowMDowMIE2BAwZRx0VBwIBAoFDM0JVNzgzMlN0cmFpZ2h0IFRhbGsgQWJvdXQgQ29tcHV0ZXJzYnVzaW5lc3MxMzg5QDP9cKPXCj0TiAoP/0Fubm90YXRlZCBhbmFseXNpcyBvZiB3aGF0IGNvbXB1dGVycyBjYW4gZG8gZm9yIHlvdTogYSBuby1oeXBlIGd1aWRlIGZvciB0aGUgY3JpdGljYWwgdXNlci4xOTkxLTA2LTIyIDAwOjAwOjAwgVQDDBlLHRUHAgECgXszQlUyMDc1WW91IENhbiBDb21iYXQgQ29tcHV0ZXIgU3RyZXNzIWJ1c2luZXNzMDczNkAH64UeuFHsJ40YSSJUaGUgbGF0ZXN0IG1lZGljYWwgYW5kIHBzeWNob2xvZ2ljYWwgdGVjaG5pcXVlcyBmb3IgbGl2aW5nIHdpdGggdGhlIGVsZWN0cm9uaWMgb2ZmaWNlLiBFYXN5LXRvLXVuZGVyc3RhbmQgZXhwbGFuYXRpb25zLjE5OTEtMDYtMzAgMDA6MDA6MDCBPgIMGXUdFQcCAQKBJTNCVTExMTFDb29raW5nIHdpdGggQ29tcHV0ZXJzOiBTdXJyZXB0aXRpb3VzIEJhbGFuY2UgU2hlZXRzYnVzaW5lc3MxMzg5QCfmZmZmZmYTiAoPJEhlbHBmdWwgaGludHMgb24gaG93IHRvIHVzZSB5b3VyIGVsZWN0cm9uaWMgcmVzb3VyY2VzIHRvIHRoZSBiZXN0IGFkdmFudGFnZS4xOTkxLTA2LTA5IDAwOjAwOjAwgUYBDBlTHRUHAgECgVczQlUxMDMyVGhlIEJ1c3kgRXhlY3V0aXZlJ3MgRGF0YWJhc2UgR3VpZGVidXNpbmVzczEzODlAM/1wo9cKPROICg//QW4gb3ZlcnZpZXcgb2YgYXZhaWxhYmxlIGRhdGFiYXNlIHN5c3RlbXMgd2l0aCBlbXBoYXNpcyBvbiBjb21tb24gYnVzaW5lc3MgYXBwbGljYXRpb25zLiBJbGx1c3RyYXRlZC4xOTkxLTA2LTEyIDAwOjAwOjAwAAAADq68Nosh7ttm7aFfE0e+Lf3rtEp7fGiJJHKUc+tzMi9OjY274U2WC2UZvOVyS7lXiTUOl+pL83GM3WQGjXVaJh2LFTnW3N48N/aOH7WOXc7YpER3U3BJhS79JTzuOMlzt+nZekiMKXn7k2+6/yz1y3njWDBADDGGD0qb6SXUQ5+BtqBzvvFXX1k8AaJbJhJyVdRdSkW2W4VaNsVhVGeFaKIOETAwO1RoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIAAAAA9Cb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGQAAAAQYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgAAAAETA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbgAAABIgQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQAAAATIGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUAAAAFGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTQAAABVhc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG8AAAAWY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5lAAAAF3cgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZQAAABggcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWIAAAAZbGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOAAAAGmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcAAAABtsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHQAAAAccy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvAAAAAHN0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBOZXcgTW9vbiBCb29rcywgcHVibGlzaGVyIDA3MzYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIE5ldyBNb29uIEJvb2tzIGlzIGxvY2F0ZWQgaW4gQm9zdG9uLCBNYXNzYWNodXNldHRzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIE5ldyBNb29uIEJvb2tzLCBwdWJsaXNoZXIgMDczNiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTmV3IE1vb24gQm9va3MgaXMgbG9jYXRlZCBpbiBCb3N0b24sIE1hc3NhY2h1c2V0dHMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTmV3IE1vb24gQm9va3MsIHB1Ymxpc2hlciAwNzM2IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBOZXcgTW9vbiBCb29rcyBpcyBsb2NhdGVkIGluIEJvc3RvbiwgTWFzc2FjaHVzZXR0cy4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB5lIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGkAAAAfbiB0aGUgcHVicyBkYXRhYmFzZS4gRml2ZSBMYWtlcyBQdWJsaXNoaW5nIGlzIGxvY2F0ZWQgaW4gQ2hpY2FnbywgSWxsaW5vaXMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgRml2ZSBMYWtlcyBQdWJsaXNoaW5nLCBwdWJsaXNoZXIgMTYyMiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gRml2ZSBMYWtlcyBQdWJsaXNoaW5nIGlzIGxvY2F0ZWQgaW4gQ2hpY2FnbywgSWxsaW5vaXMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgRml2ZSBMYWtlcyBQdWJsaXNoaW5nLCBwdWJsaXNoZXIgMTYyMiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gRml2ZSBMYWtlcyBQdWJsaXNoaW5nIGlzIGxvY2F0ZWQgaW4gQ2hpY2FnbywgSWxsaW5vaXMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgRml2ZSBMYWtlcyBQdWJsaXNoaW5nLCBwdWJsaXNoZXIgMTYyMiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gRml2ZSBMYWtlcyBQdWJsaXNoaW5nIGlzIGxvY2F0ZWQgaW4gQ2hpY2FnbywgSWxsaW5vaXMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgRml2ZSBMYWtlcyBQdWJsaXNoaW5nLCBwdWJsaXNoZXIgMTYyMiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gRml2ZSBMYWtlcyBQdWJsaXNoaW5nIGlzIGxvY2F0ZWQgaW4gQ2hpY2FnbywgSWxsaW5vaXMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgRml2ZSBMYWtlcyBQdWJsaXNoaW5nLCBwdWJsaXNoZXIgMTYyMiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gRml2ZSBMYWtlcyBQdWJsaXNoaW5nIGlzIGxvY2F0ZWQgaW4gQ2hpY2FnbywgSWxsaW5vaXMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgRml2ZSBMYWtlcyBQdWJsaXNoaW5nLCBwdWJsaXNoZXIgMTYyMiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gRml2ZSBMYWtlcyBQdWJsaXNoaW5nIGlzIGxvY2F0ZWQgaW4gQ2hpY2FnbywgSWxsaW5vaXMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgRml2ZSBMYWtlcyBQdWJsaXNoaW5nLCBwdWJsaXNoZXIgMTYyMiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gRml2ZSBMYWtlcyBQdWJsaXNoaW5nIGlzIGxvY2F0ZWQgaW4gQ2hpY2FnbywgSWxsaW5vaXMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgRml2ZSBMYWtlcyBQdWJsaXNoaW5nLCBwdWJsaXNoZXIgMTYyMiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gRml2ZSBMYWtlcyBQdWJsaXNoaW5nIGlzIGxvY2F0ZWQgaW4gQ2hpY2FnbywgSWxsaW5vaXMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgRml2ZSBMYWtlcyBQdWJsaXNoaW5nLCBwdWJsaXNoZXIgMTYyMiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gRml2ZSBMYWtlcyBQdWJsaXNoaW5nIGlzIGxvY2F0ZWQgaW4gQ2hpY2FnbywgSWxsaW5vaXMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgRml2ZSBMYWtlcyBQdWJsaXNoaW5nLCBwdWJsaXNoZXIgMTYyMiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gRml2ZSBMYWtlcyBQdWJsaXNoaW5nIGlzIGxvY2F0ZWQgaW4gQ2hpY2FnbywgSWxsaW5vaXMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgRml2ZSBMYWtlcyBQdWJsaXNoaW5nLCBwdWJsaXNoZXIgMTYyMiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gRml2ZSBMYWtlcyBQdWJsaXNoaW5nIGlzIGxvY2F0ZWQgaW4gQ2hpY2FnbywgSWxsaW5vaXMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgRml2ZSBMYWtlcyBQdWJsaXNoaW5nLCBwdWJsaXNoZXIgMTYyMiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gRml2ZSBMYWtlcyBQdWJsaXNoaW5nIGlzIGxvY2F0ZWQgaW4gQ2hpY2FnbywgSWxsaW5vaXMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgRml2ZSBMYWtlcyBQdWJsaXNoaW5nLCBwdWJsaXNoZXIgMTYyMiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gRml2ZSBMYWtlcyBQdWJsaXNoaW5nIGlzIGxvY2F0ZWQgaW4gQ2hpY2FnbywgSWxsaW5vaXMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgRml2ZSBMYWtlcyBQdWJsaXNoaW5nLCBwdWJsaXNoZXIgMTYyMiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gRml2ZSBMYWtlcyBQdWJsaXNoaW5nIGlzIGxvY2F0ZWQgaW4gQ2hpY2FnbywgSWxsaW5vaXMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgRml2ZSBMYWtlcyBQdWJsaXNoaW5nLCBwdWJsaXNoZXIgMTYyMiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gRml2ZSBMYWtlcyBQdWJsaXNoaW5nIGlzIGxvY2F0ZWQgaW4gQ2hpY2FnbywgSWxsaW5vaXMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgRml2ZSBMYWtlcyBQdWJsaXNoaW5nLCBwdWJsaXNoZXIgMTYyMiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gRml2ZSBMYWtlcyBQdWJsaXNoaW5nIGlzIGxvY2F0ZWQgaW4gQ2hpY2FnbywgSWxsaW5vaXMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgRml2ZSBMYWtlcyBQdWJsaXNoaW5nLCBwdWJsaXNoZXIgMTYyMiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gRml2ZSBMYWtlcyBQdWJsaXNoaW5nIGlzIGxvY2F0ZWQgaW4gQ2hpY2FnbywgSWxsaW5vaXMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgRml2ZSBMYWtlcyBQdWJsaXNoaW5nLCBwdWJsaXNoZXIgMTYyMiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gRml2ZSBMYWtlcyBQdWJsaXNoaW5nIGlzIGxvY2F0ZWQgaW4gQ2hpY2FnbywgSWxsaW5vaXMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgRml2ZSBMYWtlcyBQdWJsaXNoaW5nLCBwdWJsaXNoZXIgMTYyMiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gRml2ZSBMYWtlcyBQdWJsaXNoaW5nIGlzIGxvY2F0ZWQgaW4gQ2hpY2FnbywgSWxsaW5vaXMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgRml2ZSBMYWtlcyBQdWJsaXNoaW5nLCBwdWJsaXNoZXIgMTYyMiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gRml2ZSBMYWtlcyBQdWJsaXNoaW5nIGlzIGxvY2F0ZWQgaW4gQ2hpY2FnbywgSWxsaW5vaXMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgRml2ZSBMYWtlcyBQdWJsaXNoaW5nLCBwdWJsaXNoZXIgMTYyMiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gRml2ZSBMYWtlcyBQdWJsaXNoaW5nIGlzIGxvY2F0ZWQgaW4gQ2hpY2FnbywgSWxsaW5vaXMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgRml2ZSBMYWtlcyBQdWJsaXNoaW5nLCBwdWJsaXNoZXIgMTYyMiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gRml2ZSBMYWtlcyBQdWJsaXNoaW5nIGlzIGxvY2F0ZWQgaW4gQ2hpY2FnbywgSWxsaW5vaXMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgRml2ZSBMYWtlcyBQdWJsaXNoaW5nLCBwdWJsaXNoZXIgMTYyMiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gRml2ZSBMYWtlcyBQdWJsaXNoaW5nIGlzIGxvY2F0ZWQgaW4gQ2hpY2FnbywgSWxsaW5vaXMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgRml2ZSBMYWtlcyBQdWJsaXNoaW5nLCBwdWJsaXNoZXIgMTYyMiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gRml2ZSBMYWtlcyBQdWJsaXNoaW5nIGlzIGxvY2F0ZWQgaW4gQ2hpY2FnbywgSWxsaW5vaXMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgRml2ZSBMYWtlcyBQdWJsaXNoaW5nLCBwdWJsaXNoZXIgMTYyMiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gRml2ZSBMYWtlcyBQdWJsaXNoaW5nIGlzIGxvY2F0ZWQgaW4gQ2hpY2FnbywgSWxsaW5vaXMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgRml2ZSBMYWtlcyBQdWJsaXNoaW5nLCBwdWJsaXNoZXIgMTYyMiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gRml2ZSBMYWtlcyBQdWJsaXNoaW5nIGlzIGxvY2F0ZWQgaW4gQ2hpY2FnbywgSWxsaW5vaXMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgRml2ZSBMYWtlcyBQdWJsaXNoaW5nLCBwdWJsaXNoZXIgMTYyMiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gRml2ZSBMYWtlcyBQdWJsaXNoaW5nIGlzIGxvY2F0ZWQgaW4gQ2hpY2FnbywgSWxsaW5vaXMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgRml2ZSBMYWtlcyBQdWJsAAAAIGlzaGluZywgcHVibGlzaGVyIDE2MjIgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIEZpdmUgTGFrZXMgUHVibGlzaGluZyBpcyBsb2NhdGVkIGluIENoaWNhZ28sIElsbGlub2lzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIEZpdmUgTGFrZXMgUHVibGlzaGluZywgcHVibGlzaGVyIDE2MjIgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIEZpdmUgTGFrZXMgUHVibGlzaGluZyBpcyBsb2NhdGVkIGluIENoaWNhZ28sIElsbGlub2lzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIEZpdmUgTGFrZXMgUHVibGlzaGluZywgcHVibGlzaGVyIDE2MjIgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIEZpdmUgTGFrZXMgUHVibGlzaGluZyBpcyBsb2NhdGVkIGluIENoaWNhZ28sIElsbGlub2lzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIEZpdmUgTGFrZXMgUHVibGlzaGluZywgcHVibGlzaGVyIDE2MjIgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIEZpdmUgTGFrZXMgUHVibGlzaGluZyBpcyBsb2NhdGVkIGluIENoaWNhZ28sIElsbGlub2lzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIEZpdmUgTGFrZXMgUHVibGlzaGluZywgcHVibGlzaGVyIDE2MjIgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIEZpdmUgTGFrZXMgUHVibGlzaGluZyBpcyBsb2NhdGVkIGluIENoaWNhZ28sIElsbGlub2lzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIEZpdmUgTGFrZXMgUHVibGlzaGluZywgcHVibGlzaGVyIDE2MjIgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIEZpdmUgTGFrZXMgUHVibGlzaGluZyBpcyBsb2NhdGVkIGluIENoaWNhZ28sIElsbGlub2lzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIEZpdmUgTGFrZXMgUHVibGlzaGluZywgcHVibGlzaGVyIDE2MjIgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIEZpdmUgTGFrZXMgUHVibGlzaGluZyBpcyBsb2NhdGVkIGluIENoaWNhZ28sIElsbGlub2lzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIEZpdmUgTGFrZXMgUHVibGlzaGluZywgcHVibGlzaGVyIDE2MjIgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIEZpdmUgTGFrZXMgUHVibGlzaGluZyBpcyBsb2NhdGVkIGluIENoaWNhZ28sIElsbGlub2lzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIEZpdmUgTGFrZXMgUHVibGlzaGluZywgcHVibGlzaGVyIDE2MjIgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIEZpdmUgTGFrZXMgUHVibGlzaGluZyBpcyBsb2NhdGVkIGluIENoaWNhZ28sIElsbGlub2lzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIEZpdmUgTGFrZXMgUHVibGlzaGluZywgcHVibGlzaGVyIDE2MjIgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIEZpdmUgTGFrZXMgUHVibGlzaGluZyBpcyBsb2NhdGVkIGluIENoaWNhZ28sIElsbGlub2lzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIEZpdmUgTGFrZXMgUHVibGlzaGluZywgcHVibGlzaGVyIDE2MjIgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIEZpdmUgTGFrZXMgUHVibGlzaGluZyBpcyBsb2NhdGVkIGluIENoaWNhZ28sIElsbGlub2lzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIEZpdmUgTGFrZXMgUHVibGlzaGluZywgcHVibGlzaGVyIDE2MjIgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIEZpdmUgTGFrZXMgUHVibGlzaGluZyBpcyBsb2NhdGVkIGluIENoaWNhZ28sIElsbGlub2lzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIEZpdmUgTGFrZXMgUHVibGlzaGluZywgcHVibGlzaGVyIDE2MjIgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIEZpdmUgTGFrZXMgUHVibGlzaGluZyBpcyBsb2NhdGVkIGluIENoaWNhZ28sIElsbGlub2lzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIEZpdmUgTGFrZXMgUHVibGlzaGluZywgcHVibGlzaGVyIDE2MjIgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIEZpdmUgTGFrZXMgUHVibGlzaGluZyBpcyBsb2NhdGVkIGluIENoaWNhZ28sIElsbGlub2lzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIEZpdmUgTGFrZXMgUHVibGlzaGluZywgcHVibGlzaGVyIDE2MjIgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIEZpdmUgTGFrZXMgUHVibGlzaGluZyBpcyBsb2NhdGVkIGluIENoaWNhZ28sIElsbGlub2lzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIEZpdmUgTGFrZXMgUHVibGlzaGluZywgcHVibGlzaGVyIDE2MjIgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIEZpdmUgTGFrZXMgUHVibGlzaGluZyBpcyBsb2NhdGVkIGluIENoaWNhZ28sIElsbGlub2lzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIEZpdmUgTGFrZXMgUHVibGlzaGluZywgcHVibGlzaGVyIDE2MjIgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIEZpdmUgTGFrZXMgUHVibGlzaGluZyBpcyBsb2NhdGVkIGluIENoaWNhZ28sIElsbGlub2lzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIEZpdmUgTGFrZXMgUHVibGlzaGluZywgcHVibGlzaGVyIDE2MjIgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIEZpdmUgTGFrZXMgUHVibGlzaGluZyBpcyBsb2NhdGVkIGluIENoaWNhZ28sIElsbGlub2lzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIEZpdmUgTGFrZXMgUHVibGlzaGluZywgcHVibGlzaGVyIDE2MjIgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIEZpdmUgTGFrZXMgUHVibGlzaGluZyBpcyBsb2NhdGVkIGluIENoaWNhZ28sIElsbGlub2lzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIEZpdmUgTGFrZXMgUHVibGlzaGluZywgcHVibGlzaGVyIDE2MjIgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIEZpdmUgTGFrZXMgUHVibGlzaGluZyBpcyBsb2NhdGVkIGluIENoaWNhZ28sIElsbGlub2lzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIEZpdmUgTGFrZXMgUHVibGlzaGluZywgcHVibGlzaGVyIDE2MjIgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIEZpdmUgTGFrZXMgUHVibGlzaGluZyBpcyBsb2NhdGVkIGluIENoaWNhZ28sIElsbGlub2lzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIEZpdmUgTGFrZXMgUHVibGlzaGluZywgcHVibGlzaGVyIDE2MjIgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIEZpdmUgTGFrZXMgUHVibGlzaGluZyBpcyBsb2NhdGVkIGluIENoaWNhZ28sIElsbGlub2lzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIEZpdmUgTGFrZXMgUHVibGlzaGluZywgcHVibGlzaGVyIDE2MjIgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIEZpdmUgTGFrZXMgUHVibGlzaGluZyBpcyBsb2NhdGVkIGluIENoaWNhZ28sIElsbGlub2lzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIEZpdmUgTGFrZXMgUHVibGlzaGluZywgcHVibGlzaGVyIDE2MjIgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIEZpdmUgTGFrZXMgUHVibGlzaGluZyBpcyBsb2NhdGVkIGluIENoaWNhZ28sIElsbGlub2lzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIEZpdmUgTGFrZXMgUHVibGlzaGluZywgcHVibGlzaGVyIDE2MjIgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIEZpdmUgTGFrZXMgUHVibGlzaGluZyBpcyBsb2NhdGVkIGluIENoaWNhZ28sIElsbGlub2lzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIEZpdmUgTGFrZXMgUHVibGlzaGluZywgcHVibGlzaGVyIDE2MjIgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIEZpdmUgTGFrZXMgUHVibGlzaGluZyBpcyBsb2NhdGVkIGluIENoaWNhZ28sIElsbGlub2lzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIEZpdmUgTGFrZXMgUHVibGlzaGluZywgcHVibGlzaGVyIDE2MjIgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIEZpdmUgTGFrZXMgUHVibGlzaGluZyBpcyBsb2NhdGVkIGluIENoaWNhZ28sIElsbGlub2lzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIEZpdmUgTGFrZXMgUHVibGlzaGluZywgcHVibGlzaGVyIDE2MjIgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIEZpdmUgTGFrZXMgUHVibGlzaGluZyBpcyBsb2NhdGVkIGluIENoaWNhZ28sIElsbGlub2lzLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IAAAAABkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBGaXZlIExha2VzIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciAxNjIyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBGaXZlIExha2VzIFB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBDaGljYWdvLCBJbGxpbm9pcy4NCg0KVGhpcyBpcyBzYW1w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ZXh0IGRhdGEgZm9yIEFsZ29kYXRhIEluZm9zeXN0ZW1zLCBwdWJsaXNoZXIgMTM4OSBpbiB0aGUgcHVicyBkYXRhYmFzZS4gQWxnb2RhdGEgSW5mb3N5c3RlbXMgaXMgbG9jYXRlZCBpbiBCZXJrZWxleSwgQ2FsaWZvcm5pYS4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBBbGdvZGF0YSBJbmZvc3lzdGVtcywgcHVibGlzaGVyIDEzODkgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIEFsZ29kYXRhIEluZm9zeXN0ZW1zIGlzIGxvY2F0ZWQgaW4gQmVya2VsZXksIENhbGlmb3JuaWEuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgQWxnb2RhdGEgSW5mb3N5c3RlbXMsIHB1Ymxpc2hlciAxMzg5IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBBbGdvZGF0YSBJbmZvc3lzdGVtcyBpcyBsb2NhdGVkIGluIEJlcmtlbGV5LCBDYWxpZm9ybmlhLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIEFsZ29kYXRhIEluZm9zeXN0ZW1zLCBwdWJsaXNoZXIgMTM4OSBpbiB0aGUgcHVicyBkYXRhYmFzZS4gQWxnb2RhdGEgSW5mb3N5c3RlbXMgaXMgbG9jYXRlZCBpbiBCZXJrZWxleSwgQ2FsaWZvcm5pYS4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBBbGdvZGF0YSBJbmZvc3lzdGVtcywgcHVibGlzaGVyIDEzODkgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIEFsZ29kYXRhIEluZm9zeXN0ZW1zIGlzIGxvY2F0ZWQgaW4gQmVya2VsZXksIENhbGlmb3JuaWEuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgQWxnb2RhdGEgSW5mb3N5c3RlbXMsIHB1Ymxpc2hlciAxMzg5IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBBbGdvZGF0YSBJbmZvc3lzdGVtcyBpcyBsb2NhdGVkIGluIEJlcmtlbGV5LCBDYWxpZm9ybmlhLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9y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aXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgRml2ZSBMYWtlcyBQdWJsaXNoaW5nLCBwdWJsaXNoZXIgMTYyMiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gRml2ZSBMYWtlcyBQdWJsaXNoaW5nIGlzIGxvY2F0ZWQgaW4gQ2hpY2FnbywgSWxsaW5vaXMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgRml2ZSBMYWtlcyBQdWJsaXNoaW5nLCBwdWJsaXNoZXIgMTYyMiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gRml2ZSBMYWtlcyBQdWJsaXNoaW5nIGlzIGxvY2F0ZWQgaW4gQ2hpY2FnbywgSWxsaW5vaXMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgRml2ZSBMYWtlcyBQdWJsaXNoaW5nLCBwdWJsaXNoZXIgMTYyMiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gRml2ZSBMYWtlcyBQdWJsaXNoaW5nIGlzIGxvY2F0ZWQgaW4gQ2hpY2FnbywgSWxsaW5vaXMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgRml2ZSBMYWtlcyBQdWJsaXNoaW5nLCBwdWJsaXNoZXIgMTYyMiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gRml2ZSBMYWtlcyBQdWJsaXNoaW5nIGlzIGxvY2F0ZWQgaW4gQ2hpY2FnbywgSWxsaW5vaXMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgRml2ZSBMYWtlcyBQdWJsaXNoaW5nLCBwdWJsaXNoZXIgMTYyMiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gRml2ZSBMYWtlcyBQdWJsaXNoaW5nIGlzIGxvY2F0ZWQgaW4gQ2hpY2FnbywgSWxsaW5vaXMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgRml2ZSBMYWtlcyBQdWJsaXNoaW5nLCBwdWJsaXNoZXIgMTYyMiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gRml2ZSBMYWtlcyBQdWJsaXNoaW5nIGlzIGxvY2F0ZWQgaW4gQ2hpY2FnbywgSWxsaW5vaXMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgRml2ZSBMYWtlcyBQdWJsaXNoaW5nLCBwdWJsaXNoZXIgMTYyMiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gRml2ZSBMYWtlcyBQdWJsaXNoaW5nIGlzIGxvY2F0ZWQgaW4gQ2hpY2FnbywgSWxsaW5vaXMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgRml2ZSBMYWtlcyBQdWJsaXNoaW5nLCBwdWJsaXNoZXIgMTYyMiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gRml2ZSBMYWtlcyBQdWJsaXNoaW5nIGlzIGxvY2F0ZWQgaW4gQ2hpY2FnbywgSWxsaW5vaXMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgRml2ZSBMYWtlcyBQdWJsaXNoaW5nLCBwdWJsaXNoZXIgMTYyMiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gRml2ZSBMYWtlcyBQdWJsaXNoaW5nIGlzIGxvY2F0ZWQgaW4gQ2hpY2FnbywgSWxsaW5vaXMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgRml2ZSBMYWtlcyBQdWJsaXNoaW5nLCBwdWJsaXNoZXIgMTYyMiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gRml2ZSBMYWtlcyBQdWJsaXNoaW5nIGlzIGxvY2F0ZWQgaW4gQ2hpY2FnbywgSWxsaW5vaXMuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgRml2ZSBMYWtlcyBQdWJsaXNoaW5nLCBwdWJsaXNoZXIgMTYyMiBpbiB0aGUgcHVicyBkYXRhYmFzZS4gRml2AAAAHQ0AAAAEAcUAC8UJvQYIAcUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIhACAYViDiITTk5OTlHSUY4OWGpMCQwsw8wMDAwgDAwMIAwgIAwMDCAgDCAMICAgICAwMDA/zAwMP8w//8wMDD//zD/MP//////IfkEATAwDzAsMDAwMKkwJDBABP/wyUmrvTjrzbv/YPgBWmCeZ2U+qNSKcCzP9EVmaJ7WfO//I9WOdRO2hkRKbqJrEm/I50rIJCGnq+X0WU1ht7vw1vVicZpooHrNxjiZJXSa/G7b77yiTT6W4v+APXoWckaBMXNuSUqLXISNhjODS5FuWYtlfkqDkF99m3tWmGBkoJuipo1jYDoucXyUh7KzIJynrVJZR1G0vYC2XXW3mb7Fv698xsrLZjiFKsxAn5Ab0z62vM3B0c6plnsjwILDcJZipp+kpZHnroTYel+gq1AvQ6xddOuTZ7BiRZP6XLEB7RRBc+X0MVroSFtCh/y+OeRGsWJBc/6sWdwoCVlGI9nDOIpU5KzVnGQjU+LwmOkZMZUw3WHEBcfLy5gxxeWiGSwkTpg6P/4c2iEoLKJIq7GMJTNpUqOJ1onkibDSRIMkO2bNh3WjFYBapaZuay2sB043Qda7qJArpofpptGjttbRXHRgx3qj4+VW15669Kqqss/PV4Zx395ldZgwXVH3vl5aJTYe0ziO7W6EsrdTXWBywdYttViL5cylsb2jd7mePL6e2jGUSpVa332xUmOhQps3u35CnY7E11S4cWQHjyuHASACMDtUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIEx1Y2VybmUgUHVibGlzaGluZywgcHVibGlzaGVyIDk5OTkgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIEx1Y2VybmUgcHVibGlzaGluZyBpcyBsb2NhdGVkIGluIFBhcmlzLCBGcmFuY2UuDQoNClRoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgTHVjZXJuZSBQdWJsaXNoaW5nLCBwdWJsaXNoZXIgOTk5OSBpbiB0aGUgcHVicyBkYXRhYmFzZS4gTHVjZXJuZSBwdWJsaXNoaW5nIGlzIGxvY2F0ZWQgaW4gUGFyaXMsIEZyYW5jZS4NCg0KVGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBMdWNlcm5lIFB1Ymxpc2hpbmcsIHB1Ymxpc2hlciA5OTk5IGluIHRoZSBwdWJzIGRhdGFiYXNlLiBMdWNlcm5lIHB1Ymxpc2hpbmcgaXMgbG9jYXRlZCBpbiBQYXJpcywgRnJhbmNlLg0KDQpUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIEx1Y2VybmUgUHVibGlzaGluZywgcHVibGlzaGVyIDk5OTkgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIEx1Y2VybmUgcHVibGlzaGluZyBpcyBsb2NhdGVkIGluIFBhcmlzLCBGcmFuY2UuhzIHBhWMToIbOTk1MkdJRjg5YQcBKDCzDzAwMDCAMDAwgDCAgDAwMICAMIAwgICAgIDAwMD/MDAw/zD//zAwMP//MP8w//////8h+QQBMDAPMCwwMDAwBwEoMEAE//DJSau9OOvNu/9gKI5kaWYwBawse7VtBafSTE8znj92X8cWmAw4JPKEGOTRpVLaisylUXp7Um8nWRJpciqb0R0Uq4uCV+fpd2ve5FLCJ5xHpcvt7ys8P7+fyFmBgh19doaFiIeKiYyLg48cjZKOcziQgpOZlJuXnZ6foHSho6SlpqdFj1g+aYA/U69MYq1ebbE7az2urG66ZLNlsmu3q761wH+0KLzEyMHMx7uwZWN8ept7voza29qLfDHZ4diOL6iemunkmuftpI2i7vLz9PWXrvb5+vv8gF1s0owBZMZNGL46rYjYeqXB28B/1ZzlQpPw4Igqw57ZyiiG4zCPs/8mLrxybVkYIyBPLgwJpKOzLP6svCQZjYbEj9PiCNQ4MuPAZ1otiXNxZyhaozMhmsBI0GFJmjyDvsgJC9hOWpnegItzculRa3J86FrnwSK/c+rSklXLdq3btuxUnIUE961ds3NDqY2XV27dv3z7bu6EV+9dToMTK66xuLHjx0kgS56suDDly5hN4fM5pOHMiMk8t9mJ1yI00dOmcv74UFXEg8huBnQq22ZPNWMRnkF9Wo9S37FRKuxdgunIZipHf7Gacrby5xRBP40GVKp1qMTGSP28NGrNzVSHr8Q5vovI6Kp/a9d9K3305sWILlffveL1au5th9+4v+Br5+jxxsvOTS3BV1GAPFlWVn76HUegQeXxF2GDzB1XHSHChQOWVlz1sdVXHYrCHQjgmaFehSaehyB7FzazHm/mIDJOWCEW9SFReMhnY1GKkGjff+jJxiB9zQEEpHtrcXOIkB76JyOONIJFTkO7YejTiPf9RN0yRz551DpSdjMjJWHm+GU2ZgJWiRaZ0XWYmm9aAm6cdcnV5oJ0xhnXnZG1xRifeQbKZylxKdiPnohaOqg+irYj6F6LDtronIkiFumlhLgDGKacfjJpp6BG+mmopLYJQAQwO1RoaXMgaXMgc2FtcGxlIHRleHQgZGF0YSBmb3IgU2Nvb3RuZXkgQm9va3MsIHB1Ymxpc2hlciA5OTUyIGluIHRoZSBwdWJzIGRhdGFiYXNlLiBTY29vdG5leSBCb29rcyBpcyBsb2NhdGVkIGluIE5ldyBZb3JrIENpdHksIE5ldyBZb3JrLoQFBgYVhiSBazk5MDFHSUY4OWFdMCIwsw8wMDAwgDAwMIAwgIAwMDCAgDCAMICAgICAwMDA/zAwMP8w//8wMDD//zD/MP//////IfkEATAwDzAsMDAwMF0wIjBABP/wyUmrvTjrzfsD3weMJJiVo4aqaLuebm7OYjq9G8npmF3/uJ6ONmvteCxTMlY6ukJFpnRKrVqvTSJ2y+1eodAmxSiyMM04ssknIdeMxHclJnSPn2Eeso3nr+JegYKDYEoeh4iJinOFg46PVYVvbCwdhjkva5cwcI1sVHdnN1ijhl6SYn6UdU4XNpemqXWAk2iUm7Kue5poZapzT4CioX2ldqpbtmfCkM3OQ3nP0s6e09anzNfapNnHk0HIud9fwFKo3rqbtpZ2e5x/1bi78j6ruXBryuXwWrfmxMdIjdr3JRvAYlMO/pNjjFs1gOzUlRMSwhfEJec+idOHCdedgXI5O9JuUozgqnBKotTTCC5YPIm9LC1yB1PhyJIml9RM9q5Tv21AQXULStRnxUVIkyodc3Sp06eJMEQwMDtUaGlzIGlzIHNhbXBsZSB0ZXh0IGRhdGEgZm9yIEdHRyZHLCBwdWJsaXNoZXIgOTkwMSBpbiB0aGUgcHVicyBkYXRhYmFzZS4gR0dHJkcgaXMgbG9jYXRlZCBpbiBNw7xuY2hlbiwgR2VybWFueS6IOAUGFY5ighMxNzU2R0lGODlh4zAlMLMPMDAwMIAwMDCAMICAMDAwgIAwgDCAgICAgMDAwP8wMDD/MP//MDAw//8w/zD//////yH5BAEwMA8wLDAwMDDjMCUwQAT/8MlJq7046827/2AojiQIWOcFpNLqTm4MxzJN0euc27r84ayHjeervYRHZFLJYzafLyiOkzpZW0BNsng05npf7Des7FF9TrJOXI0GmWY2Wl6O08PcpapUubKuLUIwgoF/hIKGiYOGhYdUiHuKjZOQlJR+kYt9h4CVnp2BfBiYb6Kmp1p7IqWbN44drK6xjxlAtqi4qFNyerW9TnZnaje/ua8qVk1rwHduY1vObc/Sw8hzcWh51HRsYFPaduDas6Ez1tWykJKfnOrt62+gxDXvnpf1mJbsKO76nf9pohwbtMoePmMITbQrlw/WQH0FyeWSmLCixYsYM3qg6I2jRo3D/9BpIYenmC9fInGxUhYt5UeVzrDw2vjr2iqTLx/yA7OMSEtu0HZ0GUrNY5Z5QktO2zYnm004Uv4QlSZnQ5VROMUgmtptXLJtzfxkTdNR6s+AS80yQlpWLbaWXyWq3RGwVr17pDbJA+gqHUo9Akdpuud3sLt4h/VaDgIulYm8/ODdZSdZciPEkXUCrLz41ebEnwtvpgdRp8J0ij7n3WtwtWKPmlhzxttZNuV+uEPHJgQ7leveOU81hOxwlu2NpnKGMB68ufPnL5lDnw597HKXuoTZkk79sVplVmuO+1EMfMJY27d3n3g0qXVubJfRFPleVCnxPOX3+ar1HJlpKGBHEP9USv3HlxfBDNhRV8bt119+tJyB1FxeqWdOW7ugZZQb+0Xz1i1emeEUiFFlaKFdEpIlX2NegEXgUg8+FaB5jbXFoIEF7lLjiEwFJVd45vXEoofMtNhNHUHOCM2RPFZlZILq7ejjjXG5dFU8GZ7DJFc8NmkjfFhViOUtWs4En4VSFkhllVbNg0RdJ8n01oUBzlgOMXSO1JSMDj6IlZslfIfjnW6OxdgSVZI0mWqe5bboZP4xulJilx3kD6W3XZpIepp5l1xqtd0G6mzKnblPpqFWitikwz26almV7lRQrG6iSpxtuun2iDy0iXbQq6jZbqmojWJGwquj/oobQ8oim5xYr8EeB1qx0b42bbXJroXcpIWVRmuDrJXGHaZyEUbus7uBetpAoIz727LrmXLrbttm0m1xdo1bKx/vxlsRr6X6lsk69W6mr77+JjwdwPyiq4rCEEcsMW4RMDA7VGhpcyBpcyBzYW1wbGUgdGV4dCBkYXRhIGZvciBSYW1vbmEgUHVibGlzaGVycywgcHVibGlzaGVyIDE3NTYgaW4gdGhlIHB1YnMgZGF0YWJhc2UuIFJhbW9uYSBQdWJsaXNoZXJzIGlzIGxvY2F0ZWQgaW4gRGFsbGFzLCBUZXhhcy4=";
const SCHEMA = [
{name:"authors", desc:"Autor:innen mit Adresse und Vertragsstatus", cols:[
["au_id","TEXT","PK"],["au_lname","TEXT"],["au_fname","TEXT"],["phone","TEXT"],
["address","TEXT"],["city","TEXT"],["state","TEXT"],["zip","TEXT"],["contract","INTEGER"]]},
{name:"titles", desc:"Bücher / Titel", cols:[
["title_id","TEXT","PK"],["title","TEXT"],["type","TEXT"],["pub_id","TEXT"],["price","NUMERIC"],
["advance","NUMERIC"],["royalty","INTEGER"],["ytd_sales","INTEGER"],["notes","TEXT"],["pubdate","TEXT"]]},
{name:"titleauthor", desc:"Verknüpfung: welche Autor:in schrieb welches Buch", cols:[
["au_id","TEXT","PK"],["title_id","TEXT","PK"],["au_ord","INTEGER"],["royaltyper","INTEGER"]]},
{name:"publishers", desc:"Verlage", cols:[
["pub_id","TEXT","PK"],["pub_name","TEXT"],["city","TEXT"],["state","TEXT"],["country","TEXT"]]},
{name:"pub_info", desc:"Zusatzinfos zu Verlagen (PR-Text, Logo)", cols:[
["pub_id","TEXT","PK"],["logo","BLOB"],["pr_info","TEXT"]]},
{name:"sales", desc:"Einzelne Verkäufe / Bestellungen", cols:[
["stor_id","TEXT","PK"],["ord_num","TEXT","PK"],["ord_date","TEXT"],["qty","INTEGER"],["payterms","TEXT"],["title_id","TEXT","PK"]]},
{name:"stores", desc:"Buchhandlungen, die verkaufen", cols:[
["stor_id","TEXT","PK"],["stor_name","TEXT"],["stor_address","TEXT"],["city","TEXT"],["state","TEXT"],["zip","TEXT"]]},
{name:"discounts", desc:"Rabatte, die manche Stores anbieten", cols:[
["discounttype","TEXT"],["stor_id","TEXT"],["lowqty","INTEGER"],["highqty","INTEGER"],["discount","NUMERIC"]]},
{name:"roysched", desc:"Staffelung der Tantiemen (royalty) je Buch", cols:[
["title_id","TEXT"],["lorange","INTEGER"],["hirange","INTEGER"],["royalty","INTEGER"]]},
{name:"employee", desc:"Mitarbeitende der Verlage", cols:[
["emp_id","TEXT","PK"],["fname","TEXT"],["minit","TEXT"],["lname","TEXT"],["job_id","INTEGER"],
["job_lvl","INTEGER"],["pub_id","TEXT"],["hire_date","TEXT"]]},
{name:"jobs", desc:"Jobbezeichnungen und Gehaltsstufen", cols:[
["job_id","INTEGER","PK"],["job_desc","TEXT"],["min_lvl","INTEGER"],["max_lvl","INTEGER"]]},
];
const TOPICS = [
{id:"select_from", icon:"🔍", color:"#06b6d4", title:"SELECT · FROM · AS · DISTINCT",
concept:"SELECT bestimmt WELCHE Spalten du sehen willst, FROM WOHER die Daten kommen. AS gibt einer Spalte oder Tabelle in der Ausgabe einen anderen Namen — das ändert nichts an der echten Tabelle. DISTINCT entfernt doppelte Zeilen aus dem Ergebnis.",
example:"Ohne DISTINCT:<br>SELECT au_lname FROM authors<br>→ 'Ringer' taucht zweimal auf (zwei Autor:innen mit diesem Nachnamen)<br><br>Mit DISTINCT:<br>SELECT DISTINCT au_lname FROM authors<br>→ 'Ringer' nur einmal",
syntax:"SELECT [DISTINCT] spalte1 [AS alias1], spalte2, ...\nFROM tabelle;",
intro:"<div class=\"ns-intro-title\">🧱 Die Grundbausteine: SELECT und FROM</div><b>Wozu brauchst du das überhaupt?</b> Stell dir vor, du hast eine gigantische Tabelle mit hunderten von Spalten vor dir, aber für deine Arbeit brauchst du eigentlich nur den Vor- und Nachnamen. Genau dafür gibt es diese beiden Befehle. Jede einzelne Datenbank-Abfrage der Welt besteht aus diesen zwei Grundbausteinen: Du musst sagen, was genau du sehen willst (<code>SELECT</code>) und woher die Daten kommen sollen (<code>FROM</code>).",
lesson:[
{title:"SELECT (Die Einkaufsliste)",
was:"Er wählt aus, welche Spalten in deinem finalen Ergebnis angezeigt werden sollen.",
einfach:"SELECT ist wortwörtlich deine Einkaufsliste. Du sagst der Datenbank damit exakt, welche Informations-Häppchen sie aus dem Lager holen soll. Jedes Wort, das du hier aufschreibst, wird zu einer Spalte in deiner Ansicht. Wenn du zu faul bist, alles aufzuschreiben und einfach alle Spalten sehen willst, benutzt du den Platzhalter `*` (das Sternchen). Das bedeutet für die Datenbank: \"Bring mir einfach alles!\"",
syntax:"SELECT spalte_1, spalte_2",
tipp:"Die Spalten werden immer mit einem Komma getrennt. Nach der allerletzten Spalte kommt KEIN Komma mehr!",
beispiele:[{code:"SELECT au_lname, state", note:"(Holt dir exakt diese zwei Spalten – nicht mehr und nicht weniger.)"}]},
{title:"FROM (Die Wegbeschreibung)",
was:"Er sagt der Datenbank, in welcher Tabelle sie suchen soll.",
einfach:"Das ist die Wegbeschreibung in dein Lagerhaus. Deine Datenbank hat oft viele verschiedene Regale (Tabellen) – zum Beispiel eine für Autoren, eine für Bücher und eine für Verkäufe. Mit `FROM` schickst du das System gezielt an das richtige Regal. Ohne `FROM` steht die Datenbank völlig verloren da und weiß nicht, wo sie suchen soll.",
syntax:"FROM tabellenname",
beispiele:[{code:"SELECT au_lname, state\nFROM authors;", note:"(Bedeutet: Zeig mir den Nachnamen und das Bundesland, und hol dir diese Infos aus dem Regal der Autoren.)"}]},
{title:"AS (Das neue Preisschild)",
was:"Er gibt einer Spalte für deine Ansicht einen neuen, schöneren Namen (einen sogenannten Alias).",
einfach:"Manchmal heißen die Spalten in der echten Datenbank furchtbar technisch, zum Beispiel `au_lname` für den Nachnamen eines Autors. Mit `AS` nimmst du einfach ein neues Preisschild und klebst es für deine Anzeige darüber. Die echten Daten im Lagerhaus behalten ihren komplizierten Namen, aber dein Schaufenster (dein Ergebnis) sieht für Menschen wunderbar lesbar aus.",
syntax:"SELECT original_spalte AS neuer_name",
beispiele:[{code:"SELECT au_lname AS Nachname\nFROM authors;", note:"(Bedeutet: Die Spalte heißt in deinem Ergebnis jetzt \"Nachname\". Die echte Datenbank bleibt unverändert.)"}]},
{title:"DISTINCT (Der Aufräumer)",
was:"Er filtert doppelte Einträge aus deiner Ansicht heraus, sodass jeder Wert nur noch ein einziges Mal auftaucht.",
einfach:"Stell dir vor, du willst wissen, aus welchen Bundesländern deine Autoren kommen. Wenn fünf Autoren aus Kalifornien (CA) kommen, würde eine normale Abfrage fünfmal stumpf \"CA\" untereinander auflisten. `DISTINCT` räumt hier auf. Es sagt der Datenbank: \"Zeig mir jeden Wert nur ein einziges Mal. Mich interessieren keine Wiederholungen.\" Du bekommst dadurch eine saubere, übersichtliche Liste.",
syntax:"SELECT DISTINCT spalte_die_gefiltert_werden_soll",
tipp:"Das Wort DISTINCT steht immer direkt nach dem SELECT!",
beispiele:[
{label:"Normale Abfrage ohne Aufräumer:", code:"SELECT state FROM authors;", note:"(Ergebnis: CA, CA, CA, UT, UT)"},
{label:"Mit unserem Aufräumer:", code:"SELECT DISTINCT state FROM authors;", note:"(Ergebnis: CA, UT – kurz und knackig.)"}
]}
]},
{id:"where", icon:"🧭", color:"#f59e0b", title:"WHERE · AND / OR / NOT",
concept:"WHERE filtert einzelne Zeilen. Mit AND müssen alle Bedingungen gleichzeitig wahr sein, mit OR reicht eine. Ohne Klammern wertet SQL AND vor OR aus — das kann zu überraschenden Ergebnissen führen.",
example:"❌ Ohne Klammern:<br>WHERE city='Oakland' OR city='Berkeley' AND contract=1<br>→ Green + Stringer (Oakland, Vertrag egal) + Bennet (Berkeley MIT Vertrag) → Stringer hat aber gar keinen Vertrag!<br><br>✅ Mit Klammern:<br>WHERE (city='Oakland' OR city='Berkeley') AND contract=1<br>→ nur Green + Bennet, Stringer korrekt draußen",
syntax:"SELECT ...\nFROM tabelle\nWHERE bedingung1 [AND|OR bedingung2 ...];",
intro:"<div class=\"ns-intro-title\">🧭 Der Türsteher: <code>WHERE</code> · <code>AND</code> / <code>OR</code> / <code>NOT</code></div><b>Wozu brauchst du das überhaupt?</b> Ohne Filter bekommst du aus deinem Lagerhaus bei einer Abfrage immer alle Zeilen auf einmal geliefert (bei unseren Autoren zum Beispiel alle 23). Meistens suchst du aber etwas ganz Bestimmtes: Nur die Produkte aus einer bestimmten Stadt oder nur die, die gerade auf Lager sind. Hier kommt dein persönlicher Türsteher ins Spiel. Er prüft jede einzelne Zeile in deiner Tabelle und lässt nur die durch, die exakt auf deine Beschreibung passen.",
detailHeading:"🤓 Gut zu wissen: Deine kleinen Retter im Alltag",
lesson:[
{title:"WHERE (Der Türsteher)",
was:"Er filtert deine Tabelle und lässt nur die Zeilen durch, die eine bestimmte Bedingung erfüllen. Alle anderen werden verworfen.",
einfach:"`WHERE` steht buchstäblich an der Tür zu deinem Schaufenster. Du gibst ihm eine Regel mit (z.B. \"Nur Autoren aus Oakland\"), und er schaut sich jede Zeile einzeln an. Passt die Zeile? Darf sie rein. Passt sie nicht? Wird sie eiskalt aussortiert.",
syntax:"WHERE spalte = 'dein_suchbegriff'",
beispiele:[{code:"SELECT * FROM authors WHERE city = 'Oakland';", note:"(Ergebnis: Du siehst nur die Autoren, bei denen in der Spalte 'city' genau 'Oakland' steht. Verträge spielen hier noch keine Rolle.)"}]},
{title:"Vergleichsoperatoren (Die Maßbänder)",
was:"Sie vergleichen Werte miteinander und legen fest, wie genau der Türsteher prüfen soll (`=`, `!=`, `<>`, `>`, `>=`, `<`, `<=`).",
einfach:"Du musst nicht immer nach exakten Wörtern suchen. Manchmal willst du Zahlen vergleichen (z.B. \"Zeig mir alle Bücher, die teurer als 10 Euro sind\"). Dafür gibt es die bekannten mathematischen Zeichen.<br><br>(💡 Gut zu wissen: Wenn etwas nicht übereinstimmen soll, also \"ungleich\" ist, schreiben Datenbank-Profis meistens `!=` oder `<>`. Beide Zeichenfolgen bedeuten exakt das Gleiche.)",
syntax:"WHERE spalte > zahl",
beispiele:[{code:"WHERE contract = 1;", note:"(Ergebnis: Nur die Autoren, bei denen eine 1 für \"hat einen Vertrag\" steht. Alle mit einer 0 fallen raus.)"}]},
{title:"AND / OR (Die Kombinierer)",
was:"Sie verknüpfen mehrere Bedingungen miteinander.",
einfach:"Oft reicht eine einzige Regel nicht aus. `AND` (UND) ist hierbei sehr streng: Es müssen alle genannten Bedingungen gleichzeitig erfüllt sein, sonst bleibt die Tür zu. `OR` (ODER) ist viel entspannter: Es reicht völlig, wenn mindestens eine der Bedingungen zutrifft, damit die Zeile durchgelassen wird.",
syntax:"WHERE bedingung_1 AND bedingung_2",
beispiele:[
{label:"Streng (`AND`):", code:"WHERE city = 'Oakland' AND contract = 1;", note:"(Muss aus Oakland kommen UND einen Vertrag haben. Eins allein reicht nicht!)"},
{label:"Entspannt (`OR`):", code:"WHERE city = 'Oakland' OR city = 'Berkeley';", note:"(Egal welche von beiden Städten, Hauptsache eine davon passt.)"}
]},
{title:"Klammern ( ) (Die Vorfahrtsregeln)",
was:"Sie steuern zwingend, welche Bedingungen zuerst geprüft werden, wenn du `AND` und `OR` in einer Abfrage mischst.",
einfach:"Mischst du `AND` und `OR` wild durcheinander, verhält sich die Datenbank wie ein sturer Taschenrechner: Sie wertet das `AND` nämlich immer zuerst aus! Das kann dein Ergebnis völlig verfälschen. Wenn du Klammern setzt, erzwingst du die Reihenfolge, die du willst. Alles in der Klammer wird immer als Erstes erledigt.",
syntax:"WHERE (bedingung_1 OR bedingung_2) AND bedingung_3",
beispiele:[
{label:"❌ Falsch (Ohne Klammern):", code:"WHERE city = 'Oakland' OR city = 'Berkeley' AND contract = 1;", note:"(Ergebnis: Gibt dir auch Leute aus Oakland, die gar keinen Vertrag haben, weil das AND nur an Berkeley klebt.)"},
{label:"✅ Richtig (Mit Klammern):", code:"WHERE (city = 'Oakland' OR city = 'Berkeley') AND contract = 1;", note:"(Ergebnis: Die Klammer sorgt dafür, dass zuerst geklärt wird: \"Kommt diese Person aus einer der beiden Städte?\" Erst danach wird geschaut, ob sie auch wirklich einen Vertrag hat.)"}
]},
{kind:"detail", title:"Der Rebell: `NOT`",
text:"Manchmal ist es viel einfacher zu sagen, was du nicht willst, anstatt eine lange Liste von Dingen aufzuzählen, die du willst. `NOT` dreht eine Bedingung einfach um: Alles, was nicht zutrifft, landet im Ergebnis. Schreibst du `WHERE NOT contract = 1`, bekommst du sofort alle Autor:innen ohne Vertrag. Das entspricht genau einem `WHERE contract != 1`."},
{kind:"detail", title:"Das absolute Nichts finden: `IS NULL`",
text:"Erinnerst du dich an das leere Nichts, das in der Datenbank NULL genannt wird? Du kannst nach fehlenden Werten nicht mit einem normalen Gleichheitszeichen suchen (`WHERE spalte = NULL` liefert nie ein Ergebnis!). Um zu prüfen, ob ein Wert wirklich fehlt, brauchst du zwingend `IS NULL`. Schreibst du `WHERE price IS NULL`, findest du sofort die Datensätze, wo schlichtweg noch kein Preis eingetragen wurde."}
]},
{id:"sort_agg", icon:"📊", color:"#8b5cf6", title:"ORDER BY · LIMIT · Aggregatfunktionen",
concept:"ORDER BY sortiert das gesamte Ergebnis, LIMIT schneidet danach nur die ersten n Zeilen ab — deshalb wird erst sortiert, dann limitiert. MIN/MAX/COUNT/AVG/SUM fassen viele Zeilen zu EINEM Wert zusammen.",
example:"COUNT(*):<br>zählt ALLE Zeilen, auch NULL-Werte<br><br>COUNT(spalte):<br>zählt nur Zeilen, in denen die Spalte nicht NULL ist<br><br>Beispiel: 18 Titel, 2 davon ohne Preis<br>→ COUNT(*) = 18, COUNT(price) = 16",
syntax:"SELECT spalte, MIN|MAX|COUNT|SUM|AVG(spalte)\nFROM tabelle\nORDER BY spalte [ASC|DESC]\nLIMIT n;",
intro:"<div class=\"ns-intro-title\">📊 Die Sortiermaschine und der Taschenrechner: <code>ORDER BY</code> · <code>LIMIT</code> · Aggregatfunktionen</div><b>Wozu brauchst du das überhaupt?</b> Eine Tabelle liefert dir ihre Zeilen normalerweise in einem völlig chaotischen Haufen aus dem Lagerhaus. Willst du die teuersten Produkte ganz oben sehen oder nur die \"Top 3\" anzeigen? Dann brauchst du deine Sortiermaschine (<code>ORDER BY</code> und <code>LIMIT</code>).<br><br>Willst du hingegen nicht jedes einzelne Produkt sehen, sondern wissen, wie viele es insgesamt gibt oder was der Durchschnittspreis ist? Dann brauchst du sogenannte Aggregatfunktionen – das ist dein eingebauter Taschenrechner, der viele einzelne Zeilen zu einem einzigen Wert zusammenfasst.",
detailHeading:"🤓 Gut zu wissen: Deine kleinen Retter im Alltag",
lesson:[
{title:"ORDER BY (Die Sortiermaschine)",
was:"Er legt die Reihenfolge deiner Ergebniszeilen fest (aufsteigend oder absteigend).",
einfach:"Ohne `ORDER BY` wirft dir die Datenbank die Ergebnisse einfach in irgendeiner Reihenfolge vor die Füße. Du willst Struktur? Dieser Befehl sortiert alles sauber durch. Der Standard ist aufsteigend (klein nach groß, A bis Z). Willst du es umdrehen (z.B. teuerste Bücher zuerst), hängst du einfach ein `DESC` (für \"descending\" = absteigend) an.",
syntax:"ORDER BY spalte DESC",
beispiele:[{code:"SELECT title, price FROM titles ORDER BY price DESC;", note:"(Ergebnis: Holt dir Titel und Preis, und sortiert sie so, dass das allerteuerste Buch ganz oben steht.)"}]},
{title:"LIMIT (Der Türsteher für die Top-Listen)",
was:"Er schneidet dein Ergebnis nach einer von dir bestimmten Anzahl von Zeilen einfach ab.",
einfach:"Manchmal willst du keine riesige Liste mit tausenden Einträgen, sondern nur die \"Top 3\". `LIMIT` macht genau das. Ganz wichtig: Die Datenbank sortiert immer zuerst und schneidet danach ab – niemals umgekehrt!",
syntax:"LIMIT zahl",
beispiele:[{code:"ORDER BY price DESC LIMIT 3;", note:"(Ergebnis: Sortiert zuerst nach dem höchsten Preis und zeigt dir dann nur die obersten 3 Zeilen – deine Top 3!)"}]},
{title:"Aggregatfunktionen (`COUNT`, `SUM`, `AVG`, `MIN`, `MAX`)",
was:"Sie fassen viele Zeilen zu einem einzigen mathematischen Ergebnis zusammen.",
einfach:"Das ist dein Taschenrechner! `COUNT` zählt durch, wie viele Zeilen es gibt. `SUM` addiert alle Werte zusammen. `AVG` (Average) rechnet den Durchschnitt aus. `MIN` und `MAX` suchen dir den kleinsten oder größten Wert raus. Wichtig: Du siehst danach keine einzelnen Bücher mehr, sondern nur noch die fertige Rechnung!",
syntax:"FUNKTION(spalte)",
beispiele:[{code:"SELECT MAX(price), AVG(price) FROM titles;", note:"(Ergebnis: Gibt dir genau eine einzige Zeile zurück – nämlich den Preis des allerteuersten Buches und den Durchschnittspreis aller Bücher.)"}]},
{title:"Die Tücke beim Zählen: `COUNT(*)` vs. `COUNT(spalte)`",
was:"`COUNT(*)` zählt wirklich jede Zeile, `COUNT(spalte)` überspringt hingegen die leeren Felder (NULL).",
einfach:"Erinnerst du dich an das leere Nichts (NULL)? Wenn du einfach nur `COUNT(*)` (mit dem Sternchen) sagst, zählt die Datenbank stumpf jede Zeile in deinem Lagerhaus durch, egal ob da Infos drin stehen oder nicht. Sagst du aber `COUNT(price)`, guckt die Datenbank ganz genau in die Preis-Spalte und zählt nur die Zeilen, wo auch wirklich ein Preis auf dem Etikett steht!",
syntax:"COUNT(*)",
beispiele:[{code:"SELECT COUNT(*), COUNT(price) FROM titles;", note:"(Ergebnis: Gibt dir z.B. 18 für alle Titel, aber nur 16 für Bücher mit einem echten Preis – 2 Bücher hatten gar keinen Preis hinterlegt und wurden ignoriert.)"}]},
{kind:"detail", title:"Tie-Breaker: Mehrere Spalten sortieren",
text:"Du kannst `ORDER BY` auch mehrere Spalten geben (durch Komma getrennt). Die erste Spalte ist der Chef und bestimmt die Hauptrichtung. Nur wenn es dort einen Gleichstand gibt (z.B. zwei Autoren aus dem gleichen Bundesstaat), wird die zweite Spalte als Tie-Breaker benutzt (z.B. um sie dann innerhalb des Bundesstaates noch einmal alphabetisch nach Nachnamen zu sortieren)."},
{kind:"detail", title:"Seiten blättern mit `OFFSET`",
text:"Stell dir vor, du baust Seite 2 eines Online-Shops. Du schreibst `LIMIT 3 OFFSET 3`. Das bedeutet: \"Überspringe die allerersten 3 Ergebnisse komplett und zeige mir dann erst die nächsten 3.\""},
{kind:"detail", title:"Schönere Zahlen mit `ROUND`",
text:"Funktionen wie `AVG` spucken oft wilde, unleserliche Kommazahlen aus. Mit `ROUND(AVG(price), 2)` rundest du dein Ergebnis sauber auf 2 Nachkommastellen ab. Lässt du die 2 am Ende einfach weg, rundet die Datenbank knallhart auf eine glatte, ganze Zahl."}
]},
{id:"pattern", icon:"🔎", color:"#ec4899", title:"LIKE · IN · BETWEEN",
concept:"= sucht einen exakten Wert. LIKE erlaubt Platzhalter (% = beliebig viele Zeichen, _ = genau ein Zeichen). IN prüft, ob ein Wert in einer Liste vorkommt (aber ohne Platzhalter). BETWEEN prüft einen Bereich inklusive beider Grenzen.",
example:"WHERE title LIKE '%ing'<br>→ Titel, die auf 'ing' enden<br><br>WHERE au_lname LIKE 'D___'<br>→ 4-Buchstaben-Nachnamen, die mit D beginnen<br><br>WHERE type IN ('business','psychology')<br>→ kurz für type='business' OR type='psychology'",
syntax:"SELECT ... FROM tabelle WHERE spalte LIKE 'muster%';\nSELECT ... FROM tabelle WHERE spalte IN (wert1, wert2, ...);\nSELECT ... FROM tabelle WHERE spalte BETWEEN wert1 AND wert2;",
intro:"<div class=\"ns-intro-title\">🔎 Die Spürhunde: <code>LIKE</code> · <code>IN</code> · <code>BETWEEN</code></div><b>Wozu brauchst du das überhaupt?</b> Bisher kennst du das Gleichheitszeichen (<code>=</code>). Das ist aber extrem streng: Es findet nur exakte, 100-prozentige Treffer. Was aber, wenn du nur weißt, dass ein Nachname mit \"M\" anfängt? Oder wenn du alle Preise zwischen 10 und 20 Euro sehen willst? Für diese weicheren Suchen brauchst du unsere drei Spürhunde: <code>LIKE</code> (für Text-Muster), <code>IN</code> (für Wunschlisten) und <code>BETWEEN</code> (für Zahlenbereiche).",
detailHeading:"🤓 Gut zu wissen: Deine kleinen Retter im Alltag",
lesson:[
{title:"LIKE (Der Muster-Sucher)",
was:"Er sucht nicht nach exakten Wörtern, sondern nach einem bestimmten Text-Muster, das du vorgibst.",
einfach:"Stell dir vor, du hast ein Wort auf der Zunge, aber dir fehlt ein Teil. `LIKE` nutzt dafür Platzhalter. Das Prozentzeichen `%` steht für \"hier dürfen beliebig viele Zeichen kommen (oder gar keine)\". Der Unterstrich `_` steht für \"hier fehlt exakt EIN Buchstabe\". (💡 Gut zu wissen: MySQL ist hier entspannt und unterscheidet standardmäßig nicht zwischen Groß- und Kleinschreibung.)",
syntax:"WHERE spalte LIKE 'muster'",
beispiele:[{code:"WHERE title LIKE '%ing';", note:"(Ergebnis: Findet alle Titel, die auf \"ing\" enden – ganz egal, was vorher im Text steht. Zum Beispiel 'The Psychology of Computer Cooking'.)"}]},
{title:"IN (Die Wunschliste)",
was:"Er prüft auf einen Schlag, ob ein Wert in einer von dir festgelegten Liste vorkommt.",
einfach:"Erinnerst du dich an den Kombinierer `OR`? Anstatt umständlich zu schreiben \"Ist es Buch A? ODER ist es Buch B? ODER ist es Buch C?\", schreibst du einfach eine bequeme Einkaufsliste in Klammern. `IN` hakt dann ab, ob das Produkt auf dieser Liste steht. Wichtig: Hier gibt es keine Platzhalter wie `%`, die Wörter müssen exakt passen!",
syntax:"WHERE spalte IN ('wert_1', 'wert_2', 'wert_3')",
beispiele:[{code:"WHERE type IN ('business', 'psychology');", note:"(Ergebnis: Gibt dir sofort alle Bücher, die entweder zur Kategorie Business oder zur Kategorie Psychologie gehören. Alles andere fliegt raus.)"}]},
{title:"BETWEEN...AND (Das Maßband)",
was:"Er prüft, ob ein Wert innerhalb eines bestimmten Bereichs liegt (inklusive der beiden Grenzen!).",
einfach:"Wenn du nach Produkten suchst, die \"zwischen 20 und 40 Euro\" kosten, sparst du dir mit `BETWEEN` eine Menge Tipparbeit. Das funktioniert mit Zahlen genauso gut wie mit Datumsangaben.<br><br>⚠️ Absolute Stolperfalle: Die kleinere Zahl muss immer zuerst stehen! Schreibst du es falsch herum (z.B. 40 bis 20), gibt dir die Datenbank kein einziges Ergebnis zurück, obwohl es logisch derselbe Bereich wäre.",
syntax:"WHERE spalte BETWEEN kleinere_zahl AND größere_zahl",
beispiele:[{code:"WHERE qty BETWEEN 20 AND 40;", note:"(Ergebnis: Gibt dir alle Bestellungen, bei denen die Menge im Bereich 20 bis 40 liegt. Bestellungen mit exakt 20 oder 40 sind da fest mit eingeschlossen!)"}]},
{kind:"detail", title:"Listen ausschließen mit `NOT IN`",
text:"Willst du eine ganze Liste von Dingen ausschließen? Das Ungleich-Zeichen (`!=`) funktioniert immer nur bei einem einzigen Wort. Für eine ganze Liste brauchst du `NOT IN`. Schreibst du `WHERE city NOT IN ('Oakland', 'Berkeley')`, fliegen alle Autor:innen aus diesen beiden Städten sofort aus deinem Ergebnis."},
{kind:"detail", title:"Zahlen mögen kein `LIKE`",
text:"Merke dir: `LIKE` ist nur für Text da! Versuche bitte nie, echte Zahlen damit zu filtern. Schreibst du `WHERE menge LIKE '2%'` in der Hoffnung, alle 20er-Mengen zu finden, sucht die Datenbank einfach nach Text, der mit der Ziffer 2 anfängt – und liefert dir fälschlicherweise auch 200, 2000 oder 250 aus. Nimm für Zahlen immer `=`, `<`, `>` oder `BETWEEN`!"}
]},
{id:"group_having", icon:"🗂️", color:"#10b981", title:"GROUP BY · HAVING",
concept:"GROUP BY fasst Zeilen mit gleichem Wert zu einer Gruppe zusammen. WHERE filtert VOR der Gruppierung einzelne Zeilen, HAVING filtert NACH der Gruppierung die fertigen Gruppen — meist anhand einer Aggregatfunktion (Sammelbegriff für COUNT, SUM, AVG, MIN, MAX: Funktionen, die viele Zeilen zu einem einzigen Wert zusammenfassen, z.B. 'wie viele Zeilen hat diese Gruppe'). Deshalb darf in WHERE keine Aggregatfunktion stehen — die ist an der Stelle noch gar nicht berechnet.",
example:"WHERE contract=1<br>→ filtert einzelne Zeilen (vor der Gruppierung)<br><br>GROUP BY state HAVING COUNT(*) > 3<br>→ filtert fertige Gruppen (nach der Gruppierung)",
syntax:"SELECT spalte, MIN|MAX|COUNT|SUM|AVG(spalte)\nFROM tabelle\n[WHERE zeilen_bedingung]\nGROUP BY spalte\n[HAVING gruppen_bedingung];",
intro:"<div class=\"ns-intro-title\">🗂️ Kisten packen und filtern: <code>GROUP BY</code> · <code>HAVING</code></div><b>Wozu brauchst du das überhaupt?</b> Oft willst du dir im Lagerhaus nicht jeden Artikel einzeln ansehen, sondern eine Zusammenfassung pro Kategorie haben. Du fragst dich zum Beispiel: \"Wie viele Autor:innen haben wir eigentlich in jedem Bundesstaat?\"<br><br>Um das herauszufinden, müssen wir die Daten erst in verschiedene Kisten sortieren (<code>GROUP BY</code>) und dann für jede Kiste einen Wert berechnen (z.B. mit unserem Taschenrechner <code>COUNT</code>).",
detailHeading:"🤓 Gut zu wissen: Deine kleinen Retter im Alltag",
lesson:[
{title:"GROUP BY (Der Kisten-Packer)",
was:"Er fasst alle Zeilen, die in einer Spalte denselben Wert haben, zu einer einzigen Gruppe zusammen.",
einfach:"`GROUP BY` sortiert deine Daten in Kisten. Kommen fünf Autor:innen aus Kalifornien (CA), packt der Befehl sie alle zusammen in die Kiste mit der Aufschrift \"CA\". Du bekommst am Ende für jede Kiste genau eine Ergebniszeile. Aus 23 einzelnen Autor:innen werden so ganz übersichtlich 8 Zeilen – eine für jeden Bundesstaat.",
syntax:"GROUP BY spalte",
beispiele:[{code:"SELECT state, COUNT(*) FROM authors GROUP BY state;", note:"(Ergebnis: Gibt dir genau 8 Zeilen zurück. In einer Spalte steht der Bundesstaat, in der anderen die Anzahl der Autor:innen, die in dieser Kiste liegen.)"}]},
{title:"Aggregatfunktionen im Einsatz (Der Kisten-Zähler)",
was:"Sie rechnen Werte (`COUNT`, `SUM`, `AVG`, `MIN`, `MAX`) für jede Gruppe getrennt aus.",
einfach:"Wenn du Daten in Kisten packst, musst du der Datenbank sagen, was sie mit dem Inhalt machen soll. Soll sie die Einträge zählen (`COUNT`)? Soll sie Preise addieren (`SUM`)?<br><br>⚠️ Die goldene Faustregel: Jede Spalte, die du ganz oben in deinem `SELECT` aufschreibst, muss entweder die Kiste selbst sein (also im `GROUP BY` stehen) oder sie muss eine Rechnung (Aggregatfunktion) sein. Sonst weiß die Datenbank nicht, welchen der vielen Werte in der Kiste sie dir zeigen soll!",
syntax:"FUNKTION(spalte)",
beispiele:[{code:"SELECT state, COUNT(*) FROM authors GROUP BY state;", note:"(Hier ist `COUNT(*)` die Aggregatfunktion – sie zählt fleißig durch, wie viele Zeilen in der jeweiligen State-Kiste stecken.)"}]},
{title:"HAVING (Der Türsteher für Kisten)",
was:"Er filtert die fertigen Gruppen, meistens anhand der berechneten Ergebnisse (wie COUNT oder SUM).",
einfach:"Du kennst bereits `WHERE` als Türsteher. Aber `WHERE` filtert einzelne Zeilen, bevor sie in die Kisten gepackt werden. Was ist, wenn du dir am Ende nur die Kisten ansehen willst, in denen mehr als 3 Leute stecken? Dafür gibt es `HAVING`. Es ist der Türsteher, der erst ganz am Ende die fertig gepackten Kisten kontrolliert. Deshalb dürfen Rechnungen wie `COUNT` auch nur in `HAVING` stehen, niemals in `WHERE`!",
syntax:"HAVING bedingung",
beispiele:[{code:"SELECT state, COUNT(*) FROM authors GROUP BY state HAVING COUNT(*) > 3;", note:"(Ergebnis: Von allen Bundesstaaten bleibt nur noch 'CA' übrig, weil alle anderen Staaten höchstens 2 Autor:innen in ihrer Kiste hatten.)"}]},
{kind:"detail", title:"Noch speziellere Kisten: Mehrspaltiges `GROUP BY`",
text:"Du kannst auch nach mehreren Spalten gleichzeitig gruppieren (einfach durch Komma trennen). Schreibst du `GROUP BY state, city`, baust du noch speziellere Kisten. Dann landen nicht mehr alle aus Kalifornien in einer großen Kiste, sondern es gibt eine Kiste für \"Kalifornien, Oakland\" und eine extra Kiste für \"Kalifornien, Berkeley\"."},
{kind:"detail", title:"Die unsichtbare Reihenfolge der Datenbank",
text:"Eine Datenbank arbeitet deine Befehle nicht in der Reihenfolge ab, in der du sie schreibst! Die echte, unsichtbare Reihenfolge ist:<br>`FROM` ➔ `WHERE` ➔ `GROUP BY` ➔ `HAVING` ➔ `SELECT` ➔ `ORDER BY` ➔ `LIMIT`.<br>Das erklärt auch logisch, warum du in `WHERE` noch nicht rechnen (`COUNT/SUM`) darfst: Das Kistenpacken (`GROUP BY`) und Zählen passiert erst danach!"}
]},
{id:"joins", icon:"🔗", color:"#3b82f6", title:"LEFT / RIGHT / INNER JOIN",
concept:"INNER JOIN zeigt nur Zeilen, die in BEIDEN Tabellen einen Treffer haben. LEFT JOIN zeigt ALLE Zeilen der linken Tabelle, auch ohne Treffer rechts (dann NULL). RIGHT JOIN macht dasselbe umgekehrt. ON erlaubt unterschiedliche Spaltennamen, USING nur wenn beide Tabellen die Spalte gleich benennen.",
example:"INNER JOIN titles+sales:<br>→ nur die 16 Titel, die tatsächlich verkauft wurden<br><br>LEFT JOIN titles+sales (titles zuerst):<br>→ alle 18 Titel, unverkaufte zeigen NULL bei qty",
syntax:"SELECT ...\nFROM tabelleA\n[INNER|LEFT|RIGHT] JOIN tabelleB ON tabelleA.spalte = tabelleB.spalte;",
diagram:"joins",
intro:"<div class=\"ns-intro-title\">🔗 Die Brückenbauer: <code>LEFT</code> / <code>RIGHT</code> / <code>INNER JOIN</code></div><b>Wozu brauchst du das überhaupt?</b> Daten liegen in deinem Lagerhaus fast nie in einer einzigen, riesigen Tabelle. Sie sind auf verschiedene Regale verteilt: Bücher stehen im Regal 'titles', Verkäufe im Regal 'sales'. Beide Regale teilen sich aber eine Gemeinsamkeit – die Artikelnummer (<code>title_id</code>). Mit einem <code>JOIN</code> baust du eine Brücke zwischen diesen Regalen. So kannst du dir mit einer einzigen Abfrage den Buchtitel und gleichzeitig seine Verkaufszahlen anzeigen lassen, als wären sie in einer Tabelle!",
detailHeading:"🤓 Gut zu wissen: Deine kleinen Retter und Stolperfallen",
lesson:[
{title:"INNER JOIN (Der strenge Brückenbauer)",
was:"Er zeigt nur Zeilen an, bei denen es auf beiden Seiten der Brücke einen echten Treffer gibt.",
einfach:"Der `INNER JOIN` (in MySQL oft einfach nur `JOIN` genannt) ist sehr streng. Er verknüpft dein Buch-Regal mit dem Verkaufs-Regal. Findet er ein Buch, das noch nie verkauft wurde? Dann wirft er es eiskalt aus dem Ergebnis! Es müssen zwingend auf beiden Seiten passende Daten vorhanden sein.",
syntax:"FROM tabelle_1 INNER JOIN tabelle_2 ON tabelle_1.spalte = tabelle_2.spalte",
tipp:"Praxistipp: Nutze kurze Spitznamen/Aliase wie `t` für titles und `s` für sales, das spart enorm viel Tipparbeit!",
beispiele:[{code:"SELECT t.title FROM titles t INNER JOIN sales s ON t.title_id = s.title_id;", note:"(Ergebnis: Zeigt dir nur die Titel, die auch wirklich verkauft wurden. Unverkaufte Bücher fallen hier komplett raus.)"}]},
{title:"LEFT JOIN (Das gutmütige Sicherheitsnetz)",
was:"Er behält alle Zeilen der linken Tabelle, auch wenn es in der rechten Tabelle gar keinen Treffer gibt.",
einfach:"`LEFT JOIN` ist dein Sicherheitsnetz. Wenn du sagst \"Zeig mir alle Bücher (links) und häng die Verkäufe dran (rechts)\", sorgt der `LEFT JOIN` dafür, dass kein einziges Buch verloren geht. Hat ein Buch keine Verkäufe? Dann bleibt es trotzdem in der Liste und bekommt in der Verkaufs-Spalte einfach ein leeres Nichts (`NULL`) eingetragen. (Ein `RIGHT JOIN` macht exakt dasselbe, nur spiegelverkehrt für die rechte Seite.)",
syntax:"FROM linke_tabelle LEFT JOIN rechte_tabelle ON linke_tabelle.spalte = rechte_tabelle.spalte",
beispiele:[{code:"SELECT t.title, s.qty FROM titles t LEFT JOIN sales s ON t.title_id = s.title_id;", note:"(Ergebnis: Zeigt dir wirklich alle Bücher. Bei den unverkauften Büchern steht in der Verkaufsmenge `qty` nun einfach `NULL`.)"}]},
{title:"Die Platzwahl (Wer kommt nach links?)",
was:"Die Basistabelle, aus der du alles sehen willst, steht immer links vom `LEFT JOIN`.",
einfach:"Eine praktische Faustregel für deine Übungsaufgaben: Wenn die Frage verlangt \"Zeige mir alle Titel, auch die unverkauften\", dann ist 'titles' ganz klar deine linke Basistabelle. Du schreibst also `titles LEFT JOIN sales`. Geht es in der Aufgabe aber um \"Zeige mir nur die Titel, die tatsächlich verkauft wurden\", dann reicht der strenge `INNER JOIN` völlig aus.",
syntax:"FROM tabelle_von_der_du_alles_willst LEFT JOIN andere_tabelle",
beispiele:[{label:"Aufgabe: \"Zeige mir alle Autor:innen\"", code:"FROM authors LEFT JOIN ..."}]},
{kind:"detail", title:"Der fatale Fehler ohne `ON`",
text:"Wenn du bei einem JOIN vergisst, die `ON`-Bedingung (die gemeinsame Brücke) anzugeben, meldet die Datenbank keinen Fehler! Stattdessen kombiniert sie völlig wild jede Zeile von links mit jeder Zeile von rechts. Bei 3 Autor:innen und 2 Verlagen hast du plötzlich 6 Zeilen völligen Unsinn (ein sogenanntes kartesisches Produkt). Das ist ein Logikfehler, kein Syntaxfehler – und deshalb besonders tückisch!"},
{kind:"detail", title:"Plötzlich Duplikate?",
text:"Wenn ein Buch vier verschiedene Verkäufe hat, taucht dieses eine Buch nach einem JOIN plötzlich viermal in deiner Liste auf! Das ist kein Fehler, sondern völlig normal: Die Datenbank zeigt dir die linke Zeile (das Buch) genau so oft an, wie sie rechts Treffer (Verkäufe) findet. Erst ein `GROUP BY` packt das später bei Bedarf wieder in eine einzige Zeile zusammen."},
{kind:"detail", title:"Die Abkürzung: `USING` statt `ON`",
text:"Wenn die Verbindungs-Spalte in beiden Tabellen exakt gleich heißt (z.B. beide heißen `pub_id`), kannst du dir Tipparbeit sparen. Statt `ON titles.pub_id = publishers.pub_id` schreibst du einfach kurz `USING(pub_id)`. Heißen die Spalten unterschiedlich, musst du zwingend `ON` verwenden."}
]},
{id:"case", icon:"🧩", color:"#eab308", title:"CASE WHEN",
concept:"CASE WHEN erstellt eine neue Spalte mit eigener Wenn-dann-sonst-Logik: WENN eine Bedingung zutrifft, DANN dieser Wert, SONST (ELSE) ein anderer. SQL prüft die Bedingungen der Reihe nach und nimmt die erste, die passt.",
example:"CASE<br>WHEN qty >= 50 THEN 'high'<br>WHEN qty >= 20 THEN 'medium'<br>ELSE 'low' END<br><br>Zeile mit qty=60 → landet in 'high'<br>(obwohl 'qty >= 20' auch zuträfe — SQL stoppt bei der ersten Treffer-Bedingung)",
syntax:"SELECT spalte,\n CASE\n WHEN bedingung1 THEN wert1\n WHEN bedingung2 THEN wert2\n ELSE wert3\n END AS neue_spalte\nFROM tabelle;",
intro:"<div class=\"ns-intro-title\">🧩 Die Ampel-Logik: <code>CASE WHEN</code></div><b>Wozu brauchst du das überhaupt?</b> Ein normales <code>SELECT</code> zeigt dir immer nur die rohen Daten, die sowieso schon in deinem Lagerhaus liegen. Oft willst du diese Daten aber bewerten und einschätzen: Ist eine Bestellmenge von 60 Stück \"GROSS\", \"MITTEL\" oder \"KLEIN\"? Diese Kategorie steht nirgends in der Datenbank – du musst sie ihr erst beibringen!<br><br>Dafür gibt es <code>CASE WHEN</code>. Das ist die Wenn-Dann-Sonst-Logik von SQL. Stell es dir vor wie eine Ampel: WENN eine bestimmte Bedingung zutrifft, DANN nimm diesen Wert, SONST nimm einen anderen. Das Ergebnis taucht am Ende als eine ganz normale, brandneue Spalte in deinem Schaufenster auf.",
detailHeading:"🤓 Gut zu wissen: Deine kleinen Retter im Alltag",
lesson:[
{title:"CASE WHEN (Die neue Spalte bauen)",
was:"Er erstellt anhand von eigenen Regeln eine komplett neue Ergebnis-Spalte für deine Ausgabe.",
einfach:"Du schreibst `CASE` genau dorthin in deine Einkaufsliste (`SELECT`), wo auch normale Spalten (wie Vorname oder Preis) stehen. Dann legst du mit `WHEN` (Wenn) deine Bedingung fest. Trifft sie zu, sagst du der Datenbank mit `THEN` (Dann), welches Wort dort stehen soll. Am Ende musst du zwingend mit `END` sagen, dass deine Ampel-Regel jetzt fertig ist. Wie immer klebst du mit `AS` noch ein schickes Preisschild (einen Namen) an deine neue Spalte.",
syntax:"CASE WHEN bedingung THEN 'wert' END AS neuer_spaltenname",
beispiele:[{code:"SELECT qty, CASE WHEN qty >= 50 THEN 'high' ELSE 'low' END AS kategorie FROM sales;", note:"(Ergebnis: Zeigt dir die echte Menge und zaubert direkt daneben eine neue Spalte namens \"kategorie\", in der automatisch \"high\" oder \"low\" steht.)"}]},
{title:"Die Reihenfolge (Der Flur mit offenen Türen)",
was:"Er prüft mehrere `WHEN`-Regeln streng von oben nach unten und stoppt sofort beim allerersten Treffer.",
einfach:"Wenn du mehrere Regeln aufstellst, geht SQL sie strikt von oben nach unten durch. Stell dir einen Flur mit mehreren Türen vor: SQL geht Tür für Tür entlang und bleibt an der allerersten offenen Tür stehen. Alles, was danach kommt, wird gar nicht mehr angesehen!<br><br>⚠️ Wichtige Regel: Die genaueste Bedingung muss immer ganz oben stehen! Sonst schnappt sich eine zu allgemeine Tür weiter oben schon alle deine Treffer weg.",
syntax:"CASE \n WHEN bedingung_1 THEN 'wert_1' \n WHEN bedingung_2 THEN 'wert_2' \nEND",
beispiele:[{code:"CASE \n WHEN qty >= 50 THEN 'high' \n WHEN qty >= 20 THEN 'medium' \n ELSE 'low' \nEND", note:"(Ergebnis: Bei einer Bestellmenge von 60 stoppt SQL sofort an Tür 1 (\"high\"). Bei einer Menge von 32 ist Tür 1 zu, SQL geht weiter und stoppt erfolgreich an Tür 2 (\"medium\").)"}]},
{title:"ELSE (Der Auffangkorb)",
was:"Er definiert den Standard-Wert für alle Zeilen, bei denen keine einzige deiner `WHEN`-Regeln zutrifft.",
einfach:"`ELSE` (Sonst) ist dein sicherer Auffangkorb ganz am Ende des Flurs. Wenn keine einzige Tür für einen Datensatz offen war, fällt die Zeile automatisch hier hinein.<br><br>Was passiert, wenn du diesen Korb weglässt? Dann fallen die übrig gebliebenen Zeilen einfach ins Leere und in deiner neuen Spalte steht das absolute Nichts: NULL. Lass das `ELSE` also nur dann weg, wenn du wirklich ganz bewusst leere Felder erzeugen möchtest.",
syntax:"ELSE 'standard_wert'",
beispiele:[{code:"CASE WHEN state = 'CA' THEN 'West' END AS region", note:"(Ergebnis: Hier hast du den Auffangkorb vergessen! Alle Autor:innen aus Kalifornien bekommen brav das Wort \"West\", aber alle anderen Staaten bekommen knallhart ein leeres `NULL` eingetragen.)"}]},
{kind:"detail", title:"Die Abkürzung: Simple CASE",
text:"Wenn du keine komplexen Größer-Kleiner-Rechnungen machst, sondern nur auf absolute Gleichheit prüfst (z.B. \"Ist es eine 9? Ist es eine 10?\"), geht das auch kürzer. Du schreibst den Namen der Spalte direkt hinter das `CASE` und prüfst dann nur noch die Ergebnisse ab: `CASE grade WHEN 9 THEN 'Freshman' WHEN 10 THEN 'Sophomore' END`. Das spart ungemein viel Tipparbeit! (💡 Tipp: Auch ein `IN ('wort1', 'wort2')` funktioniert wunderbar innerhalb einer `WHEN`-Regel, um mehrere Werte auf einmal abzufangen!)"},
{kind:"detail", title:"Kisten packen mit der neuen Spalte (`GROUP BY`)",
text:"Du kannst deine selbstgebaute `CASE`-Spalte direkt nutzen, um deine Daten in neue Kisten zu sortieren! Du schreibst deinen ganzen `CASE`-Block dafür einfach unten ins `GROUP BY`. So kannst du dir am Ende wunderbar zusammenrechnen lassen, wie viele Verkäufe in deiner Kategorie \"high\" und wie viele in \"low\" gelandet sind."}
]},
{id:"subquery", icon:"🪆", color:"#a855f7", title:"Subqueries",
concept:"Eine Subquery ist eine Abfrage in einer Abfrage, meist in Klammern. Sie wird zuerst berechnet, ihr Ergebnis wird dann außen benutzt (mit =, IN oder als Vergleichswert). Eine correlated Subquery verweist zusätzlich auf eine Spalte der äußeren Abfrage und läuft deshalb für jede Zeile neu.",
example:"WHERE price = (SELECT MAX(price) FROM titles) funktioniert nur, wenn die Subquery genau EINEN Wert liefert. Liefert sie mehrere Werte, brauchst du IN statt =.",
syntax:"SELECT ... FROM tabelle\nWHERE spalte = (SELECT ... FROM ... );\n\nSELECT ... FROM tabelle\nWHERE spalte IN (SELECT ... FROM ... );",
intro:"<div class=\"ns-intro-title\">🪆 Die Matroschka-Puppen: Subqueries</div><b>Wozu brauchst du das überhaupt?</b> Manchmal brauchst du für eine Bedingung erst das Ergebnis einer ganz anderen Abfrage. Ein Beispiel: \"Zeig mir das teuerste Buch\". Das Problem? Du weißt vorher gar nicht, wie hoch dieser Preis genau ist!<br><br>Eine Subquery (Unterabfrage) löst genau dieses Problem. Sie ist eine Abfrage in einer Abfrage, fast immer versteckt in Klammern (wie eine russische Matroschka-Puppe). Sie wird heimlich zuerst berechnet, und ihr Ergebnis wird danach in deiner eigentlichen Hauptabfrage weiterbenutzt.",
detailHeading:"🤓 Gut zu wissen: Deine kleinen Retter im Alltag",
lesson:[
{title:"Die Klammer-Regel (Die versteckte Vorab-Rechnung)",
was:"Er führt eine versteckte Vorab-Rechnung aus, deren Ergebnis dann im Hauptbefehl als Filter genutzt wird.",
einfach:"Die Subquery steht meistens in Klammern. Die Datenbank ist schlau und löst immer zuerst die Rechnung in der Klammer auf. Sobald sie das Ergebnis der Klammer hat, setzt sie diesen fertigen Wert einfach in deine Hauptabfrage ein und macht mit der eigentlichen Arbeit weiter.",
syntax:"WHERE spalte = (SELECT spalte FROM tabelle)",
beispiele:[{code:"SELECT title FROM titles WHERE price = (SELECT MAX(price) FROM titles);", note:"(Ergebnis: Die Klammer sucht zuerst heimlich nach dem höchsten Preis, z.B. 22.95. Danach filtert die äußere Hauptabfrage ganz normal nach dem Buch, das exakt diese 22.95 kostet.)"}]},
{title:"`=` vs. `IN` (Wie viele Werte kommen zurück?)",
was:"Das Gleichheitszeichen `=` funktioniert nur bei einem einzigen Wert. `IN` brauchst du zwingend, wenn die Klammer mehrere Werte ausspucken könnte.",
einfach:"Liefert deine Vorab-Rechnung in der Klammer garantiert nur eine einzige Zahl (wie beim allerhöchsten Preis)? Dann reicht ein normales `=`.<br><br>Wenn deine Klammer aber eine ganze Liste von Werten zurückgeben kann (z.B. alle Verlags-IDs aus den USA), verschluckt sich das `=` und die Datenbank wirft einen Fehler. Nutze in diesem Fall stattdessen `IN` (unsere bekannte Wunschliste), um die Treffer abzugleichen.",
syntax:"WHERE spalte IN (SELECT spalte FROM tabelle WHERE bedingung)",
beispiele:[{code:"WHERE pub_id IN (SELECT pub_id FROM publishers WHERE country = 'USA');", note:"(Ergebnis: Da es mehrere Verlage in den USA geben kann, liefert die Klammer eine ganze Liste von IDs. Das IN verarbeitet diese Liste dann fehlerfrei.)"}]},
{title:"`NOT IN` (Die Fehlenden finden)",
was:"Er findet gezielt die Datensätze, die in einer anderen Tabelle nicht existieren.",
einfach:"Das ist eine der praktischsten Anwendungen im Arbeitsalltag! Willst du wissen, welche Bücher noch nie verkauft wurden? Du lässt die Klammer einfach alle Buch-IDs aus der Verkaufs-Tabelle sammeln. Mit `NOT IN` sagst du der Hauptabfrage dann: \"Zeig mir alle Titel, die NICHT auf dieser Verkaufs-Liste stehen!\"",
syntax:"WHERE spalte NOT IN (SELECT spalte FROM andere_tabelle)",
beispiele:[{code:"SELECT title FROM titles WHERE title_id NOT IN (SELECT title_id FROM sales);", note:"(Ergebnis: Spuckt dir genau die traurigen Bücher aus, die bisher keinen einzigen Eintrag im Verkaufs-Regal hatten.)"}]},
{kind:"detail", title:"Subqueries als völlig neue Spalte",
text:"Unterabfragen müssen nicht zwingend unten im `WHERE`-Filter stehen. Du kannst sie auch ganz oben in deine `SELECT`-Einkaufsliste packen, um eine neue, berechnete Spalte zu erzeugen! Zum Beispiel, um den Preis jedes einzelnen Buches mit dem Durchschnittspreis aller Bücher zu vergleichen. Wichtig: Wenn eine Subquery im `SELECT`-Teil steht, musst du ihr am Ende zwingend mit `AS` einen neuen Namen geben."},
{kind:"detail", title:"Die gekoppelte Subquery (Correlated)",
text:"Normale Subqueries laufen nur ein einziges Mal ab. Es gibt aber auch spezielle Versionen, die direkt auf eine Spalte der Hauptabfrage verweisen. Diese laufen dann wie in einer Endlosschleife für jede einzelne Zeile deiner Hauptabfrage immer wieder neu ab! Das ist extrem nützlich, wenn du zum Beispiel für jeden einzelnen Autor individuell zählen willst, wie viele Bücher er geschrieben hat."}
]},
{id:"functions", icon:"🧮", color:"#14b8a6", title:"Funktionen (Text & Datum)",
concept:"String-Funktionen (LENGTH, UPPER, CONCAT, LEFT) verändern Text, Datumsfunktionen (DATEDIFF, TIMESTAMPDIFF, DATE_FORMAT) rechnen mit Datumswerten. Meist im SELECT-Teil, um Daten lesbarer zu machen oder neue berechnete Spalten zu erzeugen.",
example:"DATEDIFF(a, b) = a MINUS b in Tagen<br><br>DATEDIFF(heute, pubdate)<br>→ positiv (Buch liegt in der Vergangenheit)<br><br>DATEDIFF(pubdate, heute)<br>→ negativ (umgekehrte Reihenfolge)",
syntax:"SELECT LENGTH|UPPER|LOWER|CONCAT|LEFT(spalte, n)\nFROM tabelle;\n\nSELECT DATEDIFF(a,b) | TIMESTAMPDIFF(einheit,a,b) | DATE_FORMAT(spalte,muster)\nFROM tabelle;",
intro:"<div class=\"ns-intro-title\">🧮 Werkzeuge für Text & Datum: Der Feinschliff für deine Daten</div><b>Wozu brauchst du das überhaupt?</b> Rohdaten in einer Tabelle sind selten schon so, wie du sie am Ende im Schaufenster (deinem Ergebnis) präsentieren willst. Oft stehen Vor- und Nachname in getrennten Spalten oder ein Datum hat das völlig falsche Format. Mit Text- und Datumsfunktionen polierst du diese Werte direkt im <code>SELECT</code>-Teil auf, ohne die echten Daten im Lagerhaus anzufassen. Du änderst nur die finale Anzeige!",
detailHeading:"🤓 Gut zu wissen: Deine kleinen Retter im Alltag",
lesson:[
{title:"Text-Werkzeuge (String-Funktionen)",
was:"Sie verändern, kombinieren oder beschneiden Text direkt in deiner Ausgabe, um Daten lesbarer zu machen.",
einfach:"<br>• `CONCAT` ist dein Kleber: Es fügt mehrere Texte zusammen. Wichtig: Du musst das Leerzeichen als eigenen Baustein mit in den Kleber mischen!<br>• `UPPER` und `LOWER` zwingen deinen Text in reine Groß- oder Kleinschreibung.<br>• `LENGTH` zählt ganz simpel die Zeichenanzahl eines Wortes.<br>• `LEFT` (oder `SUBSTRING`) schneidet dir ein genaues Teilstück aus dem Text heraus.",
syntax:"CONCAT(spalte_1, ' ', spalte_2)\nUPPER(spalte)\nLENGTH(spalte)\nLEFT(spalte, anzahl_zeichen)",
beispiele:[{label:"`CONCAT`:", code:"SELECT CONCAT(au_fname, ' ', au_lname) AS name FROM authors;", note:"(Ergebnis: Klebt Vor- und Nachname zu 'Johnson White' zusammen. Ohne das Leerzeichen in der Mitte hieße es fälschlicherweise 'JohnsonWhite'.)"}]},
{title:"Datums-Werkzeuge",
was:"Sie nehmen dir die nervige Mathearbeit mit Zeiträumen ab oder formatieren Datumsangaben um.",
einfach:"<br>• `DATEDIFF` rechnet stumpf \"Datum A minus Datum B\" in Tagen. Die Reihenfolge der Werte in der Klammer entscheidet darüber, ob das Vorzeichen am Ende positiv oder negativ ist!<br>• `TIMESTAMPDIFF` ist der große Bruder: Hier rechnest du nicht nur in Tagen, sondern darfst die Einheit (DAY, MONTH, YEAR) frei wählen.<br>• `DATE_FORMAT` bringt ein hässliches Computer-Datum in ein Muster, das Menschen gerne lesen.",
syntax:"DATEDIFF(datum_a, datum_b)\nTIMESTAMPDIFF(einheit, datum_a, datum_b)",
beispiele:[{label:"`DATEDIFF`:", code:"DATEDIFF(CURDATE(), pubdate)", note:"(Ergebnis: Rechnet das heutige Datum `CURDATE()` minus das Erscheinungsdatum `pubdate`. Das Ergebnis ist eine positive Zahl, weil das Erscheinen des Buches logischerweise in der Vergangenheit liegt.)"}]},
{kind:"detail", title:"Der Lückenfüller: `COALESCE` / `IFNULL`",
text:"NULL-Werte (also leere Felder) sehen in einer fertigen Ausgabe extrem unschön aus und verwirren den Leser. `COALESCE` (oder `IFNULL`) ist dein Lückenfüller. Du sagst damit: \"Wenn in dieser Spalte NULL steht, zeig stattdessen bitte eine 0 oder einen Ersatzwert.\" Die echte Tabelle bleibt völlig unverändert. So sieht's aus: `SELECT title, COALESCE(price, 0) FROM titles;` (Macht aus einem fehlenden Preis sauber eine 0 statt dem Wort NULL)."},
{kind:"detail", title:"Die Tücke beim Zählen: `LENGTH` vs. `CHAR_LENGTH`",
text:"Ein fieses Detail im Alltag mit echtem MySQL: Die Funktion `LENGTH` zählt eigentlich nicht die sichtbaren Buchstaben, sondern den verbrauchten Speicherplatz (Bytes). Bei englischem Text ist das völlig egal. Aber bei Sonderzeichen wie Umlauten (z.B. 'ü' oder 'ä') verbraucht ein Buchstabe plötzlich zwei Bytes! Bei dem Namen 'Müller' würde `LENGTH` dir also fälschlicherweise eine 7 ausspucken. Wenn du zuverlässig tatsächliche Buchstaben zählen willst, nutze im Zweifel immer `CHAR_LENGTH()`."}
]},
{id:"advanced", icon:"🏆", color:"#ef4444", title:"Advanced Mix (+ Bonus)",
concept:"Hier kombinierst du alles: mehrere JOINs, Subqueries, GROUP BY und Rechenoperationen (+ - * / %) in einer Abfrage. Zerlege die Aufgabe in kleine Schritte und teste jeden Schritt einzeln, bevor du alles zusammensetzt.",
example:"Umsatz pro Buch berechnen: erst den JOIN allein testen, dann price * qty hinzufügen, dann erst GROUP BY und SUM().",
syntax:"-- Baukasten, je nach Aufgabe kombiniert:\nSELECT spalte, AGG_FUNKTION(a.spalte * b.spalte)\nFROM tabelleA a\nJOIN tabelleB b ON a.id = b.id\nWHERE spalte % 2 = 0\nGROUP BY spalte\nHAVING AGG_FUNKTION(...) > wert;",
intro:"<b>Wozu brauchst du das überhaupt?</b> Die bisherigen Themen einzeln reichen oft nicht für echte Fragen — 'wie viel Umsatz hat jeder Titel gemacht?' braucht gleichzeitig einen JOIN (Titel mit Verkauf verbinden), eine Rechnung (price × qty) und GROUP BY (pro Titel zusammenfassen). Hier kombinierst du alles, was du bisher gelernt hast, in einer einzigen Abfrage.",
worked:{
note:"Umsatz pro Titel (price × qty, aufsummiert über alle Verkäufe) — kombiniert JOIN, Rechnen und GROUP BY:",
headers:["title","Umsatz (SUM(price*qty))"],
rows:[["Is Anger the Enemy?","1182.60"],["Secrets of Silicon Valley","1000.00"],["Onions, Leeks, and Garlic...","838.00"]],
highlightCol:1
},
lesson:[
{t:"Rechenoperatoren: + - * / %", merk:"% (Modulo) ist der Rest einer Division — praktisch für gerade/ungerade.", b:"SQL kann direkt rechnen: + - * / und % (Modulo, der Rest einer Division — praktisch um gerade/ungerade Zahlen zu prüfen).", ex:"WHERE qty % 2 = 0;\n→ 10 von 21 Bestellungen haben eine gerade Menge\n\nprice * qty\n→ Umsatz einer einzelnen Verkaufszeile"},
{t:"Strategie: Schritt für Schritt aufbauen", merk:"Erst Teilschritte einzeln testen, dann erst zusammensetzen.", b:"Schreib nicht die ganze komplexe Query auf einmal. Baue sie in kleinen, testbaren Schritten auf und prüfe nach jedem Schritt, ob das Zwischenergebnis plausibel aussieht.", ex:"Umsatz pro Titel:\n1) JOIN allein testen (titles + sales)\n2) price*qty als neue Spalte hinzufügen\n3) erst dann GROUP BY + SUM() ergänzen\n\n→ Ergebnis: die Tabelle oben"},
{t:"Mehrere JOINs kombinieren", merk:"Bei mehreren JOINs: eine Verbindung nach der anderen denken.", b:"Für komplexere Fragen brauchst du oft eine Kette aus 2-3 JOINs über mehrere Tabellen hinweg.", ex:"titles → sales → stores:\nSELECT st.stor_name, t.title\nFROM titles t\nJOIN sales s ON t.title_id=s.title_id\nJOIN stores st ON s.stor_id=st.stor_id;\n\n→ verbindet Titel, Verkauf UND Buchhandlung in einer Abfrage"},
{t:"Weitere Rechenfunktionen (Bonus)", kind:"detail", merk:"ABS, CEIL, FLOOR, POWER, SQRT — für Sonderfälle beim Rechnen.", b:"Neben ROUND() gibt es noch ein paar weitere eingebaute Rechenfunktionen, die dir seltener, aber ab und zu begegnen: ABS() (macht negative Zahlen positiv), CEIL() (rundet immer AUF), FLOOR() (rundet immer AB), POWER(zahl, hoch) (Potenz) und SQRT() (Quadratwurzel).", ex:"SELECT CEIL(4.2), FLOOR(4.8), POWER(2,3), SQRT(9);\n→ ergibt 5, 4, 8, 3"}
]},
{id:"self_join", icon:"🪞", color:"#f97316", title:"Self Join",
concept:"Ein Self Join verbindet eine Tabelle mit sich selbst — technisch dieselbe JOIN-Syntax wie immer, nur dass beide Seiten aus derselben Tabelle kommen. Über zwei Aliase (z.B. a und b) behandelst du sie wie zwei getrennte Tabellen. Eine Zusatzbedingung wie a.id < b.id verhindert, dass eine Zeile sich selbst matcht und dass Paare doppelt erscheinen.",
example:"FROM authors a JOIN authors b ON a.au_lname = b.au_lname AND a.au_id < b.au_id<br>→ findet Autor:innen-Paare mit demselben Nachnamen, jedes Paar nur einmal",
syntax:"SELECT a.spalte, b.spalte\nFROM tabelle a\nJOIN tabelle b ON a.gemeinsamkeit = b.gemeinsamkeit AND a.id < b.id;",
intro:"<b>Wozu brauchst du das überhaupt?</b> Bisher hast du IMMER zwei VERSCHIEDENE Tabellen mit JOIN verbunden (z.B. titles mit publishers). Ein Self Join ist ungewöhnlich, weil du dieselbe Tabelle mit SICH SELBST verbindest — z.B. um innerhalb von 'authors' herauszufinden, welche zwei Autor:innen denselben Nachnamen haben. Das klingt zunächst verwirrend, ist aber technisch nichts Neues: du benutzt exakt dieselbe JOIN-Syntax wie immer, nur dass beide Seiten des JOINs zufällig aus derselben Tabelle kommen.",
worked:{
note:"Die Tabelle 'authors' zweimal gleichzeitig benutzt (einmal als 'a', einmal als 'b') — gesucht: gleicher Nachname, unterschiedliche Person:",
headers:["a.au_fname","a.au_lname","b.au_fname","b.au_lname"],
rows:[["Anne","Ringer","Albert","Ringer"]],
},
lesson:[
{t:"Der Trick: dieselbe Tabelle zweimal benutzen, mit zwei Aliasen", merk:"Du gibst derselben Tabelle zwei verschiedene Alias-Namen — SQL behandelt sie dann wie zwei getrennte Tabellen.", b:"Ein Self Join sieht syntaktisch aus wie ein ganz normaler JOIN — der einzige Unterschied: FROM und JOIN nennen BEIDE dieselbe Tabelle, z.B. authors. Damit SQL (und du selbst) die beiden Seiten auseinanderhalten kann, gibst du jeder ein eigenes Alias, z.B. 'a' und 'b'. Ab da tust du einfach so, als wären es zwei komplett unabhängige Tabellen.", ex:"FROM authors a\nJOIN authors b ON a.au_lname = b.au_lname\n\n→ 'a' und 'b' sind beide die Tabelle authors, SQL behandelt sie trotzdem getrennt"},
{t:"Die ON-Bedingung: was soll übereinstimmen?", merk:"Die ON-Bedingung bei Self Join ist meist eine inhaltliche Gemeinsamkeit, kein ID-Feld.", b:"Anders als bei normalen JOINs (die meist über eine ID-Spalte verknüpfen) verbindest du bei einem Self Join oft über eine inhaltliche Spalte — hier: 'hat denselben Nachnamen'.", ex:"ON a.au_lname = b.au_lname\n\n→ verbindet jede Zeile mit jeder anderen Zeile, die denselben Nachnamen hat"},
{t:"Die Stolperfalle: ohne Zusatzbedingung matcht jede Zeile sich selbst", merk:"a.id < b.id verhindert, dass eine Zeile sich selbst matcht und dass Paare doppelt erscheinen.", b:"Ohne weitere Einschränkung matcht z.B. Anne Ringer auch MIT SICH SELBST (au_lname='Ringer' = au_lname='Ringer' ist für die gleiche Zeile logisch wahr) — das ist nutzlos. Und ohne Einschränkung würde jedes Paar zweimal auftauchen (einmal als a=Anne/b=Albert, einmal umgekehrt als a=Albert/b=Anne). Die Lösung: eine zusätzliche Bedingung wie a.au_id < b.au_id — sie schließt den Vergleich mit sich selbst aus UND lässt jedes Paar nur einmal übrig.", ex:"SELECT a.au_fname, a.au_lname, b.au_fname, b.au_lname\nFROM authors a\nJOIN authors b ON a.au_lname = b.au_lname AND a.au_id < b.au_id;\n\n→ genau ein Treffer: Anne Ringer + Albert Ringer (das einzige Paar in dieser Datenbank)"}
]},
{id:"union", icon:"🔀", color:"#84cc16", title:"UNION",
concept:"UNION stapelt die Ergebnisse von zwei SELECT-Abfragen untereinander (mehr Zeilen), statt sie wie JOIN nebeneinanderzulegen (mehr Spalten). Beide SELECTs brauchen dieselbe Anzahl Spalten. UNION entfernt Duplikate automatisch, UNION ALL behält jede Zeile.",
example:"SELECT pub_id FROM titles UNION ALL SELECT pub_id FROM employee<br>→ 61 Zeilen (mit Duplikaten)<br><br>SELECT pub_id FROM titles UNION SELECT pub_id FROM employee<br>→ 8 Zeilen (jeder Verlag nur einmal)",
syntax:"SELECT spalte FROM tabelleA\nUNION [ALL]\nSELECT spalte FROM tabelleB\n[ORDER BY spalte];",
intro:"<b>Wozu brauchst du das überhaupt?</b> Ein JOIN verbindet zwei Tabellen NEBENEINANDER (mehr Spalten pro Zeile). UNION dagegen stapelt die Ergebnisse von zwei SELECT-Abfragen UNTEREINANDER (mehr Zeilen, gleiche Spalten) — als wären es von Anfang an eine einzige Abfrage gewesen. Typischer Einsatz: du willst zwei Listen aus unterschiedlichen Tabellen zu EINER gemeinsamen Liste zusammenfassen, z.B. 'alle Verlage, die entweder ein Buch ODER Mitarbeitende haben' in einer einzigen Spalte.",
worked:{
note:"pub_id aus 'titles' UND aus 'employee' — mit UNION zu einer Liste zusammengefasst, ohne Duplikate:",
headers:["Abfrage","Anzahl Zeilen im Ergebnis"],
rows:[["... UNION ALL ...","61 (alle Zeilen, mit Duplikaten)"],["... UNION ...","8 (jeder Verlag nur einmal)"]],
highlightCol:1
},
lesson:[
{t:"UNION stapelt zwei Abfragen untereinander", merk:"UNION braucht in beiden SELECTs die GLEICHE Anzahl Spalten, in der gleichen Bedeutung.", b:"Bei UNION schreibst du zwei komplette SELECT-Abfragen und verbindest sie mit dem Schlüsselwort UNION dazwischen. Wichtig: beide SELECTs müssen die gleiche ANZAHL Spalten liefern (die Spaltennamen dürfen unterschiedlich sein, das Ergebnis übernimmt einfach die Namen der ERSTEN Abfrage).", ex:"SELECT pub_id FROM titles\nUNION\nSELECT pub_id FROM employee;\n\n→ eine einzige Spalte 'pub_id', mit Zeilen aus BEIDEN Tabellen"},
{t:"UNION entfernt Duplikate automatisch, UNION ALL nicht", merk:"UNION = wie DISTINCT über beide Abfragen hinweg. UNION ALL behält jede Zeile, auch doppelte.", b:"UNION vergleicht das komplette Ergebnis und entfernt doppelt vorkommende Zeilen — genau wie DISTINCT, nur über zwei Abfragen hinweg statt über eine. UNION ALL macht das NICHT: es hängt einfach alle Zeilen aneinander, Duplikate inklusive. UNION ALL ist außerdem schneller, weil SQL sich die Dedup-Arbeit spart.", ex:"SELECT pub_id FROM titles UNION ALL SELECT pub_id FROM employee;\n→ 61 Zeilen (siehe Tabelle oben, mit Duplikaten)\n\nSELECT pub_id FROM titles UNION SELECT pub_id FROM employee;\n→ 8 Zeilen (jeder der 8 Verlage nur einmal)"},
{t:"Wann UNION statt JOIN?", merk:"JOIN = mehr Spalten pro Zeile (nebeneinander). UNION = mehr Zeilen (untereinander).", b:"Ein JOIN beantwortet 'zeig mir Zeile A UND die dazu passende Zeile B in einer Zeile'. UNION beantwortet dagegen 'zeig mir Zeile A ODER Zeile B als jeweils eigene Zeile in derselben Liste'.", ex:"UNION: zwei Listen zu einer zusammenfassen (mehr Zeilen).\nz.B. 'welche Verlage haben Bücher ODER Mitarbeitende'\n\nJOIN: zwei Tabellen nebeneinanderlegen (mehr Spalten).\nz.B. 'zeig Buchtitel UND den zugehörigen Verlagsnamen'"},
{t:"ORDER BY bei UNION — nur einmal, ganz am Ende", kind:"detail", merk:"ORDER BY gehört nur ans Ende der GESAMTEN UNION-Abfrage, nicht in die einzelnen SELECTs.", b:"Willst du das kombinierte Ergebnis sortieren, steht ORDER BY nur EINMAL, ganz am Ende der gesamten Abfrage — nicht in jedem der beiden SELECTs einzeln.", ex:"SELECT pub_id FROM titles\nUNION\nSELECT pub_id FROM employee\nORDER BY pub_id;\n\n→ sortiert das gesamte kombinierte Ergebnis"}
]},
{id:"exists", icon:"🕵️", color:"#6366f1", title:"EXISTS",
concept:"EXISTS prüft mit einer Subquery nur, OB überhaupt mindestens eine passende Zeile existiert (wahr/falsch) — nicht WELCHE Werte sie liefert. Die Subquery bezieht sich fast immer auf die äußere Zeile (correlated). NOT EXISTS findet das Gegenteil: Zeilen, für die es KEINEN passenden Eintrag gibt.",
example:"SELECT au_lname FROM authors a WHERE EXISTS (SELECT 1 FROM titleauthor ta WHERE ta.au_id = a.au_id)<br>→ 19 von 23 Autor:innen — die mit mindestens einem Buch",
syntax:"SELECT ... FROM tabelleA a\nWHERE [NOT] EXISTS (SELECT 1 FROM tabelleB b WHERE b.spalte = a.spalte);",
intro:"<b>Wozu brauchst du das überhaupt?</b> Du kennst schon IN und NOT IN mit Subqueries — die prüfen, ob ein WERT in einer Liste vorkommt. EXISTS prüft etwas anderes: nicht WELCHEN Wert eine Subquery liefert, sondern nur OB sie überhaupt mindestens eine Zeile liefert (wahr/falsch). Das klingt ähnlich zu IN, ist aber oft klarer zu lesen, vor allem wenn die Subquery mehrere Bedingungen gleichzeitig prüfen muss.",
worked:{
note:"23 Autor:innen insgesamt — EXISTS prüft für jede: gibt es mindestens einen Eintrag in 'titleauthor'?",
headers:["au_lname","hat mindestens ein Buch?"],
rows:[["White","ja"],["Green","ja"],["Smith","nein"],["Greene","nein"]],
highlightCol:1
},
lesson:[
{t:"EXISTS prüft nur: gibt es mindestens EINE Zeile?", merk:"EXISTS liefert wahr/falsch — nicht die Werte selbst, nur OB überhaupt etwas gefunden wurde.", b:"EXISTS steht mit einer Subquery dahinter. SQL prüft für jede Zeile der äußeren Abfrage: liefert die Subquery MINDESTENS eine Zeile? Wenn ja, ist die Bedingung wahr — WELCHE Werte die Subquery dabei liefert, ist völlig egal, deshalb schreibt man in der Subquery oft einfach SELECT 1 statt einer echten Spalte.", ex:"SELECT au_lname FROM authors a\nWHERE EXISTS (SELECT 1 FROM titleauthor ta WHERE ta.au_id = a.au_id);\n\n→ 19 von 23 Autor:innen (siehe Tabelle oben) — die mit mindestens einem Buch"},
{t:"EXISTS ist fast immer eine correlated Subquery", merk:"Die Subquery bei EXISTS bezieht sich fast immer auf die äußere Zeile — genau wie bei correlated Subqueries.", b:"Damit EXISTS pro Zeile etwas Sinnvolles prüfen kann, verweist die Subquery normalerweise auf die aktuelle Zeile der äußeren Abfrage (hier: ta.au_id = a.au_id). Ohne diesen Bezug würde EXISTS für JEDE Zeile dasselbe liefern — immer wahr oder immer falsch, nicht besonders nützlich.", ex:"WHERE EXISTS (SELECT 1 FROM titleauthor ta WHERE ta.au_id = a.au_id)\n\n→ 'ta.au_id = a.au_id' verweist auf die äußere Zeile 'a' — für jede Autor:in wird neu geprüft"},
{t:"NOT EXISTS — das Gegenteil, findet Fehlendes", merk:"NOT EXISTS findet Zeilen, für die die Subquery NICHTS liefert.", b:"Genau wie NOT IN das Gegenstück zu IN ist, ist NOT EXISTS das Gegenstück zu EXISTS. Praktisch für dieselbe Art von Frage wie NOT IN: 'zeig mir alles, wozu es KEINEN passenden Eintrag gibt'.", ex:"SELECT title FROM titles t\nWHERE NOT EXISTS (SELECT 1 FROM sales s WHERE s.title_id = t.title_id);\n\n→ dieselben 2 Titel wie beim NOT IN im Subquery-Thema: 'The Psychology of Computer Cooking' und 'Net Etiquette'"},
{t:"EXISTS vs. IN — wann welches?", kind:"detail", merk:"Bei einfachen Wertlisten reicht IN. Bei mehreren Bedingungen ist EXISTS oft klarer — und bei NULL-Werten in der Subquery zuverlässiger.", b:"Für die meisten einfachen Fälle sind IN und EXISTS austauschbar und liefern dasselbe Ergebnis. EXISTS wird vor allem dann bevorzugt, wenn die Subquery mehrere Bedingungen braucht — dann ist der Code oft leichter zu lesen. Ein zweiter, weniger bekannter Grund: enthält die Subquery bei NOT IN irgendwo einen NULL-Wert, liefert NOT IN überraschend GAR KEIN Ergebnis mehr (getestet und bestätigt) — NOT EXISTS hat dieses Problem nicht.", ex:"Beide finden dieselben Autor:innen:\nWHERE au_id IN (SELECT au_id FROM titleauthor)\nWHERE EXISTS (SELECT 1 FROM titleauthor ta WHERE ta.au_id = a.au_id)"}
]},
{id:"full_join", icon:"➕", color:"#f43f5e", title:"FULL JOIN",
concept:"FULL JOIN zeigt ALLE Zeilen aus BEIDEN Tabellen, mit oder ohne Treffer auf der jeweils anderen Seite — quasi LEFT JOIN und RIGHT JOIN gleichzeitig. Fehlende Gegenstücke werden NULL, das kann jetzt auf beiden Seiten passieren.",
example:"stores FULL JOIN discounts:<br>→ alle 6 Stores (auch ohne Rabatt) UND alle Rabatt-Einträge (auch ohne zugeordneten Store)",
syntax:"SELECT ...\nFROM tabelleA a\nFULL JOIN tabelleB b ON a.spalte = b.spalte;",
intro:"<b>Wozu brauchst du das überhaupt?</b> Du kennst schon LEFT JOIN (alles von links, Rest NULL) und RIGHT JOIN (alles von rechts, Rest NULL). FULL JOIN kombiniert beides: es zeigt ALLE Zeilen aus BEIDEN Tabellen — auch die, die auf der jeweils anderen Seite gar keinen Treffer haben. Genau da, wo bei LEFT JOIN Zeilen von rechts fehlen würden und bei RIGHT JOIN Zeilen von links fehlen würden, zeigt FULL JOIN einfach alles, mit NULL an den fehlenden Stellen.",
worked:{
note:"6 Stores, aber nur 1 hat einen eigenen Rabatt — und 2 Rabatte gehören zu KEINEM bestimmten Store:",
headers:["stor_name","discounttype"],
rows:[["Eric the Read Books","NULL"],["Bookbeat","Customer Discount"],["NULL","Initial Customer"],["NULL","Volume Discount"]],
},
lesson:[
{t:"FULL JOIN zeigt alles von BEIDEN Seiten", merk:"FULL JOIN = LEFT JOIN + RIGHT JOIN gleichzeitig — nichts geht verloren, auf keiner Seite.", b:"FULL JOIN zeigt ALLE Zeilen der linken UND ALLE Zeilen der rechten Tabelle. Gibt es auf der jeweils anderen Seite keinen Treffer, stehen dort NULL-Werte — das kann jetzt auf BEIDEN Seiten passieren, nicht nur auf einer wie bei LEFT/RIGHT JOIN.", ex:"SELECT s.stor_name, d.discounttype\nFROM stores s\nFULL JOIN discounts d ON s.stor_id = d.stor_id;\n\n→ alle 6 Stores UND alle Rabatt-Einträge, auch die ohne Gegenstück (siehe Tabelle oben)"},
{t:"Erkennen, wo genau eine Zeile 'einsam' ist", merk:"IS NULL auf der jeweils anderen Seite zeigt dir, wo eine Zeile ohne Gegenstück geblieben ist.", b:"Nach einem FULL JOIN kannst du mit WHERE ... IS NULL gezielt nachschauen, welche Zeilen auf der einen oder anderen Seite kein Gegenstück gefunden haben — praktisch, um z.B. 'Stores ohne Rabatt' oder 'Rabatte ohne zugeordneten Store' herauszufiltern.", ex:"... WHERE d.discounttype IS NULL;\n→ nur Stores OHNE eigenen Rabatt (aus der Tabelle oben: Eric the Read Books)\n\n... WHERE s.stor_name IS NULL;\n→ nur Rabatte OHNE zugeordneten Store (Initial Customer, Volume Discount)"},
{t:"FULL JOIN, LEFT JOIN oder RIGHT JOIN — welches brauchst du wirklich?", merk:"Willst du wirklich nichts verlieren, auf keiner Seite: FULL JOIN. Reicht eine Basistabelle: LEFT oder RIGHT.", b:"FULL JOIN ist der Sonderfall für 'zeig mir wirklich alles, von beiden Seiten' — in der Praxis brauchst du das seltener als LEFT JOIN, weil meistens EINE der beiden Tabellen klar die 'Basis' ist (siehe JOIN-Thema: 'welche Tabelle kommt nach links'). FULL JOIN lohnt sich vor allem, wenn beide Seiten gleichberechtigt sind und du gezielt nach Lücken auf BEIDEN Seiten suchst.", ex:"Nur Stores, auch ohne Rabatt → LEFT JOIN reicht.\nNur Rabatte, auch ohne Store → RIGHT JOIN reicht.\nBeides gleichzeitig, nichts verlieren → FULL JOIN."}
]},
];
const QUESTIONS = [{"id": "select-1", "topic": "select_from", "difficulty": 1, "de_prompt": "Wähle alle Spalten und Zeilen aus der Tabelle authors aus.", "sql": "SELECT * FROM authors", "test_params": [{}]}, {"id": "select-2", "topic": "select_from", "difficulty": 1, "de_prompt": "Wähle Vor- und Nachname (au_fname, au_lname) aller Autor:innen aus.", "sql": "SELECT au_fname, au_lname FROM authors", "test_params": [{}]}, {"id": "select-3", "topic": "select_from", "difficulty": 1, "de_prompt": "Wähle den Vornamen aller Autor:innen aus, aber benenne die Spalte in der Ausgabe in first_name um (AS).", "sql": "SELECT au_fname AS first_name FROM authors", "test_params": [{}]}, {"id": "select-4", "topic": "select_from", "difficulty": 1, "de_prompt": "Wähle alle unterschiedlichen (keine Duplikate) Nachnamen der Autor:innen aus (DISTINCT).", "sql": "SELECT DISTINCT au_lname FROM authors", "test_params": [{}]}, {"id": "select-5", "topic": "select_from", "difficulty": 1, "de_prompt": "Wähle alle eindeutigen title_id aus, die jemals in der Tabelle sales verkauft wurden.", "sql": "SELECT DISTINCT title_id FROM sales", "test_params": [{}]}, {"id": "select-6", "topic": "select_from", "difficulty": 1, "de_prompt": "Wähle title, price und ytd_sales aus der Tabelle titles aus.", "sql": "SELECT title, price, ytd_sales FROM titles", "test_params": [{}]}, {"id": "select-7", "topic": "select_from", "difficulty": 2, "de_prompt": "Wähle job_id und job_desc aus der Tabelle jobs aus. Benenne die Spalten in der Ausgabe in id und description um.", "sql": "SELECT job_id AS id, job_desc AS description FROM jobs", "test_params": [{}]}, {"id": "select-8", "topic": "select_from", "difficulty": 1, "de_prompt": "Wähle die Namen aller Verlage (pub_name) aus der Tabelle publishers aus.", "sql": "SELECT pub_name FROM publishers", "test_params": [{}]}, {"id": "where-1", "topic": "where", "difficulty": 1, "de_prompt": "Wähle Vor- und Nachname der Autor:innen mit Nachname 'Ringer' aus.", "sql": "SELECT au_fname, au_lname FROM authors WHERE au_lname = 'Ringer'", "test_params": [{}]}, {"id": "where-2", "topic": "where", "difficulty": 1, "de_prompt": "Wähle Vor- und Nachname der Autor:innen mit Nachname '{lname}' aus.", "sql": "SELECT au_fname, au_lname FROM authors WHERE au_lname = '{lname}'", "param_pool": {"lname": ["Carson", "Green", "White", "Dull", "Smith", "Straight", "Bennet"]}, "test_params": [{"lname": "Carson"}, {"lname": "Green"}, {"lname": "White"}]}, {"id": "where-3", "topic": "where", "difficulty": 1, "de_prompt": "Wähle Bestellnummer, Bestelldatum und Menge aus sales aus, bei denen genau {qty} Bücher verkauft wurden.", "sql": "SELECT ord_num, ord_date, qty FROM sales WHERE qty = {qty}", "param_pool": {"qty": [3, 5, 10, 15, 20, 25, 30, 35, 40, 50, 75]}, "allow_empty": true, "test_params": [{"qty": 20}, {"qty": 15}, {"qty": 75}]}, {"id": "where-4", "topic": "where", "difficulty": 2, "de_prompt": "Wähle Vor- und Nachname der Autor:innen aus, deren Vorname 'Anne' UND Nachname 'Ringer' ist.", "sql": "SELECT au_fname, au_lname FROM authors WHERE au_fname = 'Anne' AND au_lname = 'Ringer'", "test_params": [{}]}, {"id": "where-5", "topic": "where", "difficulty": 2, "de_prompt": "Wähle Name und Stadt aller Verlage aus, die entweder in Deutschland ('Germany') ODER Frankreich ('France') sitzen.", "sql": "SELECT pub_name, city FROM publishers WHERE country = 'Germany' OR country = 'France'", "test_params": [{}]}, {"id": "where-6", "topic": "where", "difficulty": 2, "de_prompt": "Wähle Vorname, Nachname und Stadt der Autor:innen aus, deren Vorname 'Dean' ist UND die entweder aus 'Oakland' oder 'Berkeley' kommen. Tipp: Klammern nicht vergessen.", "sql": "SELECT au_fname, au_lname, city FROM authors WHERE au_fname = 'Dean' AND (city = 'Oakland' OR city = 'Berkeley')", "test_params": [{}]}, {"id": "where-7", "topic": "where", "difficulty": 2, "de_prompt": "Wähle Name, Stadt und Land aller Verlage aus, die NICHT in den USA sitzen.", "sql": "SELECT pub_name, city, country FROM publishers WHERE country != 'USA'", "test_params": [{}]}, {"id": "where-8", "topic": "where", "difficulty": 2, "de_prompt": "Wähle Vorname, Nachname und Stadt der Autor:innen aus 'Oakland' oder 'Berkeley', deren Nachname NICHT 'Straight' ist.", "sql": "SELECT au_fname, au_lname, city FROM authors WHERE (city = 'Oakland' OR city = 'Berkeley') AND au_lname != 'Straight'", "test_params": [{}]}, {"id": "where-9", "topic": "where", "difficulty": 2, "de_prompt": "Wähle Name, Stadt, Bundesland und Land aller Verlage aus, bei denen das Bundesland (state) fehlt (IS NULL).", "sql": "SELECT pub_name, city, state, country FROM publishers WHERE state IS NULL", "test_params": [{}]}, {"id": "where-10", "topic": "where", "difficulty": 1, "de_prompt": "Wähle Name, Stadt und Bundesland aller Stores aus, die NICHT in Kalifornien ('CA') liegen. Probier diesmal <> statt !=.", "sql": "SELECT stor_name, city, state FROM stores WHERE state <> 'CA'", "test_params": [{}]}, {"id": "sort-1", "topic": "sort_agg", "difficulty": 1, "de_prompt": "Wähle title und ytd_sales aus titles aus, aufsteigend sortiert nach ytd_sales.", "sql": "SELECT title, ytd_sales FROM titles ORDER BY ytd_sales", "sortCol": 1, "sortDir": "asc", "test_params": [{}]}, {"id": "sort-2", "topic": "sort_agg", "difficulty": 1, "de_prompt": "Wiederhole die letzte Abfrage, aber sortiere diesmal absteigend.", "sql": "SELECT title, ytd_sales FROM titles ORDER BY ytd_sales DESC", "sortCol": 1, "sortDir": "desc", "test_params": [{}]}, {"id": "sort-3", "topic": "sort_agg", "difficulty": 2, "de_prompt": "Wähle die Top 5 Titel mit den meisten ytd_sales aus.", "sql": "SELECT title, ytd_sales FROM titles ORDER BY ytd_sales DESC LIMIT 5", "test_params": [{}]}, {"id": "sort-4", "topic": "sort_agg", "difficulty": 1, "de_prompt": "Was ist die maximale Anzahl an Büchern, die jemals in einer einzigen Bestellung verkauft wurde?", "sql": "SELECT MAX(qty) FROM sales", "test_params": [{}], "alt": {"sql": "SELECT title_id, qty FROM sales ORDER BY qty DESC LIMIT 1", "note": "MAX() ist kompakter und macht sofort klar, dass du einen Extremwert suchst — du bekommst aber nur die Zahl selbst. ORDER BY + LIMIT 1 ist etwas länger, zeigt dir dafür die ganze Zeile, z.B. WELCHE Bestellung das war."}}, {"id": "sort-5", "topic": "sort_agg", "difficulty": 1, "de_prompt": "Was kostet das günstigste Buch (MIN)?", "sql": "SELECT MIN(price) FROM titles", "test_params": [{}], "alt": {"sql": "SELECT title, price FROM titles WHERE price IS NOT NULL ORDER BY price LIMIT 1", "note": "Gleiches Prinzip wie bei MAX(): MIN() liefert nur die Zahl, ORDER BY + LIMIT zeigt zusätzlich, welcher Titel das ist. Achte bei ORDER BY auf NULL-Werte — die stehen bei ASC ganz vorne, deshalb hier WHERE price IS NOT NULL."}}, {"id": "sort-6", "topic": "sort_agg", "difficulty": 1, "de_prompt": "Wie viele Zeilen gibt es in der Tabelle authors?", "sql": "SELECT COUNT(*) FROM authors", "test_params": [{}]}, {"id": "sort-7", "topic": "sort_agg", "difficulty": 1, "de_prompt": "Wie hoch ist die Summe aller year-to-date sales (ytd_sales)?", "sql": "SELECT SUM(ytd_sales) FROM titles", "test_params": [{}]}, {"id": "sort-8", "topic": "sort_agg", "difficulty": 2, "de_prompt": "Wie hoch ist der durchschnittliche Buchpreis, gerundet auf 2 Nachkommastellen?", "sql": "SELECT ROUND(AVG(price), 2) FROM titles", "test_params": [{}]}, {"id": "sort-9", "topic": "sort_agg", "difficulty": 2, "de_prompt": "Wähle in einer einzigen Abfrage Anzahl, Durchschnitt und Summe der qty aus sales aus.", "sql": "SELECT COUNT(qty), AVG(qty), SUM(qty) FROM sales", "test_params": [{}]}, {"id": "sort-10", "topic": "sort_agg", "difficulty": 2, "de_prompt": "Wie hoch ist die durchschnittliche verkaufte Menge (qty) für den Store mit der stor_id '{stor_id}'?", "sql": "SELECT AVG(qty) FROM sales WHERE stor_id = '{stor_id}'", "param_pool": {"stor_id": ["6380", "7066", "7067", "7131", "7896", "8042"]}, "allow_empty": true, "test_params": [{"stor_id": "7131"}, {"stor_id": "7067"}, {"stor_id": "8042"}]}, {"id": "sort-11", "topic": "sort_agg", "difficulty": 2, "de_prompt": "Wie hoch ist der durchschnittliche Preis der Bücher vom Typ '{type}'?", "sql": "SELECT AVG(price) FROM titles WHERE type = '{type}'", "param_pool": {"type": ["business", "mod_cook", "psychology", "trad_cook", "popular_comp"]}, "test_params": [{"type": "psychology"}, {"type": "business"}, {"type": "trad_cook"}]}, {"id": "sort-12", "topic": "sort_agg", "difficulty": 2, "de_prompt": "Aus wie vielen unterschiedlichen Bundesstaaten kommen unsere Autor:innen (COUNT DISTINCT)?", "sql": "SELECT COUNT(DISTINCT state) FROM authors", "test_params": [{}]}, {"id": "pattern-1", "topic": "pattern", "difficulty": 1, "de_prompt": "Wähle alle Buchtitel aus, die das Wort 'cooking' enthalten (LIKE).", "sql": "SELECT title FROM titles WHERE title LIKE '%cooking%'", "test_params": [{}]}, {"id": "pattern-2", "topic": "pattern", "difficulty": 1, "de_prompt": "Wähle alle Titel aus, die mit 'The' beginnen.", "sql": "SELECT title FROM titles WHERE title LIKE 'The%'", "test_params": [{}]}, {"id": "pattern-3", "topic": "pattern", "difficulty": 2, "de_prompt": "Wähle Vor- und Nachname der Autor:innen aus, deren Nachname mit '{letter}' beginnt.", "sql": "SELECT au_fname, au_lname FROM authors WHERE au_lname LIKE '{letter}%'", "param_pool": {"letter": ["S", "C", "G", "D", "B", "M"]}, "allow_empty": true, "test_params": [{"letter": "S"}, {"letter": "C"}, {"letter": "G"}]}, {"id": "pattern-4", "topic": "pattern", "difficulty": 1, "de_prompt": "Wähle Name und Adresse aller Stores aus, deren Adresse auf 'Ave.' endet.", "sql": "SELECT stor_name, stor_address FROM stores WHERE stor_address LIKE '%Ave.'", "test_params": [{}]}, {"id": "pattern-5", "topic": "pattern", "difficulty": 2, "de_prompt": "Wähle Name und Adresse aller Stores aus, die in einer 'Ave.' ODER 'St.' liegen.", "sql": "SELECT stor_name, stor_address FROM stores WHERE stor_address LIKE '%Ave.' OR stor_address LIKE '%St.'", "test_params": [{}]}, {"id": "pattern-6", "topic": "pattern", "difficulty": 2, "de_prompt": "In der Tabelle employee steckt im emp_id ein Muster, das zeigt, ob die Person weiblich oder männlich ist. Wähle alle Mitarbeitenden aus, deren emp_id auf 'F' endet.", "sql": "SELECT * FROM employee WHERE emp_id LIKE '%F'", "test_params": [{}]}, {"id": "pattern-7", "topic": "pattern", "difficulty": 1, "de_prompt": "Wähle Name und Bundesstaat aller Stores aus, die entweder in Kalifornien ('CA') oder Oregon ('OR') liegen. Benutze IN.", "sql": "SELECT stor_name, state FROM stores WHERE state IN ('CA', 'OR')", "test_params": [{}]}, {"id": "pattern-8", "topic": "pattern", "difficulty": 1, "de_prompt": "Wähle alle Titel vom Typ 'psychology', 'mod_cook' oder 'trad_cook' aus (IN).", "sql": "SELECT title FROM titles WHERE type IN ('psychology', 'mod_cook', 'trad_cook')", "test_params": [{}]}, {"id": "pattern-9", "topic": "pattern", "difficulty": 2, "de_prompt": "Wähle alle Autor:innen aus, die NICHT aus 'Salt Lake City', 'Ann Arbor' oder 'Oakland' kommen (NOT IN).", "sql": "SELECT * FROM authors WHERE city NOT IN ('Salt Lake City', 'Ann Arbor', 'Oakland')", "test_params": [{}]}, {"id": "pattern-10", "topic": "pattern", "difficulty": 1, "de_prompt": "Wähle alle Bestellnummern aus sales aus, bei denen zwischen 25 und 45 Büchern verkauft wurden (BETWEEN).", "sql": "SELECT ord_num FROM sales WHERE qty BETWEEN 25 AND 45", "test_params": [{}]}, {"id": "pattern-11", "topic": "pattern", "difficulty": 2, "de_prompt": "Wähle Titel und Preis aller Bücher aus, deren Preis zwischen {lo} und {hi} liegt.", "sql": "SELECT title, price FROM titles WHERE price BETWEEN {lo} AND {hi}", "param_pool": {"lo_hi": [[5, 10], [10, 15], [15, 20], [8, 12]]}, "allow_empty": true, "test_params": [{"lo": 5, "hi": 10}, {"lo": 10, "hi": 15}, {"lo": 15, "hi": 20}]}, {"id": "pattern-12", "topic": "pattern", "difficulty": 1, "de_prompt": "Wähle alle Verkäufe aus, die zwischen '1993-03-11' und '1994-09-13' getätigt wurden (BETWEEN mit Datum).", "sql": "SELECT * FROM sales WHERE ord_date BETWEEN '1993-03-11' AND '1994-09-13'", "test_params": [{}]}, {"id": "pattern-13", "topic": "pattern", "difficulty": 2, "de_prompt": "Wähle die Nachnamen der Autor:innen aus, die mit 'D' beginnen UND genau 4 Buchstaben lang sind. Tipp: dafür brauchst du den Unterstrich-Platzhalter _, nicht %.", "sql": "SELECT au_lname FROM authors WHERE au_lname LIKE 'D___'", "test_params": [{}]}, {"id": "group-1", "topic": "group_having", "difficulty": 1, "de_prompt": "Finde die Gesamtzahl der Autor:innen pro Bundesstaat (GROUP BY state).", "sql": "SELECT state, COUNT(*) AS total_authors FROM authors GROUP BY state", "test_params": [{}], "alt": {"sql": "SELECT state, COUNT(au_id) AS total_authors FROM authors GROUP BY state", "note": "COUNT(*) zählt alle Zeilen, COUNT(au_id) nur Zeilen, in denen au_id nicht NULL ist. Hier macht es keinen Unterschied, weil au_id ein Primärschlüssel ist (nie NULL). Bei Spalten, die NULL enthalten können, liefern beide Varianten unterschiedliche Ergebnisse — dann bewusst wählen!"}}, {"id": "group-2", "topic": "group_having", "difficulty": 2, "de_prompt": "Wiederhole die letzte Abfrage, aber sortiere absteigend nach der Anzahl.", "sql": "SELECT state, COUNT(*) AS total_authors FROM authors GROUP BY state ORDER BY total_authors DESC", "sortCol": 1, "sortDir": "desc", "test_params": [{}]}, {"id": "group-3", "topic": "group_having", "difficulty": 2, "de_prompt": "Was ist der Preis des teuersten Titels pro Verlag (GROUP BY pub_id)?", "sql": "SELECT pub_id, ROUND(MAX(price),2) AS max_price FROM titles GROUP BY pub_id", "test_params": [{}]}, {"id": "group-4", "topic": "group_having", "difficulty": 2, "de_prompt": "Finde die Top 3 Stores mit den meisten verkauften Büchern (SUM(qty)).", "sql": "SELECT stor_id, SUM(qty) AS total_qty FROM sales GROUP BY stor_id ORDER BY total_qty DESC LIMIT 3", "test_params": [{}]}, {"id": "group-5", "topic": "group_having", "difficulty": 2, "de_prompt": "Finde das durchschnittliche job_lvl pro job_id aus employee, aufsteigend sortiert.", "sql": "SELECT job_id, AVG(job_lvl) AS avg_lvl FROM employee GROUP BY job_id ORDER BY avg_lvl ASC", "sortCol": 1, "sortDir": "asc", "test_params": [{}]}, {"id": "group-6", "topic": "group_having", "difficulty": 2, "de_prompt": "Finde für jede Kombination aus Buchtyp (type) und Verlag (pub_id), wie viele Bücher es gibt.", "sql": "SELECT type, pub_id, COUNT(*) AS book_number FROM titles GROUP BY type, pub_id", "test_params": [{}]}, {"id": "group-7", "topic": "group_having", "difficulty": 2, "de_prompt": "Erweitere die letzte Abfrage um den durchschnittlichen Preis pro Kombination, gerundet auf 2 Nachkommastellen.", "sql": "SELECT type, pub_id, COUNT(*) AS qty, ROUND(AVG(price),2) AS avg_price FROM titles GROUP BY type, pub_id", "test_params": [{}]}, {"id": "group-8", "topic": "group_having", "difficulty": 3, "de_prompt": "Behalte aus der letzten Abfrage nur die Kombinationen mit einem Durchschnittspreis über 12 (HAVING statt WHERE!).", "sql": "SELECT type, pub_id, COUNT(*) AS numb, AVG(price) AS avg_price FROM titles GROUP BY type, pub_id HAVING avg_price > 12", "test_params": [{}]}, {"id": "group-9", "topic": "group_having", "difficulty": 3, "de_prompt": "Zeige alle Bundesstaaten und Städte, in denen es {n} oder mehr Autor:innen mit Vertrag gibt (SUM(contract) >= {n}).", "sql": "SELECT state, city, SUM(contract) AS sum_contract FROM authors GROUP BY state, city HAVING sum_contract >= {n}", "param_pool": {"n": [1, 2]}, "test_params": [{"n": 1}, {"n": 2}]}, {"id": "join-1", "topic": "joins", "difficulty": 1, "de_prompt": "Wähle die Bestellnummer (ord_num) aus sales aus, gib der Tabelle den Alias 's' und benutze die Schreibweise s.ord_num.", "sql": "SELECT s.ord_num FROM sales AS s", "test_params": [{}]}, {"id": "join-2", "topic": "joins", "difficulty": 2, "de_prompt": "Wähle Titel und Verlagsname aller Bücher aus (auch wenn kein Verlag zugeordnet ist).", "sql": "SELECT t.title, p.pub_name FROM titles t LEFT JOIN publishers p ON t.pub_id = p.pub_id", "test_params": [{}]}, {"id": "join-3", "topic": "joins", "difficulty": 2, "de_prompt": "Wähle Bestellnummer, Menge und Buchtitel für alle Verkäufe aus (nutze USING).", "sql": "SELECT s.ord_num, s.qty, t.title FROM sales s LEFT JOIN titles t USING(title_id)", "test_params": [{}]}, {"id": "join-4", "topic": "joins", "difficulty": 2, "de_prompt": "Wähle den vollständigen Namen aller Mitarbeitenden und den Namen des Verlags, für den sie arbeiten.", "sql": "SELECT e.fname, e.minit, e.lname, p.pub_name FROM employee e LEFT JOIN publishers p ON e.pub_id = p.pub_id", "test_params": [{}]}, {"id": "join-5", "topic": "joins", "difficulty": 2, "de_prompt": "Wähle den vollständigen Namen und die Jobbezeichnung (job_desc) aller Mitarbeitenden aus.", "sql": "SELECT e.fname, e.minit, e.lname, j.job_desc FROM employee e LEFT JOIN jobs j ON e.job_id = j.job_id", "test_params": [{}]}, {"id": "join-6", "topic": "joins", "difficulty": 3, "de_prompt": "Wähle Name, Jobbezeichnung und Verlagsname aller Mitarbeitenden aus – dafür brauchst du zwei JOINs in einer Abfrage.", "sql": "SELECT e.fname, e.minit, e.lname, j.job_desc, p.pub_name FROM employee e LEFT JOIN publishers p ON e.pub_id = p.pub_id LEFT JOIN jobs j ON e.job_id = j.job_id", "test_params": [{}]}, {"id": "join-7", "topic": "joins", "difficulty": 3, "de_prompt": "Wähle Name, Jobbezeichnung und Verlagsname der Mitarbeitenden aus, die für '{pub_name}' arbeiten.", "sql": "SELECT e.fname, e.minit, e.lname, j.job_desc, p.pub_name FROM employee e INNER JOIN publishers p ON e.pub_id = p.pub_id LEFT JOIN jobs j ON e.job_id = j.job_id WHERE p.pub_name = '{pub_name}'", "param_pool": {"pub_name": ["New Moon Books", "Binnet & Hardley", "Algodata Infosystems", "Five Lakes Publishing", "Ramona Publishers", "GGG&G", "Scootney Books", "Lucerne Publishing"]}, "allow_empty": true, "test_params": [{"pub_name": "Binnet & Hardley"}, {"pub_name": "New Moon Books"}, {"pub_name": "Algodata Infosystems"}]}, {"id": "join-8", "topic": "joins", "difficulty": 2, "de_prompt": "Wähle Verlagsname und PR-Info (pub_info) aller Verlage aus Berkeley, Kalifornien aus.", "sql": "SELECT p.pub_name, pubi.pr_info FROM publishers p LEFT JOIN pub_info pubi USING(pub_id) WHERE p.city = 'Berkeley' AND p.state = 'CA'", "test_params": [{}]}, {"id": "join-9", "topic": "joins", "difficulty": 2, "de_prompt": "Wähle Name, stor_id, Rabatttyp und Rabatt (discounttype, discount) aus discounts für ALLE Stores – auch die ohne Rabatt.", "sql": "SELECT s.stor_name, s.stor_id, d.discounttype, d.discount FROM stores s LEFT JOIN discounts d USING(stor_id)", "test_params": [{}]}, {"id": "join-10", "topic": "joins", "difficulty": 2, "de_prompt": "Wiederhole die letzte Abfrage, aber zeige nur Stores an, die tatsächlich einen Rabatt anbieten.", "sql": "SELECT s.stor_name, s.stor_id, d.discounttype, d.discount FROM stores s INNER JOIN discounts d USING(stor_id)", "test_params": [{}]}, {"id": "join-11", "topic": "joins", "difficulty": 2, "de_prompt": "Nutze RIGHT JOIN: Wähle Rabatttyp und Store-Name aller Einträge aus discounts aus.", "sql": "SELECT d.discounttype, s.stor_name FROM discounts d LEFT JOIN stores s USING(stor_id)", "test_params": [{}]}, {"id": "case-1", "topic": "case", "difficulty": 2, "de_prompt": "Wähle alles aus sales aus und füge eine neue Spalte sales_category hinzu: qty >= 50 'high sales', 20 <= qty < 50 'medium sales', sonst 'low sales'.", "sql": "SELECT *, CASE WHEN qty >= 50 THEN 'high sales' WHEN qty >= 20 AND qty < 50 THEN 'medium sales' ELSE 'low sales' END AS sales_category FROM sales", "test_params": [{}], "alt": {"sql": "SELECT *, CASE WHEN qty < 20 THEN 'low sales' WHEN qty < 50 THEN 'medium sales' ELSE 'high sales' END AS sales_category FROM sales", "note": "Beide Varianten liefern hier dasselbe Ergebnis, weil sich die Bedingungen nicht überschneiden — einmal fängst du oben (größter Wert zuerst) an, einmal unten (kleinster Wert zuerst) und sparst dir dadurch eine Bedingung. Wichtig: sobald sich Bedingungen überschneiden könnten, entscheidet allein die Reihenfolge der WHEN-Zeilen, welche Kategorie gewinnt — SQL prüft von oben nach unten und nimmt die erste, die passt."}}, {"id": "case-2", "topic": "case", "difficulty": 3, "de_prompt": "Berechne für jede der drei sales_category (high/medium/low sales) die Gesamtmenge verkaufter Bücher (SUM(qty)).", "sql": "SELECT CASE WHEN qty >= 50 THEN 'high sales' WHEN qty >= 20 AND qty < 50 THEN 'medium sales' ELSE 'low sales' END AS sales_category, SUM(qty) AS total_sold FROM sales GROUP BY sales_category", "test_params": [{}]}, {"id": "case-3", "topic": "case", "difficulty": 3, "de_prompt": "Erweitere die letzte Abfrage: zeige nur Kategorien mit einer Summe über 100, absteigend sortiert.", "sql": "SELECT CASE WHEN qty >= 50 THEN 'high sales' WHEN qty >= 20 AND qty < 50 THEN 'medium sales' ELSE 'low sales' END AS sales_category, SUM(qty) AS total_sold FROM sales GROUP BY sales_category HAVING total_sold > 100 ORDER BY total_sold DESC", "sortCol": 1, "sortDir": "desc", "test_params": [{}]}, {"id": "case-4", "topic": "case", "difficulty": 3, "de_prompt": "Finde den durchschnittlichen Buchpreis pro Verlag für die Preiskategorien <=5 'super low', <=10 'low', <=15 'medium', sonst 'high'. Beschränke dich auf die Typen 'business', 'trad_cook' und 'psychology'. Runde den Durchschnitt.", "sql": "SELECT pub_id, CASE WHEN price <= 5 THEN 'super low' WHEN price <= 10 THEN 'low' WHEN price <= 15 THEN 'medium' ELSE 'high' END AS price_category, ROUND(AVG(price)) AS average_price FROM titles WHERE type IN ('business','trad_cook','psychology') GROUP BY pub_id, price_category", "test_params": [{}]}, {"id": "sub-1", "topic": "subquery", "difficulty": 2, "de_prompt": "Finde den Namen des Verlags mit dem höchsten Vorschuss (advance) – benutze eine Subquery.", "sql": "SELECT pub_name FROM publishers WHERE pub_id = (SELECT pub_id FROM titles ORDER BY advance DESC LIMIT 1)", "test_params": [{}], "alt": {"sql": "SELECT pub_name FROM publishers WHERE pub_id IN (SELECT pub_id FROM titles WHERE advance = (SELECT MAX(advance) FROM titles))", "note": "Die erste Variante (ORDER BY + LIMIT 1) ist kürzer. Die zweite mit MAX() in einer zweiten Subquery ist etwas länger, verhält sich aber anders bei einem Gleichstand: sie zeigt ALLE Verlage mit dem Höchstwert, nicht nur einen zufälligen."}}, {"id": "sub-2", "topic": "subquery", "difficulty": 2, "de_prompt": "Liste die Titel aller Bücher auf, die von Verlagen aus 'Boston' veröffentlicht wurden.", "sql": "SELECT title FROM titles WHERE pub_id IN (SELECT pub_id FROM publishers WHERE city = 'Boston')", "test_params": [{}], "alt": {"sql": "SELECT t.title FROM titles t JOIN publishers p USING(pub_id) WHERE p.city = 'Boston'", "note": "Die Subquery ist gut lesbar, wenn du nur EINE Bedingung aus der anderen Tabelle brauchst. Sobald du zusätzlich Spalten aus der anderen Tabelle mit ausgeben willst (z.B. den Verlagsnamen selbst), lohnt sich der JOIN, weil die Subquery dir diese Spalten gar nicht zur Verfügung stellt."}}, {"id": "sub-3", "topic": "subquery", "difficulty": 2, "de_prompt": "Finde die Autor:innen, die mehr als ein Buch geschrieben haben.", "sql": "SELECT au_fname, au_lname FROM authors WHERE au_id IN (SELECT au_id FROM titleauthor GROUP BY au_id HAVING COUNT(title_id) > 1)", "test_params": [{}], "alt": {"sql": "SELECT au_fname, au_lname FROM authors a WHERE (SELECT COUNT(*) FROM titleauthor ta WHERE ta.au_id = a.au_id) > 1", "note": "Beide kommen zum gleichen Ergebnis. Die GROUP BY/HAVING-Subquery läuft nur EINMAL komplett durch titleauthor. Die correlated Subquery rechnet für JEDE Zeile aus authors neu nach — bei kleinen Tabellen wie hier egal, bei großen Datenmengen spürbar langsamer."}}, {"id": "sub-4", "topic": "subquery", "difficulty": 3, "de_prompt": "Liste alle Autor:innen mit der Anzahl ihrer Bücher auf – benutze eine correlated Subquery im SELECT-Teil.", "sql": "SELECT au_lname, au_fname, (SELECT COUNT(title_id) FROM titleauthor ta WHERE ta.au_id = a.au_id) AS book_no FROM authors a", "test_params": [{}]}, {"id": "sub-5", "topic": "subquery", "difficulty": 3, "de_prompt": "Finde alle Titel, deren Preis mehr als {pct}% über dem Durchschnittspreis liegt.", "sql": "SELECT title, price FROM titles WHERE price > (SELECT AVG(price) * {factor} FROM titles)", "param_pool": {"pct_factor": [[10, 1.1], [20, 1.2], [15, 1.15]]}, "allow_empty": true, "test_params": [{"pct": 10, "factor": 1.1}, {"pct": 20, "factor": 1.2}]}, {"id": "sub-6", "topic": "subquery", "difficulty": 2, "de_prompt": "Finde den Namen des Verlags, der die meisten Bücher veröffentlicht hat.", "sql": "SELECT pub_name FROM publishers WHERE pub_id = (SELECT pub_id FROM titles GROUP BY pub_id ORDER BY COUNT(*) DESC LIMIT 1)", "test_params": [{}], "alt": {"sql": "SELECT p.pub_name FROM publishers p JOIN titles t ON p.pub_id = t.pub_id GROUP BY p.pub_name ORDER BY COUNT(t.title_id) DESC LIMIT 1", "note": "Die Subquery mit LIMIT 1 ist kurz und funktioniert gut, wenn du wirklich nur den EINEN Spitzenreiter brauchst. Der JOIN mit GROUP BY ist die bessere Basis, wenn du die Abfrage später erweitern willst — z.B. auf die Top 5 statt nur Platz 1."}}, {"id": "sub-7", "topic": "subquery", "difficulty": 2, "de_prompt": "Liste die Titel auf, die noch nie verkauft wurden (NOT IN).", "sql": "SELECT title FROM titles WHERE title_id NOT IN (SELECT title_id FROM sales)", "test_params": [{}]}, {"id": "sub-8", "topic": "subquery", "difficulty": 3, "de_prompt": "Finde die Mitarbeitenden mit demselben Job wie '{fname} {lname}'.", "sql": "SELECT fname, lname, job_id FROM employee WHERE job_id = (SELECT job_id FROM employee WHERE fname = '{fname}' AND lname = '{lname}')", "param_pool": {"name": [["Aria", "Cruz"], ["Annette", "Roulet"], ["Ann", "Devon"], ["Carlos", "Hernadez"], ["Daniel", "Tonini"]]}, "test_params": [{"fname": "Aria", "lname": "Cruz"}, {"fname": "Daniel", "lname": "Tonini"}]}, {"id": "func-1", "topic": "functions", "difficulty": 1, "de_prompt": "Füge eine Spalte hinzu, die zeigt, wie viele Zeichen der Nachname jeder Autorin/jedes Autors hat (LENGTH).", "sql": "SELECT au_lname, LENGTH(au_lname) AS lname_len FROM authors", "test_params": [{}]}, {"id": "func-2", "topic": "functions", "difficulty": 1, "de_prompt": "Wie lautet der Vorname jeder Autorin/jedes Autors in Großbuchstaben (UPPER)?", "sql": "SELECT UPPER(au_fname) AS fname_upper FROM authors", "test_params": [{}]}, {"id": "func-3", "topic": "functions", "difficulty": 2, "de_prompt": "Verbinde Vor- und Nachname der Autor:innen zu einer einzigen Spalte, mit Leerzeichen dazwischen (CONCAT).", "sql": "SELECT CONCAT(au_fname, ' ', au_lname) AS full_name FROM authors", "test_params": [{}]}, {"id": "func-4", "topic": "functions", "difficulty": 2, "de_prompt": "Berechne den Unterschied in Tagen zwischen dem Erscheinungsdatum (pubdate) jedes Buchs und heute (DATEDIFF).", "sql": "SELECT title, DATEDIFF(CURDATE(), pubdate) AS days_since_pub FROM titles", "test_params": [{}]}, {"id": "func-5", "topic": "functions", "difficulty": 2, "de_prompt": "Wie viele Jahre ist es her, seit jeder Titel veröffentlicht wurde (TIMESTAMPDIFF)?", "sql": "SELECT title, TIMESTAMPDIFF(YEAR, pubdate, CURDATE()) AS years_since_pub FROM titles", "test_params": [{}]}, {"id": "func-6", "topic": "functions", "difficulty": 2, "de_prompt": "Zeige Erscheinungsjahr und -monat jedes Titels im Format 'YYYY-MM' (DATE_FORMAT).", "sql": "SELECT title, DATE_FORMAT(pubdate, '%Y-%m') AS pub_year_month FROM titles", "test_params": [{}]}, {"id": "func-7", "topic": "functions", "difficulty": 1, "de_prompt": "Verbinde Verlagsname und Stadt zu einer Spalte, getrennt durch Komma.", "sql": "SELECT CONCAT(pub_name, ', ', city) AS name_city FROM publishers", "test_params": [{}]}, {"id": "func-8", "topic": "functions", "difficulty": 3, "de_prompt": "Finde den/die Titel mit dem längsten Buchtitel (über eine Subquery, damit es auch bei mehreren gleich langen Titeln funktioniert).", "sql": "SELECT title FROM titles WHERE LENGTH(title) = (SELECT MAX(LENGTH(title)) FROM titles)", "test_params": [{}], "alt": {"sql": "SELECT title FROM titles ORDER BY LENGTH(title) DESC LIMIT 1", "note": "ORDER BY + LIMIT ist einfacher zu schreiben, zeigt bei einem Gleichstand (zwei gleich lange Titel) aber nur EINEN davon. Die Subquery mit MAX(LENGTH()) zeigt dir ALLE Titel, die den Rekord halten — bei Fragen wie 'wer/was ist der Spitzenreiter' oft die robustere Wahl."}}, {"id": "func-9", "topic": "functions", "difficulty": 2, "de_prompt": "Zeige die ersten 5 Zeichen der Adresse aller Autor:innen, deren Nachname mit 'C' beginnt (LEFT).", "sql": "SELECT au_fname, au_lname, LEFT(address, 5) AS address_start FROM authors WHERE au_lname LIKE 'C%'", "test_params": [{}], "alt": {"sql": "SELECT au_fname, au_lname, SUBSTRING(address, 1, 5) AS address_start FROM authors WHERE au_lname LIKE 'C%'", "note": "LEFT() und SUBSTRING() machen hier dasselbe. LEFT() ist kürzer und eindeutig für 'von vorne X Zeichen'. SUBSTRING(text, start, länge) ist flexibler, weil du damit auch mitten im Text oder ab einer beliebigen Position anfangen kannst."}}, {"id": "func-10", "topic": "functions", "difficulty": 2, "de_prompt": "Finde alle Titel, bei denen der Unterschied zwischen heute und dem Erscheinungsdatum mehr als {n} Tage beträgt.", "sql": "SELECT title, DATEDIFF(CURDATE(), pubdate) AS days_diff FROM titles WHERE DATEDIFF(CURDATE(), pubdate) > {n}", "param_pool": {"n": [1000, 5000, 10000, 12000]}, "test_params": [{"n": 1000}, {"n": 5000}, {"n": 10000}]}, {"id": "func-11", "topic": "functions", "difficulty": 3, "de_prompt": "Finde die Titel, deren Länge über der durchschnittlichen Titellänge liegt.", "sql": "SELECT title FROM titles WHERE LENGTH(title) > (SELECT AVG(LENGTH(title)) FROM titles)", "test_params": [{}]}, {"id": "func-12", "topic": "functions", "difficulty": 2, "de_prompt": "Finde Autor:innen, bei denen Vor- und Nachname gleich lang sind.", "sql": "SELECT au_fname, au_lname FROM authors WHERE LENGTH(au_fname) = LENGTH(au_lname)", "test_params": [{}]}, {"id": "adv-1", "topic": "advanced", "difficulty": 2, "de_prompt": "Wie groß ist der Unterschied zwischen dem teuersten und dem günstigsten Buchpreis? Runde auf 2 Nachkommastellen.", "sql": "SELECT ROUND(MAX(price) - MIN(price), 2) AS difference FROM titles", "test_params": [{}]}, {"id": "adv-2", "topic": "advanced", "difficulty": 3, "de_prompt": "Finde die Titel, bei denen die verkaufte Gesamtmenge (SUM(qty)) eine gerade Zahl ist (Modulo %).", "sql": "SELECT t.title, SUM(s.qty) AS total_sold FROM titles t INNER JOIN sales s ON t.title_id = s.title_id GROUP BY t.title_id HAVING total_sold % 2 = 0", "test_params": [{}]}, {"id": "adv-3", "topic": "advanced", "difficulty": 3, "de_prompt": "Berechne den Umsatz (Preis × verkaufte Menge) pro Titel.", "sql": "SELECT t.title, ROUND(SUM(t.price * s.qty), 2) AS revenue FROM titles t JOIN sales s USING(title_id) GROUP BY t.title_id", "test_params": [{}], "alt": {"sql": "SELECT t.title, (SELECT ROUND(SUM(t.price * s.qty), 2) FROM sales s WHERE s.title_id = t.title_id) AS revenue FROM titles t", "note": "Der JOIN mit GROUP BY ist die üblichere und meist schnellere Lösung. Die correlated Subquery rechnet für jeden Titel einzeln nach — bei größeren Datenmengen spürbar langsamer. Es gibt aber einen echten inhaltlichen Unterschied, nicht nur Geschmackssache: der INNER JOIN lässt Titel ohne Verkäufe komplett weg (hier 2 Titel), die correlated Subquery zeigt sie zusätzlich mit NULL als Umsatz. Je nachdem, ob 'kein Umsatz' als Zeile sichtbar sein soll oder nicht, ist das eine bewusste Entscheidung, kein Zufall."}}, {"id": "adv-4", "topic": "advanced", "difficulty": 3, "de_prompt": "Cheryl Carson und Charlene Locksley haben geheiratet – wie hoch ist ihr gemeinsamer Umsatz (Preis × Menge über alle ihre Bücher)?", "sql": "SELECT SUM(t.price * s.qty) AS revenue_total FROM titles t JOIN sales s USING(title_id) JOIN titleauthor ta USING(title_id) JOIN authors a USING(au_id) WHERE (a.au_fname = 'Cheryl' AND a.au_lname = 'Carson') OR (a.au_fname = 'Charlene' AND a.au_lname = 'Locksley')", "test_params": [{}], "alt": {"sql": "SELECT SUM(t.price * s.qty) AS revenue_total FROM titles t JOIN sales s USING(title_id) WHERE t.title_id IN (SELECT ta.title_id FROM titleauthor ta JOIN authors a USING(au_id) WHERE (a.au_fname = 'Cheryl' AND a.au_lname = 'Carson') OR (a.au_fname = 'Charlene' AND a.au_lname = 'Locksley'))", "note": "Beide kommen zum gleichen Ergebnis. Die zweite Variante trennt das Problem in zwei Schritte: erst herausfinden, WELCHE Bücher den beiden gehören (Subquery), dann erst den Umsatz dafür berechnen. Das ist oft leichter zu debuggen, wenn mal etwas nicht stimmt — du kannst die Subquery einzeln laufen lassen und prüfen."}}, {"id": "adv-5", "topic": "advanced", "difficulty": 2, "de_prompt": "Wie viele Bücher wurden insgesamt von den Verlagen mit der pub_id '0736' und '0877' veröffentlicht?", "sql": "SELECT COUNT(*) AS total_books FROM titles WHERE pub_id IN ('0736', '0877')", "test_params": [{}]}, {"id": "adv-6", "topic": "advanced", "difficulty": 3, "de_prompt": "Finde alle Bücher, die mehr als {pct}% über dem Durchschnittspreis liegen.", "sql": "SELECT title, price FROM titles WHERE price > (SELECT AVG(price) * {factor} FROM titles)", "param_pool": {"pct_factor": [[5, 1.05], [15, 1.15], [25, 1.25]]}, "allow_empty": true, "test_params": [{"pct": 5, "factor": 1.05}, {"pct": 15, "factor": 1.15}, {"pct": 25, "factor": 1.25}]}, {"id": "adv-7", "topic": "advanced", "difficulty": 3, "de_prompt": "Wähle die Top 5 Bestellungen mit der höchsten verkauften Menge zwischen '1993-03-11' und '1994-09-13' (gruppiert nach Bestellnummer).", "sql": "SELECT SUM(qty) AS total_qty, ord_num FROM sales WHERE ord_date BETWEEN '1993-03-11' AND '1994-09-13' GROUP BY ord_num ORDER BY total_qty DESC LIMIT 5", "test_params": [{}]}, {"id": "adv-8", "topic": "advanced", "difficulty": 2, "de_prompt": "Wie viele Autor:innen haben ein 'i' im Vornamen und kommen aus Utah, Maryland oder Kansas?", "sql": "SELECT COUNT(*) FROM authors WHERE au_fname LIKE '%i%' AND state IN ('UT','MD','KS')", "test_params": [{}]}, {"id": "adv-9", "topic": "advanced", "difficulty": 3, "de_prompt": "Wie viele Autor:innen aus Kalifornien leben in Städten mit einem 'o' im Namen? Zeige nur Städte mit mehr als 1 Autor:in, aufsteigend sortiert nach Anzahl.", "sql": "SELECT city, COUNT(au_fname) AS n FROM authors WHERE state = 'CA' AND city LIKE '%o%' GROUP BY city HAVING n > 1 ORDER BY n", "sortCol": 1, "sortDir": "asc", "test_params": [{}]}, {"id": "adv-10", "topic": "advanced", "difficulty": 3, "de_prompt": "Nutze LEFT JOIN: In welchen Städten wurde das Buch 'Is Anger the Enemy?' verkauft?", "sql": "SELECT DISTINCT st.city FROM titles t LEFT JOIN sales s ON t.title_id = s.title_id LEFT JOIN stores st ON s.stor_id = st.stor_id WHERE t.title = 'Is Anger the Enemy?'", "test_params": [{}]}, {"id": "adv-11", "topic": "advanced", "difficulty": 3, "de_prompt": "Finde den Buchtitel mit der höchsten Verkaufsmenge insgesamt (SUM(qty)).", "sql": "SELECT s.title_id, t.title, SUM(s.qty) AS total_sales FROM sales s LEFT JOIN titles t ON s.title_id = t.title_id GROUP BY s.title_id, t.title ORDER BY total_sales DESC LIMIT 1", "test_params": [{}]}, {"id": "adv-12", "topic": "advanced", "difficulty": 3, "de_prompt": "Wähle alle Buchtitel mit dem vollen Namen ihrer Autor:innen aus. Bücher mit mehreren Autor:innen sollen mehrfach erscheinen (eine Zeile pro Autor:in).", "sql": "SELECT t.title, a.au_fname, a.au_lname FROM titles t INNER JOIN titleauthor ta ON t.title_id = ta.title_id INNER JOIN authors a ON ta.au_id = a.au_id", "test_params": [{}]}, {"id": "adv-13", "topic": "advanced", "difficulty": 2, "de_prompt": "Wähle die vollständigen Namen (ohne Duplikate) der Autor:innen von Psychology-Büchern aus.", "sql": "SELECT DISTINCT CONCAT(a.au_fname, ' ', a.au_lname) AS full_name FROM authors a INNER JOIN titleauthor ta ON a.au_id = ta.au_id INNER JOIN titles t ON ta.title_id = t.title_id WHERE t.type = 'psychology'", "test_params": [{}]}, {"id": "adv-14", "topic": "advanced", "difficulty": 3, "de_prompt": "Wähle alle Buchtitel mit ihrem maximal erreichbaren Royalty aus der Tabelle roysched aus, absteigend sortiert.", "sql": "SELECT t.title, MAX(r.royalty) AS max_royalty FROM titles t INNER JOIN roysched r ON t.title_id = r.title_id GROUP BY t.title ORDER BY max_royalty DESC", "sortCol": 1, "sortDir": "desc", "test_params": [{}]}, {"id": "selfjoin-1", "topic": "self_join", "difficulty": 1, "de_prompt": "Finde alle Paare von Autor:innen mit demselben Nachnamen (Vor- und Nachname beider Personen, jedes Paar nur einmal). Nutze einen Self Join auf authors.", "sql": "SELECT a.au_fname, a.au_lname, b.au_fname, b.au_lname FROM authors a JOIN authors b ON a.au_lname = b.au_lname AND a.au_id < b.au_id", "test_params": [{}]}, {"id": "selfjoin-2", "topic": "self_join", "difficulty": 2, "de_prompt": "Finde Paare unterschiedlicher Buchtitel, die vom selben Verlag (pub_id) veröffentlicht wurden. Zeig beide Titel nebeneinander.", "sql": "SELECT t1.title, t2.title FROM titles t1 JOIN titles t2 ON t1.pub_id = t2.pub_id AND t1.title_id < t2.title_id", "test_params": [{}]}, {"id": "selfjoin-3", "topic": "self_join", "difficulty": 2, "de_prompt": "Finde Paare von Autor:innen, die in derselben Stadt (city) wohnen. Zeig beide Nachnamen und die Stadt.", "sql": "SELECT a.au_lname, b.au_lname, a.city FROM authors a JOIN authors b ON a.city = b.city AND a.au_id < b.au_id", "test_params": [{}]}, {"id": "union-1", "topic": "union", "difficulty": 1, "de_prompt": "Liste alle pub_id auf, die entweder in titles ODER in employee vorkommen (jede nur einmal).", "sql": "SELECT pub_id FROM titles UNION SELECT pub_id FROM employee", "test_params": [{}]}, {"id": "union-2", "topic": "union", "difficulty": 2, "de_prompt": "Wiederhole die letzte Abfrage, aber diesmal OHNE Duplikate zu entfernen — jede Zeile soll erhalten bleiben.", "sql": "SELECT pub_id FROM titles UNION ALL SELECT pub_id FROM employee", "test_params": [{}]}, {"id": "union-3", "topic": "union", "difficulty": 2, "de_prompt": "Liste alle Städte auf, in denen es entweder eine Autor:in ODER eine Buchhandlung (stores) gibt — jede Stadt nur einmal.", "sql": "SELECT city FROM authors UNION SELECT city FROM stores", "test_params": [{}]}, {"id": "exists-1", "topic": "exists", "difficulty": 1, "de_prompt": "Finde alle Autor:innen (Nachname), die mindestens ein Buch geschrieben haben. Nutze EXISTS.", "sql": "SELECT au_lname FROM authors a WHERE EXISTS (SELECT 1 FROM titleauthor ta WHERE ta.au_id = a.au_id)", "test_params": [{}]}, {"id": "exists-2", "topic": "exists", "difficulty": 2, "de_prompt": "Finde alle Buchtitel, die noch nie verkauft wurden. Nutze NOT EXISTS.", "sql": "SELECT title FROM titles t WHERE NOT EXISTS (SELECT 1 FROM sales s WHERE s.title_id = t.title_id)", "test_params": [{}], "alt": {"sql": "SELECT title FROM titles WHERE title_id NOT IN (SELECT title_id FROM sales)", "note": "Beide liefern hier dasselbe Ergebnis. NOT EXISTS und NOT IN sind bei einfachen Fällen austauschbar — NOT EXISTS verhält sich aber zuverlässiger, wenn die Subquery selbst NULL-Werte enthalten könnte (NOT IN kann dann überraschend leer werden). Hier in sales.title_id gibt es keine NULLs, deshalb funktionieren beide gleich gut."}}, {"id": "exists-3", "topic": "exists", "difficulty": 2, "de_prompt": "Finde alle Verlagsnamen, für die es mindestens einen Titel in titles gibt.", "sql": "SELECT pub_name FROM publishers p WHERE EXISTS (SELECT 1 FROM titles t WHERE t.pub_id = p.pub_id)", "test_params": [{}]}, {"id": "fulljoin-1", "topic": "full_join", "difficulty": 1, "de_prompt": "Zeige stor_name und discounttype für ALLE Stores und ALLE Rabatte, auch wenn es auf der jeweils anderen Seite keinen passenden Eintrag gibt. Nutze FULL JOIN.", "sql": "SELECT s.stor_name, d.discounttype FROM stores s FULL JOIN discounts d ON s.stor_id = d.stor_id", "test_params": [{}]}, {"id": "fulljoin-2", "topic": "full_join", "difficulty": 2, "de_prompt": "Nutze einen FULL JOIN zwischen stores und discounts, um NUR die Rabatt-Einträge zu finden, die KEINEM bestimmten Store zugeordnet sind.", "sql": "SELECT d.discounttype, d.discount FROM stores s FULL JOIN discounts d ON s.stor_id = d.stor_id WHERE s.stor_name IS NULL", "test_params": [{}]}];
/* ================= MySQL-Kompatibilitätsschicht ================= */
function mysqlCompat(sql){
sql = sql.replace(/\bLEFT\s*\(/gi, "LEFTSTR(");
sql = sql.replace(/\bRIGHT\s*\(/gi, "RIGHTSTR(");
sql = sql.replace(/(TIMESTAMPDIFF\s*\(\s*)(YEAR|MONTH|DAY|WEEK|HOUR|MINUTE|SECOND)(\s*,)/gi, "$1'$2'$3");
sql = sql.replace(/^\s*USE\s+\w+\s*;?\s*/i, "");
return sql;
}
function parseSqlDate(s){
if (s===null || s===undefined) return null;
const datePart = String(s).split(" ")[0];
const d = new Date(datePart+"T00:00:00Z");
return isNaN(d.getTime()) ? null : d;
}
const MONTHS_DE = ["January","February","March","April","May","June","July","August","September","October","November","December"];
const WEEKDAYS_DE = ["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"];
function registerUdfs(db){
db.create_function("CONCAT", function(...args){
if (args.some(a=>a===null||a===undefined)) return null;
return args.join("");
});
db.create_function("LEFTSTR", function(s,n){ return s===null ? null : String(s).slice(0, Number(n)); });
db.create_function("RIGHTSTR", function(s,n){
if (s===null) return null;
n = Number(n);
return n>0 ? String(s).slice(-n) : "";
});
db.create_function("CURDATE", function(){ return new Date().toISOString().slice(0,10); });
db.create_function("CURRENT_DATE", function(){ return new Date().toISOString().slice(0,10); });
db.create_function("DATEDIFF", function(a,b){
const da=parseSqlDate(a), db_=parseSqlDate(b);
if (!da || !db_) return null;
return Math.round((da-db_)/86400000);
});
db.create_function("TIMESTAMPDIFF", function(unit,a,b){
const da=parseSqlDate(a), db_=parseSqlDate(b);
if (!da || !db_) return null;
const days = Math.round((db_-da)/86400000);
unit = String(unit).toUpperCase();
if (unit==="DAY") return days;
if (unit==="YEAR"){
let y = db_.getUTCFullYear()-da.getUTCFullYear();
if ((db_.getUTCMonth()<da.getUTCMonth()) || (db_.getUTCMonth()===da.getUTCMonth() && db_.getUTCDate()<da.getUTCDate())) y--;
return y;
}
if (unit==="MONTH"){
let m = (db_.getUTCFullYear()-da.getUTCFullYear())*12 + (db_.getUTCMonth()-da.getUTCMonth());
if (db_.getUTCDate() < da.getUTCDate()) m--;
return m;
}
return days;
});
db.create_function("DATE_FORMAT", function(s, fmt){
const d = parseSqlDate(s);
if (!d) return null;
let out = "";
for (let i=0;i<fmt.length;i++){
if (fmt[i]==="%" && i+1<fmt.length){
const spec = fmt[i+1];
if (spec==="Y") out += String(d.getUTCFullYear()).padStart(4,"0");
else if (spec==="m") out += String(d.getUTCMonth()+1).padStart(2,"0");
else if (spec==="d") out += String(d.getUTCDate()).padStart(2,"0");
else if (spec==="e") out += String(d.getUTCDate());
else if (spec==="M") out += MONTHS_DE[d.getUTCMonth()];
else if (spec==="W") out += WEEKDAYS_DE[(d.getUTCDay()+6)%7];
else out += spec;
i++;
} else out += fmt[i];
}
return out;
});
db.create_function("CHAR_LENGTH", function(s){ return s===null ? null : String(s).length; });
}
function rewriteRightJoin(sql){
const m = sql.match(/^(.*?FROM\s+)([`"\w]+(?:\s+(?:AS\s+)?[`"\w]+)?)\s+RIGHT\s+JOIN\s+([`"\w]+(?:\s+(?:AS\s+)?[`"\w]+)?)\s+(ON\s+[\s\S]+?|USING\s*\([\s\S]+?\))(\s+(?:WHERE|GROUP BY|ORDER BY|LIMIT)[\s\S]*)?$/i);
if (!m) return null;
const [, pre, tblA, tblB, cond, rest] = m;
return `${pre}${tblB} LEFT JOIN ${tblA} ${cond}${rest||""}`;
}
function execSqlRaw(sql){
const res = db.exec(sql);
if (!res.length) return {columns:[], values:[]};
return res[res.length-1];
}
function execSqlSafe(sql){
try{
return execSqlRaw(sql);
}catch(e){
if (/RIGHT\s+JOIN/i.test(sql) && /RIGHT and FULL OUTER JOINs? are not (currently )?supported/i.test(e.message)){
const rewritten = rewriteRightJoin(sql);
if (rewritten){ return execSqlRaw(rewritten); }
}
throw e;
}
}
function base64ToUint8Array(b64){
const binary = atob(b64);
const bytes = new Uint8Array(binary.length);
for (let i=0;i<binary.length;i++) bytes[i] = binary.charCodeAt(i);
return bytes;
}
/* ================= Fragen-Engine ================= */
function fillTemplate(tpl, params){
return tpl.replace(/\{(\w+)\}/g, (m,k)=> (params[k]!==undefined ? params[k] : m));
}
function pickParams(q){
if (!q.param_pool) return {};
const pool = q.param_pool;
const result = {};
for (const key of Object.keys(pool)){
const values = pool[key];
const choice = values[Math.floor(Math.random()*values.length)];
if (Array.isArray(choice)){
if (key==="lo_hi"){ result.lo=choice[0]; result.hi=choice[1]; }
else if (key==="pct_factor"){ result.pct=choice[0]; result.factor=choice[1]; }
else if (key==="name"){ result.fname=choice[0]; result.lname=choice[1]; }
} else {
result[key] = choice;
}
}
return result;
}
function buildInstance(q){
const params = pickParams(q);
const sql = mysqlCompat(fillTemplate(q.sql, params));
const promptText = fillTemplate(q.de_prompt, params);
let refResult = null, refError = null;
try{ refResult = execSqlSafe(sql); }
catch(e){ refError = e.message; }
return {qdef:q, params, sql, promptText, refResult, refError};
}
function normVal(v){
if (v===null || v===undefined) return null;
if (typeof v === "number") return Math.round(v*10000)/10000;
if (typeof v === "string") return v.trim();
return v;
}
function rowKey(row){ return row.map(v=>String(v)).join(""); }
function compareResults(expected, actual){
if (!expected) return {ok:false, reason:"no_reference"};
if (expected.columns.length !== actual.columns.length){
return {ok:false, reason:"column_count", expCols:expected.columns.length, actCols:actual.columns.length};
}
const exp = expected.values.map(r=>r.map(normVal));
const act = actual.values.map(r=>r.map(normVal));
if (exp.length !== act.length){
return {ok:false, reason:"row_count", expRows:exp.length, actRows:act.length};
}
const expSorted = [...exp].sort((a,b)=> rowKey(a)<rowKey(b) ? -1 : (rowKey(a)>rowKey(b) ? 1 : 0));
const actSorted = [...act].sort((a,b)=> rowKey(a)<rowKey(b) ? -1 : (rowKey(a)>rowKey(b) ? 1 : 0));
for (let i=0;i<expSorted.length;i++){
for (let j=0;j<expSorted[i].length;j++){
if (expSorted[i][j] !== actSorted[i][j]) return {ok:false, reason:"value_mismatch"};
}
}
return {ok:true};
}
function checkMonotonic(actual, colIdx, dir){
const vals = actual.values.map(r=>r[colIdx]);
for (let i=1;i<vals.length;i++){
const a=vals[i-1], b=vals[i];
if (a===null||b===null) continue;
if (dir==="asc" && a>b) return false;
if (dir==="desc" && a<b) return false;
}
return true;
}
function gradeAnswer(inst, actual){
const cmp = compareResults(inst.refResult, actual);
if (!cmp.ok) return cmp;
if (inst.qdef.sortCol !== undefined){
if (!checkMonotonic(actual, inst.qdef.sortCol, inst.qdef.sortDir)){
return {ok:false, reason:"sort_missing"};
}
}
return {ok:true};
}
function explainFailure(reason, extra, topic){
const t = TOPICS.find(x=>x.id===topic);
switch(reason){
case "column_count":
return `Deine Abfrage liefert <b>${extra.actCols}</b> Spalte(n), erwartet werden <b>${extra.expCols}</b>. Schau nochmal in der Aufgabenstellung nach, welche Spalten genau gefragt sind.`;
case "row_count":
if (extra.actRows > extra.expRows)
return `Deine Abfrage liefert <b>mehr Zeilen</b> (${extra.actRows}) als erwartet (${extra.expRows}) — vermutlich filtert deine Bedingung nicht genug ein.<br><br>${t.concept}`;
return `Deine Abfrage liefert <b>weniger Zeilen</b> (${extra.actRows}) als erwartet (${extra.expRows}) — vermutlich ist deine Bedingung zu streng, oder AND/OR sind vertauscht.<br><br>${t.concept}`;
case "value_mismatch":
return `Die Anzahl der Zeilen passt, aber die <b>Werte stimmen nicht überein</b>. Prüfe Berechnungen, Gruppierung oder Rundung.<br><br>${t.concept}`;
case "sort_missing":
return `Deine Werte stimmen, aber die <b>Sortierung passt nicht</b>. Denk an ORDER BY (und die Richtung ASC/DESC).`;
case "no_reference":
return `Für diese Frage konnte im Hintergrund keine Referenzlösung berechnet werden — das ist ein Fehler im Tool, nicht bei dir. Klick auf "Nächste Frage".`;
default:
return t.concept;
}
}
function explainSqlError(msg){
if (/no such column/i.test(msg)) return `Diese Spalte gibt es in der Tabelle nicht. Schau links in der Seitenleiste nach den passenden Spaltennamen.<br><br><span class="text-faint">Fehlermeldung: ${msg}</span>`;
if (/no such table/i.test(msg)) return `Diese Tabelle gibt es nicht. Schau links in der Seitenleiste nach den verfügbaren Tabellennamen.<br><br><span class="text-faint">Fehlermeldung: ${msg}</span>`;
if (/syntax error/i.test(msg)) return `Da steckt ein Tippfehler in der SQL-Syntax (z.B. fehlendes Komma, Klammer oder Anführungszeichen).<br><br><span class="text-faint">Fehlermeldung: ${msg}</span>`;
return `SQL-Fehler: <span class="text-faint">${msg}</span>`;
}
/* ================= App-State ================= */
let db = null;
let cm = null;
let session = null;
let lastSession = null;
function showScreen(name){
["setup","lesson","question","summary"].forEach(s=>{
document.getElementById("screen-"+s).classList.toggle("hidden", s!==name);
});
}
/* ---------- Sidebar / Schema ---------- */
const REFCARD_HTML = `
<details class="refcard">
<summary>📋 Spickzettel <span class="text-faint">Reihenfolge & Operatoren</span></summary>
<div class="refbody">
<div style="margin-bottom:8px;"><b style="color:var(--accent-2);">Geschrieben vs. tatsächlich ausgeführt:</b></div>
<table>
<tr><td class="k">SELECT</td><td>→ ausgeführt als: FROM</td></tr>
<tr><td class="k">FROM</td><td>→ WHERE</td></tr>
<tr><td class="k">WHERE</td><td>→ GROUP BY</td></tr>
<tr><td class="k">GROUP BY</td><td>→ HAVING</td></tr>
<tr><td class="k">HAVING</td><td>→ SELECT</td></tr>
<tr><td class="k">ORDER BY</td><td>→ ORDER BY</td></tr>
<tr><td class="k">LIMIT</td><td>→ LIMIT</td></tr>
</table>
<div style="margin:10px 0 6px;"><b style="color:var(--accent-2);">Vergleichsoperatoren:</b></div>
<table>
<tr><td class="k">=</td><td>gleich</td><td class="k">!= / <></td><td>ungleich</td></tr>
<tr><td class="k">> / >=</td><td>größer / größer-gleich</td><td class="k">< / <=</td><td>kleiner / kleiner-gleich</td></tr>
</table>
<div style="margin:10px 0 6px;"><b style="color:var(--accent-2);">Platzhalter:</b></div>
<table>
<tr><td class="k">*</td><td>alle Spalten</td></tr>
<tr><td class="k">%</td><td>beliebig viele Zeichen (LIKE)</td></tr>
<tr><td class="k">_</td><td>genau ein Zeichen (LIKE)</td></tr>
</table>
</div>
</details>`;
function filterSchema(q){
q = q.trim().toLowerCase();
document.querySelectorAll("#schema-tree .table-card").forEach(card=>{
const name = card.getAttribute("data-t").toLowerCase();
card.style.display = !q || name.includes(q) ? "" : "none";
});
}
function renderSchemaTree(){
const root = document.getElementById("schema-tree");
root.innerHTML = REFCARD_HTML + SCHEMA.map(t=>`
<div class="table-card" data-t="${t.name}">
<div class="table-head" onclick="toggleTable('${t.name}')">
<span class="tname">${t.name}</span>
<span class="arrow">▶</span>
</div>
<div class="table-desc">${t.desc}</div>
<div class="table-cols">
${t.cols.map(c=>`<div class="col-row ${c[2]==='PK'?'pk':''}"><span>${c[2]==='PK'?'🔑 ':''}${c[0]}</span><span class="ctype">${c[1]}</span></div>`).join("")}
<button class="secondary preview-btn" onclick="event.stopPropagation(); previewTable('${t.name}')">📂 Alle Daten ansehen</button>
</div>