Version 2.9.0-19.0.dev

Merge commit 'b5470ae013d24a6f6b5fd4bb7fb803ec24682add' into dev
diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json
index cd9ba19..a62e37d 100644
--- a/.dart_tool/package_config.json
+++ b/.dart_tool/package_config.json
@@ -11,7 +11,7 @@
     "constraint, update this by running tools/generate_package_config.dart."
   ],
   "configVersion": 2,
-  "generated": "2020-06-17T09:39:51.245406",
+  "generated": "2020-06-23T13:49:13.378284",
   "generator": "tools/generate_package_config.dart",
   "packages": [
     {
@@ -380,7 +380,8 @@
     {
       "name": "meta",
       "rootUri": "../pkg/meta",
-      "packageUri": "lib/"
+      "packageUri": "lib/",
+      "languageVersion": "2.9"
     },
     {
       "name": "mime",
@@ -559,7 +560,7 @@
       "name": "stack_trace",
       "rootUri": "../third_party/pkg/stack_trace",
       "packageUri": "lib/",
-      "languageVersion": "1.23"
+      "languageVersion": "2.0"
     },
     {
       "name": "stagehand",
@@ -676,6 +677,12 @@
       "languageVersion": "2.6"
     },
     {
+      "name": "vm_snapshot_analysis",
+      "rootUri": "../pkg/vm_snapshot_analysis",
+      "packageUri": "lib/",
+      "languageVersion": "2.8"
+    },
+    {
       "name": "watcher",
       "rootUri": "../third_party/pkg/watcher",
       "packageUri": "lib/",
diff --git a/.packages b/.packages
index 368824f..2b486aa 100644
--- a/.packages
+++ b/.packages
@@ -112,6 +112,7 @@
 usage:third_party/pkg/usage/lib
 vm:pkg/vm/lib
 vm_service:pkg/vm_service/lib
+vm_snapshot_analysis:pkg/vm_snapshot_analysis/lib
 watcher:third_party/pkg/watcher/lib
 web_components:third_party/pkg/web_components/lib
 web_socket_channel:third_party/pkg/web_socket_channel/lib
diff --git a/DEPS b/DEPS
index 6ebc4f9..9335624 100644
--- a/DEPS
+++ b/DEPS
@@ -39,16 +39,16 @@
 
   # Checked-in SDK version. The checked-in SDK is a Dart SDK distribution in a
   # cipd package used to run Dart scripts in the build and test infrastructure.
-  "sdk_tag": "version:2.9.0-16.0.dev",
+  "sdk_tag": "version:2.9.0-18.0.dev",
 
   # co19 is a cipd package. Use update.sh in tests/co19[_2] to update these
   # hashes. It requires access to the dart-build-access group, which EngProd
   # has.
-  "co19_rev": "b071a4729a57ee47dcc7330ab9ea3566ef58e5c2",
+  "co19_rev": "443e4b3cd3953e9d8feef85bb712a93f6dac0858",
   "co19_2_rev": "620c1148c8b7a3d7f74afacf348c46f109eb64f2",
 
   # The internal benchmarks to use. See go/dart-benchmarks-internal
-  "benchmarks_internal_rev": "478f5a8be0bad2b1bc3c1c9cf150486ec77516e1",
+  "benchmarks_internal_rev": "8a7ce78ada809beb62fcfdf2f8e7a400a7bc5ed3",
   "checkout_benchmarks_internal": False,
 
   # As Flutter does, we use Fuchsia's GN and Clang toolchain. These revision
@@ -142,7 +142,7 @@
   "source_maps-0.9.4_rev": "38524",
   "source_maps_rev": "87b4fd9027378bbd51b02e9d7df794eee8a82b7a",
   "source_span_tag": "1.7.0",
-  "stack_trace_tag": "1.9.3",
+  "stack_trace_tag": "07569831f17844ef90214a179db211954a7f7324",
   "stagehand_tag": "v3.3.7",
   "stream_channel_tag": "70433d577be02c48cb16d72d65654f3b4d82c6ed",
   "string_scanner_rev": "a918e7371af6b6e73bfd534ff9da6084741c1f99",
diff --git a/benchmarks/BigIntParsePrint/dart/BigIntParsePrint.dart b/benchmarks/BigIntParsePrint/dart/BigIntParsePrint.dart
index b7ed19e..f9e05e7 100644
--- a/benchmarks/BigIntParsePrint/dart/BigIntParsePrint.dart
+++ b/benchmarks/BigIntParsePrint/dart/BigIntParsePrint.dart
@@ -168,10 +168,11 @@
 
   @override
   void run() {
+    final one = BigInt.one;
     for (final b0 in values) {
       // Instances might cache `toString()`, so use arithmetic to create a new
       // instance to try to protect against measuring a cached string.
-      final b = b0 + BigInt.one;
+      final b = b0 + one;
       final s = b.toString();
       sink1 = s;
       sink2 = b;
@@ -206,10 +207,11 @@
 
   @override
   void run() {
+    final one = Int64.ONE;
     for (final b0 in values) {
       // Instances might cache `toString()`, so use arithmetic to create a new
       // instance to try to protect against measuring a cached string.
-      final b = b0 + Int64.ONE;
+      final b = b0 + one;
       final s = b.toStringUnsigned();
       sink1 = s;
       sink2 = b;
diff --git a/benchmarks/BigIntParsePrint/dart2/BigIntParsePrint.dart b/benchmarks/BigIntParsePrint/dart2/BigIntParsePrint.dart
index b7ed19e..f9e05e7 100644
--- a/benchmarks/BigIntParsePrint/dart2/BigIntParsePrint.dart
+++ b/benchmarks/BigIntParsePrint/dart2/BigIntParsePrint.dart
@@ -168,10 +168,11 @@
 
   @override
   void run() {
+    final one = BigInt.one;
     for (final b0 in values) {
       // Instances might cache `toString()`, so use arithmetic to create a new
       // instance to try to protect against measuring a cached string.
-      final b = b0 + BigInt.one;
+      final b = b0 + one;
       final s = b.toString();
       sink1 = s;
       sink2 = b;
@@ -206,10 +207,11 @@
 
   @override
   void run() {
+    final one = Int64.ONE;
     for (final b0 in values) {
       // Instances might cache `toString()`, so use arithmetic to create a new
       // instance to try to protect against measuring a cached string.
-      final b = b0 + Int64.ONE;
+      final b = b0 + one;
       final s = b.toStringUnsigned();
       sink1 = s;
       sink2 = b;
diff --git a/benchmarks/Calls/dart/Calls.dart b/benchmarks/Calls/dart/Calls.dart
index ac78efe..5b94b2a 100644
--- a/benchmarks/Calls/dart/Calls.dart
+++ b/benchmarks/Calls/dart/Calls.dart
@@ -4,7 +4,7 @@
 
 // Micro-benchmarks for sync/sync*/async/async* functionality.
 
-import "dart:async";
+import 'dart:async';
 
 const int iterationLimitAsync = 200;
 const int sumOfIterationLimitAsync =
@@ -14,35 +14,35 @@
 const int sumOfIterationLimitSync =
     iterationLimitSync * (iterationLimitSync - 1) ~/ 2;
 
-main() async {
+Future main() async {
   final target = Target();
   final target2 = Target2();
   final target3 = Target3();
 
   // Ensure the call sites will have another target in the ICData.
-  performAwaitCallsClosureTargetPolymorphic(returnAsync);
-  performAwaitCallsClosureTargetPolymorphic(returnFuture);
-  performAwaitCallsClosureTargetPolymorphic(returnFutureOr);
-  performAwaitAsyncCallsInstanceTargetPolymorphic(target);
-  performAwaitAsyncCallsInstanceTargetPolymorphic(target2);
-  performAwaitAsyncCallsInstanceTargetPolymorphic(target3);
-  performAwaitFutureCallsInstanceTargetPolymorphic(target);
-  performAwaitFutureCallsInstanceTargetPolymorphic(target2);
-  performAwaitFutureCallsInstanceTargetPolymorphic(target3);
-  performAwaitFutureOrCallsInstanceTargetPolymorphic(target);
-  performAwaitFutureOrCallsInstanceTargetPolymorphic(target2);
-  performAwaitFutureOrCallsInstanceTargetPolymorphic(target3);
+  await performAwaitCallsClosureTargetPolymorphic(returnAsync);
+  await performAwaitCallsClosureTargetPolymorphic(returnFuture);
+  await performAwaitCallsClosureTargetPolymorphic(returnFutureOr);
+  await performAwaitAsyncCallsInstanceTargetPolymorphic(target);
+  await performAwaitAsyncCallsInstanceTargetPolymorphic(target2);
+  await performAwaitAsyncCallsInstanceTargetPolymorphic(target3);
+  await performAwaitFutureCallsInstanceTargetPolymorphic(target);
+  await performAwaitFutureCallsInstanceTargetPolymorphic(target2);
+  await performAwaitFutureCallsInstanceTargetPolymorphic(target3);
+  await performAwaitFutureOrCallsInstanceTargetPolymorphic(target);
+  await performAwaitFutureOrCallsInstanceTargetPolymorphic(target2);
+  await performAwaitFutureOrCallsInstanceTargetPolymorphic(target3);
   performSyncCallsInstanceTargetPolymorphic(target);
   performSyncCallsInstanceTargetPolymorphic(target2);
   performSyncCallsInstanceTargetPolymorphic(target3);
-  performAwaitAsyncCallsInstanceTargetPolymorphicManyAwaits(target);
-  performAwaitAsyncCallsInstanceTargetPolymorphicManyAwaits(target2);
-  performAwaitAsyncCallsInstanceTargetPolymorphicManyAwaits(target3);
+  await performAwaitAsyncCallsInstanceTargetPolymorphicManyAwaits(target);
+  await performAwaitAsyncCallsInstanceTargetPolymorphicManyAwaits(target2);
+  await performAwaitAsyncCallsInstanceTargetPolymorphicManyAwaits(target3);
 
-  performAwaitForIterationPolymorphic(generateNumbersAsyncStar);
-  performAwaitForIterationPolymorphic(generateNumbersAsyncStar2);
-  performAwaitForIterationPolymorphic(generateNumbersManualAsync);
-  performAwaitForIterationPolymorphic(generateNumbersAsyncStarManyYields);
+  await performAwaitForIterationPolymorphic(generateNumbersAsyncStar);
+  await performAwaitForIterationPolymorphic(generateNumbersAsyncStar2);
+  await performAwaitForIterationPolymorphic(generateNumbersManualAsync);
+  await performAwaitForIterationPolymorphic(generateNumbersAsyncStarManyYields);
   performSyncIterationPolymorphic(generateNumbersSyncStar);
   performSyncIterationPolymorphic(generateNumbersSyncStar2);
   performSyncIterationPolymorphic(generateNumbersManual);
@@ -105,7 +105,7 @@
 @pragma('vm:never-inline')
 @pragma('dart2js:noInline')
 Future<int> performAwaitCallsClosureTargetPolymorphic(
-    FutureOr<int> fun(int count)) async {
+    FutureOr<int> Function(int) fun) async {
   int sum = 0;
   for (int i = 0; i < iterationLimitAsync; ++i) {
     sum += await fun(i);
@@ -286,7 +286,7 @@
 @pragma('vm:never-inline')
 @pragma('dart2js:noInline')
 Future<int> performAwaitForIterationPolymorphic(
-    Stream<int> fun(int count)) async {
+    Stream<int> Function(int) fun) async {
   int sum = 0;
   await for (int value in fun(iterationLimitAsync)) {
     sum += value;
@@ -297,7 +297,7 @@
 
 @pragma('vm:never-inline')
 @pragma('dart2js:noInline')
-int performSyncCallsClosureTarget(int fun(int count)) {
+int performSyncCallsClosureTarget(int Function(int) fun) {
   int sum = 0;
   for (int i = 0; i < iterationLimitSync; ++i) {
     sum += fun(i);
@@ -330,7 +330,7 @@
 
 @pragma('vm:never-inline')
 @pragma('dart2js:noInline')
-int performSyncIterationPolymorphic(Iterable<int> fun(int count)) {
+int performSyncIterationPolymorphic(Iterable<int> Function(int) fun) {
   int sum = 0;
   for (int value in fun(iterationLimitSync)) {
     sum += value;
@@ -371,7 +371,7 @@
 @pragma('dart2js:noInline')
 Stream<int> generateNumbersManualAsync(int limit) {
   int current = 0;
-  StreamController<int> controller = StreamController(sync: true);
+  final controller = StreamController<int>(sync: true);
   void emit() {
     while (true) {
       if (controller.isPaused || !controller.hasListener) return;
@@ -746,36 +746,44 @@
 }
 
 class Target2 extends Target {
+  @override
   @pragma('vm:never-inline')
   @pragma('dart2js:noInline')
   FutureOr<int> returnFutureOr(int i) => i;
 
+  @override
   @pragma('vm:never-inline')
   @pragma('dart2js:noInline')
   Future<int> returnFuture(int i) => Future.value(i);
 
+  @override
   @pragma('vm:never-inline')
   @pragma('dart2js:noInline')
   Future<int> returnAsync(int i) async => i;
 
+  @override
   @pragma('vm:never-inline')
   @pragma('dart2js:noInline')
   int returnSync(int i) => i;
 }
 
 class Target3 extends Target {
+  @override
   @pragma('vm:never-inline')
   @pragma('dart2js:noInline')
   FutureOr<int> returnFutureOr(int i) => i;
 
+  @override
   @pragma('vm:never-inline')
   @pragma('dart2js:noInline')
   Future<int> returnFuture(int i) => Future.value(i);
 
+  @override
   @pragma('vm:never-inline')
   @pragma('dart2js:noInline')
   Future<int> returnAsync(int i) async => i;
 
+  @override
   @pragma('vm:never-inline')
   @pragma('dart2js:noInline')
   int returnSync(int i) => i;
@@ -815,7 +823,7 @@
     final double nsPerCall = measureFor(const Duration(seconds: 2));
 
     // Report result.
-    print("$name(RunTimeRaw): $nsPerCall ns.");
+    print('$name(RunTimeRaw): $nsPerCall ns.');
   }
 }
 
@@ -850,6 +858,6 @@
     final double nsPerCall = await measureFor(const Duration(seconds: 2));
 
     // Report result.
-    print("$name(RunTimeRaw): $nsPerCall ns.");
+    print('$name(RunTimeRaw): $nsPerCall ns.');
   }
 }
diff --git a/benchmarks/Calls/dart2/Calls.dart b/benchmarks/Calls/dart2/Calls.dart
index ac78efe..5b94b2a 100644
--- a/benchmarks/Calls/dart2/Calls.dart
+++ b/benchmarks/Calls/dart2/Calls.dart
@@ -4,7 +4,7 @@
 
 // Micro-benchmarks for sync/sync*/async/async* functionality.
 
-import "dart:async";
+import 'dart:async';
 
 const int iterationLimitAsync = 200;
 const int sumOfIterationLimitAsync =
@@ -14,35 +14,35 @@
 const int sumOfIterationLimitSync =
     iterationLimitSync * (iterationLimitSync - 1) ~/ 2;
 
-main() async {
+Future main() async {
   final target = Target();
   final target2 = Target2();
   final target3 = Target3();
 
   // Ensure the call sites will have another target in the ICData.
-  performAwaitCallsClosureTargetPolymorphic(returnAsync);
-  performAwaitCallsClosureTargetPolymorphic(returnFuture);
-  performAwaitCallsClosureTargetPolymorphic(returnFutureOr);
-  performAwaitAsyncCallsInstanceTargetPolymorphic(target);
-  performAwaitAsyncCallsInstanceTargetPolymorphic(target2);
-  performAwaitAsyncCallsInstanceTargetPolymorphic(target3);
-  performAwaitFutureCallsInstanceTargetPolymorphic(target);
-  performAwaitFutureCallsInstanceTargetPolymorphic(target2);
-  performAwaitFutureCallsInstanceTargetPolymorphic(target3);
-  performAwaitFutureOrCallsInstanceTargetPolymorphic(target);
-  performAwaitFutureOrCallsInstanceTargetPolymorphic(target2);
-  performAwaitFutureOrCallsInstanceTargetPolymorphic(target3);
+  await performAwaitCallsClosureTargetPolymorphic(returnAsync);
+  await performAwaitCallsClosureTargetPolymorphic(returnFuture);
+  await performAwaitCallsClosureTargetPolymorphic(returnFutureOr);
+  await performAwaitAsyncCallsInstanceTargetPolymorphic(target);
+  await performAwaitAsyncCallsInstanceTargetPolymorphic(target2);
+  await performAwaitAsyncCallsInstanceTargetPolymorphic(target3);
+  await performAwaitFutureCallsInstanceTargetPolymorphic(target);
+  await performAwaitFutureCallsInstanceTargetPolymorphic(target2);
+  await performAwaitFutureCallsInstanceTargetPolymorphic(target3);
+  await performAwaitFutureOrCallsInstanceTargetPolymorphic(target);
+  await performAwaitFutureOrCallsInstanceTargetPolymorphic(target2);
+  await performAwaitFutureOrCallsInstanceTargetPolymorphic(target3);
   performSyncCallsInstanceTargetPolymorphic(target);
   performSyncCallsInstanceTargetPolymorphic(target2);
   performSyncCallsInstanceTargetPolymorphic(target3);
-  performAwaitAsyncCallsInstanceTargetPolymorphicManyAwaits(target);
-  performAwaitAsyncCallsInstanceTargetPolymorphicManyAwaits(target2);
-  performAwaitAsyncCallsInstanceTargetPolymorphicManyAwaits(target3);
+  await performAwaitAsyncCallsInstanceTargetPolymorphicManyAwaits(target);
+  await performAwaitAsyncCallsInstanceTargetPolymorphicManyAwaits(target2);
+  await performAwaitAsyncCallsInstanceTargetPolymorphicManyAwaits(target3);
 
-  performAwaitForIterationPolymorphic(generateNumbersAsyncStar);
-  performAwaitForIterationPolymorphic(generateNumbersAsyncStar2);
-  performAwaitForIterationPolymorphic(generateNumbersManualAsync);
-  performAwaitForIterationPolymorphic(generateNumbersAsyncStarManyYields);
+  await performAwaitForIterationPolymorphic(generateNumbersAsyncStar);
+  await performAwaitForIterationPolymorphic(generateNumbersAsyncStar2);
+  await performAwaitForIterationPolymorphic(generateNumbersManualAsync);
+  await performAwaitForIterationPolymorphic(generateNumbersAsyncStarManyYields);
   performSyncIterationPolymorphic(generateNumbersSyncStar);
   performSyncIterationPolymorphic(generateNumbersSyncStar2);
   performSyncIterationPolymorphic(generateNumbersManual);
@@ -105,7 +105,7 @@
 @pragma('vm:never-inline')
 @pragma('dart2js:noInline')
 Future<int> performAwaitCallsClosureTargetPolymorphic(
-    FutureOr<int> fun(int count)) async {
+    FutureOr<int> Function(int) fun) async {
   int sum = 0;
   for (int i = 0; i < iterationLimitAsync; ++i) {
     sum += await fun(i);
@@ -286,7 +286,7 @@
 @pragma('vm:never-inline')
 @pragma('dart2js:noInline')
 Future<int> performAwaitForIterationPolymorphic(
-    Stream<int> fun(int count)) async {
+    Stream<int> Function(int) fun) async {
   int sum = 0;
   await for (int value in fun(iterationLimitAsync)) {
     sum += value;
@@ -297,7 +297,7 @@
 
 @pragma('vm:never-inline')
 @pragma('dart2js:noInline')
-int performSyncCallsClosureTarget(int fun(int count)) {
+int performSyncCallsClosureTarget(int Function(int) fun) {
   int sum = 0;
   for (int i = 0; i < iterationLimitSync; ++i) {
     sum += fun(i);
@@ -330,7 +330,7 @@
 
 @pragma('vm:never-inline')
 @pragma('dart2js:noInline')
-int performSyncIterationPolymorphic(Iterable<int> fun(int count)) {
+int performSyncIterationPolymorphic(Iterable<int> Function(int) fun) {
   int sum = 0;
   for (int value in fun(iterationLimitSync)) {
     sum += value;
@@ -371,7 +371,7 @@
 @pragma('dart2js:noInline')
 Stream<int> generateNumbersManualAsync(int limit) {
   int current = 0;
-  StreamController<int> controller = StreamController(sync: true);
+  final controller = StreamController<int>(sync: true);
   void emit() {
     while (true) {
       if (controller.isPaused || !controller.hasListener) return;
@@ -746,36 +746,44 @@
 }
 
 class Target2 extends Target {
+  @override
   @pragma('vm:never-inline')
   @pragma('dart2js:noInline')
   FutureOr<int> returnFutureOr(int i) => i;
 
+  @override
   @pragma('vm:never-inline')
   @pragma('dart2js:noInline')
   Future<int> returnFuture(int i) => Future.value(i);
 
+  @override
   @pragma('vm:never-inline')
   @pragma('dart2js:noInline')
   Future<int> returnAsync(int i) async => i;
 
+  @override
   @pragma('vm:never-inline')
   @pragma('dart2js:noInline')
   int returnSync(int i) => i;
 }
 
 class Target3 extends Target {
+  @override
   @pragma('vm:never-inline')
   @pragma('dart2js:noInline')
   FutureOr<int> returnFutureOr(int i) => i;
 
+  @override
   @pragma('vm:never-inline')
   @pragma('dart2js:noInline')
   Future<int> returnFuture(int i) => Future.value(i);
 
+  @override
   @pragma('vm:never-inline')
   @pragma('dart2js:noInline')
   Future<int> returnAsync(int i) async => i;
 
+  @override
   @pragma('vm:never-inline')
   @pragma('dart2js:noInline')
   int returnSync(int i) => i;
@@ -815,7 +823,7 @@
     final double nsPerCall = measureFor(const Duration(seconds: 2));
 
     // Report result.
-    print("$name(RunTimeRaw): $nsPerCall ns.");
+    print('$name(RunTimeRaw): $nsPerCall ns.');
   }
 }
 
@@ -850,6 +858,6 @@
     final double nsPerCall = await measureFor(const Duration(seconds: 2));
 
     // Report result.
-    print("$name(RunTimeRaw): $nsPerCall ns.");
+    print('$name(RunTimeRaw): $nsPerCall ns.');
   }
 }
diff --git a/benchmarks/Example/dart/Example.dart b/benchmarks/Example/dart/Example.dart
index 451124b..bf0f06f 100644
--- a/benchmarks/Example/dart/Example.dart
+++ b/benchmarks/Example/dart/Example.dart
@@ -5,18 +5,21 @@
 import 'package:benchmark_harness/benchmark_harness.dart';
 
 class Example extends BenchmarkBase {
-  const Example() : super("Example");
+  const Example() : super('Example');
 
   // The benchmark code.
+  @override
   void run() {}
 
   // Not measured setup code executed prior to the benchmark runs.
+  @override
   void setup() {}
 
   // Not measures teardown code executed after the benchark runs.
+  @override
   void teardown() {}
 }
 
-main() {
+void main() {
   const Example().report();
 }
diff --git a/benchmarks/Example/dart2/Example.dart b/benchmarks/Example/dart2/Example.dart
index 451124b..bf0f06f 100644
--- a/benchmarks/Example/dart2/Example.dart
+++ b/benchmarks/Example/dart2/Example.dart
@@ -5,18 +5,21 @@
 import 'package:benchmark_harness/benchmark_harness.dart';
 
 class Example extends BenchmarkBase {
-  const Example() : super("Example");
+  const Example() : super('Example');
 
   // The benchmark code.
+  @override
   void run() {}
 
   // Not measured setup code executed prior to the benchmark runs.
+  @override
   void setup() {}
 
   // Not measures teardown code executed after the benchark runs.
+  @override
   void teardown() {}
 }
 
-main() {
+void main() {
   const Example().report();
 }
diff --git a/benchmarks/Isolate/dart/Isolate.dart b/benchmarks/Isolate/dart/Isolate.dart
index 465d56a..b703340 100644
--- a/benchmarks/Isolate/dart/Isolate.dart
+++ b/benchmarks/Isolate/dart/Isolate.dart
@@ -8,11 +8,10 @@
 
 import 'package:benchmark_harness/benchmark_harness.dart'
     show PrintEmitter, ScoreEmitter;
-import 'package:meta/meta.dart';
 
 class SendReceiveBytes extends AsyncBenchmarkBase {
   SendReceiveBytes(String name,
-      {@required int this.size, @required bool this.useTransferable})
+      {required this.size, required this.useTransferable})
       : super(name);
 
   @override
@@ -33,7 +32,7 @@
 
   final bool useTransferable;
   final int size;
-  SendReceiveHelper helper;
+  late SendReceiveHelper helper;
 }
 
 // Identical to BenchmarkBase from package:benchmark_harness but async.
@@ -86,10 +85,10 @@
 
 // Measures how long sending and receiving of [size]-length Uint8List takes.
 class SendReceiveHelper {
-  SendReceiveHelper(this.size, {@required bool this.useTransferable});
+  SendReceiveHelper(this.size, {required this.useTransferable});
 
   Future<void> setup() async {
-    data = new Uint8List(size);
+    data = Uint8List(size);
 
     port = ReceivePort();
     inbox = StreamIterator<dynamic>(port);
@@ -121,24 +120,24 @@
     }
   }
 
-  Uint8List data;
-  ReceivePort port;
-  StreamIterator<dynamic> inbox;
-  SendPort outbox;
-  Isolate worker;
-  Completer<bool> workerCompleted;
-  ReceivePort workerExitedPort;
+  late Uint8List data;
+  late ReceivePort port;
+  late StreamIterator<dynamic> inbox;
+  late SendPort outbox;
+  late Isolate worker;
+  late Completer<bool> workerCompleted;
+  late ReceivePort workerExitedPort;
   final int size;
   final bool useTransferable;
 }
 
-packageList(Uint8List data, bool useTransferable) =>
+Object packageList(Uint8List data, bool useTransferable) =>
     useTransferable ? TransferableTypedData.fromList(<Uint8List>[data]) : data;
 
 Future<void> isolate(StartMessage startMessage) async {
   final port = ReceivePort();
   final inbox = StreamIterator<dynamic>(port);
-  final data = Uint8List.view(new Uint8List(startMessage.size).buffer);
+  final data = Uint8List.view(Uint8List(startMessage.size).buffer);
 
   startMessage.sendPort.send(port.sendPort);
   while (true) {
@@ -163,22 +162,22 @@
   final String name;
 }
 
-final List<SizeName> sizes = <SizeName>[
-  SizeName(1 * 1024, "1KB"),
-  SizeName(10 * 1024, "10KB"),
-  SizeName(100 * 1024, "100KB"),
-  SizeName(1 * 1024 * 1024, "1MB"),
-  SizeName(10 * 1024 * 1024, "10MB"),
-  SizeName(100 * 1024 * 1024, "100MB")
+const List<SizeName> sizes = <SizeName>[
+  SizeName(1 * 1024, '1KB'),
+  SizeName(10 * 1024, '10KB'),
+  SizeName(100 * 1024, '100KB'),
+  SizeName(1 * 1024 * 1024, '1MB'),
+  SizeName(10 * 1024 * 1024, '10MB'),
+  SizeName(100 * 1024 * 1024, '100MB')
 ];
 
 Future<void> main() async {
-  for (SizeName sizeName in sizes) {
-    await SendReceiveBytes("Isolate.SendReceiveBytes${sizeName.name}",
+  for (final sizeName in sizes) {
+    await SendReceiveBytes('Isolate.SendReceiveBytes${sizeName.name}',
             size: sizeName.size, useTransferable: false)
         .report();
     await SendReceiveBytes(
-            "Isolate.SendReceiveBytesTransferable${sizeName.name}",
+            'Isolate.SendReceiveBytesTransferable${sizeName.name}',
             size: sizeName.size,
             useTransferable: true)
         .report();
diff --git a/benchmarks/Isolate/dart2/Isolate.dart b/benchmarks/Isolate/dart2/Isolate.dart
index 465d56a..aba6224 100644
--- a/benchmarks/Isolate/dart2/Isolate.dart
+++ b/benchmarks/Isolate/dart2/Isolate.dart
@@ -12,7 +12,7 @@
 
 class SendReceiveBytes extends AsyncBenchmarkBase {
   SendReceiveBytes(String name,
-      {@required int this.size, @required bool this.useTransferable})
+      {@required this.size, @required this.useTransferable})
       : super(name);
 
   @override
@@ -86,10 +86,10 @@
 
 // Measures how long sending and receiving of [size]-length Uint8List takes.
 class SendReceiveHelper {
-  SendReceiveHelper(this.size, {@required bool this.useTransferable});
+  SendReceiveHelper(this.size, {@required this.useTransferable});
 
   Future<void> setup() async {
-    data = new Uint8List(size);
+    data = Uint8List(size);
 
     port = ReceivePort();
     inbox = StreamIterator<dynamic>(port);
@@ -132,13 +132,13 @@
   final bool useTransferable;
 }
 
-packageList(Uint8List data, bool useTransferable) =>
+Object packageList(Uint8List data, bool useTransferable) =>
     useTransferable ? TransferableTypedData.fromList(<Uint8List>[data]) : data;
 
 Future<void> isolate(StartMessage startMessage) async {
   final port = ReceivePort();
   final inbox = StreamIterator<dynamic>(port);
-  final data = Uint8List.view(new Uint8List(startMessage.size).buffer);
+  final data = Uint8List.view(Uint8List(startMessage.size).buffer);
 
   startMessage.sendPort.send(port.sendPort);
   while (true) {
@@ -163,22 +163,22 @@
   final String name;
 }
 
-final List<SizeName> sizes = <SizeName>[
-  SizeName(1 * 1024, "1KB"),
-  SizeName(10 * 1024, "10KB"),
-  SizeName(100 * 1024, "100KB"),
-  SizeName(1 * 1024 * 1024, "1MB"),
-  SizeName(10 * 1024 * 1024, "10MB"),
-  SizeName(100 * 1024 * 1024, "100MB")
+const List<SizeName> sizes = <SizeName>[
+  SizeName(1 * 1024, '1KB'),
+  SizeName(10 * 1024, '10KB'),
+  SizeName(100 * 1024, '100KB'),
+  SizeName(1 * 1024 * 1024, '1MB'),
+  SizeName(10 * 1024 * 1024, '10MB'),
+  SizeName(100 * 1024 * 1024, '100MB')
 ];
 
 Future<void> main() async {
-  for (SizeName sizeName in sizes) {
-    await SendReceiveBytes("Isolate.SendReceiveBytes${sizeName.name}",
+  for (final sizeName in sizes) {
+    await SendReceiveBytes('Isolate.SendReceiveBytes${sizeName.name}',
             size: sizeName.size, useTransferable: false)
         .report();
     await SendReceiveBytes(
-            "Isolate.SendReceiveBytesTransferable${sizeName.name}",
+            'Isolate.SendReceiveBytesTransferable${sizeName.name}',
             size: sizeName.size,
             useTransferable: true)
         .report();
diff --git a/benchmarks/IsolateJson/dart/IsolateJson.dart b/benchmarks/IsolateJson/dart/IsolateJson.dart
index 1fa4919..5b5a9ee 100644
--- a/benchmarks/IsolateJson/dart/IsolateJson.dart
+++ b/benchmarks/IsolateJson/dart/IsolateJson.dart
@@ -9,15 +9,14 @@
 import 'dart:typed_data';
 
 import 'package:benchmark_harness/benchmark_harness.dart' show BenchmarkBase;
-import 'package:meta/meta.dart';
 
 import 'runtime/tests/vm/dart/export_sendAndExit_helper.dart' show sendAndExit;
 
 class JsonDecodingBenchmark {
   JsonDecodingBenchmark(this.name,
-      {@required this.sample,
-      @required this.numTasks,
-      @required this.useSendAndExit});
+      {required this.sample,
+      required this.numTasks,
+      required this.useSendAndExit});
 
   Future<void> report() async {
     final stopwatch = Stopwatch()..start();
@@ -30,7 +29,7 @@
       await Future.wait(decodedFutures);
     }
 
-    print("$name(RunTime): ${stopwatch.elapsedMicroseconds} us.");
+    print('$name(RunTime): ${stopwatch.elapsedMicroseconds} us.');
   }
 
   final String name;
@@ -45,7 +44,7 @@
   for (int i = 0; i < size; i++) {
     map['$i'] = list;
   }
-  return utf8.encode(json.encode(map));
+  return utf8.encode(json.encode(map)) as Uint8List;
 }
 
 class JsonDecodeRequest {
@@ -73,7 +72,7 @@
   workerExitedPort.close();
   workerErroredPort.close();
   await inbox.moveNext();
-  final decodedJson = inbox.current;
+  final decodedJson = inbox.current as Map;
   port.close();
   return decodedJson;
 }
@@ -89,7 +88,7 @@
 
 class SyncJsonDecodingBenchmark extends BenchmarkBase {
   SyncJsonDecodingBenchmark(String name,
-      {@required this.sample, @required this.iterations})
+      {required this.sample, required this.iterations})
       : super(name);
 
   @override
@@ -116,43 +115,46 @@
 Future<void> main() async {
   final jsonString =
       File('benchmarks/IsolateJson/dart/sample.json').readAsStringSync();
-  final json250KB = utf8.encode(jsonString); // 294356 bytes
+  final json250KB = utf8.encode(jsonString) as Uint8List; // 294356 bytes
   final decoded = json.decode(utf8.decode(json250KB));
   final decoded1MB = <dynamic, dynamic>{
-    "1": decoded["1"],
-    "2": decoded["1"],
-    "3": decoded["1"],
-    "4": decoded["1"],
+    '1': decoded['1'],
+    '2': decoded['1'],
+    '3': decoded['1'],
+    '4': decoded['1'],
   };
-  final json1MB = utf8.encode(json.encode(decoded1MB)); // 1177397 bytes
-  decoded["1"] = (decoded["1"] as List).sublist(0, 200);
-  final json100KB = utf8.encode(json.encode(decoded)); // 104685 bytes
-  decoded["1"] = (decoded["1"] as List).sublist(0, 100);
-  final json50KB = utf8.encode(json.encode(decoded)); // 51760 bytes
+  final json1MB =
+      utf8.encode(json.encode(decoded1MB)) as Uint8List; // 1177397 bytes
+  decoded['1'] = (decoded['1'] as List).sublist(0, 200);
+  final json100KB =
+      utf8.encode(json.encode(decoded)) as Uint8List; // 104685 bytes
+  decoded['1'] = (decoded['1'] as List).sublist(0, 100);
+  final json50KB =
+      utf8.encode(json.encode(decoded)) as Uint8List; // 51760 bytes
 
   final configs = <BenchmarkConfig>[
-    BenchmarkConfig("50KB", json50KB),
-    BenchmarkConfig("100KB", json100KB),
-    BenchmarkConfig("250KB", json250KB),
-    BenchmarkConfig("1MB", json1MB),
+    BenchmarkConfig('50KB', json50KB),
+    BenchmarkConfig('100KB', json100KB),
+    BenchmarkConfig('250KB', json250KB),
+    BenchmarkConfig('1MB', json1MB),
   ];
 
-  for (BenchmarkConfig config in configs) {
+  for (final config in configs) {
     for (final iterations in <int>[1, 4]) {
       await JsonDecodingBenchmark(
-              "IsolateJson.Decode${config.suffix}x$iterations",
+              'IsolateJson.Decode${config.suffix}x$iterations',
               useSendAndExit: false,
               sample: config.sample,
               numTasks: iterations)
           .report();
       await JsonDecodingBenchmark(
-              "IsolateJson.SendAndExit_Decode${config.suffix}x$iterations",
+              'IsolateJson.SendAndExit_Decode${config.suffix}x$iterations',
               useSendAndExit: true,
               sample: config.sample,
               numTasks: iterations)
           .report();
       SyncJsonDecodingBenchmark(
-              "IsolateJson.SyncDecode${config.suffix}x$iterations",
+              'IsolateJson.SyncDecode${config.suffix}x$iterations',
               sample: config.sample,
               iterations: iterations)
           .report();
diff --git a/benchmarks/IsolateJson/dart2/IsolateJson.dart b/benchmarks/IsolateJson/dart2/IsolateJson.dart
index 459c133..4e64477 100644
--- a/benchmarks/IsolateJson/dart2/IsolateJson.dart
+++ b/benchmarks/IsolateJson/dart2/IsolateJson.dart
@@ -30,7 +30,7 @@
       await Future.wait(decodedFutures);
     }
 
-    print("$name(RunTime): ${stopwatch.elapsedMicroseconds} us.");
+    print('$name(RunTime): ${stopwatch.elapsedMicroseconds} us.');
   }
 
   final String name;
@@ -119,40 +119,40 @@
   final json250KB = utf8.encode(jsonString); // 294356 bytes
   final decoded = json.decode(utf8.decode(json250KB));
   final decoded1MB = <dynamic, dynamic>{
-    "1": decoded["1"],
-    "2": decoded["1"],
-    "3": decoded["1"],
-    "4": decoded["1"],
+    '1': decoded['1'],
+    '2': decoded['1'],
+    '3': decoded['1'],
+    '4': decoded['1'],
   };
   final json1MB = utf8.encode(json.encode(decoded1MB)); // 1177397 bytes
-  decoded["1"] = (decoded["1"] as List).sublist(0, 200);
+  decoded['1'] = (decoded['1'] as List).sublist(0, 200);
   final json100KB = utf8.encode(json.encode(decoded)); // 104685 bytes
-  decoded["1"] = (decoded["1"] as List).sublist(0, 100);
+  decoded['1'] = (decoded['1'] as List).sublist(0, 100);
   final json50KB = utf8.encode(json.encode(decoded)); // 51760 bytes
 
   final configs = <BenchmarkConfig>[
-    BenchmarkConfig("50KB", json50KB),
-    BenchmarkConfig("100KB", json100KB),
-    BenchmarkConfig("250KB", json250KB),
-    BenchmarkConfig("1MB", json1MB),
+    BenchmarkConfig('50KB', json50KB),
+    BenchmarkConfig('100KB', json100KB),
+    BenchmarkConfig('250KB', json250KB),
+    BenchmarkConfig('1MB', json1MB),
   ];
 
-  for (BenchmarkConfig config in configs) {
+  for (final config in configs) {
     for (final iterations in <int>[1, 4]) {
       await JsonDecodingBenchmark(
-              "IsolateJson.Decode${config.suffix}x$iterations",
+              'IsolateJson.Decode${config.suffix}x$iterations',
               useSendAndExit: false,
               sample: config.sample,
               numTasks: iterations)
           .report();
       await JsonDecodingBenchmark(
-              "IsolateJson.SendAndExit_Decode${config.suffix}x$iterations",
+              'IsolateJson.SendAndExit_Decode${config.suffix}x$iterations',
               useSendAndExit: true,
               sample: config.sample,
               numTasks: iterations)
           .report();
       SyncJsonDecodingBenchmark(
-              "IsolateJson.SyncDecode${config.suffix}x$iterations",
+              'IsolateJson.SyncDecode${config.suffix}x$iterations',
               sample: config.sample,
               iterations: iterations)
           .report();
diff --git a/benchmarks/IsolateSpawn/dart/IsolateSpawn.dart b/benchmarks/IsolateSpawn/dart/IsolateSpawn.dart
index 5742568..6212abe 100644
--- a/benchmarks/IsolateSpawn/dart/IsolateSpawn.dart
+++ b/benchmarks/IsolateSpawn/dart/IsolateSpawn.dart
@@ -6,8 +6,6 @@
 import 'dart:isolate';
 import 'dart:math';
 
-import 'package:meta/meta.dart';
-
 import 'package:compiler/src/dart2js.dart' as dart2js_main;
 
 class SpawnLatency {
@@ -16,17 +14,17 @@
   Future<ResultMessageLatency> run() async {
     final completerResult = Completer();
     final receivePort = ReceivePort()..listen(completerResult.complete);
-    final Completer<DateTime> isolateExitedCompleter = Completer<DateTime>();
+    final isolateExitedCompleter = Completer<DateTime>();
     final onExitReceivePort = ReceivePort()
       ..listen((_) {
         isolateExitedCompleter.complete(DateTime.now());
       });
-    final DateTime beforeSpawn = DateTime.now();
+    final beforeSpawn = DateTime.now();
     await Isolate.spawn(
         isolateCompiler, StartMessageLatency(receivePort.sendPort, beforeSpawn),
         onExit: onExitReceivePort.sendPort,
         onError: onExitReceivePort.sendPort);
-    final DateTime afterSpawn = DateTime.now();
+    final afterSpawn = DateTime.now();
 
     final ResultMessageLatency result = await completerResult.future;
     receivePort.close();
@@ -42,13 +40,13 @@
   Future<AggregatedResultMessageLatency> measureFor(int minimumMillis) async {
     final minimumMicros = minimumMillis * 1000;
     final watch = Stopwatch()..start();
-    final Metric toAfterIsolateSpawnUs = LatencyMetric("${name}ToAfterSpawn");
-    final Metric toStartRunningCodeUs = LatencyMetric("${name}ToStartRunning");
+    final Metric toAfterIsolateSpawnUs = LatencyMetric('${name}ToAfterSpawn');
+    final Metric toStartRunningCodeUs = LatencyMetric('${name}ToStartRunning');
     final Metric toFinishRunningCodeUs =
-        LatencyMetric("${name}ToFinishRunning");
-    final Metric toExitUs = LatencyMetric("${name}ToExit");
+        LatencyMetric('${name}ToFinishRunning');
+    final Metric toExitUs = LatencyMetric('${name}ToExit');
     while (watch.elapsedMicroseconds < minimumMicros) {
-      final ResultMessageLatency result = await run();
+      final result = await run();
       toAfterIsolateSpawnUs.add(result.timeToIsolateSpawnUs);
       toStartRunningCodeUs.add(result.timeToStartRunningCodeUs);
       toFinishRunningCodeUs.add(result.timeToFinishRunningCodeUs);
@@ -64,16 +62,16 @@
   }
 
   Future<void> report() async {
-    final AggregatedResultMessageLatency result = await measure();
+    final result = await measure();
     print(result);
   }
 
   final String name;
-  RawReceivePort receivePort;
+  late RawReceivePort receivePort;
 }
 
 class Metric {
-  Metric({@required this.prefix, @required this.suffix});
+  Metric({required this.prefix, required this.suffix});
 
   void add(int value) {
     if (value > max) {
@@ -87,9 +85,10 @@
   double _average() => sum / count;
   double _rms() => sqrt(sumOfSquares / count);
 
-  toString() => "$prefix): ${_average()}$suffix\n"
-      "${prefix}Max): $max$suffix\n"
-      "${prefix}RMS): ${_rms()}$suffix";
+  @override
+  String toString() => '$prefix): ${_average()}$suffix\n'
+      '${prefix}Max): $max$suffix\n'
+      '${prefix}RMS): ${_rms()}$suffix';
 
   final String prefix;
   final String suffix;
@@ -100,7 +99,7 @@
 }
 
 class LatencyMetric extends Metric {
-  LatencyMetric(String name) : super(prefix: "$name(Latency", suffix: " us.");
+  LatencyMetric(String name) : super(prefix: '$name(Latency', suffix: ' us.');
 }
 
 class StartMessageLatency {
@@ -112,16 +111,14 @@
 
 class ResultMessageLatency {
   ResultMessageLatency(
-      {this.timeToStartRunningCodeUs,
-      this.timeToFinishRunningCodeUs,
-      this.deltaHeap});
+      {required this.timeToStartRunningCodeUs,
+      required this.timeToFinishRunningCodeUs});
 
   final int timeToStartRunningCodeUs;
   final int timeToFinishRunningCodeUs;
-  final int deltaHeap;
 
-  int timeToIsolateSpawnUs;
-  int timeToExitUs;
+  late int timeToIsolateSpawnUs;
+  late int timeToExitUs;
 }
 
 class AggregatedResultMessageLatency {
@@ -132,10 +129,11 @@
     this.toExitUs,
   );
 
-  String toString() => """$toAfterIsolateSpawnUs
+  @override
+  String toString() => '''$toAfterIsolateSpawnUs
 $toStartRunningCodeUs
 $toFinishRunningCodeUs
-$toExitUs""";
+$toExitUs''';
 
   final Metric toAfterIsolateSpawnUs;
   final Metric toStartRunningCodeUs;
@@ -144,15 +142,15 @@
 }
 
 Future<void> isolateCompiler(StartMessageLatency start) async {
-  final DateTime timeRunningCodeUs = DateTime.now();
+  final timeRunningCodeUs = DateTime.now();
   await runZoned(
       () => dart2js_main.internalMain(<String>[
-            "benchmarks/IsolateSpawn/dart/helloworld.dart",
+            'benchmarks/IsolateSpawn/dart/helloworld.dart',
             '--libraries-spec=sdk/lib/libraries.json'
           ]),
       zoneSpecification: ZoneSpecification(
           print: (Zone self, ZoneDelegate parent, Zone zone, String line) {}));
-  final DateTime timeFinishRunningCodeUs = DateTime.now();
+  final timeFinishRunningCodeUs = DateTime.now();
   start.sendPort.send(ResultMessageLatency(
       timeToStartRunningCodeUs:
           timeRunningCodeUs.difference(start.spawned).inMicroseconds,
@@ -161,5 +159,5 @@
 }
 
 Future<void> main() async {
-  await SpawnLatency("IsolateSpawn.Dart2JS").report();
+  await SpawnLatency('IsolateSpawn.Dart2JS').report();
 }
diff --git a/benchmarks/IsolateSpawn/dart2/IsolateSpawn.dart b/benchmarks/IsolateSpawn/dart2/IsolateSpawn.dart
index e8ec25c..a754441 100644
--- a/benchmarks/IsolateSpawn/dart2/IsolateSpawn.dart
+++ b/benchmarks/IsolateSpawn/dart2/IsolateSpawn.dart
@@ -16,17 +16,17 @@
   Future<ResultMessageLatency> run() async {
     final completerResult = Completer();
     final receivePort = ReceivePort()..listen(completerResult.complete);
-    final Completer<DateTime> isolateExitedCompleter = Completer<DateTime>();
+    final isolateExitedCompleter = Completer<DateTime>();
     final onExitReceivePort = ReceivePort()
       ..listen((_) {
         isolateExitedCompleter.complete(DateTime.now());
       });
-    final DateTime beforeSpawn = DateTime.now();
+    final beforeSpawn = DateTime.now();
     await Isolate.spawn(
         isolateCompiler, StartMessageLatency(receivePort.sendPort, beforeSpawn),
         onExit: onExitReceivePort.sendPort,
         onError: onExitReceivePort.sendPort);
-    final DateTime afterSpawn = DateTime.now();
+    final afterSpawn = DateTime.now();
 
     final ResultMessageLatency result = await completerResult.future;
     receivePort.close();
@@ -42,13 +42,13 @@
   Future<AggregatedResultMessageLatency> measureFor(int minimumMillis) async {
     final minimumMicros = minimumMillis * 1000;
     final watch = Stopwatch()..start();
-    final Metric toAfterIsolateSpawnUs = LatencyMetric("${name}ToAfterSpawn");
-    final Metric toStartRunningCodeUs = LatencyMetric("${name}ToStartRunning");
+    final Metric toAfterIsolateSpawnUs = LatencyMetric('${name}ToAfterSpawn');
+    final Metric toStartRunningCodeUs = LatencyMetric('${name}ToStartRunning');
     final Metric toFinishRunningCodeUs =
-        LatencyMetric("${name}ToFinishRunning");
-    final Metric toExitUs = LatencyMetric("${name}ToExit");
+        LatencyMetric('${name}ToFinishRunning');
+    final Metric toExitUs = LatencyMetric('${name}ToExit');
     while (watch.elapsedMicroseconds < minimumMicros) {
-      final ResultMessageLatency result = await run();
+      final result = await run();
       toAfterIsolateSpawnUs.add(result.timeToIsolateSpawnUs);
       toStartRunningCodeUs.add(result.timeToStartRunningCodeUs);
       toFinishRunningCodeUs.add(result.timeToFinishRunningCodeUs);
@@ -64,7 +64,7 @@
   }
 
   Future<void> report() async {
-    final AggregatedResultMessageLatency result = await measure();
+    final result = await measure();
     print(result);
   }
 
@@ -87,9 +87,10 @@
   double _average() => sum / count;
   double _rms() => sqrt(sumOfSquares / count);
 
-  toString() => "$prefix): ${_average()}$suffix\n"
-      "${prefix}Max): $max$suffix\n"
-      "${prefix}RMS): ${_rms()}$suffix";
+  @override
+  String toString() => '$prefix): ${_average()}$suffix\n'
+      '${prefix}Max): $max$suffix\n'
+      '${prefix}RMS): ${_rms()}$suffix';
 
   final String prefix;
   final String suffix;
@@ -100,7 +101,7 @@
 }
 
 class LatencyMetric extends Metric {
-  LatencyMetric(String name) : super(prefix: "$name(Latency", suffix: " us.");
+  LatencyMetric(String name) : super(prefix: '$name(Latency', suffix: ' us.');
 }
 
 class StartMessageLatency {
@@ -132,10 +133,11 @@
     this.toExitUs,
   );
 
-  String toString() => """$toAfterIsolateSpawnUs
+  @override
+  String toString() => '''$toAfterIsolateSpawnUs
 $toStartRunningCodeUs
 $toFinishRunningCodeUs
-$toExitUs""";
+$toExitUs''';
 
   final Metric toAfterIsolateSpawnUs;
   final Metric toStartRunningCodeUs;
@@ -144,15 +146,15 @@
 }
 
 Future<void> isolateCompiler(StartMessageLatency start) async {
-  final DateTime timeRunningCodeUs = DateTime.now();
+  final timeRunningCodeUs = DateTime.now();
   await runZoned(
       () => dart2js_main.internalMain(<String>[
-            "benchmarks/IsolateSpawn/dart2/helloworld.dart",
+            'benchmarks/IsolateSpawn/dart/helloworld.dart',
             '--libraries-spec=sdk/lib/libraries.json'
           ]),
       zoneSpecification: ZoneSpecification(
           print: (Zone self, ZoneDelegate parent, Zone zone, String line) {}));
-  final DateTime timeFinishRunningCodeUs = DateTime.now();
+  final timeFinishRunningCodeUs = DateTime.now();
   start.sendPort.send(ResultMessageLatency(
       timeToStartRunningCodeUs:
           timeRunningCodeUs.difference(start.spawned).inMicroseconds,
@@ -161,5 +163,5 @@
 }
 
 Future<void> main() async {
-  await SpawnLatency("IsolateSpawn.Dart2JS").report();
+  await SpawnLatency('IsolateSpawn.Dart2JS').report();
 }
diff --git a/benchmarks/IsolateSpawnMemory/dart/IsolateSpawnMemory.dart b/benchmarks/IsolateSpawnMemory/dart/IsolateSpawnMemory.dart
index 322f1af..1f7b009 100644
--- a/benchmarks/IsolateSpawnMemory/dart/IsolateSpawnMemory.dart
+++ b/benchmarks/IsolateSpawnMemory/dart/IsolateSpawnMemory.dart
@@ -96,11 +96,11 @@
     final doneDiffHeap =
         math.max(0, doneHeap - beforeHeap) ~/ numberOfBenchmarks;
 
-    print("${name}RssOnStart(MemoryUse): $readyDiffRss");
-    print("${name}RssOnEnd(MemoryUse): $doneDiffRss");
-    print("${name}HeapOnStart(MemoryUse): $readyDiffHeap");
-    print("${name}HeapOnEnd(MemoryUse): $doneDiffHeap");
-    print("${name}PeakProcessRss(MemoryUse): $maxProcessRss");
+    print('${name}RssOnStart(MemoryUse): $readyDiffRss');
+    print('${name}RssOnEnd(MemoryUse): $doneDiffRss');
+    print('${name}HeapOnStart(MemoryUse): $readyDiffHeap');
+    print('${name}HeapOnEnd(MemoryUse): $doneDiffHeap');
+    print('${name}PeakProcessRss(MemoryUse): $maxProcessRss');
   }
 
   final String name;
@@ -117,7 +117,7 @@
 
   await runZoned(
       () => dart2js_main.internalMain(<String>[
-            "benchmarks/IsolateSpawnMemory/dart/helloworld.dart",
+            'benchmarks/IsolateSpawnMemory/dart/helloworld.dart',
             '--libraries-spec=sdk/lib/libraries.json'
           ]),
       zoneSpecification: ZoneSpecification(
@@ -133,13 +133,11 @@
 }
 
 Future<int> currentHeapUsage(String wsUri) async {
-  final vm_service.VmService vmService =
-      await vm_service_io.vmServiceConnectUri(wsUri);
+  final vmService = await vm_service_io.vmServiceConnectUri(wsUri);
   final groupIds = await getGroupIds(vmService);
   int sum = 0;
   for (final groupId in groupIds) {
-    final vm_service.MemoryUsage usage =
-        await vmService.getIsolateGroupMemoryUsage(groupId);
+    final usage = await vmService.getIsolateGroupMemoryUsage(groupId);
     sum += usage.heapUsage + usage.externalUsage;
   }
   vmService.dispose();
@@ -150,11 +148,10 @@
   // Only if we successfully reach the end will we set 0 exit code.
   exitCode = 255;
 
-  final ServiceProtocolInfo info = await Service.controlWebServer(enable: true);
-  final Uri observatoryUri = info.serverUri;
-  final String wsUri =
-      'ws://${observatoryUri.authority}${observatoryUri.path}ws';
-  await SpawnMemory("IsolateSpawnMemory.Dart2JSDelta", wsUri).report();
+  final info = await Service.controlWebServer(enable: true);
+  final observatoryUri = info.serverUri!;
+  final wsUri = 'ws://${observatoryUri.authority}${observatoryUri.path}ws';
+  await SpawnMemory('IsolateSpawnMemory.Dart2JSDelta', wsUri).report();
 
   // Only if we successfully reach the end will we set 0 exit code.
   exitCode = 0;
@@ -174,10 +171,9 @@
 Future<List<String>> getGroupIds(vm_service.VmService vmService) async {
   final groupIds = <String>{};
   final vm = await vmService.getVM();
-  for (vm_service.IsolateGroupRef groupRef in vm.isolateGroups) {
-    final vm_service.IsolateGroup group =
-        await vmService.getIsolateGroup(groupRef.id);
-    for (vm_service.IsolateRef isolateRef in group.isolates) {
+  for (final groupRef in vm.isolateGroups) {
+    final group = await vmService.getIsolateGroup(groupRef.id);
+    for (final isolateRef in group.isolates) {
       final isolateOrSentinel = await vmService.getIsolate(isolateRef.id);
       if (isolateOrSentinel is vm_service.Isolate) {
         groupIds.add(groupRef.id);
@@ -185,7 +181,7 @@
     }
   }
   if (groupIds.isEmpty) {
-    throw "Could not find main isolate";
+    throw 'Could not find main isolate';
   }
   return groupIds.toList();
 }
diff --git a/benchmarks/IsolateSpawnMemory/dart2/IsolateSpawnMemory.dart b/benchmarks/IsolateSpawnMemory/dart2/IsolateSpawnMemory.dart
index 609a8c2..5a13d96 100644
--- a/benchmarks/IsolateSpawnMemory/dart2/IsolateSpawnMemory.dart
+++ b/benchmarks/IsolateSpawnMemory/dart2/IsolateSpawnMemory.dart
@@ -96,11 +96,11 @@
     final doneDiffHeap =
         math.max(0, doneHeap - beforeHeap) ~/ numberOfBenchmarks;
 
-    print("${name}RssOnStart(MemoryUse): $readyDiffRss");
-    print("${name}RssOnEnd(MemoryUse): $doneDiffRss");
-    print("${name}HeapOnStart(MemoryUse): $readyDiffHeap");
-    print("${name}HeapOnEnd(MemoryUse): $doneDiffHeap");
-    print("${name}PeakProcessRss(MemoryUse): $maxProcessRss");
+    print('${name}RssOnStart(MemoryUse): $readyDiffRss');
+    print('${name}RssOnEnd(MemoryUse): $doneDiffRss');
+    print('${name}HeapOnStart(MemoryUse): $readyDiffHeap');
+    print('${name}HeapOnEnd(MemoryUse): $doneDiffHeap');
+    print('${name}PeakProcessRss(MemoryUse): $maxProcessRss');
   }
 
   final String name;
@@ -117,7 +117,7 @@
 
   await runZoned(
       () => dart2js_main.internalMain(<String>[
-            "benchmarks/IsolateSpawnMemory/dart2/helloworld.dart",
+            'benchmarks/IsolateSpawnMemory/dart/helloworld.dart',
             '--libraries-spec=sdk/lib/libraries.json'
           ]),
       zoneSpecification: ZoneSpecification(
@@ -133,13 +133,11 @@
 }
 
 Future<int> currentHeapUsage(String wsUri) async {
-  final vm_service.VmService vmService =
-      await vm_service_io.vmServiceConnectUri(wsUri);
+  final vmService = await vm_service_io.vmServiceConnectUri(wsUri);
   final groupIds = await getGroupIds(vmService);
   int sum = 0;
   for (final groupId in groupIds) {
-    final vm_service.MemoryUsage usage =
-        await vmService.getIsolateGroupMemoryUsage(groupId);
+    final usage = await vmService.getIsolateGroupMemoryUsage(groupId);
     sum += usage.heapUsage + usage.externalUsage;
   }
   vmService.dispose();
@@ -150,11 +148,10 @@
   // Only if we successfully reach the end will we set 0 exit code.
   exitCode = 255;
 
-  final ServiceProtocolInfo info = await Service.controlWebServer(enable: true);
-  final Uri observatoryUri = info.serverUri;
-  final String wsUri =
-      'ws://${observatoryUri.authority}${observatoryUri.path}ws';
-  await SpawnMemory("IsolateSpawnMemory.Dart2JSDelta", wsUri).report();
+  final info = await Service.controlWebServer(enable: true);
+  final observatoryUri = info.serverUri;
+  final wsUri = 'ws://${observatoryUri.authority}${observatoryUri.path}ws';
+  await SpawnMemory('IsolateSpawnMemory.Dart2JSDelta', wsUri).report();
 
   // Only if we successfully reach the end will we set 0 exit code.
   exitCode = 0;
@@ -174,10 +171,9 @@
 Future<List<String>> getGroupIds(vm_service.VmService vmService) async {
   final groupIds = <String>{};
   final vm = await vmService.getVM();
-  for (vm_service.IsolateGroupRef groupRef in vm.isolateGroups) {
-    final vm_service.IsolateGroup group =
-        await vmService.getIsolateGroup(groupRef.id);
-    for (vm_service.IsolateRef isolateRef in group.isolates) {
+  for (final groupRef in vm.isolateGroups) {
+    final group = await vmService.getIsolateGroup(groupRef.id);
+    for (final isolateRef in group.isolates) {
       final isolateOrSentinel = await vmService.getIsolate(isolateRef.id);
       if (isolateOrSentinel is vm_service.Isolate) {
         groupIds.add(groupRef.id);
@@ -185,7 +181,7 @@
     }
   }
   if (groupIds.isEmpty) {
-    throw "Could not find main isolate";
+    throw 'Could not find main isolate';
   }
   return groupIds.toList();
 }
diff --git a/benchmarks/analysis_options.yaml b/benchmarks/analysis_options.yaml
index 8099cf0..e7100d3 100644
--- a/benchmarks/analysis_options.yaml
+++ b/benchmarks/analysis_options.yaml
@@ -1,11 +1,15 @@
-include: package:pedantic/analysis_options.yaml
+# Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
 #analyzer:
 #  strong-mode:
 #    implicit-casts: false
 linter:
   rules:
-    #- always_declare_return_types
-    #- annotate_overrides
+    - always_declare_return_types
+    - always_require_non_null_named_parameters
+    - annotate_overrides
     - avoid_empty_else
     - avoid_function_literals_in_foreach_calls
     - avoid_init_to_null
@@ -19,11 +23,13 @@
     - avoid_types_as_parameter_names
     - avoid_unused_constructor_parameters
     - await_only_futures
+    - camel_case_extensions
     - camel_case_types
     - cancel_subscriptions
     - comment_references
     #- constant_identifier_names
     - control_flow_in_finally
+    - curly_braces_in_flow_control_structures
     - directives_ordering
     - empty_catches
     - empty_constructor_bodies
@@ -35,7 +41,7 @@
     - library_names
     - library_prefixes
     - list_remove_unrelated_type
-    - literal_only_boolean_expressions
+    #- literal_only_boolean_expressions
     - no_adjacent_strings_in_list
     - no_duplicate_case_values
     #- non_constant_identifier_names
@@ -52,14 +58,18 @@
     - prefer_const_constructors
     - prefer_contains
     - prefer_equal_for_default_values
-    - prefer_generic_function_type_aliases
     - prefer_final_fields
     - prefer_final_locals
+    - prefer_for_elements_to_map_fromIterable
+    - prefer_generic_function_type_aliases
+    - prefer_if_null_operators
     - prefer_initializing_formals
     - prefer_interpolation_to_compose_strings
     - prefer_is_empty
     - prefer_is_not_empty
-    #- prefer_single_quotes
+    - prefer_iterable_whereType
+    - prefer_single_quotes
+    - prefer_spread_collections
     #- prefer_typing_uninitialized_variables
     - recursive_getters
     - slash_for_doc_comments
@@ -67,16 +77,17 @@
     - throw_in_finally
     - type_init_formals
     - unawaited_futures
-    - unnecessary_await_in_return
+    #- unnecessary_await_in_return
     - unnecessary_brace_in_string_interps
     - unnecessary_const
     - unnecessary_getters_setters
     - unnecessary_lambdas
     - unnecessary_new
     - unnecessary_null_aware_assignments
+    - unnecessary_null_in_if_null_operators
     - unnecessary_parenthesis
     - unnecessary_statements
-    #- unnecessary_this
+    - unnecessary_this
     - unrelated_type_equality_checks
     - use_function_type_syntax_for_parameters
     - use_rethrow_when_possible
diff --git a/pkg/_js_interop_checks/pubspec.yaml b/pkg/_js_interop_checks/pubspec.yaml
index abca579..336d433 100644
--- a/pkg/_js_interop_checks/pubspec.yaml
+++ b/pkg/_js_interop_checks/pubspec.yaml
@@ -1,4 +1,5 @@
 name: _js_interop_checks
+# This package is not intended for consumption on pub.dev. DO NOT publish.
 publish_to: none
 
 environment:
diff --git a/pkg/analysis_server/lib/src/cider/completion.dart b/pkg/analysis_server/lib/src/cider/completion.dart
index bd1f8d5..51d7bfb 100644
--- a/pkg/analysis_server/lib/src/cider/completion.dart
+++ b/pkg/analysis_server/lib/src/cider/completion.dart
@@ -14,6 +14,7 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart' show LibraryElement;
 import 'package:analyzer/src/dart/analysis/performance_logger.dart';
+import 'package:analyzer/src/dart/micro/performance.dart';
 import 'package:analyzer/src/dart/micro/resolve_file.dart';
 import 'package:analyzer/src/dartdoc/dartdoc_directive_info.dart';
 import 'package:analyzer/src/test_utilities/function_ast_visitor.dart';
@@ -33,6 +34,9 @@
   final CiderCompletionCache _cache;
   final FileResolver _fileResolver;
 
+  final CiderOperationPerformanceImpl _performanceRoot =
+      CiderOperationPerformanceImpl('<root>');
+
   DartCompletionRequestImpl _dartCompletionRequest;
 
   /// Paths of imported libraries for which suggestions were (re)computed
@@ -55,91 +59,109 @@
     @required int line,
     @required int column,
   }) async {
-    var getFileTimer = Stopwatch()..start();
-    var fileContext = _logger.run('Get file $path', () {
-      try {
-        return _fileResolver.getFileContext(path);
-      } finally {
-        getFileTimer.stop();
-      }
-    });
-
-    var file = fileContext.file;
-
-    var lineInfo = file.lineInfo;
-    var offset = lineInfo.getOffsetOfLine(line) + column;
-
-    var resolutionTimer = Stopwatch()..start();
-    var resolvedUnit = _fileResolver.resolve(path);
-    resolutionTimer.stop();
-
-    var completionRequest = CompletionRequestImpl(
-      resolvedUnit,
-      offset,
-      false,
-      CompletionPerformance(),
-    );
-    var dartdocDirectiveInfo = DartdocDirectiveInfo();
-
-    var suggestionsTimer = Stopwatch()..start();
-    var suggestions = await _logger.runAsync('Compute suggestions', () async {
-      var includedElementKinds = <ElementKind>{};
-      var includedElementNames = <String>{};
-      var includedSuggestionRelevanceTags = <IncludedSuggestionRelevanceTag>[];
-
-      var manager = DartCompletionManager(
-        dartdocDirectiveInfo: dartdocDirectiveInfo,
-        includedElementKinds: includedElementKinds,
-        includedElementNames: includedElementNames,
-        includedSuggestionRelevanceTags: includedSuggestionRelevanceTags,
-      );
-
-      return await manager.computeSuggestions(
-        completionRequest,
-        enableUriContributor: false,
-      );
-    });
-    suggestionsTimer.stop();
-
-    _dartCompletionRequest = await DartCompletionRequestImpl.from(
-      completionRequest,
-      dartdocDirectiveInfo,
-    );
-
-    var importsTimer = Stopwatch();
-    if (_dartCompletionRequest.includeIdentifiers) {
-      _logger.run('Add imported suggestions', () {
-        importsTimer.start();
-        suggestions.addAll(
-          _importedLibrariesSuggestions(
-            resolvedUnit.libraryElement,
-          ),
+    return _performanceRoot.runAsync('completion', (performance) async {
+      var fileContext = _logger.run('Get file $path', () {
+        return _fileResolver.getFileContext(
+          path: path,
+          performance: performance,
         );
-        importsTimer.stop();
       });
-    }
 
-    var filter = _FilterSort(
-      _dartCompletionRequest,
-      suggestions,
-    );
+      var file = fileContext.file;
 
-    _logger.run('Filter suggestions', () {
-      suggestions = filter.perform();
+      var lineInfo = file.lineInfo;
+      var offset = lineInfo.getOffsetOfLine(line) + column;
+
+      var resolvedUnit = performance.run('resolution', (performance) {
+        return _fileResolver.resolve2(
+          path: path,
+          performance: performance,
+        );
+      });
+
+      var completionRequest = CompletionRequestImpl(
+        resolvedUnit,
+        offset,
+        false,
+        CompletionPerformance(),
+      );
+      var dartdocDirectiveInfo = DartdocDirectiveInfo();
+
+      var suggestions = await performance.runAsync(
+        'suggestions',
+        (performance) async {
+          var result = await _logger.runAsync('Compute suggestions', () async {
+            var includedElementKinds = <ElementKind>{};
+            var includedElementNames = <String>{};
+            var includedSuggestionRelevanceTags =
+                <IncludedSuggestionRelevanceTag>[];
+
+            var manager = DartCompletionManager(
+              dartdocDirectiveInfo: dartdocDirectiveInfo,
+              includedElementKinds: includedElementKinds,
+              includedElementNames: includedElementNames,
+              includedSuggestionRelevanceTags: includedSuggestionRelevanceTags,
+            );
+
+            return await manager.computeSuggestions(
+              completionRequest,
+              enableUriContributor: false,
+            );
+          });
+
+          for (var operation in completionRequest.performance.operations) {
+            performance.addChildFixed(
+              operation.name,
+              operation.elapsed,
+            );
+          }
+
+          return result;
+        },
+      );
+
+      _dartCompletionRequest = await DartCompletionRequestImpl.from(
+        completionRequest,
+        dartdocDirectiveInfo,
+      );
+
+      performance.run('imports', (performance) {
+        if (_dartCompletionRequest.includeIdentifiers) {
+          _logger.run('Add imported suggestions', () {
+            suggestions.addAll(
+              _importedLibrariesSuggestions(
+                resolvedUnit.libraryElement,
+              ),
+            );
+          });
+        }
+      });
+
+      var filter = _FilterSort(
+        _dartCompletionRequest,
+        suggestions,
+      );
+
+      performance.run('filter', (performance) {
+        _logger.run('Filter suggestions', () {
+          suggestions = filter.perform();
+        });
+      });
+
+      var result = CiderCompletionResult._(
+        suggestions: suggestions,
+        performance: CiderCompletionPerformance._(
+          file: performance.getChild('fileContext').elapsed,
+          imports: performance.getChild('imports').elapsed,
+          resolution: performance.getChild('resolution').elapsed,
+          suggestions: performance.getChild('suggestions').elapsed,
+          operations: _performanceRoot.children.first,
+        ),
+        prefixStart: CiderPosition(line, column - filter._pattern.length),
+      );
+
+      return result;
     });
-
-    var result = CiderCompletionResult._(
-      suggestions: suggestions,
-      performance: CiderCompletionPerformance(
-        file: getFileTimer.elapsed,
-        imports: importsTimer.elapsed,
-        resolution: resolutionTimer.elapsed,
-        suggestions: suggestionsTimer.elapsed,
-      ),
-      prefixStart: CiderPosition(line, column - filter._pattern.length),
-    );
-
-    return result;
   }
 
   @Deprecated('Use compute')
@@ -151,6 +173,17 @@
     return compute(path: path, line: line, column: column);
   }
 
+  /// Prepare for computing completions in files from the [pathList].
+  ///
+  /// This method might be called when we are finishing a large initial
+  /// analysis, so spending additionally a fraction of this time to make
+  /// any subsequent completion seem fast is a reasonable trade-off.
+  Future<void> warmUp(List<String> pathList) async {
+    for (var path in pathList) {
+      await compute(path: path, line: 0, column: 0);
+    }
+  }
+
   /// Return suggestions from libraries imported into the [target].
   ///
   /// TODO(scheglov) Implement show / hide combinators.
@@ -214,11 +247,15 @@
   /// The elapsed time to compute suggestions.
   final Duration suggestions;
 
-  CiderCompletionPerformance({
+  /// The tree of operation performances.
+  final CiderOperationPerformance operations;
+
+  CiderCompletionPerformance._({
     @required this.file,
     @required this.imports,
     @required this.resolution,
     @required this.suggestions,
+    @required this.operations,
   });
 }
 
diff --git a/pkg/analysis_server/lib/src/cider/fixes.dart b/pkg/analysis_server/lib/src/cider/fixes.dart
index 5a19221..29205e0 100644
--- a/pkg/analysis_server/lib/src/cider/fixes.dart
+++ b/pkg/analysis_server/lib/src/cider/fixes.dart
@@ -34,7 +34,7 @@
   /// Compute quick fixes for errors on the line with the [offset].
   Future<List<CiderErrorFixes>> compute(String path, int offset) async {
     var result = <CiderErrorFixes>[];
-    var resolvedUnit = _fileResolver.resolve(path);
+    var resolvedUnit = _fileResolver.resolve2(path: path);
 
     var lineInfo = resolvedUnit.lineInfo;
     var requestLine = lineInfo.getLocation(offset).lineNumber;
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
index 5fe7fa0..c83138a 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
@@ -362,26 +362,38 @@
   }
 
   /// Return the pattern to match suggestions against, from the identifier
-  /// to the left of the caret. Return the empty string if cannot find the
-  /// identifier.
+  /// to the left of (or spanning) the caret. Return the empty string if cannot
+  /// find the identifier.
+  ///
+  /// If the caret is within the identifier, the returned pattern will be truncated
+  /// to the position of the caret. For example at:
+  ///
+  ///     new MyClass^Foo
+  ///
+  /// will return "MyClass" as the search pattern.
   String _prefixMatchingPattern(DartCompletionRequestImpl request) {
-    final nodeAtOffsetVisitor =
-        _IdentifierEndingAtOffsetVisitor(request.offset);
-    request.target.containingNode.accept(nodeAtOffsetVisitor);
+    final nodeSpanningOffsetVisitor =
+        _IdentifierSpanningOffsetVisitor(request.offset);
+    request.target.containingNode.accept(nodeSpanningOffsetVisitor);
+    final node = nodeSpanningOffsetVisitor.matchingNode;
 
-    return nodeAtOffsetVisitor.matchingNode?.name ?? '';
+    final prefix = node != null && request.offset - node.offset < node.length
+        ? node.name.substring(0, request.offset - node.offset)
+        : node?.name;
+
+    return prefix ?? '';
   }
 }
 
-/// An AST visitor to locate a [SimpleIdentifier] that ends at the provided offset.
-class _IdentifierEndingAtOffsetVisitor extends RecursiveAstVisitor<void> {
+/// An AST visitor to locate a [SimpleIdentifier] that spans the provided offset.
+class _IdentifierSpanningOffsetVisitor extends RecursiveAstVisitor<void> {
   final int offset;
   SimpleIdentifier _matchingNode;
-  _IdentifierEndingAtOffsetVisitor(this.offset);
+  _IdentifierSpanningOffsetVisitor(this.offset);
   SimpleIdentifier get matchingNode => _matchingNode;
   @override
   void visitSimpleIdentifier(SimpleIdentifier node) {
-    if (node.end == offset) {
+    if (node.offset <= offset && node.end >= offset) {
       _matchingNode = node;
     }
   }
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart b/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart
index e9857ad..944f8cc 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart
@@ -29,6 +29,40 @@
 import 'package:analyzer/src/dart/resolver/body_inference_context.dart';
 import 'package:analyzer_plugin/utilities/range_factory.dart';
 
+const List<String> intNames = ['i', 'j', 'index', 'length'];
+const List<String> listNames = ['list', 'items'];
+const List<String> numNames = ['height', 'width'];
+const List<String> stringNames = [
+  'key',
+  'text',
+  'url',
+  'uri',
+  'name',
+  'str',
+  'string'
+];
+
+DartType impliedDartTypeWithName(TypeProvider typeProvider, String name) {
+  if (typeProvider == null || name == null || name.isEmpty) {
+    return null;
+  }
+  if (intNames.contains(name)) {
+    return typeProvider.intType;
+  } else if (numNames.contains(name)) {
+    return typeProvider.numType;
+  } else if (listNames.contains(name)) {
+    return typeProvider.listType2(typeProvider.dynamicType);
+  } else if (stringNames.contains(name)) {
+    return typeProvider.stringType;
+  } else if (name == 'iterator') {
+    return typeProvider.iterableDynamicType;
+  } else if (name == 'map') {
+    return typeProvider.mapType2(
+        typeProvider.dynamicType, typeProvider.dynamicType);
+  }
+  return null;
+}
+
 /// Convert a relevance score (assumed to be between `0.0` and `1.0` inclusive)
 /// to a relevance value between `0` and `1000`. If the score is outside that
 /// range, return the [defaultValue].
@@ -225,6 +259,33 @@
     return 0.0;
   }
 
+  /// Return the value of the _keyword_ feature for the [keyword] when
+  /// completing at the given [completionLocation].
+  double keywordFeature(String keyword, String completionLocation) {
+    if (completionLocation == null) {
+      return -1.0;
+    }
+    var locationTable = keywordRelevance[completionLocation];
+    if (locationTable == null) {
+      return -1.0;
+    }
+    var range = locationTable[keyword];
+    if (range == null) {
+      // We sometimes suggest multiple tokens where a keyword is allowed, such
+      // as 'async*'. In those cases a valid keyword is always first followed by
+      // a non-alphabetic character. Try stripping off everything after the
+      // keyword and indexing into the table again.
+      var index = keyword.indexOf(RegExp('[^a-z]'));
+      if (index > 0) {
+        range = locationTable[keyword.substring(0, index)];
+      }
+    }
+    if (range == null) {
+      return 0.0;
+    }
+    return range.upper;
+  }
+
   /// Return the value of the _starts with dollar_ feature.
   double startsWithDollarFeature(String name) =>
       name.startsWith('\$') ? 0.0 : 1.0;
@@ -726,7 +787,8 @@
     if (node.equals != null && node.equals.end <= offset) {
       var parent = node.parent;
       if (parent is VariableDeclarationList) {
-        return parent.type?.type;
+        return parent.type?.type ??
+            impliedDartTypeWithName(typeProvider, node.name?.name);
       }
     }
     return null;
@@ -736,8 +798,10 @@
   DartType visitVariableDeclarationList(VariableDeclarationList node) {
     for (var varDecl in node.variables) {
       if (varDecl != null && varDecl.contains(offset)) {
-        if (varDecl.equals.end <= offset) {
-          return node.type?.type;
+        var equals = varDecl.equals;
+        if (equals != null && equals.end <= offset) {
+          return node.type?.type ??
+              impliedDartTypeWithName(typeProvider, varDecl.name?.name);
         }
       }
     }
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/relevance_tables.g.dart b/pkg/analysis_server/lib/src/services/completion/dart/relevance_tables.g.dart
index e461203..943669e 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/relevance_tables.g.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/relevance_tables.g.dart
@@ -15,132 +15,132 @@
 /// ranges of the relevance of those element kinds in those locations.
 const elementKindRelevance = {
   'Annotation_name': {
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.000, upper: 0.042),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.000, upper: 0.041),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.042, upper: 1.000),
+        ProbabilityRange(lower: 0.041, upper: 1.000),
   },
   'ArgumentList_annotation_named': {
-    ElementKind.METHOD: ProbabilityRange(lower: 0.000, upper: 0.979),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.979, upper: 0.984),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.984, upper: 1.000),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.000, upper: 0.026),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.026, upper: 0.060),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.060, upper: 0.159),
   },
   'ArgumentList_annotation_unnamed': {
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.000, upper: 1.000),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.375, upper: 1.000),
   },
   'ArgumentList_constructorRedirect_named': {
-    ElementKind.METHOD: ProbabilityRange(lower: 0.000, upper: 0.041),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.041, upper: 0.044),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.044, upper: 0.047),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.047, upper: 0.050),
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.050, upper: 0.064),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.064, upper: 1.000),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.000, upper: 0.001),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.008, upper: 0.011),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.011, upper: 0.014),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.014, upper: 0.017),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.017, upper: 0.031),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.031, upper: 1.000),
   },
   'ArgumentList_constructorRedirect_unnamed': {
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.000, upper: 0.199),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.199, upper: 0.201),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.201, upper: 0.206),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.206, upper: 0.212),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.212, upper: 0.230),
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.230, upper: 0.279),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.279, upper: 1.000),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.000, upper: 0.003),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.003, upper: 0.005),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.011, upper: 0.016),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.016, upper: 0.024),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.041, upper: 0.062),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.062, upper: 0.122),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.122, upper: 1.000),
   },
   'ArgumentList_constructor_named': {
-    ElementKind.METHOD: ProbabilityRange(lower: 0.000, upper: 0.492),
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.492, upper: 0.493),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.493, upper: 0.495),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.000, upper: 0.002),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.002, upper: 0.004),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.007, upper: 0.011),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.495, upper: 0.504),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.504, upper: 0.516),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.516, upper: 0.545),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.545, upper: 0.574),
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.574, upper: 0.642),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.642, upper: 0.731),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.731, upper: 1.000),
+        ProbabilityRange(lower: 0.042, upper: 0.059),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.059, upper: 0.082),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.082, upper: 0.135),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.135, upper: 0.192),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.192, upper: 0.321),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.321, upper: 0.492),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.492, upper: 1.000),
   },
   'ArgumentList_constructor_unnamed': {
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.617),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.617, upper: 0.622),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.622, upper: 0.630),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.001, upper: 0.004),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.020, upper: 0.031),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.049, upper: 0.070),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.630, upper: 0.641),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.641, upper: 0.656),
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.656, upper: 0.694),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.694, upper: 0.734),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.734, upper: 0.811),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.811, upper: 0.905),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.905, upper: 1.000),
+        ProbabilityRange(lower: 0.070, upper: 0.095),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.124, upper: 0.162),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.162, upper: 0.255),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.255, upper: 0.351),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.351, upper: 0.539),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.539, upper: 0.768),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.768, upper: 1.000),
   },
   'ArgumentList_function_named': {
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.000, upper: 0.616),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.616, upper: 0.648),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.648, upper: 0.792),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.792, upper: 1.000),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.038, upper: 0.077),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.077, upper: 0.154),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.154, upper: 0.500),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.500, upper: 1.000),
   },
   'ArgumentList_function_unnamed': {
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.000, upper: 0.216),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.216, upper: 0.222),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.222, upper: 0.229),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.229, upper: 0.239),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.239, upper: 0.257),
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.257, upper: 0.282),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.282, upper: 0.347),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.347, upper: 0.583),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.583, upper: 1.000),
+        ProbabilityRange(lower: 0.003, upper: 0.005),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.010, upper: 0.016),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.024, upper: 0.032),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.041, upper: 0.052),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.052, upper: 0.074),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.074, upper: 0.103),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.171, upper: 0.246),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.246, upper: 0.519),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.519, upper: 1.000),
   },
   'ArgumentList_method_named': {
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.549),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.549, upper: 0.552),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.552, upper: 0.556),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.002, upper: 0.005),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.005, upper: 0.011),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.011, upper: 0.017),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.556, upper: 0.566),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.566, upper: 0.579),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.579, upper: 0.637),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.637, upper: 0.696),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.696, upper: 0.764),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.764, upper: 0.854),
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.854, upper: 1.000),
+        ProbabilityRange(lower: 0.017, upper: 0.033),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.033, upper: 0.055),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.114, upper: 0.209),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.209, upper: 0.306),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.306, upper: 0.417),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.417, upper: 0.564),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.760, upper: 1.000),
   },
   'ArgumentList_method_unnamed': {
-    ElementKind.MIXIN: ProbabilityRange(lower: 0.000, upper: 0.388),
-    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.388, upper: 0.388),
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.388, upper: 0.389),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.389, upper: 0.395),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.395, upper: 0.403),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.403, upper: 0.426),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.426, upper: 0.453),
+    ElementKind.MIXIN: ProbabilityRange(lower: 0.000, upper: 0.000),
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.000),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.002, upper: 0.004),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.025, upper: 0.035),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.035, upper: 0.047),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.060, upper: 0.096),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.096, upper: 0.138),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.453, upper: 0.484),
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.484, upper: 0.542),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.542, upper: 0.633),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.633, upper: 0.747),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.747, upper: 1.000),
+        ProbabilityRange(lower: 0.138, upper: 0.188),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.188, upper: 0.279),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.279, upper: 0.422),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.422, upper: 0.601),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.601, upper: 1.000),
   },
   'ArgumentList_widgetConstructor_named': {
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.353),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.353, upper: 0.355),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.001),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.006, upper: 0.009),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.355, upper: 0.363),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.363, upper: 0.376),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.376, upper: 0.395),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.395, upper: 0.430),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.430, upper: 0.490),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.490, upper: 0.552),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.552, upper: 0.636),
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.636, upper: 1.000),
+        ProbabilityRange(lower: 0.019, upper: 0.031),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.047, upper: 0.066),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.066, upper: 0.093),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.138, upper: 0.187),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.187, upper: 0.273),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.273, upper: 0.361),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.361, upper: 0.482),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.482, upper: 1.000),
   },
   'ArgumentList_widgetConstructor_unnamed': {
-    ElementKind.ENUM: ProbabilityRange(lower: 0.000, upper: 0.462),
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.462, upper: 0.464),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.464, upper: 0.470),
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.470, upper: 0.476),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.004, upper: 0.008),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.008, upper: 0.012),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.018, upper: 0.029),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.029, upper: 0.040),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.476, upper: 0.485),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.485, upper: 0.501),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.501, upper: 0.552),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.552, upper: 0.622),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.622, upper: 0.757),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.757, upper: 1.000),
+        ProbabilityRange(lower: 0.040, upper: 0.057),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.057, upper: 0.087),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.087, upper: 0.179),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.179, upper: 0.307),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.307, upper: 0.555),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.555, upper: 1.000),
   },
   'AsExpression_type': {
     ElementKind.FUNCTION_TYPE_ALIAS:
@@ -157,210 +157,210 @@
     ElementKind.PARAMETER: ProbabilityRange(lower: 0.000, upper: 1.000),
   },
   'AssertStatement_condition': {
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.144),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.002, upper: 0.004),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.144, upper: 0.150),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.150, upper: 0.185),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.185, upper: 0.236),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.236, upper: 0.352),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.352, upper: 0.650),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.650, upper: 1.000),
+        ProbabilityRange(lower: 0.009, upper: 0.015),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.015, upper: 0.054),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.054, upper: 0.110),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.166, upper: 0.292),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.292, upper: 0.617),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.617, upper: 1.000),
   },
   'AssertStatement_message': {
     ElementKind.METHOD: ProbabilityRange(lower: 0.000, upper: 1.000),
   },
   'AssignmentExpression_rightHandSide': {
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.306),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.002),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.306, upper: 0.315),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.315, upper: 0.326),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.326, upper: 0.338),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.338, upper: 0.358),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.358, upper: 0.403),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.403, upper: 0.497),
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.497, upper: 0.608),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.608, upper: 0.739),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.739, upper: 1.000),
+        ProbabilityRange(lower: 0.005, upper: 0.016),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.016, upper: 0.029),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.029, upper: 0.043),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.066, upper: 0.090),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.233, upper: 0.287),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.287, upper: 0.400),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.400, upper: 0.533),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.533, upper: 0.689),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.689, upper: 1.000),
   },
   'AwaitExpression_expression': {
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.000, upper: 0.022),
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.022, upper: 0.049),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.009, upper: 0.019),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.019, upper: 0.046),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.049, upper: 0.086),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.086, upper: 0.181),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.181, upper: 0.329),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.329, upper: 0.487),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.487, upper: 0.645),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.645, upper: 0.809),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.809, upper: 1.000),
+        ProbabilityRange(lower: 0.046, upper: 0.083),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.083, upper: 0.178),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.178, upper: 0.327),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.327, upper: 0.485),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.485, upper: 0.645),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.645, upper: 0.808),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.808, upper: 1.000),
   },
   'BinaryExpression_!=_rightOperand': {
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.000, upper: 0.874),
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.874, upper: 0.875),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.875, upper: 0.875),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.000, upper: 0.000),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.001),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.001, upper: 0.001),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.875, upper: 0.878),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.878, upper: 0.889),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.889, upper: 0.906),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.906, upper: 0.924),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.924, upper: 0.957),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.957, upper: 1.000),
+        ProbabilityRange(lower: 0.007, upper: 0.010),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.010, upper: 0.022),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.022, upper: 0.040),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.040, upper: 0.059),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.059, upper: 0.094),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.094, upper: 0.140),
   },
   'BinaryExpression_%_rightOperand': {
-    ElementKind.ENUM: ProbabilityRange(lower: 0.000, upper: 0.722),
-    ElementKind.MIXIN: ProbabilityRange(lower: 0.722, upper: 0.728),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.000, upper: 0.012),
+    ElementKind.MIXIN: ProbabilityRange(lower: 0.012, upper: 0.035),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.728, upper: 0.745),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.745, upper: 0.772),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.772, upper: 0.805),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.805, upper: 0.868),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.868, upper: 1.000),
+        ProbabilityRange(lower: 0.035, upper: 0.094),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.094, upper: 0.188),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.188, upper: 0.306),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.306, upper: 0.529),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.529, upper: 1.000),
   },
   'BinaryExpression_&&_rightOperand': {
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.107),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.107, upper: 0.112),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.001),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.005, upper: 0.010),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.112, upper: 0.117),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.117, upper: 0.128),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.128, upper: 0.142),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.142, upper: 0.264),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.264, upper: 0.445),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.445, upper: 1.000),
+        ProbabilityRange(lower: 0.010, upper: 0.018),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.018, upper: 0.029),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.029, upper: 0.045),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.045, upper: 0.181),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.181, upper: 0.382),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.382, upper: 1.000),
   },
   'BinaryExpression_&_rightOperand': {
-    ElementKind.CLASS: ProbabilityRange(lower: 0.000, upper: 0.285),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.285, upper: 0.390),
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.390, upper: 0.494),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.494, upper: 0.703),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.703, upper: 1.000),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.023, upper: 0.068),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.068, upper: 0.205),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.205, upper: 0.341),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.341, upper: 0.614),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.614, upper: 1.000),
   },
   'BinaryExpression_*_rightOperand': {
-    ElementKind.MIXIN: ProbabilityRange(lower: 0.000, upper: 0.622),
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.622, upper: 0.624),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.624, upper: 0.627),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.627, upper: 0.636),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.636, upper: 0.651),
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.651, upper: 0.672),
+    ElementKind.MIXIN: ProbabilityRange(lower: 0.000, upper: 0.001),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.004, upper: 0.010),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.010, upper: 0.018),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.018, upper: 0.041),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.041, upper: 0.081),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.081, upper: 0.136),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.672, upper: 0.702),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.702, upper: 0.751),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.751, upper: 0.870),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.870, upper: 1.000),
+        ProbabilityRange(lower: 0.136, upper: 0.214),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.214, upper: 0.344),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.344, upper: 0.658),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.658, upper: 1.000),
   },
   'BinaryExpression_+_rightOperand': {
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.508),
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.508, upper: 0.510),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.510, upper: 0.517),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.517, upper: 0.532),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.532, upper: 0.556),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.003),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.007, upper: 0.012),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.012, upper: 0.025),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.025, upper: 0.056),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.056, upper: 0.104),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.556, upper: 0.582),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.582, upper: 0.701),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.701, upper: 0.829),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.829, upper: 1.000),
+        ProbabilityRange(lower: 0.104, upper: 0.156),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.156, upper: 0.396),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.396, upper: 0.655),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.655, upper: 1.000),
   },
   'BinaryExpression_-_rightOperand': {
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.485),
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.485, upper: 0.488),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.488, upper: 0.490),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.490, upper: 0.499),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.499, upper: 0.515),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.001, upper: 0.005),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.005, upper: 0.010),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.010, upper: 0.014),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.021, upper: 0.038),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.038, upper: 0.068),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.515, upper: 0.542),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.542, upper: 0.633),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.633, upper: 0.802),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.802, upper: 1.000),
+        ProbabilityRange(lower: 0.068, upper: 0.120),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.120, upper: 0.295),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.295, upper: 0.619),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.619, upper: 1.000),
   },
   'BinaryExpression_/_rightOperand': {
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.000, upper: 0.768),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.768, upper: 0.768),
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.768, upper: 0.771),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.771, upper: 0.777),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.000, upper: 0.002),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.002, upper: 0.004),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.006, upper: 0.017),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.017, upper: 0.042),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.777, upper: 0.785),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.785, upper: 0.793),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.793, upper: 0.830),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.830, upper: 0.912),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.912, upper: 1.000),
+        ProbabilityRange(lower: 0.042, upper: 0.075),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.075, upper: 0.112),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.112, upper: 0.268),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.268, upper: 0.624),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.624, upper: 1.000),
   },
   'BinaryExpression_<<_rightOperand': {
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.756),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.756, upper: 0.854),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.854, upper: 1.000),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.167),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.167, upper: 0.500),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.500, upper: 1.000),
   },
   'BinaryExpression_<=_rightOperand': {
-    ElementKind.CLASS: ProbabilityRange(lower: 0.000, upper: 0.609),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.000, upper: 0.015),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.609, upper: 0.621),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.621, upper: 0.733),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.733, upper: 0.861),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.861, upper: 1.000),
+        ProbabilityRange(lower: 0.037, upper: 0.067),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.067, upper: 0.343),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.343, upper: 0.657),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.657, upper: 1.000),
   },
   'BinaryExpression_<_rightOperand': {
-    ElementKind.ENUM: ProbabilityRange(lower: 0.000, upper: 0.424),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.424, upper: 0.426),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.426, upper: 0.427),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.427, upper: 0.439),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.000, upper: 0.002),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.002, upper: 0.005),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.005, upper: 0.007),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.023, upper: 0.042),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.439, upper: 0.461),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.461, upper: 0.580),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.580, upper: 0.785),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.785, upper: 1.000),
+        ProbabilityRange(lower: 0.042, upper: 0.083),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.083, upper: 0.284),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.284, upper: 0.635),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.635, upper: 1.000),
   },
   'BinaryExpression_==_rightOperand': {
-    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.000, upper: 0.568),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.568, upper: 0.568),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.568, upper: 0.568),
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.568, upper: 0.569),
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.569, upper: 0.569),
+    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.000, upper: 0.000),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.000, upper: 0.000),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.000, upper: 0.000),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.000, upper: 0.001),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.001, upper: 0.002),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.569, upper: 0.577),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.577, upper: 0.601),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.601, upper: 0.639),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.639, upper: 0.679),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.679, upper: 0.807),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.807, upper: 1.000),
+        ProbabilityRange(lower: 0.008, upper: 0.018),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.055, upper: 0.085),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.085, upper: 0.133),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.133, upper: 0.183),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.183, upper: 0.342),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.342, upper: 0.583),
   },
   'BinaryExpression_>=_rightOperand': {
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.000, upper: 0.714),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.714, upper: 0.731),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.000, upper: 0.006),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.018, upper: 0.077),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.731, upper: 0.761),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.761, upper: 0.821),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.821, upper: 0.884),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.884, upper: 1.000),
+        ProbabilityRange(lower: 0.077, upper: 0.179),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.179, upper: 0.387),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.387, upper: 0.601),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.601, upper: 1.000),
   },
   'BinaryExpression_>>_rightOperand': {
     ElementKind.PARAMETER: ProbabilityRange(lower: 0.000, upper: 1.000),
   },
   'BinaryExpression_>_rightOperand': {
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.815),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.815, upper: 0.815),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.815, upper: 0.817),
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.817, upper: 0.820),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.820, upper: 0.828),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.004),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.004, upper: 0.007),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.007, upper: 0.014),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.014, upper: 0.029),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.068, upper: 0.112),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.828, upper: 0.850),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.850, upper: 0.890),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.890, upper: 0.939),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.939, upper: 1.000),
+        ProbabilityRange(lower: 0.112, upper: 0.227),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.227, upper: 0.432),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.432, upper: 0.687),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.687, upper: 1.000),
   },
   'BinaryExpression_??_rightOperand': {
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.665),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.665, upper: 0.668),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.668, upper: 0.673),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.000),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.002, upper: 0.009),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.017, upper: 0.027),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.673, upper: 0.680),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.680, upper: 0.692),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.692, upper: 0.728),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.728, upper: 0.769),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.769, upper: 0.817),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.817, upper: 0.871),
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.871, upper: 1.000),
+        ProbabilityRange(lower: 0.027, upper: 0.042),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.058, upper: 0.083),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.108, upper: 0.183),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.183, upper: 0.269),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.367, upper: 0.467),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.467, upper: 0.578),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.731, upper: 1.000),
   },
   'BinaryExpression_^_rightOperand': {
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.118),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.118, upper: 1.000),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.026),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.026, upper: 1.000),
   },
   'BinaryExpression_|_rightOperand': {
     ElementKind.PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.143),
@@ -368,185 +368,185 @@
     ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.429, upper: 1.000),
   },
   'BinaryExpression_||_rightOperand': {
+    ElementKind.METHOD: ProbabilityRange(lower: 0.004, upper: 0.008),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.008, upper: 0.013),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.000, upper: 0.141),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.141, upper: 0.145),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.145, upper: 0.149),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.149, upper: 0.169),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.169, upper: 0.382),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.382, upper: 0.666),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.666, upper: 1.000),
+        ProbabilityRange(lower: 0.018, upper: 0.027),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.027, upper: 0.050),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.050, upper: 0.294),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.294, upper: 0.618),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.618, upper: 1.000),
   },
   'BinaryExpression_~/_rightOperand': {
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.000, upper: 0.629),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.629, upper: 0.642),
-    ElementKind.MIXIN: ProbabilityRange(lower: 0.642, upper: 0.654),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.654, upper: 0.692),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.692, upper: 0.799),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.799, upper: 1.000),
+        ProbabilityRange(lower: 0.000, upper: 0.017),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.017, upper: 0.050),
+    ElementKind.MIXIN: ProbabilityRange(lower: 0.050, upper: 0.083),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.083, upper: 0.183),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.183, upper: 0.467),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.467, upper: 1.000),
   },
   'Block_statement': {
-    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.537),
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.000),
     ElementKind.FUNCTION_TYPE_ALIAS:
-        ProbabilityRange(lower: 0.537, upper: 0.537),
-    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.537, upper: 0.537),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.537, upper: 0.538),
-    ElementKind.MIXIN: ProbabilityRange(lower: 0.538, upper: 0.538),
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.538, upper: 0.540),
+        ProbabilityRange(lower: 0.000, upper: 0.000),
+    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.000, upper: 0.001),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.001, upper: 0.001),
+    ElementKind.MIXIN: ProbabilityRange(lower: 0.002, upper: 0.003),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.005, upper: 0.006),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.540, upper: 0.554),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.554, upper: 0.577),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.577, upper: 0.627),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.627, upper: 0.687),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.687, upper: 0.770),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.770, upper: 0.858),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.858, upper: 1.000),
+        ProbabilityRange(lower: 0.062, upper: 0.077),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.093, upper: 0.116),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.171, upper: 0.221),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.221, upper: 0.282),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.282, upper: 0.364),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.364, upper: 0.453),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.661, upper: 0.802),
   },
   'CatchClause_exceptionType': {
     ElementKind.CLASS: ProbabilityRange(lower: 0.000, upper: 1.000),
   },
   'ClassDeclaration_member': {
-    ElementKind.MIXIN: ProbabilityRange(lower: 0.000, upper: 0.424),
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.424, upper: 0.425),
-    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.425, upper: 0.426),
-    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.426, upper: 0.426),
+    ElementKind.MIXIN: ProbabilityRange(lower: 0.000, upper: 0.000),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.000),
+    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.000, upper: 0.001),
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.001, upper: 0.002),
     ElementKind.FUNCTION_TYPE_ALIAS:
-        ProbabilityRange(lower: 0.426, upper: 0.428),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.428, upper: 0.433),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.433, upper: 1.000),
+        ProbabilityRange(lower: 0.002, upper: 0.004),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.010, upper: 0.015),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.442, upper: 1.000),
   },
   'ClassTypeAlias_superclass': {
-    ElementKind.CLASS: ProbabilityRange(lower: 0.000, upper: 1.000),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.000, upper: 0.500),
   },
   'CommentReference_identifier': {
-    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.000, upper: 0.001),
+    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.000, upper: 0.000),
     ElementKind.FUNCTION_TYPE_ALIAS:
-        ProbabilityRange(lower: 0.001, upper: 0.002),
+        ProbabilityRange(lower: 0.000, upper: 0.002),
     ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.002, upper: 0.004),
     ElementKind.PREFIX: ProbabilityRange(lower: 0.004, upper: 0.008),
     ElementKind.TOP_LEVEL_VARIABLE:
         ProbabilityRange(lower: 0.008, upper: 0.012),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.012, upper: 0.026),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.026, upper: 0.060),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.012, upper: 0.025),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.025, upper: 0.060),
     ElementKind.PARAMETER: ProbabilityRange(lower: 0.060, upper: 0.118),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.118, upper: 0.181),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.181, upper: 0.456),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.118, upper: 0.180),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.180, upper: 0.456),
     ElementKind.CLASS: ProbabilityRange(lower: 0.456, upper: 1.000),
   },
   'CompilationUnit_declaration': {
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.818),
-    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.818, upper: 0.819),
-    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.819, upper: 0.820),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.820, upper: 0.822),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.000),
+    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.000, upper: 0.000),
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.001),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.001, upper: 0.003),
     ElementKind.FUNCTION_TYPE_ALIAS:
-        ProbabilityRange(lower: 0.822, upper: 0.836),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.836, upper: 1.000),
+        ProbabilityRange(lower: 0.024, upper: 0.036),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.205, upper: 0.342),
   },
   'ConditionalExpression_elseExpression': {
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.369),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.369, upper: 0.378),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.002, upper: 0.005),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.030, upper: 0.041),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.378, upper: 0.388),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.388, upper: 0.407),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.407, upper: 0.431),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.431, upper: 0.487),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.487, upper: 0.554),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.554, upper: 0.655),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.655, upper: 0.790),
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.790, upper: 1.000),
+        ProbabilityRange(lower: 0.041, upper: 0.055),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.071, upper: 0.096),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.096, upper: 0.128),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.128, upper: 0.201),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.201, upper: 0.289),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.412, upper: 0.544),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.544, upper: 0.722),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.722, upper: 1.000),
   },
   'ConditionalExpression_thenExpression': {
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.390),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.390, upper: 0.397),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.001, upper: 0.004),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.024, upper: 0.034),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.397, upper: 0.408),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.408, upper: 0.429),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.429, upper: 0.456),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.456, upper: 0.506),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.506, upper: 0.562),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.562, upper: 0.633),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.633, upper: 0.776),
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.776, upper: 1.000),
+        ProbabilityRange(lower: 0.034, upper: 0.048),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.069, upper: 0.097),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.097, upper: 0.132),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.132, upper: 0.198),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.198, upper: 0.272),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.272, upper: 0.367),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.513, upper: 0.703),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.703, upper: 1.000),
   },
   'ConstructorDeclaration_initializer': {
-    ElementKind.FIELD: ProbabilityRange(lower: 0.000, upper: 1.000),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.181, upper: 0.448),
   },
   'ConstructorDeclaration_returnType': {
     ElementKind.CLASS: ProbabilityRange(lower: 0.000, upper: 1.000),
   },
   'ConstructorFieldInitializer_expression': {
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.000, upper: 0.183),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.183, upper: 0.185),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.185, upper: 0.188),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.188, upper: 0.196),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.196, upper: 0.221),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.221, upper: 0.274),
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.274, upper: 0.399),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.399, upper: 1.000),
+        ProbabilityRange(lower: 0.000, upper: 0.002),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.002, upper: 0.003),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.005, upper: 0.010),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.017, upper: 0.026),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.037, upper: 0.067),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.067, upper: 0.130),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.130, upper: 0.280),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.280, upper: 1.000),
   },
   'DefaultFormalParameter_defaultValue': {
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.694),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.694, upper: 0.695),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.695, upper: 0.696),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.696, upper: 0.702),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.001, upper: 0.002),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.002, upper: 0.002),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.002, upper: 0.004),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.004, upper: 0.014),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.702, upper: 0.713),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.713, upper: 0.760),
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.760, upper: 0.827),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.827, upper: 1.000),
+        ProbabilityRange(lower: 0.014, upper: 0.031),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.031, upper: 0.107),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.199, upper: 0.307),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.719, upper: 1.000),
   },
   'DoStatement_condition': {
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.333),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.333, upper: 1.000),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.143),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.143, upper: 1.000),
   },
   'Expression': {
-    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.000, upper: 0.386),
+    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.000, upper: 0.000),
     ElementKind.FUNCTION_TYPE_ALIAS:
-        ProbabilityRange(lower: 0.386, upper: 0.386),
-    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.386, upper: 0.387),
-    ElementKind.MIXIN: ProbabilityRange(lower: 0.387, upper: 0.387),
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.387, upper: 0.388),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.388, upper: 0.404),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.404, upper: 0.420),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.420, upper: 0.437),
+        ProbabilityRange(lower: 0.000, upper: 0.000),
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.000),
+    ElementKind.MIXIN: ProbabilityRange(lower: 0.000, upper: 0.000),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.003),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.003, upper: 0.029),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.029, upper: 0.055),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.055, upper: 0.083),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.437, upper: 0.470),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.470, upper: 0.542),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.542, upper: 0.626),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.626, upper: 0.722),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.722, upper: 0.835),
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.835, upper: 1.000),
+        ProbabilityRange(lower: 0.083, upper: 0.137),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.137, upper: 0.255),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.255, upper: 0.391),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.391, upper: 0.547),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.547, upper: 0.731),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.731, upper: 1.000),
   },
   'ExpressionFunctionBody_expression': {
-    ElementKind.MIXIN: ProbabilityRange(lower: 0.000, upper: 0.162),
-    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.162, upper: 0.163),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.163, upper: 0.164),
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.164, upper: 0.171),
+    ElementKind.MIXIN: ProbabilityRange(lower: 0.000, upper: 0.000),
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.000),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.004, upper: 0.005),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.027, upper: 0.034),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.171, upper: 0.184),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.184, upper: 0.211),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.211, upper: 0.244),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.244, upper: 0.286),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.286, upper: 0.332),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.332, upper: 0.497),
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.497, upper: 0.731),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.731, upper: 1.000),
+        ProbabilityRange(lower: 0.045, upper: 0.061),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.061, upper: 0.092),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.092, upper: 0.130),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.130, upper: 0.179),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.179, upper: 0.231),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.231, upper: 0.421),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.421, upper: 0.691),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.691, upper: 1.000),
   },
   'ExpressionStatement_expression': {
-    ElementKind.ENUM: ProbabilityRange(lower: 0.000, upper: 0.132),
-    ElementKind.MIXIN: ProbabilityRange(lower: 0.132, upper: 0.134),
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.134, upper: 0.136),
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.136, upper: 0.139),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.000, upper: 0.000),
+    ElementKind.MIXIN: ProbabilityRange(lower: 0.000, upper: 0.002),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.002, upper: 0.004),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.006, upper: 0.009),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.139, upper: 0.168),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.168, upper: 0.218),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.218, upper: 0.283),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.283, upper: 0.388),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.388, upper: 0.510),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.510, upper: 0.709),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.709, upper: 1.000),
+        ProbabilityRange(lower: 0.054, upper: 0.084),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.117, upper: 0.168),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.218, upper: 0.284),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.284, upper: 0.389),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.389, upper: 0.511),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.511, upper: 0.710),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.710, upper: 1.000),
   },
   'ExtendsClause_superclass': {
     ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.000),
@@ -558,103 +558,103 @@
     ElementKind.CLASS: ProbabilityRange(lower: 0.105, upper: 1.000),
   },
   'ExtensionDeclaration_member': {
-    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.120),
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.040, upper: 0.120),
     ElementKind.CLASS: ProbabilityRange(lower: 0.120, upper: 1.000),
   },
   'FieldDeclaration_fields': {
-    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.000, upper: 0.617),
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.617, upper: 0.618),
-    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.618, upper: 0.619),
+    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.000, upper: 0.001),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.001, upper: 0.002),
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.002, upper: 0.003),
     ElementKind.FUNCTION_TYPE_ALIAS:
-        ProbabilityRange(lower: 0.619, upper: 0.620),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.620, upper: 0.628),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.628, upper: 1.000),
+        ProbabilityRange(lower: 0.003, upper: 0.004),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.004, upper: 0.011),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.119, upper: 0.491),
   },
   'ForEachPartsWithDeclaration_iterable': {
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.000, upper: 0.016),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.016, upper: 0.018),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.018, upper: 0.022),
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.022, upper: 0.029),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.029, upper: 0.037),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.001, upper: 0.003),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.003, upper: 0.005),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.005, upper: 0.009),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.009, upper: 0.016),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.016, upper: 0.023),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.037, upper: 0.076),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.076, upper: 0.287),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.287, upper: 0.606),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.606, upper: 1.000),
+        ProbabilityRange(lower: 0.031, upper: 0.072),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.072, upper: 0.283),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.283, upper: 0.602),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.602, upper: 1.000),
   },
   'ForEachPartsWithDeclaration_loopVariable': {
-    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.703),
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.001),
     ElementKind.FUNCTION_TYPE_ALIAS:
-        ProbabilityRange(lower: 0.703, upper: 0.704),
-    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.704, upper: 0.705),
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.705, upper: 0.708),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.708, upper: 0.712),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.712, upper: 1.000),
+        ProbabilityRange(lower: 0.001, upper: 0.003),
+    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.003, upper: 0.004),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.004, upper: 0.006),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.006, upper: 0.010),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.010, upper: 0.298),
   },
   'ForElement_body': {
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.000, upper: 0.172),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.172, upper: 0.221),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.221, upper: 0.290),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.290, upper: 0.366),
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.366, upper: 1.000),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.038, upper: 0.083),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.083, upper: 0.136),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.136, upper: 0.220),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.220, upper: 0.303),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.303, upper: 1.000),
   },
   'ForElement_forLoopParts': {
-    ElementKind.ENUM: ProbabilityRange(lower: 0.000, upper: 0.634),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.634, upper: 1.000),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.000, upper: 0.007),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.630, upper: 1.000),
   },
   'ForParts_condition': {
-    ElementKind.FIELD: ProbabilityRange(lower: 0.000, upper: 0.004),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.000, upper: 0.001),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.004, upper: 0.024),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.024, upper: 1.000),
+        ProbabilityRange(lower: 0.004, upper: 0.023),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.023, upper: 1.000),
   },
   'ForParts_updater': {
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.000, upper: 0.068),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.068, upper: 1.000),
+        ProbabilityRange(lower: 0.000, upper: 0.020),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.020, upper: 1.000),
   },
   'ForStatement_body': {
-    ElementKind.METHOD: ProbabilityRange(lower: 0.000, upper: 0.981),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.981, upper: 0.986),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.986, upper: 1.000),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.065, upper: 0.194),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.194, upper: 0.387),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.387, upper: 1.000),
   },
   'ForStatement_forLoopParts': {
-    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.536),
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.001),
     ElementKind.FUNCTION_TYPE_ALIAS:
-        ProbabilityRange(lower: 0.536, upper: 0.537),
-    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.537, upper: 0.538),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.538, upper: 0.539),
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.539, upper: 0.541),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.541, upper: 0.551),
+        ProbabilityRange(lower: 0.001, upper: 0.001),
+    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.001, upper: 0.002),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.002, upper: 0.004),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.004, upper: 0.005),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.005, upper: 0.015),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.551, upper: 0.561),
+        ProbabilityRange(lower: 0.015, upper: 0.025),
     ElementKind.CLASS: ProbabilityRange(lower: 0.561, upper: 1.000),
   },
   'FormalParameterList_parameter': {
-    ElementKind.MIXIN: ProbabilityRange(lower: 0.000, upper: 0.251),
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.251, upper: 0.252),
-    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.252, upper: 0.255),
+    ElementKind.MIXIN: ProbabilityRange(lower: 0.000, upper: 0.000),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.001, upper: 0.003),
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.003, upper: 0.005),
     ElementKind.FUNCTION_TYPE_ALIAS:
-        ProbabilityRange(lower: 0.255, upper: 0.263),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.263, upper: 0.276),
-    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.276, upper: 0.293),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.293, upper: 1.000),
+        ProbabilityRange(lower: 0.005, upper: 0.013),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.013, upper: 0.024),
+    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.038, upper: 0.054),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.360, upper: 1.000),
   },
   'FunctionDeclaration_returnType': {
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.284),
-    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.284, upper: 0.286),
-    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.286, upper: 0.290),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.290, upper: 0.301),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.000),
+    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.000, upper: 0.002),
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.002, upper: 0.006),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.006, upper: 0.017),
     ElementKind.FUNCTION_TYPE_ALIAS:
-        ProbabilityRange(lower: 0.301, upper: 0.354),
+        ProbabilityRange(lower: 0.017, upper: 0.070),
     ElementKind.CLASS: ProbabilityRange(lower: 0.354, upper: 1.000),
   },
   'GenericTypeAlias_functionType': {
     ElementKind.FUNCTION_TYPE_ALIAS:
-        ProbabilityRange(lower: 0.000, upper: 0.590),
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.590, upper: 0.610),
-    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.610, upper: 0.660),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.660, upper: 1.000),
+        ProbabilityRange(lower: 0.000, upper: 0.020),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.020, upper: 0.040),
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.040, upper: 0.090),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.140, upper: 0.480),
   },
   'HideCombinator_hiddenName': {
     ElementKind.ENUM: ProbabilityRange(lower: 0.000, upper: 0.059),
@@ -662,97 +662,97 @@
   },
   'IfElement_condition': {
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.000, upper: 0.158),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.158, upper: 0.163),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.163, upper: 0.179),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.179, upper: 0.339),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.339, upper: 0.633),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.633, upper: 1.000),
+        ProbabilityRange(lower: 0.000, upper: 0.005),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.011, upper: 0.016),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.016, upper: 0.035),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.035, upper: 0.223),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.223, upper: 0.569),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.569, upper: 1.000),
   },
   'IfElement_elseElement': {
-    ElementKind.METHOD: ProbabilityRange(lower: 0.000, upper: 0.346),
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.346, upper: 1.000),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.043, upper: 0.087),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.261, upper: 1.000),
   },
   'IfElement_thenElement': {
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.000, upper: 0.215),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.215, upper: 0.222),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.222, upper: 0.230),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.230, upper: 0.242),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.242, upper: 0.257),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.257, upper: 0.284),
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.284, upper: 1.000),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.000, upper: 0.003),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.003, upper: 0.011),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.022, upper: 0.033),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.033, upper: 0.047),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.063, upper: 0.082),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.082, upper: 0.115),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.115, upper: 1.000),
   },
   'IfStatement_condition': {
-    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.118),
-    ElementKind.MIXIN: ProbabilityRange(lower: 0.118, upper: 0.118),
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.118, upper: 0.118),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.118, upper: 0.118),
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.118, upper: 0.119),
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.000),
+    ElementKind.MIXIN: ProbabilityRange(lower: 0.000, upper: 0.000),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.000, upper: 0.000),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.001, upper: 0.001),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.002, upper: 0.002),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.119, upper: 0.127),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.127, upper: 0.137),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.137, upper: 0.153),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.153, upper: 0.175),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.175, upper: 0.397),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.397, upper: 0.696),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.696, upper: 1.000),
+        ProbabilityRange(lower: 0.002, upper: 0.013),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.013, upper: 0.023),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.023, upper: 0.041),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.084, upper: 0.107),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.107, upper: 0.347),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.347, upper: 0.672),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.672, upper: 1.000),
   },
   'IfStatement_elseStatement': {
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.000, upper: 0.968),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.968, upper: 0.969),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.969, upper: 0.970),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.970, upper: 0.973),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.973, upper: 0.982),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.982, upper: 0.991),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.991, upper: 1.000),
+        ProbabilityRange(lower: 0.004, upper: 0.007),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.007, upper: 0.009),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.009, upper: 0.012),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.012, upper: 0.021),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.021, upper: 0.045),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.045, upper: 0.069),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.069, upper: 0.095),
   },
   'IfStatement_thenStatement': {
-    ElementKind.MIXIN: ProbabilityRange(lower: 0.000, upper: 0.935),
+    ElementKind.MIXIN: ProbabilityRange(lower: 0.002, upper: 0.003),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.935, upper: 0.936),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.936, upper: 0.937),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.937, upper: 0.939),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.939, upper: 0.948),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.948, upper: 0.965),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.965, upper: 0.981),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.981, upper: 1.000),
+        ProbabilityRange(lower: 0.013, upper: 0.019),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.019, upper: 0.025),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.058, upper: 0.069),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.069, upper: 0.134),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.134, upper: 0.243),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.243, upper: 0.355),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.355, upper: 0.480),
   },
   'ImplementsClause_interface': {
     ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.003),
     ElementKind.CLASS: ProbabilityRange(lower: 0.003, upper: 1.000),
   },
   'IndexExpression_index': {
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.655),
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.655, upper: 0.655),
-    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.655, upper: 0.656),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.656, upper: 0.656),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.656, upper: 0.657),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.657, upper: 0.659),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.659, upper: 0.664),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.000),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.002, upper: 0.003),
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.003, upper: 0.004),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.004, upper: 0.006),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.006, upper: 0.008),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.008, upper: 0.015),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.015, upper: 0.029),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.664, upper: 0.670),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.670, upper: 0.761),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.761, upper: 0.863),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.863, upper: 1.000),
+        ProbabilityRange(lower: 0.029, upper: 0.046),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.046, upper: 0.307),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.307, upper: 0.605),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.605, upper: 1.000),
   },
   'InstanceCreationExpression_constructorName': {
     ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.006),
     ElementKind.CLASS: ProbabilityRange(lower: 0.006, upper: 1.000),
   },
   'InterpolationExpression_expression': {
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.000, upper: 0.035),
-    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.035, upper: 0.035),
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.035, upper: 0.036),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.036, upper: 0.037),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.037, upper: 0.044),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.044, upper: 0.074),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.000, upper: 0.001),
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.001, upper: 0.001),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.001, upper: 0.002),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.002, upper: 0.002),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.002, upper: 0.010),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.032, upper: 0.062),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.074, upper: 0.133),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.133, upper: 0.257),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.257, upper: 0.447),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.447, upper: 0.693),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.693, upper: 1.000),
+        ProbabilityRange(lower: 0.062, upper: 0.121),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.121, upper: 0.247),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.247, upper: 0.440),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.440, upper: 0.689),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.689, upper: 1.000),
   },
   'IsExpression_type': {
     ElementKind.MIXIN: ProbabilityRange(lower: 0.000, upper: 0.001),
@@ -764,45 +764,45 @@
     ElementKind.CLASS: ProbabilityRange(lower: 0.013, upper: 1.000),
   },
   'ListLiteral_element': {
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.324),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.324, upper: 0.326),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.001),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.004, upper: 0.008),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.326, upper: 0.329),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.329, upper: 0.333),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.333, upper: 0.340),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.340, upper: 0.350),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.350, upper: 0.361),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.361, upper: 0.379),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.379, upper: 0.406),
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.406, upper: 1.000),
+        ProbabilityRange(lower: 0.008, upper: 0.011),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.017, upper: 0.023),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.023, upper: 0.033),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.033, upper: 0.047),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.047, upper: 0.063),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.082, upper: 0.107),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.107, upper: 0.147),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.147, upper: 1.000),
   },
   'MapLiteralEntry_value': {
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.814),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.814, upper: 0.814),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.814, upper: 0.816),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.816, upper: 0.818),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.005, upper: 0.008),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.008, upper: 0.011),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.019, upper: 0.028),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.038, upper: 0.049),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.818, upper: 0.823),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.823, upper: 0.828),
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.828, upper: 0.833),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.833, upper: 0.854),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.854, upper: 0.884),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.884, upper: 1.000),
+        ProbabilityRange(lower: 0.049, upper: 0.073),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.073, upper: 0.099),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.099, upper: 0.128),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.128, upper: 0.234),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.234, upper: 0.393),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.393, upper: 1.000),
   },
   'MethodDeclaration_returnType': {
-    ElementKind.MIXIN: ProbabilityRange(lower: 0.000, upper: 0.169),
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.169, upper: 0.169),
-    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.169, upper: 0.171),
-    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.171, upper: 0.172),
+    ElementKind.MIXIN: ProbabilityRange(lower: 0.000, upper: 0.000),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.000, upper: 0.000),
+    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.000, upper: 0.002),
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.002, upper: 0.004),
     ElementKind.FUNCTION_TYPE_ALIAS:
-        ProbabilityRange(lower: 0.172, upper: 0.175),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.175, upper: 0.179),
+        ProbabilityRange(lower: 0.004, upper: 0.006),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.006, upper: 0.010),
     ElementKind.CLASS: ProbabilityRange(lower: 0.179, upper: 1.000),
   },
   'MixinDeclaration_member': {
-    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.116),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.116, upper: 0.121),
-    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.121, upper: 0.128),
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.002),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.002, upper: 0.007),
+    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.007, upper: 0.014),
     ElementKind.CLASS: ProbabilityRange(lower: 0.128, upper: 1.000),
   },
   'OnClause_superclassConstraint': {
@@ -810,31 +810,31 @@
     ElementKind.CLASS: ProbabilityRange(lower: 0.392, upper: 1.000),
   },
   'ParenthesizedExpression_expression': {
-    ElementKind.MIXIN: ProbabilityRange(lower: 0.000, upper: 0.218),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.218, upper: 0.219),
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.219, upper: 0.221),
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.221, upper: 0.224),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.224, upper: 0.228),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.228, upper: 0.274),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.274, upper: 0.331),
+    ElementKind.MIXIN: ProbabilityRange(lower: 0.000, upper: 0.000),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.001, upper: 0.002),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.002, upper: 0.004),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.004, upper: 0.008),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.008, upper: 0.013),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.051, upper: 0.107),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.107, upper: 0.177),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.331, upper: 0.403),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.403, upper: 0.586),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.586, upper: 0.786),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.786, upper: 1.000),
+        ProbabilityRange(lower: 0.177, upper: 0.267),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.267, upper: 0.491),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.491, upper: 0.737),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.737, upper: 1.000),
   },
   'PrefixExpression_!_operand': {
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.000, upper: 0.062),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.062, upper: 0.090),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.015, upper: 0.028),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.028, upper: 0.057),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.090, upper: 0.124),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.124, upper: 0.173),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.173, upper: 0.360),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.360, upper: 0.616),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.616, upper: 1.000),
+        ProbabilityRange(lower: 0.057, upper: 0.093),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.093, upper: 0.144),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.144, upper: 0.338),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.338, upper: 0.603),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.603, upper: 1.000),
   },
   'PrefixExpression_++_operand': {
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.035),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.018),
     ElementKind.FIELD: ProbabilityRange(lower: 0.035, upper: 0.351),
     ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.351, upper: 1.000),
   },
@@ -844,15 +844,15 @@
     ElementKind.FIELD: ProbabilityRange(lower: 0.313, upper: 1.000),
   },
   'PrefixExpression_-_operand': {
-    ElementKind.METHOD: ProbabilityRange(lower: 0.000, upper: 0.830),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.830, upper: 0.832),
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.832, upper: 0.839),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.839, upper: 0.857),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.000, upper: 0.006),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.006, upper: 0.022),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.022, upper: 0.061),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.061, upper: 0.166),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.857, upper: 0.877),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.877, upper: 0.902),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.902, upper: 0.930),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.930, upper: 1.000),
+        ProbabilityRange(lower: 0.166, upper: 0.282),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.282, upper: 0.431),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.431, upper: 0.591),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.591, upper: 1.000),
   },
   'PrefixExpression_~_operand': {
     ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.000, upper: 1.000),
@@ -862,31 +862,31 @@
     ElementKind.FIELD: ProbabilityRange(lower: 0.002, upper: 1.000),
   },
   'ReturnStatement_expression': {
-    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.243),
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.243, upper: 0.246),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.246, upper: 0.254),
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.000),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.003, upper: 0.008),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.020, upper: 0.029),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.254, upper: 0.262),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.262, upper: 0.279),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.279, upper: 0.303),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.303, upper: 0.352),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.352, upper: 0.406),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.406, upper: 0.466),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.466, upper: 0.564),
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.564, upper: 1.000),
+        ProbabilityRange(lower: 0.029, upper: 0.038),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.070, upper: 0.090),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.142, upper: 0.171),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.171, upper: 0.229),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.229, upper: 0.292),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.292, upper: 0.365),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.365, upper: 0.481),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.481, upper: 1.000),
   },
   'SetOrMapLiteral_element': {
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.000, upper: 0.974),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.974, upper: 0.974),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.974, upper: 0.974),
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.974, upper: 0.974),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.974, upper: 0.975),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.000, upper: 0.002),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.002, upper: 0.005),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.005, upper: 0.009),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.015, upper: 0.022),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.040, upper: 0.051),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.975, upper: 0.976),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.976, upper: 0.979),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.979, upper: 0.985),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.985, upper: 0.991),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.991, upper: 1.000),
+        ProbabilityRange(lower: 0.051, upper: 0.107),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.107, upper: 0.231),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.231, upper: 0.423),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.423, upper: 0.653),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.653, upper: 1.000),
   },
   'ShowCombinator_shownName': {
     ElementKind.FUNCTION_TYPE_ALIAS:
@@ -898,77 +898,77 @@
     ElementKind.CLASS: ProbabilityRange(lower: 0.568, upper: 1.000),
   },
   'SpreadElement_expression': {
-    ElementKind.ENUM: ProbabilityRange(lower: 0.000, upper: 0.335),
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.335, upper: 0.349),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.349, upper: 0.379),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.379, upper: 0.446),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.000, upper: 0.005),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.022, upper: 0.044),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.044, upper: 0.087),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.087, upper: 0.186),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.446, upper: 0.520),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.520, upper: 0.610),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.610, upper: 0.710),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.710, upper: 0.814),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.814, upper: 1.000),
+        ProbabilityRange(lower: 0.186, upper: 0.295),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.295, upper: 0.426),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.426, upper: 0.574),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.574, upper: 0.727),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.727, upper: 1.000),
   },
   'Statement': {
-    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.599),
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.000),
     ElementKind.FUNCTION_TYPE_ALIAS:
-        ProbabilityRange(lower: 0.599, upper: 0.599),
-    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.599, upper: 0.600),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.600, upper: 0.600),
-    ElementKind.MIXIN: ProbabilityRange(lower: 0.600, upper: 0.601),
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.601, upper: 0.602),
+        ProbabilityRange(lower: 0.000, upper: 0.000),
+    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.000, upper: 0.001),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.001, upper: 0.002),
+    ElementKind.MIXIN: ProbabilityRange(lower: 0.002, upper: 0.003),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.003, upper: 0.006),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.602, upper: 0.613),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.613, upper: 0.634),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.634, upper: 0.677),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.677, upper: 0.727),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.727, upper: 0.800),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.800, upper: 0.881),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.881, upper: 1.000),
+        ProbabilityRange(lower: 0.006, upper: 0.037),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.037, upper: 0.088),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.088, upper: 0.195),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.195, upper: 0.319),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.319, upper: 0.502),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.502, upper: 0.705),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.705, upper: 1.000),
   },
   'SwitchCase_expression': {
-    ElementKind.FIELD: ProbabilityRange(lower: 0.000, upper: 0.508),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.009, upper: 0.016),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.508, upper: 0.525),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.525, upper: 0.668),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.668, upper: 1.000),
+        ProbabilityRange(lower: 0.016, upper: 0.049),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.049, upper: 0.336),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.336, upper: 1.000),
   },
   'SwitchMember_statement': {
-    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.000, upper: 0.683),
-    ElementKind.MIXIN: ProbabilityRange(lower: 0.683, upper: 0.683),
+    ElementKind.UNKNOWN: ProbabilityRange(lower: 0.000, upper: 0.000),
+    ElementKind.MIXIN: ProbabilityRange(lower: 0.000, upper: 0.000),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.683, upper: 0.685),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.685, upper: 0.691),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.691, upper: 0.703),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.703, upper: 0.715),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.715, upper: 0.730),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.730, upper: 0.759),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.759, upper: 1.000),
+        ProbabilityRange(lower: 0.013, upper: 0.017),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.027, upper: 0.033),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.045, upper: 0.056),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.056, upper: 0.069),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.069, upper: 0.085),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.109, upper: 0.138),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.138, upper: 0.380),
   },
   'SwitchStatement_expression': {
-    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.010),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.010, upper: 0.012),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.012, upper: 0.016),
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.001),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.001, upper: 0.003),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.006, upper: 0.010),
     ElementKind.TOP_LEVEL_VARIABLE:
         ProbabilityRange(lower: 0.016, upper: 0.023),
     ElementKind.CLASS: ProbabilityRange(lower: 0.023, upper: 0.039),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.039, upper: 0.212),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.212, upper: 0.516),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.516, upper: 1.000),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.039, upper: 0.211),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.211, upper: 0.517),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.517, upper: 1.000),
   },
   'ThrowExpression_expression': {
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.834),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.834, upper: 0.835),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.835, upper: 0.837),
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.837, upper: 1.000),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.001, upper: 0.004),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.004, upper: 0.010),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.010, upper: 0.022),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.022, upper: 1.000),
   },
   'TypeArgumentList_argument': {
-    ElementKind.MIXIN: ProbabilityRange(lower: 0.000, upper: 0.021),
+    ElementKind.MIXIN: ProbabilityRange(lower: 0.000, upper: 0.000),
     ElementKind.FUNCTION_TYPE_ALIAS:
-        ProbabilityRange(lower: 0.021, upper: 0.024),
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.024, upper: 0.031),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.031, upper: 0.039),
-    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.039, upper: 0.053),
+        ProbabilityRange(lower: 0.000, upper: 0.003),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.003, upper: 0.010),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.010, upper: 0.018),
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.018, upper: 0.032),
     ElementKind.UNKNOWN: ProbabilityRange(lower: 0.053, upper: 0.164),
     ElementKind.CLASS: ProbabilityRange(lower: 0.164, upper: 1.000),
   },
@@ -978,7 +978,7 @@
     ElementKind.CLASS: ProbabilityRange(lower: 0.039, upper: 1.000),
   },
   'VariableDeclarationList_type': {
-    ElementKind.MIXIN: ProbabilityRange(lower: 0.000, upper: 0.002),
+    ElementKind.MIXIN: ProbabilityRange(lower: 0.000, upper: 0.000),
     ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.002, upper: 0.003),
     ElementKind.PREFIX: ProbabilityRange(lower: 0.003, upper: 0.007),
     ElementKind.UNKNOWN: ProbabilityRange(lower: 0.007, upper: 0.015),
@@ -988,41 +988,572 @@
     ElementKind.CLASS: ProbabilityRange(lower: 0.047, upper: 1.000),
   },
   'VariableDeclaration_initializer': {
-    ElementKind.MIXIN: ProbabilityRange(lower: 0.000, upper: 0.452),
-    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.452, upper: 0.452),
-    ElementKind.PREFIX: ProbabilityRange(lower: 0.452, upper: 0.455),
-    ElementKind.ENUM: ProbabilityRange(lower: 0.455, upper: 0.459),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.459, upper: 0.471),
+    ElementKind.MIXIN: ProbabilityRange(lower: 0.000, upper: 0.000),
+    ElementKind.TYPE_PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.000),
+    ElementKind.PREFIX: ProbabilityRange(lower: 0.004, upper: 0.010),
+    ElementKind.ENUM: ProbabilityRange(lower: 0.010, upper: 0.016),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.023, upper: 0.041),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.471, upper: 0.489),
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.489, upper: 0.515),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.515, upper: 0.578),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.578, upper: 0.641),
-    ElementKind.CLASS: ProbabilityRange(lower: 0.641, upper: 0.712),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.712, upper: 0.794),
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.794, upper: 1.000),
+        ProbabilityRange(lower: 0.041, upper: 0.069),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.128, upper: 0.167),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.167, upper: 0.261),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.261, upper: 0.357),
+    ElementKind.CLASS: ProbabilityRange(lower: 0.459, upper: 0.565),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.565, upper: 0.689),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.689, upper: 1.000),
   },
   'WhileStatement_body': {
-    ElementKind.METHOD: ProbabilityRange(lower: 0.000, upper: 0.985),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.985, upper: 1.000),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.000, upper: 0.200),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.200, upper: 1.000),
   },
   'WhileStatement_condition': {
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.083),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.083, upper: 0.109),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.109, upper: 1.000),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.000, upper: 0.008),
+    ElementKind.TOP_LEVEL_VARIABLE:
+        ProbabilityRange(lower: 0.008, upper: 0.023),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.023, upper: 0.050),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.085, upper: 1.000),
   },
   'WithClause_mixinType': {
     ElementKind.CLASS: ProbabilityRange(lower: 0.000, upper: 0.282),
     ElementKind.MIXIN: ProbabilityRange(lower: 0.282, upper: 1.000),
   },
   'YieldStatement_expression': {
-    ElementKind.FUNCTION: ProbabilityRange(lower: 0.000, upper: 0.065),
+    ElementKind.FUNCTION: ProbabilityRange(lower: 0.000, upper: 0.003),
     ElementKind.TOP_LEVEL_VARIABLE:
-        ProbabilityRange(lower: 0.065, upper: 0.068),
-    ElementKind.FIELD: ProbabilityRange(lower: 0.068, upper: 0.086),
-    ElementKind.PARAMETER: ProbabilityRange(lower: 0.086, upper: 0.122),
-    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.122, upper: 0.161),
-    ElementKind.METHOD: ProbabilityRange(lower: 0.161, upper: 0.309),
-    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.309, upper: 1.000),
+        ProbabilityRange(lower: 0.003, upper: 0.006),
+    ElementKind.FIELD: ProbabilityRange(lower: 0.009, upper: 0.028),
+    ElementKind.PARAMETER: ProbabilityRange(lower: 0.073, upper: 0.110),
+    ElementKind.LOCAL_VARIABLE: ProbabilityRange(lower: 0.110, upper: 0.150),
+    ElementKind.METHOD: ProbabilityRange(lower: 0.150, upper: 0.300),
+    ElementKind.CONSTRUCTOR: ProbabilityRange(lower: 0.300, upper: 1.000),
+  },
+};
+
+/// A table keyed by completion location and keyword whose values are the
+/// ranges of the relevance of those keywords in those locations.
+const keywordRelevance = {
+  'ArgumentList_annotation_named': {
+    'false': ProbabilityRange(lower: 0.159, upper: 0.517),
+    'true': ProbabilityRange(lower: 0.517, upper: 1.000),
+  },
+  'ArgumentList_annotation_unnamed': {
+    'const': ProbabilityRange(lower: 0.000, upper: 0.375),
+  },
+  'ArgumentList_constructorRedirect_named': {
+    'null': ProbabilityRange(lower: 0.001, upper: 0.002),
+    'const': ProbabilityRange(lower: 0.002, upper: 0.003),
+    'true': ProbabilityRange(lower: 0.003, upper: 0.005),
+    'false': ProbabilityRange(lower: 0.005, upper: 0.008),
+  },
+  'ArgumentList_constructorRedirect_unnamed': {
+    'const': ProbabilityRange(lower: 0.005, upper: 0.011),
+    'null': ProbabilityRange(lower: 0.024, upper: 0.041),
+  },
+  'ArgumentList_constructor_named': {
+    'super': ProbabilityRange(lower: 0.000, upper: 0.000),
+    'await': ProbabilityRange(lower: 0.000, upper: 0.000),
+    'null': ProbabilityRange(lower: 0.004, upper: 0.007),
+    'false': ProbabilityRange(lower: 0.011, upper: 0.016),
+    'this': ProbabilityRange(lower: 0.016, upper: 0.023),
+    'true': ProbabilityRange(lower: 0.023, upper: 0.031),
+    'const': ProbabilityRange(lower: 0.031, upper: 0.042),
+  },
+  'ArgumentList_constructor_unnamed': {
+    'await': ProbabilityRange(lower: 0.000, upper: 0.001),
+    'true': ProbabilityRange(lower: 0.004, upper: 0.008),
+    'false': ProbabilityRange(lower: 0.008, upper: 0.014),
+    'this': ProbabilityRange(lower: 0.014, upper: 0.020),
+    'null': ProbabilityRange(lower: 0.031, upper: 0.049),
+    'const': ProbabilityRange(lower: 0.095, upper: 0.124),
+  },
+  'ArgumentList_function_named': {
+    'true': ProbabilityRange(lower: 0.000, upper: 0.038),
+  },
+  'ArgumentList_function_unnamed': {
+    'await': ProbabilityRange(lower: 0.000, upper: 0.001),
+    'null': ProbabilityRange(lower: 0.001, upper: 0.003),
+    'false': ProbabilityRange(lower: 0.005, upper: 0.010),
+    'const': ProbabilityRange(lower: 0.016, upper: 0.024),
+    'true': ProbabilityRange(lower: 0.032, upper: 0.041),
+    'this': ProbabilityRange(lower: 0.103, upper: 0.171),
+  },
+  'ArgumentList_method_named': {
+    'null': ProbabilityRange(lower: 0.000, upper: 0.001),
+    'this': ProbabilityRange(lower: 0.001, upper: 0.002),
+    'false': ProbabilityRange(lower: 0.055, upper: 0.079),
+    'true': ProbabilityRange(lower: 0.079, upper: 0.114),
+    'const': ProbabilityRange(lower: 0.564, upper: 0.760),
+  },
+  'ArgumentList_method_unnamed': {
+    'super': ProbabilityRange(lower: 0.000, upper: 0.000),
+    'await': ProbabilityRange(lower: 0.000, upper: 0.002),
+    'null': ProbabilityRange(lower: 0.004, upper: 0.008),
+    'false': ProbabilityRange(lower: 0.008, upper: 0.013),
+    'true': ProbabilityRange(lower: 0.013, upper: 0.018),
+    'const': ProbabilityRange(lower: 0.018, upper: 0.025),
+    'this': ProbabilityRange(lower: 0.047, upper: 0.060),
+  },
+  'ArgumentList_widgetConstructor_named': {
+    'super': ProbabilityRange(lower: 0.000, upper: 0.000),
+    'null': ProbabilityRange(lower: 0.001, upper: 0.003),
+    'this': ProbabilityRange(lower: 0.003, upper: 0.006),
+    'false': ProbabilityRange(lower: 0.009, upper: 0.019),
+    'true': ProbabilityRange(lower: 0.031, upper: 0.047),
+    'const': ProbabilityRange(lower: 0.093, upper: 0.138),
+  },
+  'ArgumentList_widgetConstructor_unnamed': {
+    'const': ProbabilityRange(lower: 0.000, upper: 0.000),
+    'true': ProbabilityRange(lower: 0.000, upper: 0.001),
+    'false': ProbabilityRange(lower: 0.001, upper: 0.002),
+    'null': ProbabilityRange(lower: 0.002, upper: 0.004),
+    'this': ProbabilityRange(lower: 0.012, upper: 0.018),
+  },
+  'AssertStatement_condition': {
+    'this': ProbabilityRange(lower: 0.000, upper: 0.002),
+    'await': ProbabilityRange(lower: 0.004, upper: 0.009),
+    'false': ProbabilityRange(lower: 0.110, upper: 0.166),
+  },
+  'AssignmentExpression_rightHandSide': {
+    'super': ProbabilityRange(lower: 0.000, upper: 0.000),
+    'const': ProbabilityRange(lower: 0.002, upper: 0.005),
+    'await': ProbabilityRange(lower: 0.043, upper: 0.066),
+    'null': ProbabilityRange(lower: 0.090, upper: 0.116),
+    'false': ProbabilityRange(lower: 0.116, upper: 0.153),
+    'true': ProbabilityRange(lower: 0.153, upper: 0.192),
+    'this': ProbabilityRange(lower: 0.192, upper: 0.233),
+  },
+  'AwaitExpression_expression': {
+    'null': ProbabilityRange(lower: 0.000, upper: 0.000),
+    'const': ProbabilityRange(lower: 0.000, upper: 0.000),
+    'super': ProbabilityRange(lower: 0.000, upper: 0.000),
+    'this': ProbabilityRange(lower: 0.000, upper: 0.009),
+  },
+  'BinaryExpression_!=_rightOperand': {
+    'false': ProbabilityRange(lower: 0.001, upper: 0.002),
+    'this': ProbabilityRange(lower: 0.002, upper: 0.004),
+    'true': ProbabilityRange(lower: 0.004, upper: 0.007),
+    'null': ProbabilityRange(lower: 0.140, upper: 1.000),
+  },
+  'BinaryExpression_&&_rightOperand': {
+    'false': ProbabilityRange(lower: 0.000, upper: 0.000),
+    'const': ProbabilityRange(lower: 0.001, upper: 0.002),
+    'await': ProbabilityRange(lower: 0.002, upper: 0.003),
+    'this': ProbabilityRange(lower: 0.003, upper: 0.005),
+  },
+  'BinaryExpression_&_rightOperand': {
+    'const': ProbabilityRange(lower: 0.000, upper: 0.023),
+  },
+  'BinaryExpression_*_rightOperand': {
+    'this': ProbabilityRange(lower: 0.001, upper: 0.004),
+  },
+  'BinaryExpression_+_rightOperand': {
+    'const': ProbabilityRange(lower: 0.000, upper: 0.000),
+    'this': ProbabilityRange(lower: 0.003, upper: 0.007),
+  },
+  'BinaryExpression_-_rightOperand': {
+    'const': ProbabilityRange(lower: 0.000, upper: 0.001),
+    'this': ProbabilityRange(lower: 0.014, upper: 0.021),
+  },
+  'BinaryExpression_/_rightOperand': {
+    'this': ProbabilityRange(lower: 0.004, upper: 0.006),
+  },
+  'BinaryExpression_<=_rightOperand': {
+    'this': ProbabilityRange(lower: 0.015, upper: 0.037),
+  },
+  'BinaryExpression_<_rightOperand': {
+    'this': ProbabilityRange(lower: 0.007, upper: 0.023),
+  },
+  'BinaryExpression_==_rightOperand': {
+    'this': ProbabilityRange(lower: 0.002, upper: 0.008),
+    'false': ProbabilityRange(lower: 0.018, upper: 0.032),
+    'true': ProbabilityRange(lower: 0.032, upper: 0.055),
+    'null': ProbabilityRange(lower: 0.583, upper: 1.000),
+  },
+  'BinaryExpression_>=_rightOperand': {
+    'this': ProbabilityRange(lower: 0.006, upper: 0.018),
+  },
+  'BinaryExpression_>_rightOperand': {
+    'const': ProbabilityRange(lower: 0.029, upper: 0.043),
+    'this': ProbabilityRange(lower: 0.043, upper: 0.068),
+  },
+  'BinaryExpression_??_rightOperand': {
+    'super': ProbabilityRange(lower: 0.000, upper: 0.001),
+    'await': ProbabilityRange(lower: 0.001, upper: 0.002),
+    'const': ProbabilityRange(lower: 0.009, upper: 0.017),
+    'null': ProbabilityRange(lower: 0.042, upper: 0.058),
+    'true': ProbabilityRange(lower: 0.083, upper: 0.108),
+    'false': ProbabilityRange(lower: 0.269, upper: 0.367),
+    'this': ProbabilityRange(lower: 0.578, upper: 0.731),
+  },
+  'BinaryExpression_||_rightOperand': {
+    'await': ProbabilityRange(lower: 0.000, upper: 0.004),
+    'this': ProbabilityRange(lower: 0.013, upper: 0.018),
+  },
+  'BlockFunctionBody_start': {
+    'sync': ProbabilityRange(lower: 0.000, upper: 0.003),
+    'async': ProbabilityRange(lower: 0.003, upper: 1.000),
+  },
+  'Block_statement': {
+    'do': ProbabilityRange(lower: 0.000, upper: 0.000),
+    'void': ProbabilityRange(lower: 0.001, upper: 0.001),
+    'break': ProbabilityRange(lower: 0.001, upper: 0.002),
+    'continue': ProbabilityRange(lower: 0.003, upper: 0.004),
+    'rethrow': ProbabilityRange(lower: 0.004, upper: 0.005),
+    'while': ProbabilityRange(lower: 0.006, upper: 0.008),
+    'yield': ProbabilityRange(lower: 0.008, upper: 0.010),
+    'assert': ProbabilityRange(lower: 0.010, upper: 0.014),
+    'const': ProbabilityRange(lower: 0.014, upper: 0.017),
+    'switch': ProbabilityRange(lower: 0.017, upper: 0.024),
+    'try': ProbabilityRange(lower: 0.024, upper: 0.032),
+    'for': ProbabilityRange(lower: 0.032, upper: 0.041),
+    'this': ProbabilityRange(lower: 0.041, upper: 0.050),
+    'throw': ProbabilityRange(lower: 0.050, upper: 0.062),
+    'super': ProbabilityRange(lower: 0.077, upper: 0.093),
+    'await': ProbabilityRange(lower: 0.116, upper: 0.141),
+    'var': ProbabilityRange(lower: 0.141, upper: 0.171),
+    'final': ProbabilityRange(lower: 0.453, upper: 0.548),
+    'if': ProbabilityRange(lower: 0.548, upper: 0.661),
+    'return': ProbabilityRange(lower: 0.802, upper: 1.000),
+  },
+  'BooleanLiteral_start': {
+    'false': ProbabilityRange(lower: 0.000, upper: 0.484),
+    'true': ProbabilityRange(lower: 0.484, upper: 1.000),
+  },
+  'ClassDeclaration_extends': {
+    'implements': ProbabilityRange(lower: 0.000, upper: 0.350),
+    'with': ProbabilityRange(lower: 0.350, upper: 1.000),
+  },
+  'ClassDeclaration_member': {
+    'operator': ProbabilityRange(lower: 0.000, upper: 0.000),
+    'get': ProbabilityRange(lower: 0.004, upper: 0.005),
+    'var': ProbabilityRange(lower: 0.005, upper: 0.010),
+    'factory': ProbabilityRange(lower: 0.015, upper: 0.031),
+    'set': ProbabilityRange(lower: 0.031, upper: 0.051),
+    'const': ProbabilityRange(lower: 0.051, upper: 0.078),
+    'void': ProbabilityRange(lower: 0.078, upper: 0.150),
+    'static': ProbabilityRange(lower: 0.150, upper: 0.230),
+    'final': ProbabilityRange(lower: 0.230, upper: 0.442),
+  },
+  'ClassDeclaration_name': {
+    'with': ProbabilityRange(lower: 0.000, upper: 0.008),
+    'implements': ProbabilityRange(lower: 0.008, upper: 0.141),
+    'extends': ProbabilityRange(lower: 0.141, upper: 1.000),
+  },
+  'ClassDeclaration_with': {
+    'implements': ProbabilityRange(lower: 0.000, upper: 1.000),
+  },
+  'ClassTypeAlias_superclass': {
+    'with': ProbabilityRange(lower: 0.500, upper: 1.000),
+  },
+  'CompilationUnit_declaration': {
+    'mixin': ProbabilityRange(lower: 0.003, upper: 0.005),
+    'var': ProbabilityRange(lower: 0.005, upper: 0.013),
+    'typedef': ProbabilityRange(lower: 0.013, upper: 0.024),
+    'enum': ProbabilityRange(lower: 0.036, upper: 0.057),
+    'final': ProbabilityRange(lower: 0.057, upper: 0.081),
+    'void': ProbabilityRange(lower: 0.081, upper: 0.127),
+    'const': ProbabilityRange(lower: 0.127, upper: 0.205),
+    'class': ProbabilityRange(lower: 0.342, upper: 1.000),
+  },
+  'CompilationUnit_directive': {
+    'library': ProbabilityRange(lower: 0.000, upper: 0.001),
+    'part': ProbabilityRange(lower: 0.001, upper: 0.015),
+    'export': ProbabilityRange(lower: 0.015, upper: 0.037),
+    'import': ProbabilityRange(lower: 0.037, upper: 1.000),
+  },
+  'ConditionalExpression_elseExpression': {
+    'await': ProbabilityRange(lower: 0.000, upper: 0.001),
+    'throw': ProbabilityRange(lower: 0.001, upper: 0.002),
+    'true': ProbabilityRange(lower: 0.005, upper: 0.009),
+    'false': ProbabilityRange(lower: 0.009, upper: 0.019),
+    'this': ProbabilityRange(lower: 0.019, upper: 0.030),
+    'const': ProbabilityRange(lower: 0.055, upper: 0.071),
+    'null': ProbabilityRange(lower: 0.289, upper: 0.412),
+  },
+  'ConditionalExpression_thenExpression': {
+    'super': ProbabilityRange(lower: 0.000, upper: 0.000),
+    'await': ProbabilityRange(lower: 0.000, upper: 0.001),
+    'this': ProbabilityRange(lower: 0.004, upper: 0.009),
+    'false': ProbabilityRange(lower: 0.009, upper: 0.016),
+    'true': ProbabilityRange(lower: 0.016, upper: 0.024),
+    'const': ProbabilityRange(lower: 0.048, upper: 0.069),
+    'null': ProbabilityRange(lower: 0.367, upper: 0.513),
+  },
+  'ConstructorDeclaration_initializer': {
+    'this': ProbabilityRange(lower: 0.000, upper: 0.033),
+    'assert': ProbabilityRange(lower: 0.033, upper: 0.181),
+    'super': ProbabilityRange(lower: 0.448, upper: 1.000),
+  },
+  'ConstructorFieldInitializer_expression': {
+    'true': ProbabilityRange(lower: 0.003, upper: 0.005),
+    'false': ProbabilityRange(lower: 0.010, upper: 0.017),
+    'null': ProbabilityRange(lower: 0.026, upper: 0.037),
+  },
+  'DefaultFormalParameter_defaultValue': {
+    'null': ProbabilityRange(lower: 0.000, upper: 0.001),
+    'true': ProbabilityRange(lower: 0.107, upper: 0.199),
+    'const': ProbabilityRange(lower: 0.307, upper: 0.452),
+    'false': ProbabilityRange(lower: 0.452, upper: 0.719),
+  },
+  'ExpressionFunctionBody_expression': {
+    'throw': ProbabilityRange(lower: 0.000, upper: 0.001),
+    'super': ProbabilityRange(lower: 0.001, upper: 0.002),
+    'await': ProbabilityRange(lower: 0.002, upper: 0.004),
+    'const': ProbabilityRange(lower: 0.005, upper: 0.008),
+    'true': ProbabilityRange(lower: 0.008, upper: 0.013),
+    'this': ProbabilityRange(lower: 0.013, upper: 0.019),
+    'false': ProbabilityRange(lower: 0.019, upper: 0.027),
+    'null': ProbabilityRange(lower: 0.034, upper: 0.045),
+  },
+  'ExpressionFunctionBody_start': {
+    'async': ProbabilityRange(lower: 0.000, upper: 1.000),
+  },
+  'ExpressionStatement_expression': {
+    'const': ProbabilityRange(lower: 0.000, upper: 0.000),
+    'rethrow': ProbabilityRange(lower: 0.004, upper: 0.006),
+    'this': ProbabilityRange(lower: 0.009, upper: 0.029),
+    'throw': ProbabilityRange(lower: 0.029, upper: 0.054),
+    'super': ProbabilityRange(lower: 0.084, upper: 0.117),
+    'await': ProbabilityRange(lower: 0.168, upper: 0.218),
+  },
+  'ExtensionDeclaration_member': {
+    'void': ProbabilityRange(lower: 0.000, upper: 0.040),
+  },
+  'FieldDeclaration_fields': {
+    'void': ProbabilityRange(lower: 0.000, upper: 0.000),
+    'var': ProbabilityRange(lower: 0.011, upper: 0.024),
+    'const': ProbabilityRange(lower: 0.024, upper: 0.119),
+    'final': ProbabilityRange(lower: 0.491, upper: 1.000),
+  },
+  'ForEachPartsWithDeclaration_iterable': {
+    'await': ProbabilityRange(lower: 0.000, upper: 0.001),
+    'this': ProbabilityRange(lower: 0.023, upper: 0.031),
+  },
+  'ForEachPartsWithDeclaration_loopVariable': {
+    'var': ProbabilityRange(lower: 0.298, upper: 0.628),
+    'final': ProbabilityRange(lower: 0.628, upper: 1.000),
+  },
+  'ForElement_body': {
+    'for': ProbabilityRange(lower: 0.000, upper: 0.008),
+    'if': ProbabilityRange(lower: 0.008, upper: 0.038),
+  },
+  'ForElement_forLoopParts': {
+    'var': ProbabilityRange(lower: 0.007, upper: 0.274),
+    'final': ProbabilityRange(lower: 0.274, upper: 0.630),
+  },
+  'ForParts_condition': {
+    'true': ProbabilityRange(lower: 0.001, upper: 0.004),
+  },
+  'ForStatement_body': {
+    'for': ProbabilityRange(lower: 0.000, upper: 0.032),
+    'if': ProbabilityRange(lower: 0.032, upper: 0.065),
+  },
+  'ForStatement_forLoopParts': {
+    'final': ProbabilityRange(lower: 0.025, upper: 0.199),
+    'var': ProbabilityRange(lower: 0.199, upper: 0.561),
+  },
+  'FormalParameterList_parameter': {
+    'covariant': ProbabilityRange(lower: 0.000, upper: 0.000),
+    'final': ProbabilityRange(lower: 0.000, upper: 0.001),
+    'var': ProbabilityRange(lower: 0.001, upper: 0.001),
+    'void': ProbabilityRange(lower: 0.024, upper: 0.038),
+    'this': ProbabilityRange(lower: 0.054, upper: 0.360),
+  },
+  'FunctionDeclaration_returnType': {
+    'void': ProbabilityRange(lower: 0.070, upper: 0.354),
+  },
+  'GenericTypeAlias_functionType': {
+    'Function': ProbabilityRange(lower: 0.090, upper: 0.140),
+    'void': ProbabilityRange(lower: 0.480, upper: 1.000),
+  },
+  'IfElement_condition': {
+    'this': ProbabilityRange(lower: 0.005, upper: 0.011),
+  },
+  'IfElement_elseElement': {
+    'for': ProbabilityRange(lower: 0.000, upper: 0.043),
+    'if': ProbabilityRange(lower: 0.087, upper: 0.261),
+  },
+  'IfElement_thenElement': {
+    'for': ProbabilityRange(lower: 0.011, upper: 0.022),
+    'const': ProbabilityRange(lower: 0.047, upper: 0.063),
+  },
+  'IfStatement_condition': {
+    'const': ProbabilityRange(lower: 0.000, upper: 0.000),
+    'super': ProbabilityRange(lower: 0.000, upper: 0.000),
+    'null': ProbabilityRange(lower: 0.000, upper: 0.001),
+    'true': ProbabilityRange(lower: 0.001, upper: 0.002),
+    'await': ProbabilityRange(lower: 0.041, upper: 0.061),
+    'this': ProbabilityRange(lower: 0.061, upper: 0.084),
+  },
+  'IfStatement_elseStatement': {
+    'await': ProbabilityRange(lower: 0.000, upper: 0.001),
+    'this': ProbabilityRange(lower: 0.001, upper: 0.002),
+    'throw': ProbabilityRange(lower: 0.002, upper: 0.003),
+    'rethrow': ProbabilityRange(lower: 0.003, upper: 0.004),
+    'return': ProbabilityRange(lower: 0.095, upper: 0.145),
+    'if': ProbabilityRange(lower: 0.145, upper: 1.000),
+  },
+  'IfStatement_thenStatement': {
+    'super': ProbabilityRange(lower: 0.000, upper: 0.000),
+    'rethrow': ProbabilityRange(lower: 0.000, upper: 0.001),
+    'for': ProbabilityRange(lower: 0.001, upper: 0.001),
+    'while': ProbabilityRange(lower: 0.001, upper: 0.002),
+    'if': ProbabilityRange(lower: 0.003, upper: 0.006),
+    'break': ProbabilityRange(lower: 0.006, upper: 0.009),
+    'this': ProbabilityRange(lower: 0.009, upper: 0.013),
+    'await': ProbabilityRange(lower: 0.025, upper: 0.031),
+    'continue': ProbabilityRange(lower: 0.031, upper: 0.038),
+    'yield': ProbabilityRange(lower: 0.038, upper: 0.048),
+    'throw': ProbabilityRange(lower: 0.048, upper: 0.058),
+    'return': ProbabilityRange(lower: 0.480, upper: 1.000),
+  },
+  'ImportDirective_combinator': {
+    'hide': ProbabilityRange(lower: 0.000, upper: 0.106),
+    'show': ProbabilityRange(lower: 0.106, upper: 1.000),
+  },
+  'ImportDirective_deferred': {
+    'as': ProbabilityRange(lower: 0.000, upper: 1.000),
+  },
+  'ImportDirective_prefix': {
+    'if': ProbabilityRange(lower: 0.000, upper: 0.059),
+    'show': ProbabilityRange(lower: 0.059, upper: 1.000),
+  },
+  'ImportDirective_uri': {
+    'deferred': ProbabilityRange(lower: 0.000, upper: 0.005),
+    'if': ProbabilityRange(lower: 0.005, upper: 0.017),
+    'hide': ProbabilityRange(lower: 0.017, upper: 0.036),
+    'show': ProbabilityRange(lower: 0.036, upper: 0.175),
+    'as': ProbabilityRange(lower: 0.175, upper: 1.000),
+  },
+  'IndexExpression_index': {
+    'await': ProbabilityRange(lower: 0.000, upper: 0.001),
+    'this': ProbabilityRange(lower: 0.001, upper: 0.002),
+  },
+  'InterpolationExpression_expression': {
+    'false': ProbabilityRange(lower: 0.000, upper: 0.000),
+    'await': ProbabilityRange(lower: 0.000, upper: 0.000),
+    'this': ProbabilityRange(lower: 0.010, upper: 0.032),
+  },
+  'ListLiteral_element': {
+    'super': ProbabilityRange(lower: 0.000, upper: 0.000),
+    'null': ProbabilityRange(lower: 0.000, upper: 0.000),
+    'await': ProbabilityRange(lower: 0.000, upper: 0.000),
+    'this': ProbabilityRange(lower: 0.000, upper: 0.000),
+    'false': ProbabilityRange(lower: 0.001, upper: 0.002),
+    'true': ProbabilityRange(lower: 0.002, upper: 0.003),
+    'for': ProbabilityRange(lower: 0.003, upper: 0.004),
+    'if': ProbabilityRange(lower: 0.011, upper: 0.017),
+    'const': ProbabilityRange(lower: 0.063, upper: 0.082),
+  },
+  'MapLiteralEntry_value': {
+    'this': ProbabilityRange(lower: 0.000, upper: 0.002),
+    'true': ProbabilityRange(lower: 0.002, upper: 0.005),
+    'false': ProbabilityRange(lower: 0.011, upper: 0.015),
+    'const': ProbabilityRange(lower: 0.015, upper: 0.019),
+    'null': ProbabilityRange(lower: 0.028, upper: 0.038),
+  },
+  'MethodDeclaration_returnType': {
+    'void': ProbabilityRange(lower: 0.010, upper: 0.179),
+  },
+  'MixinDeclaration_member': {
+    'static': ProbabilityRange(lower: 0.014, upper: 0.024),
+    'void': ProbabilityRange(lower: 0.024, upper: 0.040),
+    'set': ProbabilityRange(lower: 0.040, upper: 0.077),
+    'final': ProbabilityRange(lower: 0.077, upper: 0.128),
+  },
+  'MixinDeclaration_name': {
+    'implements': ProbabilityRange(lower: 0.000, upper: 0.083),
+    'on': ProbabilityRange(lower: 0.083, upper: 1.000),
+  },
+  'ParenthesizedExpression_expression': {
+    'true': ProbabilityRange(lower: 0.000, upper: 0.001),
+    'this': ProbabilityRange(lower: 0.013, upper: 0.023),
+    'await': ProbabilityRange(lower: 0.023, upper: 0.051),
+  },
+  'PrefixExpression_!_operand': {
+    'this': ProbabilityRange(lower: 0.000, upper: 0.004),
+    'await': ProbabilityRange(lower: 0.004, upper: 0.015),
+  },
+  'PrefixExpression_++_operand': {
+    'this': ProbabilityRange(lower: 0.018, upper: 0.035),
+  },
+  'ReturnStatement_expression': {
+    'const': ProbabilityRange(lower: 0.000, upper: 0.003),
+    'super': ProbabilityRange(lower: 0.008, upper: 0.012),
+    'await': ProbabilityRange(lower: 0.012, upper: 0.020),
+    'this': ProbabilityRange(lower: 0.038, upper: 0.050),
+    'false': ProbabilityRange(lower: 0.050, upper: 0.070),
+    'null': ProbabilityRange(lower: 0.090, upper: 0.113),
+    'true': ProbabilityRange(lower: 0.113, upper: 0.142),
+  },
+  'SetOrMapLiteral_element': {
+    'const': ProbabilityRange(lower: 0.009, upper: 0.015),
+    'for': ProbabilityRange(lower: 0.022, upper: 0.031),
+    'if': ProbabilityRange(lower: 0.031, upper: 0.040),
+  },
+  'SpreadElement_expression': {
+    'this': ProbabilityRange(lower: 0.005, upper: 0.022),
+  },
+  'SwitchCase_expression': {
+    'true': ProbabilityRange(lower: 0.000, upper: 0.005),
+    'false': ProbabilityRange(lower: 0.005, upper: 0.009),
+  },
+  'SwitchMember_statement': {
+    'rethrow': ProbabilityRange(lower: 0.000, upper: 0.000),
+    'try': ProbabilityRange(lower: 0.000, upper: 0.001),
+    'continue': ProbabilityRange(lower: 0.001, upper: 0.001),
+    'super': ProbabilityRange(lower: 0.001, upper: 0.002),
+    'var': ProbabilityRange(lower: 0.002, upper: 0.003),
+    'yield': ProbabilityRange(lower: 0.003, upper: 0.005),
+    'switch': ProbabilityRange(lower: 0.005, upper: 0.006),
+    'assert': ProbabilityRange(lower: 0.006, upper: 0.008),
+    'this': ProbabilityRange(lower: 0.008, upper: 0.011),
+    'await': ProbabilityRange(lower: 0.011, upper: 0.013),
+    'for': ProbabilityRange(lower: 0.017, upper: 0.022),
+    'throw': ProbabilityRange(lower: 0.022, upper: 0.027),
+    'final': ProbabilityRange(lower: 0.033, upper: 0.045),
+    'if': ProbabilityRange(lower: 0.085, upper: 0.109),
+    'return': ProbabilityRange(lower: 0.380, upper: 0.642),
+    'break': ProbabilityRange(lower: 0.642, upper: 1.000),
+  },
+  'SwitchStatement_expression': {
+    'await': ProbabilityRange(lower: 0.003, upper: 0.006),
+    'this': ProbabilityRange(lower: 0.010, upper: 0.016),
+  },
+  'ThrowExpression_expression': {
+    'const': ProbabilityRange(lower: 0.000, upper: 0.001),
+  },
+  'TryStatement_catch': {
+    'catch': ProbabilityRange(lower: 0.000, upper: 0.238),
+    'finally': ProbabilityRange(lower: 0.238, upper: 0.595),
+    'on': ProbabilityRange(lower: 0.595, upper: 1.000),
+  },
+  'TryStatement_try': {
+    'finally': ProbabilityRange(lower: 0.000, upper: 0.022),
+    'on': ProbabilityRange(lower: 0.022, upper: 0.183),
+    'catch': ProbabilityRange(lower: 0.183, upper: 1.000),
+  },
+  'TypeArgumentList_argument': {
+    'void': ProbabilityRange(lower: 0.032, upper: 0.053),
+  },
+  'VariableDeclarationList_type': {
+    'void': ProbabilityRange(lower: 0.000, upper: 0.002),
+  },
+  'VariableDeclaration_initializer': {
+    'super': ProbabilityRange(lower: 0.000, upper: 0.000),
+    'null': ProbabilityRange(lower: 0.000, upper: 0.001),
+    'this': ProbabilityRange(lower: 0.001, upper: 0.004),
+    'true': ProbabilityRange(lower: 0.016, upper: 0.023),
+    'false': ProbabilityRange(lower: 0.069, upper: 0.098),
+    'const': ProbabilityRange(lower: 0.098, upper: 0.128),
+    'await': ProbabilityRange(lower: 0.357, upper: 0.459),
+  },
+  'WhileStatement_condition': {
+    'true': ProbabilityRange(lower: 0.050, upper: 0.085),
+  },
+  'YieldStatement_expression': {
+    'null': ProbabilityRange(lower: 0.006, upper: 0.009),
+    'const': ProbabilityRange(lower: 0.028, upper: 0.049),
+    'await': ProbabilityRange(lower: 0.049, upper: 0.073),
   },
 };
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
index 7d74ff0..adcd138 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
@@ -607,8 +607,13 @@
   /// Add a suggestion for a [keyword]. The [offset] is the offset from the
   /// beginning of the keyword where the cursor will be left.
   void suggestKeyword(String keyword, {int offset, @required int relevance}) {
-    // TODO(brianwilkerson) Use the location at which the keyword is being
-    //  inserted to compute the relevance.
+    if (request.useNewRelevance) {
+      // TODO(brianwilkerson) The default value should probably be a constant.
+      relevance = toRelevance(
+          request.featureComputer
+              .keywordFeature(keyword, request.opType.completionLocation),
+          800);
+    }
     _add(CompletionSuggestion(CompletionSuggestionKind.KEYWORD, relevance,
         keyword, offset ?? keyword.length, 0, false, false));
   }
diff --git a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
index 1aeb413..f0074a511 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
@@ -3,8 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
-import 'dart:collection';
-import 'dart:math';
 
 import 'package:analysis_server/plugin/edit/assist/assist_core.dart';
 import 'package:analysis_server/plugin/edit/assist/assist_dart.dart';
@@ -12,6 +10,7 @@
 import 'package:analysis_server/src/services/correction/base_processor.dart';
 import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
 import 'package:analysis_server/src/services/correction/dart/add_diagnostic_property_reference.dart';
+import 'package:analysis_server/src/services/correction/dart/add_not_null_assert.dart';
 import 'package:analysis_server/src/services/correction/dart/add_return_type.dart';
 import 'package:analysis_server/src/services/correction/dart/add_type_annotation.dart';
 import 'package:analysis_server/src/services/correction/dart/assign_to_local_variable.dart';
@@ -23,52 +22,60 @@
 import 'package:analysis_server/src/services/correction/dart/convert_into_async_body.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_into_block_body.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_into_final_field.dart';
+import 'package:analysis_server/src/services/correction/dart/convert_into_for_index.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_into_getter.dart';
+import 'package:analysis_server/src/services/correction/dart/convert_into_is_not.dart';
+import 'package:analysis_server/src/services/correction/dart/convert_into_is_not_empty.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_map_from_iterable_to_for_literal.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_part_of_to_uri.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_quotes.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_expression_function_body.dart';
+import 'package:analysis_server/src/services/correction/dart/convert_to_field_parameter.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_generic_function_syntax.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_int_literal.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_list_literal.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_map_literal.dart';
+import 'package:analysis_server/src/services/correction/dart/convert_to_multiline_string.dart';
+import 'package:analysis_server/src/services/correction/dart/convert_to_normal_parameter.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_null_aware.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_package_import.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_relative_import.dart';
 import 'package:analysis_server/src/services/correction/dart/convert_to_set_literal.dart';
+import 'package:analysis_server/src/services/correction/dart/encapsulate_field.dart';
 import 'package:analysis_server/src/services/correction/dart/exchange_operands.dart';
+import 'package:analysis_server/src/services/correction/dart/flutter_convert_to_children.dart';
+import 'package:analysis_server/src/services/correction/dart/flutter_convert_to_stateful_widget.dart';
+import 'package:analysis_server/src/services/correction/dart/flutter_move_down.dart';
+import 'package:analysis_server/src/services/correction/dart/flutter_move_up.dart';
+import 'package:analysis_server/src/services/correction/dart/flutter_remove_widget.dart';
+import 'package:analysis_server/src/services/correction/dart/flutter_swap_with_child.dart';
+import 'package:analysis_server/src/services/correction/dart/flutter_swap_with_parent.dart';
+import 'package:analysis_server/src/services/correction/dart/flutter_wrap.dart';
+import 'package:analysis_server/src/services/correction/dart/flutter_wrap_generic.dart';
+import 'package:analysis_server/src/services/correction/dart/flutter_wrap_stream_builder.dart';
+import 'package:analysis_server/src/services/correction/dart/import_add_show.dart';
 import 'package:analysis_server/src/services/correction/dart/inline_invocation.dart';
+import 'package:analysis_server/src/services/correction/dart/introduce_local_cast_type.dart';
+import 'package:analysis_server/src/services/correction/dart/invert_if_statement.dart';
+import 'package:analysis_server/src/services/correction/dart/join_if_with_inner.dart';
+import 'package:analysis_server/src/services/correction/dart/join_if_with_outer.dart';
+import 'package:analysis_server/src/services/correction/dart/join_variable_declaration.dart';
 import 'package:analysis_server/src/services/correction/dart/remove_type_annotation.dart';
+import 'package:analysis_server/src/services/correction/dart/replace_conditional_with_if_else.dart';
+import 'package:analysis_server/src/services/correction/dart/replace_if_else_with_conditional.dart';
 import 'package:analysis_server/src/services/correction/dart/replace_with_var.dart';
 import 'package:analysis_server/src/services/correction/dart/shadow_field.dart';
 import 'package:analysis_server/src/services/correction/dart/sort_child_property_last.dart';
 import 'package:analysis_server/src/services/correction/dart/split_and_condition.dart';
+import 'package:analysis_server/src/services/correction/dart/split_variable_declaration.dart';
+import 'package:analysis_server/src/services/correction/dart/surround_with.dart';
 import 'package:analysis_server/src/services/correction/dart/use_curly_braces.dart';
 import 'package:analysis_server/src/services/correction/fix_internal.dart';
-import 'package:analysis_server/src/services/correction/name_suggestion.dart';
-import 'package:analysis_server/src/services/correction/selection_analyzer.dart';
-import 'package:analysis_server/src/services/correction/statement_analyzer.dart';
-import 'package:analysis_server/src/services/correction/util.dart';
-import 'package:analysis_server/src/services/search/hierarchy.dart';
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/precedence.dart';
-import 'package:analyzer/dart/ast/token.dart';
-import 'package:analyzer/dart/ast/visitor.dart';
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/dart/ast/token.dart';
-import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/generated/java_core.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer_plugin/protocol/protocol_common.dart' hide Element;
 import 'package:analyzer_plugin/src/utilities/change_builder/change_builder_dart.dart';
 import 'package:analyzer_plugin/utilities/assist/assist.dart'
     hide AssistContributor;
 import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
-import 'package:analyzer_plugin/utilities/range_factory.dart';
-import 'package:meta/meta.dart';
-
-typedef _SimpleIdentifierVisitor = void Function(SimpleIdentifier node);
 
 /// The computer for Dart assists.
 class AssistProcessor extends BaseProcessor {
@@ -80,6 +87,7 @@
   /// A list of the generators used to produce assists.
   static const List<ProducerGenerator> generators = [
     AddDiagnosticPropertyReference.newInstance,
+    AddNotNullAssert.newInstance,
     AddReturnType.newInstance,
     AddTypeAnnotation.newInstance,
     AssignToLocalVariable.newInstance,
@@ -91,10 +99,16 @@
     ConvertIntoAsyncBody.newInstance,
     ConvertIntoBlockBody.newInstance,
     ConvertIntoFinalField.newInstance,
+    ConvertIntoForIndex.newInstance,
     ConvertIntoGetter.newInstance,
+    ConvertIntoIsNot.newInstance,
+    ConvertIntoIsNotEmpty.newInstance,
     ConvertMapFromIterableToForLiteral.newInstance,
     ConvertPartOfToUri.newInstance,
     ConvertToDoubleQuotes.newInstance,
+    ConvertToFieldParameter.newInstance,
+    ConvertToMutilineString.newInstance,
+    ConvertToNormalParameter.newInstance,
     ConvertToSingleQuotes.newInstance,
     ConvertToExpressionFunctionBody.newInstance,
     ConvertToGenericFunctionSyntax.newInstance,
@@ -105,16 +119,41 @@
     ConvertToPackageImport.newInstance,
     ConvertToRelativeImport.newInstance,
     ConvertToSetLiteral.newInstance,
+    EncapsulateField.newInstance,
     ExchangeOperands.newInstance,
+    FlutterConvertToChildren.newInstance,
+    FlutterConvertToStatefulWidget.newInstance,
+    FlutterMoveDown.newInstance,
+    FlutterMoveUp.newInstance,
+    FlutterRemoveWidget.newInstance,
+    FlutterSwapWithChild.newInstance,
+    FlutterSwapWithParent.newInstance,
+    FlutterWrapGeneric.newInstance,
+    FlutterWrapStreamBuilder.newInstance,
+    ImportAddShow.newInstance,
     InlineInvocation.newInstance,
+    IntroduceLocalCastType.newInstance,
+    InvertIfStatement.newInstance,
+    JoinIfWithInner.newInstance,
+    JoinIfWithOuter.newInstance,
+    JoinVariableDeclaration.newInstance,
     RemoveTypeAnnotation.newInstance,
+    ReplaceConditionalWithIfElse.newInstance,
+    ReplaceIfElseWithConditional.newInstance,
     ReplaceWithVar.newInstance,
     ShadowField.newInstance,
     SortChildPropertyLast.newInstance,
     SplitAndCondition.newInstance,
+    SplitVariableDeclaration.newInstance,
     UseCurlyBraces.newInstance,
   ];
 
+  /// A list of the multi-generators used to produce assists.
+  static const List<MultiProducerGenerator> multiGenerators = [
+    FlutterWrap.newInstance,
+    SurroundWith.newInstance,
+  ];
+
   final DartAssistContext context;
 
   final List<Assist> assists = <Assist>[];
@@ -131,39 +170,6 @@
     if (!setupCompute()) {
       return assists;
     }
-    await _addProposal_addNotNullAssert();
-    await _addProposal_convertToFieldParameter();
-    await _addProposal_convertToForIndexLoop();
-    await _addProposal_convertToIsNot_onIs();
-    await _addProposal_convertToIsNot_onNot();
-    await _addProposal_convertToIsNotEmpty();
-    await _addProposal_convertToMultilineString();
-    await _addProposal_convertToNormalParameter();
-    await _addProposal_encapsulateField();
-    await _addProposal_flutterConvertToChildren();
-    await _addProposal_flutterConvertToStatefulWidget();
-    await _addProposal_flutterMoveWidgetDown();
-    await _addProposal_flutterMoveWidgetUp();
-    await _addProposal_flutterRemoveWidget_singleChild();
-    await _addProposal_flutterRemoveWidget_multipleChildren();
-    await _addProposal_flutterSwapWithChild();
-    await _addProposal_flutterSwapWithParent();
-    await _addProposal_flutterWrapStreamBuilder();
-    await _addProposal_flutterWrapWidget();
-    await _addProposal_flutterWrapWidgets();
-    await _addProposal_importAddShow();
-    await _addProposal_introduceLocalTestedType();
-    await _addProposal_invertIf();
-    await _addProposal_joinIfStatementInner();
-    await _addProposal_joinIfStatementOuter();
-    await _addProposal_joinVariableDeclaration_onAssignment();
-    await _addProposal_joinVariableDeclaration_onDeclaration();
-    await _addProposal_reparentFlutterList();
-    await _addProposal_replaceConditionalWithIfElse();
-    await _addProposal_replaceIfElseWithConditional();
-    await _addProposal_splitVariableDeclaration();
-    await _addProposal_surroundWith();
-
     await _addFromProducers();
 
     return assists;
@@ -189,7 +195,7 @@
     Future<void> compute(CorrectionProducer producer) async {
       producer.configure(context);
 
-      var builder = _newDartChangeBuilder();
+      var builder = DartChangeBuilderImpl.forWorkspace(context.workspace);
       await producer.compute(builder);
 
       _addAssistFromBuilder(builder, producer.assistKind,
@@ -243,2077 +249,21 @@
         var producer = generator();
         producer.configure(context);
 
-        var builder = _newDartChangeBuilder();
+        var builder = DartChangeBuilderImpl.forWorkspace(context.workspace);
         await producer.compute(builder);
-
         _addAssistFromBuilder(builder, producer.assistKind,
             args: producer.assistArguments);
       }
     }
-  }
-
-  Future<void> _addProposal_addNotNullAssert() async {
-    final identifier = node;
-    if (identifier is SimpleIdentifier) {
-      if (identifier.parent is FormalParameter) {
-        final exp = identifier.parent.thisOrAncestorMatching(
-            (node) => node is FunctionExpression || node is MethodDeclaration);
-        var body;
-        if (exp is FunctionExpression) {
-          body = exp.body;
-        } else if (exp is MethodDeclaration) {
-          body = exp.body;
-        }
-        if (body is BlockFunctionBody) {
-          var blockBody = body;
-          // Check for an obvious pre-existing assertion.
-          for (var statement in blockBody.block.statements) {
-            if (statement is AssertStatement) {
-              final condition = statement.condition;
-              if (condition is BinaryExpression) {
-                final leftOperand = condition.leftOperand;
-                if (leftOperand is SimpleIdentifier) {
-                  if (leftOperand.staticElement == identifier.staticElement &&
-                      condition.operator.type == TokenType.BANG_EQ &&
-                      condition.rightOperand is NullLiteral) {
-                    return;
-                  }
-                }
-              }
-            }
-          }
-
-          final changeBuilder = _newDartChangeBuilder();
-          await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
-            final id = identifier.name;
-            final prefix = utils.getNodePrefix(exp);
-            final indent = utils.getIndent(1);
-            // todo (pq): follow-ups:
-            // 1. if the end token is on the same line as the body
-            // we should add an `eol` before the assert as well.
-            // 2. also, consider asking the block for the list of statements and
-            // adding the statement to the beginning of the list, special casing
-            // when there are no statements (or when there's a single statement
-            // and the whole block is on the same line).
-            var offset = min(utils.getLineNext(blockBody.beginToken.offset),
-                blockBody.endToken.offset);
-            builder.addSimpleInsertion(
-                offset, '$prefix${indent}assert($id != null);$eol');
-            _addAssistFromBuilder(
-                changeBuilder, DartAssistKind.ADD_NOT_NULL_ASSERT);
-          });
-        }
-      }
-    }
-  }
-
-  Future<void> _addProposal_convertToFieldParameter() async {
-    if (node == null) {
-      return;
-    }
-    // prepare ConstructorDeclaration
-    var constructor = node.thisOrAncestorOfType<ConstructorDeclaration>();
-    if (constructor == null) {
-      return;
-    }
-    var parameterList = constructor.parameters;
-    List<ConstructorInitializer> initializers = constructor.initializers;
-    // prepare parameter
-    SimpleFormalParameter parameter;
-    if (node.parent is SimpleFormalParameter &&
-        node.parent.parent is FormalParameterList &&
-        node.parent.parent.parent is ConstructorDeclaration) {
-      parameter = node.parent;
-    }
-    if (node is SimpleIdentifier &&
-        node.parent is ConstructorFieldInitializer) {
-      var name = (node as SimpleIdentifier).name;
-      ConstructorFieldInitializer initializer = node.parent;
-      if (initializer.expression == node) {
-        for (var formalParameter in parameterList.parameters) {
-          if (formalParameter is SimpleFormalParameter &&
-              formalParameter.identifier.name == name) {
-            parameter = formalParameter;
-          }
-        }
-      }
-    }
-    // analyze parameter
-    if (parameter != null) {
-      var parameterName = parameter.identifier.name;
-      var parameterElement = parameter.declaredElement;
-      // check number of references
-      {
-        var numOfReferences = 0;
-        AstVisitor visitor =
-            _SimpleIdentifierRecursiveAstVisitor((SimpleIdentifier node) {
-          if (node.staticElement == parameterElement) {
-            numOfReferences++;
-          }
-        });
-        for (var initializer in initializers) {
-          initializer.accept(visitor);
-        }
-        if (numOfReferences != 1) {
-          return;
-        }
-      }
-      // find the field initializer
-      ConstructorFieldInitializer parameterInitializer;
-      for (var initializer in initializers) {
-        if (initializer is ConstructorFieldInitializer) {
-          var expression = initializer.expression;
-          if (expression is SimpleIdentifier &&
-              expression.name == parameterName) {
-            parameterInitializer = initializer;
-          }
-        }
-      }
-      if (parameterInitializer == null) {
-        return;
-      }
-      var fieldName = parameterInitializer.fieldName.name;
-
-      var changeBuilder = _newDartChangeBuilder();
-      await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
-        // replace parameter
-        builder.addSimpleReplacement(range.node(parameter), 'this.$fieldName');
-        // remove initializer
-        var initializerIndex = initializers.indexOf(parameterInitializer);
-        if (initializers.length == 1) {
-          builder
-              .addDeletion(range.endEnd(parameterList, parameterInitializer));
-        } else {
-          if (initializerIndex == 0) {
-            var next = initializers[initializerIndex + 1];
-            builder.addDeletion(range.startStart(parameterInitializer, next));
-          } else {
-            var prev = initializers[initializerIndex - 1];
-            builder.addDeletion(range.endEnd(prev, parameterInitializer));
-          }
-        }
-      });
-      _addAssistFromBuilder(
-          changeBuilder, DartAssistKind.CONVERT_TO_FIELD_PARAMETER);
-    }
-  }
-
-  Future<void> _addProposal_convertToForIndexLoop() async {
-    // find enclosing ForEachStatement
-    var forEachStatement = node.thisOrAncestorMatching(
-            (node) => node is ForStatement && node.forLoopParts is ForEachParts)
-        as ForStatement;
-    if (forEachStatement == null) {
-      return;
-    }
-    ForEachParts forEachParts = forEachStatement.forLoopParts;
-    if (selectionOffset < forEachStatement.offset ||
-        forEachStatement.rightParenthesis.end < selectionOffset) {
-      return;
-    }
-    // loop should declare variable
-    var loopVariable = forEachParts is ForEachPartsWithDeclaration
-        ? forEachParts.loopVariable
-        : null;
-    if (loopVariable == null) {
-      return;
-    }
-    // iterable should be VariableElement
-    String listName;
-    var iterable = forEachParts.iterable;
-    if (iterable is SimpleIdentifier &&
-        iterable.staticElement is VariableElement) {
-      listName = iterable.name;
-    } else {
-      return;
-    }
-    // iterable should be List
-    {
-      var iterableType = iterable.staticType;
-      if (iterableType is! InterfaceType ||
-          iterableType.element != typeProvider.listElement) {
-        return;
-      }
-    }
-    // body should be Block
-    if (forEachStatement.body is! Block) {
-      return;
-    }
-    Block body = forEachStatement.body;
-    // prepare a name for the index variable
-    String indexName;
-    {
-      var conflicts =
-          utils.findPossibleLocalVariableConflicts(forEachStatement.offset);
-      if (!conflicts.contains('i')) {
-        indexName = 'i';
-      } else if (!conflicts.contains('j')) {
-        indexName = 'j';
-      } else if (!conflicts.contains('k')) {
-        indexName = 'k';
-      } else {
-        return;
-      }
-    }
-    // prepare environment
-    var prefix = utils.getNodePrefix(forEachStatement);
-    var indent = utils.getIndent(1);
-    var firstBlockLine = utils.getLineContentEnd(body.leftBracket.end);
-    // add change
-    var changeBuilder = _newDartChangeBuilder();
-    await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
-      // TODO(brianwilkerson) Create linked positions for the loop variable.
-      builder.addSimpleReplacement(
-          range.startEnd(forEachStatement, forEachStatement.rightParenthesis),
-          'for (int $indexName = 0; $indexName < $listName.length; $indexName++)');
-      builder.addSimpleInsertion(firstBlockLine,
-          '$prefix$indent$loopVariable = $listName[$indexName];$eol');
-    });
-    _addAssistFromBuilder(changeBuilder, DartAssistKind.CONVERT_INTO_FOR_INDEX);
-  }
-
-  Future<void> _addProposal_convertToIsNot_onIs() async {
-    // may be child of "is"
-    var node = this.node;
-    while (node != null && node is! IsExpression) {
-      node = node.parent;
-    }
-    // prepare "is"
-    if (node is! IsExpression) {
-      return;
-    }
-    var isExpression = node as IsExpression;
-    if (isExpression.notOperator != null) {
-      return;
-    }
-    // prepare enclosing ()
-    var parent = isExpression.parent;
-    if (parent is! ParenthesizedExpression) {
-      return;
-    }
-    var parExpression = parent as ParenthesizedExpression;
-    // prepare enclosing !()
-    var parent2 = parent.parent;
-    if (parent2 is! PrefixExpression) {
-      return;
-    }
-    var prefExpression = parent2 as PrefixExpression;
-    if (prefExpression.operator.type != TokenType.BANG) {
-      return;
-    }
-
-    var changeBuilder = _newDartChangeBuilder();
-    await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
-      if (getExpressionParentPrecedence(prefExpression) >=
-          Precedence.relational) {
-        builder.addDeletion(range.token(prefExpression.operator));
-      } else {
-        builder.addDeletion(
-            range.startEnd(prefExpression, parExpression.leftParenthesis));
-        builder.addDeletion(
-            range.startEnd(parExpression.rightParenthesis, prefExpression));
-      }
-      builder.addSimpleInsertion(isExpression.isOperator.end, '!');
-    });
-    _addAssistFromBuilder(changeBuilder, DartAssistKind.CONVERT_INTO_IS_NOT);
-  }
-
-  Future<void> _addProposal_convertToIsNot_onNot() async {
-    // may be () in prefix expression
-    var node = this.node;
-    if (node is ParenthesizedExpression && node.parent is PrefixExpression) {
-      node = node.parent;
-    }
-    // prepare !()
-    if (node is! PrefixExpression) {
-      return;
-    }
-    var prefExpression = node as PrefixExpression;
-    // should be ! operator
-    if (prefExpression.operator.type != TokenType.BANG) {
-      return;
-    }
-    // prepare !()
-    var operand = prefExpression.operand;
-    if (operand is! ParenthesizedExpression) {
-      return;
-    }
-    var parExpression = operand as ParenthesizedExpression;
-    operand = parExpression.expression;
-    // prepare "is"
-    if (operand is! IsExpression) {
-      return;
-    }
-    var isExpression = operand as IsExpression;
-    if (isExpression.notOperator != null) {
-      return;
-    }
-
-    var changeBuilder = _newDartChangeBuilder();
-    await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
-      if (getExpressionParentPrecedence(prefExpression) >=
-          Precedence.relational) {
-        builder.addDeletion(range.token(prefExpression.operator));
-      } else {
-        builder.addDeletion(
-            range.startEnd(prefExpression, parExpression.leftParenthesis));
-        builder.addDeletion(
-            range.startEnd(parExpression.rightParenthesis, prefExpression));
-      }
-      builder.addSimpleInsertion(isExpression.isOperator.end, '!');
-    });
-    _addAssistFromBuilder(changeBuilder, DartAssistKind.CONVERT_INTO_IS_NOT);
-  }
-
-  /// Converts "!isEmpty" -> "isNotEmpty" if possible.
-  Future<void> _addProposal_convertToIsNotEmpty() async {
-    // prepare "expr.isEmpty"
-    AstNode isEmptyAccess;
-    SimpleIdentifier isEmptyIdentifier;
-    if (node is SimpleIdentifier) {
-      var identifier = node as SimpleIdentifier;
-      var parent = identifier.parent;
-      // normal case (but rare)
-      if (parent is PropertyAccess) {
-        isEmptyIdentifier = parent.propertyName;
-        isEmptyAccess = parent;
-      }
-      // usual case
-      if (parent is PrefixedIdentifier) {
-        isEmptyIdentifier = parent.identifier;
-        isEmptyAccess = parent;
-      }
-    }
-    if (isEmptyIdentifier == null) {
-      return;
-    }
-    // should be "isEmpty"
-    var propertyElement = isEmptyIdentifier.staticElement;
-    if (propertyElement == null || 'isEmpty' != propertyElement.name) {
-      return;
-    }
-    // should have "isNotEmpty"
-    var propertyTarget = propertyElement.enclosingElement;
-    if (propertyTarget == null ||
-        getChildren(propertyTarget, 'isNotEmpty').isEmpty) {
-      return;
-    }
-    // should be in PrefixExpression
-    if (isEmptyAccess.parent is! PrefixExpression) {
-      return;
-    }
-    var prefixExpression = isEmptyAccess.parent as PrefixExpression;
-    // should be !
-    if (prefixExpression.operator.type != TokenType.BANG) {
-      return;
-    }
-
-    var changeBuilder = _newDartChangeBuilder();
-    await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
-      builder.addDeletion(
-          range.startStart(prefixExpression, prefixExpression.operand));
-      builder.addSimpleReplacement(range.node(isEmptyIdentifier), 'isNotEmpty');
-    });
-    _addAssistFromBuilder(
-        changeBuilder, DartAssistKind.CONVERT_INTO_IS_NOT_EMPTY);
-  }
-
-  Future<void> _addProposal_convertToMultilineString() async {
-    var node = this.node;
-    if (node is InterpolationElement) {
-      node = (node as InterpolationElement).parent;
-    }
-    if (node is SingleStringLiteral) {
-      var literal = node;
-      if (!literal.isMultiline) {
-        var changeBuilder = _newDartChangeBuilder();
-        await changeBuilder.addFileEdit(file, (builder) {
-          var newQuote = literal.isSingleQuoted ? "'''" : '"""';
-          builder.addReplacement(
-            SourceRange(literal.offset + (literal.isRaw ? 1 : 0), 1),
-            (builder) {
-              builder.writeln(newQuote);
-            },
-          );
-          builder.addSimpleReplacement(
-            SourceRange(literal.end - 1, 1),
-            newQuote,
-          );
-        });
-        _addAssistFromBuilder(
-          changeBuilder,
-          DartAssistKind.CONVERT_TO_MULTILINE_STRING,
-        );
-      }
-    }
-  }
-
-  Future<void> _addProposal_convertToNormalParameter() async {
-    if (node is SimpleIdentifier &&
-        node.parent is FieldFormalParameter &&
-        node.parent.parent is FormalParameterList &&
-        node.parent.parent.parent is ConstructorDeclaration) {
-      ConstructorDeclaration constructor = node.parent.parent.parent;
-      FormalParameterList parameterList = node.parent.parent;
-      FieldFormalParameter parameter = node.parent;
-      var parameterElement = parameter.declaredElement;
-      var name = (node as SimpleIdentifier).name;
-      // prepare type
-      var type = parameterElement.type;
-
-      var changeBuilder = _newDartChangeBuilder();
-      await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
-        // replace parameter
-        if (type.isDynamic) {
-          builder.addSimpleReplacement(range.node(parameter), name);
-        } else {
-          builder.addReplacement(range.node(parameter),
-              (DartEditBuilder builder) {
-            builder.writeType(type);
-            builder.write(' ');
-            builder.write(name);
-          });
-        }
-        // add field initializer
-        List<ConstructorInitializer> initializers = constructor.initializers;
-        if (initializers.isEmpty) {
-          builder.addSimpleInsertion(parameterList.end, ' : $name = $name');
-        } else {
-          builder.addSimpleInsertion(initializers.last.end, ', $name = $name');
-        }
-      });
-      _addAssistFromBuilder(
-          changeBuilder, DartAssistKind.CONVERT_TO_NORMAL_PARAMETER);
-    }
-  }
-
-  Future<void> _addProposal_encapsulateField() async {
-    // find FieldDeclaration
-    var fieldDeclaration = node.thisOrAncestorOfType<FieldDeclaration>();
-    if (fieldDeclaration == null) {
-      return;
-    }
-    // not interesting for static
-    if (fieldDeclaration.isStatic) {
-      return;
-    }
-    // has a parse error
-    var variableList = fieldDeclaration.fields;
-    if (variableList.keyword == null && variableList.type == null) {
-      return;
-    }
-    // not interesting for final
-    if (variableList.isFinal) {
-      return;
-    }
-    // should have exactly one field
-    List<VariableDeclaration> fields = variableList.variables;
-    if (fields.length != 1) {
-      return;
-    }
-    var field = fields.first;
-    var nameNode = field.name;
-    FieldElement fieldElement = nameNode.staticElement;
-    // should have a public name
-    var name = nameNode.name;
-    if (Identifier.isPrivateName(name)) {
-      return;
-    }
-    // should be on the name
-    if (nameNode != node) {
-      return;
-    }
-    var changeBuilder = _newDartChangeBuilder();
-    await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
-      // rename field
-      builder.addSimpleReplacement(range.node(nameNode), '_$name');
-      // update references in constructors
-      ClassOrMixinDeclaration classDeclaration = fieldDeclaration.parent;
-      for (var member in classDeclaration.members) {
-        if (member is ConstructorDeclaration) {
-          for (var parameter in member.parameters.parameters) {
-            var parameterElement = parameter.declaredElement;
-            if (parameterElement is FieldFormalParameterElement &&
-                parameterElement.field == fieldElement) {
-              var identifier = parameter.identifier;
-              builder.addSimpleReplacement(range.node(identifier), '_$name');
-            }
-          }
-        }
-      }
-
-      // Write getter and setter.
-      builder.addInsertion(fieldDeclaration.end, (builder) {
-        String docCode;
-        if (fieldDeclaration.documentationComment != null) {
-          docCode = utils.getNodeText(fieldDeclaration.documentationComment);
-        }
-
-        var typeCode = '';
-        if (variableList.type != null) {
-          typeCode = _getNodeText(variableList.type) + ' ';
-        }
-
-        // Write getter.
-        builder.writeln();
-        builder.writeln();
-        if (docCode != null) {
-          builder.write('  ');
-          builder.writeln(docCode);
-        }
-        builder.write('  ${typeCode}get $name => _$name;');
-
-        // Write setter.
-        builder.writeln();
-        builder.writeln();
-        if (docCode != null) {
-          builder.write('  ');
-          builder.writeln(docCode);
-        }
-        builder.writeln('  set $name($typeCode$name) {');
-        builder.writeln('    _$name = $name;');
-        builder.write('  }');
-      });
-    });
-    _addAssistFromBuilder(changeBuilder, DartAssistKind.ENCAPSULATE_FIELD);
-  }
-
-  Future<void> _addProposal_flutterConvertToChildren() async {
-    // Find "child: widget" under selection.
-    NamedExpression namedExp;
-    {
-      var node = this.node;
-      var parent = node?.parent;
-      var parent2 = parent?.parent;
-      if (node is SimpleIdentifier &&
-          parent is Label &&
-          parent2 is NamedExpression &&
-          node.name == 'child' &&
-          node.staticElement != null &&
-          flutter.isWidgetExpression(parent2.expression)) {
-        namedExp = parent2;
-      } else {
-        return;
-      }
-    }
-
-    var changeBuilder = _newDartChangeBuilder();
-    await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
-      _convertFlutterChildToChildren(namedExp, eol, utils.getNodeText,
-          utils.getLinePrefix, utils.getIndent, utils.getText, builder);
-    });
-    _addAssistFromBuilder(
-        changeBuilder, DartAssistKind.FLUTTER_CONVERT_TO_CHILDREN);
-  }
-
-  Future<void> _addProposal_flutterConvertToStatefulWidget() async {
-    var widgetClass = node.thisOrAncestorOfType<ClassDeclaration>();
-    var superclass = widgetClass?.extendsClause?.superclass;
-    if (widgetClass == null || superclass == null) {
-      return;
-    }
-
-    // Don't spam, activate only from the `class` keyword to the class body.
-    if (selectionOffset < widgetClass.classKeyword.offset ||
-        selectionOffset > widgetClass.leftBracket.end) {
-      return;
-    }
-
-    // Find the build() method.
-    MethodDeclaration buildMethod;
-    for (var member in widgetClass.members) {
-      if (member is MethodDeclaration &&
-          member.name.name == 'build' &&
-          member.parameters != null &&
-          member.parameters.parameters.length == 1) {
-        buildMethod = member;
-        break;
-      }
-    }
-    if (buildMethod == null) {
-      return;
-    }
-
-    // Must be a StatelessWidget subclasses.
-    var widgetClassElement = widgetClass.declaredElement;
-    if (!flutter.isExactlyStatelessWidgetType(widgetClassElement.supertype)) {
-      return;
-    }
-
-    var widgetName = widgetClassElement.displayName;
-    var stateName = '_${widgetName}State';
-
-    // Find fields assigned in constructors.
-    var fieldsAssignedInConstructors = <FieldElement>{};
-    for (var member in widgetClass.members) {
-      if (member is ConstructorDeclaration) {
-        member.accept(_SimpleIdentifierRecursiveAstVisitor((node) {
-          if (node.parent is FieldFormalParameter) {
-            var element = node.staticElement;
-            if (element is FieldFormalParameterElement) {
-              fieldsAssignedInConstructors.add(element.field);
-            }
-          }
-          if (node.parent is ConstructorFieldInitializer) {
-            var element = node.staticElement;
-            if (element is FieldElement) {
-              fieldsAssignedInConstructors.add(element);
-            }
-          }
-          if (node.inSetterContext()) {
-            var element = node.staticElement;
-            if (element is PropertyAccessorElement) {
-              var field = element.variable;
-              if (field is FieldElement) {
-                fieldsAssignedInConstructors.add(field);
-              }
-            }
-          }
-        }));
-      }
-    }
-
-    // Prepare nodes to move.
-    var nodesToMove = <ClassMember>{};
-    var elementsToMove = <Element>{};
-    for (var member in widgetClass.members) {
-      if (member is FieldDeclaration && !member.isStatic) {
-        for (var fieldNode in member.fields.variables) {
-          FieldElement fieldElement = fieldNode.declaredElement;
-          if (!fieldsAssignedInConstructors.contains(fieldElement)) {
-            nodesToMove.add(member);
-            elementsToMove.add(fieldElement);
-            elementsToMove.add(fieldElement.getter);
-            if (fieldElement.setter != null) {
-              elementsToMove.add(fieldElement.setter);
-            }
-          }
-        }
-      }
-      if (member is MethodDeclaration && !member.isStatic) {
-        nodesToMove.add(member);
-        elementsToMove.add(member.declaredElement);
-      }
-    }
-
-    /// Return the code for the [movedNode] which is suitable to be used
-    /// inside the `State` class, so that references to the widget fields and
-    /// methods, that are not moved, are qualified with the corresponding
-    /// instance `widget.`, or static `MyWidgetClass.` qualifier.
-    String rewriteWidgetMemberReferences(AstNode movedNode) {
-      var linesRange = utils.getLinesRange(range.node(movedNode));
-      var text = utils.getRangeText(linesRange);
-
-      // Insert `widget.` before references to the widget instance members.
-      var edits = <SourceEdit>[];
-      movedNode.accept(_SimpleIdentifierRecursiveAstVisitor((node) {
-        if (node.inDeclarationContext()) {
-          return;
-        }
-        var element = node.staticElement;
-        if (element is ExecutableElement &&
-            element?.enclosingElement == widgetClassElement &&
-            !elementsToMove.contains(element)) {
-          var offset = node.offset - linesRange.offset;
-          var qualifier = element.isStatic ? widgetName : 'widget';
-
-          var parent = node.parent;
-          if (parent is InterpolationExpression &&
-              parent.leftBracket.type ==
-                  TokenType.STRING_INTERPOLATION_IDENTIFIER) {
-            edits.add(SourceEdit(offset, 0, '{$qualifier.'));
-            edits.add(SourceEdit(offset + node.length, 0, '}'));
-          } else {
-            edits.add(SourceEdit(offset, 0, '$qualifier.'));
-          }
-        }
-      }));
-      return SourceEdit.applySequence(text, edits.reversed);
-    }
-
-    var statefulWidgetClass = await sessionHelper.getClass(
-      flutter.widgetsUri,
-      'StatefulWidget',
-    );
-    var stateClass = await sessionHelper.getClass(
-      flutter.widgetsUri,
-      'State',
-    );
-    if (statefulWidgetClass == null || stateClass == null) {
-      return;
-    }
-
-    var changeBuilder = _newDartChangeBuilder();
-    await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
-      builder.addReplacement(range.node(superclass), (builder) {
-        builder.writeReference(statefulWidgetClass);
-      });
-
-      var replaceOffset = 0;
-      var hasBuildMethod = false;
-
-      var typeParams = '';
-      if (widgetClass.typeParameters != null) {
-        typeParams = utils.getNodeText(widgetClass.typeParameters);
-      }
-
-      /// Replace code between [replaceOffset] and [replaceEnd] with
-      /// `createState()`, empty line, or nothing.
-      void replaceInterval(int replaceEnd,
-          {bool replaceWithEmptyLine = false,
-          bool hasEmptyLineBeforeCreateState = false,
-          bool hasEmptyLineAfterCreateState = true}) {
-        var replaceLength = replaceEnd - replaceOffset;
-        builder.addReplacement(
-          SourceRange(replaceOffset, replaceLength),
-          (builder) {
-            if (hasBuildMethod) {
-              if (hasEmptyLineBeforeCreateState) {
-                builder.writeln();
-              }
-              builder.writeln('  @override');
-              builder.writeln(
-                  '  $stateName$typeParams createState() => $stateName$typeParams();');
-              if (hasEmptyLineAfterCreateState) {
-                builder.writeln();
-              }
-              hasBuildMethod = false;
-            } else if (replaceWithEmptyLine) {
-              builder.writeln();
-            }
-          },
-        );
-        replaceOffset = 0;
-      }
-
-      // Remove continuous ranges of lines of nodes being moved.
-      var lastToRemoveIsField = false;
-      var endOfLastNodeToKeep = 0;
-      for (var node in widgetClass.members) {
-        if (nodesToMove.contains(node)) {
-          if (replaceOffset == 0) {
-            var linesRange = utils.getLinesRange(range.node(node));
-            replaceOffset = linesRange.offset;
-          }
-          if (node == buildMethod) {
-            hasBuildMethod = true;
-          }
-          lastToRemoveIsField = node is FieldDeclaration;
-        } else {
-          var linesRange = utils.getLinesRange(range.node(node));
-          endOfLastNodeToKeep = linesRange.end;
-          if (replaceOffset != 0) {
-            replaceInterval(linesRange.offset,
-                replaceWithEmptyLine:
-                    lastToRemoveIsField && node is! FieldDeclaration);
-          }
-        }
-      }
-
-      // Remove nodes at the end of the widget class.
-      if (replaceOffset != 0) {
-        // Remove from the last node to keep, so remove empty lines.
-        if (endOfLastNodeToKeep != 0) {
-          replaceOffset = endOfLastNodeToKeep;
-        }
-        replaceInterval(widgetClass.rightBracket.offset,
-            hasEmptyLineBeforeCreateState: endOfLastNodeToKeep != 0,
-            hasEmptyLineAfterCreateState: false);
-      }
-
-      // Create the State subclass.
-      builder.addInsertion(widgetClass.end, (builder) {
-        builder.writeln();
-        builder.writeln();
-
-        builder.write('class $stateName$typeParams extends ');
-        builder.writeReference(stateClass);
-
-        // Write just param names (and not bounds, metadata and docs).
-        builder.write('<${widgetClass.name}');
-        if (widgetClass.typeParameters != null) {
-          builder.write('<');
-          var first = true;
-          for (var param in widgetClass.typeParameters.typeParameters) {
-            if (!first) {
-              builder.write(', ');
-              first = false;
-            }
-            builder.write(param.name.name);
-          }
-          builder.write('>');
-        }
-
-        builder.writeln('> {');
-
-        var writeEmptyLine = false;
-        for (var member in nodesToMove) {
-          if (writeEmptyLine) {
-            builder.writeln();
-          }
-          var text = rewriteWidgetMemberReferences(member);
-          builder.write(text);
-          // Write empty lines between members, but not before the first.
-          writeEmptyLine = true;
-        }
-
-        builder.write('}');
-      });
-    });
-    _addAssistFromBuilder(
-        changeBuilder, DartAssistKind.FLUTTER_CONVERT_TO_STATEFUL_WIDGET);
-  }
-
-  Future<void> _addProposal_flutterMoveWidgetDown() async {
-    var widget = flutter.identifyWidgetExpression(node);
-    if (widget == null) {
-      return;
-    }
-
-    var parentList = widget.parent;
-    if (parentList is ListLiteral) {
-      List<CollectionElement> parentElements = parentList.elements;
-      var index = parentElements.indexOf(widget);
-      if (index != parentElements.length - 1) {
-        var changeBuilder = _newDartChangeBuilder();
-        await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
-          var nextWidget = parentElements[index + 1];
-          var nextRange = range.node(nextWidget);
-          var nextText = utils.getRangeText(nextRange);
-
-          var widgetRange = range.node(widget);
-          var widgetText = utils.getRangeText(widgetRange);
-
-          builder.addSimpleReplacement(nextRange, widgetText);
-          builder.addSimpleReplacement(widgetRange, nextText);
-
-          var lengthDelta = nextRange.length - widgetRange.length;
-          var newWidgetOffset = nextRange.offset + lengthDelta;
-          changeBuilder.setSelection(Position(file, newWidgetOffset));
-        });
-        _addAssistFromBuilder(changeBuilder, DartAssistKind.FLUTTER_MOVE_DOWN);
-      }
-    }
-  }
-
-  Future<void> _addProposal_flutterMoveWidgetUp() async {
-    var widget = flutter.identifyWidgetExpression(node);
-    if (widget == null) {
-      return;
-    }
-
-    var parentList = widget.parent;
-    if (parentList is ListLiteral) {
-      List<CollectionElement> parentElements = parentList.elements;
-      var index = parentElements.indexOf(widget);
-      if (index > 0) {
-        var changeBuilder = _newDartChangeBuilder();
-        await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
-          var previousWidget = parentElements[index - 1];
-          var previousRange = range.node(previousWidget);
-          var previousText = utils.getRangeText(previousRange);
-
-          var widgetRange = range.node(widget);
-          var widgetText = utils.getRangeText(widgetRange);
-
-          builder.addSimpleReplacement(previousRange, widgetText);
-          builder.addSimpleReplacement(widgetRange, previousText);
-
-          var newWidgetOffset = previousRange.offset;
-          changeBuilder.setSelection(Position(file, newWidgetOffset));
-        });
-        _addAssistFromBuilder(changeBuilder, DartAssistKind.FLUTTER_MOVE_UP);
-      }
-    }
-  }
-
-  Future<void> _addProposal_flutterRemoveWidget_multipleChildren() async {
-    var widgetCreation = flutter.identifyNewExpression(node);
-    if (widgetCreation == null) {
-      return;
-    }
-
-    // Prepare the list of our children.
-    List<CollectionElement> childrenExpressions;
-    {
-      var childrenArgument = flutter.findChildrenArgument(widgetCreation);
-      var childrenExpression = childrenArgument?.expression;
-      if (childrenExpression is ListLiteral &&
-          childrenExpression.elements.isNotEmpty) {
-        childrenExpressions = childrenExpression.elements;
-      } else {
-        return;
-      }
-    }
-
-    // We can inline the list of our children only into another list.
-    var widgetParentNode = widgetCreation.parent;
-    if (childrenExpressions.length > 1 && widgetParentNode is! ListLiteral) {
-      return;
-    }
-
-    var changeBuilder = _newDartChangeBuilder();
-    await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
-      var firstChild = childrenExpressions.first;
-      var lastChild = childrenExpressions.last;
-      var childText = utils.getRangeText(range.startEnd(firstChild, lastChild));
-      var indentOld = utils.getLinePrefix(firstChild.offset);
-      var indentNew = utils.getLinePrefix(widgetCreation.offset);
-      childText = _replaceSourceIndent(childText, indentOld, indentNew);
-      builder.addSimpleReplacement(range.node(widgetCreation), childText);
-    });
-    _addAssistFromBuilder(changeBuilder, DartAssistKind.FLUTTER_REMOVE_WIDGET);
-  }
-
-  Future<void> _addProposal_flutterRemoveWidget_singleChild() async {
-    var widgetCreation = flutter.identifyNewExpression(node);
-    if (widgetCreation == null) {
-      return;
-    }
-
-    var childArgument = flutter.findChildArgument(widgetCreation);
-    if (childArgument == null) {
-      return;
-    }
-
-    // child: ThisWidget(child: ourChild)
-    // children: [foo, ThisWidget(child: ourChild), bar]
-    var changeBuilder = _newDartChangeBuilder();
-    await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
-      var childExpression = childArgument.expression;
-      var childText = utils.getNodeText(childExpression);
-      var indentOld = utils.getLinePrefix(childExpression.offset);
-      var indentNew = utils.getLinePrefix(widgetCreation.offset);
-      childText = _replaceSourceIndent(childText, indentOld, indentNew);
-      builder.addSimpleReplacement(range.node(widgetCreation), childText);
-    });
-    _addAssistFromBuilder(changeBuilder, DartAssistKind.FLUTTER_REMOVE_WIDGET);
-  }
-
-  Future<void> _addProposal_flutterSwapWithChild() async {
-    var parent = flutter.identifyNewExpression(node);
-    if (!flutter.isWidgetCreation(parent)) {
-      return;
-    }
-
-    var childArgument = flutter.findChildArgument(parent);
-    if (childArgument?.expression is! InstanceCreationExpression ||
-        !flutter.isWidgetCreation(childArgument.expression)) {
-      return;
-    }
-    InstanceCreationExpression child = childArgument.expression;
-
-    await _swapParentAndChild(
-        parent, child, DartAssistKind.FLUTTER_SWAP_WITH_CHILD);
-  }
-
-  Future<void> _addProposal_flutterSwapWithParent() async {
-    var child = flutter.identifyNewExpression(node);
-    if (!flutter.isWidgetCreation(child)) {
-      return;
-    }
-
-    // NamedExpression (child:), ArgumentList, InstanceCreationExpression
-    var expr = child.parent?.parent?.parent;
-    if (expr is! InstanceCreationExpression) {
-      return;
-    }
-    InstanceCreationExpression parent = expr;
-
-    await _swapParentAndChild(
-        parent, child, DartAssistKind.FLUTTER_SWAP_WITH_PARENT);
-  }
-
-  Future<void> _addProposal_flutterWrapStreamBuilder() async {
-    var widgetExpr = flutter.identifyWidgetExpression(node);
-    if (widgetExpr == null) {
-      return;
-    }
-    if (flutter.isExactWidgetTypeStreamBuilder(widgetExpr.staticType)) {
-      return;
-    }
-    var widgetSrc = utils.getNodeText(widgetExpr);
-
-    var streamBuilderElement = await sessionHelper.getClass(
-      flutter.widgetsUri,
-      'StreamBuilder',
-    );
-    if (streamBuilderElement == null) {
-      return;
-    }
-
-    var changeBuilder = _newDartChangeBuilder();
-    await changeBuilder.addFileEdit(file, (builder) {
-      builder.addReplacement(range.node(widgetExpr), (builder) {
-        builder.writeReference(streamBuilderElement);
-
-        builder.write('<');
-        builder.addSimpleLinkedEdit('type', 'Object');
-        builder.writeln('>(');
-
-        var indentOld = utils.getLinePrefix(widgetExpr.offset);
-        var indentNew1 = indentOld + utils.getIndent(1);
-        var indentNew2 = indentOld + utils.getIndent(2);
-
-        builder.write(indentNew1);
-        builder.writeln('stream: null,');
-
-        builder.write(indentNew1);
-        builder.writeln('builder: (context, snapshot) {');
-
-        widgetSrc = widgetSrc.replaceAll(
-          RegExp('^$indentOld', multiLine: true),
-          indentNew2,
-        );
-        builder.write(indentNew2);
-        builder.write('return $widgetSrc');
-        builder.writeln(';');
-
-        builder.write(indentNew1);
-        builder.writeln('}');
-
-        builder.write(indentOld);
-        builder.write(')');
-      });
-    });
-    _addAssistFromBuilder(
-      changeBuilder,
-      DartAssistKind.FLUTTER_WRAP_STREAM_BUILDER,
-    );
-  }
-
-  Future<void> _addProposal_flutterWrapWidget() async {
-    await _addProposal_flutterWrapWidgetImpl();
-    await _addProposal_flutterWrapWidgetImpl(
-        kind: DartAssistKind.FLUTTER_WRAP_CENTER,
-        parentLibraryUri: flutter.widgetsUri,
-        parentClassName: 'Center',
-        widgetValidator: (expr) {
-          return !flutter.isExactWidgetTypeCenter(expr.staticType);
-        });
-    await _addProposal_flutterWrapWidgetImpl(
-        kind: DartAssistKind.FLUTTER_WRAP_CONTAINER,
-        parentLibraryUri: flutter.widgetsUri,
-        parentClassName: 'Container',
-        widgetValidator: (expr) {
-          return !flutter.isExactWidgetTypeContainer(expr.staticType);
-        });
-    await _addProposal_flutterWrapWidgetImpl(
-        kind: DartAssistKind.FLUTTER_WRAP_PADDING,
-        parentLibraryUri: flutter.widgetsUri,
-        parentClassName: 'Padding',
-        leadingLines: ['padding: const EdgeInsets.all(8.0),'],
-        widgetValidator: (expr) {
-          return !flutter.isExactWidgetTypePadding(expr.staticType);
-        });
-  }
-
-  Future<void> _addProposal_flutterWrapWidgetImpl(
-      {AssistKind kind = DartAssistKind.FLUTTER_WRAP_GENERIC,
-      bool Function(Expression widgetExpr) widgetValidator,
-      String parentLibraryUri,
-      String parentClassName,
-      List<String> leadingLines = const []}) async {
-    var widgetExpr = flutter.identifyWidgetExpression(node);
-    if (widgetExpr == null) {
-      return;
-    }
-    if (widgetValidator != null && !widgetValidator(widgetExpr)) {
-      return;
-    }
-    var widgetSrc = utils.getNodeText(widgetExpr);
-
-    // If the wrapper class is specified, find its element.
-    ClassElement parentClassElement;
-    if (parentLibraryUri != null && parentClassName != null) {
-      parentClassElement =
-          await sessionHelper.getClass(parentLibraryUri, parentClassName);
-      if (parentClassElement == null) {
-        return;
-      }
-    }
-
-    var changeBuilder = _newDartChangeBuilder();
-    await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
-      builder.addReplacement(range.node(widgetExpr), (DartEditBuilder builder) {
-        if (parentClassElement == null) {
-          builder.addSimpleLinkedEdit('WIDGET', 'widget');
-        } else {
-          builder.writeReference(parentClassElement);
-        }
-        builder.write('(');
-        if (widgetSrc.contains(eol) || leadingLines.isNotEmpty) {
-          var indentOld = utils.getLinePrefix(widgetExpr.offset);
-          var indentNew = '$indentOld${utils.getIndent(1)}';
-
-          for (var leadingLine in leadingLines) {
-            builder.write(eol);
-            builder.write(indentNew);
-            builder.write(leadingLine);
-          }
-
-          builder.write(eol);
-          builder.write(indentNew);
-          widgetSrc = widgetSrc.replaceAll(
-              RegExp('^$indentOld', multiLine: true), indentNew);
-          widgetSrc += ',$eol$indentOld';
-        }
-        if (parentClassElement == null) {
-          builder.addSimpleLinkedEdit('CHILD', 'child');
-        } else {
-          builder.write('child');
-        }
-        builder.write(': ');
-        builder.write(widgetSrc);
-        builder.write(')');
-      });
-    });
-    _addAssistFromBuilder(changeBuilder, kind);
-  }
-
-  Future<void> _addProposal_flutterWrapWidgets() async {
-    var selectionRange = SourceRange(selectionOffset, selectionLength);
-    var analyzer = SelectionAnalyzer(selectionRange);
-    context.resolveResult.unit.accept(analyzer);
-
-    var widgetExpressions = <Expression>[];
-    if (analyzer.hasSelectedNodes) {
-      for (var selectedNode in analyzer.selectedNodes) {
-        if (!flutter.isWidgetExpression(selectedNode)) {
-          return;
-        }
-        widgetExpressions.add(selectedNode);
-      }
-    } else {
-      var widget = flutter.identifyWidgetExpression(analyzer.coveringNode);
-      if (widget != null) {
-        widgetExpressions.add(widget);
-      }
-    }
-    if (widgetExpressions.isEmpty) {
-      return;
-    }
-
-    var firstWidget = widgetExpressions.first;
-    var lastWidget = widgetExpressions.last;
-    var selectedRange = range.startEnd(firstWidget, lastWidget);
-    var src = utils.getRangeText(selectedRange);
-
-    Future<void> addAssist(
-        {@required AssistKind kind,
-        @required String parentLibraryUri,
-        @required String parentClassName}) async {
-      var parentClassElement =
-          await sessionHelper.getClass(parentLibraryUri, parentClassName);
-      var widgetClassElement =
-          await sessionHelper.getClass(flutter.widgetsUri, 'Widget');
-      if (parentClassElement == null || widgetClassElement == null) {
-        return;
-      }
-
-      var changeBuilder = _newDartChangeBuilder();
-      await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
-        builder.addReplacement(selectedRange, (DartEditBuilder builder) {
-          builder.writeReference(parentClassElement);
-          builder.write('(');
-
-          var indentOld = utils.getLinePrefix(firstWidget.offset);
-          var indentNew1 = indentOld + utils.getIndent(1);
-          var indentNew2 = indentOld + utils.getIndent(2);
-
-          builder.write(eol);
-          builder.write(indentNew1);
-          builder.write('children: [');
-          builder.write(eol);
-
-          var newSrc = _replaceSourceIndent(src, indentOld, indentNew2);
-          builder.write(indentNew2);
-          builder.write(newSrc);
-
-          builder.write(',');
-          builder.write(eol);
-
-          builder.write(indentNew1);
-          builder.write('],');
-          builder.write(eol);
-
-          builder.write(indentOld);
-          builder.write(')');
-        });
-      });
-      _addAssistFromBuilder(changeBuilder, kind);
-    }
-
-    await addAssist(
-        kind: DartAssistKind.FLUTTER_WRAP_COLUMN,
-        parentLibraryUri: flutter.widgetsUri,
-        parentClassName: 'Column');
-    await addAssist(
-        kind: DartAssistKind.FLUTTER_WRAP_ROW,
-        parentLibraryUri: flutter.widgetsUri,
-        parentClassName: 'Row');
-  }
-
-  Future<void> _addProposal_importAddShow() async {
-    // prepare ImportDirective
-    var importDirective = node.thisOrAncestorOfType<ImportDirective>();
-    if (importDirective == null) {
-      return;
-    }
-    // there should be no existing combinators
-    if (importDirective.combinators.isNotEmpty) {
-      return;
-    }
-    // prepare whole import namespace
-    ImportElement importElement = importDirective.element;
-    if (importElement == null) {
-      return;
-    }
-    var namespace = getImportNamespace(importElement);
-    // prepare names of referenced elements (from this import)
-    var referencedNames = SplayTreeSet<String>();
-    var visitor = _SimpleIdentifierRecursiveAstVisitor((SimpleIdentifier node) {
-      var element = node.staticElement;
-      if (element != null &&
-          (namespace[node.name] == element ||
-              (node.name != element.name &&
-                  namespace[element.name] == element))) {
-        referencedNames.add(element.displayName);
-      }
-    });
-    context.resolveResult.unit.accept(visitor);
-    // ignore if unused
-    if (referencedNames.isEmpty) {
-      return;
-    }
-    var changeBuilder = _newDartChangeBuilder();
-    await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
-      var showCombinator = ' show ${referencedNames.join(', ')}';
-      builder.addSimpleInsertion(importDirective.end - 1, showCombinator);
-    });
-    _addAssistFromBuilder(changeBuilder, DartAssistKind.IMPORT_ADD_SHOW);
-  }
-
-  Future<void> _addProposal_introduceLocalTestedType() async {
-    var node = this.node;
-    if (node is IfStatement) {
-      node = (node as IfStatement).condition;
-    } else if (node is WhileStatement) {
-      node = (node as WhileStatement).condition;
-    }
-    // prepare IsExpression
-    if (node is! IsExpression) {
-      return;
-    }
-    IsExpression isExpression = node;
-    var castType = isExpression.type.type;
-    var castTypeCode = _getNodeText(isExpression.type);
-    // prepare environment
-    var indent = utils.getIndent(1);
-    String prefix;
-    Block targetBlock;
-    {
-      var statement = node.thisOrAncestorOfType<Statement>();
-      if (statement is IfStatement && statement.thenStatement is Block) {
-        targetBlock = statement.thenStatement;
-      } else if (statement is WhileStatement && statement.body is Block) {
-        targetBlock = statement.body;
-      } else {
-        return;
-      }
-      prefix = utils.getNodePrefix(statement);
-    }
-    // prepare location
-    int offset;
-    String statementPrefix;
-    if (isExpression.notOperator == null) {
-      offset = targetBlock.leftBracket.end;
-      statementPrefix = indent;
-    } else {
-      offset = targetBlock.rightBracket.end;
-      statementPrefix = '';
-    }
-    // prepare excluded names
-    var excluded = <String>{};
-    var scopedNameFinder = ScopedNameFinder(offset);
-    isExpression.accept(scopedNameFinder);
-    excluded.addAll(scopedNameFinder.locals.keys.toSet());
-    // name(s)
-    var suggestions =
-        getVariableNameSuggestionsForExpression(castType, null, excluded);
-
-    if (suggestions.isNotEmpty) {
-      var changeBuilder = _newDartChangeBuilder();
-      await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
-        builder.addInsertion(offset, (DartEditBuilder builder) {
-          builder.write(eol + prefix + statementPrefix);
-          builder.write(castTypeCode);
-          builder.write(' ');
-          builder.addSimpleLinkedEdit('NAME', suggestions[0],
-              kind: LinkedEditSuggestionKind.VARIABLE,
-              suggestions: suggestions);
-          builder.write(' = ');
-          builder.write(_getNodeText(isExpression.expression));
-          builder.write(';');
-          builder.selectHere();
-        });
-      });
-      _addAssistFromBuilder(
-          changeBuilder, DartAssistKind.INTRODUCE_LOCAL_CAST_TYPE);
-    }
-  }
-
-  Future<void> _addProposal_invertIf() async {
-    if (node is! IfStatement) {
-      return;
-    }
-    var ifStatement = node as IfStatement;
-    var condition = ifStatement.condition;
-    // should have both "then" and "else"
-    var thenStatement = ifStatement.thenStatement;
-    var elseStatement = ifStatement.elseStatement;
-    if (thenStatement == null || elseStatement == null) {
-      return;
-    }
-    // prepare source
-    var invertedCondition = utils.invertCondition(condition);
-    var thenSource = _getNodeText(thenStatement);
-    var elseSource = _getNodeText(elseStatement);
-
-    var changeBuilder = _newDartChangeBuilder();
-    await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
-      builder.addSimpleReplacement(range.node(condition), invertedCondition);
-      builder.addSimpleReplacement(range.node(thenStatement), elseSource);
-      builder.addSimpleReplacement(range.node(elseStatement), thenSource);
-    });
-    _addAssistFromBuilder(changeBuilder, DartAssistKind.INVERT_IF_STATEMENT);
-  }
-
-  Future<void> _addProposal_joinIfStatementInner() async {
-    // climb up condition to the (supposedly) "if" statement
-    var node = this.node;
-    while (node is Expression) {
-      node = node.parent;
-    }
-    // prepare target "if" statement
-    if (node is! IfStatement) {
-      return;
-    }
-    var targetIfStatement = node as IfStatement;
-    if (targetIfStatement.elseStatement != null) {
-      return;
-    }
-    // prepare inner "if" statement
-    var targetThenStatement = targetIfStatement.thenStatement;
-    var innerStatement = getSingleStatement(targetThenStatement);
-    if (innerStatement is! IfStatement) {
-      return;
-    }
-    var innerIfStatement = innerStatement as IfStatement;
-    if (innerIfStatement.elseStatement != null) {
-      return;
-    }
-    // prepare environment
-    var prefix = utils.getNodePrefix(targetIfStatement);
-    // merge conditions
-    String condition;
-    {
-      var targetCondition = targetIfStatement.condition;
-      var innerCondition = innerIfStatement.condition;
-      var targetConditionSource = _getNodeText(targetCondition);
-      var innerConditionSource = _getNodeText(innerCondition);
-      if (_shouldWrapParenthesisBeforeAnd(targetCondition)) {
-        targetConditionSource = '($targetConditionSource)';
-      }
-      if (_shouldWrapParenthesisBeforeAnd(innerCondition)) {
-        innerConditionSource = '($innerConditionSource)';
-      }
-      condition = '$targetConditionSource && $innerConditionSource';
-    }
-    // replace target "if" statement
-    var innerThenStatement = innerIfStatement.thenStatement;
-    var innerThenStatements = getStatements(innerThenStatement);
-    var lineRanges = utils.getLinesRangeStatements(innerThenStatements);
-    var oldSource = utils.getRangeText(lineRanges);
-    var newSource = utils.indentSourceLeftRight(oldSource);
-
-    var changeBuilder = _newDartChangeBuilder();
-    await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
-      builder.addSimpleReplacement(range.node(targetIfStatement),
-          'if ($condition) {$eol$newSource$prefix}');
-    });
-    _addAssistFromBuilder(changeBuilder, DartAssistKind.JOIN_IF_WITH_INNER);
-  }
-
-  Future<void> _addProposal_joinIfStatementOuter() async {
-    // climb up condition to the (supposedly) "if" statement
-    var node = this.node;
-    while (node is Expression) {
-      node = node.parent;
-    }
-    // prepare target "if" statement
-    if (node is! IfStatement) {
-      return;
-    }
-    var targetIfStatement = node as IfStatement;
-    if (targetIfStatement.elseStatement != null) {
-      return;
-    }
-    // prepare outer "if" statement
-    var parent = targetIfStatement.parent;
-    if (parent is Block) {
-      if ((parent as Block).statements.length != 1) {
-        return;
-      }
-      parent = parent.parent;
-    }
-    if (parent is! IfStatement) {
-      return;
-    }
-    var outerIfStatement = parent as IfStatement;
-    if (outerIfStatement.elseStatement != null) {
-      return;
-    }
-    // prepare environment
-    var prefix = utils.getNodePrefix(outerIfStatement);
-    // merge conditions
-    var targetCondition = targetIfStatement.condition;
-    var outerCondition = outerIfStatement.condition;
-    var targetConditionSource = _getNodeText(targetCondition);
-    var outerConditionSource = _getNodeText(outerCondition);
-    if (_shouldWrapParenthesisBeforeAnd(targetCondition)) {
-      targetConditionSource = '($targetConditionSource)';
-    }
-    if (_shouldWrapParenthesisBeforeAnd(outerCondition)) {
-      outerConditionSource = '($outerConditionSource)';
-    }
-    var condition = '$outerConditionSource && $targetConditionSource';
-    // replace outer "if" statement
-    var targetThenStatement = targetIfStatement.thenStatement;
-    var targetThenStatements = getStatements(targetThenStatement);
-    var lineRanges = utils.getLinesRangeStatements(targetThenStatements);
-    var oldSource = utils.getRangeText(lineRanges);
-    var newSource = utils.indentSourceLeftRight(oldSource);
-
-    var changeBuilder = _newDartChangeBuilder();
-    await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
-      builder.addSimpleReplacement(range.node(outerIfStatement),
-          'if ($condition) {$eol$newSource$prefix}');
-    });
-    _addAssistFromBuilder(changeBuilder, DartAssistKind.JOIN_IF_WITH_OUTER);
-  }
-
-  Future<void> _addProposal_joinVariableDeclaration_onAssignment() async {
-    // check that node is LHS in assignment
-    if (node is SimpleIdentifier &&
-        node.parent is AssignmentExpression &&
-        (node.parent as AssignmentExpression).leftHandSide == node &&
-        node.parent.parent is ExpressionStatement) {
-    } else {
-      return;
-    }
-    var assignExpression = node.parent as AssignmentExpression;
-    // check that binary expression is assignment
-    if (assignExpression.operator.type != TokenType.EQ) {
-      return;
-    }
-    // prepare "declaration" statement
-    var element = (node as SimpleIdentifier).staticElement;
-    if (element == null) {
-      return;
-    }
-    var declOffset = element.nameOffset;
-    var unit = context.resolveResult.unit;
-    var declNode = NodeLocator(declOffset).searchWithin(unit);
-    if (declNode != null &&
-        declNode.parent is VariableDeclaration &&
-        (declNode.parent as VariableDeclaration).name == declNode &&
-        declNode.parent.parent is VariableDeclarationList &&
-        declNode.parent.parent.parent is VariableDeclarationStatement) {
-    } else {
-      return;
-    }
-    var decl = declNode.parent as VariableDeclaration;
-    var declStatement = decl.parent.parent as VariableDeclarationStatement;
-    // may be has initializer
-    if (decl.initializer != null) {
-      return;
-    }
-    // check that "declaration" statement declared only one variable
-    if (declStatement.variables.variables.length != 1) {
-      return;
-    }
-    // check that the "declaration" and "assignment" statements are
-    // parts of the same Block
-    var assignStatement = node.parent.parent as ExpressionStatement;
-    if (assignStatement.parent is Block &&
-        assignStatement.parent == declStatement.parent) {
-    } else {
-      return;
-    }
-    var block = assignStatement.parent as Block;
-    // check that "declaration" and "assignment" statements are adjacent
-    List<Statement> statements = block.statements;
-    if (statements.indexOf(assignStatement) ==
-        statements.indexOf(declStatement) + 1) {
-    } else {
-      return;
-    }
-
-    var changeBuilder = _newDartChangeBuilder();
-    await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
-      builder.addSimpleReplacement(
-          range.endStart(declNode, assignExpression.operator), ' ');
-    });
-    _addAssistFromBuilder(
-        changeBuilder, DartAssistKind.JOIN_VARIABLE_DECLARATION);
-  }
-
-  Future<void> _addProposal_joinVariableDeclaration_onDeclaration() async {
-    // prepare enclosing VariableDeclarationList
-    var declList = node.thisOrAncestorOfType<VariableDeclarationList>();
-    if (declList != null && declList.variables.length == 1) {
-    } else {
-      return;
-    }
-    var decl = declList.variables[0];
-    // already initialized
-    if (decl.initializer != null) {
-      return;
-    }
-    // prepare VariableDeclarationStatement in Block
-    if (declList.parent is VariableDeclarationStatement &&
-        declList.parent.parent is Block) {
-    } else {
-      return;
-    }
-    var declStatement = declList.parent as VariableDeclarationStatement;
-    var block = declStatement.parent as Block;
-    List<Statement> statements = block.statements;
-    // prepare assignment
-    AssignmentExpression assignExpression;
-    {
-      // declaration should not be last Statement
-      var declIndex = statements.indexOf(declStatement);
-      if (declIndex < statements.length - 1) {
-      } else {
-        return;
-      }
-      // next Statement should be assignment
-      var assignStatement = statements[declIndex + 1];
-      if (assignStatement is ExpressionStatement) {
-      } else {
-        return;
-      }
-      var expressionStatement = assignStatement as ExpressionStatement;
-      // expression should be assignment
-      if (expressionStatement.expression is AssignmentExpression) {
-      } else {
-        return;
-      }
-      assignExpression = expressionStatement.expression as AssignmentExpression;
-    }
-    // check that pure assignment
-    if (assignExpression.operator.type != TokenType.EQ) {
-      return;
-    }
-
-    var changeBuilder = _newDartChangeBuilder();
-    await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
-      builder.addSimpleReplacement(
-          range.endStart(decl.name, assignExpression.operator), ' ');
-    });
-    _addAssistFromBuilder(
-        changeBuilder, DartAssistKind.JOIN_VARIABLE_DECLARATION);
-  }
-
-  Future<void> _addProposal_reparentFlutterList() async {
-    if (node is! ListLiteral) {
-      return;
-    }
-    if ((node as ListLiteral).elements.any((CollectionElement exp) =>
-        !(exp is InstanceCreationExpression &&
-            flutter.isWidgetCreation(exp)))) {
-      return;
-    }
-    var literalSrc = utils.getNodeText(node);
-    var newlineIdx = literalSrc.lastIndexOf(eol);
-    if (newlineIdx < 0 || newlineIdx == literalSrc.length - 1) {
-      return; // Lists need to be in multi-line format already.
-    }
-    var indentOld = utils.getLinePrefix(node.offset + 1 + newlineIdx);
-    var indentArg = '$indentOld${utils.getIndent(1)}';
-    var indentList = '$indentOld${utils.getIndent(2)}';
-
-    var changeBuilder = _newDartChangeBuilder();
-    await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
-      builder.addReplacement(range.node(node), (DartEditBuilder builder) {
-        builder.write('[');
-        builder.write(eol);
-        builder.write(indentArg);
-        builder.addSimpleLinkedEdit('WIDGET', 'widget');
-        builder.write('(');
-        builder.write(eol);
-        builder.write(indentList);
-        // Linked editing not needed since arg is always a list.
-        builder.write('children: ');
-        builder.write(literalSrc.replaceAll(
-            RegExp('^$indentOld', multiLine: true), '$indentList'));
-        builder.write(',');
-        builder.write(eol);
-        builder.write(indentArg);
-        builder.write('),');
-        builder.write(eol);
-        builder.write(indentOld);
-        builder.write(']');
-      });
-    });
-    _addAssistFromBuilder(changeBuilder, DartAssistKind.FLUTTER_WRAP_GENERIC);
-  }
-
-  Future<void> _addProposal_replaceConditionalWithIfElse() async {
-    ConditionalExpression conditional;
-    // may be on Statement with Conditional
-    var statement = node.thisOrAncestorOfType<Statement>();
-    if (statement == null) {
-      return;
-    }
-    // variable declaration
-    var inVariable = false;
-    if (statement is VariableDeclarationStatement) {
-      var variableStatement = statement;
-      for (var variable in variableStatement.variables.variables) {
-        if (variable.initializer is ConditionalExpression) {
-          conditional = variable.initializer as ConditionalExpression;
-          inVariable = true;
-          break;
-        }
-      }
-    }
-    // assignment
-    var inAssignment = false;
-    if (statement is ExpressionStatement) {
-      var exprStmt = statement;
-      if (exprStmt.expression is AssignmentExpression) {
-        var assignment = exprStmt.expression as AssignmentExpression;
-        if (assignment.operator.type == TokenType.EQ &&
-            assignment.rightHandSide is ConditionalExpression) {
-          conditional = assignment.rightHandSide as ConditionalExpression;
-          inAssignment = true;
-        }
-      }
-    }
-    // return
-    var inReturn = false;
-    if (statement is ReturnStatement) {
-      var returnStatement = statement;
-      if (returnStatement.expression is ConditionalExpression) {
-        conditional = returnStatement.expression as ConditionalExpression;
-        inReturn = true;
-      }
-    }
-    // prepare environment
-    var indent = utils.getIndent(1);
-    var prefix = utils.getNodePrefix(statement);
-
-    if (inVariable || inAssignment || inReturn) {
-      var changeBuilder = _newDartChangeBuilder();
-      await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
-        // Type v = Conditional;
-        if (inVariable) {
-          var variable = conditional.parent as VariableDeclaration;
-          builder.addDeletion(range.endEnd(variable.name, conditional));
-          var conditionSrc = _getNodeText(conditional.condition);
-          var thenSrc = _getNodeText(conditional.thenExpression);
-          var elseSrc = _getNodeText(conditional.elseExpression);
-          var name = variable.name.name;
-          var src = eol;
-          src += prefix + 'if ($conditionSrc) {' + eol;
-          src += prefix + indent + '$name = $thenSrc;' + eol;
-          src += prefix + '} else {' + eol;
-          src += prefix + indent + '$name = $elseSrc;' + eol;
-          src += prefix + '}';
-          builder.addSimpleReplacement(range.endLength(statement, 0), src);
-        }
-        // v = Conditional;
-        if (inAssignment) {
-          var assignment = conditional.parent as AssignmentExpression;
-          var leftSide = assignment.leftHandSide;
-          var conditionSrc = _getNodeText(conditional.condition);
-          var thenSrc = _getNodeText(conditional.thenExpression);
-          var elseSrc = _getNodeText(conditional.elseExpression);
-          var name = _getNodeText(leftSide);
-          var src = '';
-          src += 'if ($conditionSrc) {' + eol;
-          src += prefix + indent + '$name = $thenSrc;' + eol;
-          src += prefix + '} else {' + eol;
-          src += prefix + indent + '$name = $elseSrc;' + eol;
-          src += prefix + '}';
-          builder.addSimpleReplacement(range.node(statement), src);
-        }
-        // return Conditional;
-        if (inReturn) {
-          var conditionSrc = _getNodeText(conditional.condition);
-          var thenSrc = _getNodeText(conditional.thenExpression);
-          var elseSrc = _getNodeText(conditional.elseExpression);
-          var src = '';
-          src += 'if ($conditionSrc) {' + eol;
-          src += prefix + indent + 'return $thenSrc;' + eol;
-          src += prefix + '} else {' + eol;
-          src += prefix + indent + 'return $elseSrc;' + eol;
-          src += prefix + '}';
-          builder.addSimpleReplacement(range.node(statement), src);
-        }
-      });
-      _addAssistFromBuilder(
-          changeBuilder, DartAssistKind.REPLACE_CONDITIONAL_WITH_IF_ELSE);
-    }
-  }
-
-  Future<void> _addProposal_replaceIfElseWithConditional() async {
-    // should be "if"
-    if (node is! IfStatement) {
-      return;
-    }
-    var ifStatement = node as IfStatement;
-    // single then/else statements
-    var thenStatement = getSingleStatement(ifStatement.thenStatement);
-    var elseStatement = getSingleStatement(ifStatement.elseStatement);
-    if (thenStatement == null || elseStatement == null) {
-      return;
-    }
-    Expression thenExpression;
-    Expression elseExpression;
-    var hasReturnStatements = false;
-    if (thenStatement is ReturnStatement && elseStatement is ReturnStatement) {
-      hasReturnStatements = true;
-      thenExpression = thenStatement.expression;
-      elseExpression = elseStatement.expression;
-    }
-    var hasExpressionStatements = false;
-    if (thenStatement is ExpressionStatement &&
-        elseStatement is ExpressionStatement) {
-      if (thenStatement.expression is AssignmentExpression &&
-          elseStatement.expression is AssignmentExpression) {
-        hasExpressionStatements = true;
-        thenExpression = thenStatement.expression;
-        elseExpression = elseStatement.expression;
-      }
-    }
-
-    if (hasReturnStatements || hasExpressionStatements) {
-      var changeBuilder = _newDartChangeBuilder();
-      await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
-        // returns
-        if (hasReturnStatements) {
-          var conditionSrc = _getNodeText(ifStatement.condition);
-          var theSrc = _getNodeText(thenExpression);
-          var elseSrc = _getNodeText(elseExpression);
-          builder.addSimpleReplacement(range.node(ifStatement),
-              'return $conditionSrc ? $theSrc : $elseSrc;');
-        }
-        // assignments -> v = Conditional;
-        if (hasExpressionStatements) {
-          AssignmentExpression thenAssignment = thenExpression;
-          AssignmentExpression elseAssignment = elseExpression;
-          var thenTarget = _getNodeText(thenAssignment.leftHandSide);
-          var elseTarget = _getNodeText(elseAssignment.leftHandSide);
-          if (thenAssignment.operator.type == TokenType.EQ &&
-              elseAssignment.operator.type == TokenType.EQ &&
-              thenTarget == elseTarget) {
-            var conditionSrc = _getNodeText(ifStatement.condition);
-            var theSrc = _getNodeText(thenAssignment.rightHandSide);
-            var elseSrc = _getNodeText(elseAssignment.rightHandSide);
-            builder.addSimpleReplacement(range.node(ifStatement),
-                '$thenTarget = $conditionSrc ? $theSrc : $elseSrc;');
-          }
-        }
-      });
-      _addAssistFromBuilder(
-          changeBuilder, DartAssistKind.REPLACE_IF_ELSE_WITH_CONDITIONAL);
-    }
-  }
-
-  Future<void> _addProposal_splitVariableDeclaration() async {
-    var variableList = node?.thisOrAncestorOfType<VariableDeclarationList>();
-
-    // Must be a local variable declaration.
-    if (variableList?.parent is! VariableDeclarationStatement) {
-      return;
-    }
-    VariableDeclarationStatement statement = variableList.parent;
-
-    // Cannot be `const` or `final`.
-    var keywordKind = variableList.keyword?.keyword;
-    if (keywordKind == Keyword.CONST || keywordKind == Keyword.FINAL) {
-      return;
-    }
-
-    var variables = variableList.variables;
-    if (variables.length != 1) {
-      return;
-    }
-
-    // The caret must be between the type and the variable name.
-    var variable = variables[0];
-    if (!range.startEnd(statement, variable.name).contains(selectionOffset)) {
-      return;
-    }
-
-    // The variable must have an initializer.
-    if (variable.initializer == null) {
-      return;
-    }
-
-    var changeBuilder = _newDartChangeBuilder();
-    await changeBuilder.addFileEdit(file, (builder) {
-      if (variableList.type == null) {
-        final type = variable.declaredElement.type;
-        if (!type.isDynamic) {
-          builder.addReplacement(range.token(variableList.keyword), (builder) {
-            builder.writeType(type);
-          });
-        }
-      }
-
-      var indent = utils.getNodePrefix(statement);
-      var name = variable.name.name;
-      builder.addSimpleInsertion(variable.name.end, ';' + eol + indent + name);
-    });
-    _addAssistFromBuilder(
-        changeBuilder, DartAssistKind.SPLIT_VARIABLE_DECLARATION);
-  }
-
-  Future<void> _addProposal_surroundWith() async {
-    // prepare selected statements
-    List<Statement> selectedStatements;
-    {
-      var selectionAnalyzer = StatementAnalyzer(
-          context.resolveResult, SourceRange(selectionOffset, selectionLength));
-      selectionAnalyzer.analyze();
-      var selectedNodes = selectionAnalyzer.selectedNodes;
-      // convert nodes to statements
-      selectedStatements = [];
-      for (var selectedNode in selectedNodes) {
-        if (selectedNode is Statement) {
-          selectedStatements.add(selectedNode);
-        }
-      }
-      // we want only statements in blocks
-      for (var statement in selectedStatements) {
-        if (statement.parent is! Block) {
-          return;
-        }
-      }
-      // we want only statements
-      if (selectedStatements.isEmpty ||
-          selectedStatements.length != selectedNodes.length) {
-        return;
-      }
-    }
-    // prepare statement information
-    var firstStatement = selectedStatements[0];
-    var statementsRange = utils.getLinesRangeStatements(selectedStatements);
-    // prepare environment
-    var indentOld = utils.getNodePrefix(firstStatement);
-    var indentNew = '$indentOld${utils.getIndent(1)}';
-    var indentedCode =
-        utils.replaceSourceRangeIndent(statementsRange, indentOld, indentNew);
-    // "block"
-    {
-      var changeBuilder = _newDartChangeBuilder();
-      await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
-        builder.addSimpleInsertion(statementsRange.offset, '$indentOld{$eol');
-        builder.addSimpleReplacement(
-            statementsRange,
-            utils.replaceSourceRangeIndent(
-                statementsRange, indentOld, indentNew));
-        builder.addSimpleInsertion(statementsRange.end, '$indentOld}$eol');
-      });
-      _addAssistFromBuilder(changeBuilder, DartAssistKind.SURROUND_WITH_BLOCK);
-    }
-    // "if"
-    {
-      var changeBuilder = _newDartChangeBuilder();
-      await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
-        builder.addReplacement(statementsRange, (DartEditBuilder builder) {
-          builder.write(indentOld);
-          builder.write('if (');
-          builder.addSimpleLinkedEdit('CONDITION', 'condition');
-          builder.write(') {');
-          builder.write(eol);
-          builder.write(indentedCode);
-          builder.write(indentOld);
-          builder.write('}');
-          builder.selectHere();
-          builder.write(eol);
-        });
-      });
-      _addAssistFromBuilder(changeBuilder, DartAssistKind.SURROUND_WITH_IF);
-    }
-    // "while"
-    {
-      var changeBuilder = _newDartChangeBuilder();
-      await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
-        builder.addReplacement(statementsRange, (DartEditBuilder builder) {
-          builder.write(indentOld);
-          builder.write('while (');
-          builder.addSimpleLinkedEdit('CONDITION', 'condition');
-          builder.write(') {');
-          builder.write(eol);
-          builder.write(indentedCode);
-          builder.write(indentOld);
-          builder.write('}');
-          builder.selectHere();
-          builder.write(eol);
-        });
-      });
-      _addAssistFromBuilder(changeBuilder, DartAssistKind.SURROUND_WITH_WHILE);
-    }
-    // "for-in"
-    {
-      var changeBuilder = _newDartChangeBuilder();
-      await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
-        builder.addReplacement(statementsRange, (DartEditBuilder builder) {
-          builder.write(indentOld);
-          builder.write('for (var ');
-          builder.addSimpleLinkedEdit('NAME', 'item');
-          builder.write(' in ');
-          builder.addSimpleLinkedEdit('ITERABLE', 'iterable');
-          builder.write(') {');
-          builder.write(eol);
-          builder.write(indentedCode);
-          builder.write(indentOld);
-          builder.write('}');
-          builder.selectHere();
-          builder.write(eol);
-        });
-      });
-      _addAssistFromBuilder(changeBuilder, DartAssistKind.SURROUND_WITH_FOR_IN);
-    }
-    // "for"
-    {
-      var changeBuilder = _newDartChangeBuilder();
-      await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
-        builder.addReplacement(statementsRange, (DartEditBuilder builder) {
-          builder.write(indentOld);
-          builder.write('for (var ');
-          builder.addSimpleLinkedEdit('VAR', 'v');
-          builder.write(' = ');
-          builder.addSimpleLinkedEdit('INIT', 'init');
-          builder.write('; ');
-          builder.addSimpleLinkedEdit('CONDITION', 'condition');
-          builder.write('; ');
-          builder.addSimpleLinkedEdit('INCREMENT', 'increment');
-          builder.write(') {');
-          builder.write(eol);
-          builder.write(indentedCode);
-          builder.write(indentOld);
-          builder.write('}');
-          builder.selectHere();
-          builder.write(eol);
-        });
-      });
-      _addAssistFromBuilder(changeBuilder, DartAssistKind.SURROUND_WITH_FOR);
-    }
-    // "do-while"
-    {
-      var changeBuilder = _newDartChangeBuilder();
-      await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
-        builder.addReplacement(statementsRange, (DartEditBuilder builder) {
-          builder.write(indentOld);
-          builder.write('do {');
-          builder.write(eol);
-          builder.write(indentedCode);
-          builder.write(indentOld);
-          builder.write('} while (');
-          builder.addSimpleLinkedEdit('CONDITION', 'condition');
-          builder.write(');');
-          builder.selectHere();
-          builder.write(eol);
-        });
-      });
-      _addAssistFromBuilder(
-          changeBuilder, DartAssistKind.SURROUND_WITH_DO_WHILE);
-    }
-    // "try-catch"
-    {
-      var changeBuilder = _newDartChangeBuilder();
-      await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
-        builder.addReplacement(statementsRange, (DartEditBuilder builder) {
-          builder.write(indentOld);
-          builder.write('try {');
-          builder.write(eol);
-          builder.write(indentedCode);
-          builder.write(indentOld);
-          builder.write('} on ');
-          builder.addSimpleLinkedEdit('EXCEPTION_TYPE', 'Exception');
-          builder.write(' catch (');
-          builder.addSimpleLinkedEdit('EXCEPTION_VAR', 'e');
-          builder.write(') {');
-          builder.write(eol);
-          //
-          builder.write(indentNew);
-          builder.addSimpleLinkedEdit('CATCH', '// TODO');
-          builder.selectHere();
-          builder.write(eol);
-          //
-          builder.write(indentOld);
-          builder.write('}');
-          builder.write(eol);
-        });
-      });
-      _addAssistFromBuilder(
-          changeBuilder, DartAssistKind.SURROUND_WITH_TRY_CATCH);
-    }
-    // "try-finally"
-    {
-      var changeBuilder = _newDartChangeBuilder();
-      await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
-        builder.addReplacement(statementsRange, (DartEditBuilder builder) {
-          builder.write(indentOld);
-          builder.write('try {');
-          builder.write(eol);
-          //
-          builder.write(indentedCode);
-          //
-          builder.write(indentOld);
-          builder.write('} finally {');
-          builder.write(eol);
-          //
-          builder.write(indentNew);
-          builder.addSimpleLinkedEdit('FINALLY', '// TODO');
-          builder.selectHere();
-          builder.write(eol);
-          //
-          builder.write(indentOld);
-          builder.write('}');
-          builder.write(eol);
-        });
-      });
-      _addAssistFromBuilder(
-          changeBuilder, DartAssistKind.SURROUND_WITH_TRY_FINALLY);
-    }
-
-    // flutter "setState((){ .. });"
-    {
-      var classDeclaration =
-          node.parent.thisOrAncestorOfType<ClassDeclaration>();
-      if (classDeclaration != null &&
-          flutter.isState(classDeclaration.declaredElement)) {
-        final changeBuilder = _newDartChangeBuilder();
-        await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
-          builder.addReplacement(statementsRange, (DartEditBuilder builder) {
-            builder.write(indentOld);
-            builder.writeln('setState(() {');
-            builder.write(indentedCode);
-            builder.write(indentOld);
-            builder.selectHere();
-            builder.writeln('});');
-          });
-        });
-        _addAssistFromBuilder(
-            changeBuilder, DartAssistKind.SURROUND_WITH_SET_STATE);
+    for (var multiGenerator in multiGenerators) {
+      var multiProducer = multiGenerator();
+      multiProducer.configure(context);
+      for (var producer in multiProducer.producers) {
+        var builder = DartChangeBuilderImpl.forWorkspace(context.workspace);
+        producer.configure(context);
+        await producer.compute(builder);
+        _addAssistFromBuilder(builder, producer.assistKind,
+            args: producer.assistArguments);
       }
     }
   }
@@ -2334,141 +284,6 @@
     return false;
   }
 
-  void _convertFlutterChildToChildren(
-      NamedExpression namedExp,
-      String eol,
-      Function getNodeText,
-      Function getLinePrefix,
-      Function getIndent,
-      Function getText,
-      DartFileEditBuilder builder) {
-    var childArg = namedExp.expression;
-    var childLoc = namedExp.offset + 'child'.length;
-    builder.addSimpleInsertion(childLoc, 'ren');
-    var listLoc = childArg.offset;
-    String childArgSrc = getNodeText(childArg);
-    if (!childArgSrc.contains(eol)) {
-      builder.addSimpleInsertion(listLoc, '[');
-      builder.addSimpleInsertion(listLoc + childArg.length, ']');
-    } else {
-      var newlineLoc = childArgSrc.lastIndexOf(eol);
-      if (newlineLoc == childArgSrc.length) {
-        newlineLoc -= 1;
-      }
-      String indentOld = getLinePrefix(childArg.offset + 1 + newlineLoc);
-      var indentNew = '$indentOld${getIndent(1)}';
-      // The separator includes 'child:' but that has no newlines.
-      String separator =
-          getText(namedExp.offset, childArg.offset - namedExp.offset);
-      var prefix = separator.contains(eol) ? '' : '$eol$indentNew';
-      if (prefix.isEmpty) {
-        builder.addSimpleInsertion(namedExp.offset + 'child:'.length, ' [');
-        var argOffset = childArg.offset;
-        builder
-            .addDeletion(range.startOffsetEndOffset(argOffset - 2, argOffset));
-      } else {
-        builder.addSimpleInsertion(listLoc, '[');
-      }
-      var newChildArgSrc =
-          _replaceSourceIndent(childArgSrc, indentOld, indentNew);
-      newChildArgSrc = '$prefix$newChildArgSrc,$eol$indentOld]';
-      builder.addSimpleReplacement(range.node(childArg), newChildArgSrc);
-    }
-  }
-
-  /// Returns the text of the given node in the unit.
-  String _getNodeText(AstNode node) {
-    return utils.getNodeText(node);
-  }
-
-  /// Returns the text of the given range in the unit.
-  String _getRangeText(SourceRange range) {
-    return utils.getRangeText(range);
-  }
-
-  DartChangeBuilder _newDartChangeBuilder() {
-    return DartChangeBuilderImpl.forWorkspace(context.workspace);
-  }
-
-  Future<void> _swapParentAndChild(InstanceCreationExpression parent,
-      InstanceCreationExpression child, AssistKind kind) async {
-    // The child must have its own child.
-    if (flutter.findChildArgument(child) == null) {
-      return;
-    }
-
-    var changeBuilder = _newDartChangeBuilder();
-    await changeBuilder.addFileEdit(file, (builder) {
-      builder.addReplacement(range.node(parent), (builder) {
-        var childArgs = child.argumentList;
-        var parentArgs = parent.argumentList;
-        var childText = _getRangeText(range.startStart(child, childArgs));
-        var parentText = _getRangeText(range.startStart(parent, parentArgs));
-
-        var parentIndent = utils.getLinePrefix(parent.offset);
-        var childIndent = parentIndent + '  ';
-
-        // Write the beginning of the child.
-        builder.write(childText);
-        builder.writeln('(');
-
-        // Write all the arguments of the parent.
-        // Don't write the "child".
-        Expression stableChild;
-        for (var argument in childArgs.arguments) {
-          if (flutter.isChildArgument(argument)) {
-            stableChild = argument;
-          } else {
-            var text = _getNodeText(argument);
-            text = _replaceSourceIndent(text, childIndent, parentIndent);
-            builder.write(parentIndent);
-            builder.write('  ');
-            builder.write(text);
-            builder.writeln(',');
-          }
-        }
-
-        // Write the parent as a new child.
-        builder.write(parentIndent);
-        builder.write('  ');
-        builder.write('child: ');
-        builder.write(parentText);
-        builder.writeln('(');
-
-        // Write all arguments of the parent.
-        // Don't write its child.
-        for (var argument in parentArgs.arguments) {
-          if (!flutter.isChildArgument(argument)) {
-            var text = _getNodeText(argument);
-            text = _replaceSourceIndent(text, parentIndent, childIndent);
-            builder.write(childIndent);
-            builder.write('  ');
-            builder.write(text);
-            builder.writeln(',');
-          }
-        }
-
-        // Write the child of the "child" now, as the child of the "parent".
-        {
-          var text = _getNodeText(stableChild);
-          builder.write(childIndent);
-          builder.write('  ');
-          builder.write(text);
-          builder.writeln(',');
-        }
-
-        // Close the parent expression.
-        builder.write(childIndent);
-        builder.writeln('),');
-
-        // Close the child expression.
-        builder.write(parentIndent);
-        builder.write(')');
-      });
-    });
-    _addAssistFromBuilder(changeBuilder, kind);
-  }
-
   /// Create and return a map that can be used to look up the names of the lints
   /// for which a given `CorrectionProducer` will be used. This allows us to
   /// ensure that we do not also offer the change as an assist when it's already
@@ -2483,31 +298,4 @@
     }
     return map;
   }
-
-  static String _replaceSourceIndent(
-      String source, String indentOld, String indentNew) {
-    return source.replaceAll(RegExp('^$indentOld', multiLine: true), indentNew);
-  }
-
-  /// Checks if the given [Expression] should be wrapped with parenthesis when
-  /// we want to use it as operand of a logical `and` expression.
-  static bool _shouldWrapParenthesisBeforeAnd(Expression expr) {
-    if (expr is BinaryExpression) {
-      var binary = expr;
-      var precedence = binary.operator.type.precedence;
-      return precedence < TokenClass.LOGICAL_AND_OPERATOR.precedence;
-    }
-    return false;
-  }
-}
-
-class _SimpleIdentifierRecursiveAstVisitor extends RecursiveAstVisitor<void> {
-  final _SimpleIdentifierVisitor visitor;
-
-  _SimpleIdentifierRecursiveAstVisitor(this.visitor);
-
-  @override
-  void visitSimpleIdentifier(SimpleIdentifier node) {
-    visitor(node);
-  }
 }
diff --git a/pkg/analysis_server/lib/src/services/correction/base_processor.dart b/pkg/analysis_server/lib/src/services/correction/base_processor.dart
index 2e797a5..0bb0cff 100644
--- a/pkg/analysis_server/lib/src/services/correction/base_processor.dart
+++ b/pkg/analysis_server/lib/src/services/correction/base_processor.dart
@@ -8,10 +8,8 @@
 import 'package:analyzer/dart/analysis/session.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/type_provider.dart';
-import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/dart/analysis/session_helper.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
-import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
 import 'package:analyzer_plugin/utilities/change_builder/change_workspace.dart';
 import 'package:meta/meta.dart';
 
@@ -47,14 +45,6 @@
         selectionEnd = (selectionOffset ?? 0) + (selectionLength ?? 0),
         utils = CorrectionUtils(resolvedResult);
 
-  /// Returns the EOL to use for this [CompilationUnit].
-  String get eol => utils.endOfLine;
-
-  /// Return the status of known experiments.
-  ExperimentStatus get experimentStatus =>
-      (session.analysisContext.analysisOptions as AnalysisOptionsImpl)
-          .experimentStatus;
-
   @protected
   bool setupCompute() {
     final locator = NodeLocator(selectionOffset, selectionEnd);
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/abstract_producer.dart b/pkg/analysis_server/lib/src/services/correction/dart/abstract_producer.dart
index b470bf4..00a5cc6 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/abstract_producer.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/abstract_producer.dart
@@ -4,6 +4,7 @@
 
 import 'dart:math' as math;
 
+import 'package:_fe_analyzer_shared/src/scanner/token.dart';
 import 'package:analysis_server/plugin/edit/fix/fix_dart.dart';
 import 'package:analysis_server/src/services/correction/fix/dart/top_level_declarations.dart';
 import 'package:analysis_server/src/services/correction/util.dart';
@@ -462,6 +463,24 @@
     return false;
   }
 
+  /// Replace all occurrences of the [oldIndent] with the [newIndent] within the
+  /// [source].
+  String replaceSourceIndent(
+      String source, String oldIndent, String newIndent) {
+    return source.replaceAll(RegExp('^$oldIndent', multiLine: true), newIndent);
+  }
+
+  /// Return `true` if the given [expression] should be wrapped with parenthesis
+  /// when we want to use it as operand of a logical `and` expression.
+  bool shouldWrapParenthesisBeforeAnd(Expression expression) {
+    if (expression is BinaryExpression) {
+      var binary = expression;
+      var precedence = binary.operator.type.precedence;
+      return precedence < TokenClass.LOGICAL_AND_OPERATOR.precedence;
+    }
+    return false;
+  }
+
   /// Return `true` if the [name] is capitalized.
   bool _isNameOfType(String name) {
     if (name.isEmpty) {
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/add_late.dart b/pkg/analysis_server/lib/src/services/correction/dart/add_late.dart
new file mode 100644
index 0000000..c1de45b
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/add_late.dart
@@ -0,0 +1,55 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+
+class AddLate extends CorrectionProducer {
+  @override
+  FixKind get fixKind => DartFixKind.ADD_LATE;
+
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    if (!libraryElement.isNonNullableByDefault) {
+      return;
+    }
+    if (node is SimpleIdentifier &&
+        node.parent is VariableDeclaration &&
+        node.parent.parent is VariableDeclarationList) {
+      var list = node.parent.parent as VariableDeclarationList;
+      if (!list.isLate) {
+        if (list.type == null) {
+          var keyword = list.keyword;
+          if (keyword == null) {
+            await _insertAt(builder, list.variables[0].offset);
+            // TODO(brianwilkerson) Consider converting this into an assist and
+            //  expand it to support converting `var` to `late` as well as
+            //  working anywhere a non-late local variable or field is selected.
+//          } else if (keyword.type == Keyword.VAR) {
+//            builder.addFileEdit(file, (builder) {
+//              builder.addSimpleReplacement(range.token(keyword), 'late');
+//            });
+          } else if (keyword.type != Keyword.CONST) {
+            await _insertAt(builder, list.variables[0].offset);
+          }
+        } else {
+          await _insertAt(builder, list.type.offset);
+        }
+      }
+    }
+  }
+
+  void _insertAt(DartChangeBuilder builder, int offset) async {
+    await builder.addFileEdit(file, (builder) {
+      builder.addSimpleInsertion(offset, 'late ');
+    });
+  }
+
+  /// Return an instance of this class. Used as a tear-off in `FixProcessor`.
+  static AddLate newInstance() => AddLate();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/add_not_null_assert.dart b/pkg/analysis_server/lib/src/services/correction/dart/add_not_null_assert.dart
new file mode 100644
index 0000000..05c17eb
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/add_not_null_assert.dart
@@ -0,0 +1,73 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:math';
+
+import 'package:_fe_analyzer_shared/src/scanner/token.dart';
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+
+class AddNotNullAssert extends CorrectionProducer {
+  @override
+  AssistKind get assistKind => DartAssistKind.ADD_NOT_NULL_ASSERT;
+
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    final identifier = node;
+    if (identifier is SimpleIdentifier) {
+      if (identifier.parent is FormalParameter) {
+        final exp = identifier.parent.thisOrAncestorMatching(
+            (node) => node is FunctionExpression || node is MethodDeclaration);
+        var body;
+        if (exp is FunctionExpression) {
+          body = exp.body;
+        } else if (exp is MethodDeclaration) {
+          body = exp.body;
+        }
+        if (body is BlockFunctionBody) {
+          var blockBody = body;
+          // Check for an obvious pre-existing assertion.
+          for (var statement in blockBody.block.statements) {
+            if (statement is AssertStatement) {
+              final condition = statement.condition;
+              if (condition is BinaryExpression) {
+                final leftOperand = condition.leftOperand;
+                if (leftOperand is SimpleIdentifier) {
+                  if (leftOperand.staticElement == identifier.staticElement &&
+                      condition.operator.type == TokenType.BANG_EQ &&
+                      condition.rightOperand is NullLiteral) {
+                    return;
+                  }
+                }
+              }
+            }
+          }
+
+          await builder.addFileEdit(file, (DartFileEditBuilder builder) {
+            final id = identifier.name;
+            final prefix = utils.getNodePrefix(exp);
+            final indent = utils.getIndent(1);
+            // todo (pq): follow-ups:
+            // 1. if the end token is on the same line as the body
+            // we should add an `eol` before the assert as well.
+            // 2. also, consider asking the block for the list of statements and
+            // adding the statement to the beginning of the list, special casing
+            // when there are no statements (or when there's a single statement
+            // and the whole block is on the same line).
+            var offset = min(utils.getLineNext(blockBody.beginToken.offset),
+                blockBody.endToken.offset);
+            builder.addSimpleInsertion(
+                offset, '$prefix${indent}assert($id != null);$eol');
+          });
+        }
+      }
+    }
+  }
+
+  /// Return an instance of this class. Used as a tear-off in `AssistProcessor`.
+  static AddNotNullAssert newInstance() => AddNotNullAssert();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_into_for_index.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_into_for_index.dart
new file mode 100644
index 0000000..8859bcb
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_into_for_index.dart
@@ -0,0 +1,93 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+
+class ConvertIntoForIndex extends CorrectionProducer {
+  @override
+  AssistKind get assistKind => DartAssistKind.CONVERT_INTO_FOR_INDEX;
+
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    // find enclosing ForEachStatement
+    var forEachStatement = node.thisOrAncestorMatching(
+            (node) => node is ForStatement && node.forLoopParts is ForEachParts)
+        as ForStatement;
+    if (forEachStatement == null) {
+      return;
+    }
+    ForEachParts forEachParts = forEachStatement.forLoopParts;
+    if (selectionOffset < forEachStatement.offset ||
+        forEachStatement.rightParenthesis.end < selectionOffset) {
+      return;
+    }
+    // loop should declare variable
+    var loopVariable = forEachParts is ForEachPartsWithDeclaration
+        ? forEachParts.loopVariable
+        : null;
+    if (loopVariable == null) {
+      return;
+    }
+    // iterable should be VariableElement
+    String listName;
+    var iterable = forEachParts.iterable;
+    if (iterable is SimpleIdentifier &&
+        iterable.staticElement is VariableElement) {
+      listName = iterable.name;
+    } else {
+      return;
+    }
+    // iterable should be List
+    {
+      var iterableType = iterable.staticType;
+      if (iterableType is! InterfaceType ||
+          iterableType.element != typeProvider.listElement) {
+        return;
+      }
+    }
+    // body should be Block
+    if (forEachStatement.body is! Block) {
+      return;
+    }
+    Block body = forEachStatement.body;
+    // prepare a name for the index variable
+    String indexName;
+    {
+      var conflicts =
+          utils.findPossibleLocalVariableConflicts(forEachStatement.offset);
+      if (!conflicts.contains('i')) {
+        indexName = 'i';
+      } else if (!conflicts.contains('j')) {
+        indexName = 'j';
+      } else if (!conflicts.contains('k')) {
+        indexName = 'k';
+      } else {
+        return;
+      }
+    }
+    // prepare environment
+    var prefix = utils.getNodePrefix(forEachStatement);
+    var indent = utils.getIndent(1);
+    var firstBlockLine = utils.getLineContentEnd(body.leftBracket.end);
+    // add change
+    await builder.addFileEdit(file, (DartFileEditBuilder builder) {
+      // TODO(brianwilkerson) Create linked positions for the loop variable.
+      builder.addSimpleReplacement(
+          range.startEnd(forEachStatement, forEachStatement.rightParenthesis),
+          'for (int $indexName = 0; $indexName < $listName.length; $indexName++)');
+      builder.addSimpleInsertion(firstBlockLine,
+          '$prefix$indent$loopVariable = $listName[$indexName];$eol');
+    });
+  }
+
+  /// Return an instance of this class. Used as a tear-off in `AssistProcessor`.
+  static ConvertIntoForIndex newInstance() => ConvertIntoForIndex();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_into_is_not.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_into_is_not.dart
new file mode 100644
index 0000000..8a2fd09
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_into_is_not.dart
@@ -0,0 +1,74 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analysis_server/src/services/correction/util.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/precedence.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+
+class ConvertIntoIsNot extends CorrectionProducer {
+  @override
+  AssistKind get assistKind => DartAssistKind.CONVERT_INTO_IS_NOT;
+
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    // Find the is expression
+    var isExpression = node.thisOrAncestorOfType<IsExpression>();
+    if (isExpression == null) {
+      var node = this.node;
+      if (node is PrefixExpression) {
+        var operand = node.operand;
+        if (operand is ParenthesizedExpression &&
+            operand.expression is IsExpression) {
+          isExpression = operand.expression as IsExpression;
+        }
+      } else if (node is ParenthesizedExpression &&
+          node.expression is IsExpression) {
+        isExpression = node.expression as IsExpression;
+      }
+    }
+    if (isExpression == null) {
+      return;
+    }
+    if (isExpression.notOperator != null) {
+      return;
+    }
+    // prepare enclosing ()
+    var parent = isExpression.parent;
+    if (parent is! ParenthesizedExpression) {
+      return;
+    }
+    var parExpression = parent as ParenthesizedExpression;
+    // prepare enclosing !()
+    var parent2 = parent.parent;
+    if (parent2 is! PrefixExpression) {
+      return;
+    }
+    var prefExpression = parent2 as PrefixExpression;
+    if (prefExpression.operator.type != TokenType.BANG) {
+      return;
+    }
+
+    await builder.addFileEdit(file, (DartFileEditBuilder builder) {
+      if (getExpressionParentPrecedence(prefExpression) >=
+          Precedence.relational) {
+        builder.addDeletion(range.token(prefExpression.operator));
+      } else {
+        builder.addDeletion(
+            range.startEnd(prefExpression, parExpression.leftParenthesis));
+        builder.addDeletion(
+            range.startEnd(parExpression.rightParenthesis, prefExpression));
+      }
+      builder.addSimpleInsertion(isExpression.isOperator.end, '!');
+    });
+  }
+
+  /// Return an instance of this class. Used as a tear-off in `AssistProcessor`.
+  static ConvertIntoIsNot newInstance() => ConvertIntoIsNot();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_into_is_not_empty.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_into_is_not_empty.dart
new file mode 100644
index 0000000..2b82a89
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_into_is_not_empty.dart
@@ -0,0 +1,70 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:_fe_analyzer_shared/src/scanner/token.dart';
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analysis_server/src/services/search/hierarchy.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+
+class ConvertIntoIsNotEmpty extends CorrectionProducer {
+  @override
+  AssistKind get assistKind => DartAssistKind.CONVERT_INTO_IS_NOT_EMPTY;
+
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    // prepare "expr.isEmpty"
+    AstNode isEmptyAccess;
+    SimpleIdentifier isEmptyIdentifier;
+    if (node is SimpleIdentifier) {
+      var identifier = node as SimpleIdentifier;
+      var parent = identifier.parent;
+      // normal case (but rare)
+      if (parent is PropertyAccess) {
+        isEmptyIdentifier = parent.propertyName;
+        isEmptyAccess = parent;
+      }
+      // usual case
+      if (parent is PrefixedIdentifier) {
+        isEmptyIdentifier = parent.identifier;
+        isEmptyAccess = parent;
+      }
+    }
+    if (isEmptyIdentifier == null) {
+      return;
+    }
+    // should be "isEmpty"
+    var propertyElement = isEmptyIdentifier.staticElement;
+    if (propertyElement == null || 'isEmpty' != propertyElement.name) {
+      return;
+    }
+    // should have "isNotEmpty"
+    var propertyTarget = propertyElement.enclosingElement;
+    if (propertyTarget == null ||
+        getChildren(propertyTarget, 'isNotEmpty').isEmpty) {
+      return;
+    }
+    // should be in PrefixExpression
+    if (isEmptyAccess.parent is! PrefixExpression) {
+      return;
+    }
+    var prefixExpression = isEmptyAccess.parent as PrefixExpression;
+    // should be !
+    if (prefixExpression.operator.type != TokenType.BANG) {
+      return;
+    }
+
+    await builder.addFileEdit(file, (DartFileEditBuilder builder) {
+      builder.addDeletion(
+          range.startStart(prefixExpression, prefixExpression.operand));
+      builder.addSimpleReplacement(range.node(isEmptyIdentifier), 'isNotEmpty');
+    });
+  }
+
+  /// Return an instance of this class. Used as a tear-off in `AssistProcessor`.
+  static ConvertIntoIsNotEmpty newInstance() => ConvertIntoIsNotEmpty();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_to_field_parameter.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_field_parameter.dart
new file mode 100644
index 0000000..0223626
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_field_parameter.dart
@@ -0,0 +1,116 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+
+class ConvertToFieldParameter extends CorrectionProducer {
+  @override
+  AssistKind get assistKind => DartAssistKind.CONVERT_TO_FIELD_PARAMETER;
+
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    if (node == null) {
+      return;
+    }
+    // prepare ConstructorDeclaration
+    var constructor = node.thisOrAncestorOfType<ConstructorDeclaration>();
+    if (constructor == null) {
+      return;
+    }
+    var parameterList = constructor.parameters;
+    List<ConstructorInitializer> initializers = constructor.initializers;
+    // prepare parameter
+    SimpleFormalParameter parameter;
+    if (node.parent is SimpleFormalParameter &&
+        node.parent.parent is FormalParameterList &&
+        node.parent.parent.parent is ConstructorDeclaration) {
+      parameter = node.parent;
+    }
+    if (node is SimpleIdentifier &&
+        node.parent is ConstructorFieldInitializer) {
+      var name = (node as SimpleIdentifier).name;
+      ConstructorFieldInitializer initializer = node.parent;
+      if (initializer.expression == node) {
+        for (var formalParameter in parameterList.parameters) {
+          if (formalParameter is SimpleFormalParameter &&
+              formalParameter.identifier.name == name) {
+            parameter = formalParameter;
+          }
+        }
+      }
+    }
+    // analyze parameter
+    if (parameter != null) {
+      var parameterName = parameter.identifier.name;
+      var parameterElement = parameter.declaredElement;
+      // check number of references
+      var visitor = _ReferenceCounter(parameterElement);
+      for (var initializer in initializers) {
+        initializer.accept(visitor);
+      }
+      if (visitor.count != 1) {
+        return;
+      }
+      // find the field initializer
+      ConstructorFieldInitializer parameterInitializer;
+      for (var initializer in initializers) {
+        if (initializer is ConstructorFieldInitializer) {
+          var expression = initializer.expression;
+          if (expression is SimpleIdentifier &&
+              expression.name == parameterName) {
+            parameterInitializer = initializer;
+          }
+        }
+      }
+      if (parameterInitializer == null) {
+        return;
+      }
+      var fieldName = parameterInitializer.fieldName.name;
+
+      await builder.addFileEdit(file, (DartFileEditBuilder builder) {
+        // replace parameter
+        builder.addSimpleReplacement(range.node(parameter), 'this.$fieldName');
+        // remove initializer
+        var initializerIndex = initializers.indexOf(parameterInitializer);
+        if (initializers.length == 1) {
+          builder
+              .addDeletion(range.endEnd(parameterList, parameterInitializer));
+        } else {
+          if (initializerIndex == 0) {
+            var next = initializers[initializerIndex + 1];
+            builder.addDeletion(range.startStart(parameterInitializer, next));
+          } else {
+            var prev = initializers[initializerIndex - 1];
+            builder.addDeletion(range.endEnd(prev, parameterInitializer));
+          }
+        }
+      });
+    }
+  }
+
+  /// Return an instance of this class. Used as a tear-off in `AssistProcessor`.
+  static ConvertToFieldParameter newInstance() => ConvertToFieldParameter();
+}
+
+class _ReferenceCounter extends RecursiveAstVisitor<void> {
+  final ParameterElement parameterElement;
+
+  int count = 0;
+
+  _ReferenceCounter(this.parameterElement);
+
+  @override
+  void visitSimpleIdentifier(SimpleIdentifier node) {
+    if (node.staticElement == parameterElement) {
+      count++;
+    }
+  }
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_to_multiline_string.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_multiline_string.dart
new file mode 100644
index 0000000..bf43b16
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_multiline_string.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/source/source_range.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+
+class ConvertToMutilineString extends CorrectionProducer {
+  @override
+  AssistKind get assistKind => DartAssistKind.CONVERT_TO_MULTILINE_STRING;
+
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    var node = this.node;
+    if (node is InterpolationElement) {
+      node = (node as InterpolationElement).parent;
+    }
+    if (node is SingleStringLiteral) {
+      var literal = node;
+      if (!literal.isMultiline) {
+        await builder.addFileEdit(file, (builder) {
+          var newQuote = literal.isSingleQuoted ? "'''" : '"""';
+          builder.addReplacement(
+            SourceRange(literal.offset + (literal.isRaw ? 1 : 0), 1),
+            (builder) {
+              builder.writeln(newQuote);
+            },
+          );
+          builder.addSimpleReplacement(
+            SourceRange(literal.end - 1, 1),
+            newQuote,
+          );
+        });
+      }
+    }
+  }
+
+  /// Return an instance of this class. Used as a tear-off in `AssistProcessor`.
+  static ConvertToMutilineString newInstance() => ConvertToMutilineString();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_to_normal_parameter.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_normal_parameter.dart
new file mode 100644
index 0000000..d3c13e5
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_to_normal_parameter.dart
@@ -0,0 +1,55 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+
+class ConvertToNormalParameter extends CorrectionProducer {
+  @override
+  AssistKind get assistKind => DartAssistKind.CONVERT_TO_NORMAL_PARAMETER;
+
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    if (node is SimpleIdentifier &&
+        node.parent is FieldFormalParameter &&
+        node.parent.parent is FormalParameterList &&
+        node.parent.parent.parent is ConstructorDeclaration) {
+      ConstructorDeclaration constructor = node.parent.parent.parent;
+      FormalParameterList parameterList = node.parent.parent;
+      FieldFormalParameter parameter = node.parent;
+      var parameterElement = parameter.declaredElement;
+      var name = (node as SimpleIdentifier).name;
+      // prepare type
+      var type = parameterElement.type;
+
+      await builder.addFileEdit(file, (DartFileEditBuilder builder) {
+        // replace parameter
+        if (type.isDynamic) {
+          builder.addSimpleReplacement(range.node(parameter), name);
+        } else {
+          builder.addReplacement(range.node(parameter),
+              (DartEditBuilder builder) {
+            builder.writeType(type);
+            builder.write(' ');
+            builder.write(name);
+          });
+        }
+        // add field initializer
+        List<ConstructorInitializer> initializers = constructor.initializers;
+        if (initializers.isEmpty) {
+          builder.addSimpleInsertion(parameterList.end, ' : $name = $name');
+        } else {
+          builder.addSimpleInsertion(initializers.last.end, ', $name = $name');
+        }
+      });
+    }
+  }
+
+  /// Return an instance of this class. Used as a tear-off in `AssistProcessor`.
+  static ConvertToNormalParameter newInstance() => ConvertToNormalParameter();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/encapsulate_field.dart b/pkg/analysis_server/lib/src/services/correction/dart/encapsulate_field.dart
new file mode 100644
index 0000000..3c7106d
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/encapsulate_field.dart
@@ -0,0 +1,109 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+
+class EncapsulateField extends CorrectionProducer {
+  @override
+  AssistKind get assistKind => DartAssistKind.ENCAPSULATE_FIELD;
+
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    // find FieldDeclaration
+    var fieldDeclaration = node.thisOrAncestorOfType<FieldDeclaration>();
+    if (fieldDeclaration == null) {
+      return;
+    }
+    // not interesting for static
+    if (fieldDeclaration.isStatic) {
+      return;
+    }
+    // has a parse error
+    var variableList = fieldDeclaration.fields;
+    if (variableList.keyword == null && variableList.type == null) {
+      return;
+    }
+    // not interesting for final
+    if (variableList.isFinal) {
+      return;
+    }
+    // should have exactly one field
+    List<VariableDeclaration> fields = variableList.variables;
+    if (fields.length != 1) {
+      return;
+    }
+    var field = fields.first;
+    var nameNode = field.name;
+    FieldElement fieldElement = nameNode.staticElement;
+    // should have a public name
+    var name = nameNode.name;
+    if (Identifier.isPrivateName(name)) {
+      return;
+    }
+    // should be on the name
+    if (nameNode != node) {
+      return;
+    }
+    await builder.addFileEdit(file, (DartFileEditBuilder builder) {
+      // rename field
+      builder.addSimpleReplacement(range.node(nameNode), '_$name');
+      // update references in constructors
+      ClassOrMixinDeclaration classDeclaration = fieldDeclaration.parent;
+      for (var member in classDeclaration.members) {
+        if (member is ConstructorDeclaration) {
+          for (var parameter in member.parameters.parameters) {
+            var parameterElement = parameter.declaredElement;
+            if (parameterElement is FieldFormalParameterElement &&
+                parameterElement.field == fieldElement) {
+              var identifier = parameter.identifier;
+              builder.addSimpleReplacement(range.node(identifier), '_$name');
+            }
+          }
+        }
+      }
+
+      // Write getter and setter.
+      builder.addInsertion(fieldDeclaration.end, (builder) {
+        String docCode;
+        if (fieldDeclaration.documentationComment != null) {
+          docCode = utils.getNodeText(fieldDeclaration.documentationComment);
+        }
+
+        var typeCode = '';
+        if (variableList.type != null) {
+          typeCode = utils.getNodeText(variableList.type) + ' ';
+        }
+
+        // Write getter.
+        builder.writeln();
+        builder.writeln();
+        if (docCode != null) {
+          builder.write('  ');
+          builder.writeln(docCode);
+        }
+        builder.write('  ${typeCode}get $name => _$name;');
+
+        // Write setter.
+        builder.writeln();
+        builder.writeln();
+        if (docCode != null) {
+          builder.write('  ');
+          builder.writeln(docCode);
+        }
+        builder.writeln('  set $name($typeCode$name) {');
+        builder.writeln('    _$name = $name;');
+        builder.write('  }');
+      });
+    });
+  }
+
+  /// Return an instance of this class. Used as a tear-off in `AssistProcessor`.
+  static EncapsulateField newInstance() => EncapsulateField();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/flutter_convert_to_children.dart b/pkg/analysis_server/lib/src/services/correction/dart/flutter_convert_to_children.dart
new file mode 100644
index 0000000..08e28d1
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/flutter_convert_to_children.dart
@@ -0,0 +1,86 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+
+class FlutterConvertToChildren extends CorrectionProducer {
+  @override
+  AssistKind get assistKind => DartAssistKind.FLUTTER_CONVERT_TO_CHILDREN;
+
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    // Find "child: widget" under selection.
+    NamedExpression namedExp;
+    {
+      var node = this.node;
+      var parent = node?.parent;
+      var parent2 = parent?.parent;
+      if (node is SimpleIdentifier &&
+          parent is Label &&
+          parent2 is NamedExpression &&
+          node.name == 'child' &&
+          node.staticElement != null &&
+          flutter.isWidgetExpression(parent2.expression)) {
+        namedExp = parent2;
+      } else {
+        return;
+      }
+    }
+
+    await builder.addFileEdit(file, (DartFileEditBuilder builder) {
+      _convertFlutterChildToChildren(namedExp, eol, utils.getNodeText,
+          utils.getLinePrefix, utils.getIndent, utils.getText, builder);
+    });
+  }
+
+  void _convertFlutterChildToChildren(
+      NamedExpression namedExp,
+      String eol,
+      Function getNodeText,
+      Function getLinePrefix,
+      Function getIndent,
+      Function getText,
+      DartFileEditBuilder builder) {
+    var childArg = namedExp.expression;
+    var childLoc = namedExp.offset + 'child'.length;
+    builder.addSimpleInsertion(childLoc, 'ren');
+    var listLoc = childArg.offset;
+    String childArgSrc = getNodeText(childArg);
+    if (!childArgSrc.contains(eol)) {
+      builder.addSimpleInsertion(listLoc, '[');
+      builder.addSimpleInsertion(listLoc + childArg.length, ']');
+    } else {
+      var newlineLoc = childArgSrc.lastIndexOf(eol);
+      if (newlineLoc == childArgSrc.length) {
+        newlineLoc -= 1;
+      }
+      String indentOld = getLinePrefix(childArg.offset + 1 + newlineLoc);
+      var indentNew = '$indentOld${getIndent(1)}';
+      // The separator includes 'child:' but that has no newlines.
+      String separator =
+          getText(namedExp.offset, childArg.offset - namedExp.offset);
+      var prefix = separator.contains(eol) ? '' : '$eol$indentNew';
+      if (prefix.isEmpty) {
+        builder.addSimpleInsertion(namedExp.offset + 'child:'.length, ' [');
+        var argOffset = childArg.offset;
+        builder
+            .addDeletion(range.startOffsetEndOffset(argOffset - 2, argOffset));
+      } else {
+        builder.addSimpleInsertion(listLoc, '[');
+      }
+      var newChildArgSrc =
+          replaceSourceIndent(childArgSrc, indentOld, indentNew);
+      newChildArgSrc = '$prefix$newChildArgSrc,$eol$indentOld]';
+      builder.addSimpleReplacement(range.node(childArg), newChildArgSrc);
+    }
+  }
+
+  /// Return an instance of this class. Used as a tear-off in `AssistProcessor`.
+  static FlutterConvertToChildren newInstance() => FlutterConvertToChildren();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/flutter_convert_to_stateful_widget.dart b/pkg/analysis_server/lib/src/services/correction/dart/flutter_convert_to_stateful_widget.dart
new file mode 100644
index 0000000..b535b69
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/flutter_convert_to_stateful_widget.dart
@@ -0,0 +1,307 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:_fe_analyzer_shared/src/scanner/token.dart';
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/source/source_range.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart' hide Element;
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+
+class FlutterConvertToStatefulWidget extends CorrectionProducer {
+  @override
+  AssistKind get assistKind =>
+      DartAssistKind.FLUTTER_CONVERT_TO_STATEFUL_WIDGET;
+
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    var widgetClass = node.thisOrAncestorOfType<ClassDeclaration>();
+    var superclass = widgetClass?.extendsClause?.superclass;
+    if (widgetClass == null || superclass == null) {
+      return;
+    }
+
+    // Don't spam, activate only from the `class` keyword to the class body.
+    if (selectionOffset < widgetClass.classKeyword.offset ||
+        selectionOffset > widgetClass.leftBracket.end) {
+      return;
+    }
+
+    // Find the build() method.
+    MethodDeclaration buildMethod;
+    for (var member in widgetClass.members) {
+      if (member is MethodDeclaration &&
+          member.name.name == 'build' &&
+          member.parameters != null &&
+          member.parameters.parameters.length == 1) {
+        buildMethod = member;
+        break;
+      }
+    }
+    if (buildMethod == null) {
+      return;
+    }
+
+    // Must be a StatelessWidget subclasses.
+    var widgetClassElement = widgetClass.declaredElement;
+    if (!flutter.isExactlyStatelessWidgetType(widgetClassElement.supertype)) {
+      return;
+    }
+
+    var widgetName = widgetClassElement.displayName;
+    var stateName = '_${widgetName}State';
+
+    // Find fields assigned in constructors.
+    var visitor = _FieldFinder();
+    for (var member in widgetClass.members) {
+      if (member is ConstructorDeclaration) {
+        member.accept(visitor);
+      }
+    }
+    var fieldsAssignedInConstructors = visitor.fieldsAssignedInConstructors;
+
+    // Prepare nodes to move.
+    var nodesToMove = <ClassMember>{};
+    var elementsToMove = <Element>{};
+    for (var member in widgetClass.members) {
+      if (member is FieldDeclaration && !member.isStatic) {
+        for (var fieldNode in member.fields.variables) {
+          FieldElement fieldElement = fieldNode.declaredElement;
+          if (!fieldsAssignedInConstructors.contains(fieldElement)) {
+            nodesToMove.add(member);
+            elementsToMove.add(fieldElement);
+            elementsToMove.add(fieldElement.getter);
+            if (fieldElement.setter != null) {
+              elementsToMove.add(fieldElement.setter);
+            }
+          }
+        }
+      }
+      if (member is MethodDeclaration && !member.isStatic) {
+        nodesToMove.add(member);
+        elementsToMove.add(member.declaredElement);
+      }
+    }
+
+    /// Return the code for the [movedNode] which is suitable to be used
+    /// inside the `State` class, so that references to the widget fields and
+    /// methods, that are not moved, are qualified with the corresponding
+    /// instance `widget.`, or static `MyWidgetClass.` qualifier.
+    String rewriteWidgetMemberReferences(AstNode movedNode) {
+      var linesRange = utils.getLinesRange(range.node(movedNode));
+      var text = utils.getRangeText(linesRange);
+
+      // Insert `widget.` before references to the widget instance members.
+      var visitor = _ReplacementEditBuilder(
+          widgetClassElement, elementsToMove, linesRange);
+      movedNode.accept(visitor);
+      return SourceEdit.applySequence(text, visitor.edits.reversed);
+    }
+
+    var statefulWidgetClass = await sessionHelper.getClass(
+      flutter.widgetsUri,
+      'StatefulWidget',
+    );
+    var stateClass = await sessionHelper.getClass(
+      flutter.widgetsUri,
+      'State',
+    );
+    if (statefulWidgetClass == null || stateClass == null) {
+      return;
+    }
+
+    await builder.addFileEdit(file, (DartFileEditBuilder builder) {
+      builder.addReplacement(range.node(superclass), (builder) {
+        builder.writeReference(statefulWidgetClass);
+      });
+
+      var replaceOffset = 0;
+      var hasBuildMethod = false;
+
+      var typeParams = '';
+      if (widgetClass.typeParameters != null) {
+        typeParams = utils.getNodeText(widgetClass.typeParameters);
+      }
+
+      /// Replace code between [replaceOffset] and [replaceEnd] with
+      /// `createState()`, empty line, or nothing.
+      void replaceInterval(int replaceEnd,
+          {bool replaceWithEmptyLine = false,
+          bool hasEmptyLineBeforeCreateState = false,
+          bool hasEmptyLineAfterCreateState = true}) {
+        var replaceLength = replaceEnd - replaceOffset;
+        builder.addReplacement(
+          SourceRange(replaceOffset, replaceLength),
+          (builder) {
+            if (hasBuildMethod) {
+              if (hasEmptyLineBeforeCreateState) {
+                builder.writeln();
+              }
+              builder.writeln('  @override');
+              builder.writeln(
+                  '  $stateName$typeParams createState() => $stateName$typeParams();');
+              if (hasEmptyLineAfterCreateState) {
+                builder.writeln();
+              }
+              hasBuildMethod = false;
+            } else if (replaceWithEmptyLine) {
+              builder.writeln();
+            }
+          },
+        );
+        replaceOffset = 0;
+      }
+
+      // Remove continuous ranges of lines of nodes being moved.
+      var lastToRemoveIsField = false;
+      var endOfLastNodeToKeep = 0;
+      for (var node in widgetClass.members) {
+        if (nodesToMove.contains(node)) {
+          if (replaceOffset == 0) {
+            var linesRange = utils.getLinesRange(range.node(node));
+            replaceOffset = linesRange.offset;
+          }
+          if (node == buildMethod) {
+            hasBuildMethod = true;
+          }
+          lastToRemoveIsField = node is FieldDeclaration;
+        } else {
+          var linesRange = utils.getLinesRange(range.node(node));
+          endOfLastNodeToKeep = linesRange.end;
+          if (replaceOffset != 0) {
+            replaceInterval(linesRange.offset,
+                replaceWithEmptyLine:
+                    lastToRemoveIsField && node is! FieldDeclaration);
+          }
+        }
+      }
+
+      // Remove nodes at the end of the widget class.
+      if (replaceOffset != 0) {
+        // Remove from the last node to keep, so remove empty lines.
+        if (endOfLastNodeToKeep != 0) {
+          replaceOffset = endOfLastNodeToKeep;
+        }
+        replaceInterval(widgetClass.rightBracket.offset,
+            hasEmptyLineBeforeCreateState: endOfLastNodeToKeep != 0,
+            hasEmptyLineAfterCreateState: false);
+      }
+
+      // Create the State subclass.
+      builder.addInsertion(widgetClass.end, (builder) {
+        builder.writeln();
+        builder.writeln();
+
+        builder.write('class $stateName$typeParams extends ');
+        builder.writeReference(stateClass);
+
+        // Write just param names (and not bounds, metadata and docs).
+        builder.write('<${widgetClass.name}');
+        if (widgetClass.typeParameters != null) {
+          builder.write('<');
+          var first = true;
+          for (var param in widgetClass.typeParameters.typeParameters) {
+            if (!first) {
+              builder.write(', ');
+              first = false;
+            }
+            builder.write(param.name.name);
+          }
+          builder.write('>');
+        }
+
+        builder.writeln('> {');
+
+        var writeEmptyLine = false;
+        for (var member in nodesToMove) {
+          if (writeEmptyLine) {
+            builder.writeln();
+          }
+          var text = rewriteWidgetMemberReferences(member);
+          builder.write(text);
+          // Write empty lines between members, but not before the first.
+          writeEmptyLine = true;
+        }
+
+        builder.write('}');
+      });
+    });
+  }
+
+  /// Return an instance of this class. Used as a tear-off in `AssistProcessor`.
+  static FlutterConvertToStatefulWidget newInstance() =>
+      FlutterConvertToStatefulWidget();
+}
+
+class _FieldFinder extends RecursiveAstVisitor<void> {
+  Set<FieldElement> fieldsAssignedInConstructors = {};
+
+  @override
+  void visitSimpleIdentifier(SimpleIdentifier node) {
+    if (node.parent is FieldFormalParameter) {
+      var element = node.staticElement;
+      if (element is FieldFormalParameterElement) {
+        fieldsAssignedInConstructors.add(element.field);
+      }
+    }
+    if (node.parent is ConstructorFieldInitializer) {
+      var element = node.staticElement;
+      if (element is FieldElement) {
+        fieldsAssignedInConstructors.add(element);
+      }
+    }
+    if (node.inSetterContext()) {
+      var element = node.staticElement;
+      if (element is PropertyAccessorElement) {
+        var field = element.variable;
+        if (field is FieldElement) {
+          fieldsAssignedInConstructors.add(field);
+        }
+      }
+    }
+  }
+}
+
+class _ReplacementEditBuilder extends RecursiveAstVisitor<void> {
+  final ClassElement widgetClassElement;
+
+  final Set<Element> elementsToMove;
+
+  final SourceRange linesRange;
+
+  List<SourceEdit> edits = [];
+
+  _ReplacementEditBuilder(
+      this.widgetClassElement, this.elementsToMove, this.linesRange);
+
+  @override
+  void visitSimpleIdentifier(SimpleIdentifier node) {
+    if (node.inDeclarationContext()) {
+      return;
+    }
+    var element = node.staticElement;
+    if (element is ExecutableElement &&
+        element?.enclosingElement == widgetClassElement &&
+        !elementsToMove.contains(element)) {
+      var offset = node.offset - linesRange.offset;
+      var qualifier =
+          element.isStatic ? widgetClassElement.displayName : 'widget';
+
+      var parent = node.parent;
+      if (parent is InterpolationExpression &&
+          parent.leftBracket.type ==
+              TokenType.STRING_INTERPOLATION_IDENTIFIER) {
+        edits.add(SourceEdit(offset, 0, '{$qualifier.'));
+        edits.add(SourceEdit(offset + node.length, 0, '}'));
+      } else {
+        edits.add(SourceEdit(offset, 0, '$qualifier.'));
+      }
+    }
+  }
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/flutter_move_down.dart b/pkg/analysis_server/lib/src/services/correction/dart/flutter_move_down.dart
new file mode 100644
index 0000000..dd16b00
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/flutter_move_down.dart
@@ -0,0 +1,50 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+
+class FlutterMoveDown extends CorrectionProducer {
+  @override
+  AssistKind get assistKind => DartAssistKind.FLUTTER_MOVE_DOWN;
+
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    var widget = flutter.identifyWidgetExpression(node);
+    if (widget == null) {
+      return;
+    }
+
+    var parentList = widget.parent;
+    if (parentList is ListLiteral) {
+      List<CollectionElement> parentElements = parentList.elements;
+      var index = parentElements.indexOf(widget);
+      if (index != parentElements.length - 1) {
+        await builder.addFileEdit(file, (fileBuilder) {
+          var nextWidget = parentElements[index + 1];
+          var nextRange = range.node(nextWidget);
+          var nextText = utils.getRangeText(nextRange);
+
+          var widgetRange = range.node(widget);
+          var widgetText = utils.getRangeText(widgetRange);
+
+          fileBuilder.addSimpleReplacement(nextRange, widgetText);
+          fileBuilder.addSimpleReplacement(widgetRange, nextText);
+
+          var lengthDelta = nextRange.length - widgetRange.length;
+          var newWidgetOffset = nextRange.offset + lengthDelta;
+          builder.setSelection(Position(file, newWidgetOffset));
+        });
+      }
+    }
+  }
+
+  /// Return an instance of this class. Used as a tear-off in `AssistProcessor`.
+  static FlutterMoveDown newInstance() => FlutterMoveDown();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/flutter_move_up.dart b/pkg/analysis_server/lib/src/services/correction/dart/flutter_move_up.dart
new file mode 100644
index 0000000..eabb367
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/flutter_move_up.dart
@@ -0,0 +1,49 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+
+class FlutterMoveUp extends CorrectionProducer {
+  @override
+  AssistKind get assistKind => DartAssistKind.FLUTTER_MOVE_UP;
+
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    var widget = flutter.identifyWidgetExpression(node);
+    if (widget == null) {
+      return;
+    }
+
+    var parentList = widget.parent;
+    if (parentList is ListLiteral) {
+      List<CollectionElement> parentElements = parentList.elements;
+      var index = parentElements.indexOf(widget);
+      if (index > 0) {
+        await builder.addFileEdit(file, (fileBuilder) {
+          var previousWidget = parentElements[index - 1];
+          var previousRange = range.node(previousWidget);
+          var previousText = utils.getRangeText(previousRange);
+
+          var widgetRange = range.node(widget);
+          var widgetText = utils.getRangeText(widgetRange);
+
+          fileBuilder.addSimpleReplacement(previousRange, widgetText);
+          fileBuilder.addSimpleReplacement(widgetRange, previousText);
+
+          var newWidgetOffset = previousRange.offset;
+          builder.setSelection(Position(file, newWidgetOffset));
+        });
+      }
+    }
+  }
+
+  /// Return an instance of this class. Used as a tear-off in `AssistProcessor`.
+  static FlutterMoveUp newInstance() => FlutterMoveUp();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/flutter_remove_widget.dart b/pkg/analysis_server/lib/src/services/correction/dart/flutter_remove_widget.dart
new file mode 100644
index 0000000..4e9ea67
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/flutter_remove_widget.dart
@@ -0,0 +1,79 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+
+class FlutterRemoveWidget extends CorrectionProducer {
+  @override
+  AssistKind get assistKind => DartAssistKind.FLUTTER_REMOVE_WIDGET;
+
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    var widgetCreation = flutter.identifyNewExpression(node);
+    if (widgetCreation == null) {
+      return;
+    }
+
+    // Prepare the list of our children.
+    var childrenArgument = flutter.findChildrenArgument(widgetCreation);
+    if (childrenArgument != null) {
+      var childrenExpression = childrenArgument?.expression;
+      if (childrenExpression is ListLiteral &&
+          childrenExpression.elements.isNotEmpty) {
+        await _removeChildren(
+            builder, widgetCreation, childrenExpression.elements);
+      }
+    } else {
+      var childArgument = flutter.findChildArgument(widgetCreation);
+      if (childArgument != null) {
+        await _removeChild(builder, widgetCreation, childArgument);
+      }
+    }
+  }
+
+  Future<void> _removeChild(
+      DartChangeBuilder builder,
+      InstanceCreationExpression widgetCreation,
+      NamedExpression childArgument) async {
+    // child: ThisWidget(child: ourChild)
+    // children: [foo, ThisWidget(child: ourChild), bar]
+    await builder.addFileEdit(file, (DartFileEditBuilder builder) {
+      var childExpression = childArgument.expression;
+      var childText = utils.getNodeText(childExpression);
+      var indentOld = utils.getLinePrefix(childExpression.offset);
+      var indentNew = utils.getLinePrefix(widgetCreation.offset);
+      childText = replaceSourceIndent(childText, indentOld, indentNew);
+      builder.addSimpleReplacement(range.node(widgetCreation), childText);
+    });
+  }
+
+  Future<void> _removeChildren(
+      DartChangeBuilder builder,
+      InstanceCreationExpression widgetCreation,
+      List<CollectionElement> childrenExpressions) async {
+    // We can inline the list of our children only into another list.
+    var widgetParentNode = widgetCreation.parent;
+    if (childrenExpressions.length > 1 && widgetParentNode is! ListLiteral) {
+      return;
+    }
+
+    await builder.addFileEdit(file, (DartFileEditBuilder builder) {
+      var firstChild = childrenExpressions.first;
+      var lastChild = childrenExpressions.last;
+      var childText = utils.getRangeText(range.startEnd(firstChild, lastChild));
+      var indentOld = utils.getLinePrefix(firstChild.offset);
+      var indentNew = utils.getLinePrefix(widgetCreation.offset);
+      childText = replaceSourceIndent(childText, indentOld, indentNew);
+      builder.addSimpleReplacement(range.node(widgetCreation), childText);
+    });
+  }
+
+  /// Return an instance of this class. Used as a tear-off in `AssistProcessor`.
+  static FlutterRemoveWidget newInstance() => FlutterRemoveWidget();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/flutter_swap_with_child.dart b/pkg/analysis_server/lib/src/services/correction/dart/flutter_swap_with_child.dart
new file mode 100644
index 0000000..af9c47b
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/flutter_swap_with_child.dart
@@ -0,0 +1,117 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+
+abstract class FlutterParentAndChild extends CorrectionProducer {
+  Future<void> swapParentAndChild(
+      DartChangeBuilder builder,
+      InstanceCreationExpression parent,
+      InstanceCreationExpression child) async {
+    // The child must have its own child.
+    if (flutter.findChildArgument(child) == null) {
+      return;
+    }
+
+    await builder.addFileEdit(file, (builder) {
+      builder.addReplacement(range.node(parent), (builder) {
+        var childArgs = child.argumentList;
+        var parentArgs = parent.argumentList;
+        var childText = utils.getRangeText(range.startStart(child, childArgs));
+        var parentText =
+            utils.getRangeText(range.startStart(parent, parentArgs));
+
+        var parentIndent = utils.getLinePrefix(parent.offset);
+        var childIndent = parentIndent + '  ';
+
+        // Write the beginning of the child.
+        builder.write(childText);
+        builder.writeln('(');
+
+        // Write all the arguments of the parent.
+        // Don't write the "child".
+        Expression stableChild;
+        for (var argument in childArgs.arguments) {
+          if (flutter.isChildArgument(argument)) {
+            stableChild = argument;
+          } else {
+            var text = utils.getNodeText(argument);
+            text = replaceSourceIndent(text, childIndent, parentIndent);
+            builder.write(parentIndent);
+            builder.write('  ');
+            builder.write(text);
+            builder.writeln(',');
+          }
+        }
+
+        // Write the parent as a new child.
+        builder.write(parentIndent);
+        builder.write('  ');
+        builder.write('child: ');
+        builder.write(parentText);
+        builder.writeln('(');
+
+        // Write all arguments of the parent.
+        // Don't write its child.
+        for (var argument in parentArgs.arguments) {
+          if (!flutter.isChildArgument(argument)) {
+            var text = utils.getNodeText(argument);
+            text = replaceSourceIndent(text, parentIndent, childIndent);
+            builder.write(childIndent);
+            builder.write('  ');
+            builder.write(text);
+            builder.writeln(',');
+          }
+        }
+
+        // Write the child of the "child" now, as the child of the "parent".
+        {
+          var text = utils.getNodeText(stableChild);
+          builder.write(childIndent);
+          builder.write('  ');
+          builder.write(text);
+          builder.writeln(',');
+        }
+
+        // Close the parent expression.
+        builder.write(childIndent);
+        builder.writeln('),');
+
+        // Close the child expression.
+        builder.write(parentIndent);
+        builder.write(')');
+      });
+    });
+  }
+}
+
+class FlutterSwapWithChild extends FlutterParentAndChild {
+  @override
+  AssistKind get assistKind => DartAssistKind.FLUTTER_SWAP_WITH_CHILD;
+
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    var parent = flutter.identifyNewExpression(node);
+    if (!flutter.isWidgetCreation(parent)) {
+      return;
+    }
+
+    var childArgument = flutter.findChildArgument(parent);
+    if (childArgument?.expression is! InstanceCreationExpression ||
+        !flutter.isWidgetCreation(childArgument.expression)) {
+      return;
+    }
+    InstanceCreationExpression child = childArgument.expression;
+
+    await swapParentAndChild(builder, parent, child);
+  }
+
+  /// Return an instance of this class. Used as a tear-off in `AssistProcessor`.
+  static FlutterSwapWithChild newInstance() => FlutterSwapWithChild();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/flutter_swap_with_parent.dart b/pkg/analysis_server/lib/src/services/correction/dart/flutter_swap_with_parent.dart
new file mode 100644
index 0000000..e385a15
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/flutter_swap_with_parent.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analysis_server/src/services/correction/dart/flutter_swap_with_child.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+
+class FlutterSwapWithParent extends FlutterParentAndChild {
+  @override
+  AssistKind get assistKind => DartAssistKind.FLUTTER_SWAP_WITH_PARENT;
+
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    var child = flutter.identifyNewExpression(node);
+    if (!flutter.isWidgetCreation(child)) {
+      return;
+    }
+
+    // NamedExpression (child:), ArgumentList, InstanceCreationExpression
+    var expr = child.parent?.parent?.parent;
+    if (expr is! InstanceCreationExpression) {
+      return;
+    }
+
+    await swapParentAndChild(builder, expr, child);
+  }
+
+  /// Return an instance of this class. Used as a tear-off in `AssistProcessor`.
+  static FlutterSwapWithParent newInstance() => FlutterSwapWithParent();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap.dart b/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap.dart
new file mode 100644
index 0000000..0c077db
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap.dart
@@ -0,0 +1,273 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analysis_server/src/services/correction/selection_analyzer.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/source/source_range.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+
+class FlutterWrap extends MultiCorrectionProducer {
+  @override
+  Iterable<CorrectionProducer> get producers sync* {
+    var widgetExpr = flutter.identifyWidgetExpression(node);
+    if (widgetExpr != null) {
+      var widgetType = widgetExpr.staticType;
+      yield _FlutterWrapGeneric(widgetExpr);
+      if (!flutter.isExactWidgetTypeCenter(widgetType)) {
+        yield _FlutterWrapCenter(widgetExpr);
+      }
+      if (!flutter.isExactWidgetTypeContainer(widgetType)) {
+        yield _FlutterWrapContainer(widgetExpr);
+      }
+      if (!flutter.isExactWidgetTypePadding(widgetType)) {
+        yield _FlutterWrapPadding(widgetExpr);
+      }
+    }
+    yield* _wrapMultipleWidgets();
+  }
+
+  Iterable<CorrectionProducer> _wrapMultipleWidgets() sync* {
+    var selectionRange = SourceRange(selectionOffset, selectionLength);
+    var analyzer = SelectionAnalyzer(selectionRange);
+    resolvedResult.unit.accept(analyzer);
+
+    var widgetExpressions = <Expression>[];
+    if (analyzer.hasSelectedNodes) {
+      for (var selectedNode in analyzer.selectedNodes) {
+        if (!flutter.isWidgetExpression(selectedNode)) {
+          return;
+        }
+        widgetExpressions.add(selectedNode);
+      }
+    } else {
+      var widget = flutter.identifyWidgetExpression(analyzer.coveringNode);
+      if (widget != null) {
+        widgetExpressions.add(widget);
+      }
+    }
+    if (widgetExpressions.isEmpty) {
+      return;
+    }
+
+    var firstWidget = widgetExpressions.first;
+    var lastWidget = widgetExpressions.last;
+    yield _FlutterWrapColumn(firstWidget, lastWidget);
+    yield _FlutterWrapRow(firstWidget, lastWidget);
+  }
+
+  /// Return an instance of this class. Used as a tear-off in `AssistProcessor`.
+  static FlutterWrap newInstance() => FlutterWrap();
+}
+
+/// A correction processor that can make one of the possible change computed by
+/// the [FlutterWrap] producer.
+class _FlutterWrapCenter extends _WrapSingleWidget {
+  _FlutterWrapCenter(Expression widgetExpr) : super(widgetExpr);
+
+  @override
+  AssistKind get assistKind => DartAssistKind.FLUTTER_WRAP_CENTER;
+
+  @override
+  String get _parentClassName => 'Center';
+
+  @override
+  String get _parentLibraryUri => flutter.widgetsUri;
+}
+
+/// A correction processor that can make one of the possible change computed by
+/// the [FlutterWrap] producer.
+class _FlutterWrapColumn extends _WrapMultipleWidgets {
+  _FlutterWrapColumn(Expression firstWidget, Expression lastWidget)
+      : super(firstWidget, lastWidget);
+
+  @override
+  AssistKind get assistKind => DartAssistKind.FLUTTER_WRAP_COLUMN;
+
+  @override
+  String get _parentClassName => 'Column';
+}
+
+/// A correction processor that can make one of the possible change computed by
+/// the [FlutterWrap] producer.
+class _FlutterWrapContainer extends _WrapSingleWidget {
+  _FlutterWrapContainer(Expression widgetExpr) : super(widgetExpr);
+
+  @override
+  AssistKind get assistKind => DartAssistKind.FLUTTER_WRAP_CONTAINER;
+
+  @override
+  String get _parentClassName => 'Container';
+
+  @override
+  String get _parentLibraryUri => flutter.widgetsUri;
+}
+
+/// A correction processor that can make one of the possible change computed by
+/// the [FlutterWrap] producer.
+class _FlutterWrapGeneric extends _WrapSingleWidget {
+  _FlutterWrapGeneric(Expression widgetExpr) : super(widgetExpr);
+
+  @override
+  AssistKind get assistKind => DartAssistKind.FLUTTER_WRAP_GENERIC;
+}
+
+/// A correction processor that can make one of the possible change computed by
+/// the [FlutterWrap] producer.
+class _FlutterWrapPadding extends _WrapSingleWidget {
+  _FlutterWrapPadding(Expression widgetExpr) : super(widgetExpr);
+
+  @override
+  AssistKind get assistKind => DartAssistKind.FLUTTER_WRAP_PADDING;
+
+  @override
+  List<String> get _leadingLines => ['padding: const EdgeInsets.all(8.0),'];
+
+  @override
+  String get _parentClassName => 'Padding';
+
+  @override
+  String get _parentLibraryUri => flutter.widgetsUri;
+}
+
+/// A correction processor that can make one of the possible change computed by
+/// the [FlutterWrap] producer.
+class _FlutterWrapRow extends _WrapMultipleWidgets {
+  _FlutterWrapRow(Expression firstWidget, Expression lastWidget)
+      : super(firstWidget, lastWidget);
+
+  @override
+  AssistKind get assistKind => DartAssistKind.FLUTTER_WRAP_ROW;
+
+  @override
+  String get _parentClassName => 'Row';
+}
+
+/// A correction processor that can make one of the possible change computed by
+/// the [FlutterWrap] producer.
+abstract class _WrapMultipleWidgets extends CorrectionProducer {
+  final Expression firstWidget;
+
+  final Expression lastWidget;
+
+  _WrapMultipleWidgets(this.firstWidget, this.lastWidget);
+
+  String get _parentClassName;
+
+  String get _parentLibraryUri => flutter.widgetsUri;
+
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    var selectedRange = range.startEnd(firstWidget, lastWidget);
+    var src = utils.getRangeText(selectedRange);
+    var parentClassElement =
+        await sessionHelper.getClass(_parentLibraryUri, _parentClassName);
+    var widgetClassElement =
+        await sessionHelper.getClass(flutter.widgetsUri, 'Widget');
+    if (parentClassElement == null || widgetClassElement == null) {
+      return;
+    }
+
+    await builder.addFileEdit(file, (DartFileEditBuilder builder) {
+      builder.addReplacement(selectedRange, (DartEditBuilder builder) {
+        builder.writeReference(parentClassElement);
+        builder.write('(');
+
+        var indentOld = utils.getLinePrefix(firstWidget.offset);
+        var indentNew1 = indentOld + utils.getIndent(1);
+        var indentNew2 = indentOld + utils.getIndent(2);
+
+        builder.write(eol);
+        builder.write(indentNew1);
+        builder.write('children: [');
+        builder.write(eol);
+
+        var newSrc = replaceSourceIndent(src, indentOld, indentNew2);
+        builder.write(indentNew2);
+        builder.write(newSrc);
+
+        builder.write(',');
+        builder.write(eol);
+
+        builder.write(indentNew1);
+        builder.write('],');
+        builder.write(eol);
+
+        builder.write(indentOld);
+        builder.write(')');
+      });
+    });
+  }
+}
+
+/// A correction processor that can make one of the possible change computed by
+/// the [FlutterWrap] producer.
+abstract class _WrapSingleWidget extends CorrectionProducer {
+  final Expression widgetExpr;
+
+  _WrapSingleWidget(this.widgetExpr);
+
+  List<String> get _leadingLines => const [];
+
+  String get _parentClassName => null;
+
+  String get _parentLibraryUri => null;
+
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    var widgetSrc = utils.getNodeText(widgetExpr);
+
+    // If the wrapper class is specified, find its element.
+    var parentLibraryUri = _parentLibraryUri;
+    var parentClassName = _parentClassName;
+    ClassElement parentClassElement;
+    if (parentLibraryUri != null && parentClassName != null) {
+      parentClassElement =
+          await sessionHelper.getClass(parentLibraryUri, parentClassName);
+      if (parentClassElement == null) {
+        return;
+      }
+    }
+
+    await builder.addFileEdit(file, (DartFileEditBuilder builder) {
+      builder.addReplacement(range.node(widgetExpr), (DartEditBuilder builder) {
+        if (parentClassElement == null) {
+          builder.addSimpleLinkedEdit('WIDGET', 'widget');
+        } else {
+          builder.writeReference(parentClassElement);
+        }
+        builder.write('(');
+        var leadingLines = _leadingLines;
+        if (widgetSrc.contains(eol) || leadingLines.isNotEmpty) {
+          var indentOld = utils.getLinePrefix(widgetExpr.offset);
+          var indentNew = '$indentOld${utils.getIndent(1)}';
+
+          for (var leadingLine in leadingLines) {
+            builder.write(eol);
+            builder.write(indentNew);
+            builder.write(leadingLine);
+          }
+
+          builder.write(eol);
+          builder.write(indentNew);
+          widgetSrc = widgetSrc.replaceAll(
+              RegExp('^$indentOld', multiLine: true), indentNew);
+          widgetSrc += ',$eol$indentOld';
+        }
+        if (parentClassElement == null) {
+          builder.addSimpleLinkedEdit('CHILD', 'child');
+        } else {
+          builder.write('child');
+        }
+        builder.write(': ');
+        builder.write(widgetSrc);
+        builder.write(')');
+      });
+    });
+  }
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap_generic.dart b/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap_generic.dart
new file mode 100644
index 0000000..3eaec41
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap_generic.dart
@@ -0,0 +1,61 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+
+class FlutterWrapGeneric extends CorrectionProducer {
+  @override
+  AssistKind get assistKind => DartAssistKind.FLUTTER_WRAP_GENERIC;
+
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    if (node is! ListLiteral) {
+      return;
+    }
+    if ((node as ListLiteral).elements.any((CollectionElement exp) =>
+        !(exp is InstanceCreationExpression &&
+            flutter.isWidgetCreation(exp)))) {
+      return;
+    }
+    var literalSrc = utils.getNodeText(node);
+    var newlineIdx = literalSrc.lastIndexOf(eol);
+    if (newlineIdx < 0 || newlineIdx == literalSrc.length - 1) {
+      return; // Lists need to be in multi-line format already.
+    }
+    var indentOld = utils.getLinePrefix(node.offset + 1 + newlineIdx);
+    var indentArg = '$indentOld${utils.getIndent(1)}';
+    var indentList = '$indentOld${utils.getIndent(2)}';
+
+    await builder.addFileEdit(file, (DartFileEditBuilder builder) {
+      builder.addReplacement(range.node(node), (DartEditBuilder builder) {
+        builder.write('[');
+        builder.write(eol);
+        builder.write(indentArg);
+        builder.addSimpleLinkedEdit('WIDGET', 'widget');
+        builder.write('(');
+        builder.write(eol);
+        builder.write(indentList);
+        // Linked editing not needed since arg is always a list.
+        builder.write('children: ');
+        builder.write(literalSrc.replaceAll(
+            RegExp('^$indentOld', multiLine: true), '$indentList'));
+        builder.write(',');
+        builder.write(eol);
+        builder.write(indentArg);
+        builder.write('),');
+        builder.write(eol);
+        builder.write(indentOld);
+        builder.write(']');
+      });
+    });
+  }
+
+  /// Return an instance of this class. Used as a tear-off in `AssistProcessor`.
+  static FlutterWrapGeneric newInstance() => FlutterWrapGeneric();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap_stream_builder.dart b/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap_stream_builder.dart
new file mode 100644
index 0000000..aad39af
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap_stream_builder.dart
@@ -0,0 +1,71 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+
+class FlutterWrapStreamBuilder extends CorrectionProducer {
+  @override
+  AssistKind get assistKind => DartAssistKind.FLUTTER_WRAP_STREAM_BUILDER;
+
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    var widgetExpr = flutter.identifyWidgetExpression(node);
+    if (widgetExpr == null) {
+      return;
+    }
+    if (flutter.isExactWidgetTypeStreamBuilder(widgetExpr.staticType)) {
+      return;
+    }
+    var widgetSrc = utils.getNodeText(widgetExpr);
+
+    var streamBuilderElement = await sessionHelper.getClass(
+      flutter.widgetsUri,
+      'StreamBuilder',
+    );
+    if (streamBuilderElement == null) {
+      return;
+    }
+
+    await builder.addFileEdit(file, (builder) {
+      builder.addReplacement(range.node(widgetExpr), (builder) {
+        builder.writeReference(streamBuilderElement);
+
+        builder.write('<');
+        builder.addSimpleLinkedEdit('type', 'Object');
+        builder.writeln('>(');
+
+        var indentOld = utils.getLinePrefix(widgetExpr.offset);
+        var indentNew1 = indentOld + utils.getIndent(1);
+        var indentNew2 = indentOld + utils.getIndent(2);
+
+        builder.write(indentNew1);
+        builder.writeln('stream: null,');
+
+        builder.write(indentNew1);
+        builder.writeln('builder: (context, snapshot) {');
+
+        widgetSrc = widgetSrc.replaceAll(
+          RegExp('^$indentOld', multiLine: true),
+          indentNew2,
+        );
+        builder.write(indentNew2);
+        builder.write('return $widgetSrc');
+        builder.writeln(';');
+
+        builder.write(indentNew1);
+        builder.writeln('}');
+
+        builder.write(indentOld);
+        builder.write(')');
+      });
+    });
+  }
+
+  /// Return an instance of this class. Used as a tear-off in `AssistProcessor`.
+  static FlutterWrapStreamBuilder newInstance() => FlutterWrapStreamBuilder();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/import_add_show.dart b/pkg/analysis_server/lib/src/services/correction/dart/import_add_show.dart
new file mode 100644
index 0000000..c820844
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/import_add_show.dart
@@ -0,0 +1,72 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:collection';
+
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analysis_server/src/services/correction/util.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+
+class ImportAddShow extends CorrectionProducer {
+  @override
+  AssistKind get assistKind => DartAssistKind.IMPORT_ADD_SHOW;
+
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    // prepare ImportDirective
+    var importDirective = node.thisOrAncestorOfType<ImportDirective>();
+    if (importDirective == null) {
+      return;
+    }
+    // there should be no existing combinators
+    if (importDirective.combinators.isNotEmpty) {
+      return;
+    }
+    // prepare whole import namespace
+    ImportElement importElement = importDirective.element;
+    if (importElement == null) {
+      return;
+    }
+    var namespace = getImportNamespace(importElement);
+    // prepare names of referenced elements (from this import)
+    var visitor = _ReferenceFinder(namespace);
+    resolvedResult.unit.accept(visitor);
+    var referencedNames = visitor.referencedNames;
+    // ignore if unused
+    if (referencedNames.isEmpty) {
+      return;
+    }
+    await builder.addFileEdit(file, (DartFileEditBuilder builder) {
+      var showCombinator = ' show ${referencedNames.join(', ')}';
+      builder.addSimpleInsertion(importDirective.end - 1, showCombinator);
+    });
+  }
+
+  /// Return an instance of this class. Used as a tear-off in `AssistProcessor`.
+  static ImportAddShow newInstance() => ImportAddShow();
+}
+
+class _ReferenceFinder extends RecursiveAstVisitor<void> {
+  final Map<String, Element> namespace;
+
+  Set<String> referencedNames = SplayTreeSet<String>();
+
+  _ReferenceFinder(this.namespace);
+
+  @override
+  void visitSimpleIdentifier(SimpleIdentifier node) {
+    var element = node.staticElement;
+    if (element != null &&
+        (namespace[node.name] == element ||
+            (node.name != element.name &&
+                namespace[element.name] == element))) {
+      referencedNames.add(element.displayName);
+    }
+  }
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/introduce_local_cast_type.dart b/pkg/analysis_server/lib/src/services/correction/dart/introduce_local_cast_type.dart
new file mode 100644
index 0000000..30bf94a
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/introduce_local_cast_type.dart
@@ -0,0 +1,87 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analysis_server/src/services/correction/name_suggestion.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/ast/utilities.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+
+class IntroduceLocalCastType extends CorrectionProducer {
+  @override
+  AssistKind get assistKind => DartAssistKind.INTRODUCE_LOCAL_CAST_TYPE;
+
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    var node = this.node;
+    if (node is IfStatement) {
+      node = (node as IfStatement).condition;
+    } else if (node is WhileStatement) {
+      node = (node as WhileStatement).condition;
+    }
+    // prepare IsExpression
+    if (node is! IsExpression) {
+      return;
+    }
+    IsExpression isExpression = node;
+    var castType = isExpression.type.type;
+    var castTypeCode = utils.getNodeText(isExpression.type);
+    // prepare environment
+    var indent = utils.getIndent(1);
+    String prefix;
+    Block targetBlock;
+    {
+      var statement = node.thisOrAncestorOfType<Statement>();
+      if (statement is IfStatement && statement.thenStatement is Block) {
+        targetBlock = statement.thenStatement;
+      } else if (statement is WhileStatement && statement.body is Block) {
+        targetBlock = statement.body;
+      } else {
+        return;
+      }
+      prefix = utils.getNodePrefix(statement);
+    }
+    // prepare location
+    int offset;
+    String statementPrefix;
+    if (isExpression.notOperator == null) {
+      offset = targetBlock.leftBracket.end;
+      statementPrefix = indent;
+    } else {
+      offset = targetBlock.rightBracket.end;
+      statementPrefix = '';
+    }
+    // prepare excluded names
+    var excluded = <String>{};
+    var scopedNameFinder = ScopedNameFinder(offset);
+    isExpression.accept(scopedNameFinder);
+    excluded.addAll(scopedNameFinder.locals.keys.toSet());
+    // name(s)
+    var suggestions =
+        getVariableNameSuggestionsForExpression(castType, null, excluded);
+
+    if (suggestions.isNotEmpty) {
+      await builder.addFileEdit(file, (DartFileEditBuilder builder) {
+        builder.addInsertion(offset, (DartEditBuilder builder) {
+          builder.write(eol + prefix + statementPrefix);
+          builder.write(castTypeCode);
+          builder.write(' ');
+          builder.addSimpleLinkedEdit('NAME', suggestions[0],
+              kind: LinkedEditSuggestionKind.VARIABLE,
+              suggestions: suggestions);
+          builder.write(' = ');
+          builder.write(utils.getNodeText(isExpression.expression));
+          builder.write(';');
+          builder.selectHere();
+        });
+      });
+    }
+  }
+
+  /// Return an instance of this class. Used as a tear-off in `AssistProcessor`.
+  static IntroduceLocalCastType newInstance() => IntroduceLocalCastType();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/invert_if_statement.dart b/pkg/analysis_server/lib/src/services/correction/dart/invert_if_statement.dart
new file mode 100644
index 0000000..b632c3d
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/invert_if_statement.dart
@@ -0,0 +1,43 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+
+class InvertIfStatement extends CorrectionProducer {
+  @override
+  AssistKind get assistKind => DartAssistKind.INVERT_IF_STATEMENT;
+
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    if (node is! IfStatement) {
+      return;
+    }
+    var ifStatement = node as IfStatement;
+    var condition = ifStatement.condition;
+    // should have both "then" and "else"
+    var thenStatement = ifStatement.thenStatement;
+    var elseStatement = ifStatement.elseStatement;
+    if (thenStatement == null || elseStatement == null) {
+      return;
+    }
+    // prepare source
+    var invertedCondition = utils.invertCondition(condition);
+    var thenSource = utils.getNodeText(thenStatement);
+    var elseSource = utils.getNodeText(elseStatement);
+
+    await builder.addFileEdit(file, (DartFileEditBuilder builder) {
+      builder.addSimpleReplacement(range.node(condition), invertedCondition);
+      builder.addSimpleReplacement(range.node(thenStatement), elseSource);
+      builder.addSimpleReplacement(range.node(elseStatement), thenSource);
+    });
+  }
+
+  /// Return an instance of this class. Used as a tear-off in `AssistProcessor`.
+  static InvertIfStatement newInstance() => InvertIfStatement();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/join_if_with_inner.dart b/pkg/analysis_server/lib/src/services/correction/dart/join_if_with_inner.dart
new file mode 100644
index 0000000..82f33e7
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/join_if_with_inner.dart
@@ -0,0 +1,71 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analysis_server/src/services/correction/util.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+
+class JoinIfWithInner extends CorrectionProducer {
+  @override
+  AssistKind get assistKind => DartAssistKind.JOIN_IF_WITH_INNER;
+
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    // climb up condition to the (supposedly) "if" statement
+    var node = this.node;
+    while (node is Expression) {
+      node = node.parent;
+    }
+    // prepare target "if" statement
+    if (node is! IfStatement) {
+      return;
+    }
+    var targetIfStatement = node as IfStatement;
+    if (targetIfStatement.elseStatement != null) {
+      return;
+    }
+    // prepare inner "if" statement
+    var targetThenStatement = targetIfStatement.thenStatement;
+    var innerStatement = getSingleStatement(targetThenStatement);
+    if (innerStatement is! IfStatement) {
+      return;
+    }
+    var innerIfStatement = innerStatement as IfStatement;
+    if (innerIfStatement.elseStatement != null) {
+      return;
+    }
+    // prepare environment
+    var prefix = utils.getNodePrefix(targetIfStatement);
+    // merge conditions
+    var targetCondition = targetIfStatement.condition;
+    var innerCondition = innerIfStatement.condition;
+    var targetConditionSource = utils.getNodeText(targetCondition);
+    var innerConditionSource = utils.getNodeText(innerCondition);
+    if (shouldWrapParenthesisBeforeAnd(targetCondition)) {
+      targetConditionSource = '($targetConditionSource)';
+    }
+    if (shouldWrapParenthesisBeforeAnd(innerCondition)) {
+      innerConditionSource = '($innerConditionSource)';
+    }
+    var condition = '$targetConditionSource && $innerConditionSource';
+    // replace target "if" statement
+    var innerThenStatement = innerIfStatement.thenStatement;
+    var innerThenStatements = getStatements(innerThenStatement);
+    var lineRanges = utils.getLinesRangeStatements(innerThenStatements);
+    var oldSource = utils.getRangeText(lineRanges);
+    var newSource = utils.indentSourceLeftRight(oldSource);
+
+    await builder.addFileEdit(file, (DartFileEditBuilder builder) {
+      builder.addSimpleReplacement(range.node(targetIfStatement),
+          'if ($condition) {$eol$newSource$prefix}');
+    });
+  }
+
+  /// Return an instance of this class. Used as a tear-off in `AssistProcessor`.
+  static JoinIfWithInner newInstance() => JoinIfWithInner();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/join_if_with_outer.dart b/pkg/analysis_server/lib/src/services/correction/dart/join_if_with_outer.dart
new file mode 100644
index 0000000..5f61bae
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/join_if_with_outer.dart
@@ -0,0 +1,76 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analysis_server/src/services/correction/util.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+
+class JoinIfWithOuter extends CorrectionProducer {
+  @override
+  AssistKind get assistKind => DartAssistKind.JOIN_IF_WITH_OUTER;
+
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    // climb up condition to the (supposedly) "if" statement
+    var node = this.node;
+    while (node is Expression) {
+      node = node.parent;
+    }
+    // prepare target "if" statement
+    if (node is! IfStatement) {
+      return;
+    }
+    var targetIfStatement = node as IfStatement;
+    if (targetIfStatement.elseStatement != null) {
+      return;
+    }
+    // prepare outer "if" statement
+    var parent = targetIfStatement.parent;
+    if (parent is Block) {
+      if ((parent as Block).statements.length != 1) {
+        return;
+      }
+      parent = parent.parent;
+    }
+    if (parent is! IfStatement) {
+      return;
+    }
+    var outerIfStatement = parent as IfStatement;
+    if (outerIfStatement.elseStatement != null) {
+      return;
+    }
+    // prepare environment
+    var prefix = utils.getNodePrefix(outerIfStatement);
+    // merge conditions
+    var targetCondition = targetIfStatement.condition;
+    var outerCondition = outerIfStatement.condition;
+    var targetConditionSource = utils.getNodeText(targetCondition);
+    var outerConditionSource = utils.getNodeText(outerCondition);
+    if (shouldWrapParenthesisBeforeAnd(targetCondition)) {
+      targetConditionSource = '($targetConditionSource)';
+    }
+    if (shouldWrapParenthesisBeforeAnd(outerCondition)) {
+      outerConditionSource = '($outerConditionSource)';
+    }
+    var condition = '$outerConditionSource && $targetConditionSource';
+    // replace outer "if" statement
+    var targetThenStatement = targetIfStatement.thenStatement;
+    var targetThenStatements = getStatements(targetThenStatement);
+    var lineRanges = utils.getLinesRangeStatements(targetThenStatements);
+    var oldSource = utils.getRangeText(lineRanges);
+    var newSource = utils.indentSourceLeftRight(oldSource);
+
+    await builder.addFileEdit(file, (DartFileEditBuilder builder) {
+      builder.addSimpleReplacement(range.node(outerIfStatement),
+          'if ($condition) {$eol$newSource$prefix}');
+    });
+  }
+
+  /// Return an instance of this class. Used as a tear-off in `AssistProcessor`.
+  static JoinIfWithOuter newInstance() => JoinIfWithOuter();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/join_variable_declaration.dart b/pkg/analysis_server/lib/src/services/correction/dart/join_variable_declaration.dart
new file mode 100644
index 0000000..bba3f14
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/join_variable_declaration.dart
@@ -0,0 +1,145 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:_fe_analyzer_shared/src/scanner/token.dart';
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/ast/utilities.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+
+class JoinVariableDeclaration extends CorrectionProducer {
+  @override
+  AssistKind get assistKind => DartAssistKind.JOIN_VARIABLE_DECLARATION;
+
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    if (node is SimpleIdentifier) {
+      var parent = node.parent;
+      if (parent is AssignmentExpression &&
+          parent.leftHandSide == node &&
+          parent.parent is ExpressionStatement) {
+        await _joinOnAssignment(builder, parent);
+        return;
+      }
+    }
+    var declList = node.thisOrAncestorOfType<VariableDeclarationList>();
+    if (declList != null && declList.variables.length == 1) {
+      await _joinOnDeclaration(builder, declList);
+    }
+  }
+
+  /// Join the declaration when the variable is on the left-hand side of an
+  /// assignment.
+  Future<void> _joinOnAssignment(
+      DartChangeBuilder builder, AssignmentExpression assignExpression) async {
+    // Check that assignment is not a compound assignment.
+    if (assignExpression.operator.type != TokenType.EQ) {
+      return;
+    }
+    // prepare "declaration" statement
+    var element = (node as SimpleIdentifier).staticElement;
+    if (element == null) {
+      return;
+    }
+    var declOffset = element.nameOffset;
+    var unit = resolvedResult.unit;
+    var declNode = NodeLocator(declOffset).searchWithin(unit);
+    if (declNode != null &&
+        declNode.parent is VariableDeclaration &&
+        (declNode.parent as VariableDeclaration).name == declNode &&
+        declNode.parent.parent is VariableDeclarationList &&
+        declNode.parent.parent.parent is VariableDeclarationStatement) {
+    } else {
+      return;
+    }
+    var decl = declNode.parent as VariableDeclaration;
+    var declStatement = decl.parent.parent as VariableDeclarationStatement;
+    // may be has initializer
+    if (decl.initializer != null) {
+      return;
+    }
+    // check that "declaration" statement declared only one variable
+    if (declStatement.variables.variables.length != 1) {
+      return;
+    }
+    // check that the "declaration" and "assignment" statements are
+    // parts of the same Block
+    var assignStatement = node.parent.parent as ExpressionStatement;
+    if (assignStatement.parent is Block &&
+        assignStatement.parent == declStatement.parent) {
+    } else {
+      return;
+    }
+    var block = assignStatement.parent as Block;
+    // check that "declaration" and "assignment" statements are adjacent
+    List<Statement> statements = block.statements;
+    if (statements.indexOf(assignStatement) ==
+        statements.indexOf(declStatement) + 1) {
+    } else {
+      return;
+    }
+
+    await builder.addFileEdit(file, (DartFileEditBuilder builder) {
+      builder.addSimpleReplacement(
+          range.endStart(declNode, assignExpression.operator), ' ');
+    });
+  }
+
+  /// Join the declaration when the variable is on the left-hand side of an
+  /// assignment.
+  Future<void> _joinOnDeclaration(
+      DartChangeBuilder builder, VariableDeclarationList declList) async {
+    // prepare enclosing VariableDeclarationList
+    var decl = declList.variables[0];
+    // already initialized
+    if (decl.initializer != null) {
+      return;
+    }
+    // prepare VariableDeclarationStatement in Block
+    if (declList.parent is VariableDeclarationStatement &&
+        declList.parent.parent is Block) {
+    } else {
+      return;
+    }
+    var declStatement = declList.parent as VariableDeclarationStatement;
+    var block = declStatement.parent as Block;
+    List<Statement> statements = block.statements;
+    // prepare assignment
+    // declaration should not be last Statement
+    var declIndex = statements.indexOf(declStatement);
+    if (declIndex < statements.length - 1) {
+    } else {
+      return;
+    }
+    // next Statement should be assignment
+    var assignStatement = statements[declIndex + 1];
+    if (assignStatement is ExpressionStatement) {
+    } else {
+      return;
+    }
+    var expressionStatement = assignStatement as ExpressionStatement;
+    // expression should be assignment
+    if (expressionStatement.expression is AssignmentExpression) {
+    } else {
+      return;
+    }
+    var assignExpression =
+        expressionStatement.expression as AssignmentExpression;
+    // check that pure assignment
+    if (assignExpression.operator.type != TokenType.EQ) {
+      return;
+    }
+
+    await builder.addFileEdit(file, (DartFileEditBuilder builder) {
+      builder.addSimpleReplacement(
+          range.endStart(decl.name, assignExpression.operator), ' ');
+    });
+  }
+
+  /// Return an instance of this class. Used as a tear-off in `AssistProcessor`.
+  static JoinVariableDeclaration newInstance() => JoinVariableDeclaration();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/replace_conditional_with_if_else.dart b/pkg/analysis_server/lib/src/services/correction/dart/replace_conditional_with_if_else.dart
new file mode 100644
index 0000000..1ee5fb7
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/replace_conditional_with_if_else.dart
@@ -0,0 +1,117 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:_fe_analyzer_shared/src/scanner/token.dart';
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+
+class ReplaceConditionalWithIfElse extends CorrectionProducer {
+  @override
+  AssistKind get assistKind => DartAssistKind.REPLACE_CONDITIONAL_WITH_IF_ELSE;
+
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    ConditionalExpression conditional;
+    // may be on Statement with Conditional
+    var statement = node.thisOrAncestorOfType<Statement>();
+    if (statement == null) {
+      return;
+    }
+    // variable declaration
+    var inVariable = false;
+    if (statement is VariableDeclarationStatement) {
+      var variableStatement = statement;
+      for (var variable in variableStatement.variables.variables) {
+        if (variable.initializer is ConditionalExpression) {
+          conditional = variable.initializer as ConditionalExpression;
+          inVariable = true;
+          break;
+        }
+      }
+    }
+    // assignment
+    var inAssignment = false;
+    if (statement is ExpressionStatement) {
+      var exprStmt = statement;
+      if (exprStmt.expression is AssignmentExpression) {
+        var assignment = exprStmt.expression as AssignmentExpression;
+        if (assignment.operator.type == TokenType.EQ &&
+            assignment.rightHandSide is ConditionalExpression) {
+          conditional = assignment.rightHandSide as ConditionalExpression;
+          inAssignment = true;
+        }
+      }
+    }
+    // return
+    var inReturn = false;
+    if (statement is ReturnStatement) {
+      var returnStatement = statement;
+      if (returnStatement.expression is ConditionalExpression) {
+        conditional = returnStatement.expression as ConditionalExpression;
+        inReturn = true;
+      }
+    }
+    // prepare environment
+    var indent = utils.getIndent(1);
+    var prefix = utils.getNodePrefix(statement);
+
+    if (inVariable || inAssignment || inReturn) {
+      await builder.addFileEdit(file, (DartFileEditBuilder builder) {
+        // Type v = Conditional;
+        if (inVariable) {
+          var variable = conditional.parent as VariableDeclaration;
+          builder.addDeletion(range.endEnd(variable.name, conditional));
+          var conditionSrc = utils.getNodeText(conditional.condition);
+          var thenSrc = utils.getNodeText(conditional.thenExpression);
+          var elseSrc = utils.getNodeText(conditional.elseExpression);
+          var name = variable.name.name;
+          var src = eol;
+          src += prefix + 'if ($conditionSrc) {' + eol;
+          src += prefix + indent + '$name = $thenSrc;' + eol;
+          src += prefix + '} else {' + eol;
+          src += prefix + indent + '$name = $elseSrc;' + eol;
+          src += prefix + '}';
+          builder.addSimpleReplacement(range.endLength(statement, 0), src);
+        }
+        // v = Conditional;
+        if (inAssignment) {
+          var assignment = conditional.parent as AssignmentExpression;
+          var leftSide = assignment.leftHandSide;
+          var conditionSrc = utils.getNodeText(conditional.condition);
+          var thenSrc = utils.getNodeText(conditional.thenExpression);
+          var elseSrc = utils.getNodeText(conditional.elseExpression);
+          var name = utils.getNodeText(leftSide);
+          var src = '';
+          src += 'if ($conditionSrc) {' + eol;
+          src += prefix + indent + '$name = $thenSrc;' + eol;
+          src += prefix + '} else {' + eol;
+          src += prefix + indent + '$name = $elseSrc;' + eol;
+          src += prefix + '}';
+          builder.addSimpleReplacement(range.node(statement), src);
+        }
+        // return Conditional;
+        if (inReturn) {
+          var conditionSrc = utils.getNodeText(conditional.condition);
+          var thenSrc = utils.getNodeText(conditional.thenExpression);
+          var elseSrc = utils.getNodeText(conditional.elseExpression);
+          var src = '';
+          src += 'if ($conditionSrc) {' + eol;
+          src += prefix + indent + 'return $thenSrc;' + eol;
+          src += prefix + '} else {' + eol;
+          src += prefix + indent + 'return $elseSrc;' + eol;
+          src += prefix + '}';
+          builder.addSimpleReplacement(range.node(statement), src);
+        }
+      });
+    }
+  }
+
+  /// Return an instance of this class. Used as a tear-off in `AssistProcessor`.
+  static ReplaceConditionalWithIfElse newInstance() =>
+      ReplaceConditionalWithIfElse();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/replace_if_else_with_conditional.dart b/pkg/analysis_server/lib/src/services/correction/dart/replace_if_else_with_conditional.dart
new file mode 100644
index 0000000..afeaf2d
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/replace_if_else_with_conditional.dart
@@ -0,0 +1,83 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:_fe_analyzer_shared/src/scanner/token.dart';
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analysis_server/src/services/correction/util.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+
+class ReplaceIfElseWithConditional extends CorrectionProducer {
+  @override
+  AssistKind get assistKind => DartAssistKind.REPLACE_IF_ELSE_WITH_CONDITIONAL;
+
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    // should be "if"
+    if (node is! IfStatement) {
+      return;
+    }
+    var ifStatement = node as IfStatement;
+    // single then/else statements
+    var thenStatement = getSingleStatement(ifStatement.thenStatement);
+    var elseStatement = getSingleStatement(ifStatement.elseStatement);
+    if (thenStatement == null || elseStatement == null) {
+      return;
+    }
+    Expression thenExpression;
+    Expression elseExpression;
+    var hasReturnStatements = false;
+    if (thenStatement is ReturnStatement && elseStatement is ReturnStatement) {
+      hasReturnStatements = true;
+      thenExpression = thenStatement.expression;
+      elseExpression = elseStatement.expression;
+    }
+    var hasExpressionStatements = false;
+    if (thenStatement is ExpressionStatement &&
+        elseStatement is ExpressionStatement) {
+      if (thenStatement.expression is AssignmentExpression &&
+          elseStatement.expression is AssignmentExpression) {
+        hasExpressionStatements = true;
+        thenExpression = thenStatement.expression;
+        elseExpression = elseStatement.expression;
+      }
+    }
+
+    if (hasReturnStatements || hasExpressionStatements) {
+      await builder.addFileEdit(file, (DartFileEditBuilder builder) {
+        // returns
+        if (hasReturnStatements) {
+          var conditionSrc = utils.getNodeText(ifStatement.condition);
+          var theSrc = utils.getNodeText(thenExpression);
+          var elseSrc = utils.getNodeText(elseExpression);
+          builder.addSimpleReplacement(range.node(ifStatement),
+              'return $conditionSrc ? $theSrc : $elseSrc;');
+        }
+        // assignments -> v = Conditional;
+        if (hasExpressionStatements) {
+          AssignmentExpression thenAssignment = thenExpression;
+          AssignmentExpression elseAssignment = elseExpression;
+          var thenTarget = utils.getNodeText(thenAssignment.leftHandSide);
+          var elseTarget = utils.getNodeText(elseAssignment.leftHandSide);
+          if (thenAssignment.operator.type == TokenType.EQ &&
+              elseAssignment.operator.type == TokenType.EQ &&
+              thenTarget == elseTarget) {
+            var conditionSrc = utils.getNodeText(ifStatement.condition);
+            var theSrc = utils.getNodeText(thenAssignment.rightHandSide);
+            var elseSrc = utils.getNodeText(elseAssignment.rightHandSide);
+            builder.addSimpleReplacement(range.node(ifStatement),
+                '$thenTarget = $conditionSrc ? $theSrc : $elseSrc;');
+          }
+        }
+      });
+    }
+  }
+
+  /// Return an instance of this class. Used as a tear-off in `AssistProcessor`.
+  static ReplaceIfElseWithConditional newInstance() =>
+      ReplaceIfElseWithConditional();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/split_variable_declaration.dart b/pkg/analysis_server/lib/src/services/correction/dart/split_variable_declaration.dart
new file mode 100644
index 0000000..088e644
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/split_variable_declaration.dart
@@ -0,0 +1,67 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:_fe_analyzer_shared/src/scanner/token.dart';
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+
+class SplitVariableDeclaration extends CorrectionProducer {
+  @override
+  AssistKind get assistKind => DartAssistKind.SPLIT_VARIABLE_DECLARATION;
+
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    var variableList = node?.thisOrAncestorOfType<VariableDeclarationList>();
+
+    // Must be a local variable declaration.
+    if (variableList?.parent is! VariableDeclarationStatement) {
+      return;
+    }
+    VariableDeclarationStatement statement = variableList.parent;
+
+    // Cannot be `const` or `final`.
+    var keywordKind = variableList.keyword?.keyword;
+    if (keywordKind == Keyword.CONST || keywordKind == Keyword.FINAL) {
+      return;
+    }
+
+    var variables = variableList.variables;
+    if (variables.length != 1) {
+      return;
+    }
+
+    // The caret must be between the type and the variable name.
+    var variable = variables[0];
+    if (!range.startEnd(statement, variable.name).contains(selectionOffset)) {
+      return;
+    }
+
+    // The variable must have an initializer.
+    if (variable.initializer == null) {
+      return;
+    }
+
+    await builder.addFileEdit(file, (builder) {
+      if (variableList.type == null) {
+        final type = variable.declaredElement.type;
+        if (!type.isDynamic) {
+          builder.addReplacement(range.token(variableList.keyword), (builder) {
+            builder.writeType(type);
+          });
+        }
+      }
+
+      var indent = utils.getNodePrefix(statement);
+      var name = variable.name.name;
+      builder.addSimpleInsertion(variable.name.end, ';' + eol + indent + name);
+    });
+  }
+
+  /// Return an instance of this class. Used as a tear-off in `AssistProcessor`.
+  static SplitVariableDeclaration newInstance() => SplitVariableDeclaration();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/surround_with.dart b/pkg/analysis_server/lib/src/services/correction/dart/surround_with.dart
new file mode 100644
index 0000000..a66877f
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/surround_with.dart
@@ -0,0 +1,364 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analysis_server/src/services/correction/statement_analyzer.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/source/source_range.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+
+class SurroundWith extends MultiCorrectionProducer {
+  @override
+  Iterable<CorrectionProducer> get producers sync* {
+    // prepare selected statements
+    var selectionAnalyzer = StatementAnalyzer(
+        resolvedResult, SourceRange(selectionOffset, selectionLength));
+    selectionAnalyzer.analyze();
+    var selectedNodes = selectionAnalyzer.selectedNodes;
+    // convert nodes to statements
+    var selectedStatements = <Statement>[];
+    for (var selectedNode in selectedNodes) {
+      if (selectedNode is Statement) {
+        selectedStatements.add(selectedNode);
+      }
+    }
+    // we want only statements in blocks
+    for (var statement in selectedStatements) {
+      if (statement.parent is! Block) {
+        return;
+      }
+    }
+    // we want only statements
+    if (selectedStatements.isEmpty ||
+        selectedStatements.length != selectedNodes.length) {
+      return;
+    }
+    // prepare statement information
+    var firstStatement = selectedStatements[0];
+    var statementsRange = utils.getLinesRangeStatements(selectedStatements);
+    // prepare environment
+    var indentOld = utils.getNodePrefix(firstStatement);
+    var indentNew = '$indentOld${utils.getIndent(1)}';
+    var indentedCode =
+        utils.replaceSourceRangeIndent(statementsRange, indentOld, indentNew);
+
+    yield _SurroundWithBlock(
+        statementsRange, indentOld, indentNew, indentedCode);
+    yield _SurroundWithDoWhile(
+        statementsRange, indentOld, indentNew, indentedCode);
+    yield _SurroundWithFor(statementsRange, indentOld, indentNew, indentedCode);
+    yield _SurroundWithForIn(
+        statementsRange, indentOld, indentNew, indentedCode);
+    yield _SurroundWithIf(statementsRange, indentOld, indentNew, indentedCode);
+    yield _SurroundWithSetState(
+        statementsRange, indentOld, indentNew, indentedCode);
+    yield _SurroundWithTryCatch(
+        statementsRange, indentOld, indentNew, indentedCode);
+    yield _SurroundWithTryFinally(
+        statementsRange, indentOld, indentNew, indentedCode);
+    yield _SurroundWithWhile(
+        statementsRange, indentOld, indentNew, indentedCode);
+  }
+
+  /// Return an instance of this class. Used as a tear-off in `AssistProcessor`.
+  static SurroundWith newInstance() => SurroundWith();
+}
+
+/// A correction processor that can make one of the possible change computed by
+/// the [SurroundWith] producer.
+abstract class _SurroundWith extends CorrectionProducer {
+  final SourceRange statementsRange;
+
+  final String indentOld;
+
+  final String indentNew;
+
+  final String indentedCode;
+
+  _SurroundWith(
+      this.statementsRange, this.indentOld, this.indentNew, this.indentedCode);
+}
+
+/// A correction processor that can make one of the possible change computed by
+/// the [SurroundWith] producer.
+class _SurroundWithBlock extends _SurroundWith {
+  _SurroundWithBlock(SourceRange statementsRange, String indentOld,
+      String indentNew, String indentedCode)
+      : super(statementsRange, indentOld, indentNew, indentedCode);
+
+  @override
+  AssistKind get assistKind => DartAssistKind.SURROUND_WITH_BLOCK;
+
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    await builder.addFileEdit(file, (DartFileEditBuilder builder) {
+      builder.addSimpleInsertion(statementsRange.offset, '$indentOld{$eol');
+      builder.addSimpleReplacement(
+          statementsRange,
+          utils.replaceSourceRangeIndent(
+              statementsRange, indentOld, indentNew));
+      builder.addSimpleInsertion(statementsRange.end, '$indentOld}$eol');
+    });
+  }
+}
+
+/// A correction processor that can make one of the possible change computed by
+/// the [SurroundWith] producer.
+class _SurroundWithDoWhile extends _SurroundWith {
+  _SurroundWithDoWhile(SourceRange statementsRange, String indentOld,
+      String indentNew, String indentedCode)
+      : super(statementsRange, indentOld, indentNew, indentedCode);
+
+  @override
+  AssistKind get assistKind => DartAssistKind.SURROUND_WITH_DO_WHILE;
+
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    await builder.addFileEdit(file, (DartFileEditBuilder builder) {
+      builder.addReplacement(statementsRange, (DartEditBuilder builder) {
+        builder.write(indentOld);
+        builder.write('do {');
+        builder.write(eol);
+        builder.write(indentedCode);
+        builder.write(indentOld);
+        builder.write('} while (');
+        builder.addSimpleLinkedEdit('CONDITION', 'condition');
+        builder.write(');');
+        builder.selectHere();
+        builder.write(eol);
+      });
+    });
+  }
+}
+
+/// A correction processor that can make one of the possible change computed by
+/// the [SurroundWith] producer.
+class _SurroundWithFor extends _SurroundWith {
+  _SurroundWithFor(SourceRange statementsRange, String indentOld,
+      String indentNew, String indentedCode)
+      : super(statementsRange, indentOld, indentNew, indentedCode);
+
+  @override
+  AssistKind get assistKind => DartAssistKind.SURROUND_WITH_FOR;
+
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    await builder.addFileEdit(file, (DartFileEditBuilder builder) {
+      builder.addReplacement(statementsRange, (DartEditBuilder builder) {
+        builder.write(indentOld);
+        builder.write('for (var ');
+        builder.addSimpleLinkedEdit('VAR', 'v');
+        builder.write(' = ');
+        builder.addSimpleLinkedEdit('INIT', 'init');
+        builder.write('; ');
+        builder.addSimpleLinkedEdit('CONDITION', 'condition');
+        builder.write('; ');
+        builder.addSimpleLinkedEdit('INCREMENT', 'increment');
+        builder.write(') {');
+        builder.write(eol);
+        builder.write(indentedCode);
+        builder.write(indentOld);
+        builder.write('}');
+        builder.selectHere();
+        builder.write(eol);
+      });
+    });
+  }
+}
+
+/// A correction processor that can make one of the possible change computed by
+/// the [SurroundWith] producer.
+class _SurroundWithForIn extends _SurroundWith {
+  _SurroundWithForIn(SourceRange statementsRange, String indentOld,
+      String indentNew, String indentedCode)
+      : super(statementsRange, indentOld, indentNew, indentedCode);
+
+  @override
+  AssistKind get assistKind => DartAssistKind.SURROUND_WITH_FOR_IN;
+
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    await builder.addFileEdit(file, (DartFileEditBuilder builder) {
+      builder.addReplacement(statementsRange, (DartEditBuilder builder) {
+        builder.write(indentOld);
+        builder.write('for (var ');
+        builder.addSimpleLinkedEdit('NAME', 'item');
+        builder.write(' in ');
+        builder.addSimpleLinkedEdit('ITERABLE', 'iterable');
+        builder.write(') {');
+        builder.write(eol);
+        builder.write(indentedCode);
+        builder.write(indentOld);
+        builder.write('}');
+        builder.selectHere();
+        builder.write(eol);
+      });
+    });
+  }
+}
+
+/// A correction processor that can make one of the possible change computed by
+/// the [SurroundWith] producer.
+class _SurroundWithIf extends _SurroundWith {
+  _SurroundWithIf(SourceRange statementsRange, String indentOld,
+      String indentNew, String indentedCode)
+      : super(statementsRange, indentOld, indentNew, indentedCode);
+
+  @override
+  AssistKind get assistKind => DartAssistKind.SURROUND_WITH_IF;
+
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    await builder.addFileEdit(file, (DartFileEditBuilder builder) {
+      builder.addReplacement(statementsRange, (DartEditBuilder builder) {
+        builder.write(indentOld);
+        builder.write('if (');
+        builder.addSimpleLinkedEdit('CONDITION', 'condition');
+        builder.write(') {');
+        builder.write(eol);
+        builder.write(indentedCode);
+        builder.write(indentOld);
+        builder.write('}');
+        builder.selectHere();
+        builder.write(eol);
+      });
+    });
+  }
+}
+
+/// A correction processor that can make one of the possible change computed by
+/// the [SurroundWith] producer.
+class _SurroundWithSetState extends _SurroundWith {
+  _SurroundWithSetState(SourceRange statementsRange, String indentOld,
+      String indentNew, String indentedCode)
+      : super(statementsRange, indentOld, indentNew, indentedCode);
+
+  @override
+  AssistKind get assistKind => DartAssistKind.SURROUND_WITH_SET_STATE;
+
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    var classDeclaration = node.parent.thisOrAncestorOfType<ClassDeclaration>();
+    if (classDeclaration != null &&
+        flutter.isState(classDeclaration.declaredElement)) {
+      await builder.addFileEdit(file, (DartFileEditBuilder builder) {
+        builder.addReplacement(statementsRange, (DartEditBuilder builder) {
+          builder.write(indentOld);
+          builder.writeln('setState(() {');
+          builder.write(indentedCode);
+          builder.write(indentOld);
+          builder.selectHere();
+          builder.writeln('});');
+        });
+      });
+    }
+  }
+}
+
+/// A correction processor that can make one of the possible change computed by
+/// the [SurroundWith] producer.
+class _SurroundWithTryCatch extends _SurroundWith {
+  _SurroundWithTryCatch(SourceRange statementsRange, String indentOld,
+      String indentNew, String indentedCode)
+      : super(statementsRange, indentOld, indentNew, indentedCode);
+
+  @override
+  AssistKind get assistKind => DartAssistKind.SURROUND_WITH_TRY_CATCH;
+
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    await builder.addFileEdit(file, (DartFileEditBuilder builder) {
+      builder.addReplacement(statementsRange, (DartEditBuilder builder) {
+        builder.write(indentOld);
+        builder.write('try {');
+        builder.write(eol);
+        builder.write(indentedCode);
+        builder.write(indentOld);
+        builder.write('} on ');
+        builder.addSimpleLinkedEdit('EXCEPTION_TYPE', 'Exception');
+        builder.write(' catch (');
+        builder.addSimpleLinkedEdit('EXCEPTION_VAR', 'e');
+        builder.write(') {');
+        builder.write(eol);
+        //
+        builder.write(indentNew);
+        builder.addSimpleLinkedEdit('CATCH', '// TODO');
+        builder.selectHere();
+        builder.write(eol);
+        //
+        builder.write(indentOld);
+        builder.write('}');
+        builder.write(eol);
+      });
+    });
+  }
+}
+
+/// A correction processor that can make one of the possible change computed by
+/// the [SurroundWith] producer.
+class _SurroundWithTryFinally extends _SurroundWith {
+  _SurroundWithTryFinally(SourceRange statementsRange, String indentOld,
+      String indentNew, String indentedCode)
+      : super(statementsRange, indentOld, indentNew, indentedCode);
+
+  @override
+  AssistKind get assistKind => DartAssistKind.SURROUND_WITH_TRY_FINALLY;
+
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    await builder.addFileEdit(file, (DartFileEditBuilder builder) {
+      builder.addReplacement(statementsRange, (DartEditBuilder builder) {
+        builder.write(indentOld);
+        builder.write('try {');
+        builder.write(eol);
+        //
+        builder.write(indentedCode);
+        //
+        builder.write(indentOld);
+        builder.write('} finally {');
+        builder.write(eol);
+        //
+        builder.write(indentNew);
+        builder.addSimpleLinkedEdit('FINALLY', '// TODO');
+        builder.selectHere();
+        builder.write(eol);
+        //
+        builder.write(indentOld);
+        builder.write('}');
+        builder.write(eol);
+      });
+    });
+  }
+}
+
+/// A correction processor that can make one of the possible change computed by
+/// the [SurroundWith] producer.
+class _SurroundWithWhile extends _SurroundWith {
+  _SurroundWithWhile(SourceRange statementsRange, String indentOld,
+      String indentNew, String indentedCode)
+      : super(statementsRange, indentOld, indentNew, indentedCode);
+
+  @override
+  AssistKind get assistKind => DartAssistKind.SURROUND_WITH_WHILE;
+
+  @override
+  Future<void> compute(DartChangeBuilder builder) async {
+    await builder.addFileEdit(file, (DartFileEditBuilder builder) {
+      builder.addReplacement(statementsRange, (DartEditBuilder builder) {
+        builder.write(indentOld);
+        builder.write('while (');
+        builder.addSimpleLinkedEdit('CONDITION', 'condition');
+        builder.write(') {');
+        builder.write(eol);
+        builder.write(indentedCode);
+        builder.write(indentOld);
+        builder.write('}');
+        builder.selectHere();
+        builder.write(eol);
+      });
+    });
+  }
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/fix.dart b/pkg/analysis_server/lib/src/services/correction/fix.dart
index 3983092..a24e389 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix.dart
@@ -154,6 +154,8 @@
       'dart.fix.add.fieldFormalParameters',
       70,
       'Add final field formal parameters');
+  static const ADD_LATE =
+      FixKind('dart.fix.add.late', 50, "Add 'late' modifier");
   static const ADD_MISSING_ENUM_CASE_CLAUSES = FixKind(
       'dart.fix.add.missingEnumCaseClauses', 50, 'Add missing case clauses');
   static const ADD_MISSING_PARAMETER_NAMED = FixKind(
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index 82bcb0d..3b987e9 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -15,6 +15,7 @@
 import 'package:analysis_server/src/services/correction/dart/add_diagnostic_property_reference.dart';
 import 'package:analysis_server/src/services/correction/dart/add_explicit_cast.dart';
 import 'package:analysis_server/src/services/correction/dart/add_field_formal_parameters.dart';
+import 'package:analysis_server/src/services/correction/dart/add_late.dart';
 import 'package:analysis_server/src/services/correction/dart/add_missing_enum_case_clauses.dart';
 import 'package:analysis_server/src/services/correction/dart/add_missing_parameter.dart';
 import 'package:analysis_server/src/services/correction/dart/add_missing_parameter_named.dart';
@@ -627,6 +628,9 @@
       ChangeTo.classOrMixin,
       CreateClass.newInstance,
     ],
+    CompileTimeErrorCode.NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD: [
+      AddLate.newInstance,
+    ],
     CompileTimeErrorCode.NULLABLE_TYPE_IN_EXTENDS_CLAUSE: [
       RemoveQuestionMark.newInstance,
     ],
@@ -912,6 +916,7 @@
       RemoveDeadIfNull.newInstance,
     ],
     StaticWarningCode.FINAL_NOT_INITIALIZED: [
+      AddLate.newInstance,
       CreateConstructorForFinalFields.newInstance,
     ],
     StaticWarningCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_1: [
diff --git a/pkg/analysis_server/pubspec.yaml b/pkg/analysis_server/pubspec.yaml
index 03a88e3..d82ba92 100644
--- a/pkg/analysis_server/pubspec.yaml
+++ b/pkg/analysis_server/pubspec.yaml
@@ -1,4 +1,5 @@
 name: analysis_server
+# This package is not intended for consumption on pub.dev. DO NOT publish.
 publish_to: none
 
 environment:
diff --git a/pkg/analysis_server/test/client/completion_driver_test.dart b/pkg/analysis_server/test/client/completion_driver_test.dart
index e318791..2311453 100644
--- a/pkg/analysis_server/test/client/completion_driver_test.dart
+++ b/pkg/analysis_server/test/client/completion_driver_test.dart
@@ -695,7 +695,7 @@
 
     // + Top level variables.
     assertSuggestion(
-        completion: 'PI',
+        completion: 'pi',
         file: '/sdk/lib/math/math.dart',
         element: ElementKind.TOP_LEVEL_VARIABLE,
         kind: CompletionSuggestionKind.INVOCATION);
diff --git a/pkg/analysis_server/test/completion_test.dart b/pkg/analysis_server/test/completion_test.dart
index d98a7c5..f5f37f4 100644
--- a/pkg/analysis_server/test/completion_test.dart
+++ b/pkg/analysis_server/test/completion_test.dart
@@ -811,23 +811,23 @@
 
     buildTests('testCompletion_combinator_afterComma', '''
 import 'dart:math' show cos, !1;''',
-        <String>['1+PI', '1+sin', '1+Random', '1-String']);
+        <String>['1+pi', '1+sin', '1+Random', '1-String']);
 
     buildTests('testCompletion_combinator_ended', '''
 import 'dart:math' show !1;"''',
-        <String>['1+PI', '1+sin', '1+Random', '1-String']);
+        <String>['1+pi', '1+sin', '1+Random', '1-String']);
 
     buildTests('testCompletion_combinator_export', '''
 export 'dart:math' show !1;"''',
-        <String>['1+PI', '1+sin', '1+Random', '1-String']);
+        <String>['1+pi', '1+sin', '1+Random', '1-String']);
 
     buildTests('testCompletion_combinator_hide', '''
 import 'dart:math' hide !1;"''',
-        <String>['1+PI', '1+sin', '1+Random', '1-String']);
+        <String>['1+pi', '1+sin', '1+Random', '1-String']);
 
     buildTests('testCompletion_combinator_notEnded', '''
 import 'dart:math' show !1"''',
-        <String>['1+PI', '1+sin', '1+Random', '1-String']);
+        <String>['1+pi', '1+sin', '1+Random', '1-String']);
 
     buildTests('testCompletion_combinator_usePrefix', '''
 import 'dart:math' show s!1"''',
@@ -1615,16 +1615,16 @@
         failingTests: '1');
 
     buildTests('test_importPrefix_hideCombinator', '''
-import 'dart:math' as math hide PI;
+import 'dart:math' as math hide pi;
 main() {
   math.!1
-}''', <String>['1-PI', '1+LN10']);
+}''', <String>['1-pi', '1+ln10']);
 
     buildTests('test_importPrefix_showCombinator', '''
-import 'dart:math' as math show PI;
+import 'dart:math' as math show pi;
 main() {
   math.!1
-}''', <String>['1+PI', '1-LN10']);
+}''', <String>['1+pi', '1-ln10']);
 
     sources.clear();
     sources['/lib.dart'] = '''
diff --git a/pkg/analysis_server/test/edit/organize_directives_test.dart b/pkg/analysis_server/test/edit/organize_directives_test.dart
index dff0f63..618c6d6 100644
--- a/pkg/analysis_server/test/edit/organize_directives_test.dart
+++ b/pkg/analysis_server/test/edit/organize_directives_test.dart
@@ -130,7 +130,7 @@
 import 'dart:collection';
 
 main() {
-  print(PI);
+  print(pi);
   new HashMap();
 }
 ''');
@@ -141,7 +141,7 @@
 import 'dart:math';
 
 main() {
-  print(PI);
+  print(pi);
   new HashMap();
 }
 ''');
diff --git a/pkg/analysis_server/test/edit/refactoring_test.dart b/pkg/analysis_server/test/edit/refactoring_test.dart
index 4ae3ed16..acf5f34 100644
--- a/pkg/analysis_server/test/edit/refactoring_test.dart
+++ b/pkg/analysis_server/test/edit/refactoring_test.dart
@@ -992,9 +992,9 @@
 import 'dart:async' as test;
 import 'dart:math' as test;
 main() {
-  test.PI;
+  test.pi;
 }
-''', 'test.PI;');
+''', 'test.pi;');
   }
 
   Future test_rename_hasElement_instanceGetter() {
diff --git a/pkg/analysis_server/test/lsp/completion_test.dart b/pkg/analysis_server/test/lsp/completion_test.dart
index 59b9095..52cad68 100644
--- a/pkg/analysis_server/test/lsp/completion_test.dart
+++ b/pkg/analysis_server/test/lsp/completion_test.dart
@@ -417,7 +417,7 @@
     expect(updated, contains('a.abcdefghij'));
   }
 
-  Future<void> test_prefixFilter() async {
+  Future<void> test_prefixFilter_endOfSymbol() async {
     final content = '''
     class UniqueNamedClassForLspOne {}
     class UniqueNamedClassForLspTwo {}
@@ -425,7 +425,7 @@
 
     main() {
       // Should match only Two and Three
-      class UniqueNamedClassForLspT^
+      UniqueNamedClassForLspT^
     }
     ''';
 
@@ -437,6 +437,46 @@
     expect(res.any((c) => c.label == 'UniqueNamedClassForLspThree'), isTrue);
   }
 
+  Future<void> test_prefixFilter_midSymbol() async {
+    final content = '''
+    class UniqueNamedClassForLspOne {}
+    class UniqueNamedClassForLspTwo {}
+    class UniqueNamedClassForLspThree {}
+
+    main() {
+      // Should match only Two and Three
+      UniqueNamedClassForLspT^hree
+    }
+    ''';
+
+    await initialize();
+    await openFile(mainFileUri, withoutMarkers(content));
+    final res = await getCompletion(mainFileUri, positionFromMarker(content));
+    expect(res.any((c) => c.label == 'UniqueNamedClassForLspOne'), isFalse);
+    expect(res.any((c) => c.label == 'UniqueNamedClassForLspTwo'), isTrue);
+    expect(res.any((c) => c.label == 'UniqueNamedClassForLspThree'), isTrue);
+  }
+
+  Future<void> test_prefixFilter_startOfSymbol() async {
+    final content = '''
+    class UniqueNamedClassForLspOne {}
+    class UniqueNamedClassForLspTwo {}
+    class UniqueNamedClassForLspThree {}
+
+    main() {
+      // Should match all three
+      ^UniqueNamedClassForLspT
+    }
+    ''';
+
+    await initialize();
+    await openFile(mainFileUri, withoutMarkers(content));
+    final res = await getCompletion(mainFileUri, positionFromMarker(content));
+    expect(res.any((c) => c.label == 'UniqueNamedClassForLspOne'), isTrue);
+    expect(res.any((c) => c.label == 'UniqueNamedClassForLspTwo'), isTrue);
+    expect(res.any((c) => c.label == 'UniqueNamedClassForLspThree'), isTrue);
+  }
+
   Future<void> test_suggestionSets() async {
     newFile(
       join(projectFolderPath, 'other_file.dart'),
diff --git a/pkg/analysis_server/test/services/completion/dart/combinator_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/combinator_contributor_test.dart
index ec3822e..f984fb0 100644
--- a/pkg/analysis_server/test/services/completion/dart/combinator_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/combinator_contributor_test.dart
@@ -153,10 +153,10 @@
     assertNotSuggested('B');
   }
 
-  Future<void> test_Combinator_show_PI() async {
+  Future<void> test_Combinator_show_pi() async {
     addTestSource('import "dart:math" show ^;');
     await computeSuggestions();
-    assertSuggestTopLevelVar('PI', 'double',
+    assertSuggestTopLevelVar('pi', 'double',
         kind: CompletionSuggestionKind.IDENTIFIER);
   }
 
diff --git a/pkg/analysis_server/test/services/completion/dart/relevance/bool_assignment_relevance_test.dart b/pkg/analysis_server/test/services/completion/dart/relevance/bool_assignment_relevance_test.dart
index 3e64f9e..5c01e77 100644
--- a/pkg/analysis_server/test/services/completion/dart/relevance/bool_assignment_relevance_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/relevance/bool_assignment_relevance_test.dart
@@ -56,6 +56,6 @@
         element: ElementKind.LOCAL_VARIABLE,
         kind: CompletionSuggestionKind.INVOCATION);
 
-    assertOrder([trueSuggestion, falseSuggestion, bLocalVar]);
+    assertOrder([bLocalVar, trueSuggestion, falseSuggestion]);
   }
 }
diff --git a/pkg/analysis_server/test/services/correction/organize_directives_test.dart b/pkg/analysis_server/test/services/correction/organize_directives_test.dart
index c1dd563..78175d0 100644
--- a/pkg/analysis_server/test/services/correction/organize_directives_test.dart
+++ b/pkg/analysis_server/test/services/correction/organize_directives_test.dart
@@ -140,7 +140,7 @@
 import 'dart:collection';
 
 main() {
-  print(PI);
+  print(pi);
   new HashMap();
 }
 ''');
@@ -152,7 +152,7 @@
 import 'dart:math';
 
 main() {
-  print(PI);
+  print(pi);
   new HashMap();
 }
 ''', removeUnused: true);
diff --git a/pkg/analysis_server/test/services/refactoring/rename_import_test.dart b/pkg/analysis_server/test/services/refactoring/rename_import_test.dart
index 7c7bc63..da9fa1c 100644
--- a/pkg/analysis_server/test/services/refactoring/rename_import_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/rename_import_test.dart
@@ -166,12 +166,12 @@
 import 'dart:math' as test;
 main() {
   test.Future f;
-  test.PI;
-  test.E;
+  test.pi;
+  test.e;
 }
 ''');
     // configure refactoring
-    createRenameRefactoringAtString('test.PI');
+    createRenameRefactoringAtString('test.pi');
     expect(refactoring.refactoringName, 'Rename Import Prefix');
     expect(refactoring.oldName, 'test');
     refactoring.newName = 'newName';
@@ -181,8 +181,8 @@
 import 'dart:math' as newName;
 main() {
   test.Future f;
-  newName.PI;
-  newName.E;
+  newName.pi;
+  newName.e;
 }
 ''');
   }
diff --git a/pkg/analysis_server/test/src/cider/completion_test.dart b/pkg/analysis_server/test/src/cider/completion_test.dart
index ed599c0..e0e3371 100644
--- a/pkg/analysis_server/test/src/cider/completion_test.dart
+++ b/pkg/analysis_server/test/src/cider/completion_test.dart
@@ -52,6 +52,40 @@
     _assertNoClass(text: 'Random');
   }
 
+  Future<void> test_compute_performance_operations() async {
+    await _compute(r'''
+main() {
+  ^
+}
+''');
+
+    _assertHasOperationPerformance(['resolution']);
+    _assertHasOperationPerformance(['suggestions']);
+    _assertHasOperationPerformance([
+      'suggestions',
+      'DartCompletionManager - KeywordContributor',
+    ]);
+  }
+
+  Future<void> test_compute_performance_timers() async {
+    await _compute(r'''
+main() {
+  ^
+}
+''');
+
+    void assertTimerNotEmpty(Duration duration) {
+      expect(duration, isNotNull);
+      expect(duration, isNot(Duration.zero));
+    }
+
+    var performance = _completionResult.performance;
+    assertTimerNotEmpty(performance.file);
+    assertTimerNotEmpty(performance.imports);
+    assertTimerNotEmpty(performance.resolution);
+    assertTimerNotEmpty(performance.suggestions);
+  }
+
   Future<void> test_compute_prefixStart_hasPrefix() async {
     await _compute('''
 class A {
@@ -278,6 +312,30 @@
     ]);
   }
 
+  Future<void> test_warmUp_cachesImportedLibraries() async {
+    var aPath = convertPath('/workspace/dart/test/lib/a.dart');
+    newFile(aPath, content: r'''
+class A {}
+''');
+
+    var bPath = convertPath('/workspace/dart/test/lib/b.dart');
+    newFile(bPath, content: r'''
+import 'a.dart';
+''');
+
+    // Pre-cache `a.dart` using import in `b.dart`
+    await _newComputer().warmUp([bPath]);
+    _assertComputedImportedLibraries([aPath], hasCore: true);
+
+    // Now we complete in `test.dart`, and `a.dart` is already cached.
+    await _compute(r'''
+import 'a.dart';
+^
+''');
+    _assertComputedImportedLibraries([]);
+    _assertHasClass(text: 'A');
+  }
+
   void _assertComputedImportedLibraries(
     List<String> expected, {
     bool hasCore = false,
@@ -328,6 +386,15 @@
     return matching.single;
   }
 
+  void _assertHasOperationPerformance(List<String> path) {
+    var current = _completionResult.performance.operations;
+    for (var name in path) {
+      var child = current.getChild(name);
+      expect(child, isNotNull, reason: "No '$name' in $current");
+      current = child;
+    }
+  }
+
   CompletionSuggestion _assertHasTopLevelVariable({@required String text}) {
     var matching = _matchingCompletions(
       text: text,
diff --git a/pkg/analysis_server/test/src/services/completion/dart/feature_computer_test.dart b/pkg/analysis_server/test/src/services/completion/dart/feature_computer_test.dart
index cd03280..6684dc5 100644
--- a/pkg/analysis_server/test/src/services/completion/dart/feature_computer_test.dart
+++ b/pkg/analysis_server/test/src/services/completion/dart/feature_computer_test.dart
@@ -268,7 +268,7 @@
   Future<void> test_assignmentExpression_withoutType() async {
     await assertContextType('''
 void g(String s) {
-  var i = ^s.length;
+  var x = ^s.length;
 }
 ''', null);
   }
@@ -332,15 +332,39 @@
   Future<void> test_fieldDeclaration_var() async {
     await assertContextType('''
 class Foo {
-  var i =^;
+  var x =^;
 }
 ''', null);
   }
 
+  Future<void> test_fieldDeclaration_var_impliedType_int() async {
+    await assertContextType('''
+class Foo {
+  var i = ^ ;
+}
+''', 'int');
+  }
+
+  Future<void> test_fieldDeclaration_var_impliedType_list() async {
+    await assertContextType('''
+class Foo {
+  var list = ^ ;
+}
+''', 'List<dynamic>');
+  }
+
+  Future<void> test_fieldDeclaration_var_impliedType_string() async {
+    await assertContextType('''
+class Foo {
+  var string = ^ ;
+}
+''', 'String');
+  }
+
   Future<void> test_fieldDeclaration_var_whitespace() async {
     await assertContextType('''
 class Foo {
-  var i = ^ ;
+  var x = ^ ;
 }
 ''', null);
   }
@@ -534,13 +558,19 @@
 
   Future<void> test_topLevelVariableDeclaration_var() async {
     await assertContextType('''
-var i=^;
+var x=^;
+''', null);
+  }
+
+  Future<void> test_topLevelVariableDeclaration_var_noEqual() async {
+    await assertContextType('''
+int x^;
 ''', null);
   }
 
   Future<void> test_topLevelVariableDeclaration_var_whitespace() async {
     await assertContextType('''
-var i=  ^  ;
+var x=  ^  ;
 ''', null);
   }
 }
diff --git a/pkg/analysis_server/test/src/services/correction/assist/add_not_null_assert.dart b/pkg/analysis_server/test/src/services/correction/assist/add_not_null_assert_test.dart
similarity index 93%
rename from pkg/analysis_server/test/src/services/correction/assist/add_not_null_assert.dart
rename to pkg/analysis_server/test/src/services/correction/assist/add_not_null_assert_test.dart
index bd8122e..92c6865 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/add_not_null_assert.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/add_not_null_assert_test.dart
@@ -10,12 +10,12 @@
 
 void main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(AddNotNullAssert);
+    defineReflectiveTests(AddNotNullAssertTest);
   });
 }
 
 @reflectiveTest
-class AddNotNullAssert extends AssistProcessorTest {
+class AddNotNullAssertTest extends AssistProcessorTest {
   @override
   AssistKind get kind => DartAssistKind.ADD_NOT_NULL_ASSERT;
 
diff --git a/pkg/analysis_server/test/src/services/correction/assist/import_add_show_test.dart b/pkg/analysis_server/test/src/services/correction/assist/import_add_show_test.dart
index a196bfb..bb801c2 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/import_add_show_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/import_add_show_test.dart
@@ -21,9 +21,9 @@
 
   Future<void> test_hasShow() async {
     await resolveTestUnit('''
-import 'dart:math' show PI;
+import 'dart:math' show pi;
 main() {
-  PI;
+  pi;
 }
 ''');
     await assertNoAssistAt('import ');
@@ -33,14 +33,14 @@
     await resolveTestUnit('''
 import 'dart:math';
 main(x) {
-  PI;
+  pi;
   return x.foo();
 }
 ''');
     await assertHasAssistAt('import ', '''
-import 'dart:math' show PI;
+import 'dart:math' show pi;
 main(x) {
-  PI;
+  pi;
   return x.foo();
 }
 ''');
@@ -50,16 +50,16 @@
     await resolveTestUnit('''
 import 'dart:math';
 main() {
-  PI;
-  E;
+  pi;
+  e;
   max(1, 2);
 }
 ''');
     await assertHasAssistAt('import ', '''
-import 'dart:math' show E, PI, max;
+import 'dart:math' show e, max, pi;
 main() {
-  PI;
-  E;
+  pi;
+  e;
   max(1, 2);
 }
 ''');
@@ -69,16 +69,16 @@
     await resolveTestUnit('''
 import 'dart:math';
 main() {
-  PI;
-  E;
+  pi;
+  e;
   max(1, 2);
 }
 ''');
     await assertHasAssistAt('art:math', '''
-import 'dart:math' show E, PI, max;
+import 'dart:math' show e, max, pi;
 main() {
-  PI;
-  E;
+  pi;
+  e;
   max(1, 2);
 }
 ''');
diff --git a/pkg/analysis_server/test/src/services/correction/assist/join_if_with_inner_test.dart b/pkg/analysis_server/test/src/services/correction/assist/join_if_with_inner_test.dart
index ec1c3df..bd1cf73 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/join_if_with_inner_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/join_if_with_inner_test.dart
@@ -10,12 +10,12 @@
 
 void main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(JoinInWithInnerTest);
+    defineReflectiveTests(JoinIfWithInnerTest);
   });
 }
 
 @reflectiveTest
-class JoinInWithInnerTest extends AssistProcessorTest {
+class JoinIfWithInnerTest extends AssistProcessorTest {
   @override
   AssistKind get kind => DartAssistKind.JOIN_IF_WITH_INNER;
 
diff --git a/pkg/analysis_server/test/src/services/correction/assist/test_all.dart b/pkg/analysis_server/test/src/services/correction/assist/test_all.dart
index 4280ef9..18c3539 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/test_all.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/test_all.dart
@@ -5,7 +5,7 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'add_diagnostic_property_reference_test.dart' as add_diagnostic_property;
-import 'add_not_null_assert.dart' as add_not_null_assert;
+import 'add_not_null_assert_test.dart' as add_not_null_assert;
 import 'add_return_type_test.dart' as add_return_type;
 import 'add_type_annotation_test.dart' as add_type_annotation;
 import 'assign_to_local_variable_test.dart' as assign_to_local_variable;
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_late_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_late_test.dart
new file mode 100644
index 0000000..9a67e6e
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/add_late_test.dart
@@ -0,0 +1,76 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(AddLatePreNnbdTest);
+    defineReflectiveTests(AddLateTest);
+  });
+}
+
+@reflectiveTest
+class AddLatePreNnbdTest extends FixProcessorTest {
+  @override
+  FixKind get kind => DartFixKind.ADD_LATE;
+
+  Future<void> test_withFinal() async {
+    await resolveTestUnit('''
+class C {
+  final String s;
+}
+''');
+    await assertNoFix();
+  }
+}
+
+@reflectiveTest
+class AddLateTest extends FixProcessorTest {
+  @override
+  List<String> get experiments => [EnableString.non_nullable];
+
+  @override
+  FixKind get kind => DartFixKind.ADD_LATE;
+
+  Future<void> test_withFinal() async {
+    await resolveTestUnit('''
+class C {
+  final String s;
+}
+''');
+    await assertHasFix('''
+class C {
+  final late String s;
+}
+''');
+  }
+
+  Future<void> test_withLate() async {
+    await resolveTestUnit('''
+class C {
+  late s;
+}
+''');
+    await assertNoFix();
+  }
+
+  Future<void> test_withType() async {
+    await resolveTestUnit('''
+class C {
+  String s;
+}
+''');
+    await assertHasFix('''
+class C {
+  late String s;
+}
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/import_library_prefix_test.dart b/pkg/analysis_server/test/src/services/correction/fix/import_library_prefix_test.dart
index b5979a9..73e5996 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/import_library_prefix_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/import_library_prefix_test.dart
@@ -63,15 +63,15 @@
     await resolveTestUnit('''
 import 'dart:math' as pref;
 main() {
-  print(pref.E);
-  print(PI);
+  print(pref.e);
+  print(pi);
 }
 ''');
     await assertHasFix('''
 import 'dart:math' as pref;
 main() {
-  print(pref.E);
-  print(pref.PI);
+  print(pref.e);
+  print(pref.pi);
 }
 ''');
   }
diff --git a/pkg/analysis_server/test/src/services/correction/fix/import_library_sdk_test.dart b/pkg/analysis_server/test/src/services/correction/fix/import_library_sdk_test.dart
index b504421..b64f017 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/import_library_sdk_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/import_library_sdk_test.dart
@@ -278,28 +278,28 @@
   Future<void> test_withTopLevelVariable() async {
     await resolveTestUnit('''
 main() {
-  print(PI);
+  print(pi);
 }
 ''');
     await assertHasFix('''
 import 'dart:math';
 
 main() {
-  print(PI);
+  print(pi);
 }
 ''');
   }
 
   Future<void> test_withTopLevelVariable_annotation() async {
     await resolveTestUnit('''
-@PI
+@pi
 main() {
 }
 ''');
     await assertHasFix('''
 import 'dart:math';
 
-@PI
+@pi
 main() {
 }
 ''');
diff --git a/pkg/analysis_server/test/src/services/correction/fix/test_all.dart b/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
index 00a1f08..0185dd0 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
@@ -12,6 +12,7 @@
     as add_diagnostic_property_reference;
 import 'add_explicit_cast_test.dart' as add_explicit_cast;
 import 'add_field_formal_parameters_test.dart' as add_field_formal_parameters;
+import 'add_late_test.dart' as add_late;
 import 'add_missing_enum_case_clauses_test.dart'
     as add_missing_enum_case_clauses;
 import 'add_missing_parameter_named_test.dart' as add_missing_parameter_named;
@@ -170,6 +171,7 @@
     add_diagnostic_property_reference.main();
     add_explicit_cast.main();
     add_field_formal_parameters.main();
+    add_late.main();
     add_missing_enum_case_clauses.main();
     add_missing_parameter_named.main();
     add_missing_parameter_positional.main();
diff --git a/pkg/analysis_server/tool/completion_metrics/implicit_type_declarations.dart b/pkg/analysis_server/tool/completion_metrics/implicit_type_declarations.dart
new file mode 100644
index 0000000..a2c0c4b
--- /dev/null
+++ b/pkg/analysis_server/tool/completion_metrics/implicit_type_declarations.dart
@@ -0,0 +1,245 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:io' as io;
+
+import 'package:analysis_server/src/status/pages.dart';
+import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
+import 'package:analyzer/dart/analysis/context_root.dart';
+import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/diagnostic/diagnostic.dart';
+import 'package:analyzer/file_system/physical_file_system.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:args/args.dart';
+import 'package:meta/meta.dart';
+
+/// Compute metrics to determine which untyped variable declarations can be used
+/// to imply an expected context type, i.e. the RHS of 'var string = ^' could be
+/// assumed to be a [String].
+Future<void> main(List<String> args) async {
+  var parser = createArgParser();
+  var result = parser.parse(args);
+
+  if (validArguments(parser, result)) {
+    var out = io.stdout;
+    var rootPath = result.rest[0];
+    out.writeln('Analyzing root: "$rootPath"');
+
+    var computer = ImpliedTypeComputer();
+    var stopwatch = Stopwatch();
+    stopwatch.start();
+    await computer.compute(rootPath, verbose: result['verbose']);
+    stopwatch.stop();
+
+    var duration = Duration(milliseconds: stopwatch.elapsedMilliseconds);
+    out.writeln('Metrics computed in $duration');
+    computer.writeMetrics(out);
+    await out.flush();
+  }
+  io.exit(0);
+}
+
+/// Create a parser that can be used to parse the command-line arguments.
+ArgParser createArgParser() {
+  var parser = ArgParser();
+  parser.addOption(
+    'help',
+    abbr: 'h',
+    help: 'Print this help message.',
+  );
+  parser.addFlag(
+    'verbose',
+    abbr: 'v',
+    help: 'Print additional information about the analysis',
+    negatable: false,
+  );
+  return parser;
+}
+
+/// Print usage information for this tool.
+void printUsage(ArgParser parser, {String error}) {
+  if (error != null) {
+    print(error);
+    print('');
+  }
+  print('usage: dart implicit_type_declarations.dart [options] packagePath');
+  print('');
+  print('Compute implicit types in field declaration locations without a '
+      'specified type.');
+  print('');
+  print(parser.usage);
+}
+
+/// Return `true` if the command-line arguments (represented by the [result] and
+/// parsed by the [parser]) are valid.
+bool validArguments(ArgParser parser, ArgResults result) {
+  if (result.wasParsed('help')) {
+    printUsage(parser);
+    return false;
+  } else if (result.rest.length != 1) {
+    printUsage(parser, error: 'No package path specified.');
+    return false;
+  }
+  var rootPath = result.rest[0];
+  if (!io.Directory(rootPath).existsSync()) {
+    printUsage(parser, error: 'The directory "$rootPath" does not exist.');
+    return false;
+  }
+  return true;
+}
+
+/// An object that visits a compilation unit in order to record the data used to
+/// compute the metrics.
+class ImpliedTypeCollector extends RecursiveAstVisitor<void> {
+  /// The implied type data being collected.
+  ImpliedTypeData data;
+
+  /// Initialize a newly created collector to add data points to the given
+  /// [data].
+  ImpliedTypeCollector(this.data);
+
+  void handleVariableDeclaration(VariableDeclaration node, DartType dartType) {
+    // If some untyped variable declaration
+    if (node.equals != null && dartType == null ||
+        (dartType != null && (dartType.isDynamic || dartType.isVoid))) {
+      // And if we can determine the type on the RHS of the variable declaration
+      var rhsType = node.initializer?.staticType;
+      if (rhsType != null && !rhsType.isDynamic) {
+        // Record the name with the type.
+        data.recordImpliedType(node.name.name, rhsType.getDisplayString());
+      }
+    }
+  }
+
+  @override
+  void visitVariableDeclarationList(VariableDeclarationList node) {
+    for (var varDecl in node.variables) {
+      handleVariableDeclaration(varDecl, node.type?.type);
+    }
+    return null;
+  }
+}
+
+/// An object used to compute metrics for a single file or directory.
+class ImpliedTypeComputer {
+  /// The metrics data that was computed.
+  final ImpliedTypeData data = ImpliedTypeData();
+
+  /// Initialize a newly created metrics computer that can compute the metrics
+  /// in one or more files and directories.
+  ImpliedTypeComputer();
+
+  /// Compute the metrics for the file(s) in the [rootPath].
+  /// If [corpus] is true, treat rootPath as a container of packages, creating
+  /// a new context collection for each subdirectory.
+  void compute(String rootPath, {@required bool verbose}) async {
+    final collection = AnalysisContextCollection(
+      includedPaths: [rootPath],
+      resourceProvider: PhysicalResourceProvider.INSTANCE,
+    );
+    final collector = ImpliedTypeCollector(data);
+    for (var context in collection.contexts) {
+      await _computeInContext(context.contextRoot, collector, verbose: verbose);
+    }
+  }
+
+  /// Write a report of the metrics that were computed to the [sink].
+  void writeMetrics(StringSink sink) {
+    data.impliedTypesMap.forEach((String name, Map<String, int> displayStrMap) {
+      var sum = 0;
+      displayStrMap.forEach((String displayStr, int count) {
+        sum += count;
+      });
+      if (sum >= 5) {
+        sink.writeln('$name $sum:');
+        displayStrMap.forEach((String displayStr, int count) {
+          sink.writeln('  $displayStr $count ${printPercentage(count / sum)}');
+        });
+      }
+    });
+  }
+
+  /// Compute the metrics for the files in the context [root], creating a
+  /// separate context collection to prevent accumulating memory. The metrics
+  /// should be captured in the [collector]. Include additional details in the
+  /// output if [verbose] is `true`.
+  void _computeInContext(ContextRoot root, ImpliedTypeCollector collector,
+      {@required bool verbose}) async {
+    // Create a new collection to avoid consuming large quantities of memory.
+    final collection = AnalysisContextCollection(
+      includedPaths: root.includedPaths.toList(),
+      excludedPaths: root.excludedPaths.toList(),
+      resourceProvider: PhysicalResourceProvider.INSTANCE,
+    );
+    var context = collection.contexts[0];
+    for (var filePath in context.contextRoot.analyzedFiles()) {
+      if (AnalysisEngine.isDartFileName(filePath)) {
+        try {
+          var resolvedUnitResult =
+              await context.currentSession.getResolvedUnit(filePath);
+          //
+          // Check for errors that cause the file to be skipped.
+          //
+          if (resolvedUnitResult == null) {
+            print('File $filePath skipped because resolved unit was null.');
+            if (verbose) {
+              print('');
+            }
+            continue;
+          } else if (resolvedUnitResult.state != ResultState.VALID) {
+            print('File $filePath skipped because it could not be analyzed.');
+            if (verbose) {
+              print('');
+            }
+            continue;
+          } else if (hasError(resolvedUnitResult)) {
+            if (verbose) {
+              print('File $filePath skipped due to errors:');
+              for (var error in resolvedUnitResult.errors
+                  .where((e) => e.severity == Severity.error)) {
+                print('  ${error.toString()}');
+              }
+              print('');
+            } else {
+              print('File $filePath skipped due to analysis errors.');
+            }
+            continue;
+          }
+
+          resolvedUnitResult.unit.accept(collector);
+        } catch (exception, stacktrace) {
+          print('Exception caught analyzing: "$filePath"');
+          print(exception);
+          print(stacktrace);
+        }
+      }
+    }
+  }
+
+  /// Return `true` if the [result] contains an error.
+  static bool hasError(ResolvedUnitResult result) {
+    for (var error in result.errors) {
+      if (error.severity == Severity.error) {
+        return true;
+      }
+    }
+    return false;
+  }
+}
+
+class ImpliedTypeData {
+  Map<String, Map<String, int>> impliedTypesMap = {};
+
+  /// Record the variable name with the type.
+  void recordImpliedType(String name, String displayString) {
+    assert(name != null);
+    assert(displayString != null);
+    var nameMap = impliedTypesMap.putIfAbsent(name, () => {});
+    nameMap[displayString] = (nameMap[displayString] ?? 0) + 1;
+  }
+}
diff --git a/pkg/analysis_server/tool/completion_metrics/relevance_table_generator.dart b/pkg/analysis_server/tool/completion_metrics/relevance_table_generator.dart
index 5a89a32..4b6d1dc 100644
--- a/pkg/analysis_server/tool/completion_metrics/relevance_table_generator.dart
+++ b/pkg/analysis_server/tool/completion_metrics/relevance_table_generator.dart
@@ -122,33 +122,29 @@
 
 /// An object that records the data used to compute the tables.
 class RelevanceData {
-  /// A table mapping element kinds to counts by context.
-  Map<String, Map<String, int>> byElementKind = {};
-
-  /// A table mapping token types to counts by context.
-  Map<String, Map<String, int>> byTokenType = {};
+  /// A table mapping element kinds and keywords to counts by context.
+  Map<String, Map<_Kind, int>> byKind = {};
 
   /// Initialize a newly created set of relevance data to be empty.
   RelevanceData();
 
   /// Add the data from the given relevance [data] to this set of data.
   void addDataFrom(RelevanceData data) {
-    _addToMap(byElementKind, data.byElementKind);
-    _addToMap(byTokenType, data.byTokenType);
+    _addToMap(byKind, data.byKind);
   }
 
   /// Record that an element of the given [kind] was found in the given
   /// [context].
   void recordElementKind(String context, ElementKind kind) {
-    var contextMap = byElementKind.putIfAbsent(context, () => {});
-    var key = kind.name;
+    var contextMap = byKind.putIfAbsent(context, () => {});
+    var key = _ElementKind(kind);
     contextMap[key] = (contextMap[key] ?? 0) + 1;
   }
 
-  /// Record that a token of the given [type] was found in the given [context].
-  void recordTokenType(String context, TokenType type) {
-    var contextMap = byTokenType.putIfAbsent(context, () => {});
-    var key = type.name;
+  /// Record that the given [keyword] was found in the given [context].
+  void recordKeyword(String context, Keyword keyword) {
+    var contextMap = byKind.putIfAbsent(context, () => {});
+    var key = _Keyword(keyword);
     contextMap[key] = (contextMap[key] ?? 0) + 1;
   }
 
@@ -334,14 +330,14 @@
 
   @override
   void visitBlockFunctionBody(BlockFunctionBody node) {
-    _recordTokenType('BlockFunctionBody_start', node,
+    _recordKeyword('BlockFunctionBody_start', node,
         allowedKeywords: functionBodyKeywords);
     super.visitBlockFunctionBody(node);
   }
 
   @override
   void visitBooleanLiteral(BooleanLiteral node) {
-    _recordTokenType('BooleanLiteral_start', node);
+    _recordKeyword('BooleanLiteral_start', node);
     super.visitBooleanLiteral(node);
   }
 
@@ -369,15 +365,15 @@
   void visitClassDeclaration(ClassDeclaration node) {
     var context = 'name';
     if (node.extendsClause != null) {
-      _recordTokenType('ClassDeclaration_$context', node.extendsClause,
+      _recordKeyword('ClassDeclaration_$context', node.extendsClause,
           allowedKeywords: [Keyword.EXTENDS]);
       context = 'extends';
     }
     if (node.withClause != null) {
-      _recordTokenType('ClassDeclaration_$context', node.withClause);
+      _recordKeyword('ClassDeclaration_$context', node.withClause);
       context = 'with';
     }
-    _recordTokenType('ClassDeclaration_$context', node.implementsClause,
+    _recordKeyword('ClassDeclaration_$context', node.implementsClause,
         allowedKeywords: [Keyword.IMPLEMENTS]);
 
     for (var member in node.members) {
@@ -392,10 +388,10 @@
     _recordDataForNode('ClassTypeAlias_superclass', node.superclass);
     var context = 'superclass';
     if (node.withClause != null) {
-      _recordTokenType('ClassTypeAlias_$context', node.withClause);
+      _recordKeyword('ClassTypeAlias_$context', node.withClause);
       context = 'with';
     }
-    _recordTokenType('ClassTypeAlias_$context', node.implementsClause);
+    _recordKeyword('ClassTypeAlias_$context', node.implementsClause);
     super.visitClassTypeAlias(node);
   }
 
@@ -420,7 +416,7 @@
     featureComputer = FeatureComputer(typeSystem, typeProvider);
 
     for (var directive in node.directives) {
-      _recordTokenType('CompilationUnit_directive', directive,
+      _recordKeyword('CompilationUnit_directive', directive,
           allowedKeywords: directiveKeywords);
     }
     for (var declaration in node.declarations) {
@@ -544,16 +540,16 @@
   void visitExportDirective(ExportDirective node) {
     var context = 'uri';
     if (node.configurations.isNotEmpty) {
-      _recordTokenType('ImportDirective_$context', node.configurations[0],
+      _recordKeyword('ImportDirective_$context', node.configurations[0],
           allowedKeywords: exportKeywords);
       context = 'configurations';
     }
     if (node.combinators.isNotEmpty) {
-      _recordTokenType('ImportDirective_$context', node.combinators[0],
+      _recordKeyword('ImportDirective_$context', node.combinators[0],
           allowedKeywords: exportKeywords);
     }
     for (var combinator in node.combinators) {
-      _recordTokenType('ImportDirective_combinator', combinator,
+      _recordKeyword('ImportDirective_combinator', combinator,
           allowedKeywords: exportKeywords);
     }
     super.visitExportDirective(node);
@@ -561,7 +557,7 @@
 
   @override
   void visitExpressionFunctionBody(ExpressionFunctionBody node) {
-    _recordTokenType('ExpressionFunctionBody_start', node,
+    _recordKeyword('ExpressionFunctionBody_start', node,
         allowedKeywords: functionBodyKeywords);
     _recordDataForNode('ExpressionFunctionBody_expression', node.expression,
         allowedKeywords: expressionKeywords);
@@ -763,25 +759,24 @@
   void visitImportDirective(ImportDirective node) {
     var context = 'uri';
     if (node.deferredKeyword != null) {
-      data.recordTokenType(
-          'ImportDirective_$context', node.deferredKeyword.type);
+      data.recordKeyword('ImportDirective_$context', node.deferredKeyword.type);
       context = 'deferred';
     }
     if (node.asKeyword != null) {
-      data.recordTokenType('ImportDirective_$context', node.asKeyword.type);
+      data.recordKeyword('ImportDirective_$context', node.asKeyword.type);
       context = 'prefix';
     }
     if (node.configurations.isNotEmpty) {
-      _recordTokenType('ImportDirective_$context', node.configurations[0],
+      _recordKeyword('ImportDirective_$context', node.configurations[0],
           allowedKeywords: importKeywords);
       context = 'configurations';
     }
     if (node.combinators.isNotEmpty) {
-      _recordTokenType('ImportDirective_$context', node.combinators[0],
+      _recordKeyword('ImportDirective_$context', node.combinators[0],
           allowedKeywords: importKeywords);
     }
     for (var combinator in node.combinators) {
-      _recordTokenType('ImportDirective_combinator', combinator,
+      _recordKeyword('ImportDirective_combinator', combinator,
           allowedKeywords: importKeywords);
     }
     super.visitImportDirective(node);
@@ -885,11 +880,11 @@
   void visitMixinDeclaration(MixinDeclaration node) {
     var context = 'name';
     if (node.onClause != null) {
-      _recordTokenType('MixinDeclaration_$context', node.onClause,
+      _recordKeyword('MixinDeclaration_$context', node.onClause,
           allowedKeywords: [Keyword.ON]);
       context = 'on';
     }
-    _recordTokenType('MixinDeclaration_$context', node.implementsClause,
+    _recordKeyword('MixinDeclaration_$context', node.implementsClause,
         allowedKeywords: [Keyword.IMPLEMENTS]);
 
     for (var member in node.members) {
@@ -993,9 +988,6 @@
   void visitReturnStatement(ReturnStatement node) {
     _recordDataForNode('ReturnStatement_expression', node.expression,
         allowedKeywords: expressionKeywords);
-    if (node.expression == null) {
-      data.recordTokenType('ReturnStatement_expression', node.semicolon.type);
-    }
     super.visitReturnStatement(node);
   }
 
@@ -1115,12 +1107,12 @@
   void visitTryStatement(TryStatement node) {
     var context = 'try';
     for (var clause in node.catchClauses) {
-      _recordTokenType('TryStatement_$context', clause,
+      _recordKeyword('TryStatement_$context', clause,
           allowedKeywords: [Keyword.ON]);
       context = 'catch';
     }
     if (node.finallyKeyword != null) {
-      data.recordTokenType('TryStatement_$context', node.finallyKeyword.type);
+      data.recordKeyword('TryStatement_$context', node.finallyKeyword.type);
     }
     super.visitTryStatement(node);
   }
@@ -1308,7 +1300,7 @@
   void _recordDataForNode(String context, AstNode node,
       {List<Keyword> allowedKeywords = noKeywords}) {
     _recordElementKind(context, node);
-    _recordTokenType(context, node, allowedKeywords: allowedKeywords);
+    _recordKeyword(context, node, allowedKeywords: allowedKeywords);
   }
 
   /// Record the element kind of the element associated with the left-most
@@ -1327,27 +1319,25 @@
     }
   }
 
-  /// Record the token type of the left-most token that is a child of the
-  /// [node] in the given [context].
-  void _recordTokenType(String context, AstNode node,
+  /// If the left-most token of the [node] is a keyword, then record that it
+  /// occurred in the given [context].
+  void _recordKeyword(String context, AstNode node,
       {List<Keyword> allowedKeywords = noKeywords}) {
     if (node != null) {
       var token = _leftMostToken(node);
-      if (token != null) {
-        var type = token.type;
-        if (token.isKeyword && token.keyword.isBuiltInOrPseudo) {
-          // These keywords can be used as identifiers, so determine whether it
-          // is being used as a keyword or an identifier.
-          if (!allowedKeywords.contains(token.keyword)) {
-            type = TokenType.IDENTIFIER;
-          }
+      if (token.isKeyword) {
+        var keyword = token.type;
+        if (keyword == Keyword.NEW) {
+          // We don't suggest `new`, so we don't care about the frequency with
+          // which it is used.
+          return;
+        } else if (token.keyword.isBuiltInOrPseudo &&
+            !allowedKeywords.contains(token.keyword)) {
+          // These keywords can be used as identifiers, so determine whether
+          // it is being used as a keyword or an identifier.
+          return;
         }
-        data.recordTokenType(context, type);
-        if (node is Expression) {
-          data.recordTokenType('Expression', type);
-        } else if (node is Statement) {
-          data.recordTokenType('Statement', type);
-        }
+        data.recordKeyword(context, keyword);
       }
     }
   }
@@ -1452,20 +1442,13 @@
 
   RelevanceTableWriter(this.sink);
 
-  int totalCount(Map<String, int> counts) {
-    return counts.values
-        .fold(0, (previousValue, value) => previousValue + value);
-  }
-
   void write(RelevanceData data) {
     writeFileHeader();
     writeElementKindTable(data);
+    writeKeywordTable(data);
   }
 
   void writeElementKindTable(RelevanceData data) {
-    var byTokenType = data.byTokenType;
-    var byElementKind = data.byElementKind;
-
     sink.writeln();
     sink.write('''
 /// A table keyed by completion location and element kind whose values are the
@@ -1473,46 +1456,39 @@
 const elementKindRelevance = {
 ''');
 
-    var completionLocations = byElementKind.keys.toList()..sort();
+    var byKind = data.byKind;
+    var completionLocations = byKind.keys.toList()..sort();
     for (var completionLocation in completionLocations) {
-      var elementCounts = byElementKind[completionLocation];
-      var identifierPercent = 1.0;
-      var tokenCounts = byTokenType[completionLocation];
-      if (tokenCounts != null) {
-        var identifierCount = tokenCounts['IDENTIFIER'];
-        if (identifierCount != null) {
-          var totalTokenCount = totalCount(tokenCounts);
-          identifierPercent = identifierCount / totalTokenCount;
+      var counts = byKind[completionLocation];
+      if (_hasElementKind(counts)) {
+        var totalCount = _totalCount(counts);
+        // TODO(brianwilkerson) If two element kinds have the same count they
+        //  ought to have the same probability. This doesn't correctly do that.
+        var entries = counts.entries.toList()
+          ..sort((first, second) => first.value.compareTo(second.value));
+
+        sink.write("  '");
+        sink.write(completionLocation);
+        sink.writeln("': {");
+        var cumulativeCount = 0;
+        var lowerBound = 0.0;
+        for (var entry in entries) {
+          var kind = entry.key;
+          cumulativeCount += entry.value;
+          var upperBound = cumulativeCount / totalCount;
+          if (kind is _ElementKind) {
+            sink.write('    ElementKind.');
+            sink.write(kind.elementKind.name);
+            sink.write(': ProbabilityRange(lower: ');
+            sink.write(lowerBound.toStringAsFixed(3));
+            sink.write(', upper: ');
+            sink.write(upperBound.toStringAsFixed(3));
+            sink.writeln('),');
+          }
+          lowerBound = upperBound;
         }
+        sink.writeln('  },');
       }
-      // TODO(brianwilkerson) This incorrectly assumes that identifiers are
-      //  always the most common first token in a completion location.
-      var startOfBand = 1.0 - identifierPercent;
-      sink.write("  '");
-      sink.write(completionLocation);
-      sink.writeln("': {");
-      var totalElementCount = totalCount(elementCounts);
-      var cumulativeCount = 0;
-      // TODO(brianwilkerson) If two element kinds have the same count they
-      //  ought to have the same probability. This doesn't correctly do that.
-      var entries = elementCounts.entries.toList()
-        ..sort((first, second) => first.value.compareTo(second.value));
-      var lowerBound = 0.0;
-      for (var entry in entries) {
-        var elementKind = entry.key;
-        cumulativeCount += entry.value;
-        var percentInBand = cumulativeCount / totalElementCount;
-        var upperBound = (percentInBand * identifierPercent) + startOfBand;
-        sink.write('    ElementKind.');
-        sink.write(elementKind);
-        sink.write(': ProbabilityRange(lower: ');
-        sink.write(lowerBound.toStringAsFixed(3));
-        sink.write(', upper: ');
-        sink.write(upperBound.toStringAsFixed(3));
-        sink.writeln('),');
-        lowerBound = upperBound;
-      }
-      sink.writeln('  },');
     }
     sink.writeln('};');
   }
@@ -1533,25 +1509,107 @@
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 ''');
   }
-}
 
-class Timer {
-  Stopwatch stopwatch = Stopwatch();
+  void writeKeywordTable(RelevanceData data) {
+    sink.writeln();
+    sink.write('''
+/// A table keyed by completion location and keyword whose values are the
+/// ranges of the relevance of those keywords in those locations.
+const keywordRelevance = {
+''');
 
-  int count = 0;
+    var byKind = data.byKind;
+    var completionLocations = byKind.keys.toList()..sort();
+    for (var completionLocation in completionLocations) {
+      var counts = byKind[completionLocation];
+      if (_hasKeyword(counts)) {
+        var totalCount = _totalCount(counts);
+        // TODO(brianwilkerson) If two keywords have the same count they ought to
+        //  have the same probability. This doesn't correctly do that.
+        var entries = counts.entries.toList()
+          ..sort((first, second) => first.value.compareTo(second.value));
 
-  Timer();
-
-  double get averageTime => count == 0 ? 0 : totalTime / count;
-
-  int get totalTime => stopwatch.elapsedMilliseconds;
-
-  void start() {
-    stopwatch.start();
+        sink.write("  '");
+        sink.write(completionLocation);
+        sink.writeln("': {");
+        var cumulativeCount = 0;
+        var lowerBound = 0.0;
+        for (var entry in entries) {
+          var kind = entry.key;
+          cumulativeCount += entry.value;
+          var upperBound = cumulativeCount / totalCount;
+          if (kind is _Keyword) {
+            sink.write("    '");
+            sink.write(kind.keyword.lexeme);
+            sink.write("': ProbabilityRange(lower: ");
+            sink.write(lowerBound.toStringAsFixed(3));
+            sink.write(', upper: ');
+            sink.write(upperBound.toStringAsFixed(3));
+            sink.writeln('),');
+          }
+          lowerBound = upperBound;
+        }
+        sink.writeln('  },');
+      }
+    }
+    sink.writeln('};');
   }
 
-  void stop() {
-    stopwatch.stop();
-    count++;
+  /// Return `true` if the table of [counts] contains at least one key that is
+  /// an element kind.
+  bool _hasElementKind(Map<_Kind, int> counts) {
+    for (var kind in counts.keys) {
+      if (kind is _ElementKind) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /// Return `true` if the table of [counts] contains at least one key that is a
+  /// keyword.
+  bool _hasKeyword(Map<_Kind, int> counts) {
+    for (var kind in counts.keys) {
+      if (kind is _Keyword) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /// Return the total of the counts in the given table of [counts].
+  int _totalCount(Map<_Kind, int> counts) {
+    return counts.values
+        .fold(0, (previousValue, value) => previousValue + value);
   }
 }
+
+/// A wrapper for an element kind to allow keywords and element kinds to be used
+/// as keys in a single table.
+class _ElementKind extends _Kind {
+  static final Map<ElementKind, _ElementKind> instances = {};
+
+  final ElementKind elementKind;
+
+  factory _ElementKind(ElementKind elementKind) =>
+      instances.putIfAbsent(elementKind, () => _ElementKind._(elementKind));
+
+  _ElementKind._(this.elementKind);
+}
+
+/// A wrapper for a keyword to allow keywords and element kinds to be used as
+/// keys in a single table.
+class _Keyword extends _Kind {
+  static final Map<Keyword, _Keyword> instances = {};
+
+  final Keyword keyword;
+
+  factory _Keyword(Keyword keyword) =>
+      instances.putIfAbsent(keyword, () => _Keyword._(keyword));
+
+  _Keyword._(this.keyword);
+}
+
+/// A superclass for [_ElementKind] and [_Keyword] to allow keywords and element
+/// kinds to be used as keys in a single table.
+class _Kind {}
diff --git a/pkg/analysis_tool/pubspec.yaml b/pkg/analysis_tool/pubspec.yaml
index 57ab3ee..32199b3 100644
--- a/pkg/analysis_tool/pubspec.yaml
+++ b/pkg/analysis_tool/pubspec.yaml
@@ -1,4 +1,5 @@
 name: analysis_tool
+# This package is not intended for consumption on pub.dev. DO NOT publish.
 publish_to: none
 
 environment:
diff --git a/pkg/analyzer/lib/src/context/source.dart b/pkg/analyzer/lib/src/context/source.dart
index 0ced545..8f31594 100644
--- a/pkg/analyzer/lib/src/context/source.dart
+++ b/pkg/analyzer/lib/src/context/source.dart
@@ -11,6 +11,7 @@
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart' as utils;
 import 'package:analyzer/src/source/package_map_resolver.dart';
+import 'package:analyzer/src/workspace/package_build.dart';
 
 /**
  * Instances of the class `SourceFactory` resolve possibly relative URI's
@@ -49,9 +50,15 @@
 
   @override
   Map<String, List<Folder>> get packageMap {
-    PackageMapUriResolver resolver = resolvers
-        .firstWhere((r) => r is PackageMapUriResolver, orElse: () => null);
-    return resolver?.packageMap;
+    for (var resolver in resolvers) {
+      if (resolver is PackageMapUriResolver) {
+        return resolver.packageMap;
+      }
+      if (resolver is PackageBuildPackageUriResolver) {
+        return resolver.packageMap;
+      }
+    }
+    return null;
   }
 
   @override
diff --git a/pkg/analyzer/lib/src/dart/analysis/feature_set_provider.dart b/pkg/analyzer/lib/src/dart/analysis/feature_set_provider.dart
index b73866b..8604562 100644
--- a/pkg/analyzer/lib/src/dart/analysis/feature_set_provider.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/feature_set_provider.dart
@@ -44,19 +44,13 @@
       }
     }
 
-    if (uri.isScheme('package')) {
-      var pathSegments = uri.pathSegments;
-      if (pathSegments.isNotEmpty) {
-        var packageName = pathSegments.first;
-        var experiments = _allowedExperiments.forPackage(packageName);
-        if (experiments != null) {
-          return FeatureSet.fromEnableFlags(experiments);
-        }
-      }
-    }
-
     var package = _packages.packageForPath(path);
     if (package != null) {
+      var experiments = _allowedExperiments.forPackage(package.name);
+      if (experiments != null) {
+        return FeatureSet.fromEnableFlags(experiments);
+      }
+
       return _packageDefaultFeatureSet;
     }
 
diff --git a/pkg/analyzer/lib/src/dart/error/hint_codes.dart b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
index a9b2866..586a0a1 100644
--- a/pkg/analyzer/lib/src/dart/error/hint_codes.dart
+++ b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
@@ -373,6 +373,46 @@
   /**
    * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when an element in a non-constant set
+  // is the same as a previous element in the same set. If two elements are the
+  // same, then the second value is  ignored, which makes having both elements
+  // pointless and likely signals a bug.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the element `1` appears
+  // twice:
+  //
+  // ```dart
+  // const a = 1;
+  // const b = 1;
+  // var s = <int>{a, [!b!]};
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If both elements should be included in the set, then change one of the
+  // elements:
+  //
+  // ```dart
+  // const a = 1;
+  // const b = 2;
+  // var s = <int>{a, b};
+  // ```
+  //
+  // If only one of the elements is needed, then remove the one that isn't
+  // needed:
+  //
+  // ```dart
+  // const a = 1;
+  // var s = <int>{a};
+  // ```
+  //
+  // Note that literal sets preserve the order of their elements, so the choice
+  // of which element to remove might affect the order in which elements are
+  // returned by an iterator.
   static const HintCode EQUAL_ELEMENTS_IN_SET = HintCode(
       'EQUAL_ELEMENTS_IN_SET',
       "Two elements in a set literal shouldn't be equal.",
@@ -381,6 +421,45 @@
   /**
    * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a key in a non-constant map is
+  // the same as a previous key in the same map. If two keys are the same, then
+  // the second value overwrites the first value, which makes having both pairs
+  // pointless and likely signals a bug.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the keys `a` and `b`
+  // have the same value:
+  //
+  // ```dart
+  // const a = 1;
+  // const b = 1;
+  // var m = <int, String>{a: 'a', [!b!]: 'b'};
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If both entries should be included in the map, then change one of the keys:
+  //
+  // ```dart
+  // const a = 1;
+  // const b = 2;
+  // var m = <int, String>{a: 'a', b: 'b'};
+  // ```
+  //
+  // If only one of the entries is needed, then remove the one that isn't
+  // needed:
+  //
+  // ```dart
+  // const a = 1;
+  // var m = <int, String>{a: 'a'};
+  // ```
+  //
+  // Note that literal maps preserve the order of their entries, so the choice
+  // of which entry to remove might affect the order in which the keys and
+  // values are returned by an iterator.
   static const HintCode EQUAL_KEYS_IN_MAP = HintCode(
       'EQUAL_KEYS_IN_MAP', "Two keys in a map literal shouldn't be equal.",
       correction: "Change or remove the duplicate key.");
diff --git a/pkg/analyzer/lib/src/dart/micro/analysis_context.dart b/pkg/analyzer/lib/src/dart/micro/analysis_context.dart
index 8254469..98faa15 100644
--- a/pkg/analyzer/lib/src/dart/micro/analysis_context.dart
+++ b/pkg/analyzer/lib/src/dart/micro/analysis_context.dart
@@ -190,7 +190,7 @@
 
   @override
   Future<ResolvedUnitResult> getResolvedUnit(String path) async {
-    return analysisContext.fileResolver.resolve(path);
+    return analysisContext.fileResolver.resolve2(path: path);
   }
 
   @override
diff --git a/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart b/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart
index 54f9035..5c56a19 100644
--- a/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart
@@ -20,6 +20,7 @@
 import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
 import 'package:analyzer/src/dart/element/type_provider.dart';
 import 'package:analyzer/src/dart/micro/library_graph.dart';
+import 'package:analyzer/src/dart/micro/performance.dart';
 import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
 import 'package:analyzer/src/dart/resolver/legacy_type_asserter.dart';
 import 'package:analyzer/src/dart/resolver/resolution_visitor.dart';
@@ -45,15 +46,9 @@
 import 'package:analyzer/src/summary2/linked_element_factory.dart';
 import 'package:analyzer/src/task/strong/checker.dart';
 import 'package:analyzer/src/workspace/workspace.dart';
+import 'package:meta/meta.dart';
 import 'package:pub_semver/pub_semver.dart';
 
-var timerLibraryAnalyzer = Stopwatch();
-var timerLibraryAnalyzerConst = Stopwatch();
-var timerLibraryAnalyzerFreshUnit = Stopwatch();
-var timerLibraryAnalyzerResolve = Stopwatch();
-var timerLibraryAnalyzerSplicer = Stopwatch();
-var timerLibraryAnalyzerVerify = Stopwatch();
-
 /**
  * Analyzer of a single library.
  */
@@ -115,25 +110,17 @@
   /**
    * Compute analysis results for all units of the library.
    */
-  Map<FileState, UnitAnalysisResult> analyze() {
-    return PerformanceStatistics.analysis.makeCurrentWhile(() {
-      return analyzeSync();
-    });
-  }
-
-  /**
-   * Compute analysis results for all units of the library.
-   */
-  Map<FileState, UnitAnalysisResult> analyzeSync() {
-    timerLibraryAnalyzer.start();
+  Map<FileState, UnitAnalysisResult> analyzeSync({
+    @required CiderOperationPerformanceImpl performance,
+  }) {
     Map<FileState, CompilationUnit> units = {};
 
     // Parse all files.
-    timerLibraryAnalyzerFreshUnit.start();
-    for (FileState file in _library.libraryFiles) {
-      units[file] = _parse(file);
-    }
-    timerLibraryAnalyzerFreshUnit.stop();
+    performance.run('parse', (performance) {
+      for (FileState file in _library.libraryFiles) {
+        units[file] = _parse(file);
+      }
+    });
 
     // Resolve URIs in directives to corresponding sources.
     FeatureSet featureSet = units[_library].featureSet;
@@ -147,29 +134,30 @@
 
     _libraryScope = LibraryScope(_libraryElement);
 
-    timerLibraryAnalyzerResolve.start();
-    _resolveDirectives(units);
-
-    units.forEach((file, unit) {
-      _resolveFile(file, unit);
+    performance.run('resolveDirectives', (performance) {
+      _resolveDirectives(units);
     });
-    timerLibraryAnalyzerResolve.stop();
 
-    timerLibraryAnalyzerConst.start();
-    units.values.forEach(_findConstants);
-    _clearConstantEvaluationResults();
-    _computeConstants();
-    timerLibraryAnalyzerConst.stop();
+    performance.run('resolveFiles', (performance) {
+      units.forEach((file, unit) {
+        _resolveFile(file, unit);
+      });
+    });
 
-    timerLibraryAnalyzerVerify.start();
-    PerformanceStatistics.errors.makeCurrentWhile(() {
+    performance.run('computeConstants', (performance) {
+      units.values.forEach(_findConstants);
+      _clearConstantEvaluationResults();
+      _computeConstants();
+    });
+
+    performance.run('computeVerifyErrors', (performance) {
       units.forEach((file, unit) {
         _computeVerifyErrors(file, unit);
       });
     });
 
     if (_analysisOptions.hint) {
-      PerformanceStatistics.hints.makeCurrentWhile(() {
+      performance.run('computeHints', (performance) {
         units.forEach((file, unit) {
           {
             var visitor = GatherUsedLocalElementsVisitor(_libraryElement);
@@ -189,13 +177,11 @@
     }
 
     if (_analysisOptions.lint) {
-      PerformanceStatistics.lints.makeCurrentWhile(() {
-        var allUnits = _library.libraryFiles.map(
-          (file) {
-            var content = _getFileContent(file.path);
-            return LinterContextUnit(content, units[file]);
-          },
-        ).toList();
+      performance.run('computeLints', (performance) {
+        var allUnits = _library.libraryFiles.map((file) {
+          var content = _getFileContent(file.path);
+          return LinterContextUnit(content, units[file]);
+        }).toList();
         for (int i = 0; i < allUnits.length; i++) {
           _computeLints(_library.libraryFiles[i], allUnits[i], allUnits);
         }
@@ -204,8 +190,6 @@
 
     assert(units.values.every(LegacyTypeAsserter.assertLegacyTypes));
 
-    timerLibraryAnalyzerVerify.stop();
-
     // Return full results.
     Map<FileState, UnitAnalysisResult> results = {};
     units.forEach((file, unit) {
@@ -213,7 +197,6 @@
       errors = _filterIgnoredErrors(file, errors);
       results[file] = UnitAnalysisResult(file, unit, errors);
     });
-    timerLibraryAnalyzer.stop();
     return results;
   }
 
diff --git a/pkg/analyzer/lib/src/dart/micro/performance.dart b/pkg/analyzer/lib/src/dart/micro/performance.dart
new file mode 100644
index 0000000..5a398f2
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/micro/performance.dart
@@ -0,0 +1,156 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:meta/meta.dart';
+
+/// The performance of an operation.
+abstract class CiderOperationPerformance {
+  /// The children operation, might be empty.
+  List<CiderOperationPerformance> get children;
+
+  /// The duration of the operation itself and its children.
+  Duration get elapsed;
+
+  /// The duration of the operation itself.
+  Duration get elapsedSelf;
+
+  /// The name of the operation.
+  String get name;
+
+  CiderOperationPerformance getChild(String name);
+
+  /// Write this operation and its children into the [buffer].
+  void write({
+    @required StringBuffer buffer,
+    String indent = '',
+  });
+}
+
+class CiderOperationPerformanceFixed implements CiderOperationPerformance {
+  @override
+  final String name;
+
+  @override
+  final Duration elapsedSelf;
+
+  CiderOperationPerformanceFixed(this.name, this.elapsedSelf);
+
+  @override
+  List<CiderOperationPerformance> get children => const [];
+
+  @override
+  Duration get elapsed => elapsedSelf;
+
+  @override
+  CiderOperationPerformance getChild(String name) {
+    return null;
+  }
+
+  @override
+  String toString() {
+    return '(name: $name, elapsed: $elapsed)';
+  }
+
+  @override
+  void write({StringBuffer buffer, String indent = ''}) {
+    buffer.writeln('$indent${toString()}');
+  }
+}
+
+class CiderOperationPerformanceImpl implements CiderOperationPerformance {
+  @override
+  final String name;
+
+  final Stopwatch _timer = Stopwatch();
+  final List<CiderOperationPerformance> _children = [];
+
+  CiderOperationPerformanceImpl(this.name);
+
+  @override
+  List<CiderOperationPerformance> get children {
+    return _children;
+  }
+
+  @override
+  Duration get elapsed {
+    return _timer.elapsed;
+  }
+
+  @override
+  Duration get elapsedSelf {
+    return elapsed - _elapsedChildren;
+  }
+
+  Duration get _elapsedChildren {
+    return children.fold<Duration>(
+      Duration.zero,
+      (sum, child) => sum + child.elapsed,
+    );
+  }
+
+  /// Add a new child with the known elapsed time.
+  ///
+  /// This method is used when we already measure performance using some other
+  /// mechanism, but want to add it to this performance hierarchy.
+  void addChildFixed(String name, Duration elapsed) {
+    _children.add(
+      CiderOperationPerformanceFixed(name, elapsed),
+    );
+  }
+
+  @override
+  CiderOperationPerformance getChild(String name) {
+    return children.firstWhere(
+      (child) => child.name == name,
+      orElse: () => null,
+    );
+  }
+
+  /// Run the [operation] as a new child.
+  T run<T>(
+    String name,
+    T Function(CiderOperationPerformanceImpl) operation,
+  ) {
+    var child = CiderOperationPerformanceImpl(name);
+    _children.add(child);
+    child._timer.start();
+
+    try {
+      return operation(child);
+    } finally {
+      child._timer.stop();
+    }
+  }
+
+  /// Run the [operation] as a new child.
+  Future<T> runAsync<T>(
+    String name,
+    Future<T> Function(CiderOperationPerformanceImpl) operation,
+  ) async {
+    var child = CiderOperationPerformanceImpl(name);
+    _children.add(child);
+    child._timer.start();
+
+    try {
+      return await operation(child);
+    } finally {
+      child._timer.stop();
+    }
+  }
+
+  @override
+  String toString() {
+    return '(name: $name, elapsed: $elapsed, elapsedSelf: $elapsedSelf)';
+  }
+
+  @override
+  void write({StringBuffer buffer, String indent = ''}) {
+    buffer.writeln('$indent${toString()}');
+
+    var childIndent = '$indent  ';
+    for (var child in children) {
+      child.write(buffer: buffer, indent: childIndent);
+    }
+  }
+}
diff --git a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
index 74d6026..0117946 100644
--- a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
+++ b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
@@ -22,6 +22,7 @@
 import 'package:analyzer/src/dart/micro/cider_byte_store.dart';
 import 'package:analyzer/src/dart/micro/library_analyzer.dart';
 import 'package:analyzer/src/dart/micro/library_graph.dart';
+import 'package:analyzer/src/dart/micro/performance.dart';
 import 'package:analyzer/src/generated/engine.dart'
     show AnalysisEngine, AnalysisOptionsImpl;
 import 'package:analyzer/src/generated/source.dart';
@@ -146,12 +147,25 @@
     _libraryContextReset.dispose();
   }
 
+  @deprecated
   ErrorsResult getErrors(String path) {
+    return getErrors2(path: path);
+  }
+
+  ErrorsResult getErrors2({
+    @required String path,
+    CiderOperationPerformanceImpl performance,
+  }) {
     _throwIfNotAbsoluteNormalizedPath(path);
 
+    performance ??= CiderOperationPerformanceImpl('<default>');
+
     return _withLibraryContextReset(() {
       return logger.run('Get errors for $path', () {
-        var fileContext = getFileContext(path);
+        var fileContext = getFileContext(
+          path: path,
+          performance: performance,
+        );
         var file = fileContext.file;
 
         var errorsSignatureBuilder = ApiSignature();
@@ -170,7 +184,10 @@
         }
 
         if (errors == null) {
-          var unitResult = resolve(path);
+          var unitResult = resolve2(
+            path: path,
+            performance: performance,
+          );
           errors = unitResult.errors;
 
           bytes = CiderUnitErrorsBuilder(
@@ -192,12 +209,17 @@
     });
   }
 
-  FileContext getFileContext(String path) {
-    var analysisOptions = _getAnalysisOptions(path);
-    _createContext(path, analysisOptions);
+  FileContext getFileContext({
+    @required String path,
+    @required CiderOperationPerformanceImpl performance,
+  }) {
+    return performance.run('fileContext', (performance) {
+      var analysisOptions = _getAnalysisOptions(path);
+      _createContext(path, analysisOptions);
 
-    var file = fsState.getFileForPath(path);
-    return FileContext(analysisOptions, file);
+      var file = fsState.getFileForPath(path);
+      return FileContext(analysisOptions, file);
+    });
   }
 
   String getLibraryLinkedSignature(String path) {
@@ -207,16 +229,31 @@
     return file.libraryCycle.signatureStr;
   }
 
+  @deprecated
   ResolvedUnitResult resolve(String path) {
+    return resolve2(path: path);
+  }
+
+  ResolvedUnitResult resolve2({
+    @required String path,
+    CiderOperationPerformanceImpl performance,
+  }) {
     _throwIfNotAbsoluteNormalizedPath(path);
 
+    performance ??= CiderOperationPerformanceImpl('<default>');
+
     return _withLibraryContextReset(() {
       return logger.run('Resolve $path', () {
-        var fileContext = getFileContext(path);
+        var fileContext = getFileContext(
+          path: path,
+          performance: performance,
+        );
         var file = fileContext.file;
         var libraryFile = file.partOfLibrary ?? file;
 
-        libraryContext.load2(libraryFile);
+        performance.run('libraryContext', (performance) {
+          libraryContext.load2(libraryFile);
+        });
 
         testView?.addResolvedFile(path);
 
@@ -240,7 +277,11 @@
             (String path) => resourceProvider.getFile(path).readAsStringSync(),
           );
 
-          results = libraryAnalyzer.analyzeSync();
+          results = performance.run('analyze', (performance) {
+            return libraryAnalyzer.analyzeSync(
+              performance: performance,
+            );
+          });
         });
         UnitAnalysisResult fileResult = results[file];
 
diff --git a/pkg/analyzer/lib/src/dart/resolver/function_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/function_expression_resolver.dart
index 9dc3e92..bdf9dee 100644
--- a/pkg/analyzer/lib/src/dart/resolver/function_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/function_expression_resolver.dart
@@ -52,7 +52,7 @@
 
     var contextType = InferenceContext.getContext(node);
     if (contextType is FunctionType) {
-      contextType = _matchFunctionTypeParameters(
+      contextType = _matchTypeParameters(
         node.typeParameters,
         contextType,
       );
@@ -151,44 +151,27 @@
     return InferenceContext.getContext(body) ?? DynamicTypeImpl.instance;
   }
 
-  /// Given a downward inference type [fnType], and the declared
-  /// [typeParameterList] for a function expression, determines if we can enable
-  /// downward inference and if so, returns the function type to use for
-  /// inference.
+  /// Given the downward inference [type], return the function type expressed
+  /// in terms of the type parameters from [typeParameterList].
   ///
-  /// This will return null if inference is not possible. This happens when
-  /// there is no way we can find a subtype of the function type, given the
-  /// provided type parameter list.
-  FunctionType _matchFunctionTypeParameters(
-      TypeParameterList typeParameterList, FunctionType fnType) {
+  /// Return `null` is the number of element in [typeParameterList] is not
+  /// the same as the number of type parameters in the [type].
+  FunctionType _matchTypeParameters(
+      TypeParameterList typeParameterList, FunctionType type) {
     if (typeParameterList == null) {
-      if (fnType.typeFormals.isEmpty) {
-        return fnType;
+      if (type.typeFormals.isEmpty) {
+        return type;
       }
-
-      // A non-generic function cannot be a subtype of a generic one.
       return null;
     }
 
-    NodeList<TypeParameter> typeParameters = typeParameterList.typeParameters;
-    if (fnType.typeFormals.isEmpty) {
-      // TODO(jmesserly): this is a legal subtype. We don't currently infer
-      // here, but we could.  This is similar to
-      // Dart2TypeSystem.inferFunctionTypeInstantiation, but we don't
-      // have the FunctionType yet for the current node, so it's not quite
-      // straightforward to apply.
+    var typeParameters = typeParameterList.typeParameters;
+    if (typeParameters.length != type.typeFormals.length) {
       return null;
     }
 
-    if (fnType.typeFormals.length != typeParameters.length) {
-      // A subtype cannot have different number of type formals.
-      return null;
-    }
-
-    // Same number of type formals. Instantiate the function type so its
-    // parameter and return type are in terms of the surrounding context.
-    return fnType.instantiate(typeParameters.map((TypeParameter t) {
-      return t.declaredElement.instantiate(
+    return type.instantiate(typeParameters.map((typeParameter) {
+      return typeParameter.declaredElement.instantiate(
         nullabilitySuffix: _resolver.noneOrStarSuffix,
       );
     }).toList());
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index 754ed2f..0d7bb149b 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -43,9 +43,52 @@
               "has type '{2}'.");
 
   /**
-   * 16.12.2 Const: It is a compile-time error if evaluation of a constant
-   * object results in an uncaught exception being thrown.
+   * Parameters:
+   * 0: The type of the runtime value of the argument
+   * 1: The static type of the parameter
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when the runtime type of a constant
+  // value can't be assigned to the static type of a constant constructor's
+  // parameter.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the runtime type of `i`
+  // is `int`, which can't be assigned to the static type of `s`:
+  //
+  // ```dart
+  // class C {
+  //   final String s;
+  //
+  //   const C(this.s);
+  // }
+  //
+  // const dynamic i = 0;
+  //
+  // void f() {
+  //   const C([!i!]);
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Pass a value of the correct type to the constructor:
+  //
+  // ```dart
+  // class C {
+  //   final String s;
+  //
+  //   const C(this.s);
+  // }
+  //
+  // const dynamic i = 0;
+  //
+  // void f() {
+  //   const C('$i');
+  // }
+  // ```
   static const CheckedModeCompileTimeErrorCode
       CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH = CheckedModeCompileTimeErrorCode(
           'CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH',
@@ -2086,35 +2129,13 @@
       hasPublishedDocs: true);
 
   /**
-   * 12.2 Null: It is a compile-time error for a class to attempt to extend or
-   * implement Null.
-   *
-   * 12.3 Numbers: It is a compile-time error for a class to attempt to extend
-   * or implement int.
-   *
-   * 12.3 Numbers: It is a compile-time error for a class to attempt to extend
-   * or implement double.
-   *
-   * 12.3 Numbers: It is a compile-time error for any type other than the types
-   * int and double to
-   * attempt to extend or implement num.
-   *
-   * 12.4 Booleans: It is a compile-time error for a class to attempt to extend
-   * or implement bool.
-   *
-   * 12.5 Strings: It is a compile-time error for a class to attempt to extend
-   * or implement String.
-   *
    * Parameters:
-   * 0: the name of the type that cannot be extended
-   *
-   * See [IMPLEMENTS_DISALLOWED_CLASS] and [MIXIN_OF_DISALLOWED_CLASS].
-   *
-   * TODO(scheglov) We might want to restore specific code with FrontEnd.
-   * https://github.com/dart-lang/sdk/issues/31821
+   * 0: The name of the disallowed type
    */
   static const CompileTimeErrorCode EXTENDS_DISALLOWED_CLASS =
-      CompileTimeErrorCode(
+      // TODO(scheglov) We might want to restore specific code with FrontEnd.
+      //  https://github.com/dart-lang/sdk/issues/31821
+      CompileTimeErrorCodeWithUniqueName('SUBTYPE_OF_DISALLOWED_TYPE',
           'EXTENDS_DISALLOWED_CLASS', "Classes can't extend '{0}'.",
           correction: "Try specifying a different superclass, or "
               "removing the extends clause.");
@@ -2719,32 +2740,13 @@
               "changing the import to not be deferred.");
 
   /**
-   * 12.2 Null: It is a compile-time error for a class to attempt to extend or
-   * implement Null.
-   *
-   * 12.3 Numbers: It is a compile-time error for a class to attempt to extend
-   * or implement int.
-   *
-   * 12.3 Numbers: It is a compile-time error for a class to attempt to extend
-   * or implement double.
-   *
-   * 12.3 Numbers: It is a compile-time error for any type other than the types
-   * int and double to
-   * attempt to extend or implement num.
-   *
-   * 12.4 Booleans: It is a compile-time error for a class to attempt to extend
-   * or implement bool.
-   *
-   * 12.5 Strings: It is a compile-time error for a class to attempt to extend
-   * or implement String.
-   *
    * Parameters:
-   * 0: the name of the type that cannot be implemented
-   *
-   * See [EXTENDS_DISALLOWED_CLASS].
+   * 0: The name of the disallowed type
    */
   static const CompileTimeErrorCode IMPLEMENTS_DISALLOWED_CLASS =
-      CompileTimeErrorCode('IMPLEMENTS_DISALLOWED_CLASS',
+      CompileTimeErrorCodeWithUniqueName(
+          'SUBTYPE_OF_DISALLOWED_TYPE',
+          'IMPLEMENTS_DISALLOWED_CLASS',
           "Classes and mixins can't implement '{0}'.",
           correction: "Try specifying a different interface, or "
               "remove the class from the list.");
@@ -2836,7 +2838,8 @@
           correction: "Try removing one of the occurrences.");
 
   /**
-   * No parameters.
+   * Parameters:
+   * 0: the name of the instance member
    */
   // #### Description
   //
@@ -2886,15 +2889,33 @@
   // ```
   static const CompileTimeErrorCode IMPLICIT_THIS_REFERENCE_IN_INITIALIZER =
       CompileTimeErrorCode('IMPLICIT_THIS_REFERENCE_IN_INITIALIZER',
-          "Only static members can be accessed in initializers.",
+          "The instance member '{0}' can't be accessed in an initializer.",
+          correction:
+              'Try replacing the reference to the instance member with a '
+              'different expression',
           hasPublishedDocs: true);
 
   /**
-   * SDK implementation libraries can be imported only by other SDK libraries.
-   *
    * Parameters:
    * 0: the uri pointing to a library
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when it finds an import whose `dart:`
+  // URI references an internal library.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because `_interceptors` is an
+  // internal library:
+  //
+  // ```dart
+  // import [!'dart:_interceptors'!];
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Remove the import directive.
   static const CompileTimeErrorCode IMPORT_INTERNAL_LIBRARY =
       CompileTimeErrorCode('IMPORT_INTERNAL_LIBRARY',
           "The library '{0}' is internal and can't be imported.");
@@ -2925,17 +2946,53 @@
           "Case expressions must have the same types, '{0}' isn't a '{1}'.");
 
   /**
-   * If a class declaration does not have a member declaration with a
-   * particular name, but some super-interfaces do have a member with that
-   * name, it's a compile-time error if there is no signature among the
-   * super-interfaces that is a valid override of all the other super-interface
-   * signatures with the same name. That "most specific" signature becomes the
-   * signature of the class's interface.
-   *
    * Parameters:
    * 0: the name of the instance member with inconsistent inheritance.
    * 1: the list of all inherited signatures for this member.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a class inherits two or more
+  // conflicting signatures for a member and doesn't provide an implementation
+  // that satisfies all the inherited signatures.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because `C` is inheriting the
+  // declaration of `m` from `A`, and that implementation isn't consistent with
+  // the signature of `m` that's inherited from `B`:
+  //
+  // ```dart
+  // class A {
+  //   void m({int a}) {}
+  // }
+  //
+  // class B {
+  //   void m({int b}) {}
+  // }
+  //
+  // class [!C!] extends A implements B {
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Add an implementation of the method that satisfies all the inherited
+  // signatures:
+  //
+  // ```dart
+  // class A {
+  //   void m({int a}) {}
+  // }
+  //
+  // class B {
+  //   void m({int b}) {}
+  // }
+  //
+  // class C extends A implements B {
+  //   void m({int a, int b}) {}
+  // }
+  // ```
   static const CompileTimeErrorCode INCONSISTENT_INHERITANCE =
       CompileTimeErrorCode('INCONSISTENT_INHERITANCE',
           "Superinterfaces don't have a valid override for '{0}': {1}.",
@@ -4076,31 +4133,11 @@
       'MIXIN_INSTANTIATE', "Mixins can't be instantiated.");
 
   /**
-   * 12.2 Null: It is a compile-time error for a class to attempt to extend or
-   * implement Null.
-   *
-   * 12.3 Numbers: It is a compile-time error for a class to attempt to extend
-   * or implement int.
-   *
-   * 12.3 Numbers: It is a compile-time error for a class to attempt to extend
-   * or implement double.
-   *
-   * 12.3 Numbers: It is a compile-time error for any type other than the types
-   * int and double to attempt to extend or implement num.
-   *
-   * 12.4 Booleans: It is a compile-time error for a class to attempt to extend
-   * or implement bool.
-   *
-   * 12.5 Strings: It is a compile-time error for a class to attempt to extend
-   * or implement String.
-   *
    * Parameters:
-   * 0: the name of the type that cannot be extended
-   *
-   * See [IMPLEMENTS_DISALLOWED_CLASS].
+   * 0: The name of the disallowed type
    */
   static const CompileTimeErrorCode MIXIN_OF_DISALLOWED_CLASS =
-      CompileTimeErrorCode(
+      CompileTimeErrorCodeWithUniqueName('SUBTYPE_OF_DISALLOWED_TYPE',
           'MIXIN_OF_DISALLOWED_CLASS', "Classes can't mixin '{0}'.");
 
   /**
@@ -4135,14 +4172,23 @@
       'MIXIN_OF_NON_CLASS', "Classes can only mix in mixins and classes.",
       hasPublishedDocs: true);
 
+  /**
+   * No parameters.
+   */
   static const CompileTimeErrorCode
       MIXIN_SUPER_CLASS_CONSTRAINT_DEFERRED_CLASS = CompileTimeErrorCode(
           'MIXIN_SUPER_CLASS_CONSTRAINT_DEFERRED_CLASS',
           "Deferred classes can't be used as super-class constraints.",
           correction: "Try changing the import to not be deferred.");
 
+  /**
+   * Parameters:
+   * 0: The name of the disallowed type
+   */
   static const CompileTimeErrorCode
-      MIXIN_SUPER_CLASS_CONSTRAINT_DISALLOWED_CLASS = CompileTimeErrorCode(
+      MIXIN_SUPER_CLASS_CONSTRAINT_DISALLOWED_CLASS =
+      CompileTimeErrorCodeWithUniqueName(
+          'SUBTYPE_OF_DISALLOWED_TYPE',
           'MIXIN_SUPER_CLASS_CONSTRAINT_DISALLOWED_CLASS',
           "'{0}' can't be used as a super-class constraint.");
 
@@ -4646,14 +4692,46 @@
           correction: "Try removing the keyword 'const' from the map literal.");
 
   /**
-   * 15 Metadata: Metadata consists of a series of annotations, each of which
-   * begin with the character @, followed by a constant expression that must be
-   * either a reference to a compile-time constant variable, or a call to a
-   * constant constructor.
-   *
-   * "From deferred library" case is covered by
-   * [CompileTimeErrorCode.INVALID_ANNOTATION_FROM_DEFERRED_LIBRARY].
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when an annotation is the invocation
+  // of an existing constructor even though the invoked constructor isn't a
+  // const constructor.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the constructor for `C`
+  // isn't a const constructor:
+  //
+  // ```dart
+  // [!@C()!]
+  // void f() {
+  // }
+  //
+  // class C {
+  //   C();
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If it's valid for the class to have a const constructor, then create a
+  // const constructor that can be used for the annotation:
+  //
+  // ```dart
+  // @C()
+  // void f() {
+  // }
+  //
+  // class C {
+  //   const C();
+  // }
+  // ```
+  //
+  // If it isn't valid for the class to have a const constructor, then either
+  // remove the annotation or use a different class for the annotation.
   static const CompileTimeErrorCode NON_CONSTANT_ANNOTATION_CONSTRUCTOR =
       CompileTimeErrorCode('NON_CONSTANT_ANNOTATION_CONSTRUCTOR',
           "Annotation creation can only call a const constructor.");
@@ -5411,9 +5489,43 @@
               "Try renaming either the top-level element or the prefix.");
 
   /**
-   * 16.32 Identifier Reference: If d is a prefix p, a compile-time error
-   * occurs unless the token immediately following d is '.'.
+   * Parameters:
+   * 0: The name of the prefix
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when an import prefix is used by
+  // itself, without accessing any of the names declared in the libraries
+  // associated with the prefix. Prefixes aren't variables, and therefore can't
+  // be used as a value.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the prefix `math` is
+  // being used as if it were a variable:
+  //
+  // ```dart
+  // import 'dart:math' as math;
+  //
+  // void f() {
+  //   print([!math!]);
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the code is incomplete, then reference something in one of the libraries
+  // associated with the prefix:
+  //
+  // ```dart
+  // import 'dart:math' as math;
+  //
+  // void f() {
+  //   print(math.pi);
+  // }
+  // ```
+  //
+  // If the name is wrong, then correct the name.
   static const CompileTimeErrorCode PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT =
       CompileTimeErrorCode(
           'PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT',
@@ -5721,9 +5833,53 @@
               "'throw' expression.");
 
   /**
-   * 13.12 Return: It is a compile-time error if a return statement of the form
-   * <i>return e;</i> appears in a generative constructor.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a generative constructor
+  // contains a return statement that specifies a value to be returned.
+  // Generative constructors always return the object that was created, and
+  // therefore can't return a different object.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the return statement
+  // has an expression:
+  //
+  // ```dart
+  // class C {
+  //   C() {
+  //     return [!this!];
+  //   }
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the constructor should create a new instance, then remove either the
+  // return statement or the expression:
+  //
+  // ```dart
+  // class C {
+  //   C();
+  // }
+  // ```
+  //
+  // If the constructor shouldn't create a new instance, then convert it to be a
+  // factory constructor:
+  //
+  // ```dart
+  // class C {
+  //   factory C() {
+  //     return _instance;
+  //   }
+  //
+  //   static C _instance = C._();
+  //
+  //   C._();
+  // }
+  // ```
   static const CompileTimeErrorCode RETURN_IN_GENERATIVE_CONSTRUCTOR =
       CompileTimeErrorCode('RETURN_IN_GENERATIVE_CONSTRUCTOR',
           "Constructors can't return values.",
@@ -6935,9 +7091,44 @@
               "removing the modifier 'async*' from the function body.");
 
   /**
-   * 9 Functions: It is a static warning if the declared return type of a
-   * function marked async may not be assigned to Future.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when the body of a function has the
+  // `async` modifier even though the return type of the function isn't
+  // assignable to `Future`.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the body of the
+  // function `f` has the `async` modifier even though the return type isn't
+  // assignable to `Future`:
+  //
+  // ```dart
+  // [!int!] f() async {
+  //   return 0;
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the function should be asynchronous, then change the return type to be
+  // assignable to `Future`:
+  //
+  // ```dart
+  // Future<int> f() async {
+  //   return 0;
+  // }
+  // ```
+  //
+  // If the function should be synchronous, then remove the `async` modifier:
+  //
+  // ```dart
+  // int f() {
+  //   return 0;
+  // }
+  // ```
   static const StaticTypeWarningCode ILLEGAL_ASYNC_RETURN_TYPE =
       StaticTypeWarningCode(
           'ILLEGAL_ASYNC_RETURN_TYPE',
@@ -7446,17 +7637,49 @@
           correction: "Try using a type that is or is a subclass of '{1}'.");
 
   /**
-   * 12.17 Getter Invocation: It is a static warning if there is no class
-   * <i>C</i> in the enclosing lexical scope of <i>i</i>, or if <i>C</i> does
-   * not declare, implicitly or explicitly, a getter named <i>m</i>.
-   *
    * Parameters:
    * 0: the name of the enumeration constant that is not defined
    * 1: the name of the enumeration used to access the constant
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when it encounters an identifier that
+  // appears to be the name of an enum constant, and the name either isn't
+  // defined or isn't visible in the scope in which it's being referenced.
+  //
+  // #### Examples
+  //
+  // The following code produces this diagnostic because `E` doesn't define a
+  // constant named `c`:
+  //
+  // ```dart
+  // enum E {a, b}
+  //
+  // var e = E.[!c!];
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the constant should be defined, then add it to the declaration of the
+  // enum:
+  //
+  // ```dart
+  // enum E {a, b, c}
+  //
+  // var e = E.c;
+  // ```
+  //
+  // If the constant shouldn't be defined, then change the name to the name of
+  // an existing constant:
+  //
+  // ```dart
+  // enum E {a, b}
+  //
+  // var e = E.b;
+  // ```
   static const StaticTypeWarningCode UNDEFINED_ENUM_CONSTANT =
       StaticTypeWarningCode('UNDEFINED_ENUM_CONSTANT',
-          "There is no constant named '{0}' in '{1}'.",
+          "There's no constant named '{0}' in '{1}'.",
           correction:
               "Try correcting the name to the name of an existing constant, or "
               "defining a constant named '{0}'.");
@@ -8613,15 +8836,54 @@
       CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS_COULD_BE_NAMED;
 
   /**
-   * 5. Variables: It is a static warning if a final instance variable that has
-   * been initialized at its point of declaration is also initialized in a
-   * constructor.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a final field is initialized in
+  // both the declaration of the field and in an initializer in a constructor.
+  // Final fields can only be assigned once, so it can't be initialized in both
+  // places.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because `f` is :
+  //
+  // ```dart
+  // class C {
+  //   final int f = 0;
+  //   C() : [!f!] = 1;
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the initialization doesn't depend on any values passed to the
+  // constructor, and if all of the constructors need to initialize the field to
+  // the same value, then remove the initializer from the constructor:
+  //
+  // ```dart
+  // class C {
+  //   final int f = 0;
+  //   C();
+  // }
+  // ```
+  //
+  // If the initialization depends on a value passed to the constructor, or if
+  // different constructors need to initialize the field differently, then
+  // remove the initializer in the field's declaration:
+  //
+  // ```dart
+  // class C {
+  //   final int f;
+  //   C() : f = 1;
+  // }
+  // ```
   static const StaticWarningCode
       FIELD_INITIALIZED_IN_INITIALIZER_AND_DECLARATION = StaticWarningCode(
           'FIELD_INITIALIZED_IN_INITIALIZER_AND_DECLARATION',
           "Fields can't be initialized in the constructor if they are final "
-              "and have already been initialized at their declaration.",
+              "and were already initialized at their declaration.",
           correction: "Try removing one of the initializations.");
 
   /**
@@ -8640,22 +8902,52 @@
           correction: "Try removing one of the initializations.");
 
   /**
-   * 7.6.1 Generative Constructors: Execution of an initializer of the form
-   * <b>this</b>.<i>v</i> = <i>e</i> proceeds as follows: First, the expression
-   * <i>e</i> is evaluated to an object <i>o</i>. Then, the instance variable
-   * <i>v</i> of the object denoted by this is bound to <i>o</i>.
-   *
-   * 12.14.2 Binding Actuals to Formals: Let <i>T<sub>i</sub></i> be the static
-   * type of <i>a<sub>i</sub></i>, let <i>S<sub>i</sub></i> be the type of
-   * <i>p<sub>i</sub>, 1 &lt;= i &lt;= n+k</i> and let <i>S<sub>q</sub></i> be
-   * the type of the named parameter <i>q</i> of <i>f</i>. It is a static
-   * warning if <i>T<sub>j</sub></i> may not be assigned to <i>S<sub>j</sub>, 1
-   * &lt;= j &lt;= m</i>.
-   *
    * Parameters:
    * 0: the name of the type of the initializer expression
    * 1: the name of the type of the field
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when the initializer list of a
+  // constructor initializes a field to a value that isn't assignable to the
+  // field.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because `0` has the type `int`,
+  // and an `int` can't be assigned to a field of type `String`:
+  //
+  // ```dart
+  // class C {
+  //   String s;
+  //
+  //   C() : s = [!0!];
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the type of the field is correct, then change the value assigned to it
+  // so that the value has a valid type:
+  //
+  // ```dart
+  // class C {
+  //   String s;
+  //
+  //   C() : s = '0';
+  // }
+  // ```
+  //
+  // If the type of the value is correct, then change the type of the field to
+  // allow the assignment:
+  //
+  // ```dart
+  // class C {
+  //   int s;
+  //
+  //   C() : s = 0;
+  // }
+  // ```
   static const StaticWarningCode FIELD_INITIALIZER_NOT_ASSIGNABLE =
       StaticWarningCode(
           'FIELD_INITIALIZER_NOT_ASSIGNABLE',
@@ -9587,14 +9879,41 @@
       CompileTimeErrorCode.NOT_ENOUGH_POSITIONAL_ARGUMENTS;
 
   /**
-   * 14.3 Parts: It is a static warning if the referenced part declaration
-   * <i>p</i> names a library other than the current library as the library to
-   * which <i>p</i> belongs.
-   *
    * Parameters:
    * 0: the name of expected library name
    * 1: the non-matching actual library name from the "part of" declaration
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when a library attempts to include a
+  // file as a part of itself when the other file is a part of a different
+  // library.
+  //
+  // #### Example
+  //
+  // Given a file named `part.dart` containing
+  //
+  // ```dart
+  // %uri="package:a/part.dart"
+  // part of 'library.dart';
+  // ```
+  //
+  // The following code, in any file other than `library.dart`, produces this
+  // diagnostic because it attempts to include `part.dart` as a part of itself
+  // when `part.dart` is a part of a different library:
+  //
+  // ```dart
+  // part [!'package:a/part.dart'!];
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the library should be using a different file as a part, then change the
+  // URI in the part directive to be the URI of the other file.
+  //
+  // If the part file should be a part of this library, then update the URI (or
+  // library name) in the part-of directive to be the URI (or name) of the
+  // correct library.
   static const StaticWarningCode PART_OF_DIFFERENT_LIBRARY = StaticWarningCode(
       'PART_OF_DIFFERENT_LIBRARY',
       "Expected this library to be part of '{0}', not '{1}'.",
@@ -9850,9 +10169,55 @@
           hasPublishedDocs: true);
 
   /**
-   * 13.9 Switch: It is a static warning if the type of <i>e</i> may not be
-   * assigned to the type of <i>e<sub>k</sub></i>.
+   * Parameters:
+   * 0: The static type of the switch expression
+   * 1: The static type of the case expressions
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when the type of the expression in a
+  // switch statement isn't assignable to the type of the expressions in the
+  // case clauses.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the type of `s`
+  // (`String`) isn't assignable to the type of `0` (`int`):
+  //
+  // ```dart
+  // void f(String s) {
+  //   switch ([!s!]) {
+  //     case 0:
+  //       break;
+  //   }
+  // }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // If the type of the case expressions is correct, then change the expression
+  // in the switch statement to have the correct type:
+  //
+  // ```dart
+  // void f(String s) {
+  //   switch (int.parse(s)) {
+  //     case 0:
+  //       break;
+  //   }
+  // }
+  // ```
+  //
+  // If the type of the switch expression is correct, then change the case
+  // expressions to have the correct type:
+  //
+  // ```dart
+  // void f(String s) {
+  //   switch (s) {
+  //     case '0':
+  //       break;
+  //   }
+  // }
+  // ```
   static const StaticWarningCode SWITCH_EXPRESSION_NOT_ASSIGNABLE =
       StaticWarningCode(
           'SWITCH_EXPRESSION_NOT_ASSIGNABLE',
@@ -9992,8 +10357,32 @@
           isUnresolvedIdentifier: true);
 
   /**
-   * If the identifier is 'await', be helpful about it.
+   * No parameters.
    */
+  // #### Description
+  //
+  // The analyzer produces this diagnostic when the name `await` is used in a
+  // method or function body without being declared, and the body isn't marked
+  // with the `async` keyword. The name `await` only introduces an await
+  // expression in an asynchronous function.
+  //
+  // #### Example
+  //
+  // The following code produces this diagnostic because the name `await` is
+  // used in the body of `f` even though the body of `f` isn't marked with the
+  // `async` keyword:
+  //
+  // ```dart
+  // void f(p) { [!await!] p; }
+  // ```
+  //
+  // #### Common fixes
+  //
+  // Add the keyword `async` to the function body:
+  //
+  // ```dart
+  // void f(p) async { await p; }
+  // ```
   static const StaticWarningCode UNDEFINED_IDENTIFIER_AWAIT = StaticWarningCode(
       'UNDEFINED_IDENTIFIER_AWAIT',
       "Undefined name 'await' in function body not marked with 'async'.",
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 17069da..2cab966 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -2869,7 +2869,8 @@
     } else {
       _errorReporter.reportErrorForNode(
           CompileTimeErrorCode.IMPLICIT_THIS_REFERENCE_IN_INITIALIZER,
-          identifier);
+          identifier,
+          [identifier.name]);
     }
   }
 
diff --git a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
index 0ca7c3f..d44f818 100644
--- a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
+++ b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
@@ -1020,9 +1020,9 @@
       '''
 library dart.math;
 
-const double E = 2.718281828459045;
-const double PI = 3.1415926535897932;
-const double LN10 = 2.302585092994046;
+const double e = 2.718281828459045;
+const double pi = 3.1415926535897932;
+const double ln10 = 2.302585092994046;
 
 T min<T extends num>(T a, T b) => throw 0;
 T max<T extends num>(T a, T b) => throw 0;
diff --git a/pkg/analyzer/lib/src/workspace/package_build.dart b/pkg/analyzer/lib/src/workspace/package_build.dart
index 1fc9340..effc784 100644
--- a/pkg/analyzer/lib/src/workspace/package_build.dart
+++ b/pkg/analyzer/lib/src/workspace/package_build.dart
@@ -60,6 +60,8 @@
       : _workspace = workspace,
         _context = workspace.provider.pathContext;
 
+  Map<String, List<Folder>> get packageMap => _workspace._packageMap;
+
   @override
   Source resolveAbsolute(Uri _ignore, [Uri uri]) {
     uri ??= _ignore;
diff --git a/pkg/analyzer/test/src/dart/analysis/feature_set_provider_test.dart b/pkg/analyzer/test/src/dart/analysis/feature_set_provider_test.dart
index 0696a67..f5328f8 100644
--- a/pkg/analyzer/test/src/dart/analysis/feature_set_provider_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/feature_set_provider_test.dart
@@ -85,8 +85,12 @@
     );
 
     _assertNonNullableForPath('/packages/aaa/lib/a.dart', true);
+    _assertNonNullableForPath('/packages/aaa/bin/b.dart', true);
+    _assertNonNullableForPath('/packages/aaa/test/c.dart', true);
 
-    _assertNonNullableForPath('/packages/bbb/lib/b.dart', false);
+    _assertNonNullableForPath('/packages/bbb/lib/a.dart', false);
+    _assertNonNullableForPath('/packages/bbb/bin/b.dart', false);
+    _assertNonNullableForPath('/packages/bbb/test/c.dart', false);
 
     _assertNonNullableForPath('/other/file.dart', false);
   }
diff --git a/pkg/analyzer/test/src/dart/analysis/search_test.dart b/pkg/analyzer/test/src/dart/analysis/search_test.dart
index 47d262f..ec7fe9f 100644
--- a/pkg/analyzer/test/src/dart/analysis/search_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/search_test.dart
@@ -541,10 +541,10 @@
 
   test_searchReferences_ImportElement_noPrefix() async {
     await _resolveTestUnit('''
-import 'dart:math' show max, PI, Random hide min;
-export 'dart:math' show max, PI, Random hide min;
+import 'dart:math' show max, pi, Random hide min;
+export 'dart:math' show max, pi, Random hide min;
 main() {
-  print(PI);
+  print(pi);
   print(new Random());
   print(max(1, 2));
 }
@@ -555,7 +555,7 @@
     var bar = findElement.function('bar');
     var kind = SearchResultKind.REFERENCE;
     var expected = [
-      _expectId(main, kind, 'PI);', length: 0),
+      _expectId(main, kind, 'pi);', length: 0),
       _expectId(main, kind, 'Random()', length: 0),
       _expectId(main, kind, 'max(', length: 0),
       _expectId(bar, kind, 'Random bar()', length: 0),
@@ -566,10 +566,10 @@
   test_searchReferences_ImportElement_noPrefix_inPackage() async {
     testFile = convertPath('/aaa/lib/a.dart');
     await _resolveTestUnit('''
-import 'dart:math' show max, PI, Random hide min;
-export 'dart:math' show max, PI, Random hide min;
+import 'dart:math' show max, pi, Random hide min;
+export 'dart:math' show max, pi, Random hide min;
 main() {
-  PI;
+  pi;
   new Random();
   max(1, 2);
 }
@@ -580,7 +580,7 @@
     var bar = findElement.function('bar');
     var kind = SearchResultKind.REFERENCE;
     var expected = [
-      _expectId(main, kind, 'PI;', length: 0),
+      _expectId(main, kind, 'pi;', length: 0),
       _expectId(main, kind, 'Random();', length: 0),
       _expectId(main, kind, 'max(1, 2);', length: 0),
       _expectId(bar, kind, 'Random bar()', length: 0),
@@ -590,10 +590,10 @@
 
   test_searchReferences_ImportElement_withPrefix() async {
     await _resolveTestUnit('''
-import 'dart:math' as math show max, PI, Random hide min;
-export 'dart:math' show max, PI, Random hide min;
+import 'dart:math' as math show max, pi, Random hide min;
+export 'dart:math' show max, pi, Random hide min;
 main() {
-  print(math.PI);
+  print(math.pi);
   print(new math.Random());
   print(math.max(1, 2));
 }
@@ -605,7 +605,7 @@
     var kind = SearchResultKind.REFERENCE;
     var length = 'math.'.length;
     var expected = [
-      _expectId(main, kind, 'math.PI);', length: length),
+      _expectId(main, kind, 'math.pi);', length: length),
       _expectId(main, kind, 'math.Random()', length: length),
       _expectId(main, kind, 'math.max(', length: length),
       _expectId(bar, kind, 'math.Random bar()', length: length),
@@ -1728,19 +1728,19 @@
 class B = Object with A;
 mixin C {}
 typedef D();
-e() {}
-var f = null;
+f() {}
+var g = null;
 class NoMatchABCDEF {}
 ''');
     var a = findElement.class_('A');
     var b = findElement.class_('B');
     var c = findElement.mixin('C');
     var d = findElement.functionTypeAlias('D');
-    var e = findElement.function('e');
-    var f = findElement.topVar('f');
-    RegExp regExp = RegExp(r'^[ABCDef]$');
+    var f = findElement.function('f');
+    var g = findElement.topVar('g');
+    RegExp regExp = RegExp(r'^[ABCDfg]$');
     expect(await driver.search.topLevelElements(regExp),
-        unorderedEquals([a, b, c, d, e, f]));
+        unorderedEquals([a, b, c, d, f, g]));
   }
 
   ExpectedResult _expectId(
diff --git a/pkg/analyzer/test/src/dart/micro/file_resolution.dart b/pkg/analyzer/test/src/dart/micro/file_resolution.dart
index 395f676..27b5316 100644
--- a/pkg/analyzer/test/src/dart/micro/file_resolution.dart
+++ b/pkg/analyzer/test/src/dart/micro/file_resolution.dart
@@ -58,12 +58,12 @@
 
   ErrorsResult getTestErrors() {
     var path = convertPath(_testFile);
-    return fileResolver.getErrors(path);
+    return fileResolver.getErrors2(path: path);
   }
 
   @override
   Future<ResolvedUnitResult> resolveFile(String path) async {
-    return fileResolver.resolve(path);
+    return fileResolver.resolve2(path: path);
   }
 
   @override
diff --git a/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart b/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
index de3b2ed..40a6e38 100644
--- a/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
+++ b/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
@@ -46,20 +46,20 @@
 ''');
 
     // First time we refresh everything.
-    await fileResolver.resolve(cPath);
+    await fileResolver.resolve2(path: cPath);
     _assertRefreshedFiles([aPath, bPath, cPath], withSdk: true);
 
     // Without changes we refresh nothing.
-    await fileResolver.resolve(cPath);
+    await fileResolver.resolve2(path: cPath);
     _assertRefreshedFiles([]);
 
     // We already know a.dart, refresh nothing.
-    await fileResolver.resolve(aPath);
+    await fileResolver.resolve2(path: aPath);
     _assertRefreshedFiles([]);
 
     // Change a.dart, refresh a.dart and c.dart, but not b.dart
     fileResolver.changeFile(aPath);
-    await fileResolver.resolve(cPath);
+    await fileResolver.resolve2(path: cPath);
     _assertRefreshedFiles([aPath, cPath]);
   }
 
@@ -74,7 +74,7 @@
 B b;
 ''');
 
-    result = fileResolver.resolve(bPath);
+    result = fileResolver.resolve2(path: bPath);
     assertErrorsInResolvedUnit(result, [
       error(CompileTimeErrorCode.UNDEFINED_CLASS, 22, 1),
     ]);
@@ -85,7 +85,7 @@
 ''');
     fileResolver.changeFile(aPath);
 
-    result = fileResolver.resolve(bPath);
+    result = fileResolver.resolve2(path: bPath);
     assertErrorsInResolvedUnit(result, []);
   }
 
@@ -107,17 +107,17 @@
 ''');
 
     // First time we refresh everything.
-    await fileResolver.resolve(bPath);
+    await fileResolver.resolve2(path: bPath);
     _assertRefreshedFiles([aPath, bPath], withSdk: true);
     // Change b.dart, refresh a.dart
     fileResolver.changeFile(bPath);
-    await fileResolver.resolve(bPath);
+    await fileResolver.resolve2(path: bPath);
     _assertRefreshedFiles([aPath, bPath]);
     // now with c.dart
-    await fileResolver.resolve(cPath);
+    await fileResolver.resolve2(path: cPath);
     _assertRefreshedFiles([cPath]);
     fileResolver.changeFile(bPath);
-    await fileResolver.resolve(cPath);
+    await fileResolver.resolve2(path: cPath);
     _assertRefreshedFiles([aPath, bPath, cPath]);
   }
 
diff --git a/pkg/analyzer/test/src/dart/resolution/language_version_test.dart b/pkg/analyzer/test/src/dart/resolution/language_version_test.dart
index 685009e..2d30010 100644
--- a/pkg/analyzer/test/src/dart/resolution/language_version_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/language_version_test.dart
@@ -8,6 +8,8 @@
 import 'package:analyzer/src/dart/error/syntactic_errors.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/test_utilities/find_element.dart';
+import 'package:analyzer/src/test_utilities/find_node.dart';
 import 'package:analyzer/src/test_utilities/mock_sdk.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -62,7 +64,7 @@
 
 var x = 0;
 var y = a;
-var z = PI;
+var z = pi;
 ''');
     assertType(findElement.topVar('x').type, 'int*');
     assertType(findElement.topVar('y').type, 'int*');
@@ -99,7 +101,7 @@
 
 var x = 0;
 var y = a;
-var z = PI;
+var z = pi;
 ''');
     assertType(findElement.topVar('x').type, 'int');
     assertType(findElement.topVar('y').type, 'int');
@@ -115,7 +117,40 @@
   @override
   bool get typeToStringWithNullability => true;
 
-  test_jsonConfig_disable() async {
+  test_jsonConfig_disable_bin() async {
+    _configureAllowedExperimentsTestNullSafety();
+
+    _configureTestWithJsonConfig('''
+{
+  "configVersion": 2,
+  "packages": [
+    {
+      "name": "test",
+      "rootUri": "../",
+      "packageUri": "lib/",
+      "languageVersion": "2.8"
+    }
+  ]
+}
+''');
+
+    var path = convertPath('/test/bin/a.dart');
+    await _resolveFile(path, r'''
+var x = 0;
+''');
+    assertErrorsInList(result.errors, []);
+    assertType(findElement.topVar('x').type, 'int*');
+
+    // Upgrade the language version to `2.9`, so enabled Null Safety.
+    driver.changeFile(path);
+    await _resolveFile(path, r'''
+// @dart = 2.9
+var x = 0;
+''');
+    assertType(findElement.topVar('x').type, 'int');
+  }
+
+  test_jsonConfig_disable_lib() async {
     _configureAllowedExperimentsTestNullSafety();
 
     _configureTestWithJsonConfig('''
@@ -146,7 +181,39 @@
     assertType(findElement.topVar('x').type, 'int');
   }
 
-  test_jsonConfig_enable() async {
+  test_jsonConfig_enable_bin() async {
+    _configureAllowedExperimentsTestNullSafety();
+
+    _configureTestWithJsonConfig('''
+{
+  "configVersion": 2,
+  "packages": [
+    {
+      "name": "test",
+      "rootUri": "../",
+      "packageUri": "lib/"
+    }
+  ]
+}
+''');
+
+    var path = convertPath('/test/bin/a.dart');
+    await _resolveFile(path, r'''
+var x = 0;
+''');
+    assertErrorsInList(result.errors, []);
+    assertType(findElement.topVar('x').type, 'int');
+
+    // Downgrade the version to `2.8`, so disable Null Safety.
+    driver.changeFile(path);
+    await _resolveFile(path, r'''
+// @dart = 2.8
+var x = 0;
+''');
+    assertType(findElement.topVar('x').type, 'int*');
+  }
+
+  test_jsonConfig_enable_lib() async {
     _configureAllowedExperimentsTestNullSafety();
 
     _configureTestWithJsonConfig('''
@@ -203,8 +270,18 @@
   }
 
   void _newSdkExperimentsFile(String content) {
-    newFile('$sdkRoot/lib/_internal/allowed_experiments.json',
-        content: content);
+    newFile(
+      '$sdkRoot/lib/_internal/allowed_experiments.json',
+      content: content,
+    );
+  }
+
+  Future<void> _resolveFile(String path, String content) async {
+    newFile(path, content: content);
+    result = await resolveFile(path);
+
+    findNode = FindNode(result.content, result.unit);
+    findElement = FindElement(result.unit);
   }
 }
 
diff --git a/pkg/analyzer/test/src/diagnostics/unnecessary_cast_test.dart b/pkg/analyzer/test/src/diagnostics/unnecessary_cast_test.dart
index 97a4925..79c6f59 100644
--- a/pkg/analyzer/test/src/diagnostics/unnecessary_cast_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unnecessary_cast_test.dart
@@ -27,13 +27,11 @@
   }
 
   test_dynamic_type() async {
-    await assertErrorsInCode(r'''
+    await assertNoErrorsInCode(r'''
 m(v) {
-  var b = v as Object;
+  v as Object;
 }
-''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 13, 1),
-    ]);
+''');
   }
 
   test_function() async {
@@ -46,19 +44,16 @@
   }
 
   test_function2() async {
-    await assertErrorsInCode(r'''
+    await assertNoErrorsInCode(r'''
 class A {}
 
 class B<T extends A> {
   void foo() {
     T Function(T) f;
-    A Function(A) g;
-    g = f as A Function(A);
+    f as A Function(A);
   }
 }
-''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 89, 1),
-    ]);
+''');
   }
 
   test_generics() async {
@@ -90,34 +85,30 @@
   }
 
   test_type_dynamic() async {
-    await assertErrorsInCode(r'''
+    await assertNoErrorsInCode(r'''
 m(v) {
-  var b = Object as dynamic;
+  Object as dynamic;
 }
-''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 13, 1),
-    ]);
+''');
   }
 
   test_type_supertype() async {
     await assertErrorsInCode(r'''
 m(int i) {
-  var b = i as Object;
+  i as Object;
 }
 ''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 17, 1),
-      error(HintCode.UNNECESSARY_CAST, 21, 11),
+      error(HintCode.UNNECESSARY_CAST, 13, 11),
     ]);
   }
 
   test_type_type() async {
     await assertErrorsInCode(r'''
 m(num i) {
-  var b = i as num;
+  i as num;
 }
 ''', [
-      error(HintCode.UNUSED_LOCAL_VARIABLE, 17, 1),
-      error(HintCode.UNNECESSARY_CAST, 21, 8),
+      error(HintCode.UNNECESSARY_CAST, 13, 8),
     ]);
   }
 }
diff --git a/pkg/analyzer/test/verify_diagnostics_test.dart b/pkg/analyzer/test/verify_diagnostics_test.dart
index 5cd6fd9..ee476e0 100644
--- a/pkg/analyzer/test/verify_diagnostics_test.dart
+++ b/pkg/analyzer/test/verify_diagnostics_test.dart
@@ -40,6 +40,10 @@
   static const List<String> unverifiedDocs = [
     // Produces two diagnostics when it should only produce one.
     'CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE',
+    // Produces two diagnostics when it should only produce one. We could get
+    // rid of the invalid error by adding a declaration of a top-level variable
+    // (such as `JSBool b;`), but that would complicate the example.
+    'CompileTimeErrorCode.IMPORT_INTERNAL_LIBRARY',
     // Produces two diagnostics when it should only produce one.
     'CompileTimeErrorCode.INVALID_URI',
     // Need a way to make auxiliary files that (a) are not included in the
@@ -51,6 +55,8 @@
     'StaticWarningCode.AMBIGUOUS_IMPORT',
     // Produces two diagnostics when it should only produce one.
     'StaticWarningCode.INVALID_USE_OF_NULL_VALUE',
+    // Produces the diagnostic HintCode.UNUSED_LOCAL_VARIABLE when it shouldn't.
+    'StaticWarningCode.UNDEFINED_IDENTIFIER_AWAIT',
   ];
 
   /// The prefix used on directive lines to specify the experiments that should
diff --git a/pkg/analyzer/tool/diagnostics/diagnostics.md b/pkg/analyzer/tool/diagnostics/diagnostics.md
index a7a82ea..59b565b 100644
--- a/pkg/analyzer/tool/diagnostics/diagnostics.md
+++ b/pkg/analyzer/tool/diagnostics/diagnostics.md
@@ -860,6 +860,53 @@
 }
 {% endprettify %}
 
+### const_constructor_param_type_mismatch
+
+_A value of type '{0}' can't be assigned to a parameter of type '{1}'._
+
+#### Description
+
+The analyzer produces this diagnostic when the runtime type of a constant
+value can't be assigned to the static type of a constant constructor's
+parameter.
+
+#### Example
+
+The following code produces this diagnostic because the runtime type of `i`
+is `int`, which can't be assigned to the static type of `s`:
+
+{% prettify dart %}
+class C {
+  final String s;
+
+  const C(this.s);
+}
+
+const dynamic i = 0;
+
+void f() {
+  const C([!i!]);
+}
+{% endprettify %}
+
+#### Common fixes
+
+Pass a value of the correct type to the constructor:
+
+{% prettify dart %}
+class C {
+  final String s;
+
+  const C(this.s);
+}
+
+const dynamic i = 0;
+
+void f() {
+  const C('$i');
+}
+{% endprettify %}
+
 ### const_constructor_with_non_final_field
 
 _Can't define a const constructor for a class with non-final fields._
@@ -1725,6 +1772,51 @@
 of which element to remove might affect the order in which elements are
 returned by an iterator.
 
+### equal_elements_in_set
+
+_Two elements in a set literal shouldn't be equal._
+
+#### Description
+
+The analyzer produces this diagnostic when an element in a non-constant set
+is the same as a previous element in the same set. If two elements are the
+same, then the second value is  ignored, which makes having both elements
+pointless and likely signals a bug.
+
+#### Example
+
+The following code produces this diagnostic because the element `1` appears
+twice:
+
+{% prettify dart %}
+const a = 1;
+const b = 1;
+var s = <int>{a, [!b!]};
+{% endprettify %}
+
+#### Common fixes
+
+If both elements should be included in the set, then change one of the
+elements:
+
+{% prettify dart %}
+const a = 1;
+const b = 2;
+var s = <int>{a, b};
+{% endprettify %}
+
+If only one of the elements is needed, then remove the one that isn't
+needed:
+
+{% prettify dart %}
+const a = 1;
+var s = <int>{a};
+{% endprettify %}
+
+Note that literal sets preserve the order of their elements, so the choice
+of which element to remove might affect the order in which elements are
+returned by an iterator.
+
 ### equal_keys_in_const_map
 
 _Two keys in a constant map literal can't be equal._
@@ -1765,6 +1857,50 @@
 of which entry to remove might affect the order in which keys and values
 are returned by an iterator.
 
+### equal_keys_in_map
+
+_Two keys in a map literal shouldn't be equal._
+
+#### Description
+
+The analyzer produces this diagnostic when a key in a non-constant map is
+the same as a previous key in the same map. If two keys are the same, then
+the second value overwrites the first value, which makes having both pairs
+pointless and likely signals a bug.
+
+#### Example
+
+The following code produces this diagnostic because the keys `a` and `b`
+have the same value:
+
+{% prettify dart %}
+const a = 1;
+const b = 1;
+var m = <int, String>{a: 'a', [!b!]: 'b'};
+{% endprettify %}
+
+#### Common fixes
+
+If both entries should be included in the map, then change one of the keys:
+
+{% prettify dart %}
+const a = 1;
+const b = 2;
+var m = <int, String>{a: 'a', b: 'b'};
+{% endprettify %}
+
+If only one of the entries is needed, then remove the one that isn't
+needed:
+
+{% prettify dart %}
+const a = 1;
+var m = <int, String>{a: 'a'};
+{% endprettify %}
+
+Note that literal maps preserve the order of their entries, so the choice
+of which entry to remove might affect the order in which the keys and
+values are returned by an iterator.
+
 ### export_legacy_symbol
 
 _The symbol '{0}' is defined in a legacy library, and can't be re-exported from
@@ -2322,6 +2458,100 @@
 }
 {% endprettify %}
 
+### field_initialized_in_initializer_and_declaration
+
+_Fields can't be initialized in the constructor if they are final and were
+already initialized at their declaration._
+
+#### Description
+
+The analyzer produces this diagnostic when a final field is initialized in
+both the declaration of the field and in an initializer in a constructor.
+Final fields can only be assigned once, so it can't be initialized in both
+places.
+
+#### Example
+
+The following code produces this diagnostic because `f` is :
+
+{% prettify dart %}
+class C {
+  final int f = 0;
+  C() : [!f!] = 1;
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the initialization doesn't depend on any values passed to the
+constructor, and if all of the constructors need to initialize the field to
+the same value, then remove the initializer from the constructor:
+
+{% prettify dart %}
+class C {
+  final int f = 0;
+  C();
+}
+{% endprettify %}
+
+If the initialization depends on a value passed to the constructor, or if
+different constructors need to initialize the field differently, then
+remove the initializer in the field's declaration:
+
+{% prettify dart %}
+class C {
+  final int f;
+  C() : f = 1;
+}
+{% endprettify %}
+
+### field_initializer_not_assignable
+
+_The initializer type '{0}' can't be assigned to the field type '{1}'._
+
+#### Description
+
+The analyzer produces this diagnostic when the initializer list of a
+constructor initializes a field to a value that isn't assignable to the
+field.
+
+#### Example
+
+The following code produces this diagnostic because `0` has the type `int`,
+and an `int` can't be assigned to a field of type `String`:
+
+{% prettify dart %}
+class C {
+  String s;
+
+  C() : s = [!0!];
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the type of the field is correct, then change the value assigned to it
+so that the value has a valid type:
+
+{% prettify dart %}
+class C {
+  String s;
+
+  C() : s = '0';
+}
+{% endprettify %}
+
+If the type of the value is correct, then change the type of the field to
+allow the assignment:
+
+{% prettify dart %}
+class C {
+  int s;
+
+  C() : s = 0;
+}
+{% endprettify %}
+
 ### final_not_initialized
 
 _The final variable '{0}' must be initialized._
@@ -2494,6 +2724,47 @@
 }
 {% endprettify %}
 
+### illegal_async_return_type
+
+_Functions marked 'async' must have a return type assignable to 'Future'._
+
+#### Description
+
+The analyzer produces this diagnostic when the body of a function has the
+`async` modifier even though the return type of the function isn't
+assignable to `Future`.
+
+#### Example
+
+The following code produces this diagnostic because the body of the
+function `f` has the `async` modifier even though the return type isn't
+assignable to `Future`:
+
+{% prettify dart %}
+[!int!] f() async {
+  return 0;
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the function should be asynchronous, then change the return type to be
+assignable to `Future`:
+
+{% prettify dart %}
+Future<int> f() async {
+  return 0;
+}
+{% endprettify %}
+
+If the function should be synchronous, then remove the `async` modifier:
+
+{% prettify dart %}
+int f() {
+  return 0;
+}
+{% endprettify %}
+
 ### implements_non_class
 
 _Classes and mixins can only implement other classes and mixins._
@@ -2558,7 +2829,7 @@
 
 ### implicit_this_reference_in_initializer
 
-_Only static members can be accessed in initializers._
+_The instance member '{0}' can't be accessed in an initializer._
 
 #### Description
 
@@ -2607,6 +2878,76 @@
 }
 {% endprettify %}
 
+### import_internal_library
+
+_The library '{0}' is internal and can't be imported._
+
+#### Description
+
+The analyzer produces this diagnostic when it finds an import whose `dart:`
+URI references an internal library.
+
+#### Example
+
+The following code produces this diagnostic because `_interceptors` is an
+internal library:
+
+{% prettify dart %}
+import [!'dart:_interceptors'!];
+{% endprettify %}
+
+#### Common fixes
+
+Remove the import directive.
+
+### inconsistent_inheritance
+
+_Superinterfaces don't have a valid override for '{0}': {1}._
+
+#### Description
+
+The analyzer produces this diagnostic when a class inherits two or more
+conflicting signatures for a member and doesn't provide an implementation
+that satisfies all the inherited signatures.
+
+#### Example
+
+The following code produces this diagnostic because `C` is inheriting the
+declaration of `m` from `A`, and that implementation isn't consistent with
+the signature of `m` that's inherited from `B`:
+
+{% prettify dart %}
+class A {
+  void m({int a}) {}
+}
+
+class B {
+  void m({int b}) {}
+}
+
+class [!C!] extends A implements B {
+}
+{% endprettify %}
+
+#### Common fixes
+
+Add an implementation of the method that satisfies all the inherited
+signatures:
+
+{% prettify dart %}
+class A {
+  void m({int a}) {}
+}
+
+class B {
+  void m({int b}) {}
+}
+
+class C extends A implements B {
+  void m({int a, int b}) {}
+}
+{% endprettify %}
+
 ### initializer_for_non_existent_field
 
 _'{0}' isn't a field in the enclosing class._
@@ -4280,6 +4621,49 @@
 bool b = a == 0 || a > 1;
 {% endprettify %}
 
+### non_constant_annotation_constructor
+
+_Annotation creation can only call a const constructor._
+
+#### Description
+
+The analyzer produces this diagnostic when an annotation is the invocation
+of an existing constructor even though the invoked constructor isn't a
+const constructor.
+
+#### Example
+
+The following code produces this diagnostic because the constructor for `C`
+isn't a const constructor:
+
+{% prettify dart %}
+[!@C()!]
+void f() {
+}
+
+class C {
+  C();
+}
+{% endprettify %}
+
+#### Common fixes
+
+If it's valid for the class to have a const constructor, then create a
+const constructor that can be used for the annotation:
+
+{% prettify dart %}
+@C()
+void f() {
+}
+
+class C {
+  const C();
+}
+{% endprettify %}
+
+If it isn't valid for the class to have a const constructor, then either
+remove the annotation or use a different class for the annotation.
+
 ### non_constant_case_expression
 
 _Case expressions must be constant._
@@ -5292,6 +5676,41 @@
 
 If the member can't be removed, then remove the annotation.
 
+### part_of_different_library
+
+_Expected this library to be part of '{0}', not '{1}'._
+
+#### Description
+
+The analyzer produces this diagnostic when a library attempts to include a
+file as a part of itself when the other file is a part of a different
+library.
+
+#### Example
+
+Given a file named `part.dart` containing
+
+{% prettify dart %}
+part of 'library.dart';
+{% endprettify %}
+
+The following code, in any file other than `library.dart`, produces this
+diagnostic because it attempts to include `part.dart` as a part of itself
+when `part.dart` is a part of a different library:
+
+{% prettify dart %}
+part [!'package:a/part.dart'!];
+{% endprettify %}
+
+#### Common fixes
+
+If the library should be using a different file as a part, then change the
+URI in the part directive to be the URI of the other file.
+
+If the part file should be a part of this library, then update the URI (or
+library name) in the part-of directive to be the URI (or name) of the
+correct library.
+
 ### part_of_non_part
 
 _The included part '{0}' must have a part-of directive._
@@ -5334,6 +5753,45 @@
 import 'a.dart';
 {% endprettify %}
 
+### prefix_identifier_not_followed_by_dot
+
+_The name '{0}' refers to an import prefix, so it must be followed by '.'._
+
+#### Description
+
+The analyzer produces this diagnostic when an import prefix is used by
+itself, without accessing any of the names declared in the libraries
+associated with the prefix. Prefixes aren't variables, and therefore can't
+be used as a value.
+
+#### Example
+
+The following code produces this diagnostic because the prefix `math` is
+being used as if it were a variable:
+
+{% prettify dart %}
+import 'dart:math' as math;
+
+void f() {
+  print([!math!]);
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the code is incomplete, then reference something in one of the libraries
+associated with the prefix:
+
+{% prettify dart %}
+import 'dart:math' as math;
+
+void f() {
+  print(math.pi);
+}
+{% endprettify %}
+
+If the name is wrong, then correct the name.
+
 ### redirect_to_invalid_function_type
 
 _The redirected constructor '{0}' has incompatible parameters with '{1}'._
@@ -5552,6 +6010,56 @@
 }
 {% endprettify %}
 
+### return_in_generative_constructor
+
+_Constructors can't return values._
+
+#### Description
+
+The analyzer produces this diagnostic when a generative constructor
+contains a return statement that specifies a value to be returned.
+Generative constructors always return the object that was created, and
+therefore can't return a different object.
+
+#### Example
+
+The following code produces this diagnostic because the return statement
+has an expression:
+
+{% prettify dart %}
+class C {
+  C() {
+    return [!this!];
+  }
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the constructor should create a new instance, then remove either the
+return statement or the expression:
+
+{% prettify dart %}
+class C {
+  C();
+}
+{% endprettify %}
+
+If the constructor shouldn't create a new instance, then convert it to be a
+factory constructor:
+
+{% prettify dart %}
+class C {
+  factory C() {
+    return _instance;
+  }
+
+  static C _instance = C._();
+
+  C._();
+}
+{% endprettify %}
+
 ### return_of_invalid_type
 
 _A value of type '{0}' can't be returned from constructor '{2}' because it has a
@@ -6234,6 +6742,57 @@
 
 Rewrite the code to not use `super`.
 
+### switch_expression_not_assignable
+
+_Type '{0}' of the switch expression isn't assignable to the type '{1}' of case
+expressions._
+
+#### Description
+
+The analyzer produces this diagnostic when the type of the expression in a
+switch statement isn't assignable to the type of the expressions in the
+case clauses.
+
+#### Example
+
+The following code produces this diagnostic because the type of `s`
+(`String`) isn't assignable to the type of `0` (`int`):
+
+{% prettify dart %}
+void f(String s) {
+  switch ([!s!]) {
+    case 0:
+      break;
+  }
+}
+{% endprettify %}
+
+#### Common fixes
+
+If the type of the case expressions is correct, then change the expression
+in the switch statement to have the correct type:
+
+{% prettify dart %}
+void f(String s) {
+  switch (int.parse(s)) {
+    case 0:
+      break;
+  }
+}
+{% endprettify %}
+
+If the type of the switch expression is correct, then change the case
+expressions to have the correct type:
+
+{% prettify dart %}
+void f(String s) {
+  switch (s) {
+    case '0':
+      break;
+  }
+}
+{% endprettify %}
+
 ### throw_of_invalid_type
 
 _The type '{0}' of the thrown expression must be assignable to 'Object'._
@@ -6530,6 +7089,47 @@
 }
 {% endprettify %}
 
+### undefined_enum_constant
+
+_There's no constant named '{0}' in '{1}'._
+
+#### Description
+
+The analyzer produces this diagnostic when it encounters an identifier that
+appears to be the name of an enum constant, and the name either isn't
+defined or isn't visible in the scope in which it's being referenced.
+
+#### Examples
+
+The following code produces this diagnostic because `E` doesn't define a
+constant named `c`:
+
+{% prettify dart %}
+enum E {a, b}
+
+var e = E.[!c!];
+{% endprettify %}
+
+#### Common fixes
+
+If the constant should be defined, then add it to the declaration of the
+enum:
+
+{% prettify dart %}
+enum E {a, b, c}
+
+var e = E.c;
+{% endprettify %}
+
+If the constant shouldn't be defined, then change the name to the name of
+an existing constant:
+
+{% prettify dart %}
+enum E {a, b}
+
+var e = E.b;
+{% endprettify %}
+
 ### undefined_extension_getter
 
 _The getter '{0}' isn't defined for the extension '{1}'._
@@ -6943,6 +7543,35 @@
 If the identifier is defined but isn't visible, then you probably need to
 add an import or re-arrange your code to make the identifier visible.
 
+### undefined_identifier_await
+
+_Undefined name 'await' in function body not marked with 'async'._
+
+#### Description
+
+The analyzer produces this diagnostic when the name `await` is used in a
+method or function body without being declared, and the body isn't marked
+with the `async` keyword. The name `await` only introduces an await
+expression in an asynchronous function.
+
+#### Example
+
+The following code produces this diagnostic because the name `await` is
+used in the body of `f` even though the body of `f` isn't marked with the
+`async` keyword:
+
+{% prettify dart %}
+void f(p) { [!await!] p; }
+{% endprettify %}
+
+#### Common fixes
+
+Add the keyword `async` to the function body:
+
+{% prettify dart %}
+void f(p) async { await p; }
+{% endprettify %}
+
 ### undefined_method
 
 _The method '{0}' isn't defined for the type '{1}'._
diff --git a/pkg/analyzer_cli/lib/src/build_mode.dart b/pkg/analyzer_cli/lib/src/build_mode.dart
index 60d403e..bf9eeb1 100644
--- a/pkg/analyzer_cli/lib/src/build_mode.dart
+++ b/pkg/analyzer_cli/lib/src/build_mode.dart
@@ -482,11 +482,18 @@
   }
 
   Packages _findPackages(String path) {
-    if (path != null) {
-      return findPackagesFrom(resourceProvider, resourceProvider.getFile(path));
-    } else {
-      return Packages.empty;
+    var configPath = options.packageConfigPath;
+    if (configPath != null) {
+      var configFile = resourceProvider.getFile(configPath);
+      return parsePackagesFile(resourceProvider, configFile);
     }
+
+    if (path != null) {
+      var file = resourceProvider.getFile(path);
+      return findPackagesFrom(resourceProvider, file);
+    }
+
+    return Packages.empty;
   }
 
   /// Ensure that the parsed unit for [absoluteUri] is available.
diff --git a/pkg/analyzer_cli/pubspec.yaml b/pkg/analyzer_cli/pubspec.yaml
index 295f5cf..06a9e27 100644
--- a/pkg/analyzer_cli/pubspec.yaml
+++ b/pkg/analyzer_cli/pubspec.yaml
@@ -1,5 +1,6 @@
 name: analyzer_cli
 description: Command line interface for the Dart Analyzer.
+# This package is not intended for consumption on pub.dev. DO NOT publish.
 publish_to: none
 environment:
   sdk: "^2.7.0"
diff --git a/pkg/analyzer_cli/test/driver_test.dart b/pkg/analyzer_cli/test/driver_test.dart
index 8a29242..4735d87 100644
--- a/pkg/analyzer_cli/test/driver_test.dart
+++ b/pkg/analyzer_cli/test/driver_test.dart
@@ -622,6 +622,88 @@
     });
   }
 
+  Future<void> test_packageConfig_packagesOptions() async {
+    await withTempDirAsync((tempDir) async {
+      var packagesPath = path.join(tempDir, 'aaa.packages');
+
+      var aaaRoot = path.join(tempDir, 'packages', 'aaa');
+      var aPath = path.join(aaaRoot, 'lib', 'a.dart');
+
+      var aUri = 'package:aaa/a.dart';
+
+      File(packagesPath).createSync(recursive: true);
+      File(packagesPath).writeAsStringSync('''
+{
+  "configVersion": 2,
+  "packages": [
+    {
+      "name": "aaa",
+      "rootUri": "${path.toUri(aaaRoot)}",
+      "packageUri": "lib/",
+      "languageVersion": "2.4"
+    }
+  ]
+}
+''');
+
+      File(aPath).createSync(recursive: true);
+      File(aPath).writeAsStringSync(r'''
+extension E on int {}
+''');
+
+      // Analyze package:aaa/a.dart and compute errors.
+      await _doDrive(
+        aPath,
+        fileUri: aUri,
+        additionalArgs: [
+          '--packages=$packagesPath',
+        ],
+      );
+      expect(exitCode, ErrorSeverity.ERROR.ordinal);
+      expect(errorSink.toString(), contains('extension-methods'));
+    });
+  }
+
+  Future<void> test_packageConfig_relativeToFile() async {
+    await withTempDirAsync((tempDir) async {
+      var packagesPath = path.join(tempDir, '.dart_tool/package_config.json');
+
+      var aaaRoot = path.join(tempDir, 'packages', 'aaa');
+      var aPath = path.join(aaaRoot, 'lib', 'a.dart');
+
+      var aUri = 'package:aaa/a.dart';
+
+      File(packagesPath).createSync(recursive: true);
+      File(packagesPath).writeAsStringSync('''
+{
+  "configVersion": 2,
+  "packages": [
+    {
+      "name": "aaa",
+      "rootUri": "${path.toUri(aaaRoot)}",
+      "packageUri": "lib/",
+      "languageVersion": "2.4"
+    }
+  ]
+}
+''');
+
+      File(aPath).createSync(recursive: true);
+      File(aPath).writeAsStringSync(r'''
+extension E on int {}
+''');
+
+      // Analyze package:aaa/a.dart and compute errors.
+      await _doDrive(
+        aPath,
+        fileUri: aUri,
+        additionalArgs: [],
+      );
+      expect(exitCode, ErrorSeverity.ERROR.ordinal);
+      expect(errorSink.toString(), contains('extension-methods'));
+    });
+  }
+
   Iterable<String> _linkedLibraryUnitUriList(
     LinkedNodeBundle bundle2,
     String libraryUriStr,
diff --git a/pkg/async_helper/pubspec.yaml b/pkg/async_helper/pubspec.yaml
index 9497752..817b5fe 100644
--- a/pkg/async_helper/pubspec.yaml
+++ b/pkg/async_helper/pubspec.yaml
@@ -1,5 +1,5 @@
 name: async_helper
-# This package is not intended to be published
+# This package is not intended for consumption on pub.dev. DO NOT publish.
 publish_to: none
 description: >-
  Async_helper is used for asynchronous tests that do not want to
diff --git a/pkg/build_integration/pubspec.yaml b/pkg/build_integration/pubspec.yaml
index 722a284..7d5fb5db 100644
--- a/pkg/build_integration/pubspec.yaml
+++ b/pkg/build_integration/pubspec.yaml
@@ -2,7 +2,7 @@
 description: >
   Libraries for integrating Dart tools with build systems like bazel
   and build_runner.
-# This package is not intended to be published - yet
+# This package is not intended for consumption on pub.dev. DO NOT publish.
 publish_to: none
 
 environment:
diff --git a/pkg/compiler/lib/src/common/codegen.dart b/pkg/compiler/lib/src/common/codegen.dart
index 44e3980..33de3f1 100644
--- a/pkg/compiler/lib/src/common/codegen.dart
+++ b/pkg/compiler/lib/src/common/codegen.dart
@@ -18,6 +18,7 @@
 import '../js/js.dart' as js;
 import '../js_backend/backend.dart';
 import '../js_backend/namer.dart';
+import '../js_backend/string_reference.dart' show StringReference;
 import '../js_backend/type_reference.dart' show TypeReference;
 import '../js_emitter/code_emitter_task.dart' show Emitter;
 import '../js_model/type_recipe.dart' show TypeRecipe;
@@ -1001,6 +1002,7 @@
   expressionStatement,
   block,
   program,
+  stringReference,
   typeReference,
 }
 
@@ -1064,6 +1066,7 @@
   static const String expressionStatement = 'js-expressionStatement';
   static const String block = 'js-block';
   static const String program = 'js-program';
+  static const String stringReference = 'js-stringReference';
   static const String typeReference = 'js-typeReference';
 }
 
@@ -1307,6 +1310,12 @@
       node.writeToDataSink(sink);
       sink.end(JsNodeTags.typeReference);
       _writeInfo(node);
+    } else if (node is StringReference) {
+      sink.writeEnum(JsNodeKind.stringReference);
+      sink.begin(JsNodeTags.stringReference);
+      node.writeToDataSink(sink);
+      sink.end(JsNodeTags.stringReference);
+      _writeInfo(node);
     } else {
       throw new UnsupportedError(
           'Unexpected deferred expression: ${node.runtimeType}.');
@@ -2098,6 +2107,11 @@
         node = new js.Program(body);
         source.end(JsNodeTags.program);
         break;
+      case JsNodeKind.stringReference:
+        source.begin(JsNodeTags.stringReference);
+        node = StringReference.readFromDataSource(source);
+        source.end(JsNodeTags.stringReference);
+        break;
       case JsNodeKind.typeReference:
         source.begin(JsNodeTags.typeReference);
         node = TypeReference.readFromDataSource(source);
diff --git a/pkg/compiler/lib/src/common_elements.dart b/pkg/compiler/lib/src/common_elements.dart
index 6e0d183..dfcea46 100644
--- a/pkg/compiler/lib/src/common_elements.dart
+++ b/pkg/compiler/lib/src/common_elements.dart
@@ -412,14 +412,10 @@
 
   FunctionEntity get exceptionUnwrapper;
 
-  FunctionEntity get throwRuntimeError;
-
   FunctionEntity get throwUnsupportedError;
 
   FunctionEntity get throwTypeError;
 
-  FunctionEntity get throwAbstractClassInstantiationError;
-
   /// Recognizes the `checkConcurrentModificationError` helper without needing
   /// it to be resolved.
   bool isCheckConcurrentModificationError(MemberEntity member);
@@ -1698,10 +1694,6 @@
       _findHelperFunction('unwrapException');
 
   @override
-  FunctionEntity get throwRuntimeError =>
-      _findHelperFunction('throwRuntimeError');
-
-  @override
   FunctionEntity get throwUnsupportedError =>
       _findHelperFunction('throwUnsupportedError');
 
@@ -1709,10 +1701,6 @@
   FunctionEntity get throwTypeError => _findRtiFunction('throwTypeError');
 
   @override
-  FunctionEntity get throwAbstractClassInstantiationError =>
-      _findHelperFunction('throwAbstractClassInstantiationError');
-
-  @override
   bool isCheckConcurrentModificationError(MemberEntity member) {
     return member.name == 'checkConcurrentModificationError' &&
         member.isFunction &&
diff --git a/pkg/compiler/lib/src/ir/scope_visitor.dart b/pkg/compiler/lib/src/ir/scope_visitor.dart
index 22be758..7ef94b7 100644
--- a/pkg/compiler/lib/src/ir/scope_visitor.dart
+++ b/pkg/compiler/lib/src/ir/scope_visitor.dart
@@ -143,7 +143,7 @@
     for (ir.Node variable in _scopeVariables) {
       // No need to box non-assignable elements.
       if (variable is ir.VariableDeclaration) {
-        if (variable.isFinal || variable.isConst) continue;
+        if (variable.isConst) continue;
         if (!_mutatedVariables.contains(variable)) continue;
         if (_capturedVariables.contains(variable)) {
           capturedVariablesForScope.add(variable);
@@ -345,6 +345,9 @@
             typeVariable(context.enclosingLibrary), _currentTypeUsage);
       }
     }
+
+    visitNode(typeParameter.bound);
+
     return const InitializerComplexity.constant();
   }
 
diff --git a/pkg/compiler/lib/src/js_backend/backend_impact.dart b/pkg/compiler/lib/src/js_backend/backend_impact.dart
index 6fd3844..cbb0bdd 100644
--- a/pkg/compiler/lib/src/js_backend/backend_impact.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_impact.dart
@@ -165,14 +165,6 @@
     ]);
   }
 
-  BackendImpact _abstractClassInstantiation;
-
-  BackendImpact get abstractClassInstantiation {
-    return _abstractClassInstantiation ??= new BackendImpact(
-        staticUses: [_commonElements.throwAbstractClassInstantiationError],
-        otherImpacts: [_needsString('Needed to encode the message.')]);
-  }
-
   BackendImpact _fallThroughError;
 
   BackendImpact get fallThroughError {
@@ -183,9 +175,7 @@
   BackendImpact _asCheck;
 
   BackendImpact get asCheck {
-    return _asCheck ??= new BackendImpact(staticUses: [
-      _commonElements.throwRuntimeError,
-    ], otherImpacts: [
+    return _asCheck ??= new BackendImpact(staticUses: [], otherImpacts: [
       newRtiImpact,
     ]);
   }
@@ -256,9 +246,7 @@
   BackendImpact _throwRuntimeError;
 
   BackendImpact get throwRuntimeError {
-    return _throwRuntimeError ??= new BackendImpact(staticUses: [
-      _commonElements.throwRuntimeError,
-    ], otherImpacts: [
+    return _throwRuntimeError ??= new BackendImpact(otherImpacts: [
       // Also register the types of the arguments passed to this method.
       stringValues
     ]);
diff --git a/pkg/compiler/lib/src/js_backend/constant_emitter.dart b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
index 80b45fa..95166e4 100644
--- a/pkg/compiler/lib/src/js_backend/constant_emitter.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
@@ -13,6 +13,8 @@
 import '../js/js.dart' show js;
 import '../js_backend/field_analysis.dart';
 import '../js_backend/type_reference.dart' show TypeReference;
+import '../js_backend/string_reference.dart'
+    show StringReference, StringReferencePolicy;
 import '../js_emitter/code_emitter_task.dart';
 import '../js_model/type_recipe.dart' show TypeExpressionRecipe;
 import '../options.dart';
@@ -143,7 +145,11 @@
   /// The string is assumed quoted by double quote characters.
   @override
   jsAst.Expression visitString(StringConstantValue constant, [_]) {
-    return js.escapedString(constant.stringValue, ascii: true);
+    String value = constant.stringValue;
+    if (value.length < StringReferencePolicy.minimumLength) {
+      return js.escapedString(value, ascii: true);
+    }
+    return StringReference(constant);
   }
 
   @override
@@ -276,7 +282,8 @@
         }
 
         // Keys in literal maps must be emitted in place.
-        jsAst.Literal keyExpression = _visit(key);
+        jsAst.Literal keyExpression =
+            js.escapedString(key.stringValue, ascii: true);
         jsAst.Expression valueExpression =
             _constantReferenceGenerator(constant.values[i]);
         properties.add(new jsAst.Property(keyExpression, valueExpression));
diff --git a/pkg/compiler/lib/src/js_backend/impact_transformer.dart b/pkg/compiler/lib/src/js_backend/impact_transformer.dart
index f0de179..842a94e 100644
--- a/pkg/compiler/lib/src/js_backend/impact_transformer.dart
+++ b/pkg/compiler/lib/src/js_backend/impact_transformer.dart
@@ -72,9 +72,6 @@
 
     for (Feature feature in worldImpact.features) {
       switch (feature) {
-        case Feature.ABSTRACT_CLASS_INSTANTIATION:
-          registerImpact(_impacts.abstractClassInstantiation);
-          break;
         case Feature.ASSERT:
           registerImpact(_impacts.assertWithoutMessage);
           break;
diff --git a/pkg/compiler/lib/src/js_backend/name_sequence.dart b/pkg/compiler/lib/src/js_backend/name_sequence.dart
new file mode 100644
index 0000000..1f7bdf1
--- /dev/null
+++ b/pkg/compiler/lib/src/js_backend/name_sequence.dart
@@ -0,0 +1,48 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:front_end/src/api_unstable/dart2js.dart'
+    show $0, $9, $A, $Z, $_, $a, $z;
+
+/// Returns an infinite sequence of property names in increasing size.
+Iterable<String> generalMinifiedNameSequence() sync* {
+  List<int> nextName = [$a];
+
+  /// Increments the letter at [pos] in the current name. Also takes care of
+  /// overflows to the left. Returns the carry bit, i.e., it returns `true`
+  /// if all positions to the left have wrapped around.
+  ///
+  /// If [nextName] is initially 'a', this will generate the sequence
+  ///
+  ///     [a-zA-Z_]
+  ///     [a-zA-Z_][0-9a-zA-Z_]
+  ///     [a-zA-Z_][0-9a-zA-Z_][0-9a-zA-Z_]
+  ///     ...
+  bool incrementPosition(int pos) {
+    bool overflow = false;
+    if (pos < 0) return true;
+    int value = nextName[pos];
+    if (value == $9) {
+      value = $a;
+    } else if (value == $z) {
+      value = $A;
+    } else if (value == $Z) {
+      value = $_;
+    } else if (value == $_) {
+      overflow = incrementPosition(pos - 1);
+      value = (pos > 0) ? $0 : $a;
+    } else {
+      value++;
+    }
+    nextName[pos] = value;
+    return overflow;
+  }
+
+  while (true) {
+    yield String.fromCharCodes(nextName);
+    if (incrementPosition(nextName.length - 1)) {
+      nextName.add($0);
+    }
+  }
+}
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index 9b4e0ee..e44beff 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -1614,6 +1614,7 @@
   String getTypeRepresentationForTypeConstant(DartType type) {
     type = type.withoutNullability;
     if (type is DynamicType) return "dynamic";
+    if (type is NeverType) return "Never";
     if (type is FutureOrType) {
       return "FutureOr<dynamic>";
     }
@@ -2246,8 +2247,6 @@
   String get callPrefix => 'call';
   String get callCatchAllName => r'call*';
   String get callNameField => r'$callName';
-  String get reflectableField => r'$reflectable';
-  String get classDescriptorProperty => r'^';
   String get defaultValuesField => r'$defaultValues';
   String get deferredAction => r'$deferredAction';
   String get operatorIsPrefix => r'$is';
@@ -2544,10 +2543,6 @@
         return asName('${fixedNames.callPrefix}\$5');
       case JsGetName.CALL_CATCH_ALL:
         return asName(fixedNames.callCatchAllName);
-      case JsGetName.REFLECTABLE:
-        return asName(fixedNames.reflectableField);
-      case JsGetName.CLASS_DESCRIPTOR_PROPERTY:
-        return asName(fixedNames.classDescriptorProperty);
       case JsGetName.REQUIRED_PARAMETER_PROPERTY:
         return asName(fixedNames.requiredParameterField);
       case JsGetName.DEFAULT_VALUES_PROPERTY:
@@ -2570,10 +2565,6 @@
         return runtimeTypeName(_commonElements.nullClass);
       case JsGetName.OBJECT_CLASS_TYPE_NAME:
         return runtimeTypeName(_commonElements.objectClass);
-      case JsGetName.FUNCTION_CLASS_TYPE_NAME:
-        return runtimeTypeName(_commonElements.functionClass);
-      case JsGetName.JS_FUNCTION_CLASS_TYPE_NAME:
-        return runtimeTypeName(_commonElements.jsJavaScriptFunctionClass);
       case JsGetName.FUTURE_CLASS_TYPE_NAME:
         return runtimeTypeName(_commonElements.futureClass);
       case JsGetName.RTI_FIELD_AS:
diff --git a/pkg/compiler/lib/src/js_backend/string_abbreviation.dart b/pkg/compiler/lib/src/js_backend/string_abbreviation.dart
new file mode 100644
index 0000000..0e442bd
--- /dev/null
+++ b/pkg/compiler/lib/src/js_backend/string_abbreviation.dart
@@ -0,0 +1,169 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:front_end/src/api_unstable/dart2js.dart'
+    show $0, $9, $A, $Z, $a, $z;
+
+/// Returns a list of strings that are short valid identifiers based on the
+/// corresponding full strings in [strings].
+///
+/// [strings] must not contain the empty string.
+/// [strings] must have no duplicates.
+List<String> abbreviateToIdentifiers(Iterable<String> strings,
+    {int minLength = 6}) {
+  var nodes = [for (final string in strings) _Node(string)];
+  _partition(nodes, minLength, [], 0);
+  return [for (final node in nodes) node.assignment];
+}
+
+class _Node {
+  final String string;
+  String assignment;
+  _Node(this.string);
+}
+
+/// Walk the prefix tree or TRIE of [nodes], assigning compressed names built
+/// from the distinguishing characters along the path.
+///
+/// - [index] is the position of the first potentially different character,
+///   i.e. the current TRIE depth.
+/// - [path] contains the prefix of the compressed name at this depth.
+/// - Path compression starts after the first [minLength] characters.
+void _partition(
+    List<_Node> nodes, int minLength, List<String> path, int index) {
+  while (true) {
+    // Handle trivial partitions.
+    if (nodes.length == 0) return;
+    if (nodes.length == 1 && path.length >= minLength) {
+      String name = path.join();
+      assert(name.isNotEmpty);
+      nodes.single.assignment = name;
+      return;
+    }
+
+    // Partition on the code unit at position [index], setting [terminating] if
+    // some string ends at this length;
+    Map<int, List<_Node>> partition = {};
+    _Node terminating;
+
+    for (final node in nodes) {
+      String string = node.string;
+      assert(string.length > 0);
+      if (index < string.length) {
+        int codeUnit = string.codeUnitAt(index);
+        (partition[codeUnit] ??= []).add(node);
+      } else {
+        assert(terminating == null); // i.e. no duplicates.
+        terminating = node;
+      }
+    }
+
+    if (terminating != null) {
+      terminating.assignment = path.join();
+    }
+
+    if (partition.length == 0) return;
+
+    if (partition.length > 1) {
+      var keys = partition.keys.toList();
+      var keyEncodings = _discriminators(keys, path.isEmpty);
+      for (int key in keys) {
+        var children = partition[key];
+        var discriminator = keyEncodings[key];
+        _partition(children, minLength, [...path, discriminator], index + 1);
+      }
+      return;
+    }
+
+    assert(partition.length == 1);
+    // All the strings have the same code unit at [index]. Use iteration to
+    // find next partition point to avoid recursing down the whole string
+    // length. The path is compressed by omitting to add fragments to [path]
+    // unless we are near the start of the string.
+
+    int codeUnit = partition.keys.single;
+    // Add some characters to name to distinguish from terminating strings.
+    // Add the first few legal identifier characters of the string regardless.
+    if (terminating != null || path.length < minLength) {
+      path.add(_isIdentifier(codeUnit, path.isEmpty)
+          ? String.fromCharCode(codeUnit)
+          : '_');
+    }
+    nodes = partition.values.single;
+    index += 1;
+  }
+}
+
+Map<int, String> _discriminators(List<int> keys, bool atStart) {
+  // Assign each partition a distinguishing short string. If the partition key
+  // is a valid identifier character, it can be used, otherwise we could use
+  // `'_'` or an escaped code like `'x3b'` or `'u12ef'`. If we use an escape
+  // like `'x3b'` then we need to be careful with the partition key `x`, as it
+  // might be followed by `3b`. We avoid this problem without lookahead by
+  // encoding `x` as an escape (i.e. `'x78'`) if there is another `x`-escape.
+
+  const xCode = 0x78;
+  const uCode = 0x75;
+
+  bool hasX = false;
+  bool hasU = false;
+
+  int xEscapes = 0;
+  int uEscapes = 0;
+  for (int key in keys) {
+    if (_isIdentifier(key, atStart)) {
+      if (key == xCode) hasX = true;
+      if (key == uCode) hasU = true;
+    } else if (key < 256) {
+      xEscapes++;
+    } else {
+      uEscapes++;
+    }
+  }
+
+  Map<int, String> encoding = {};
+  bool escapeToUnderscore = false;
+
+  if (uEscapes + xEscapes <= 1) {
+    escapeToUnderscore = true;
+    xEscapes = uEscapes = 0;
+  }
+
+  if (uEscapes > 0 && hasU) {
+    encoding[uCode] = 'x75';
+    xEscapes++;
+  }
+  if (xEscapes > 0 && hasX) {
+    encoding[xCode] = 'x78';
+  }
+
+  for (int key in keys) {
+    if (encoding.containsKey(key)) continue;
+    if (_isIdentifier(key, atStart)) {
+      encoding[key] = String.fromCharCode(key);
+    } else {
+      if (escapeToUnderscore) {
+        encoding[key] = '_';
+      } else if (key < 256) {
+        encoding[key] = 'x' + key.toRadixString(16).padLeft(2, '0');
+      } else {
+        encoding[key] = 'u' + key.toRadixString(16).padLeft(4, '0');
+      }
+    }
+  }
+
+  return encoding;
+}
+
+bool _isIdentifier(int codeUnit, bool atStart) {
+  return atStart ? _isAsciiAlpha(codeUnit) : _isAsciiAlphanumeric(codeUnit);
+}
+
+bool _isAsciiAlphanumeric(int codeUnit) {
+  return $0 <= codeUnit && codeUnit <= $9 || _isAsciiAlpha(codeUnit);
+}
+
+bool _isAsciiAlpha(int codeUnit) {
+  return $A <= codeUnit && codeUnit <= $Z || $a <= codeUnit && codeUnit <= $z;
+}
diff --git a/pkg/compiler/lib/src/js_backend/string_reference.dart b/pkg/compiler/lib/src/js_backend/string_reference.dart
new file mode 100644
index 0000000..95fa795
--- /dev/null
+++ b/pkg/compiler/lib/src/js_backend/string_reference.dart
@@ -0,0 +1,435 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// StringReferences are 'holes' in the generated JavaScript that are filled in
+/// by the emitter with code to access a large string.
+///
+/// The Dart code
+///
+///     foo1() => 'A very long string';
+///
+/// might be compiled to something like the following, where StringReference1 is
+/// assocatied with the string `'A very long string'`.
+///
+///     foo1: function() {
+///       return StringReference1;
+///     }
+///
+/// The dart method `foo2` would be compiled separately, with the generated code
+/// containing StringReference2, also 3 referring to `int`:
+///
+///     foo2() => 'A very long string';
+/// -->
+///     foo2: function() {
+///       return StringReference2;
+///     }
+///
+/// When the code for an output unit (main unit or deferred loaded unit) is
+/// assembled, there will also be a StringReferenceResource 'hole', so the
+/// assembled looks something like
+///
+///     foo: function() {
+///       return StringReference1;
+///     }
+///     foo2: function() {
+///       return StringReference2;
+///     }
+///     ...
+///     StringReferenceResource
+///
+/// The StringReferenceFinalizer decides on a strategy for accessing the
+/// strings. In most cases a string will have one reference and it should be
+/// generated in-place. Shared strings can be referenced via a object. The
+/// StringReference nodes are filled in with property access expressions and the
+/// StringReferenceResource is filled in with the precomputed data, something
+/// like:
+///
+///     foo1: function() {
+///       return string$.A_very;
+///     }
+///     foo2: function() {
+///       return string$.A_very;
+///     }
+///     ...
+///     var string$ = {
+///       A_very: "A very long string",
+///     };
+///
+/// In minified mode, the properties (`A_very`) can be replaced by shorter
+/// names.
+library js_backend.string_reference;
+
+import '../constants/values.dart' show StringConstantValue;
+import '../js/js.dart' as js;
+import '../serialization/serialization.dart';
+import '../util/util.dart' show Hashing;
+import 'frequency_assignment.dart';
+import 'name_sequence.dart';
+import 'string_abbreviation.dart';
+
+class StringReferencePolicy {
+  /// Minimum length to generate a StringReference for further processing.
+  static const int minimumLength = 11;
+
+  /// Strings shorter that [shortestSharedLength] are not shared.
+  // TODO(sra): Split this into different settings depending on code contexts
+  // (hot, cold, execute-once, etc).
+  static const int shortestSharedLength = 40;
+
+  // TODO(sra): Add policy for huge non-shared strings, strings occuring in
+  // run-once code, etc. Maybe make policy settings assignable for testing or
+  // command-line configuration.
+}
+
+/// A [StringReference] is a deferred JavaScript expression that refers to the
+/// runtime representation of a ground type or ground type environment.  The
+/// deferred expression is filled in by the StringReferenceFinalizer which is
+/// called from the fragment emitter. The replacement expression could be any
+/// expression, e.g. a call, or a reference to a variable, or property of a
+/// variable.
+class StringReference extends js.DeferredExpression implements js.AstContainer {
+  static const String tag = 'string-reference';
+
+  final StringConstantValue constant;
+
+  js.Expression _value;
+
+  @override
+  final js.JavaScriptNodeSourceInformation sourceInformation;
+
+  StringReference(this.constant) : sourceInformation = null;
+  StringReference._(this.constant, this._value, this.sourceInformation);
+
+  factory StringReference.readFromDataSource(DataSource source) {
+    source.begin(tag);
+    StringConstantValue constant = source.readConstant() as StringConstantValue;
+    source.end(tag);
+    return StringReference(constant);
+  }
+
+  void writeToDataSink(DataSink sink) {
+    sink.begin(tag);
+    sink.writeConstant(constant);
+    sink.end(tag);
+  }
+
+  set value(js.Expression value) {
+    assert(_value == null && value != null);
+    _value = value;
+  }
+
+  @override
+  js.Expression get value {
+    assert(_value != null, 'StringReference is unassigned');
+    return _value;
+  }
+
+  // Precedence will be CALL or LEFT_HAND_SIDE depending on what expression the
+  // reference is resolved to.
+  @override
+  int get precedenceLevel => value.precedenceLevel;
+
+  @override
+  StringReference withSourceInformation(
+      js.JavaScriptNodeSourceInformation newSourceInformation) {
+    if (newSourceInformation == sourceInformation) return this;
+    if (newSourceInformation == null) return this;
+    return StringReference._(constant, _value, newSourceInformation);
+  }
+
+  @override
+  Iterable<js.Node> get containedNodes => _value == null ? const [] : [_value];
+}
+
+/// A [StringReferenceResource] is a deferred JavaScript expression determined
+/// by the finalization of string references. It is the injection point for data
+/// or code to support string references. For example, if the
+/// [StringReferenceFinalizer] decides that a string should be referred to via a
+/// variable, the [StringReferenceResource] would be set to code that declares
+/// and initializes the variable.
+class StringReferenceResource extends js.DeferredExpression
+    implements js.AstContainer {
+  js.Expression _value;
+
+  @override
+  final js.JavaScriptNodeSourceInformation sourceInformation;
+
+  StringReferenceResource() : sourceInformation = null;
+  StringReferenceResource._(this._value, this.sourceInformation);
+
+  set value(js.Expression value) {
+    assert(_value == null && value != null);
+    _value = value;
+  }
+
+  @override
+  js.Expression get value {
+    assert(_value != null, 'StringReferenceResource is unassigned');
+    return _value;
+  }
+
+  @override
+  int get precedenceLevel => value.precedenceLevel;
+
+  @override
+  StringReferenceResource withSourceInformation(
+      js.JavaScriptNodeSourceInformation newSourceInformation) {
+    if (newSourceInformation == sourceInformation) return this;
+    if (newSourceInformation == null) return this;
+    return StringReferenceResource._(_value, newSourceInformation);
+  }
+
+  @override
+  Iterable<js.Node> get containedNodes => _value == null ? const [] : [_value];
+
+  @override
+  void visitChildren<T>(js.NodeVisitor<T> visitor) {
+    _value?.accept<T>(visitor);
+  }
+
+  @override
+  void visitChildren1<R, A>(js.NodeVisitor1<R, A> visitor, A arg) {
+    _value?.accept1<R, A>(visitor, arg);
+  }
+}
+
+abstract class StringReferenceFinalizer {
+  /// Collects StringReference and StringReferenceResource nodes from the
+  /// JavaScript AST [code];
+  void addCode(js.Node code);
+
+  /// Performs analysis on all collected StringReference nodes finalizes the
+  /// values to expressions to access the types.
+  void finalize();
+}
+
+class StringReferenceFinalizerImpl implements StringReferenceFinalizer {
+  final bool _minify;
+  final int shortestSharedLength; // Configurable for testing.
+
+  /*late final*/ _StringReferenceCollectorVisitor _visitor;
+  StringReferenceResource _resource;
+
+  /// Maps the recipe (type expression) to the references with the same recipe.
+  /// Much of the algorithm's state is stored in the _ReferenceSet objects.
+  Map<StringConstantValue, _ReferenceSet> _referencesByString = {};
+
+  StringReferenceFinalizerImpl(this._minify,
+      {this.shortestSharedLength =
+          StringReferencePolicy.shortestSharedLength}) {
+    _visitor = _StringReferenceCollectorVisitor(this);
+  }
+
+  @override
+  void addCode(js.Node code) {
+    code.accept(_visitor);
+  }
+
+  @override
+  void finalize() {
+    assert(_resource != null, 'StringReferenceFinalizer needs resource');
+    _allocateNames();
+    _updateReferences();
+  }
+
+  // Called from collector visitor.
+  void registerStringReference(StringReference node) {
+    StringConstantValue constant = node.constant;
+    _ReferenceSet refs =
+        _referencesByString[constant] ??= _ReferenceSet(constant);
+    refs.count++;
+    refs._references.add(node);
+  }
+
+  // Called from collector visitor.
+  void registerStringReferenceResource(StringReferenceResource node) {
+    assert(_resource == null);
+    _resource = node;
+  }
+
+  void _updateReferences() {
+    // Emit generate-at-use references.
+    for (_ReferenceSet referenceSet in _referencesByString.values) {
+      if (referenceSet.generateAtUse) {
+        StringConstantValue constant = referenceSet.constant;
+        js.Expression reference =
+            js.js.escapedString(constant.stringValue, ascii: true);
+        for (StringReference ref in referenceSet._references) {
+          ref.value = reference;
+        }
+      }
+    }
+
+    List<_ReferenceSet> referenceSetsUsingProperties =
+        _referencesByString.values.where((ref) => !ref.generateAtUse).toList();
+
+    // Sort by string (which is unique and stable) so that similar strings are
+    // grouped together.
+    referenceSetsUsingProperties.sort(_ReferenceSet.compareByString);
+
+    List<js.Property> properties = [];
+    for (_ReferenceSet referenceSet in referenceSetsUsingProperties) {
+      String string = referenceSet.constant.stringValue;
+      var propertyName = js.string(referenceSet.propertyName);
+      properties.add(
+          js.Property(propertyName, js.js.escapedString(string, ascii: true)));
+      var access = js.js('#.#', [holderLocalName, propertyName]);
+      for (StringReference ref in referenceSet._references) {
+        ref.value = access;
+      }
+    }
+
+    if (properties.isEmpty) {
+      // We don't have a deferred statement sequence. "0;" is the smallest we
+      // can do with an expression statement.
+      // TODO(sra): Add deferred expression statement sequences.
+      _resource.value = js.js('0');
+    } else {
+      js.Expression initializer =
+          js.ObjectInitializer(properties, isOneLiner: false);
+      _resource.value = js.js(
+          r'var # = #', [js.VariableDeclaration(holderLocalName), initializer]);
+    }
+  }
+
+  // This is a top-level local name in the generated JavaScript top-level
+  // function, so will be minified automatically. The name should not collide
+  // with any other locals.
+  static const holderLocalName = r'string$';
+
+  void _allocateNames() {
+    // Filter out generate-at-use cases and allocate unique names to the rest.
+    List<_ReferenceSet> referencesInTable = [];
+
+    for (final referenceSet in _referencesByString.values) {
+      String text = referenceSet.constant.stringValue;
+      if (referenceSet.count == 1) continue;
+      // TODO(sra): We might want to always extract very large strings,
+      // e.g. replace above with:
+      //
+      //     if (referenceSet.count == 1 && text.length < 1000) continue;
+      if (text.length <= shortestSharedLength) continue;
+      referencesInTable.add(referenceSet);
+    }
+
+    if (referencesInTable.isEmpty) return;
+
+    List<String> names = abbreviateToIdentifiers(
+        referencesInTable.map((r) => r.constant.stringValue));
+    assert(referencesInTable.length == names.length);
+    for (int i = 0; i < referencesInTable.length; i++) {
+      referencesInTable[i].name = names[i];
+    }
+
+    if (!_minify) {
+      // For unminified code, use the characteristic names as property names.
+      for (final referenceSet in referencesInTable) {
+        referenceSet.propertyName = referenceSet.name;
+      }
+
+      return;
+    }
+
+    // Step 2. Sort by frequency to arrange common entries have shorter property
+    // names.
+    List<_ReferenceSet> referencesByFrequency = referencesInTable.toList()
+      ..sort((a, b) {
+        assert(a.name != b.name);
+        int r = b.count.compareTo(a.count); // Decreasing frequency.
+        if (r != 0) return r;
+        // Tie-break with raw string.
+        return _ReferenceSet.compareByString(a, b);
+      });
+
+    for (final referenceSet in referencesByFrequency) {
+      // TODO(sra): Assess the dispersal of this hash function in the
+      // semistableFrequencyAssignment algorithm.
+      // TODO(sra): Consider a cheaper but stable hash. We are generally hashing
+      // a relatively small set of large strings.
+      referenceSet.hash = Hashing.stringHash(referenceSet.constant.stringValue);
+    }
+
+    int hashOf(int index) => referencesByFrequency[index].hash;
+    int countOf(int index) => referencesByFrequency[index].count;
+    void assign(int index, String name) {
+      if (_minify) {
+        referencesByFrequency[index].propertyName = name;
+      } else {
+        var refSet = referencesByFrequency[index];
+        refSet.propertyName = name + '_' + refSet.name;
+      }
+    }
+
+    semistableFrequencyAssignment(referencesByFrequency.length,
+        generalMinifiedNameSequence(), hashOf, countOf, assign);
+  }
+}
+
+/// Set of references to a single recipe.
+class _ReferenceSet {
+  final StringConstantValue constant;
+
+  // Number of times a StringReference for [constant] occurs in the tree-scan of
+  // the JavaScript ASTs.
+  int count = 0;
+
+  // It is possible for the JavaScript AST to be a DAG, so collect
+  // [StringReference]s as set so we don't try to update one twice.
+  final Set<StringReference> _references = Set.identity();
+
+  /// Characteristic name of the recipe - this can be used as a property name
+  /// for emitting unminified code, and as a stable hash source for minified
+  /// names.  [name] is `null` if [recipe] should always be generated at use.
+  String name;
+
+  /// Property name for 'indexing' into the precomputed types.
+  String propertyName;
+
+  /// A stable hash code that can be used for picking stable minified names.
+  int hash = 0;
+
+  _ReferenceSet(this.constant);
+
+  // If we don't assign a name it means we should not precompute the recipe.
+  bool get generateAtUse => name == null;
+
+  static int compareByString(_ReferenceSet a, _ReferenceSet b) {
+    return a.constant.stringValue.compareTo(b.constant.stringValue);
+  }
+}
+
+/// Scans a JavaScript AST to collect all the StringReference nodes.
+///
+/// The state is kept in the finalizer so that this scan could be extended to
+/// look for other deferred expressions in one pass.
+// TODO(sra): Merge with TypeReferenceCollectorVisitor.
+class _StringReferenceCollectorVisitor extends js.BaseVisitor<void> {
+  final StringReferenceFinalizerImpl _finalizer;
+
+  _StringReferenceCollectorVisitor(this._finalizer);
+
+  @override
+  void visitNode(js.Node node) {
+    assert(node is! StringReference);
+    assert(node is! StringReferenceResource);
+    if (node is js.AstContainer) {
+      for (js.Node element in node.containedNodes) {
+        element.accept(this);
+      }
+    } else {
+      super.visitNode(node);
+    }
+  }
+
+  @override
+  void visitDeferredExpression(js.DeferredExpression node) {
+    if (node is StringReference) {
+      _finalizer.registerStringReference(node);
+    } else if (node is StringReferenceResource) {
+      _finalizer.registerStringReferenceResource(node);
+    } else {
+      visitNode(node);
+    }
+  }
+}
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
index 2e5779b..8ae8d3a3 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
@@ -432,6 +432,9 @@
 // Adds the variance table for the new RTI.
 #variances;
 
+// Shared strings need to be initialized before constants.
+#sharedStrings;
+
 // Shared types need to be initialized before constants.
 #sharedTypeRtis;
 
@@ -536,6 +539,8 @@
 // Adds the variance table for the new RTI.
 #variances;
 
+#sharedStrings;
+
 #sharedTypeRtis;
 // Instantiates all constants of this deferred fragment.
 // Note that the constant-holder has been updated earlier and storing the
@@ -695,6 +700,7 @@
       'embeddedGlobalsPart2':
           emitEmbeddedGlobalsPart2(program, deferredLoadingState),
       'typeRules': emitTypeRules(fragment),
+      'sharedStrings': StringReferenceResource(),
       'variances': emitVariances(fragment),
       'sharedTypeRtis': TypeReferenceResource(),
       'nativeSupport': emitNativeSupport(fragment),
@@ -725,7 +731,7 @@
         mainCode
       ]);
     }
-    finalizeTypeReferences(mainCode);
+    finalizeStringAndTypeReferences(mainCode);
     return mainCode;
   }
 
@@ -827,17 +833,22 @@
       'types': deferredTypes,
       'nativeSupport': nativeSupport,
       'typesOffset': _namer.typesOffsetName,
+      'sharedStrings': StringReferenceResource(),
       'sharedTypeRtis': TypeReferenceResource(),
     });
 
     if (_options.experimentStartupFunctions) {
       code = js.Parentheses(code);
     }
-    finalizeTypeReferences(code);
+    finalizeStringAndTypeReferences(code);
     return code;
   }
 
-  void finalizeTypeReferences(js.Node code) {
+  void finalizeStringAndTypeReferences(js.Node code) {
+    StringReferenceFinalizer stringFinalizer =
+        StringReferenceFinalizerImpl(_options.enableMinification);
+    stringFinalizer.addCode(code);
+    stringFinalizer.finalize();
     TypeReferenceFinalizer finalizer = TypeReferenceFinalizerImpl(
         _emitter, _commonElements, _recipeEncoder, _options.enableMinification);
     finalizer.addCode(code);
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
index 33479d9..f549f60 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/model_emitter.dart
@@ -60,6 +60,11 @@
         TypeReferenceFinalizer,
         TypeReferenceFinalizerImpl,
         TypeReferenceResource;
+import '../../js_backend/string_reference.dart'
+    show
+        StringReferenceFinalizer,
+        StringReferenceFinalizerImpl,
+        StringReferenceResource;
 import '../../options.dart';
 import '../../universe/class_hierarchy.dart' show ClassHierarchy;
 import '../../universe/codegen_world_builder.dart' show CodegenWorld;
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 801f78f..02e6e5c 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -3251,6 +3251,7 @@
     ir.DartType type = node.type;
     if (type is ir.InterfaceType ||
         type is ir.DynamicType ||
+        type is ir.NeverType ||
         type is ir.TypedefType ||
         type is ir.FunctionType ||
         type is ir.FutureOrType) {
@@ -4495,16 +4496,6 @@
         return js.js
             .expressionTemplateYielding(_emitter.typeAccess(closureClass));
 
-      case JsBuiltin.isCheckPropertyToJsConstructorName:
-        int isPrefixLength = _namer.fixedNames.operatorIsPrefix.length;
-        return js.js.expressionTemplateFor('#.substring($isPrefixLength)');
-
-      case JsBuiltin.rawRtiToJsConstructorName:
-        return js.js.expressionTemplateFor("#.name");
-
-      case JsBuiltin.rawRuntimeType:
-        return js.js.expressionTemplateFor("#.constructor");
-
       case JsBuiltin.getMetadata:
         String metadataAccess =
             _emitter.generateEmbeddedGlobalAccessString(METADATA);
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index afcc43f..dc5adf4 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -2512,11 +2512,7 @@
     bool handledBySpecialCase = false;
     if (isGenerateAtUseSite(input)) {
       handledBySpecialCase = true;
-      if (input is HIs) {
-        emitIs(input, '!==', sourceInformation);
-      } else if (input is HIsViaInterceptor) {
-        emitIsViaInterceptor(input, sourceInformation, negative: true);
-      } else if (input is HIsTestSimple) {
+      if (input is HIsTestSimple) {
         _emitIsTestSimple(input, negative: true);
       } else if (input is HNot) {
         use(input.inputs[0]);
@@ -2855,21 +2851,6 @@
     push(new js.Binary(cmp, left, or0));
   }
 
-  void checkBigInt(
-      HInstruction input, String cmp, SourceInformation sourceInformation) {
-    use(input);
-    js.Expression left = pop();
-    use(input);
-    js.Expression right = pop();
-    // TODO(4984): Deal with infinity and -0.0.
-    js.Expression mathFloorCall = js.js('Math.floor(#)',
-        <js.Expression>[left]).withSourceInformation(sourceInformation);
-    push(js.js('# $cmp #', <js.Expression>[
-      mathFloorCall,
-      right
-    ]).withSourceInformation(sourceInformation));
-  }
-
   void checkTypeOf(HInstruction input, String cmp, String typeName,
       SourceInformation sourceInformation) {
     use(input);
@@ -2883,328 +2864,11 @@
     return checkTypeOf(input, cmp, 'number', sourceInformation);
   }
 
-  void checkDouble(
-      HInstruction input, String cmp, SourceInformation sourceInformation) {
-    return checkNum(input, cmp, sourceInformation);
-  }
-
-  void checkString(
-      HInstruction input, String cmp, SourceInformation sourceInformation) {
-    return checkTypeOf(input, cmp, 'string', sourceInformation);
-  }
-
   void checkBool(
       HInstruction input, String cmp, SourceInformation sourceInformation) {
     return checkTypeOf(input, cmp, 'boolean', sourceInformation);
   }
 
-  void checkObject(
-      HInstruction input, String cmp, SourceInformation sourceInformation) {
-    assert(NullConstantValue.JsNull == 'null');
-    if (cmp == "===") {
-      checkTypeOf(input, '===', 'object', sourceInformation);
-      js.Expression left = pop();
-      use(input);
-      js.Expression notNull = new js.Binary("!==", pop(), new js.LiteralNull());
-      push(new js.Binary("&&", left, notNull)
-          .withSourceInformation(sourceInformation));
-    } else {
-      assert(cmp == "!==");
-      checkTypeOf(input, '!==', 'object', sourceInformation);
-      js.Expression left = pop();
-      use(input);
-      js.Expression eqNull = new js.Binary("===", pop(), new js.LiteralNull());
-      push(new js.Binary("||", left, eqNull)
-          .withSourceInformation(sourceInformation));
-    }
-  }
-
-  void checkArray(HInstruction input, String cmp) {
-    use(input);
-    js.PropertyAccess constructor =
-        new js.PropertyAccess.field(pop(), 'constructor');
-    push(new js.Binary(cmp, constructor, new js.VariableUse('Array')));
-  }
-
-  void checkFieldExists(HInstruction input, String fieldName) {
-    use(input);
-    js.PropertyAccess field = new js.PropertyAccess.field(pop(), fieldName);
-    // Double negate to boolify the result.
-    push(new js.Prefix('!', new js.Prefix('!', field)));
-  }
-
-  void checkFieldDoesNotExist(HInstruction input, String fieldName) {
-    use(input);
-    js.PropertyAccess field = new js.PropertyAccess.field(pop(), fieldName);
-    push(new js.Prefix('!', field));
-  }
-
-  void checkImmutableArray(HInstruction input) {
-    checkFieldExists(input, 'immutable\$list');
-  }
-
-  void checkMutableArray(HInstruction input) {
-    checkFieldDoesNotExist(input, 'immutable\$list');
-  }
-
-  void checkExtendableArray(HInstruction input) {
-    checkFieldDoesNotExist(input, 'fixed\$length');
-  }
-
-  void checkFixedArray(HInstruction input) {
-    checkFieldExists(input, 'fixed\$length');
-  }
-
-  void checkNull(HInstruction input) {
-    use(input);
-    push(new js.Binary('==', pop(), new js.LiteralNull()));
-  }
-
-  void checkNonNull(HInstruction input) {
-    use(input);
-    push(new js.Binary('!=', pop(), new js.LiteralNull()));
-  }
-
-  void checkType(HInstruction input, HInstruction interceptor, DartType type,
-      SourceInformation sourceInformation,
-      {bool negative: false}) {
-    if (type is InterfaceType) {
-      InterfaceType interfaceType = type;
-      ClassEntity element = interfaceType.element;
-      if (element == _commonElements.jsArrayClass) {
-        checkArray(input, negative ? '!==' : '===');
-        return;
-      } else if (element == _commonElements.jsMutableArrayClass) {
-        if (negative) {
-          checkImmutableArray(input);
-        } else {
-          checkMutableArray(input);
-        }
-        return;
-      } else if (element == _commonElements.jsExtendableArrayClass) {
-        if (negative) {
-          checkFixedArray(input);
-        } else {
-          checkExtendableArray(input);
-        }
-        return;
-      } else if (element == _commonElements.jsFixedArrayClass) {
-        if (negative) {
-          checkExtendableArray(input);
-        } else {
-          checkFixedArray(input);
-        }
-        return;
-      } else if (element == _commonElements.jsUnmodifiableArrayClass) {
-        if (negative) {
-          checkMutableArray(input);
-        } else {
-          checkImmutableArray(input);
-        }
-        return;
-      }
-    }
-    if (interceptor != null) {
-      checkTypeViaProperty(interceptor, type, sourceInformation,
-          negative: negative);
-    } else {
-      checkTypeViaProperty(input, type, sourceInformation, negative: negative);
-    }
-  }
-
-  void checkTypeViaProperty(
-      HInstruction input, DartType type, SourceInformation sourceInformation,
-      {bool negative: false}) {
-    _registry.registerTypeUse(new TypeUse.isCheck(type));
-
-    use(input);
-
-    js.PropertyAccess field =
-        new js.PropertyAccess(pop(), _namer.operatorIsType(type))
-            .withSourceInformation(sourceInformation);
-    // We always negate at least once so that the result is boolified.
-    push(new js.Prefix('!', field).withSourceInformation(sourceInformation));
-    // If the result is not negated, put another '!' in front.
-    if (!negative) {
-      push(new js.Prefix('!', pop()).withSourceInformation(sourceInformation));
-    }
-  }
-
-  void checkTypeViaInstanceof(HInstruction input, InterfaceType type,
-      SourceInformation sourceInformation,
-      {bool negative: false}) {
-    _registry.registerTypeUse(new TypeUse.instanceConstructor(type));
-
-    use(input);
-
-    js.Expression jsClassReference = _emitter.constructorAccess(type.element);
-    push(js.js('# instanceof #',
-        [pop(), jsClassReference]).withSourceInformation(sourceInformation));
-    if (negative) {
-      push(new js.Prefix('!', pop()).withSourceInformation(sourceInformation));
-    }
-  }
-
-  void handleNumberOrStringSupertypeCheck(
-      HInstruction input,
-      HInstruction interceptor,
-      InterfaceType type,
-      SourceInformation sourceInformation,
-      {bool negative: false}) {
-    assert(!identical(type.element, _commonElements.listClass) &&
-        !_commonElements.isListSupertype(type.element) &&
-        !_commonElements.isStringOnlySupertype(type.element));
-    String relation = negative ? '!==' : '===';
-    checkNum(input, relation, sourceInformation);
-    js.Expression numberTest = pop();
-    checkString(input, relation, sourceInformation);
-    js.Expression stringTest = pop();
-    checkObject(input, relation, sourceInformation);
-    js.Expression objectTest = pop();
-    checkType(input, interceptor, type, sourceInformation, negative: negative);
-    String combiner = negative ? '&&' : '||';
-    String combiner2 = negative ? '||' : '&&';
-    push(new js.Binary(
-            combiner,
-            new js.Binary(combiner, numberTest, stringTest)
-                .withSourceInformation(sourceInformation),
-            new js.Binary(combiner2, objectTest, pop())
-                .withSourceInformation(sourceInformation))
-        .withSourceInformation(sourceInformation));
-  }
-
-  void handleStringSupertypeCheck(HInstruction input, HInstruction interceptor,
-      InterfaceType type, SourceInformation sourceInformation,
-      {bool negative: false}) {
-    assert(!identical(type.element, _commonElements.listClass) &&
-        !_commonElements.isListSupertype(type.element) &&
-        !_commonElements.isNumberOrStringSupertype(type.element));
-    String relation = negative ? '!==' : '===';
-    checkString(input, relation, sourceInformation);
-    js.Expression stringTest = pop();
-    checkObject(input, relation, sourceInformation);
-    js.Expression objectTest = pop();
-    checkType(input, interceptor, type, sourceInformation, negative: negative);
-    String combiner = negative ? '||' : '&&';
-    push(new js.Binary(negative ? '&&' : '||', stringTest,
-        new js.Binary(combiner, objectTest, pop())));
-  }
-
-  void handleListOrSupertypeCheck(HInstruction input, HInstruction interceptor,
-      InterfaceType type, SourceInformation sourceInformation,
-      {bool negative: false}) {
-    assert(!identical(type.element, _commonElements.stringClass) &&
-        !_commonElements.isStringOnlySupertype(type.element) &&
-        !_commonElements.isNumberOrStringSupertype(type.element));
-    String relation = negative ? '!==' : '===';
-    checkObject(input, relation, sourceInformation);
-    js.Expression objectTest = pop();
-    checkArray(input, relation);
-    js.Expression arrayTest = pop();
-    checkType(input, interceptor, type, sourceInformation, negative: negative);
-    String combiner = negative ? '&&' : '||';
-    push(new js.Binary(negative ? '||' : '&&', objectTest,
-            new js.Binary(combiner, arrayTest, pop()))
-        .withSourceInformation(sourceInformation));
-  }
-
-  @override
-  void visitIs(HIs node) {
-    emitIs(node, "===", node.sourceInformation);
-  }
-
-  @override
-  void visitIsViaInterceptor(HIsViaInterceptor node) {
-    emitIsViaInterceptor(node, node.sourceInformation, negative: false);
-  }
-
-  void emitIs(HIs node, String relation, SourceInformation sourceInformation) {
-    DartType type = node.typeExpression;
-    _registry.registerTypeUse(new TypeUse.isCheck(type));
-    HInstruction input = node.expression;
-
-    // If this is changed to single == there are several places below that must
-    // be changed to match.
-    assert(relation == '===' || relation == '!==');
-    bool negative = relation == '!==';
-
-    if (node.isVariableCheck || node.isCompoundCheck) {
-      use(node.checkCall);
-      if (negative) push(new js.Prefix('!', pop()));
-    } else {
-      assert(node.isRawCheck);
-      HInstruction interceptor = node.interceptor;
-      InterfaceType interfaceType = type;
-      ClassEntity element = interfaceType.element;
-      if (element == _commonElements.nullClass) {
-        if (negative) {
-          checkNonNull(input);
-        } else {
-          checkNull(input);
-        }
-      } else if (element == _commonElements.objectClass /* || type.isTop*/) {
-        // The constant folder also does this optimization, but we make
-        // it safe by assuming it may have not run.
-        push(newLiteralBool(!negative, sourceInformation));
-      } else if (element == _commonElements.stringClass) {
-        checkString(input, relation, sourceInformation);
-      } else if (element == _commonElements.doubleClass) {
-        checkDouble(input, relation, sourceInformation);
-      } else if (element == _commonElements.numClass) {
-        checkNum(input, relation, sourceInformation);
-      } else if (element == _commonElements.boolClass) {
-        checkBool(input, relation, sourceInformation);
-      } else if (element == _commonElements.intClass) {
-        // The is check in the code tells us that it might not be an
-        // int. So we do a typeof first to avoid possible
-        // deoptimizations on the JS engine due to the Math.floor check.
-        checkNum(input, relation, sourceInformation);
-        js.Expression numTest = pop();
-        checkBigInt(input, relation, sourceInformation);
-        push(new js.Binary(negative ? '||' : '&&', numTest, pop())
-            .withSourceInformation(sourceInformation));
-      } else if (node.useInstanceOf) {
-        assert(interceptor == null);
-        checkTypeViaInstanceof(input, type, sourceInformation,
-            negative: negative);
-      } else if (_commonElements.isNumberOrStringSupertype(element)) {
-        handleNumberOrStringSupertypeCheck(
-            input, interceptor, type, sourceInformation,
-            negative: negative);
-      } else if (_commonElements.isStringOnlySupertype(element)) {
-        handleStringSupertypeCheck(input, interceptor, type, sourceInformation,
-            negative: negative);
-      } else if (element == _commonElements.listClass ||
-          _commonElements.isListSupertype(element)) {
-        handleListOrSupertypeCheck(input, interceptor, type, sourceInformation,
-            negative: negative);
-      } else if (type is FunctionType) {
-        checkType(input, interceptor, type, sourceInformation,
-            negative: negative);
-      } else if ((input.isPrimitive(_abstractValueDomain).isPotentiallyTrue &&
-              input.isPrimitiveArray(_abstractValueDomain).isDefinitelyFalse) ||
-          input.isNull(_abstractValueDomain).isPotentiallyTrue) {
-        checkObject(input, relation, node.sourceInformation);
-        js.Expression objectTest = pop();
-        checkType(input, interceptor, type, sourceInformation,
-            negative: negative);
-        push(new js.Binary(negative ? '||' : '&&', objectTest, pop())
-            .withSourceInformation(sourceInformation));
-      } else {
-        checkType(input, interceptor, type, sourceInformation,
-            negative: negative);
-      }
-    }
-  }
-
-  void emitIsViaInterceptor(
-      HIsViaInterceptor node, SourceInformation sourceInformation,
-      {bool negative: false}) {
-    checkTypeViaProperty(
-        node.interceptor, node.typeExpression, sourceInformation,
-        negative: negative);
-  }
-
   @override
   void visitPrimitiveCheck(HPrimitiveCheck node) {
     js.Expression test = _generateReceiverOrArgumentTypeTest(node);
diff --git a/pkg/compiler/lib/src/ssa/codegen_helpers.dart b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
index 05f415f..be25134 100644
--- a/pkg/compiler/lib/src/ssa/codegen_helpers.dart
+++ b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
@@ -170,18 +170,6 @@
   }
 
   @override
-  HInstruction visitIs(HIs node) {
-    if (node.kind == HIs.RAW_CHECK) {
-      HInstruction interceptor = node.interceptor;
-      if (interceptor != null) {
-        return new HIsViaInterceptor(
-            node.typeExpression, interceptor, _abstractValueDomain.boolType);
-      }
-    }
-    return node;
-  }
-
-  @override
   HInstruction visitIdentity(HIdentity node) {
     node.singleComparisonOp = simpleOp(node.left, node.right);
     return node;
@@ -810,23 +798,6 @@
     }
   }
 
-  @override
-  void visitIs(HIs instruction) {
-    // In the general case the input might be used multple multiple times, so it
-    // must not be set generate at use site.
-
-    // If the code will generate 'instanceof' then we can generate at use site.
-    if (instruction.useInstanceOf) {
-      analyzeInputs(instruction, 0);
-    }
-
-    // Compound and variable checks use a separate instruction to compute the
-    // result.
-    if (instruction.isCompoundCheck || instruction.isVariableCheck) {
-      analyzeInputs(instruction, 0);
-    }
-  }
-
   // A bounds check method must not have its first input generated at use site,
   // because it's using it twice.
   @override
@@ -1086,9 +1057,6 @@
     // A [HCheck] instruction with control flow uses its input
     // multiple times, so we avoid generating it at use site.
     if (user is HCheck && user.isControlFlow()) return false;
-    // A [HIs] instruction uses its input multiple times, so we
-    // avoid generating it at use site.
-    if (user is HIs) return false;
     // Avoid code motion into a loop.
     return user.hasSameLoopHeaderAs(input);
   }
diff --git a/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart b/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
index a1b208c..a484821 100644
--- a/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
+++ b/pkg/compiler/lib/src/ssa/interceptor_simplifier.dart
@@ -27,9 +27,6 @@
 /// the interceptor and then call the method.  This saves code size and makes the
 /// receiver of an intercepted call a candidate for being generated at use site.
 ///
-/// 5) Some HIs operations on an interceptor are replaced with a HIs version that
-/// uses 'instanceof' rather than testing a type flag.
-///
 class SsaSimplifyInterceptors extends HBaseVisitor
     implements OptimizationPhase {
   @override
@@ -243,8 +240,8 @@
     // Specialize the interceptor with set of classes it intercepts, considering
     // all uses.  (The specialized interceptor has a shorter dispatch chain).
     // This operation applies only where the interceptor is used to dispatch a
-    // method.  Other uses, e.g. as an ordinary argument or a HIs check use the
-    // most general interceptor.
+    // method.  Other uses, e.g. as an ordinary argument use the most general
+    // interceptor.
     //
     // TODO(sra): Take into account the receiver type at each call.  e.g:
     //
@@ -377,19 +374,7 @@
       return false;
     }
 
-    if (user is HIs) {
-      // See if we can rewrite the is-check to use 'instanceof', i.e. rewrite
-      // "getInterceptor(x).$isT" to "x instanceof T".
-      if (node == user.interceptor) {
-        if (_interceptorData.mayGenerateInstanceofCheck(
-            user.typeExpression, _closedWorld)) {
-          HInstruction instanceofCheck = new HIs.instanceOf(user.typeExpression,
-              user.expression, user.instructionType, user.sourceInformation);
-          instanceofCheck.sourceElement = user.sourceElement;
-          return replaceUserWith(instanceofCheck);
-        }
-      }
-    } else if (user is HInvokeDynamic) {
+    if (user is HInvokeDynamic) {
       if (node == user.inputs[0]) {
         // Replace the user with a [HOneShotInterceptor].
         HConstant nullConstant = _graph.addConstantNull(_closedWorld);
@@ -439,14 +424,7 @@
     }
 
     for (HInstruction user in node.usedBy.toList()) {
-      if (user is HIs) {
-        if (user.interceptor == node) {
-          HInstruction expression = user.expression;
-          if (canUseSelfForInterceptor(expression)) {
-            user.changeUse(node, expression);
-          }
-        }
-      } else if (user is HInvokeDynamic) {
+      if (user is HInvokeDynamic) {
         if (user.isCallOnInterceptor(_closedWorld) &&
             node == user.inputs[0] &&
             useCount(user, node) == 1) {
diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart
index e654310..86310fe 100644
--- a/pkg/compiler/lib/src/ssa/nodes.dart
+++ b/pkg/compiler/lib/src/ssa/nodes.dart
@@ -65,8 +65,6 @@
   R visitInvokeSuper(HInvokeSuper node);
   R visitInvokeConstructorBody(HInvokeConstructorBody node);
   R visitInvokeGeneratorBody(HInvokeGeneratorBody node);
-  R visitIs(HIs node);
-  R visitIsViaInterceptor(HIsViaInterceptor node);
   R visitLateValue(HLateValue node);
   R visitLazyStatic(HLazyStatic node);
   R visitLess(HLess node);
@@ -578,12 +576,8 @@
   @override
   visitTry(HTry node) => visitControlFlow(node);
   @override
-  visitIs(HIs node) => visitInstruction(node);
-  @override
   visitLateValue(HLateValue node) => visitInstruction(node);
   @override
-  visitIsViaInterceptor(HIsViaInterceptor node) => visitInstruction(node);
-  @override
   visitBoolConversion(HBoolConversion node) => visitCheck(node);
   @override
   visitNullCheck(HNullCheck node) => visitCheck(node);
@@ -1074,12 +1068,10 @@
   static const int TYPE_KNOWN_TYPECODE = 26;
   static const int INVOKE_STATIC_TYPECODE = 27;
   static const int INDEX_TYPECODE = 28;
-  static const int IS_TYPECODE = 29;
-  static const int INVOKE_DYNAMIC_TYPECODE = 30;
-  static const int SHIFT_RIGHT_TYPECODE = 31;
+  static const int INVOKE_DYNAMIC_TYPECODE = 29;
+  static const int SHIFT_RIGHT_TYPECODE = 30;
 
   static const int TRUNCATING_DIVIDE_TYPECODE = 36;
-  static const int IS_VIA_INTERCEPTOR_TYPECODE = 37;
 
   static const int INVOKE_EXTERNAL_TYPECODE = 41;
   static const int FOREIGN_CODE_TYPECODE = 42;
@@ -3476,136 +3468,6 @@
       receiver.isNull(domain).isPotentiallyTrue;
 }
 
-/// Is-test using legacy constructor based typ representation.
-class HIs extends HInstruction {
-  /// A check against a raw type: 'o is int', 'o is A'.
-  static const int RAW_CHECK = 0;
-
-  /// A check against a type with type arguments: 'o is List<int>', 'o is C<T>'.
-  static const int COMPOUND_CHECK = 1;
-
-  /// A check against a single type variable: 'o is T'.
-  static const int VARIABLE_CHECK = 2;
-
-  final DartType typeExpression;
-  final int kind;
-  final bool useInstanceOf;
-
-  HIs.direct(DartType typeExpression, HInstruction expression,
-      AbstractValue type, SourceInformation sourceInformation)
-      : this.internal(
-            typeExpression, [expression], RAW_CHECK, type, sourceInformation);
-
-  // Pre-verified that the check can be done using 'instanceof'.
-  HIs.instanceOf(DartType typeExpression, HInstruction expression,
-      AbstractValue type, SourceInformation sourceInformation)
-      : this.internal(
-            typeExpression, [expression], RAW_CHECK, type, sourceInformation,
-            useInstanceOf: true);
-
-  factory HIs.raw(
-      DartType typeExpression,
-      HInstruction expression,
-      HInterceptor interceptor,
-      AbstractValue type,
-      SourceInformation sourceInformation) {
-    // TODO(sigmund): re-add `&& typeExpression.treatAsRaw` or something
-    // equivalent (which started failing once we allowed typeExpressions that
-    // contain type parameters matching the original bounds of the type).
-    assert((typeExpression is FunctionType || typeExpression is InterfaceType),
-        "Unexpected raw is-test type: $typeExpression");
-    return new HIs.internal(typeExpression, [expression, interceptor],
-        RAW_CHECK, type, sourceInformation);
-  }
-
-  HIs.compound(
-      DartType typeExpression,
-      HInstruction expression,
-      HInstruction call,
-      AbstractValue type,
-      SourceInformation sourceInformation)
-      : this.internal(typeExpression, [expression, call], COMPOUND_CHECK, type,
-            sourceInformation);
-
-  HIs.variable(
-      DartType typeExpression,
-      HInstruction expression,
-      HInstruction call,
-      AbstractValue type,
-      SourceInformation sourceInformation)
-      : this.internal(typeExpression, [expression, call], VARIABLE_CHECK, type,
-            sourceInformation);
-
-  HIs.internal(this.typeExpression, List<HInstruction> inputs, this.kind,
-      AbstractValue type, SourceInformation sourceInformation,
-      {bool this.useInstanceOf: false})
-      : super(inputs, type) {
-    assert(kind >= RAW_CHECK && kind <= VARIABLE_CHECK);
-    setUseGvn();
-    this.sourceInformation = sourceInformation;
-  }
-
-  HInstruction get expression => inputs[0];
-
-  HInstruction get interceptor {
-    assert(kind == RAW_CHECK);
-    return inputs.length > 1 ? inputs[1] : null;
-  }
-
-  HInstruction get checkCall {
-    assert(kind == VARIABLE_CHECK || kind == COMPOUND_CHECK);
-    return inputs[1];
-  }
-
-  bool get isRawCheck => kind == RAW_CHECK;
-  bool get isVariableCheck => kind == VARIABLE_CHECK;
-  bool get isCompoundCheck => kind == COMPOUND_CHECK;
-
-  @override
-  accept(HVisitor visitor) => visitor.visitIs(this);
-
-  @override
-  toString() => "$expression is $typeExpression";
-
-  @override
-  int typeCode() => HInstruction.IS_TYPECODE;
-
-  @override
-  bool typeEquals(HInstruction other) => other is HIs;
-
-  @override
-  bool dataEquals(HIs other) {
-    return typeExpression == other.typeExpression && kind == other.kind;
-  }
-}
-
-/// HIsViaInterceptor is a late-stage instruction for a type test that can be
-/// done entirely on an interceptor.  It is not a HCheck because the checked
-/// input is not one of the inputs.
-class HIsViaInterceptor extends HLateInstruction {
-  final DartType typeExpression;
-  HIsViaInterceptor(
-      this.typeExpression, HInstruction interceptor, AbstractValue type)
-      : super(<HInstruction>[interceptor], type) {
-    setUseGvn();
-  }
-
-  HInstruction get interceptor => inputs[0];
-
-  @override
-  accept(HVisitor visitor) => visitor.visitIsViaInterceptor(this);
-  @override
-  toString() => "$interceptor is $typeExpression";
-  @override
-  int typeCode() => HInstruction.IS_VIA_INTERCEPTOR_TYPECODE;
-  @override
-  bool typeEquals(HInstruction other) => other is HIsViaInterceptor;
-  @override
-  bool dataEquals(HIs other) {
-    return typeExpression == other.typeExpression;
-  }
-}
-
 /// HLateValue is a late-stage instruction that can be used to force a value
 /// into a temporary.
 ///
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index f075382..e21dd7d 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -1223,80 +1223,6 @@
   }
 
   @override
-  HInstruction visitIs(HIs node) {
-    DartType type = node.typeExpression;
-
-    if (!node.isRawCheck) {
-      return node;
-    } else if (type is FunctionType) {
-      return node;
-    } else if (type is FutureOrType) {
-      return node;
-    }
-
-    if (_closedWorld.dartTypes.isTopType(type)) {
-      return _graph.addConstantBool(true, _closedWorld);
-    }
-    InterfaceType interfaceType = type;
-    ClassEntity element = interfaceType.element;
-    HInstruction expression = node.expression;
-    if (expression.isInteger(_abstractValueDomain).isDefinitelyTrue) {
-      if (element == commonElements.intClass ||
-          element == commonElements.numClass ||
-          commonElements.isNumberOrStringSupertype(element)) {
-        return _graph.addConstantBool(true, _closedWorld);
-      } else if (element == commonElements.doubleClass) {
-        // We let the JS semantics decide for that check. Currently
-        // the code we emit will always return true.
-        return node;
-      } else {
-        return _graph.addConstantBool(false, _closedWorld);
-      }
-    } else if (expression.isDouble(_abstractValueDomain).isDefinitelyTrue) {
-      if (element == commonElements.doubleClass ||
-          element == commonElements.numClass ||
-          commonElements.isNumberOrStringSupertype(element)) {
-        return _graph.addConstantBool(true, _closedWorld);
-      } else if (element == commonElements.intClass) {
-        // We let the JS semantics decide for that check. Currently
-        // the code we emit will return true for a double that can be
-        // represented as a 31-bit integer and for -0.0.
-        return node;
-      } else {
-        return _graph.addConstantBool(false, _closedWorld);
-      }
-    } else if (expression.isNumber(_abstractValueDomain).isDefinitelyTrue) {
-      if (element == commonElements.numClass) {
-        return _graph.addConstantBool(true, _closedWorld);
-      } else {
-        // We cannot just return false, because the expression may be of
-        // type int or double.
-      }
-    } else if (expression
-            .isPrimitiveNumber(_abstractValueDomain)
-            .isPotentiallyTrue &&
-        element == commonElements.intClass) {
-      // We let the JS semantics decide for that check.
-      return node;
-      // We need the [:hasTypeArguments:] check because we don't have
-      // the notion of generics in the backend. For example, [:this:] in
-      // a class [:A<T>:], is currently always considered to have the
-      // raw type.
-    } else if (!RuntimeTypesSubstitutions.hasTypeArguments(
-        _closedWorld.dartTypes, type)) {
-      AbstractValue expressionMask = expression.instructionType;
-      AbstractBool isInstanceOf =
-          _abstractValueDomain.isInstanceOf(expressionMask, element);
-      if (isInstanceOf.isDefinitelyTrue) {
-        return _graph.addConstantBool(true, _closedWorld);
-      } else if (isInstanceOf.isDefinitelyFalse) {
-        return _graph.addConstantBool(false, _closedWorld);
-      }
-    }
-    return node;
-  }
-
-  @override
   HInstruction visitPrimitiveCheck(HPrimitiveCheck node) {
     if (node.isRedundant(_closedWorld)) return node.checkedInput;
     return node;
@@ -3057,35 +2983,6 @@
   }
 
   @override
-  void visitIs(HIs instruction) {
-    DartType type = instruction.typeExpression;
-    if (!instruction.isRawCheck) {
-      return;
-    } else if (type is FutureOrType) {
-      return;
-    }
-    InterfaceType interfaceType = type;
-    ClassEntity cls = interfaceType.element;
-
-    List<HBasicBlock> trueTargets = <HBasicBlock>[];
-    List<HBasicBlock> falseTargets = <HBasicBlock>[];
-
-    collectTargets(instruction, trueTargets, falseTargets);
-
-    if (trueTargets.isEmpty && falseTargets.isEmpty) return;
-
-    AbstractValue convertedType =
-        _abstractValueDomain.createNonNullSubtype(cls);
-    HInstruction input = instruction.expression;
-
-    for (HBasicBlock block in trueTargets) {
-      insertTypePropagationForDominatedUsers(block, input, convertedType);
-    }
-    // TODO(sra): Also strengthen uses for when the condition is known
-    // false. Avoid strengthening to `null`.
-  }
-
-  @override
   void visitIsTest(HIsTest instruction) {
     List<HBasicBlock> trueTargets = <HBasicBlock>[];
     List<HBasicBlock> falseTargets = <HBasicBlock>[];
@@ -3464,10 +3361,6 @@
   @override
   void visitInterceptor(HInterceptor instruction) {}
   @override
-  void visitIs(HIs instruction) {}
-  @override
-  void visitIsViaInterceptor(HIsViaInterceptor instruction) {}
-  @override
   void visitNot(HNot instruction) {}
   @override
   void visitNullCheck(HNullCheck instruction) {}
diff --git a/pkg/compiler/lib/src/ssa/ssa_tracer.dart b/pkg/compiler/lib/src/ssa/ssa_tracer.dart
index 053beb2f..ef1ad6a 100644
--- a/pkg/compiler/lib/src/ssa/ssa_tracer.dart
+++ b/pkg/compiler/lib/src/ssa/ssa_tracer.dart
@@ -597,18 +597,6 @@
   }
 
   @override
-  String visitIs(HIs node) {
-    String type = node.typeExpression.toString();
-    return "Is: ${temporaryId(node.expression)} is $type";
-  }
-
-  @override
-  String visitIsViaInterceptor(HIsViaInterceptor node) {
-    String type = node.typeExpression.toString();
-    return "IsViaInterceptor: ${temporaryId(node.inputs[0])} is $type";
-  }
-
-  @override
   String visitPrimitiveCheck(HPrimitiveCheck node) {
     String checkedInput = temporaryId(node.checkedInput);
     assert(node.inputs.length == 1);
diff --git a/pkg/compiler/lib/src/universe/feature.dart b/pkg/compiler/lib/src/universe/feature.dart
index 1cb6aff..7ea60b7 100644
--- a/pkg/compiler/lib/src/universe/feature.dart
+++ b/pkg/compiler/lib/src/universe/feature.dart
@@ -16,9 +16,6 @@
 /// A language feature that may be seen in the program.
 // TODO(johnniwinther): Should mirror usage be part of this?
 enum Feature {
-  /// Invocation of a generative construction on an abstract class.
-  ABSTRACT_CLASS_INSTANTIATION,
-
   /// An assert statement with no message.
   ASSERT,
 
diff --git a/pkg/compiler/lib/src/util/util.dart b/pkg/compiler/lib/src/util/util.dart
index a4e0f16..423c0b2 100644
--- a/pkg/compiler/lib/src/util/util.dart
+++ b/pkg/compiler/lib/src/util/util.dart
@@ -36,6 +36,15 @@
     return ((high * 13) ^ (low * 997) ^ h) & SMI_MASK;
   }
 
+  /// Returns a hash value computed from all the characters in the string.
+  static int stringHash(String s) {
+    int hash = mixHashCodeBits(0, s.length);
+    for (int i = 0; i < s.length; i++) {
+      hash = mixHashCodeBits(hash, s.codeUnitAt(i));
+    }
+    return hash;
+  }
+
   /// Mix the bits of `object.hashCode` with [existing].
   static int objectHash(Object object, [int existing = 0]) {
     return mixHashCodeBits(existing, object.hashCode);
diff --git a/pkg/compiler/pubspec.yaml b/pkg/compiler/pubspec.yaml
index 2bc338e..80667e6 100644
--- a/pkg/compiler/pubspec.yaml
+++ b/pkg/compiler/pubspec.yaml
@@ -1,6 +1,7 @@
 # This pubspec is currently mainly used to make it easier to develop on dart2js
 # by making it a standalone package.
 name: compiler
+# This package is not intended for consumption on pub.dev. DO NOT publish.
 publish_to: none
 environment:
   sdk: '>=2.6.0 <3.0.0'
diff --git a/pkg/compiler/test/codegen/string_abbreviation_test.dart b/pkg/compiler/test/codegen/string_abbreviation_test.dart
new file mode 100644
index 0000000..00ed589
--- /dev/null
+++ b/pkg/compiler/test/codegen/string_abbreviation_test.dart
@@ -0,0 +1,111 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart = 2.7
+
+import 'package:expect/expect.dart';
+import 'package:compiler/src/js_backend/string_abbreviation.dart';
+
+void test(List<String> inputs, List<String> expected, {int minLength = 6}) {
+  Expect.listEquals(
+      expected, abbreviateToIdentifiers(inputs, minLength: minLength));
+}
+
+void main() {
+  // No strings yields an empty pool.
+  test([], []);
+
+  // Results identical stretches compressed-out.
+  test(
+    [
+      'Greetings Bob Smith',
+      'Great work!',
+      'Greetings Alice',
+      'Greetings Bob Henry',
+    ],
+    [
+      'GreetiBS',
+      'Great_',
+      'GreetiA',
+      'GreetiBH',
+    ],
+  );
+
+  test(
+    [
+      'Greetings Bob Smith',
+      'Great work!',
+      'Greetings Alice',
+      'Greetings Bob Henry',
+    ],
+    [
+      'GeBS',
+      'Ga',
+      'GeA',
+      'GeBH',
+    ],
+    minLength: 1,
+  );
+
+  // Non-identifiers are replaced with '_' if that is unambiguous.
+  test(
+    ['!pingpong', 'xylograph'],
+    ['_pingp', 'xylogr'],
+  );
+
+  test(['\u1234\xff'], ['__']);
+  test(['\u1234\xff', 'smile'], ['__', 'smile']);
+
+  test(
+    ['a*b+c', '(x,y)', 'a*c-e', '(x,z)'],
+    ['a_b_c', '_x_y_', 'a_c_e', '_x_z_'],
+  );
+
+  // Multiple discriminating non-identifier characters are replaced with an
+  // escape, which causes a potentially ambiguous non-escape to be escaped.
+  test(
+    ['a xylograph', 'a !pingpong', 'a %percent'],
+    ['a_x78ylo', 'a_x21pin', 'a_x25per'],
+  );
+
+  test(
+    ['a\u1234z', 'auz'],
+    ['a_z', 'auz'],
+  );
+  test(
+    ['a\u1234z', 'auz'],
+    ['a_', 'au'],
+    minLength: 1,
+  );
+
+  test(
+    ['a\u1234z', 'auz', 'a&z'],
+    ['au1234z', 'ax75z', 'ax26z'],
+  );
+  test(
+    ['a\u1234z', 'auz', 'a&z'],
+    ['au1234', 'ax75', 'ax26'],
+    minLength: 1,
+  );
+
+  test(
+    ['a\u1234z', 'auz', 'a&z', 'a\u2345z'],
+    ['au1234z', 'ax75z', 'ax26z', 'au2345z'],
+  );
+  test(
+    ['a\u1234z', 'auz', 'a&z', 'a\u2345z'],
+    ['au1234', 'ax75', 'ax26', 'au2345'],
+    minLength: 1,
+  );
+
+  test(
+    ['a\u1234z', 'auz', 'a&z', 'a\u2345z', 'axe'],
+    ['au1234z', 'ax75z', 'ax26z', 'au2345z', 'ax78e'],
+  );
+  test(
+    ['a\u1234z', 'auz', 'a&z', 'a\u2345z', 'axe'],
+    ['au1234', 'ax75', 'ax26', 'au2345', 'ax78'],
+    minLength: 1,
+  );
+}
diff --git a/pkg/compiler/test/codegen/string_reference_test.dart b/pkg/compiler/test/codegen/string_reference_test.dart
new file mode 100644
index 0000000..f7e20d2
--- /dev/null
+++ b/pkg/compiler/test/codegen/string_reference_test.dart
@@ -0,0 +1,119 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart = 2.7
+
+import "package:expect/expect.dart";
+
+import 'package:compiler/src/constants/values.dart' show StringConstantValue;
+import 'package:compiler/src/js_backend/string_reference.dart'
+    show StringReference, StringReferenceResource, StringReferenceFinalizerImpl;
+
+import 'package:compiler/src/js/js.dart' show prettyPrint;
+
+void test(List<String> strings, String expected, {bool minified: false}) {
+  var finalizer =
+      StringReferenceFinalizerImpl(minified, shortestSharedLength: 5);
+
+  for (var string in strings) {
+    finalizer.addCode(StringReference(StringConstantValue(string)));
+  }
+
+  StringReferenceResource resource = StringReferenceResource();
+  finalizer.registerStringReferenceResource(resource);
+  finalizer.finalize();
+
+  Expect.equals(expected.trim(), prettyPrint(resource).trim());
+}
+
+extension on List<String> {
+  // TODO(42122): Remove when analyzer doesn't think `*` is unused.
+  // ignore: unused_element
+  List<String> operator *(int count) {
+    return List.filled(count, this).expand((list) => list).toList();
+  }
+}
+
+void main() {
+  // No strings yields an empty pool.
+  test([], '0');
+
+  // Single occurrence strings are not pooled.
+  test(
+    ['Yellow', 'Blue', 'Crimson'],
+    '0',
+  );
+
+  // Repeated strings that are long enough are pooled.
+  test(
+    ['Yellow', 'Blue', 'Blue', 'Crimson', 'Crimson'],
+    r'''
+var string$ = {
+  Crimso: "Crimson"
+}''',
+  );
+
+  // Readable property names have identical stretches compressed-out.
+  var greets = [
+    'Greetings Bob Smith',
+    'Great work!',
+    'Greetings Alice',
+    'Greetings Bob Henry'
+  ];
+
+  test(
+    greets * 2,
+    r'''
+var string$ = {
+  Great_: "Great work!",
+  GreetiA: "Greetings Alice",
+  GreetiBH: "Greetings Bob Henry",
+  GreetiBS: "Greetings Bob Smith"
+}''',
+  );
+
+  // Non-identifiers are replaced with '_' if that is unambiguous.
+  test(
+    ['xylograph', '!pingpong'] * 2,
+    r'''
+var string$ = {
+  _pingp: "!pingpong",
+  xylogr: "xylograph"
+}''',
+  );
+
+  final strings1 = [
+    ...['a xylograph'] * 2,
+    ...['a !pingpong'] * 4,
+    ...['a %percent'] * 6,
+  ];
+
+  // Multiple discriminating non-identifier characters are replaced with an
+  // escape, which causes a potentially ambiguous non-escape to be escaped.
+  test(
+    strings1,
+    r'''
+var string$ = {
+  a_x21pin: "a !pingpong",
+  a_x25per: "a %percent",
+  a_x78ylo: "a xylograph"
+}''',
+  );
+
+  // Minified version keeps the strings in the same order as unminified, and
+  // tries to allocate the same minified name.
+  const minified1 = r'''
+var string$ = {
+  l: "a !pingpong",
+  o: "a %percent",
+  n: "a xylograph"
+}''';
+
+  final strings2 = [
+    ...['a xylograph'] * 20, // now most frequent.
+    ...strings1
+  ];
+  test(strings1, minified1, minified: true);
+  test(strings2, minified1, minified: true);
+}
diff --git a/pkg/compiler/test/impact/data/expressions.dart b/pkg/compiler/test/impact/data/expressions.dart
index 6b3d103..1f63b48 100644
--- a/pkg/compiler/test/impact/data/expressions.dart
+++ b/pkg/compiler/test/impact/data/expressions.dart
@@ -1329,8 +1329,7 @@
   _isString(1),
   _isTop(1),
   findType(1),
-  instanceType(1),
-  throwRuntimeError(1)],
+  instanceType(1)],
  type=[
   as:Class,
   inst:Closure,
@@ -1372,8 +1371,7 @@
   _isString(1),
   _isTop(1),
   findType(1),
-  instanceType(1),
-  throwRuntimeError(1)],
+  instanceType(1)],
  type=[
   as:Class*,
   inst:Closure,
@@ -1416,8 +1414,7 @@
   _isTop(1),
   findType(1),
   instanceType(1),
-  setRuntimeTypeInfo(2),
-  throwRuntimeError(1)],
+  setRuntimeTypeInfo(2)],
  type=[
   as:GenericClass<int,String>,
   inst:Closure,
@@ -1465,8 +1462,7 @@
   _isTop(1),
   findType(1),
   instanceType(1),
-  setRuntimeTypeInfo(2),
-  throwRuntimeError(1)],
+  setRuntimeTypeInfo(2)],
  type=[
   as:GenericClass<int*,String*>*,
   inst:Closure,
@@ -1513,8 +1509,7 @@
   _isString(1),
   _isTop(1),
   findType(1),
-  instanceType(1),
-  throwRuntimeError(1)],
+  instanceType(1)],
  type=[
   as:GenericClass<dynamic,dynamic>,
   inst:Closure,
@@ -1556,8 +1551,7 @@
   _isString(1),
   _isTop(1),
   findType(1),
-  instanceType(1),
-  throwRuntimeError(1)],
+  instanceType(1)],
  type=[
   as:GenericClass<dynamic,dynamic>*,
   inst:Closure,
@@ -1599,8 +1593,7 @@
   _isString(1),
   _isTop(1),
   findType(1),
-  instanceType(1),
-  throwRuntimeError(1)],
+  instanceType(1)],
  type=[
   as:GenericClass<dynamic,dynamic>,
   inst:Closure,
@@ -1642,8 +1635,7 @@
   _isString(1),
   _isTop(1),
   findType(1),
-  instanceType(1),
-  throwRuntimeError(1)],
+  instanceType(1)],
  type=[
   as:GenericClass<dynamic,dynamic>*,
   inst:Closure,
diff --git a/pkg/compiler/test/inference/data/foreign.dart b/pkg/compiler/test/inference/data/foreign.dart
index 2f304f7..e0b7078 100644
--- a/pkg/compiler/test/inference/data/foreign.dart
+++ b/pkg/compiler/test/inference/data/foreign.dart
@@ -20,10 +20,7 @@
   jsCallVoid();
   jsCallUnion();
 
-  jsBuiltin_rawRtiToJsConstructorName();
-
   jsEmbeddedGlobal_getTypeFromName();
-  jsEmbeddedGlobal_libraries();
 
   jsStringConcat();
 
@@ -42,21 +39,11 @@
 /*member: jsCallUnion:Union([exact=JSString], [subclass=JSInt])*/
 jsCallUnion() => JS('int|String', '#', 0);
 
-/*member: jsBuiltin_rawRtiToJsConstructorName:[exact=JSString]*/
-jsBuiltin_rawRtiToJsConstructorName() {
-  return JS_BUILTIN('String', JsBuiltin.rawRtiToJsConstructorName, null);
-}
-
 /*member: jsEmbeddedGlobal_getTypeFromName:[null|subclass=Object]*/
 jsEmbeddedGlobal_getTypeFromName() {
   return JS_EMBEDDED_GLOBAL('', GET_TYPE_FROM_NAME);
 }
 
-/*member: jsEmbeddedGlobal_libraries:[null|exact=JSExtendableArray]*/
-jsEmbeddedGlobal_libraries() {
-  return JS_EMBEDDED_GLOBAL('JSExtendableArray|Null', LIBRARIES);
-}
-
 /*member: jsStringConcat:[exact=JSString]*/
 jsStringConcat() => JS_STRING_CONCAT('a', 'b');
 
diff --git a/pkg/compiler/test/inference/side_effects/foreign.dart b/pkg/compiler/test/inference/side_effects/foreign.dart
index d73e3a4..9884d38 100644
--- a/pkg/compiler/test/inference/side_effects/foreign.dart
+++ b/pkg/compiler/test/inference/side_effects/foreign.dart
@@ -26,21 +26,11 @@
 jsCallEffectsNoInstanceDependsNoStatic() =>
     JS('effects:no-instance;depends:no-static', '#', 0);
 
-/*member: jsBuiltin_rawRtiToJsConstructorName:SideEffects(reads anything; writes anything)*/
-jsBuiltin_rawRtiToJsConstructorName() {
-  return JS_BUILTIN('String', JsBuiltin.rawRtiToJsConstructorName, null);
-}
-
 /*member: jsEmbeddedGlobal_getTypeFromName:SideEffects(reads nothing; writes nothing)*/
 jsEmbeddedGlobal_getTypeFromName() {
   return JS_EMBEDDED_GLOBAL('', GET_TYPE_FROM_NAME);
 }
 
-/*member: jsEmbeddedGlobal_libraries:SideEffects(reads nothing; writes nothing)*/
-jsEmbeddedGlobal_libraries() {
-  return JS_EMBEDDED_GLOBAL('JSExtendableArray|Null', LIBRARIES);
-}
-
 /*member: jsStringConcat:SideEffects(reads nothing; writes nothing)*/
 jsStringConcat() => JS_STRING_CONCAT('a', 'b');
 
@@ -54,10 +44,7 @@
   jsCallEffectsAllDependsNoIndex();
   jsCallEffectsNoInstanceDependsNoStatic();
 
-  jsBuiltin_rawRtiToJsConstructorName();
-
   jsEmbeddedGlobal_getTypeFromName();
-  jsEmbeddedGlobal_libraries();
 
   jsStringConcat();
 
diff --git a/pkg/dart2js_tools/pubspec.yaml b/pkg/dart2js_tools/pubspec.yaml
index 294d05f..d007dbe 100644
--- a/pkg/dart2js_tools/pubspec.yaml
+++ b/pkg/dart2js_tools/pubspec.yaml
@@ -1,4 +1,5 @@
 name: dart2js_tools
+# This package is not intended for consumption on pub.dev. DO NOT publish.
 publish_to: none
 description: >
   Collection of tools used with dart2js including analyzing compilation
diff --git a/pkg/dart2native/analysis_options.yaml b/pkg/dart2native/analysis_options.yaml
new file mode 100644
index 0000000..c84f27c
--- /dev/null
+++ b/pkg/dart2native/analysis_options.yaml
@@ -0,0 +1,13 @@
+include: package:pedantic/analysis_options.1.8.0.yaml
+
+analyzer:
+  errors:
+    # Increase the severity of several hints.
+    prefer_single_quotes: warning
+    unused_import: warning
+
+linter:
+  rules:
+    - directives_ordering
+    - prefer_relative_imports
+    - prefer_single_quotes
diff --git a/pkg/dart2native/bin/dart2native.dart b/pkg/dart2native/bin/dart2native.dart
index 19015f6..57c6f21 100644
--- a/pkg/dart2native/bin/dart2native.dart
+++ b/pkg/dart2native/bin/dart2native.dart
@@ -6,83 +6,7 @@
 import 'dart:io';
 
 import 'package:args/args.dart';
-import 'package:dart2native/dart2native.dart';
-import 'package:path/path.dart' as path;
-
-final String executableSuffix = Platform.isWindows ? '.exe' : '';
-final String snapshotDir = path.dirname(Platform.script.toFilePath());
-final String binDir = path.canonicalize(path.join(snapshotDir, '..'));
-final String sdkDir = path.canonicalize(path.join(binDir, '..'));
-final String dart = path.join(binDir, 'dart${executableSuffix}');
-final String genKernel = path.join(snapshotDir, 'gen_kernel.dart.snapshot');
-final String dartaotruntime =
-    path.join(binDir, 'dartaotruntime${executableSuffix}');
-final String genSnapshot =
-    path.join(binDir, 'utils', 'gen_snapshot${executableSuffix}');
-final String productPlatformDill =
-    path.join(sdkDir, 'lib', '_internal', 'vm_platform_strong_product.dill');
-
-Future<void> generateNative(
-    Kind kind,
-    String sourceFile,
-    String outputFile,
-    String debugFile,
-    String packages,
-    List<String> defines,
-    bool enableAsserts,
-    bool verbose,
-    List<String> extraGenSnapshotOptions) async {
-  final Directory tempDir = Directory.systemTemp.createTempSync();
-  try {
-    final String kernelFile = path.join(tempDir.path, 'kernel.dill');
-    final String snapshotFile = (kind == Kind.aot
-        ? outputFile
-        : path.join(tempDir.path, 'snapshot.aot'));
-
-    if (verbose) {
-      print('Generating AOT kernel dill.');
-    }
-
-    final kernelResult = await generateAotKernel(dart, genKernel,
-        productPlatformDill, sourceFile, kernelFile, packages, defines);
-    if (kernelResult.exitCode != 0) {
-      stderr.writeln(kernelResult.stdout);
-      stderr.writeln(kernelResult.stderr);
-      await stderr.flush();
-      throw 'Generating AOT kernel dill failed!';
-    }
-
-    if (verbose) {
-      print('Generating AOT snapshot.');
-    }
-    final snapshotResult = await generateAotSnapshot(genSnapshot, kernelFile,
-        snapshotFile, debugFile, enableAsserts, extraGenSnapshotOptions);
-    if (snapshotResult.exitCode != 0) {
-      stderr.writeln(snapshotResult.stdout);
-      stderr.writeln(snapshotResult.stderr);
-      await stderr.flush();
-      throw 'Generating AOT snapshot failed!';
-    }
-
-    if (kind == Kind.exe) {
-      if (verbose) {
-        print('Generating executable.');
-      }
-      await writeAppendedExecutable(dartaotruntime, snapshotFile, outputFile);
-
-      if (Platform.isLinux || Platform.isMacOS) {
-        if (verbose) {
-          print('Marking binary executable.');
-        }
-        await markExecutable(outputFile);
-      }
-    }
-
-    print('Generated: ${outputFile}');
-  } finally {
-    tempDir.deleteSync(recursive: true);
-  }
-}
+import 'package:dart2native/generate.dart';
 
 void printUsage(final ArgParser parser) {
   print('''
@@ -95,7 +19,7 @@
 
 Future<void> main(List<String> args) async {
   // If we're outputting to a terminal, wrap usage text to that width.
-  int outputLineWidth = null;
+  int outputLineWidth;
   try {
     outputLineWidth = stdout.terminalColumns;
   } catch (_) {/* Ignore. */}
@@ -159,42 +83,25 @@
     exit(1);
   }
 
-  final Kind kind = {
-    'aot': Kind.aot,
-    'exe': Kind.exe,
-  }[parsedArgs['output-kind']];
-
-  final sourcePath = path.canonicalize(path.normalize(parsedArgs.rest[0]));
-  final sourceWithoutDart = sourcePath.replaceFirst(new RegExp(r'\.dart$'), '');
-  final outputPath =
-      path.canonicalize(path.normalize(parsedArgs['output'] != null
-          ? parsedArgs['output']
-          : {
-              Kind.aot: '${sourceWithoutDart}.aot',
-              Kind.exe: '${sourceWithoutDart}.exe',
-            }[kind]));
-  final debugPath = parsedArgs['save-debugging-info'] != null
-      ? path.canonicalize(path.normalize(parsedArgs['save-debugging-info']))
-      : null;
-
-  if (!FileSystemEntity.isFileSync(sourcePath)) {
+  final String sourceFile = parsedArgs.rest[0];
+  if (!FileSystemEntity.isFileSync(sourceFile)) {
     stderr.writeln(
-        '"${sourcePath}" is not a file. See \'--help\' for more information.');
+        '"${sourceFile}" is not a file. See \'--help\' for more information.');
     await stderr.flush();
     exit(1);
   }
 
   try {
     await generateNative(
-        kind,
-        sourcePath,
-        outputPath,
-        debugPath,
-        parsedArgs['packages'],
-        parsedArgs['define'],
-        parsedArgs['enable-asserts'],
-        parsedArgs['verbose'],
-        parsedArgs['extra-gen-snapshot-options']);
+        kind: parsedArgs['output-kind'],
+        sourceFile: sourceFile,
+        outputFile: parsedArgs['output'],
+        debugFile: parsedArgs['save-debugging-info'],
+        packages: parsedArgs['packages'],
+        defines: parsedArgs['define'],
+        enableAsserts: parsedArgs['enable-asserts'],
+        verbose: parsedArgs['verbose'],
+        extraOptions: parsedArgs['extra-gen-snapshot-options']);
   } catch (e) {
     stderr.writeln('Failed to generate native files:');
     stderr.writeln(e);
diff --git a/pkg/dart2native/lib/dart2native.dart b/pkg/dart2native/lib/dart2native.dart
index 5bcceb1..06aaeec 100644
--- a/pkg/dart2native/lib/dart2native.dart
+++ b/pkg/dart2native/lib/dart2native.dart
@@ -21,7 +21,7 @@
   final offset = dartaotruntimeLength + padding;
 
   // Note: The offset is always Little Endian regardless of host.
-  final offsetBytes = new ByteData(8) // 64 bit in bytes.
+  final offsetBytes = ByteData(8) // 64 bit in bytes.
     ..setUint64(0, offset, Endian.little);
 
   final outputFile = File(outputPath).openWrite();
diff --git a/pkg/dart2native/lib/generate.dart b/pkg/dart2native/lib/generate.dart
new file mode 100644
index 0000000..c4cbbcb
--- /dev/null
+++ b/pkg/dart2native/lib/generate.dart
@@ -0,0 +1,97 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+import 'package:path/path.dart' as path;
+import 'dart2native.dart';
+
+final Directory binDir = File(Platform.resolvedExecutable).parent;
+final String executableSuffix = Platform.isWindows ? '.exe' : '';
+final String dartaotruntime =
+    path.join(binDir.path, 'dartaotruntime${executableSuffix}');
+final String genKernel =
+    path.join(binDir.path, 'snapshots', 'gen_kernel.dart.snapshot');
+final String genSnapshot =
+    path.join(binDir.path, 'utils', 'gen_snapshot${executableSuffix}');
+final String productPlatformDill = path.join(
+    binDir.parent.path, 'lib', '_internal', 'vm_platform_strong_product.dill');
+
+Future<void> generateNative({
+  String kind = 'exe',
+  String sourceFile,
+  String outputFile,
+  String debugFile,
+  String packages,
+  List<String> defines,
+  bool enableAsserts = false,
+  bool verbose = false,
+  List<String> extraOptions = const [],
+}) async {
+  final Directory tempDir = Directory.systemTemp.createTempSync();
+  try {
+    final sourcePath = path.canonicalize(path.normalize(sourceFile));
+    final Kind outputKind = {
+      'aot': Kind.aot,
+      'exe': Kind.exe,
+    }[kind];
+    final sourceWithoutDart = sourcePath.replaceFirst(RegExp(r'\.dart$'), '');
+    final outputPath = path.canonicalize(path.normalize(outputFile != null
+        ? outputFile
+        : {
+            Kind.aot: '${sourceWithoutDart}.aot',
+            Kind.exe: '${sourceWithoutDart}.exe',
+          }[outputKind]));
+    final debugPath =
+        debugFile != null ? path.canonicalize(path.normalize(debugFile)) : null;
+
+    if (verbose) {
+      print('Compiling $sourcePath to $outputPath using format $kind:');
+      print('Generating AOT kernel dill.');
+    }
+
+    final String kernelFile = path.join(tempDir.path, 'kernel.dill');
+    final kernelResult = await generateAotKernel(Platform.executable, genKernel,
+        productPlatformDill, sourcePath, kernelFile, packages, defines);
+    if (kernelResult.exitCode != 0) {
+      stderr.writeln(kernelResult.stdout);
+      stderr.writeln(kernelResult.stderr);
+      await stderr.flush();
+      throw 'Generating AOT kernel dill failed!';
+    }
+
+    if (verbose) {
+      print('Generating AOT snapshot.');
+    }
+
+    final String snapshotFile = (outputKind == Kind.aot
+        ? outputPath
+        : path.join(tempDir.path, 'snapshot.aot'));
+    final snapshotResult = await generateAotSnapshot(genSnapshot, kernelFile,
+        snapshotFile, debugPath, enableAsserts, extraOptions);
+    if (snapshotResult.exitCode != 0) {
+      stderr.writeln(snapshotResult.stdout);
+      stderr.writeln(snapshotResult.stderr);
+      await stderr.flush();
+      throw 'Generating AOT snapshot failed!';
+    }
+
+    if (outputKind == Kind.exe) {
+      if (verbose) {
+        print('Generating executable.');
+      }
+      await writeAppendedExecutable(dartaotruntime, snapshotFile, outputPath);
+
+      if (Platform.isLinux || Platform.isMacOS) {
+        if (verbose) {
+          print('Marking binary executable.');
+        }
+        await markExecutable(outputPath);
+      }
+    }
+
+    print('Generated: ${outputPath}');
+  } finally {
+    tempDir.deleteSync(recursive: true);
+  }
+}
diff --git a/pkg/dart2native/pubspec.yaml b/pkg/dart2native/pubspec.yaml
index c89834f..3bdd2c5 100644
--- a/pkg/dart2native/pubspec.yaml
+++ b/pkg/dart2native/pubspec.yaml
@@ -1,4 +1,5 @@
 name: dart2native
+# This package is not intended for consumption on pub.dev. DO NOT publish.
 publish_to: none
 
 environment:
diff --git a/pkg/dartdev/analysis_options.yaml b/pkg/dartdev/analysis_options.yaml
index 0f9f6b8..b1e4858 100644
--- a/pkg/dartdev/analysis_options.yaml
+++ b/pkg/dartdev/analysis_options.yaml
@@ -1,4 +1,4 @@
-include: package:pedantic/analysis_options.1.8.0.yaml
+include: package:pedantic/analysis_options.1.9.0.yaml
 
 analyzer:
   errors:
@@ -7,9 +7,59 @@
     unused_import: warning
     unnecessary_brace_in_string_interps: warning
 
+    # Ignore one pedantic lint
+    omit_local_variable_types: ignore
+
 linter:
   rules:
+    - avoid_function_literals_in_foreach_calls
+    - avoid_private_typedef_functions
+    - avoid_redundant_argument_values
+    - avoid_renaming_method_parameters
+    - avoid_returning_null_for_void
+    - avoid_void_async
+    - await_only_futures
+    - camel_case_types
+    - constant_identifier_names
     - directives_ordering
+    - empty_statements
+    - file_names
+    - iterable_contains_unrelated_type
+    - lines_longer_than_80_chars
+    - list_remove_unrelated_type
+    - missing_whitespace_between_adjacent_strings
+    - no_runtimeType_toString
+    - non_constant_identifier_names
+    - only_throw_errors
+    - overridden_fields
+    - package_names
+    - package_prefixed_library_names
+    - prefer_asserts_in_initializer_lists
+    - prefer_const_constructors
+    - prefer_const_declarations
+    - prefer_expression_function_bodies
+    - prefer_function_declarations_over_variables
+    - prefer_initializing_formals
+    - prefer_inlined_adds
+    - prefer_interpolation_to_compose_strings
+    - prefer_is_not_operator
+    - prefer_final_fields
+    - prefer_null_aware_operators
     - prefer_relative_imports
-    - prefer_single_quotes
+    - prefer_typing_uninitialized_variables
+    - prefer_void_to_null
+    - provide_deprecation_message
+    - sort_pub_dependencies
+    - test_types_in_equals
+    - throw_in_finally
+    - type_annotate_public_apis
     - unnecessary_brace_in_string_interps
+    - unnecessary_lambdas
+    - unnecessary_null_aware_assignments
+    - unnecessary_overrides
+    - unnecessary_parenthesis
+    - unnecessary_statements
+    - unnecessary_string_interpolations
+    - use_is_even_rather_than_modulo
+    - use_string_buffers
+    - void_checks
diff --git a/pkg/dartdev/bin/dartdev.dart b/pkg/dartdev/bin/dartdev.dart
index c0a850e9..1035f4e 100644
--- a/pkg/dartdev/bin/dartdev.dart
+++ b/pkg/dartdev/bin/dartdev.dart
@@ -5,6 +5,6 @@
 import 'package:dartdev/dartdev.dart';
 
 /// The entry point for dartdev.
-void main(List<String> args) async {
+Future<void> main(List<String> args) async {
   await runDartdev(args);
 }
diff --git a/pkg/dartdev/lib/dartdev.dart b/pkg/dartdev/lib/dartdev.dart
index c0afd77..c1cc224 100644
--- a/pkg/dartdev/lib/dartdev.dart
+++ b/pkg/dartdev/lib/dartdev.dart
@@ -12,6 +12,7 @@
 
 import 'src/analytics.dart';
 import 'src/commands/analyze.dart';
+import 'src/commands/compile.dart';
 import 'src/commands/create.dart';
 import 'src/commands/format.dart';
 import 'src/commands/pub.dart';
@@ -22,7 +23,7 @@
 /// This is typically called from bin/, but given the length of the method and
 /// analytics logic, it has been moved here. Also note that this method calls
 /// [io.exit(code)] directly.
-void runDartdev(List<String> args) async {
+Future<void> runDartdev(List<String> args) async {
   final stopwatch = Stopwatch();
   dynamic result;
 
@@ -35,11 +36,9 @@
   int exitCode;
 
   // Any caught non-UsageExceptions when running the sub command
-  Exception exception;
+  Object exception;
   StackTrace stackTrace;
 
-  var runner;
-
   analytics =
       createAnalyticsInstance(args.contains('--disable-dartdev-analytics'));
 
@@ -67,11 +66,11 @@
     io.exit(0);
   }
 
-  var commandName;
+  String commandName;
 
   try {
     stopwatch.start();
-    runner = DartdevRunner(args);
+    final runner = DartdevRunner(args);
     // Run can't be called with the '--disable-dartdev-analytics' flag, remove
     // it if it is contained in args.
     if (args.contains('--disable-dartdev-analytics')) {
@@ -105,9 +104,7 @@
     stopwatch.stop();
 
     // Set the exitCode, if it wasn't set in the catch block above.
-    if (exitCode == null) {
-      exitCode = result is int ? result : 0;
-    }
+    exitCode ??= result is int ? result : 0;
 
     // Send analytics before exiting
     if (analytics.enabled) {
@@ -124,7 +121,8 @@
             fatal: true);
       }
 
-      await analytics.waitForLastPing(timeout: Duration(milliseconds: 200));
+      await analytics.waitForLastPing(
+          timeout: const Duration(milliseconds: 200));
     }
 
     // As the notification to the user read on the first run, analytics are
@@ -153,6 +151,9 @@
     argParser.addFlag('disable-analytics',
         negatable: false, help: 'Disable anonymous analytics.');
 
+    // TODO(jwren): hook up.
+    argParser.addMultiOption('enable-experiment', hide: true);
+
     // A hidden flag to disable analytics on this run, this constructor can be
     // called with this flag, but should be removed before run() is called as
     // the flag has not been added to all sub-commands.
@@ -163,6 +164,7 @@
 
     addCommand(AnalyzeCommand(verbose: verbose));
     addCommand(CreateCommand(verbose: verbose));
+    addCommand(CompileCommand(verbose: verbose));
     addCommand(FormatCommand(verbose: verbose));
     addCommand(MigrateCommand(verbose: verbose));
     addCommand(PubCommand(verbose: verbose));
@@ -175,10 +177,11 @@
       'dart [<vm-flags>] <command|dart-file> [<arguments>]';
 
   @override
-  Future<int> runCommand(ArgResults results) async {
-    assert(!results.arguments.contains('--disable-dartdev-analytics'));
-    if (results.command == null && results.arguments.isNotEmpty) {
-      final firstArg = results.arguments.first;
+  Future<int> runCommand(ArgResults topLevelResults) async {
+    assert(!topLevelResults.arguments.contains('--disable-dartdev-analytics'));
+    if (topLevelResults.command == null &&
+        topLevelResults.arguments.isNotEmpty) {
+      final firstArg = topLevelResults.arguments.first;
       // If we make it this far, it means the VM couldn't find the file on disk.
       if (firstArg.endsWith('.dart')) {
         io.stderr.writeln(
@@ -187,11 +190,11 @@
         io.exit(254);
       }
     }
-    isVerbose = results['verbose'];
+    isVerbose = topLevelResults['verbose'];
 
     final Ansi ansi = Ansi(Ansi.terminalSupportsAnsi);
     log = isVerbose ? Logger.verbose(ansi: ansi) : Logger.standard(ansi: ansi);
 
-    return await super.runCommand(results);
+    return await super.runCommand(topLevelResults);
   }
 }
diff --git a/pkg/dartdev/lib/src/analytics.dart b/pkg/dartdev/lib/src/analytics.dart
index 112eb70..b00dca4 100644
--- a/pkg/dartdev/lib/src/analytics.dart
+++ b/pkg/dartdev/lib/src/analytics.dart
@@ -26,7 +26,7 @@
   ║ `dart --enable-analytics`                                                  ║
   ╚════════════════════════════════════════════════════════════════════════════╝
 ''';
-const String _unknown_command = '<unknown>';
+const String _unknownCommand = '<unknown>';
 const String _appName = 'dartdev';
 const String _dartDirectoryName = '.dart';
 const String _settingsFileName = 'dartdev.json';
@@ -87,7 +87,7 @@
     return 'help';
   }
   return args.firstWhere((arg) => allCommands.contains(arg),
-      orElse: () => _unknown_command);
+      orElse: () => _unknownCommand);
 }
 
 /// Given some set of arguments and parameters, this returns a proper subset
diff --git a/pkg/dartdev/lib/src/commands/analyze.dart b/pkg/dartdev/lib/src/commands/analyze.dart
index 30b096f..ccf9a57 100644
--- a/pkg/dartdev/lib/src/commands/analyze.dart
+++ b/pkg/dartdev/lib/src/commands/analyze.dart
@@ -17,13 +17,9 @@
       : super('analyze', "Analyze the project's Dart code.") {
     argParser
       ..addFlag('fatal-infos',
-          help: 'Treat info level issues as fatal.',
-          defaultsTo: false,
-          negatable: false)
+          help: 'Treat info level issues as fatal.', negatable: false)
       ..addFlag('fatal-warnings',
-          help: 'Treat warning level issues as fatal.',
-          defaultsTo: true,
-          negatable: true);
+          help: 'Treat warning level issues as fatal.', defaultsTo: true);
   }
 
   @override
@@ -69,7 +65,7 @@
     await server.start();
     // Completing the future in the callback can't fail.
     //ignore: unawaited_futures
-    server.onExit.then<void>((int exitCode) {
+    server.onExit.then((int exitCode) {
       if (!analysisCompleter.isCompleted) {
         analysisCompleter.completeError('analysis server exited: $exitCode');
       }
diff --git a/pkg/dartdev/lib/src/commands/analyze_impl.dart b/pkg/dartdev/lib/src/commands/analyze_impl.dart
index c32eae9..76e1fcb 100644
--- a/pkg/dartdev/lib/src/commands/analyze_impl.dart
+++ b/pkg/dartdev/lib/src/commands/analyze_impl.dart
@@ -38,7 +38,7 @@
 
   Future<void> start() async {
     final List<String> command = <String>[
-      sdk.analysis_server_snapshot,
+      sdk.analysisServerSnapshot,
       '--disable-server-feature-completion',
       '--disable-server-feature-search',
       '--sdk',
@@ -116,7 +116,9 @@
         final Map<String, dynamic> error =
             castStringKeyedMap(response['error']);
         log.stderr(
-            'Error response from the server: ${error['code']} ${error['message']}');
+          'Error response from the server: '
+          '${error['code']} ${error['message']}',
+        );
         if (error['stackTrace'] != null) {
           log.stderr(error['stackTrace'] as String);
         }
@@ -235,11 +237,9 @@
   }
 
   @override
-  String toString() {
-    return '${severity.toLowerCase()} • '
-        '$messageSentenceFragment at $file:$startLine:$startColumn • '
-        '($code)';
-  }
+  String toString() => '${severity.toLowerCase()} • '
+      '$messageSentenceFragment at $file:$startLine:$startColumn • '
+      '($code)';
 }
 
 class FileAnalysisErrors {
diff --git a/pkg/dartdev/lib/src/commands/compile.dart b/pkg/dartdev/lib/src/commands/compile.dart
new file mode 100644
index 0000000..025d5c6
--- /dev/null
+++ b/pkg/dartdev/lib/src/commands/compile.dart
@@ -0,0 +1,244 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:io';
+
+import 'package:args/command_runner.dart';
+import 'package:dart2native/generate.dart';
+import 'package:path/path.dart' as path;
+
+import '../core.dart';
+import '../sdk.dart';
+
+const int compileErrorExitCode = 64;
+
+class Option {
+  final String flag;
+  final String help;
+  final String abbr;
+  Option({this.flag, this.help, this.abbr});
+}
+
+final Map<String, Option> commonOptions = {
+  'outputFile': Option(
+    flag: 'output',
+    abbr: 'o',
+    help: '''
+Write the output to <file name>.
+This can be an absolute or reletive path.
+''',
+  ),
+};
+
+bool checkFile(String sourcePath) {
+  if (!FileSystemEntity.isFileSync(sourcePath)) {
+    stderr.writeln(
+        '"$sourcePath" is not a file. See \'--help\' for more information.');
+    stderr.flush();
+    return false;
+  }
+
+  return true;
+}
+
+class CompileJSCommand extends DartdevCommand<int> {
+  bool verbose = false;
+  CompileJSCommand({
+    this.verbose,
+  }) : super('js', 'Compile Dart to JavaScript') {
+    argParser
+      ..addOption(
+        commonOptions['outputFile'].flag,
+        help: commonOptions['outputFile'].help,
+        abbr: commonOptions['outputFile'].abbr,
+      )
+      ..addFlag(
+        'minified',
+        help: 'Generate minified output.',
+        abbr: 'm',
+        negatable: false,
+      );
+  }
+
+  @override
+  String get invocation => '${super.invocation} <dart entry point>';
+
+  @override
+  FutureOr<int> run() async {
+    // We expect a single rest argument; the dart entry point.
+    if (argResults.rest.length != 1) {
+      log.stderr('Missing Dart entry point.');
+      printUsage();
+      return compileErrorExitCode;
+    }
+    final String sourcePath = argResults.rest[0];
+    if (!checkFile(sourcePath)) {
+      return -1;
+    }
+
+    final process = await startProcess(sdk.dart2js, argResults.arguments);
+    routeToStdout(process);
+    return process.exitCode;
+  }
+}
+
+class CompileSnapshotCommand extends DartdevCommand<int> {
+  bool verbose = false;
+  final String commandName;
+  final String help;
+  final String fileExt;
+  final String formatName;
+
+  CompileSnapshotCommand({
+    this.verbose,
+    this.commandName,
+    this.help,
+    this.fileExt,
+    this.formatName,
+  }) : super(commandName, 'Compile Dart $help') {
+    argParser
+      ..addOption(
+        commonOptions['outputFile'].flag,
+        help: commonOptions['outputFile'].help,
+        abbr: commonOptions['outputFile'].abbr,
+      );
+  }
+
+  @override
+  String get invocation => '${super.invocation} <dart entry point>';
+
+  @override
+  FutureOr<int> run() async {
+    // We expect a single rest argument; the dart entry point.
+    if (argResults.rest.length != 1) {
+      log.stderr('Missing Dart entry point.');
+      printUsage();
+      return compileErrorExitCode;
+    }
+    final String sourcePath = argResults.rest[0];
+    if (!checkFile(sourcePath)) {
+      return -1;
+    }
+
+    // Determine output file name.
+    String outputFile = argResults[commonOptions['outputFile'].flag];
+    if (outputFile == null) {
+      final inputWithoutDart = sourcePath.replaceFirst(RegExp(r'\.dart$'), '');
+      outputFile = '$inputWithoutDart.$fileExt';
+    }
+
+    // Build arguments.
+    List<String> args = [];
+    args.add('--snapshot-kind=$formatName');
+    args.add('--snapshot=${path.canonicalize(outputFile)}');
+    if (verbose) {
+      args.add('-v');
+    }
+    args.add(path.canonicalize(sourcePath));
+
+    log.stdout('Compiling $sourcePath to $commandName file $outputFile.');
+    final process = await startProcess(sdk.dart, args);
+    routeToStdout(process);
+    return process.exitCode;
+  }
+}
+
+class CompileNativeCommand extends DartdevCommand<int> {
+  bool verbose = false;
+  final String commandName;
+  final String format;
+  final String help;
+
+  CompileNativeCommand({
+    this.verbose,
+    this.commandName,
+    this.format,
+    this.help,
+  }) : super(commandName, 'Compile Dart $help') {
+    argParser
+      ..addOption(
+        commonOptions['outputFile'].flag,
+        help: commonOptions['outputFile'].help,
+        abbr: commonOptions['outputFile'].abbr,
+      )
+      ..addMultiOption('define', abbr: 'D', valueHelp: 'key=value', help: '''
+Set values of environment variables. To specify multiple variables, use multiple options or use commas to separate key-value pairs.
+E.g.: dart2native -Da=1,b=2 main.dart''')
+      ..addFlag('enable-asserts',
+          negatable: false, help: 'Enable assert statements.')
+      ..addOption('packages', abbr: 'p', valueHelp: 'path', help: '''
+Get package locations from the specified file instead of .packages. <path> can be relative or absolute.
+E.g.: dart2native --packages=/tmp/pkgs main.dart
+''')
+      ..addOption('save-debugging-info', abbr: 'S', valueHelp: 'path', help: '''
+Remove debugging information from the output and save it separately to the specified file. <path> can be relative or absolute.
+''');
+  }
+
+  @override
+  String get invocation => '${super.invocation} <dart entry point>';
+
+  @override
+  FutureOr<int> run() async {
+    // We expect a single rest argument; the dart entry point.
+    if (argResults.rest.length != 1) {
+      log.stderr('Missing Dart entry point.');
+      printUsage();
+      return compileErrorExitCode;
+    }
+    final String sourcePath = argResults.rest[0];
+    if (!checkFile(sourcePath)) {
+      return -1;
+    }
+
+    try {
+      await generateNative(
+        kind: format,
+        sourceFile: sourcePath,
+        outputFile: argResults['output'],
+        defines: argResults['define'],
+        packages: argResults['packages'],
+        enableAsserts: argResults['enable-asserts'],
+        debugFile: argResults['save-debugging-info'],
+        verbose: verbose,
+      );
+      return 0;
+    } catch (e) {
+      log.stderr('Error: AOT compilation failed');
+      log.stderr(e.toString());
+      return compileErrorExitCode;
+    }
+  }
+}
+
+class CompileCommand extends Command {
+  @override
+  String get description => 'Compile Dart to various formats.';
+  @override
+  String get name => 'compile';
+
+  CompileCommand({bool verbose = false}) {
+    addSubcommand(CompileJSCommand());
+    addSubcommand(CompileSnapshotCommand(
+      commandName: 'jit-snapshot',
+      help: 'to a JIT snapshot',
+      fileExt: 'jit',
+      formatName: 'app-jit',
+      verbose: verbose,
+    ));
+    addSubcommand(CompileNativeCommand(
+      commandName: 'exe',
+      help: 'to a self-contained executable',
+      format: 'exe',
+      verbose: verbose,
+    ));
+    addSubcommand(CompileNativeCommand(
+      commandName: 'aot-snapshot',
+      help: 'to an AOT snapshot',
+      format: 'aot',
+      verbose: verbose,
+    ));
+  }
+}
diff --git a/pkg/dartdev/lib/src/commands/create.dart b/pkg/dartdev/lib/src/commands/create.dart
index cb95a1c..55d53d8 100644
--- a/pkg/dartdev/lib/src/commands/create.dart
+++ b/pkg/dartdev/lib/src/commands/create.dart
@@ -7,7 +7,7 @@
 import 'dart:io' as io;
 import 'dart:math' as math;
 
-import 'package:path/path.dart' as path;
+import 'package:path/path.dart' as p;
 import 'package:stagehand/stagehand.dart' as stagehand;
 
 import '../core.dart';
@@ -24,13 +24,11 @@
     'web-simple'
   ];
 
-  static Iterable<stagehand.Generator> get generators {
-    return legalTemplateIds.map(retrieveTemplateGenerator);
-  }
+  static Iterable<stagehand.Generator> get generators =>
+      legalTemplateIds.map(retrieveTemplateGenerator);
 
-  static stagehand.Generator retrieveTemplateGenerator(String templateId) {
-    return stagehand.getGenerator(templateId);
-  }
+  static stagehand.Generator retrieveTemplateGenerator(String templateId) =>
+      stagehand.getGenerator(templateId);
 
   CreateCommand({bool verbose = false})
       : super('create', 'Create a new project.') {
@@ -53,8 +51,8 @@
     argParser.addFlag(
       'force',
       negatable: false,
-      help:
-          'Force project generation, even if the target directory already exists.',
+      help: 'Force project generation, even if the target directory already '
+          'exists.',
     );
   }
 
@@ -77,19 +75,23 @@
 
     String dir = argResults.rest.first;
     var targetDir = io.Directory(dir);
-    if (targetDir.existsSync() && !(argResults['force'])) {
+    if (targetDir.existsSync() && !argResults['force']) {
       log.stderr(
-          "Directory '$dir' already exists (use '--force' to force project generation).");
+        "Directory '$dir' already exists "
+        "(use '--force' to force project generation).",
+      );
       return 73;
     }
 
     log.stdout(
-        'Creating ${log.ansi.emphasized(path.absolute(dir))} using template $templateId...');
+      'Creating ${log.ansi.emphasized(p.absolute(dir))} '
+      'using template $templateId...',
+    );
     log.stdout('');
 
     var generator = retrieveTemplateGenerator(templateId);
     await generator.generate(
-      path.basename(dir),
+      p.basename(dir),
       DirectoryGeneratorTarget(generator, io.Directory(dir)),
     );
 
@@ -125,7 +127,7 @@
     log.stdout('');
     log.stdout('Created project $dir! In order to get started, type:');
     log.stdout('');
-    log.stdout(log.ansi.emphasized('  cd ${path.relative(dir)}'));
+    log.stdout(log.ansi.emphasized('  cd ${p.relative(dir)}'));
     // TODO(devoncarew): Once we have a 'run' command, print out here how to run
     // the app.
     log.stdout('');
@@ -159,7 +161,7 @@
       return m;
     });
 
-    JsonEncoder encoder = JsonEncoder.withIndent('  ');
+    JsonEncoder encoder = const JsonEncoder.withIndent('  ');
     return encoder.convert(items.toList());
   }
 }
@@ -173,10 +175,10 @@
   }
 
   @override
-  Future createFile(String filePath, List<int> contents) async {
-    io.File file = io.File(path.join(dir.path, filePath));
+  Future createFile(String path, List<int> contents) async {
+    io.File file = io.File(p.join(dir.path, path));
 
-    String name = path.relative(file.path, from: dir.path);
+    String name = p.relative(file.path, from: dir.path);
     log.stdout('  $name');
 
     await file.create(recursive: true);
diff --git a/pkg/dartdev/lib/src/commands/pub.dart b/pkg/dartdev/lib/src/commands/pub.dart
index 2d983df..0019696 100644
--- a/pkg/dartdev/lib/src/commands/pub.dart
+++ b/pkg/dartdev/lib/src/commands/pub.dart
@@ -13,6 +13,7 @@
 class PubCommand extends DartdevCommand<int> {
   PubCommand({bool verbose = false}) : super('pub', 'Work with packages.');
 
+  @override
   final ArgParser argParser = ArgParser.allowAnything();
 
   @override
diff --git a/pkg/dartdev/lib/src/commands/run.dart b/pkg/dartdev/lib/src/commands/run.dart
index 2f4a942..7496a2a 100644
--- a/pkg/dartdev/lib/src/commands/run.dart
+++ b/pkg/dartdev/lib/src/commands/run.dart
@@ -15,8 +15,10 @@
 import '../utils.dart';
 
 class RunCommand extends DartdevCommand<int> {
+  @override
   final ArgParser argParser = ArgParser.allowAnything();
   final bool verbose;
+
   RunCommand({this.verbose = false}) : super('run', '''
 Run a Dart file.''');
 
@@ -90,7 +92,9 @@
       }
       if (!foundImplicitFileToRun) {
         log.stderr(
-            'Could not find the implicit file to run: bin$separator$cwdName.dart.');
+          'Could not find the implicit file to run: '
+          'bin$separator$cwdName.dart.',
+        );
       }
     }
 
@@ -99,8 +103,9 @@
     // service intermediary which implements the VM service protocol and
     // provides non-VM specific extensions (e.g., log caching, client
     // synchronization).
-    if (args.any((element) => (element.startsWith('--observe') ||
-        element.startsWith('--enable-vm-service')))) {
+    if (args.any((element) =>
+        element.startsWith('--observe') ||
+        element.startsWith('--enable-vm-service'))) {
       return await _DebuggingSession(this, args).start();
     }
 
@@ -137,8 +142,8 @@
             try {
               _bindAddress = Uri.http(observatoryBindInfo[1], '');
             } on FormatException {
-              // TODO(bkonyi): log invalid parse? The VM service just ignores bad
-              // input flags.
+              // TODO(bkonyi): log invalid parse? The VM service just ignores
+              // bad input flags.
               // Ignore.
             }
           }
@@ -165,9 +170,10 @@
     // Strip --observe and --write-service-info from the arguments as we'll be
     // providing our own.
     _args.removeWhere(
-      (arg) => (arg.startsWith('--observe') ||
+      (arg) =>
+          arg.startsWith('--observe') ||
           arg.startsWith('--enable-vm-service') ||
-          arg.startsWith('--write-service-info')),
+          arg.startsWith('--write-service-info'),
     );
   }
 
@@ -195,8 +201,7 @@
 
     // Start DDS once the VM service has finished starting up.
     await Future.any([
-      _waitForRemoteServiceUri(serviceInfoFile)
-          .then((serviceUri) => _startDDS(serviceUri)),
+      _waitForRemoteServiceUri(serviceInfoFile).then(_startDDS),
       _process.exitCode,
     ]);
 
@@ -214,7 +219,7 @@
 
   Future<Uri> _waitForRemoteServiceUri(File serviceInfoFile) async {
     // Wait for VM service to write its connection info to disk.
-    while ((await serviceInfoFile.length() <= 5)) {
+    while (await serviceInfoFile.length() <= 5) {
       await Future.delayed(const Duration(milliseconds: 50));
     }
     final serviceInfoStr = await serviceInfoFile.readAsString();
@@ -263,14 +268,14 @@
     // to ensure we don't let any unfiltered messages slip through.
     // TODO(bkonyi): consider filtering on bytes rather than decoding the UTF8.
     _stderrDone = process.stderr
-        .transform(Utf8Decoder(allowMalformed: true))
+        .transform(const Utf8Decoder(allowMalformed: true))
         .listen((event) async {
       await _waitForDDS();
       stderr.write(filterObservatoryUri(event));
     }).asFuture();
 
     _stdoutDone = process.stdout
-        .transform(Utf8Decoder(allowMalformed: true))
+        .transform(const Utf8Decoder(allowMalformed: true))
         .listen((event) async {
       await _waitForDDS();
       stdout.write(filterObservatoryUri(event));
diff --git a/pkg/dartdev/lib/src/commands/test.dart b/pkg/dartdev/lib/src/commands/test.dart
index d56cd11..d52b802 100644
--- a/pkg/dartdev/lib/src/commands/test.dart
+++ b/pkg/dartdev/lib/src/commands/test.dart
@@ -14,6 +14,7 @@
   TestCommand({bool verbose = false})
       : super('test', 'Runs tests in this project.');
 
+  @override
   final ArgParser argParser = ArgParser.allowAnything();
 
   @override
diff --git a/pkg/dartdev/lib/src/core.dart b/pkg/dartdev/lib/src/core.dart
index ea7cb9b..b0bb75e 100644
--- a/pkg/dartdev/lib/src/core.dart
+++ b/pkg/dartdev/lib/src/core.dart
@@ -31,7 +31,7 @@
   @override
   String get description => _description;
 
-  Project get project => (_project ??= Project());
+  Project get project => _project ??= Project();
 }
 
 /// A utility method to start the given executable as a process, optionally
@@ -48,7 +48,7 @@
 void routeToStdout(
   Process process, {
   bool logToTrace = false,
-  void listener(String str),
+  void Function(String str) listener,
 }) {
   if (isVerbose) {
     _streamLineTransform(process.stdout, (String line) {
@@ -72,7 +72,10 @@
   }
 }
 
-void _streamLineTransform(Stream<List<int>> stream, handler(String line)) {
+void _streamLineTransform(
+  Stream<List<int>> stream,
+  Function(String line) handler,
+) {
   stream
       .transform(utf8.decoder)
       .transform(const LineSplitter())
@@ -119,7 +122,6 @@
     return _packages.map<Map<String, dynamic>>(castStringKeyedMap).toList();
   }
 
-  bool hasDependency(String packageName) {
-    return packages.any((element) => element['name'] == packageName);
-  }
+  bool hasDependency(String packageName) =>
+      packages.any((element) => element['name'] == packageName);
 }
diff --git a/pkg/dartdev/lib/src/sdk.dart b/pkg/dartdev/lib/src/sdk.dart
index e7c1c97..8481714 100644
--- a/pkg/dartdev/lib/src/sdk.dart
+++ b/pkg/dartdev/lib/src/sdk.dart
@@ -45,9 +45,11 @@
   // if the SDK isn't completely built.
   String get dart => Platform.resolvedExecutable;
 
-  String get analysis_server_snapshot => path.absolute(
+  String get analysisServerSnapshot => path.absolute(
       sdkPath, 'bin', 'snapshots', 'analysis_server.dart.snapshot');
 
+  String get dart2js => path.absolute(sdkPath, 'bin', _binName('dart2js'));
+
   String get dartfmt => path.absolute(sdkPath, 'bin', _binName('dartfmt'));
 
   String get pub => path.absolute(sdkPath, 'bin', _binName('pub'));
diff --git a/pkg/dartdev/pubspec.yaml b/pkg/dartdev/pubspec.yaml
index 8714110..061f6fa 100644
--- a/pkg/dartdev/pubspec.yaml
+++ b/pkg/dartdev/pubspec.yaml
@@ -1,21 +1,28 @@
 name: dartdev
 
-# This package is not intended to be published
+# This package is not intended for consumption on pub.dev. DO NOT publish.
 publish_to: none
 
 environment:
   sdk: '>=2.6.0 <3.0.0'
 dependencies:
-  args: ^1.5.2
-  cli_util: ^0.1.0
+  args: ^1.6.0
+  cli_util: ^0.1.4
+  dart2native:
+    path: ../dart2native
   dds:
-    path: '../dds'
-  intl: ^0.16.0
-  path: ^1.6.2
+    path: ../dds
+  intl: ^0.16.1
+  nnbd_migration: any # this uses the SDK version
+  path: ^1.0.0
+  stack_trace: ^1.9.3
   stagehand: 3.3.7
-  watcher: ^0.9.7+13
+  telemetry:
+    path: ../telemetry
+  usage: ^3.4.0
+  watcher: ^0.9.6
   yaml: ^2.2.0
 
 dev_dependencies:
   test: ^1.0.0
-  pedantic: ^1.8.0
+  pedantic: ^1.9.0
diff --git a/pkg/dartdev/test/analytics_test.dart b/pkg/dartdev/test/analytics_test.dart
index 6f7d3d3..8632697 100644
--- a/pkg/dartdev/test/analytics_test.dart
+++ b/pkg/dartdev/test/analytics_test.dart
@@ -6,11 +6,11 @@
 import 'package:test/test.dart';
 
 void main() {
-  group('DisabledAnalytics', disabledAnalytics_object);
+  group('DisabledAnalytics', disabledAnalyticsObject);
   group('utils', utils);
 }
 
-void disabledAnalytics_object() {
+void disabledAnalyticsObject() {
   test('object', () {
     var diabledAnalytics = DisabledAnalytics('trackingId', 'appName');
     expect(diabledAnalytics.trackingId, 'trackingId');
diff --git a/pkg/dartdev/test/commands/compile_test.dart b/pkg/dartdev/test/commands/compile_test.dart
new file mode 100644
index 0000000..489181d
--- /dev/null
+++ b/pkg/dartdev/test/commands/compile_test.dart
@@ -0,0 +1,180 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:path/path.dart' as path;
+import 'package:test/test.dart';
+
+import '../utils.dart';
+
+const int compileErrorExitCode = 64;
+
+void main() {
+  group('compile', defineCompileTests, timeout: longTimeout);
+}
+
+void defineCompileTests() {
+  // *** NOTE ***: These tests *must* be run with the `--use-sdk` option
+  // as they depend on a fully built SDK to resolve various snapshot files
+  // used by compilation.
+  test('Running from built SDK', () {
+    final Directory binDir = File(Platform.resolvedExecutable).parent;
+    expect(binDir.path, contains('bin'));
+  });
+
+  test('Implicit --help', () {
+    final p = project();
+    var result = p.runSync(
+      'compile',
+      [],
+    );
+    expect(result.stderr, contains('Compile Dart'));
+    expect(result.exitCode, compileErrorExitCode);
+  });
+
+  test('--help', () {
+    final p = project();
+    final result = p.runSync(
+      'compile',
+      ['--help'],
+    );
+    expect(result.stdout, contains('Compile Dart'));
+    expect(result.exitCode, 0);
+  });
+
+  test('Compile and run jit snapshot', () {
+    final p = project(mainSrc: 'void main() { print("I love jit"); }');
+    final outFile = path.join(p.dirPath, 'main.jit');
+    var result = p.runSync(
+      'compile',
+      [
+        'jit-snapshot',
+        '-o',
+        outFile,
+        p.relativeFilePath,
+      ],
+    );
+    expect(File(outFile).existsSync(), true,
+        reason: 'File not found: $outFile');
+    expect(result.stderr, isEmpty);
+    expect(result.exitCode, 0);
+
+    result = p.runSync('run', ['main.jit']);
+    expect(result.stdout, contains('I love jit'));
+    expect(result.stderr, isEmpty);
+    expect(result.exitCode, 0);
+  });
+
+  test('Compile and run executable', () {
+    final p = project(mainSrc: 'void main() { print("I love executables"); }');
+    final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
+    final outFile = path.canonicalize(path.join(p.dirPath, 'lib', 'main.exe'));
+
+    var result = p.runSync(
+      'compile',
+      [
+        'exe',
+        inFile,
+      ],
+    );
+
+    expect(File(outFile).existsSync(), true,
+        reason: 'File not found: $outFile');
+    expect(result.stderr, isEmpty);
+    expect(result.exitCode, 0);
+
+    result = Process.runSync(
+      outFile,
+      [],
+    );
+
+    expect(result.stdout, contains('I love executables'));
+    expect(result.stderr, isEmpty);
+    expect(result.exitCode, 0);
+  });
+
+  test('Compile and run executable with options', () {
+    final p = project(
+        mainSrc: 'void main() {print(const String.fromEnvironment("life"));}');
+    final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
+    final outFile = path.canonicalize(path.join(p.dirPath, 'myexe'));
+
+    var result = p.runSync(
+      'compile',
+      [
+        'exe',
+        '--define',
+        'life=42',
+        '-o',
+        outFile,
+        inFile,
+      ],
+    );
+
+    expect(File(outFile).existsSync(), true,
+        reason: 'File not found: $outFile');
+    expect(result.stderr, isEmpty);
+    expect(result.exitCode, 0);
+
+    result = Process.runSync(
+      outFile,
+      [],
+    );
+
+    expect(result.stdout, contains('42'));
+    expect(result.stderr, isEmpty);
+    expect(result.exitCode, 0);
+  });
+
+  test('Compile and run aot snapshot', () {
+    final p = project(mainSrc: 'void main() { print("I love AOT"); }');
+    final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
+    final outFile = path.canonicalize(path.join(p.dirPath, 'main.aot'));
+
+    var result = p.runSync(
+      'compile',
+      [
+        'aot-snapshot',
+        '-o',
+        'main.aot',
+        inFile,
+      ],
+    );
+
+    expect(File(outFile).existsSync(), true,
+        reason: 'File not found: $outFile');
+    expect(result.stderr, isEmpty);
+    expect(result.exitCode, 0);
+
+    final Directory binDir = File(Platform.resolvedExecutable).parent;
+    result = Process.runSync(
+      path.join(binDir.path, 'dartaotruntime'),
+      [outFile],
+    );
+
+    expect(result.stdout, contains('I love AOT'));
+    expect(result.stderr, isEmpty);
+    expect(result.exitCode, 0);
+  });
+
+  test('Compile JS', () {
+    final p = project(mainSrc: "void main() { print('Hello from JS'); }");
+    final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
+    final outFile = path.canonicalize(path.join(p.dirPath, 'main.js'));
+
+    final result = p.runSync('compile', [
+      'js',
+      '-m',
+      '-o',
+      outFile,
+      '-v',
+      inFile,
+    ]);
+    expect(File(outFile).existsSync(), true,
+        reason: 'File not found: $outFile');
+    expect(result.stderr, isEmpty);
+    expect(result.exitCode, 0);
+  });
+}
diff --git a/pkg/dartdev/test/commands/flag_test.dart b/pkg/dartdev/test/commands/flag_test.dart
index 7e35ef8..978c6ae 100644
--- a/pkg/dartdev/test/commands/flag_test.dart
+++ b/pkg/dartdev/test/commands/flag_test.dart
@@ -57,6 +57,7 @@
     expect(result.stdout, contains('Available commands:'));
     expect(result.stdout, contains('analyze '));
     expect(result.stdout, contains('create '));
+    expect(result.stdout, contains('compile '));
     expect(result.stdout, contains('format '));
     expect(result.stdout, contains('migrate '));
   });
diff --git a/pkg/dartdev/test/commands/format_test.dart b/pkg/dartdev/test/commands/format_test.dart
index 15dd356..1b68d98 100644
--- a/pkg/dartdev/test/commands/format_test.dart
+++ b/pkg/dartdev/test/commands/format_test.dart
@@ -71,7 +71,7 @@
 
   test('unknown file', () {
     p = project(mainSrc: 'int get foo => 1;\n');
-    var unknownFilePath = p.relativeFilePath + '-unknown-file.dart';
+    var unknownFilePath = '${p.relativeFilePath}-unknown-file.dart';
     ProcessResult result = p.runSync('format', [unknownFilePath]);
     expect(result.exitCode, 0);
     expect(result.stderr,
diff --git a/pkg/dartdev/test/commands/run_test.dart b/pkg/dartdev/test/commands/run_test.dart
index fcec9f5..e6b8931 100644
--- a/pkg/dartdev/test/commands/run_test.dart
+++ b/pkg/dartdev/test/commands/run_test.dart
@@ -39,7 +39,7 @@
   test('no such file', () {
     p = project(mainSrc: "void main() { print('Hello World'); }");
     ProcessResult result =
-        p.runSync('run', ['no/such/file/' + p.relativeFilePath]);
+        p.runSync('run', ['no/such/file/${p.relativeFilePath}']);
 
     expect(result.stderr, isNotEmpty);
     expect(result.exitCode, isNot(0));
diff --git a/pkg/dartdev/test/core_test.dart b/pkg/dartdev/test/core_test.dart
index 23cab3c..6384d9b 100644
--- a/pkg/dartdev/test/core_test.dart
+++ b/pkg/dartdev/test/core_test.dart
@@ -48,7 +48,7 @@
   });
 }
 
-final String _packageData = '''{
+const String _packageData = '''{
   "configVersion": 2,
   "packages": [
     {
diff --git a/pkg/dartdev/test/sdk_test.dart b/pkg/dartdev/test/sdk_test.dart
index 8bf7ed9..2fcb0ca 100644
--- a/pkg/dartdev/test/sdk_test.dart
+++ b/pkg/dartdev/test/sdk_test.dart
@@ -21,7 +21,7 @@
   });
 
   test('analysis_server_snapshot', () {
-    expectFileExists(Sdk().analysis_server_snapshot);
+    expectFileExists(Sdk().analysisServerSnapshot);
   });
 
   test('dartfmt', () {
diff --git a/pkg/dartdev/test/test_all.dart b/pkg/dartdev/test/test_all.dart
index 8811904..153ebb9 100644
--- a/pkg/dartdev/test/test_all.dart
+++ b/pkg/dartdev/test/test_all.dart
@@ -6,6 +6,7 @@
 
 import 'analytics_test.dart' as analytics;
 import 'commands/analyze_test.dart' as analyze;
+import 'commands/compile_test.dart' as compile;
 import 'commands/create_test.dart' as create;
 import 'commands/flag_test.dart' as flag;
 import 'commands/format_test.dart' as format;
@@ -18,7 +19,7 @@
 import 'sdk_test.dart' as sdk;
 import 'utils_test.dart' as utils;
 
-main() {
+void main() {
   group('dart', () {
     analytics.main();
     analyze.main();
@@ -29,6 +30,7 @@
     migrate.main();
     pub.main();
     run.main();
+    compile.main();
     test.main();
     core.main();
     sdk.main();
diff --git a/pkg/dartdev/test/utils.dart b/pkg/dartdev/test/utils.dart
index c1fdab7..7fd5c73 100644
--- a/pkg/dartdev/test/utils.dart
+++ b/pkg/dartdev/test/utils.dart
@@ -12,9 +12,8 @@
 /// invocation requires the VM to compile the entire dependency graph.
 const Timeout longTimeout = Timeout(Duration(minutes: 5));
 
-TestProject project({String mainSrc, String analysisOptions}) {
-  return TestProject(mainSrc: mainSrc, analysisOptions: analysisOptions);
-}
+TestProject project({String mainSrc, String analysisOptions}) =>
+    TestProject(mainSrc: mainSrc, analysisOptions: analysisOptions);
 
 class TestProject {
   static String get defaultProjectName => 'dartdev_temp';
@@ -94,9 +93,8 @@
     return _sdkRootPath;
   }
 
-  String get absolutePathToDartdevFile {
-    return path.join(sdkRootPath, 'pkg', 'dartdev', 'bin', 'dartdev.dart');
-  }
+  String get absolutePathToDartdevFile =>
+      path.join(sdkRootPath, 'pkg', 'dartdev', 'bin', 'dartdev.dart');
 
   File findFile(String name) {
     var file = File(path.join(dir.path, name));
diff --git a/pkg/dartdev/test/utils_test.dart b/pkg/dartdev/test/utils_test.dart
index 489348c..1a579c8 100644
--- a/pkg/dartdev/test/utils_test.dart
+++ b/pkg/dartdev/test/utils_test.dart
@@ -90,7 +90,7 @@
   });
 }
 
-final String _packageData = '''{
+const String _packageData = '''{
   "configVersion": 2,
   "packages": [
     {
diff --git a/pkg/dev_compiler/lib/src/compiler/module_builder.dart b/pkg/dev_compiler/lib/src/compiler/module_builder.dart
index ce17c8c..dd1cc90 100644
--- a/pkg/dev_compiler/lib/src/compiler/module_builder.dart
+++ b/pkg/dev_compiler/lib/src/compiler/module_builder.dart
@@ -191,7 +191,7 @@
     }
 
     var resultModule = NamedFunction(
-        loadFunctionName(module.name),
+        loadFunctionIdentifier(module.name),
         js.fun("function(#) { 'use strict'; #; }", [parameters, statements]),
         true);
 
@@ -299,7 +299,7 @@
       statements.add(Return(ObjectInitializer(exportedProps, multiline: true)));
     }
     var resultModule = NamedFunction(
-        loadFunctionName(module.name),
+        loadFunctionIdentifier(module.name),
         js.fun("function(#) { 'use strict'; #; }", [fnParams, statements]),
         true);
     var block = js.statement(
@@ -309,6 +309,17 @@
   }
 }
 
+bool isSdkInternalRuntimeUri(Uri importUri) {
+  return importUri.scheme == 'dart' && importUri.path == '_runtime';
+}
+
+String libraryUriToJsIdentifier(Uri importUri) {
+  if (importUri.scheme == 'dart') {
+    return isSdkInternalRuntimeUri(importUri) ? 'dart' : importUri.path;
+  }
+  return pathToJSIdentifier(p.withoutExtension(importUri.pathSegments.last));
+}
+
 /// Converts an entire arbitrary path string into a string compatible with
 /// JS identifier naming rules while conserving path information.
 ///
@@ -327,9 +338,13 @@
       .replaceAll('-', '_'));
 }
 
+/// Creates function name given [moduleName].
+String loadFunctionName(String moduleName) =>
+    'load__' + pathToJSIdentifier(moduleName.replaceAll('.', '_'));
+
 /// Creates function name identifier given [moduleName].
-Identifier loadFunctionName(String moduleName) =>
-    Identifier('load__' + pathToJSIdentifier(moduleName.replaceAll('.', '_')));
+Identifier loadFunctionIdentifier(String moduleName) =>
+    Identifier(loadFunctionName(moduleName));
 
 // Replacement string for path separators (i.e., '/', '\', '..').
 final encodedSeparator = '__';
diff --git a/pkg/dev_compiler/lib/src/compiler/shared_command.dart b/pkg/dev_compiler/lib/src/compiler/shared_command.dart
index f1b8d93..1b7b01e 100644
--- a/pkg/dev_compiler/lib/src/compiler/shared_command.dart
+++ b/pkg/dev_compiler/lib/src/compiler/shared_command.dart
@@ -61,6 +61,13 @@
   /// runtime can enable synchronous stack trace deobsfuscation.
   final bool inlineSourceMap;
 
+  /// Whether to emit the debug metadata
+  ///
+  /// Debugger uses this information about to construct mapping between
+  /// modules and libraries that otherwise requires expensive communication with
+  /// the browser.
+  final bool emitDebugMetadata;
+
   /// Whether to emit a summary file containing API signatures.
   ///
   /// This is required for a modular build process.
@@ -99,6 +106,7 @@
       this.summarizeApi = true,
       this.enableAsserts = true,
       this.replCompile = false,
+      this.emitDebugMetadata = false,
       this.summaryModules = const {},
       this.moduleFormats = const [],
       this.experiments = const {},
@@ -119,32 +127,34 @@
             moduleFormats: parseModuleFormatOption(args),
             moduleName: _getModuleName(args, moduleRoot),
             replCompile: args['repl-compile'] as bool,
-            soundNullSafety: args['sound-null-safety'] as bool);
+            soundNullSafety: args['sound-null-safety'] as bool,
+            emitDebugMetadata:
+                args['experimental-emit-debug-metadata'] as bool);
 
   static void addArguments(ArgParser parser, {bool hide = true}) {
     addModuleFormatOptions(parser, hide: hide);
 
     parser
+      ..addMultiOption('out', abbr: 'o', help: 'Output file (required).')
       ..addMultiOption('summary',
           abbr: 's',
-          help: 'summary file(s) of imported libraries, optionally\n'
-              'with module import path: -s path.sum=js/import/path')
+          help: 'API summary file(s) of imported libraries, optionally\n'
+              'with module import path: -s path.dill=js/import/path')
       ..addMultiOption('enable-experiment',
-          help: 'used to enable/disable experimental language features',
-          hide: hide)
+          help: 'Enable/disable experimental language features.', hide: hide)
       ..addFlag('summarize',
-          help: 'emit an API summary file', defaultsTo: true, hide: hide)
+          help: 'Emit an API summary file.', defaultsTo: true, hide: hide)
       ..addFlag('source-map',
-          help: 'emit source mapping', defaultsTo: true, hide: hide)
+          help: 'Emit source mapping.', defaultsTo: true, hide: hide)
       ..addFlag('inline-source-map',
-          help: 'emit source mapping inline', defaultsTo: false, hide: hide)
+          help: 'Emit source mapping inline.', defaultsTo: false, hide: hide)
       ..addFlag('enable-asserts',
-          help: 'enable assertions', defaultsTo: true, hide: hide)
+          help: 'Enable assertions.', defaultsTo: true, hide: hide)
       ..addOption('module-name',
           help: 'The output module name, used in some JS module formats.\n'
               'Defaults to the output file name (without .js).')
       ..addFlag('repl-compile',
-          help: 'compile in a more permissive REPL mode, allowing access'
+          help: 'Compile in a more permissive REPL mode, allowing access'
               ' to private members across library boundaries. This should'
               ' only be used by debugging tools.',
           defaultsTo: false,
@@ -152,7 +162,21 @@
       ..addFlag('sound-null-safety',
           help: 'Compile for sound null safety at runtime.',
           negatable: true,
-          defaultsTo: false);
+          defaultsTo: false)
+      ..addOption('multi-root-scheme',
+          help: 'The custom scheme to indicate a multi-root uri.',
+          defaultsTo: 'org-dartlang-app')
+      ..addOption('multi-root-output-path',
+          help: 'Path to set multi-root files relative to when generating'
+              ' source-maps.',
+          hide: true)
+      // TODO(41852) Define a process for breaking changes before graduating from
+      // experimental.
+      ..addFlag('experimental-emit-debug-metadata',
+          help: 'Experimental option for compiler development.\n'
+              'Output a metadata file for debug tools next to the .js output.',
+          defaultsTo: false,
+          hide: true);
   }
 
   static String _getModuleName(ArgResults args, String moduleRoot) {
diff --git a/pkg/dev_compiler/lib/src/kernel/command.dart b/pkg/dev_compiler/lib/src/kernel/command.dart
index c968376..c764b0f 100644
--- a/pkg/dev_compiler/lib/src/kernel/command.dart
+++ b/pkg/dev_compiler/lib/src/kernel/command.dart
@@ -27,6 +27,7 @@
 import '../js_ast/js_ast.dart' show js;
 import '../js_ast/source_map_printer.dart' show SourceMapPrintingContext;
 import 'compiler.dart';
+import 'module_metadata.dart';
 import 'target.dart';
 
 const _binaryName = 'dartdevc -k';
@@ -80,27 +81,21 @@
   var argParser = ArgParser(allowTrailingOptions: true)
     ..addFlag('help',
         abbr: 'h', help: 'Display this message.', negatable: false)
-    ..addMultiOption('out', abbr: 'o', help: 'Output file (required).')
     ..addOption('packages', help: 'The package spec file to use.')
     // TODO(jmesserly): is this still useful for us, or can we remove it now?
     ..addFlag('summarize-text',
-        help: 'emit API summary in a .js.txt file',
+        help: 'Emit API summary in a .js.txt file.',
         defaultsTo: false,
         hide: true)
     ..addFlag('track-widget-creation',
-        help: 'enable inspecting of Flutter widgets', hide: true)
+        help: 'Enable inspecting of Flutter widgets.', hide: true)
     // TODO(jmesserly): add verbose help to show hidden options
     ..addOption('dart-sdk-summary',
         help: 'The path to the Dart SDK summary file.', hide: true)
-    ..addOption('multi-root-scheme',
-        help: 'The custom scheme to indicate a multi-root uri.',
-        defaultsTo: 'org-dartlang-app')
     ..addMultiOption('multi-root',
         help: 'The directories to search when encountering uris with the '
             'specified multi-root scheme.',
         defaultsTo: [Uri.base.path])
-    ..addOption('multi-root-output-path',
-        help: 'Path to set multi-root files relative to.', hide: true)
     ..addOption('dart-sdk',
         help: '(unsupported with --kernel) path to the Dart SDK.', hide: true)
     ..addFlag('compile-sdk',
@@ -109,13 +104,6 @@
         help: 'The path to the libraries.json file for the sdk.')
     ..addOption('used-inputs-file',
         help: 'If set, the file to record inputs used.', hide: true)
-    // TODO(41852) Define a process for breaking changes before graduating from
-    // experimental.
-    ..addFlag('experimental-emit-debug-metadata',
-        help: 'Experimental option for compiler development.\n'
-            'Output a metadata file for debug tools next to the .js output.',
-        defaultsTo: false,
-        hide: true)
     ..addFlag('kernel',
         abbr: 'k',
         help: 'Deprecated and ignored. To be removed in a future release.',
@@ -214,6 +202,11 @@
     throw StateError('Non-dill file detected in input: $summaryPaths');
   }
 
+  var inputs = [for (var arg in argResults.rest) sourcePathToCustomUri(arg)];
+  if (inputs.length == 1 && inputs.single.path.endsWith('.dill')) {
+    return compileSdkFromDill(args);
+  }
+
   if (librarySpecPath == null) {
     // TODO(jmesserly): the `isSupported` bit should be included in the SDK
     // summary, but front_end requires a separate file, so we have to work
@@ -245,8 +238,6 @@
   // This needs further investigation.
   var packageFile = argResults['packages'] as String ?? _findPackagesFilePath();
 
-  var inputs = argResults.rest.map(sourcePathToCustomUri).toList();
-
   var succeeded = true;
   void diagnosticMessageHandler(fe.DiagnosticMessage message) {
     if (message.severity == fe.Severity.error) {
@@ -268,6 +259,7 @@
   fe.WorkerInputComponent cachedSdkInput;
   var recordUsedInputs = argResults['used-inputs-file'] != null;
   var additionalDills = summaryModules.keys.toList();
+
   if (!useIncrementalCompiler) {
     compilerState = await fe.initializeCompiler(
         oldCompilerState,
@@ -425,6 +417,7 @@
     var jsCode = jsProgramToCode(jsModule, moduleFormat,
         buildSourceMap: options.sourceMap,
         inlineSourceMap: options.inlineSourceMap,
+        emitDebugMetadata: options.emitDebugMetadata,
         jsUrl: p.toUri(output).toString(),
         mapUrl: mapUrl,
         customScheme: multiRootScheme,
@@ -436,21 +429,9 @@
       outFiles.add(
           File('$output.map').writeAsString(json.encode(jsCode.sourceMap)));
     }
-
-    if (argResults['experimental-emit-debug-metadata'] as bool) {
-      var moduleMetadata = [
-        for (var lib in compiledLibraries.libraries)
-          {
-            'name': compiler.jsLibraryName(lib),
-            'sourceMapFileUri': mapUrl,
-            'dartFileUris': [
-              lib.fileUri.toString(),
-              ...lib.parts.map((p) => p.partUri.toString())
-            ],
-          }
-      ];
+    if (jsCode.metadata != null) {
       outFiles.add(
-          File('$output.metadata').writeAsString(json.encode(moduleMetadata)));
+          File('$output.metadata').writeAsString(json.encode(jsCode.metadata)));
     }
   }
 
@@ -487,13 +468,7 @@
 // well.
 // TODO(sigmund): refactor the underlying pieces to reduce the code duplication.
 Future<CompilerResult> compileSdkFromDill(List<String> args) async {
-  var argParser = ArgParser(allowTrailingOptions: true)
-    ..addMultiOption('out', abbr: 'o', help: 'Output file (required).')
-    ..addOption('multi-root-scheme', defaultsTo: 'org-dartlang-sdk')
-    ..addOption('multi-root-output-path',
-        help: 'Path to set multi-root files relative to when generating'
-            ' source-maps.',
-        hide: true);
+  var argParser = ArgParser(allowTrailingOptions: true);
   SharedCompilerOptions.addArguments(argParser);
 
   ArgResults argResults;
@@ -505,6 +480,18 @@
     return CompilerResult(64);
   }
 
+  var inputs = argResults.rest.toList();
+  if (inputs.length != 1) {
+    print('Only a single input file is supported to compile the sdk from dill'
+        'but found: \n${inputs.join('\n')}');
+    return CompilerResult(64);
+  }
+
+  if (!inputs.single.endsWith('.dill')) {
+    print('Input must be a .dill file: ${inputs.single}');
+    return CompilerResult(64);
+  }
+
   var outPaths = argResults['out'] as List<String>;
   var moduleFormats = parseModuleFormatOption(argResults);
   if (outPaths.isEmpty) {
@@ -517,7 +504,19 @@
     return CompilerResult(64);
   }
 
-  var component = loadComponentFromBinary(argResults.rest[0]);
+  var component = loadComponentFromBinary(inputs.single);
+  var invalidLibraries = <Uri>[];
+  for (var library in component.libraries) {
+    if (library.importUri.scheme != 'dart') {
+      invalidLibraries.add(library.importUri);
+    }
+  }
+
+  if (invalidLibraries.isNotEmpty) {
+    print('Only the SDK libraries can be compiled from .dill but found:\n'
+        '${invalidLibraries.join('\n')}');
+    return CompilerResult(64);
+  }
   var coreTypes = CoreTypes(component);
   var hierarchy = ClassHierarchy(component, coreTypes);
   var multiRootScheme = argResults['multi-root-scheme'] as String;
@@ -598,7 +597,14 @@
   /// using [placeSourceMap].
   final Map sourceMap;
 
-  JSCode(this.code, this.sourceMap);
+  /// Module and library information
+  ///
+  /// The [metadata] is a contract between compiler and the debugger,
+  /// helping the debugger map between libraries, modules, source paths.
+  /// see: https://goto.google.com/dart-web-debugger-metadata
+  final ModuleMetadata metadata;
+
+  JSCode(this.code, this.sourceMap, {this.metadata});
 }
 
 /// Converts [moduleTree] to [JSCode], using [format].
@@ -608,6 +614,7 @@
 JSCode jsProgramToCode(js_ast.Program moduleTree, ModuleFormat format,
     {bool buildSourceMap = false,
     bool inlineSourceMap = false,
+    bool emitDebugMetadata = false,
     String jsUrl,
     String mapUrl,
     String sourceMapBase,
@@ -666,7 +673,27 @@
   };
   text = text.replaceFirst(
       SharedCompiler.metricsLocationID, '$compileTimeStatistics');
-  return JSCode(text, builtMap);
+
+  var debugMetadata = emitDebugMetadata
+      ? _emitMetadata(moduleTree, component, mapUrl, jsUrl)
+      : null;
+
+  return JSCode(text, builtMap, metadata: debugMetadata);
+}
+
+ModuleMetadata _emitMetadata(js_ast.Program program, Component component,
+    String sourceMapUri, String moduleUri) {
+  var metadata = ModuleMetadata(
+      program.name, loadFunctionName(program.name), sourceMapUri, moduleUri);
+
+  for (var lib in component.libraries) {
+    metadata.addLibrary(LibraryMetadata(
+        libraryUriToJsIdentifier(lib.importUri),
+        lib.importUri.toString(),
+        lib.fileUri.toString(),
+        [...lib.parts.map((p) => p.partUri)]));
+  }
+  return metadata;
 }
 
 /// Parses Dart's non-standard `-Dname=value` syntax for declared variables,
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index d7fcce0..0e7f31e 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -17,7 +17,8 @@
 
 import '../compiler/js_names.dart' as js_ast;
 import '../compiler/js_utils.dart' as js_ast;
-import '../compiler/module_builder.dart' show pathToJSIdentifier;
+import '../compiler/module_builder.dart'
+    show isSdkInternalRuntimeUri, libraryUriToJsIdentifier, pathToJSIdentifier;
 import '../compiler/shared_command.dart' show SharedCompilerOptions;
 import '../compiler/shared_compiler.dart';
 import '../js_ast/js_ast.dart' as js_ast;
@@ -371,11 +372,7 @@
 
   @override
   String jsLibraryName(Library library) {
-    var uri = library.importUri;
-    if (uri.scheme == 'dart') {
-      return isSdkInternalRuntime(library) ? 'dart' : uri.path;
-    }
-    return pathToJSIdentifier(p.withoutExtension(uri.pathSegments.last));
+    return libraryUriToJsIdentifier(library.importUri);
   }
 
   @override
@@ -405,8 +402,7 @@
 
   @override
   bool isSdkInternalRuntime(Library l) {
-    var uri = l.importUri;
-    return uri.scheme == 'dart' && uri.path == '_runtime';
+    return isSdkInternalRuntimeUri(l.importUri);
   }
 
   @override
diff --git a/pkg/dev_compiler/lib/src/kernel/module_metadata.dart b/pkg/dev_compiler/lib/src/kernel/module_metadata.dart
new file mode 100644
index 0000000..7286843
--- /dev/null
+++ b/pkg/dev_compiler/lib/src/kernel/module_metadata.dart
@@ -0,0 +1,173 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// Module metadata format version
+///
+/// Module reader always creates the current version but is able to read
+/// metadata files with later versions as long as the changes are backward
+/// compatible, i.e. only minor or patch versions have changed.
+///
+/// See: https://goto.google.com/dart-web-debugger-metadata
+class ModuleMetadataVersion {
+  final int majorVersion;
+  final int minorVersion;
+  final int patchVersion;
+
+  const ModuleMetadataVersion(
+    this.majorVersion,
+    this.minorVersion,
+    this.patchVersion,
+  );
+
+  /// Current metadata version
+  ///
+  /// Version follows simple semantic versioning format 'major.minor.patch'
+  /// See https://semver.org
+  ///
+  /// TODO(annagrin): create metadata package, make version the same as the
+  /// metadata package version, automate updating with the package update
+  static const ModuleMetadataVersion current = ModuleMetadataVersion(1, 0, 0);
+
+  /// Current metadata version created by the reader
+  String get version => '$majorVersion.$minorVersion.$patchVersion';
+
+  /// Is this metadata version compatible with the given version
+  ///
+  /// The minor and patch version changes never remove any fields that current
+  /// version supports, so the reader can create current metadata version from
+  /// any file created with a later reader, as long as the major version does
+  /// not change.
+  bool isCompatibleWith(String version) {
+    var parts = version.split('.');
+    if (parts.length != 3) {
+      throw FormatException('Version: $version'
+          'does not follow simple semantic versioning format');
+    }
+    var major = int.parse(parts[0]);
+    var minor = int.parse(parts[1]);
+    var patch = int.parse(parts[2]);
+    return major == majorVersion &&
+        minor >= minorVersion &&
+        patch >= patchVersion;
+  }
+}
+
+/// Library metadata
+///
+/// Represents library metadata used in the debugger,
+/// supports reading from and writing to json
+/// See: https://goto.google.com/dart-web-debugger-metadata
+class LibraryMetadata {
+  /// Library name as defined in pubspec.yaml
+  final String name;
+
+  /// Library importUri
+  ///
+  /// Example package:path/path.dart
+  final String importUri;
+
+  /// Library fileUri
+  ///
+  /// Example file:///path/to/path/path.dart
+  final String fileUri;
+
+  /// All file uris from the library
+  ///
+  /// Can be relative paths to the directory of the fileUri
+  final List<String> partUris;
+
+  LibraryMetadata(this.name, this.importUri, this.fileUri, this.partUris);
+
+  LibraryMetadata.fromJson(Map<String, dynamic> json)
+      : name = json['name'] as String,
+        importUri = json['importUri'] as String,
+        fileUri = json['fileUri'] as String,
+        partUris =
+            List.castFrom<dynamic, String>(json['partUris'] as List<dynamic>);
+
+  Map<String, dynamic> toJson() {
+    return {
+      'name': name,
+      'importUri': importUri,
+      'fileUri': fileUri,
+      'partUris': [...partUris]
+    };
+  }
+}
+
+/// Module metadata
+///
+/// Represents module metadata used in the debugger,
+/// supports reading from and writing to json
+/// See: https://goto.google.com/dart-web-debugger-metadata
+class ModuleMetadata {
+  /// Metadata format version
+  String version;
+
+  /// Module name
+  ///
+  /// Used as a name of the js module created by the compiler and
+  /// as key to store and load modules in the debugger and the browser
+  final String name;
+
+  /// Name of the function enclosing the module
+  ///
+  /// Used by debugger to determine the top dart scope
+  final String closureName;
+
+  /// Source map uri
+  final String sourceMapUri;
+
+  /// Module uri
+  final String moduleUri;
+
+  final Map<String, LibraryMetadata> libraries = {};
+
+  ModuleMetadata(this.name, this.closureName, this.sourceMapUri, this.moduleUri,
+      {this.version}) {
+    version ??= ModuleMetadataVersion.current.version;
+  }
+
+  /// Add [library] to metadata
+  ///
+  /// Used for filling the metadata in the compiler or for reading from
+  /// stored metadata files.
+  void addLibrary(LibraryMetadata library) {
+    if (!libraries.containsKey(library.importUri)) {
+      libraries[library.importUri] = library;
+    } else {
+      throw ('Metadata creation error: '
+          'Cannot add library $library with uri ${library.importUri}: '
+          'another library "${libraries[library.importUri]}" is found '
+          'with the same uri');
+    }
+  }
+
+  ModuleMetadata.fromJson(Map<String, dynamic> json)
+      : version = json['version'] as String,
+        name = json['name'] as String,
+        closureName = json['closureName'] as String,
+        sourceMapUri = json['sourceMapUri'] as String,
+        moduleUri = json['moduleUri'] as String {
+    var fileVersion = json['version'] as String;
+    if (!ModuleMetadataVersion.current.isCompatibleWith(version)) {
+      throw Exception('Unsupported metadata version $fileVersion');
+    }
+
+    for (var l in json['libraries'] as List<dynamic>) {
+      addLibrary(LibraryMetadata.fromJson(l as Map<String, dynamic>));
+    }
+  }
+
+  Map<String, dynamic> toJson() {
+    return {
+      'version': version,
+      'name': name,
+      'closureName': closureName,
+      'sourceMapUri': sourceMapUri,
+      'moduleUri': moduleUri,
+      'libraries': [for (var lib in libraries.values) lib.toJson()]
+    };
+  }
+}
diff --git a/pkg/dev_compiler/pubspec.yaml b/pkg/dev_compiler/pubspec.yaml
index 4dc3d73..a4e9b89 100644
--- a/pkg/dev_compiler/pubspec.yaml
+++ b/pkg/dev_compiler/pubspec.yaml
@@ -1,4 +1,5 @@
 name: dev_compiler
+# This package is not intended for consumption on pub.dev. DO NOT publish.
 publish_to: none
 
 environment:
diff --git a/pkg/dev_compiler/test/module_metadata_test.dart b/pkg/dev_compiler/test/module_metadata_test.dart
new file mode 100644
index 0000000..93f9d7b
--- /dev/null
+++ b/pkg/dev_compiler/test/module_metadata_test.dart
@@ -0,0 +1,135 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:convert';
+import 'dart:io';
+
+import 'package:dev_compiler/src/kernel/module_metadata.dart';
+import 'package:test/test.dart';
+
+// Test creating, reading and writing debugger metadata
+void main() {
+  group('Module metadata', () {
+    Directory tempDir;
+    File file;
+
+    setUpAll(() {
+      var systemTempDir = Directory.systemTemp;
+      tempDir = systemTempDir.createTempSync('foo bar');
+      var input = tempDir.uri.resolve('module.metadata');
+      file = File.fromUri(input)..createSync();
+    });
+
+    tearDownAll(() {
+      tempDir.delete(recursive: true);
+    });
+
+    test('create, write, and read', () async {
+      // create metadata
+      var version = ModuleMetadataVersion.current.version;
+      var module = createMetadata(version);
+      testMetadataFields(module, version);
+
+      // write metadata
+      file.writeAsBytesSync(utf8.encode(json.encode(module)));
+      expect(file.existsSync(), true);
+
+      // read metadata
+      var moduleJson = json.decode(utf8.decode(file.readAsBytesSync()));
+      var newModule =
+          ModuleMetadata.fromJson(moduleJson as Map<String, dynamic>);
+      testMetadataFields(newModule, version);
+    });
+
+    test('read later backward-compatible patch version', () async {
+      // create metadata with next patch version
+      var version = ModuleMetadataVersion(
+              ModuleMetadataVersion.current.majorVersion,
+              ModuleMetadataVersion.current.minorVersion,
+              ModuleMetadataVersion.current.patchVersion + 1)
+          .version;
+
+      var module = createMetadata(version);
+
+      // write metadata
+      file.writeAsBytesSync(utf8.encode(json.encode(module)));
+      expect(file.existsSync(), true);
+
+      // read metadata
+      var moduleJson = json.decode(utf8.decode(file.readAsBytesSync()));
+      var newModule =
+          ModuleMetadata.fromJson(moduleJson as Map<String, dynamic>);
+      testMetadataFields(newModule, version);
+    });
+
+    test('read later backward-compatible minor version', () async {
+      // create metadata with next minor version
+      var version = ModuleMetadataVersion(
+              ModuleMetadataVersion.current.majorVersion,
+              ModuleMetadataVersion.current.minorVersion + 1,
+              ModuleMetadataVersion.current.patchVersion + 1)
+          .version;
+      var module = createMetadata(version);
+
+      // write metadata
+      file.writeAsBytesSync(utf8.encode(json.encode(module)));
+      expect(file.existsSync(), true);
+
+      // read metadata
+      var moduleJson = json.decode(utf8.decode(file.readAsBytesSync()));
+      var newModule =
+          ModuleMetadata.fromJson(moduleJson as Map<String, dynamic>);
+      testMetadataFields(newModule, version);
+    });
+
+    test('fail to read later non-backward-compatible major version', () async {
+      // create metadata with next minor version
+      var version = ModuleMetadataVersion(
+              ModuleMetadataVersion.current.majorVersion + 1,
+              ModuleMetadataVersion.current.minorVersion + 1,
+              ModuleMetadataVersion.current.patchVersion + 1)
+          .version;
+      var module = createMetadata(version);
+
+      // write metadata
+      file.writeAsBytesSync(utf8.encode(json.encode(module)));
+      expect(file.existsSync(), true);
+
+      // try read metadata, expect to fail
+      var moduleJson = json.decode(utf8.decode(file.readAsBytesSync()));
+      ModuleMetadata newModule;
+      try {
+        newModule = ModuleMetadata.fromJson(moduleJson as Map<String, dynamic>);
+      } catch (e) {
+        expect(
+            e.toString(), 'Exception: Unsupported metadata version $version');
+      }
+
+      expect(newModule, null);
+    });
+  });
+}
+
+ModuleMetadata createMetadata(String version) => ModuleMetadata(
+    'module', 'closure', 'module.map', 'module.js', version: version)
+  ..addLibrary(LibraryMetadata('library', 'package:library/test.dart',
+      'file:///source/library/lib/test.dart', ['src/test2.dart']));
+
+void testMetadataFields(ModuleMetadata module, String version) {
+  // reader always creates current metadata version
+  expect(module.version, version);
+  expect(module.name, 'module');
+  expect(module.closureName, 'closure');
+  expect(module.sourceMapUri, 'module.map');
+  expect(module.moduleUri, 'module.js');
+
+  var libUri = module.libraries.keys.first;
+  var lib = module.libraries[libUri];
+
+  expect(libUri, 'package:library/test.dart');
+  expect(lib.name, 'library');
+  expect(lib.importUri, 'package:library/test.dart');
+  expect(lib.fileUri, 'file:///source/library/lib/test.dart');
+  expect(lib.partUris[0], 'src/test2.dart');
+}
diff --git a/pkg/diagnostic/pubspec.yaml b/pkg/diagnostic/pubspec.yaml
index 98411d4..b42e69b 100644
--- a/pkg/diagnostic/pubspec.yaml
+++ b/pkg/diagnostic/pubspec.yaml
@@ -1,4 +1,5 @@
 name: diagnostic
+# This package is not intended for consumption on pub.dev. DO NOT publish.
 publish_to: none
 author: Dart Team <misc@dartlang.org>
 description: Diagnostics for Dart
diff --git a/pkg/expect/pubspec.yaml b/pkg/expect/pubspec.yaml
index 595d26c..60226bb 100644
--- a/pkg/expect/pubspec.yaml
+++ b/pkg/expect/pubspec.yaml
@@ -1,4 +1,5 @@
 name: expect
+# This package is not intended for consumption on pub.dev. DO NOT publish.
 publish_to: none
 description: >
  Expect is used for tests that do not want to make use of the
diff --git a/pkg/front_end/lib/src/fasta/builder/class_builder.dart b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
index 1bfd961..7dcfad3 100644
--- a/pkg/front_end/lib/src/fasta/builder/class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
@@ -1252,7 +1252,9 @@
           declaredParameter.isCovariant,
           declaredParameter,
           isInterfaceCheck);
-      if (declaredParameter.isRequired &&
+      if (declaredMember.isNonNullableByDefault &&
+          declaredParameter.isRequired &&
+          interfaceMember.isNonNullableByDefault &&
           !interfaceNamedParameters.current.isRequired) {
         reportInvalidOverride(
             isInterfaceCheck,
diff --git a/pkg/front_end/lib/src/fasta/builder/field_builder.dart b/pkg/front_end/lib/src/fasta/builder/field_builder.dart
index 81af315..a04c39f 100644
--- a/pkg/front_end/lib/src/fasta/builder/field_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/field_builder.dart
@@ -392,7 +392,7 @@
       }
       if (needsCheckVisitor != null) {
         if (fieldType.accept(needsCheckVisitor)) {
-          field.isGenericCovariantImpl = true;
+          _fieldEncoding.setGenericCovariantImpl();
         }
       }
     }
@@ -843,9 +843,11 @@
 
   @override
   void setGenericCovariantImpl() {
-    // TODO(johnniwinther): Is this correct? Should the [_lateSetter] be
-    //  annotated instead?
     _field.isGenericCovariantImpl = true;
+    if (_lateSetter != null) {
+      _lateSetter.function.positionalParameters.single.isGenericCovariantImpl =
+          true;
+    }
   }
 
   @override
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index 2d1f0a2..12b828d 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -317,6 +317,16 @@
   /// invocations are to be resolved in a separate step.
   final List<Expression> redirectingFactoryInvocations = <Expression>[];
 
+  /// List of built type aliased generative constructor invocations that
+  /// require unaliasing.
+  final List<ConstructorInvocation> typeAliasedConstructorInvocations =
+      <ConstructorInvocation>[];
+
+  /// List of built type aliased factory constructor invocations that require
+  /// unaliasing.
+  final List<StaticInvocation> typeAliasedFactoryInvocations =
+      <StaticInvocation>[];
+
   /// Variables with metadata.  Their types need to be inferred late, for
   /// example, in [finishFunction].
   List<VariableDeclaration> variablesWithMetadata;
@@ -1129,7 +1139,14 @@
     return true;
   }
 
+  // TODO(eernst): Rename this method now that it handles more tasks.
   void resolveRedirectingFactoryTargets() {
+    _unaliasTypeAliasedConstructorInvocations();
+    _unaliasTypeAliasedFactoryInvocations();
+    _resolveRedirectingFactoryTargets();
+  }
+
+  void _resolveRedirectingFactoryTargets() {
     for (StaticInvocation invocation in redirectingFactoryInvocations) {
       // If the invocation was invalid, it or its parent has already been
       // desugared into an exception throwing expression.  There is nothing to
@@ -1221,6 +1238,25 @@
     redirectingFactoryInvocations.clear();
   }
 
+  void _unaliasTypeAliasedConstructorInvocations() {
+    for (ConstructorInvocation invocation
+        in typeAliasedConstructorInvocations) {
+      // TODO(eernst): Should replace aliased constructor invocations,
+      // such that back ends don't see instance creations on type aliases.
+      invocation.replaceWith(new NullLiteral());
+    }
+    typeAliasedConstructorInvocations.clear();
+  }
+
+  void _unaliasTypeAliasedFactoryInvocations() {
+    for (StaticInvocation invocation in typeAliasedFactoryInvocations) {
+      // TODO(eernst): Should replace aliased factory invocations,
+      // such that back ends don't see instance creations on type aliases.
+      invocation.replaceWith(new NullLiteral());
+    }
+    typeAliasedFactoryInvocations.clear();
+  }
+
   void finishVariableMetadata() {
     List<VariableDeclaration> variablesWithMetadata =
         this.variablesWithMetadata;
@@ -3907,6 +3943,7 @@
   @override
   Expression buildStaticInvocation(Member target, Arguments arguments,
       {Constness constness: Constness.implicit,
+      TypeAliasBuilder typeAliasBuilder,
       int charOffset: -1,
       int charLength: noLength}) {
     // The argument checks for the initial target of redirecting factories
@@ -3935,11 +3972,21 @@
         return buildProblem(
             fasta.messageNonConstConstructor, charOffset, charLength);
       }
-      ConstructorInvocation node =
-          new ConstructorInvocation(target, arguments, isConst: isConst)
-            ..fileOffset = charOffset;
-      libraryBuilder.checkBoundsInConstructorInvocation(
-          node, typeEnvironment, uri);
+      ConstructorInvocation node;
+      if (typeAliasBuilder == null) {
+        node = new ConstructorInvocation(target, arguments, isConst: isConst)
+          ..fileOffset = charOffset;
+        libraryBuilder.checkBoundsInConstructorInvocation(
+            node, typeEnvironment, uri);
+      } else {
+        node = new TypeAliasedConstructorInvocationJudgment(
+            typeAliasBuilder, target, arguments,
+            isConst: isConst)
+          ..fileOffset = charOffset;
+        // No type arguments were passed, so we need not check bounds.
+        assert(arguments.types.isEmpty);
+        typeAliasedConstructorInvocations.add(node);
+      }
       return node;
     } else {
       Procedure procedure = target;
@@ -3952,12 +3999,22 @@
           return buildProblem(
               fasta.messageNonConstFactory, charOffset, charLength);
         }
-        StaticInvocation node = new FactoryConstructorInvocationJudgment(
-            target, arguments,
-            isConst: isConst)
-          ..fileOffset = charOffset;
-        libraryBuilder.checkBoundsInFactoryInvocation(
-            node, typeEnvironment, uri);
+        StaticInvocation node;
+        if (typeAliasBuilder == null) {
+          node = new FactoryConstructorInvocationJudgment(target, arguments,
+              isConst: isConst)
+            ..fileOffset = charOffset;
+          libraryBuilder.checkBoundsInFactoryInvocation(
+              node, typeEnvironment, uri);
+        } else {
+          node = new TypeAliasedFactoryInvocationJudgment(
+              typeAliasBuilder, target, arguments,
+              isConst: isConst)
+            ..fileOffset = charOffset;
+          // No type arguments were passed, so we need not check bounds.
+          assert(arguments.types.isEmpty);
+          typeAliasedFactoryInvocations.add(node);
+        }
         return node;
       } else {
         assert(constness == Constness.implicit);
@@ -4248,13 +4305,83 @@
         }
       } else {
         if (aliasBuilder.typeVariables?.isNotEmpty ?? false) {
-          // No type arguments provided to alias, but it is generic.
-          typeArgumentBuilders = new List<TypeBuilder>.filled(
-              aliasBuilder.typeVariables.length, null,
-              growable: true);
-          for (int i = 0; i < typeArgumentBuilders.length; ++i) {
-            // TODO(eernst): We must use inferred types, for now use defaults.
-            typeArgumentBuilders[i] = aliasBuilder.typeVariables[i].defaultType;
+          // Raw generic type alias used for instance creation, needs inference.
+          ClassBuilder classBuilder;
+          if (type is ClassBuilder) {
+            classBuilder = type;
+          } else {
+            if (type is InvalidTypeDeclarationBuilder) {
+              LocatedMessage message = type.message;
+              return evaluateArgumentsBefore(
+                  arguments,
+                  buildProblem(message.messageObject, nameToken.charOffset,
+                      nameToken.lexeme.length));
+            } else {
+              errorName ??= debugName(type.fullNameForErrors, name);
+            }
+            errorName ??= name;
+
+            return throwNoSuchMethodError(forest.createNullLiteral(charOffset),
+                errorName, arguments, nameLastToken.charOffset,
+                message: message);
+          }
+          MemberBuilder b = classBuilder.findConstructorOrFactory(
+              name, charOffset, uri, libraryBuilder);
+          Member target = b?.member;
+          if (b == null) {
+            // Not found. Reported below.
+          } else if (b is AmbiguousMemberBuilder) {
+            message = b.message.withLocation(uri, charOffset, noLength);
+          } else if (b.isConstructor) {
+            if (classBuilder.isAbstract) {
+              return evaluateArgumentsBefore(
+                  arguments,
+                  buildAbstractClassInstantiationError(
+                      fasta.templateAbstractClassInstantiation
+                          .withArguments(type.name),
+                      type.name,
+                      nameToken.charOffset));
+            }
+          }
+          if (target is Constructor ||
+              (target is Procedure && target.kind == ProcedureKind.Factory)) {
+            Expression invocation;
+            invocation = buildStaticInvocation(target, arguments,
+                constness: constness,
+                typeAliasBuilder: aliasBuilder,
+                charOffset: nameToken.charOffset,
+                charLength: nameToken.length);
+            return invocation;
+          } else {
+            errorName ??= debugName(type.name, name);
+            return throwNoSuchMethodError(forest.createNullLiteral(charOffset),
+                errorName, arguments, nameLastToken.charOffset,
+                message: message);
+          }
+        } else {
+          // Empty `typeArguments` and `aliasBuilder``is non-generic, but it
+          // may still unalias to a class type with some type arguments.
+          if (type is ClassBuilder) {
+            List<TypeBuilder> unaliasedTypeArgumentBuilders =
+                aliasBuilder.unaliasTypeArguments(const []);
+            if (unaliasedTypeArgumentBuilders == null) {
+              // TODO(eernst): This is a wrong number of type arguments,
+              // occurring indirectly (in an alias of an alias, etc.).
+              return evaluateArgumentsBefore(
+                  arguments,
+                  buildProblem(
+                      fasta.templateTypeArgumentMismatch
+                          .withArguments(numberOfTypeParameters),
+                      nameToken.charOffset,
+                      nameToken.length,
+                      suppressMessage: true));
+            }
+            List<DartType> dartTypeArguments = [];
+            for (TypeBuilder typeBuilder in unaliasedTypeArgumentBuilders) {
+              dartTypeArguments.add(typeBuilder.build(libraryBuilder));
+            }
+            assert(forest.argumentsTypeArguments(arguments).isEmpty);
+            forest.argumentsSetTypeArguments(arguments, dartTypeArguments);
           }
         }
       }
@@ -4296,16 +4423,17 @@
             assert(forest.argumentsTypeArguments(arguments).isEmpty);
             forest.argumentsSetTypeArguments(arguments, []);
           } else {
-            // No type arguments provided to unaliased class, use defaults.
-            List<DartType> result = new List<DartType>.filled(
-                type.typeVariables.length, null,
-                growable: true);
-            for (int i = 0; i < result.length; ++i) {
-              result[i] =
-                  type.typeVariables[i].defaultType?.build(type.library);
+            if (forest.argumentsTypeArguments(arguments).isEmpty) {
+              // No type arguments provided to unaliased class, use defaults.
+              List<DartType> result = new List<DartType>.filled(
+                  type.typeVariables.length, null,
+                  growable: true);
+              for (int i = 0; i < result.length; ++i) {
+                result[i] =
+                    type.typeVariables[i].defaultType?.build(type.library);
+              }
+              forest.argumentsSetTypeArguments(arguments, result);
             }
-            assert(forest.argumentsTypeArguments(arguments).isEmpty);
-            forest.argumentsSetTypeArguments(arguments, result);
           }
         }
       }
diff --git a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
index 3f4c1e8..9644894 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -743,6 +743,41 @@
         result.inferredType, result.applyResult(resultNode));
   }
 
+  ExpressionInferenceResult visitTypeAliasedConstructorInvocationJudgment(
+      TypeAliasedConstructorInvocationJudgment node, DartType typeContext) {
+    assert(getExplicitTypeArguments(node.arguments) == null);
+    Typedef typedef = node.typeAliasBuilder.typedef;
+    FunctionType calleeType = node.target.function
+        .computeAliasedFunctionType(typedef, inferrer.library.library);
+    InvocationInferenceResult result = inferrer.inferInvocation(
+        typeContext, node.fileOffset, calleeType, node.arguments,
+        returnType: calleeType.returnType.unalias, isConst: node.isConst);
+    node.hasBeenInferred = true;
+    Expression resultNode = node;
+    if (!inferrer.isTopLevel) {
+      SourceLibraryBuilder library = inferrer.library;
+      library.checkBoundsInType(result.inferredType,
+          inferrer.typeSchemaEnvironment, inferrer.helper.uri, node.fileOffset,
+          inferred: true);
+      if (inferrer.isNonNullableByDefault) {
+        if (node.target == inferrer.coreTypes.listDefaultConstructor) {
+          resultNode = inferrer.helper.wrapInProblem(node,
+              messageDefaultListConstructorError, node.fileOffset, noLength);
+        }
+      }
+    }
+    return new ExpressionInferenceResult(
+        result.inferredType, result.applyResult(resultNode));
+  }
+
+  ExpressionInferenceResult visitTypeAliasedFactoryInvocationJudgment(
+      TypeAliasedFactoryInvocationJudgment node, DartType typeContext) {
+    // TODO(eernst): See visitTypeAliasedConstructorInvocationJudgment
+    // for an implementation handling a similar task.
+    throw "visitTypeAliasedFactoryInvocationJudgment: "
+        "${node.typeAliasBuilder}, ${node.target}, $typeContext";
+  }
+
   @override
   void visitFieldInitializer(FieldInitializer node) {
     ExpressionInferenceResult initializerResult =
@@ -4887,9 +4922,7 @@
   StatementInferenceResult visitReturnStatement(
       covariant ReturnStatementImpl node) {
     ClosureContext closureContext = inferrer.closureContext;
-    DartType typeContext = !closureContext.isGenerator
-        ? closureContext.returnOrYieldContext
-        : const UnknownType();
+    DartType typeContext = closureContext.returnContext;
     DartType inferredType;
     if (node.expression != null) {
       ExpressionInferenceResult expressionResult = inferrer.inferExpression(
@@ -5682,24 +5715,18 @@
   StatementInferenceResult visitYieldStatement(YieldStatement node) {
     ClosureContext closureContext = inferrer.closureContext;
     ExpressionInferenceResult expressionResult;
-    if (closureContext.isGenerator) {
-      DartType typeContext = closureContext.returnOrYieldContext;
-      if (node.isYieldStar && typeContext != null) {
-        typeContext = inferrer.wrapType(
-            typeContext,
-            closureContext.isAsync
-                ? inferrer.coreTypes.streamClass
-                : inferrer.coreTypes.iterableClass,
-            inferrer.library.nonNullable);
-      }
-      expressionResult = inferrer.inferExpression(
-          node.expression, typeContext, true,
-          isVoidAllowed: true);
-    } else {
-      expressionResult = inferrer.inferExpression(
-          node.expression, const UnknownType(), true,
-          isVoidAllowed: true);
+    DartType typeContext = closureContext.yieldContext;
+    if (node.isYieldStar && typeContext is! UnknownType) {
+      typeContext = inferrer.wrapType(
+          typeContext,
+          closureContext.isAsync
+              ? inferrer.coreTypes.streamClass
+              : inferrer.coreTypes.iterableClass,
+          inferrer.library.nonNullable);
     }
+    expressionResult = inferrer.inferExpression(
+        node.expression, typeContext, true,
+        isVoidAllowed: true);
     closureContext.handleYield(inferrer, node, expressionResult);
     return const StatementInferenceResult();
   }
diff --git a/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart b/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart
index 991d0cd..377dace 100644
--- a/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart
@@ -25,6 +25,8 @@
 import 'package:kernel/src/printer.dart';
 import 'package:kernel/core_types.dart';
 
+import '../builder/type_alias_builder.dart';
+
 import '../fasta_codes.dart'
     show noLength, templateWebLiteralCannotBeRepresentedExactly;
 
@@ -704,6 +706,65 @@
   }
 }
 
+/// Shadow object for [ConstructorInvocation] when the procedure being invoked
+/// is a type aliased constructor.
+class TypeAliasedConstructorInvocationJudgment extends ConstructorInvocation
+    implements ExpressionJudgment {
+  bool hasBeenInferred = false;
+  final TypeAliasBuilder typeAliasBuilder;
+
+  TypeAliasedConstructorInvocationJudgment(
+      this.typeAliasBuilder, Constructor target, ArgumentsImpl arguments,
+      {bool isConst: false})
+      : super(target, arguments, isConst: isConst);
+
+  @override
+  ExpressionInferenceResult acceptInference(
+      InferenceVisitor visitor, DartType typeContext) {
+    return visitor.visitTypeAliasedConstructorInvocationJudgment(
+        this, typeContext);
+  }
+
+  @override
+  String toString() {
+    return "TypeAliasedConstructorInvocationJudgment(${toStringInternal()})";
+  }
+
+  @override
+  String toStringInternal() {
+    return "";
+  }
+}
+
+/// Shadow object for [StaticInvocation] when the procedure being invoked is a
+/// type aliased factory constructor.
+class TypeAliasedFactoryInvocationJudgment extends StaticInvocation
+    implements ExpressionJudgment {
+  bool hasBeenInferred = false;
+  final TypeAliasBuilder typeAliasBuilder;
+
+  TypeAliasedFactoryInvocationJudgment(
+      this.typeAliasBuilder, Procedure target, ArgumentsImpl arguments,
+      {bool isConst: false})
+      : super(target, arguments, isConst: isConst);
+
+  @override
+  ExpressionInferenceResult acceptInference(
+      InferenceVisitor visitor, DartType typeContext) {
+    return visitor.visitTypeAliasedFactoryInvocationJudgment(this, typeContext);
+  }
+
+  @override
+  String toString() {
+    return "TypeAliasedConstructorInvocationJudgment(${toStringInternal()})";
+  }
+
+  @override
+  String toStringInternal() {
+    return "";
+  }
+}
+
 /// Front end specific implementation of [FunctionDeclaration].
 class FunctionDeclarationImpl extends FunctionDeclaration {
   bool hasImplicitReturnType = false;
diff --git a/pkg/front_end/lib/src/fasta/type_inference/closure_context.dart b/pkg/front_end/lib/src/fasta/type_inference/closure_context.dart
new file mode 100644
index 0000000..1ff344f
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/type_inference/closure_context.dart
@@ -0,0 +1,856 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE.md file.
+
+part of 'type_inferrer.dart';
+
+/// Keeps track of information about the innermost function or closure being
+/// inferred.
+abstract class ClosureContext {
+  /// Returns `true` if this is an `async` or an `async*` function.
+  bool get isAsync;
+
+  /// The typing expectation for the subexpression of a `return` statement
+  /// inside the function.
+  ///
+  /// For an `async` function, this is a "FutureOr" type (since it is
+  /// permissible for such a function to return either a direct value or a
+  /// future).
+  ///
+  /// For generator functions (which do not allow return statements) this is the
+  /// unknown type.
+  DartType get returnContext;
+
+  /// The typing expectation for the subexpression of a `yield` statement inside
+  /// the function.
+  ///
+  /// For `sync*` and `async*` functions, the expected type is the element type
+  /// of the generated `Iterable` or `Stream`, respectively.
+  ///
+  /// For non-generator functions (which do not allow yield statements) this is
+  /// the unknown type.
+  DartType get yieldContext;
+
+  factory ClosureContext(TypeInferrerImpl inferrer, AsyncMarker asyncMarker,
+      DartType returnContext, bool needToInferReturnType) {
+    assert(returnContext != null);
+    DartType declaredReturnType =
+        inferrer.computeGreatestClosure(returnContext);
+    bool isAsync = asyncMarker == AsyncMarker.Async ||
+        asyncMarker == AsyncMarker.AsyncStar;
+    bool isGenerator = asyncMarker == AsyncMarker.SyncStar ||
+        asyncMarker == AsyncMarker.AsyncStar;
+    if (isGenerator) {
+      if (isAsync) {
+        DartType yieldContext = inferrer.getTypeArgumentOf(
+            returnContext, inferrer.coreTypes.streamClass);
+        return new _AsyncStarClosureContext(
+            yieldContext, declaredReturnType, needToInferReturnType);
+      } else {
+        DartType yieldContext = inferrer.getTypeArgumentOf(
+            returnContext, inferrer.coreTypes.iterableClass);
+        return new _SyncStarClosureContext(
+            yieldContext, declaredReturnType, needToInferReturnType);
+      }
+    } else if (isAsync) {
+      returnContext = inferrer.wrapFutureOrType(
+          inferrer.typeSchemaEnvironment.unfutureType(returnContext));
+      return new _AsyncClosureContext(
+          returnContext, declaredReturnType, needToInferReturnType);
+    } else {
+      return new _SyncClosureContext(
+          returnContext, declaredReturnType, needToInferReturnType);
+    }
+  }
+
+  /// Handles an explicit return statement.
+  ///
+  /// If the return type is declared, the expression type is checked. If the
+  /// return type is inferred the expression type registered for inference
+  /// in [inferReturnType].
+  void handleReturn(TypeInferrerImpl inferrer, ReturnStatement statement,
+      DartType type, bool isArrow);
+
+  /// Handles an explicit yield statement.
+  ///
+  /// If the return type is declared, the expression type is checked. If the
+  /// return type is inferred the expression type registered for inference
+  /// in [inferReturnType].
+  void handleYield(TypeInferrerImpl inferrer, YieldStatement node,
+      ExpressionInferenceResult expressionResult);
+
+  /// Handles an implicit return statement.
+  ///
+  /// If the return type is declared, the expression type is checked. If the
+  /// return type is inferred the expression type registered for inference
+  /// in [inferReturnType].
+  StatementInferenceResult handleImplicitReturn(TypeInferrerImpl inferrer,
+      Statement body, StatementInferenceResult inferenceResult, int fileOffset);
+
+  /// Infers the return type for the function.
+  ///
+  /// If the function is a non-generator function this is based on the explicit
+  /// and implicit return statements registered in [handleReturn] and
+  /// [handleImplicitReturn].
+  ///
+  /// If the function is a generator function this is based on the explicit
+  /// yield statements registered in [handleYield].
+  DartType inferReturnType(TypeInferrerImpl inferrer, {bool hasImplicitReturn});
+}
+
+class _SyncClosureContext implements ClosureContext {
+  bool get isAsync => false;
+
+  /// The typing expectation for the subexpression of a `return` or `yield`
+  /// statement inside the function.
+  ///
+  /// For non-generator async functions, this will be a "FutureOr" type (since
+  /// it is permissible for such a function to return either a direct value or
+  /// a future).
+  ///
+  /// For generator functions containing a `yield*` statement, the expected type
+  /// for the subexpression of the `yield*` statement is the result of wrapping
+  /// this typing expectation in `Stream` or `Iterator`, as appropriate.
+  final DartType _returnContext;
+
+  @override
+  DartType get returnContext => _returnContext;
+
+  @override
+  DartType get yieldContext => const UnknownType();
+
+  final DartType _declaredReturnType;
+
+  final bool _needToInferReturnType;
+
+  DartType _inferredReturnType;
+
+  /// Whether the function is an arrow function.
+  bool _isArrow;
+
+  /// A list of return statements in functions whose return type is being
+  /// inferred.
+  ///
+  /// The returns are checked for validity after the return type is inferred.
+  List<ReturnStatement> _returnStatements;
+
+  /// A list of return expression types in functions whose return type is
+  /// being inferred.
+  List<DartType> _returnExpressionTypes;
+
+  _SyncClosureContext(this._returnContext, this._declaredReturnType,
+      this._needToInferReturnType) {
+    if (_needToInferReturnType) {
+      _returnStatements = [];
+      _returnExpressionTypes = [];
+    }
+  }
+
+  void _checkValidReturn(TypeInferrerImpl inferrer, DartType returnType,
+      ReturnStatement statement, DartType expressionType) {
+    // The rules for valid returns for functions with [returnType] `T` and
+    // a return expression with static [expressionType] `S`.
+    if (statement.expression == null) {
+      // `return;` is a valid return if T is void, dynamic, or Null.
+      if (returnType is VoidType ||
+          returnType is DynamicType ||
+          returnType == inferrer.coreTypes.nullType) {
+        // Valid return;
+      } else {
+        statement.expression = inferrer.helper.wrapInProblem(
+            new NullLiteral()..fileOffset = statement.fileOffset,
+            messageReturnWithoutExpression,
+            statement.fileOffset,
+            noLength)
+          ..parent = statement;
+      }
+    } else {
+      void ensureAssignability() {
+        Expression expression = inferrer.ensureAssignable(
+            _returnContext, expressionType, statement.expression,
+            fileOffset: statement.fileOffset, isVoidAllowed: true);
+        statement.expression = expression..parent = statement;
+      }
+
+      if (_isArrow && returnType is VoidType) {
+        // Arrow functions are valid if: T is void or return exp; is a valid for
+        // a block-bodied function.
+        ensureAssignability();
+      } else if (returnType is VoidType &&
+          expressionType is! VoidType &&
+          expressionType is! DynamicType &&
+          expressionType != inferrer.coreTypes.nullType) {
+        // Invalid if T is void and S is not void, dynamic, or Null
+        statement.expression = inferrer.helper.wrapInProblem(
+            statement.expression,
+            messageReturnFromVoidFunction,
+            statement.expression.fileOffset,
+            noLength)
+          ..parent = statement;
+      } else if (expressionType is VoidType &&
+          returnType is! VoidType &&
+          returnType is! DynamicType &&
+          returnType != inferrer.coreTypes.nullType) {
+        // Invalid if S is void and T is not void, dynamic, or Null.
+        statement.expression = inferrer.helper.wrapInProblem(
+            statement.expression,
+            messageVoidExpression,
+            statement.expression.fileOffset,
+            noLength)
+          ..parent = statement;
+      } else {
+        ensureAssignability();
+      }
+    }
+  }
+
+  /// Updates the inferred return type based on the presence of a return
+  /// statement returning the given [type].
+  @override
+  void handleReturn(TypeInferrerImpl inferrer, ReturnStatement statement,
+      DartType type, bool isArrow) {
+    // The first return we see tells us if we have an arrow function.
+    if (this._isArrow == null) {
+      this._isArrow = isArrow;
+    } else {
+      assert(this._isArrow == isArrow);
+    }
+
+    if (_needToInferReturnType) {
+      // Add the return to a list to be checked for validity after we've
+      // inferred the return type.
+      _returnStatements.add(statement);
+      _returnExpressionTypes.add(type);
+    } else {
+      _checkValidReturn(inferrer, _declaredReturnType, statement, type);
+    }
+  }
+
+  @override
+  void handleYield(TypeInferrerImpl inferrer, YieldStatement node,
+      ExpressionInferenceResult expressionResult) {
+    node.expression = expressionResult.expression..parent = node;
+  }
+
+  @override
+  DartType inferReturnType(TypeInferrerImpl inferrer,
+      {bool hasImplicitReturn}) {
+    assert(_needToInferReturnType);
+    assert(hasImplicitReturn != null);
+    DartType inferredType;
+    if (_returnStatements.isNotEmpty) {
+      // Use the types seen from the explicit return statements.
+      for (int i = 0; i < _returnStatements.length; i++) {
+        ReturnStatement statement = _returnStatements[i];
+        DartType type = _returnExpressionTypes[i];
+        // The return expression has to be assignable to the return type
+        // expectation from the downwards inference context.
+        if (statement.expression != null) {
+          if (!inferrer.isAssignable(_returnContext, type)) {
+            type = inferrer.computeGreatestClosure(_returnContext);
+          }
+        }
+        if (inferredType == null) {
+          inferredType = type;
+        } else {
+          inferredType = inferrer.typeSchemaEnvironment.getStandardUpperBound(
+              inferredType, type, inferrer.library.library);
+        }
+      }
+    } else if (hasImplicitReturn) {
+      // No explicit returns we have an implicit `return null`.
+      inferredType = inferrer.typeSchemaEnvironment.nullType;
+    } else {
+      // No explicit return and the function doesn't complete normally; that is,
+      // it throws.
+      if (inferrer.isNonNullableByDefault) {
+        inferredType = new NeverType(inferrer.library.nonNullable);
+      } else {
+        inferredType = inferrer.typeSchemaEnvironment.nullType;
+      }
+    }
+
+    if (!inferrer.typeSchemaEnvironment.isSubtypeOf(
+        inferredType, _returnContext, SubtypeCheckMode.withNullabilities)) {
+      // If the inferred return type isn't a subtype of the context, we use the
+      // context.
+      inferredType = inferrer.computeGreatestClosure2(_declaredReturnType);
+    }
+
+    for (int i = 0; i < _returnStatements.length; ++i) {
+      _checkValidReturn(inferrer, inferredType, _returnStatements[i],
+          _returnExpressionTypes[i]);
+    }
+
+    return _inferredReturnType =
+        demoteTypeInLibrary(inferredType, inferrer.library.library);
+  }
+
+  @override
+  StatementInferenceResult handleImplicitReturn(
+      TypeInferrerImpl inferrer,
+      Statement body,
+      StatementInferenceResult inferenceResult,
+      int fileOffset) {
+    DartType returnType;
+    if (_needToInferReturnType) {
+      assert(_inferredReturnType != null,
+          "Return type has not yet been inferred.");
+      returnType = _inferredReturnType;
+    } else {
+      returnType = _declaredReturnType;
+    }
+    if (inferrer.library.isNonNullableByDefault &&
+        (containsInvalidType(returnType) ||
+            returnType.isPotentiallyNonNullable) &&
+        inferrer.flowAnalysis.isReachable) {
+      Statement resultStatement =
+          inferenceResult.hasChanged ? inferenceResult.statement : body;
+      // Create a synthetic return statement with the error.
+      Statement returnStatement = new ReturnStatement(inferrer.helper
+          .wrapInProblem(
+              new NullLiteral()..fileOffset = fileOffset,
+              templateImplicitReturnNull.withArguments(
+                  returnType, inferrer.library.isNonNullableByDefault),
+              fileOffset,
+              noLength))
+        ..fileOffset = fileOffset;
+      if (resultStatement is Block) {
+        resultStatement.statements.add(returnStatement);
+      } else {
+        resultStatement =
+            new Block(<Statement>[resultStatement, returnStatement])
+              ..fileOffset = fileOffset;
+      }
+      return new StatementInferenceResult.single(resultStatement);
+    }
+    return inferenceResult;
+  }
+}
+
+/// Keeps track of information about the innermost function or closure being
+/// inferred.
+class _AsyncClosureContext implements ClosureContext {
+  bool get isAsync => true;
+
+  /// The typing expectation for the subexpression of a `return` or `yield`
+  /// statement inside the function.
+  ///
+  /// For non-generator async functions, this will be a "FutureOr" type (since
+  /// it is permissible for such a function to return either a direct value or
+  /// a future).
+  ///
+  /// For generator functions containing a `yield*` statement, the expected type
+  /// for the subexpression of the `yield*` statement is the result of wrapping
+  /// this typing expectation in `Stream` or `Iterator`, as appropriate.
+  final DartType _returnContext;
+
+  @override
+  DartType get returnContext => _returnContext;
+
+  @override
+  DartType get yieldContext => const UnknownType();
+
+  final DartType _declaredReturnType;
+
+  final bool _needToInferReturnType;
+
+  DartType _inferredReturnType;
+
+  /// Whether the function is an arrow function.
+  bool _isArrow;
+
+  /// A list of return statements in functions whose return type is being
+  /// inferred.
+  ///
+  /// The returns are checked for validity after the return type is inferred.
+  List<ReturnStatement> _returnStatements;
+
+  /// A list of return expression types in functions whose return type is
+  /// being inferred.
+  List<DartType> _returnExpressionTypes;
+
+  _AsyncClosureContext(this._returnContext, this._declaredReturnType,
+      this._needToInferReturnType) {
+    if (_needToInferReturnType) {
+      _returnStatements = [];
+      _returnExpressionTypes = [];
+    }
+  }
+
+  void _checkValidReturn(TypeInferrerImpl inferrer, DartType returnType,
+      ReturnStatement statement, DartType expressionType) {
+    // The rules for valid returns for async functions with [returnType] `T` and
+    // a return expression with static [expressionType] `S`.
+    DartType flattenedReturnType =
+        inferrer.typeSchemaEnvironment.unfutureType(returnType);
+    if (statement.expression == null) {
+      // `return;` is a valid return if flatten(T) is void, dynamic, or Null.
+      if (flattenedReturnType is VoidType ||
+          flattenedReturnType is DynamicType ||
+          flattenedReturnType == inferrer.coreTypes.nullType) {
+        // Valid return;
+      } else {
+        statement.expression = inferrer.helper.wrapInProblem(
+            new NullLiteral()..fileOffset = statement.fileOffset,
+            messageReturnWithoutExpression,
+            statement.fileOffset,
+            noLength)
+          ..parent = statement;
+      }
+    } else {
+      DartType flattenedExpressionType =
+          inferrer.typeSchemaEnvironment.unfutureType(expressionType);
+
+      void ensureAssignability() {
+        DartType wrappedType = inferrer.typeSchemaEnvironment
+            .futureType(flattenedExpressionType, Nullability.nonNullable);
+        Expression expression = inferrer.ensureAssignable(
+            computeAssignableType(inferrer, _returnContext, wrappedType),
+            wrappedType,
+            statement.expression,
+            fileOffset: statement.fileOffset,
+            isVoidAllowed: true,
+            runtimeCheckedType: _returnContext);
+        statement.expression = expression..parent = statement;
+      }
+
+      if (_isArrow && flattenedReturnType is VoidType) {
+        // Arrow functions are valid if: flatten(T) is void or return exp; is
+        // valid for a block-bodied function.
+        ensureAssignability();
+      } else if (returnType is VoidType &&
+          flattenedExpressionType is! VoidType &&
+          flattenedExpressionType is! DynamicType &&
+          flattenedExpressionType != inferrer.coreTypes.nullType) {
+        // Invalid if T is void and flatten(S) is not void, dynamic, or Null.
+        statement.expression = inferrer.helper.wrapInProblem(
+            statement.expression,
+            messageReturnFromVoidFunction,
+            statement.expression.fileOffset,
+            noLength)
+          ..parent = statement;
+      } else if (flattenedExpressionType is VoidType &&
+          flattenedReturnType is! VoidType &&
+          flattenedReturnType is! DynamicType &&
+          flattenedReturnType != inferrer.coreTypes.nullType) {
+        // Invalid if flatten(S) is void and flatten(T) is not void, dynamic,
+        // or Null.
+        statement.expression = inferrer.helper.wrapInProblem(
+            statement.expression,
+            messageVoidExpression,
+            statement.expression.fileOffset,
+            noLength)
+          ..parent = statement;
+      } else {
+        // The caller will check that the return expression is assignable to the
+        // return type.
+        ensureAssignability();
+      }
+    }
+  }
+
+  /// Updates the inferred return type based on the presence of a return
+  /// statement returning the given [type].
+  @override
+  void handleReturn(TypeInferrerImpl inferrer, ReturnStatement statement,
+      DartType type, bool isArrow) {
+    // The first return we see tells us if we have an arrow function.
+    if (this._isArrow == null) {
+      this._isArrow = isArrow;
+    } else {
+      assert(this._isArrow == isArrow);
+    }
+
+    if (_needToInferReturnType) {
+      // Add the return to a list to be checked for validity after we've
+      // inferred the return type.
+      _returnStatements.add(statement);
+      _returnExpressionTypes.add(type);
+    } else {
+      _checkValidReturn(inferrer, _declaredReturnType, statement, type);
+    }
+  }
+
+  @override
+  void handleYield(TypeInferrerImpl inferrer, YieldStatement node,
+      ExpressionInferenceResult expressionResult) {
+    node.expression = expressionResult.expression..parent = node;
+  }
+
+  DartType computeAssignableType(TypeInferrerImpl inferrer,
+      DartType contextType, DartType expressionType) {
+    contextType = inferrer.computeGreatestClosure(contextType);
+
+    DartType initialContextType = contextType;
+    if (!inferrer.isAssignable(initialContextType, expressionType)) {
+      // If the body of the function is async, the expected return type has the
+      // shape FutureOr<T>.  We check both branches for FutureOr here: both T
+      // and Future<T>.
+      DartType unfuturedExpectedType =
+          inferrer.typeSchemaEnvironment.unfutureType(contextType);
+      DartType futuredExpectedType = inferrer.wrapFutureType(
+          unfuturedExpectedType, inferrer.library.nonNullable);
+      if (inferrer.isAssignable(unfuturedExpectedType, expressionType)) {
+        contextType = unfuturedExpectedType;
+      } else if (inferrer.isAssignable(futuredExpectedType, expressionType)) {
+        contextType = futuredExpectedType;
+      }
+    }
+    return contextType;
+  }
+
+  @override
+  DartType inferReturnType(TypeInferrerImpl inferrer,
+      {bool hasImplicitReturn}) {
+    assert(_needToInferReturnType);
+    assert(hasImplicitReturn != null);
+    DartType inferredType;
+    if (_returnStatements.isNotEmpty) {
+      // Use the types seen from the explicit return statements.
+      for (int i = 0; i < _returnStatements.length; i++) {
+        ReturnStatement statement = _returnStatements[i];
+        DartType type = _returnExpressionTypes[i];
+
+        // The return expression has to be assignable to the return type
+        // expectation from the downwards inference context.
+        if (statement.expression != null) {
+          if (!inferrer.isAssignable(
+              computeAssignableType(inferrer, _returnContext, type), type)) {
+            // Not assignable, use the expectation.
+            type = inferrer.computeGreatestClosure(_returnContext);
+          }
+        }
+        DartType unwrappedType =
+            inferrer.typeSchemaEnvironment.unfutureType(type);
+        if (inferredType == null) {
+          inferredType = unwrappedType;
+        } else {
+          inferredType = inferrer.typeSchemaEnvironment.getStandardUpperBound(
+              inferredType, unwrappedType, inferrer.library.library);
+        }
+      }
+    } else if (hasImplicitReturn) {
+      // No explicit returns we have an implicit `return null`.
+      inferredType = inferrer.typeSchemaEnvironment.nullType;
+    } else {
+      // No explicit return and the function doesn't complete normally; that is,
+      // it throws.
+      if (inferrer.isNonNullableByDefault) {
+        inferredType = new NeverType(inferrer.library.nonNullable);
+      } else {
+        inferredType = inferrer.typeSchemaEnvironment.nullType;
+      }
+    }
+
+    inferredType =
+        inferrer.wrapFutureType(inferredType, inferrer.library.nonNullable);
+
+    if (!inferrer.typeSchemaEnvironment.isSubtypeOf(
+        inferredType, _returnContext, SubtypeCheckMode.withNullabilities)) {
+      // If the inferred return type isn't a subtype of the context, we use the
+      // context.
+      inferredType = inferrer.computeGreatestClosure2(_declaredReturnType);
+    }
+
+    for (int i = 0; i < _returnStatements.length; ++i) {
+      _checkValidReturn(inferrer, inferredType, _returnStatements[i],
+          _returnExpressionTypes[i]);
+    }
+
+    return _inferredReturnType =
+        demoteTypeInLibrary(inferredType, inferrer.library.library);
+  }
+
+  @override
+  StatementInferenceResult handleImplicitReturn(
+      TypeInferrerImpl inferrer,
+      Statement body,
+      StatementInferenceResult inferenceResult,
+      int fileOffset) {
+    DartType returnType;
+    if (_needToInferReturnType) {
+      assert(_inferredReturnType != null,
+          "Return type has not yet been inferred.");
+      returnType = _inferredReturnType;
+    } else {
+      returnType = _declaredReturnType;
+    }
+    returnType = inferrer.typeSchemaEnvironment.unfutureType(returnType);
+    if (inferrer.library.isNonNullableByDefault &&
+        (containsInvalidType(returnType) ||
+            returnType.isPotentiallyNonNullable) &&
+        inferrer.flowAnalysis.isReachable) {
+      Statement resultStatement =
+          inferenceResult.hasChanged ? inferenceResult.statement : body;
+      // Create a synthetic return statement with the error.
+      Statement returnStatement = new ReturnStatement(inferrer.helper
+          .wrapInProblem(
+              new NullLiteral()..fileOffset = fileOffset,
+              templateImplicitReturnNull.withArguments(
+                  returnType, inferrer.library.isNonNullableByDefault),
+              fileOffset,
+              noLength))
+        ..fileOffset = fileOffset;
+      if (resultStatement is Block) {
+        resultStatement.statements.add(returnStatement);
+      } else {
+        resultStatement =
+            new Block(<Statement>[resultStatement, returnStatement])
+              ..fileOffset = fileOffset;
+      }
+      return new StatementInferenceResult.single(resultStatement);
+    }
+    return inferenceResult;
+  }
+}
+
+/// Keeps track of information about the innermost function or closure being
+/// inferred.
+class _SyncStarClosureContext implements ClosureContext {
+  bool get isAsync => false;
+
+  /// The typing expectation for the subexpression of a `return` or `yield`
+  /// statement inside the function.
+  ///
+  /// For non-generator async functions, this will be a "FutureOr" type (since
+  /// it is permissible for such a function to return either a direct value or
+  /// a future).
+  ///
+  /// For generator functions containing a `yield*` statement, the expected type
+  /// for the subexpression of the `yield*` statement is the result of wrapping
+  /// this typing expectation in `Stream` or `Iterator`, as appropriate.
+  final DartType _yieldElementContext;
+
+  @override
+  DartType get returnContext => const UnknownType();
+
+  @override
+  DartType get yieldContext => _yieldElementContext;
+
+  final DartType _declaredReturnType;
+
+  final bool _needToInferReturnType;
+
+  /// A list of return expression types in functions whose return type is
+  /// being inferred.
+  List<DartType> _yieldElementTypes;
+
+  _SyncStarClosureContext(this._yieldElementContext, this._declaredReturnType,
+      this._needToInferReturnType) {
+    if (_needToInferReturnType) {
+      _yieldElementTypes = [];
+    }
+  }
+
+  /// Updates the inferred return type based on the presence of a return
+  /// statement returning the given [type].
+  @override
+  void handleReturn(TypeInferrerImpl inferrer, ReturnStatement statement,
+      DartType type, bool isArrow) {}
+
+  @override
+  void handleYield(TypeInferrerImpl inferrer, YieldStatement node,
+      ExpressionInferenceResult expressionResult) {
+    DartType expectedType = node.isYieldStar
+        ? inferrer.wrapType(_yieldElementContext,
+            inferrer.coreTypes.iterableClass, inferrer.library.nonNullable)
+        : _yieldElementContext;
+    Expression expression = inferrer.ensureAssignableResult(
+        expectedType, expressionResult,
+        fileOffset: node.fileOffset);
+    node.expression = expression..parent = node;
+    DartType type = expressionResult.inferredType;
+    if (!identical(expressionResult.expression, expression)) {
+      type = inferrer.computeGreatestClosure(expectedType);
+    }
+    if (_needToInferReturnType) {
+      DartType elementType = type;
+      if (node.isYieldStar) {
+        elementType = inferrer.getDerivedTypeArgumentOf(
+                type, inferrer.coreTypes.iterableClass) ??
+            elementType;
+      }
+      _yieldElementTypes.add(elementType);
+    }
+  }
+
+  @override
+  DartType inferReturnType(TypeInferrerImpl inferrer,
+      {bool hasImplicitReturn}) {
+    assert(_needToInferReturnType);
+    assert(hasImplicitReturn != null);
+    DartType inferredElementType;
+    if (_yieldElementTypes.isNotEmpty) {
+      // Use the types seen from the explicit return statements.
+      for (int i = 0; i < _yieldElementTypes.length; i++) {
+        DartType type = _yieldElementTypes[i];
+        if (inferredElementType == null) {
+          inferredElementType = type;
+        } else {
+          inferredElementType = inferrer.typeSchemaEnvironment
+              .getStandardUpperBound(
+                  inferredElementType, type, inferrer.library.library);
+        }
+      }
+    } else if (hasImplicitReturn) {
+      // No explicit returns we have an implicit `return null`.
+      inferredElementType = inferrer.typeSchemaEnvironment.nullType;
+    } else {
+      // No explicit return and the function doesn't complete normally; that is,
+      // it throws.
+      if (inferrer.isNonNullableByDefault) {
+        inferredElementType = new NeverType(inferrer.library.nonNullable);
+      } else {
+        inferredElementType = inferrer.typeSchemaEnvironment.nullType;
+      }
+    }
+
+    DartType inferredType = inferrer.wrapType(inferredElementType,
+        inferrer.coreTypes.iterableClass, inferrer.library.nonNullable);
+
+    if (!inferrer.typeSchemaEnvironment.isSubtypeOf(inferredType,
+        _yieldElementContext, SubtypeCheckMode.withNullabilities)) {
+      // If the inferred return type isn't a subtype of the context, we use the
+      // context.
+      inferredType = inferrer.computeGreatestClosure2(_declaredReturnType);
+    }
+
+    return demoteTypeInLibrary(inferredType, inferrer.library.library);
+  }
+
+  @override
+  StatementInferenceResult handleImplicitReturn(
+      TypeInferrerImpl inferrer,
+      Statement body,
+      StatementInferenceResult inferenceResult,
+      int fileOffset) {
+    // There is no implicit return.
+    return inferenceResult;
+  }
+}
+
+/// Keeps track of information about the innermost function or closure being
+/// inferred.
+class _AsyncStarClosureContext implements ClosureContext {
+  bool get isAsync => true;
+
+  /// The typing expectation for the subexpression of a `return` or `yield`
+  /// statement inside the function.
+  ///
+  /// For non-generator async functions, this will be a "FutureOr" type (since
+  /// it is permissible for such a function to return either a direct value or
+  /// a future).
+  ///
+  /// For generator functions containing a `yield*` statement, the expected type
+  /// for the subexpression of the `yield*` statement is the result of wrapping
+  /// this typing expectation in `Stream` or `Iterator`, as appropriate.
+  final DartType _yieldElementContext;
+
+  @override
+  DartType get returnContext => const UnknownType();
+
+  @override
+  DartType get yieldContext => _yieldElementContext;
+
+  final DartType _declaredReturnType;
+
+  final bool _needToInferReturnType;
+
+  /// A list of return expression types in functions whose return type is
+  /// being inferred.
+  List<DartType> _yieldElementTypes;
+
+  _AsyncStarClosureContext(this._yieldElementContext, this._declaredReturnType,
+      this._needToInferReturnType) {
+    if (_needToInferReturnType) {
+      _yieldElementTypes = [];
+    }
+  }
+
+  /// Updates the inferred return type based on the presence of a return
+  /// statement returning the given [type].
+  @override
+  void handleReturn(TypeInferrerImpl inferrer, ReturnStatement statement,
+      DartType type, bool isArrow) {}
+
+  @override
+  void handleYield(TypeInferrerImpl inferrer, YieldStatement node,
+      ExpressionInferenceResult expressionResult) {
+    DartType expectedType = node.isYieldStar
+        ? inferrer.wrapType(_yieldElementContext,
+            inferrer.coreTypes.streamClass, inferrer.library.nonNullable)
+        : _yieldElementContext;
+
+    Expression expression = inferrer.ensureAssignableResult(
+        expectedType, expressionResult,
+        fileOffset: node.fileOffset);
+    node.expression = expression..parent = node;
+    DartType type = expressionResult.inferredType;
+    if (!identical(expressionResult.expression, expression)) {
+      type = inferrer.computeGreatestClosure(expectedType);
+    }
+    if (_needToInferReturnType) {
+      DartType elementType = type;
+      if (node.isYieldStar) {
+        elementType = inferrer.getDerivedTypeArgumentOf(
+                type, inferrer.coreTypes.streamClass) ??
+            type;
+      }
+      _yieldElementTypes.add(elementType);
+    }
+  }
+
+  @override
+  DartType inferReturnType(TypeInferrerImpl inferrer,
+      {bool hasImplicitReturn}) {
+    assert(_needToInferReturnType);
+    assert(hasImplicitReturn != null);
+    DartType inferredElementType;
+    if (_yieldElementTypes.isNotEmpty) {
+      // Use the types seen from the explicit return statements.
+      for (DartType elementType in _yieldElementTypes) {
+        if (inferredElementType == null) {
+          inferredElementType = elementType;
+        } else {
+          inferredElementType = inferrer.typeSchemaEnvironment
+              .getStandardUpperBound(
+                  inferredElementType, elementType, inferrer.library.library);
+        }
+      }
+    } else if (hasImplicitReturn) {
+      // No explicit returns we have an implicit `return null`.
+      inferredElementType = inferrer.typeSchemaEnvironment.nullType;
+    } else {
+      // No explicit return and the function doesn't complete normally; that is,
+      // it throws.
+      if (inferrer.isNonNullableByDefault) {
+        inferredElementType = new NeverType(inferrer.library.nonNullable);
+      } else {
+        inferredElementType = inferrer.typeSchemaEnvironment.nullType;
+      }
+    }
+
+    DartType inferredType = inferrer.wrapType(inferredElementType,
+        inferrer.coreTypes.streamClass, inferrer.library.nonNullable);
+
+    if (!inferrer.typeSchemaEnvironment.isSubtypeOf(inferredType,
+        _yieldElementContext, SubtypeCheckMode.withNullabilities)) {
+      // If the inferred return type isn't a subtype of the context, we use the
+      // context.
+      inferredType = inferrer.computeGreatestClosure2(_declaredReturnType);
+    }
+
+    return demoteTypeInLibrary(inferredType, inferrer.library.library);
+  }
+
+  @override
+  StatementInferenceResult handleImplicitReturn(
+      TypeInferrerImpl inferrer,
+      Statement body,
+      StatementInferenceResult inferenceResult,
+      int fileOffset) {
+    // There is no implicit return.
+    return inferenceResult;
+  }
+}
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
index e814390..59fa0b1 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
@@ -78,6 +78,8 @@
         TypeVariableEliminator,
         TypeSchemaEnvironment;
 
+part 'closure_context.dart';
+
 /// Given a [FunctionNode], gets the named parameter identified by [name], or
 /// `null` if there is no parameter with the given name.
 VariableDeclaration getNamedFormal(FunctionNode function, String name) {
@@ -104,361 +106,6 @@
       identical(name, '%');
 }
 
-/// Keeps track of information about the innermost function or closure being
-/// inferred.
-class ClosureContext {
-  final bool isAsync;
-
-  final bool isGenerator;
-
-  /// The typing expectation for the subexpression of a `return` or `yield`
-  /// statement inside the function.
-  ///
-  /// For non-generator async functions, this will be a "FutureOr" type (since
-  /// it is permissible for such a function to return either a direct value or
-  /// a future).
-  ///
-  /// For generator functions containing a `yield*` statement, the expected type
-  /// for the subexpression of the `yield*` statement is the result of wrapping
-  /// this typing expectation in `Stream` or `Iterator`, as appropriate.
-  final DartType returnOrYieldContext;
-
-  final DartType declaredReturnType;
-
-  final bool _needToInferReturnType;
-
-  DartType _inferredReturnType;
-
-  /// The type that actually appeared as the subexpression of `return` or
-  /// `yield` statements inside the function.
-  ///
-  /// For non-generator async functions, this is the "unwrapped" type (e.g. if
-  /// the function is expected to return `Future<int>`, this is `int`).
-  ///
-  /// For generator functions containing a `yield*` statement, the type that
-  /// appeared as the subexpression of the `yield*` statement was the result of
-  /// wrapping this type in `Stream` or `Iterator`, as appropriate.
-  DartType _inferredUnwrappedReturnOrYieldType;
-
-  /// Whether the function is an arrow function.
-  bool isArrow;
-
-  /// A list of return statements in functions whose return type is being
-  /// inferred.
-  ///
-  /// The returns are checked for validity after the return type is inferred.
-  List<ReturnStatement> returnStatements;
-
-  /// A list of return expression types in functions whose return type is
-  /// being inferred.
-  List<DartType> returnExpressionTypes;
-
-  factory ClosureContext(TypeInferrerImpl inferrer, AsyncMarker asyncMarker,
-      DartType returnContext, bool needToInferReturnType) {
-    assert(returnContext != null);
-    DartType declaredReturnType =
-        inferrer.computeGreatestClosure(returnContext);
-    bool isAsync = asyncMarker == AsyncMarker.Async ||
-        asyncMarker == AsyncMarker.AsyncStar;
-    bool isGenerator = asyncMarker == AsyncMarker.SyncStar ||
-        asyncMarker == AsyncMarker.AsyncStar;
-    if (isGenerator) {
-      if (isAsync) {
-        returnContext = inferrer.getTypeArgumentOf(
-            returnContext, inferrer.coreTypes.streamClass);
-      } else {
-        returnContext = inferrer.getTypeArgumentOf(
-            returnContext, inferrer.coreTypes.iterableClass);
-      }
-    } else if (isAsync) {
-      returnContext = inferrer.wrapFutureOrType(
-          inferrer.typeSchemaEnvironment.unfutureType(returnContext));
-    }
-    return new ClosureContext._(isAsync, isGenerator, returnContext,
-        declaredReturnType, needToInferReturnType);
-  }
-
-  ClosureContext._(this.isAsync, this.isGenerator, this.returnOrYieldContext,
-      this.declaredReturnType, this._needToInferReturnType) {
-    if (_needToInferReturnType) {
-      returnStatements = [];
-      returnExpressionTypes = [];
-    }
-  }
-
-  bool checkValidReturn(TypeInferrerImpl inferrer, DartType returnType,
-      ReturnStatement statement, DartType expressionType) {
-    // The rules for valid returns for functions with return type T and possibly
-    // a return expression with static type S.
-    DartType flattenedReturnType = isAsync
-        ? inferrer.typeSchemaEnvironment.unfutureType(returnType)
-        : returnType;
-    if (statement.expression == null) {
-      // Sync: return; is a valid return if T is void, dynamic, or Null.
-      // Async: return; is a valid return if flatten(T) is void, dynamic, or
-      // Null.
-      if (flattenedReturnType is VoidType ||
-          flattenedReturnType is DynamicType ||
-          flattenedReturnType == inferrer.coreTypes.nullType) {
-        return true;
-      }
-      statement.expression = inferrer.helper.wrapInProblem(
-          new NullLiteral()..fileOffset = statement.fileOffset,
-          messageReturnWithoutExpression,
-          statement.fileOffset,
-          noLength)
-        ..parent = statement;
-      return false;
-    }
-
-    // Arrow functions are valid if:
-    // Sync: T is void or return exp; is a valid for a block-bodied function.
-    // Async: flatten(T) is void or return exp; is valid for a block-bodied
-    // function.
-    if (isArrow && flattenedReturnType is VoidType) return true;
-
-    // Sync: invalid if T is void and S is not void, dynamic, or Null
-    // Async: invalid if T is void and flatten(S) is not void, dynamic, or Null.
-    DartType flattenedExpressionType = isAsync
-        ? inferrer.typeSchemaEnvironment.unfutureType(expressionType)
-        : expressionType;
-    if (returnType is VoidType &&
-        flattenedExpressionType is! VoidType &&
-        flattenedExpressionType is! DynamicType &&
-        flattenedExpressionType != inferrer.coreTypes.nullType) {
-      statement.expression = inferrer.helper.wrapInProblem(
-          statement.expression,
-          messageReturnFromVoidFunction,
-          statement.expression.fileOffset,
-          noLength)
-        ..parent = statement;
-      return false;
-    }
-
-    // Sync: invalid if S is void and T is not void, dynamic, or Null.
-    // Async: invalid if flatten(S) is void and flatten(T) is not void, dynamic,
-    // or Null.
-    if (flattenedExpressionType is VoidType &&
-        flattenedReturnType is! VoidType &&
-        flattenedReturnType is! DynamicType &&
-        flattenedReturnType != inferrer.coreTypes.nullType) {
-      statement.expression = inferrer.helper.wrapInProblem(statement.expression,
-          messageVoidExpression, statement.expression.fileOffset, noLength)
-        ..parent = statement;
-      return false;
-    }
-
-    // The caller will check that the return expression is assignable to the
-    // return type.
-    return true;
-  }
-
-  void _updateInferredUnwrappedReturnOrYieldType(
-      TypeInferrerImpl inferrer, DartType unwrappedType) {
-    if (_inferredUnwrappedReturnOrYieldType == null) {
-      _inferredUnwrappedReturnOrYieldType = unwrappedType;
-    } else {
-      _inferredUnwrappedReturnOrYieldType = inferrer.typeSchemaEnvironment
-          .getStandardUpperBound(_inferredUnwrappedReturnOrYieldType,
-              unwrappedType, inferrer.library.library);
-    }
-  }
-
-  /// Updates the inferred return type based on the presence of a return
-  /// statement returning the given [type].
-  void handleReturn(TypeInferrerImpl inferrer, ReturnStatement statement,
-      DartType type, bool isArrow) {
-    if (isGenerator) return;
-    // The first return we see tells us if we have an arrow function.
-    if (this.isArrow == null) {
-      this.isArrow = isArrow;
-    } else {
-      assert(this.isArrow == isArrow);
-    }
-
-    if (_needToInferReturnType) {
-      // Add the return to a list to be checked for validity after we've
-      // inferred the return type.
-      returnStatements.add(statement);
-      returnExpressionTypes.add(type);
-
-      // The return expression has to be assignable to the return type
-      // expectation from the downwards inference context.
-      if (statement.expression != null) {
-        Expression expression = inferrer.ensureAssignable(
-            returnOrYieldContext, type, statement.expression,
-            fileOffset: statement.fileOffset,
-            isReturnFromAsync: isAsync,
-            isVoidAllowed: true);
-        if (!identical(statement.expression, expression)) {
-          statement.expression = expression..parent = statement;
-          // Not assignable, use the expectation.
-          type = inferrer.computeGreatestClosure(returnOrYieldContext);
-        }
-      }
-      DartType unwrappedType = type;
-      if (isAsync) {
-        unwrappedType = inferrer.typeSchemaEnvironment.unfutureType(type);
-      }
-      _updateInferredUnwrappedReturnOrYieldType(inferrer, unwrappedType);
-    } else if (checkValidReturn(
-            inferrer, declaredReturnType, statement, type) &&
-        statement.expression != null) {
-      // If we are not inferring a type we can immediately check that the return
-      // is valid.
-      DartType wrappedType = type;
-      if (isAsync) {
-        wrappedType = inferrer.typeSchemaEnvironment.futureType(
-            inferrer.typeSchemaEnvironment.unfutureType(type),
-            Nullability.nonNullable);
-      }
-      Expression expression = inferrer.ensureAssignable(
-          returnOrYieldContext, wrappedType, statement.expression,
-          fileOffset: statement.fileOffset,
-          isReturnFromAsync: isAsync,
-          isVoidAllowed: true);
-      statement.expression = expression..parent = statement;
-    }
-  }
-
-  void handleYield(TypeInferrerImpl inferrer, YieldStatement node,
-      ExpressionInferenceResult expressionResult) {
-    if (!isGenerator) {
-      node.expression = expressionResult.expression..parent = node;
-      return;
-    }
-    DartType expectedType = node.isYieldStar
-        ? _wrapAsyncOrGenerator(
-            inferrer, returnOrYieldContext, inferrer.library.nonNullable)
-        : returnOrYieldContext;
-    Expression expression = inferrer.ensureAssignableResult(
-        expectedType, expressionResult,
-        fileOffset: node.fileOffset, isReturnFromAsync: isAsync);
-    node.expression = expression..parent = node;
-    DartType type = expressionResult.inferredType;
-    if (!identical(expressionResult.expression, expression)) {
-      type = inferrer.computeGreatestClosure(expectedType);
-    }
-    if (_needToInferReturnType) {
-      DartType unwrappedType = type;
-      if (node.isYieldStar) {
-        unwrappedType = inferrer.getDerivedTypeArgumentOf(
-                type,
-                isAsync
-                    ? inferrer.coreTypes.streamClass
-                    : inferrer.coreTypes.iterableClass) ??
-            type;
-      }
-      _updateInferredUnwrappedReturnOrYieldType(inferrer, unwrappedType);
-    }
-  }
-
-  DartType inferReturnType(TypeInferrerImpl inferrer,
-      {bool hasImplicitReturn}) {
-    assert(_needToInferReturnType);
-    assert(hasImplicitReturn != null);
-    DartType inferredType;
-    if (_inferredUnwrappedReturnOrYieldType != null) {
-      // Use the types seen from the explicit return statements.
-      inferredType = _inferredUnwrappedReturnOrYieldType;
-    } else if (hasImplicitReturn) {
-      // No explicit returns we have an implicit `return null`.
-      inferredType = inferrer.typeSchemaEnvironment.nullType;
-    } else {
-      // No explicit return and the function doesn't complete normally; that is,
-      // it throws.
-      if (inferrer.isNonNullableByDefault) {
-        inferredType = new NeverType(inferrer.library.nonNullable);
-      } else {
-        inferredType = inferrer.typeSchemaEnvironment.nullType;
-      }
-    }
-
-    inferredType = _wrapAsyncOrGenerator(
-        inferrer, inferredType, inferrer.library.nonNullable);
-
-    if (!inferrer.typeSchemaEnvironment.isSubtypeOf(inferredType,
-        returnOrYieldContext, SubtypeCheckMode.withNullabilities)) {
-      // If the inferred return type isn't a subtype of the context, we use the
-      // context.
-      inferredType = inferrer.computeGreatestClosure2(declaredReturnType);
-    }
-
-    for (int i = 0; i < returnStatements.length; ++i) {
-      checkValidReturn(inferrer, inferredType, returnStatements[i],
-          returnExpressionTypes[i]);
-    }
-
-    return _inferredReturnType =
-        demoteTypeInLibrary(inferredType, inferrer.library.library);
-  }
-
-  StatementInferenceResult handleImplicitReturn(
-      TypeInferrerImpl inferrer,
-      Statement body,
-      StatementInferenceResult inferenceResult,
-      int fileOffset) {
-    if (isGenerator) {
-      // There is no implicit return.
-      return inferenceResult;
-    }
-
-    DartType returnType;
-    if (_needToInferReturnType) {
-      assert(_inferredReturnType != null,
-          "Return type has not yet been inferred.");
-      returnType = _inferredReturnType;
-    } else {
-      returnType = declaredReturnType;
-    }
-    if (isAsync) {
-      returnType = inferrer.typeSchemaEnvironment.unfutureType(returnType);
-    }
-    if (inferrer.library.isNonNullableByDefault &&
-        (containsInvalidType(returnType) ||
-            returnType.isPotentiallyNonNullable) &&
-        inferrer.flowAnalysis.isReachable) {
-      Statement resultStatement =
-          inferenceResult.hasChanged ? inferenceResult.statement : body;
-      // Create a synthetic return statement with the error.
-      Statement returnStatement = new ReturnStatement(inferrer.helper
-          .wrapInProblem(
-              new NullLiteral()..fileOffset = fileOffset,
-              templateImplicitReturnNull.withArguments(
-                  returnType, inferrer.library.isNonNullableByDefault),
-              fileOffset,
-              noLength))
-        ..fileOffset = fileOffset;
-      if (resultStatement is Block) {
-        resultStatement.statements.add(returnStatement);
-      } else {
-        resultStatement =
-            new Block(<Statement>[resultStatement, returnStatement])
-              ..fileOffset = fileOffset;
-      }
-      return new StatementInferenceResult.single(resultStatement);
-    }
-    return inferenceResult;
-  }
-
-  DartType _wrapAsyncOrGenerator(
-      TypeInferrerImpl inferrer, DartType type, Nullability nullability) {
-    if (isGenerator) {
-      if (isAsync) {
-        return inferrer.wrapType(
-            type, inferrer.coreTypes.streamClass, nullability);
-      } else {
-        return inferrer.wrapType(
-            type, inferrer.coreTypes.iterableClass, nullability);
-      }
-    } else if (isAsync) {
-      return inferrer.wrapFutureType(type, nullability);
-    } else {
-      return type;
-    }
-  }
-}
-
 /// Enum denoting the kinds of contravariance check that might need to be
 /// inserted for a method call.
 enum MethodContravarianceCheckKind {
@@ -731,13 +378,11 @@
       DartType expectedType, ExpressionInferenceResult result,
       {int fileOffset,
       bool isVoidAllowed: false,
-      bool isReturnFromAsync: false,
       Template<Message Function(DartType, DartType, bool)> errorTemplate}) {
     return ensureAssignable(
         expectedType, result.inferredType, result.expression,
         fileOffset: fileOffset,
         isVoidAllowed: isVoidAllowed,
-        isReturnFromAsync: isReturnFromAsync,
         errorTemplate: errorTemplate);
   }
 
@@ -746,10 +391,16 @@
   /// Checks whether [expressionType] can be assigned to the greatest closure of
   /// [contextType], and inserts an implicit downcast, inserts a tear-off, or
   /// reports an error if appropriate.
+  ///
+  /// If [runtimeCheckedType] is provided, this is used for the implicit cast,
+  /// otherwise [contextType] is used. This is used for return from async
+  /// where the returned expression is wrapped in a `Future`, if necessary,
+  /// before returned and therefore shouldn't be checked to be a `Future`
+  /// directly.
   Expression ensureAssignable(
       DartType contextType, DartType expressionType, Expression expression,
       {int fileOffset,
-      bool isReturnFromAsync: false,
+      DartType runtimeCheckedType,
       bool isVoidAllowed: false,
       Template<Message Function(DartType, DartType, bool)> errorTemplate}) {
     assert(contextType != null);
@@ -762,22 +413,7 @@
     fileOffset ??= expression.fileOffset;
     contextType = computeGreatestClosure(contextType);
 
-    DartType initialContextType = contextType;
-    if (isReturnFromAsync &&
-        !isAssignable(initialContextType, expressionType)) {
-      // If the body of the function is async, the expected return type has the
-      // shape FutureOr<T>.  We check both branches for FutureOr here: both T
-      // and Future<T>.
-      DartType unfuturedExpectedType =
-          typeSchemaEnvironment.unfutureType(contextType);
-      DartType futuredExpectedType =
-          wrapFutureType(unfuturedExpectedType, library.nonNullable);
-      if (isAssignable(unfuturedExpectedType, expressionType)) {
-        contextType = unfuturedExpectedType;
-      } else if (isAssignable(futuredExpectedType, expressionType)) {
-        contextType = futuredExpectedType;
-      }
-    }
+    DartType initialContextType = runtimeCheckedType ?? contextType;
 
     Template<Message Function(DartType, DartType, bool)>
         preciseTypeErrorTemplate = _getPreciseTypeErrorTemplate(expression);
diff --git a/pkg/front_end/pubspec.yaml b/pkg/front_end/pubspec.yaml
index dd1b0c5..73e86ee 100644
--- a/pkg/front_end/pubspec.yaml
+++ b/pkg/front_end/pubspec.yaml
@@ -1,10 +1,10 @@
-name: front_end
 # Currently, front_end API is not stable and users should not
 # depend on semver semantics when depending on this package.
-version: 0.1.29
-author: Dart Team <misc@dartlang.org>
-description: Front end for compilation of Dart code.
-homepage: https://github.com/dart-lang/sdk/tree/master/pkg/front_end
+name: front_end
+
+# This package is not intended for consumption on pub.dev. DO NOT publish.
+publish_to: none
+
 environment:
   sdk: '>=2.2.2 <3.0.0'
 dependencies:
diff --git a/pkg/front_end/test/spell_checking_list_common.txt b/pkg/front_end/test/spell_checking_list_common.txt
index 2e12861..4e0e201 100644
--- a/pkg/front_end/test/spell_checking_list_common.txt
+++ b/pkg/front_end/test/spell_checking_list_common.txt
@@ -686,6 +686,7 @@
 creates
 creating
 creation
+creations
 crossed
 curly
 current
@@ -1077,6 +1078,7 @@
 experiments
 expired
 explanation
+explain
 explicit
 explicitly
 exponent
@@ -2901,6 +2903,7 @@
 targeting
 targets
 task
+tasks
 tear
 tearing
 technically
diff --git a/pkg/front_end/test/spell_checking_list_tests.txt b/pkg/front_end/test/spell_checking_list_tests.txt
index 1df02b2..8af47b7 100644
--- a/pkg/front_end/test/spell_checking_list_tests.txt
+++ b/pkg/front_end/test/spell_checking_list_tests.txt
@@ -21,6 +21,8 @@
 affected
 albeit
 allocations
+allowlist
+allowlisting
 alt
 amortized
 analyses
@@ -54,7 +56,6 @@
 besides
 beta
 bigger
-denylist
 blah
 blindly
 blocked
@@ -131,6 +132,7 @@
 decrements
 def
 deleting
+denylist
 depended
 depfile
 desc
@@ -233,6 +235,7 @@
 forces
 foreign
 forrest
+foundation
 fox
 fulfill
 func
@@ -472,6 +475,7 @@
 runtimes
 say
 scans
+scheduler
 screen
 scripts
 sdkroot
@@ -479,6 +483,7 @@
 secondary
 segment
 sensitive
+services
 severe
 sheets
 shipped
@@ -577,8 +582,6 @@
 walt
 warmup
 wherever
-allowlist
-allowlisting
 wins
 workflow
 worlds
diff --git a/pkg/front_end/testcases/general/future_return.dart b/pkg/front_end/testcases/general/future_return.dart
new file mode 100644
index 0000000..aae7105
--- /dev/null
+++ b/pkg/front_end/testcases/general/future_return.dart
@@ -0,0 +1,51 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+class Class {}
+
+dynamic returnDynamic() => new Class();
+
+Class returnClass() async => new Class();
+
+Future<Class> returnFutureClass() async => new Class();
+
+FutureOr<Class> returnFutureOrClass() async => new Class();
+
+Class returnClassFromDynamic() async => returnDynamic();
+
+Future<Class> returnFutureClassDynamic() async => returnDynamic();
+
+FutureOr<Class> returnFutureOrClassDynamic() async => returnDynamic();
+
+Class returnClassFromFutureClass() async => returnFutureClass();
+
+Future<Class> returnFutureClassFromFutureClass() async => returnFutureClass();
+
+FutureOr<Class> returnFutureOrClassFromFutureClass() async =>
+    returnFutureClass();
+
+Class returnClassFromFutureOrClass() async => returnFutureOrClass();
+
+Future<Class> returnFutureClassFromFutureOrClass() async =>
+    returnFutureOrClass();
+
+FutureOr<Class> returnFutureOrClassFromFutureOrClass() async =>
+    returnFutureOrClass();
+
+main() async {
+  await returnClass();
+  await returnFutureClass();
+  await returnFutureOrClass();
+  await returnClassFromDynamic();
+  await returnFutureClassDynamic();
+  await returnFutureOrClassDynamic();
+  await returnClassFromFutureClass();
+  await returnFutureClassFromFutureClass();
+  await returnFutureOrClassFromFutureClass();
+  await returnClassFromFutureOrClass();
+  await returnFutureClassFromFutureOrClass();
+  await returnFutureOrClassFromFutureOrClass();
+}
diff --git a/pkg/front_end/testcases/general/future_return.dart.outline.expect b/pkg/front_end/testcases/general/future_return.dart.outline.expect
new file mode 100644
index 0000000..7fed171
--- /dev/null
+++ b/pkg/front_end/testcases/general/future_return.dart.outline.expect
@@ -0,0 +1,49 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+import "dart:async";
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    ;
+  abstract member-signature get _identityHashCode() → core::int*;
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*;
+  abstract member-signature operator ==(dynamic other) → core::bool*;
+  abstract member-signature get hashCode() → core::int*;
+  abstract member-signature method toString() → core::String*;
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic;
+  abstract member-signature get runtimeType() → core::Type*;
+}
+static method returnDynamic() → dynamic
+  ;
+static method returnClass() → self::Class*
+  ;
+static method returnFutureClass() → asy::Future<self::Class*>*
+  ;
+static method returnFutureOrClass() → FutureOr<self::Class*>*
+  ;
+static method returnClassFromDynamic() → self::Class*
+  ;
+static method returnFutureClassDynamic() → asy::Future<self::Class*>*
+  ;
+static method returnFutureOrClassDynamic() → FutureOr<self::Class*>*
+  ;
+static method returnClassFromFutureClass() → self::Class*
+  ;
+static method returnFutureClassFromFutureClass() → asy::Future<self::Class*>*
+  ;
+static method returnFutureOrClassFromFutureClass() → FutureOr<self::Class*>*
+  ;
+static method returnClassFromFutureOrClass() → self::Class*
+  ;
+static method returnFutureClassFromFutureOrClass() → asy::Future<self::Class*>*
+  ;
+static method returnFutureOrClassFromFutureOrClass() → FutureOr<self::Class*>*
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/future_return.dart.strong.expect b/pkg/front_end/testcases/general/future_return.dart.strong.expect
new file mode 100644
index 0000000..7cec040
--- /dev/null
+++ b/pkg/front_end/testcases/general/future_return.dart.strong.expect
@@ -0,0 +1,81 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/future_return.dart:11:7: Error: Functions marked 'async' must have a return type assignable to 'Future'.
+// Class returnClass() async => new Class();
+//       ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/future_return.dart:17:7: Error: Functions marked 'async' must have a return type assignable to 'Future'.
+// Class returnClassFromDynamic() async => returnDynamic();
+//       ^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/future_return.dart:23:7: Error: Functions marked 'async' must have a return type assignable to 'Future'.
+// Class returnClassFromFutureClass() async => returnFutureClass();
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/future_return.dart:30:7: Error: Functions marked 'async' must have a return type assignable to 'Future'.
+// Class returnClassFromFutureOrClass() async => returnFutureOrClass();
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+import "dart:async";
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*;
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*;
+  abstract member-signature operator ==(dynamic other) → core::bool*;
+  abstract member-signature get hashCode() → core::int*;
+  abstract member-signature method toString() → core::String*;
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic;
+  abstract member-signature get runtimeType() → core::Type*;
+}
+static method returnDynamic() → dynamic
+  return new self::Class::•();
+static method returnClass() → self::Class* async 
+  return new self::Class::•();
+static method returnFutureClass() → asy::Future<self::Class*>* async 
+  return new self::Class::•();
+static method returnFutureOrClass() → FutureOr<self::Class*>* async 
+  return new self::Class::•();
+static method returnClassFromDynamic() → self::Class* async 
+  return self::returnDynamic() as{TypeError} FutureOr<self::Class*>*;
+static method returnFutureClassDynamic() → asy::Future<self::Class*>* async 
+  return self::returnDynamic() as{TypeError} FutureOr<self::Class*>*;
+static method returnFutureOrClassDynamic() → FutureOr<self::Class*>* async 
+  return self::returnDynamic() as{TypeError} FutureOr<self::Class*>*;
+static method returnClassFromFutureClass() → self::Class* async 
+  return self::returnFutureClass();
+static method returnFutureClassFromFutureClass() → asy::Future<self::Class*>* async 
+  return self::returnFutureClass();
+static method returnFutureOrClassFromFutureClass() → FutureOr<self::Class*>* async 
+  return self::returnFutureClass();
+static method returnClassFromFutureOrClass() → self::Class* async 
+  return self::returnFutureOrClass();
+static method returnFutureClassFromFutureOrClass() → asy::Future<self::Class*>* async 
+  return self::returnFutureOrClass();
+static method returnFutureOrClassFromFutureOrClass() → FutureOr<self::Class*>* async 
+  return self::returnFutureOrClass();
+static method main() → dynamic async {
+  await self::returnClass();
+  await self::returnFutureClass();
+  await self::returnFutureOrClass();
+  await self::returnClassFromDynamic();
+  await self::returnFutureClassDynamic();
+  await self::returnFutureOrClassDynamic();
+  await self::returnClassFromFutureClass();
+  await self::returnFutureClassFromFutureClass();
+  await self::returnFutureOrClassFromFutureClass();
+  await self::returnClassFromFutureOrClass();
+  await self::returnFutureClassFromFutureOrClass();
+  await self::returnFutureOrClassFromFutureOrClass();
+}
diff --git a/pkg/front_end/testcases/general/future_return.dart.strong.transformed.expect b/pkg/front_end/testcases/general/future_return.dart.strong.transformed.expect
new file mode 100644
index 0000000..0bb1231
--- /dev/null
+++ b/pkg/front_end/testcases/general/future_return.dart.strong.transformed.expect
@@ -0,0 +1,418 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/future_return.dart:11:7: Error: Functions marked 'async' must have a return type assignable to 'Future'.
+// Class returnClass() async => new Class();
+//       ^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/future_return.dart:17:7: Error: Functions marked 'async' must have a return type assignable to 'Future'.
+// Class returnClassFromDynamic() async => returnDynamic();
+//       ^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/future_return.dart:23:7: Error: Functions marked 'async' must have a return type assignable to 'Future'.
+// Class returnClassFromFutureClass() async => returnFutureClass();
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/general/future_return.dart:30:7: Error: Functions marked 'async' must have a return type assignable to 'Future'.
+// Class returnClassFromFutureOrClass() async => returnFutureOrClass();
+//       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+import "dart:_internal" as _in;
+
+import "dart:async";
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*;
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*;
+  abstract member-signature operator ==(dynamic other) → core::bool*;
+  abstract member-signature get hashCode() → core::int*;
+  abstract member-signature method toString() → core::String*;
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic;
+  abstract member-signature get runtimeType() → core::Type*;
+}
+static method returnDynamic() → dynamic
+  return new self::Class::•();
+static method returnClass() → self::Class* /* originally async */ {
+  final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
+  FutureOr<dynamic>* :return_value;
+  dynamic :async_stack_trace;
+  (dynamic) →* dynamic :async_op_then;
+  (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
+  core::int* :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L1:
+      {
+        :return_value = new self::Class::•();
+        break #L1;
+      }
+      asy::_completeOnAsyncReturn(:async_completer, :return_value);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
+      :async_completer.{asy::Completer::completeError}(exception, stack_trace);
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
+  return :async_completer.{asy::Completer::future};
+}
+static method returnFutureClass() → asy::Future<self::Class*>* /* originally async */ {
+  final asy::_AsyncAwaitCompleter<self::Class*>* :async_completer = new asy::_AsyncAwaitCompleter::•<self::Class*>();
+  FutureOr<self::Class*>* :return_value;
+  dynamic :async_stack_trace;
+  (dynamic) →* dynamic :async_op_then;
+  (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
+  core::int* :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L2:
+      {
+        :return_value = new self::Class::•();
+        break #L2;
+      }
+      asy::_completeOnAsyncReturn(:async_completer, :return_value);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
+      :async_completer.{asy::Completer::completeError}(exception, stack_trace);
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
+  return :async_completer.{asy::Completer::future};
+}
+static method returnFutureOrClass() → FutureOr<self::Class*>* /* originally async */ {
+  final asy::_AsyncAwaitCompleter<self::Class*>* :async_completer = new asy::_AsyncAwaitCompleter::•<self::Class*>();
+  FutureOr<self::Class*>* :return_value;
+  dynamic :async_stack_trace;
+  (dynamic) →* dynamic :async_op_then;
+  (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
+  core::int* :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L3:
+      {
+        :return_value = new self::Class::•();
+        break #L3;
+      }
+      asy::_completeOnAsyncReturn(:async_completer, :return_value);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
+      :async_completer.{asy::Completer::completeError}(exception, stack_trace);
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
+  return :async_completer.{asy::Completer::future};
+}
+static method returnClassFromDynamic() → self::Class* /* originally async */ {
+  final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
+  FutureOr<dynamic>* :return_value;
+  dynamic :async_stack_trace;
+  (dynamic) →* dynamic :async_op_then;
+  (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
+  core::int* :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L4:
+      {
+        :return_value = self::returnDynamic() as{TypeError} FutureOr<self::Class*>*;
+        break #L4;
+      }
+      asy::_completeOnAsyncReturn(:async_completer, :return_value);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
+      :async_completer.{asy::Completer::completeError}(exception, stack_trace);
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
+  return :async_completer.{asy::Completer::future};
+}
+static method returnFutureClassDynamic() → asy::Future<self::Class*>* /* originally async */ {
+  final asy::_AsyncAwaitCompleter<self::Class*>* :async_completer = new asy::_AsyncAwaitCompleter::•<self::Class*>();
+  FutureOr<self::Class*>* :return_value;
+  dynamic :async_stack_trace;
+  (dynamic) →* dynamic :async_op_then;
+  (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
+  core::int* :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L5:
+      {
+        :return_value = self::returnDynamic() as{TypeError} FutureOr<self::Class*>*;
+        break #L5;
+      }
+      asy::_completeOnAsyncReturn(:async_completer, :return_value);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
+      :async_completer.{asy::Completer::completeError}(exception, stack_trace);
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
+  return :async_completer.{asy::Completer::future};
+}
+static method returnFutureOrClassDynamic() → FutureOr<self::Class*>* /* originally async */ {
+  final asy::_AsyncAwaitCompleter<self::Class*>* :async_completer = new asy::_AsyncAwaitCompleter::•<self::Class*>();
+  FutureOr<self::Class*>* :return_value;
+  dynamic :async_stack_trace;
+  (dynamic) →* dynamic :async_op_then;
+  (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
+  core::int* :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L6:
+      {
+        :return_value = self::returnDynamic() as{TypeError} FutureOr<self::Class*>*;
+        break #L6;
+      }
+      asy::_completeOnAsyncReturn(:async_completer, :return_value);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
+      :async_completer.{asy::Completer::completeError}(exception, stack_trace);
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
+  return :async_completer.{asy::Completer::future};
+}
+static method returnClassFromFutureClass() → self::Class* /* originally async */ {
+  final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
+  FutureOr<dynamic>* :return_value;
+  dynamic :async_stack_trace;
+  (dynamic) →* dynamic :async_op_then;
+  (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
+  core::int* :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L7:
+      {
+        :return_value = self::returnFutureClass();
+        break #L7;
+      }
+      asy::_completeOnAsyncReturn(:async_completer, :return_value);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
+      :async_completer.{asy::Completer::completeError}(exception, stack_trace);
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
+  return :async_completer.{asy::Completer::future};
+}
+static method returnFutureClassFromFutureClass() → asy::Future<self::Class*>* /* originally async */ {
+  final asy::_AsyncAwaitCompleter<self::Class*>* :async_completer = new asy::_AsyncAwaitCompleter::•<self::Class*>();
+  FutureOr<self::Class*>* :return_value;
+  dynamic :async_stack_trace;
+  (dynamic) →* dynamic :async_op_then;
+  (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
+  core::int* :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L8:
+      {
+        :return_value = self::returnFutureClass();
+        break #L8;
+      }
+      asy::_completeOnAsyncReturn(:async_completer, :return_value);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
+      :async_completer.{asy::Completer::completeError}(exception, stack_trace);
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
+  return :async_completer.{asy::Completer::future};
+}
+static method returnFutureOrClassFromFutureClass() → FutureOr<self::Class*>* /* originally async */ {
+  final asy::_AsyncAwaitCompleter<self::Class*>* :async_completer = new asy::_AsyncAwaitCompleter::•<self::Class*>();
+  FutureOr<self::Class*>* :return_value;
+  dynamic :async_stack_trace;
+  (dynamic) →* dynamic :async_op_then;
+  (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
+  core::int* :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L9:
+      {
+        :return_value = self::returnFutureClass();
+        break #L9;
+      }
+      asy::_completeOnAsyncReturn(:async_completer, :return_value);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
+      :async_completer.{asy::Completer::completeError}(exception, stack_trace);
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
+  return :async_completer.{asy::Completer::future};
+}
+static method returnClassFromFutureOrClass() → self::Class* /* originally async */ {
+  final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
+  FutureOr<dynamic>* :return_value;
+  dynamic :async_stack_trace;
+  (dynamic) →* dynamic :async_op_then;
+  (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
+  core::int* :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L10:
+      {
+        :return_value = self::returnFutureOrClass();
+        break #L10;
+      }
+      asy::_completeOnAsyncReturn(:async_completer, :return_value);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
+      :async_completer.{asy::Completer::completeError}(exception, stack_trace);
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
+  return :async_completer.{asy::Completer::future};
+}
+static method returnFutureClassFromFutureOrClass() → asy::Future<self::Class*>* /* originally async */ {
+  final asy::_AsyncAwaitCompleter<self::Class*>* :async_completer = new asy::_AsyncAwaitCompleter::•<self::Class*>();
+  FutureOr<self::Class*>* :return_value;
+  dynamic :async_stack_trace;
+  (dynamic) →* dynamic :async_op_then;
+  (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
+  core::int* :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L11:
+      {
+        :return_value = self::returnFutureOrClass();
+        break #L11;
+      }
+      asy::_completeOnAsyncReturn(:async_completer, :return_value);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
+      :async_completer.{asy::Completer::completeError}(exception, stack_trace);
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
+  return :async_completer.{asy::Completer::future};
+}
+static method returnFutureOrClassFromFutureOrClass() → FutureOr<self::Class*>* /* originally async */ {
+  final asy::_AsyncAwaitCompleter<self::Class*>* :async_completer = new asy::_AsyncAwaitCompleter::•<self::Class*>();
+  FutureOr<self::Class*>* :return_value;
+  dynamic :async_stack_trace;
+  (dynamic) →* dynamic :async_op_then;
+  (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
+  core::int* :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L12:
+      {
+        :return_value = self::returnFutureOrClass();
+        break #L12;
+      }
+      asy::_completeOnAsyncReturn(:async_completer, :return_value);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
+      :async_completer.{asy::Completer::completeError}(exception, stack_trace);
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
+  return :async_completer.{asy::Completer::future};
+}
+static method main() → dynamic /* originally async */ {
+  final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
+  FutureOr<dynamic>* :return_value;
+  dynamic :async_stack_trace;
+  (dynamic) →* dynamic :async_op_then;
+  (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
+  core::int* :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L13:
+      {
+        [yield] let dynamic #t1 = asy::_awaitHelper(self::returnClass(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<self::Class*>(:result);
+        [yield] let dynamic #t2 = asy::_awaitHelper(self::returnFutureClass(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<self::Class*>(:result);
+        [yield] let dynamic #t3 = asy::_awaitHelper(self::returnFutureOrClass(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<self::Class*>(:result);
+        [yield] let dynamic #t4 = asy::_awaitHelper(self::returnClassFromDynamic(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<self::Class*>(:result);
+        [yield] let dynamic #t5 = asy::_awaitHelper(self::returnFutureClassDynamic(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<self::Class*>(:result);
+        [yield] let dynamic #t6 = asy::_awaitHelper(self::returnFutureOrClassDynamic(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<self::Class*>(:result);
+        [yield] let dynamic #t7 = asy::_awaitHelper(self::returnClassFromFutureClass(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<self::Class*>(:result);
+        [yield] let dynamic #t8 = asy::_awaitHelper(self::returnFutureClassFromFutureClass(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<self::Class*>(:result);
+        [yield] let dynamic #t9 = asy::_awaitHelper(self::returnFutureOrClassFromFutureClass(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<self::Class*>(:result);
+        [yield] let dynamic #t10 = asy::_awaitHelper(self::returnClassFromFutureOrClass(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<self::Class*>(:result);
+        [yield] let dynamic #t11 = asy::_awaitHelper(self::returnFutureClassFromFutureOrClass(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<self::Class*>(:result);
+        [yield] let dynamic #t12 = asy::_awaitHelper(self::returnFutureOrClassFromFutureOrClass(), :async_op_then, :async_op_error, :async_op) in null;
+        _in::unsafeCast<self::Class*>(:result);
+      }
+      asy::_completeOnAsyncReturn(:async_completer, :return_value);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
+      :async_completer.{asy::Completer::completeError}(exception, stack_trace);
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
+  return :async_completer.{asy::Completer::future};
+}
diff --git a/pkg/front_end/testcases/general/future_return.dart.textual_outline.expect b/pkg/front_end/testcases/general/future_return.dart.textual_outline.expect
new file mode 100644
index 0000000..75767f5
--- /dev/null
+++ b/pkg/front_end/testcases/general/future_return.dart.textual_outline.expect
@@ -0,0 +1,21 @@
+import 'dart:async';
+
+class Class {}
+
+dynamic returnDynamic() => new Class();
+Class returnClass() async => new Class();
+Future<Class> returnFutureClass() async => new Class();
+FutureOr<Class> returnFutureOrClass() async => new Class();
+Class returnClassFromDynamic() async => returnDynamic();
+Future<Class> returnFutureClassDynamic() async => returnDynamic();
+FutureOr<Class> returnFutureOrClassDynamic() async => returnDynamic();
+Class returnClassFromFutureClass() async => returnFutureClass();
+Future<Class> returnFutureClassFromFutureClass() async => returnFutureClass();
+FutureOr<Class> returnFutureOrClassFromFutureClass() async =>
+    returnFutureClass();
+Class returnClassFromFutureOrClass() async => returnFutureOrClass();
+Future<Class> returnFutureClassFromFutureOrClass() async =>
+    returnFutureOrClass();
+FutureOr<Class> returnFutureOrClassFromFutureOrClass() async =>
+    returnFutureOrClass();
+main() async {}
diff --git a/pkg/front_end/testcases/general/future_return.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/future_return.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..0e7261f
--- /dev/null
+++ b/pkg/front_end/testcases/general/future_return.dart.textual_outline_modelled.expect
@@ -0,0 +1,22 @@
+import 'dart:async';
+
+Class returnClass() async => new Class();
+Class returnClassFromDynamic() async => returnDynamic();
+Class returnClassFromFutureClass() async => returnFutureClass();
+Class returnClassFromFutureOrClass() async => returnFutureOrClass();
+Future<Class> returnFutureClass() async => new Class();
+Future<Class> returnFutureClassDynamic() async => returnDynamic();
+Future<Class> returnFutureClassFromFutureClass() async => returnFutureClass();
+Future<Class> returnFutureClassFromFutureOrClass() async =>
+    returnFutureOrClass();
+FutureOr<Class> returnFutureOrClass() async => new Class();
+FutureOr<Class> returnFutureOrClassDynamic() async => returnDynamic();
+FutureOr<Class> returnFutureOrClassFromFutureClass() async =>
+    returnFutureClass();
+FutureOr<Class> returnFutureOrClassFromFutureOrClass() async =>
+    returnFutureOrClass();
+
+class Class {}
+
+dynamic returnDynamic() => new Class();
+main() async {}
diff --git a/pkg/front_end/testcases/general/stream_future.dart b/pkg/front_end/testcases/general/stream_future.dart
new file mode 100644
index 0000000..8904ea0
--- /dev/null
+++ b/pkg/front_end/testcases/general/stream_future.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+class Class {}
+
+dynamic returnDynamic() => new Class();
+
+Class returnClass() => new Class();
+
+Future<dynamic> returnFutureDynamic() async => new Class();
+
+Future<Class> returnFutureClass() async => new Class();
+
+Stream<FutureOr<Class>> error() async* {
+  yield returnFutureDynamic();
+}
+
+Stream<FutureOr<Class>> stream() async* {
+  yield returnDynamic();
+  yield returnClass();
+  yield returnFutureClass();
+}
+
+main() async {
+  await for (FutureOr<Class> cls in stream()) {
+    print(cls);
+  }
+}
diff --git a/pkg/front_end/testcases/general/stream_future.dart.outline.expect b/pkg/front_end/testcases/general/stream_future.dart.outline.expect
new file mode 100644
index 0000000..7554d93
--- /dev/null
+++ b/pkg/front_end/testcases/general/stream_future.dart.outline.expect
@@ -0,0 +1,35 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+import "dart:async";
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    ;
+  abstract member-signature get _identityHashCode() → core::int*;
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*;
+  abstract member-signature operator ==(dynamic other) → core::bool*;
+  abstract member-signature get hashCode() → core::int*;
+  abstract member-signature method toString() → core::String*;
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic;
+  abstract member-signature get runtimeType() → core::Type*;
+}
+static method returnDynamic() → dynamic
+  ;
+static method returnClass() → self::Class*
+  ;
+static method returnFutureDynamic() → asy::Future<dynamic>*
+  ;
+static method returnFutureClass() → asy::Future<self::Class*>*
+  ;
+static method error() → asy::Stream<FutureOr<self::Class*>*>*
+  ;
+static method stream() → asy::Stream<FutureOr<self::Class*>*>*
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/general/stream_future.dart.strong.expect b/pkg/front_end/testcases/general/stream_future.dart.strong.expect
new file mode 100644
index 0000000..34be18d
--- /dev/null
+++ b/pkg/front_end/testcases/general/stream_future.dart.strong.expect
@@ -0,0 +1,56 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/stream_future.dart:18:9: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'FutureOr<Class>'.
+//  - 'Future' is from 'dart:async'.
+//  - 'Class' is from 'pkg/front_end/testcases/general/stream_future.dart'.
+//   yield returnFutureDynamic();
+//         ^
+//
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+import "dart:async";
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*;
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*;
+  abstract member-signature operator ==(dynamic other) → core::bool*;
+  abstract member-signature get hashCode() → core::int*;
+  abstract member-signature method toString() → core::String*;
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic;
+  abstract member-signature get runtimeType() → core::Type*;
+}
+static method returnDynamic() → dynamic
+  return new self::Class::•();
+static method returnClass() → self::Class*
+  return new self::Class::•();
+static method returnFutureDynamic() → asy::Future<dynamic>* async 
+  return new self::Class::•();
+static method returnFutureClass() → asy::Future<self::Class*>* async 
+  return new self::Class::•();
+static method error() → asy::Stream<FutureOr<self::Class*>*>* async* {
+  yield let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general/stream_future.dart:18:9: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'FutureOr<Class>'.
+ - 'Future' is from 'dart:async'.
+ - 'Class' is from 'pkg/front_end/testcases/general/stream_future.dart'.
+  yield returnFutureDynamic();
+        ^" in self::returnFutureDynamic() as{TypeError} FutureOr<self::Class*>*;
+}
+static method stream() → asy::Stream<FutureOr<self::Class*>*>* async* {
+  yield self::returnDynamic() as{TypeError,ForDynamic} FutureOr<self::Class*>*;
+  yield self::returnClass();
+  yield self::returnFutureClass();
+}
+static method main() → dynamic async {
+  await for (FutureOr<self::Class*>* cls in self::stream()) {
+    core::print(cls);
+  }
+}
diff --git a/pkg/front_end/testcases/general/stream_future.dart.strong.transformed.expect b/pkg/front_end/testcases/general/stream_future.dart.strong.transformed.expect
new file mode 100644
index 0000000..54b455b
--- /dev/null
+++ b/pkg/front_end/testcases/general/stream_future.dart.strong.transformed.expect
@@ -0,0 +1,225 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/general/stream_future.dart:18:9: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'FutureOr<Class>'.
+//  - 'Future' is from 'dart:async'.
+//  - 'Class' is from 'pkg/front_end/testcases/general/stream_future.dart'.
+//   yield returnFutureDynamic();
+//         ^
+//
+import self as self;
+import "dart:core" as core;
+import "dart:async" as asy;
+import "dart:_internal" as _in;
+
+import "dart:async";
+
+class Class extends core::Object {
+  synthetic constructor •() → self::Class*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*;
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*;
+  abstract member-signature operator ==(dynamic other) → core::bool*;
+  abstract member-signature get hashCode() → core::int*;
+  abstract member-signature method toString() → core::String*;
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic;
+  abstract member-signature get runtimeType() → core::Type*;
+}
+static method returnDynamic() → dynamic
+  return new self::Class::•();
+static method returnClass() → self::Class*
+  return new self::Class::•();
+static method returnFutureDynamic() → asy::Future<dynamic>* /* originally async */ {
+  final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
+  FutureOr<dynamic>* :return_value;
+  dynamic :async_stack_trace;
+  (dynamic) →* dynamic :async_op_then;
+  (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
+  core::int* :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L1:
+      {
+        :return_value = new self::Class::•();
+        break #L1;
+      }
+      asy::_completeOnAsyncReturn(:async_completer, :return_value);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
+      :async_completer.{asy::Completer::completeError}(exception, stack_trace);
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
+  return :async_completer.{asy::Completer::future};
+}
+static method returnFutureClass() → asy::Future<self::Class*>* /* originally async */ {
+  final asy::_AsyncAwaitCompleter<self::Class*>* :async_completer = new asy::_AsyncAwaitCompleter::•<self::Class*>();
+  FutureOr<self::Class*>* :return_value;
+  dynamic :async_stack_trace;
+  (dynamic) →* dynamic :async_op_then;
+  (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
+  core::int* :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L2:
+      {
+        :return_value = new self::Class::•();
+        break #L2;
+      }
+      asy::_completeOnAsyncReturn(:async_completer, :return_value);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
+      :async_completer.{asy::Completer::completeError}(exception, stack_trace);
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
+  return :async_completer.{asy::Completer::future};
+}
+static method error() → asy::Stream<FutureOr<self::Class*>*>* /* originally async* */ {
+  asy::_AsyncStarStreamController<FutureOr<self::Class*>*>* :controller;
+  dynamic :controller_stream;
+  dynamic :async_stack_trace;
+  (dynamic) →* dynamic :async_op_then;
+  (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
+  core::int* :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  dynamic :saved_try_context_var1;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try
+      try {
+        #L3:
+        {
+          if(:controller.{asy::_AsyncStarStreamController::add}(let final<BottomType> #t1 = invalid-expression "pkg/front_end/testcases/general/stream_future.dart:18:9: Error: A value of type 'Future<dynamic>' can't be assigned to a variable of type 'FutureOr<Class>'.
+ - 'Future' is from 'dart:async'.
+ - 'Class' is from 'pkg/front_end/testcases/general/stream_future.dart'.
+  yield returnFutureDynamic();
+        ^" in self::returnFutureDynamic() as{TypeError} FutureOr<self::Class*>*))
+            return null;
+          else
+            [yield] null;
+        }
+        return;
+      }
+      on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
+        :controller.{asy::_AsyncStarStreamController::addError}(exception, stack_trace);
+      }
+    finally {
+      :controller.{asy::_AsyncStarStreamController::close}();
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :controller = new asy::_AsyncStarStreamController::•<FutureOr<self::Class*>*>(:async_op);
+  :controller_stream = :controller.{asy::_AsyncStarStreamController::stream};
+  return :controller_stream;
+}
+static method stream() → asy::Stream<FutureOr<self::Class*>*>* /* originally async* */ {
+  asy::_AsyncStarStreamController<FutureOr<self::Class*>*>* :controller;
+  dynamic :controller_stream;
+  dynamic :async_stack_trace;
+  (dynamic) →* dynamic :async_op_then;
+  (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
+  core::int* :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  dynamic :saved_try_context_var1;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try
+      try {
+        #L4:
+        {
+          if(:controller.{asy::_AsyncStarStreamController::add}(self::returnDynamic() as{TypeError,ForDynamic} FutureOr<self::Class*>*))
+            return null;
+          else
+            [yield] null;
+          if(:controller.{asy::_AsyncStarStreamController::add}(self::returnClass()))
+            return null;
+          else
+            [yield] null;
+          if(:controller.{asy::_AsyncStarStreamController::add}(self::returnFutureClass()))
+            return null;
+          else
+            [yield] null;
+        }
+        return;
+      }
+      on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
+        :controller.{asy::_AsyncStarStreamController::addError}(exception, stack_trace);
+      }
+    finally {
+      :controller.{asy::_AsyncStarStreamController::close}();
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :controller = new asy::_AsyncStarStreamController::•<FutureOr<self::Class*>*>(:async_op);
+  :controller_stream = :controller.{asy::_AsyncStarStreamController::stream};
+  return :controller_stream;
+}
+static method main() → dynamic /* originally async */ {
+  final asy::_AsyncAwaitCompleter<dynamic>* :async_completer = new asy::_AsyncAwaitCompleter::•<dynamic>();
+  FutureOr<dynamic>* :return_value;
+  dynamic :async_stack_trace;
+  (dynamic) →* dynamic :async_op_then;
+  (core::Object*, core::StackTrace*) →* dynamic :async_op_error;
+  core::int* :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  dynamic :saved_try_context_var1;
+  dynamic :exception0;
+  dynamic :stack_trace0;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L5:
+      {
+        {
+          asy::Stream<FutureOr<self::Class*>*>* :stream = self::stream();
+          asy::_asyncStarListenHelper(:stream, :async_op);
+          asy::_StreamIterator<FutureOr<self::Class*>*>* :for-iterator = new asy::_StreamIterator::•<FutureOr<self::Class*>*>(:stream);
+          try
+            #L6:
+            while (true) {
+              dynamic #t2 = asy::_asyncStarMoveNextHelper(:stream);
+              [yield] let dynamic #t3 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::moveNext}(), :async_op_then, :async_op_error, :async_op) in null;
+              if(_in::unsafeCast<core::bool>(:result)) {
+                FutureOr<self::Class*>* cls = :for-iterator.{asy::_StreamIterator::current};
+                {
+                  core::print(cls);
+                }
+              }
+              else
+                break #L6;
+            }
+          finally
+            if(!:for-iterator.{asy::_StreamIterator::_subscription}.{core::Object::==}(null)) {
+              [yield] let dynamic #t4 = asy::_awaitHelper(:for-iterator.{asy::_StreamIterator::cancel}(), :async_op_then, :async_op_error, :async_op) in null;
+              :result;
+            }
+        }
+      }
+      asy::_completeOnAsyncReturn(:async_completer, :return_value);
+      return;
+    }
+    on dynamic catch(dynamic exception, core::StackTrace* stack_trace) {
+      :async_completer.{asy::Completer::completeError}(exception, stack_trace);
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
+  return :async_completer.{asy::Completer::future};
+}
diff --git a/pkg/front_end/testcases/general/stream_future.dart.textual_outline.expect b/pkg/front_end/testcases/general/stream_future.dart.textual_outline.expect
new file mode 100644
index 0000000..b720b02
--- /dev/null
+++ b/pkg/front_end/testcases/general/stream_future.dart.textual_outline.expect
@@ -0,0 +1,11 @@
+import 'dart:async';
+
+class Class {}
+
+dynamic returnDynamic() => new Class();
+Class returnClass() => new Class();
+Future<dynamic> returnFutureDynamic() async => new Class();
+Future<Class> returnFutureClass() async => new Class();
+Stream<FutureOr<Class>> error() async* {}
+Stream<FutureOr<Class>> stream() async* {}
+main() async {}
diff --git a/pkg/front_end/testcases/general/stream_future.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/general/stream_future.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..38f650e
--- /dev/null
+++ b/pkg/front_end/testcases/general/stream_future.dart.textual_outline_modelled.expect
@@ -0,0 +1,12 @@
+import 'dart:async';
+
+Class returnClass() => new Class();
+Future<Class> returnFutureClass() async => new Class();
+Future<dynamic> returnFutureDynamic() async => new Class();
+Stream<FutureOr<Class>> error() async* {}
+Stream<FutureOr<Class>> stream() async* {}
+
+class Class {}
+
+dynamic returnDynamic() => new Class();
+main() async {}
diff --git a/pkg/front_end/testcases/inference/future_then_conditional.dart b/pkg/front_end/testcases/inference/future_then_conditional.dart
index b9c870e..3a00196 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional.dart
+++ b/pkg/front_end/testcases/inference/future_then_conditional.dart
@@ -20,7 +20,7 @@
       /*@ returnType=Future<int*>* */ (/*@ type=bool* */ x) async =>
           x ? 2 : await new Future<int>.value(3));
   Future<int> t2 = f. /*@ typeArgs=int* */ /*@target=MyFuture.then*/ then(
-      /*@ returnType=Future<int*>* */ (/*@ type=bool* */ x) async {
+      /*@returnType=FutureOr<int*>**/ (/*@ type=bool* */ x) async {
     return /*info:DOWN_CAST_COMPOSITE*/ await x ? 2 : new Future<int>.value(3);
   });
   Future<int> t5 = f. /*@ typeArgs=int* */ /*@target=MyFuture.then*/ then(
diff --git a/pkg/front_end/testcases/inference/future_then_conditional.dart.strong.expect b/pkg/front_end/testcases/inference/future_then_conditional.dart.strong.expect
index 390633b..2210fc5 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional.dart.strong.expect
@@ -35,7 +35,7 @@
 static method test() → void {
   self::MyFuture<core::bool*>* f;
   asy::Future<core::int*>* t1 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → asy::Future<core::int*>* async => x ?{core::int*} 2 : await asy::Future::value<core::int*>(3));
-  asy::Future<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → asy::Future<core::int*>* async {
+  asy::Future<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → FutureOr<core::int*>* async {
     return (await x ?{core::Object*} 2 : asy::Future::value<core::int*>(3)) as{TypeError} FutureOr<core::int*>*;
   });
   asy::Future<core::int*>* t5 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → FutureOr<core::int*>* => (x ?{core::Object*} 2 : asy::Future::value<core::int*>(3)) as{TypeError} FutureOr<core::int*>*);
diff --git a/pkg/front_end/testcases/inference/future_then_conditional.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional.dart.strong.transformed.expect
index d466ab6..2c09036 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional.dart.strong.transformed.expect
@@ -71,7 +71,7 @@
     :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
-  asy::Future<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → asy::Future<core::int*>* /* originally async */ {
+  asy::Future<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → FutureOr<core::int*>* /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_2.dart b/pkg/front_end/testcases/inference/future_then_conditional_2.dart
index e492066..3738cae 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_2.dart
+++ b/pkg/front_end/testcases/inference/future_then_conditional_2.dart
@@ -20,7 +20,7 @@
       /*@ returnType=Future<int*>* */ (/*@ type=bool* */ x) async =>
           x ? 2 : await new MyFuture<int>.value(3));
   Future<int> t2 = f. /*@ typeArgs=int* */ /*@target=MyFuture.then*/ then(
-      /*@ returnType=Future<int*>* */ (/*@ type=bool* */ x) async {
+      /*@returnType=FutureOr<int*>**/ (/*@ type=bool* */ x) async {
     return /*info:DOWN_CAST_COMPOSITE*/ await x
         ? 2
         : new MyFuture<int>.value(3);
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_2.dart.strong.expect b/pkg/front_end/testcases/inference/future_then_conditional_2.dart.strong.expect
index f52ac69..086050d 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_2.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_2.dart.strong.expect
@@ -35,7 +35,7 @@
 static method test() → void {
   self::MyFuture<core::bool*>* f;
   asy::Future<core::int*>* t1 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → asy::Future<core::int*>* async => x ?{core::int*} 2 : await new self::MyFuture::value<core::int*>(3));
-  asy::Future<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → asy::Future<core::int*>* async {
+  asy::Future<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → FutureOr<core::int*>* async {
     return (await x ?{core::Object*} 2 : new self::MyFuture::value<core::int*>(3)) as{TypeError} FutureOr<core::int*>*;
   });
   asy::Future<core::int*>* t5 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → FutureOr<core::int*>* => (x ?{core::Object*} 2 : new self::MyFuture::value<core::int*>(3)) as{TypeError} FutureOr<core::int*>*);
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_2.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_2.dart.strong.transformed.expect
index 0738d0a1..72ca616 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_2.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_2.dart.strong.transformed.expect
@@ -71,7 +71,7 @@
     :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
-  asy::Future<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → asy::Future<core::int*>* /* originally async */ {
+  asy::Future<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → FutureOr<core::int*>* /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_3.dart b/pkg/front_end/testcases/inference/future_then_conditional_3.dart
index bb97825..f6a18b5 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_3.dart
+++ b/pkg/front_end/testcases/inference/future_then_conditional_3.dart
@@ -20,7 +20,7 @@
       /*@ returnType=Future<int*>* */ (/*@ type=bool* */ x) async =>
           x ? 2 : await new Future<int>.value(3));
   MyFuture<int> t2 = f. /*@ typeArgs=int* */ /*@target=MyFuture.then*/ then(
-      /*@ returnType=Future<int*>* */ (/*@ type=bool* */ x) async {
+      /*@returnType=FutureOr<int*>**/ (/*@ type=bool* */ x) async {
     return /*info:DOWN_CAST_COMPOSITE*/ await x ? 2 : new Future<int>.value(3);
   });
   MyFuture<int> t5 = f. /*@ typeArgs=int* */ /*@target=MyFuture.then*/ then(
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_3.dart.strong.expect b/pkg/front_end/testcases/inference/future_then_conditional_3.dart.strong.expect
index 9b83c6d..a86e98a 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_3.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_3.dart.strong.expect
@@ -35,7 +35,7 @@
 static method test() → void {
   self::MyFuture<core::bool*>* f;
   self::MyFuture<core::int*>* t1 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → asy::Future<core::int*>* async => x ?{core::int*} 2 : await asy::Future::value<core::int*>(3));
-  self::MyFuture<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → asy::Future<core::int*>* async {
+  self::MyFuture<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → FutureOr<core::int*>* async {
     return (await x ?{core::Object*} 2 : asy::Future::value<core::int*>(3)) as{TypeError} FutureOr<core::int*>*;
   });
   self::MyFuture<core::int*>* t5 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → FutureOr<core::int*>* => (x ?{core::Object*} 2 : asy::Future::value<core::int*>(3)) as{TypeError} FutureOr<core::int*>*);
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_3.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_3.dart.strong.transformed.expect
index 12e2069..614bb632d 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_3.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_3.dart.strong.transformed.expect
@@ -71,7 +71,7 @@
     :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
-  self::MyFuture<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → asy::Future<core::int*>* /* originally async */ {
+  self::MyFuture<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → FutureOr<core::int*>* /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_4.dart b/pkg/front_end/testcases/inference/future_then_conditional_4.dart
index 900063b..19fafd4 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_4.dart
+++ b/pkg/front_end/testcases/inference/future_then_conditional_4.dart
@@ -20,7 +20,7 @@
       /*@ returnType=Future<int*>* */ (/*@ type=bool* */ x) async =>
           x ? 2 : await new MyFuture<int>.value(3));
   MyFuture<int> t2 = f. /*@ typeArgs=int* */ /*@target=MyFuture.then*/ then(
-      /*@ returnType=Future<int*>* */ (/*@ type=bool* */ x) async {
+      /*@returnType=FutureOr<int*>**/ (/*@ type=bool* */ x) async {
     return /*info:DOWN_CAST_COMPOSITE*/ await x
         ? 2
         : new MyFuture<int>.value(3);
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_4.dart.strong.expect b/pkg/front_end/testcases/inference/future_then_conditional_4.dart.strong.expect
index bf3ab6b..1f5026e 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_4.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_4.dart.strong.expect
@@ -35,7 +35,7 @@
 static method test() → void {
   self::MyFuture<core::bool*>* f;
   self::MyFuture<core::int*>* t1 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → asy::Future<core::int*>* async => x ?{core::int*} 2 : await new self::MyFuture::value<core::int*>(3));
-  self::MyFuture<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → asy::Future<core::int*>* async {
+  self::MyFuture<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → FutureOr<core::int*>* async {
     return (await x ?{core::Object*} 2 : new self::MyFuture::value<core::int*>(3)) as{TypeError} FutureOr<core::int*>*;
   });
   self::MyFuture<core::int*>* t5 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → FutureOr<core::int*>* => (x ?{core::Object*} 2 : new self::MyFuture::value<core::int*>(3)) as{TypeError} FutureOr<core::int*>*);
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_4.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_4.dart.strong.transformed.expect
index 8142e71..6ea94f5 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_4.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_4.dart.strong.transformed.expect
@@ -71,7 +71,7 @@
     :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
-  self::MyFuture<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → asy::Future<core::int*>* /* originally async */ {
+  self::MyFuture<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((core::bool* x) → FutureOr<core::int*>* /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_5.dart b/pkg/front_end/testcases/inference/future_then_conditional_5.dart
index de773b9..e44607b 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_5.dart
+++ b/pkg/front_end/testcases/inference/future_then_conditional_5.dart
@@ -20,7 +20,7 @@
       /*@ returnType=Future<int*>* */ (/*@ type=bool* */ x) async =>
           x ? 2 : await new MyFuture<int>.value(3));
   Future<int> t2 = f. /*@ typeArgs=int* */ /*@target=Future.then*/ then(
-      /*@ returnType=Future<int*>* */ (/*@ type=bool* */ x) async {
+      /*@returnType=FutureOr<int*>*/ (/*@ type=bool* */ x) async {
     return /*info:DOWN_CAST_COMPOSITE*/ await x
         ? 2
         : new MyFuture<int>.value(3);
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_5.dart.strong.expect b/pkg/front_end/testcases/inference/future_then_conditional_5.dart.strong.expect
index 8bb9c69..778a252 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_5.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_5.dart.strong.expect
@@ -35,7 +35,7 @@
 static method test() → void {
   asy::Future<core::bool*>* f;
   asy::Future<core::int*>* t1 = f.{asy::Future::then}<core::int*>((core::bool* x) → asy::Future<core::int*>* async => x ?{core::int*} 2 : await new self::MyFuture::value<core::int*>(3));
-  asy::Future<core::int*>* t2 = f.{asy::Future::then}<core::int*>((core::bool* x) → asy::Future<core::int*>* async {
+  asy::Future<core::int*>* t2 = f.{asy::Future::then}<core::int*>((core::bool* x) → FutureOr<core::int*> async {
     return (await x ?{core::Object*} 2 : new self::MyFuture::value<core::int*>(3)) as{TypeError} FutureOr<core::int*>*;
   });
   asy::Future<core::int*>* t5 = f.{asy::Future::then}<core::int*>((core::bool* x) → FutureOr<core::int*> => (x ?{core::Object*} 2 : new self::MyFuture::value<core::int*>(3)) as{TypeError} FutureOr<core::int*>);
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_5.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_5.dart.strong.transformed.expect
index b3e2352..4885d08 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_5.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_5.dart.strong.transformed.expect
@@ -71,7 +71,7 @@
     :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
-  asy::Future<core::int*>* t2 = f.{asy::Future::then}<core::int*>((core::bool* x) → asy::Future<core::int*>* /* originally async */ {
+  asy::Future<core::int*>* t2 = f.{asy::Future::then}<core::int*>((core::bool* x) → FutureOr<core::int*> /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_6.dart b/pkg/front_end/testcases/inference/future_then_conditional_6.dart
index 9ee9c32..4a0cc0e 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_6.dart
+++ b/pkg/front_end/testcases/inference/future_then_conditional_6.dart
@@ -20,7 +20,7 @@
       /*@ returnType=Future<int*>* */ (/*@ type=bool* */ x) async =>
           x ? 2 : await new Future<int>.value(3));
   Future<int> t2 = f. /*@ typeArgs=int* */ /*@target=Future.then*/ then(
-      /*@ returnType=Future<int*>* */ (/*@ type=bool* */ x) async {
+      /*@returnType=FutureOr<int*>*/ (/*@ type=bool* */ x) async {
     return /*info:DOWN_CAST_COMPOSITE*/ await x ? 2 : new Future<int>.value(3);
   });
   Future<int> t5 = f. /*@ typeArgs=int* */ /*@target=Future.then*/ then(
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_6.dart.strong.expect b/pkg/front_end/testcases/inference/future_then_conditional_6.dart.strong.expect
index 7ff41c8..a620834 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_6.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_6.dart.strong.expect
@@ -35,7 +35,7 @@
 static method test() → void {
   asy::Future<core::bool*>* f;
   asy::Future<core::int*>* t1 = f.{asy::Future::then}<core::int*>((core::bool* x) → asy::Future<core::int*>* async => x ?{core::int*} 2 : await asy::Future::value<core::int*>(3));
-  asy::Future<core::int*>* t2 = f.{asy::Future::then}<core::int*>((core::bool* x) → asy::Future<core::int*>* async {
+  asy::Future<core::int*>* t2 = f.{asy::Future::then}<core::int*>((core::bool* x) → FutureOr<core::int*> async {
     return (await x ?{core::Object*} 2 : asy::Future::value<core::int*>(3)) as{TypeError} FutureOr<core::int*>*;
   });
   asy::Future<core::int*>* t5 = f.{asy::Future::then}<core::int*>((core::bool* x) → FutureOr<core::int*> => (x ?{core::Object*} 2 : asy::Future::value<core::int*>(3)) as{TypeError} FutureOr<core::int*>);
diff --git a/pkg/front_end/testcases/inference/future_then_conditional_6.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_conditional_6.dart.strong.transformed.expect
index f5032974..59dd08b 100644
--- a/pkg/front_end/testcases/inference/future_then_conditional_6.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_conditional_6.dart.strong.transformed.expect
@@ -71,7 +71,7 @@
     :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
-  asy::Future<core::int*>* t2 = f.{asy::Future::then}<core::int*>((core::bool* x) → asy::Future<core::int*>* /* originally async */ {
+  asy::Future<core::int*>* t2 = f.{asy::Future::then}<core::int*>((core::bool* x) → FutureOr<core::int*> /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
diff --git a/pkg/front_end/testcases/inference/future_then_ifNull.dart b/pkg/front_end/testcases/inference/future_then_ifNull.dart
index 06b9f65..013774e 100644
--- a/pkg/front_end/testcases/inference/future_then_ifNull.dart
+++ b/pkg/front_end/testcases/inference/future_then_ifNull.dart
@@ -20,7 +20,7 @@
       /*@ returnType=Future<int*>* */ (/*@ type=int* */ x) async =>
           x /*@target=num.==*/ ?? await new Future<int>.value(3));
   Future<int> t2 = f. /*@ typeArgs=int* */ /*@target=MyFuture.then*/ then(
-      /*@ returnType=Future<int*>* */ (/*@ type=int* */ x) async {
+      /*@returnType=FutureOr<int*>**/ (/*@ type=int* */ x) async {
     return /*info:DOWN_CAST_COMPOSITE*/ await x /*@target=num.==*/ ??
         new Future<int>.value(3);
   });
diff --git a/pkg/front_end/testcases/inference/future_then_ifNull.dart.strong.expect b/pkg/front_end/testcases/inference/future_then_ifNull.dart.strong.expect
index dd021c0..602b1db 100644
--- a/pkg/front_end/testcases/inference/future_then_ifNull.dart.strong.expect
+++ b/pkg/front_end/testcases/inference/future_then_ifNull.dart.strong.expect
@@ -35,7 +35,7 @@
 static method test() → void {
   self::MyFuture<core::int*>* f;
   asy::Future<core::int*>* t1 = f.{self::MyFuture::then}<core::int*>((core::int* x) → asy::Future<core::int*>* async => let final core::int* #t1 = x in #t1.{core::num::==}(null) ?{core::int*} await asy::Future::value<core::int*>(3) : #t1);
-  asy::Future<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((core::int* x) → asy::Future<core::int*>* async {
+  asy::Future<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((core::int* x) → FutureOr<core::int*>* async {
     return (let final core::int* #t2 = await x in #t2.{core::num::==}(null) ?{core::Object*} asy::Future::value<core::int*>(3) : #t2) as{TypeError} FutureOr<core::int*>*;
   });
   asy::Future<core::int*>* t5 = f.{self::MyFuture::then}<core::int*>((core::int* x) → FutureOr<core::int*>* => (let final core::int* #t3 = x in #t3.{core::num::==}(null) ?{core::Object*} asy::Future::value<core::int*>(3) : #t3) as{TypeError} FutureOr<core::int*>*);
diff --git a/pkg/front_end/testcases/inference/future_then_ifNull.dart.strong.transformed.expect b/pkg/front_end/testcases/inference/future_then_ifNull.dart.strong.transformed.expect
index 1332feb..e254364 100644
--- a/pkg/front_end/testcases/inference/future_then_ifNull.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/inference/future_then_ifNull.dart.strong.transformed.expect
@@ -72,7 +72,7 @@
     :async_completer.{asy::_AsyncAwaitCompleter::start}(:async_op);
     return :async_completer.{asy::Completer::future};
   });
-  asy::Future<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((core::int* x) → asy::Future<core::int*>* /* originally async */ {
+  asy::Future<core::int*>* t2 = f.{self::MyFuture::then}<core::int*>((core::int* x) → FutureOr<core::int*>* /* originally async */ {
     final asy::_AsyncAwaitCompleter<core::int*>* :async_completer = new asy::_AsyncAwaitCompleter::•<core::int*>();
     FutureOr<core::int*>* :return_value;
     dynamic :async_stack_trace;
diff --git a/pkg/front_end/testcases/late_lowering/issue42407.dart b/pkg/front_end/testcases/late_lowering/issue42407.dart
new file mode 100644
index 0000000..97ac374
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue42407.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class A<T> {
+  late T x;
+}
+
+class B<T> {
+  T? _y;
+  T? get y => _y;
+  set y(T? val) {
+    _y = val;
+  }
+}
+
+main() {
+  A<num> a = new A<int>();
+  expect(42, a.x = 42);
+  throws(() => a.x = 0.5);
+
+  B<num> b = new B<int>();
+  expect(42, b.y = 42);
+  throws(() => b.y = 0.5);
+}
+
+expect(expected, actual) {
+  if (expected != actual) throw "Expected $expected, actual $actual";
+}
+
+throws(void Function() f) {
+  try {
+    f();
+  } catch (_) {
+    return;
+  }
+  throw "Expected exception";
+}
diff --git a/pkg/front_end/testcases/late_lowering/issue42407.dart.outline.expect b/pkg/front_end/testcases/late_lowering/issue42407.dart.outline.expect
new file mode 100644
index 0000000..9abba16
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue42407.dart.outline.expect
@@ -0,0 +1,27 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class A<T extends core::Object? = dynamic> extends core::Object {
+  generic-covariant-impl field self::A::T? _#A#x;
+  field core::bool _#A#x#isSet;
+  synthetic constructor •() → self::A<self::A::T%>
+    ;
+  get x() → self::A::T%;
+  set x(generic-covariant-impl self::A::T% #t1) → void;
+}
+class B<T extends core::Object? = dynamic> extends core::Object {
+  generic-covariant-impl field self::B::T? _y;
+  synthetic constructor •() → self::B<self::B::T%>
+    ;
+  get y() → self::B::T?
+    ;
+  set y(generic-covariant-impl self::B::T? val) → void
+    ;
+}
+static method main() → dynamic
+  ;
+static method expect(dynamic expected, dynamic actual) → dynamic
+  ;
+static method throws(() → void f) → dynamic
+  ;
diff --git a/pkg/front_end/testcases/late_lowering/issue42407.dart.strong.expect b/pkg/front_end/testcases/late_lowering/issue42407.dart.strong.expect
new file mode 100644
index 0000000..59101b9
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue42407.dart.strong.expect
@@ -0,0 +1,50 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class A<T extends core::Object? = dynamic> extends core::Object {
+  generic-covariant-impl field self::A::T? _#A#x = null;
+  field core::bool _#A#x#isSet = false;
+  synthetic constructor •() → self::A<self::A::T%>
+    : super core::Object::•()
+    ;
+  get x() → self::A::T%
+    return this.{self::A::_#A#x#isSet} ?{self::A::T%} let final self::A::T? #t1 = this.{self::A::_#A#x} in #t1{self::A::T%} : throw new _in::LateInitializationErrorImpl::•("Field 'x' has not been initialized.");
+  set x(generic-covariant-impl self::A::T% #t2) → void {
+    this.{self::A::_#A#x#isSet} = true;
+    this.{self::A::_#A#x} = #t2;
+  }
+}
+class B<T extends core::Object? = dynamic> extends core::Object {
+  generic-covariant-impl field self::B::T? _y = null;
+  synthetic constructor •() → self::B<self::B::T%>
+    : super core::Object::•()
+    ;
+  get y() → self::B::T?
+    return this.{self::B::_y};
+  set y(generic-covariant-impl self::B::T? val) → void {
+    this.{self::B::_y} = val;
+  }
+}
+static method main() → dynamic {
+  self::A<core::num> a = new self::A::•<core::int>();
+  self::expect(42, a.{self::A::x} = 42);
+  self::throws(() → core::double => a.{self::A::x} = 0.5);
+  self::B<core::num> b = new self::B::•<core::int>();
+  self::expect(42, b.{self::B::y} = 42);
+  self::throws(() → core::double => b.{self::B::y} = 0.5);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → void f) → dynamic {
+  try {
+    f.call();
+  }
+  on core::Object catch(final core::Object _) {
+    return;
+  }
+  throw "Expected exception";
+}
diff --git a/pkg/front_end/testcases/late_lowering/issue42407.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/issue42407.dart.strong.transformed.expect
new file mode 100644
index 0000000..59101b9
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue42407.dart.strong.transformed.expect
@@ -0,0 +1,50 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class A<T extends core::Object? = dynamic> extends core::Object {
+  generic-covariant-impl field self::A::T? _#A#x = null;
+  field core::bool _#A#x#isSet = false;
+  synthetic constructor •() → self::A<self::A::T%>
+    : super core::Object::•()
+    ;
+  get x() → self::A::T%
+    return this.{self::A::_#A#x#isSet} ?{self::A::T%} let final self::A::T? #t1 = this.{self::A::_#A#x} in #t1{self::A::T%} : throw new _in::LateInitializationErrorImpl::•("Field 'x' has not been initialized.");
+  set x(generic-covariant-impl self::A::T% #t2) → void {
+    this.{self::A::_#A#x#isSet} = true;
+    this.{self::A::_#A#x} = #t2;
+  }
+}
+class B<T extends core::Object? = dynamic> extends core::Object {
+  generic-covariant-impl field self::B::T? _y = null;
+  synthetic constructor •() → self::B<self::B::T%>
+    : super core::Object::•()
+    ;
+  get y() → self::B::T?
+    return this.{self::B::_y};
+  set y(generic-covariant-impl self::B::T? val) → void {
+    this.{self::B::_y} = val;
+  }
+}
+static method main() → dynamic {
+  self::A<core::num> a = new self::A::•<core::int>();
+  self::expect(42, a.{self::A::x} = 42);
+  self::throws(() → core::double => a.{self::A::x} = 0.5);
+  self::B<core::num> b = new self::B::•<core::int>();
+  self::expect(42, b.{self::B::y} = 42);
+  self::throws(() → core::double => b.{self::B::y} = 0.5);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → void f) → dynamic {
+  try {
+    f.call();
+  }
+  on core::Object catch(final core::Object _) {
+    return;
+  }
+  throw "Expected exception";
+}
diff --git a/pkg/front_end/testcases/late_lowering/issue42407.dart.textual_outline.expect b/pkg/front_end/testcases/late_lowering/issue42407.dart.textual_outline.expect
new file mode 100644
index 0000000..d50d6fd
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue42407.dart.textual_outline.expect
@@ -0,0 +1,12 @@
+class A<T> {
+  late T ;
+  x;
+}
+class B<T> {
+  T? _y;
+  T? get y => _y;
+  set y(T? val) { }
+}
+main() { }
+expect(expected, actual) { }
+throws(void Function() f) { }
diff --git a/pkg/front_end/testcases/late_lowering/issue42407.dart.weak.expect b/pkg/front_end/testcases/late_lowering/issue42407.dart.weak.expect
new file mode 100644
index 0000000..59101b9
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue42407.dart.weak.expect
@@ -0,0 +1,50 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class A<T extends core::Object? = dynamic> extends core::Object {
+  generic-covariant-impl field self::A::T? _#A#x = null;
+  field core::bool _#A#x#isSet = false;
+  synthetic constructor •() → self::A<self::A::T%>
+    : super core::Object::•()
+    ;
+  get x() → self::A::T%
+    return this.{self::A::_#A#x#isSet} ?{self::A::T%} let final self::A::T? #t1 = this.{self::A::_#A#x} in #t1{self::A::T%} : throw new _in::LateInitializationErrorImpl::•("Field 'x' has not been initialized.");
+  set x(generic-covariant-impl self::A::T% #t2) → void {
+    this.{self::A::_#A#x#isSet} = true;
+    this.{self::A::_#A#x} = #t2;
+  }
+}
+class B<T extends core::Object? = dynamic> extends core::Object {
+  generic-covariant-impl field self::B::T? _y = null;
+  synthetic constructor •() → self::B<self::B::T%>
+    : super core::Object::•()
+    ;
+  get y() → self::B::T?
+    return this.{self::B::_y};
+  set y(generic-covariant-impl self::B::T? val) → void {
+    this.{self::B::_y} = val;
+  }
+}
+static method main() → dynamic {
+  self::A<core::num> a = new self::A::•<core::int>();
+  self::expect(42, a.{self::A::x} = 42);
+  self::throws(() → core::double => a.{self::A::x} = 0.5);
+  self::B<core::num> b = new self::B::•<core::int>();
+  self::expect(42, b.{self::B::y} = 42);
+  self::throws(() → core::double => b.{self::B::y} = 0.5);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → void f) → dynamic {
+  try {
+    f.call();
+  }
+  on core::Object catch(final core::Object _) {
+    return;
+  }
+  throw "Expected exception";
+}
diff --git a/pkg/front_end/testcases/late_lowering/issue42407.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/issue42407.dart.weak.transformed.expect
new file mode 100644
index 0000000..59101b9
--- /dev/null
+++ b/pkg/front_end/testcases/late_lowering/issue42407.dart.weak.transformed.expect
@@ -0,0 +1,50 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class A<T extends core::Object? = dynamic> extends core::Object {
+  generic-covariant-impl field self::A::T? _#A#x = null;
+  field core::bool _#A#x#isSet = false;
+  synthetic constructor •() → self::A<self::A::T%>
+    : super core::Object::•()
+    ;
+  get x() → self::A::T%
+    return this.{self::A::_#A#x#isSet} ?{self::A::T%} let final self::A::T? #t1 = this.{self::A::_#A#x} in #t1{self::A::T%} : throw new _in::LateInitializationErrorImpl::•("Field 'x' has not been initialized.");
+  set x(generic-covariant-impl self::A::T% #t2) → void {
+    this.{self::A::_#A#x#isSet} = true;
+    this.{self::A::_#A#x} = #t2;
+  }
+}
+class B<T extends core::Object? = dynamic> extends core::Object {
+  generic-covariant-impl field self::B::T? _y = null;
+  synthetic constructor •() → self::B<self::B::T%>
+    : super core::Object::•()
+    ;
+  get y() → self::B::T?
+    return this.{self::B::_y};
+  set y(generic-covariant-impl self::B::T? val) → void {
+    this.{self::B::_y} = val;
+  }
+}
+static method main() → dynamic {
+  self::A<core::num> a = new self::A::•<core::int>();
+  self::expect(42, a.{self::A::x} = 42);
+  self::throws(() → core::double => a.{self::A::x} = 0.5);
+  self::B<core::num> b = new self::B::•<core::int>();
+  self::expect(42, b.{self::B::y} = 42);
+  self::throws(() → core::double => b.{self::B::y} = 0.5);
+}
+static method expect(dynamic expected, dynamic actual) → dynamic {
+  if(!expected.{core::Object::==}(actual))
+    throw "Expected ${expected}, actual ${actual}";
+}
+static method throws(() → void f) → dynamic {
+  try {
+    f.call();
+  }
+  on core::Object catch(final core::Object _) {
+    return;
+  }
+  throw "Expected exception";
+}
diff --git a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.outline.expect
index e0a070f..3df6d7f 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.outline.expect
@@ -22,9 +22,9 @@
   get lateInstanceField() → core::int;
   set lateInstanceField(core::int #t3) → void;
   get lateGenericField1() → self::Class::T%;
-  set lateGenericField1(self::Class::T% #t4) → void;
+  set lateGenericField1(generic-covariant-impl self::Class::T% #t4) → void;
   get lateGenericField2() → self::Class::T%;
-  set lateGenericField2(self::Class::T% #t5) → void;
+  set lateGenericField2(generic-covariant-impl self::Class::T% #t5) → void;
   method instanceMethod(generic-covariant-impl self::Class::T% value) → dynamic
     ;
 }
diff --git a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.strong.expect
index 18cb216..4030034 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.strong.expect
@@ -38,7 +38,7 @@
     }
     return let final self::Class::T? #t7 = this.{self::Class::_#Class#lateGenericField1} in #t7{self::Class::T%};
   }
-  set lateGenericField1(self::Class::T% #t8) → void {
+  set lateGenericField1(generic-covariant-impl self::Class::T% #t8) → void {
     this.{self::Class::_#Class#lateGenericField1#isSet} = true;
     this.{self::Class::_#Class#lateGenericField1} = #t8;
   }
@@ -49,7 +49,7 @@
     }
     return let final self::Class::T? #t9 = this.{self::Class::_#Class#lateGenericField2} in #t9{self::Class::T%};
   }
-  set lateGenericField2(self::Class::T% #t10) → void {
+  set lateGenericField2(generic-covariant-impl self::Class::T% #t10) → void {
     this.{self::Class::_#Class#lateGenericField2#isSet} = true;
     this.{self::Class::_#Class#lateGenericField2} = #t10;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.strong.transformed.expect
index 18cb216..4030034 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.strong.transformed.expect
@@ -38,7 +38,7 @@
     }
     return let final self::Class::T? #t7 = this.{self::Class::_#Class#lateGenericField1} in #t7{self::Class::T%};
   }
-  set lateGenericField1(self::Class::T% #t8) → void {
+  set lateGenericField1(generic-covariant-impl self::Class::T% #t8) → void {
     this.{self::Class::_#Class#lateGenericField1#isSet} = true;
     this.{self::Class::_#Class#lateGenericField1} = #t8;
   }
@@ -49,7 +49,7 @@
     }
     return let final self::Class::T? #t9 = this.{self::Class::_#Class#lateGenericField2} in #t9{self::Class::T%};
   }
-  set lateGenericField2(self::Class::T% #t10) → void {
+  set lateGenericField2(generic-covariant-impl self::Class::T% #t10) → void {
     this.{self::Class::_#Class#lateGenericField2#isSet} = true;
     this.{self::Class::_#Class#lateGenericField2} = #t10;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.expect
index 18cb216..4030034 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.expect
@@ -38,7 +38,7 @@
     }
     return let final self::Class::T? #t7 = this.{self::Class::_#Class#lateGenericField1} in #t7{self::Class::T%};
   }
-  set lateGenericField1(self::Class::T% #t8) → void {
+  set lateGenericField1(generic-covariant-impl self::Class::T% #t8) → void {
     this.{self::Class::_#Class#lateGenericField1#isSet} = true;
     this.{self::Class::_#Class#lateGenericField1} = #t8;
   }
@@ -49,7 +49,7 @@
     }
     return let final self::Class::T? #t9 = this.{self::Class::_#Class#lateGenericField2} in #t9{self::Class::T%};
   }
-  set lateGenericField2(self::Class::T% #t10) → void {
+  set lateGenericField2(generic-covariant-impl self::Class::T% #t10) → void {
     this.{self::Class::_#Class#lateGenericField2#isSet} = true;
     this.{self::Class::_#Class#lateGenericField2} = #t10;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.transformed.expect
index 18cb216..4030034 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_with_initializer.dart.weak.transformed.expect
@@ -38,7 +38,7 @@
     }
     return let final self::Class::T? #t7 = this.{self::Class::_#Class#lateGenericField1} in #t7{self::Class::T%};
   }
-  set lateGenericField1(self::Class::T% #t8) → void {
+  set lateGenericField1(generic-covariant-impl self::Class::T% #t8) → void {
     this.{self::Class::_#Class#lateGenericField1#isSet} = true;
     this.{self::Class::_#Class#lateGenericField1} = #t8;
   }
@@ -49,7 +49,7 @@
     }
     return let final self::Class::T? #t9 = this.{self::Class::_#Class#lateGenericField2} in #t9{self::Class::T%};
   }
-  set lateGenericField2(self::Class::T% #t10) → void {
+  set lateGenericField2(generic-covariant-impl self::Class::T% #t10) → void {
     this.{self::Class::_#Class#lateGenericField2#isSet} = true;
     this.{self::Class::_#Class#lateGenericField2} = #t10;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.outline.expect
index 10a2e03..4eeb05b 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.outline.expect
@@ -19,7 +19,7 @@
   get lateInstanceField() → core::int;
   set lateInstanceField(core::int #t3) → void;
   get lateGenericInstanceField() → self::Class::T%;
-  set lateGenericInstanceField(self::Class::T% #t4) → void;
+  set lateGenericInstanceField(generic-covariant-impl self::Class::T% #t4) → void;
   method instanceMethod(generic-covariant-impl self::Class::T% value) → dynamic
     ;
 }
diff --git a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.expect
index 4d78e46..28513d18 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.expect
@@ -31,7 +31,7 @@
     this.{self::Class::_#Class#lateInstanceField} = #t6;
   get lateGenericInstanceField() → self::Class::T%
     return this.{self::Class::_#Class#lateGenericInstanceField#isSet} ?{self::Class::T%} let final self::Class::T? #t7 = this.{self::Class::_#Class#lateGenericInstanceField} in #t7{self::Class::T%} : throw new _in::LateInitializationErrorImpl::•("Field 'lateGenericInstanceField' has not been initialized.");
-  set lateGenericInstanceField(self::Class::T% #t8) → void {
+  set lateGenericInstanceField(generic-covariant-impl self::Class::T% #t8) → void {
     this.{self::Class::_#Class#lateGenericInstanceField#isSet} = true;
     this.{self::Class::_#Class#lateGenericInstanceField} = #t8;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.transformed.expect
index 4d78e46..28513d18 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.strong.transformed.expect
@@ -31,7 +31,7 @@
     this.{self::Class::_#Class#lateInstanceField} = #t6;
   get lateGenericInstanceField() → self::Class::T%
     return this.{self::Class::_#Class#lateGenericInstanceField#isSet} ?{self::Class::T%} let final self::Class::T? #t7 = this.{self::Class::_#Class#lateGenericInstanceField} in #t7{self::Class::T%} : throw new _in::LateInitializationErrorImpl::•("Field 'lateGenericInstanceField' has not been initialized.");
-  set lateGenericInstanceField(self::Class::T% #t8) → void {
+  set lateGenericInstanceField(generic-covariant-impl self::Class::T% #t8) → void {
     this.{self::Class::_#Class#lateGenericInstanceField#isSet} = true;
     this.{self::Class::_#Class#lateGenericInstanceField} = #t8;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.expect
index 4d78e46..28513d18 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.expect
@@ -31,7 +31,7 @@
     this.{self::Class::_#Class#lateInstanceField} = #t6;
   get lateGenericInstanceField() → self::Class::T%
     return this.{self::Class::_#Class#lateGenericInstanceField#isSet} ?{self::Class::T%} let final self::Class::T? #t7 = this.{self::Class::_#Class#lateGenericInstanceField} in #t7{self::Class::T%} : throw new _in::LateInitializationErrorImpl::•("Field 'lateGenericInstanceField' has not been initialized.");
-  set lateGenericInstanceField(self::Class::T% #t8) → void {
+  set lateGenericInstanceField(generic-covariant-impl self::Class::T% #t8) → void {
     this.{self::Class::_#Class#lateGenericInstanceField#isSet} = true;
     this.{self::Class::_#Class#lateGenericInstanceField} = #t8;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.transformed.expect
index 4d78e46..28513d18 100644
--- a/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_field_without_initializer.dart.weak.transformed.expect
@@ -31,7 +31,7 @@
     this.{self::Class::_#Class#lateInstanceField} = #t6;
   get lateGenericInstanceField() → self::Class::T%
     return this.{self::Class::_#Class#lateGenericInstanceField#isSet} ?{self::Class::T%} let final self::Class::T? #t7 = this.{self::Class::_#Class#lateGenericInstanceField} in #t7{self::Class::T%} : throw new _in::LateInitializationErrorImpl::•("Field 'lateGenericInstanceField' has not been initialized.");
-  set lateGenericInstanceField(self::Class::T% #t8) → void {
+  set lateGenericInstanceField(generic-covariant-impl self::Class::T% #t8) → void {
     this.{self::Class::_#Class#lateGenericInstanceField#isSet} = true;
     this.{self::Class::_#Class#lateGenericInstanceField} = #t8;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_future_or.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_future_or.dart.outline.expect
index ac02afe..14dcaea 100644
--- a/pkg/front_end/testcases/late_lowering/late_future_or.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_future_or.dart.outline.expect
@@ -22,11 +22,11 @@
   get field2() → FutureOr<dynamic>?;
   set field2(FutureOr<dynamic>? #t2) → void;
   get field3() → FutureOr<self::C::T%>;
-  set field3(FutureOr<self::C::T%>#t3) → void;
+  set field3(generic-covariant-impl FutureOr<self::C::T%>#t3) → void;
   get field4() → FutureOr<self::C::T?>;
-  set field4(FutureOr<self::C::T?>#t4) → void;
+  set field4(generic-covariant-impl FutureOr<self::C::T?>#t4) → void;
   get field5() → FutureOr<self::C::T?>?;
-  set field5(FutureOr<self::C::T?>? #t5) → void;
+  set field5(generic-covariant-impl FutureOr<self::C::T?>? #t5) → void;
   method method() → dynamic
     ;
 }
diff --git a/pkg/front_end/testcases/late_lowering/late_future_or.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_future_or.dart.strong.expect
index c8d8ea6..6a5587c 100644
--- a/pkg/front_end/testcases/late_lowering/late_future_or.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_future_or.dart.strong.expect
@@ -33,19 +33,19 @@
   }
   get field3() → FutureOr<self::C::T%>
     return this.{self::C::_#C#field3#isSet} ?{FutureOr<self::C::T%>} let final FutureOr<self::C::T%>? #t3 = this.{self::C::_#C#field3} in #t3{FutureOr<self::C::T%>} : throw new _in::LateInitializationErrorImpl::•("Field 'field3' has not been initialized.");
-  set field3(FutureOr<self::C::T%>#t4) → void {
+  set field3(generic-covariant-impl FutureOr<self::C::T%>#t4) → void {
     this.{self::C::_#C#field3#isSet} = true;
     this.{self::C::_#C#field3} = #t4;
   }
   get field4() → FutureOr<self::C::T?>
     return this.{self::C::_#C#field4#isSet} ?{FutureOr<self::C::T?>} this.{self::C::_#C#field4} : throw new _in::LateInitializationErrorImpl::•("Field 'field4' has not been initialized.");
-  set field4(FutureOr<self::C::T?>#t5) → void {
+  set field4(generic-covariant-impl FutureOr<self::C::T?>#t5) → void {
     this.{self::C::_#C#field4#isSet} = true;
     this.{self::C::_#C#field4} = #t5;
   }
   get field5() → FutureOr<self::C::T?>?
     return this.{self::C::_#C#field5#isSet} ?{FutureOr<self::C::T?>?} this.{self::C::_#C#field5} : throw new _in::LateInitializationErrorImpl::•("Field 'field5' has not been initialized.");
-  set field5(FutureOr<self::C::T?>? #t6) → void {
+  set field5(generic-covariant-impl FutureOr<self::C::T?>? #t6) → void {
     this.{self::C::_#C#field5#isSet} = true;
     this.{self::C::_#C#field5} = #t6;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_future_or.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_future_or.dart.strong.transformed.expect
index c8d8ea6..6a5587c 100644
--- a/pkg/front_end/testcases/late_lowering/late_future_or.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_future_or.dart.strong.transformed.expect
@@ -33,19 +33,19 @@
   }
   get field3() → FutureOr<self::C::T%>
     return this.{self::C::_#C#field3#isSet} ?{FutureOr<self::C::T%>} let final FutureOr<self::C::T%>? #t3 = this.{self::C::_#C#field3} in #t3{FutureOr<self::C::T%>} : throw new _in::LateInitializationErrorImpl::•("Field 'field3' has not been initialized.");
-  set field3(FutureOr<self::C::T%>#t4) → void {
+  set field3(generic-covariant-impl FutureOr<self::C::T%>#t4) → void {
     this.{self::C::_#C#field3#isSet} = true;
     this.{self::C::_#C#field3} = #t4;
   }
   get field4() → FutureOr<self::C::T?>
     return this.{self::C::_#C#field4#isSet} ?{FutureOr<self::C::T?>} this.{self::C::_#C#field4} : throw new _in::LateInitializationErrorImpl::•("Field 'field4' has not been initialized.");
-  set field4(FutureOr<self::C::T?>#t5) → void {
+  set field4(generic-covariant-impl FutureOr<self::C::T?>#t5) → void {
     this.{self::C::_#C#field4#isSet} = true;
     this.{self::C::_#C#field4} = #t5;
   }
   get field5() → FutureOr<self::C::T?>?
     return this.{self::C::_#C#field5#isSet} ?{FutureOr<self::C::T?>?} this.{self::C::_#C#field5} : throw new _in::LateInitializationErrorImpl::•("Field 'field5' has not been initialized.");
-  set field5(FutureOr<self::C::T?>? #t6) → void {
+  set field5(generic-covariant-impl FutureOr<self::C::T?>? #t6) → void {
     this.{self::C::_#C#field5#isSet} = true;
     this.{self::C::_#C#field5} = #t6;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_future_or.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_future_or.dart.weak.expect
index c8d8ea6..6a5587c 100644
--- a/pkg/front_end/testcases/late_lowering/late_future_or.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_future_or.dart.weak.expect
@@ -33,19 +33,19 @@
   }
   get field3() → FutureOr<self::C::T%>
     return this.{self::C::_#C#field3#isSet} ?{FutureOr<self::C::T%>} let final FutureOr<self::C::T%>? #t3 = this.{self::C::_#C#field3} in #t3{FutureOr<self::C::T%>} : throw new _in::LateInitializationErrorImpl::•("Field 'field3' has not been initialized.");
-  set field3(FutureOr<self::C::T%>#t4) → void {
+  set field3(generic-covariant-impl FutureOr<self::C::T%>#t4) → void {
     this.{self::C::_#C#field3#isSet} = true;
     this.{self::C::_#C#field3} = #t4;
   }
   get field4() → FutureOr<self::C::T?>
     return this.{self::C::_#C#field4#isSet} ?{FutureOr<self::C::T?>} this.{self::C::_#C#field4} : throw new _in::LateInitializationErrorImpl::•("Field 'field4' has not been initialized.");
-  set field4(FutureOr<self::C::T?>#t5) → void {
+  set field4(generic-covariant-impl FutureOr<self::C::T?>#t5) → void {
     this.{self::C::_#C#field4#isSet} = true;
     this.{self::C::_#C#field4} = #t5;
   }
   get field5() → FutureOr<self::C::T?>?
     return this.{self::C::_#C#field5#isSet} ?{FutureOr<self::C::T?>?} this.{self::C::_#C#field5} : throw new _in::LateInitializationErrorImpl::•("Field 'field5' has not been initialized.");
-  set field5(FutureOr<self::C::T?>? #t6) → void {
+  set field5(generic-covariant-impl FutureOr<self::C::T?>? #t6) → void {
     this.{self::C::_#C#field5#isSet} = true;
     this.{self::C::_#C#field5} = #t6;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_future_or.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_future_or.dart.weak.transformed.expect
index c8d8ea6..6a5587c 100644
--- a/pkg/front_end/testcases/late_lowering/late_future_or.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_future_or.dart.weak.transformed.expect
@@ -33,19 +33,19 @@
   }
   get field3() → FutureOr<self::C::T%>
     return this.{self::C::_#C#field3#isSet} ?{FutureOr<self::C::T%>} let final FutureOr<self::C::T%>? #t3 = this.{self::C::_#C#field3} in #t3{FutureOr<self::C::T%>} : throw new _in::LateInitializationErrorImpl::•("Field 'field3' has not been initialized.");
-  set field3(FutureOr<self::C::T%>#t4) → void {
+  set field3(generic-covariant-impl FutureOr<self::C::T%>#t4) → void {
     this.{self::C::_#C#field3#isSet} = true;
     this.{self::C::_#C#field3} = #t4;
   }
   get field4() → FutureOr<self::C::T?>
     return this.{self::C::_#C#field4#isSet} ?{FutureOr<self::C::T?>} this.{self::C::_#C#field4} : throw new _in::LateInitializationErrorImpl::•("Field 'field4' has not been initialized.");
-  set field4(FutureOr<self::C::T?>#t5) → void {
+  set field4(generic-covariant-impl FutureOr<self::C::T?>#t5) → void {
     this.{self::C::_#C#field4#isSet} = true;
     this.{self::C::_#C#field4} = #t5;
   }
   get field5() → FutureOr<self::C::T?>?
     return this.{self::C::_#C#field5#isSet} ?{FutureOr<self::C::T?>?} this.{self::C::_#C#field5} : throw new _in::LateInitializationErrorImpl::•("Field 'field5' has not been initialized.");
-  set field5(FutureOr<self::C::T?>? #t6) → void {
+  set field5(generic-covariant-impl FutureOr<self::C::T?>? #t6) → void {
     this.{self::C::_#C#field5#isSet} = true;
     this.{self::C::_#C#field5} = #t6;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.outline.expect
index f377c7e..995658d 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.outline.expect
@@ -31,7 +31,7 @@
   method lateGenericInstanceFieldInit() → self::Class::T?
     ;
   get lateGenericInstanceField() → self::Class::T?;
-  set lateGenericInstanceField(self::Class::T? #t4) → void;
+  set lateGenericInstanceField(generic-covariant-impl self::Class::T? #t4) → void;
   method instanceMethod(generic-covariant-impl self::Class::T? value) → dynamic
     ;
 }
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.strong.expect
index e44eb03..36b9cb9 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.strong.expect
@@ -68,7 +68,7 @@
     }
     return this.{self::Class::_#Class#lateGenericInstanceField};
   }
-  set lateGenericInstanceField(self::Class::T? #t4) → void {
+  set lateGenericInstanceField(generic-covariant-impl self::Class::T? #t4) → void {
     this.{self::Class::_#Class#lateGenericInstanceField#isSet} = true;
     this.{self::Class::_#Class#lateGenericInstanceField} = #t4;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.strong.transformed.expect
index e44eb03..36b9cb9 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.strong.transformed.expect
@@ -68,7 +68,7 @@
     }
     return this.{self::Class::_#Class#lateGenericInstanceField};
   }
-  set lateGenericInstanceField(self::Class::T? #t4) → void {
+  set lateGenericInstanceField(generic-covariant-impl self::Class::T? #t4) → void {
     this.{self::Class::_#Class#lateGenericInstanceField#isSet} = true;
     this.{self::Class::_#Class#lateGenericInstanceField} = #t4;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.weak.expect
index e44eb03..36b9cb9 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.weak.expect
@@ -68,7 +68,7 @@
     }
     return this.{self::Class::_#Class#lateGenericInstanceField};
   }
-  set lateGenericInstanceField(self::Class::T? #t4) → void {
+  set lateGenericInstanceField(generic-covariant-impl self::Class::T? #t4) → void {
     this.{self::Class::_#Class#lateGenericInstanceField#isSet} = true;
     this.{self::Class::_#Class#lateGenericInstanceField} = #t4;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.weak.transformed.expect
index e44eb03..36b9cb9 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_with_initializer.dart.weak.transformed.expect
@@ -68,7 +68,7 @@
     }
     return this.{self::Class::_#Class#lateGenericInstanceField};
   }
-  set lateGenericInstanceField(self::Class::T? #t4) → void {
+  set lateGenericInstanceField(generic-covariant-impl self::Class::T? #t4) → void {
     this.{self::Class::_#Class#lateGenericInstanceField#isSet} = true;
     this.{self::Class::_#Class#lateGenericInstanceField} = #t4;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.outline.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.outline.expect
index b5c1e15..b36f1a2 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.outline.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.outline.expect
@@ -22,7 +22,7 @@
   get lateInstanceField() → core::int?;
   set lateInstanceField(core::int? #t3) → void;
   get lateGenericInstanceField() → self::Class::T?;
-  set lateGenericInstanceField(self::Class::T? #t4) → void;
+  set lateGenericInstanceField(generic-covariant-impl self::Class::T? #t4) → void;
   method instanceMethod(generic-covariant-impl self::Class::T? value) → dynamic
     ;
 }
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.expect
index f0bc8b7..fe6ab5e 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.expect
@@ -40,7 +40,7 @@
   }
   get lateGenericInstanceField() → self::Class::T?
     return this.{self::Class::_#Class#lateGenericInstanceField#isSet} ?{self::Class::T?} this.{self::Class::_#Class#lateGenericInstanceField} : throw new _in::LateInitializationErrorImpl::•("Field 'lateGenericInstanceField' has not been initialized.");
-  set lateGenericInstanceField(self::Class::T? #t4) → void {
+  set lateGenericInstanceField(generic-covariant-impl self::Class::T? #t4) → void {
     this.{self::Class::_#Class#lateGenericInstanceField#isSet} = true;
     this.{self::Class::_#Class#lateGenericInstanceField} = #t4;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.transformed.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.transformed.expect
index f0bc8b7..fe6ab5e 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.strong.transformed.expect
@@ -40,7 +40,7 @@
   }
   get lateGenericInstanceField() → self::Class::T?
     return this.{self::Class::_#Class#lateGenericInstanceField#isSet} ?{self::Class::T?} this.{self::Class::_#Class#lateGenericInstanceField} : throw new _in::LateInitializationErrorImpl::•("Field 'lateGenericInstanceField' has not been initialized.");
-  set lateGenericInstanceField(self::Class::T? #t4) → void {
+  set lateGenericInstanceField(generic-covariant-impl self::Class::T? #t4) → void {
     this.{self::Class::_#Class#lateGenericInstanceField#isSet} = true;
     this.{self::Class::_#Class#lateGenericInstanceField} = #t4;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.expect
index f0bc8b7..fe6ab5e 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.expect
@@ -40,7 +40,7 @@
   }
   get lateGenericInstanceField() → self::Class::T?
     return this.{self::Class::_#Class#lateGenericInstanceField#isSet} ?{self::Class::T?} this.{self::Class::_#Class#lateGenericInstanceField} : throw new _in::LateInitializationErrorImpl::•("Field 'lateGenericInstanceField' has not been initialized.");
-  set lateGenericInstanceField(self::Class::T? #t4) → void {
+  set lateGenericInstanceField(generic-covariant-impl self::Class::T? #t4) → void {
     this.{self::Class::_#Class#lateGenericInstanceField#isSet} = true;
     this.{self::Class::_#Class#lateGenericInstanceField} = #t4;
   }
diff --git a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.transformed.expect b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.transformed.expect
index f0bc8b7..fe6ab5e 100644
--- a/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/late_lowering/late_nullable_field_without_initializer.dart.weak.transformed.expect
@@ -40,7 +40,7 @@
   }
   get lateGenericInstanceField() → self::Class::T?
     return this.{self::Class::_#Class#lateGenericInstanceField#isSet} ?{self::Class::T?} this.{self::Class::_#Class#lateGenericInstanceField} : throw new _in::LateInitializationErrorImpl::•("Field 'lateGenericInstanceField' has not been initialized.");
-  set lateGenericInstanceField(self::Class::T? #t4) → void {
+  set lateGenericInstanceField(generic-covariant-impl self::Class::T? #t4) → void {
     this.{self::Class::_#Class#lateGenericInstanceField#isSet} = true;
     this.{self::Class::_#Class#lateGenericInstanceField} = #t4;
   }
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue42387/foundation_basic_types_lib.dart b/pkg/front_end/testcases/nnbd_mixed/issue42387/foundation_basic_types_lib.dart
new file mode 100644
index 0000000..c2736fd
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/issue42387/foundation_basic_types_lib.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart = 2.9
+
+typedef Future<Null> AsyncCallback();
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue42387/foundation_basic_types_lib.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/issue42387/foundation_basic_types_lib.dart.weak.expect
new file mode 100644
index 0000000..4d3ffdd
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/issue42387/foundation_basic_types_lib.dart.weak.expect
@@ -0,0 +1,129 @@
+library;
+import self as self;
+import "foundation_binding_lib.dart" as fou;
+import "scheduler_binding_lib.dart" as sch;
+import "services_binding_lib.dart" as ser;
+
+import "org-dartlang-testcase:///foundation_lib.dart";
+import "org-dartlang-testcase:///services_lib.dart";
+import "org-dartlang-testcase:///scheduler_lib.dart";
+
+abstract class _TestSchedulerBinding&BindingBase&SchedulerBinding = fou::BindingBase with sch::SchedulerBinding /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_TestSchedulerBinding&BindingBase&SchedulerBinding*
+    : super fou::BindingBase::•()
+    ;
+}
+abstract class _TestSchedulerBinding&BindingBase&SchedulerBinding&ServicesBinding = self::_TestSchedulerBinding&BindingBase&SchedulerBinding with ser::ServicesBinding /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_TestSchedulerBinding&BindingBase&SchedulerBinding&ServicesBinding*
+    : super self::_TestSchedulerBinding&BindingBase&SchedulerBinding::•()
+    ;
+}
+class TestSchedulerBinding extends self::_TestSchedulerBinding&BindingBase&SchedulerBinding&ServicesBinding {
+  synthetic constructor •() → self::TestSchedulerBinding*
+    : super self::_TestSchedulerBinding&BindingBase&SchedulerBinding&ServicesBinding::•()
+    ;
+}
+static method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+import self as self2;
+import "dart:async" as asy;
+import "dart:core" as core;
+
+typedef AsyncCallback = () → asy::Future<core::Null?>;
+
+library /*isNonNullableByDefault*/;
+import self as fou;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+import "org-dartlang-testcase:///foundation_basic_types_lib.dart";
+
+abstract class BindingBase extends core::Object {
+  synthetic constructor •() → fou::BindingBase
+    : super core::Object::•()
+    ;
+  method registerSignalServiceExtension({required core::String name = #C1, required () → asy::Future<core::Null?> callback = #C1}) → void {}
+}
+
+library;
+import self as self3;
+import "foundation_basic_types_lib.dart" as self2;
+import "foundation_binding_lib.dart" as fou;
+additionalExports = (self2::AsyncCallback,
+  fou::BindingBase)
+
+export "org-dartlang-testcase:///foundation_basic_types_lib.dart";
+export "org-dartlang-testcase:///foundation_binding_lib.dart";
+
+
+library;
+import self as sch;
+import "foundation_binding_lib.dart" as fou;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+import "org-dartlang-testcase:///foundation_lib.dart";
+
+abstract class SchedulerBinding extends fou::BindingBase /*isMixinDeclaration*/  {
+  abstract member-signature method registerSignalServiceExtension({core::String* name = #C1, () →* asy::Future<core::Null?>* callback = #C1}) → void;
+  abstract member-signature get _identityHashCode() → core::int*;
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*;
+  abstract member-signature operator ==(dynamic other) → core::bool*;
+  abstract member-signature get hashCode() → core::int*;
+  abstract member-signature method toString() → core::String*;
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic;
+  abstract member-signature get runtimeType() → core::Type*;
+}
+
+library;
+import self as self4;
+import "scheduler_binding_lib.dart" as sch;
+additionalExports = (sch::SchedulerBinding)
+
+export "org-dartlang-testcase:///scheduler_binding_lib.dart";
+
+
+library;
+import self as ser;
+import "dart:core" as core;
+import "foundation_binding_lib.dart" as fou;
+import "scheduler_binding_lib.dart" as sch;
+import "dart:async" as asy;
+
+import "org-dartlang-testcase:///foundation_lib.dart";
+import "org-dartlang-testcase:///scheduler_lib.dart";
+
+abstract class _ServicesBinding&BindingBase&SchedulerBinding extends core::Object implements fou::BindingBase, sch::SchedulerBinding /*isAnonymousMixin*/  {
+  synthetic constructor •() → ser::_ServicesBinding&BindingBase&SchedulerBinding*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*;
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*;
+  abstract member-signature operator ==(dynamic other) → core::bool*;
+  abstract member-signature get hashCode() → core::int*;
+  abstract member-signature method toString() → core::String*;
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic;
+  abstract member-signature get runtimeType() → core::Type*;
+  abstract member-signature method registerSignalServiceExtension({core::String* name = #C1, () →* asy::Future<core::Null?>* callback = #C1}) → void;
+}
+abstract class ServicesBinding extends ser::_ServicesBinding&BindingBase&SchedulerBinding /*isMixinDeclaration*/  {
+}
+
+library;
+import self as self5;
+import "services_binding_lib.dart" as ser;
+additionalExports = (ser::ServicesBinding)
+
+export "org-dartlang-testcase:///services_binding_lib.dart";
+
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue42387/foundation_basic_types_lib.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/issue42387/foundation_basic_types_lib.dart.weak.transformed.expect
new file mode 100644
index 0000000..3670831
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/issue42387/foundation_basic_types_lib.dart.weak.transformed.expect
@@ -0,0 +1,142 @@
+library;
+import self as self;
+import "foundation_binding_lib.dart" as fou;
+import "scheduler_binding_lib.dart" as sch;
+import "dart:core" as core;
+import "dart:async" as asy;
+import "services_binding_lib.dart" as ser;
+
+import "org-dartlang-testcase:///foundation_lib.dart";
+import "org-dartlang-testcase:///services_lib.dart";
+import "org-dartlang-testcase:///scheduler_lib.dart";
+
+abstract class _TestSchedulerBinding&BindingBase&SchedulerBinding extends fou::BindingBase implements sch::SchedulerBinding /*isAnonymousMixin,isEliminatedMixin*/  {
+  synthetic constructor •() → self::_TestSchedulerBinding&BindingBase&SchedulerBinding*
+    : super fou::BindingBase::•()
+    ;
+  abstract member-signature method /* from org-dartlang-testcase:///scheduler_binding_lib.dart */ registerSignalServiceExtension({core::String* name = #C1, () →* asy::Future<core::Null?>* callback = #C1}) → void;
+  abstract member-signature get /* from org-dartlang-testcase:///scheduler_binding_lib.dart */ _identityHashCode() → core::int*;
+  abstract member-signature method /* from org-dartlang-testcase:///scheduler_binding_lib.dart */ _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*;
+  abstract member-signature method /* from org-dartlang-testcase:///scheduler_binding_lib.dart */ _simpleInstanceOf(dynamic type) → core::bool*;
+  abstract member-signature method /* from org-dartlang-testcase:///scheduler_binding_lib.dart */ _simpleInstanceOfTrue(dynamic type) → core::bool*;
+  abstract member-signature method /* from org-dartlang-testcase:///scheduler_binding_lib.dart */ _simpleInstanceOfFalse(dynamic type) → core::bool*;
+  abstract member-signature operator /* from org-dartlang-testcase:///scheduler_binding_lib.dart */ ==(dynamic other) → core::bool*;
+  abstract member-signature get /* from org-dartlang-testcase:///scheduler_binding_lib.dart */ hashCode() → core::int*;
+  abstract member-signature method /* from org-dartlang-testcase:///scheduler_binding_lib.dart */ toString() → core::String*;
+  abstract member-signature method /* from org-dartlang-testcase:///scheduler_binding_lib.dart */ noSuchMethod(core::Invocation* invocation) → dynamic;
+  abstract member-signature get /* from org-dartlang-testcase:///scheduler_binding_lib.dart */ runtimeType() → core::Type*;
+}
+abstract class _TestSchedulerBinding&BindingBase&SchedulerBinding&ServicesBinding extends self::_TestSchedulerBinding&BindingBase&SchedulerBinding implements ser::ServicesBinding /*isAnonymousMixin,isEliminatedMixin*/  {
+  synthetic constructor •() → self::_TestSchedulerBinding&BindingBase&SchedulerBinding&ServicesBinding*
+    : super self::_TestSchedulerBinding&BindingBase&SchedulerBinding::•()
+    ;
+}
+class TestSchedulerBinding extends self::_TestSchedulerBinding&BindingBase&SchedulerBinding&ServicesBinding {
+  synthetic constructor •() → self::TestSchedulerBinding*
+    : super self::_TestSchedulerBinding&BindingBase&SchedulerBinding&ServicesBinding::•()
+    ;
+}
+static method main() → dynamic {}
+
+library /*isNonNullableByDefault*/;
+import self as self2;
+import "dart:async" as asy;
+import "dart:core" as core;
+
+typedef AsyncCallback = () → asy::Future<core::Null?>;
+
+library /*isNonNullableByDefault*/;
+import self as fou;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+import "org-dartlang-testcase:///foundation_basic_types_lib.dart";
+
+abstract class BindingBase extends core::Object {
+  synthetic constructor •() → fou::BindingBase
+    : super core::Object::•()
+    ;
+  method registerSignalServiceExtension({required core::String name = #C1, required () → asy::Future<core::Null?> callback = #C1}) → void {}
+}
+
+library;
+import self as self3;
+import "foundation_basic_types_lib.dart" as self2;
+import "foundation_binding_lib.dart" as fou;
+additionalExports = (self2::AsyncCallback,
+  fou::BindingBase)
+
+export "org-dartlang-testcase:///foundation_basic_types_lib.dart";
+export "org-dartlang-testcase:///foundation_binding_lib.dart";
+
+
+library;
+import self as sch;
+import "foundation_binding_lib.dart" as fou;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+import "org-dartlang-testcase:///foundation_lib.dart";
+
+abstract class SchedulerBinding extends fou::BindingBase /*isMixinDeclaration*/  {
+  abstract member-signature method registerSignalServiceExtension({core::String* name = #C1, () →* asy::Future<core::Null?>* callback = #C1}) → void;
+  abstract member-signature get _identityHashCode() → core::int*;
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*;
+  abstract member-signature operator ==(dynamic other) → core::bool*;
+  abstract member-signature get hashCode() → core::int*;
+  abstract member-signature method toString() → core::String*;
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic;
+  abstract member-signature get runtimeType() → core::Type*;
+}
+
+library;
+import self as self4;
+import "scheduler_binding_lib.dart" as sch;
+additionalExports = (sch::SchedulerBinding)
+
+export "org-dartlang-testcase:///scheduler_binding_lib.dart";
+
+
+library;
+import self as ser;
+import "dart:core" as core;
+import "foundation_binding_lib.dart" as fou;
+import "scheduler_binding_lib.dart" as sch;
+import "dart:async" as asy;
+
+import "org-dartlang-testcase:///foundation_lib.dart";
+import "org-dartlang-testcase:///scheduler_lib.dart";
+
+abstract class _ServicesBinding&BindingBase&SchedulerBinding extends core::Object implements fou::BindingBase, sch::SchedulerBinding /*isAnonymousMixin*/  {
+  synthetic constructor •() → ser::_ServicesBinding&BindingBase&SchedulerBinding*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*;
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*;
+  abstract member-signature operator ==(dynamic other) → core::bool*;
+  abstract member-signature get hashCode() → core::int*;
+  abstract member-signature method toString() → core::String*;
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic;
+  abstract member-signature get runtimeType() → core::Type*;
+  abstract member-signature method registerSignalServiceExtension({core::String* name = #C1, () →* asy::Future<core::Null?>* callback = #C1}) → void;
+}
+abstract class ServicesBinding extends ser::_ServicesBinding&BindingBase&SchedulerBinding /*isMixinDeclaration*/  {
+}
+
+library;
+import self as self5;
+import "services_binding_lib.dart" as ser;
+additionalExports = (ser::ServicesBinding)
+
+export "org-dartlang-testcase:///services_binding_lib.dart";
+
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue42387/foundation_binding_lib.dart b/pkg/front_end/testcases/nnbd_mixed/issue42387/foundation_binding_lib.dart
new file mode 100644
index 0000000..a1fb380
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/issue42387/foundation_binding_lib.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart = 2.9
+
+import 'foundation_basic_types_lib.dart';
+
+abstract class BindingBase {
+  void registerSignalServiceExtension(
+      {required String name, required AsyncCallback callback}) {}
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue42387/foundation_lib.dart b/pkg/front_end/testcases/nnbd_mixed/issue42387/foundation_lib.dart
new file mode 100644
index 0000000..65bff9e
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/issue42387/foundation_lib.dart
@@ -0,0 +1,8 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart=2.8
+
+export 'foundation_basic_types_lib.dart';
+export 'foundation_binding_lib.dart';
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue42387/link.options b/pkg/front_end/testcases/nnbd_mixed/issue42387/link.options
new file mode 100644
index 0000000..a8d1069
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/issue42387/link.options
@@ -0,0 +1,7 @@
+foundation_basic_types_lib.dart
+foundation_binding_lib.dart
+foundation_lib.dart
+scheduler_binding_lib.dart
+scheduler_lib.dart
+services_binding_lib.dart
+services_lib.dart
\ No newline at end of file
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue42387/scheduler_binding_lib.dart b/pkg/front_end/testcases/nnbd_mixed/issue42387/scheduler_binding_lib.dart
new file mode 100644
index 0000000..66baa12
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/issue42387/scheduler_binding_lib.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart = 2.8
+
+import 'foundation_lib.dart';
+
+//abstract class SchedulerBinding extends BindingBase with ServicesBinding {}
+mixin SchedulerBinding on BindingBase {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue42387/scheduler_lib.dart b/pkg/front_end/testcases/nnbd_mixed/issue42387/scheduler_lib.dart
new file mode 100644
index 0000000..3e8e8e8
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/issue42387/scheduler_lib.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart=2.8
+
+export 'scheduler_binding_lib.dart';
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue42387/scheduler_tester.dart b/pkg/front_end/testcases/nnbd_mixed/issue42387/scheduler_tester.dart
new file mode 100644
index 0000000..335e5d3
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/issue42387/scheduler_tester.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart = 2.8
+
+import 'foundation_lib.dart';
+import 'services_lib.dart';
+import 'scheduler_lib.dart';
+
+class TestSchedulerBinding extends BindingBase
+    with SchedulerBinding, ServicesBinding {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue42387/scheduler_tester.dart.textual_outline.expect b/pkg/front_end/testcases/nnbd_mixed/issue42387/scheduler_tester.dart.textual_outline.expect
new file mode 100644
index 0000000..2ee5d32
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/issue42387/scheduler_tester.dart.textual_outline.expect
@@ -0,0 +1,9 @@
+// @dart = 2.8
+import 'foundation_lib.dart';
+import 'services_lib.dart';
+import 'scheduler_lib.dart';
+
+class TestSchedulerBinding extends BindingBase
+    with SchedulerBinding, ServicesBinding {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue42387/scheduler_tester.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/nnbd_mixed/issue42387/scheduler_tester.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..2ee5d32
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/issue42387/scheduler_tester.dart.textual_outline_modelled.expect
@@ -0,0 +1,9 @@
+// @dart = 2.8
+import 'foundation_lib.dart';
+import 'services_lib.dart';
+import 'scheduler_lib.dart';
+
+class TestSchedulerBinding extends BindingBase
+    with SchedulerBinding, ServicesBinding {}
+
+main() {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue42387/scheduler_tester.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/issue42387/scheduler_tester.dart.weak.expect
new file mode 100644
index 0000000..dcefbab
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/issue42387/scheduler_tester.dart.weak.expect
@@ -0,0 +1,142 @@
+library;
+import self as self;
+import "foundation_binding_lib.dart" as fou;
+import "scheduler_binding_lib.dart" as sch;
+import "dart:core" as core;
+import "dart:async" as asy;
+import "services_binding_lib.dart" as ser;
+
+import "org-dartlang-testcase:///foundation_lib.dart";
+import "org-dartlang-testcase:///services_lib.dart";
+import "org-dartlang-testcase:///scheduler_lib.dart";
+
+abstract class _TestSchedulerBinding&BindingBase&SchedulerBinding = fou::BindingBase with sch::SchedulerBinding /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_TestSchedulerBinding&BindingBase&SchedulerBinding*
+    : super fou::BindingBase::•()
+    ;
+  abstract member-signature method registerSignalServiceExtension({core::String* name = #C1, () →* asy::Future<core::Null?>* callback = #C1}) → void;
+  abstract member-signature get _identityHashCode() → core::int*;
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*;
+  abstract member-signature operator ==(dynamic other) → core::bool*;
+  abstract member-signature get hashCode() → core::int*;
+  abstract member-signature method toString() → core::String*;
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic;
+  abstract member-signature get runtimeType() → core::Type*;
+}
+abstract class _TestSchedulerBinding&BindingBase&SchedulerBinding&ServicesBinding = self::_TestSchedulerBinding&BindingBase&SchedulerBinding with ser::ServicesBinding /*isAnonymousMixin*/  {
+  synthetic constructor •() → self::_TestSchedulerBinding&BindingBase&SchedulerBinding&ServicesBinding*
+    : super self::_TestSchedulerBinding&BindingBase&SchedulerBinding::•()
+    ;
+}
+class TestSchedulerBinding extends self::_TestSchedulerBinding&BindingBase&SchedulerBinding&ServicesBinding {
+  synthetic constructor •() → self::TestSchedulerBinding*
+    : super self::_TestSchedulerBinding&BindingBase&SchedulerBinding&ServicesBinding::•()
+    ;
+}
+static method main() → dynamic {}
+
+library;
+import self as self2;
+import "foundation_basic_types_lib.dart" as fou2;
+import "foundation_binding_lib.dart" as fou;
+additionalExports = (fou2::AsyncCallback,
+  fou::BindingBase)
+
+export "org-dartlang-testcase:///foundation_basic_types_lib.dart";
+export "org-dartlang-testcase:///foundation_binding_lib.dart";
+
+
+library;
+import self as self3;
+import "services_binding_lib.dart" as ser;
+additionalExports = (ser::ServicesBinding)
+
+export "org-dartlang-testcase:///services_binding_lib.dart";
+
+
+library;
+import self as self4;
+import "scheduler_binding_lib.dart" as sch;
+additionalExports = (sch::SchedulerBinding)
+
+export "org-dartlang-testcase:///scheduler_binding_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as fou2;
+import "dart:async" as asy;
+import "dart:core" as core;
+
+typedef AsyncCallback = () → asy::Future<core::Null?>;
+
+library /*isNonNullableByDefault*/;
+import self as fou;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+import "org-dartlang-testcase:///foundation_basic_types_lib.dart";
+
+abstract class BindingBase extends core::Object {
+  synthetic constructor •() → fou::BindingBase
+    : super core::Object::•()
+    ;
+  method registerSignalServiceExtension({required core::String name = #C1, required () → asy::Future<core::Null?> callback = #C1}) → void {}
+}
+
+library;
+import self as ser;
+import "dart:core" as core;
+import "foundation_binding_lib.dart" as fou;
+import "scheduler_binding_lib.dart" as sch;
+import "dart:async" as asy;
+
+import "org-dartlang-testcase:///foundation_lib.dart";
+import "org-dartlang-testcase:///scheduler_lib.dart";
+
+abstract class _ServicesBinding&BindingBase&SchedulerBinding extends core::Object implements fou::BindingBase, sch::SchedulerBinding /*isAnonymousMixin*/  {
+  synthetic constructor •() → ser::_ServicesBinding&BindingBase&SchedulerBinding*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*;
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*;
+  abstract member-signature operator ==(dynamic other) → core::bool*;
+  abstract member-signature get hashCode() → core::int*;
+  abstract member-signature method toString() → core::String*;
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic;
+  abstract member-signature get runtimeType() → core::Type*;
+  abstract member-signature method registerSignalServiceExtension({core::String* name = #C1, () →* asy::Future<core::Null?>* callback = #C1}) → void;
+}
+abstract class ServicesBinding extends ser::_ServicesBinding&BindingBase&SchedulerBinding /*isMixinDeclaration*/  {
+}
+
+library;
+import self as sch;
+import "foundation_binding_lib.dart" as fou;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+import "org-dartlang-testcase:///foundation_lib.dart";
+
+abstract class SchedulerBinding extends fou::BindingBase /*isMixinDeclaration*/  {
+  abstract member-signature method registerSignalServiceExtension({core::String* name = #C1, () →* asy::Future<core::Null?>* callback = #C1}) → void;
+  abstract member-signature get _identityHashCode() → core::int*;
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*;
+  abstract member-signature operator ==(dynamic other) → core::bool*;
+  abstract member-signature get hashCode() → core::int*;
+  abstract member-signature method toString() → core::String*;
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic;
+  abstract member-signature get runtimeType() → core::Type*;
+}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue42387/scheduler_tester.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/issue42387/scheduler_tester.dart.weak.transformed.expect
new file mode 100644
index 0000000..bdc0c68
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/issue42387/scheduler_tester.dart.weak.transformed.expect
@@ -0,0 +1,142 @@
+library;
+import self as self;
+import "foundation_binding_lib.dart" as fou;
+import "scheduler_binding_lib.dart" as sch;
+import "dart:core" as core;
+import "dart:async" as asy;
+import "services_binding_lib.dart" as ser;
+
+import "org-dartlang-testcase:///foundation_lib.dart";
+import "org-dartlang-testcase:///services_lib.dart";
+import "org-dartlang-testcase:///scheduler_lib.dart";
+
+abstract class _TestSchedulerBinding&BindingBase&SchedulerBinding extends fou::BindingBase implements sch::SchedulerBinding /*isAnonymousMixin,isEliminatedMixin*/  {
+  synthetic constructor •() → self::_TestSchedulerBinding&BindingBase&SchedulerBinding*
+    : super fou::BindingBase::•()
+    ;
+  abstract member-signature method /* from org-dartlang-testcase:///scheduler_binding_lib.dart */ registerSignalServiceExtension({core::String* name = #C1, () →* asy::Future<core::Null?>* callback = #C1}) → void;
+  abstract member-signature get /* from org-dartlang-testcase:///scheduler_binding_lib.dart */ _identityHashCode() → core::int*;
+  abstract member-signature method /* from org-dartlang-testcase:///scheduler_binding_lib.dart */ _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*;
+  abstract member-signature method /* from org-dartlang-testcase:///scheduler_binding_lib.dart */ _simpleInstanceOf(dynamic type) → core::bool*;
+  abstract member-signature method /* from org-dartlang-testcase:///scheduler_binding_lib.dart */ _simpleInstanceOfTrue(dynamic type) → core::bool*;
+  abstract member-signature method /* from org-dartlang-testcase:///scheduler_binding_lib.dart */ _simpleInstanceOfFalse(dynamic type) → core::bool*;
+  abstract member-signature operator /* from org-dartlang-testcase:///scheduler_binding_lib.dart */ ==(dynamic other) → core::bool*;
+  abstract member-signature get /* from org-dartlang-testcase:///scheduler_binding_lib.dart */ hashCode() → core::int*;
+  abstract member-signature method /* from org-dartlang-testcase:///scheduler_binding_lib.dart */ toString() → core::String*;
+  abstract member-signature method /* from org-dartlang-testcase:///scheduler_binding_lib.dart */ noSuchMethod(core::Invocation* invocation) → dynamic;
+  abstract member-signature get /* from org-dartlang-testcase:///scheduler_binding_lib.dart */ runtimeType() → core::Type*;
+}
+abstract class _TestSchedulerBinding&BindingBase&SchedulerBinding&ServicesBinding extends self::_TestSchedulerBinding&BindingBase&SchedulerBinding implements ser::ServicesBinding /*isAnonymousMixin,isEliminatedMixin*/  {
+  synthetic constructor •() → self::_TestSchedulerBinding&BindingBase&SchedulerBinding&ServicesBinding*
+    : super self::_TestSchedulerBinding&BindingBase&SchedulerBinding::•()
+    ;
+}
+class TestSchedulerBinding extends self::_TestSchedulerBinding&BindingBase&SchedulerBinding&ServicesBinding {
+  synthetic constructor •() → self::TestSchedulerBinding*
+    : super self::_TestSchedulerBinding&BindingBase&SchedulerBinding&ServicesBinding::•()
+    ;
+}
+static method main() → dynamic {}
+
+library;
+import self as self2;
+import "foundation_basic_types_lib.dart" as fou2;
+import "foundation_binding_lib.dart" as fou;
+additionalExports = (fou2::AsyncCallback,
+  fou::BindingBase)
+
+export "org-dartlang-testcase:///foundation_basic_types_lib.dart";
+export "org-dartlang-testcase:///foundation_binding_lib.dart";
+
+
+library;
+import self as self3;
+import "services_binding_lib.dart" as ser;
+additionalExports = (ser::ServicesBinding)
+
+export "org-dartlang-testcase:///services_binding_lib.dart";
+
+
+library;
+import self as self4;
+import "scheduler_binding_lib.dart" as sch;
+additionalExports = (sch::SchedulerBinding)
+
+export "org-dartlang-testcase:///scheduler_binding_lib.dart";
+
+
+library /*isNonNullableByDefault*/;
+import self as fou2;
+import "dart:async" as asy;
+import "dart:core" as core;
+
+typedef AsyncCallback = () → asy::Future<core::Null?>;
+
+library /*isNonNullableByDefault*/;
+import self as fou;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+import "org-dartlang-testcase:///foundation_basic_types_lib.dart";
+
+abstract class BindingBase extends core::Object {
+  synthetic constructor •() → fou::BindingBase
+    : super core::Object::•()
+    ;
+  method registerSignalServiceExtension({required core::String name = #C1, required () → asy::Future<core::Null?> callback = #C1}) → void {}
+}
+
+library;
+import self as ser;
+import "dart:core" as core;
+import "foundation_binding_lib.dart" as fou;
+import "scheduler_binding_lib.dart" as sch;
+import "dart:async" as asy;
+
+import "org-dartlang-testcase:///foundation_lib.dart";
+import "org-dartlang-testcase:///scheduler_lib.dart";
+
+abstract class _ServicesBinding&BindingBase&SchedulerBinding extends core::Object implements fou::BindingBase, sch::SchedulerBinding /*isAnonymousMixin*/  {
+  synthetic constructor •() → ser::_ServicesBinding&BindingBase&SchedulerBinding*
+    : super core::Object::•()
+    ;
+  abstract member-signature get _identityHashCode() → core::int*;
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*;
+  abstract member-signature operator ==(dynamic other) → core::bool*;
+  abstract member-signature get hashCode() → core::int*;
+  abstract member-signature method toString() → core::String*;
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic;
+  abstract member-signature get runtimeType() → core::Type*;
+  abstract member-signature method registerSignalServiceExtension({core::String* name = #C1, () →* asy::Future<core::Null?>* callback = #C1}) → void;
+}
+abstract class ServicesBinding extends ser::_ServicesBinding&BindingBase&SchedulerBinding /*isMixinDeclaration*/  {
+}
+
+library;
+import self as sch;
+import "foundation_binding_lib.dart" as fou;
+import "dart:core" as core;
+import "dart:async" as asy;
+
+import "org-dartlang-testcase:///foundation_lib.dart";
+
+abstract class SchedulerBinding extends fou::BindingBase /*isMixinDeclaration*/  {
+  abstract member-signature method registerSignalServiceExtension({core::String* name = #C1, () →* asy::Future<core::Null?>* callback = #C1}) → void;
+  abstract member-signature get _identityHashCode() → core::int*;
+  abstract member-signature method _instanceOf(dynamic instantiatorTypeArguments, dynamic functionTypeArguments, dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOf(dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOfTrue(dynamic type) → core::bool*;
+  abstract member-signature method _simpleInstanceOfFalse(dynamic type) → core::bool*;
+  abstract member-signature operator ==(dynamic other) → core::bool*;
+  abstract member-signature get hashCode() → core::int*;
+  abstract member-signature method toString() → core::String*;
+  abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic;
+  abstract member-signature get runtimeType() → core::Type*;
+}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue42387/services_binding_lib.dart b/pkg/front_end/testcases/nnbd_mixed/issue42387/services_binding_lib.dart
new file mode 100644
index 0000000..fabdac7
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/issue42387/services_binding_lib.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart = 2.8
+
+import 'foundation_lib.dart';
+import 'scheduler_lib.dart';
+
+mixin ServicesBinding on BindingBase, SchedulerBinding {}
diff --git a/pkg/front_end/testcases/nnbd_mixed/issue42387/services_lib.dart b/pkg/front_end/testcases/nnbd_mixed/issue42387/services_lib.dart
new file mode 100644
index 0000000..4727785
--- /dev/null
+++ b/pkg/front_end/testcases/nnbd_mixed/issue42387/services_lib.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart=2.8
+
+export 'services_binding_lib.dart';
diff --git a/pkg/front_end/testcases/nnbd_mixed/member_inheritance_from_opt_out.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/member_inheritance_from_opt_out.dart.weak.expect
index 7e6e97a..d282884 100644
--- a/pkg/front_end/testcases/nnbd_mixed/member_inheritance_from_opt_out.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/member_inheritance_from_opt_out.dart.weak.expect
@@ -1,35 +1,4 @@
 library main /*isNonNullableByDefault*/;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/nnbd_mixed/member_inheritance_from_opt_out.dart:96:30: Error: The required named parameter 'a' in method 'Class2b.method5c' is not required in overridden method 'LegacyClass.method5c'.
-//   int method5c({required int a, required int b}) => 0;
-//                              ^
-// pkg/front_end/testcases/nnbd_mixed/member_inheritance_from_opt_out_lib.dart:30:7: Context: This is the overridden method ('method5c').
-//   int method5c({int a, int b}) => 0;
-//       ^
-//
-// pkg/front_end/testcases/nnbd_mixed/member_inheritance_from_opt_out.dart:96:46: Error: The required named parameter 'b' in method 'Class2b.method5c' is not required in overridden method 'LegacyClass.method5c'.
-//   int method5c({required int a, required int b}) => 0;
-//                                              ^
-// pkg/front_end/testcases/nnbd_mixed/member_inheritance_from_opt_out_lib.dart:30:7: Context: This is the overridden method ('method5c').
-//   int method5c({int a, int b}) => 0;
-//       ^
-//
-// pkg/front_end/testcases/nnbd_mixed/member_inheritance_from_opt_out.dart:102:32: Error: The required named parameter 'a' in method 'Class2b.method6c' is not required in overridden method 'LegacyClass.method6c'.
-//   int? method6c({required int? a, required int? b}) => 0;
-//                                ^
-// pkg/front_end/testcases/nnbd_mixed/member_inheritance_from_opt_out_lib.dart:36:7: Context: This is the overridden method ('method6c').
-//   int method6c({int a, int b}) => 0;
-//       ^
-//
-// pkg/front_end/testcases/nnbd_mixed/member_inheritance_from_opt_out.dart:102:49: Error: The required named parameter 'b' in method 'Class2b.method6c' is not required in overridden method 'LegacyClass.method6c'.
-//   int? method6c({required int? a, required int? b}) => 0;
-//                                                 ^
-// pkg/front_end/testcases/nnbd_mixed/member_inheritance_from_opt_out_lib.dart:36:7: Context: This is the overridden method ('method6c').
-//   int method6c({int a, int b}) => 0;
-//       ^
-//
 import self as self;
 import "dart:core" as core;
 import "member_inheritance_from_opt_out_lib.dart" as opt;
diff --git a/pkg/front_end/testcases/nnbd_mixed/member_inheritance_from_opt_out.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/member_inheritance_from_opt_out.dart.weak.transformed.expect
index 7e6e97a..d282884 100644
--- a/pkg/front_end/testcases/nnbd_mixed/member_inheritance_from_opt_out.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/member_inheritance_from_opt_out.dart.weak.transformed.expect
@@ -1,35 +1,4 @@
 library main /*isNonNullableByDefault*/;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/nnbd_mixed/member_inheritance_from_opt_out.dart:96:30: Error: The required named parameter 'a' in method 'Class2b.method5c' is not required in overridden method 'LegacyClass.method5c'.
-//   int method5c({required int a, required int b}) => 0;
-//                              ^
-// pkg/front_end/testcases/nnbd_mixed/member_inheritance_from_opt_out_lib.dart:30:7: Context: This is the overridden method ('method5c').
-//   int method5c({int a, int b}) => 0;
-//       ^
-//
-// pkg/front_end/testcases/nnbd_mixed/member_inheritance_from_opt_out.dart:96:46: Error: The required named parameter 'b' in method 'Class2b.method5c' is not required in overridden method 'LegacyClass.method5c'.
-//   int method5c({required int a, required int b}) => 0;
-//                                              ^
-// pkg/front_end/testcases/nnbd_mixed/member_inheritance_from_opt_out_lib.dart:30:7: Context: This is the overridden method ('method5c').
-//   int method5c({int a, int b}) => 0;
-//       ^
-//
-// pkg/front_end/testcases/nnbd_mixed/member_inheritance_from_opt_out.dart:102:32: Error: The required named parameter 'a' in method 'Class2b.method6c' is not required in overridden method 'LegacyClass.method6c'.
-//   int? method6c({required int? a, required int? b}) => 0;
-//                                ^
-// pkg/front_end/testcases/nnbd_mixed/member_inheritance_from_opt_out_lib.dart:36:7: Context: This is the overridden method ('method6c').
-//   int method6c({int a, int b}) => 0;
-//       ^
-//
-// pkg/front_end/testcases/nnbd_mixed/member_inheritance_from_opt_out.dart:102:49: Error: The required named parameter 'b' in method 'Class2b.method6c' is not required in overridden method 'LegacyClass.method6c'.
-//   int? method6c({required int? a, required int? b}) => 0;
-//                                                 ^
-// pkg/front_end/testcases/nnbd_mixed/member_inheritance_from_opt_out_lib.dart:36:7: Context: This is the overridden method ('method6c').
-//   int method6c({int a, int b}) => 0;
-//       ^
-//
 import self as self;
 import "dart:core" as core;
 import "member_inheritance_from_opt_out_lib.dart" as opt;
diff --git a/pkg/front_end/testcases/nnbd_mixed/required_name_override.dart.weak.expect b/pkg/front_end/testcases/nnbd_mixed/required_name_override.dart.weak.expect
index 2d1b6db..677cac9 100644
--- a/pkg/front_end/testcases/nnbd_mixed/required_name_override.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/required_name_override.dart.weak.expect
@@ -16,13 +16,6 @@
 //   void test_nondefault({int? i = 1}) {}
 //        ^
 //
-// pkg/front_end/testcases/nnbd_mixed/required_name_override.dart:15:35: Error: The required named parameter 'i' in method 'A.test_legacy' is not required in overridden method 'C.test_legacy'.
-//   void test_legacy({required int? i}) {}
-//                                   ^
-// pkg/front_end/testcases/nnbd_mixed/required_name_override_lib.dart:8:8: Context: This is the overridden method ('test_legacy').
-//   void test_legacy({int i}) {}
-//        ^
-//
 import self as self;
 import "dart:core" as core;
 import "required_name_override_lib.dart" as req;
diff --git a/pkg/front_end/testcases/nnbd_mixed/required_name_override.dart.weak.transformed.expect b/pkg/front_end/testcases/nnbd_mixed/required_name_override.dart.weak.transformed.expect
index 2d1b6db..677cac9 100644
--- a/pkg/front_end/testcases/nnbd_mixed/required_name_override.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/required_name_override.dart.weak.transformed.expect
@@ -16,13 +16,6 @@
 //   void test_nondefault({int? i = 1}) {}
 //        ^
 //
-// pkg/front_end/testcases/nnbd_mixed/required_name_override.dart:15:35: Error: The required named parameter 'i' in method 'A.test_legacy' is not required in overridden method 'C.test_legacy'.
-//   void test_legacy({required int? i}) {}
-//                                   ^
-// pkg/front_end/testcases/nnbd_mixed/required_name_override_lib.dart:8:8: Context: This is the overridden method ('test_legacy').
-//   void test_legacy({int i}) {}
-//        ^
-//
 import self as self;
 import "dart:core" as core;
 import "required_name_override_lib.dart" as req;
diff --git a/pkg/front_end/testcases/textual_outline.status b/pkg/front_end/testcases/textual_outline.status
index e5a6a25..f05e3ba 100644
--- a/pkg/front_end/testcases/textual_outline.status
+++ b/pkg/front_end/testcases/textual_outline.status
@@ -140,6 +140,7 @@
 late_lowering/issue40805: FormatterCrash
 late_lowering/issue41436b: FormatterCrash
 late_lowering/issue41922: FormatterCrash
+late_lowering/issue42407: FormatterCrash
 late_lowering/late_annotations: FormatterCrash
 late_lowering/late_field_inference: FormatterCrash
 late_lowering/late_field_with_initializer: FormatterCrash
diff --git a/pkg/frontend_server/lib/frontend_server.dart b/pkg/frontend_server/lib/frontend_server.dart
index 714708d..d9e4fbf 100644
--- a/pkg/frontend_server/lib/frontend_server.dart
+++ b/pkg/frontend_server/lib/frontend_server.dart
@@ -64,6 +64,8 @@
   ..addFlag('protobuf-tree-shaker',
       help: 'Enable protobuf tree shaker transformation in AOT mode.',
       defaultsTo: false)
+  ..addFlag('protobuf-tree-shaker-v2',
+      help: 'Enable protobuf tree shaker v2 in AOT mode.', defaultsTo: false)
   ..addFlag('minimal-kernel',
       help: 'Produce minimal tree-shaken kernel file.', defaultsTo: false)
   ..addFlag('link-platform',
@@ -171,6 +173,9 @@
       help: 'A path or uri to the libraries specification JSON file')
   ..addFlag('debugger-module-names',
       help: 'Use debugger-friendly modules names', defaultsTo: false)
+  ..addFlag('experimental-emit-debug-metadata',
+      help: 'Emit module and library metadata for the debugger',
+      defaultsTo: false)
   ..addOption('dartdevc-module-format',
       help: 'The module format to use on for the dartdevc compiler',
       defaultsTo: 'amd');
@@ -320,7 +325,8 @@
       this.transformer,
       this.unsafePackageSerialization,
       this.incrementalSerialization: true,
-      this.useDebuggerModuleNames: false}) {
+      this.useDebuggerModuleNames: false,
+      this.emitDebugMetadata: false}) {
     _outputStream ??= stdout;
     printerFactory ??= new BinaryPrinterFactory();
   }
@@ -330,6 +336,7 @@
   bool unsafePackageSerialization;
   bool incrementalSerialization;
   bool useDebuggerModuleNames;
+  bool emitDebugMetadata;
 
   CompilerOptions _compilerOptions;
   BytecodeOptions _bytecodeOptions;
@@ -542,6 +549,7 @@
           environmentDefines: environmentDefines,
           enableAsserts: options['enable-asserts'],
           useProtobufTreeShaker: options['protobuf-tree-shaker'],
+          useProtobufTreeShakerV2: options['protobuf-tree-shaker-v2'],
           minimalKernel: options['minimal-kernel'],
           treeShakeWriteOnlyFields: options['tree-shake-write-only-fields'],
           fromDillFile: options['from-dill']));
@@ -636,27 +644,33 @@
     final File sourceFile = File('$filename.sources');
     final File manifestFile = File('$filename.json');
     final File sourceMapsFile = File('$filename.map');
+    final File metadataFile = File('$filename.metadata');
     if (!sourceFile.parent.existsSync()) {
       sourceFile.parent.createSync(recursive: true);
     }
     _bundler = JavaScriptBundler(
         component, strongComponents, fileSystemScheme, packageConfig,
         useDebuggerModuleNames: useDebuggerModuleNames,
+        emitDebugMetadata: emitDebugMetadata,
         moduleFormat: moduleFormat);
     final sourceFileSink = sourceFile.openWrite();
     final manifestFileSink = manifestFile.openWrite();
     final sourceMapsFileSink = sourceMapsFile.openWrite();
+    final metadataFileSink =
+        emitDebugMetadata ? metadataFile.openWrite() : null;
     await _bundler.compile(
         results.classHierarchy,
         results.coreTypes,
         results.loadedLibraries,
         sourceFileSink,
         manifestFileSink,
-        sourceMapsFileSink);
+        sourceMapsFileSink,
+        metadataFileSink);
     await Future.wait([
       sourceFileSink.close(),
       manifestFileSink.close(),
-      sourceMapsFileSink.close()
+      sourceMapsFileSink.close(),
+      if (metadataFileSink != null) metadataFileSink.close()
     ]);
   }
 
@@ -1409,7 +1423,8 @@
       printerFactory: binaryPrinterFactory,
       unsafePackageSerialization: options["unsafe-package-serialization"],
       incrementalSerialization: options["incremental-serialization"],
-      useDebuggerModuleNames: options['debugger-module-names']);
+      useDebuggerModuleNames: options['debugger-module-names'],
+      emitDebugMetadata: options['experimental-emit-debug-metadata']);
 
   if (options.rest.isNotEmpty) {
     return await compiler.compile(options.rest[0], options,
diff --git a/pkg/frontend_server/lib/src/javascript_bundle.dart b/pkg/frontend_server/lib/src/javascript_bundle.dart
index 98443f8..d67f9bc 100644
--- a/pkg/frontend_server/lib/src/javascript_bundle.dart
+++ b/pkg/frontend_server/lib/src/javascript_bundle.dart
@@ -25,7 +25,9 @@
 class JavaScriptBundler {
   JavaScriptBundler(this._originalComponent, this._strongComponents,
       this._fileSystemScheme, this._packageConfig,
-      {this.useDebuggerModuleNames = false, String moduleFormat})
+      {this.useDebuggerModuleNames = false,
+      this.emitDebugMetadata = false,
+      String moduleFormat})
       : compilers = <String, ProgramCompiler>{},
         _moduleFormat = parseModuleFormat(moduleFormat ?? 'amd') {
     _summaries = <Component>[];
@@ -58,6 +60,7 @@
   final String _fileSystemScheme;
   final PackageConfig _packageConfig;
   final bool useDebuggerModuleNames;
+  final bool emitDebugMetadata;
   final Map<String, ProgramCompiler> compilers;
   final ModuleFormat _moduleFormat;
 
@@ -74,9 +77,11 @@
       Set<Library> loadedLibraries,
       IOSink codeSink,
       IOSink manifestSink,
-      IOSink sourceMapsSink) async {
+      IOSink sourceMapsSink,
+      IOSink metadataSink) async {
     var codeOffset = 0;
     var sourceMapOffset = 0;
+    var metadataOffset = 0;
     final manifest = <String, Map<String, List<int>>>{};
     final Set<Uri> visited = <Uri>{};
 
@@ -124,7 +129,11 @@
         _originalComponent,
         classHierarchy,
         SharedCompilerOptions(
-            sourceMap: true, summarizeApi: false, moduleName: moduleName),
+          sourceMap: true,
+          summarizeApi: false,
+          emitDebugMetadata: emitDebugMetadata,
+          moduleName: moduleName,
+        ),
         importToSummary,
         summaryToModule,
         coreTypes: coreTypes,
@@ -149,11 +158,13 @@
         sourceMapBase =
             p.dirname((await _packageConfig.resolve(moduleUri)).path);
       }
+
       final code = jsProgramToCode(
         jsModule,
         _moduleFormat,
         inlineSourceMap: true,
         buildSourceMap: true,
+        emitDebugMetadata: emitDebugMetadata,
         jsUrl: '$moduleUrl.lib.js',
         mapUrl: '$moduleUrl.lib.js.map',
         sourceMapBase: sourceMapBase,
@@ -162,9 +173,14 @@
       );
       final codeBytes = utf8.encode(code.code);
       final sourceMapBytes = utf8.encode(json.encode(code.sourceMap));
+      final metadataBytes =
+          emitDebugMetadata ? utf8.encode(json.encode(code.metadata)) : null;
+
       codeSink.add(codeBytes);
       sourceMapsSink.add(sourceMapBytes);
-
+      if (emitDebugMetadata) {
+        metadataSink.add(metadataBytes);
+      }
       final String moduleKey = _moduleImportForSummary[moduleUri];
       manifest[moduleKey] = {
         'code': <int>[codeOffset, codeOffset += codeBytes.length],
@@ -172,6 +188,11 @@
           sourceMapOffset,
           sourceMapOffset += sourceMapBytes.length
         ],
+        if (emitDebugMetadata)
+          'metadata': <int>[
+            metadataOffset,
+            metadataOffset += metadataBytes.length
+          ],
       };
     }
     manifestSink.add(utf8.encode(json.encode(manifest)));
diff --git a/pkg/frontend_server/pubspec.yaml b/pkg/frontend_server/pubspec.yaml
index 2effb3b..f682159 100644
--- a/pkg/frontend_server/pubspec.yaml
+++ b/pkg/frontend_server/pubspec.yaml
@@ -1,7 +1,7 @@
-# This package is not intended to be published.
 name: frontend_server
-# version: do-not-upload
 description: A resident kernel compiler
+# This package is not intended for consumption on pub.dev. DO NOT publish.
+publish_to: none
 
 environment:
   sdk: "^2.7.0"
diff --git a/pkg/frontend_server/test/frontend_server_test.dart b/pkg/frontend_server/test/frontend_server_test.dart
index 8e521f4..a042a1e 100644
--- a/pkg/frontend_server/test/frontend_server_test.dart
+++ b/pkg/frontend_server/test/frontend_server_test.dart
@@ -1462,6 +1462,141 @@
       expect(await starter(args), 0);
     });
 
+    test('compile to JavaScript with no metadata', () async {
+      var file = File('${tempDir.path}/foo.dart')..createSync();
+      file.writeAsStringSync("main() {\n\n}\n");
+      File('${tempDir.path}/.packages')
+        ..createSync()
+        ..writeAsStringSync("hello:${tempDir.uri}\n");
+
+      var library = 'package:hello/foo.dart';
+
+      var dillFile = File('${tempDir.path}/app.dill');
+      var sourceFile = File('${dillFile.path}.sources');
+      var manifestFile = File('${dillFile.path}.json');
+      var sourceMapsFile = File('${dillFile.path}.map');
+      var metadataFile = File('${dillFile.path}.metadata');
+
+      expect(dillFile.existsSync(), false);
+      expect(sourceFile.existsSync(), false);
+      expect(manifestFile.existsSync(), false);
+      expect(sourceMapsFile.existsSync(), false);
+      expect(metadataFile.existsSync(), false);
+
+      final List<String> args = <String>[
+        '--sdk-root=${sdkRoot.toFilePath()}',
+        '--incremental',
+        '--platform=${ddcPlatformKernel.path}',
+        '--output-dill=${dillFile.path}',
+        '--target=dartdevc',
+        '--packages=${tempDir.path}/.packages',
+        '--debugger-module-names'
+      ];
+
+      final StreamController<List<int>> streamController =
+          StreamController<List<int>>();
+      final StreamController<List<int>> stdoutStreamController =
+          StreamController<List<int>>();
+      final IOSink ioSink = IOSink(stdoutStreamController.sink);
+      StreamController<Result> receivedResults = StreamController<Result>();
+      final outputParser = OutputParser(receivedResults);
+      stdoutStreamController.stream
+          .transform(utf8.decoder)
+          .transform(const LineSplitter())
+          .listen(outputParser.listener);
+
+      Future<int> result =
+          starter(args, input: streamController.stream, output: ioSink);
+      streamController.add('compile $library\n'.codeUnits);
+      var count = 0;
+      receivedResults.stream.listen((Result compiledResult) {
+        CompilationResult result =
+            CompilationResult.parse(compiledResult.status);
+        count++;
+        // Request to 'compile', which results in full JavaScript and no metadata
+        expect(result.errorsCount, equals(0));
+        expect(sourceFile.existsSync(), equals(true));
+        expect(manifestFile.existsSync(), equals(true));
+        expect(sourceMapsFile.existsSync(), equals(true));
+        expect(metadataFile.existsSync(), equals(false));
+        expect(result.filename, dillFile.path);
+        streamController.add('accept\n'.codeUnits);
+        outputParser.expectSources = false;
+        streamController.add('quit\n'.codeUnits);
+      });
+
+      expect(await result, 0);
+      expect(count, 1);
+    });
+
+    test('compile to JavaScript with metadata', () async {
+      var file = File('${tempDir.path}/foo.dart')..createSync();
+      file.writeAsStringSync("main() {\n\n}\n");
+      File('${tempDir.path}/.packages')
+        ..createSync()
+        ..writeAsStringSync("hello:${tempDir.uri}\n");
+
+      var library = 'package:hello/foo.dart';
+
+      var dillFile = File('${tempDir.path}/app.dill');
+      var sourceFile = File('${dillFile.path}.sources');
+      var manifestFile = File('${dillFile.path}.json');
+      var sourceMapsFile = File('${dillFile.path}.map');
+      var metadataFile = File('${dillFile.path}.metadata');
+
+      expect(dillFile.existsSync(), false);
+      expect(sourceFile.existsSync(), false);
+      expect(manifestFile.existsSync(), false);
+      expect(sourceMapsFile.existsSync(), false);
+      expect(metadataFile.existsSync(), false);
+
+      final List<String> args = <String>[
+        '--sdk-root=${sdkRoot.toFilePath()}',
+        '--incremental',
+        '--platform=${ddcPlatformKernel.path}',
+        '--output-dill=${dillFile.path}',
+        '--target=dartdevc',
+        '--packages=${tempDir.path}/.packages',
+        '--debugger-module-names',
+        '--experimental-emit-debug-metadata'
+      ];
+
+      final StreamController<List<int>> streamController =
+          StreamController<List<int>>();
+      final StreamController<List<int>> stdoutStreamController =
+          StreamController<List<int>>();
+      final IOSink ioSink = IOSink(stdoutStreamController.sink);
+      StreamController<Result> receivedResults = StreamController<Result>();
+      final outputParser = OutputParser(receivedResults);
+      stdoutStreamController.stream
+          .transform(utf8.decoder)
+          .transform(const LineSplitter())
+          .listen(outputParser.listener);
+
+      Future<int> result =
+          starter(args, input: streamController.stream, output: ioSink);
+      streamController.add('compile $library\n'.codeUnits);
+      int count = 0;
+      receivedResults.stream.listen((Result compiledResult) {
+        CompilationResult result =
+            CompilationResult.parse(compiledResult.status);
+        count++;
+        // Request to 'compile', which results in full JavaScript and no metadata
+        expect(result.errorsCount, equals(0));
+        expect(sourceFile.existsSync(), equals(true));
+        expect(manifestFile.existsSync(), equals(true));
+        expect(sourceMapsFile.existsSync(), equals(true));
+        expect(metadataFile.existsSync(), equals(true));
+        expect(result.filename, dillFile.path);
+        streamController.add('accept\n'.codeUnits);
+        outputParser.expectSources = false;
+        streamController.add('quit\n'.codeUnits);
+      });
+
+      expect(await result, 0);
+      expect(count, 1);
+    });
+
     test('compile expression to Javascript', () async {
       var file = File('${tempDir.path}/foo.dart')..createSync();
       file.writeAsStringSync("main() {\n\n}\n");
diff --git a/pkg/frontend_server/test/src/javascript_bundle_test.dart b/pkg/frontend_server/test/src/javascript_bundle_test.dart
index 7c5a12d..26a7c21 100644
--- a/pkg/frontend_server/test/src/javascript_bundle_test.dart
+++ b/pkg/frontend_server/test/src/javascript_bundle_test.dart
@@ -103,10 +103,11 @@
     final manifestSink = _MemorySink();
     final codeSink = _MemorySink();
     final sourcemapSink = _MemorySink();
+    final metadataSink = _MemorySink();
     final coreTypes = CoreTypes(testComponent);
 
     await javaScriptBundler.compile(ClassHierarchy(testComponent, coreTypes),
-        coreTypes, {}, codeSink, manifestSink, sourcemapSink);
+        coreTypes, {}, codeSink, manifestSink, sourcemapSink, metadataSink);
 
     final Map manifest = json.decode(utf8.decode(manifestSink.buffer));
     final String code = utf8.decode(codeSink.buffer);
@@ -143,10 +144,11 @@
     final manifestSink = _MemorySink();
     final codeSink = _MemorySink();
     final sourcemapSink = _MemorySink();
+    final metadataSink = _MemorySink();
     final coreTypes = CoreTypes(testComponent);
 
     await javaScriptBundler.compile(ClassHierarchy(testComponent, coreTypes),
-        coreTypes, {}, codeSink, manifestSink, sourcemapSink);
+        coreTypes, {}, codeSink, manifestSink, sourcemapSink, metadataSink);
 
     final Map manifest = json.decode(utf8.decode(manifestSink.buffer));
     final String code = utf8.decode(codeSink.buffer);
@@ -183,10 +185,11 @@
     final manifestSink = _MemorySink();
     final codeSink = _MemorySink();
     final sourcemapSink = _MemorySink();
+    final metadataSink = _MemorySink();
     final coreTypes = CoreTypes(testComponent);
 
     await javaScriptBundler.compile(ClassHierarchy(testComponent, coreTypes),
-        coreTypes, {}, codeSink, manifestSink, sourcemapSink);
+        coreTypes, {}, codeSink, manifestSink, sourcemapSink, metadataSink);
 
     final Map manifest = json.decode(utf8.decode(manifestSink.buffer));
     final String code = utf8.decode(codeSink.buffer);
@@ -232,10 +235,11 @@
     final manifestSink = _MemorySink();
     final codeSink = _MemorySink();
     final sourcemapSink = _MemorySink();
+    final metadataSink = _MemorySink();
     final coreTypes = CoreTypes(testComponent);
 
     javaScriptBundler.compile(ClassHierarchy(testComponent, coreTypes),
-        coreTypes, {}, codeSink, manifestSink, sourcemapSink);
+        coreTypes, {}, codeSink, manifestSink, sourcemapSink, metadataSink);
 
     final code = utf8.decode(codeSink.buffer);
     final manifest = json.decode(utf8.decode(manifestSink.buffer));
diff --git a/pkg/js_ast/pubspec.yaml b/pkg/js_ast/pubspec.yaml
index 8db366a..7349f57 100644
--- a/pkg/js_ast/pubspec.yaml
+++ b/pkg/js_ast/pubspec.yaml
@@ -1,4 +1,5 @@
 name: js_ast
+# This package is not intended for consumption on pub.dev. DO NOT publish.
 publish_to: none
 
 environment:
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index c0d3f99..7eff1a0 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -2818,6 +2818,49 @@
             .applyToFunctionType(computeThisFunctionType(nullability));
   }
 
+  /// Return function type of node: return [typedefType], reuse type parameters.
+  ///
+  /// When this getter is invoked, the parent must be a [Constructor].
+  /// This getter works similarly to [computeThisFunctionType], but uses
+  /// [typedef] to compute the return type of the returned function type. It
+  /// is useful in some contexts, especially during inference of aliased
+  /// constructor invocations.
+  FunctionType computeAliasedFunctionType(Typedef typedef, Library library) {
+    TreeNode parent = this.parent;
+    assert(parent is Constructor, "Only run this method on constructors");
+    Constructor parentConstructor = parent;
+    // We need create a copy of the list of type parameters, otherwise
+    // transformations like erasure don't work.
+    List<TypeParameter> classTypeParametersCopy =
+        List.from(parentConstructor.enclosingClass.typeParameters);
+    List<TypeParameter> typedefTypeParametersCopy =
+        List.from(typedef.typeParameters);
+    List<DartType> asTypeArguments =
+        getAsTypeArguments(typedefTypeParametersCopy, library);
+    TypedefType typedefType =
+        TypedefType(typedef, library.nonNullable, asTypeArguments);
+    DartType unaliasedTypedef = typedefType.unalias;
+    assert(unaliasedTypedef is InterfaceType,
+        "[typedef] is assumed to resolve to an interface type");
+    InterfaceType targetType = unaliasedTypedef;
+    Substitution substitution = Substitution.fromPairs(
+        classTypeParametersCopy, targetType.typeArguments);
+    List<DartType> positional = positionalParameters
+        .map((VariableDeclaration decl) =>
+            substitution.substituteType(decl.type))
+        .toList(growable: false);
+    List<NamedType> named = namedParameters
+        .map((VariableDeclaration decl) => NamedType(
+            decl.name, substitution.substituteType(decl.type),
+            isRequired: decl.isRequired))
+        .toList(growable: false);
+    named.sort();
+    return new FunctionType(positional, typedefType, library.nonNullable,
+        namedParameters: named,
+        typeParameters: typedefTypeParametersCopy,
+        requiredParameterCount: requiredParameterCount);
+  }
+
   R accept<R>(TreeVisitor<R> v) => v.visitFunctionNode(this);
 
   visitChildren(Visitor v) {
diff --git a/pkg/kernel/pubspec.yaml b/pkg/kernel/pubspec.yaml
index 7c83598..2d80a28 100644
--- a/pkg/kernel/pubspec.yaml
+++ b/pkg/kernel/pubspec.yaml
@@ -1,10 +1,10 @@
-name: kernel
 # Currently, kernel API is not stable and users should
 # not depend on semver semantics when depending on this package.
-version: 0.3.29
-author: Dart Team <misc@dartlang.org>
-description: Dart IR (Intermediate Representation)
-homepage: https://github.com/dart-lang/sdk/tree/master/pkg/kernel
+name: kernel
+
+# This package is not intended for consumption on pub.dev. DO NOT publish.
+publish_to: none
+
 environment:
   sdk: '>=2.2.2 <3.0.0'
 dependencies:
diff --git a/pkg/meta/CHANGELOG.md b/pkg/meta/CHANGELOG.md
index b5b8c99..78a0ddb 100644
--- a/pkg/meta/CHANGELOG.md
+++ b/pkg/meta/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.2.0-nnbd
+
+* Opt into null safety.
+
 ## 1.1.8
 
 * Introduce `@nonVirtual` to annotate instance members that should not be
diff --git a/pkg/meta/analysis_options.yaml b/pkg/meta/analysis_options.yaml
new file mode 100644
index 0000000..4163582
--- /dev/null
+++ b/pkg/meta/analysis_options.yaml
@@ -0,0 +1,3 @@
+analyzer:
+  enable-experiment:
+    - non-nullable
diff --git a/pkg/meta/pubspec.yaml b/pkg/meta/pubspec.yaml
index 4ca8152..0a745e0 100644
--- a/pkg/meta/pubspec.yaml
+++ b/pkg/meta/pubspec.yaml
@@ -1,5 +1,5 @@
 name: meta
-version: 1.1.8
+version: 1.2.0-nnbd
 author: Dart Team <misc@dartlang.org>
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/meta
 description: >
@@ -7,4 +7,6 @@
  semantic information about the program being annotated. These annotations are
  intended to be used by tools to provide a better user experience.
 environment:
-  sdk: '>=2.9.0 <3.0.0'
+  # This must remain a tight constraint (only allow dev versions) until nnbd is
+  # stable.
+  sdk: '>=2.9.0-18.0 <2.9.0'
diff --git a/pkg/modular_test/pubspec.yaml b/pkg/modular_test/pubspec.yaml
index 39f65c8..e0a48d0 100644
--- a/pkg/modular_test/pubspec.yaml
+++ b/pkg/modular_test/pubspec.yaml
@@ -1,4 +1,5 @@
 name: modular_test
+# This package is not intended for consumption on pub.dev. DO NOT publish.
 publish_to: none
 description: >
  Small framework to test modular pipelines.
diff --git a/pkg/native_stack_traces/CHANGELOG.md b/pkg/native_stack_traces/CHANGELOG.md
index 10e8638..71ca8ba 100644
--- a/pkg/native_stack_traces/CHANGELOG.md
+++ b/pkg/native_stack_traces/CHANGELOG.md
@@ -1,5 +1,9 @@
 # Changelog
 
+## 0.3.8
+
+- Support columns when present in line number programs.
+
 ## 0.3.7
 
 - Added buildId accessor for retrieving GNU build IDs from DWARF files that
diff --git a/pkg/native_stack_traces/lib/src/dwarf.dart b/pkg/native_stack_traces/lib/src/dwarf.dart
index 72f7623..fd0911b 100644
--- a/pkg/native_stack_traces/lib/src/dwarf.dart
+++ b/pkg/native_stack_traces/lib/src/dwarf.dart
@@ -313,6 +313,11 @@
 
   int get callLine => this[_AttributeName.callLine] as int;
 
+  // We don't assume that call columns are present for backwards compatibility.
+  int get callColumn => containsKey(_AttributeName.callColumn)
+      ? this[_AttributeName.callColumn] as int
+      : 0;
+
   List<CallInfo> callInfo(
       CompilationUnit unit, LineNumberProgram lineNumberProgram, int address) {
     String callFilename(int index) =>
@@ -333,7 +338,8 @@
               function: unit.nameOfOrigin(abstractOrigin),
               inlined: inlined,
               filename: callFilename(child.callFileIndex),
-              line: child.callLine));
+              line: child.callLine,
+              column: child.callColumn));
       }
     }
 
@@ -341,12 +347,14 @@
 
     final filename = lineNumberProgram.filename(address);
     final line = lineNumberProgram.lineNumber(address);
+    final column = lineNumberProgram.column(address);
     return [
       DartCallInfo(
           function: unit.nameOfOrigin(abstractOrigin),
           inlined: inlined,
           filename: filename,
-          line: line)
+          line: line,
+          column: column)
     ];
   }
 
@@ -980,6 +988,8 @@
 
   int lineNumber(int address) => this[address]?.line;
 
+  int column(int address) => this[address]?.column;
+
   void writeToStringBuffer(StringBuffer buffer) {
     header.writeToStringBuffer(buffer);
 
@@ -1054,8 +1064,14 @@
   final String function;
   final String filename;
   final int line;
+  final int column;
 
-  DartCallInfo({this.inlined = false, this.function, this.filename, this.line});
+  DartCallInfo(
+      {this.inlined = false,
+      this.function,
+      this.filename,
+      this.line,
+      this.column});
 
   @override
   bool get isInternal => false;
@@ -1063,9 +1079,12 @@
   @override
   int get hashCode => _hashFinish(_hashCombine(
       _hashCombine(
-          _hashCombine(_hashCombine(0, inlined.hashCode), function.hashCode),
-          filename.hashCode),
-      line.hashCode));
+          _hashCombine(
+              _hashCombine(
+                  _hashCombine(0, inlined.hashCode), function.hashCode),
+              filename.hashCode),
+          line.hashCode),
+      column.hashCode));
 
   @override
   bool operator ==(Object other) {
@@ -1073,13 +1092,29 @@
       return inlined == other.inlined &&
           function == other.function &&
           filename == other.filename &&
-          line == other.line;
+          line == other.line &&
+          column == other.column;
     }
     return false;
   }
 
+  void writeToStringBuffer(StringBuffer buffer) {
+    buffer..write(function)..write(' (')..write(filename);
+    if (line > 0) {
+      buffer..write(':')..write(line);
+      if (column > 0) {
+        buffer..write(':')..write(column);
+      }
+    }
+    buffer.write(')');
+  }
+
   @override
-  String toString() => "${function} (${filename}${line <= 0 ? '' : ':$line'})";
+  String toString() {
+    final buffer = StringBuffer();
+    writeToStringBuffer(buffer);
+    return buffer.toString();
+  }
 }
 
 /// Represents the information for a call site located in a Dart stub.
diff --git a/pkg/native_stack_traces/pubspec.yaml b/pkg/native_stack_traces/pubspec.yaml
index b086b607..cc0d214 100644
--- a/pkg/native_stack_traces/pubspec.yaml
+++ b/pkg/native_stack_traces/pubspec.yaml
@@ -1,6 +1,6 @@
 name: native_stack_traces
 description: Utilities for working with non-symbolic stack traces.
-version: 0.3.7
+version: 0.3.8
 
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/native_stack_traces
 
diff --git a/pkg/nnbd_migration/lib/migration_cli.dart b/pkg/nnbd_migration/lib/migration_cli.dart
index 4d74b5d..3c5a8d9 100644
--- a/pkg/nnbd_migration/lib/migration_cli.dart
+++ b/pkg/nnbd_migration/lib/migration_cli.dart
@@ -50,6 +50,7 @@
   static const helpFlag = 'help';
   static const ignoreErrorsFlag = 'ignore-errors';
   static const ignoreExceptionsFlag = 'ignore-exceptions';
+  static const previewHostnameOption = 'preview-hostname';
   static const previewPortOption = 'preview-port';
   static const sdkPathOption = 'sdk-path';
   static const skipPubOutdatedFlag = 'skip-pub-outdated';
@@ -65,6 +66,8 @@
 
   final bool ignoreExceptions;
 
+  final String previewHostname;
+
   final int previewPort;
 
   final String sdkPath;
@@ -80,6 +83,7 @@
       @required this.directory,
       @required this.ignoreErrors,
       @required this.ignoreExceptions,
+      @required this.previewHostname,
       @required this.previewPort,
       @required this.sdkPath,
       @required this.skipPubOutdated,
@@ -311,6 +315,8 @@
           ignoreErrors: argResults[CommandLineOptions.ignoreErrorsFlag] as bool,
           ignoreExceptions:
               argResults[CommandLineOptions.ignoreExceptionsFlag] as bool,
+          previewHostname:
+              argResults[CommandLineOptions.previewHostnameOption] as String,
           previewPort: previewPort,
           sdkPath: argResults[CommandLineOptions.sdkPathOption] as String ??
               defaultSdkPathOverride ??
@@ -394,6 +400,11 @@
         help:
             'Attempt to perform null safety analysis even if exceptions occur.',
         hide: hide);
+    parser.addOption(CommandLineOptions.previewHostnameOption,
+        defaultsTo: 'localhost',
+        help: 'Run the preview server on the specified hostname.  If not '
+            'specified, "localhost" is used. Use "any" to specify IPv6.any or '
+            'IPv4.any.');
     parser.addOption(CommandLineOptions.previewPortOption,
         help:
             'Run the preview server on the specified port.  If not specified, '
@@ -517,10 +528,12 @@
   NonNullableFix createNonNullableFix(DartFixListener listener,
       ResourceProvider resourceProvider, LineInfo getLineInfo(String path),
       {List<String> included = const <String>[],
+      String hostname,
       int preferredPort,
       String summaryPath}) {
     return NonNullableFix(listener, resourceProvider, getLineInfo,
         included: included,
+        hostname: hostname,
         preferredPort: preferredPort,
         summaryPath: summaryPath);
   }
@@ -538,8 +551,9 @@
     logger.stdout('');
 
     if (hasMultipleAnalysisContext) {
-      logger.stdout(
-          'Note: more than one project found; migrating the top-level project.');
+      logger
+          .stdout('Note: more than one project found; migrating the top-level '
+              'project.');
       logger.stdout('');
     }
 
@@ -555,6 +569,7 @@
     nonNullableFix = createNonNullableFix(
         _dartFixListener, resourceProvider, _fixCodeProcessor.getLineInfo,
         included: [options.directory],
+        hostname: options.previewHostname,
         preferredPort: options.previewPort,
         summaryPath: options.summary);
     nonNullableFix.rerunFunction = _rerunFunction;
diff --git a/pkg/nnbd_migration/lib/src/edge_builder.dart b/pkg/nnbd_migration/lib/src/edge_builder.dart
index 78012f8..64bab25 100644
--- a/pkg/nnbd_migration/lib/src/edge_builder.dart
+++ b/pkg/nnbd_migration/lib/src/edge_builder.dart
@@ -1068,6 +1068,8 @@
 
   @override
   DecoratedType visitIsExpression(IsExpression node) {
+    var expression = node.expression;
+    var expressionNode = _dispatch(expression).node;
     var type = node.type;
     _dispatch(type);
     var decoratedType = _variables.decoratedTypeAnnotation(source, type);
@@ -1076,6 +1078,14 @@
       // Making it nullable could change runtime behavior.
       _graph.makeNonNullable(
           decoratedType.node, IsCheckMainTypeOrigin(source, type));
+      _conditionInfo = _ConditionInfo(node,
+          isPure: expression is SimpleIdentifier,
+          postDominatingIntent:
+              _postDominatedLocals.isReferenceInScope(expression),
+          trueDemonstratesNonNullIntent: expressionNode);
+      if (node.notOperator != null) {
+        _conditionInfo = _conditionInfo.not(node);
+      }
       if (!_assumeNonNullabilityInCasts) {
         // TODO(mfairhurst): wire this to handleDowncast if we do not assume
         // nullability.
@@ -1085,8 +1095,6 @@
       // TODO(brianwilkerson)
       _unimplemented(node, 'Is expression with GenericFunctionType');
     }
-    var expression = node.expression;
-    _dispatch(expression);
     _flowAnalysis.isExpression_end(
         node, expression, node.notOperator != null, decoratedType);
     return _makeNonNullableBoolType(node);
diff --git a/pkg/nnbd_migration/lib/src/fix_builder.dart b/pkg/nnbd_migration/lib/src/fix_builder.dart
index 602ef69..ad8710d 100644
--- a/pkg/nnbd_migration/lib/src/fix_builder.dart
+++ b/pkg/nnbd_migration/lib/src/fix_builder.dart
@@ -310,18 +310,6 @@
 
   TypeProvider get typeProvider => _fixBuilder.typeProvider;
 
-  Element get _elementHashCode =>
-      _fixBuilder.typeProvider.objectType.getGetter('hashCode');
-
-  Element get _elementNoSuchMethod =>
-      _fixBuilder.typeProvider.objectType.getGetter('noSuchMethod');
-
-  Element get _elementRuntimeType =>
-      _fixBuilder.typeProvider.objectType.getMethod('runtimeType');
-
-  Element get _elementToString =>
-      _fixBuilder.typeProvider.objectType.getMethod('toString');
-
   @override
   void freshTypeParameterCreated(TypeParameterElement newTypeParameter,
       TypeParameterElement oldTypeParameter) {
diff --git a/pkg/nnbd_migration/lib/src/front_end/migration_info.dart b/pkg/nnbd_migration/lib/src/front_end/migration_info.dart
index ddc8ed6..52e5a2f 100644
--- a/pkg/nnbd_migration/lib/src/front_end/migration_info.dart
+++ b/pkg/nnbd_migration/lib/src/front_end/migration_info.dart
@@ -86,6 +86,15 @@
   /// The path of the Dart logo displayed in the toolbar.
   String get dartLogoPath => PreviewSite.dartLogoPath;
 
+  /// The path of the Material icons font.
+  String get materialIconsPath => PreviewSite.materialIconsPath;
+
+  /// The path of the Roboto font.
+  String get robotoFont => PreviewSite.robotoFontPath;
+
+  /// The path of the Roboto Mono font.
+  String get robotoMonoFont => PreviewSite.robotoMonoFontPath;
+
   /// Return the path to [unit] from [includedRoot], to be used as a display
   /// name for a library.
   String computeName(UnitInfo unit) =>
diff --git a/pkg/nnbd_migration/lib/src/front_end/non_nullable_fix.dart b/pkg/nnbd_migration/lib/src/front_end/non_nullable_fix.dart
index b34a302..fb43d4e 100644
--- a/pkg/nnbd_migration/lib/src/front_end/non_nullable_fix.dart
+++ b/pkg/nnbd_migration/lib/src/front_end/non_nullable_fix.dart
@@ -38,6 +38,8 @@
 
   static final List<HttpPreviewServer> _allServers = [];
 
+  final String hostname;
+
   final int preferredPort;
 
   final DartFixListener listener;
@@ -60,10 +62,6 @@
   /// The HTTP server that serves the preview tool.
   HttpPreviewServer _server;
 
-  /// The port on which preview pages should be served, or `null` if no preview
-  /// server should be started.
-  int port;
-
   String authToken;
 
   InstrumentationListener instrumentationListener;
@@ -83,7 +81,10 @@
   List<String> previewUrls;
 
   NonNullableFix(this.listener, this.resourceProvider, this._getLineInfo,
-      {List<String> included = const [], this.preferredPort, this.summaryPath})
+      {List<String> included = const [],
+      this.hostname,
+      this.preferredPort,
+      this.summaryPath})
       : includedRoot =
             _getIncludedRoot(included, listener.server.resourceProvider) {
     reset();
@@ -183,18 +184,19 @@
 
   Future<void> startPreviewServer(MigrationState state) async {
     if (_server == null) {
-      _server = HttpPreviewServer(state, rerun, preferredPort);
+      _server = HttpPreviewServer(state, rerun, hostname, preferredPort);
       _server.serveHttp();
       _allServers.add(_server);
-      port = await _server.boundPort;
+      var serverHostname = await _server.boundHostname;
+      var serverPort = await _server.boundPort;
       authToken = await _server.authToken;
 
       previewUrls = [
         // TODO(jcollins-g): Change protocol to only return a single string.
         Uri(
             scheme: 'http',
-            host: 'localhost',
-            port: port,
+            host: serverHostname,
+            port: serverPort,
             path: state.pathMapper.map(includedRoot),
             queryParameters: {'authToken': authToken}).toString()
       ];
diff --git a/pkg/nnbd_migration/lib/src/front_end/resources/MaterialIconsRegular.ttf b/pkg/nnbd_migration/lib/src/front_end/resources/MaterialIconsRegular.ttf
new file mode 100644
index 0000000..7015564a
--- /dev/null
+++ b/pkg/nnbd_migration/lib/src/front_end/resources/MaterialIconsRegular.ttf
Binary files differ
diff --git a/pkg/nnbd_migration/lib/src/front_end/resources/RobotoMonoRegular.ttf b/pkg/nnbd_migration/lib/src/front_end/resources/RobotoMonoRegular.ttf
new file mode 100644
index 0000000..5919b5d
--- /dev/null
+++ b/pkg/nnbd_migration/lib/src/front_end/resources/RobotoMonoRegular.ttf
Binary files differ
diff --git a/pkg/nnbd_migration/lib/src/front_end/resources/RobotoRegular.ttf b/pkg/nnbd_migration/lib/src/front_end/resources/RobotoRegular.ttf
new file mode 100644
index 0000000..2b6392f
--- /dev/null
+++ b/pkg/nnbd_migration/lib/src/front_end/resources/RobotoRegular.ttf
Binary files differ
diff --git a/pkg/nnbd_migration/lib/src/front_end/resources/index.html b/pkg/nnbd_migration/lib/src/front_end/resources/index.html
index ecfd0c3..1b67ad7 100644
--- a/pkg/nnbd_migration/lib/src/front_end/resources/index.html
+++ b/pkg/nnbd_migration/lib/src/front_end/resources/index.html
@@ -21,16 +21,36 @@
 <p class="root">{{ root }}</p>
 <header class="elevation-z4">
     <img src="{{ dartLogoPath }}" alt="DartPad Logo" class="logo"/>
-    <h1 class="before-apply">Proposed null safety changes</h1>
-    <h1 class="after-apply">&#10003; Null safety migration applied</h1>
-    <h2 id="unit-name">&nbsp;</h2>
-    <button class="apply-migration">&#9998; Apply Migration</button>
-    <button class="apply-migration" disabled>&#9998; Apply Migration</button>
-    <button class="rerun-migration before-apply">
-      <span class="optional">&#8635; Rerun From Sources</span>
+    <h1>Dart</h1>
+    <h2 class="before-apply">Proposed null safety changes</h2>
+    <h2 class="after-apply">&#10003; Null safety migration applied</h2>
+    <h3 id="unit-name">&nbsp;</h3>
+    <a target="_blank"
+       href="https://goo.gle/dart-null-safety-migration-tool">
+      <button class="action-button">
+        <i class="material-icons">launch</i>
+        <span>Help</span>
+      </button>
+    </a>
+    <button class="action-button apply-migration">
+        <i class="material-icons">edit</i>
+        <span class="label">
+          Apply Migration
+        </span>
+    </button>
+    <button class="action-button apply-migration" disabled>
+        <i class="material-icons">edit</i>
+        <span class="label">
+          Apply Migration
+        </span>
+    </button>
+    <button class="action-button rerun-migration before-apply">
+      <span class="optional">
+        <i class="material-icons">replay</i>
+        Rerun From Sources
+      </span>
       <span class="required">
-        <span class="icon" 
-          title="Disk contents have changed. Rerun to get an up-to-date migration.">!</span>
+        <i class="material-icons">warning</i>
         Rerun With Changes
       </span>
     </button>
@@ -68,12 +88,9 @@
     </div><!-- /info-panel -->
 </div><!-- /panels -->
 <footer>
-    <a target="_blank"
-      href="https://goo.gle/dart-null-safety-migration-tool">Null safety
-        migration help</a>
+  <button class="report-problem">Send Feedback</button>
     <span class="wide"> </span>
-    <div>Based on <span id="sdk-version">{{ sdkVersion }}</span></div>
-    <button class="report-problem">Report a Problem</button>
+    <div class="sdk-version">Based on <span id="sdk-version">{{ sdkVersion }}</span></div>
 </footer>
 </body>
 </html>
diff --git a/pkg/nnbd_migration/lib/src/front_end/resources/migration.css b/pkg/nnbd_migration/lib/src/front_end/resources/migration.css
index 8f8c4e0..53fb7cc 100644
--- a/pkg/nnbd_migration/lib/src/front_end/resources/migration.css
+++ b/pkg/nnbd_migration/lib/src/front_end/resources/migration.css
@@ -2,6 +2,55 @@
 /* for details. All rights reserved. Use of this source code is governed by a */
 /* BSD-style license that can be found in the LICENSE file.                   */
 
+/*
+ * Colors mentioned in this file, e.g. "$dark-text-color" are from DartPad:
+ * https://github.com/dart-lang/dart-pad/blob/master/lib/scss/colors.scss
+ */
+
+/* Text selection */
+::selection {
+  background: #6e8eb1; /* $dark-selection-color */;
+}
+
+/* Material icons configuration */
+@font-face {
+  font-family: 'Material Icons';
+  font-style: normal;
+  font-weight: 400;
+  src: local('Material Icons'),
+  local('MaterialIcons-Regular'),
+  url(/MaterialIconsRegular.ttf) format('truetype');
+}
+
+/*
+ * Required for Material Icons:
+ * https://google.github.io/material-design-icons/
+ */
+.material-icons {
+  font-family: 'Material Icons';
+  font-weight: normal;
+  font-style: normal;
+  font-size: 24px;  /* Preferred icon size */
+  display: inline-block;
+  line-height: 1;
+  text-transform: none;
+  letter-spacing: normal;
+  word-wrap: normal;
+  white-space: nowrap;
+  direction: ltr;
+
+  /* Support for all WebKit browsers. */
+  -webkit-font-smoothing: antialiased;
+  /* Support for Safari and Chrome. */
+  text-rendering: optimizeLegibility;
+
+  /* Support for Firefox. */
+  -moz-osx-font-smoothing: grayscale;
+
+  /* Support for IE. */
+  font-feature-settings: 'liga';
+}
+
 body {
   background-color: #12202f;
   color: #ccc;
@@ -44,7 +93,8 @@
 }
 
 header h1,
-header h2 {
+header h2,
+header h3 {
   display: inline-block;
   font-family: "Google Sans","Roboto",sans-serif;
   font-weight: 400;
@@ -57,9 +107,20 @@
 
 header h2 {
   font-size: 1.2em;
+
+  /* Shift text up */
+  position: relative;
+  top: -2px;
 }
 
-header .apply-migration, .rerun-migration {
+header h3 {
+  /* Shift text up */
+  position: relative;
+  top: -2px;
+}
+
+
+header .action-button, header a {
   right: 0px;
   float: right;
   margin: 10px;
@@ -69,6 +130,8 @@
   height: 24px;
   width: 24px;
   margin-right: 8px;
+  position: relative;
+  top: 4px;
 }
 
 footer .report-problem {
@@ -88,36 +151,6 @@
   display:none;
 }
 
-/* Red triangle */
-.rerun-migration .required .icon::before {
-  transform: translate(-8px, -11px);
-  content: '\25B3';
-  font-size: 25px;
-  position: fixed;
-  color: #e82c2c;
-  text-shadow: 0px 0px 5px white;
-  z-index: -3;
-}
-
-/* Red triangle fill */
-.rerun-migration .required .icon::after {
-  transform: translate(-9px, -10px);
-  content: '\25B4';
-  font-size: 25px;
-  position: fixed;
-  color: #b3ecff;
-  z-index: -1;
-}
-
-/* Red triangle exclamation */
-.rerun-migration .required .icon {
-  display: inline-block;
-  margin-right: 8px;
-  transform: translate(0px, 2px);
-  margin-left: 2px;
-  color: #2b2b2b;
-}
-
 footer {
   color: #ccc;
   background-color: #27323a;
@@ -131,6 +164,10 @@
   flex: 1;
 }
 
+footer .sdk-version {
+  margin-right: 32px;
+}
+
 .horizontal {
   display: flex;
 }
@@ -142,7 +179,7 @@
 }
 
 .panel-heading {
-  color: gray;
+  color: #676767;
   margin: 8px;
 }
 
@@ -152,10 +189,11 @@
 }
 
 .nav-panel {
-  background-color: #282b2e;
+  background-color: #12202f;
   flex: 1 200px;
   margin: 0;
   overflow: scroll;
+  user-select: none;
 }
 
 .nav-inner {
@@ -176,6 +214,14 @@
   padding-left: 6px;
 }
 
+.nav-tree .material-icons {
+  font-size: 20px;
+  position: relative;
+  top: 5px;
+  margin-right: 8px;
+  color: #676767;
+}
+
 .nav-inner ul {
   padding-left: 12px;
   margin: 0;
@@ -220,9 +266,9 @@
 }
 
 .edit-count {
-  background-color: #37aedc;
+  background-color: #676767;
   border-radius: 10px;
-  color: #000000;
+  color: #fff;
   display: inline-block;
   font-size: 11px;
   font-weight: 600;
@@ -235,8 +281,8 @@
 
 .content {
   flex: 4 300px;
-  background: #282b2e;
-  font-family: monospace;
+  background: #12202f;
+  font-family: "Roboto Mono", monospace;
   margin: 0 6px;
   position: relative;
   white-space: pre;
@@ -251,13 +297,6 @@
   margin-left: 56px;
 }
 
-.hljs {
-  background-color: #282b2e;
-  display: block;
-  overflow-x: auto;
-  padding: 0.5em;
-}
-
 .code .welcome {
   font-family: "Google Sans","Roboto",sans-serif;
   font-size: 18px;
@@ -266,12 +305,12 @@
 }
 
 .code .nav-link {
-  color: inherit;
+  color: #16adca;
   text-decoration-line: none;
 }
 
 .code .nav-link:visited {
-  color: inherit;
+  color: #139bb5; /* #16adca darkened 10% */
   text-decoration-line: none;
 }
 
@@ -311,7 +350,7 @@
 }
 
 .regions td.line-no {
-  border-right: solid #282b2e 2px;
+  border-right: solid #12202f 2px;
   color: #999999;
   padding-right: 4px;
   text-align: right;
@@ -332,22 +371,22 @@
 }
 
 .region.added-region {
-  background-color: #ccffcc;
-  color: #003300;
+  background-color: #263952; /* $dark-selection-color */
+  color: #c0c2c5; /* $dark-editor-text */
 }
 
 .region.removed-region {
-  background-color: #ff6666;
-  color: #001100;
+  background-color: #FA557d; /* $dark-pink */
+  color: #fff;
 }
 
 .region.informative-region {
-  background-color: #404549; /* #282b2e, lightened 10% */
-  border-bottom: solid rgba(255, 255, 0, 0.7) 1px;
+  background-color: #178afd; /* $dark-selection-color */
+  color: #fff;
   display: inline-block;
-  height: 14px; 
+  height: 18px;
   position: relative;
-  top: 1px;
+  top: 3px;
 }
 
 .target {
@@ -366,7 +405,7 @@
 }
 
 .info-panel .edit-panel {
-  background-color: #282b2e;
+  background-color: #12202f;
   overflow: auto;
 }
 
@@ -392,11 +431,15 @@
 }
 
 .info-panel a {
-  color: #33ccff;
+  color: #139bb5;
+}
+
+.info-panel a:hover {
+  color: #1ec7e7; /* #139bb5 lightened 20% */
 }
 
 .info-panel .edit-list {
-  background-color: #282b2e;
+  background-color: #12202f;
   overflow: auto;
 }
 
@@ -456,7 +499,7 @@
 }
 
 .popup-pane pre {
-  background: #282b2e;
+  background: #12202f;
   padding: 20px;
   bottom: 0px;
   overflow: auto scroll;
@@ -494,8 +537,8 @@
 }
 
 .edit-panel .type-description {
-  /* From HLJS's .hljs-keyword, .hljs-selector-tag, .hljs-deletion */
-  color: #cc7832;
+  /* From DartPad $dark-orange */
+  color: #ff916e;
   font-family: monospace;
 }
 
@@ -510,8 +553,8 @@
 }
 
 ul.trace li .function {
-  /* From HLJS's .hljs-section, .hljs-title, .hljs-type */
-  color: #ffc66d;
+  /* from .hljs-variable */
+  color: #16adca;
   font-family: monospace;
   font-weight: 600;
 }
@@ -538,7 +581,7 @@
 }
 
 a:hover {
-  color: #fff;
+  color: #dbdbdb; /* #ccc lightented 30%*/
   fill: #fff;
 }
 
@@ -547,30 +590,79 @@
   margin: 3px;
 }
 
+.add-hint-link:hover {
+  color: #fff;
+}
+
+header button {
+  text-transform: uppercase;
+}
+
+header a {
+  margin: 0;
+}
+
 /* Careful here. `a.button` is repetitive but required to get correct
  * specificity */
 button, .button, a.button {
-  background-color: #33ccff;
-  border: 2px solid #37aedc;
+  background-color: rgba(22, 138, 253, 0.15);
+  border: none;
   border-radius: 3px;
-  padding: 6px 10px;
-  font-weight: bold;
-  color: #282828;
+  padding: 3px 10px;
+  font-weight: 500;
+  font-font: Roboto, sans-serif;
+  color: #fff;
 }
 
 button:hover, .button:hover {
-  background-color: #80dfff;
-  border: 2px solid #52b8e0;
+  background-color: rgba(22, 138, 253, 0.29);
   cursor: pointer;
 }
 
 button[disabled] {
-  background-color: #7aa8b8;
-  color: #507177;
-  border: 2px solid #507177;
+  background-color: rgba(255,255,255,.12);
+  color: rgba(255,255,255,.37);
   cursor: not-allowed;
 }
 
+/* Change edit panel button colors */
+.edit-panel .button, .edit-panel button {
+  background-color: rgba(63, 104, 148, 0.6);
+  color: white;
+}
+.edit-panel .button:hover, .edit-panel button:hover {
+  background-color: rgba(101, 153, 208, 0.6);
+  color: white;
+}
+
+/*
+ * Adjustments to align material icons in the toolbar buttons.
+*/
+.action-button > span {
+  position:relative;
+  top: -3px;
+}
+
+.action-button .material-icons {
+  top: 4px;
+}
+
+/* Don't shift the icon when it's a direct child of the button */
+.action-button > .material-icons {
+  top: 1px;
+}
+
+/* Shift the text to center with the icon. */
+.action-button > span.label {
+  position:relative;
+  top: -4px;
+}
+
+.action-button .material-icons {
+  font-size: 20px;
+  position: relative;
+}
+
 .placeholder {
   color: #777;
   text-align: center;
@@ -581,8 +673,57 @@
  * HLJS Overrides
  */
 .hljs {
+  background-color: #12202f; /* $dark-code-background-color */
+  color: #c0c2c5; /* $dark-editor-text */
+  display: block;
+  overflow-x: auto;
+  padding: 0.5em;
   /**
    * This allows the per-line highlights to show.
    */
   background: none;
 }
+
+.hljs-keyword,
+.hljs-selector-tag,
+.hljs-deletion {
+  color: #51c686; /* cm-keyword */
+}
+
+.hljs-number {
+  color: #627978; /* cm-number */
+}
+
+.hljs-comment {
+  color: #9198b4; /* cm-comment */
+}
+
+.hljs-literal {
+  color: #ee8666; /* cm-atom */
+}
+
+.hljs-string {
+  color: #e55074; /* cm-string */
+}
+
+.hljs-variable {
+  color: #16adca; /* cm-variable */
+}
+
+.hljs-link {
+  color: #e55074; /* cm-string */
+}
+.hljs-section,
+.hljs-type,
+.hljs-built_in,
+.hljs-title {
+  color: #ee8666; /* cm-variable-2 */
+}
+
+.hljs-addition {
+  color: #263952; /* $dark-selection-color */
+}
+
+.hljs-meta {
+  color: #627978;
+}
diff --git a/pkg/nnbd_migration/lib/src/front_end/resources/resources.g.dart b/pkg/nnbd_migration/lib/src/front_end/resources/resources.g.dart
index e03b662..52c6871 100644
--- a/pkg/nnbd_migration/lib/src/front_end/resources/resources.g.dart
+++ b/pkg/nnbd_migration/lib/src/front_end/resources/resources.g.dart
@@ -9,6 +9,19 @@
 
 import 'dart:convert' as convert;
 
+String get MaterialIconsRegular_ttf {
+  return _MaterialIconsRegular_ttf ??=
+      _decode(_MaterialIconsRegular_ttf_base64);
+}
+
+String get RobotoMonoRegular_ttf {
+  return _RobotoMonoRegular_ttf ??= _decode(_RobotoMonoRegular_ttf_base64);
+}
+
+String get RobotoRegular_ttf {
+  return _RobotoRegular_ttf ??= _decode(_RobotoRegular_ttf_base64);
+}
+
 String get dart_192_png {
   return _dart_192_png ??= _decode(_dart_192_png_base64);
 }
@@ -38,6 +51,6834 @@
   return String.fromCharCodes(convert.base64Decode(data));
 }
 
+String _MaterialIconsRegular_ttf;
+// MaterialIconsRegular_ttf md5 is 'a37b0c01c0baf1888ca812cc0508f6e2'
+String _MaterialIconsRegular_ttf_base64 = '''
+AAEAAAAPAIAAAwBwR0RFRgQAAFMAAYsIAAAAJEdQT1PgGO+cAAGLLAAAADZHU1VC5NKpUQABi2QAAGlQ
+T1MvMgpzImMAAAF4AAAAYGNtYXDx8DHgAAAJeAAABgJjdnQgABEBRAAAD3wAAAAEZ2FzcP//AAMAAYsA
+AAAACGdseWZEfewEAAAXHAABckhoZWFkBtqLZgAAAPwAAAA2aGhlYQQBAgQAAAE0AAAAJGhtdHhq5mlG
+AAAB2AAAB6Bsb2NhOymWhQAAD4AAAAecbWF4cAQnAOEAAAFYAAAAIG5hbWUcDzXkAAGJZAAAAXpwb3N0
+/4YAMgABiuAAAAAgAAEAAAABAtBPvyKIXw889QAJAgAAAAAA0t6jygAAAADS3qPNAAD//gIAAgQAAAAI
+AAIAAAAAAAAAAQAAAgAAAAAAAgAAAAAAAgAAAQAAAAAAAAAAAAAAAAAAAAMAAQAAA80AsAAYAAAAAAAC
+AAAAAQABAAAAQAAuAAAAAAAEAgABkAAFAAABTAFmAAAARwFMAWYAAAD1ABkAhAAAAgAFAwAAAAAAAAAA
+AAESAAAABAAAAAAAAAAAAAAAAIAAMP//AgAAAAAAAgAAAAAAAAEAAAAAAAAAAAAAACAAKwIAABEAAAAA
+AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAACsAKwAVAEAAKwBAAEAAVQBAAFUANQArAEAAQABVAGsAawBAACsAKwAr
+ACsAFQArAIAAKwArAKsAKwArACsAKwBAACsAFQBAAEAAVQBVAIAAgAArAIAAKwArACsAQAArAGsAlQBA
+AEAAKwBAACIAFQBVAFUAVQBVAFUAVQAVABUAKwArACsAVQAVABUAKwArABUAFQAsAEAAKwAVABUAFQAV
+ACsAQAAVACsAQAAAAFUAdwBAAGsAVQArAEAAKwArAEAAVQArACsAawBAAEAAKwBrACsAKwArADMAQAAr
+AAAAAAAAAFsAFQBrABUAawArACsAAAAVAEAAVQArAD4AFQAVACsAAAAAAEAAVQBrAEAAKwArAEAAAAAr
+AGsAKwArAEAAQAArAEAAawBVAD0AQAArACsAKwAhAGsAKwArAEAAAABAAEAAQAArAEAAawArACsAQABA
+ACsAFQArACsAKwArACsAKwArACsAlQCVAJUAlQCVAGsAQABVAEAADwAPAA8ADwArAFUAAAAVABUAFQAV
+ABUAFQBAACsACAArACsAQAAVAGsAFQABAFUAFQArACsAMwArABUACAAJAAgAKwBmAAAAKwCVAIcAQABA
+AEAAAABAAEAAQABAAEAAQABAAEAAQABAAEAAQACVACsAAABVAAAAQABAAIAAIAA1ACsAVQBrAEAAQABr
+AFUAawCAAEAAKwBVACsAQAArAEAAdwArAEAAawBVAEAAVQBVAFUAVQBXAFUAFQBLACsAVQA1ACsAawAr
+AAAAKwAAAAAAAAAAAAAAawBrACsAKwArACsAFQAVAAAAFQAVACsAgAArAEAAQAArAIAAqwC3AIAAQACA
+ACsAKwAVAGsAAAAAAAAAAABAAFUAawBrAAAAAABAAEAAQABVAGsAawBVABUAQAArABUAFQBVAEAAKwAV
+ABUAKwArAEAAawCAACsAQAA1ADUAKwBrAIAADwAPAA8ADwBAACsAKwArAGsAawArAEAAQAArAEAAQABA
+ACsAAABAAEAAFQBAAEAAQABAAEAAQABrAFUAKwBAAEAAKwBVACsAVQArAKgAFQAVABUAFQAVABUAFQAV
+ABUAFQAVAEAAQAAAACsAFQAVACwAMQAVAEAAKwCVAEAAQABVAAAAKwAeAEAAFQAVACoAQAArAEAAFQBA
+AEAAKwBAABUAQABAAEAAQABAACsAKwArAIAAawArAKsAtwBAABUAKwArAFUAKwBAAFUAKwArACsAQAAV
+ABIAVwBVAEAAFQAYACsAKwArAEAAKwAAAFkAQAAlACsAKwBAAEAAQAAAAAAAFQAVACsAFQAVABUAFQBM
+AAAAKwAAACsAQAAVAEAAKwAAAFUAQAAlAFUAVQBVAIAAKwAVAEAAKwArACsAKwBAACsAQAArAEAAQABV
+ABUAQAAVAFUAQABAAFUAKwCAAEAAQABAACsAKwArADoAKwAVAEAAQABAABUAYABrAGsAKwA6AEAAQAAV
+AFUAPgBrAGsAQABrAEAAQABVAEAAKwBVAGsAKwBVAFUAlQArAJUAVQArAEkAqwC3AGsAgACAAGsAawBA
+AFUA1QBWAJ4AngBVAGsAVQBVAIAAdwBrAEAAKwArACsAQABAAEAAQAArACsAAAAVAEAAQABAAEAAAABA
+AFUAVQArACsAVQA9AEAAawArAEAAAAArABUAKgAgABUAKwBAAEAAKwBVACsAFQAVABUAgABVABUAVQAV
+AEAAVQAVACsA1QArACsAVQArACsAQAArABUAAABAACsAKwBVAFUAVQArAFUAQAArABUAFQBVABUAVQBV
+AEAAKwAVAEAAVQArACsAKwArACsAQABAACsAKwArACsAKwABAEAAKwBAAEAAKwAVACsAKwAjACsAKwAr
+ABUAQABAAEAAQABAAEAAQABVAAAAVQBrAGsAVQAOABUAKwArABUAVQArACsAQABrAFUAQABJAAkAQABA
+ACsAKwArACsAKwArAFUAVQBAAEAAawArACsAKwArABUAKwCAAIAAVQArACsAFQBVAEAAQAArAEAAQABV
+AFUAVQArACsAVQBAAEAAFQArACsAKwBAAAAAawBVAAAAQAAAABUACwBAACsAKwArAEAAKwAVABUAawAr
+AEAALQBAAAAAawCAABUAEQAVABUAFQBrABUAFQBAAFUAWgBrACsAFQAVABUAKwA0ACsAQABVACsAQABr
+ACsAFQAVABUAVQAVABUAAABAAEAAFQArABUAKwBAACsAawBrAEAAKwBVACsAVQArAFUAVQBVAFUAVQAr
+ABUAFQArACsAKwArACsAawArACsAQABAAEAAFQArADUAJwCAAGsAQAArAFoAKwA+ABUAawAVAAAAZQBr
+ACsAQAArACsAQABAAAAAVQArAKsAFQBAAFUAFQBAACsAFQBAACsAAABVAAAAawArABUAAAA/ACsAQAAV
+ACsAKwBVAFUAKwBVACsAKwArACsAKwAAAAAABQAAAAMAAAAsAAAACgAAAhwAAQAAAAAE/AADAAEAAAAs
+AAMACgAAAhwABAHwAAAAeABAAAUAOAA5AF8AeuAD4BngIeAk4CzgMeA54FPgceC84L/gxODl4W3hleGc
+4cPhyOHQ4dvh4uJk4sTiyeLM4wjjGOM44+Dj7uQT5C7kPOU25XLl3eYg5kXmxebd5t/m4efp6AHoDugV
+6DroUehz6LbozukA6QbpD+kr60z//wAAADAAXwBh4ADgGeAb4CPgKOAu4DPgO+BV4K/gvuDD4MbhReGQ
+4Zzho+HI4c3h2OHg4ibivOLG4szjB+MK4xrjnePi4/HkFeQw5S3lOeXD5g7mI+bE5t3m3+bh5+nn7ugL
+6BHoNOhN6FPodei46NDpAukI6RHrO////9P/rv+tICggEyASIBEgDiANIAwgCyAKH80fzB/JH8gfaR9H
+H0EfOx83HzMfLB8oHuUejh6NHoseUR5QHk8d6x3qHegd5x3mHPYc9BykHHQcchv0G90b3BvbGtQa0BrH
+GsUapxqVGpQakxqSGpEakBqPGo4YfwABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAuAAAAAAAAAAPAAAADAAAAA5AAAAAwAAAF8AAABf
+AAAADQAAAGEAAAB6AAAADgAA4AAAAOADAAAAKAAA4BkAAOAZAAAALAAA4BsAAOAhAAAALQAA4CMAAOAk
+AAAANAAA4CgAAOAsAAAANgAA4C4AAOAxAAAAOwAA4DMAAOA5AAAAPwAA4DsAAOBTAAAARgAA4FUAAOBx
+AAAAXwAA4K8AAOC8AAAAfAAA4L4AAOC/AAAAigAA4MMAAODEAAAAjAAA4MYAAODlAAAAjgAA4UUAAOFt
+AAAArgAA4ZAAAOGVAAAA1wAA4ZwAAOGcAAAA3QAA4aMAAOHDAAAA3gAA4cgAAOHIAAAA/wAA4c0AAOHQ
+AAABAAAA4dgAAOHbAAABBAAA4eAAAOHiAAABCAAA4iYAAOJkAAABCwAA4rwAAOLEAAABSgAA4sYAAOLJ
+AAABUwAA4swAAOLMAAABVwAA4wcAAOMIAAABWAAA4woAAOMYAAABWgAA4xoAAOM4AAABaQAA450AAOPg
+AAABiAAA4+IAAOPuAAABzAAA4/EAAOQTAAAB2QAA5BUAAOQuAAAB/AAA5DAAAOQ8AAACFgAA5S0AAOU2
+AAACIwAA5TkAAOVyAAACLQAA5cMAAOXdAAACZwAA5g4AAOYgAAACggAA5iMAAOZFAAAClQAA5sQAAObF
+AAACuAAA5t0AAObdAAACugAA5t8AAObfAAACuwAA5uEAAObhAAACvAAA5+kAAOfpAAACvQAA5+4AAOgB
+AAACvgAA6AsAAOgOAAAC0gAA6BEAAOgVAAAC1gAA6DQAAOg6AAAC2wAA6E0AAOhRAAAC4gAA6FMAAOhz
+AAAC5wAA6HUAAOi2AAADCAAA6LgAAOjOAAADSgAA6NAAAOkAAAADYQAA6QIAAOkGAAADkgAA6QgAAOkP
+AAADlwAA6REAAOkrAAADnwAA6zsAAOtMAAADugAQ//0AEP/9AAADzAAAAQYAAAEAAAAAAAAAAQIAAAAC
+AAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAMEBQYHCAkKCwwAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAADQAODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJwAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAARAUQAAAApACkAKQAxADkAQQBJAFEAWQBhAGkAcQB5AIEAiQCRAJkAoQCpALEAuQDBAMkA0QDZ
+AOEA6QDxAPkBAQEJAREBGQEhASkBMQE5AUEBSQFRAW4BlQGtAeQCDAJVAqgCwALqAvwDDQMzA4QDygP5
+BCQEYASeBMUE/AU2BXEFogXLBd4F+wYjBi8GRgZoBo4GxQbwByYHZQeDB6oHywfwCAIIFQhNCFsIjAjZ
+CQcJKAlQCWYJdgm0CdwKCQpFCnMKngsNC8AMIQyQDUYNqQ3fDjAOew6aDswO3Q8BDzUPYw+HD8EP7xA2
+EFkQmhC8EN8RBxEpEUgRdhGZEe8SGxJNEmASexKREqQSwRLsEwYTNBNxE74UNBRZFIQUnRTSFRQVTRV1
+FaMVvRXgFgMWLxaRFtoXGxdgF5gXuxfdGAAYIhhSGHwYsxjaGREZWRmTGg0aOhp0Gp8ayhsJGx4bRhta
+G4MbohvMG/8cLhxXHHEcoBzxHSsdSh1sHYUdmR2qHg4eNx5rHpAetR7RHt4e9R8XHysfSR9sH5cgCiAb
+IDMgUSBtIJsgziEAITQhbiGdIcoh/iIyIlkikiK/IuQjDyM2I1YjdiO2I9okDSQ4JHEkniTRJPglHCVM
+JYkluSX4JjQmZSavJvknKidQJ10ncye2J/0oGyhiKKkpCSlOKXgptSnCKdsp/ioSKisqOiqJKqwq1isS
+K1AroCvYLBIsNyydLRgtPC2gLfYuXi6PLvQvKi+RL/cwHDBCMGgwjzC6MN0xFjE7MVkxgjGsMcEx6DIj
+Ml8yjDKlMsAy3TL/MyEzQTNYM4QzsjPSNA40PjRyNJY0sTTMNOs1ATUTNWI1eTWaNbE13DYUNiY2djac
+Nsc22Tb1NzM3RTd3N5g3wzftOBY4WjiUOL441TjrOQk5LjlhOYw5xjoLOjA6WTqEOso68TsXOzw7ZTu9
+O8473zvvO/88FDwqPIY8njy5POQ9CT0mPVs9gj3NPe4+Fj5DPnM+sj79Pyg/Sz+HP6k/6EAxQFVAfkCs
+QNRA/EEfQUVBY0GxQfBCJ0JQQn1CkUKsQ0JD1USzRadFuEXSRexGHEZDRmdGmkbIRu9HL0dlR6RH20gl
+SGNIrEjdSSpJUkmDSa1J6EoJSi1KUkp0SpVKuUrsSw5LOktcS4BLmUusS8tMAUwXTElMZ0ysTOtNJE1t
+TbxN9U4yTnlOx08BT2FPsFAJUDBQblCtUN9Q8lEjUYNR5FInUklSZ1J4UsJTJFODU+FUMVR3VLRU3FUE
+VXlVnVXWVgtWHlZbVqxWvlb3VxxXRFd1V69X01gHWDVYeFifWLhY1VkLWRxZLVl6WZ5Zu1nuWh9aUlp2
+WqFa11sIW2NbnVvJW/1cN1xwXJlcyl0KXThdZ12jXdNd/F57XvpfLF93X71f62AgYGZgf2C1YNZhDmFT
+YYNhp2IHYmxik2LIYxBjXWOfY+FkGmRJZG5kmmT2ZT1lgGXPZg5mPWZ8ZrBm1Wb5ZxdnSGdqZ7Jn7GgJ
+aDBooGjPaPxpUmmdad9qCGosanJqkWrKawprNGtTa3trp2vMbAZsK2xabIdsvWz7bUJtd22dbdlt624W
+bj5ubG6Zbs5u8m8Fb2hvnW/Ib/pwC3A/cHBwmXDlcRZxZ3GucexyNHJscoFyjXKkcrByxXLqcvtzDHMd
+czdzSHNZc31zonO7c+N0CnQxdE10aHR9dJN0qXS+dNV07HUsdWV1j3W4deF2JHZZdpd2zXb7dx13WneX
+d+J4GHhaeKx463kkeU55dHmeecR583o3enJ6nnrbex57V3t7e+B8CHw0fFR8hXyyfON9KX1nfaJ91n4E
+fix+TH6KfrF+7X8zf2p/qX/Yf++ABoAmgFCAeoCkgLeBEoFogaCB5YIqgmaCooLMgv+DPYN6g7GD54Qs
+hGSEwITchQaFOoVYhYSFwYXchhWGR4aIhsCHAYdNh4eHrYfRh+6IFogtiE6IdYjiiQOJKYlgiZGJuYoK
+ij6Kd4rJiv6LaYuOi8GL7YwtjHKMrIzljR2NVY2Eja6N0Y3ojgeOVY5/jq6OwY7cjw6PMY9Mj3aPk4+0
+j9+QJZA2kFaQhpC5kN2RHJFYkXqRvpHkkhiSTZKrkvSTC5Mik1aTipO6k+iT/JQhlDaUcJSOlLaU45UB
+lRuVPZWhlcyV9pYwlm2WrZbvlxOXQZdul5mXxpgAmCqYbZinmRuZSJl8mbCZ5JoCmiyaSZpwmp+axprx
+mzObkpuqm9icAJwnnFGcs50rnVqdjp3AngKeLp5qnsqfKp9Un6yf5qAjoFmgmaDVoP+hN6Ftoa+h66IO
+ojCiVKJyoqeiwKLZov2jLKNRo7aj9qQkpFKkmKTCpPOlIaVspaalvqXPpeel/qYdpjymbKaGpp+muabh
+pwGnK6dSp2+ngqfGp/KoRaikqNKpEqk9qW+pgqm7qfaqFqpOqn6quarjqwurNatUq4SrpqvHq/esO60C
+rSatYq2LrduuG65mroCuuq7rrxmvWq96r7+v37BOsHGwprDzsTKxfLGusciyBrI/sriy/7M5s3Czo7Pk
+tCu0abSbtNe1K7Wmteq2HLZFtm223LcQt8G35rg5uIi4tLkkAAIAEQAAAJkBVQADAAcALrEBAC88sgcE
+AO0ysQYF3DyyAwIA7TIAsQMALzyyBQQA7TKyBwYB/DyyAQIA7TIzETMRJzMRIxGId2ZmAVX+qxEBMwAB
+AAAAAAAAAAAAAAAAMQAAAQAAAAAAAAAAAAAAADEAAAEAAAAAAAAAAAAAAAAxAAABAAAAAAAAAAAAAAAA
+MQAAAQAAAAAAAAAAAAAAADEAAAEAAAAAAAAAAAAAAAAxAAABAAAAAAAAAAAAAAAAMQAAAQAAAAAAAAAA
+AAAAADEAAAEAAAAAAAAAAAAAAAAxAAABAAAAAAAAAAAAAAAAMQAAAQAAAAAAAAAAAAAAADEAAAEAAAAA
+AAAAAAAAAAAxAAABAAAAAAAAAAAAAAAAMQAAAQAAAAAAAAAAAAAAADEAAAEAAAAAAAAAAAAAAAAxAAAB
+AAAAAAAAAAAAAAAAMQAAAQAAAAAAAAAAAAAAADEAAAEAAAAAAAAAAAAAAAAxAAABAAAAAAAAAAAAAAAA
+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
+NCYnNRYWFRQHJzYnFAcnNRYBAC14AWUbLCUpGRdba1VlZQFVOy9BVBYgCzUBNDUBq1otQv6bGywdCiwH
+EluQa4BlpTNODiwOaUQwKSEbHQkENC8aAAMAQABFAcABuwALAA8AFQAAARYWFAYHNTY2NCYnFhQHNQcz
+NxEnIwErQVRUQS87Oy81NetVa2tVAbsOaYhpDiwOTmZODlN4GqwWa/6qawAABAArAFUB1QGrAAMABwAL
+ABsAACU1IxUnNSMVFzUjFQEyFhURFAYjISImNRE0NjMBq1YV6+vrAVYRGRkR/qoRGRkRgMDAa1VVa1VV
+ASsaEf8AERoaEQEAERoABABAAEABwAHAAAMADQAZACkAACU1MxUnFTMyNjU1NCYjBzUjFSM1IxUzNTMV
+EzIWFREUBiMhIiY1ETQ2MwE1K0tWCQwMCYAgKyAgK8oRGhoR/tYSGRkS4EBAYIAMCVYJDICANTWAKysB
+ABoR/tYRGhoRASoRGgAABQAiADEB0gHPAAkADAAUABcAGgAAJTMVIzU3IzUzFQUzJyczFyMnIwcjFzMH
+EyM3AVCCtn59sf6cUyoRI2AnFG0UJ7ljMjNlMqgiG7ciG4JvLvQ0NCMyAWwyAAACABUAKwHrAcAAFwAa
+AAABMhYVERQGIyM1MxEhETMVIyImNRE0NjMTNxcBwBEaGhFVVf6AVVURGhoRQICAAcAaEf8AERkqAQD/
+ACoZEQEAERr+a4CAAAQAVQBAAasB6wATADQAOwBPAAAlFDMyNzc2NTUmNCYjIgcHBhUVFjcUBwcGIyIG
+IyInJiYnJjU1NDc3NjMyNjMyFx4CFxYVByM1BzU3Mwc0NjM1Fwc1IgYUFjI2NTMUBiImARoKBQIEAgIJ
+AgMDBAMDKAIGBwQCCQIJBAIGAgkCBwYEAgkCCQQCBwQEAlkUFSYDlGRHa2s0TExoTCtljGW8BwIFBAIr
+BAQFAwQEAisEEw0EDQYCAgEEAQUZDw0EDQYCAgEEAgwGCzVGBg8MG0ZkVmtrVktqS0s1R2RkAAQAVQBA
+AasB6wATACcARwCJAAA3NDYzNRcHNSIGFBYyNjUzFAYiJjcUMzI3NzY1NSY0JiMiBwcGFRUWNxQHBwYj
+IgYjIicmJyY1NTQ3NzYzMjYzMhceAhcWFSMyNTUmNCMjBiIVFSM0NjMyNjMyFxYVFQYVFCMiBxYXFhUU
+BwYGBwYjIgYjIicmJicmNTMVFhQzMzYyNTUmNCMjNVVkR2trNExMaEwrZYxlxwoFAgQCAgkCAwMEAgIq
+AgYHBAIJAgcQAgQDAwYHBAIIAgkEAgcEBAJxDwIECwIEFgsHAQgBDAwIAgQCBQkCBAIBBAEEBwIJAggC
+AQgCCRICBAsCBAIEDetGZFZra1ZLaktLNUdkZBgHAgUEAisEBAUDBAQCKwQTDQQNBgIIAQwJCA8LBg0G
+AgIBBAIMBgsNBAIEAgQECA8CBgQPBwQCBAUFAwgFCQIBBgEEAgIBAgEFEAQCBAIECwIEDwACAFUAQAGr
+AesAMgBGAAA3BhUHIzczFSMHMjU0NjUzMzIXFhYXFhUUBwYGBwYjIicmJicmNTMUMzI3NzY1NScnJiMn
+NDYzNRcHNSIGFBYyNjUzFAYiJvoHAg0FMyUCAgMEBAgDAQYBCQIBBAIIDwkCAQcCCRENBAIFAgIFBAKp
+ZEdrazRMTGhMK2WMZd4DAQMvDxMCAQEBAwEEAQkOCQIBCAIIAgECAQUOCgIEBAINBAUCDUZkVmtrVktq
+S0s1R2RkAAQAVQBAAasB6wATADQAOwBPAAAlFDMyNzc2NTUmNCYjIgcHBhUVFjcUBwcGIyIGIyInJiYn
+JjU1NDc3NjMyNjMyFx4CFxYVByM1BzU3MzcyFhUUBiImNTMUFjI2NCYjFSc3ARoKBQIEAgIJAgMDBAMD
+KgIGBwQCCQIJBAIGAgkCBwYEAgkCCQQCBwQEAlsUFSYDF0dkZYxlK0xoTEw0a2u8BwIFBAIrBAQFAwQE
+AisEEw0EDQYCAgEEAQUZDw0EDQYCAgEEAgwGCzVGBg8Mj2RGR2RkRzVLS2pLVmtrAAQAVQBAAasB6wAV
+ADUAdwCLAAAlFDMyNzc2NTU0JjU0JiMiBwcGFRUWNxQHBwYjIgYjIicmJyY1NTQ3NzYzMjYzMhceAhcW
+FSMyNTUmNCMjBiIVFSM0NjMyNjMyFxYVFQYVFCMiBxYXFhUUBwYGBwYjIgYjIicmJicmNTMVFhQzMzYy
+NTUmNCMjNTcyFhUUBiImNTMUFjI2NCYjFSc3AR4LBAIEAgIIAgQDBAICKAIGBwQCCQIHEAIEAwMGBwQC
+CAIJBAIHBAQCcQ8CBAsCBBYLBwEIAQwMCAIEAgUJAgQCAQQBBAcCCQIIAgEIAgkSAgQLAgQCBA0zR2Rl
+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
+EzMVIzUHJzcjwNUq+B74jQGV1Y34HvgAAAIAdwBNAYkBtQAIAAwAABM3FyMVByc3NRMnNxegYGBLgB50
+gEkeSQFVYGCIgB5zd/74SB5IAAEAQACNAcABawAKAAABFwcnFSM1MxUjFwGiHsCVK6tidwFrHsCVYqsr
+dwAAAQBrAGsBqwGrAAgAAAEHMxUjNTMVNwGr+I3VKvgBjfgq1Y34AAACAFUAVQGrAasACAAPAAATBxcV
+IzUnBzUzMxUnByc31TFxKmUx1oAxPh4+AasxcbSiZTGAgDE+Hj4ABAArACsB1QHVAAMABwALABkAAAE1
+IRUXNSMVNRUhNTcyFhURFAYjIQcRNDYzAYD/AKurAQArERkZEf7VVRkRAVUrK4ArK2srK5UZEf8AERpV
+AYARGQADAEAAlQHAAWsAAwAHAAsAABMhFSEHNSEVJTUhFZUBK/7VVQEr/wABKgFrK6srK1YqKgAABAAr
+ACsB1QHVAAMABwALABkAAAE1IRUFNSEVBTUhFSURJyEiJjURNDYzITIWAYD/AAEA/wABAP8AAVVV/tUR
+GRkRAVYRGQFVKytAKytAKyvW/oBVGhEBABEZGQAFACsAAAHVAgAABwAPAB8AIwAnAAAlNTQmIgYVFTYi
+BhQWMjY0NzIWFREUBiMhIiY1ETQ2MxE1IRURFSE1AWtJREl/KBwcKBx7ERkZEf6qERkZEQFW/qqVIBge
+Hhgg2xwoHBwoVxoR/wARGhoRAQARGv5VKysCACsrAAUAQABAAcABwAAcACAAJgAyADYAACUyFhUVFAYj
+IiY1NDYzMzIWFRQXFgcHFhc3NhcWNzUjFSczFSMVIycVIzUzNSM1MxUjFTcVIzUBqwkMDAmW1QwJSwkM
+DAQJLy9eLwkNJCgWFUArFUBAKytAK1YWtQwJSwkM1ZYJDAwJKCQNCS9cMS8JBAzgFhYrQCtAQBYVQBUW
+K2trAAAKAFUAFQGrAesABwAPABcAHwAnAC8ANwA/AEcATwAAEjIWFAYiJjQWMhYUBiImNDYyFhQGIiY0
+FjIWFAYiJjQmMhYUBiImNDYiJjQ2MhYUBDIWFAYiJjQ2MhYUBiImNDYyFhQGIiY0EjIWFAYiJjTvIhoa
+IhoaIhoaIhqaIhoaIhoaIhoaIhpmIhoaIhq8IhoaIhr+xCIaGiIaGiIaGiIaGiIaGiIamiIaGiIaAesa
+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
+NjMBq6urq6sRGRkR/qoRGRkRAVUra2srasAaEf8AERoaEQEAERoAAQAhAKsB1QFrAA4AAAE3FSM3JiMi
+BgcnNjYzMgGJTMBOMD44WREyFnVJVQEeTcBNKEE0EERWAAABAGsA6wGVARUAAwAAJSE1IQGV/tYBKusq
+AAIAKwArAdUB1QADAAsAACU1IxU2MhYUBiImNAFr1hOwfX2wfesqKup9sH19sAADACsAKwHVAdUABwAP
+ABMAADYyNjQmIgYUEjIWFAYiJjQXMxUjuoxlZYxlU7B9fbB9atbWVWWMZWWMARt9sH19sEMqAAEAQABV
+AcABlQAIAAATFhYXJiMVJzfVaHESTZ6VlQFAD4FbbVeVlQACAAAAVQIAAZUACAAOAAABFhYXJiMVJzcH
+BxcVJzcBFWhxEk2elZWAVVWVlQFAD4FbbVeVlUBVVUCVlQADAEAAQAHAAcAAAwALABMAACU1IxUWMjY0
+JiIGFBMXFQcjJzU3ARUqChYRERYRbHBwoHBw64CAXBEWEBAWASBwoHBwoHAAAwBAAEABwAHAAAMACwAZ
+AAABNSMVFjI2NCYiBhQTFxEUBiMhIiY1ETQ2MwFA1Xs0JiY0JqtVGhH+1hIZGRIBQFVV1SY0JiY0AS9V
+/wARGhoRASoRGgASAEAAQAHAAcAAAwAHAAsADwATABcAHAAgACQAKAAsADEANgA6AD4AQgBGAEsAABMV
+MzUHNTMVAzUzFQM1MxU3NTMVJzUzFQM1MxQGJzUzFQc1MxUDFSM1AzUzFRUiJjUzATIWFSMnFSM1BzUz
+FRM1MxUnNTMVJzQ2MxXAgKvWKysrKyorKysrKxoRK9UqVStVKxEaKwEqERorgCqrKyorgCsrGhEBQICA
+q9bWAQArK/6rKytVKyurKyv/ACsRGqsqKqsrKwGAKyv+1SsrVRoRAVUaESsrK4ArK/8AKyurKiqqERor
+AAEAKwBAAesBwAAFAAA3NSUlNQUrAUD+wAHAQJUrK5XAAAADAEAAgAHAAYAAAwAHAAsAADc1IRUlIRUh
+FTUzFUABAP8AAYD+gIDrKiqVK9UrKwADAGsAawGVAasAAgAKAA4AAAEHMwcHIzczFyMnByEVIQEAKFBd
+FCxlIGUsFMoBKv7WAYBrJi/r6y9aKgABACsAqwHfAWsADgAAATIWFwcmJiMiBxcjNRc2AQtJdBcyEVk4
+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
+FREVNzMHFwcjNQcnNyc3FzUzBwcnNwGVKysqLigoPVxcehViHnd3HmIVayorKwErKysrXClRAQhRKVxc
+eaJiHnd3HmKi1SsrKwAAAwBVACsBqwHVAAIADQAWAAAlNycnAQcnByM1Byc3JxcVJzUzFwcnNwEVKCii
+ATgeMVwVYh53jcAqFXpBHiJ8KCne/sgeMVuiYh53jQlFK2t5QR4jAAAFAEAAKwHAAdUAAgAFABMAGwAh
+AAAlJxURFTczBxcHIzUHJzcnNxc1MxcWFAcnNjQnBzcWFRQHARMoKDxcXHoVYh53dx5iFcwfIRkVFVYx
+CgqkKVEBCFEpXFx5omIed3ceYqJkMno0GSpYKlYxGRgZGQADAA8ADwHxAfEABwAXABoAACUzJyMHMzcz
+NxcHFSMHJyM1Jzc1MzcXMwc3FwExKUUqRSkPRIlGRmRHR2RGRmRHR2TEGRmrwMAqckdHZEZGZEdHZEZG
+uU5OAAADAA8ADwHxAfEABwAPAB8AABIyFhQGIiY0FjI2NCYiBhQlFwcVIwcnIzUnNzUzNxcz3UYyMkYy
+IGpLS2pLAStGRmRHR2RGRmRHR2QBVTJGMjJGo0tqS0tqfEdHZEZGZEdHZEZGAAACAA8ADwHxAfEABwAX
+AAA2MjY0JiIGFAUVIwcnIzUnNzUzNxczFRfLaktLaksBK2RHR2RGRmRHR2RGgEtqS0tqEmRGRmRHR2RG
+RmRHAAACAA8ADwHxAfEABQAVAAAlMjY0JiMXFSMHJyM1Jzc1MzcXMxUXAQA1S0s1q2RHR2RGRmRHR2RG
+gEtqS8dkRkZkR0dkRkZkRwACACsAKwHVAdQAEQAdAAAlMjcXBiMiJjU0NjcVBgYVFBYTFhYVFAcnNjU0
+JicBAEgsOEBsWH1vUTZKV1NRbxI4Cko2azghV31YU3kIQAhUOD5XAWkIeVMwJyEcGjhUCAAEAFUAFQGr
+AesADQATABkAJwAAJTUzFRQGIyMiJjU1MxU3Byc3FwcXJzcnNxclFSM1NDYzFzIWFRUjNQFrKhkR1hEZ
+KkAeYmIeQ7ceQ0MeYv7qKhkR1hEZKmsqVREaGhFVKlEeYmIeRGIeREQeYpUqVREaARkRVSoAAAMAAABV
+AgABqwADABMAIAAAJTUjFTcyFhUVFAYjIyImNTU0NjMlFTMVITUzNTQ2MyEVAdVVawkMDAmACQ0NCf7q
+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
+AEMARwBLAE8AUwAAATUzFQc1MxUHNTMVAzUzFTczFSMHNTMVMzUzFQM1MxUnNTMVBzUzFSc1MxUnNTMV
+BzUzFQc1MxUHNTMVBzUzFTM1MxUnNTMVBzUzFSc1MxUnNTMVAUArKysrK4AqgCsrqiqAKysrKysrK9Uq
+1SsrKysrKysrK4AqKiqAKysrKysBlSsrqioqqysrAVUrKysrVSsrKyv/ACsrqyoqVisrVioqqisrVSsr
+VSoqVisrVSsrKytVKytVKyurKiqqKysAAAMAAAAAAgACAAADAA0AEgAANSEVIQEHJzc2MhcXFhQHByM1
+NwIA/gABuipQKgYSBjIGRdZQ1lVVAaoqUCoGBjIGEkXWUNYAABEAQABAAcABwAADAAcACwAPABMAFwAb
+AB8AIwAnACsALwAzADcAOwA/AEMAACU1MxUjNTMVJzUzFTc1MxUnMxUjBTUhFQc1MxU3NTMVAxUjNRcV
+IzU3FSM1IxUjNSMVIzUTNTMVJzUzFTUVIzURNTMVAZUrgCuAKoArKysr/qsBgNUqgCurKioqgCuAKyor
+VSuAKysrQCsrKytVKyurKyuAK6oqKqsrK1UrKwErKytVKytVKysrKysr/oArK1UrK9YrK/7VKysADQBA
+AEABwAHAAAMABwATABcAGwAfACMAJwArAC8AMwA3ADsAACU1MxUHNTMVAxUzFSMVIzUjNTM1EzUzFRMz
+FSMVNTMVJxUjNSMVIzUzFSM1AzUzFTUVIzUTNTMVIzUzFQGVKysrq6urKqurVSsqKysrVSvVK4ArVSsr
+VSuAK5UrK1UrKwGAqyqrqyqr/oArKwGAK1UrK4ArKysrKyv+1Ssr1isr/tUrKysrABEAQABAAcABwAAD
+AAcACwAPABMAFwAbAB8AIwAnACsALwAzADcAOwA/AEMAAAE1MxUHNTMVFzUzFSc1MxUnMxUjETUzFQc1
+MxUTNTMVAREzETc1MxUnNTMVAzUzFTc1MxUnNTMVJzUzFQM1MxUHNTMVAUArKysqKysrKysrK4ArKiv+
+gCsqKysrKysrKioqKioqKioqAZUrK6oqKqsrK6sqKtUr/wArK1UrKwEAKyv/AAGA/oCrKiqqKyv+qysr
+qyoqVSsrVSsr/wArK1UrKwAHAEAAQAHAAcAAAwAHAAsADwATABcAGwAAExUjNRcVIzUXESERAyERISUV
+IzUjFSM1NxUjNcArgCqq/tYrAYD+gAErKysqKioBFSoqVSsrVQEq/tYBVf6A1SoqKipWKysAABEAQABA
+AcABwAADAAcACwAPABMAFwAbAB8AIwAnACsALwAzADcAOwA/AEMAABM1MxUnNTMVBzUzFTc1MxUDNTMV
+EzMRIyc1MxUHNTMVJzUzFQc1MxUnNTMVFzUzFSM1MxU3NTMVJzUzFSM1MxUTNTMV6yoqKioqKysrKyor
+K1UrgCrVKysrKyuAKtUrKisrK4ArKisBQCsrVSsrqioqqisr/qsrKwGA/oCrKipWKyurKyurKytWKiqr
+KysrK6sqKqorKysr/qsrKwAIAEAAQAHAAcAAAwAJAA0AEQAVABkAHQAhAAABNTMVJSEVIREjJTUzFQc1
+MxUHNTMVIzUzFTM1MxUjNTMVAZUr/oABgP6rKwFVKysr1SqAK9UrgCsBQCsrgCv+q6sqKlYrK1UrKysr
+KysrKwARAEAAQAHAAcAAAwAHAAsADwATABcAGwAfACMAJwArAC8AMwA3ADsAPwBDAAAlNTMVFzUzFQM1
+MxUTNTMVNzUzFQEhFSEFNTMVJzUzFQc1MxUnNTMVBzUzFQc1MxUnNTMVFzUzFSc1MxUjNTMVBzUzFQFA
+Kyor1SorKyor/oABgP6AAVUrKyvVKtUrKysrKysrgCoqKoArKyvrKiqrKysBACsr/wArK1UrKwErK6oq
+KlUrK6srK6srK1UqKqsrK1UrK1UrK6sqKioqqysrABEAQABAAcABwAADAAcACwAPABMAFwAbAB8AIwAn
+ACsALwAzADcAOwA/AEMAACU1MxUHNTMVAzUzFRc1MxUnMxUjFTUzFQc1MxUjETMRNzUzFQE1MxUDNTMV
+BzUzFSc1MxUzNTMVBzUzFQM1MxUHNTMVAUArKysrKyorKysrKysr1SqAK/7VK4ArKysrKyorKyuAKysr
+6yoqqysrAVUrK1UrK4ArqioqqysrAYD+gFUrKwEAKyv/ACsrVSsrqyoqKiqrKysBVSsrVSsrAAUAQABA
+AcABwAADAAcACwAPABMAABMhFSEXMxUjBzUhFQU1IRUlMxUjQAGA/oBV1tZVAYD+gAGA/tXW1gHAKyor
+VSoqqysrgCsABQBAAEABwAHAAAMABwALAA8AEwAAEyEVIRU1IRUFNSEVBTUhFQU1IRVAAYD+gAGA/oAB
+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
+ATMnJzMXERQGIyEiJjUTNDYBFXZ2lauAGhH/ABEaARkBQHUggP8AERkZEQFWERkAAAUAKwArAdUB1QAF
+AA0AFQAdACUAACQiJiczBiYiJjQ2MhYUFiImNDYyFhQGMjY0JiIGFBIyFhQGIiY0ASVKOw3aDZ4aExMa
+E4MaExMaE7GMZWWMZVOwfX2wfYspISFhExoTExoTExoTExrTZYxlZYwBG32wfX2wAAMAQABAAcAB6wAD
+ABsAHwAAJTUhFRMzFTMyFhURFAYjISImNRE0NjMzNTMVMxcVIzUBlf7W6isVERoaEf7WEhkZEhUrqhZr
+a+rqAYArGhH+1hEaGhEBKhEaKyvAa2sAAAMAKwCVAdUBawAPABMAIwAAATIWFAYjIzUzMjY0JiMjNQc1
+MxUkFBYzMxUjIiY0NjMzFSMiAWssPj4sVlYbJycbVmqq/v4nG1ZWLD4+LFZWGwFrP1g/KSc2JymAKiow
+NicpP1g/KQAAAgBAAEABwAHAAAQAFAAANwchJwcXFAYjISImNRE0NjMhMhYVtUoBKmBK1RoR/tYRGhoR
+ASoRGuBggGA1ERoaEQEqERoaEQAAAgB3AE0BiQG1AAgADAAAEzcXIxUHJzc1Eyc3F6BgYEuAHnSASR5J
+AVVgYIiAHnN3/vhIHkgAAQArACsB1QHVAA0AAAERJyEiJjURNDYzITIWAdVV/tURGRkRAVYRGQGr/oBV
+GhEBABEZGQAAAgBAAEABwAHAAAkADgAAAQcnNzYyFxcWFAU3FwcjAbonUCcGEgYyBv6A7FDsUAFqJ1An
+BgYyBhLg7FDsAAACAGsAVQGVAasABgAKAAA3NxcjFSM1JyEVIWuVlVWAVQEq/tbVlpaAgNYrAAEAVQDA
+AasBQAAHAAABMxUhNTMVIQGAK/6qKwEAAUCAgFUAAAIAQACAAcABwAAfADgAADcUMzI1NCYnIiYmIyM1
+IRUjFBYXFhUUBwYjIicmJyY1NzQjIgcGFRQXFhcjNCY1JjU0NzYzMhcWFcg+MQ0RAQUEAs0BgFMDAQdD
+FRkQDyQUJ64zJAsDEBAOYgQIICIxNR4f6DYkEA4IAgIrKwEFARESPRMGAwcPHTJ4LRYGCA8LCgUBAwEN
+FyUaGBscKQAAAgBVAEABqwHAAAMACgAANyEVISUHJzM1MxVVAVb+qgEAVVVAKmsrq1ZW1dUAAAMAVQAV
+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
+KyorKyoRGhoRASoRGhoRKgADAIAAFQGAAesAAwATABcAACU1IxUTMhYVERQGIyMiJjURNDYzETUzFQFV
+qqoRGhoRqhEaGhGqwNXVASoZEf7VERkZEQErERr+KisrAAAEACsAKwHVAdUABAAJAA4AEwAAATMVIycH
+NxcVIwMXByM1JQcnNTMBYHV1QGBAQIAgQEB1ARVAQIABQIBAYEBAdQEVQECAIEBAdQAAAQBAAFUBwAHr
+ABkAABIyFhUVFAYjIzUzNTQmIgYVFTMVIyImNTU0sKBwJhpAVVd8V1VAGiYB63FPlhomqys+V1c+K6sm
+GpZPAAABAEAAFQHAAesAHQAAEjIWFRUUBiMjNTM1IzUzNTQmIgYVFTMVIyImNTU0sKBwJhqAlVVVV3xX
+VUAaJgHrcU/WGiYrFasrPldXPiurJhqWTwAADAArAGsB1QGVAAMABwALAA8AEwAXABsAHwAjACcAKwA7
+AAABNSMVFzUjFSc1IxUXNSMVFzUjFSc1IxUXNSMVNxUzNScVMzUXFTM1JxUzNTcyFhUVFAYjISImNTU0
+NjMBlSoqKhYqKioqqhYqKipAKioqFioqKpYRGRkR/qoRGRkRASsqKkAqKkAqKkAqKlYrK5YqKkAqKioq
+KkAqKkAqKkAqKkAZEdYRGRkR1hEZAAABAIAAuwGAAVkABQAAExc3FwcnnmJiHoCAAVliYh6AgAAAAQCr
+AIsBSQGLAAUAACUHJzcXBwFJHoCAHmKpHoCAHmIAAAEAtwCFAVUBhQAFAAA3Nyc3Fwe3YmIegICjYmIe
+gIAAAQCAALcBgAFVAAUAADcnNxcHJ54egIAeYrcegIAeYgABAEAAgAHAAYAACAAAARUhFwcnNxcHAcD+
+0kwegIAeTAEVKk0egIAeTQACAIAAgAGAAYkAAwAJAAA3NSEVJwcnNxcHgAEAgGIegIAegCsrzWIegIAe
+AA0AKwAVAdUBwAACAAYACgAOABIAFgAaAB4AIgAmACoALgA+AAAlJzM3NSMVFzUjFSc1IxUXNSMVFzUj
+FSc1IxUXNSMVNxUzNScVMzUXFTM1JxUzNTcyFhUVFAYjISImNTU0NjMBAFWqQCoqKhYqKioqqhYqKipA
+KioqFioqKpYRGRkR/qoRGRkRFVbqKytAKytAKytAKytVKyuVKytAKysrKytAKytAKytAKytAGhHVERoa
+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
+FhUVFAYjISImNTU0NjMBkhwSEhwSQhoTExoTQEArQEArARURGhoR/oARGhoRAQASHBISHFISHBISHBkq
+QEAqQECVGhGqERoaEaoRGgADACsAKwHVAdUACwAbACQAAAE1IzUjFSMVMxUzNTcyFhURFAYjISImNRE0
+NjMHESEVISImNREBlVUrVVUraxEZGRH/ABEaGhFWASv+1REZARUrVVUrVVXAGRH/ABEaGhEBABEZVf7V
+KhkRASsAAAMAKwArAdUB1QAHAA8AFwAAABQGIiY0NjIGMjY0JiIGFBIyFhQGIiY0AUAmNCYmNGCMZWWM
+ZVOwfX2wfQEaNCYmNCbrZYxlZYwBG32wfX2wAAACAEAAFQHAAdUABwAaAAAlNycnBwcXFxMyFhURFAYj
+IwcnIyImNRE0NjMBKFhYKChYWCiVERoaEVVAQFURGhoR7SgoWFgoKFgBQBkR/tURGkBAGhEBKxEZAAAB
+AGsAQAGrAasACQAAATMVIycjFSMRMwEzeJYIeCrAAYDVKpUBawAAAQCAAEABlQHAAA8AAAEzFSMVIwYG
+IyImNDYzMhcBAJVVAQQ2JSg4OCgRDwHAQOskMThQOAYADgArACsB1QHVAAcADwAXAB8AJwAvADcAPwBH
+AE8AVwBfAGcAbwAAJDIWFAYiJjQXMhUUIyI1NAYyNjQmIgYUEjIWFAYiJjQFMhUUIyI1NBcyFRQjIjU0
+JyI1NDMyFRQGMhYUBiImNCciNTQzMhUUBzIVFCMiNTQXMhUUIyI1NCcyFRQjIjU0FjIWFAYiJjQ2MhYU
+BiImNAEiEgwMEg0WCgoLZoxlZYxlU7B9fbB9AUAKCgsLCgoLNQsLChMSDAwSDUAKCgtLCwsKSgsLCjYL
+CwpBEg0NEgwMEg0NEgzrDRIMDBI+CwoKC0tljGVljAEbfbB9fbAjCgsLClULCgoLgAsKCgsgDBINDRIs
+CwoKC4ALCgoLQAsKCguVCgsLCkoNEgwMEmIMEg0NEgAADgBAAEABwAHAAAcADwAXAB0AJQApADEAOQBB
+AEkATQBVAF0AZQAAJCImNDYyFhQmIiY0NjIWFCYiJjQ2MhYUFyI0MzIUJyI1NDMyFRQlIRUhBSI1NDMy
+FRQGIiY0NjIWFCYiJjQ2MhYUJiImNDYyFhQDNSEVAiImNDYyFhQGIiY0NjIWFAYiJjQ2MhYUAR4SDAwS
+DQ0SDAwSDQ0SDAwSDUALCwoKCwsK/ssBgP6AASsLCwqsEgwMEgxdGhMTGhMTGhMTGhNLAYD3EgwMEgwM
+EgwMEgxdGhMTGhOVDRIMDBJJDBIMDBJJDBINDRJXFhZWCgsLCnUr9QsKCgsLDRIMDBI+EhwSEhxDExoT
+Exr++CsrAQAMEg0NEmEMEgwMEmwTGhMTGgAAEgA1ADUBywHLAAUADQATABkAIQAnAC8AVABaAGIAagBy
+AHoAgACGAIwAmACgAAA2MhUUIjUWMhYUBiImNBcyFCMiNCYyFRQiNRYyFhQGIiY0JDIVFCI1BjIWFAYi
+JjQDNwEHJxYVFAYiJjQ2MzIXJwYGIyImNTQ2NycWFRQGIiY0NjMXFzIUIyI0EiImNDYyFhQGIiY0NjIW
+FAYiJjQ2MhYUJiImNDYyFhQWIjU0MhUnIjQzMhQzIjQzMhQHJiYnNTQ2MhYUBiM2IiY0NjIWFDUWFkIS
+DAwSDGoLCwqWFhZCEgwMEgwBShYW6RINDRIMixsBWxxQAQwSDQ0JBAI8AhIMDRMQCzwBDBIMDAkGpQoK
+C2kSDAwSDAwSDAwSDAwSDAwSDLcSDAwSDeAWFvYKCgtLCwsKDwoQARMaExMNCRINDRIM4AsKCkAMEgwM
+Ej4WFuoKCwtADRIMDBICCwoKQAwSDAwSAQcb/qUbUQIECQwMEgwBPAsQEw0MEgI8AgQJDQ0SDAH0FhYB
+IAwSDAwSYg0SDAwSYgwSDQ0SnwwSDAwSVwsKCooWFhYWqgEQCgUNExMaE2AMEgwMEgAAGAA1ADUBywHL
+AAcADwAXAB8AJQAtADMAOwBDAEsAUwBbAGMAaQBvAHUAewCDAIkAkQCXAJ8ApwCvAAAAMhYUBiImNBYy
+FhQGIiY0BjIWFAYiJjQ2MhYUBiImNBcyFCMiNDYyFhQGIiY0NjIVFCI1JjIWFAYiJjQWMhYUBiImNBYy
+FhQGIiY0NjIWFAYiJjQmMhYUBiImNDYiJjQ2MhYUJyI0MzIUAzIUIyI0JjIVFCI1NyI0MzIUBiImNDYy
+FhQWIjU0MhUkMhYUBiImNAYyFRQiNTYyFhQGIiY0FjIWFAYiJjQ2MhYUBiImNAEeGhMTGhMTGhMTGhM/
+Eg0NEgwIGhMTGhN2CgoLAhIMDBINoBYWPhIMDBIMDBIMDBIMDBIMDBIMDBIMDBIMoxoTExoTKRIMDBIN
+FgoKCwsLCwqWFhb2CwsKARINDRIMixYW/qwSDAwSDDYWFkISDAwSDAwSDAwSDAwSDAwSDAFLExoTExpD
+ExoTExpNDBIMDBLCExoTExrtFhZKDBIMDBJXCwoKwAwSDAwSSQwSDQ0SnwwSDAwSYg0SDAwSFxMaExMa
+iQwSDAwSPhYW/pYWFpULCgrgFhZKDBIMDBJXCwoKagwSDAwSVAoLCxUMEg0NEp8MEgwMEmINEgwMEgAB
+ACsAKwHVAdUABwAANjQ2MhYUBiIrfbB9fbCosH19sH0AAQBrACsBqwHVAA0AABMyFhQGIyInNjY0Jic2
+1Vl9fVk6MDE5OTEwAdV9sH0cHGN0YxwcAAEAgAArAZUB1QANAAATMhYUBiMiJzY2NCYnNsBYfX1YIh5C
+U1NCHgHVfbB9CRRxjnEUCQACAA8ADwHxAfEADQAdAAAlMjY0JiMiBxYWFAYHFjcXBxUjBycjNSc3NTM3
+FzMBADVLSzUaGyEpKSEbxUZGZEdHZEZGZEdHZIBLaksMDz9MPw8Mx0dHZEZGZEdHZEZGAAACAA8ADwHx
+AfEABwAXAAA2MjY0JiIGFAUVIwcnIzUnNzUzNxczFRfLaktLaksBK2RHR2RGRmRHR2RGgEtqS0tqEmRG
+RmRHR2RGRmRHAAACAA8ADwHxAfEABQAVAAAlMjY0JiMXFSMHJyM1Jzc1MzcXMxUXAQA1S0s1q2RHR2RG
+RmRHR2RGgEtqS8dkRkZkR0dkRkZkRwADAA8ADwHxAfEABwAPAB8AABIyFhQGIiY0FjI2NCYiBhQlFwcV
+IwcnIzUnNzUzNxcz3UYyMkYyIGpLS2pLAStGRmRHR2RGRmRHR2QBVTJGMjJGo0tqS0tqfEdHZEZGZEdH
+ZEZGAAACAEAAQAHAAcAADQAbAAABFxUUBiMhIiY1NRc3FzcVJwcnByc1NDYzITIWAYBAGhH+1hEaQFVW
+lUBVVlVAGhEBKhEaAQxAYREaGhGMQFZW3oxAVlZWQWERGhoAAAIAKwBAAcABwAAJABYAAAEWFAcHJzc2
+MhcEMhYVFAYjIicyNjU0AboGBr87vwYSBv7eNCYyIzQhDxsBnQYSBr87vwYG5SYaIzIrFxMaAAYAKwAr
+AdUB1QAHAAwAEgAZAB4AJQAANzY2NxcGIyInMwcmJjcXIyY1NAUWFRQHJyc3IzcWFgcHJzYzMhfSBE4V
+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
+JjURAcD+1QErKyorKyorERoaEf7VERkZEVYVFUAaEUBAFREaGhEVERrrAVX+qxEaAUCA/tWAKiorKyur
+GhH+1REZGREBKxEaqxVVEhkrFRkSFRIZGRJA/qsrGhEBVQADAEAAQAHAAcAAAwATABYAACURIxU3MhYV
+ERQGIyEiJjURNDYzFwczAZWVlREaGhH+1hEaGhGVlZVrASqAqxoR/tYRGhoRASoRGquqAAAFAEAAQAHA
+AcAABwAQABkAIgArAAASMhYUBiImNBc1MxUUBiMjNRMyFhUVIzUjNQcVIzU0NjMzFQcVMxUjIiY1NeY0
+JiY0JtUrGhFVVREaK1XVKxoRVVVVVREaAUAmNCYmNK9VVREaKwFVGhFVVSsrVVURGivVVSsaEVUAAgAA
+AFUCAAGrABcAKgAAJTI2NCYjIzU0JiMiBxYWFSM0JiIGFBYzJRYWFRQGIyEiJjU0Njc2NjMyFgGVGiYm
+GiBEMTokKTUrMkYyMiMBHSk6Pyz+6zVLQjAVTC06WIAmNCYLMUQvC0UsIzMzRjKqAz0qLD9LNTFJBScw
+SQAAAwArACsB1QIAAAMACgAdAAABIRUhFxEjJwcjEQEyFhURFAYjISImNRE0NjMzNxcBgP8AAQArYEpL
+YQFWERkZEf6qERkZEVZVVQFV1SsBK0tL/tUBVhoR/tURGRkRASsRGlVVAAEAFQCAAesBgAAGAAABEyE3
+FzcnASvA/iqAYCI8AYD/AKuAGVEAAwAVABUB6wHrAAMAEwAcAAAlESERATIWFREUBiMhIiY1ETQ2MwcR
+IRUhIiY1EQHA/tUBKxEaGhH+1REZGRFVAVX+qxEalQEr/tUBVhoR/tURGRkRASsRGlb+qysaEQFVAAAJ
+ACwALAHUAdQABQALABEAGQAfACUAKwAxADcAADc3FhcVJjc2NxcGBzc2NzMGByYUBiImNDYyBxYXByYn
+NwYHIzY3BSYnNxYXJwcmJzUWBwYHJzY3eR4lLz9pLyQfMz9yHAYrBillJjQmJjTDBhweKQZNHAYrBikB
+TgYcHikGTR4lLz9pLyUeMz9bHhwGKwYlBhweKQZrJi0+M6E0JiY0JlUvJB8zP34lLz8zci8lHjM/kB4c
+BisGJQYcHikGAAACADEAEQHPAe8ABwBAAAA2MjY0JiIGFAc0NjcnJiY1NhcWFyY1NDY3FhYVFAc2NzYX
+FAYHDgIHHgIXFhYVBicmJxYVFAYHJiY1NDcGBwbdRjIyRjJ6LSUSHiJAQAkIAiMdHSMCCAlAQCIeAgcG
+AwMGBwIeIkBACQgCIx0dIwIICUCrMkYyMkZUJkUMCRI7ISUlBAcOBiM7ERE7IwYOBwQlJSE7EgEEAwEB
+AwQBEjshJSUEBw4GIzsRETsjBg4HBCUAAAkAFQAVAesB6wADAAcACwATABcAGwAfACMAJwAANzUzFSc3
+Fwc3NxcHJjIWFAYiJjQXMxUjNwcnNycVIzUHByc3BxUjNesqnS4eLqYeLh6ENCYmNCargIAdLh4uVSon
+Hi4eAYAVgICBLh4uLh4uHsgmNCYmNAUqfy4eLmOAgJEeLh5zKioAAwBAABUB2gHVAAIACgARAAABMyc3
+FyMnIwcjNyEzBzMDNSMBZzIZFUUpD0QPKUX+1dVVVZVAAV1OKsArK8DA/wDAAAACACsAKwGVAdUABQAO
+AAABByc1MwcnAQcnBzUjNScBayG11lbPAU8bWE1AagErObUuqpX+sBtZg8BPawABAJUAKwFrAdUABgAA
+EzMHMwM1I5XWVlaWQAHVqv8AwAAACQBAABUBwAHrAAQACAAMABAAFAAZACcAKwAvAAAlNTMUBic1MxUn
+NTMVEzUzFQcRMxETMhYVIyE0NjMzFSMRMxUjIiY1JTUzFQM1MxUBlSsaESuAKyor1SqAERor/qsaEVVV
+VVURGgFVK4ArQCsRGqsqKqorK/8AKyuAAdb+KgGrGhERGiv+1isaEdUrK/8AKysAAAoAQABAAcABwAAP
+ABMAFwAbACsALwAzAD8AQwBHAAABNSEVMxUzFTM1MxUzNTM1FTUjFSM1IxUjNSMVATIWFREUBiMhIiY1
+ETQ2MxczFSM3MxUjJzMVMxUjNSMVIzUzFxUzNSEjFTMBlf7WKisrKisrKysqKysBABEaGhH+1hEaGhEq
+KyurKytVKisrKisrgCr/ACoqARWAgCorKysrKpUrKysrKysBQBoR/tYRGhoRASoRGoArKysrKyoqKioq
+KysrAAAIAFUAVQGrAasABwAPABcAHwAnAC8ANwA/AAASMhYUBiImNBYyFhQGIiY0FjIWFAYiJjQGMhYU
+BiImNDYiJjQ2MhYUBDIWFAYiJjQ2MhYUBiImNBYyFhQGIiY0xCIaGiIZbyIZGSIabyIaGiIaOyIZGSIa
+kSIaGiIa/sQiGhoiGhoiGhoiGm8iGhoiGQGrGiIaGiI8GSIaGiI8GiIZGSI7GiIaGiLEGiIaGiLEGiIa
+GiLEGSIaGiI8GiIZGSIACQAAAAAB5QHlAAIABwAMABAAEwAWACAAJAA9AAAlMycHNScjFSc1JyMVFzUj
+FREVMxcVMwMBBychIiY1EScFFTM1ISMnITIWFREnNSMnMzUjFSc1IyczNSMVJwFVHx8qDEoqDEpWVh9h
+H9kByhsr/rYRGSsBVVb/AB8rAUoRGSofK0pWKh8rSlYqVR8fSgxWgEoMVoBWVgEfH2EfARD+NhsrGREB
+SisfVlYqGRH+tisfKlZKKx8qVkorAAAKACsAKwHVAdUAAwAHAAsADwATABcAGwAfACMAMwAAATUjFRc1
+IxUXNSMVAzUjFRc1IxUXNSMVAzUjFRc1IxUXNSMVATIWFREUBiMhIiY1ETQ2MwGrVlZWVlYqVlZWVlYq
+VlZWVlYBVhEZGRH+qhEZGREBVVZWgFZWgFZWAQBWVoBWVoBWVgEAVlaAVlaAVlYBgBkR/qoRGRkRAVYR
+GQAABAAeAB4BzQHLABQAHQAhADAAABMWAQcnIzUnFSM1IxUjNTMVMzUzJxcjJzMyFhUVJzcVMzUHIyc1
+MzIWFRUUBxcjJyM1YgE2GKJIICArICArCHX3CCAoDRMgYCsrCBhLDRMTEyATGAHLY/7NF6JJIGk1NYAr
+K3WVIBMNKSAJFRVgF2kTDRUXBy0rAAAFAEAAwAHAAUAAAwANABkAHQArAAAlNSMVNzIWFRUUBiMjNQc1
+MxUjNSMVIzUzFQU1IxUzFAcXIycjFSM1MzIWFQEVKioNExMNSkAgICsgIAFAK0sTEyATGCBLDRPgQEBg
+Ew1ADROAKyuANTWAKwoVFRQKLSsrgBMNAAMAFQCAAesBgAAHAA8AFwAANjI2NCYiBhQ2MhYUBiImNCQy
+FhQGIiY0WiIZGSIaCEYyMkYzASFqS0tqS9UaIhoaImYyRjIyRl1LaktLagAAAwAVAIAB6wGAAAcADwAX
+AAAkMjY0JiIGFDYyFhQGIiY0JjIWFAYiJjQBSEYyMkYzIWpLS2pLo0YyMkYzqzJGMjJGo0tqS0tqIDJG
+MjJGAAAHACoAKgHVAdUAAwALABMAGwAfACcATAAAJTcnBzYiBhQWMjY0BjI2NCYiBhQmMjY0JiIGFCc3
+JwcWIgYUFjI2NBcXFhQHBwYjIicnBwYiJycmNDc3JyY0Nzc2MhcXNzYyFxcWFAcBY05OTR4SDQ0SDEkS
+DAwSDB8SDQ0SDCRNTU67EgwMEgxlVQYGXAYJCgZUVQYSBl0GBlVVBgZdBhIGVVQGEwZcBgZOTk1OegwS
+DAwSSQwSDQ0SHwwSDAwSH05NTiMMEg0NEjRVBhIGXQYGVVUGBl0GEgZVVAYTBlwGBlVVBgZcBhMGAAAC
+AEAAQAHAAcAABAAUAAA3ByEnBxcUBiMhIiY1ETQ2MyEyFhW1SgEqYErVGhH+1hEaGhEBKhEa4GCAYDUR
+GhoRASoRGhoRAAAGACsAVQHVAasAAwATABcAGwAfACMAACURIREBMhYVERQGIyEiJjURNDYzFxUjNSMV
+IzUXFSM1NxUjNQGr/qoBVhEZGRH+qhEZGRGrKyor1SoqKoABAP8AASsaEf8AERoaEQEAERqAKysrK1Yq
+KlYrKwAEAEAAQAHAAcAAAwAGABIAIgAAJSM1MxcRATcVMxUzNTM1IzUjFTcyFhURFAYjISImNRE0NjMB
+a2trKv7WCisgKysg9REaGhH+1hEaGhGVIEoBKv7W9SArKyArK2AaEf7WERoaEQEqERoAAQAVAIAB6wGA
+AAYAAAETITcXNycBK8D+KoBgIjwBgP8Aq4AZUQAGAEAAQAHAAcAABwAMABQAHAAkACkAACU0NjMVIgYV
+MzQ2MxUjNDYzFSIGFQMUBiM1MjY1MxQGIzUyNjUjFAYjNQErVz4sPysmGuuKYVBwK1c+LD+AimFQcIAm
+GkA+Vyo/LBomQGGKK3BQAYA+Vyo/LGGKK3BQGiZAAAUAQABAAcABwAAFAAsAEQAtADMAAAE2MxUiBxcn
+NjMVIgMUByc2NQc3AQcnBhUjNDcnBhUjNDcnBiM1MjcnBiM1Mjc3FAcnNjUBSDk/LypCIhseDIkiHxbA
+GwFlGz0TKh8fKys4NUJWRTUfKTIiG1gLIgMBCSIrFkIiCyoBFT85HyovGxv+mxs9GyIyKR41RFZCNTgr
+Kx8fKhNYHhsiCwwAAAEAKwArAdUB1QAHAAASMhYUBiImNKiwfX2wfQHVfbB9fbAAAAIAQABAAcABwAAY
+ACgAAAE1NCYjIxUzFSMVMxUjFTMyNjU1NCYjMjY3MhYVERQGIyEiJjURNDYzAUAZEVZWKytWVhEZEg4O
+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
+jGVTsH19sH0BCUxKaiZaVWWMZWWMARt9sH19sChMaEwmWoAAAAQAAAB+AgABggASAB4AVQBcAAAlNTQn
+JiMiBwYVFRQXFhYyNzY2JzQzMhcWFRUUIyI1JSIVFB4FMxYXFhcWFxYXFhUUBwYjIicmNTMUMzI1NC4D
+JyYnJjU0NzYzMhYVIzQnJiU3MxEjNQcBEwoHFwoIFwIBECwIBgR7UykTFlJTARweAQICBAIHAQkKCRMI
+DggFBSwMEjkRBSkmIQYGDiMGCAwTKgwRISoqEgz+SWUGK0DmNiQRDwMONDUYCQUgEAwSR20YHDkpbm41
+FwMFAwMCAQMEAQIGAwkFCwoLJQ8EJwwKHhcGCQMGCQIDCA0XJg4EHh0VBAM6Jf8AzRYAAgBZAH4BwgGC
+ADgAXgAAASIVFB4EMhYzFhcWFxYXFhcWFRQHBiMiJyY1MxQWMzI1NCYmJyYnJicmNTQ3NjMyFhUjNCcm
+BxYVFAcGIiY1MxQXFjMyNCMjNTMyNzY1NCMiBwYVIzQ3NjMyFhQBdh8BAQMCBAIGAQkJCxIIDgcGBSwM
+EzgRBSgWESEGBgcFEBwUEioMESEqKhMMoSoYF0ovKwsNESouGhkgCQImGgoDKjARECYqASEXAwQDAwED
+AwQBAgYDCQULCgslDwQnDAoPDxcGCQMDAgQGDQwYJg4EHh0UBQMeEColEhQmIhQIClIhFwULJhQGCS0T
+BSRIAAAEAEAAKwHAAesABwAWABoAHgAANjI2NCYiBhQlFhUUBiImNDYzMhc3FhcHNTMVExUjNcJ8V1d8
+VwErKnCgcHBQQTceEA7JKiuAVVh8V1d8tTVCT3FxnnErHw0RrICAARYrKwAABQAlABUBwAHrAAcAEwAX
+ABsALwAAJTI3JwYVFBYDAQcnBiMiJjU0NycXNTMVNxUjNRcXBxYVFAcnNjU0JiMiByc2MzIXAQAnJMwU
+V4IBexs2MjhQcCA7xiorgNYeHiogHxRXPigiIDA6QzVVFcwiKT5YAVb+hRs2IHFPOjA7WR5J3ysrTB4f
+NUI6MB8iKT5XFB8gKgAACAArACsB1QHVAAQACQANABIAFwAbACEAKQAAJTY3IxUXNjcjFRU2NyM1FTMm
+JycVMyYnJxUzJgMRBgYUFgIyFhQGIiY0AaUCApRwDAN/IB4+lAICkH8DDHA+Hko/V1cEsH19sH3VBhAW
+QBEFFj4EEMAWEAZAFgURPhQQ/rIBUghggmABdn2wfX2wAAACACsAFQHVAesACAAfAAATNTMyFhUVIzUX
+IxUzByczNSMiJjU1IzUzNSM3FyMRIdWAERorgFUrQEAqqhEaVVUrQEAqASoBVSsaEYCA1StAQCsaEaor
+K0BA/wAAAAYAQABAAcABwAAHAAsAEwAbAB8AIwAAATUzFTMVIxUXIzUzJTMVIzUjNTMXIzUzFTMVIwMz
+FSMVMxUjAUArVVVV1dX+1SsrVVWAKiqrq9XV1YCAAUCAKyorVSorgCsq1YArKgEqKtYqAAAMAEAAawHV
+AZUAAwAHAAsADwATABcAGwAfACMAJwArAC8AAAEzFSMVNTMVIzUzFSM1MxUjNTMVNzUzFSczFSMjNTMV
+FzUzFSM1MxUjNTMVJzUzFQGAVVVVwFbAVcBV61XAVlZqVRVWwFXAVVVVAZVV1VVVVVVVVVVValZWwFVV
+VWtWVlZWVlZrVVUAAAMAQABrAdUBlQADAAcACwAAEyEVIRc1IRUhNTMVQAGV/muVAQD+a4ABlYCqlZWV
+lQAAAwAAAFUB/AGrAAcAHgAhAAA3MycjBzM3MyUzByMnByMnBgYjIiY0NjMyFzMXNzMXJTcX3ChEK0Qp
+D0QBCCcsJSAgJgIVUjFHZGRHUjMQGiAiIP7WGRirwMAqlsCCggkrNGWMZUCHh4cOTk4AAQAAAFUCAAGr
+ABIAAAEWFhUUBiMhIiY1NDY3NjYzMhYBnSk6Pyz+6zVLQjAVTC06WAEqAz0qLD9LNTFJBScwSQAABgAV
+ACEB6wHgAAMABwAVABkAHQAhAAAlNxcHNzMVIycWFhUUBiImNTQ2NzUzBxUjNRc1MxUnNxcHAXAeJh4V
+QEBrHSNLaksjHYDrQNYqySYeJn0dJh7KK4QROiM1S0s1IzoRZ8ArK/8/P1MnHicAAAkAFQAhAesB9AAD
+AAcADwATABcAGwAfACMAJwAANzcXBxc1MxUCMhYUBiImNAUzFSMHNxcHEwcnNycVIzUHFSM1NwcnN0wm
+HiaBKkpqS0tqSwErQEA7HiYeHiYeJoEqlkB7HiYedCceJzU/PwFqS2pLS2ogK3gdJh4BSyYeJjU/P9Qr
+K3keJh4AAAMAKwArAdUB1QAEABQAHQAAATUjFTc3MhYVERQGIyEiJjURNDYzBxEhFSEiJjURAatrNTYR
+GRkR/wARGhoRVgEr/tURGQEAq6sgtRkR/wARGhoRAQARGVX+1SoZEQErAAIAFQBAAesBwAAEABQAADch
+JwcnJTIWFREUBiMhIiY1ETQ2M2sBKmBKNgELEBsbEP6AERobEJWAYEDLGxD+1hAbGhEBKhAbAA4AFQBA
+AesBwAAEAAsADwATABgAHAAgACQAKQAtADEANgA6AD4AADczJwcnJyEVISImNRMzFSM3MxUjJxUjNDYB
+MxUjETMVIwUzFSMlMhYVIxUzFSMnMxUjExQGIzU1MxUjFTMVI0DVRDUnYAEr/wARGlYqKlUrK4ArGwE7
+KioqKv6qKysBqxAbKysrqysr1hsQKysrK2tbRS5m1RoRAVUrKysrKxAb/qsrAYArKiuAGxAqK4Ar/tYQ
+GyuqKisrAA8AFQBAAesBwAADAAcACwAQABQAGAAcACAAJwAsADAANAA5AD0AQQAAExUjNTMVIzUHFSM1
+NxUjNDYBFSM1ExUjNQMVIzUDFSM1EyImNTUzFRMyFhUjFxUjNScVIzUTFAYjNTcVIzUXFSM1lSqAK4Ar
+KysbAWUqKiorK9UrKxEa1tUQGysrK4Ar1hsQKysrKwHAKysrK6sqKqsrEBv+qysrAVUrK/6rKysBACsr
+/tUaEVWAAYAbECorK1UrK/6rEBsrqioqVSsrAAACABUAQAHrAcAABwAXAAA2MjY0JiIGFCUyFhURFAYj
+ISImNRE0NjO5jmRkjmQBaxEaGhH+gBEaGhGAS2pLS2r1GhH+1hEaGhEBKhEaAAAHAEwAIQG0AfQAAwAH
+AAsADwATABcAGwAANyc3FwM3FwcBByc3ByM1MxMXBycnMxUjBzUhFWoeJh5EHiYeAUIeJh55KiqBHiYe
+hSoqgAEqVh8mHgEkHiYe/vkeJx56PwFfHiYeWz/qgIAABAAAAAACAAIAABAAGQAlADEAADchFSMVIzUj
+IiY1NSM1MzUzFzUjNTMyFhUVAzIWFyMmJicHJzI2AzcXIgYjIiYnMxYWqwEAKyuqEhkrKyuqgIARGn9k
+kwggBkQ1HVEDCF8dUQMIA2STCCAGRKsrKysaEaorK9aAKxkSgAEriGM8YBkcUQH+NhxRAYhjPGAABQAr
+ACsB1QHVAAgAEAAkACwANAAAATIWFTM0JiMVAjI2NCYiBhQ3MxUUBiMhIiY1ETQ2MzM3MxUyFic1MhYV
+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
+FxgkIDwgIBgXIQQrLv5WLisrorvV1QoMEg0NEokNEgwMEq2TJhoaJpMXIRgIICAIGCEBLhBELf7oARgt
+RBARlWszEgwMEg0NEgwMEg0AAAUAVQBAAasB1QAHAAsADwAXADAAACQyNjQmIgYUJzM1Iwc1IxUWMjY0
+JiIGFBMyFhUVFAYjFxUjJyMHIzU3IiY1NTQ+AgFSHBISHBIra2sqaxIcEhIcEoBTWCwfICsqUSowIB8s
+HDU1lRMaExMag1VVVVWWExoTExoBLSIzyx8rIAsrKwsgKx/LGyQQBgADAGsAKwGVAdUAAwALACoAACU1
+IxUWMjY0JiIGFDcUBiMzFxUjJyMHIzU3JiY1NTQ2NzcjNTMVIwcWFhUBa9ZdHBISHBK1HRoCICsqUSow
+IhcgRDsRZtZGED9B1WtrYBMaExMaDxwmIAoqKgoiBSQXtCkfAiAgICACHioABAArABUB1QHgABkAIQAo
+AC8AABMDMzcXFTM1JzcWMzUiJicnJiMiBwcVMzU3NiImNDYyFhQTNRcHNSM1NzMVIxUnN3s7LSUuKywN
+LUcdMQ8UCxkJB3AqJmEiGhoiGas1NXU1dXU1NQFC/tOrK4ChLEA3Kh0YIhQDLmRHEEkZIhoaIv63JTU2
+JiBaICU1NgAACQBVAFUBqwGrAAMABwALAA8AEwAXABsAHwAjAAAlNTMVJzUzFSc1MxU3MxUjBzUzFSM1
+MxUHNTMVMzUzFQM1MxUBVVZWVtZWKlZWgFbWVlZWKlbWVlVWVoBWVoBWVlZWgFZWVlaAVlZWVgEAVlYA
+AAEAVQBVAasBqwAIAAABFSEXByc3FwcBq/78dx6rqx53ARUqeB6rqx54AAEAlQDAAWsBKwACAAATMweV
+1msBK2sAAAIAKwArAdUB1QACAAoAACU3IyYyFhQGIiY0AQBVqgOwfX2wfdVWqn2wfX2wAAABAJUA1QFr
+AUAAAgAANzcXlWtr1WtrAAABAFUAVQGrAasACAAAARcHJzchNSEnAQCrqx53/vwBBHcBq6urHngqeAAC
+ACsAKwHVAdUACwATAAAlJzcnBycHFwcXNxcCMhYUBiImNAFrTU0eTU0eTU0eTU2lsH19sH2zTU0eTU0e
+TU0eTU0BQH2wfX2wAAEASQBrAcABiQAFAAA3NxcBJzfA4h7/AHcep+Ie/wB3HgABAKsAgAFJAYAABQAA
+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
+AAwAKwBAAdUBwAADAAcAEwAXABsAHwAjACcAKwAvADMAOQAAJRUjNTcVIzUXNSMVMxUjFTMVIxUDNSMV
+FzUjFRc1IxUXNSMVAzUjFRc1IxUXNSMVFzUjFRMzESERMwGAKysrVqsrKysrKyoqKioqKiorKysrKysr
+K6vV/lbVwCsrVSoqqtUrKisrKgEAKipWKytVKytVKioBACoqVisrVSsrVSoqAQD+1QGAAAAEABUAawHr
+AZUACgAUABwAJAAAJTIWFhUVIzU0JzYiMhYWFRUhNTQ2NiImNDYyFhQWIiY0NjIWFAFVHEI4gCoHuThC
+N/7VOHg0JiY0JYU0JiY0JusQJBc1NSweARAkFzU1FyQ6JjQmJjQmJjQmJjQABQAAAIACAAGVAAcADwAX
+ACMALwAANjIWFRUhNTQlFhYVFSM1NCYiJjQ2MhYUFyInNjQnNjMyFhQGJxUjFSM1IzUzNTMV7VBY/wAB
+DiU4QJE0JiY0JisKCRMTCQoaJibvQCtAQCvrIx0rKx0fBh8XKysiSCY0JiY0JgMbRBsDJjQmFitAQCtA
+QAAACgBAAEABwAHVAAMABwALAA8AEwAXABsAHwAjACwAACU1IxUXNSMVAzUjFRc1IxUXNSMVFzUjFSc1
+IxUXNSMVFzUjFTczFSERMzU3FwGVKioqVioqKioqKipWKioqKirVgP6AgEBAwCsrVSoqAQAqKlYrK1Ur
+K1UqKqorK1UrK1UqKqrVASsqQEAABQArACsB1QHVAAUADQAVAB0AJQAAJCImJzMGJiImNDYyFhQWIiY0
+NjIWFAYyNjQmIgYUEjIWFAYiJjQBJUo7DdoNnhoTExoTgxoTExoTsYxlZYxlU7B9fbB9iykhIWETGhMT
+GhMTGhMTGtNljGVljAEbfbB9fbAABQArACsB1QHVAAUADQAVAB0AJQAANjIWFyM2NiImNDYyFhQWIiY0
+NjIWFAYyNjQmIgYUEjIWFAYiJjTbSjsN2g0iGhMTGhODGhMTGhOxjGVljGVTsH19sH3VKSEhaRMaExMa
+ExMaExMa02WMZWWMARt9sH19sAAAAgBVACsBqwHLABMAGgAAJRcVITU3NTQ2NzU0NjIWFRUWFhUHIiY1
+MxQGAYAr/qorMy0SHBItM4ASGVYaqysVFStqMkoLDw0TEw0PC0oy6hkRERkAAwBVACsBqwHLAAcAGwAh
+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
+AdUACQAAJQc3Jzc3FxcHFwEAhCN0mTw8mXQjkFCWZQ2NjQ1llgAAAgArAEAB1QHVAAUADwAAJRcnNycn
+FwcXJwc3Jzc3FwEAUBVHXiTVdCOEhCN0mTw8tzBbPghWQ2WWUFCWZQ2NjQAAAgArAEAB1QHVAAkAEwAA
+JRcnNycnBwcXByUHFycHNyc3NxcBAFAVR14kJF5HFQEldCOEhCN0mTw8tzBbPghWVgg+W7RlllBQlmUN
+jY0ABQABAAAB/wIAAAkAEwAfAEQATgAAATIWFyMmJicHJxc0IyMVMzI3NjUnMhcWFRUUBwYjIzUHFhUU
+BwYHBiMiJjUzFBYzMjQjIzUzMjQjIhUjNDc2MzIXFhUUBzcXByImJzMWFgEAZJMIIAVFNR1Rby8UEyQK
+Ai81EwUVFiMxMRwFBgUPGRgeGw8MHB8QEB0aGRwPEBYjDgRIHVEOZJMIIAZEAgCHYztgGRxR+zl7IgcR
+WS8MFggmFRaqUwscCgoMBAwYFwsONhYyFxEPDRsIDBfZHFEBiGM8YAACAEAAKwHAAdUACwATAAABIxEj
+NSMVIxEjNSEmMhYUBiImNAHAgCsqK4ABgNEiGhoiGgFA/uuAgAEVK2oZIhoaIgAFACsAKwHAAesABAAI
+AAwAEAAUAAATFxUhNQUzFSMFNSEVAzMVIyczFSP1y/5rASpAQP7WAZXrQECAQEAB62srK1WWakBAAQCW
+lpYAAwBAAEAB1QHAAAcACwAlAAAkMjY0JiIGFAc1MxUHFRQGIyEiJjURNDYzITIWFRUjIgYVFRQWMwFI
+GhMTGhM11RUaEf7WEhkZEgEqERrAEhkZEuASHBISHEeqqisVERoaEQEqERoaERUaEaoRGgADAEAAQAHA
+AcAABwAPAB8AADcVITU0JiIGNjQmIgYUFjInNDYzITIWFREUBiMhIiY1gAEAWFBYwCY0JiY02hkSASoR
+GhoR/tYSGZUVFR0lJXQ0JiY0JpURGhoR/tYRGhoRAAMAKwArAdUB1QAHAA8AFwAANjI3JiYiBgc2IgYU
+FjI2NCYyFhQGIiY0r6IvAVhOWAGaNCYmNCaYsH19sH1mRRwmJR3qJjQmJjRmfbB9fbAABAAVACsBwwHr
+AB0AJQAtADkAADcUMzMVISImNTQ3NycjNTMWFxYWFzM2NxcHBiMjBxYyFhQGIiY0JjIWFAYiJjQ3NSM1
+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
+ABIAGgAiAAA3MhcGFRUjNTQ2NhYyFhUVIzU0JiImNDYyFhQWIiY0NjIWFMAWHTOVN0KXSlDqETQmJjQm
+diwfHywf6wYcLjA1FyQQFiAaMDAaYCY0JiY0Ox8sICAsAAACAEAAawHAAZUABgANAAABBzUjNTM1BxUz
+FSMVJwHAVZaW1paWVQFAVUAqQIBAKkBVAAIAawBAAZUBwAAGAA0AABMXIxUjNSMXMwcnMzUzwFVAKkDq
+QFVVQCoBwFWWltZVVZYAAwArACsB1QHVAAYADQAVAAAlIzUjFSMXJzMVMzUzJyYyFhQGIiY0AXU1KzVL
+oDUrNUstsH19sH3AVVVLy1VVS0p9sH19sAAAAgAVADUB6wG1ABcAHgAAATIWFREUBiMhIiY1ETQ2MzMV
+IxEhESM1AyczNTMVMwHAERoaEf6AERoaEYCAAYCAQFVAKkABtRkR/tURGhoRASsRGSr+1QErKv7rVcDA
+AAIAFQBAAesBwAAFABUAACU1IzUjEQEyFhURFAYjISImNRE0NjMBwKvVAYARGhoR/oARGhoRa9VV/tYB
+VRoR/tYRGhoRASoRGgAADwAVAEAB6wHAAAMABwALABAAFAAYABwAIAAnACwAMAA0ADkAPQBBAAAlNTMV
+IzUzFTc1MxUHNTMUBgE1MxUDNTMVEzUzFRM1MxUDMhYVFSM1AyImNTMnNTMVFzUzFQM0NjMVBzUzFSc1
+MxUBayqAK4ArKysa/poqKiorK9UrKxEa1tURGisrK4Ar1hoRKysrK0ArKysrqyoqqysRGgFVKyv+qysr
+AVUrK/8AKysBKxoRVYD+gBoRKisrVSsrAVURGiuqKipVKysAAAcAVQBAAasBwAADAAcACwAPABMAFwAr
+AAABNSMVFzUjFRc1IxUnNSMVFzUjFRc1IxUBMxEjNSMVIzUjFSMRMxUzNTMVMwGAKysrKyuqKysrKysB
+ACsrK6orKysrqisBQCsrVSoqVisrqysrVSoqVisrASv+gCsrKysBgCsrKwAAAgAVABUB6wHAAAMAHAAA
+ATMRIwMyFhUVFAcHJyY1NTcjIiY1NyM1NDc3NjMBlVZWVREaDYwXCRWHERoBAQNBCh0BwP8AAQAaEdUR
+DY0XCQ0HYhkRAikICJYaAAACABUAQAHrAesAGAAcAAABBzMVFAcHBiMjIiY1NTQ3NxcWFRUHMzIWBREz
+EQHrAQEDQQodwBEaDYwXCRWHERr+KlYBKwIpCAiWGhoR1RENjRcJDQdiGfwBAP8AAAIAAAAAAgACAAAX
+AC8AAAEyFhUVFAcHJyY1NjY3IyImNTU0Nzc2MycVFAcHBiMjIiY1NTQ3NxcWFQYGBzMyFgHgDhIJahEH
+AwsBbwkMAjEJFFACMQkUkA4SCWoRBwMLAW8JDAErEw2LDglpEQcKDjQHDAkbAwhxFFUbAwhxFBMNiw4J
+aREHCg40BwwABgBAAJUBwAFrAAMABwALAA8AEwAXAAAlNTMVJzMVIxU1MxUhNSEVJTUhFSU1IRUBlSsr
+Kysr/oABK/7VASv+1QEr6yoqgCurKysrK1YqKlUrKwAAAwBAAEABwAHrAAMABwAfAAATMxUjBTUhFQEy
+FhURFAYjISImNRE0NjMzNTMVMzUzFZVrawEA/tYBKhEaGhH+1hIZGRIVK6orAStrVerqAVUaEf7WERoa
+EQEqERorKysrAAADABUAVQHrAasACwATABsAABIUFhcVJiY0NjcVBhYyNjQmIgYUNjIWFAYiJjRALyY4
+SEg4JpxqS0tqSzqMZWWMZQEqVEINLA5cdlwOLA3sS2pLS2rgZYxlZYwAAAEAKwArAdUB1QA1AAABFhUU
+BiImNDYzMxUWFRQGIiY1NDc1BgYVFBYyNjU0JzcWFRQGIiY1NDY3NQYGFRQWMjY1NCcBlz59sH19WBUW
+GiIaFhwkMkYyGR4mS2pLPS4/V2WMZTIBlz5ZWH19sH2wDBkRGhoRGQwtCCweIzIyIyEbHiY0NUtLNS9H
+CCsIYEFGZWVGRzIAAAMAFQArAesB1QACAAoAIwAAJTMnNxMjJyMHIxMHBycHJzcmJzMWFzY3IzUzNTMV
+MxUjBgcHAVNFIxZgKxhlGCtgTRFCax5tKBgrFRwuFu+WKpY/GjUBlV05/wBAQAEAbCxCah5rLDUoHzM/
+KyoqK1A7AQAAAQArAIAB1QGAAAoAACU3JwcnNxc3FzcVAVUxaFWeHoBVhjGAMWhVnh6AVYYxgAAAAQBA
+AKsB1QFVAAYAAAEHNSE1ITUB1VX+wAFAAQBVQCpAAAEAKwCAAdUBgAAKAAABMxUnBycHJzcXNwFVgDGG
+VYAenlVoAYCAMYZVgB6eVWgAAAEAawBAAZUBwAAKAAABMhYVEScHETQ2MwFrERmVlRkRAcAaEf6rQEAB
+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
+NjIWFAYiAaw+PiMsLCMgICQODrhsdf6qVjJGMjJGAdVBqz4iM4MwJSNYICQTLROqLyYrKyaMRjIyRjIA
+AAsAQABAAcABwAALAA8AEwAXABsAHwAjACcAKwAvADMAAAEVIzU0JiMjNTMyFgE1MxUzNTMVMzUzFQM1
+MxUjNTMVBzUzFQc1MxUnNTMVBTUzFQczFSMBwCsmGmpqLD/+gCsqKysqgCuAKysrKysrKwEqKysrKwFV
+amoaJis//r8rKysrKysBVSsrKytVKyurKytWKipWKysqKwADAFUAAAHAAesAGgAiACcAACUHJzUnBiM1
+FjY3NzYzMzIWFRUUByc1BgcXMwIyFhQGIiY0AxcjBycBwEBAlwcNGjgSHhATARMdFEwUHYYgUSIaGiIa
+YDYrSyBAQEAglwEuARkTIRAcFHsaFEwxEQ2GAWsaIhoaIv76NkogAAABABUAgAHrAYAAMwAAABQGIyIn
+BxYVFAYiJjU0NycGIicHFhUUBiImNDYzMhc3JjU0NjIWFRQHFzYyFzcmNTQ2MgHrGhEIA0wCGiIaAjcG
+CgZhAhoiGhoRCANhARkiGgE2AxADTAIaIgFmIhkBTAYFERkZEQUGNwICYQYFERoaIhkBYQMIERoaEQgD
+NgEBSwYFERoAAgBAAEABwAHAAAUAHgAAARUXByc1FyM3JiYHBhQWMjc2NTMUBwYiJyY0NjIXNwELSg9b
+1ZE7LHssK1Z8LCsrODigODhwnjg6AVVaLRo3ai08LAErLHhYLCs9Tzc4ODedcDg8AAIAKwArAdUB1QAF
+AA0AACU3JzUjFSYyFhQGIiY0AVoRYCBDsH19sH2mHDpvgOp9sH19sAABABUAAAHrAgAALAAAAREUBiMj
+IicnNjM2MzIXFzU0NjIWFRUzNTQ2MhYVFTM1NDYyFhUVMzU0NjIWAeszI5skGagbAQcKBwZcExoTFRIc
+EhUTGhMWExoTAYv+yiMyGasaBgM0/g0TEw2Wyw4SEg7Ltg0TEw22dg0TEwAAAQBAAEABwAHAACcAACUy
+NxcGIyImJyM1MyY0NyM1MzY2MzIXByYjIgYHMxUjBhQXMxUjFhYBQDMnJjZKPmMUS0EBAUFLFGM+SjYm
+JzMnQhJ7iQICiXsSQXUiJjFIOCsHHAcrOEgxJiIpIisODg4rIikABQArACsB1QHVABgAIQAlAEEAVQAA
+JRE0JiMjFzM1MxUzFSMGBxcHJwcXBzMyNicWFzY2NzcjHwI3Jic0JyMVMwYGIyImNDYzMhcXNycmIyIG
+FBYzMjY3MhYVERQGIyMnIyImNRE0NjMzFwHADAm8GSkXTRsKHzoPOhMRK5YJDJYJDwwQAgNVBwUNDA44
+AlQvAxYUFR4eFRMNAhoCGSEkMzMkJS++ERkZEasVlhEZGRGAE1UBFgkMVhYWFickORA5EzsrDLETEQ4d
+CAgXEC8LD0YLBCEMFB8qHw0BGQEXM0gzMJwZEf7qERlAGREBFhEZQAAEAAAAAAHlAeUABwARABgALQAA
+NjIWFAYiJjQ3JyEyFhUUBwcGBzMnIwcHFAUHJwYjIiY1NDcnIyImNTQ3NycnN4QiGhoiGeHAAR8JDANM
+DMdsKzITAQFMGz0NFREaEh6fERkFHS9eG4AaIhkZIoXADQkFBYoWKysjAwWlGz0SGREWDR0aEQoKNWNe
+GwAAAgBVACsBqwHVABcAJQAAJTI2NCYjIgcnFTMnNjMyFhQGIyInIxYWExcRFAYjISImNRM0NjMBACw/
+Pyw6IBtVIhQuHywsHycWJQw1TIAaEf8AERoBGRGAP1g+MRxVIigrPiwgHSMBVYD/ABEZGREBVhEZAAAE
+AAAABgHVAdsAEQAUABgAIAAAATIWFREUBgcnMzUjJzM1IxUnFzMnFzUjFQMBBycjBxEnAasRGRgRlWmU
+FamrfikrKysrZQG6G3rAVSsB1RkR/wARGQGVKxUrKX7AK2srKwEG/kYbelUBaisAAAMAawBAAZUBwAAH
+ABMAHQAAATMVITUzNzMHFwcXNxc3JzcnBycHESERFAYjIyImAUtK/tZKFmqBLi0eLS0eLS0eLS1TAQAa
+EaoRGgGrKysVvS4tHi0tHi0uHi4utgEA/wARGhoAAAEAKwArAdUB1QArAAABFSMXBycjFRcHJxUjNQcn
+NzUjByc3IzUzJzcXMzUnNxc1MxU3FwcVMzcXBwHVWUUeYytkH0UqRR9kK2MeRVlZRR5jK2QfRSpFH2Qr
+Yx5FARUqRR9kK2MeRVlZRR5jK2QfRSpFH2QrYx5FWVlFHmMrZB9FAAAGABUAawHrAZUAAwALAA8AFwAb
+AC8AAAEzJyMWMjY0JiIGFCc1IxUGMjY0JiIGFCczNSMlFxUjFAYiJjUjFAYiJjUjNTQ2MwFAa1YVKBoT
+ExoTQFVOHBISHBIgVVUBK4A2JjQmdSY0JisZEgEVVuATGhMTGndWVooTGhMTGndWKoBqGiYmGhomJhrA
+EhgAAQAAAI0CAAFzACcAAAAyFhQGIicnNxcWMjY0JiIHBgcHBiImNDYyFxcHJyYiBhQWMjc2NzcBXWBD
+Q2AiGyAZFjwqKjwVRxM8IWBDQ2AiGyEYFjwqKjwVRxM8AXNEXkQiGBwVFio8KhU+EjUhRF5EIhgcFRYq
+PCoVPhI1AAIAQABAAcABxwAXABsAAAEmJgc2FhcHJiY3BhYXByY0NzQzNhcWFwc3FwcBdDKDPjBzMXox
+MQYVIDI9Pz8BRmJROJkfiR8BRDIgFQYxMXoxczA+gzI9P7M/AUYIBji4H4oeAAADACsAQAHVAcAAAwAd
+ACsAAAE1IxUzMhYVFRQGIyM1IxUjIiY1NTQ2MzM1NzMXFQczNTMVFAYjISImNTUzAStW1hEZGRGAVoAS
+GBkRVStVK4BWlRkS/tYSGZUBayoqGhFAERorKxkSQBEaKisrKsAVVRIZGRJVAAAGAEAAQAHAAcAABwAP
+ABcAHwAnADcAAAAyNjQmIgYUFjI2NCYiBhQmMjY0JiIGFCYyNjQmIgYUFjI2NCYiBhQBMhYVERQGIyEi
+JjURNDYzAVIcEhIcEhIcEhIcEk4cEhIcEk4cEhIcEhIcEhIcEgEVERoaEf7WERoaEQFAEhwSEhzSEhwS
+EhxOEhwSEhxOEhwSEhzSEhwSEhwBLhoR/tYRGhoRASoRGgAFABUAQAHrAcAABQAlAEMASwBTAAA3MwYG
+IiYWMjY3MhYzMjY0JiMiBiMmJiIGByImIyIGFBYzMjYzFiUGBgcGBiImJyYmJyY0NzY2NzY3NjMyFhcW
+FhcWFCQ0NjIWFAYiNjQ2MhYUBiKgwAw0QDQhZk8NAQQBERoaEQEEAQ1PZk8NAQQBERoaEQEEAQ0BawQg
+FxZfcl4WFyEEAgIEIRcRHTZJOl0WFyEEAv7FEBYPDxZbDxYQEBbVHSMjTTwvARoiGgEvPDwvARoiGgEv
+SxglBy8/Py8HJRgIDAgYJQcmGDA+MAclGAgMGxYQEBYQEBYQEBYQAAAEACsAKwHAAdUABwAPACgALQAA
+JDI2NCYiBhQGMjY0JiIGFCUWFRQGIyImJyMGBiMiJjU0NycjNTMXIRQnMhYVIwFeGhMTGhOtGhMTGhMB
+ERkrHxwqBC0EKRwfLCctL0oUATerR2SrVRMaExMaExMaExMaRRchHyslGxslKx8sFl4rKzn5ZEYAAQAr
+ACsB1QHVABsAACUXBxcHJwcnByc3JwcnNyc3JzcXNxc3FwcXNxcBtx4tHh4fLR8eH0y3TB4eHi0eHh8t
+Hx4fTLdMHsMfLR8eHi0eHh5Mt0wfHh8tHx4eLR4eHky3TB8AAAMAVQBAAdUBwAADAAcAGQAANyEVIQE1
+IxU3MhYVFRQGIyMVFAYjIyImNTVVAVb+qgFWKysSGBgSKzIjgCMzaysBFUBAaxkSQBEZQCMzMyPVAAAC
+AFUAKwHAAdUADwAXAAABBxUWFhUUBiImNTQ3FTMREjQ2MhYUBiIBa4AuPEtqS0ArwBIcEhIcAYJCwQIY
+EBEZGREZDCUBgP59HBISHBIAAAgAKwArAdUBwAAOAB4AIgAmACoALgBCAEoAAAEWBwcjNzYnJjc3MwcG
+FxcWBwcjNzYnJyY3NzMHBhcTNSMVIzUjFSM1IxUjNSMVNzMVFAYjISImNTUzNTQ2MzIXFxYmNDYyFhQG
+IgE5IQYBKQMFFSIGASkCBRNXIgYCKAIFEwIiBgIoAgUTCSorKyorKyqD5xkR/qoRGUAdExQQHQR1GCQZ
+GSQBgyAvCQwbFSIuCQ0bFAEhLgkMGxQBIi4JDRsU/tGAgICAgICAgKurERkZEasQFBwQIQVkJBkZJBkA
+AAUAVQArAasB1QADAAcACwAPAB8AABMzFSMRMxUjFzUhFQU1IRUBMhYVERQGIyEiJjURNDYzqyoqKirV
+/wABAP8AAQASGRoR/wARGhkSAQBrAQBAFWtr68HBAYAYEv6qERkZEQFWEhgABAArAEAB1QHAAAcAHwBR
+AIEAAAA0NjIWFAYiByInJic3JyYjNTIWFxcGBwYjIicmIgcGBSInJiMiBwYjIicmIyIHBiMiJyYjIgcG
+IzUyNzYzMhcWMzI3NjMyFxYzMjc2MzIXFjMVIicmIyIHBiMiJyYjIgcGIicmIyIHBiM1Mjc2MzIXFjMy
+NzYyFxYzMjc2MzIXFjMBKx8sHx8skQwNBAxFFSA1KTQYiQYDDQwLDRYyFg0BERcXCw4NCxcYFxcLDg0L
+FxgXFwsODQsXGA0LFxgXFwsODQsXGBcXCw4NCxcYFxcLDhcXCw4NCxcYFxcLDg0LFzAXCw0OCxcXDQsX
+GBcXCw4NCxcwFwsNDgsXFxgXCw0BdSwfHywgVQgDBUUWIDUTGIgEAQgIDQ0IYA4HBw4OBwcODgcHDisH
+Dg4HBw4OBwcODgeLDgcHDg4HBw4OBwcOKwcODgcHDg4HBw4OBwAAAgArAGsB1QGVAA8AEwAAARYWFyE2
+NjcmNTQ2MhYVFAUhFSEBJz9WBP6ABFY/BBoiGv8AAar+VgFaDWFBQWENCgcRGRkRB88qAAAGACsAFQHV
+AdUAAgAZACkALQAxADkAACUnMyciJjQ2MxUiBhUUFjMzMhYVFSM1NCYjNxYWFRUjNTQmIzUyNjUzFAcz
+FSM3MxUjJTcBBycjNTMBaz8/Nh0qKh0RFhcQIR4sIBkRPB4lIDEkEBcgJyAgNSAg/nYaAWsbldWVrD9b
+KzoqIBUQERonHCIbFBdSDjokLCwkMyAXER7CQEBA1Rv+lRuWQAAABQArAGsB1QHVABYALAAwADQAOAAA
+ATIWFRUjNTQmIyMiJjQ2MxUiBhUUFjM3FhYVFSM1NCYjNTI2NTQmIzUyFhUUBzMVIzczFSMlIRUhAVYf
+KyAZESEdKiodERYXEF0eJSAxJBAXFxAdKicgIDUgIP52AUD+wAEmJh0jHBQXKzoqIBUQERo1DjojMDAk
+MiAXERAXICodHsVAQEBAQAACACsAKwHVAdUABwAXAAABBgcmJzY3FgUyFhc2NjMUBgcGByYnJiYBSiog
+ICoIQ0P+50RwISFwRF9MERkVFUxfATMXIiIXX0NDZ0IzM0JUhhsGBQMIG4YAAQAAACsCAAHVAE4AAAEW
+FAcHBiMnBwYiLwIHFxQjIyIvAgcUIyMiNTcjBxcWIyMiJycHFxYjIyI1Jzc1JjUhFjcmNxYXFjYnJici
+JyY3NDMWFhcXHgIHFBcB/wEBGQICDwcCCQIOFy8RBBQCAhQKGQQVBBeHIwgCBhQDARwiBgIGFgQNFRcB
+EjAvCA4cCAcJAgkkAQIMAgQdKQcEAwcFAQIBPgEDASACAxYEBB4FcIgEA1ERYgMEh0JEBQJmJzwFAjhS
+kAkVASIWDhQFBAsHHA4BAwUDBCURAwQIDwgFAgAAAAcAWgADAAEECQAAAGAAAAADAAEECQABABwAYAAD
+AAEECQACAA4AfAADAAEECQADAFIAigADAAEECQAEABwAYAADAAEECQAFABoA3AADAAEECQAGACoA9gBD
+AG8AcAB5AHIAaQBnAGgAdAAgADIAMAAxADUAIABHAG8AbwBnAGwAZQAsACAASQBuAGMALgAgAEEAbABs
+ACAAUgBpAGcAaAB0AHMAIABSAGUAcwBlAHIAdgBlAGQALgBNAGEAdABlAHIAaQBhAGwAIABJAGMAbwBu
+AHMAUgBlAGcAdQBsAGEAcgBGAG8AbgB0AEYAbwByAGcAZQAgADIALgAwACAAOgAgAE0AYQB0AGUAcgBp
+AGEAbAAgAEkAYwBvAG4AcwAgADoAIAA4AC0AMgAtADIAMAAxADYAVgBlAHIAcwBpAG8AbgAgADEALgAw
+ADEAMQBNAGEAdABlAHIAaQBhAGwASQBjAG8AbgBzAC0AUgBlAGcAdQBsAGEAcgAAAAMAAAAAAAD/gwAy
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB//8AAgABAAAADAAAABwAAAACAAIAAwAnAAEAKAPMAAIABAAA
+AAEAAAABAAAACgAeADQAAWxhdG4ACAAEAAAAAP//AAEAAAABc2l6ZQAIAAQAAACgAAAAAAAAAAAAAAAA
+AAEAAAAKAB4ALAABbGF0bgAIAAQAAAAA//8AAQAAAAFsaWdhAAgAAAABAAAAAQAEAAQAAAABAAgAAWj8
+ABkAOABUCOIO7BegHJAfqCngK24tTC+yMW45jj0wQApAqkq6S55QEl5aYjJipGaSaIpouAABAAQC4gAL
+ABEADQAfABwAIQAOACEAFgAcABsASACSAM4BCAFAAXgBrgHkAhYCRAJyAp4CyALwAxgDPgNiA4YDqgPM
+A+wEDAQsBEwEbASMBKoEyATmBQIFHgU6BVYFcgWOBagFwgXcBfYGEAYqBkQGXAZ0BowGpAa6BtAG5gb8
+BxIHKAc+B1IHZgd6B44Hoge2B8oH3AfuB/4IDggeCC4IPghOCFwIaAh0CH4IhgKkAB0AFgAfABkAFgAb
+ABIADQAgABIADgAhAA0AFgAbABEAFgAjABYAEQAiAA4AGQANACAAIgAWACEAEgKnABwAFgAfABkAFgAb
+ABIADQAgABIADgAhAA0AGQASABQAHwAcABwAGgANAB8AEgARACIAEAASABECpgAbABYAHwAZABYAGwAS
+AA0AIAASAA4AIQANABkAEgAUAB8AHAAcABoADQAbABwAHwAaAA4AGQKpABsAFgAfABkAFgAbABIADQAg
+ABIADgAhAA0AHwASABAAGQAWABsAEgANABsAHAAfABoADgAZAqUAGgAWAB8AGQAWABsAEgANACAAEgAO
+ACEADQAZABIAFAAfABwAHAAaAA0AEgAlACEAHwAOAqgAGgAWAB8AGQAWABsAEgANACAAEgAOACEADQAf
+ABIAEAAZABYAGwASAA0AEgAlACEAHwAOAqMAGAAWAB8AGQAWABsAEgANACAAEgAOACEADQATABkADgAh
+AA0ADgAbABQAGQASABECagAWAB8AHwAcACQADQARAB8AHAAdAA0AEQAcACQAGwANABAAFgAfABAAGQAS
+AuUAFgAQABAAHAAiABsAIQANAA8ADgAZAA4AGwAQABIADQAkAA4AGQAZABIAIQDbABUAFgAfAB0AGQAO
+ABsAEgAaABwAEQASAA0AFgAbAA4AEAAhABYAIwASAvYAFAAgACAAFgAUABsAGgASABsAIQANACEAIgAf
+ABsAEgARAA0AFgAbAvUAEwAgACAAFgAUABsAGgASABsAIQANAB8AEgAhACIAHwAbABIAEQDcABMAFgAf
+AB0AGQAOABsAEgAaABwAEQASAA0ADgAQACEAFgAjABIAsQASABEAEQANABAAFgAfABAAGQASAA0AHAAi
+ACEAGQAWABsAEgLoABEAEQARAA0AIAAVABwAHQAdABYAGwAUAA0AEAAOAB8AIQL0ABEAIAAgABYAFAAb
+ABoAEgAbACEADQAfABIAIQAiAB8AGwKiABEAFgAfABkAFgAbABIADQAgABIADgAhAA0AEwAZAA4AIQDb
+ABAAFgAfAB0AGQAOABsAEgAaABwAEQASAA0AHAATABMC8wAPACAAIAAWABQAGwAaABIAGwAhAA0AGQAO
+ACEAEgGLAA8AIAAgABYAIAAhAA4AGwAhAA0AHQAVABwAIQAcAmkADwAfAB8AHAAkAA0AEQAfABwAHQAN
+ABEAHAAkABsA3AAPABYAHwAdABkADgAbABIAGgAcABEAEgANABwAGwO7AA8AFgAfAB0AHAAfACEADQAg
+ABUAIgAhACEAGQASAuQADwAQABAAHAAiABsAIQANAA8ADgAZAA4AGwAQABIC5wAOABAAEAAcACIAGwAh
+AA0AEAAWAB8AEAAZABICfwAOAB8AHwAcACQADQARABwAJAAbACQADgAfABEC8gAOACAAIAAWABQAGwAa
+ABIAGwAhAA0AFgAbABEDvAANABkAGQANABYAGwAQABkAIgAgABYAIwASAmsADQAfAB8AHAAkAA0AEQAf
+ABwAHQANACIAHQGIAA0AEQARAA0AIQAcAA0AHQAVABwAIQAcACACbAANAB8AHwAcACQADQATABwAHwAk
+AA4AHwARAuMADQAQABAAEgAgACAAFgAPABYAGQAWACEAJgDYAA0AEAAQABIAIAAgAA0ADgAZAA4AHwAa
+ACACfAAMAB8AHwAcACQADQAiAB0AJAAOAB8AEQEMAAwAIQAhAA4AEAAVAA0AGgAcABsAEgAmAGYADAAR
+ABEADQAhABwADQAeACIAEgAiABIC7wAMACAAHQASABAAIQANAB8ADgAhABYAHALuAAwAGwAbABwAIgAb
+ABAAEgAaABIAGwAhAlsADAARABEADQAZABwAEAAOACEAFgAcABsA1wAMABAAEAASACAAIAANAA4AGQAO
+AB8AGgLmAAsAEAAQABwAIgAbACEADQAPABwAJQDZAAsAEAAQABIAIAAgAA0AIQAWABoAEgIfAAsAEQAR
+AA0ADgANAB0AFQAcACEAHAELAAsAIQAhAA4AEAAVAA0AEwAWABkAEgLxAAoAIAAgABYAFAAbABoAEgAb
+ACECaAAKAB8AHwAcACQADQAPAA4AEAAYA6IACgAQABAAEgAgACAAFgAPABkAEgCwAAoAEQARAA0AEAAW
+AB8AEAAZABIC8AAKACAAIAASACAAIAAaABIAGwAhAYwACgAiABEAFgAcACEAHwAOABAAGAFKAAoAIQAh
+AA4AEAAVABoAEgAbACEAagAJAB8AIQANACEAHwAOABAAGALrAAkAGQAOAB8AGgANABwAEwATACsACQAR
+ABEADQAOABkAEgAfACEA2gAJABEAEQANAA4AGQAOAB8AGgLqAAkAGQAOAB8AGgANAA4AEQARAvcACQAi
+ACEAHAAfABIAGwASACQBigAJACAAIAAWACAAIQAOABsAIQLsAAgAGQAOAB8AGgANABwAGwAtAAgAIwAN
+ACEAFgAaABIAHwOaAAcAGQAZAA0AHAAiACEAsgAHAB8AEAAVABYAIwASAK8ABwARABEADQAPABwAJQLt
+AAcAGwARAB8AHAAWABEAXwAHABYAHwAdABkADgAmA7oABwAQAA0AIgAbABYAIQGJAAYAEQAXACIAIAAh
+AukABQAZAA4AHwAaACwABQAZAA8AIgAaAmcABAAdAB0AIACuAAMAEQARAoIAAwARAA8ANwBwAJwAxADs
+ARIBOAFcAYABogHCAeICAgIiAkICYgKCAqACvALYAvQDDgMoA0IDXAN2A5ADqgPEA94D+AQSBCwERgRg
+BHoElASuBMYE3gT2BQwFIgU4BU4FYgV2BYgFmgWsBb4FzgXcBegF9AYAAN4AFQAOACEAIQASAB8AJgAN
+ABAAFQAOAB8AFAAWABsAFAANABMAIgAZABkA4wATABkAIgASACEAHAAcACEAFQANABAAHAAbABsAEgAQ
+ACEAEgARAOUAEwAZACIAEgAhABwAHAAhABUADQAgABIADgAfABAAFQAWABsAFAB1ABIAHwAOABsAEQAW
+ABsAFAANACQADgAhABIAHwAaAA4AHwAYAOQAEgAZACIAEgAhABwAHAAhABUADQARABYAIAAOAA8AGQAS
+ABEA6QARAB8AFgAUABUAIQAbABIAIAAgAA0AGgASABEAFgAiABoBEQARABwAHwARABIAHwANABUAHAAf
+ABYAJwAcABsAIQAOABkC+wAQABwAHAAYABoADgAfABgADQAcACIAIQAZABYAGwASAOYADwAfABYAFAAV
+ACEAGwASACAAIAANAA4AIgAhABwDvgAPACIAIAAWABsAEgAgACAADQAQABIAGwAhABIAHwEYAA8AHAAf
+ABEAEgAfAA0AIwASAB8AIQAWABAADgAZAOcADwAfABYAFAAVACEAGwASACAAIAANABUAFgAUABUCgwAP
+ABkAIgASACEAHAAcACEAFQANAA4AIgARABYAHADhAA8ADgAhACEAEgAfACYADQAiABsAGAAbABwAJAAb
+AvsADwAcABwAGAAaAA4AHwAYAA0ADwAcAB8AEQASAB8A6AAOAB8AFgAUABUAIQAbABIAIAAgAA0AGQAc
+ACQBDgANABwAHwARABIAHwANAA8AHAAhACEAHAAaAY0ADQAZACIAHwANABAAFgAfABAAIgAZAA4AHwDd
+AA0ADgAhACEAEgAfACYADQAOABkAEgAfACEBEgAMABwAHwARABIAHwANABYAGwAbABIAHwGXAAwAHwAW
+ABQAFQAhABsAEgAgACAADQAKARAADAAcAB8AEQASAB8ADQAQABwAGQAcAB8BDwAMABwAHwARABIAHwAN
+ABAAGQASAA4AHwGWAAwAHwAWABQAFQAhABsAEgAgACAADQAJAZUADAAfABYAFAAVACEAGwASACAAIAAN
+AAgBlAAMAB8AFgAUABUAIQAbABIAIAAgAA0ABwGTAAwAHwAWABQAFQAhABsAEgAgACAADQAGAZIADAAf
+ABYAFAAVACEAGwASACAAIAANAAUBkQAMAB8AFgAUABUAIQAbABIAIAAgAA0ABAK6AAwAIgAPAA8AGQAS
+AA0AEAAVAA4AHwAhAZgADAAfABwAGAASABsADQAWABoADgAUABIDvQAMABIADgAQABUADQAOABAAEAAS
+ACAAIAEWAAwAHAAfABEAEgAfAA0AIAAhACYAGQASAN8ADAAOACEAIQASAB8AJgANABMAIgAZABkBFQAM
+ABwAHwARABIAHwANAB8AFgAUABUAIQEUAAwAHAAfABEAEgAfAA0AHAAiACEAEgAfAY4ACwAZACIAHwAN
+ABkAFgAbABIADgAfARMACwAcAB8AEQASAB8ADQAZABIAEwAhAOAACwAOACEAIQASAB8AJgANACAAIQAR
+ARcACgAcAB8AEQASAB8ADQAhABwAHQENAAoAHAAfABEAEgAfAA0ADgAZABkC/AAKACIAFAANAB8AEgAd
+ABwAHwAhAiIACgAiAB8AIAAhAA0AGgAcABEAEgDiAAkAGQAiABIAIQAcABwAIQAVALMACQAOABAAGAAg
+AB0ADgAQABICIwAIABIAEgAbABUAEgAfABIC+gAIABwAHAAYABoADgAfABgBjwAIABkAIgAfAA0AHAAT
+ABMAfAAIACIAIAAWABsAEgAgACABkAAHABkAIgAfAA0AHAAbAvgABgAOABAAGAAiAB0BmQAFAB8AIgAg
+ABUC/QAFACIAFgAZABEAtAAFABkAHAAQABgC+QAEABwAHAAYAFYArgDeAQ4BOAFiAYoBsgHaAgACJAJI
+AmoCigKoAsYC5AMCAyADPgNcA3oDmAO0A9AD7AQIBCQEQARcBHgEkgSsBMYE4AT6BRQFLgVGBV4FdgWO
+BaYFvgXWBe4GBgYeBjYGTAZiBngGjgakBroGzgbiBvYHCgceBzIHRgdYB2oHfAeOB6AHsgfEB9YH5gf2
+CAQIEgggCC4IPAhICFQIYAhsCHgIggiMCJYIoAiqAaYAFwAcABsAIQAfABwAGQANAB0AHAAWABsAIQAN
+ABEAIgAdABkAFgAQAA4AIQASAtwAFwAVABIAEAAYAA0ADwAcACUADQAcACIAIQAZABYAGwASAA0ADwAZ
+AA4AGwAYAhcAFAAcABkAGQASABAAIQAWABwAGwAgAA0ADwAcABwAGAAaAA4AHwAYAKwAFAAOABkAGQAN
+ABoAFgAgACAAEgARAA0AHAAiACEAFAAcABYAGwAUAJMAEwAVAA4AIQANAA8AIgAPAA8AGQASAA0AHAAi
+ACEAGQAWABsAEgGfABMAEgAbACEAEgAfAA0AEwAcABAAIgAgAA0AIAAhAB8AHAAbABQCqgATABwAGwAT
+ABYAHwAaAA4AIQAWABwAGwANABsAIgAaAA8AEgAfAwEAEgAVAB8AHAAaABIADQAfABIADgARABIAHwAN
+ABoAHAARABIBVwARAB8AEgAOACEAEgANABsAEgAkAA0AEwAcABkAEQASAB8BoAARABIAGwAhABIAHwAN
+ABMAHAAQACIAIAANACQAEgAOABgCqgAQABwAGwATABYAHwAaAA4AIQAWABwAGwANABsAIgAaA4gADwAO
+AB8AEQANABoAEgAaAA8AEgAfACAAFQAWAB0BTgAOABkAHAAiABEADQARABwAJAAbABkAHAAOABEC/wAO
+ABUADgAbABQAEgANABUAFgAgACEAHAAfACYALgAOABkAHAAgABIAEQANABAADgAdACEAFgAcABsDowAO
+ABwAGgAdAA4AHwASAA0ADgAfAB8AHAAkACABWQAOAA4AIAAhAA0AEAAcABsAGwASABAAIQASABEDwQAO
+ABUAFgAZABEADQATAB8AFgASABsAEQAZACYDjQAOAA4AGgASAB8ADgANABIAGwAVAA4AGwAQABIAdgAO
+AA4AGQAZAA0AIQAcAA0ADgAQACEAFgAcABsBrgAOAB8AHAAdAA0AGQAOABsAEQAgABAADgAdABIBpQAN
+ABwAGwAhAB8AHAAZAA0AHQAcABYAGwAhAnAADQAVABIAIwAfABwAGwANAB8AFgAUABUAIQC4AA0AHAAb
+ACEAEgAbACEADQAdAA4AIAAhABIDhwANAA4AHwARAA0AFAAWABMAIQAQAA4AHwARAJcADQAcABsAIQAO
+ABAAIQANAB0AFQAcABsAEgGvAA0AHwAcAB0ADQAcAB8AFgAUABYAGwAOABkAggANAA4AGQAZAA0AHwAS
+ABAAEgAWACMAEgARAbAADQAfABwAHQANAB0AHAAfACEAHwAOABYAIQCYAAwAHAAbACEADgAQACEADQAa
+AA4AFgAZAVEADAAZABwAIgARAA0AIgAdABkAHAAOABEBnAAMAA4AGgASAB8ADgANABMAHwAcABsAIQC2
+AAwAHAAbACEAEgAbACEADQAQABwAHQAmAUwADAAZABwAIgARAA0AEAAWAB8AEAAZABICbwAMABUAEgAj
+AB8AHAAbAA0AGQASABMAIQMAAAwAFQASABAAGAANABAAFgAfABAAGQASA4kACwAOAB8AEQANACEAHwAO
+ACMAEgAZAh0ACwAfABwAHQANAB8AHAAhAA4AIQASAaEACwAcABkAGQASABAAIQAWABwAGwAgAZ4ACwAO
+ABoAEgAfAA4ADQAfABwAGQAZAZ0ACwAOABoAEgAfAA4ADQAfABIADgAfAJIACwAVAA4AIQANAA8AIgAP
+AA8AGQASALcACwAcABsAIQASABsAIQANABAAIgAhAVAACwAZABwAIgARAA0AHgAiABIAIgASAbEACwAf
+ABwAHQANACAAHgAiAA4AHwASAwQACwAfABIAEQAWACEADQAQAA4AHwARAIEACwAOABkAGQANABoAFgAg
+ACAAEgARA8AACgAVABYAGQARAA0AEAAOAB8AEgCDAAoADgAZABkADQAgAB0AGQAWACEBogAKABwAGQAc
+AB8ADQAZABIAGwAgAU0ACgAZABwAIgARAA0AEQAcABsAEgGbAAoADgAaABIAHwAOAA0ADgAZACEAgAAK
+AA4AGQAZAA0AGgASAB8AFAASAIUACQAZABIADgAfAA0ADgAZABkBrQAJAB8AHAAdAA0AEwAfABIAEgGn
+AAkAHwAcAB0ADQAEAAkADQAMAtsACQAVABIAEAAYAA0ADwAcACUDmwAJABwAHQAmAB8AFgAUABUAIQFP
+AAkAGQAcACIAEQANABwAEwATAH8ACQAOABkAGQANABoADgARABIAhwAIABwAGwAhAA4AEAAhACABowAI
+ABwAGQAcAB8AFgAnABIBqwAIAB8AHAAdAA0ACgANAAgBqgAIAB8AHAAdAA0ACAANAAcBqAAIAB8AHAAd
+AA0ABgANAAUBrAAIAB8AHAAdAA0AEQAWABsBWgAIABwAGgAdACIAIQASAB8AfgAIAA4AGQAZAA0AEgAb
+ABEBpAAHABwAGgAdAA4AHwASAIYABwAcABoAGgASABsAIQJtAAYADgAbABAAEgAZA78ABgAOACAAFgAb
+ABwAuQAGAB8AEgAOACEAEgGaAAYADgAaABIAHwAOAv4ABgAOABAAFQASABEBSwAFABkAHAAiABEAtQAF
+ABkAEgAOAB8DAgAFABkADgAgACACbgAFABUAEgAQABgCcQAFABkAHAAgABIBqQAEAB8AHAAdAIQABAAV
+AA4AIQMDAAQAHAARABIAfQAEAA4AGQAZAr0ABAAOABgAEgFYAAQADgAgACEALwBgAIYArADSAPgBHAFA
+AWIBhAGmAcYB5gIGAiYCRgJkAoICoAK+AtwC+gMWAzADSANgA3gDkAOoA74D1APqBAAEFgQqBD4EUgRk
+BHQEhASUBKIEsAS+BMwE1gTgBOgCtQASABwADQAbABwAIQANABEAFgAgACEAIgAfAA8ADQAcABMAEwKF
+ABIAHAANABsAHAAhAA0AEQAWACAAIQAiAB8ADwANAA4AGQAhAisAEgAWAB8AEgAQACEAFgAcABsAIAAN
+ACEAHwAOABsAIAAWACECKgASABYAHwASABAAIQAWABwAGwAgAA0AHwAOABYAGQAkAA4AJgIpABEAFgAf
+ABIAEAAhABYAHAAbACAADQAgACIADwAkAA4AJgK2ABEAHAANABsAHAAhAA0AEQAWACAAIQAiAB8ADwAN
+ABwAGwKFABAAGwARAA0AEwAcAB8AJAAOAB8AEQAgABkADgAgABUCKgAQABYAHwASABAAIQAWABwAGwAg
+AA0AIQAfAA4AFgAbAigAEAAWAB8AEgAQACEAFgAcABsAIAANABMAEgAfAB8AJgIoAA8AFgAfABIAEAAh
+ABYAHAAbACAADQAPABwADgAhAiwADwAWAB8AEgAQACEAFgAcABsAIAANACQADgAZABgCJQAPABYAHwAS
+ABAAIQAWABwAGwAgAA0ADwAWABgAEgFdAA8AEgAjABIAGQAcAB0AEgAfAA0ADwAcAA4AHwARAVwADwAS
+ACAAGAAhABwAHQANACQAFgAbABEAHAAkACACWgAOABYAHwASABAAIQAWABwAGwAgAA0AHwAiABsCJwAO
+ABYAHwASABAAIQAWABwAGwAgAA0AEAAOAB8A6wAOABIAIwASABkAHAAdABIAHwANABoAHAARABICJgAO
+ABYAHwASABAAIQAWABwAGwAgAA0ADwAiACAChgAOABwADQAbABwAIQANABEAFgAgACEAIgAfAA8DuQAO
+ABIAGQASACEAEgANABMAHAAfABIAIwASAB8BhgANABIAIwAWABAAEgAgAA0AHAAhABUAEgAfANUADAAS
+ABkAEgAhABIADQAgACQAEgASAB0DpgALABwAGwAiACEADQAgABoADgAZABkBWwALABIAIAAYACEAHAAd
+AA0AGgAOABADBwALABIAIAAQAB8AFgAdACEAFgAcABsDpQALABwAGwAiACEADQAZAA4AHwAUABIBQgAL
+AB8ADgAUAA0AFQAOABsAEQAZABICJAAKABYAHwASABAAIQAWABwAGwAgAYQACgASACMAFgAQABIADQAV
+ACIADwCIAAoAFgAOABkAEgAfAA0AIAAWAB0DpAAKAA4AIQASAA0AHwAOABsAFAASAOoACgAOACEADgAN
+ACIAIAAOABQAEgKHAAkAHwAWACMAEgANABIAIQAOAoQACQAWACAAEAANABMAIgAZABkDBQAJAA4AIAAV
+AA8AHAAOAB8AEQMKAAgAHAAbABIADQAOABkAGQGzAAcAEgAhAA4AFgAZACAA7AAHABIAIwAWABAAEgAg
+AIkABwAWAA4AGQAdAA4AEQGyAAYAEgAVAA4AJwASAr4ABgAcABoADgAWABsAugAGAB8ADgATACEAIAMG
+AAYAEgAZABIAIQASAwkABAAcABsAEgFeAAQAHAAQABgDCAADABsAIADtAAMAIwAfAB4APgBuAJYAuADa
+APoBGgE6AVgBdgGSAa4BygHiAfoCEgIqAkACVgJsAoIClgKqArwCzgLeAuoC9gMCAw4DjQAXABsAFQAO
+ABsAEAASAA0AHQAVABwAIQAcAA0AIQAfAA4AGwAgABkADgAhABICsQATABsAFQAOABsAEAASABEADQAS
+ABsAEAAfACYAHQAhABYAHAAbAbcAEAAlAB0AHAAgACIAHwASAA0AGgAWABsAIgAgAA0ABQG2ABAAJQAd
+ABwAIAAiAB8AEgANABoAFgAbACIAIAANAAQCiAAPACMAEgAbACEADQAOACMADgAWABkADgAPABkAEgG5
+AA8AJQAdABwAIAAiAB8AEgANAB0AGQAiACAADQAFAbgADwAlAB0AHAAgACIAHwASAA0AHQAZACIAIAAN
+AAQBtwAOACUAHQAcACAAIgAfABIADQAbABIAFAANAAUBtgAOACUAHQAcACAAIgAfABIADQAbABIAFAAN
+AAQBugANACUAHQAcACAAIgAfABIADQAnABIAHwAcAlwADQARABYAIQANABkAHAAQAA4AIQAWABwAGwAp
+AA0AHwAfABwAHwANABwAIgAhABkAFgAbABICcgALACUAHQAOABsAEQANABkAEgAgACADDAALACUAFgAh
+AA0AIQAcAA0ADgAdAB0CcwALACUAHQAOABsAEQANABoAHAAfABIDtAALACIAHwAcAA0AIAAmABoADwAc
+ABkCiQAKACMAEgAbACEADQAPACIAIAAmA5MACgAjABIAGwAhAA0AIAASAA4AIQJhAAoAIwANACAAIQAO
+ACEAFgAcABsCigAKACMAEgAbACEADQAbABwAIQASAC8ACQAeACIADgAZABYAJwASAB8DDgAJACUAIQAS
+ABsAIAAWABwAGwG1AAgAJQAdABwAIAAiAB8AEgAwAAgAJQAdABkAFgAQABYAIQMNAAcAJQAdABkAHAAf
+ABIAigAFABoADgAWABkDjAAFABcAEgAQACEDCwAFACMAEgAbACEAKAAFAB8AHwAcAB8BtAAEABEAFgAh
+AFoAtgDuASYBVAGCAawB1gIAAioCUgJ6AqICygLwAxYDPANiA4YDqgPOA/IEFgQ4BFoEegSaBLgE1gT0
+BRIFMAVOBWwFiAWkBcAF3AX4BhQGMAZMBmYGgAaaBrQGzgboBwIHHAc0B0wHZAd8B5QHrAfEB9wH9AgK
+CCAINghMCGIIeAiMCKAItAjICNwI8AkCCRQJJgk4CUoJXAluCYAJkgmkCbYJyAnYCeYJ9AoCCg4KGgok
+Ci4BLQAbABwAHwAaAA4AIQANACEAEgAlACEAEQAWAB8AEgAQACEAFgAcABsADQAfAA0AIQAcAA0AGQEs
+ABsAHAAfABoADgAhAA0AIQASACUAIQARABYAHwASABAAIQAWABwAGwANABkADQAhABwADQAfASMAFgAc
+AB8AGgAOACEADQAWABsAEQASABsAIQANABYAGwAQAB8AEgAOACAAEgEiABYAHAAfABoADgAhAA0AFgAb
+ABEAEgAbACEADQARABIAEAAfABIADgAgABIBJgAUABwAHwAaAA4AIQANABkAFgAgACEADQAPACIAGQAZ
+ABIAIQASABEBKwAUABwAHwAaAA4AIQANACAAIQAfABYAGAASACEAFQAfABwAIgAUABUBJwAUABwAHwAa
+AA4AIQANABkAFgAgACEADQAbACIAGgAPABIAHwASABEBGgAUABwAHwAaAA4AIQANAA4AGQAWABQAGwAN
+ABcAIgAgACEAFgATACYBJQATABwAHwAaAA4AIQANABkAFgAbABIADQAgAB0ADgAQABYAGwAUARkAEwAc
+AB8AGgAOACEADQAOABkAFgAUABsADQAQABIAGwAhABIAHwHHABMAFgAZACEAEgAfAA0AEAASABsAIQAS
+AB8ADQATABwAEAAiACAAawATABYADwASAB8ADQAaAA4AGwAiAA4AGQANAB8AEgAQABwAHwARASAAEgAc
+AB8AGgAOACEADQAQABwAGQAcAB8ADQAfABIAIAASACEAbAASABYADwASAB8ADQAgABoADgAfACEADQAf
+ABIAEAAcAB8AEQEcABIAHAAfABoADgAhAA0ADgAZABYAFAAbAA0AHwAWABQAFQAhAHcAEgASAA4AIQAi
+AB8AEgARAA0AHQAZAA4AJgANABkAFgAgACEBzAARABYAGQAhABIAHwANACEAFgAZACEADQAgABUAFgAT
+ACEBIQARABwAHwAaAA4AIQANABAAHAAZABwAHwANACEAEgAlACEBGwARABwAHwAaAA4AIQANAA4AGQAW
+ABQAGwANABkAEgATACEBLgARABwAHwAaAA4AIQANACIAGwARABIAHwAZABYAGwASABEBHwARABwAHwAa
+AA4AIQANABAAHAAZABwAHwANABMAFgAZABkBLgAQABwAHwAaAA4AIQANACIAGwARABIAHwAZABYAGwAS
+AxEAEAAOACMAHAAfABYAIQASAA0AHAAiACEAGQAWABsAEgMRAA8ADgAjABwAHwAWACEAEgANAA8AHAAf
+ABEAEgAfAnUADwAiABkAGQAgABAAHwASABIAGwANABIAJQAWACEBxgAOABYAGQAhABIAHwANAA8ADQAO
+ABsAEQANACQDlQAOABkAFgAUABUAIQANACEADgAYABIAHAATABMDwgAOABYAIQAbABIAIAAgAA0AEAAS
+ABsAIQASAB8AeAAOABIADgAhACIAHwASABEADQAjABYAEQASABwBzQAOABYAGQAhABIAHwANACMAFgAb
+ACEADgAUABIDwwAOAB8AEgASAA0ADwAfABIADgAYABMADgAgACECiwAOABwAGQARABIAHwANACAAHQAS
+ABAAFgAOABkBxQANABYAGQAhABIAHwANAAwADQAdABkAIgAgAVIADQAWABkAEgANABEAHAAkABsAGQAc
+AA4AEQDQAA0AHAAbACEADQARABwAJAAbABkAHAAOABEBJAANABwAHwAaAA4AIQANABYAIQAOABkAFgAQ
+AVYADQAcABkAEQASAB8ADQAgABUADgAfABIAEQHJAA0AFgAZACEAEgAfAA0AEwAfAA4AGgASACADFgAN
+ABkAFgAdAA0AIQAcAA0AEwAfABwAGwAhAUMADQAcAB8AGgAOACEADQAgABUADgAdABIAIAEpAAwAHAAf
+ABoADgAhAA0AHgAiABwAIQASAxUADAAZABYAHQANACEAHAANAA8ADgAQABgBHgAMABwAHwAaAA4AIQAN
+ABAAGQASAA4AHwHIAAwAFgAZACEAEgAfAA0AEQAfAA4AGgAOASgADAAcAB8AGgAOACEADQAdAA4AFgAb
+ACEDFAAMABYAGwARAA0AHwASAB0AGQAOABAAEgMTAAwAFgAbABEADQAWABsADQAdAA4AFAASADEADAAO
+ACAAIQANABMAHAAfACQADgAfABEBywALABYAGQAhABIAHwANABsAHAAbABIAuwALABYAGQAhABIAHwAN
+ABkAFgAgACEDnAALABYAGwAUABIAHwAdAB8AFgAbACEBKgALABwAHwAaAA4AIQANACAAFgAnABIBVQAL
+ABwAGQARABIAHwANABwAHQASABsDlAALABkAFgAUABUAIQANABkADgAbABEBHQALABwAHwAaAA4AIQAN
+AA8AHAAZABEAMgALAA4AIAAhAA0AHwASACQAFgAbABEBUwALABYAGQASAA0AIgAdABkAHAAOABECdAAK
+ACIAGQAZACAAEAAfABIAEgAbAGEACgAcAB8AJAAOAB8AEQANAAYAAwHKAAoAFgAZACEAEgAfAA0AFQAR
+AB8BzwAKABkADgAgABUADQAOACIAIQAcAGAACgAcAB8AJAAOAB8AEQANAAQAAwKAAAoAFgAfACAAIQAN
+AB0ADgAUABIB0AAJABkADgAgABUADQAcABMAEwEvAAkAIgAbABAAIQAWABwAGwAgAHQACQAWAA8AEgAf
+AA0AHQAWABsAaAAJABYADwASAB8ADQAbABIAJABiAAkAHAAfACQADgAfABEADQAIAGcACQAWAA8AEgAf
+AA0AEQAjAB8BwgAIABYAGQAhABIAHwANAAoBwQAIABYAGQAhABIAHwANAAkBwAAIABYAGQAhABIAHwAN
+AAgBvwAIABYAGQAhABIAHwANAAcDEgAIABIAEgARAA8ADgAQABgBvQAIABYAGQAhABIAHwANAAYBvAAI
+ABYAGQAhABIAHwANAAUBuwAIABYAGQAhABIAHwANAAQB0QAIABkADgAgABUADQAcABsDEAAIAA4AIwAc
+AB8AFgAhABIBxAAIABYAGQAhABIAHwANAAwBwwAIABYAGQAhABIAHwANAAsAvQAHABwAHwAkAA4AHwAR
+Ai0ABgAZABYAFAAVACEBVAAGABwAGQARABIAHwG+AAYAFgAZACEAEgAfAIsABQAcAB8AIgAaAc4ABQAZ
+AA4AHwASAdIABAAZABYAHQC8AAQAGQAOABQDDwAEAA4AEAASABUALABIAGAAeACOAKQAuADMAN4A8AEA
+ARABIAEwAUABTAFYAWQBcAF8AYYA7wANAB0AIAANABsAHAAhAA0AEwAWACUAEgARA8QACwAcABkAEwAN
+ABAAHAAiAB8AIAASA7UACwANACEAHwAOABsAIAAZAA4AIQASAPMACgAfAA4AHQAVABYAEAANABIAHgMZ
+AAoAHwAcACIAHQANACQAHAAfABgCwAAJAB8AHAAiAB0ADQAOABEAEQDuAAkAHQAgAA0AEwAWACUAEgAR
+AdUACAAfABYAEQANABwAEwATAdMACAAfAA4AEQAWABIAGwAhAdYABwAfABYAEQANABwAGwMXAAcAEgAh
+AA0ADgAdAB0AvgAHABIAIAAhACIAHwASAV8ABwAOABoAEgAdAA4AEQDwAAcAHQAgAA0AHAATABMDGAAF
+AB8ADgARABIDnQAFAA4AIwASABkAMwAFAA4AGgASACAB1AAFAB8ADgAWABsCvwAFAB8AHAAiAB0DzAAE
+ABwADgAhA5cAAwAWABMAFwAwAFIAcgCQAKwAxgDgAPgBDgEiATQBRAFUAWQBdAGEAZQBogGuAboBxAHO
+AdgDGwAQABYAFAAVABkAFgAUABUAIQANAB8AEgAaABwAIwASAx4ADwAcACIAHwAUABkADgAgACAADQAS
+ABoAHQAhACYDHwAOABwAIgAfABQAGQAOACAAIAANABMAIgAZABkDGwANABYAFAAVABkAFgAUABUAIQAN
+ABwAEwATADUADAAWABQAFQANAB4AIgAOABkAFgAhACYDjgAMABIAGQAdAA0AHAAiACEAGQAWABsAEgFh
+AAsAEgAOABEAIAASACEADQAaABYAEAHZAAoAEQAfAA0AIAAhAB8AHAAbABQBRAAJABYAFAAVABkAFgAU
+ABUAIQHaAAgAEQAfAA0AJAASAA4AGAHbAAcAEgAOABkAFgAbABQDHAAHABYAIAAhABwAHwAmAWAABwAS
+AA4AEQAgABIAIQPFAAcAHAAhAA0AIQAiAA8ANAAHABIADgAfABYAGwAUAdcABwARAB8ADQAcABMAEwHY
+AAYAEQAfAA0AHAAbAi4ABQAcACEAEgAZAyAABQAhACEAHQAgAxoABAASABkAHQOSAAQAIQAhAB0DHQAE
+ABwAGgASAF0AAgARABUALABcAIIApgDKAO4BEgE0AVQBdAGSAa4BygHkAf4CGAIwAjwCSAJUAl4DmAAX
+ABsAEQASACEAEgAfABoAFgAbAA4AIQASAA0AEAAVABIAEAAYAA0ADwAcACUB3QASABoADgAUABIADQAO
+ACAAHQASABAAIQANAB8ADgAhABYAHAEyABEAGwAgABIAHwAhAA0AEQAfABYAIwASAA0AEwAWABkAEgCN
+ABEAGwAjABIAHwAhAA0AEAAcABkAHAAfACAADQAcABMAEwOgABEAGgAdABwAHwAhAA4AGwAhAA0AEQAS
+ACMAFgAQABIAIAE0ABEAGwAgABIAHwAhAA0AFgAbACMAFgAhAA4AIQAWABwAGwMkABAAGwAjABIAHwAh
+AA0AEAAcABkAHAAfACAADQAcABsAqAAPABoAHQAcAB8AIQANABAAHAAbACEADgAQACEAIAEzAA8AGwAg
+ABIAHwAhAA0AEgAaABwAIQAWABAAHAAbATEADgAbACAAEgAfACEADQAQABwAGgAaABIAGwAhAyQADQAb
+ACMAEgAfACEADQAQABwAGQAcAB8AIACMAA0AGgAdABwAHwAhAA0AEgAlAB0AHAAfACEDIgAMABsAEwAc
+AA0AHAAiACEAGQAWABsAEgE2AAwAGwAgABIAHwAhAA0AHQAVABwAIQAcATAADAAbACAAEgAfACEADQAQ
+ABUADgAfACEBNQALABsAIAASAB8AIQANABkAFgAbABgDIwAFABsAHQAiACEAvwAFABsADwAcACUB3AAF
+ABoADgAUABIDIQAEABsAEwAcAd4AAwAgABwADQAcAEYAbgCWALwA4AEEASYBRgFkAYABmgGsAWUAFAAS
+ACYADwAcAA4AHwARAA0ADgAfAB8AHAAkAA0AHwAWABQAFQAhAWQAEwASACYADwAcAA4AHwARAA0ADgAf
+AB8AHAAkAA0AGQASABMAIQFjABMAEgAmAA8AHAAOAB8AEQANAA4AHwAfABwAJAANABEAHAAkABsBZwAS
+ABIAJgAPABwADgAfABEADQAPAA4AEAAYACAAHQAOABAAEgFmABEAEgAmAA8AHAAOAB8AEQANAA4AHwAf
+ABwAJAANACIAHQFoABEAEgAmAA8AHAAOAB8AEQANABAADgAdACAAGQAcABAAGAJ3ABAAEgAmAA8AHAAO
+AB8AEQANABAAHAAbACEAHwAcABkBagAPABIAJgAPABwADgAfABEADQAfABIAIQAiAB8AGwFsAA4AEgAm
+AA8AHAAOAB8AEQANACMAHAAWABAAEgFpAA0AEgAmAA8AHAAOAB8AEQANABUAFgARABIBawAMABIAJgAP
+ABwADgAfABEADQAhAA4ADwFiAAgAEgAmAA8AHAAOAB8AEQPGAAcAFgAhABAAFQASABsATwCgANAA/AEk
+AUoBbgGSAbYB2gH+AiACQgJkAoYCpgLEAuIDAAMeAzwDWgN2A5IDrgPKA+YEAgQeBDoEVgRwBIoEpAS+
+BNgE8gUMBSQFPAVUBWwFhAWcBbQFzAXkBfoGEAYmBjwGUgZoBnwGkAakBrgGzAbgBvQHCAccBy4HQAdQ
+B2AHcAeAB5AHoAeuB7wHygfWB+IH7gf4CAIIDAgWAjcAFwAcABAADgAZAA0AEAAcABsAIwASABsAFgAS
+ABsAEAASAA0AIAAhABwAHwASAj4AFQAcABAADgAZAA0AGQAOACIAGwARAB8AJgANACAAEgAfACMAFgAQ
+ABICOwATABwAEAAOABkADQAUAB8AHAAQABIAHwAmAA0AIAAhABwAHwASAPIAEgAcABAADgAhABYAHAAb
+AA0AIAASAA4AHwAQABUAFgAbABQCSAARABwAEAAOABkADQAdABwAIAAhAA0AHAATABMAFgAQABICOgAR
+ABwAEAAOABkADQAUAA4AIAANACAAIQAOACEAFgAcABsA8QARABwAEAAOACEAFgAcABsADQARABYAIAAO
+AA8AGQASABEDngARABYAFAAVACEADwAiABkADwANABwAIgAhABkAFgAbABIBbgARAA4AHQAhABwAHQAN
+ABAAFQAfABwAGgASAA8AHAAcABgCTgAQABwAEAAOACEAFgAcABsADQAVABYAIAAhABwAHwAmAjMAEAAc
+ABAADgAZAA0ADgAhACEAHwAOABAAIQAWABwAGwJJABAAHAAQAA4AGQANAB0AHwAWABsAIQANACAAFQAc
+AB0CSgAQABwAEAAOABkADQAfABIAIAAhAA4AIgAfAA4AGwAhAkkADwAcABAADgAZAA0AHQAfABYAGwAh
+ACAAFQAcAB0CNgAOABwAEAAOABkADQAQAA4AHwANACQADgAgABUCMwAOABwAEAAOABkADQAOABAAIQAW
+ACMAFgAhACYCTAAOABwAEAAOABkADQAgABUAFgAdAB0AFgAbABQCPAAOABwAEAAOABkADQAVABwAIAAd
+ABYAIQAOABkBcAAOAA4AHQAhABwAHQANACQAFgAbABEAHAAkACACRAAOABwAEAAOABkADQAdABUADgAf
+ABoADgAQACYCOQANABwAEAAOABkADQATABkAHAAfABYAIAAhAkMADQAcABAADgAZAA0AHQAOAB8AGAAW
+ABsAFAIeAA0AFgAbABgAEgARAA0AEAAOABoAEgAfAA4CPwANABwAEAAOABkADQAZABYADwAfAA4AHwAm
+AD0ADQAWAA8AHwAOAB8AJgANABoAIgAgABYAEAA8AA0AFgAPAB8ADgAfACYADQAPABwAHAAYACACwQAN
+ABwAEAAOACEAFgAcABsADQAQABYAIQAmAjEADQAcABAADgAZAA0ADgAWAB8AHQAcAB8AIQMmAA0ADgAP
+ABIAGQANABwAIgAhABkAFgAbABIAjwAMABwAEAAOACEAFgAcABsADQAcABMAEwMsAAwAHAAQABgADQAc
+ACIAIQAZABYAGwASAkoADAAcABAADgAZAA0AEQAWABsAFgAbABQCMAAMAA4AJgASAB8AIAANABAAGQAS
+AA4AHwDWAAwAHAAkAA0AHQAfABYAHAAfABYAIQAmAkEADAAcABAADgAZAA0AGgAcACMAFgASACABRQAM
+ABYAGwASAA4AHwANACAAEAAOABkAEgCQAAsAHAAQAA4AIQAWABwAGwANABwAGwJGAAsAHAAQAA4AGQAN
+AB0AFgAnACcADgI4AAsAHAAQAA4AGQANABEAHwAWABsAGAA7AAsAFgAPAB8ADgAfACYADQAOABEAEQHh
+AAsAEgAOABgADQAfABIAGgAcACMAEgI9AAsAHAAQAA4AGQANABUAHAAhABIAGQJCAAsAHAAQAA4AGQAN
+ABwAEwATABIAHwJFAAsAHAAQAA4AGQANAB0AFQAcABsAEgOoAAsAFgAbABIADQAkABIAFgAUABUAIQOn
+AAoAFgAbABIADQAgACEAJgAZABICQAAKABwAEAAOABkADQAaAA4AGQAZAjUACgAcABAADgAZAA0AEAAO
+ABMAEgFvAAoADgAdACEAHAAdAA0AGgAOABACTQAKABwAEAAOABkADQAhAA4AJQAWAkcACgAcABAADgAZ
+AA0AHQAZAA4AJgJLAAkAHAAQAA4AGQANACAAEgASAjQACQAcABAADgAZAA0ADwAOAB8CMgAJABwAEAAO
+ABkADQAOACEAGgKBAAkADgAgACEADQAdAA4AFAASAekACQAcABwAGAAgAA0AIQAkABwDKwAJABwAEAAY
+AA0AHAAdABIAGwHoAAkAHAAcABgAIAANABwAGwASAd8ACQAOABsAEQAgABAADgAdABIAjgAJABYAIwAS
+AA0AFQASABkAHQHgAAgAEgAOABgADQAOABEAEQMnAAgADgAbABQAIgAOABQAEgMtAAcAHAAmAA4AGQAh
+ACYB5wAHABwAHAAYACAADQAJAeYABwAcABwAGAAgAA0ACAHlAAcAHAAcABgAIAANAAcCqwAHABYAIwAS
+AA0AIQAjAeMABwAcABwAGAAgAA0ABgIvAAYADgAmABIAHwAgAygABgAOACIAGwAQABUBbQAGAA4AHQAh
+ABwAHQHqAAUAHAAiAB0AEgHkAAUAHAAcABgAIAMlAAUADgAPABIAGQHiAAQAEgAbACAAwAAEABYAGwAY
+ADYABAAcABwAHQMpAAQAFgAgACEDKgAEABwAEAAYACcAUAB2AJoAvgDgAQIBJAFEAWQBggGgAbwB1gHw
+AgoCIgI6AlACZgJ8ApICqAK8AtAC5AL4AwoDHAMsAzwDSgNWA2IDbAN2A4ADigOSA5oDLgASAA4AHwAY
+ACIAGwAfABIADgARAA0AGgAOABYAGQAPABwAJQHrABEAHAAbABwAEAAVAB8AHAAaABIADQAdABUAHAAh
+ABwAIACTABEAEgAgACAAEgAbABQAEgAfAA0AHAAiACEAGQAWABsAEgA8ABAAJgANABkAFgAPAB8ADgAf
+ACYADQAPABwAHAAYACAA8wAQACIAGQAhABYAIQAfAA4AEAAYAA0ADgAiABEAFgAcAD0AEAAmAA0AGQAW
+AA8AHwAOAB8AJgANABoAIgAgABYAEAFIAA8AHAAbABIAIQAWACcADgAhABYAHAAbAA0AHAAbArsADwAi
+ABkAIQAWABkAFgAbABIADQAQABUADgAfACEB7AAOABwAIwAWABIADQAQAB8AEgAOACEAFgAcABsAOwAO
+ACYADQAZABYADwAfAA4AHwAmAA0ADgARABEA0QANABwAIwASAA0AIQAcAA0AFgAbAA8AHAAlAKkADAAO
+ABYAGQANABwAIgAhABkAFgAbABIBOAAMABwAEQASAA0AEAAcABoAGgASABsAIQIgAAwAHAAjABYAEgAN
+ABMAFgAZACEAEgAfAlAACwAmAA0AGQAcABAADgAhABYAHAAbAG0ACwAiACAAFgAQAA0AIwAWABEAEgAc
+AncACgAcAB8AEgANABUAHAAfABYAJwE3AAoAEgAfABQAEgANACEAJgAdABIB7QAKACIAIAAWABAADQAb
+ABwAIQASAMIACgAOAB8AGAAiABsAHwASAA4AEQOpAAoAHAAhABwAHwAQACYAEAAZABICeAAJABwAHwAS
+AA0AIwASAB8AIQE5AAkAHAARABIADQASABEAFgAhAUEACQAcABsAEgAmAA0AHAATABMAkgAJABIAIAAg
+ABIAGwAUABIAHwLDAAgAHAAcABEADQAPAA4AEQA4AAgAFgAQAA0AGwAcABsAEgA5AAcAFgAQAA0AHAAT
+ABMAkQAHABIAIAAgAA4AFAASAXEABgASABoAHAAfACYBcgAFABwAIgAgABIAOgAFABwAIwAWABICwgAE
+ABwAHAARAMEABAAOABYAGQKNAAQAHAAfABICdgAEABIAGwAiAk8AAwAOAB0CjAADABoAIAA3AAMAFgAQ
+ABoANgBgAIoAsADUAPYBFgE0AVIBbgGKAaYBwgHeAfoCFAIuAkgCYAJ2AooCnAKsAroCyALSAsgAFAAc
+ACEAFgATABYAEAAOACEAFgAcABsAIAANAB0ADgAiACAAEgARAscAFAAcACEAFgATABYAEAAOACEAFgAc
+ABsAIAANAA4AEAAhABYAIwASAsUAEgAcACEAFgATABYAEAAOACEAFgAcABsAIAANABsAHAAbABICxgAR
+ABwAIQAWABMAFgAQAA4AIQAWABwAGwAgAA0AHAATABMCxwAQABwAIQAWABMAFgAQAA4AIQAWABwAGwAg
+AA0AHAAbAfAADwAOACMAFgAUAA4AIQASAA0ADwASABMAHAAfABICjgAOABIAIQAkABwAHwAYAA0AGQAc
+ABAAGAASABEAPwAOABwAIQANABYAGwAhABIAHwASACAAIQASABECswANABwADQASABsAEAAfACYAHQAh
+ABYAHAAbAsQADQAcACEAFgATABYAEAAOACEAFgAcABsAIAKyAA0AEgAhACQAHAAfABgADQAQABUAEgAQ
+ABgB8QANAA4AIwAWABQADgAhABIADQAbABIAJQAhAPcADQAcACQADQAkAA4AGQAZAB0ADgAdABIAHwHv
+AA0ADgAhACIAHwASAA0AHQASABwAHQAZABIAPgAMABIAJAANAB8AEgAZABIADgAgABIAIAD1AAwAEgAh
+ACQAHAAfABgADQAkABYAEwAWAPQADAASACEAJAAcAB8AGAANABAAEgAZABkA+AALABwAJAANACQAFgAR
+ABQAEgAhACACUQAKAA4AIwAWABQADgAhABYAHAAbANMACQASACUAIQANACQAEgASABgDLwAIABwAIQAS
+AA0ADgARABECXQAHABIADgAfAA0AGgASAJQABgAcAA0AIAAWABoB7gAGAA4AIQAiAB8AEgB5AAQAHAAh
+ABIA9gADABMAEAAGAA4ALgBMAGQAfACQAzAADwAdABIAGwANABYAGwANAA8AHwAcACQAIAASAB8CrAAO
+ABsAEQASABoADgAbABEADQAjABYAEQASABwDMQALAB0AEgAbAA0AFgAbAA0AGwASACQDmQALABMAEwAZ
+ABYAGwASAA0AHQAWABsDMgAJAB0AEgAbAA0AJAAWACEAFQOqAAcAHQAOABAAFgAhACYAVwCwAOIBEgFC
+AXIBogHQAfwCJgJOAnYCngLGAuwDEgM4A14DhAOoA8wD8AQUBDgEWgR8BJ4EwATgBQAFIAVABV4FfAWa
+BbgF1gX0BhIGMAZOBmwGiAakBsAG3Ab4BxQHMAdMB2YHgAeaB7QHzgfoCAIIGggyCEgIXgh0CIoIoAi0
+CMgI2gjsCP4JEAkiCTQJRAlUCWQJdAmCCZAJngmqCbYJwgnOCdoJ5gnyCfwKBgIYABgAFQAcACEAHAAN
+ACAAFgAnABIADQAgABIAGQASABAAIQANAA4AEAAhACIADgAZAhkAFwAVABwAIQAcAA0AIAAWACcAEgAN
+ACAAEgAZABIAEAAhAA0AGQAOAB8AFAASAhoAFwAVABwAIQAcAA0AIAAWACcAEgANACAAEgAZABIAEAAh
+AA0AIAAaAA4AGQAZAo8AFwAVABwAGwASAA0ADwAZACIAEgAhABwAHAAhABUADQAgAB0AEgAOABgAEgAf
+AzgAFwASAB8AGgANABEAEgAjABYAEAASAA0AFgAbABMAHAAfABoADgAhABYAHAAbA58AFgAWABAAIQAi
+AB8AEgANABYAGwANAB0AFgAQACEAIgAfABIADQAOABkAIQM2ABUAEgAfABoADQAQABwAGwAhAA4AEAAh
+AA0AEAAOABkAEgAbABEADgAfAEIAFAAOACIAIAASAA0AEAAWAB8AEAAZABIADQAcACIAIQAZABYAGwAS
+AEUAEwAZAA4AJgANABAAFgAfABAAGQASAA0AHAAiACEAGQAWABsAEgBBABMADgAiACAAEgANABAAFgAf
+ABAAGQASAA0AEwAWABkAGQASABEB9wATAA4AGwAcAB8ADgAaAA4ADQAkABYAEQASAA0ADgAbABQAGQAS
+AfUAEwAOABsAHAAfAA4AGgAOAA0AFQAcAB8AFgAnABwAGwAhAA4AGQM/ABIAHAAkABIAHwANACAAEgAh
+ACEAFgAbABQAIAANABsAEgAkAEQAEgAZAA4AJgANABAAFgAfABAAGQASAA0AEwAWABkAGQASABECuQAS
+ABYAEgANABAAFQAOAB8AIQANABwAIgAhABkAFgAbABIAEQBvABIAGQAOACYAGQAWACAAIQANAA4AEQAR
+AA0AEAAVABIAEAAYAz0AEgAWABAAIQAiAB8AEgANABYAGwANAB0AFgAQACEAIgAfABIDNwARABIAHwAa
+AA0AEQAOACEADgANACAAEgAhACEAFgAbABQCXgARABIAHwAgABwAGwANAB0AFgAbAA0AEAAWAB8AEAAZ
+ABIB9gARAA4AGwAcAB8ADgAaAA4ADQAjABIAHwAhABYAEAAOABkAlgARABwAHwAhAA4ADwAZABIADQAk
+ABYAEwAWAA0AHAATABMB9AARAA4AGwAcAB8ADgAaAA4ADQATABYAIAAVAA0AEgAmABIARAAQABkADgAm
+AA0AEAAWAB8AEAAZABIADQATABYAGQAZAzgAEAASAB8AGgANABEAEgAjABYAEAASAA0AFgAbABMAHAM2
+ABAAEgAfABoADQAQABwAGwAhAA4AEAAhAA0AEAAOABkB9AAQAA4AGwAcAB8ADgAaAA4ADQATABYAIAAV
+ABIAJgASAzUADwASAB8AGgANABAADgAaABIAHwAOAA0AGgAWABAAowAPABUAHAAbABIAGQAWABsAGAAN
+ABIAHwAOACAAEgKQAA8AFQAcABsAEgANABMAHAAfACQADgAfABEAEgARAKYADwAVABwAGwASABkAFgAb
+ABgADQAgABIAIQAiAB0CrQAOABIAHwAgABwAGwAOABkADQAjABYAEQASABwApQAOABUAHAAbABIAGQAW
+ABsAGAANAB8AFgAbABQCzAAOABIAHAAdABkAEgANABwAIgAhABkAFgAbABICzwAOABIAHwAgABwAGwAN
+ABwAIgAhABkAFgAbABIDPAAOABIAHwAaAA0AIAAQAA4AGwANACQAFgATABYDOwAOABIAHwAaAA0AHQAV
+ABwAGwASAA0AGgAgABQApAAOABUAHAAbABIAGQAWABsAGAANABkAHAAQABgApwAOAB8AEgAgABIAGwAh
+AA0AIQAcAA0ADgAZABkB/AAOABYAEAAhACIAHwASAA0ADgAgAA0AHQARABMDrAAOAB8AEgAUABsADgAb
+ACEADQAkABwAGgAOABsCtwANAB8AFgAcAB8AFgAhACYADQAVABYAFAAVAzkADQASAB8AGgANABYAEQAS
+ABsAIQAWACEAJgOWAA0AGQAOACYADQATABwAHwANACQAHAAfABgBcwANABUAHAAbABIADQAOABsAEQAf
+ABwAFgARAXYADQAVABwAGwASABkAFgAbABgADQAcABMAEwBpAA0AGQAOACYAGQAWACAAIQANAB0AGQAO
+ACYB+wANABUAHAAhABwADQAZABYADwAfAA4AHwAmApEADQAVABwAGwASAA0AFgAbAA0AIQAOABkAGAKU
+AAwAFQAcABsAEgANAB0ADgAiACAAEgARApMADAAVABwAGwASAA0AGgAWACAAIAASABECkgAMABUAHAAb
+ABIADQAZABwAEAAYABIAEQF0AAwAFQAcABsAEgANABYAHQAVABwAGwASAfoADAAVABwAIQAcAA0AEAAO
+ABoAEgAfAA4ARgAMABkADgAmABkAFgAgACEADQAOABEAEQIhAAwAFQAcACEAHAANABMAFgAZACEAEgAf
+AfkACwAVABwAIQAcAA0ADgAZAA8AIgAaAYUACwAcACQAEgAfAA0AFgAbAB0AIgAhAEMACgAZAA4AJgAN
+AA4AHwAfABwAJAM6AAoAEgAfABoADQAaABIAEQAWAA4CzgAKABIAHwAgABwAGwANAA4AEQARAk4ACgAS
+AB8AIAAcABsADQAdABYAGwLKAAoADgAfACEAJgANABoAHAARABICuAAJABYAEgANABAAFQAOAB8AIQF1
+AAkAFQAcABsAEgAZABYAGwAYAlIACAAWABsADQARAB8AHAAdAf0ACAAcAB8AIQAfAA4AFgAhAtAACAAZ
+ACIAIAANABwAGwASAfMACAAOABsAHAAfAA4AGgAOA7MACAAOABsADQAhABwAHAAZAzMACAAOABQAEgAj
+ABYAEgAkAzQABwAOACYAGgASABsAIQE6AAcAIgAPABkAFgAgABUB8gAHAA4AGQASACEAIQASAz4ABwAc
+ABkAJgAaABIAHwLSAAYAIgAPABkAFgAQAssABgASABwAHQAZABICzQAGABIAHwAgABwAGwNAAAUAHwAW
+ABsAIQBAAAUADgAiACAAEgH4AAUAFQAcACEAHAKuAAUAHAAkABIAHwJTAAUAGQAOABAAEgCVAAUAFQAc
+ABsAEgLJAAUADgAUABIAIALRAAQAHAAZABkDxwAEABwAHAAZA6sABAASACEAIAAHABAAPABkAIQApADA
+ANgAlwAVACIAFgAQABgADQAQABwAGwAhAA4AEAAhACAADQARABYADgAZABIAHwCYABMAIgAWABAAGAAN
+ABAAHAAbACEADgAQACEAIAANABoADgAWABkAcAAPACIAEgAiABIADQAdABkADgAmAA0AGwASACUAIQNC
+AA8AIgASACAAIQAWABwAGwANAA4AGwAgACQAEgAfA0EADQAiABIAHwAmAA0ADwAiABYAGQARABIAHwBI
+AAsAIgASACIAEgANABoAIgAgABYAEABHAAUAIgASACIAEgAsAFoAiAC0AOABCgE0AVgBfAGeAb4B3gH8
+AhoCOAJUAnACigKkAr4C1gLuAwYDHAMyA0YDWgNuA4IDlAOmA7YDxgPWA+YD9AQCBBAEHgQsBDoESARU
+BGAEagLdABYADgARABYAHAANAA8AIgAhACEAHAAbAA0AIgAbABAAFQASABAAGAASABEAxgAVABIAGgAc
+ACMAEgANABAAFgAfABAAGQASAA0AHAAiACEAGQAWABsAEgH/ABUAHAAhAA4AIQASAA0ADAADAA0AEQAS
+ABQAHwASABIAIAANABAAEAAkA7YAFAASABoAHAAjABIADQAgABUAHAAdAB0AFgAbABQADQAQAA4AHwAh
+At4AFAAOABEAFgAcAA0ADwAiACEAIQAcABsADQAQABUAEgAQABgAEgARAHEAEQASABoAHAAjABIADQAT
+AB8AHAAaAA0AHgAiABIAIgASA60AEQASABAAHAAfABEADQAjABwAFgAQABIADQAcACMAEgAfAt0AEAAO
+ABEAFgAcAA0ADwAiACEAIQAcABsADQAcABMAEwJVAA8AEgAgACEADgAiAB8ADgAbACEADQAaABIAGwAi
+At4ADwAOABEAFgAcAA0ADwAiACEAIQAcABsADQAcABsDrgAOABwAIgAbABEAEgARAA0AEAAcAB8AGwAS
+AB8B/gAOABIAGgAcACMAEgANAB8AEgARAA0AEgAmABIDRQAOABIAHQAcAB8AIQANAB0AHwAcAA8AGQAS
+ABoAxQANABIAGgAcACMAEgANABAAFgAfABAAGQASAEoADQASABAAEgAbACEADQAOABAAIQAcAB8AIAPI
+AAwAHAAcABoADQAgABIAHwAjABYAEAASA7cADAASACAAIQAcAB8AEgANAB0ADgAUABICAQAMABwAIQAO
+ACEAEgANAB8AFgAUABUAIQCZAAsAFgAbABQADQAjABwAGQAiABoAEgJUAAsADgAhABIADQAfABIAIwAW
+ABIAJAIAAAsAHAAhAA4AIQASAA0AGQASABMAIQJgAAoAEgAgACEADgAiAB8ADgAbACEATAAKABIAHQAS
+AA4AIQANABwAGwASAMgACQASAB0AGQAmAA0ADgAZABkAZAAJABIAHQAZAA4AJgANAAYAAwBjAAkAEgAd
+ABkADgAmAA0ABAADArQACQAjAA0AFQAcABwAGAAiAB0AZQAIABIAHQAZAA4AJgANAAgArQAIACAAIAAN
+ABMAEgASABEDjwAHABIAHAAfABEAEgAfA0YABwASACAAIQAcAB8AEgNDAAcAEgAQABIAFgAdACECeQAH
+ABIAEwAfABIAIAAVA68ABgAcACQAFgAbABQASwAGABIAHQASAA4AIQDJAAYAEgAdABwAHwAhAMQABgAS
+ABoAHAAjABIBdwAGABwAIgAhABIAHwNEAAYAEgARABIAEgAaAE0ABgASAB0AGQAOACYAxwAFABIAHQAZ
+ACYASQAFAA4AEQAWABwDRwAEABwAHAAaAMMABAASABEAHAB1AOwBRAF8Aa4B4AISAkQCdgKmAtYDBAMy
+A2ADjgO8A+oEFgRCBG4EmgTGBPIFHAVGBXAFmgXEBewGFAY8BmQGigawBtQG+AccB0AHZAeIB6wH0Afy
+CBQINghWCHYIlgi2CNYI9AkSCTAJTglsCYgJpAnACdwJ+AoUCjAKTApoCoQKoAq8CtYK8AsKCyQLPAtS
+C2gLfguUC6oLwAvWC+wMAgwYDC4MRAxYDGwMgAyUDKgMvAzQDOIM9A0GDRgNKg06DUoNWg1qDXoNig2Y
+DaYNtA3CDc4N2g3mDfIN/A4GDhAOGg4kDi4OOA5AAQAAKwAWABQAGwAOABkADQAQABIAGQAZACIAGQAO
+AB8ADQAQABwAGwAbABIAEAAhABIAEQANABsAHAANABYAGwAhABIAHwAbABIAIQANAAcADQAPAA4AHwLZ
+ABsAEgAbACEAFgAaABIAGwAhAA0AIwASAB8AJgANABEAFgAgACAADgAhABYAIAATABYAEgARAP4AGAAS
+ACEAIQAWABsAFAAgAA0AIAAmACAAIQASABoADQARAA4AJgARAB8AEgAOABoDUwAYABIAIQAhABYAGwAU
+ACAADQAWABsAHQAiACEADQAQABwAGgAdABwAIAAWACEAEgNSABgAEgAhACEAFgAbABQAIAANABYAGwAd
+ACIAIQANABAAHAAaAB0AHAAbABIAGwAhAtoAGAASABsAIQAWABoAEgAbACEADQAjABIAHwAmAA0AIAAO
+ACEAFgAgABMAFgASABECfgAYACIADwARABYAHwASABAAIQAcAB8AJgANAA4AHwAfABwAJAANAB8AFgAU
+ABUAIQJ9ABcAIgAPABEAFgAfABIAEAAhABwAHwAmAA0ADgAfAB8AHAAkAA0AGQASABMAIQNMABcAEgAh
+ACEAFgAbABQAIAANAA8ADgAQABgAIgAdAA0AHwASACAAIQAcAB8AEgEBABYAFgAUABsADgAZAA0AEAAS
+ABkAGQAiABkADgAfAA0AGwAcAA0AIAAWABoDUQAWABIAIQAhABYAGwAUACAADQAWABsAHQAiACEADQAO
+ABsAIQASABsAGwAOAJ0AFgAhAA4AJgANAB0AHwAWABoADgAfACYADQAZAA4AGwARACAAEAAOAB0AEgCb
+ABYAIQAOACYADQAQACIAHwAfABIAGwAhAA0AGQAOABsAEQAgABAADgAdABIBBQAWABYAFAAbAA4AGQAN
+ACQAFgATABYADQAHAA0ADwAOAB8ADQAZABwAEAAYAtYAFgASABsAIQAWABoAEgAbACEADQARABYAIAAg
+AA4AIQAWACAAEwAWABIAEQNVABUAEgAhACEAFgAbABQAIAANABYAGwAdACIAIQANACAAIwAWABEAEgAc
+A0sAFQASACEAIQAWABsAFAAgAA0ADgAdAB0AGQAWABAADgAhABYAHAAbACAAnAAVACEADgAmAA0AEAAi
+AB8AHwASABsAIQANAB0AHAAfACEAHwAOABYAIQD/ABUAFgAUABsADgAZAA0AEAASABkAGQAiABkADgAf
+AA0ABwANAA8ADgAfAJ4AFQAhAA4AJgANAB0AHwAWABoADgAfACYADQAdABwAHwAhAB8ADgAWACEA+QAV
+ABAAHwASABIAGwANABkAHAAQABgADQAZAA4AGwARACAAEAAOAB0AEgECABQAFgAUABsADgAZAA0AEAAS
+ABkAGQAiABkADgAfAA0AGwAiABkAGQJXABQAIQAcAB8AEgANABoADgAZABkADQARABYAHwASABAAIQAc
+AB8AJgD7ABQAEAAfABIAEgAbAA0AGQAcABAAGAANAB8AHAAhAA4AIQAWABwAGwD6ABQAEAAfABIAEgAb
+AA0AGQAcABAAGAANAB0AHAAfACEAHwAOABYAIQNnABQAJAAOAB0ADQAjABIAHwAhABYAEAAOABkADQAQ
+ABYAHwAQABkAEgEDABMAFgAUABsADgAZAA0AEAASABkAGQAiABkADgAfAA0AHAATABMDTwATABIAIQAh
+ABYAGwAUACAADQAPAB8AFgAUABUAIQAbABIAIAAgA1QAEwASACEAIQAWABsAFAAgAA0AFgAbAB0AIgAh
+AA0AFQARABoAFgLYABMAEgAbACEAFgAaABIAGwAhAA0AIAAOACEAFgAgABMAFgASABEDTQASABIAIQAh
+ABYAGwAUACAADQAPABkAIgASACEAHAAcACEAFQNkABIAIgAdABIAHwAjABYAIAAcAB8ADQAOABAAEAAc
+ACIAGwAhAQQAEQAWABQAGwAOABkADQAkABYAEwAWAA0ABwANAA8ADgAfAKsAEQAhABwAHQANACAAEAAf
+ABIAEgAbAA0AIAAVAA4AHwASA1AAEQASACEAIQAWABsAFAAgAA0AEgAhABUAEgAfABsAEgAhAtcAEQAS
+ABsAIQAWABoAEgAbACEADQAbABIAIgAhAB8ADgAZA1YAEQASACEAIQAWABsAFAAgAA0AHAAjABIAHwAg
+ABAADgAbA7gAEQAdABIADgAYABIAHwANABsAHAAhABIAIAANABwAEwATAHIAEQAZABwAJAANABoAHAAh
+ABYAHAAbAA0AIwAWABEAEgAcA2gAEQAmACAAIQASABoADQAiAB0AEQAOACEAEgANAA4AGQAhA08AEAAS
+ACEAIQAWABsAFAAgAA0AEQAWACAAHQAZAA4AJgNnABAAJAAOAB0ADQAjABIAHwAhAA0AEAAWAB8AEAAZ
+ABIDaAAQACYAIAAhABIAGgANACIAHQARAA4AIQASAA0AIQAjATwADwAhAB8AFgAYABIAIQAVAB8AHAAi
+ABQAFQANACAA/AAPABAAHwASABIAGwANAB8AHAAhAA4AIQAWABwAGwNdAA8AFQAcAB0AHQAWABsAFAAN
+AA8ADgAgABgAEgAhAQYADwAWABQAGwAOABkADQAkABYAEwAWAA0AHAATABMDWQAPABIAIQAhABYAGwAU
+ACAADQAfABIAGgAcACEAEgKWAA4AFgAaAA0AEAAOAB8AEQANAA4AGQASAB8AIQBUAA4AIgAfAB8AHAAi
+ABsAEQANACAAHAAiABsAEQNYAA4AEgAhACEAFgAbABQAIAANAB0AHAAkABIAHwNXAA4AEgAhACEAFgAb
+ABQAIAANAB0AFQAcABsAEgNaAA4AEgAhACEAFgAbABQAIAANACMAHAAWABAAEgIFAA0AJAAWACEAEAAV
+AA0AEAAOABoAEgAfAA4DXwANAB0AEgAOABgAEgAfAA0AGwAcACEAEgAgAX0ADQAdABIADgAYABIAHwAN
+ABQAHwAcACIAHQBeAA0AHAAfACEADQAPACYADQAOABkAHQAVAA4DygANABoAHAAYABYAGwAUAA0AHwAc
+ABwAGgAgApwADQAmACAAIQASABoADQAiAB0AEQAOACEAEgNeAA0AFQAcAB0AHQAWABsAFAANABAADgAf
+ACEAUAANABgAFgAdAA0AHQAfABIAIwAWABwAIgAgAG4ADQAiAA8AIAAQAB8AFgAdACEAFgAcABsAIANO
+AA0AEgAhACEAFgAbABQAIAANABAAEgAZABkCmgANACYAGwAQAA0AEQAWACAADgAPABkAEgARAJoADQAd
+ABIADgAYABIAHwANAB0AFQAcABsAEgIGAAwAJAAWACEAEAAVAA0AIwAWABEAEgAcApsADAAmABsAEAAN
+AB0AHwAcAA8AGQASABoC4QAMACEADgAfAA0AHAAiACEAGQAWABsAEgCqAAwAEAAfABIAEgAbAA0AIAAV
+AA4AHwASAuEACwAhAA4AHwANAA8AHAAfABEAEgAfA2AACgAdABIAGQAZABAAFQASABAAGAKYAAoAGgAg
+AA0AEwAOABYAGQASABEDZQAKACQADgAdAA0AFQAcAB8AFgAnA8kACgAaABwAGAASAA0AEwAfABIAEgF7
+AAoAGgAOAB8AIQAdABUAHAAbABIAywAKABIAGQASABAAIQANAA4AGQAZAP0ACgARAA0AIAAhABwAHwAO
+ABQAEgCfAAoAJAAOAB0ADQAQAA4AGQAZACACYgAKACEAHwASABIAIQAjABYAEgAkAgMACgAhAB8ADgAW
+ABQAFQAhABIAGwK8AAoAFQAcACQADQAQABUADgAfACEBRgAKABUAHAAfACEADQAhABIAJQAhAFMACQAi
+AA8AIQAWACEAGQASACAC4AAJACEADgAfAA0AFQAOABkAEwICAAkAGQAWABEAEgAgABUAHAAkA2YACQAk
+AA4AHQANACMAEgAfACEATwAJABgAFgAdAA0AGwASACUAIQE7AAkAHQAOABAAEgANAA8ADgAfAlYACQAO
+ACEAEgAZABkAFgAhABIBeQAIABIAEAAiAB8AFgAhACYBegAIABYAGgANABAADgAfABEDXAAIABUAHAAd
+AA0AIQAkABwDSAAIABAAFQASABEAIgAZABIDSgAIABIAIQAhABYAGwAUACADYwAHACIADwAXABIAEAAh
+AE4ABwAVACIAEwATABkAEgKVAAcAEQANABAADgAfABEBfAAHAB0AEgAOABgAEgAfAXgABwAQAA4AGwAb
+ABIAHwEHAAcAIQAcAB8ADgAUABIC0wAGABAAFQAcABwAGQBRAAYAGwAcABwAJwASA0kABgASAA4AHwAQ
+ABUCYwAGACIADwAkAA4AJgNhAAUAIQAOAB8AIALUAAUAFQAOAB8AEgIEAAUAIQAmABkAEgNiAAUAIQAc
+AB8AEgDNAAQAHAAfACEC3wAEACEADgAfA1sABAAVABwAHQDMAAQAEgAbABECmQAEACYAGwAQAMoABAAO
+ACMAEgBSAAQAIQAcAB0ClwADABoAIAPLAAMAHQAOAC0AXACQALIA0ADuAQwBKAFEAWABfAGYAbIBygHi
+AfoCEAImAjoCTgJiAnYCigKeArICxALWAugC+gMMAxwDLAM8A0wDXANqA3YDggOOA5oDpAOuA7gDwgPK
+A9ICZgAZAB8ADgAbACAAEwASAB8ADQAkABYAIQAVABYAGwANAA4ADQAgACEADgAhABYAHAAbA3UAEAAf
+ABIAGwARABYAGwAUAA0AGwASACIAIQAfAA4AGQNuAA4AFQAiABoADwAgAA0AIgAdAA0AEQAcACQAGwF/
+AA4ADgAPABkAEgAhAA0ADgAbABEAHwAcABYAEQNqAA4ADgAPAA0AIgAbACAAEgAZABIAEAAhABIAEQNy
+AA0AHwAOABAAGAANABAAFQAOABsAFAASACACngANABYAGgASAA0AIQAcAA0AGQASAA4AIwASA3gADQAi
+AB8AGwASABEADQAWABsADQAbABwAIQN0AA0AHwASABsAEQAWABsAFAANABEAHAAkABsDdQANAB8AEgAb
+ABEAFgAbABQADQATABkADgAhAp0ADAAOAB0ADQAOABsAEQANAB0AGQAOACYDdgALAB8AEgAbABEAFgAb
+ABQADQAiAB0AzgALABIAJQAhAA0AEwAcAB8AGgAOACEBRwALABIAJQAhAA0AEwAWABIAGQARACADbAAK
+ABUAIgAaAA8ADQARABwAJAAbAYAACgAOAA8AGQASACEADQAaAA4AEAOhAAkAHAAiABAAFQANAA4AHQAd
+Ag0ACQAWABoAEgAfAA0AHAATABMCCQAJABYAGgASABkADgAdACAAEgIHAAkADgAUAA0AEwAOABAAEgAg
+Ag8ACQAfAA4AGwAgABMAHAAfABoDdwAJACIAHwAbABIAEQANABYAGwNzAAkAHwAOABsAIAAZAA4AIQAS
+A20ACAAVACIAGgAPAA0AIgAdAg4ACAAcABsADgAZABYAIQAmA2sACAAVABIADgAhABIAHwAgAgoACAAW
+ABoAEgAfAA0ABAADA7AACAAWABoAEgAZABYAGwASAggABwASACUAIQAiAB8AEgCgAAcAEgAlACEAIAAa
+ACACWQAHAB8ADgATABMAFgAQAgsABwAWABoAEgAfAA0ABgJYAAcAEgAfAB8ADgAWABsBfgAGAA4ADwAZ
+ABIAIQFJAAUAFgAhABkAEgIMAAUAFgAaABIAHwJkAAUAHwAOABYAGwNwAAUAHAARAA4AJgGBAAQAHAAm
+ACACZQAEAB8ADgAaAhAABAAiABsAEgNxAAQAHAAZABkDbwADABwAEANpAAMADgAPAYIAAgAjAAYADgAm
+AD4AUgBgAGoCewALABsAEwAcABkAEQANABoAHAAfABICegALABsAEwAcABkAEQANABkAEgAgACAA0gAJ
+ABsADgAfABAAFQAWACMAEgOxAAYAHQARAA4AIQASAM8ABAAbABEAHAEIAAMAIAAPACUATAB4AKQAygDs
+AQ4BLgFMAWgBhAGgAbwB1gHwAggCIAI4AlACaAKAApgCrgLEAtoC8AMGAxwDMgNGA1oDbgOCA5YDqAO6
+A8wD3gE+ABUAEgAfACEAFgAQAA4AGQANAA4AGQAWABQAGwANABAAEgAbACEAEgAfAT0AFQASAB8AIQAW
+ABAADgAZAA0ADgAZABYAFAAbAA0ADwAcACEAIQAcABoBPwASABIAHwAhABYAEAAOABkADQAOABkAFgAU
+ABsADQAhABwAHQBVABAAFgARABIAHAANABAAHAAZABkAEgAQACEAFgAcABsCEQAQABYAEgAkAA0AEAAc
+ABoAEwAcAB8AIQAOAA8AGQASAYcADwAWABEAEgAcABQADgAaABIADQAOACAAIAASACEDhgAOABYAIAAW
+AA8AFgAZABYAIQAmAA0AHAATABMDfwANABYAEgAkAA0AFQASAA4AEQAZABYAGwASAFUADQAWABEAEgAc
+AA0AGQAWAA8AHwAOAB8AJgN8AA0AFgASACQADQAQAA4AHwAcACIAIAASABkDeQANABIAHwAWABMAFgAS
+ABEADQAiACAAEgAfAhIADAAWABIAJAANABAAHAAaAB0ADgAQACEAVwAMABYAEQASABwAEAAOABoADQAc
+ABMAEwODAAsAFgASACQADQAgACEAHwASAA4AGgN9AAsAFgASACQADQAQABwAGQAiABoAGwB7AAsAFgAR
+ABIAHAANABkADgAPABIAGQOBAAsAFgASACQADQAaABwAEQAiABkAEgN6AAsAFgASACQADQAOABQAEgAb
+ABEADgBYAAsAHAAZACIAGgASAA0AEQAcACQAGwBZAAsAHAAZACIAGgASAA0AGgAiACEAEgOFAAoAFgAg
+ABYADwAWABkAFgAhACYDewAKABYAEgAkAA0ADgAfAB8ADgAmAHoACgAWABEAEgAcAA0AEAAOABkAGQKg
+AAoAHAAWABAAEgANABAAFQAOACECEQAKABYAEgAkAA0AEAAcABoAEwAmA4IACgAWABIAJAANAB4AIgAW
+ABkAIQBaAAoAHAAZACIAGgASAA0AHAATABMCnwAJABYADwAfAA4AIQAWABwAGwOEAAkAFgASACQADQAk
+ABIAEgAYA4AACQAWABIAJAANABkAFgAgACEAoQAJABwAFgAQABIAGgAOABYAGQBbAAkAHAAZACIAGgAS
+AA0AIgAdAhsACAAWABQAGwASACEAIQASA34ACAAWABIAJAANABEADgAmAFYACAAWABEAEgAcABAADgAa
+AqEACAAdABsADQAZABwAEAAYAKIABwAdABsADQAYABIAJgAXADAAVAB0AJQAsgDOAOoBAgEWASoBPgFS
+AWYBeAGKAZoBqgG6AcoB1gHgAeoB8gOIABEADgAZABkAEgAhAA0AGgASABoADwASAB8AIAAVABYAHQIV
+AA8ADwANABYAGwAQAA4AGwARABIAIAAQABIAGwAhA4cADwAOABkAGQASACEADQAUABYAEwAhABAADgAf
+ABEBCgAOABYAEwAWAA0AIQASACEAFQASAB8AFgAbABQCHAANAA8ADQAWAB8AFgARABIAIAAQABIAGwAh
+A4kADQAOABkAGQASACEADQAhAB8ADgAjABIAGQOyAAsADgAhABAAFQANABkADgAhABIAHwBzAAkAEgAP
+AA0ADgAgACAAEgAhAPcACQAOABkAGQAdAA4AHQASAB8BQAAJAB8ADgAdAA0AIQASACUAIQEJAAkAFgAT
+ABYADQAZABwAEAAYAhQACQAPAA0AEAAZABwAIgARACYC1QAIABUADgAhACAAFQAcACECFgAIAA8ADQAg
+ACIAGwAbACYA+AAHABYAEQAUABIAIQAgAhMABwAPAA0ADgAiACEAHADUAAcAEgASABgAEgAbABEAKgAH
+AA4AHwAbABYAGwAUAYMABQAOACEAEAAVA4oABAAcAB8AGAKwAAQAFgATABYAXAADABIADwKvAAIAEAAB
+AAQDiwAUABwAIgAhACIADwASAA0AIAASAA4AHwAQABUAEgARAA0AEwAcAB8AAwAIACIANAJfAAwAHAAc
+ABoADQAcACIAIQANABoADgAdA5EACAAcABwAGgANABwAIgAhA5AABwAcABwAGgANABYAGwACAAQABgAG
+AAAADgAWAAEAGAAkAAoAJgAnABc=
+''';
+
+String _RobotoMonoRegular_ttf;
+// RobotoMonoRegular_ttf md5 is 'b4618f1f7f4cee0ac09873fcc5a966f9'
+String _RobotoMonoRegular_ttf_base64 = '''
+AAEAAAAQAQAABAAAR0RFRgllCWQAAagYAAAAOkdTVULa5NQJAAGoVAAAAkhPUy8yutXqlgABb0AAAABg
+Y21hcN/+LfwAAW+gAAAGWGN2dCBh8hRdAAGCQAAAAJxmcGdt4RTb8AABdfgAAAuXZ2FzcAAAABAAAagQ
+AAAACGdseWb90qjjAAABDAABVjBoZWFk+TEQEAABX0AAAAA2aGhlYQwDA8IAAW8cAAAAJGhtdHiELB/Z
+AAFfeAAAD6Jsb2NhcVzFgQABV1wAAAfkbWF4cAW0DRoAAVc8AAAAIG5hbWVD7GwQAAGC3AAAAwpwb3N0
+w8NSEQABhegAACIlcHJlcDd1O78AAYGQAAAArgACAWIEIQNfBgAABQALADRLsCFQWEANAgEAAAFZAwEB
+AT4ATBtAEwMBAQAAAVUDAQEBAFkCAQABAE1ZthISEhEECBgrAQMjEzUzBQMjEzUzAfkVggGWAWUVgQGW
+BZP+jgFifW3+jgFifQAAAgA9AAAEmQWwABsAHwB0S7AXUFhAJw4LAgMMAgIAAQMAYQgBBgY8Sw8KAgQE
+BVkJBwIFBT9LDQEBAT0BTBtAJQkHAgUPCgIEAwUEYg4LAgMMAgIAAQMAYQgBBgY8Sw0BAQE9AUxZQBof
+Hh0cGxoZGBcWFRQTEhEREREREREREBAIHSsBIQMjEyM1IRMhNSETMwMhEzMDMxUjAzMVIwMjAyETIQLD
+/vhQj1DvAQlF/v4BHVKPUgEIUo9SzehF4vxQj54BCEX++AGa/mYBmokBYosBoP5gAaD+YIv+non+ZgIj
+AWIAAQCi/zAERQacAD0AQkA/EA0CAgAuKwIDBQJKAAECBAIBBHAABAUCBAVuAAAAAgEAAmMABQMDBVcA
+BQUDWQADBQNNOjg0My0sJBQeBggXKwE2JicuAzU0PgI3NTMVFhYXIzQuAiMiBgcUHgIXHgMVFA4CBxUj
+NS4DNTMUHgIzMj4CA4sBh5Ndlms6M12FUZWougG4IT9cO3l8ASBFbU1elmg3N2SPV5VOj25CuTJPZDNB
+aEgnAXdbgjAdTGmIWVSIZT4K3NwX7cxDcVEufmsyTkA3Gh9MZoZZV4pjPAnAvwg4a6JxVG9CHCA9VwAF
+ACz/6wSeBcUAFQArAEEAVwBbAD5AO1taAgIDWQEGBwJKAAIAAQQCAWMABAAHBgQHYwADAwBbAAAAREsA
+BgYFWwAFBUUFTCkpKSkpKSkkCAgcKxM0PgIzMh4CFRUUDgIjIi4CNTMUHgIzMj4CNTU0LgIjIg4CFQE0
+PgIzMh4CFRUUDgIjIi4CNTMUHgIzMj4CNTU0LgIjIg4CFQUnARcsI0NkQUJlQyMjQ2RBQWVEI4oOIDEk
+IzEeDw8fMSQjMR8OAc8jRGRBQmREIyNEY0FCZUQjig8fMiQjMR4ODh8yIyQxHw7+f28CN28EqjlnTi0t
+Tmc5TTlmTS0tTWY5HzktGxstOR9NHzstGxstOx/8qDlmTi0tTmY5TjlmTS0tTWY5HzotGxstOh9OHzot
+GxstOh+WPgQNPgADAGv/7ASpBcUAKgA5AEwAdEATPRgFAwEFLy4gGQQEASMBAgQDSkuwGVBYQCIABQUA
+WwAAAERLAAEBAlsDAQICPUsGAQQEAlsDAQICPQJMG0AgAAUFAFsAAABESwABAQJZAAICPUsGAQQEA1sA
+AwNFA0xZQA8sK0lHKzksOSMUHiwHCBgrEzQ+AjcmJjU0PgIzMh4CFRQOAgcHATY2NzMUBgcXIycGBiMi
+LgIFMjY3AQcOAxUUHgIDFBYXNz4DNTQuAiMiDgJrKEhkPUNPM16EUkd0USwfN0wsXgEzIygBp0lGtd1T
+SrJiY6BwPQGwR4Q5/r0cMj4hCyA+XDoyLXUfKBYJEyU0IStBKxYBdUNyY1krW6JYVYNZLjJVcD41V0xE
+IVD+bUCYWIDbWO1uP0M6aJGdNDABrxgpTkU5EzNYQiYD5jh1QV0VLi8wFx45KxsgNkcAAQHuBCECjQYA
+AAUALUuwIVBYQAsAAAABWQABAT4ATBtAEAABAAABVQABAQBZAAABAE1ZtBIRAggWKwEDIxM1MwKNFYoB
+ngWR/pABYH8AAQFl/ioDdQZrABsABrMUBwEwKwE0PgQ3Fw4CAhUVFBIWFhcHLgU1AWUtTGNtbjInPnth
+PT1hez4nMm9tY0stAk+P/NeyimIcei+i5/7Tuw67/tLopTJxHGGLsdf8jwAAAQFA/ioDUQZrABsABrMU
+BwEwKwEUDgQHJz4CEjU1NAImJic3HgUVA1EtTGNtbzInPnthPUBleTknMm9tY0wtAkWP/Nexi2EccS6l
+6gEwuw67ATHrpC5xHGKKstf8jwAAAQCgAPEEYATIAA4AGkAXDg0MCwoJCAcGAwIBDABHAAAAaRQBCBUr
+ASU3BQMzAyUXBQEHAwMnAhn+hzYBbRmyHQFrNv6CAQCS1tSSAqtgr5cBpf5VlrJe/rxuAWv+nmoAAQB3
+AJIEXQS2AAsAJkAjAAUAAgVVBAEAAwEBAgABYQAFBQJZAAIFAk0RERERERAGCBorASEVIREjESE1IREz
+AsYBl/5puf5qAZa5Aw24/j0Bw7gBqQABAWL+sAKDANsACwAQQA0GBQIARwAAAGkaAQgVKyUUDgIHJzY2
+NTUzAoMXLUAqczAoySsvZ2VcJD9GnlWzAAEA2gIxA9cCyQADABhAFQABAAABVQABAQBZAAABAE0REAII
+FisBITUhA9f9AwL9AjGYAAABAfD/7QMUAQcAEwATQBAAAAABWwABAUUBTCgkAggWKyU0PgIzMh4CFRQO
+AiMiLgIB8BMkNiQkNyUTEyU3JCQ2JBN4HjQnFhYnNB4dMyYVFSYzAAABAPz/gwQBBbAAAwATQBAAAAEA
+cwABATwBTBEQAggWKwUjATMBoqYCYKV9Bi0AAwCR/+wEQAXFABUAHQAlAChAJR8eFxYEAwIBSgACAgFb
+AAEBREsAAwMAWwAAAEUATCYoKSQECBgrARQOAiMiLgI1ETQ+AjMyHgIVAQEmJiMiBhUFARYWMzI2NQRA
+QHiucG+vekFAea9vcK95QP0LAjcQiYGSiwI7/coRjH2TiQIti9eTTEyT14sBVYvXlE1NlNeL/tABs5GX
+xb1X/k+NlMi8AAABANAAAAMGBbAABgAUQBEFBAMCBABIAAAAPQBMEAEIFSshIxEFNSUzAwa5/oMCJw8E
+xJGp1AABAFUAAAQrBcQAJAAuQCsCAQAEAUoAAgEEAQIEcAABAQNbAAMDREsABAQAWQAAAD0ATBokFCsQ
+BQgZKyEhNQE+AzU0LgIjIg4CFSM0PgIzMh4CFRQOAgcBIQQr/EYB3UBWNBYjQ188SWtHI7pAea9wZ6Vy
+PSxLYzf+eQLbhQISR25dUyw2X0YpKk1uRFyjekg9bJRXQX98eTz+WAABAF7/7AP5BcQAPgBFQEIeAQcA
+AUoAAgEAAQIAcAAFBwYHBQZwAAAABwUAB2MAAQEDWwADA0RLAAYGBFsABARFBEw+PDQyLi0pJyQUJiAI
+CBgrATMyPgI1NCYjIg4CFSM0PgIzMh4CFRQOAgceAxUUDgIjIi4CNTMUHgIzMj4CNTQuAiMjAYaERmtJ
+JoJ9O2FFJrpBdqVlYqJ0QBo2VTtHXzkXRnypYmCpfEm5J0hnPz9mSCctUXNFhAMxJkJcN3+BI0JcOVOT
+bT81aJplKlpVSxkXSlxmMmaebTk2aJZgOV5CJCFEZUVEY0IgAAIASwAABGcFsAAKAA4AK0AoDQEABAgB
+AQACSgUBAAMBAQIAAWIABAQ8SwACAj0CTBESEREREAYIGisBMxUjESMRITUBMwEhEQcDnMvLuf1oAozF
+/XwByx4B6Zf+rgFSbQPx/DkC0TgAAQC7/+wETwWwACoAPEA5BQEGAioBBAYCSgAEBgUGBAVwAAIABgQC
+BmMAAQEAWQAAADxLAAUFA1sAAwNFA0woIhQoIxERBwgbKxMTIRUhAzY2MzIeAhUUDgIjIi4CJzMWFjMy
+PgI1NC4CIyIOAgfwSQLr/bEpK3hPZaBwPDhxrHRZnntPCrARlXVCZkUjJ0psRi5DNi8ZAtoC1rT+fBkm
+Rn+0bmiygUkyZJhlfIAvV3pLRHZXMg0YIhYAAgCN/+wEJQWxACcAPAA6QDcJAQQBLQEFBAJKAAEGAQQF
+AQRjAAAAA1sAAwM8SwAFBQJbAAICRQJMKSg0Mig8KTwdKCohBwgYKwEVIyIOBAc+AzMyHgIVFA4CIyIu
+BDU1ND4EMwMiDgIHFRQeAjMyPgI1NC4CA1gQXJFuTzQcBBpET1sybZ5mMDlyqW9Pg2hOMxoZPGab1o/i
+L1hMOhEuTmY4QWRFIyBCZAWxpiZCW2x2PR81JxdTiKxZZrSHTi5PbHyGQ1dkybihdkT9cB42TC4+YJVm
+NTJYe0hAeV44AAABAHAAAARIBbAABgAfQBwAAQECAUoAAQECWQACAjxLAAAAPQBMERERAwgXKwEBIwEh
+NSEESP2lwgJZ/OwD2AVI+rgFDqIAAwCx/+wETwXEACUAOQBNADVAMhcDAgIFAUoABQACAwUCYwAEBAFb
+AAEBREsAAwMAWwAAAEUATEpIQD42NCwqIiAsBggVKwEGBgceAxUUDgIjIi4CNTQ+AjcuAzU0PgIzMh4C
+AzQuAiMiDgIVFB4CMzI+AgM0LgIjIg4CFRQeAjMyPgIELgF0YThbQSNJfahgYql9SCJAWjgwTjYeQHGd
+XVyedEKYKUpnPT9mSCcnSGdAPWZJKSIlQVo2NlhAIyNBWTY1WkEkBDRtqjAYR1xsPWOaaTc2aZpkPW1b
+SBgYQ1NiNl+VZjY2ZpX8+j1mSSgoSWY9P2NEJCREYwLjN1xDJSNCXTk5W0EjI0FcAAIAlf//BCkFxAAn
+ADwAQ0BALQEEBQcBAQQCSgcBBAABAAQBYwAFBQJbAAICREsGAQAAA1sAAwM9A0wpKAEANDIoPCk8JSQX
+FQ0LACcBJwgIFCslMj4ENw4DIyIuAjU0PgIzMh4EFRUUDgQjIzUTMj4CNzU0LgIjIg4CFRQeAgF1Y5Zv
+Si8WAxg+Tl84bJ1mMDlxqXBUh2dKLxYSNWCa3JcT8C9ZSzsRLU1lOUFkRSQgQWOkI0BXaXU9HjUoF1WK
+rlhnt4lRL1Nxg49IQ13DtqF4RqUB3B85TS88YZhpODRbfUhAe2A7AP//AiL/7QNGBHMCJgAQMgABBwAQ
+ADIDbAAJsQEBuANssDMrAP//Aeb+sAM9BHMCJwAQACkDbAEHAA4AhAAAAAmxAAG4A2ywMysAAAEAqgDE
+A/oESwAIAAazBwQBMCsBBxcFFQE1ARUBljU1AmT8sANQApcREuzEAXuSAXrEAAACAK0BbQQqA60AAwAH
+ACJAHwABAAADAQBhAAMCAgNVAAMDAlkAAgMCTRERERAECBgrASE1IREhNSEEKvyDA338gwN9Awyh/cCg
+AAEAsgDFBCUETAAIAAazBAEBMCsTNQEVATUlNyeyA3P8jQKHPDwDjb/+hpL+hcD0ERMAAgC///UEGwXE
+ACcAMwDES7AKUFhAJQABAAMAAQNwBgEDBAADBG4AAAACWwACAkRLAAQEBVsABQU9BUwbS7AMUFhAJQAB
+AAMAAQNwBgEDBAADBG4AAAACWwACAkRLAAQEBVsABQVFBUwbS7AOUFhAJQABAAMAAQNwBgEDBAADBG4A
+AAACWwACAkRLAAQEBVsABQU9BUwbQCUAAQADAAEDcAYBAwQAAwRuAAAAAlsAAgJESwAEBAVbAAUFRQVM
+WVlZQBAAADIwLCoAJwAnJBQsBwgXKwE+Azc+AzU0JiMiDgIVIz4DMzIeAhUUDgIHDgMVAzQ2MzIWFRQG
+IyImAf8BCiA8MiJHOyZ+dS9ZRSq5AURznVtln246Mk5hLx4hEATOOTk5Ozs5OTkBmkhdSUMuI0pRWjJt
+cxcxSzRUhl0xM2KMWkh/cWIqHTQ2PSf+xzBAQDAuPj4AAgBA//gEiwWyAE0AWwClS7AUUFhAFBgBCQJV
+TggDAwk3AQUAOAEGBQRKG0AXGAEJAlVOAggJCAEDCDcBBQA4AQYFBUpZS7AUUFhAJwACAAkDAgljCAED
+AQEABQMAYwAEBAdbAAcHPEsABQUGWwAGBj0GTBtALAACAAkIAgljAAgDAAhXAAMBAQAFAwBjAAQEB1sA
+Bwc8SwAFBQZbAAYGPQZMWUAOWFYmKikoKCcoJCQKCB0rAQ4DIyImJwYGIyIuAjc+AzMyFhcDBh4CMzI+
+Ajc2LgIjIg4CBwYeAjMyPgI3Fw4DIyImJgI3PgUzMh4CAQYWMzI2NxMmIyIOAgSHAyBBZko9UREjZz4x
+SC0RBgk4WXZHQ1gaLAMKExwQJTkmFAEEMmeWYGWnekYEBTBqpXAePjw2FiAZQEZIIJPThTsFBCpJZ4CZ
+Vnq+gUD9SwUsMDFQHiccHjVPNiEDFVCniFZAOThBNF6CTm+zfUM1JP4IKTMdCjlhgkl/yoxKX6rsjIjU
+k00JERgPdRMcEwlnugEBmWfDqo1mOF+w9/72ZnI2PwG9DTNdhQAAAgBRAAAEkAWwAAcACgAlQCIKAQQC
+AUoABAAAAQQAYgACAjxLAwEBAT0BTBEREREQBQgZKwEhAyMBMwEjASEDA2X+GnW5AdabAc64/dkBg8AB
+ef6HBbD6UAIaAngAAAMArAAABGAFsAAWACMAMAA+QDsMAQMEAUoABAcBAwIEA2MABQUAWwAAADxLAAIC
+AVsGAQEBPQFMFxcAADAuJiQXIxciGhgAFgAVIQgIFSszESEeAwcOAwceAxUWDgIHAREhPgM1Ni4CJyUh
+PgM1NC4CJyOsAbFarIZQAQEjPVIuOmFGJwFQhq9d/ugBHTpoUC8BK0xmO/7ZAQI0ZE4wL09nNv0FsAEt
+XpJmOV5LOBQRP1lwQWacaTgBAqn99AElQmA9PmBDJAKaAR87Vjk9VjcaAQAAAQBr/+wEXQXEADMANkAz
+AAIDBQMCBXAGAQUEAwUEbgADAwFbAAEBREsABAQAWwAAAEUATAAAADMAMy0kFC0kBwgZKwEOAyMiLgQn
+NT4FMzIeAhcjLgMjIg4EFRUUHgQzMj4CNwRdDU59q2lak3NTNxsBARs3U3OSW22sfEsMuQksSmtJQmVJ
+MR4NDR4wSmRDSWtKLAkBtmWpeUMzWnqQnlHLUZ6Qe1ozQ3usaEJyVjErSmJuczbNNnNvYksrLlNxQgAC
+AJsAAARwBbAADQAbACxAKQUBAwMAWwAAADxLAAICAVsEAQEBPQFMDg4AAA4bDhoRDwANAAwhBggVKzMR
+IR4DFxUOAwcDETM+Azc1LgMnmwFRmO+lVwEBV6XvmJWVdqxxNwEBOHCsdgWwAmOx95ZrlvexYwEFGPt/
+AVGMvm9tb72LUAIAAAEAtgAABDQFsAALAClAJgAFAAABBQBhAAQEA1kAAwM8SwABAQJZAAICPQJMERER
+EREQBggaKwEhESEVIREhFSERIQPP/aACxfyCA3X9RAJgAqH9/J0FsJ7+LAAAAQC/AAAEPQWwAAkAI0Ag
+AAQAAAEEAGEAAwMCWQACAjxLAAEBPQFMERERERAFCBkrASERIxEhFSERIQPY/aK7A379PQJeAoP9fQWw
+nv4OAAABAGT/6wRcBcQANQA5QDYxAAIEBQFKAAIDBgMCBnAABgAFBAYFYQADAwFbAAEBREsABAQAWwAA
+AEUATBEVLSQULSIHCBsrJQYGJy4FJzU+BTMyHgIXIy4DIyIOBBUVHgUXFj4CNxMhNSEEXFzujlqXeFo9
+HwEBGzhUdZRcZqyATgm3Cy5LaEVCZkwyIA4BESQ4T2hCJlNORBcC/tgB2L9saAEBNV1+k6FSqVGhlH9d
+Nj91pWY/a0wrLUxlcHQ2qzd1cGRMLQEBCBgpIQFHnAAAAQCNAAAEPwWwAAsAIUAeAAQAAQAEAWEFAQMD
+PEsCAQAAPQBMEREREREQBggaKyEjESERIxEzESERMwQ/r/2rrq4CVa8Cof1fBbD9jgJyAAABAK4AAAQe
+BbAACwAjQCAFAQEBAFkAAAA8SwQBAgIDWQADAz0DTBEREREREAYIGisTIRUhESEVITUhESGuA3D+owFd
+/JABVf6rBbCh+5GgoARvAAABAGL/7AQWBbAAFwAiQB8AAgADAAIDcAAAADxLAAMDAVsAAQFFAUwkFCUQ
+BAgYKwEzEQ4DIyIuAiczHgMzMj4CNwNZvQJJfqtlZqd7Sgm8AytKZ0BCaEknAgWw/AtlqntFPnOjZT1o
+TSoxVG8+AAEArAAABKQFsAAMAB9AHAoGAQMAAQFKAgEBATxLAwEAAD0ATBITERIECBgrAQcRIxEzETcB
+MwEBIwILor29jQGr4f4DAh/hAqS4/hQFsP05sAIX/YP8zQABAMYAAARHBbAABQAZQBYAAgI8SwAAAAFa
+AAEBPQFMEREQAwgXKyUhFSERMwF/Asj8f7mdnQWwAAEAlAAABEwFsAAOAC5AKwoHAQMCAAFKAAIAAQAC
+AXAFBAIAADxLAwEBAT0BTAAAAA4ADhMTERIGCBgrARMBMxEjERMBIwMTESMRAXntAQDmtA/+82r3D7QF
+sP0oAtj6UAJFAmD88AL7/bX9uwWwAAABAI8AAAQ+BbAACQAeQBsHAgIAAgFKAwECAjxLAQEAAD0ATBIR
+EhAECBgrISMBAyMRMwETMwQ+vP3LA7u8AjUDuwRA+8AFsPvCBD4AAgBq/+wEYQXEAB0AOwAfQBwAAgIB
+WwABAURLAAMDAFsAAABFAEwtLS0mBAgYKwEOBSMiLgQnNT4FMzIeBBcnLgUjIg4EBxUeBTMyPgQ3BGEB
+GTRRcJFaWpFwUjUaAQEZNVFwkVpaknBRNRkBtwEMHTBIYkFAYkgwHQ0BAQ0eMEhiQUFjRy8dCwEChE6f
+lIBgNzdggZSeTqZOn5SBYTc3YIGUoE4CNHFvZU0tLk1lb3EzqDNyb2ZNLi5NZW9yNAAAAgC/AAAEeQWw
+AA4AGwArQCgAAwUBAgADAmMABAQBWwABATxLAAAAPQBMAAAbGREPAA4ADSERBggWKwERIxEhHgMVFA4C
+ByUhPgM1NC4CJyEBeLkB2GKvhE1NhK9i/uEBH0BsUC0tT21A/uECSP24BbACOm6iaWmhbjoBmAEnSGdC
+QmpKKAEAAAIAXv8KBIwFxAAgAD4AK0AoCAUCAAMBSgcGAgBHAAICAVsAAQFESwADAwBbAAAARQBMLS0t
+KQQIGCsBDgMHFwclBiMiLgQnNT4FMzIeBBcnLgUjIg4EFRUUHgQzMj4ENwRuARo1Uzr7f/7gPkhdlHNU
+NhoBARo2UnOVXV2Vc1M1GgG4AQsdMUpnRURmSjEeDQ0eMUpnREVnSjAdCwECl1GkmIUx0Xn0EjlihZij
+UIBQpJiFYzk5YoWYpVACN3dzaE8uL09oc3c2gjZ3dGhQLy9PaHR3NwACALUAAARyBbAAEgAfACtAKA8B
+AAQBSgAEAAABBABhAAUFAlsAAgI8SwMBAQE9AUwoISohERAGCBorASERIxEhHgMVFA4CBwEHIwEzPgM1
+NC4CJyMCkP7duAGrZrSHTSlIZDwBNQHD/b/4Pm5TMC5ScUPzAlL9rgWwAjZso25HdmBKGv2SDALqASVG
+ZUJGaUckAQAAAQB2/+wEaQXEAD8AM0AwAAECBAIBBHAABAUCBAVuAAICAFsAAABESwAFBQNbAAMDRQNM
+PDo2NTEvJBQuBggXKwE0LgInLgM1ND4CMzIeAhcjLgMjIg4CFR4DFx4FFRQOAiMiLgInMx4DMzI+AgOo
+PWBzNU2fg1NThqpWX7CIUgK+CC5MaUI1ZU8vAT5fbzE2bmZYQiVXiq5XYbqTXAO9CThYc0Q2aVI0AXBD
+XD8qERlGZoteXpRmNT9yomQ/Z0opHjxYOj9XPCgPESs4RllrQWKSYTE8caNoRGlJJRs5VwABAEwAAASE
+BbAABwAbQBgCAQAAA1kAAwM8SwABAT0BTBERERAECBgrASERIxEhNSEEhP4+tP4+BDgFEvruBRKeAAAB
+AIv/7ARCBbAAGQAhQB4EAwIBATxLAAICAFsAAABFAEwAAAAZABklFSUFCBcrARMOAyMiLgInEzMTHgMz
+Mj4CNxMEQAICRn6uaGqufEYBArAEASdJbUdHbEkmAgMFsPwmZrKFTUyFs2YD2vwmQXhcODddeEED2gAB
+AEcAAAR/BbAABgAVQBICAQAAPEsAAQE9AUwREREDCBcrAQEzASMBMwJiAVjF/jWh/jTGASoEhvpQBbAA
+AAEASQAABJ4FsAAMACBAHQoFAgEAAUoEAwIAADxLAgEBAT0BTBIREhERBQgZKwETMwMjAwMjAzMTEzMD
+gG+vsb27vb6xsG+7oQGKBCb6UARJ+7cFsPvaBCYAAAEAVwAABI8FsAALAB9AHAkGAwMBAAFKAwEAADxL
+AgEBAT0BTBISEhEECBgrAQEzAQEjAQEjAQEzAnEBOtr+WQGx2P6+/r3bAbL+WdkDdQI7/S79IgJG/boC
+3gLSAAABAD0AAAR5BbAACAAcQBkGAwIBAAFKAgEAADxLAAEBPQFMEhIRAwgXKwEBMwEDIwMBMwJbAUzS
+/jsDrAP+O9MC1QLb/G/94QIfA5EAAQByAAAENwWwAAkAKUAmCQECAwQBAQACSgACAgNZAAMDPEsAAAAB
+WQABAT0BTBESERAECBgrJSEVIScBITUhFwFFAvL8PQIC1f04A5sCnZ2QBIKejQABAar+yAM2BoAABwAi
+QB8AAwAAAQMAYQABAgIBVQABAQJZAAIBAk0REREQBAgYKwEjETMVIREhAzbd3f50AYwF6Pl4mAe4AAAB
+AOf/gwPuBbAAAwATQBAAAQABcwAAADwATBEQAggWKxMzASPnpwJgpwWw+dMAAQGV/sgDIgaAAAcAIkAf
+AAAAAwIAA2EAAgEBAlUAAgIBWQABAgFNEREREAQIGCsBIREhNTMRIwGVAY3+c97eBoD4SJgGiAAAAQDn
+AqUD5QWwAAgAG0AYBwEAAQFKAgEAAQBzAAEBPAFMEREQAwgXKwEjATMBIwMnBwGTrAFAfwE/q8YPDwKl
+Awv89QHmREQAAQCb/2kEMAAAAAMAGEAVAAEAAAFVAAEBAFkAAAEATREQAggWKwUhNSEEMPxrA5WXlwAB
+AZ8EvwMtBckAAwDaS7AKUFhACwAAAQBzAAEBPAFMG0uwDFBYQAsAAAEAcwABAT4BTBtLsA5QWEALAAAB
+AHMAAQE8AUwbS7AQUFhACwAAAQBzAAEBPgFMG0uwElBYQAsAAAEAcwABATwBTBtLsBZQWEALAAABAHMA
+AQE+AUwbS7AXUFhACwAAAQBzAAEBPAFMG0uwGVBYQAsAAAEAcwABAT4BTBtLsBtQWEALAAABAHMAAQE8
+AUwbS7AqUFhACwAAAQBzAAEBPgFMG0AJAAEAAXIAAABpWVlZWVlZWVlZWbQREAIIFisBIwMzAy2W+N8E
+vwEKAAACAJz/7AQ2BE4ALgA9AERAQTQBBQYtAwIABQJKAAMCAQIDAXAAAQAGBQEGYwACAgRbAAQER0sH
+AQUFAFsAAABFAEwwLzc1Lz0wPSQUJSgnCAgZKyEmJicOAyMiLgI1ND4CMzM1NC4CIyIOAhUjPgMzMh4C
+FREUFhcVJTI+Ajc1IyIGFRQeAgN1Cw0DHEVTXjVWi2E1R4K3ccokQl87N1c8IboBO2+fZVyec0IUEv34
+Nl5NOBCsorQbNlIVPyIcMiYWMlV1RFmGWSxVMU43HhwuPyI7cls4LVuIW/4JNnktEI0cLjsg22BnKEQx
+HAAAAgCv/+wEQwYAABUAKwCiS7AZUFhADw0BBAMhIAIFBAgBAAUDShtADw0BBAMhIAIFBAgBAQUDSllL
+sBlQWEAbAAICPksABAQDWwADA0dLAAUFAFsBAQAARQBMG0uwIVBYQB8AAgI+SwAEBANbAAMDR0sAAQE9
+SwAFBQBbAAAARQBMG0AfAAQEA1sAAwNHSwACAgFZAAEBPUsABQUAWwAAAEUATFlZQAkpKSMREyQGCBor
+ARQOAiMiJicHIxEzETY2MzIeAhUjNC4CIyIOAgcRHgMzMj4CNQRDOGyfZ2iZNgmquTWWZGigbDi5H0Ru
+UDBQPzEREjFAUDBMbUUhAhF0yZRUSkV7BgD9xkJGUpLLeU+PbUAZLT0k/ickPS4ZP2yOTwABAI//7AQz
+BE4AKwA7QDgABAUBBQQBcAABAAUBAG4ABQUDWwADA0dLBgEAAAJbAAICRQJMAQAiIBwbFxUMCgYFACsB
+KwcIFCslMj4CNzMOAyMiLgI1NTQ+AjMyHgIVIy4DIyIOAhUVFB4CAnsyX0otAa8BSXqeVnu4ez4+e7h7
+YKF1Qq8BKUZhOFZ1SB8fR3WCIDlNLUiDYztYlcNsKmvElVg9aZBSMVdCJkVvikYqR4tvRQACAIv/7AQc
+BgAAFQApAIpADwgBBQAhIAIEBQ0BAgQDSkuwGVBYQBsAAQE+SwAFBQBbAAAAR0sABAQCWwMBAgI9Akwb
+S7AhUFhAHwABAT5LAAUFAFsAAABHSwACAj1LAAQEA1sAAwNFA0wbQB8ABQUAWwAAAEdLAAEBAlkAAgI9
+SwAEBANbAAMDRQNMWVlACScpIxETJAYIGisTND4CMzIWFxEzESMnBgYjIi4CNTMUHgIzMj4CNxEmJiMi
+DgIViz1xoGNhkTW5qgg2lmRin3A+uSJHbk0vTD4wEiR6W05vRyICJnnLklJBPgIx+gByQkRUlMl0T45s
+PxYpOSMB9kJVQG2PTwAAAgCH/+wERQROAB8AKwBAQD0bGgIDAgFKAAUAAgMFAmEHAQQEAVsAAQFHSwAD
+AwBbBgEAAEUATCEgAQAmJSArISsYFhIRDAoAHwEfCAgUKwUiLgI1NTQ+AjMyHgIVFSEeAzMyNjcXDgMD
+Ig4CByE1LgMCjHK/iExUi7Fdda90Ofz7AzNZfEtjmjNxG1Fqhmc4ZFA3CwJGAyNEZxROjMBxKoPPj0xR
+j8JxU0qCYThQQlgpSzojA8opT3NLDjZqVDQAAQCYAAAEawYrABkAN0A0DQEDAg4BAQMCSgACAAMBAgNj
+BQEAAAFZBAEBAT9LBwEGBj0GTAAAABkAGRETJSUREQgIGishESE1ITU0PgIzMhYXByYmIwYGFRUhFSER
+AcL+1gEqPW+cYEJ9QhYpbT6CgwGh/l8Dq49MaJ1qNhYRmQ4VAYKFTI/8VQAAAgCM/lYEHQROACkAPwCP
+S7AZUFhAFAgBBgA1NAIFBiEBBAUWFQIDBARKG0AUCAEGATU0AgUGIQEEBRYVAgMEBEpZS7AZUFhAIAAG
+BgBbAQEAAEdLAAUFBFsABARFSwADAwJbAAICQQJMG0AkAAEBP0sABgYAWwAAAEdLAAUFBFsABARFSwAD
+AwJbAAICQQJMWUAKKSknKSUTJAcIGysTND4CMzIWFzczERQOAiMiLgInNx4DMzI+AjU1BgYjIi4CNTMU
+HgIzMj4CNxEuAyMiDgIVjDtwoGVklzUJqEN5qGYqbG9nJWAiSEpKJUJqSyg2k2FjoG88uSFHbk0wTT0w
+EhIwPkwuTm9HIQImecuSUkdDdvvda6Z0PBMrSDVvKTkiDyZJbEZdPkFUlMl0T45sPxcqOiMB8CI4KRdA
+bY9PAAABAK4AAAQsBgAAFQBJthEAAgECAUpLsCFQWEAWAAQEPksAAgIAWwAAAEdLAwEBAT0BTBtAFgAC
+AgBbAAAAR0sABAQBWQMBAQE9AUxZtxETIxUiBQgZKwE2NjcyHgIVESMRNCYHIgYHESMRMwFnOqpqVYti
+Nbl/dlmRLbm5A5lVXwExaJ9t/VcCq4WCAVdI/O4GAAAAAgDLAAAEVQXDAAkAFQAtQCoABgYFWwAFBURL
+AAQEAFkAAAA/SwMBAQECWQACAj0CTCQjERERERAHCBsrEyERIRUhNSERIQE0NjMyFhUUBiMiJssCKQFh
+/HYBcP6QAVg3ODc4ODc4NwQ6/GagoAL5Ab0uPz8uLTw8AAACANP+SwNYBcMAFwAjADVAMgsBAgMKAQEC
+AkoABQUEWwAEBERLAAMDAFkAAAA/SwACAgFbAAEBSQFMJCMVRDUQBggaKwEhERQOAiMiJic3HgMzMj4C
+NREhATQ2MzIWFRQGIyImASsCIjltnWQ5YzcNETQ1MQ40XEQn/pcBTzY4ODg4ODg2BDr7v2igbTkHCpgD
+BQMBG0BpTQOgAb4tPz8tLT09AAEAsAAABGoGAAAMAEW3CgYBAwACAUpLsCFQWEARAAEBPksAAgI/SwMB
+AAA9AEwbQBcAAQEAWQMBAAA9SwACAj9LAwEAAD0ATFm2EhMREgQIGCsBBxEjETMRNwEzAQEjAfKIurp5
+AWPh/koB+esB+YP+igYA/FSCAWT+Pf2JAAEAywAABFUGAAAJAD9LsCFQWEAWAAQEAFkAAAA+SwMBAQEC
+WQACAj0CTBtAFAAAAAQBAARhAwEBAQJZAAICPQJMWbcREREREAUIGSsTIREhFSE1IREhywIpAWH8dgFw
+/pAGAPqgoKAEvwABAF0AAARyBE4AIgBxS7AbUFhADAYBAgMAHxYCAgMCShtADAYBAgMHHxYCAgMCSllL
+sBtQWEAWBQEDAwBbCAcBAwAAR0sGBAICAj0CTBtAGggBBwc/SwUBAwMAWwEBAABHSwYEAgICPQJMWUAQ
+AAAAIgAiEyMVIhMjIwkIGysBFzY2NzIXNjY3MhYVESMRNAciDgIHESMRNCYHIgYHESMRAQMFIWtMlTIg
+aUt3gLB9ITAgEgOwOj86QA+wBDpmOUABdDQ/AZKU/NgDKogBEh8pFvy/AytBRgEuJvyjBDoAAAEArgAA
+BCkETgAXAE22FAECAQIBSkuwG1BYQBMAAgIAWwUEAgAAR0sDAQEBPQFMG0AXBQEEBD9LAAICAFsAAABH
+SwMBAQE9AUxZQA0AAAAXABcTJRUjBggYKwEXNjY3Mh4CFREjETQuAiMiBgcRIxEBVA07rGpVi2I1uSA/
+WztdjSq5BDqgVF8BMGadbP1RAqtIZD4cXUz8+AQ6AAIAev/sBFIETgAVACsAH0AcAAMDAFsAAABHSwAC
+AgFbAAEBRQFMKSkpJAQIGCsTND4CMzIeAhUVFA4CIyIuAjUzFB4CMzI+AjU1NC4CIyIOAhV6RH+2cnO3
+f0REf7Zyc7d/RLkmTXRNTHNNJidNc01Nck0mAid1yZRVVZTJdRZ1yJRUVJTIdVCRbkBAbpFQFk+RbkFB
+bpFPAAACAK3+YAQ/BE4AFQAnAGJADw0BBAIfHgIFBAgBAAUDSkuwGVBYQBsABAQCWwMBAgI/SwAFBQBb
+AAAARUsAAQFBAUwbQB8AAgI/SwAEBANbAAMDR0sABQUAWwAAAEVLAAEBQQFMWUAJJSkjERMkBggaKwEU
+DgIjIiYnESMRMxc2NjMyHgIVIzQuAiMiBgcRFhYzMj4CNQQ/OGyfZmOXNrmpCTaZZWigbDi5I0lwTll5
+JCR4XE1wSCMCEXTJlFRAPP34Bdp2Q0dSkst5T49tQFNB/fdAUUFukE8AAAIAjP5gBBwETgAVACkAekuw
+GVBYQA8IAQUAHx4CBAUNAQMEA0obQA8IAQUBHx4CBAUNAQMEA0pZS7AZUFhAGwAFBQBbAQEAAEdLAAQE
+A1sAAwNFSwACAkECTBtAHwABAT9LAAUFAFsAAABHSwAEBANbAAMDRUsAAgJBAkxZQAknKSMREyQGCBor
+EzQ+AjMyFhc3MxEjEQYGIyIuAjUzFB4CMzI2NxEuAyMiDgIVjDpwo2hgkzYIqrk2kF5noXA7uSNIb01Z
+eCYTMT1JK01wSSMCJnnLklJBPmv6JgICOT1UlMl0T5BuQVBAAhYfMyYVQm+QTwABAUkAAAQxBE4AEwBo
+S7AbUFhADAUBAQARDAYDAgECShtADAUBAQMRDAYDAgECSllLsBtQWEASAAEBAFsDBAIAAEdLAAICPQJM
+G0AWAAMDP0sAAQEAWwQBAABHSwACAj0CTFlADwIAEA8ODQoIABMCEwUIFCsBMh4CFwcmJiMiBgcRIxEz
+FzY2A3MaODMrDhk2YTWCoSa6sAlCuQROAwcKBrUMC3Zq/UoEOqxZZwABAK//7AQ2BE4AOwAzQDAAAQIE
+AgEEcAAEBQIEBW4AAgIAWwAAAEdLAAUFA1sAAwNFA0w6ODQzLy0kFC4GCBcrATQuAicuAzU0PgIzMh4C
+FSM0LgIjIg4CFRQeAhceAxUUDgIjIi4CNTMeAzMyNgN9Gj5mTF2ZbTw+cJtdZKBwPbkkQFs5O1k7Hhg7
+Y0xknmw5QXSiYG6sdz+5BDVPYC91iAEfITUsJQ8TNktlQ0JzVjI0XHtHI0M0IBosOh8gMiggDxU3TWZD
+SHZULjthgEU5TjAUVgAAAQCO/+wEKQVAAB8AOUA2DwECARABAwICSgcBBgAGcgQBAQEAWQUBAAA/SwAC
+AgNbAAMDRQNMAAAAHwAfERUpJRERCAgaKwERIRUhERQeAjMyPgI3Fw4DIyIuAjURITUhEQJkAZz+ZCA4
+SSkeQD01ERoXQk5XK0h9XDX+5AEcBUD++o/9tD9SMRQHCgsEgw4VDwgpWY1kAkyPAQYAAQC0/+wEHwQ6
+ABcARLUTAQIBAUpLsBlQWEASAwEBAT9LAAICAFsEAQAARQBMG0AWAwEBAT9LAAQEPUsAAgIAWwAAAEUA
+TFm3ERMlFSIFCBkrJQYGIyIuAjURMxEUHgIzMjY3ETMRIwNsNqJqVYpiNbkcOFE1cYsiuqiVUFk1cK15
+AoP9e1h0RRxcTgMI+8YAAQBiAAAEZQQ6AAgAG0AYAQEBAAFKAgEAAD9LAAEBPQFMERETAwgXKwEXNwEz
+ASMBMwJWERIBL73+R43+Q74BCkNDAzD7xgQ6AAABADAAAASnBDoAEgAhQB4NBgEDAgABSgQBAgAAP0sD
+AQICPQJMERQRFBMFCBkrARc3EzMTFzcTMwMjAycHAyMDMwFSFhutd6wdG3ik5pKpHBunkuakAYibmwKy
+/U6qqgKy+8YCl6io/WkEOgABAG4AAARyBDoACwAfQBwJBgMDAQABSgMBAAA/SwIBAQE9AUwSEhIRBAgY
+KwEBMwEBIwEBIwEBMwJtASHZ/m0Bntb+1f7V2AGe/m3WAqkBkf3p/d0BnP5kAiMCFwAAAQBE/ksEhQQ6
+ABwAJEAhGgECAgABSgQBAAA/SwMBAgIBXAABAUkBTBYxJDUSBQgZKwEXATMBDgMjIi4CJzcyHgIzMj4C
+NzcBMwI8MAFKz/3bEztUcEkNICAcCR4HGBoYByY/MSMKSv4uzwGAgwM9+x8qXlA2AwUGApcCAgEqOj4U
+kAQHAAABAKAAAAQ9BDoACQApQCYJAQIDBAEBAAJKAAICA1kAAwM/SwAAAAFZAAEBPQFMERIREAQIGCsl
+IRUhNQEhNSEVAYwCsfxjAob9gwNwl5eIAxmZgwABAUP+kgPnBj0AKgAzQDAhAQECAUoAAwAEAgMEYwAC
+AAEFAgFjAAUAAAVXAAUFAFsAAAUATyopERkRGRAGCBkrAS4FNTU0Jic1MjY1NTQ+BDcXDgMVFQYGBxYW
+FxUUHgIXA9JBalQ9KRSJjY2JEiY7VG1FFUhVKwwBbnR0bgEUMVE+/pICKERaZ201qZCCAZGBkao1bWda
+RCgCcwJAY3w9qni1Ly61d6k+e2NAAgABAhz+cgKxBbAAAwATQBAAAQE8SwAAAEEATBEQAggWKwEjETMC
+sZWV/nIHPgAAAQFD/pID5wY9ACgAN0A0CQEEAwFKAAIAAQMCAWMAAwAEAAMEYwAABQUAVwAAAAVbAAUA
+BU8oJyAfHh0UExIREAYIFSsFPgM1NTQ2NyYmNTU0LgInNx4FFRUUFjMVBgYVFRQOAgcBQz1SMRVudHRu
+DStUSBRFbVQ7JhKKjIyKLF2OYvsCQGN7Pql3tS4vtXiqPXxjQAJzAihEWmdtNaqRgZEBgpCpUKOGVgIA
+AAEAMAGSBJwDIgAlAC5AKyUAAgECExICAAMCSgACAAEDAgFjAAMAAANXAAMDAFsAAAMATyYpJiQECBgr
+ARQOAiMiLgInJiYHIg4CFSc0PgIzMh4CFxYWNzI+AjUEnCxQbkMvUU1LKDdkOCM9LBqGLE9uQy5TTksn
+OWE4Iz0tGgLkQnpeOBIkNCItNQEdMUMmEUJ4WjUTJDQgMDMBIDVGJgACAfL+jALYBE8AAwAPADtLsBdQ
+WEAVAAICA1sAAwNHSwAAAAFZAAEBQQFMG0ASAAAAAQABXQACAgNbAAMDRwJMWbYkIxEQBAgYKwEzESMT
+FAYjIiY1NDYzMhYCCrm5zjs4OTo6OTg7AmP8KQVSLj8/LjBBQQAAAQCT/wsENwUmADEAS0BIHBkCBQMO
+CwICAAJKAAQFAQUEAXAAAQAFAQBuAAMABQQDBWMGAQACAgBXBgEAAAJZAAIAAk0BACgmIiEbGg0MBgUA
+MQExBwgUKyUyPgI3Mw4DBxUjNS4DNTU0PgI3NTMVHgMVIy4DIyIOAhUVFB4CAn8yX0otAa8BOmKDSblg
+kWAxMWCRYLlQhGA1rwEpRmE4VnVIHx9HdYIgOU0tQHVfQgzo6xJjjrBfKl+vj2MS4t4MRWaCSTFXQiZF
+b4pGKkeLb0UAAQBxAAAEfAXEACsAPkA7AAYHBAcGBHAIAQQKCQIDAAQDYQAHBwVbAAUFREsCAQAAAVkA
+AQE9AUwAAAArACsVJBQlERYRERQLCB0rARcUBgchByE1Mz4DNScjNTMDND4CMzIeAhUjNC4CIyIOAhUT
+IRUBzwgdIALiAfv6SxslFggIpaAJQ3akYGCYaTi6J0NXMDNZQCUIAUACcuJFhDCXlwc4SVEg4pgBBWai
+cTw4Zo5XP1k5GydJa0P++5gAAAIAZ//lBJIEOAAjADcAYkAgGhgSEAQDASEbDwkEAgMiCAYDAAIDShkR
+AgFIIwcCAEdLsB9QWEAVAAMDAVsAAQE/SwACAgBbAAAARQBMG0ATAAEAAwIBA2MAAgIAWwAAAEUATFlA
+CjQyKigWFCIECBUrJQYGIyImJwcnNyYmNTQ2Nyc3FzY2MzIWFzcXBxYWFRQGBxcHARQeAjMyPgI1NC4C
+IyIOAgOjPpZVVZU+aINwJigsKniDdTyPUFCQPHiEfCgsKCR0hP0nMld3RUV2VzExV3ZFRXdXMlQyNjYw
+bIdzP5NRVppBfId6LDAxLX2IgECYVVCRPneIAh5KhGM7O2OESkqEYzo6Y4QAAQAhAAAEqwWwABcAM0Aw
+CQEBCAECAwECYgcBAwYBBAUDBGEKAQAAPEsABQU9BUwXFhUUERERERESERERCwgdKwEBMwEhFSEHFSEV
+IREjESE1ITUhNSEBMwJmAXHU/lsBPv58AQGF/nu5/oQBfP6EATz+W9QDCwKl/TB5Aqd4/roBRnipeQLQ
+AAIB//7yArgFsAADAAcAJEAhAAAEAQEAAV0AAgIDWQADAzwCTAAABwYFBAADAAMRBQgVKwERMxERIxEz
+Af+5ubn+8gMX/OkDyAL2AAACAFf+EQR0BcQASQBfADlANlhNKAMEAQQBSgAEBQEFBAFwAAECBQECbgAC
+AAACAF8ABQUDWwADA0QFTDw6NjUxLyQUKgYIFysBFAYHFhYVFA4CIyIuAjU3FB4CMzI+AjU0LgInLgM1
+NDY3JiY1ND4CMzIeAhUjNC4CIyIOAhUUHgIXHgMlJiYnBgYVFB4CFxYWFzY2NzQuAgR0YlhFSUeBs21i
+u5JauTxgeDxGcE8qJlSFYGqtekJgVkJHR4C0bXK2f0W5KU5zSUtxTSYiUYZkbK16Qf3iLVElTk8kUohk
+LFAlTFYBKFaIAa9hiigwiGRYiF4xLWWleAJOa0MdIDhOLzBGOTQdHUVihl9eiykxiGRUh2AzOW2haDpn
+SywhOU4tNEg5MRweRmCFpgwZDhJkRzVKOzIcDRgOFGNHMEk8NQAAAgEfBPADqAXFAAsAFwAXQBQDAQEB
+AFsCAQAARAFMJCQkIgQIGCsBNDYzMhYVFAYjIiYlNDYzMhYVFAYjIiYBHzc2Njg4NjY3Aa43NjY4ODY2
+NwVbLT09LS08PCstPj4tLD09AAMAWv/rBIMETgAjADcATQBOQEsAAgMFAwIFcAoBBQQDBQRuAAEAAwIB
+A2MABAAABgQAYwAHBwhbAAgIR0sABgYJWwAJCUUJTAAASkhAPjQyKigAIwAjKSISKSILCBkrARQGIyIu
+AjU1ND4CMzIWFSMmJiMiDgIVFRQeAjMyNjclFB4CMzI+AjU0LgIjIg4CBzQ+BDMyHgIVFA4CIyIuAgNe
+g3Y+YEIkJEJgPnaEbgFDSCY5JhISJjkmSEIB/cFEeKNfXqN4RER4o15fo3hEVyVEYXaKS3HCj1JSj8Jx
+ccOPUgG7dHcsTWo/Vz5rTix4c0dCHjNHKFgpRjQeQkhjYq2BSkuBrGJhq4BJSYCrYU6PfWZIKFiXzHV1
+zZlYWJnNAAIBHAKzA7EFxAAiAC8AtUuwI1BYQA8UEwIBAigBBQYCAQAFA0obQA8UEwIBAigBBQYCAQQF
+A0pZS7AWUFhAHwgBBQcEAgAFAF8AAgIDWwADA0RLAAYGAVsAAQFHBkwbS7AjUFhAHQABAAYFAQZjCAEF
+BwQCAAUAXwACAgNbAAMDRAJMG0AkBwEEBQAFBABwAAEABgUBBmMIAQUAAAUAXwACAgNbAAMDRAJMWVlA
+FSQjAAArKSMvJC8AIgAiJyMkJAkIGCsBJicGBgciJjU0NjMzNSYmIyIGByc+AzMyHgIVERQWFyUyPgI3
+NSMiBhUUFgMMDwYecFR2g62ejQE+P0NRAaEBLVFyRUFrSyoMDv6LGzszJwiMT1tAAsEsNStDAXppcHc0
+QUY1NAwzVj4iI0VoRP7GMFgtexEdJBJtQjEtMf//ANQAdgPXA5ICJwF0/0j/3QEHAXQAl//dABKxAAG4
+/92wMyuxAQG4/92wMysAAQC9AXcD+wMgAAUAPkuwClBYQBYAAAEBAGcAAgEBAlUAAgIBWQABAgFNG0AV
+AAABAHMAAgEBAlUAAgIBWQABAgFNWbURERADCBcrASMRITUhA/u5/XsDPgF3AQihAAQAV//rBIAETQAT
+ACcANwBAAExASTQBBwgBSgYBBAcCBwQCcAAFAAkIBQljAAgKAQcECAdhAAMDAFsAAABHSwACAgFbAAEB
+RQFMKChAPjo4KDcoNxghFSgoKCQLCBsrEzQ+AjMyHgIVFA4CIyIuAjcUHgIzMj4CNTQuAiMiDgIFFSMR
+MzIeAhUUBgcTIycnMzY2NTQmIyNXUo/DcXHCj1JSj8JxccOPUldEeKNfXqN4RER4o15fo3hEAU5r0zdY
+PyJGQpNueH13MEY8SWgCHHXNmFdXmM11dc2XWFiXzXViq4BKSoCrYmKsf0lJf6yZ/QJ7GDBIMDhOFv7h
+/WEBLio3LAAAAQEBBSEDywWwAAMAE0AQAAAAAVkAAQE8AEwREAIIFisBITUhA8v9NgLKBSGPAAIBaQPA
+A2IFxAATACcAH0AcAAMDAFsAAABESwABAQJbAAICPwFMKCgoJAQIGCsBND4CMzIeAhUUDgIjIi4CNxQe
+AjMyPgI1NC4CIyIOAgFpKUVdNDNbRCgoRFszNF1FKXwVIzAbGy4jExMjLhsbMCMVBMA1X0cpKUdfNTVe
+RSgoRV02Gy8jExMjLxscMSQUFCQxAAACAJwAAQQwBPMACwAPACtAKAQBAAMBAQIAAWEABQACBwUCYQAH
+BwZZAAYGPQZMERERERERERAICBwrASEVIREjESE1IREzASE1IQLFAWv+laj+fwGBqAFB/L0DQwNXmP5i
+AZ6YAZz7DpcAAQE8ApsDpgW7AB4AlrUCAQAEAUpLsApQWEAaAAIBBAECBHAABAAABABdAAEBA1sAAwM8
+AUwbS7AMUFhAGgACAQQBAgRwAAQAAAQAXQABAQNbAAMDRAFMG0uwDlBYQBoAAgEEAQIEcAAEAAAEAF0A
+AQEDWwADAzwBTBtAGgACAQQBAgRwAAQAAAQAXQABAQNbAAMDRAFMWVlZtxokEicQBQgZKwEhNQE2NjU0
+JiMiBgcjND4CMzIeAhUUDgIHByEDpv2pASBBOEI6SkcBnipOb0VCakooGzNHK68BjwKbbAEPPFcjMT1L
+OjZgRykhPlc3KEdFRyeRAAABAUMCjwOfBboALwB2tRgBBwABSkuwLFBYQCwAAgEAAQIAcAAFBwYHBQZw
+AAYABAYEXwABAQNbAAMDPEsABwcAWwAAAEcHTBtAKgACAQABAgBwAAUHBgcFBnAAAAAHBQAHYwAGAAQG
+BF8AAQEDWwADAzwBTFlACyQiFC0kEiQgCAgcKwEzMjY1NCYjIgYHIzQ+AjMyHgIVFAYHFhUUDgIjIi4C
+NTMWFjMyNic0JiMjAg5URkxCQzlKAZ0tTWg8QGxOK0dBli9TcEA5a1MzngFPQURMAVdIVARlOjMtOjAs
+M1I5Hx05VDc4WhkqjjhWOh8bOVg9Ljs8Mz80AAABAZoEvwMyBckAAwDaS7AKUFhACwABAAFzAAAAPABM
+G0uwDFBYQAsAAQABcwAAAD4ATBtLsA5QWEALAAEAAXMAAAA8AEwbS7AQUFhACwABAAFzAAAAPgBMG0uw
+ElBYQAsAAQABcwAAADwATBtLsBZQWEALAAEAAXMAAAA+AEwbS7AXUFhACwABAAFzAAAAPABMG0uwGVBY
+QAsAAQABcwAAAD4ATBtLsBtQWEALAAEAAXMAAAA8AEwbS7AqUFhACwABAAFzAAAAPgBMG0AJAAABAHIA
+AQFpWVlZWVlZWVlZWbQREAIIFisBMwEjAlLg/vSMBcn+9gABALz+YAQQBDoAFgBdQAsJAQABEw4CAgAC
+SkuwGVBYQBgGBQIBAT9LAAAAAlsDAQICPUsABARBBEwbQBwGBQIBAT9LAAICPUsAAAADWwADA0VLAAQE
+QQRMWUAOAAAAFgAWEiMREyUHCBkrAREUHgIzMjY3ETMRIycGBiMiJxEjEQF1IDtRMGt9HbqnCSyBWpJS
+uQQ6/ZJkgEocUkcDH/vGdEFHSf4rBdoAAAEA0wAAA9AFsAAOAB9AHAAAAAFbAAEBPEsDAQICPQJMAAAA
+DgAOKCEECBYrIREjIi4CNTQ+AjMhEQMWV3a3fkFBfrd2ARECCEZ8rGZlq31H+lAAAAEB+AJrAt4DSQAL
+ABhAFQAAAQEAVwAAAAFbAAEAAU8kIgIIFisBNDYzMhYVFAYjIiYB+Do5ODs7ODk6AtkwQEAwLz8/AAAB
+Ac3+TQMDAAAAFQAmQCMUAQIBAgFKAwECAQJyAAEBAFwAAABJAEwAAAAVABURGAQIFishBx4DFRQGBycy
+PgI1NC4CJzcCdgwdNysanpEHIjwtGxQpPCgfNAUYKD0rYXABawsYJRsZIhUMA4YAAAEBggKZAvYFrgAG
+ABJADwUEAwIEAEgAAABpEAEIFSsBIxEHNSUzAvad1wFiEgKZAlk5gHUAAAIBEAKyA7wFxAAVACsAHEAZ
+AAIAAQIBXwADAwBbAAAARANMKSkpJAQIGCsBND4CMzIeAhUVFA4CIyIuAjUzFB4CMzI+AjU1NC4CIyIO
+AhUBEDBZfk9Pf1kvL1h+T1B/WTCjFi1ELixDLBcXLUMtLUMtFgR1SXtZMjJZe0l1SHtZMjJZe0gqRzQe
+HjRHKnUpRzUeHjVHKQD//wDxAJgD/gO1AicBdf9lAAAABwF1AL4AAP//ADAAAASNBbYALwG2/vgC7zma
+ACYBdvYIAQ8BuQFCAAA5mgARsQABuALvsDMrsQEBsAiwMysA//8AJAAABJYFsgImAXa6CAAvAbb+7ALr
+OZoBDwGVAU8AADmaABGxAAGwCLAzK7EBAbgC67AzKwD//wAlAAAErgW4AiYBdjkHAC8BuQFjAAA5mgEP
+Abj/DQLoOZoAEbEAAbAHsDMrsQMBuALosDMrAAACAMz+eAQABE0AJwAzAGVLsCpQWEAlBgEDBQEFAwFw
+AAEABQEAbgAFBQRbAAQER0sAAAACXAACAkECTBtAIgYBAwUBBQMBcAABAAUBAG4AAAACAAJgAAUFBFsA
+BARHBUxZQBAAADIwLCoAJwAnJBQsBwgXKwEOAwcOAxUUFjMyPgI1Mw4DIyIuAjU0PgI3PgM1AzQ2MzIW
+FRQGIyImAtQBCR47MR9CNyN0bStRPya5AT9ulVdhmWk3L0lbLR0gDwMeOjk5Ojo5OToCoUdcSEMtI0tS
+WjNtcxcxSzRUhl0xM2KMWkiAcWMrHTI1PCcBOzBBQTAuPz8AAAIAIAAABKsFsAAPABIAO0A4EgEFBAFK
+AAUABggFBmEACAABBwgBYQAEBANZAAMDPEsABwcAWQIBAAA9AEwRERERERERERAJCB0rISEDIQMjASEV
+IRMhFSETIQEzAwSr/e0B/sp7xgIwAkT+rwIBLv7SAQFl/PP5AgFh/p8FsJj+KZf97QF4AsIAAAEAtQDO
+BDoEYwALAAazCQMBMCsTAQE3AQEXAQEHAQG1AUr+uXcBSAFJd/64AUt3/rT+tQFJAVEBTnv+sQFPe/6y
+/q97AVH+rwAAAwBH/6MEjAXsACUANABDAD5AOx0BBAI5OCopIA0GBQQKAQAFA0oAAQABcwADAz5LAAQE
+AlsAAgJESwAFBQBbAAAARQBMLS0TLRMmBggaKwEOBSMiJicHIxMuAzU1PgUzMhYXNzMDHgMXBRYWFwEm
+JiMiDgQHISYmJwEWFjMyPgQ3BFkBGTRRcJFaW445aI6gIjIhEAEZNVFwkVpmnTtjjqEcKRsNAfy/ARcd
+AfIlb05AYkgwHQ0BAooBDxP+FSVkQkFjRy8dCwEChE6flIBgNzcwsAEOMXB4fT2mTp+UgWE3RTuo/vAv
+aW9zOKZFm0YDSzVBLk1lb3EzOoE+/MIpLy5NZW9yNAAAAgCoAAAEXgWwABAAHQA0QDEAAAcBBQQABWMA
+BAABAgQBYwYBAwM8SwACAj0CTBERAAARHREcFBIAEAAQESghCAgXKwERITIeAhUUDgIjIREjERMRITI+
+AjU0LgIjAWEBFXW1fUFBfbV1/uu5uQEVTnJLJCRKc04FsP7bP3GcXV2ccT/+xwWw/kP93i1LYjU2Y00t
+AAEAqf/rBEwGFgBDAFFACiMBAwQiAQADAkpLsBdQWEAUAAEABAMBBGMAAwMAWwIBAAA9AEwbQBgAAQAE
+AwEEYwAAAD1LAAMDAlsAAgJFAkxZQAtBPyknHhwlEAUIFishIxE0PgIzMh4CFRQOAhUUHgQVFA4CIyIu
+Aic3HgMzMj4CNTQuBDU0PgQ1NC4CIyIGBwFhuDtpkFVLgmI4KDAnLURQRC0zXH9MKVhRRBQqEjU/RSIv
+RCwVLURQRC4UHyQfFB4xPyBjdwEEP3CweD8pVH9WT2tUTTIuSkZGUmRBVX5UKgsTGhCbCxsXDxswQCYv
+TUVHU2dEJ0I7Nzs/JjJLMxqkmwAAAwAr/+wEqQROADsASABXAGpAZyEBAwVMNgIIBzcDAgAIA0oABAMC
+AwQCcAoBAgwBBwgCB2MOCQIDAwVbBgEFBUdLDwsCCAgAWwENAgAARQBMSkk9PAEAT01JV0pXQ0I8SD1I
+MjArKiUjHx0ZGBYUEQ8JBwA7ATsQCBQrBSImJw4DIyIuAjU0NjMzNTQmIyIGFSc0PgIzMhYXNjYzMh4C
+FRUhFRQeAjMyPgI3Fw4DAyIOAgcVITU0LgIBMjY3AyMiDgIVFB4CA4BnlC4TM0JQMEdsSifQxT8+RD9O
+sy1TdkhTfScrd0pRe1Qr/gcbO1xCJjsvJhAuDS5FXV0tQSoVAQFJFCg6/fAlTBwBPTVUOh8TJTcUS0cd
+NSgYLE9xRaa4lExbU0sIRW9PKzY1Mzg1YYlU6lZCaEgnDhUYC4gKHRoTA8onQlgwRYAjQTMf/MwrHQEl
+IztNKx83KRgAAgBJ/+wEKgXxACUAPQAxQC4WAQIBAUolJCMgHxwbGhkJAUgAAQACAwECYwADAwBbAAAA
+RQBMOTcvLSgoBAgWKwEWEhUVFA4CIyIuAjU0PgIzMhYXJiYnBSc3JiYnNxYWFzcXAzQmNS4DIyIOAhUU
+HgIzMj4CNQNNaHVLhrdtbLWDSEmDs2lYmTkXWj7+9knvKVcuOVCPP+ZJrwEROVBnPkVwTyoqT3NKSHNR
+LAUGdv63zj6K25lRS4SyZnO8hklEOG6oP5hjiRspEJ8WSTOEZPz8DRgNGzMnFzligkk+eV87QHOjYwAD
+AHMAsQRZBLQAAwAPABsALEApAAIAAwECA2MAAQAABAEAYQAEBQUEVwAEBAVbAAUEBU8kJCQjERAGCBor
+ASE1IQE0NjMyFhUUBiMiJgM0NjMyFhUUBiMiJgRZ/BoD5v2iNzY2ODg2NjcCNzY2ODg2NjcCWLgBOS0+
+Pi0tPDz8/i0+Pi0sPT0AAwB6/3kEUgS5AB0AKgA2AD5AOwsIAgQALy4iIQQFBBoXAgIFA0oAAQABcgAD
+AgNzAAQEAFsAAABHSwAFBQJbAAICRQJMKisTKRMkBggaKxM0PgIzMhYXNzMHFhYVFRQOAiMiJicHIzcm
+JjUzFBYXASYmIyIOAhUhNCYnARYzMj4CNXpEf7ZyOWUtSXtlXmVEf7ZyNl8rSntlY2q5MDABVh1BJk1y
+TSYCZiwt/qw3RExzTSYCJ3XJlFUVFJTNS+qQFnXIlFQTEZfNSe6UW505ArYPEUFukU9VmDn9TxpAbpFQ
+AAIArf5gBD8GFgAVACcAOkA3DQEEAx8eAgUECAEABQNKAAIDAnIABAQDWwADA0dLAAUFAFsAAABFSwAB
+AUEBTCUpIxETJAYIGisBFA4CIyImJxEjETMRNjYzMh4CFSM0LgIjIgYHERYWMzI+AjUEPzZrnGZkmji5
+uTeYZGieaja5IkduTVt8JSZ6XkxuRiICEXTJlFRBPv31B7b9tEBEUpLLeU+PbUBTQv36QVJBbpBPAAAC
+ABgAAAS8BbAAEwAXADZAMwgGAgALBQIBCgABYQAKAAMCCgNhCQEHBzxLBAECAj0CTBcWFRQTEhERERER
+EREREAwIHSsBMxUjESMRIREjESM1MxEzESERMwEhNSEEPICAr/2rrnJyrgJVr/z8AlX9qwSPj/wAAqH9
+XwQAjwEh/t8BIf2OwgAAAQDLAAAEVQQ6AAkAIUAeAAQEAFkAAAA/SwMBAQECWQACAj0CTBEREREQBQgZ
+KxMhESEVITUhESHLAikBYfx2AXD+kAQ6/GagoAL5AAIAgP/tBEwFsAADABkAT0uwG1BYQBoABAEFAQQF
+cAIBAQE8SwAFBQBbAwEAAD0ATBtAHgAEAQUBBAVwAgEBATxLAAAAPUsABQUDWwADA0UDTFlACSIUJRER
+EAYIGishIxEzITMRFA4CIyIuAjUzFBYzMj4CNQE5ubkCWrkpVYFXSXtYMrpQRC48JA8FsPuTUX9YLilU
+gFdjWhsxRywABABQ/k4ETwW/ABcAIQAtADkAT0BMCwECBgoBAQICSgwBCgoJWwsBCQlESwgBAwMAWQQB
+AAA/SwcBBQUGWQAGBj1LAAICAVsAAQFJAUw4NjIwLComJBERERERFUQ1EA0IHSsBIREUDgIjIiYnNx4D
+MzI+AjURIyUhETMVITUzESMBNDYzMhYVFAYjIiYlNDYzMhYVFAYjIiYCrgGXOW2dZDljNw0RNDYwDjRc
+RCfe/acBpN/9eO/qAxw2ODg4ODg4Nv2+Nzg3ODg3ODcEOvvBaJ9uOAcKngMFAwEZPWdNA56h/GagoAL5
+AbotPz8tLT09LC0/Py0tPT0AAAEAugAABHIEOgAMAB9AHAoGAQMAAQFKAgEBAT9LAwEAAD0ATBITERIE
+CBgrAQcRIxEzETcBMwEBIwIJlrm5bgGO3/44AezqAd2F/qgEOv3teAGb/iH9pQABADoAAARLBbAADQAm
+QCMLCgkIAwIBAAgAAgFKAAICPEsAAAABWgABAT0BTBURFAMIFysBJRUFESEVIREHNTcRMwGDAQb++gLI
+/H+QkLkDTVOiU/3ynQJwLaItAp4AAQDLAAAEVQYAABEATkANDQwLCgMCAQAIAAMBSkuwIVBYQBYAAwME
+WQAEBD5LAgEAAAFZAAEBPQFMG0AUAAQAAwAEA2ECAQAAAVkAAQE9AUxZtxEVEREUBQgZKwElBwURIRUh
+NSERBTUlESE1IQL0ASIB/t8BYfx2AXD+rQFT/pACKQPNhKKE/XWgoAI2mqKaAeehAAEAr/5LBB0FsAAa
+ADdANBkUEwMCAwoBAQIJAQABA0oFBAIDAzxLAAICPUsAAQEAWwAAAEkATAAAABoAGhEVJyUGCBgrARMU
+DgIjIiYnNx4DMzI2NTUBESMRMwERBBwBK1F2TB4zHQ4IGx0aBkFD/gW5uQH7BbD591KBWi8ICpMDBQMC
+bVdbBCv70wWw+9UEKwAAAQC4/ksEFwROACMAaUAPIAECBAMRAQIEEAEBAgNKS7AZUFhAHAADAwBbBgUC
+AABHSwAEBD1LAAICAVsAAQFJAUwbQCAGAQUFP0sAAwMAWwAAAEdLAAQEPUsAAgIBWwABAUkBTFlADgAA
+ACMAIxMlJycjBwgZKwEXNjYzMh4CFREUBgciJic3HgMzMjY1ETQmIyIGBxEjEQFeDDafalaIXjKpmh42
+Hg4JHB4aB0NHdnZefiW5BDqaUV0yZ59s/P2ntAEICp0DBQMCYFoC/498ST781gQ6AAIAT//sBKYFxAAb
+ACwA2EuwGVBYtR8BBAIBShtLsBtQWLUfAQQDAUobtR8BBAkBSllZS7AZUFhAIgAFAAYHBQZhCQEEBAJb
+AwECAkRLCggCBwcAWwEBAAA9AEwbS7AbUFhANwAFAAYHBQZhCQEEBAJbAAICREsJAQQEA1kAAwM8SwoI
+AgcHAFkAAAA9SwoIAgcHAVsAAQFFAUwbQDIABQAGBwUGYQAJCQJbAAICREsABAQDWQADAzxLAAcHAFkA
+AAA9SwoBCAgBWwABAUUBTFlZQBMeHCMgHCweLBERERESKSIQCwgcKyEhBgYjIi4CNRE0PgIzMhYXIRUh
+ESEVIREhBTI3ESYmIyIOAhURFB4CBKb+VD6ERWGbbTs6bJthRYY+AaL+cwFY/qgBl/1NMTIZMho5WDoe
+HjxYBw1DhMOAAcOAw4REDAiY/iSY/fMUAwSiAgIlVo1p/jtpj1YlAAADAC7/7ASwBE4ALABCAE8AR0BE
+CAEHABsBAwIkHAIEAwNKCgEIAAIDCAJhCQEHBwBbAQEAAEdLBgEDAwRbBQEEBEUETERDS0lDT0RPKSkk
+JyUVJCQLCBwrEzQ+AjMyFhc2NjMyHgIVFSEVFB4CMzI2NxcOAyMiJicGBiMiLgI1MxQeAjMyPgI1NTQu
+AiMiDgIVJSE1NC4CIyIOAhUuLVeAUlSALC14RlN5Tyb+NhQoPitEWyA3ES08TDBXgy0sf1NTgFgtuhEm
+PCsqOyYSEiY9Kio7JRIB/gERDyEzJSAzIxMCf2mqekJDPj9CQHKcW7VARG9QKyocfhIiGhBBPj1CQniq
+aURzUi4uUnNExkRyUy4vUnNDCFUqTj0lK05vQwABAcgAAAQLBisAEwAnQCQJAQEACgECAQJKAAAAAQIA
+AWMDAQICPQJMAAAAEwATJSUECBYrIRE0PgIzMhYXByYmIyIOAhURAcg9caBkJUclFxIuHURnRiQEZm2p
+czwMCY4FBipOcEX7mgAAAQCg/ksESgYrACkAP0A8IAEGBSEBBAYLAQIACgEBAgRKAAUABgQFBmMDAQAA
+BFkHAQQEP0sAAgIBWwABAUkBTBMlJRETJyUQCAgcKwEjERQOAiMiJic3HgMzMjY3ESM1MzU0PgIzMhYX
+ByYmIwYGBxUzA3/UMl2HVSlQJw4LKSwnC1VcAbGxOm2aYC9ZLxcaRyiCfAHUA6v8IV2QYTMQFJQICwkE
+fG0D349jYJVlNBYRkw0QAXt1YwAAAgBj/+wExgX6ACMAQQBVQAoZAQMBIAEEAwJKS7AoUFhAGgACAj5L
+AAMDAVsAAQFESwAEBABbAAAARQBMG0AaAAIBAnIAAwMBWwABAURLAAQEAFsAAABFAExZty0tFS0mBQgZ
+KwEOBSMiLgQnNT4FMzIWFzY2NzMWBgcWFhcnLgUjIg4EBxUeBTMyPgQ3BFoBGTRRcJFaWpFwUjUaAQEZ
+NVFwkVpxqT02MgGnAWReLCgCtwEMHTBIYkFAYkgwHQ0BAQ0eMEhiQUFjRy8dCwEChE6flIBgNzdggZSe
+TqZOn5SBYTdURxJsU3+oI1jKZAI0cW9lTS0uTWVvcTOoM3JvZk0uLk1lb3I0AAACAHf/7ASuBKoAHQAz
+AC9ALAgBBAAPAQMEAkoAAQABcgAEBABbAAAAR0sAAwMCWwACAkUCTCkpKxUkBQgZKxM0PgIzMhYXNjY1
+MwYGBxYWFRUUDgIjIi4CNTMUHgIzMj4CNTU0LgIjIg4CFXdEf7ZyYJ49NjOoAVtWKSpEf7Zyc7d/RLkm
+TXRNTHNNJidNc01Nck0mAid1yZRVOzURaFN5oiREpFwWdciUVFSUyHVQkW5AQG6RUBZPkW5BQW6RTwAB
+AIv/7AWDBegAIwAzQDABAQEDAUoGBQIDAzxLAAEBAFkAAAA+SwAEBAJbAAICRQJMAAAAIwAjJRUlEhYH
+CBkrARU+AzUzFAYHEw4DIyIuAicTMxMeAzMyPgI3EwRALTwkD6ecpgECRn6uaGqufEYBArAEASdJbUdH
+bEkmAgMFsLgGIjtVOLS5C/1mZrKFTUyFs2YD2vwmQXhcODddeEED2gABALT/7AU/BJMAHwBbQAkcGQYD
+BAMCAUpLsBlQWEAYBgEFAgVyBAECAj9LAAMDAFsBAQAAPQBMG0AcBgEFAgVyBAECAj9LAAAAPUsAAwMB
+WwABAUUBTFlADgAAAB8AHxMlFSMUBwgZKwEGBgcRIycGBiMiLgI1ETMRFB4CMzI2NxEzFTY2NQU/AYyT
+qAs2ompVimI1uRw4UTVxiyK6RDQEk6q0E/zelVBZNXCteQKD/XtYdEUcXE4DCI0Sb2UAAQCw/ksDKgQ6
+ABcAKUAmCwECAwoBAQICSgADAwBZAAAAP0sAAgIBWwABAUkBTBVENRAECBgrASERFA4CIyImJzceAzMy
+PgI1ESEBBAImOW2dZDljNw0RMzYxDjRbRCf+lAQ6+79ooG05BwqYAwUDARtAaU0DoAAAAgCx/+wEXwRP
+AB8AKwBDQEAbAQMAGgECAwJKAAIABQQCBWEAAwMAWwYBAABHSwcBBAQBWwABAUUBTCEgAQAmJSArISsY
+FhIRDAoAHwEfCAgUKwEyHgIVFRQOAiciLgI1NSEuAyMiBgcnPgMTMj4CNyEVFB4CAmF2vYRHToWvYHWt
+cjgC9AMsUXZOcaE2SRtLY31nOWFLMgv9yyFDaARPUZHGdSx1xo9QAUiAsWl5TIZkOj4ufRkwJhf8NS5R
+bkAaNmRMLQAAAQDBBOQDHgXtAAgAHUAaBgMAAwACAUoBAQACAHMAAgI+AkwSEhEDCBcrARUjJwcjNTcz
+Ax6alpWY9XAE/RmXlxrvAAABATAE4wObBe0ACAAbQBgGAQEAAUoAAQABcwIBAAA+AEwSEhEDCBcrATcz
+FQcjJzUzAmSXoP5y+50FVZgS+PUVAAABATsEpwORBbIAFQAeQBsAAgAAAgBfBAMCAQE8AUwAAAAVABUk
+FCQFCBcrARQOAiMiLgI1MxQeAjMyPgI1A5EqTm5ERW5OK5YSJDgoJzckEgWyO2NGJydGYzseNygYGCg3
+HgAAAQHyBOEC2AW+AAsAE0AQAAEBAFsAAABEAUwkIgIIFisBNDYzMhYVFAYjIiYB8jo5OTo6OTk6BU4w
+QEAwLj8/AAIBmgReAzEF5wATACMAHEAZAAIAAQIBXwADAwBbAAAAPgNMJigoJAQIGCsBND4CMzIeAhUU
+DgIjIi4CNxQeAjMyPgI1NCYjIgYBmiE3SyoqSTcgIDdJKipLNyFjER0mFhYlHBA7LCw+BSArSTUeHjVJ
+KytIMxwcM0grFiYdEBAcJhcwPT0AAQGO/k8DAQA4ABcAHkAbCgEBAAFKFwkCAEgAAAABWwABAUkBTCUl
+AggWKyEGBhUUFjMWNjcXBgYjIi4CNTQ+AjcC205eJCogNRAfHFVBKUY0HiNAWzgqb0IiKQETCHkQHBgw
+Ry8pU05GGwAAAQCKBOMDOgXxAB8AT0ASAAEDAhABAAECSh8BAkgPAQBHS7AWUFhAFQABAQJbAAICPksA
+AAADWwADAzwATBtAEgADAAADAF8AAQECWwACAj4BTFm2IyclJAQIGCsBFA4CIyIuBCMiBgcnND4CMzIe
+AjMyPgI1AzofNkwtITQrJicsGyw5AWgfNksuKkM/QScVJhsRBdMtUj0kDhUZFQ5BLhgtUz8mHiMeEh4p
+FwAAAgD2BOID1gXvAAMABwAXQBQDAQEBAFkCAQAAPgFMEREREAQIGCsBMwEjAzMDIwL14f7PqUrP9ZYF
+7/7zAQ3+8wAAAgGt/oYC3f+rABMAHwA/S7AbUFhAEwAAAAMCAANjAAICAVsAAQFBAUwbQBgAAAADAgAD
+YwACAQECVwACAgFbAAECAU9ZtiQmKCQECBgrBTQ+AjMyHgIVFA4CIyIuAjcWFjMyNjU0JiMiBgGtGCo4
+IB82KRgYKTYfIDgqGFYBJxwaJiYaHCfpIDcnFhYnNyAgNiYVFSY2IBsmJRwdJycAAAH8ygS8/fsGFgAD
+ABFADgABAAFyAAAAaREQAggWKwEjAzP9+36zsgS8AVoAAf1oBLz+lgYXAAMAEUAOAAABAHIAAQFpERAC
+CBYrATMDI/3qrLp0Bhf+pf///IgE4/84BfEABwCi+/4AAAAB/VkE2f6PBnQAEwAuQCsSAQMAAUoAAgAB
+AAIBYwAAAwMAVwAAAANZBAEDAANNAAAAEwATERYRBQgXKwEnNjY1NC4CIzcyFhUUDgIHB/1vAUdKGy48
+IQeQnxssOBwBBNmZBRwpFh4SCGpkWCY2JBQERwAC/AUE5P7lBe4AAwAHABdAFAIBAAABWQMBAQE+AEwR
+EREQBAgYKwEjATMBIwMz/eCp/s7hAf+W9s8E5AEK/vYBCgAB/Sf+qP4N/4UACwAYQBUAAAEBAFcAAAAB
+WwABAAFPJCICCBYrBTQ2MzIWFRQGIyIm/Sc6OTk6Ojk5OuswQEAwLj8/AAECKQT3Ay0GegADABhAFQAA
+AQEAVQAAAAFZAAEAAU0REAIHFisBMwMjAmrDqloGev59AAADARME4gPzBr8AAwAPABsAIUAeAAAAAQMA
+AWEFAQMDAlsEAQICMANMJCQkIxEQBgcaKwEzAyMFNDYzMhYVFAYjIiYlNDYzMhYVFAYjIiYCdM12h/7P
+OTk5Ojo5OTkB+zk5OTo6OTk5Br/++GcwQEAwLkBALjBAQDAuQED//wIwAmsDFgNJAgYAdjgAAAEAtQAA
+BDAFsAAFABlAFgAAAAJZAAICKEsAAQEpAUwRERADBxcrASERIxEhBDD9P7oDewUY+ugFsAACAC4AAAS0
+BbAAAwAGAB9AHAYBAgABSgAAAChLAAICAVoAAQEpAUwRERADBxcrATMBITchAQI0oAHg+3rwAqn+ugWw
++lCXBBwAAAMAav/sBGEFxAADACEAPwApQCYAAQAABQEAYQAEBANbAAMDMEsABQUCWwACAjECTC0tLScR
+EAYHGisBITUhBQ4FIyIuBCc1PgUzMh4EFycuBSMiDgQHFR4FMzI+BDcDTf4wAdABFAEZNFFwkVpakXBS
+NRoBARk1UXCRWlqScFE1GQG3AQwdMEhiQUBiSDAdDQEBDR4wSGJBQWNHLx0LAQKUl6dOn5SAYDc3YIGU
+nk6mTp+UgWE3N2CBlKBOAjRxb2VNLS5NZW9xM6gzcm9mTS4uTWVvcjQAAAEANgAABKAFsAAGABVAEgAB
+AShLAgEAACkATBEREQMHFysBASMBMwEjAmr+ib0B5KEB5b0EnPtkBbD6UAAAAwCRAAAENwWwAAMABwAL
+AClAJgACAAMAAgNhAAUFBFkABAQoSwAAAAFZAAEBKQFMEREREREQBgcaKzchFSETIRUhAyEVIZEDpvxa
+VQLy/Q5TA5b8apeXAz6YAwqYAAEAogAABCoFsAAHABtAGAABAQNZAAMDKEsCAQAAKQBMEREREAQHGCsh
+IxEhESMRIQQquf3quQOIBRj66AWwAAABAHAAAARvBbAADAAvQCwHAQMCDAYAAwADBQEBAANKAAMDAlkA
+AgIoSwAAAAFZAAEBKQFMERQREQQHGCsBASEVITUBATUhFSEBAxn+PAMa/AEB5f4bA839GQHDAs39y5iQ
+AkkCR5CY/c4AAwBFAAAEhwWwABkAJAAvACBAHSsqIB8XDQoACAABAUoAAQEoSwAAACkATBwbAgcWKwEe
+AxUUDgIHFSM1LgM1ND4CNzUzARQeAhcRDgMFNC4CJxE+AwLDYaV5RUV5pWG5YqV6RER6pWK5/jkkRWRB
+QWRFJALTJEVjQEBjRSQE4ghSirpvcLuLVAfExAdSirxwb7yKUwfO/SNQhWE7BgLuBztihE1Pg2E7B/0S
+BztihQABAGUAAARyBbAAHwAgQB0dEA0ABAEAAUoDAgIAAChLAAEBKQFMFxcXFgQHGCsBPgM1ETMRFA4C
+BxEjES4DNREzERQeAhcRMwLHN1k/I7k/cJ5euV+ccD65Ij9ZNrkB3ww4Wn1QAmb9mna3gkwL/rwBRAtM
+grd2Amb9mlB8WjgMA9AAAQBhAAAEbAXEAC8AKkAnEgACAgABSgAAAANbAAMDMEsEAQICAVkFAQEBKQFM
+ERoqERkoBgcaKyU2EjU1NC4CIyIOAhUVFhIXFSE1IS4DNTU0PgIzMh4CFRUUDgIHIRUhAqiAiC1VfE5N
+elUuAY2B/jwBBj5jRSRJh751db+HSiRDYj4BCv48wR0BIPlRdbV7QEB7tXVR+/7iHcGXL4ehsFlPi+up
+X1+p64tPWbGghy+XAAIAgf/rBIoETgAiADYAxkuwGVBYQBAhAQYDLCsCAAYQCgIBAANKG0uwIVBYQBAh
+AQYELCsCAAYQCgIBAANKG0AQIQEGBCwrAgAGEAoCAQUDSllZS7AZUFhAGQAGBgNbBwQCAwMzSwUBAAAB
+WwIBAQExAUwbS7AhUFhAHQcBBAQrSwAGBgNbAAMDM0sFAQAAAVsCAQEBMQFMG0AkAAAGBQYABXAHAQQE
+K0sABgYDWwADAzNLAAUFAVsCAQEBMQFMWVlAEQAAMjApJwAiACIpJCUlCAcYKwERFB4CMzI2NxcGBiMi
+JicGBiMiLgI1NTQ+AjMyFhc3ARQeAjMyNjcRLgMjIg4CFQPvDBUdEg8bChcfOyBLYxg2mmdilmY0NGaX
+Y2ibNjH9uxw/ZEdZdyYTMD1JK0hlPxwEOvzbJjMeDQQCihUNQ0pFSE+Lv3AVfdWbWExHf/26S4ZlPFJB
+AhMfNCYVRnebVQACAK7+gARbBcQAGgA6AH9ADggBBgMrAQUGEwEBBQNKS7AfUFhAJAgBAwAGBQMGYwAE
+BABbBwEAADBLAAUFAVsAAQExSwACAi0CTBtAJAACAQJzCAEDAAYFAwZjAAQEAFsHAQAAMEsABQUBWwAB
+ATEBTFlAGRwbAQA5Ny8tJiQbOhw6FRQRDwAaARoJBxQrATIeAhUUBgcWFhUUDgIjIiYnESMRND4CEzI+
+AjU0LgIjIg4CFREWFjMyPgI1NC4CIyM1AmthnnA9Ylh5hUR6pmJRnj66R3mhWEBePB0gPls6N19FKC2Q
+XUNrSigiQl89jwXEOWmQV1yXLyzCg2ulcjsuMv41BbFSk25A/ZYiPFQzLlZCKCdEXDX8xTU/K01rPzVm
+UTKYAAABAEf+YASWBDoACgAdQBoJBQIDAQABSgIBAAArSwABAS0BTBISEAMHFysBMwERIxEBMwEXNwPY
+vv42uv41vgFUGBoEOvv1/jEB1gQE/PBhYQAAAgB4/+wEZgYcADEARwA0QDEIAQEALAkCBAECSgAEAQMB
+BANwAAAAAQQAAWMAAwMCWwACAjECTENCODYiICckBQcWKwE0PgIzMhYXBy4DIyIOAhUUHgIXFhIVFRQO
+AiMiLgI1NTQ+Ajc3LgMTFB4CMzI+AjU1NC4CJyYOAhUBBzZjjFZQn0spFz9ITigqRTIcFzZZQ9zfRIG6
+dni7gkQ2XX9IBC9MNh4rJk94UlF2TiYtUnNHUXhQKAT1RW5MKC8mggkWEw0UJDMfFi8wMBdJ/uzPFXHB
+jlFRjsFxFVeYeFIRCxM2RVH9N02KZz09Z4pNFT99aUsMAT1pi0wAAQCL/+wEYARNADwATkBLHQEABwFK
+AAUGBwYFB3AAAgABAAIBcAAHCAEAAgcAYwAGBgRbAAQEM0sAAQEDWwADAzEDTAEAOzkxLysqJiQWFA4N
+CQcAPAE8CQcUKwEiBhUUHgIzMj4CNTMOBSMiLgI1NDY3JiY1ND4CMzIeAhcjNC4CIyIOAhUUHgIzMxUC
+apGUKE1ySkJwUS65ASdFXmx3PGy0g0hxal9pQnuvbF+rgUwBuS9OaDpLbEYhHkJoSvMB3lFdJUAvGx41
+RSc7YUs3JRErU3hOX34fI3lLTnVPKCxTd0slPy0aGi08IiU7KhaUAAABAHX+gQQvBbAAKgAlQCIBAQAB
+AUoWFQIARwAAAAFZAgEBASgATAAAACoAKikoAwcUKwEVAQ4DFRQWFxceAxUOAwcnNjY1NCYnJy4DNTQ+
+AjcBITUEL/5nRW5NKVxa3TZgRikBIzQ/HGIxMktQtVl/USYqV4ZcATL9LAWweP5VQnV4gk5jYhIyDBou
+Sz4nVk9FFlQ2VSwjOBAjEDtZelE5h5ikVwE8mAABAKT+YQQrBE4AFQBVthIBAgMCAUpLsBtQWEAXAAIC
+AFsFBAIAADNLAAMDKUsAAQEtAUwbQBsFAQQEK0sAAgIAWwAAADNLAAMDKUsAAQEtAUxZQA0AAAAVABUT
+IxUjBgcYKwEXNjY3Mh4CFREjETQmIyIGBxEjEQFLDTeqcFqOZDa6gH9liCe6BDqgVF8BLGOfc/u0BEiQ
+fU1B/NgEOgAAAwC5/+wEGAXFABUAHgAnAFFLsBBQWEAdAAQAAgMEAmEABQUBWwABATBLAAMDAFsAAAAx
+AEwbQB0ABAACAwQCYQAFBQFbAAEBMksAAwMAWwAAADEATFlACSMTIxUpJAYHGisBFA4CIyIuAjURND4C
+MzIeAhUHIRUUFjMyNjUBITU0JiMiBhUEGDluoGdmoW87Om6hZmehbjq5/hN5f392/hMB7XeAf3cCLYrX
+k01Nk9eKAVWK15VNTZXXiu+NusrKugEkgbrIyLoAAAEAuP/sBDoEOgAVAClAJgoBAQMLAQIBAkoAAwMA
+WQAAACtLAAEBAlsAAgIxAkwVJSUQBAcYKxMhExQeAjMyNjcXBgYjIi4CNREhuAIZARsvPCEtTh0pPnQ+
+SHFPKv6gBDr9CEFLJQocEYIsGiJSh2UCTQAAAQA5/+8EXAXuACoBokuwHVBYQBAMAQECKR8CAwMBAkog
+AQBHG0AQDAEBAikfAgMDASABBAADSllLsApQWEAWAAEBAlsAAgIwSwADAwBbBAEAACkATBtLsAxQWEAW
+AAEBAlsAAgIySwADAwBbBAEAACkATBtLsA5QWEAWAAEBAlsAAgIwSwADAwBbBAEAACkATBtLsA9QWEAW
+AAEBAlsAAgIySwADAwBbBAEAACkATBtLsBBQWEAWAAEBAlsAAgIwSwADAwBbBAEAACkATBtLsBJQWEAW
+AAEBAlsAAgIySwADAwBbBAEAACkATBtLsBRQWEAWAAEBAlsAAgIwSwADAwBbBAEAACkATBtLsBZQWEAW
+AAEBAlsAAgIySwADAwBbBAEAACkATBtLsBdQWEAWAAEBAlsAAgIwSwADAwBbBAEAACkATBtLsBlQWEAW
+AAEBAlsAAgIySwADAwBbBAEAACkATBtLsB1QWEAUAAIAAQMCAWMAAwMAWwQBAAApAEwbQBgAAgABAwIB
+YwAAAClLAAMDBFsABAQxBExZWVlZWVlZWVlZWbcoGSYWEAUHGSshIwEnLgMjIgYHJzY2MzIeAhcBHgMz
+MjI2NjcHBgYjIi4CJwMHAQfOAYs3DiIsNyINKA0BEjwZSGpLMQ8BagodIioYCAoJCgkCCyQMO1xJORjU
+HQQIjyNFNiEEAY4FCjZRXyj8SiE4KRgCAQKXBgkiQ2RCAit3AAEAr/53BC4FxABEACxAKUQBAAM3AQIB
+AkokIwICRwABAAIBAl8AAAADWwADAzAATEJAISgiBAcXKwEmJiMiDgIVFB4CMzMVIyIGFRQeAhcXHgMV
+DgMHJz4DNSYmJycuAzU0PgI3LgM1ND4CMzIWFwP3OXE9X4dXKSpdkWaOjt3jN117Q282X0cpASM1Phth
+GCQZDQFOTTpyuoRIL1l+T0FmRyZLjch+R4wwBQgPFR4zRCczUTkemJylRGZKLgwZDRktSj0nVE9EFlQb
+KiktHSwrEQ0WQWeacEx+YkgWFTtKVzFTgFgtFhEAAAEAWf/tBKkEOgAbAGtLsBtQWEAKCgEBAAsBAgEC
+ShtACgoBAQALAQQBAkpZS7AbUFhAGAUDAgAABlkABgYrSwABAQJbBAECAjECTBtAHAUDAgAABlkABgYr
+SwAEBClLAAEBAlsAAgIxAkxZQAoREREVJSUQBwcbKwEjERQeAjMyNjcXBgYjIi4CNREhESMRIzUhBEyP
+EBwlFhoxESkvVy85Wj0g/pK5hAPzA6H9aywzHAgQCYIgEx5FclQCi/xfA6GZAAACAKX+YARGBE4AFgAu
+AC9ALCQBBAMIAQAEAkoAAwMCWwACAjNLAAQEAFsAAAAxSwABAS0BTCspJhMkBQcZKwEUDgIjIiYnESMR
+NTQ+AjMyHgIVIzQuAiMiDgQVER4DMzI+AjUERjZpm2Zqozu5SX+pYHWvczm5HkJqTTFQPi0dDxM0Q1Qz
+TG1FIAH0cL+LTkRA/fAD4QF/xIVEWJvUflWcdkYgOEpTVyn+2yE5KRc7ZoZLAAABAHj+WQQwBE4AMwAm
+QCMhIAIBRwABAgFzAAICAFsDAQAAMwJMAQAMCgYFADMBMwQHFCsBMh4CFSM0LgIjIg4CFRUUHgIXHgMV
+DgMHJz4DNTYmJy4DNTU0PgICZmSoeUWvJEZqR1F1SyMrWYhcVopiNAEuSVotTRY2LyABcGyCxINDQn63
+BE41ZZJdMlhBJkVvikYqRHtiRQ0MIThXQjtjUDwUewofLTwoMzEOE1iFr2kqbMOVWAAAAgBt/+wEhgQ6
+ABYALAAhQB4EAQAAAlsAAgIrSwADAwFbAAEBMQFMKSUpKBAFBxkrASEWFhUVFA4CIyIuAjU1ND4CMyEB
+FB4CMzI+AjU1NC4CIyIOAhUEhv7lYWdBe7Ryc7R8QUF8s3ICN/ygJElxTUxwSiMkSXFNTHBJJAOhSNOE
+F2O4jlZUlMh1FnDDjlL911CRbkBAbpFQFkyJaD09aIlMAAABAK3/6wQyBDoAGQArQCgKAQEACwECAQJK
+AwEAAARZAAQEK0sAAQECWwACAjECTBEVJyUQBQcZKwEhAxQeAjMyNjcXDgMjIi4CNREhNSEEMv6dARss
+OiEsTRspHjs6Ox5Ib00o/pgDhQOc/ahASyYLGxGDFhsPBiRTh2UCTp4AAAEAnv/sBD8EOgAfACFAHgQD
+AgEBK0sAAAACWwACAjECTAAAAB8AHykXJQUHFysBERQeAjMyPgI1JgInMx4DFRQOAiMiLgI1EQFXJkZj
+PE1uRyIDRTTDFykgEjRwsn5uq3Y+BDr9lVl+USVNe5pOhgEFfTBxgpNSctOhYDp3t30CaQACAG7+IgR3
+BDoAJQAzAC1AKgkBAgAmIxMABAECAkoIAQBIAAECAXMAAgIAWwAAACsCTDEvJSQaGAMHFCsFLgM1NBI3
+Fw4DBxQeAhcRND4CMzIeAhUUDgIHESMTPgM1LgMjIgYHAg1xnWQte4BlLT4nEwIZNlg/Hj1eQE6GZDkw
+aKR1ublDXjwbAhctRC4hHgEOD2eXvWaqARNbhSliaWw0QIBtUxICtDBZRSlUkcVwZbyYZw/+MQJrElJv
+gT9Gim1EMCcAAQBh/igEgAQ6ACMAJkAjIhUSAQQBAAFKAAEBAFkEAwIDAAArAUwAAAAjACMXGRkFBxcr
+ARE+AzUmAiczFhIVFA4CBxEjES4DNREzERQeAhcRArxJZj8dAjEmwyAvMGusfbljm2w4uSE9VjUEOvxS
+ElZ1ikSGAQB9X/8ApGvGnmkO/jcByw5YmNeMAeb+GGecb0MPA6wAAQBP/+wEiQQ6ADAANEAxJQEAAQFK
+AAEDAAMBAHAHBgIDAytLAgEAAARcBQEEBDEETAAAADAAMCQnFyMTJwgHGisBBgIHFB4CMzI2NREzERQW
+MzI+AjUmAiczFhIVFA4CIyImJwYGIyIuAjU0EjcBcS06AgwdLiJDS7pLQiIvHQwCOi3CKDgeRnJTWnog
+IXlaU3JGHjgoBDp+/vuHVJt4R6avASv+1a+mR3acVYcBBX5h/vylb9GiYm1mZm1iotFvpQEEYQAAAgCY
+/+wEmQXGAC0AOgCHQA4tAQEEMyoZAgAFAgECSkuwEFBYQB0AAQQCBAECcAAEBANbAAMDMksAAgIAWwAA
+ADEATBtLsBdQWEAdAAEEAgQBAnAABAQDWwADAzBLAAICAFsAAAAxAEwbQB0AAQQCBAECcAAEBANbAAMD
+MksAAgIAWwAAADEATFlZQAk4Ni0lFScFBxgrAQYHFRQOAiMiLgI1ETcRFB4CMxY2NTUuAzU1ND4CMzIe
+AhURNjY3ARQeAhcRNCYjIgYVBJlDTT5wn2JmpnVBuiREYj52gG6zf0YyWHpKT35WLiNEIP2UKE1wR0pO
+Q1ECcxgIoG2qdDxBd6hnAU4C/rBFb00pAZWWphBah65kD1GBWi8zYIpY/p8DDQgBUj9yXEIQAVZtallk
+AAEANgAABKQFuwAkAIBADxkIAgEAIxgSDwkFAgECSkuwClBYQBIDAQEBAFsEAQAAKEsAAgIpAkwbS7AM
+UFhAEgMBAQEAWwQBAAAwSwACAikCTBtLsA5QWEASAwEBAQBbBAEAAChLAAICKQJMG0ASAwEBAQBbBAEA
+ADBLAAICKQJMWVlZtyQkFCQkBQcZKwE+AzMyFhcHJiMiBgcBESMRASYmIyIHJzY2MzIeAhcTFzcDORo4
+P0YoHDUbFg4eIzsS/ti4/tYSOyMdDhcbNR0nRj85GrMYGATXP1g2FwcRlQkmKP17/bwCQAKJJycJlREH
+FzZYP/5pWFgAAgAu/+wElgQ6ABoANAA2QDMMAQYHAUoABwAGAAcGcAUDAgAABFkABAQrSwgBBgYBWwIB
+AQExAUwjEycUERckJxAJBx0rASMWFhUUDgIjIiYnBgYjIi4CNTQ2NyM1IQMmJichBgYHFB4CMzI2NTUz
+FRQWMzI+AgSWfiAqHUFrTlp6ICB5Wk5rQR0pIWkEaO4CLyb+DSYvAgoYJx5DSrpKQx0nGAoDoWr7jFmj
+fUttZ2ZuS32jWYz7apn9dXz9eXn9fDttUzKmr/v7r6YxUm4AAAEAKv/1BHwFsAAfANNLsApQWEAfAAEA
+BAMBBGMGAQAAB1kABwcWSwADAwJbBQECAhcCTBtLsAxQWEAfAAEABAMBBGMGAQAAB1kABwcWSwADAwJb
+BQECAh4CTBtLsA5QWEAfAAEABAMBBGMGAQAAB1kABwcWSwADAwJbBQECAhcCTBtLsCxQWEAfAAEABAMB
+BGMGAQAAB1kABwcWSwADAwJbBQECAh4CTBtAIwABAAQDAQRjBgEAAAdZAAcHFksABQUXSwADAwJbAAIC
+HgJMWVlZWUALERERRhEWQRAIBhwrASERNjYzMh4CFRQGIycyPgI1JiYjIgYHESMRITUhBD3+AB49H2yp
+dDzKwAI6UTEWAYGJIDweuP6lBBMFGP45AgRAdqtqxtGRJURhPIueBAL9UQUYmAABAIH/7ARrBcUALwBB
+QD4AAgMEAwIEcAgBBwUGBQcGcAAEAAUHBAVhAAMDAVsAAQEdSwAGBgBbAAAAHgBMAAAALwAvJREVJBQp
+JAkGGysBDgMjIi4CNRE0PgIzMh4CFyMuAyMiDgIVFSEVIRUUHgIzMj4CNwRrCkh9sHJ1u4NGRoO7dXKw
+fUgKuQosSm1LT3dRKQI7/cUpUXdPS21LKwoBt2WpekNXndmDATmD2pxXP3itbkt2UCpDdaFeS5hYX6F2
+QydNc00AAAIAHgAABJ0FsAAcACkAOkA3AAAJAQcEAAdjAAICBVkIAQUFFksGAQQEAVsDAQEBFwFMHR0A
+AB0pHSggHgAcABwhJREoIQoGGSsBETMyHgIVFA4CIyERIwMUAgYGIyM1MzISExMBETMyPgI1NC4CIwLr
+W1SBViwsVoFU/uzFAR9GdFUgFkg3AQMCNFssPSURESY9KwWw/cdFd6JeXqJ3RAUY/ey4/uHGZ5cBOwEy
+Aqz9L/24M1NpNzZoUjIAAgCDAAAEiwWwABYAIwBfS7AjUFhAHQIBAAkIAgQHAARjBgEBARZLAAcHA1wF
+AQMDFwNMG0AjAAIJAQgEAghjAAAABAcABGEGAQEBFksABwcDXAUBAwMXA0xZQBEXFxcjFyIiERERKCER
+EAoGHCsBMxEzETMyHgIVFA4CIyMRIxEjETMBETMyPgI1NC4CIwE7+rgxW4lbLi5biVvp+ri4AbIxM0Ur
+EhMqRTMDOQJ3/Zc+b5haWptyQQKh/V8FsPz//fItSl8zM15ILAAAAQBDAAAEaAWwABoAMUAuAgEDARQB
+AgMCSgABAAMCAQNjBQEAAAZZAAYGFksEAQICFwJMERESJRUjEAcGGysBIRE2NhcyHgIVESMRNC4CIyIH
+ESMRITUhBED+Fhw2GmOdbDq5HDtZPTg0uf6mA/0FGP48BAQBLmKYav43AclEXzwbBv1DBRiYAAEAov6Z
+BCoFsAALACNAIAAEAwRzAgEAABZLAAEBA1oFAQMDFwNMEREREREQBgYaKxMzESERMxEhESMRIaK5Aha5
+/p25/pQFsPrnBRn6UP6ZAWcAAAIAogAABEwFsAAQAB0AL0AsAAEGAQUEAQVjAAAAA1kAAwMWSwAEBAJb
+AAICFwJMERERHREcIhEoIRAHBhkrASERITIeAhUUDgIjIREhAREhMj4CNTQuAiMEHf0/AQp0tXxBQXy1
+dP48A3v9PwEKTnFKIyNKcU4FGP5BPG+cYWCgcj8FsP0S/dUuTmc5OGNJKwAAAgBG/pkEeAWwABAAFwAr
+QCgCAQADAFEABwcEWQAEBBZLBgUCAwMBWQABARcBTBEUERYREREQCAYcKwEjESERIwMzPgM3EyERMwEG
+AgchESEEZqf9P50bQS5GMh4FIAKJf/2TCUJAAcD+4f6bAWX+mQH+HnGv8qACSfrnAtDy/pNxBIEAAQAd
+AAAErgWwABUAMUAuEwgCAAUBSgcBBQIBAAEFAGEIBgIEBBZLCQMCAQEXAUwVFBERERESEREREAoGHSsB
+IxEjESMDIwEDMxMzETMRMxMzAwEjAvs2tz7N5gEN5teuRbc+rdjoAQ7lAov9dQKL/XUC1wLZ/XMCjf1z
+Ao39Kf0nAAEAWf/rBHAFxAA6AE5ASxsBBwABSgACAQABAgBwAAUHBgcFBnAIAQAABwUAB2MAAQEDWwAD
+Ax1LAAYGBFsABAQeBEwBADk3Ly0pKCQiFBIODQkHADoBOgkGFCsBNjY1NC4CIyIOAhUjND4CMzIeAhUG
+BgcWFhUUDgIjIi4CNTMUHgIzMj4CNTQuAiMjNQJnn5opUnpSP3BSMblPh7Jjc72HSgF/bn2HUY/Ec1+3
+kFq6MFZ4SFGBWzAtVn1PtwMyAYdwN15GKCVDXDZdlWc4NGicZmekMCqqgWefbTgxaKFvOWRKKyhIZDxF
+Y0EfmAABAKIAAAQqBbAACQAeQBsJBAIBAAFKAwEAABZLAgEBARcBTBESERAEBhgrATMRIxMBIxEzAwNx
+ubkB/em5uQEFsPpQBDH7zwWw+9AAAQAvAAAEKwWwABEAJ0AkAAEBBFkFAQQEFksAAwMAWwIBAAAXAEwA
+AAARABEhJRERBgYYKwERIxEhAxQOAiMjNTMyEhETBCu5/lsCJlWKZDMoZlUEBbD6UAUY/ZCi/a5blwEN
+AQQDCAABACv/6wS1BbAAGgAnQCQYDQEDAgAMAQECAkoDAQAAFksAAgIBXAABAR4BTBYnJRIEBhgrARcB
+MwEOAyMiJic3HgMzMj4CNzcBMwIvRwFo1/3pFztUd1NEaRoYDSUrKxMuRjQkDSr+DtAC978DePtANF9I
+KhgLjQMJCAUbLDgcVQQ+AAABAKb+oQS0BbAACwAjQCAABAEEUgIBAAAWSwMBAQEFWgAFBRcFTBERERER
+EAYGGisTMxEhETMRMwMjESGmuQIJuZMSpvyqBbD65wUZ+uz+BQFfAAABAKsAAAQnBbAAGQAvQCwYAQMC
+AwEBAwJKAAMAAQADAWMFBAICAhZLAAAAFwBMAAAAGQAZJRUlEQYGGCsBESMRDgMjIi4CNREzERQeAjMy
+NjcRBCe5IUJHUTBhmGg3uRs3VDlTkEgFsPpQAlsMEg4HMWyqeQHI/jhVcUUdHRgCuwAAAQB9AAAEUAWw
+AAsAJUAiBgUDAwEBFksCAQAABFoABAQXBEwAAAALAAsREREREQcGGSsBETMRMxEzETMRIREBNtW41bj8
+LQWw+ucFGfrnBRn6UAWwAAABAH3+oQSqBbAAEQAtQCoABQAFUggHAwMBARZLBAICAAAGWgAGBhcGTAAA
+ABEAERERERExEREJBhsrAREzETMRMzUzETMRMwMjESERATbVuJVAuFoSpfyKBbD65wUZ+ucBBRj66P4J
+AV8FsAACADIAAAR5BbAAEAAdAC9ALAABBgEFBAEFYwADAwBZAAAAFksABAQCWwACAhcCTBERER0RHCIR
+KCEQBwYZKxMhETMyHgIVFA4CIyERIQERMzI+AjU0LgIjMgHqkG+sdT09daxv/rf+zwHqkEloQx8fQ2hJ
+BbD9qT1vnGBfn3NABRj9qv3VL05nODdjSisAAwCQAAAESwWwAA4AEgAfAC1AKgAABwEGBQAGYwQBAgIW
+SwAFBQFcAwEBARcBTBMTEx8THiIREREoIAgGGisBMzIeAhUUDgIjIREzASMRMwERMzI+AjU0LgIjAUlc
+X5FjMjJjkV/+67kDArm5/P5cN04wFhYxTTcDWT1vnV9fn3NABbD6UAWw/RL91S9PZjg3YkosAAIAqAAA
+BFEFsAAOABsAKUAmAAAFAQQDAARjAAICFksAAwMBXAABARcBTA8PDxsPGiIRKCAGBhgrASEyHgIVFA4C
+IyERMxERITI+AjU0LgIjAWEBCnS1fEFBfLV0/j25AQpOcUojI0pxTgNZPG+cYWCgcj8FsP0S/dUuTmc5
+OGNJKwABAHL/7ARTBcUALwBBQD4ABAMCAwQCcAgBBwEAAQcAcAACAAEHAgFhAAMDBVsABQUdSwAAAAZb
+AAYGHgZMAAAALwAvKSQUJREVJAkGGysBHgMzMj4CNTUhNSE1NC4CIyIOAgcjPgMzMh4CFREUDgIjIi4C
+JwErASdKbUdOelQt/hwB5CxUek9HbUonAbkBQ32wbnW+hklJhr51brB9QwEB0Ux7VzBAcp5eWpddXp9y
+QDBXfUxlsoRMVJnXg/60g9aZVEV/s24AAAIAd//sBGoFxAAdADEAX0uwGVBYQB8ABAABBwQBYQAGBgNb
+BQEDAxZLAAcHAFsCAQAAHgBMG0AnAAQAAQcEAWEAAwMWSwAGBgVbAAUFHUsAAgIXSwAHBwBbAAAAHgBM
+WUALKSclERERFSQIBhwrARQOAiMiLgI1NSMRIxEzETM1ND4CMzIeAhUnNCYjIg4CFREUHgIzMj4CNQRq
+LlyJWlaCVyxyublyK1eCVluJXC65UWQtPiYQECY+LjJFKhMCA3/HiUhIicd/ev2DBbD9ZJh/x4pISIrH
+fwK8vC9ejV7+VV+OXi8vXo5fAAIAQQAABCYFsAAPABwAM0AwBQEABAFKAAQAAAEEAGEABQUCWwACAhZL
+BgMCAQEXAUwAABkXFhQADwAPKBERBwYXKyERIQEjASYmNTQ+AjMhEQEUHgIzMxEjIg4CA23+yv7PxQFV
+jJRHhb11AbL9CSlQeE7/+VB5UioCX/2hApIzvItknWs4+lAEDjtmSyoCICVFYwACAIH/7ARHBhEALgBE
+ADhANSoBBAMBSgACAAJyBQEABgEDBAADYwAEBAFbAAEBHgFMMC8BADs5L0QwRB4dDAoALgEuBwYUKwEy
+HgIVFRQOAiMiLgI9AzQSNjY3PgM1MxQOBAcOAwc+AxciDgIVFRQeAjMyPgI1NTQuAgKGaqZ0PUF8s3Jy
+tHxCRX+1bzVbQyaYHTNFUFgsRnpgQg8gTlpmFUxwSSQkSXFNTG9KJCRKcQP8S4OzaRdxwI5QUI7AcRcH
+RbUBE8FzFQoXIzUpQl5BKRwSCg81WoNcJT8tGZg3XXpEF0yJZz09Z4lMF0R6XTcAAAMApAAABDAEOgAU
+AB0AJgA+QDsKAQMEAUoABAcBAwIEA2MABQUAWwAAABhLAAICAVsGAQEBFwFMFRUAACYkIB4VHRUcGBYA
+FAATIQgGFSszESEyHgIVFAYHHgMVFA4CIwERITI2NTQmIyUzMjY1NCYjI6QBqWSkdT9aVjRQNxw6bJlf
+/swBNHB0dW/+zPF8hYd87wQ6JEhwTU12IAwxQlAsTXNNJgHb/rpUUE5UlEpOUUwAAAEAtwAABCoEOgAF
+ABlAFgAAAAJZAAICGEsAAQEXAUwRERADBhcrASERIxEhBCr9R7oDcwOh/F8EOgACADb+wgSaBDoAEAAZ
+ADNAMAQBAgECUQAHBwBZAAAAGEsGCAUDAQEDWQADAxcDTAAAGRgXFgAQABARERERFgkGGSs3PgM3EyER
+MwMjESERIwMBDgMHIREhnCs7JhcHEAK5ixKn/Q2mEgHJBQ8WIRgBuv6ylwZPiLx0AZb8Xf4rAT7+wgHV
+Ag1UmIVwLAL4AAABABEAAASsBDoAFQAxQC4TCAIABQFKBwEFAgEAAQUAYQgGAgQEGEsJAwIBARcBTBUU
+ERERERIREREQCgYdKwEjESMRIwMjAQEzEzMRMxEzEzMBASMC9Tq5O9ffASn++ta9O7k7vtb++AEq4AHW
+/ioB1v4qAjMCB/5AAcD+QAHA/fn9zQABAIf/7QRKBE0APABOQEsbAQcAAUoAAgEAAQIAcAAFBwYHBQZw
+CAEAAAcFAAdjAAEBA1sAAwMfSwAGBgRbAAQEHgRMAQA7OTEvKyokIhQSDg0JBwA8ATwJBhQrATI2NTQu
+AiMiDgIVIz4DMzIeAhUUBgcWFhUUDgIjIi4ENTMUHgIzMj4CNTQuAiMjNQJ8gIAjQ2RBOmhPL7kBTYGr
+X2SmeEJqW2dzSYCsZDx3bF5FKLkuUnBBQGpLKSZIZj/xAnZRSyI8LRoaLT8lS3dTLChPdU5LeSMffl9O
+eFMqESQ3S2E7J0U1HxswQCUuQSkSnAABAKUAAAQnBDoACQAeQBsJBAIBAAFKAwEAABhLAgEBARcBTBES
+ERAEBhgrATMRIxEBIxEzEQNuubn977i4BDr7xgMe/OIEOvzhAAEApAAABJUEOgAMACdAJAoBAAMBSgAD
+AAABAwBhBAECAhhLBQEBARcBTBIREREREAYGGisBIxEjETMRMwEzAQEjAg2wubmgAZPh/jAB9OsBzf4z
+BDr+NgHK/ff9zwABADcAAAQmBDoAEwAnQCQAAQEEWQUBBAQYSwADAwBbAgEAABcATAAAABMAEyElEREG
+BhgrAREjESEDFA4CIyM3NzI+AjUTBCa6/nIBJFSOajYDKTlLKxECBDr7xgOh/sqU5p5TpQE5capxAc8A
+AAEAiQAABCkEOgAMACBAHQgFAgEAAUoEAQAAGEsDAgIBARcBTBESEhERBQYZKyUTMxEjEQMjAxEjETMC
+XObnudSA2rnv9QNF+8YCm/1lArP9TQQ6AAEApQAABCcEOgALACFAHgAEAAEABAFhBQEDAxhLAgEAABcA
+TBEREREREAYGGishIxEhESMRMxEhETMEJ7n98Lm5AhC5Ac7+MgQ6/isB1QAAAQClAAAEJwQ6AAcAG0AY
+AAEBA1kAAwMYSwIBAAAXAEwREREQBAYYKyEjESERIxEhBCe5/fC5A4IDofxfBDoAAAEAaAAABHsEOgAH
+ABtAGAIBAAADWQADAxhLAAEBFwFMEREREAQGGCsBIREjESE1IQR7/lC6/lcEEwOk/FwDpJYAAAMAev5g
+BFIGAAAbACcAMwAgQB0uLSIhFhMIBQgBAAFKAAABAHIAAQEaAUwdFgIGFisTND4CNxEzER4DFRUUDgIH
+ESMRLgM1JTQuAicRPgM1IRQeAhcRDgMVejZnlF25XpVoNjdnlV65XZRnNgMfGzZRNjZRNhv9mho1UDY1
+UDUbAidouI9fEQG6/kYQYI+4aBZpt49fD/5sAZUQX463aBZCfGZKEvzoEkpmfERDe2ZKEgMWEktme0IA
+AAEAqv6/BJAEOgALACNAIAAEAQRSAgEAABhLAwEBAQVaAAUFFwVMEREREREQBgYaKxMzESERMxEzAyMR
+Iaq5AfK6gRKm/NIEOvxdA6P8Xf4oAUEAAAEAjQAABCcEOgAVAClAJhMBAwICAQEDAkoAAwABAAMBYwQB
+AgIYSwAAABcATBMjFSMQBQYZKyEjEQYGIyIuAjURMxEWFjMyNjcRMwQnuUSRVWSicz65AYN6UZRFuQGL
+ERIyZZlnATv+xYV6EhECFwABAIEAAARMBDoACwAlQCIGBQMDAQEYSwIBAAAEWgAEBBcETAAAAAsACxER
+ERERBwYZKwERMxEzETMRMxEhEQE60LnQufw1BDr8XQOj/F0Do/vGBDoAAAEAdv6/BJgEOgARAC1AKgAF
+AAVSCAcDAwEBGEsEAgIAAAZaAAYGFwZMAAAAEQARERERETEREQkGGysBETMRMxEzNTMRMxEzAyMRIREB
+L9C5mja5VxKl/JUEOvxdA6P8XQEDovxe/icBQQQ6AAIAOQAABHcEOgAQAB0AL0AsAAEGAQUEAQVjAAMD
+AFkAAAAYSwAEBAJbAAICFwJMERERHREcIhEoIRAHBhkrEyERMzIeAhUUDgIjIREhAREzMj4CNTQuAiM5
+AeXIYJZmNTVmlmD+f/7UAeXIOlE0GBg0UjkEOv5mMlh6SEh8WzUDov5n/o4eM0IjIkM1IgADAJAAAAQ/
+BDoADgASAB8ALUAqAAAHAQYFAAZjBAECAhhLAAUFAVwDAQEBFwFMExMTHxMeIhERESggCAYaKwEzMh4C
+FRQOAiMhETMBIxEzAREzMj4CNTQuAiMBSWNXh1svL1uGWP7kuQL2ubn9CmMvQikTEylCLwKgMll6R0d8
+XDUEOvvGBDr9z/6OHzNBIyFDNiIAAgClAAAEQAQ6AA4AGwApQCYAAAUBBAMABGMAAgIYSwADAwFcAAEB
+FwFMDw8PGw8aIhEoIAYGGCsBITIeAhUUDgIjIREzEREhMj4CNTQuAiMBXgFLYZdoNzZomGH9/LkBSzpU
+NhkaNlM6AqAxWHpJSH1bNAQ6/c/+jh4yQiQjQzUhAAEAgf/sBDoETgAtAEhARQABAAcAAQdwAAQGBQYE
+BXAABwAGBAcGYQgBAAACWwACAh9LAAUFA1sAAwMeA0wBACkoJyYiIBwbFxUMCgYFAC0BLQkGFCsBIg4C
+FSM0PgIzMh4CFRUUDgIjIi4CNTMUHgIzMj4CNyE1IS4DAjwyYEsusEp7oFZ/wH9AQIC/f2CidkOwKkhh
+OFR2TScF/lMBqwYqTHQDtiA5TS5JhGQ7WJTEbCpsxJVXPGmPUzJYQSY7YXxBmD90WjYAAgBx/+wEgQRO
+ABsAMQBfS7AZUFhAHwAAAAMGAANhAAcHAVsFAQEBH0sABgYCWwQBAgIeAkwbQCcAAAADBgADYQAFBRhL
+AAcHAVsAAQEfSwAEBBdLAAYGAlsAAgIeAkxZQAspJRERFCkkEAgGHCsBMz4DMzIeAhUVFA4CIyIuAicj
+ESMRMwEUHgIzMj4CNTU0LgIjIg4CFQEqggcyWoBVXYpaLCxZiV1Xg1oxBoG5uQE6EClENTRFKBERKUU1
+NEQoEAJvZq+BSVaWyXIWcsmUVkuEtGj+KQQ6/ddOkW5CQm6RThZOkG9CQm+QTgACAE8AAAQhBDoADwAc
+ADNAMAcBAQQBSgAEAAEABAFhAAUFA1sGAQMDGEsCAQAAFwBMAAAZFxYUAA8ADhEREQcGFysBESMRIQEj
+ASYmNTQ+AjMDFB4CMyERISIOAgQhuf6w/v/IARFocDlqmmDjGDNMNQFa/r05VjgcBDr7xgGl/lsBwSaf
+akh5VzL+tCJAMR4BZx8zQQAB/+n+SwQlBgAALwBJQEYlAgIFBBQBAwUTAQIDA0oJAQcGAQABBwBhAAQE
+AVsAAQEfSwAICAVZAAUFF0sAAwMCWwACAiECTC8uEREREycnKSMQCgYdKwEhETY2NzIeAhUVMxEUBiMi
+Jic3HgMzMjY1NSMRNCYHIgYHESMRIzUzNTMVIQJm/vk6qmpVi2I1AamaIDYeDwgcHhsIQkgBf3ZZkS25
+vb25AQcEuf7gVV8BMWifbeP94ai0BwqUAwUDAmlbWQKrhYIBV0j87gS5l7CwAAABAI//7AQzBE4ALQBI
+QEUABAUGBQQGcAABBwAHAQBwAAYABwEGB2EABQUDWwADAx9LCAEAAAJbAAICHgJMAQApKCcmIiAcGxcV
+DAoGBQAtAS0JBhQrJTI+AjczDgMjIi4CNTU0PgIzMh4CFSMuAyMiDgIHIRUhHgMCezJfSi0BrwFJep5W
+e7h7Pj57uHtgoXVCrwEpRmE4Tm5JJgUBmv5mBSZIb4IgOU0tSINjO1iVw2wqa8SVWD1pkFIxV0ImOV15
+P5hAeV04AAIAJgAABLAEOgAeACsAOkA3AAAJAQcEAAdjAAICBVkIAQUFGEsGAQQEAVsDAQEBFwFMHx8A
+AB8rHyoiIAAeAB4hJREoIQoGGSsBETMyHgIVFA4CIyMRIxEUDgIjIzc3Mj4CNREBETMyPgI1NC4CIwMI
+QleGWi8vWoZX+8IfSXhaLQQeKTYgDQI0Qi9BKRISKUEvBDr+ZDJZeUhHe1s1A6H+ypLmn1SbAT12rHAB
+z/3M/o8jNkQiIUAyHwAAAgCCAAAEkgQ6ABYAIwAxQC4CAQAJCAIEBwAEYwYBAQEYSwAHBwNcBQEDAxcD
+TBcXFyMXIiIREREoIREQCgYcKwEzETMRMzIeAhUUDgIjIREjESMRMwERMzI+AjU0LgIjATv5uVNSf1Us
+LFV/Uv70+bm5AbJTKjokEBAkOioCoQGZ/mMyWXlHR3tbNQIK/fYEOv3M/o8jNkQiIUAyHwABABwAAAQr
+BgAAHQA2QDMTAgICAwFKCAEGBQEAAQYAYQADAwFbAAEBH0sABwcCWQQBAgIXAkwREREREyMVIxAJBh0r
+ASERNjY3Mh4CFREjETQmByIGBxEjESM1MzUzFSECmf7NOqpqVYtiNbl/dlmRLbmRkbkBMwS+/ttVXwEx
+aJ9t/VcCq4WCAVdI/O4EvperqwAAAQCl/pwEJwQ6AAsAKUAmAAMCA3MGBQIBARhLAAAAAloEAQICFwJM
+AAAACwALEREREREHBhkrAREhETMRIREjESERAV4CELn+nrn+mQQ6/F0Do/vG/pwBZAQ6AAABAGv/7AR/
+BbAAJAAtQCoJAQADAUoHBgQDAgIWSwUBAwMAWwEBAAAeAEwAAAAkACQjEyMVJCUIBhorARMUDgIjIiYn
+BgYjIi4CNRMzExQWMzI2NRMzERQWMzI2NRMEfgErTm1CTnQgIHRNQ21OKwG4ATs0PEUBv0U9NDoBBbD7
+jlJ+VixKSUhLLFZ+UgRy+45YZGRYBHL7jlhkZFgEcgAAAQBf/+sEegQ7ACQALUAqCQEAAwFKBwYEAwIC
+GEsFAQMDAFsBAQAAHgBMAAAAJAAkIxMjFSQlCAYaKwERFA4CIyImJwYGIyIuAjUTMxEUFjMyNjURMxMU
+FjMyNjURBHorT25CTnUhIHROQ25OLAG5PDU8R78BRj00PQQ7/QFSflUsSklISyxVflIC//0BWGJiWAL/
+/QFYYmJYAv8AAgAcAAAEPAYYABYAIwA3QDQABQQFcgYBBAMBAAEEAGEAAQkBCAcBCGMABwcCXAACAhcC
+TBcXFyMXIiIRERERKCEQCgYcKwEhESEyHgIVFA4CIyERIzUzETMRIQERITI+AjU0LgIjAtf+vgETYZZn
+NjZnlmH+NMDAuQFC/r4BEzpSNRkZNVI6BDT+bDFZekhIfFw0BDSYAUz+tP09/o4eM0EkIkQ1IQAAAQB9
+/+0ElAXFADcAyEuwF1BYQDEAAgMAAwIAcAAHBQYFBwZwBAEACQEFBwAFYQADAwFbCwEBAR1LAAYGCFsK
+AQgIHghMG0uwG1BYQDUAAgMAAwIAcAAHBQYFBwZwBAEACQEFBwAFYQALCxZLAAMDAVsAAQEdSwAGBghb
+CgEICB4ITBtAOQACAwADAgBwAAcFBgUHBnAEAQAJAQUHAAVhAAsLFksAAwMBWwABAR1LAAoKF0sABgYI
+WwAICB4ITFlZQBI3NjU0MzIkFCURFSQUJRAMBh0rATM1ND4CMzIeAhcjLgMjIg4CFRUhFSEVFB4CMzI+
+AjczDgMjIi4CNTUjESMRMwE1ljJfiVdRelUxB6cFGCo+LC9FLRcBGv7mFy1FLyw+KhcGpwcxVXpRV4lf
+Mpa4uANAY4HLjEo7bZxgPWNHJjZlklxll5tdk2U2JENhPliXbz5Ki8uBm/1XBbAAAAEAm//sBIkETgAz
+AIpLsBlQWEAxAAkKBwoJB3AAAgABAAIBcAsBBwQBAAIHAGEACgoGWwgBBgYYSwABAQNbBQEDAx4DTBtA
+OQAJCgcKCQdwAAIAAQACAXALAQcEAQACBwBhAAYGGEsACgoIWwAICB9LAAUFF0sAAQEDWwADAx4DTFlA
+EjMyLiwoJyQREREUJBQkEAwGHSsBIR4DMzI+AjczFA4CIyIuAicjESMRMxEzPgMzMh4CFSM0LgIjIg4C
+ByEDx/7VAhUqQy8eMiUVAa8yVXNAWYVbMAOPubmPAjBbhllHdFItrxMkMyEvQysVAQErAdBCeF03GzA/
+JEB1WjVLg7Bm/jAEOv4tZrGETDhggUooSjghOF55QAAAAgAnAAAEsgWwAAsADgApQCYOAQYEAUoABgIB
+AAEGAGEABAQWSwUDAgEBFwFMEREREREREAcGGysBIxEjESMDIwEzASMBIQMDZaG5lJO9AfqgAfG9/bcB
+hMABuP5IAbj+SAWw+lACWQJLAAIAVwAABIEEOgALABAAKUAmDwEGBAFKAAYCAQABBgBhAAQEGEsFAwIB
+ARcBTBERERERERAHBhsrASMRIxEjAyMBMwEjASEDJwcDSoC5h3a9AcSfAce+/gQBRYsYGQEp/tcBKf7X
+BDr7xgHBAVdSUgACAHEAAAS8BbAAEwAWADNAMBYBBwYBSgoBBwQCAgABBwBiCAEGBhZLCQUDAwEBFwFM
+FRQTEhEREREREREREAsGHSsBIxEjESMDIxMjESMRMxEzEzMBIwEzAwOhRpRFaL11qLm50dCfAVK8/qXb
+aAHU/iwB1P4sAdT+LAWw/MUDO/pQAnUCBAAAAgBwAAAEvQQ6ABMAFgAzQDAWAQcGAUoKAQcEAgIAAQcA
+YQgBBgYYSwkFAwMBARcBTBUUExIRERERERERERALBh0rASMRIxEjAyMTIxEjETMRMxMzASMBMwMDq0id
+T129Y5e5uc3VnwFTvf6q02UBJf7bASX+2wEl/tsEOv2MAnT7xgHGAVwAAAIAVQAABIUFsAAkACcAOEA1
+GQEDBAFKAgEABgEEAwAEYwAICAFZAAEBFksJBwUDAwMXA0wAACcmACQAJDESJRUREhUKBhsrMwM0PgIz
+MwEhAR4DFREjETQuAiMjBxEjEScjIg4CFREBEyFWATFdh1YD/q8D3/7LVoZdMLkWLEMuRAm5A1AuQysV
+AWHM/lIBq2KLWSkClv1qASlZimL+VQGrPVIyFhT9kgJ9BRYyUj3+VQM+AdoAAgBpAAAEWQQ6ACMAJwA5
+QDYbGAIDBAFKAgEABgEEAwAEYwAICAFZAAEBGEsJBwUDAwMXA0wAACcmACMAIxMSJRURERUKBhsrMzU0
+PgI3ASEBHgMVFSMnNC4CIyMHESMRJyMiDgIVFQEzEyFpK1N3S/7mA7D+5UlyUCq5ARQoPSoxCroFPSo9
+KBQBQgWy/pbbY49cLwMB3/4gBTBdjGHb20NZNhcR/k0BuwkXNllD2wJcAUYAAgBQAAAEhwWwACMAJgA7
+QDgOCwIBAgFKCQEABgQCAgEAAmMACwsIWQoBCAgWSwcFAwMBARcBTCYlIyIhIBERExNCEiMTEAwGHSsB
+FhYVESMDNCYjIwcRIxEnKwIGBhURIwM0NyMRIxEzESEDIQETIQOPeICZATM9IweZCCYCBDkxmQEUm6ur
+AYHrAun+jIH+/gMYBY2S/gwB9EtBFP2UAmkXAkFJ/gwB9FA8/YAFsP1oApj9zQGbAAIAUQAABIYEOgAk
+ACcAOEA1DwsCAAEBSgAIBQMCAQAIAWMACgoHWQkBBwcYSwYEAgMAABcATCcmJCMRERETE0IUExQLBh0r
+ARYWFREjAzQmIyMHIxEjEScrAgYGFREjAzQ3IxEjETMRIQMhARMjA6dtcpkBNT8SDAaaCiAEAjk0mQEV
+nKurAXLSAt7+kXz4AlALioz+0QEvTEAd/mIBpRYCQEr+0QEvUTv+RQQ6/hkB5/4yAT8AAgDK/kYEJAd0
+AD4ARwBUQFFFAQcGFQEFAAJKJyYCA0cIAQYHBnIABwIHcgkBAAAFBAAFYwABAQJbAAICFksABAQDWwAD
+Ax4DTAEAR0ZEQ0FAPTszMB8cDAoJBwA+AT4KBhQrATY2NTQuAiMhNSEyHgIVFA4CBxYWFRQOAiMjIgYV
+FB4CFwcuAyc0PgIzMzI+AjU0LgIjIzUTNzMVByMnNTMCHJ+ZJUptSP7OATJmr4BJI0BcOYCOSoGwZTVO
+RyEyNxdKL11LLwEwV3pLLkJtTSotVnxPja2XoP5y+50DNwGCcTJXQCSYNWWSXTVeUEAWKKyEZp9sOD4z
+KD0sHwp8FDtQZDxDYD4eKEdjPEVmQiGXA6WYEvj1FQAAAgDe/kYECQYeADwARQBUQFFDAQcGEwEFAAJK
+JSQCA0cIAQYHBnIABwIHcgkBAAAFBAAFYwABAQJbAAICGEsABAQDWwADAx4DTAEARURCQT8+OzkxLh0a
+DAoJBwA8ATwKBhQrATI2JzQuAiMhNSEyHgIVFAYHFhYVFA4CIyMiBhcUHgIXBy4DJzQ+AjMzMj4CNTQu
+AiMjNRM3MxUHIyc1MwIsiYUBIUBcPP7UASxbn3VEaFtnckR2oFswTkgBITI3F0suXUswATBXe0spN11C
+JilMbEONpZeg/nL7nQJpVUshOCgXmSlQc0lLdiMfeVlOeFIrPjMoPSwfCnwUO1BkPENgPh4YLD4mKz8o
+FJcDHZgS+PUVAAADAGP/7ARaBcQAHQAuAD8AN0A0BgECBwEEBQIEYQADAwFbAAEBHUsABQUAWwAAAB4A
+TDAvHx45Ny8/MD8oJh4uHy4tJggGFisBDgUjIi4EJzU+BTMyHgQXBSE1LgUjIg4EBwUhFR4FMzI+BDcE
+WgEZNFFwkVpakXBSNRoBARk1UXCRWlqScFE1GQH8vwKKAQwdMEhiQUBiSDAdDQECiv12AQ0eMEhiQUFj
+Ry8dCwEChE6flIBgNzdggZSeTqZOn5SBYTc3YIGUoE4JCzRxb2VNLS5NZW9xM6MFM3JvZk0uLk1lb3I0
+AAMAXf/sBDUETgAVACAAKwA3QDQABQADAgUDYQcBBAQAWwAAAB9LBgECAgFbAAEBHgFMIiEXFicmISsi
+KxwbFiAXICkkCAYWKxM0PgIzMh4CFRUUDgIjIi4CNQEyPgI3IR4DEyIOAgchLgNdRH+2cnO3f0REf7Zy
+c7d/RAHtRWtMLAf9oAcsTWtERGpMLgcCXwgtTGsCJ3XJlFVVlMl1FnXIlFRUlMh1/nE1XHtGRntcNQM0
+NFp5RER5WjQAAQAaAAAE4QXDABQAQbUBAQIBAUpLsBtQWEARAAEBAFsDAQAAHUsAAgIXAkwbQBUAAwMW
+SwABAQBbAAAAHUsAAgIXAkxZthEVIScEBhgrARc3AT4DMxcHIyIOAgcBIwEzAkciIgECGDhGWDguAQ0b
+KiMcDv59qv4G0QF2goEDKU1uSCIBqxAjNyb7eQWwAAEAUQAABGAETgAUAFtLsBtQWEALCQEBAAoBAgIB
+AkobQAsJAQEDCgECAgECSllLsBtQWEARAAEBAFsDAQAAH0sAAgIXAkwbQBUAAwMYSwABAQBbAAAAH0sA
+AgIXAkxZthETJSUEBhgrARc3EzY2FzIWFwcmJiMiBgcBIwEzAhsYGbAqg00cNBoVBhcOITwO/sON/ma+
+ATxlZQIfgXIBBxGUAwU0Kfy0BDoAAwBF/lEEugXEABUAMgBIAEFAPhcBBwIwAQAHJQEEAANKAAYGAVsA
+AQEdSwUBAgIYSwAHBwBbAAAAHksABAQDXAADAyEDTCklFjkVFykkCAYcKwEUDgIjIi4CNRE0PgIzMh4C
+FQEXEzMDDgMjIi4CJzceAzMyPgI3NwMzBTQuAiMiDgIVERQeAjMyPgI1AoonTHFJRWlHIyNHaUVJcE0n
+ARQPaaTxCSI3UDkKGRoYBwQGExQTBh0pGxEFGJ+k/nEMGy0gICsaDAwaKyAhLBsMAedzu4VISIW7cwHh
+c7yFSEiFvHP+q6MCavseJ1xPNQMFBgKQAQICASk6PhVeBDtLSHNRKytRc0j900h0USwsUXRIAAMAN/5R
+BLsETgAVADIASABvQA4XAQYHMAEBBiUBBAEDSkuwGVBYQCEABwcAWQUCAgAAGEsABgYBWwABAR5LAAQE
+A1wAAwMhA0wbQCUFAQICGEsABwcAWwAAAB9LAAYGAVsAAQEeSwAEBANcAAMDIQNMWUALKSUWORUXKSQI
+BhwrEzQ+AjMyHgIVFRQOAiMiLgI1JRcTMwMOAyMiLgInNx4DMzI+Ajc3AzMBFB4CMzI+AjU1NC4CIyIO
+AhU3I014VVZ6TSQkTXlVVnlMJANnDWyk8QkiN1A5ChkaGAcEBhMUEwYdKRsQBhifpP2PCBw1LS01GwgI
+HDYtLDUbCAIodcmUVFSUyXUXdcmTVFSTyXViswJ6+x4nXE81AwUGApABAgIBKTo+FV4EO/3XUJBuQUFu
+kFAXTpBuQkJukE4AAAQAav9zBGEGNQADAAcAJQBDAKtLsBZQWEAuAAEFBQFmAAAGAwYAaAADBwcDZgAC
+BAQCZwAGBgVbAAUFHUsABwcEXAAEBB4ETBtLsBdQWEAtAAEFBQFmAAAGAwYAaAADBwcDZgACBAJzAAYG
+BVsABQUdSwAHBwRcAAQEHgRMG0AuAAEFAXIAAAYDBgADcAADBwYDB24AAgQCcwAGBgVbAAUFHUsABwcE
+XAAEBB4ETFlZQAstLS0nEREREAgGHCsBIxEzESMRMwEOBSMiLgQnNT4FMzIeBBcnLgUjIg4EBxUeBTMy
+PgQ3AsK5ubm5AZ8BGTRRcJFaWpFwUjUaAQEZNVFwkVpaknBRNRkBtwEMHTBIYkFAYkgwHQ0BAQ0eMEhi
+QUFjRy8dCwEEswGC+T4BiwGGTp+UgGA3N2CBlJ5Opk6flIFhNzdggZSgTgI0cW9lTS0uTWVvcTOoM3Jv
+Zk0uLk1lb3I0AAAEAHr/YQRSBMsAAwAHAB0AMwEWS7ASUFhALgABBAQBZgAABwMHAGgAAwYGA2YAAgUF
+AmcABwcEWwAEBB9LAAYGBVwABQUeBUwbS7AUUFhALQABBAQBZgAABwMHAGgAAwYGA2YAAgUCcwAHBwRb
+AAQEH0sABgYFXAAFBR4FTBtLsBZQWEAsAAEEAXIAAAcDBwBoAAMGBgNmAAIFAnMABwcEWwAEBB9LAAYG
+BVwABQUeBUwbS7AXUFhALQABBAFyAAAHAwcAaAADBgcDBm4AAgUCcwAHBwRbAAQEH0sABgYFXAAFBR4F
+TBtALgABBAFyAAAHAwcAA3AAAwYHAwZuAAIFAnMABwcEWwAEBB9LAAYGBVwABQUeBUxZWVlZQAspKSkl
+EREREAgGHCsBIxEzESMRMwE0PgIzMh4CFRUUDgIjIi4CNTMUHgIzMj4CNTU0LgIjIg4CFQLEurq6uv22
+RH+2cnO3f0REf7Zyc7d/RLkmTXRNTHNNJidNc01Nck0mA0YBhfqWAZcBL3XJlFVVlMl1FnXIlFRUlMh1
+UJFuQEBukVAWT5FuQUFukU8AAAMATf/rBIMHUQA0AEwAWABpQGY/AQ0KQQEACVgBBAAOAQEFBEoADQoJ
+Cg0JcAAGBAUEBgVwAAsACg0LCmMOAQwACQAMCWMIAQQEAFsDAQAAFksHAQUFAVsCAQEBHgFMNTVSUTVM
+NUtGRD07ODYVIxMlERkkKRAPBh0rATIeAhURFA4CIyImJwYGIyIuAjURND4CMxUGBhURFBYzMjY1ETMR
+FBYzMjY3ESYmJxMVIyIuAiMiBhUHIzU0NjMyHgQzATY2NTUzFRQOAgcDIk6CXTQuU3VGTHMgIXNLR3RT
+LjNdgk9OWUU9PEa6Rjw8RgEBWk27Kkl0YFEmMjkBf3ptIj89PkRNLf5IISKLFiQvGQWvM2STYP0rV4Va
+L0hGRkgvWoVXAtVgk2QzlwF+dP0rYW1kWAH8/gRYZG1hAtV0fgEBu38oLyc2NxIkbmwTGyEcE/6QKEcm
+YGYdOzUtDQAAAwBn/+sEfAXeADQASgBWALJAEj8BDQpBAQAJVgEEAA4BAQUESkuwJlBYQDwADQoJCg0J
+cAAGBAUEBgVwDgEMAAkADAljAAoKC1sACwsdSwgBBAQAWwMBAAAfSwcBBQUBWwIBAQEeAUwbQDoADQoJ
+Cg0JcAAGBAUEBgVwAAsACg0LCmMOAQwACQAMCWMIAQQEAFsDAQAAH0sHAQUFAVsCAQEBHgFMWUAaNTVQ
+TzVKNUlGRD07ODYVIxMlERkkKRAPBh0rATIeAhURFA4CIyImJwYGIyIuAjURND4CMxUGBhURFBYzMjY3
+ETMRFBYzMjY1ETQmJxMVIyIuAiMiBhUHIzU0NjMyHgIzATY2NTUzFRQOAgcDLUp7WTErT25DTHIhIXNM
+Q25PKzFYe0tFUDs2PEYBukY8NT1RRcIrSnRhUScyOgF/e200W19sRP5DISKLFiQvGQRNMmOSYP6GV4RZ
+LUZGRkYtWYRXAXpgkmMylwF5dv6GYWlgWAEN/vNYYGlhAXp2eQEBqn8oLyc2NxIlbmsnLyj+jyhHJmBm
+HTs1LQ0AAAIAcf/sBIUHBAAHACwAdLURAQQHAUpLsBRQWEAlAAIBBgECaAAAAwEBAgABYQsKCAMGBhZL
+CQEHBwRbBQEEBB4ETBtAJgACAQYBAgZwAAADAQECAAFhCwoIAwYGFksJAQcHBFsFAQQEHgRMWUAUCAgI
+LAgsKScTIxUkJhERERAMBh0rASEXIRUjNSEFExQOAiMiJicGBiMiLgI1EzMTFBYzMjY1EzMRFBYzMjY1
+EwEbAtAB/uOo/vQDaQErTm1CTnQgIHRNQ21OKwG4ATs0PEUBv0U9NDoBBwRsfX3o+45SflYsSklISyxW
+flIEcvuOWGRkWARy+45YZGRYBHIAAgBf/+sEegWwAAcALAB4tREBBAcBSkuwFFBYQCcAAgEGAQJoAwEB
+AQBZAAAAFksLCggDBgYYSwkBBwcEWwUBBAQeBEwbQCgAAgEGAQIGcAMBAQEAWQAAABZLCwoIAwYGGEsJ
+AQcHBFsFAQQEHgRMWUAUCAgILAgsKScTIxUkJhERERAMBh0rASEXIRUjNSEBERQOAiMiJicGBiMiLgI1
+EzMRFBYzMjY1ETMTFBYzMjY1EQEEAtYB/uCo/vEDditPbkJOdSEgdE5Dbk4sAbk8NTxHvwFGPTQ9BbBs
+f3/+9/0BUn5VLEpJSEssVX5SAv/9AVhiYlgC//0BWGJiWAL/AAEAl/6CBGUFxQAkAFO1AgEABAFKS7Ad
+UFhAHQACAwQDAgRwAAMDAVsAAQEdSwAEBABZAAAAGgBMG0AaAAIDBAMCBHAABAAABABdAAMDAVsAAQEd
+A0xZtykkFCsQBQYZKwEjES4DNTU0PgIzMh4CFSMuAyMiDgIVFRQeAjMzAyq5bq97QkaCuHJusHtDuQEm
+SWxHS3VQKTBdiFht/oIBbw5rpdV594PkqWFFgLNuS3xXME2Bq175X6yDTQAAAQC//oIEOwROACQAU7UC
+AQAEAUpLsB1QWEAdAAIDBAMCBHAAAwMBWwABAR9LAAQEAFkAAAAaAEwbQBoAAgMEAwIEcAAEAAAEAF0A
+AwMBWwABAR8DTFm3KSQUKxAFBhkrASMRLgM1NTQ+AjMyHgIVIzQuAiMiDgIVFRQeAjMzAv25X5FiMz54
+sHJbmnA/ryZBWjRMbEYhIEZsTWb+ggFwEGGQs2Iqa8SVWD1qj1MxWEImRW+LRSpHi29FAAABAHYAAASS
+BT4AEwAnQCQTEhEQDQwLCgkIBwYDAgEPAAEBSgABAAFyAAAAFwBMGRQCBhYrAQUHJQMjEyU3BRMlNwUT
+MwMFByUCWgEhRP7dtqjh/t9EASXN/t5GASO8pecBJUj+4AG+rHuq/r8Bjqt7qwFtq32rAUv+aKt6qgAB
+ANEEpgORBfwABwCMS7AUUFhAGAACAQECZgAAAwMAZwQBAwMBWQABARYDTBtLsBdQWEAXAAIBAQJmAAAD
+AHMEAQMDAVkAAQEWA0wbS7AfUFhAFgACAQJyAAADAHMEAQMDAVkAAQEWA0wbQBsAAgECcgAAAwBzAAED
+AwFVAAEBA1oEAQMBA05ZWVlADAAAAAcABxEREQUGFysBFSc3IScXFQF3pgECGwGlBSN9AelsAdgAAQD8
+BRcD8AYVABcAT0uwJlBYQBUAAQADAgEDYwQBAgIAWwUBAAAWAkwbQBsFAQADAgBXAAEAAwIBA2MFAQAA
+AlsEAQIAAk9ZQBEBABYUEQ8MCwgGABcBFwYGFCsBMj4EMzIWFRUjNTQmIyIOAiMjNQEmNFpPSEdIKG6A
+gD8zLV5vh1UsBZYTHCEcE2xuJBI4NCcvJ34AAQHDBRYCsgZXAAUAEkAPBQQDAAQARwAAAGkRAQYVKwE1
+MwcXBwHDtAE8TgXce4x0QQABAjwFFgMqBlcABQARQA4FAgEDAEcAAABpEwEGFSsBJzc1MxUCiEw6tAUW
+QXSMewAI/uf+xAaDBa8AFQArAEEAVwBtAIMAmQCvAT1LsB9QWEBmIAMCAQIEAgEEcCUXFSEHBQUGCAYF
+CHAmGxkiCwUJCgwKCQxwJBMCERIRcxQBBBYBBgUEBmMYAQgaAQoJCApjHAEMHgEODQwOYwAQABIREBJj
+AAICAFsAAAAWSycfHSMPBQ0NFw1MG0BpIAMCAQIEAgEEcCUXFSEHBQUGCAYFCHAmGxkiCwUJCgwKCQxw
+Jx8dIw8FDQ4QDg0QcCQTAhESEXMUAQQWAQYFBAZjGAEIGgEKCQgKYxwBDB4BDg0MDmMAEAASERASYwAC
+AgBbAAAAFgJMWUBgmpqEhG5uWFhCQiwsFhYAAJqvmq+rqaWkoJ6EmYSZlZOPjoqIboNug399eXh0clht
+WG1pZ2NiXlxCV0JXU1FNTEhGLEEsQT07NzYyMBYrFisnJSEgHBoAFQAVJBQkKAYXKwE0PgIzMh4CFSM0
+LgIjIg4CFQE0PgIzMh4CFSM0LgIjIg4CFRM0PgIzMh4CFSM0LgIjIg4CFQE0PgIzMh4CFSM0LgIjIg4C
+FQE0PgIzMh4CFSM0LgIjIg4CFQE0PgIzMh4CFSM0LgIjIg4CFQE0PgIzMh4CFSM0LgIjIg4CFRM0PgIz
+Mh4CFSM0LgIjIg4CFQHUHTdOMDBONx5wCxglGxslFwoB3h42TjAwTjgecQsYJRsaJRcKSR42TjAwTjce
+cAsYJRsaJRcL/soeNk4wME43HnALGCUbGiUXC/1PHTdOMDBONx5wCxglGxolFwv9TR43TjAwTjcecAsY
+JRsbJRcK/t4eN00wME43HnALGCUbGiQYCzUeN00wME44HnELGCUbGiUWCwTzKUUyHBwyRSkUJBwRERwk
+FP7rKUUyHBwyRSkUJBwRERwkFP4JKUUyHBwyRSkUJBwRERwkFP35KUUyHBwyRSkUJBwRERwkFP7kKkUx
+HBwxRSoUJRwQEBwlFAUaKUUyHBwyRSkUJBwRERwkFP4JKUUyHBwyRSkUJBwRERwkFP35KUUyHBwyRSkU
+JBwRERwkFAAACABO/mMHjgXGAAQACQAOABMAGAAdACIAJwBtQB8hIBYDAwInIh0YFxMSEQ8ODQwKDQED
+JiUcGwQAAQNKS7AuUFhAFwUBAwMCWQACAhZLBAEBAQBZAAAAGgBMG0AVAAIFAQMBAgNhBAEBAQBZAAAA
+GgBMWUASBQUAAAUJBQkIBwAEAAQSBgYVKwUXAyMTAycTMwMBNwUVJQUHJTUFATclFwUBBwUnJQMnAzcT
+ARcTBwMEUQt6YEY6DHpgRgIeDQFN/qb7dA3+swFaA5wCAUFE/tr88wL+wEUBJisRlEHGA2ARlULFPA7+
+rQFhBKIOAVL+oP4RDHxiRzsMfGJHAa4QmUTI/I4RmUXIAuQCAUZF/tX84wL+u0cBKwAAAwC/AAAEeQWw
+AAMAEgAfADZAMwMCAgMEAQEAAgJKAAMFAQIAAwJjAAQEAVsAAQEWSwAAABcATAQEHx0VEwQSBBEhFQYG
+FisBBwE3AREjESEeAxUUDgIHJSE+AzU0LgInIQQxhP6Vg/6zuQHYYq+ETU2Er2L+4QEfQGxQLS1PbUD+
+4QHTRgHsRv6J/bgFsAI6bqJpaaFuOgGYASdIZ0JCakooAQADAK3+YAQ/BE4AAwAZACsAaEAVEQEEAiMi
+AwIEBQQMAQAFAQEBAARKS7AZUFhAGwAEBAJbAwECAhhLAAUFAFsAAAAeSwABARoBTBtAHwACAhhLAAQE
+A1sAAwMfSwAFBQBbAAAAHksAAQEaAUxZQAklKSMREygGBhorJQcBNyUUDgIjIiYnESMRMxc2NjMyHgIV
+IzQuAiMiBgcRFhYzMj4CNQQ2cP6VcQFzOGyfZmOXNrmpCTaZZWigbDi5I0lwTll5JCR4XE1wSCMCXQF1
+Xpl0yZRUQDz9+AXadkNHUpLLeU+PbUBTQf33QFFBbpBPAAABALYAAARHBv8ABwAfQBwAAwIDcgAAAAJZ
+AAICFksAAQEXAUwREREQBAYYKwEhESMRIREzBEf9KboC2LkFGProBbABTwAAAQC2AAAEMQV3AAcAH0Ac
+AAMCA3IAAAACWQACAhhLAAEBFwFMEREREAQGGCsBIREjESERMwQx/T+6AsG6A6H8XwQ6AT0AAAEAuf7g
+BH8FsAAbACxAKQABAAQFAQRjAAMAAgMCXwAAAAZZAAYGFksABQUXBUwRESYRGCEQBwYbKwEhETMyHgIV
+FA4CIycyPgI1JiYjIxEjESEENP0/uI7dmVA9eLFzAlFvRB4Cy864ugN7BRj+KlCV1oaDy4pJkzlok1rH
+2P1gBbAAAAEAuP7kBFIEOgAdACtAKA4NAgNHAAEAAgMBAmMAAAAEWQAEBBhLAAMDFwNMHRwbGhkXIRAF
+BhYrASERMzIeAhUUDgIHJz4DNTQuAiMjESMRIQQr/Ufab72LTyxelGcwRGA8HDNaeUfaugNzA6H+5UF5
+sXE6joRnE5ISO09gOEx2Tyn+HAQ6AAABAK4AAATEBbAAFAA9QDoBAQEGAUoIAQYDAQECBgFhCgkCBQUW
+SwACAgdZAAcHGEsEAQAAFwBMAAAAFAAUERERERERERESCwYdKwkCIwEjFSM1IxEjETMRMxEzETMBBJj+
+sQF75/66NpVlublllTYBKQWw/VH8/wKU9fX9bAWw/XsBAf7/AoUAAQCjAAAEfgQ6ABQAO0A4AQEBBgFK
+CAEGAwEBAgYBYQAHAAIABwJhCgkCBQUYSwQBAAAXAEwAAAAUABQRERERERERERILBh0rCQIjASMVIzUj
+ESMRMxEzNTMVMwEEWf6uAXfq/uozlFq6ulqULAEDBDr9/v3IAc3Cwv4zBDr+NtXVAcoAAQAtAAAEpgWw
+AA4ALUAqDAEABAFKAAQAAAEEAGEAAgIDWQUBAwMWSwYBAQEXAUwSEREREREQBwYbKwEjESMRITUhETMB
+MwEBIwKVarj+ugH+YgEe0/67AW3iApP9bQUYmP16Aob9P/0RAAEAOAAABLEEOgAOAC1AKgwBAAQBSgAE
+AAABBABhAAICA1kFAQMDGEsGAQEBFwFMEhEREREREAcGGysBIxEjESE1IREzEzMBASMCvIa5/rsB/n/5
+4P63AWzqAc3+MwOhmf42Acr9/v3IAAABAHIAAASaBbAADQAnQCQAAAAEAwAEYQACAgFZBgEBARZLBQED
+AxcDTBERERERERAHBhsrASERIRUhESMRIREjETMBKwFzAfz+vLj+jbm5Ax8CkZj66AKH/XkFsAAAAQBu
+AAAEnAQ6AA0AJ0AkAAAABAMABGEAAgIBWQYBAQEYSwUBAwMXA0wREREREREQBwYbKwEhESEVIREjESER
+IxEzAScBfAH5/sC5/oS5uQJlAdWZ/F8Bzv4yBDoAAAEAbf7fBJoFsAAdAC5AKwAAAAMEAANjAAIAAQIB
+XwAFBQdZAAcHFksGAQQEFwRMERERERgRGBAIBhwrAR4DFRQOAiMnMj4CNS4DJxEjESERIxEhAuFrpXA5
+MGGQYAI6Ti8TAR4+YEO5/v24AnQDQQJTmNOBgcqMSpM7aZNXXphrOwL9YgUY+ugFsAAAAQB0/uUEfAQ6
+ACEAL0AsDg0CAkcAAAABAgABYwADAwVZAAUFGEsEAQICFwJMISAfHh0cGxoYFyAGBhUrATMyHgIVDgUH
+Jz4DNS4DIyMRIxEjESMRIQLNCF2ccD4BECI1S2I9MDlNLxQBIj5XNgi557kCWQKFQnywbSZZXFlMOA2S
+EjxPYDZJdVAr/h0DofxfBDoAAAIAaP/iBFAFxQA1AEcAM0AwOTIgAwQDAwEABAJKBwEDAwJbBQECAh1L
+BgEEBABbAQEAAB4ATCwaKxkRGSQQCAYcKwUmJicGBiMiLgI1ETQ+AjMXIg4CFREUHgIzMjY3JiY1ETQ+
+AjMyHgIVEQYGBxYWMwEUFhc2NjURNC4CIyIOAhUEUFKSPzBtPHG2gEUvV3xOASY4JxMoTnNKESAQW2Er
+UHNISHNQKwFLRiNOLP5CSUU1Ng8fLx8gLiAPHgEhHxsdZq7phQEXeNKcW55CcZdX/udlsINNBARb/JsB
+U2W0hk5MhbRo/piM8VgMDQIBgMtEQ8V0AWtFelozNlt4QwACAFz/6wSLBE8AMwBFADNAMDcxHwMEAwMB
+AAQCSgcBAwMCWwUBAgIfSwYBBAQAWwEBAAAeAEwsGSkpERkkEAgGHCsFJiYnBgYjIi4CNTU0PgIzFSIO
+AhUVFB4CMzI3JiY1NTQ+AjMyHgIVFRQGBxYzARQWFzY2NzU0LgIjIg4CFQSLWp5FOYNKb7WBRzJcglAo
+PioWKk5ySC8sXmUrUXZLS3dRK0I+T2H+D1FNMzYBECEyIiIxIBAMAR0cICNbn9h8OmOtgUqeMVVzQjxb
+nnVDDE/ZgGhbnHNBR3qjXGlxxEsVAalppzk5nl5sOmhPLylIYjkAAQA5/qEEtgWwABMAK0AoAAYDBlIC
+AQAAAVkEAQEBFksFAQMDB1oABwcXB0wRERERERFREAgGHCsBITUhNTMVMxUjESERMxEzAyMRIQFG/vMB
+Dbnu7gFtuZESpf1HBRiXAQGX+38FGfrs/gUBXwABADT+vwSLBDoADwArQCgABgMGUgIBAAABWQQBAQEY
+SwUBAwMHWgAHBxcHTBEREREREREQCAYcKwEjNSEVIxEhETMRMwMjESEBHOgCheQBfbmAEqb9SQOjl5f8
+9AOj/F3+KAFBAAACAKsAAAQnBbAAAwAdAHJAChwBBQEHAQMFAkpLsApQWEAkAAEEBQQBBXAAAAMCAwBo
+AAUAAwAFA2QHBgIEBBZLAAICFwJMG0AlAAEEBQQBBXAAAAMCAwACcAAFAAMABQNkBwYCBAQWSwACAhcC
+TFlADwQEBB0EHSUVJRIREAgGGisBIxEzAREjEQ4DIyIuAjURMxEUHgIzMjY3EQKmlZUBgbkhQkdRMGGY
+aDe5GzdUOVOQSAE1ArwBv/pQAlsMEg4HMWyqeQHI/jhVcUUdHRgCuwACAJIAAAQsBDoAAwAZAJZAChcB
+BQEGAQMFAkpLsApQWEAiAAEEBQUBaAAAAwIDAGgABQADAAUDZAYBBAQYSwACAhcCTBtLsBJQWEAjAAEE
+BQQBBXAAAAMCAwBoAAUAAwAFA2QGAQQEGEsAAgIXAkwbQCQAAQQFBAEFcAAAAwIDAAJwAAUAAwAFA2QG
+AQQEGEsAAgIXAkxZWUAKEyMVIxEREAcGGyslIxEzASMRBgYjIi4CNREzERYWMzI2NxEzAq+WlgF9uUSR
+VWSicz65AYN6UZRFudMCNvz3AYsREjJlmWcBO/7FhXoSEQIXAAEA4wAABF8FsAAZAC9ALAMBAwEYAQID
+AkoAAQADAgEDYwAAABZLBQQCAgIXAkwAAAAZABklFSURBgYYKzMRMxE+AzMyHgIVAyMRNC4CIyIGBxHj
+uSFBR1EwYZhpNwG5GzdUOVOQRwWw/aMMEw4HMWyqef45AcdVcUUdHRj9RgAAAgAm/+oEiQXDACkANABS
+QE8PAQUBBgEDBSQBBAMlAQAEBEoIAQUAAwQFA2EABgYCWwACAh1LAAEBGEsABAQAWwcBAAAeAEwrKgEA
+MjAqNCs0IB4ZGBUTDAsAKQEpCQYUKwUiLgI1NS4DNTMWFhc0PgIzMhIRFSEVFB4CMzI+AjcXDgMBITU0
+LgIjIgYVAyp8v4JDQWFBIZUBNDpGeqVf1cb9WiRPfFgvTUE1Fi8PNUxm/ngB7RUzV0N/jBZYndeAkAw/
+X35LVHgZkOaiV/7V/uK8iFqfd0YQGh4OiAwjHxYDWHBOiWY88+YAAgAm/+wEhQROACYAMgBVQFINAQYB
+BQEDBiEBBAMiAQAEBEoAAQUGBQEGcAAGAAMEBgNhCAEFBQJbAAICH0sABAQAWwcBAAAeAEwoJwEALSwn
+MigyHx0ZGBMRCgkAJgEmCQYUKwUiLgI1NSYmNTMWFhc+AzMyHgIVFSEeAzMyNjcXDgMDIg4CByE1NC4C
+Av5ur3pCgH+UATY7D1B0kVBrn2gz/VoDJkhpRWSLMEoYQ1lwYzJUQCwJAeccOlkUUZHGdQEXs45NaxVh
+o3VASYGyaXhMhWQ6Py58GTAmGAPKLlFuQBg2ZE0uAAEAyP7aBIwFsAAeAChAJQAFAAIDBQJjAAEAAAEA
+XwYBBAQWSwADAxcDTBEREREoERkHBhsrAR4DFRQOAiMnMj4CNS4DIyMRIxEzETMBMwLKbKhyPD12r3MC
+UG1EHQEuW4td4Lm5jgGb1wM1D12SxXeDyotJkjppklpjmmo4/WYFsP2MAnQAAQC0/v4EPAQ6AB4AKUAm
+CwoCAUcAAwAAAQMAYwQBAgIYSwABARcBTB4dHBsaGRgXFhQFBhQrAR4DFRQOAgcnPgM1NC4CIyMRIxEz
+ETMBMwKvVo9mOSpYi2ExP1c4GTJXd0fHubl3AXjgAmQORG2WYDiIfWISkhA4SVszTG1FIP4zBDr+NgHK
+AAEAtv5LBBkFsAAbADtAOA4BAwUNAQIDAkoAAAAEBQAEYQcGAgEBFksABQUXSwADAwJbAAICIQJMAAAA
+GwAbERMnJRERCAYaKwERIREzERQOAiMiJic3HgMzMjY1ESERIxEBbwHxuSpRdkwdNB0OCBsdGgZBQ/4P
+uQWw/WwClPn3UoFaLwgKkwMFAwJtVwLe/XsFsAABALP+SwQWBDoAGwA7QDgOAQMFDQECAwJKAAAABAUA
+BGEHBgIBARhLAAUFF0sAAwMCWwACAiECTAAAABsAGxETJyUREQgGGisBESERMxEUDgIjIiYnNx4DMzI2
+NREhESMRAWwB8bksUnhMHjUdDggcHRoHQkf+D7kEOv4rAdX7bVOBWS8ICpMDBQMCaloCJ/4yBDoAAgBa
+/+sEVwXEACIALgBDQEAeAQMAHQECAwJKAAIABQQCBWEAAwMAWwYBAAAdSwcBBAQBWwABAR4BTCQjAQAp
+KCMuJC4ZFxIRDAoAIgEiCAYUKwEyHgIVFRQOAiciLgI1NSE1NC4CIyIOAgcnPgMTMj4CNyEVFB4CAj6C
+yIlGT4u9b368fj8DRCdVhl41WUo9GS8RO1dyW1F7VCwB/XUhS3kFxF+o54jajO6uYQFWn+CKpl1iroNM
+EBkfDogMIyAW+r5PhrNjWlOSbT8AAQCU/+sEUgWwACQAPEA5BAEAASQBAgACSgAEBgUGBAVwAAIABgQC
+BmMAAAABWQABARZLAAUFA1sAAwMeA0wmJBQoEhEQBwYbKwEhNSEXAR4DFRQOAiMiLgI1MxQeAjMyPgI1
+NCYjIzUDSv10A2UB/mVsqnU+SYOzalephFG5KkppP0dxTiqnn48FGJh2/hQGQG+fZGaebjkyaKBvOWNL
+KylIZDucjpcAAQCJ/nUESAQ6ACQAaUALBAEAASQFAgUAAkpLsDBQWEAkAAUAAwAFA3AAAwQAAwRuAAAA
+AVkAAQEYSwAEBAJbAAICGgJMG0AhAAUAAwAFA3AAAwQAAwRuAAQAAgQCXwAAAAFZAAEBGABMWUAJJiQU
+KxEQBgYaKwEhNSEXAR4DFRQOAiMiLgI1MxQeAjMyPgI1NCYjIzUDLP2IA2UB/nJppXI8SYO0aleohFK6
+KUtoP0hxTiqrn40DoZl2/hEIQW+cYmWebjkyaKBuOGNKKyhIYzudjZcA//8AQv5LBHsFsAImAK5LAAAn
+Ab3/DQA/AQcBwv9PAAAACLEBAbA/sDMr//8AdP5LBHwEOgImAOhSAAAnAb3/P/9kAQcBwv9EAAAACbEB
+Abj/ZLAzKwAAAgBhAAAEMAWwAA4AGwAwQC0FAQIAAwQCA2MAAAAWSwYBBAQBXAABARcBTA8PAAAPGw8a
+EhAADgANIREHBhYrAREzESEiLgI1ND4CMwERISIOAhUUHgIzA3e5/hh1tXxBQXy1dQEv/tFOckojI0py
+TgNtAkP6UEJ2o2BhoHI//SoCPy5NZjg5alIxAAACAE0AAASNBbAAIAAtAGZLsBdQWEAcBAEBAAUDAQVj
+AAICFksIBgIDAwBcBwEAABcATBtAIwAEAQUBBAVwAAEABQMBBWMAAgIWSwgGAgMDAFwHAQAAFwBMWUAZ
+ISEBACEtISwkIhgXEA4NDAsJACABHwkGFCshIi4CNTQ+AjMzETMRNz4DNzYmJzMWFgcOAyMnESMiDgIV
+FB4CMwHPXpBiMjJikF5yuTEpPSoWAQIgHbMbKAICOV9/R+pyNk0wFhYwTTZDd6JfX6BzQAJD+uYBAS9W
+d0hbxVtbwGB2sng8lwI/Lk5mNzhqUjIAAAIAZf/oBJQGGAArAEAAQUA+CAEGAD0sAgIDIwEEAgNKAAEA
+AXIAAwYCBgMCcAAGBgBbAAAAH0sHAQICBFwFAQQEHgRMKScjJxclEyQIBhwrEzQ+AjMyFhcRMxEGHgIz
+PgM3NiYnNxYWBw4DIwYnBgYjIi4CNQEmJiMiDgIVFRQeAjMWNjcmJidlJktySzRUIbkBCxgjFyIyIREB
+Ah8dshwoAgIyVnRDqEMlaUdKcEwmAdcWPCkuPyYQECY+LS5AFwMEAQJAb8COUSYjAhP7HCRBMB0BPGqR
+V2TKZAFiymeGzIxIA4Y/REh+qmIBqyEoPWeFSIM+b1YyATAoFCoXAAABADf/6QSKBbAAOgA7QDgbAQAB
+AUoABQIBAgUBcAABAAAEAQBjAAICA1sAAwMWSwAEBAZbAAYGHgZMODYvLiclISYhJAcGGCsBNC4CIyM1
+MzI2NTQuAiMjNTMyHgIVFAYHHgMVFRQeAjM+Azc2JiczFhYHDgMjBiYnAfcbMUUqhVKBdx06Vzvh4WKb
+bDlkWzFFLBMOHCkbK0EsFwIBIB2zGioCAjphg0qJmAYBcjpiRieYhX87X0MkmDZnmmRyqjAVQ1hqO2kc
+MiUWATtqkldkymViymeHzYtHAouXAAABAFD/4wR9BDoAMwA4QDUvAQMEAUoAAQUEBQEEcAAEAAMABANj
+AAUFBlsABgYYSwAAAAJbAAICHgJMISQhJScXIgcGGyslFBYzMj4CNzYmJzMWFgcOAyMGJic1JiYnIycz
+MjY1NCYjIyczMh4CFRQGBxYWFRUC2yY1IjMjEgECIR60GisCAjVXdUKGiAYBa2OtApV6cHR63wblZJ5t
+OWFbZlTVJzErTWxCTqNOTqBRbqZwOQNygUtKTgGWV0tPY5YsUnhMVG8kHH5VTQACALP+pQRSBbAAKwA3
+AEBAPRUBBAAeAQMFAkoyMQIDRwAABgEEBQAEYwABAQJbAAICFksABQUDWQADAxcDTAAANzYAKwAqIB8h
+JiEHBhcrATUzMjY1NC4CIyE1ITIeAhUUBgceAxUVFBYXFSMuAzU1NC4CIwEUDgIHJzY2NTUzARCjqZsk
+S3NO/uwBFHS2fUJ3cD5WNhkeJ78XGQwDJkVhPAJnFy1AKnMwKMkCeZiBgjxhQySYNWibZnOkMRRCWGw9
+iD9tJhkVQUU/E4Q8YkUl/acvZ2VcJD9GnlWzAAACAND+kgQwBDoAKQA1ADhANRMBAwABSjAvIB4ZBQRH
+AAQDBHMAAAUBAwQAA2MAAQECWwACAhgBTAAANTQAKQAoISQhBgYXKwE1MzI2NTQmIyE3ITIeAhUUBgce
+AxUVFB4CFxUjLgM1NTQmJwEUDgIHJzY2NTUzARnUfHR1e/7jAQEcZJ5uOmJeNEkuFQUNFxK/FBYKAm5l
+AiYXLUAqczAoyQG5llZOUGGWK1J3TVRzIw8yQlEuYRIqKiYNEw4wMy8NX1JaAf5UL2dlXCQ/Rp5VswAB
+ABT/6QSlBbAAKwBeS7AXUFhAHwAFAAIABQJwAAAAA1kAAwMWSwQBAgIBWwYBAQEXAUwbQCcABQACAAUC
+cAAAAANZAAMDFksAAgIBWwABARdLAAQEBlsABgYeBkxZQAonFyUVISUQBwYbKwEjExQCBgYjIzUzMj4C
+NRMhExQeAjM+Azc2Jic3FhYHDgMjBiYnAmPKASNTiWUiFzRGKhIBAjkBCBEcEyIxIRABARUUsxQdAgIy
+VnNCeoMFBRj96Lj+4sRml06b55kCsPtfGzMnGAE8apJWZMpkAWLKZ4bMjEgCkJYAAAEAL//pBIUEOgAr
+AG9LsBdQWEAqAAEDBQMBBXAAAwMGWQcBBgYYSwAFBQJbBAECAh5LAAAAAlsEAQICHgJMG0AoAAEDBQMB
+BXAAAwMGWQcBBgYYSwAFBQRbAAQEF0sAAAACWwACAh4CTFlADwAAACsAKyElEycXJQgGGisBERQeAjM+
+Azc2JiczFhYHDgMjBiYnESMRFA4CIyM3NzI+AjURAvoJEhsTITIiEQECIB2zGygCAjJWc0N5hAXFHURy
+VCYDFyQwGwsEOvznIDksGgE0XoFOX8BeXb9hfLyAQQKYoAKA/s2S56BVpQE7c6pwAcwAAQBv/+kElQWw
+ACMAaEuwF1BYQCMAAQUGBQEGcAAGAAMABgNhCAcCBQUWSwAAAAJcBAECAh4CTBtAJwABBQYFAQZwAAYA
+AwAGA2EIBwIFBRZLAAQEF0sAAAACXAACAh4CTFlAEAAAACMAIxERERMnFyUJBhsrAREUHgIzPgM3NiYn
+NxYWBw4DIwYmJxEhESMRMxEhEQMMCBIbEyIxIBEBAiAcshoqAgIyVXNDeYMF/tW5uQErBbD7hCRAMR0B
+PGuRVmTKZAFiymeFzYxIAqGqAVH9ewWw/WwClAABAHX/6QR+BDoAIwBhS7AXUFhAIgAGAgMCBgNwAAMA
+AAUDAGEEAQICGEsABQUBXAcBAQEXAUwbQCYABgIDAgYDcAADAAAFAwBhBAECAhhLAAEBF0sABQUHXAAH
+Bx4HTFlACycXJREREREQCAYcKwEhESMRMxEhETMRFB4CMz4DNzYmJzMWFgcOAyMGJicCO/7zubkBDbkK
+FyIXHSwcDwEBFhSyFB4CAi9RbT+BjQUBzf4zBDr+KgHW/OcgOSwaATRegU5fwF5dv2F8vIBBApigAAAB
+AI7/6wR1BcUALQA8QDkOAQIBDwEEAgJKAAQCAwIEA3AAAgIBWwABAR1LAAMDAFsFAQAAHgBMAQAkIx4c
+ExEMCgAtAS0GBhQrBSIuAjURND4CMzIWFwcmJiMiDgIVERQeAjM2Njc2JiczHgMHDgMClHW/iEpKiL91
+cK5DO0GPVk98VS0tVXxPjZcDAh0XswoUEQoBAk6DrRVfpuKDAQaD4adfLCyEISNKf6le/vhfqoBKAp2I
+WrVaLFpbWy1wqG83AAEAoP/rBFAETgArADxAOR0BBAMeAQEEAkoAAQQABAEAcAAEBANbAAMDH0sFAQAA
+AlsAAgIeAkwBACIgGxkQDgcGACsBKwYGFCslNjY3NCYnMxYWFQ4DIyIuAjU1ND4CMzIWFwcmJiMiDgIV
+FRQeAgK0eWgCBg6yCxACQG6VV4DGh0dEgr57a581LDaMUVZ6UCUoVIOCAWJaNW82Nm42V4BUKVmUxGwq
+bMOUWSIgkBweRW+KRipHi29FAAEATP/qBJUFsAAhACpAJwAEAAMABANwAgEAAAFZAAEBFksAAwMFWwAF
+BR4FTCcXJREREAYGGisBITUhFSERFB4CMz4DNzYmJzcWFgcOAyMGLgInAbX+lwOo/noTJjgkNU81GwIC
+IR2zGyoDAj9skFJNeVUvBAUYmJj8QS1POiEBO2mSWGTKZAFiymeHzYtHAStai18AAAEASf/pBGoEOgAh
+ACpAJwAEAAMABANwAgEAAAFZAAEBGEsAAwMFWwAFBR4FTCkXJREREAYGGisBITUhFSERFB4CMz4DNzYm
+JzMeAwcOAyMGJicBmv6vA4X+hhMnOCUwSDIZAgIhHbINGRMLAQI9aIlOm64IA6SWlv21Lk46IQErTmxC
+T6hOJ1FSUilup3E5ArG/AAABAGz/7ARvBcUAPgBOQEsdAQAHAUoABQYHBgUHcAACAAEAAgFwAAcIAQAC
+BwBjAAYGBFsABAQdSwABAQNbAAMDHgNMAQA9OzMxLSwoJhYUEA8LCQA+AT4JBhQrASIOAhUUHgIzMj4C
+NzMUDgIjIi4CNSY2Ny4DNTQ+AjMyHgIVIy4DIyIOAhUUHgIzMxUCdU99Vi0xWoFRRHBRLQG5VouwW3PD
+j1EBh3w3WD0hSoe9c1+sgUy5AS1NaDxSe1EpJk12ULYCmh9BY0U8ZEgoK0pkOW+gaDE4bJ9ngKsqF0JR
+XjNmm2k1OGiVXTZcQiYoRl43OFtBJJgA//8ASQKLBIgDIgBHAYj/bgAAUzNAAP//AE4CiwSNAyIARwGI
+/3MAAFMzQAD//wCm/moEOwAAAicAQQAL/wEBBgBBCwAACbEAAbj/AbAzKwAAAQHsBA8C/wYdAAsAEEAN
+BgUCAEgAAABpGgEIFSsBND4CNxcGBhUVIwHsFy1AKmUvL7UEoS9oZVwkSEeUVpUAAAEBzQQHAuAGFgAL
+ABBADQYFAgBHAAAAaRoBCBUrARQOAgcnNjY1NTMC4BctQCplLy+1BYMvaGVcJEhHlFaWAAABAbz+0QLT
+AOEACwAQQA0GBQIARwAAAGkaAQgVKyUUDgIHJzY2NTUzAtMXLUAqaS8vuUwvZ2RdJElGlFaX//8BzwQH
+AuMGFgBHAWgErwAAwABAAP//AUkEDwOhBh0CJwFn/10AAAAHAWcAogAA//8BLQQHA4wGFgInAWj/YAAA
+AAcBaACsAAAAAgEv/s8DaADfAAsAFwAUQBESEQYFBABHAQEAAGkbGgIIFislFA4CByc2NjU1MwUUDgIH
+JzY2NTUzAkYXLUAqaS8vuQEiFy1AKmkvL7lLL2hkXSRJRpRWl5QvaGRdJElGlFaXAAEAdwAABFUFsAAL
+ACNAIAAEBDxLAgEAAANZBQEDAz9LAAEBPQFMEREREREQBggaKwEhESMRITUhETMRIQRV/mu5/nABkLkB
+lQOh/F8DoZkBdv6KAAEAef5gBFYFsAATADRAMQAGBjxLCAEEBAVZBwEFBT9LCQEDAwBZAgEAAD1LAAEB
+QQFMExIRERERERERERAKCB0rISERIxEhNSERITUhETMRIRUhESEEVv5puf5zAY3+cwGNuQGX/mkBl/5g
+AaCXAwqZAXb+ipn89gAAAQGaAhcDMQPcABUAGEAVAAABAQBXAAAAAVsAAQABTykkAggWKwE0PgIzMh4C
+FRUUDgIjIi4CNQGaHTRLLy9MNRwcNUsvL0s1HQMWK0k0Hh40SSs6K0g1HR01SCsA//8BXP/tBDoBBwIn
+ABD/bAAAAAcAEAEmAAD//wEJ/+0FJgEHAicAEP8ZAAAAJwAQAJwAAAAHABACEgAAAAYANv/rBKAFxQAh
+ADcAOwBRAGcAfQBOQEs7OgIKCzkIAgcAGQECBgNKAAoABQAKBWMBAQAJAQcGAAdjAAsLBFsABARESwgB
+BgYCWwMBAgJFAkx5d25sY2EpKS0pKSQpJCQMCB0rATQ+AjMyFhc2NjMyHgIVFRQOAiMiJicGBiMiLgI1
+ATQ+AjMyHgIVFRQOAiMiLgI1EycBFwMUHgIzMj4CNTU0LgIjIg4CFQUUHgIzMj4CNTU0LgIjIg4CFQEU
+HgIzMj4CNTU0LgIjIg4CFQFWHz5bPDpYHx9XOj1bPh8fPVs8OlkfH1c5PVw+H/7gHz5bPD1bPh8gPVo8
+PFw+IHlEAxBEfgsaKR4dKBgLCxkpHR4oGQv+oAsZKR4dKBgLCxkoHh0oGQv+4AsaKB4cKBkLCxkoHh0o
+GQsBLzhlTS4qIyMqLk1lOCw4Zk0tKSMjKS1NZjgDqThmTS4uTWY4LDhlTC4uTGU4/T9UAoFU/MMeOi0b
+Gy06HiweOS0cHC05HiweOi0bGy06HiweOS0cHC05HgNRHjktGxstOR4sHjktHBwtOR4AAQGMAJkDQAO1
+AAYAHkAbAwEAAQFKAAEAAAFVAAEBAFkAAAEATRMRAggWKwEBIwE1ATMCPgECjf7ZASeNAib+cwGEEwGF
+AAEBjACYA0ADtQAGACZAIwUBAgABAUoCAQEAAAFVAgEBAQBZAAABAE0AAAAGAAYTAwgVKwEBFQEjAQEC
+GgEm/tqOAQL+/gO1/nsT/nsBjgGPAAABASsA1QOeBNEAAwAGswIAATArJScBFwGccQIBctVCA7pCAAAC
+AQ8COAQYBcMACgAOACtAKA0BAAQIAQEAAkoFAQADAQECAAFhAAICBFkABAQ8AkwREhERERAGCBorATMV
+IxUjNSEnATMBIREHA4GXl6P+NAMByan+QwEaFgNvfrm5XgJ0/awBiCwAAAEBSwKLA8kFugAVAGtLsCNQ
+WEAKAQECABIBAQICShtACgEBAgQSAQECAkpZS7AjUFhAGgACAgBbBQQCAAA8SwMBAQEAWwUEAgAAPAFM
+G0AXAAICAFsAAAA8SwMBAQEEWQUBBAQ8AUxZQA0AAAAVABUTIxUjBggYKwEXNjY3Mh4CFREjETQmIyIG
+BxEjEQHMHSRvSjxfRCSqTUM7SxSqBat7QEkBJEt0UP4EAdxqWTwx/c4DIAAAAQBpAAAEdgXEADMAS0BI
+AAkKBwoJB3ALAQcMAQYFBwZhDQEFBAEAAQUAYQAKCghbAAgIREsDAQEBAlkAAgI9AkwzMjEwLy4pJyMi
+JRERERYRERQQDggdKwEhFxQGByEHITUzPgM1JyM1MycjNTMnND4CMzIeAhUjNC4CIyIOAhUXIRUhFyED
+Iv6rAx0fAuIB+/pLGyQWCQOsqAWjnwZCd6NgYJhpOLkoQ1cwM1lAJQYBYf6jBAFZAddHRYQwl5cHOElR
+IEd6inu5ZqJxPDhmjlc/WTkbJ0lrQ7l7igAAAgB//+wEswWwACkANgCdS7AZUFi1CwECAQFKG7ULAQUB
+AUpZS7AZUFhAMgAIBgsGCAtwAAoABAEKBGMACwsGWwAGBjxLAwEAAAdZCQEHBz9LAAEBAlsFAQICRQJM
+G0A2AAgGCwYIC3AACgAEAQoEYwALCwZbAAYGPEsDAQAAB1kJAQcHP0sABQU9SwABAQJbAAICRQJMWUAS
+NjQsKikoERQhESQVJSUQDAgdKwEjERQeAjMyNjcXBgYjIi4CNREjDgMjIxEjETMyHgIXMxEzETMBMzI+
+AjU0LgIjIwSesA8ZJBUUKwwZF1EqNFY/I1kINVl7TkW5/k57WDYIWbmw/JpFLUApExMoQS1FA6v9fCw8
+JREKBIQRFiRNeFMCg1KKYzf9ywWwOGOJUgEG/vr+kjJSaDg4a1MyAAABAH//6wQ5BcQALwBQQE0hAQgH
+IgEGCAkBAQAKAQIBBEoJAQYKAQUEBgVhCwEEAwEAAQQAYQAICAdbAAcHREsAAQECWwACAkUCTC8uLSwr
+KiUkERERFCUkEAwIHSsBIR4DMzI2NxcGBiMiLgInIzUzNSM1Mz4DMzIWFwcmJiMiDgIHIRUhFSEDbv5+
+AjNagE87bjQSOHg/dcONUAOzs7OzBVGMwHQ/dT0SNG88Tn5aMwMBgv5+AYICH2ebZzQREZoPEEiO04t6
+inuIzopGEQ6bEBMyY5Zke4oAAAQASf/rBJQFxQArAEEAVwBbAA1AClpYUUY7MA8EBDArARQOAiMiLgI1
+NTQ+AjMyHgIVIzQuAiMiDgIVFRQeAjMyPgI1EzQ+AjMyHgIVFRQOAiMiLgI1MxQeAjMyPgI1NTQuAiMi
+DgIVBScBFwJMI0JfOz1hQyMjQmA9PF9CJIoPHiweHi0dDw8eLR8eKx0PzCNDYD09YEMjI0JgPT1hQyOL
+Dh4uHx4tHg4OHi0fHy0eDv6ccQIBcgQeNF1FKDBSbTxNPW1TMClGXTUbMiYWHzJCIk0iQDIfGCYwGP1H
+PW1SMDBSbT1OPW1SMDBSbT0jQDMeHjNAI04iQTMeHjNBIpBCA7pCAAACAN3/6wPzBckAJAAxAAi1LSUS
+AAIwKwUiLgI1NQYGIzUyNjcRND4CMzIeAhUVFA4CBxUUHgIzAz4DNTU0JiMiBhUDVGyeaTMxaDg6aC8p
+UHNKPGRIJzRlk2AXOFpE7TZPNBotKUI7FUJ3pmUODA2wDg0B31aMYzYtU3RIKU2po5E0V0RtTSkCPydg
+a3E4K05Qc2oABAB5AAAEdgXAAAkAHwA1ADkADUAKODYvJBkOBQAEMCshIwETIxEzAQMzFzQ+AjMyHgIV
+FRQOAiMiLgI1NxQeAjMyPgI1NTQuAiMiDgIVEyE1IQLjsP71AbCvAQwBsFMVKDwmJz0oFRUoPCcnOykV
+ZQQNFxMTFw0EBQ0XExIXDAXZ/s0BMwOT/G0FsPxxA4+1KEg2Hx82SCjOKEc1Hx81RygJFycdEREdJxe8
+FigdEREdKBb91V8AAAIAZwOXBDcFsAAMABQACLUTDwYBAjArAQMjAxEjETMTEzMRIwEjESMRIzUhA92M
+NItacI+QcFr+DJRbkwGCBSH+dgGJ/ncCGf5xAY/95wHI/jgByFEAAgCZ/+wElAROAB0AJgAItSIeDgIC
+MCslBgYjIi4CNTQ+BDMyHgIVFSERFhYzFjY3ASIGBxEhESYmBBdVumNuv41SKUhjdYFCZ7WFTv0AN4xO
+XrlZ/pBMjDkCHDaIXjU9WZnMc0yPfGdKKVKSxnMv/rgzOwE8PwMqQjj+6wEeMz4A//8AUP/2BLkFrwAv
+Abb/GALoOZoAJgF2+AABDwG8AYYAADmaAAmxAAG4AuiwMysA//8AMv/2BMEFugAvAbj/GgLqOZoAJgF2
+H/cBDwG8AY4AADmaABKxAAG4AuqwMyuxAQG4//ewMyv//wAk//oErQWyAC8Buv8EAus5mgAmAXYIAAEP
+AbwBegAEOZoAEbEAAbgC67AzK7ECA7AEsDMrAP//AED/9gSnBbIALwG7/y8C6zmaACYBdtMAAQ8BvAF0
+AAA5mgAJsQABuALrsDMrAAACAH7/6wRGBewAJgA8AAi1MScbEAIwKwEyFhcuAyMiBgcnPgMzMhYWEhUV
+FA4CIyIuAjU1ND4CFyIOAhUVFB4CMzI+AjU1LgMCUFumPAtCZIJKTodHEB0/S1s6j8+HQUF8tXRys3xB
+P3itgE1wSiQkSXBMT3FKIwYoSGsD/kxFabB+RyAblw0ZFAt83P7RtDuI7rBlUY3BcRdptIRLmDdee0QX
+TIlnPUl+qGBCHElBLQAAAQCn/ysEJQWwAAcABrMGAAEwKwUjESERIxEhBCW5/fS5A37VBe36EwaFAAAB
+ADP+8wSYBbAADAAGswgDATArAQEhFSE1AQE1IRUhAQNY/bwDhPubAmD9oAQZ/McCRQJB/UqYjwLMAtKQ
+mP1CAAABAKkCiwPsAyIAAwAYQBUAAQAAAVUAAQEAWQAAAQBNERACCBYrASE1IQPs/L0DQwKLlwAAAQA5
+AAAEkgWwAAoABrMFAwEwKwEXNwEzASMDIzUhAhgWGQGOvf3ijfW5ATsBUWlpBF/6UAJ0mgADADUA4ASa
+A90AKQBDAF0ACrdXSD0uGQQDMCsBFA4CIyIuAicOAyMiLgI1NTQ+AjMyHgIXPgMzMh4CFSM0LgIjIg4E
+BxUeBTMyPgI1IRQeAjMyPgQ3NS4FIyIOAhUEmiRHa0Y0VkU1ExM0RVY0R2pHJCRGakc0V0U0ExM1RVY1
+RmpHJHwQJT0tHjYtJRwRAwMRHCQuNR4uPSUQ/JMQJT0uHjUtJRsRAwMRGyUtNh4tPSUQAkpHg2Q8LEZW
+KipWRiw8ZINHKkaDZDwsRlYqKlZGLDxkg0YwV0MoHC44NzEPHQ8xNzgtHSdDWDExWEMnHS04NzAQHQ8x
+NzguHChDVzAAAQD4/ksD0wYrACAABrMUAgEwKwUUBiMiJic3HgMzMjY1ETQ+AjMyFhcHJiYjIgYVEQKq
+qJoeNR0OCBwdGgdCRy5Xfk8lRiUYES0dWlxZp7UICpMDBQMCaloFG1aGXDEMCY4FBnFg+uUAAAIAjQEU
+BD4D/wAhAEMACLVDMiEQAjArEzY2MzYeAhceAzMyNjcXBgYjIi4CJy4DBwYGBwc2Njc2HgIXHgMzMjY3
+FwYGIyIuAicuAwciBgeXMHpDJzs1MyAdMDE4JEN6LwowekIlNzEwHh80NDwnQ3ovFDB6Qyc7NTMgHTAx
+OCRDei8KMHpCJTcxMB4fNDQ8J0N6LwNpRE4BCxQbEA8ZEgtORKtDTwsSGQ8QHBQLAQFORP9DTgEBCxQc
+Dw8aEgtPRKtETgoTGQ8QGxQLAU5EAAABAKkAtQQmBEEAEwAGswwCATArASEHJzchNSE3ITUhNxcHMxUh
+ByEEJv38XE5C/u8BYoD+HgIzSk0x5P7MgAG0AW24M4Wg/6GUM2Gh////ALsACQQNBJoAZwAeABMAvEAA
+OZoBBwGIABL9fgARsQABsLywMyuxAQG4/X6wMysA//8AwgAHBDUErQBnACAAEADPQAA5mgEHAYgAGv18
+ABGxAAGwz7AzK7EBAbj9fLAzKwAAAgCOAAAEPwWwAAUADQAItQwIAwACMCsBMwEBIwEhAScHAQEXNwIe
+jQGU/m+N/m0C8v70ERH++gEMEBIFsP0n/SkC1wIKMzP99v33MzMAAQEu/1YCKADvAAsABrMKBQEwKyUU
+DgIHJzY2NTUzAigRJDclaSUlsKkqXFpTIEg+f0tJABYAXAAKBIcEBgANABwAKgA6AEAARgBMAFIAWwBf
+AGMAZwBrAG8AcwB7AH8AgwCHAIsAjwCTADFALpKQjoyKiIaEgoB+fHl0cXBtbGloZWRhYF1cWFNQTkhH
+REE8Ozk0Jh8ZDgkCFjArATQmIyIGFRUUFjMyNjUXMjY1NCYnNjY1NCYjIxEnFAYjIiY1NTQ2MzIWFQUU
+BiMiJjUjFBYzMjY1NSMBNTMVMxUhNTM1MxUBNTMVIxUlNTMVIzUBMhYVFAYjIzUDNTMVMzUzFSE1MxUT
+NTMVMzUzFSE1MxUTMzIWFRQjIwUjNTMRIzUzESM1MwEjNTMRIzUzESM1MwHwRjk5Rkc5OUWfMzkcHBcX
+PjdnWCgjJCkpIyMpAg4eFxofMzwwLToy/JE+bALXbT371apsA0OqPf5FHRsbHUYkmUOZ/bCYQ5lDmf2w
+mGczISBBM/5RPj4+Pj4+A+09PT09PT0CJTZCQjY+NkJCNncrKxcnCAkiFSso/tF3JisrJj4mKysmVRge
+GBouLTIt0P1qrm8/P2+uA1+dQF1dQJ1d/jEaFhUYXQHPQEBAQEBA/EQ/Pz8/Pz8CZhAXLFKK/qeJARaJ
+/qeK/qeJARaJAAAFAA/91QSvCHMAAwApAC0AMQA1AA9ADDQyMC4sKhIEAgAFMCsJAwU0PgI3PgM1NC4C
+IyIOAgczNjYzMhYVFA4CBw4DFRcjFTMDMxUjAzMVIwJiAk39s/2tAroGDBELFi0kFyVFZkA4YUkrAcsC
+KRglIBEYGwodIxUIysrKbAQEAgQEBlL8MfwxA8/7GScfHRAfNzlAKUBnSSceQWVGNzBANBozLycNJCgm
+MjBbqv1WBAqeBAABAToAAAOkAyAAHgAsQCkCAQAEAUoAAgEEAQIEcAADAAECAwFjAAQEAFkAAAA9AEwa
+JBInEAUIGSshITUBNjY1NCYjIgYHIzQ+AjMyHgIVFA4CBwchA6T9qQEgQThCOkpHAZ4qTm9FQmpKKBsz
+RyuvAY9sAQ88VyMxPUs6NmBHKSE+VzcoR0VHJ5EAAAIBEQTkA+8G+QAGACYACLUmFgUAAjArASMnByMB
+MzcUDgIjIi4CIyIOAhUnND4CMzIeAjMyPgI1A++rxcSqASSVuhkrOiIlMissHhAdFw9NGSs6Ih8yLjAd
+EB4XDgTksLABBvghPzEeFhsXERshERMhQTIfFhoWEBohEQACAPwE5AS6Bs8ABgAaAAi1EQcFAAIwKwEj
+JwcjATMXJzY2NTQuAiM3MhYVFA4CBwcD3avGxqoBErz2AT1AGCc0HAZ7jBcmMRkBBOS6ugEGfIMFFyMT
+GRAHXFZLIS8fEgM8AAIAEATkA/kGlQAGAAoACLUJBwUAAjArASMnByMBMwUjAzMD+cWqqsQBIpj+j4zJ
+yATknp4BBlgBAwACAQsE5AT0BpUABgAKAAi1CQcCAAIwKwEzASMnByMBMwMjAi+XASPFqarGAyLHyI0F
+6v76np4Bsf79AAACATAEpgOsBqcAFQAZAAi1GBYEAAIwKwEUDgIjIi4CNTMUHgIzMj4CNScjJzMDrC5T
+dUhJdVMtlRQpQCwrPykUU5fS2AWwO2JGJydGYjseNikXFyk2HinOAAABAfkEjgLwBjsACwAGswoFATAr
+ATQ+AjcXBgYVFSMB+RopMRhrIxu5BQ8sWVBCFVM7aj14AAACADYAAASOBI0ABwAKACVAIgoBBAIBSgAC
+BAJyAAQAAAEEAGIDAQEBPQFMERERERAFCBkrASEDIwEzASMBIQMDZv36brwB3aUB1rv9yQGPxwEX/ukE
+jftzAa4B+wAAAwDQAAAERgSNABoAJwA0ADxAOQ4BAwQBSgAAAAUEAAVjAAQHAQMCBANjAAICAVsGAQEB
+PQFMGxsAADQyKigbJxsmHhwAGgAZIQgIFSszESEyHgQVFA4CBx4DFRQOBCMBESE+AzU0LgInJTM+AzU0
+LgInI9ABnTNpYlY/JCA1RygxVD0kIjxTYGk1/vQBDCxYRismQVYv/uv5KFJCKy5KWivjBI0OHjBHXj0w
+TTsrDgwuRVs3PWBKNCIQAhL+hQETK0UzNEkvFwGNAREnQC80QyYPAQABAG7/8AQ2BJ0AJwA0QDEAAgMF
+AwIFcAYBBQQDBQRuAAEAAwIBA2MABAQAWwAAAEUATAAAACcAJykiFCkkBwgZKwEOAyMiLgInNT4DMzIe
+AhcjJiYjIg4CBxUeAzMWNjcENgxSfqNedbZ9QgEBRIG5d16heU4MuRWHfVV4TCMBASBIdVSAjRcBeWCS
+ZDNYlsZvZXHHllc2ZpRedoBDb49LZkmOcEUBeXoAAAIAtwAABFMEjQANABsAKkAnAAAFAQMCAANjAAIC
+AVsEAQEBPQFMDg4AAA4bDhoRDwANAAwhBggVKzMRIR4DFxUOAwcDETM+Azc1LgMntwFrec2VVQEBWJnQ
+e6WlXI9jNQEBMV+MWwSNAlCRyns/fsqPTgED9PyjATlok1pBWJFpOgEAAAEAyAAABCMEjQALACdAJAAD
+AAQFAwRhAAUAAAEFAGEAAQECWQACAj0CTBEREREREAYIGisBIREhFSERIRUhESEDxf3AAp78pQNV/WgC
+QAIO/omXBI2Z/rIAAAEA5wAABD0EjQAJACFAHgACAAMEAgNhAAQAAAEEAGEAAQE9AUwREREREAUIGSsB
+IREjESEVIREhA+T9w8ADVv1qAj0B8/4NBI2Z/pgAAAEAfP/wBEEEnQAtADdANCkAAgQFAUoAAgMGAwIG
+cAABAAMCAQNjAAYABQQGBWEABAQAWwAAAEUATBEVKSIUKSQHCBsrJQ4DIyIuAic1PgMzMh4CFyMmJiMi
+DgIHFR4DMzI+Ajc3ITUhBEEpZ3R8PHnAhkkBAUJ+u3pZnXpRDrcZjXBXeUshAQEoU35XIUZDPhkB/usB
+zJYxQCYPV5fKdFR0y5dXL1yLW2tuRHKRTFZOknBFBRAdGO6QAAEAmwAAA/kEjQALACFAHgAEAAEABAFh
+BQEDAwBZAgEAAD0ATBEREREREAYIGishIxEhESMRMxEhETMD+bL+BrKyAfqyAfL+DgSN/f0CAwAAAQDZ
+AAAEEASMAAsAIUAeAAAFAQECAAFhBAECAgNZAAMDPQNMEREREREQBggaKxMhFSERIRUhNSERIdkDN/69
+AUP8yQE7/sUEjKH8taCgA0sAAAEAlv/wA+YEjQAXAB9AHAAAAgByAAIDAnIAAwMBWwABAUUBTCQUJRAE
+CBgrATMDDgMjIi4CJzMUHgIzMj4CNwMovgICRHGUUFeYc0kIvihEWDEvUDwjAgSN/OpfkmMzLF2RZT5Z
+OBkhPVk5AAEAtAAABIAEjQAMAB9AHAoGAQMAAQFKAgEBAQBZAwEAAD0ATBITERIECBgrAQcRIxEzETcB
+MwEBIwIAk7m5ggGM4/4iAgDhAgeO/ocEjf3WjwGb/fn9egABANEAAARSBI0ABQAZQBYAAgACcgAAAAFa
+AAEBPQFMEREQAwgXKyUhFSERMwGVAr38f8SXlwSNAAEAmwAABDoEjQAMACdAJAgFAgIAAUoAAgABAAIB
+cAQBAAABWQMBAQE9AUwREhIREQUIGSsBEzMRIxEDIwMRIxEzAm3c8bDag+Kw+AJYAjX7cwO//X8Cc/xP
+BI0AAQDCAAAEDwSNAAkAHkAbBwICAAIBSgMBAgIAWQEBAAA9AEwSERIQBAgYKyEjARMjETMBAzMED6z+
+CwWxrgH1BrADbPyUBI38kwNtAAIAgv/wBEoEnQAVACsAHUAaAAEAAgMBAmMAAwMAWwAAAEUATCkpKSQE
+CBgrAQ4DIyIuAic1PgMzMh4CFycuAyMiDgIHFR4DMzI+AjcESgE9ebR4d7R6PwEBPnq0d3i1eT0BtwEf
+RnNUVHJHHwEBIEdyVFVzRR4BAiRuzJxeXp3MbUNtzJ5fXp3NbgJHknVKS3aRRkVHkXdLS3aSRwAAAgBe
+/zYEZwSdABoAMAAoQCUFAQADAUoHBgIARwABAAIDAQJjAAMDAFsAAABFAEwpKSkpBAgYKwEOAwcXByUG
+IyIuAic1PgMzMh4CFycuAyMiDgIHFR4DMzI+AjcEZQEdOFI1333+9j1Aer+ERwEBRoS+enq/hEYBuAEm
+UH1YV3xQJwEBJ1F9V1h8UCUBAiRKi3tmJqNvyA5ams1zQ3PNm1tams50Ak6TckVGc5NMRU2TdEZGcpRO
+AAIAkAAABCwEjQASAB8AKUAmDwEABAFKAAIABQQCBWMABAAAAQQAYQMBAQE9AUwoISohERAGCBorASER
+IxEhHgMVFA4CBwEVIwEzPgM1NC4CJyMCYf7ouQGqVKF9SyRAVzIBIsf95PYvW0ctK0heMvEBwf4/BI0B
+KFaGXz9gSzkW/hoKAlgBGDFLNThPMhgBAAEAiv/wBDkEnQBFADRAMQABAgQCAQRwAAQFAgQFbgAAAAIB
+AAJjAAUFA1sAAwNFA0xCQDw7NzUfHRkYFBIGCBQrATYuBCcuAzU0PgQzMh4CFyMuAyMiDgIVFB4EFx4D
+FRQOBCMiLgInMx4DMzI+AgN/ARotOj8/G0WZgVMnQlhjZzBUn35RBrsCL0xgMihaTDIfNEFDQBlGknhM
+KERaZGkxVquKWga8AjdWajYoXU81ASokNiodFhAHETNSeFY5XUczIRArWYZaN04yFhAnQTEiNCgdFQ8G
+EjdVeVU7XUYxHw4qWYpgPVMzFQ4lQAABAF0AAARpBI0ABwAZQBYAAwIBAAEDAGEAAQE9AUwREREQBAgY
+KwEhESMRITUhBGn+V7z+WQQMA/T8DAP0mQAAAQC1//AEKwSNABkAIUAeBAMCAQIBcgACAgBbAAAARQBM
+AAAAGQAZJRUlBQgXKwETDgMjIi4CJxMzEx4DMzI+AjcTBCoBAkd4oFtcoHdGAQG1AQElQ187O19DJQEB
+BI389F+UaDY2ZpVgAwz89DtdQCIiQF07AwwAAQBWAAAEgwSNAAgAG0AYAQEBAAFKAgEAAQByAAEBPQFM
+ERETAwgXKwEXNwEzASMBMwJQHB0BMcn+QK7+QcgBNmtqA1j7cwSNAAABAC8AAAS7BI0ADAAgQB0KBQIB
+AAFKBAMCAAEAcgIBAQE9AUwSERIREQUIGSsBEzMDIwMDIwMzExMzA3iXrOmfvMGf6KuYuJoBUwM6+3MD
+PvzCBI38xgM6AAABAGAAAARmBI0ACwAfQBwJBgMDAQABSgMBAAABWQIBAQE9AUwSEhIRBAgYKwEBMwEB
+IwEBIwEBMwJfAR3b/ngBl9z+2P7a3AGU/nXbAtoBs/2+/bUBu/5FAksCQgAAAQBNAAAEgQSNAAgAHEAZ
+BgMCAQABSgIBAAEAcgABAT0BTBISEQMIFysBATMBESMRATMCZgFH1P5Au/5H1AJEAkn9CP5rAaEC7AAB
+ALkAAARCBI0ACQAnQCQJAQIDBAEBAAJKAAMAAgADAmEAAAABWQABAT0BTBESERAECBgrJSEVITUBITUh
+FwGfAqP8dwKL/X4DZwGXl3wDeJl5AAACAVIE4AOaBwMAEQAlAAi1HBIEAAIwKwEUDgIjIi4CNTMWFjMy
+NjcnJzY2NTQuAiM3MhYVFA4CBxcDmipLbEJCbE0qkQFHTEpGAdIGRUcbLDogB4yZGio2GwMFsC9MNx4e
+N0wvMENDMBF8BBYfERcNBlJMRB0pGxADPgAAAQFbAAACzwMVAAYABrMFAAEwKyEjEQc1JTMCz53XAWIS
+Alk5gHUAAAIBQgTfA6AGigATABcACLUWFAQAAjArARQOAiMiLgI1MxQeAjMyNjcnMwcjA6AsT29ERXBP
+LJgSJTkoTUcBX5mkZgWwL003Hh43TS8YKx8SRDDaxgAAAQE4//UDlAMgAC8ABrMeDwEwKwEzMjY1NCYj
+IgYHIzQ+AjMyHgIVFAYHFhUUDgIjIi4CNTMWFjMyNic0JiMjAgNURkxCQzlKAZ0tTWg8QGxOK0dBli9T
+cEA5a1MzngFPQURMAVdIVAHLOjMtOjAsM1I5Hx05VDc4WhkqjjhWOh8bOVg9Ljs8Mz80AAACASMAAAOo
+AxUACgAOACtAKA0BAAQIAQEAAkoFAQADAQECAAFhAAQEAlkAAgI9AkwREhERERAGCBorATMVIxUjNSEn
+ATMBMxEHAz1ra53+iQYBeaH+hN8RASuCqalmAgb+FgEhHAABAUD/9QOMAxUAKAAGsxEBATArARMhFSEH
+NjYzMh4CFRQOAiMiLgInMxYWMzI+AjU0JiMiDgIHAVUyAd7+oxYUSi0/ZUYlJElvSjhoUTIDmwZKOyQz
+IhBQSBooHxgMAYMBkoSqCBUjQ2A8NmJKKx47VDYzMBUnNB8/TAgMDwgAAAEBMAAAA5sDFQAGAAazBQEB
+MCsBASMBITUhA5v+oqYBXv47AmsCu/1FApOCAAADAT7/9QOOAyAAHwAvADsAnbYTAwICBQFKS7AKUFhA
+GwABAAQFAQRjAAUAAgMFAmMAAwMAWwAAAD0ATBtLsAxQWEAbAAEABAUBBGMABQACAwUCYwADAwBbAAAA
+RQBMG0uwDlBYQBsAAQAEBQEEYwAFAAIDBQJjAAMDAFsAAAA9AEwbQBsAAQAEBQEEYwAFAAIDBQJjAAMD
+AFsAAABFAExZWVlACSQmJCguKgYIGisBBgYHFhYVFA4CIyIuAjU0NjcmJjU0PgIzMh4CAzQuAiMiBhUU
+FjMyPgIDNCYjIgYVFBYzMjYDewFANz9MLk9sPj5tUC5LQDdAKUplPDtmSiqJFiUzHj1OTj4eMiYVFUE2
+NkFCNjZAAkM7WBoaYUM5VTkcHDlVOUNhGhpYOzZSOB0dOFL+axopHA85NTY5DxwpAXEvNjUwLzc3AAAB
+ATUCiwOyAyIAAwAGswIAATArASE1IQOy/YMCfQKLlwAAAwHRBEADqAZyAAMAFwAjAAq3IBoSCAIAAzAr
+ATMHIwc0PgIzMh4CFRQOAiMiLgI3FhYzMjY3NCYjIgYC4sbcfH8cLz4jIj4tGxstPiIjPi8cVQEyJCMw
+ATEjJDIGcrjXJD4sGRksPiQkPCsYGCs8JCMyMiMmMjIAAgH1BIIDtwXEAAUADgAItQ0JBAECMCsBEzMV
+AyMnNjY3FwYHFSMCr2CouFC6CTMtSDMDewSeASYV/tWKO10eA1NmhgACAXQE2QPCBtAAEwAvAAi1LyEE
+AAIwKwEUDgIjIi4CNTMWFjMyPgI1ExQOAiMiLgIjIgYHJzQ+AjMyHgIzMjY1A8IqTW1DQ21NKpUBRE0m
+NyQRjBgsPSQoNi8vISMuAVQZKz0lITUzNCAiMAWuL084Hx84Ty8xRRMgKxgBCiRBMR0XHRczJhUkQjIe
+Fx0XMyYAAAECBv6ZAr8AmgADABhAFQABAAABVQABAQBZAAABAE0REAIGFisBIxEzAr+5uf6ZAgEAAQFg
+/ksDEgCXABEAKUAmCAEBAgcBAAECSgMBAgECcgABAQBcAAAAIQBMAAAAEQARJyMEBhYrJRUUBiMiJic3
+HgMzMjY1NQMSqJoeNR0OCBseGgdCR5fwp7UICp0DBQMCYFrwAAIAzAAABEsEjQAOABsAKUAmAAEABAMB
+BGMAAwUBAgADAmMAAAA9AEwAABsZEQ8ADgANIREGCBYrAREjESEeAxUUDgIHJSE+AzU0LgInIQGEuAHK
+VJ16Skp5nlT+7gESMVxFKipFXDH+7gG2/koEjQEuW4lcX4dXKgGYARcyTTc2UDUcAQAAAQCpAAAEtgWw
+AAwAJ0AkCgEAAwFKAAMAAAEDAGEEAQICFksFAQEBFwFMEhEREREQBgYaKwEjESMRMxEzATMBASMCDau5
+uZwBu9T+EQIY4wKT/W0FsP16Aob9P/0RAAEA0v/sBEEEnQAvAGJADSIhDg0EAQIvAQMAAkpLsBlQWEAc
+AAECAAIBAHAABAACAQQCYwAAAANbBQEDAz0DTBtAIAABAgACAQBwAAQAAgEEAmMAAwM9SwAAAAVbAAUF
+RQVMWUAJLiMVJCYiBggaKyUWFjMyPgI1NCYjIzUTJiYjIg4CFREjETQ2MzIeAhcBHgMVFA4CIyImJwIL
+IFQ2Mk42HYiHVO0dVD8/UzEVuMTMQXBjVyf+7lGCWzE7aZFXOW83tRQfITtRMWJViQEnFycsS2U4/Q8C
+8dXXHTFDJv62By9PbUZajGAyFxr//wAAAAAAAAAAAgYAAwAA//8A2gIxA9cCyQIGAA8AAAAC/9QAAASO
+BbAAEQAjADdANAcBAQQBAAUBAGEABgYCWwACAjxLAAUFA1sIAQMDPQNMAAAjIiEfFhQTEgARABAhEREJ
+CBcrMxEjNTMRIR4DFxUOAwcTIxEzPgM3NS4DJyMRM7nl5QFRmO+lVwEBV6XvmEfclXascTcBAThwrHaV
+3AKalwJ/AmOx95ZrlvexYwECmv39AVGMvm9tb72LUAL+GQAC/9QAAASOBbAAEQAjADdANAcBAQQBAAUB
+AGEABgYCWwACAjxLAAUFA1sIAQMDPQNMAAAjIiEfFhQTEgARABAhEREJCBcrMxEjNTMRIR4DFxUOAwcT
+IxEzPgM3NS4DJyMRM7nl5QFRmO+lVwEBV6XvmEfclXascTcBAThwrHaV3AKalwJ/AmOx95ZrlvexYwEC
+mv39AVGMvm9tb72LUAL+GQABABoAAARKBgAAHQBithMCAgIDAUpLsCFQWEAgCAEGBQEAAQYAYQAHBz5L
+AAMDAVsAAQFHSwQBAgI9AkwbQCAIAQYFAQABBgBhAAMDAVsAAQFHSwAHBwJZBAECAj0CTFlADBERERET
+IxUjEAkIHSsBIRE2NjcyHgIVESMRNCYHIgYHESMRIzUzNTMVIQKX/u46qmpVi2I1uX92WZEtubKyuQES
+BNL+x1VfATFon239VwKrhYIBV0j87gTSl5eXAAABAEwAAASEBbAADwApQCYHAQMCAQABAwBhBgEEBAVZ
+AAUFPEsAAQE9AUwREREREREREAgIHCsBIxEjESM1MxEhNSEVIREzA63rtN7e/j4EOP4+6wM3/MkDN5cB
+RJ6e/rwAAAEAjv/sBCkFQAAnAEhARRMBBAMUAQUEAkoLAQoACnIHAQIGAQMEAgNhCAEBAQBZCQEAAD9L
+AAQEBVsABQVFBUwAAAAnACcmJRERFSklEREREQwIHSsBESEVIRUzFSMVFB4CMzI+AjcXDgMjIi4CNTUj
+NTM1ITUhEQJkAZz+ZOrqIDhJKR5APTURGhdCTlcrSH1cNdnZ/uQBHAVA/vqPupf7P1IxFAcKCwSDDhUP
+CClZjWT7l7qPAQYA//8AUQAABJAHIwImACMAAAEHAEL/mQFaAAmxAgG4AVqwMysA//8AUQAABJAHIAIm
+ACMAAAEHAHMAhQFXAAmxAgG4AVewMysA//8AUQAABJAHSAImACMAAAEHAJwAhwFbAAmxAgG4AVuwMysA
+//8AUQAABJAHUgImACMAAAEHAKIAkwFhAAmxAgG4AWGwMysA//8AUQAABJAHIAImACMAAAEHAGgADwFb
+AAmxAgK4AVuwMysA//8AUQAABJAHiwImACMAAAEHAKAADgGkAAmxAgK4AaSwMysA//8AUQAABJAIGAIm
+ACMAAAEHAb7//AGmAAmxAgO4AaawMysA//8Aa/5NBF0FxAImACUAAAAGAHc2AP//ALYAAAQ0ByMCJgAn
+AAABBwBC/48BWgAJsQEBuAFasDMrAP//ALYAAAQ0ByACJgAnAAABBwBzAHsBVwAJsQEBuAFXsDMrAP//
+ALYAAAQ0B0gCJgAnAAABBwCcAH0BWwAJsQEBuAFbsDMrAP//ALYAAAQ0ByACJgAnAAABBwBoAAUBWwAJ
+sQECuAFbsDMrAP//AK4AAAQeByMCJgArAAABBwBC/1sBWgAJsQEBuAFasDMrAP//AK4AAAQeByACJgAr
+AAABBwBzAEcBVwAJsQEBuAFXsDMrAP//AK4AAAQeB0gCJgArAAABBwCcAEkBWwAJsQEBuAFbsDMrAP//
+AK4AAAQeByACJgArAAABBwBo/9IBWwAJsQECuAFbsDMrAP//AI8AAAQ+B1ICJgAwAAABBwCiAGwBYQAJ
+sQEBuAFhsDMrAP//AGr/7ARhBzgCJgAxAAABBwBC/50BbwAJsQIBuAFvsDMrAP//AGr/7ARhBzUCJgAx
+AAABBwBzAIkBbAAJsQIBuAFssDMrAP//AGr/7ARhB10CJgAxAAABBwCcAIsBcAAJsQIBuAFwsDMrAP//
+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
+BHIF3gImAE8AAAEHAHMAnAAVAAixAQGwFbAzK///AFH+hgSQBbACJgAjAAAABgCkJQD//wCc/oYENgRO
+AiYAQwAAAAYApOoA////if/sBGEGVgImADEAAAEHAb/9lACSAAixAgKwkrAzK///ALYAAAQ0ByMCJgAn
+AAABBwBC/48BWgAJsQEBuAFasDMrAP//AKIAAAQqBxcCJgDZAAABBwBC/4IBTgAJsQEBuAFOsDMrAP//
+AIf/7ARFBeICJgBHAAABBgBCkBkACLECAbAZsDMr//8ApQAABCcFzAImAOwAAAEHAEL/fQADAAixAQGw
+A7AzK///AGUAAARyBbACBgC2AAD//wBh/igEgAQ6AgYAygAA//8AGgAABOEHQgImARUAAAEHAKkEWQFU
+AAmxAQK4AVSwMysA//8ANQAABGAGGgImARYAAAEHAKkEMAAsAAixAQKwLLAzK///AFn+LwRwBcQCJgDY
+AAABBgHB8ZYACbEBAbj/lrAzKwD//wCH/jkESgRNAiYA6wAAAQYBwQigAAmxAQG4/6CwMysA//8Aa/45
+BF0FxAImACUAAAEGAcH/oAAJsQEBuP+gsDMrAP//AI/+OQQzBE4CJgBFAAABBgHBE6AACbEBAbj/oLAz
+KwD//wA9AAAEeQWwAgYAOwAA//8AR/5gBJYEOgIGALoAAP//AK4AAAQeBbACBgArAAD//wAdAAAErgdK
+AiYA1wAAAQcAngANAZgACbEBAbgBmLAzKwD//wARAAAErAXzAiYA6gAAAQYAnvRBAAixAQGwQbAzK///
+AK4AAAQeBbACBgArAAD//wBRAAAEkAdKAiYAIwAAAQcAngAPAZgACbECAbgBmLAzKwD//wCc/+wENgYI
+AiYAQwAAAQYAngtWAAixAgGwVrAzK///AFEAAASQByACJgAjAAABBwBoAA8BWwAJsQICuAFbsDMrAP//
+AJz/7AQ2Bd4CJgBDAAABBgBoCxkACLECArAZsDMr//8AIAAABKsFsAIGAH8AAP//ACv/7ASpBE4CBgCE
+AAD//wC2AAAENAdKAiYAJwAAAQcAngAFAZgACbEBAbgBmLAzKwD//wCH/+wERQYJAiYARwAAAQYAngZX
+AAixAgGwV7AzK///AFr/6wRXBvICJgFDAAABBwBo//sBLQAJsQICuAEtsDMrAP//ALH/7ARfBE8CBgCb
+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
+KzorvywfLHAszy0LLW4tkC2xLeMuAy5GLnwu0y70L0QvWi9wL3kvsi/TL/UwDzBNMFUwcjCXMQMxIjFR
+MXExpjH+Mj8ymDNLM940BzSFNP41UjWiNgc2QTdUN8k4KziFOOE5MzlzObQ6FjphOsQ7XDvYPEA82z0/
+PZ0+Az5HPnE+uj78Pz0/tD/aQA5AUEB6QLtA5kEcQWNBrUHuQlJCx0MRQ4pD5EQBRElEi0UDRShFV0WO
+RbhF4EYARiFGfkaoRuBHC0dBR4hH0kgTSHdI7Uk4SaFKBUpjSrJK/EsqS3pLyEwcTMxNWk2PTcdOC05P
+TqpPBE9gT7tQSFDTUUZRpFHrUkBSyVNoVBtU8VWgVnFW8FdwV85YLFhrWMRZD1koWUBayFtVW6dcH1xC
+XGVcp1zrXS9dcV2mXdteCl45Xn9eyV9JX8Nf+mAtYJZhDGFMYcFiNWJ4YrxjBmNQY7ZkCmR1ZIpkoGTm
+ZVxl3GZLZrFnIGeJZ/xodWjiaUtprGoJalRqnmsaaxprGmsaaxprGmsaaxprGmsaaxprGmsaayVrMGtC
+a2Jrgmuha6xruWvGa/hsImxfbI5sm2ysbX9tom3Lbd1uEW5sbttveG/lcGhwsnEOcTlxenGSca5xynHi
+cjtyUXJycoxyqHMoc11zxXPsdAV0HnRFdF90X3VFdZ915XYjdlR2cXaPdrx213cGd3B3xXgHeDR4W3i4
+eOB5CXk/eWt5h3m1edt6KnqGes57RXtle6F7xnvzfCJ8R3xxfK98w3zufTR9Z32nfb5+Y350frB+0n8b
+fzR/Zn+pf9iAToBWgF6Ar4EAgWCBkYHuggCCEoIkgjaCSIJagmyCd4KJgpuCrYK/gtGC44L1gweDGYMr
+gz2DT4Nhg3ODhYOXg6mDu4PNg92D7oP/hBCEIIQwhECES4RbhGuEe4SLhJuEp4S4hMiE2ITohPiFCIUZ
+hSmFOYVJhVmFaYV6hYqFnIWshb6FzoYmhsKG1IblhveHCIcahyqHPIdMh16HcIeCh5KHpIe0h8aH1ogs
+iKyIvojOiOCI8IkCiRKJJIk0iUaJVoloiXqJjImdia+JwInSieKKNYqbiq2Kv4rRiuOK9YsHixmLK4s9
+i0+LYYtzi4WLl4uni7mLy4vdi+2L+YwLjBuMLYw9jE+MYIxyjIKMlIymjLiMyIzajOuM/Y0OjR+NMI1C
+jVSNZo12jYiNmo2ljbWNwY3TjeSN9o4HjhmOKo48jkyOXo5ujoCOkY8Hj2aPeI+Ij5qPq4+9j8+P4I/y
+kAKQFJAkkDaQR5BZkGmQe5CNkJ6QrpC+kM6Q35DvkQCREZEikTORQ5FTkWORc5GEkZWRpZG2kcaR15Ho
+kfmSCZIZkiqSO5JLkluSa5J7ktWS5ZL1kwWTFZMlkzWTRZOak6qTupPKk9yT7ZP+lA6UHpRwlICUkZSj
+lLSUxpTYlOqU+5UNlR2VLZU9lU6VXpVwlYCVkJWglauVu5XLldyV7JX8lg2WHpaVlqaWtpbGlteW55b3
+lwOXD5cglzGXPZdJl1WXZpdul3aXfpeGl46Xlpeel6aXrpe2l76XxpfOl9aX6Jf6mAqYGpgqmDuYTJhU
+mFyYZJhsmHSYhJiUmKSYtZjGmNiY6plamWKZdJl8mYSZlpmombCZuJnAmciZ2pnimeqZ8pn6mgKaCpoS
+mhqaIpoqmjKaQppKmlKarJq0mryazJrXmt+a55r3mv+bCpsamyybPJtOm16bcJuAm5Kbopuqm7KbvpvP
+m9eb6Zv6nAWcEJwhnDOcRZxVnGacbpx2nIicmZyqnLuczJzdnOWc7Zz1nQedF50fnTGdQZ1TnWOda51z
+nYWdlZ2nna+dv53RneGd854DnhWeJp44nkieWp5qnnKeep6Mnpyerp6+ntCe4Z7znwOfFZ8mnzifSJ9a
+n2qfdp+Cn4qflp+in66fup/Mn92f75//oBGgIaAzoESgVqBnoH2gkqCkoLSgxqDWoOig+KEKoRqhMKFE
+oVWhYaFzoYShlqGnobmhyaHboeuh/aIOoiCiMaJLol+icaKDopSipaK3osmi26Lsov6jDqMgozCjQqNT
+o2WjdqOQo6mju6PLo92j7aP/pBCkIqQzpD+kUaRdpGmke6SNpJ+kqqS8pMyk3qTwpQKlE6UlpTGlQqVU
+pWaleKWKpZumOaZSpmOmb6Z7poemk6afpqumt6bDps+m26bnpvOm/6cLpxenKac7p0OnlafmqDeoZaiT
+qNOpE6ktqUapWKlqqXypjqmgqbKp5qodqluqmaqhqrOqvqq+qr6rGAABAAAAAgBBdgxeKl8PPPUACwgA
+AAAAAMTwES4AAAAA0YKzW/wF/dUHmQhzAAAACQACAAAAAAAABM0AAAAAAAAEzQAABM0AAATNAWIEzQA9
+BM0AogTNACwEzQBrBM0B7gTNAWUEzQFABM0AoATNAHcEzQFiBM4A2gTNAfAEzQD8BM0AkQTNANAEzQBV
+BM0AXgTNAEsEzQC7BM0AjQTNAHAEzQCxBM0AlQTNAiIEzQHmBM0AqgTNAK0EzQCyBM0AvwTNAEAEzQBR
+BM0ArATNAGsEzQCbBM0AtgTNAL8EzQBkBM0AjQTNAK4EzQBiBM0ArATNAMYEzQCUBM0AjwTNAGoEzQC/
+BM0AXgTNALUEzQB2BM0ATATNAIsEzQBHBM0ASQTNAFcEzQA9BM0AcgTNAaoEzQDnBM0BlQTNAOcEzQCb
+BM0BnwTNAJwEzQCvBM0AjwTNAIsEzQCHBM4AmATNAIwEzQCuBM0AywTNANMEzQCwBM0AywTNAF0EzQCu
+BM0AegTNAK0EzQCMBM0BSQTNAK8EzQCOBM0AtATNAGIEzQAwBM0AbgTNAEQEzQCgBM0BQwTNAhwEzQFD
+BM0AMATNAfIEzQCTBM0AcQTNAGcEzQAhBM0B/wTNAFcEzQEfBM0AWgTNARwEzQDUBM0AvQTNAFcEzQEB
+BM0BaQTNAJwEzQE8BM0BQwTNAZoEzQC8BM0A0wTNAfgEzQHNBM0BggTNARAEzQDxBM0AMATNACQEzQAl
+BM0AzATNACAEzQC1BM0ARwTNAKgEzQCpBM0AKwTNAEkEzQBzBM0AegTNAK0EzQAYBM0AywTNAIAEzQBQ
+BM0AugTNADoEzQDLBM0ArwTNALgEzQBPBM0ALgTNAcgEzQCgBM0AYwTNAHcEzQCLBM0AtATNALAEzQCx
+BM0AwQTNATAEzQE7BM0B8gTNAZoEzQGOBM0AigTNAPYEzQGtBFL8ygRS/WgEUvyIBFL9WQRS/AUEUv0n
+BM0CKQTNARMEzQIwBM0AtQTNAC4EzQBqBM0ANgTNAJEEzQCiBM0AcATNAEUEzQBlBM0AYQTNAIEEzQCu
+BM0ARwTNAHgEzQCLBM0AdQTNAKQEzQC5BM0AuATNADkEzQCvBM0AWQTNAKUEzQB4BM0AbQTNAK0EzQCe
+BM0AbgTNAGEEzQBPBM0AmATNADYEzQAuBM0AKgTNAIEEzQAeBM0AgwTNAEMEzQCiBM0AogTNAEYEzQAd
+BM0AWQTNAKIEzQAvBM0AKwTNAKYEzQCrBM0AfQTNAH0EzQAyBM0AkATNAKgEzQByBM0AdwTNAEEEzQCB
+BM0ApATNALcEzQA2BM0AEQTNAIcEzQClBM0ApATNADcEzQCJBM0ApQTNAKUEzQBoBM0AegTNAKoEzQCN
+BM0AgQTNAHYEzQA5BM0AkATNAKUEzQCBBM0AcQTNAE8Ezf/pBM0AjwTNACYEzQCCBM0AHATNAKUEzQBr
+BM0AXwTNABwEzQB9BM0AmwTNACcEzQBXBM0AcQTNAHAEzQBVBM0AaQTNAFAEzQBRBM0AygTNAN4EzQBj
+BM0AXQTNABoEzQBRBM0ARQTNADcEzQBqBM0AegTNAE0EzQBnBM0AcQTNAF8EzQCXBM0AvwTNAHYAAADR
+AAAA/AAAAcMAAAI8AAD+5wAAAE4EzQC/BM0ArQTNALYEzQC2BM0AuQTNALgEzQCuBM0AowTNAC0EzQA4
+BM0AcgTNAG4EzQBtBM0AdATNAGgEzQBcBM0AOQTNADQEzQCrBM0AkgTNAOMEzQAmBM0AJgTNAMgEzQC0
+BM0AtgTNALMEzQBaBM0AlATNAIkEzQBCBM0AdATNAGEEzQBNBM0AZQTNADcEzQBQBM0AswTNANAEzQAU
+BM0ALwTNAG8EzQB1BM0AjgTNAKAEzQBMBM0ASQTNAGwEzQAABM0AAATNAAAEzQAABM0AAATNAAAEzQAA
+BM0AAATNAAAEzQAABM0AAATNAAAEzQBJBM0ATgTNAKYEzQHsBM0BzQTNAbwEzQHPBM0BSQTNAS0EzQEv
+BM0AdwTNAHkEzQGaBM0BXATNAQkEzQA2BM0BjATNAYwEzQErBM0BDwTNAUsEzQBpBM0AfwTNAH8EzQBJ
+BM0A3QTNAHkEzQBnBM0AmQTNAFAEzQAyBM0AJATNAEAEzQB+BM0ApwTNADMEzQCpBM0AOQTNADUEzQD4
+BM0AjQTNAKkEzQC7BM0AwgTNAI4EzQEuBM0AAATNAFwEzQAPBM0BOgTNAREEzQD8BM0AEATNAQsEzQEw
+BM0B+QTNADYEzQDQBM0AbgTNALcEzQDIBM0A5wTNAHwEzQCbBM0A2QTNAJYEzQC0BM0A0QTNAJsEzQDC
+BM0AggTNAF4EzQCQBM0AigTNAF0EzQC1BM0AVgTNAC8EzQBgBM0ATQTNALkEzQFSBM0BWwTNAUIEzQE4
+BM0BIwTNAUAEzQEwBM0BPgTNATUEzQHRBM0B9QTNAXQEzQIGBM0BYATNAMwEzQCpBM0A0gTNAAAEzgDa
+BOv/1ATr/9QE6wAaBM0ATATNAI4EzQBRBM0AUQTNAFEEzQBRBM0AUQTNAFEEzQBRBM0AawTNALYEzQC2
+BM0AtgTNALYEzQCuBM0ArgTNAK4EzQCuBM0AjwTNAGoEzQBqBM0AagTNAGoEzQBqBM0AiwTNAIsEzQCL
+BM0AiwTNAD0EzQCcBM0AnATNAJwEzQCcBM0AnATNAJwEzQCcBM0AjwTNAIcEzQCHBM0AhwTNAIcEzQDL
+BM0AywTNAMsEzQDLBM0ArgTNAHoEzQB6BM0AegTNAHoEzQB6BM0AtATNALQEzQC0BM0AtATNAEQEzQBE
+BM0AUQTNAJwEzQBRBM0AnATNAFEEzQCcBM0AawTNAI8EzQBrBM0AjwTNAGsEzQCPBM0AawTNAI8EzQCb
+BWMAiwTNALYEzQCHBM0AtgTNAIcEzQC2BM0AhwTNALYEzQCHBM0AtgTNAIcEzQBkBM0AjATNAGQEzQCM
+BM0AZATNAIwEzQBkBM0AjATNAI0EzQCuBM0ArgTNAMsEzQCuBM0AywTNAK4EzQDLBM0ArgTNAMsEzQCu
+BM0AYgTNALAEzQCsBM0AsATNAMYEzQDLBM0AxgTNAMsEzQDGBWMAywTNAMYFqQDLBM0AjwTNAK4EzQCP
+BM0ArgTNAI8EzQCuBM3/ugTNAGoEzQB6BM0AagTNAHoEzQBqBM0AegTNALUEzQFJBM0AtQTNARAEzQC1
+BM0BFATNAHYEzQCvBM0AdgTNAK8EzQB2BM0ArwTNAHYEzQCvBM0AdgTNAK8EzQBMBM0AjgTNAEwEzQBd
+BM0AjgTNAEwE9QCOBM0AiwTNALQEzQCLBM0AtATNAIsEzQC0BM0AiwTNALQEzQCLBM0AtATNAIsEzQC0
+BM0ASQTNADAEzQA9BM0ARATNAD0EzQByBM0AoATNAHIEzQCgBM0AcgTNAKAEzQAgBM0AKwTNAEcEzQB6
+BM3/5wTN/+cEzQBdBM0ANgTNADYEzQA2BM0ANgTNADYEzQA2BM0ANgTNAG4EzQDIBM0AyATNAMgEzQDI
+BM0A2QTNANkEzQDZBM0A2QTNAMIEzQCCBM0AggTNAIIEzQCCBM0AggTNALUEzQC1BM0AtQTNALUEzQBN
+BM0ANgTNADYEzQA2BM0AbgTNAG4EzQBuBM0AtwTNAMgEzQDIBM0AyATNAMgEzQDIBM0AfATNAHwEzQB8
+BM0AmwTNANkEzQDZBM0A2QTNANkEzQDZBM0AlgTNALQEzQC2BM0A0QTNANEEzQDRBM0AwgTNAMIEzQDC
+BM0AggTNAIIEzQCCBM0AkATNAJAEzQCQBM0AigTNAIoEzQCKBM0AigTNAF0EzQC1BM0AtQTNALUEzQC1
+BM0AtQTNALUEzQAvBM0ATQTNAE0EzQC5BM0AuQTNALkEzQBRBTEADwUx//0FMf/sBOEACQUx/7IE4QAF
+BM0AuATNAFEEzQCsBM0AtgTNAHIEzQCNBM0ArgTNAKwEzQCUBM0AjwTNAGoEzQC/BM0ATATNAD0EzQBX
+BM0ArgTNAD0EzQCBBM0AiwTNAKQEzQC4BM0AngTNALoEzQB6BM0AvATNAGIEzQBuBM0AuATNAJ4EzQB6
+BM0AngTNAE8EzQC2BM0AtQTNAHYEzQCuBM0ArgTNAGIEzQCpBM0ArATNACsEzQBRBM0ArATNALUEzQC2
+BM0AogTNAJQEzQCNBM0AagTNAKIEzQC/BM0AawTNAEwEzQBFBM0AVwTNAJwEzQCHBM0ApQTNAHoEzQCt
+BM0AjwTNAEQEzQBuBM0AhwTNALcEzQCvBM0AywTNAMsEzQDTBM0ApATNAEQEzQBJBM0AMATNAEkEzQAw
+BM0ASQTNADAEzQA9BM0ARATNAe4EzQFiCZoB5gTNALAEzQHNBM0AlATNAF0EzQBRBM0AnATN/4kEzQC2
+BM0AogTNAIcEzQClBM0AZQTNAGEEzQAaBM0ANQTNAFkEzQCHBM0AawTNAI8EzQA9BM0ARwTNAK4EzQAd
+BM0AEQTNAK4EzQBRBM0AnATNAFEEzQCcBM0AIATNACsEzQC2BM0AhwTNAFoEzQCxBM0AsQTNAB0EzQAR
+BM0AWQTNAIcEzQCiBM0ApQTNAKIEzQClBM0AagTNAHoEzQBjBM0AXQTNAGMEzQBdBM0AcgTNAIEEzQAr
+BM0ARATNACsEzQBEBM0AKwTNAEQEzQCrBM0AjQTNAJAEzQCQBM0AVwTNAG4EzQCLBM0ALwTNADcEzQBR
+BM0AnATNAFEEzQCcBM0AUQTNAJwEzf/8BM3/+ATNAFEEzQCcBM0AUQTNAJwEzQBRBM0AnATNAFEEzQCc
+BM0AUQTNAJwEzQBRBM0AnATNAFEEzQCcBM0AUQTNAJwEzQC2BM0AhwTNALYEzQCHBM0AtgTNAIcEzQC2
+BM0AhwTN//IEzf/zBM0AtgTNAIcEzQC2BM0AhwTNALYEzQCHBM0ArgTNAMsEzQCuBM0AywTNAGoEzQB6
+BM0AagTNAHoEzQBqBM0AegTNAAAEzf/tBM0AagTNAHoEzQBqBM0AegTNAGoEzQB6BM0AYwTNAHcEzQBj
+BM0AdwTNAGMEzQB3BM0AYwTNAHcEzQBjBM0AdwTNAIsEzQC0BM0AiwTNALQEzQCLBM0AtATNAIsEzQC0
+BM0AiwTNALQEzQCLBM0AtATNAIsEzQC0BM0APQTNAEQEzQA9BM0ARATNAD0EzQBEBOsAiwTrAIsEzQCp
+BM0ApATNAI0EzQClBM0ATATNAGgEzQBXBM0AbgTNAKsEzQCNBM0AqwTNAI0EzQC1BM0AtwTNAB0EzQAR
+BM0AJgTNACYEzQCuBM0AEgTN/9QEzf/UBM3//QTN//sE4QAJBOH/8wTNAKIApQCNAKUAlACJAC8ANwA9
+AEcAVwBuAIsAEQBOAAAAAAHmAAAAAQAACGL91QAACZr8BfhyB5kAAQAAAAAAAAAAAAAAAAAAA+AAAwTO
+AZAABQAABZoFMwAAAR8FmgUzAAAD0QBmAgAAAAAAAAAAAAAAAADgAAL/EAAgWwAAACAAAAAAcHlycwBA
+AAD//Qhi/dUAAAhiAisgAAGfTwEAAAQ6BbAAAAAgAAEAAAACAAAAAwAAABQAAwABAAAAFAAEBkQAAADg
+AIAABgBgAAAAAgAJAA0AIQB+AKAArACtAL8AxgDPAOYA7wD+AQ8BEQElAScBMAFTAV8BZwF+AX8BkgGh
+AbAB8AH/AhsCNwJZArwCxwLJAt0C8wMBAwMDCQMPAyMDigOMA5IDoQOwA7kDyQPOA9ID1gQlBC8ERQRP
+BGIEbwR3BIYEzgTXBOEE9QUBBRAFEx4BHj8ehR7xHvMe+R9NIAsgFSAeICIgJiAwIDMgOiA8IEQgdCB/
+IKQgpyCsIQUhEyEWISIhJiEuIV4iAiIGIg8iEiIaIh4iKyJIImAiZSXK9sP+///9//8AAAAAAAIACQAN
+ACAAIgCgAKEArQCuAMAAxwDQAOcA8AD/ARABEgEmASgBMQFUAWABaAF/AZIBoAGvAfAB+gIYAjcCWQK8
+AsYCyQLYAvMDAAMDAwkDDwMjA4QDjAOOA5MDowOxA7oDygPRA9YEAAQmBDAERgRQBGMEcAR4BIgEzwTY
+BOIE9gUCBREeAB4+HoAeoB7yHvQfTSAAIBMgFyAgICUgMCAyIDkgPCBEIHQgfyCjIKcgqyEFIRMhFiEi
+ISYhLiFbIgIiBiIPIhEiGiIeIisiSCJgImQlyvbD/v///P//AAED7APm//UAAP/iASb/wAEa/78AAAEN
+AAABCAAAAQQAAAECAAABAAAAAPYAAAD5/xX/A/72/ukBOAAAAAD+Y/5CAG391v2l/cb9sf2l/aT9n/2a
+/YcAAP9H/0YAAAAA/QcAAP8n/Pv8+AAA/LYAAPyuAAD8owAA/J8AAP5xAAD+bgAA/EcAAOUs5OzkneTL
+5DHkyePh4VgAAOFP4U7hTOFD4vPhO+Lr4TLhA+D5AADg0wAA4HfgauBo4F3fkeBS4Cbfg96p33ffdt9v
+32zfYN9E3y3fKtvGCs4CkwGXAAEAAAAAAAAAAADYAAAAAAAAAAAAAADQAAAA2gAAAQQAAAEeAAABHgAA
+AR4AAAFgAAAAAAAAAAAAAAAAAWIBbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFaAAAAAAFiAX4AAAGW
+AAAAAAAAAa4AAAH2AAACHgAAAkAAAAJMAAAC1gAAAuYAAAL6AAAAAAAAAAAAAAAAAAAAAALuAAAAAAAA
+AAAAAAAAAAAAAAAAAAAC3gAAAt4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAADA/ABzQHOAc8B0AHRAdIAfwHJAd0B3gHfAeAB4QHiAIAAgQHjAeQB5QHmAecAggCDAegB6QHq
+AesB7AHtAIQAhQH4AfkB+gH7AfwB/QCGAIcB/gH/AgACAQICAIgByAPDAIkBygCKAIsAjAIxAjICMwI0
+AI0CNQI2AjcCOAI5AjoCOwI8AI4AjwI9Aj4CPwJAAkECQgJDAJAAkQJEAkUCRgJHAkgCSQCSAJMCWAJZ
+AlwCXgJfAmABywHMAdMB7gJ4AnkCegJ7AlYCVwJaAlsAqwCsAs8ArQLQAtEC0gCuAK8C2QLaAtsAsALc
+At0AsQLeAt8AsgLgALMC4QC0AuIC4wC1AuQAtgC3AuUC5gLnAugC6QLqAusC7ADBAu4C7wDCAu0AwwDE
+AMUAxgDHAMgAyQLwAMoAywMvAvYAzwL3ANAC+AL5AvoC+wDRANIA0wL9AzAC/gDUAv8A1QMAAwEA1gMC
+ANcA2ADZAwMC/ADaAwQDBQMGAwcDCAMJAwoA2wMLAwwDDQDmAOcA6ADpAw4A6gDrAOwDDwDtAO4A7wDw
+AxAA8QMRAxIA8gMTAPMDFAMxAxUA/gMWAP8DFwMYAxkDGgEAAQEBAgMbAzIDHAEDAQQBBQPaAzMDNAET
+ARQBFQEWAzUDNgEmAScD3wPgA9kD2AEoASkBKgErA9sD3AEsAS0D0wPUAzcDOAPFA8YBLgEvA90D3gEw
+ATEDxwPIATIBMwE0ATUBNgE3AzkDOgPJA8oDOwM8A+cD6APLA8wBOAE5A80DzgE6ATsBPAPXAT0BPgPV
+A9YDPQM+Az8BPwFAA+UD5gFBAUID4QPiA88D0APjA+QBQwNKA0kDSwNMA00DTgNPAUQBRQPRA9IDZANl
+AUYBRwNmA2cD6QPqAUgDaAPrA2kDagFkAWUD7QPsAXkDxAF7sAAsILAAVVhFWSAgS7gADlFLsAZTWliw
+NBuwKFlgZiCKVViwAiVhuQgACABjYyNiGyEhsABZsABDI0SyAAEAQ2BCLbABLLAgYGYtsAIsIGQgsMBQ
+sAQmWrIoAQpDRWNFUltYISMhG4pYILBQUFghsEBZGyCwOFBYIbA4WVkgsQEKQ0VjRWFksChQWCGxAQpD
+RWNFILAwUFghsDBZGyCwwFBYIGYgiophILAKUFhgGyCwIFBYIbAKYBsgsDZQWCGwNmAbYFlZWRuwAStZ
+WSOwAFBYZVlZLbADLCBFILAEJWFkILAFQ1BYsAUjQrAGI0IbISFZsAFgLbAELCMhIyEgZLEFYkIgsAYj
+QrEBCkNFY7EBCkOwBGBFY7ADKiEgsAZDIIogirABK7EwBSWwBCZRWGBQG2FSWVgjWSEgsEBTWLABKxsh
+sEBZI7AAUFhlWS2wBSywB0MrsgACAENgQi2wBiywByNCIyCwACNCYbACYmawAWOwAWCwBSotsAcsICBF
+ILALQ2O4BABiILAAUFiwQGBZZrABY2BEsAFgLbAILLIHCwBDRUIqIbIAAQBDYEItsAkssABDI0SyAAEA
+Q2BCLbAKLCAgRSCwASsjsABDsAQlYCBFiiNhIGQgsCBQWCGwABuwMFBYsCAbsEBZWSOwAFBYZVmwAyUj
+YUREsAFgLbALLCAgRSCwASsjsABDsAQlYCBFiiNhIGSwJFBYsAAbsEBZI7AAUFhlWbADJSNhRESwAWAt
+sAwsILAAI0KyCwoDRVghGyMhWSohLbANLLECAkWwZGFELbAOLLABYCAgsAxDSrAAUFggsAwjQlmwDUNK
+sABSWCCwDSNCWS2wDywgsBBiZrABYyC4BABjiiNhsA5DYCCKYCCwDiNCIy2wECxLVFixBGREWSSwDWUj
+eC2wESxLUVhLU1ixBGREWRshWSSwE2UjeC2wEiyxAA9DVVixDw9DsAFhQrAPK1mwAEOwAiVCsQwCJUKx
+DQIlQrABFiMgsAMlUFixAQBDYLAEJUKKiiCKI2GwDiohI7ABYSCKI2GwDiohG7EBAENgsAIlQrACJWGw
+DiohWbAMQ0ewDUNHYLACYiCwAFBYsEBgWWawAWMgsAtDY7gEAGIgsABQWLBAYFlmsAFjYLEAABMjRLAB
+Q7AAPrIBAQFDYEItsBMsALEAAkVUWLAPI0IgRbALI0KwCiOwBGBCIGCwAWG1EBABAA4AQkKKYLESBiuw
+dSsbIlktsBQssQATKy2wFSyxARMrLbAWLLECEystsBcssQMTKy2wGCyxBBMrLbAZLLEFEystsBossQYT
+Ky2wGyyxBxMrLbAcLLEIEystsB0ssQkTKy2wKSwgLrABXS2wKiwgLrABcS2wKywgLrABci2wHiwAsA0r
+sQACRVRYsA8jQiBFsAsjQrAKI7AEYEIgYLABYbUQEAEADgBCQopgsRIGK7B1KxsiWS2wHyyxAB4rLbAg
+LLEBHistsCEssQIeKy2wIiyxAx4rLbAjLLEEHistsCQssQUeKy2wJSyxBh4rLbAmLLEHHistsCcssQge
+Ky2wKCyxCR4rLbAsLCA8sAFgLbAtLCBgsBBgIEMjsAFgQ7ACJWGwAWCwLCohLbAuLLAtK7AtKi2wLywg
+IEcgILALQ2O4BABiILAAUFiwQGBZZrABY2AjYTgjIIpVWCBHICCwC0NjuAQAYiCwAFBYsEBgWWawAWNg
+I2E4GyFZLbAwLACxAAJFVFiwARawLyqxBQEVRVgwWRsiWS2wMSwAsA0rsQACRVRYsAEWsC8qsQUBFUVY
+MFkbIlktsDIsIDWwAWAtsDMsALABRWO4BABiILAAUFiwQGBZZrABY7ABK7ALQ2O4BABiILAAUFiwQGBZ
+ZrABY7ABK7AAFrQAAAAAAEQ+IzixMgEVKi2wNCwgPCBHILALQ2O4BABiILAAUFiwQGBZZrABY2CwAENh
+OC2wNSwuFzwtsDYsIDwgRyCwC0NjuAQAYiCwAFBYsEBgWWawAWNgsABDYbABQ2M4LbA3LLECABYlIC4g
+R7AAI0KwAiVJiopHI0cjYSBYYhshWbABI0KyNgEBFRQqLbA4LLAAFrAEJbAEJUcjRyNhsAlDK2WKLiMg
+IDyKOC2wOSywABawBCWwBCUgLkcjRyNhILAEI0KwCUMrILBgUFggsEBRWLMCIAMgG7MCJgMaWUJCIyCw
+CEMgiiNHI0cjYSNGYLAEQ7ACYiCwAFBYsEBgWWawAWNgILABKyCKimEgsAJDYGQjsANDYWRQWLACQ2Eb
+sANDYFmwAyWwAmIgsABQWLBAYFlmsAFjYSMgILAEJiNGYTgbI7AIQ0awAiWwCENHI0cjYWAgsARDsAJi
+ILAAUFiwQGBZZrABY2AjILABKyOwBENgsAErsAUlYbAFJbACYiCwAFBYsEBgWWawAWOwBCZhILAEJWBk
+I7ADJWBkUFghGyMhWSMgILAEJiNGYThZLbA6LLAAFiAgILAFJiAuRyNHI2EjPDgtsDsssAAWILAII0Ig
+ICBGI0ewASsjYTgtsDwssAAWsAMlsAIlRyNHI2GwAFRYLiA8IyEbsAIlsAIlRyNHI2EgsAUlsAQlRyNH
+I2GwBiWwBSVJsAIlYbkIAAgAY2MjIFhiGyFZY7gEAGIgsABQWLBAYFlmsAFjYCMuIyAgPIo4IyFZLbA9
+LLAAFiCwCEMgLkcjRyNhIGCwIGBmsAJiILAAUFiwQGBZZrABYyMgIDyKOC2wPiwjIC5GsAIlRlJYIDxZ
+LrEuARQrLbA/LCMgLkawAiVGUFggPFkusS4BFCstsEAsIyAuRrACJUZSWCA8WSMgLkawAiVGUFggPFku
+sS4BFCstsEEssDgrIyAuRrACJUZSWCA8WS6xLgEUKy2wQiywOSuKICA8sAQjQoo4IyAuRrACJUZSWCA8
+WS6xLgEUK7AEQy6wListsEMssAAWsAQlsAQmIC5HI0cjYbAJQysjIDwgLiM4sS4BFCstsEQssQgEJUKw
+ABawBCWwBCUgLkcjRyNhILAEI0KwCUMrILBgUFggsEBRWLMCIAMgG7MCJgMaWUJCIyBHsARDsAJiILAA
+UFiwQGBZZrABY2AgsAErIIqKYSCwAkNgZCOwA0NhZFBYsAJDYRuwA0NgWbADJbACYiCwAFBYsEBgWWaw
+AWNhsAIlRmE4IyA8IzgbISAgRiNHsAErI2E4IVmxLgEUKy2wRSywOCsusS4BFCstsEYssDkrISMgIDyw
+BCNCIzixLgEUK7AEQy6wListsEcssAAVIEewACNCsgABARUUEy6wNCotsEgssAAVIEewACNCsgABARUU
+Ey6wNCotsEkssQABFBOwNSotsEossDcqLbBLLLAAFkUjIC4gRoojYTixLgEUKy2wTCywCCNCsEsrLbBN
+LLIAAEQrLbBOLLIAAUQrLbBPLLIBAEQrLbBQLLIBAUQrLbBRLLIAAEUrLbBSLLIAAUUrLbBTLLIBAEUr
+LbBULLIBAUUrLbBVLLIAAEErLbBWLLIAAUErLbBXLLIBAEErLbBYLLIBAUErLbBZLLIAAEMrLbBaLLIA
+AUMrLbBbLLIBAEMrLbBcLLIBAUMrLbBdLLIAAEYrLbBeLLIAAUYrLbBfLLIBAEYrLbBgLLIBAUYrLbBh
+LLIAAEIrLbBiLLIAAUIrLbBjLLIBAEIrLbBkLLIBAUIrLbBlLLA6Ky6xLgEUKy2wZiywOiuwPistsGcs
+sDorsD8rLbBoLLAAFrA6K7BAKy2waSywOysusS4BFCstsGossDsrsD4rLbBrLLA7K7A/Ky2wbCywOyuw
+QCstsG0ssDwrLrEuARQrLbBuLLA8K7A+Ky2wbyywPCuwPystsHAssDwrsEArLbBxLLA9Ky6xLgEUKy2w
+ciywPSuwPistsHMssD0rsD8rLbB0LLA9K7BAKy2wdSyzCQQCA0VYIRsjIVlCK7AIZbADJFB4sQUBFUVY
+MFktAABLuADIUlixAQGOWbABuQgACABjcLEABkK1AEczHwQAKrEABkJACk0BOggmCBQHBAgqsQAGQkAK
+TgBEBjAGHQUECCqxAApCvROADsAJwAVAAAQACSqxAA5CvQAAAEAAQABAAAQACSqxAwBEsSQBiFFYsECI
+WLEDZESxJgGIUVi6CIAAAQRAiGNUWLEDAERZWVlZQApOADwIKAgWBwQMKrgB/4WwBI2xAgBEsQVkRAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALkAuQCXAJcFsAAABDoAAP5gCGL91QXE
+/+wETv/s/ksIYv3VALkAuQCXAJcFsAAABbAEOv/s/mAIYv3VBcT/7AXFBE7/7P5gCGL91QC5ALkAlwCX
+BbAAAAXhBDoAAP5gCGL91QXE/+wF4QRO/+z+Swhi/dUAMgAyAAAADQCiAAMAAQQJAAAAXgAAAAMAAQQJ
+AAEAFgBeAAMAAQQJAAIADgB0AAMAAQQJAAMALgCCAAMAAQQJAAQAFgBeAAMAAQQJAAUAVACwAAMAAQQJ
+AAYAJAEEAAMAAQQJAAcASgEoAAMAAQQJAAkADAFyAAMAAQQJAAsAFAF+AAMAAQQJAAwAJgGSAAMAAQQJ
+AA0AXAG4AAMAAQQJAA4AVAIUAEMAbwBwAHkAcgBpAGcAaAB0ACAAMgAwADEANQAgAEcAbwBvAGcAbABl
+ACAASQBuAGMALgAgAEEAbABsACAAUgBpAGcAaAB0AHMAIABSAGUAcwBlAHIAdgBlAGQALgBSAG8AYgBv
+AHQAbwAgAE0AbwBuAG8AUgBlAGcAdQBsAGEAcgBHAG8AbwBnAGwAZQA6AFIAbwBiAG8AdABvACAATQBv
+AG4AbwA6ADIAMAAxADUAVgBlAHIAcwBpAG8AbgAgADIALgAwADAAMAA5ADgANQA7ACAAMgAwADEANQA7
+ACAAdAB0AGYAYQB1AHQAbwBoAGkAbgB0ACAAKAB2ADEALgAzACkAUgBvAGIAbwB0AG8ATQBvAG4AbwAt
+AFIAZQBnAHUAbABhAHIAUgBvAGIAbwB0AG8AIABNAG8AbgBvACAAaQBzACAAYQAgAHQAcgBhAGQAZQBt
+AGEAcgBrACAAbwBmACAARwBvAG8AZwBsAGUALgBHAG8AbwBnAGwAZQBHAG8AbwBnAGwAZQAuAGMAbwBt
+AEMAaAByAGkAcwB0AGkAYQBuACAAUgBvAGIAZQByAHQAcwBvAG4ATABpAGMAZQBuAHMAZQBkACAAdQBu
+AGQAZQByACAAdABoAGUAIABBAHAAYQBjAGgAZQAgAEwAaQBjAGUAbgBzAGUALAAgAFYAZQByAHMAaQBv
+AG4AIAAyAC4AMABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBwAGEAYwBoAGUALgBvAHIAZwAvAGwAaQBj
+AGUAbgBzAGUAcwAvAEwASQBDAEUATgBTAEUALQAyAC4AMAAAAAIAAAAAAAD/agBkAAAAAAAAAAAAAAAA
+AAAAAAAAAAAD8QAAAQIAAgADAAUABgAHAAgACQAKAAsADAANAA4ADwAQABEAEgATABQAFQAWABcAGAAZ
+ABoAGwAcAB0AHgAfACAAIQAiACMAJAAlACYAJwAoACkAKgArACwALQAuAC8AMAAxADIAMwA0ADUANgA3
+ADgAOQA6ADsAPAA9AD4APwBAAEEAQgBDAEQARQBGAEcASABJAEoASwBMAE0ATgBPAFAAUQBSAFMAVABV
+AFYAVwBYAFkAWgBbAFwAXQBeAF8AYABhAKMAhACFAL0AlgDoAIYAjgCLAJ0AqQCkAIoA2gCDAJMA8gDz
+AI0AlwCIAMMA3gDxAJ4AqgD1APQA9gCiAJAA8ACRAO0AiQCgAOoAuAChAO4BAwDXAQQBBQEGAOIA4wEH
+AQgAsACxAQkApgEKAQsBDAENAQ4BDwDYAOEA2wDcAN0A4ADZAN8BEAERARIBEwEUARUBFgEXARgBGQEa
+AKgBGwEcAR0BHgEfASABIQCfASIBIwEkASUBJgEnASgBKQEqASsBLACbAS0BLgEvATABMQEyATMBNAE1
+ATYBNwE4ATkBOgE7ATwBPQE+AT8BQAFBAUIBQwFEAUUBRgFHAUgBSQFKAUsBTAFNAU4BTwFQAVEBUgFT
+AVQBVQFWAVcBWAFZAVoBWwFcAV0BXgFfAWABYQFiAWMBZAFlAWYBZwFoAWkBagFrAWwBbQFuAW8BcAFx
+AXIBcwF0AXUBdgF3AXgBeQF6AXsBfAF9AX4BfwGAAYEBggGDAYQBhQGGAYcBiAGJAYoBiwGMAY0BjgGP
+AZABkQGSAZMBlAGVAZYBlwGYAZkBmgGbAZwBnQGeAZ8BoAGhAaIBowGkAaUBpgGnAagBqQGqAasBrAGt
+Aa4BrwGwAbEBsgGzAbQBtQG2AbcBuAG5AboBuwG8Ab0BvgG/AcABwQHCAcMBxAHFAcYBxwHIAckBygHL
+AcwAsgCzAc0AtgC3AMQBzgC0ALUAxQCCAMIAhwHPAKsAxgC+AL8AvAHQAdEB0gHTAdQB1QHWAdcAjAHY
+AdkB2gHbAdwAmACaAJkA7wClAJIAnACnAI8AlACVALkB3QHeAd8B4AHhAeIB4wHkAeUB5gHnAegB6QHq
+AesB7AHtAe4B7wHwAfEB8gHzAfQB9QH2AfcB+AH5AfoB+wH8Af0B/gH/AgACAQICAgMCBAIFAgYCBwII
+AgkCCgILAgwCDQIOAg8CEAIRAKwCEgITAOkCFAIVAhYArQDJAMcArgBiAGMCFwBkAMsAZQDIAMoAzwDM
+AM0AzgBmANMA0ADRAK8AZwDWANQA1QBoAOsAagBpAGsAbQBsAG4CGABvAHEAcAByAHMAdQB0AHYAdwB4
+AHoAeQB7AH0AfAB/AH4AgACBAOwAugIZAhoCGwIcAh0CHgD9AP4CHwIgAiECIgD/AQACIwIkAiUCJgIn
+AigCKQIqAisCLAItAi4CLwIwAPgA+QIxAjICMwI0AjUCNgI3AjgCOQI6AjsCPAI9Aj4A+gI/AkACQQJC
+AkMCRAJFAkYCRwJIAkkCSgJLAkwCTQJOAk8CUAJRAlICUwJUAlUCVgJXAlgCWQJaAlsCXAJdAl4CXwJg
+AmEA+wD8AmICYwDkAOUCZAJlAmYCZwJoAmkCagJrAmwCbQJuAm8CcAJxAnICcwJ0AnUCdgJ3AngCeQJ6
+ALsCewJ8An0CfgDmAOcCfwKAAoECggKDAoQChQKGAocCiAKJAooCiwKMAo0CjgKPApACkQKSApMClAKV
+ApYClwKYApkCmgKbApwCnQKeAp8CoAKhAqICowKkAqUCpgKnAqgCqQKqAqsCrAKtAq4CrwKwArECsgKz
+ArQCtQK2ArcCuAK5AroCuwK8Ar0CvgK/AsACwQLCAsMCxALFAsYCxwLIAskCygLLAswCzQLOAs8C0ALR
+AtIC0wLUAtUC1gLXAtgC2QLaAtsC3ALdAt4C3wLgAuEC4gLjAuQC5QLmAucC6ALpAuoC6wLsAu0C7gLv
+AvAC8QLyAvMC9AL1AvYC9wL4AvkC+gL7AvwC/QL+Av8DAAMBAwIDAwMEAwUDBgMHAwgDCQMKAwsDDAMN
+Aw4DDwMQAxEDEgMTAxQDFQMWAxcDGAMZAxoDGwMcAx0DHgMfAyADIQMiAyMDJAMlAyYDJwMoAykDKgMr
+AywDLQMuAy8DMAMxAzIDMwM0AzUDNgM3AzgDOQM6AzsDPAM9Az4DPwNAA0EDQgNDA0QDRQNGA0cDSANJ
+A0oDSwNMA00DTgNPA1ADUQNSA1MDVANVA1YDVwNYA1kDWgNbA1wDXQNeA18DYANhA2IDYwNkA2UDZgNn
+A2gDaQNqA2sDbANtA24DbwNwA3EDcgNzA3QDdQN2A3cDeAN5A3oDewN8A30DfgN/A4ADgQOCA4MDhAOF
+A4YDhwOIA4kDigOLA4wDjQOOA48DkAORA5IDkwOUA5UDlgOXA5gDmQOaA5sDnAOdA54DnwOgA6EDogOj
+A6QDpQOmA6cDqAOpA6oDqwOsA60DrgOvA7ADsQOyA7MDtAO1A7YDtwO4A7kDugO7A7wDvQO+A78DwAPB
+A8IDwwPEA8UDxgPHA8gDyQEBA8oDywPMA80DzgPPA9AD0QPSA9MD1APVA9YD1wPYA9kD2gPbA9wD3QPe
+A98D4APhA+ID4wPkA+UD5gPnA+gD6QPqA+sD7APtA+4D7wPwA/EA9wPyA/MD9AAEBE5VTEwESGJhcgJJ
+SgJpagxrZ3JlZW5sYW5kaWMDRW5nA2VuZwVsb25ncwVPaG9ybgVvaG9ybgVVaG9ybgV1aG9ybgd1bmkw
+MjM3BXNjaHdhB3VuaTAyRjMJZ3JhdmVjb21iCWFjdXRlY29tYgl0aWxkZWNvbWIEaG9vawd1bmkwMzBG
+CGRvdGJlbG93BXRvbm9zDWRpZXJlc2lzdG9ub3MJYW5vdGVsZWlhBUdhbW1hBVRoZXRhBkxhbWJkYQJY
+aQJQaQVTaWdtYQNQaGkDUHNpBWFscGhhBGJldGEFZ2FtbWEFZGVsdGEHZXBzaWxvbgR6ZXRhA2V0YQV0
+aGV0YQRpb3RhBmxhbWJkYQJ4aQNyaG8Gc2lnbWExBXNpZ21hA3RhdQd1cHNpbG9uA3BoaQNwc2kFb21l
+Z2EHdW5pMDNEMQd1bmkwM0QyB3VuaTAzRDYHdW5pMDQwMgd1bmkwNDA0B3VuaTA0MDkHdW5pMDQwQQd1
+bmkwNDBCB3VuaTA0MEYHdW5pMDQxMQd1bmkwNDE0B3VuaTA0MTYHdW5pMDQxNwd1bmkwNDE4B3VuaTA0
+MUIHdW5pMDQyMwd1bmkwNDI2B3VuaTA0MjcHdW5pMDQyOAd1bmkwNDI5B3VuaTA0MkEHdW5pMDQyQgd1
+bmkwNDJDB3VuaTA0MkQHdW5pMDQyRQd1bmkwNDJGB3VuaTA0MzEHdW5pMDQzMgd1bmkwNDMzB3VuaTA0
+MzQHdW5pMDQzNgd1bmkwNDM3B3VuaTA0MzgHdW5pMDQzQQd1bmkwNDNCB3VuaTA0M0MHdW5pMDQzRAd1
+bmkwNDNGB3VuaTA0NDIHdW5pMDQ0NAd1bmkwNDQ2B3VuaTA0NDcHdW5pMDQ0OAd1bmkwNDQ5B3VuaTA0
+NEEHdW5pMDQ0Qgd1bmkwNDRDB3VuaTA0NEQHdW5pMDQ0RQd1bmkwNDRGB3VuaTA0NTIHdW5pMDQ1NAd1
+bmkwNDU5B3VuaTA0NUEHdW5pMDQ1Qgd1bmkwNDVGB3VuaTA0NjAHdW5pMDQ2MQd1bmkwNDYzB3VuaTA0
+NjQHdW5pMDQ2NQd1bmkwNDY2B3VuaTA0NjcHdW5pMDQ2OAd1bmkwNDY5B3VuaTA0NkEHdW5pMDQ2Qgd1
+bmkwNDZDB3VuaTA0NkQHdW5pMDQ2RQd1bmkwNDZGB3VuaTA0NzIHdW5pMDQ3Mwd1bmkwNDc0B3VuaTA0
+NzUHdW5pMDQ3OAd1bmkwNDc5B3VuaTA0N0EHdW5pMDQ3Qgd1bmkwNDdDB3VuaTA0N0QHdW5pMDQ3RQd1
+bmkwNDdGB3VuaTA0ODAHdW5pMDQ4MQd1bmkwNDgyB3VuaTA0ODMHdW5pMDQ4NAd1bmkwNDg1B3VuaTA0
+ODYHdW5pMDQ4OAd1bmkwNDg5B3VuaTA0OEUHdW5pMDQ4Rgd1bmkwNDkwB3VuaTA0OTEHdW5pMDQ5NAd1
+bmkwNDk1B3VuaTA0OUMHdW5pMDQ5RAd1bmkwNEEwB3VuaTA0QTEHdW5pMDRBNAd1bmkwNEE1B3VuaTA0
+QTYHdW5pMDRBNwd1bmkwNEE4B3VuaTA0QTkHdW5pMDRCNAd1bmkwNEI1B3VuaTA0QjgHdW5pMDRCOQd1
+bmkwNEJBB3VuaTA0QkMHdW5pMDRCRAd1bmkwNEMzB3VuaTA0QzQHdW5pMDRDNwd1bmkwNEM4B3VuaTA0
+RDgHdW5pMDRFMAd1bmkwNEUxB3VuaTA0RkEHdW5pMDRGQgd1bmkwNTAwB3VuaTA1MDIHdW5pMDUwMwd1
+bmkwNTA0B3VuaTA1MDUHdW5pMDUwNgd1bmkwNTA3B3VuaTA1MDgHdW5pMDUwOQd1bmkwNTBBB3VuaTA1
+MEIHdW5pMDUwQwd1bmkwNTBEB3VuaTA1MEUHdW5pMDUwRgd1bmkwNTEwB3VuaTIwMDAHdW5pMjAwMQd1
+bmkyMDAyB3VuaTIwMDMHdW5pMjAwNAd1bmkyMDA1B3VuaTIwMDYHdW5pMjAwNwd1bmkyMDA4B3VuaTIw
+MDkHdW5pMjAwQQd1bmkyMDBCDXVuZGVyc2NvcmVkYmwNcXVvdGVyZXZlcnNlZAd1bmkyMDI1B3VuaTIw
+NzQJbnN1cGVyaW9yBGxpcmEGcGVzZXRhBEV1cm8HdW5pMjEwNQd1bmkyMTEzB3VuaTIxMTYJZXN0aW1h
+dGVkCW9uZWVpZ2h0aAx0aHJlZWVpZ2h0aHMLZml2ZWVpZ2h0aHMMc2V2ZW5laWdodGhzC2NvbW1hYWNj
+ZW50B3VuaUZFRkYHdW5pRkZGQwd1bmlGRkZEB3R3by5zdXATY2lyY3VtZmxleHRpbGRlY29tYhJjaXJj
+dW1mbGV4aG9va2NvbWITY2lyY3VtZmxleGdyYXZlY29tYhNjaXJjdW1mbGV4YWN1dGVjb21iDmJyZXZl
+Z3JhdmVjb21iEWNvbW1hYWNjZW50cm90YXRlBkEuc21jcAZCLnNtY3AGQy5zbWNwBkQuc21jcAZFLnNt
+Y3AGRi5zbWNwBkcuc21jcAZILnNtY3AGSS5zbWNwBkouc21jcAZLLnNtY3AGTC5zbWNwBk0uc21jcAZO
+LnNtY3AGTy5zbWNwBlEuc21jcAZSLnNtY3AGUy5zbWNwBlQuc21jcAZVLnNtY3AGVi5zbWNwBlcuc21j
+cAZYLnNtY3AGWS5zbWNwBlouc21jcA1icmV2ZWhvb2tjb21iB29uZS5zdXAOYnJldmVhY3V0ZWNvbWIJ
+dGhyZWUuc3VwCGZvdXIuc3VwCGZpdmUuc3VwCXNldmVuLnN1cAllaWdodC5zdXAIY3Jvc3NiYXIJcmlu
+Z2FjdXRlCWRhc2lhb3hpYQ5icmV2ZXRpbGRlY29tYgtjeXJpbGxpY3RpYwxjeXJpbGxpY2hvb2sGUC5z
+bWNwBUsuYWx0D0dlcm1hbmRibHMuc21jcAd1bmkwMEFEBkRjcm9hdARoYmFyBFRiYXIEdGJhcgpBcmlu
+Z2FjdXRlCmFyaW5nYWN1dGUHQW1hY3JvbgdhbWFjcm9uBkFicmV2ZQZhYnJldmUHQW9nb25lawdhb2dv
+bmVrC0NjaXJjdW1mbGV4C2NjaXJjdW1mbGV4B3VuaTAxMEEHdW5pMDEwQgZEY2Fyb24GZGNhcm9uB0Vt
+YWNyb24HZW1hY3JvbgZFYnJldmUGZWJyZXZlCkVkb3RhY2NlbnQKZWRvdGFjY2VudAdFb2dvbmVrB2Vv
+Z29uZWsGRWNhcm9uBmVjYXJvbgtHY2lyY3VtZmxleAtnY2lyY3VtZmxleAd1bmkwMTIwB3VuaTAxMjEM
+R2NvbW1hYWNjZW50DGdjb21tYWFjY2VudAtIY2lyY3VtZmxleAtoY2lyY3VtZmxleAZJdGlsZGUGaXRp
+bGRlB0ltYWNyb24HaW1hY3JvbgZJYnJldmUGaWJyZXZlB0lvZ29uZWsHaW9nb25lawtKY2lyY3VtZmxl
+eAtqY2lyY3VtZmxleAxLY29tbWFhY2NlbnQMa2NvbW1hYWNjZW50BkxhY3V0ZQZsYWN1dGUMTGNvbW1h
+YWNjZW50DGxjb21tYWFjY2VudAZMY2Fyb24GbGNhcm9uBExkb3QEbGRvdAZOYWN1dGUGbmFjdXRlDE5j
+b21tYWFjY2VudAxuY29tbWFhY2NlbnQGTmNhcm9uBm5jYXJvbgtuYXBvc3Ryb3BoZQdPbWFjcm9uB29t
+YWNyb24GT2JyZXZlBm9icmV2ZQ1PaHVuZ2FydW1sYXV0DW9odW5nYXJ1bWxhdXQGUmFjdXRlBnJhY3V0
+ZQxSY29tbWFhY2NlbnQMcmNvbW1hYWNjZW50BlJjYXJvbgZyY2Fyb24GU2FjdXRlBnNhY3V0ZQtTY2ly
+Y3VtZmxleAtzY2lyY3VtZmxleAd1bmkwMjE4B3VuaTAyMTkHdW5pMDIxQQd1bmkwMjFCB3VuaTAxNjIM
+dW5pMDE2Mi5zbWNwB3VuaTAxNjMGVGNhcm9uBnRjYXJvbgZVdGlsZGUGdXRpbGRlB1VtYWNyb24HdW1h
+Y3JvbgZVYnJldmUGdWJyZXZlBVVyaW5nBXVyaW5nDVVodW5nYXJ1bWxhdXQNdWh1bmdhcnVtbGF1dAdV
+b2dvbmVrB3VvZ29uZWsLV2NpcmN1bWZsZXgLd2NpcmN1bWZsZXgLWWNpcmN1bWZsZXgLeWNpcmN1bWZs
+ZXgGWmFjdXRlBnphY3V0ZQpaZG90YWNjZW50Cnpkb3RhY2NlbnQHQUVhY3V0ZQdhZWFjdXRlC09zbGFz
+aGFjdXRlC29zbGFzaGFjdXRlC0Rjcm9hdC5zbWNwCEV0aC5zbWNwCVRiYXIuc21jcAtBZ3JhdmUuc21j
+cAtBYWN1dGUuc21jcBBBY2lyY3VtZmxleC5zbWNwC0F0aWxkZS5zbWNwDkFkaWVyZXNpcy5zbWNwCkFy
+aW5nLnNtY3APQXJpbmdhY3V0ZS5zbWNwDUNjZWRpbGxhLnNtY3ALRWdyYXZlLnNtY3ALRWFjdXRlLnNt
+Y3AQRWNpcmN1bWZsZXguc21jcA5FZGllcmVzaXMuc21jcAtJZ3JhdmUuc21jcAtJYWN1dGUuc21jcBBJ
+Y2lyY3VtZmxleC5zbWNwDklkaWVyZXNpcy5zbWNwC050aWxkZS5zbWNwC09ncmF2ZS5zbWNwC09hY3V0
+ZS5zbWNwEE9jaXJjdW1mbGV4LnNtY3ALT3RpbGRlLnNtY3AOT2RpZXJlc2lzLnNtY3ALVWdyYXZlLnNt
+Y3ALVWFjdXRlLnNtY3AQVWNpcmN1bWZsZXguc21jcA5VZGllcmVzaXMuc21jcAtZYWN1dGUuc21jcAxB
+bWFjcm9uLnNtY3ALQWJyZXZlLnNtY3AMQW9nb25lay5zbWNwC0NhY3V0ZS5zbWNwEENjaXJjdW1mbGV4
+LnNtY3ALQ2Nhcm9uLnNtY3ALRGNhcm9uLnNtY3AMRW1hY3Jvbi5zbWNwC0VicmV2ZS5zbWNwD0Vkb3Rh
+Y2NlbnQuc21jcAxFb2dvbmVrLnNtY3ALRWNhcm9uLnNtY3AQR2NpcmN1bWZsZXguc21jcAtHYnJldmUu
+c21jcBFHY29tbWFhY2NlbnQuc21jcBBIY2lyY3VtZmxleC5zbWNwC0l0aWxkZS5zbWNwDEltYWNyb24u
+c21jcAtJYnJldmUuc21jcAxJb2dvbmVrLnNtY3APSWRvdGFjY2VudC5zbWNwEEpjaXJjdW1mbGV4LnNt
+Y3ARS2NvbW1hYWNjZW50LnNtY3ALTGFjdXRlLnNtY3ARTGNvbW1hYWNjZW50LnNtY3ALTGNhcm9uLnNt
+Y3AJTGRvdC5zbWNwC05hY3V0ZS5zbWNwEU5jb21tYWFjY2VudC5zbWNwC05jYXJvbi5zbWNwDE9tYWNy
+b24uc21jcAtPYnJldmUuc21jcBJPaHVuZ2FydW1sYXV0LnNtY3ALUmFjdXRlLnNtY3ARUmNvbW1hYWNj
+ZW50LnNtY3ALUmNhcm9uLnNtY3ALU2FjdXRlLnNtY3AQU2NpcmN1bWZsZXguc21jcA1TY2VkaWxsYS5z
+bWNwC1NjYXJvbi5zbWNwC1RjYXJvbi5zbWNwC1V0aWxkZS5zbWNwDFVtYWNyb24uc21jcAtVYnJldmUu
+c21jcApVcmluZy5zbWNwElVodW5nYXJ1bWxhdXQuc21jcAxVb2dvbmVrLnNtY3AQV2NpcmN1bWZsZXgu
+c21jcBBZY2lyY3VtZmxleC5zbWNwDllkaWVyZXNpcy5zbWNwC1phY3V0ZS5zbWNwD1pkb3RhY2NlbnQu
+c21jcAtaY2Fyb24uc21jcApBbHBoYXRvbm9zDEVwc2lsb250b25vcwhFdGF0b25vcwlJb3RhdG9ub3MM
+T21pY3JvbnRvbm9zDFVwc2lsb250b25vcwpPbWVnYXRvbm9zEWlvdGFkaWVyZXNpc3Rvbm9zBUFscGhh
+BEJldGEHRXBzaWxvbgRaZXRhA0V0YQRJb3RhBUthcHBhAk11Ak51B09taWNyb24DUmhvA1RhdQdVcHNp
+bG9uA0NoaQxJb3RhZGllcmVzaXMPVXBzaWxvbmRpZXJlc2lzCmFscGhhdG9ub3MMZXBzaWxvbnRvbm9z
+CGV0YXRvbm9zCWlvdGF0b25vcxR1cHNpbG9uZGllcmVzaXN0b25vcwVrYXBwYQdvbWljcm9uB3VuaTAz
+QkMCbnUDY2hpDGlvdGFkaWVyZXNpcw91cHNpbG9uZGllcmVzaXMMb21pY3JvbnRvbm9zDHVwc2lsb250
+b25vcwpvbWVnYXRvbm9zB3VuaTA0MDEHdW5pMDQwMwd1bmkwNDA1B3VuaTA0MDYHdW5pMDQwNwd1bmkw
+NDA4B3VuaTA0MUEHdW5pMDQwQwd1bmkwNDBFB3VuaTA0MTAHdW5pMDQxMgd1bmkwNDEzB3VuaTA0MTUH
+dW5pMDQxOQd1bmkwNDFDB3VuaTA0MUQHdW5pMDQxRQd1bmkwNDFGB3VuaTA0MjAHdW5pMDQyMQd1bmkw
+NDIyB3VuaTA0MjQHdW5pMDQyNQd1bmkwNDMwB3VuaTA0MzUHdW5pMDQzOQd1bmkwNDNFB3VuaTA0NDAH
+dW5pMDQ0MQd1bmkwNDQzB3VuaTA0NDUHdW5pMDQ1MQd1bmkwNDUzB3VuaTA0NTUHdW5pMDQ1Ngd1bmkw
+NDU3B3VuaTA0NTgHdW5pMDQ1Qwd1bmkwNDVFBldncmF2ZQZ3Z3JhdmUGV2FjdXRlBndhY3V0ZQlXZGll
+cmVzaXMJd2RpZXJlc2lzBllncmF2ZQZ5Z3JhdmUGbWludXRlBnNlY29uZAlleGNsYW1kYmwHdW5pMDFG
+MAd1bmkwMkJDB3VuaTFFM0UHdW5pMUUzRgd1bmkxRTAwB3VuaTFFMDEHdW5pMUY0RAd1bmkwNDAwB3Vu
+aTA0MEQHdW5pMDQ1MAd1bmkwNDVEB3VuaTA0NzAHdW5pMDQ3MQd1bmkwNDc2B3VuaTA0NzcHdW5pMDQ5
+OAd1bmkwNDk5B3VuaTA0QUEHdW5pMDRBQgd1bmkwNEFFB3VuaTA0QUYHdW5pMDRDMAd1bmkwNEMxB3Vu
+aTA0QzIHdW5pMDRDRgd1bmkwNEQwB3VuaTA0RDEHdW5pMDREMgd1bmkwNEQzB3VuaTA0RDQHdW5pMDRE
+NQd1bmkwNEQ2B3VuaTA0RDcHdW5pMDREQQd1bmkwNEQ5B3VuaTA0REIHdW5pMDREQwd1bmkwNEREB3Vu
+aTA0REUHdW5pMDRERgd1bmkwNEUyB3VuaTA0RTMHdW5pMDRFNAd1bmkwNEU1B3VuaTA0RTYHdW5pMDRF
+Nwd1bmkwNEU4B3VuaTA0RTkHdW5pMDRFQQd1bmkwNEVCB3VuaTA0RUMHdW5pMDRFRAd1bmkwNEVFB3Vu
+aTA0RUYHdW5pMDRGMAd1bmkwNEYxB3VuaTA0RjIHdW5pMDRGMwd1bmkwNEY0B3VuaTA0RjUHdW5pMDRG
+OAd1bmkwNEY5B3VuaTA0RkMHdW5pMDRGRAd1bmkwNTAxB3VuaTA1MTIHdW5pMDUxMwd1bmkxRUEwB3Vu
+aTFFQTEHdW5pMUVBMgd1bmkxRUEzB3VuaTFFQTQHdW5pMUVBNQd1bmkxRUE2B3VuaTFFQTcHdW5pMUVB
+OAd1bmkxRUE5B3VuaTFFQUEHdW5pMUVBQgd1bmkxRUFDB3VuaTFFQUQHdW5pMUVBRQd1bmkxRUFGB3Vu
+aTFFQjAHdW5pMUVCMQd1bmkxRUIyB3VuaTFFQjMHdW5pMUVCNAd1bmkxRUI1B3VuaTFFQjYHdW5pMUVC
+Nwd1bmkxRUI4B3VuaTFFQjkHdW5pMUVCQQd1bmkxRUJCB3VuaTFFQkMHdW5pMUVCRAd1bmkxRUJFB3Vu
+aTFFQkYHdW5pMUVDMAd1bmkxRUMxB3VuaTFFQzIHdW5pMUVDMwd1bmkxRUM0B3VuaTFFQzUHdW5pMUVD
+Ngd1bmkxRUM3B3VuaTFFQzgHdW5pMUVDOQd1bmkxRUNBB3VuaTFFQ0IHdW5pMUVDQwd1bmkxRUNEB3Vu
+aTFFQ0UHdW5pMUVDRgd1bmkxRUQwB3VuaTFFRDEHdW5pMUVEMgd1bmkxRUQzB3VuaTFFRDQHdW5pMUVE
+NQd1bmkxRUQ2B3VuaTFFRDcHdW5pMUVEOAd1bmkxRUQ5B3VuaTFFREEHdW5pMUVEQgd1bmkxRURDB3Vu
+aTFFREQHdW5pMUVERQd1bmkxRURGB3VuaTFFRTAHdW5pMUVFMQd1bmkxRUUyB3VuaTFFRTMHdW5pMUVF
+NAd1bmkxRUU1B3VuaTFFRTYHdW5pMUVFNwd1bmkxRUU4B3VuaTFFRTkHdW5pMUVFQQd1bmkxRUVCB3Vu
+aTFFRUMHdW5pMUVFRAd1bmkxRUVFB3VuaTFFRUYHdW5pMUVGMAd1bmkxRUYxB3VuaTFFRjQHdW5pMUVG
+NQd1bmkxRUY2B3VuaTFFRjcHdW5pMUVGOAd1bmkxRUY5B3VuaTIwQUIHdW5pMDQ5QQd1bmkwNDlCB3Vu
+aTA0QTIHdW5pMDRBMwd1bmkwNEFDB3VuaTA0QUQHdW5pMDRCMgd1bmkwNEIzB3VuaTA0QjYHdW5pMDRC
+Nwd1bmkwNENCB3VuaTA0Q0MHdW5pMDRGNgd1bmkwNEY3B3VuaTA0OTYHdW5pMDQ5Nwd1bmkwNEJFB3Vu
+aTA0QkYHdW5pMDRCQgd1bmkwNDhEB3VuaTA0OEMHdW5pMDQ2Mgd1bmkwNDkyB3VuaTA0OTMHdW5pMDQ5
+RQd1bmkwNDlGB3VuaTA0OEEHdW5pMDQ4Qgd1bmkwNEM5B3VuaTA0Q0EHdW5pMDRDRAd1bmkwNENFB3Vu
+aTA0QzUHdW5pMDRDNgd1bmkwNEIwB3VuaTA0QjEHdW5pMDRGRQd1bmkwNEZGB3VuaTA1MTEHdW5pMjAx
+NQd1bmkwMDAyB3VuaTAwMDkAAAAAAQAB//8ADwABAAAADAAAAAAAAAACAAcAzADMAAEBIQEnAAEBWAFj
+AAEBeAF4AAEBfQF+AAEBgAGAAAEBkgGUAAEAAAABAAAACgAeACwAAURGTFQACAAEAAAAAP//AAEAAAAB
+c21jcAAIAAAAAQAAAAEABAABAAAAAQAIAAIBvgDcAZwBnQGeAZ8BoAGhAaIBowGkAaUBpgGnAagBqQGq
+AcMBqwGsAa0BrgGvAbABsQGyAbMBtAGcAZ0BngGfAaABoQGiAaMBpAGlAaYBpwGoAakBqgHDAasBrAGt
+Aa4BrwGwAbEBsgGzAbQBxQJ9AnwCfQJ+An4CfwKAAoECggKDAoQChQKGAocCiAKJAooCiwKMAo0CjgKP
+ApACkQKSApMClAKVApYClwKYApkCfwKAAoECggKDAoQChQKGAocCiAKJAooCiwKMAo0CjgKPApACkQKS
+ApMClAKVApYClwKYApkCywKaApoCmwKbApwCnAKdAp0CngKeAp8CnwKgAqACoQKhAqICogKjAqMCpAKk
+AqUCpQKmAqYCpwKnAqgCqAKpAqkCqgKqAqsCqwKsAqwCrQKtAq4CrwKvArACsAKxArECsgKyArMCswK0
+ArQCtQK1ArYCtgK3ArcCuAK4ArkCuQK6AroCuwK7ArwCvAK9Ar0CvgK+Ar8CvwLAAsACwQLBAl0CXQLC
+AsICwwLDAsQCxALFAsUCxgLGAscCxwLIAsgCyQLJAsoCygLLAswCzALNAs0CzgLOAnwAAgANACMAPAAA
+AEMAXAAaAIMAgwA0AIUAhQA1AcgByQA2AcsCDQA4AhACIQB7AiQCQgCNAkQCVQCsAlgCWQC+AlwCXADA
+Al4CdwDBA8MDwwDb
+''';
+
+String _RobotoRegular_ttf;
+// RobotoRegular_ttf md5 is '11eabca2251325cfc5589c9c6fb57b46'
+String _RobotoRegular_ttf_base64 = '''
+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
+MhYVIzQmIyIGFf0Ic750cDMwLjMB3nRdX3VxNS4sM0h1XV90cDVcM/7LdF1fdHA1Li0z/U9zvnRwMzAu
+M/1NdL50cDMwLjP+3nVdX3RwNVwzNXVdX3VxNS4tMwTzVGhoVC43NTD+61RoZ1UxNDUw/glVZ2hUMTQ3
+Lv35VGhoVDE0Ny7+5FRoaFQuNzcuBRpUaGhULjc1MP4JVWdoVDE0Ny79+VVnZ1UxNDUwAAAI+iz+YwFr
+BcYABAAJAA4AEwAYAB0AIgAnADkAsCEvsBIvsAsvsBsvsCYvsABFWLAHLxuxBx4+WbAARViwFi8bsRYc
+PlmwAEVYsAIvG7ECFD5ZMDEFFwMjEwMnEzMDATcFFSUFByU1BQE3JRcFAQcFJyUDJwM3EwEXEwcD/i8L
+emBGOgx6YEYCHQ0BTf6m+3UN/rMBWgOcAgFARP7b/PMC/sBFASYrEZRBxgNgEZRCxDwO/q0BYQSiDgFS
+/qD+EQx8Ykc7DHxiRwGuEJlEyPyOEZlFyALkAgFGRf7V/OMC/rtHASsA//8Asf6bBbMHGQAmANwAAAAn
+AKEBMQFCAQcAEAR//70AEwCwAEVYsAgvG7EIHj5ZsA3cMDEA//8AnP6bBLUFwwAmAPAAAAAnAKEAof/s
+AQcAEAOB/70AEwCwAEVYsAgvG7EIGj5ZsA3cMDEAAAL/3AAAA/wGcQARABoAd7IUGxwREjmwFBCwA9AA
+sABFWLAMLxuxDB4+WbAARViwEC8bsRAePlmwAEVYsAgvG7EIEj5ZsBAQsQABsAorWCHYG/RZsgIMCBES
+ObACL7AAELAK0LAL0LACELESAbAKK1gh2Bv0WbAIELETAbAKK1gh2Bv0WTAxASERIRYWEAYHIREjNTM1
+MxUhAREhMjY1NCYnApb+vwEYu9TUt/4qv7+6AUH+vwESaXFvZAUY/dICyv620QMFGJjBwfyi/kV3ZGF9
+AgAAAgCoAAAE1wWwAA4AGwBWsgQcHRESObAEELAX0ACwAEVYsAMvG7EDHj5ZsABFWLABLxuxARI+WbIW
+AwEREjmwFi+xAAGwCitYIdgb9FmyCQADERI5sAMQsRQBsAorWCHYG/RZMDEBESMRITIEFRQHFwcnBiMB
+NjU0JichESEyNyc3AWnBAhnsARNnfm2LdqgBGSWlkf6gAVhiRW5uAjr9xgWw8su6cIpnmTcBG0Fbgp0C
+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
+AAD//wAC/lEFawSdAiYCFwAAAAcCUQK8/7j//wCKAAAEYQXLAiYB/gAAAQcAcACcACYAEwCwAEVYsAgv
+G7EIHD5ZsAvcMDEA//8AIv/sBAsFywImAgEAAAEGAHA6JgATALAARViwES8bsREcPlmwE9wwMQD//wBg
+AAAFBgSNAgYB8QAA//8Al//wBTUEjQAmAeMAAAAHAeIB6AAA//8ACQAABfEGAAImAnMAAAAHAHUCngAA
+//8AYP/HBFoGHgImAnUAAAAHAHUBfQAe//8AQ/3/A90EnQImAdkAAAAHAboBKf6g//8AMQAABfEGHgIm
+AdUAAAAHAEQBogAe//8AMQAABfEGHgImAdUAAAAHAHUCMQAe//8AMQAABfEF4wImAdUAAAAHAGoBawAe
+//8ADQAABBwGHgImAdMAAAAHAEQApAAe//8AHP5PBR0FsAImACUAAAAHAKQBfAAA//8Abf5PA+oETgIm
+AEUAAAAHAKQAxAAA//8Aqf5ZBEYFsAImACkAAAAHAKQBOgAK//8AXf5PA/METgImAEkAAAAHAKQBBgAA
+//8AE/5PBHAEjQImAjMAAAAHAKQBHgAA//8Aiv5XA64EjQImAigAAAAHAKQA5wAI//8Ahf6sAWAEOgIm
+AI0AAAAHAK0DTQAKAAEAAAUOAI8AFgBUAAUAAQAAAAAADgAAAgACJAAGAAEAAABhAGEAYQBhAGEAlAC5
+AToBrgJAAtQC6wMVAz8DcgOYA7cDzgPwBAcEVQSDBNMFSgWOBfAGUQZ+BvMHWwdwB4UHpAfMB+sISgjv
+CTUJlQnqCjAKcgqpCxYLYQt8C68MBAwoDHYMsg0IDVQNug4XDoMOrg7wDyAPdQ/KD/oQMxBYEG8QlRC8
+ENcQ9xFxEdASJBKDEuwTPxO6FAAUORSGFN0U+BVkFa8V/hZjFsUXAxdvF8IYCRg5GIcYzhkUGU0Zjhml
+GeUaLRphGr4bMRuVG/ccFhy9HOwdlB4EHhAeLh7oHwIfPx+DH9QgUCBwILog5iEGIUIhdCG/Icsh5SH/
+IhkieyLgIx4jmiPvJGAlICWQJeMmVSa1JywniyemJ/YoQSh/KNApLCmxKkwqfSrkK0wrtywYLGwsxiz1
+LVotiC2sLbot5i4GLj8udS66Lu0vKy9IL2Uvbi+hL9Iv7jAKME4wWjCBMK8xLDFZMZ0xzDIJMn4y2DNB
+M7c0LjRhNNQ1QjWfNeo2azaZNvM3Yze1OBA4bDjEOQg5Sjm0OhE6eDrwO0Q7uzwXPJI9Cj1+PdM+ED5p
+PsI/MT+oP+1AOECAQPJBKEFtQatB9EJNQrFC/kN9RA9Ea0TcRVRFe0XSRkZGwUb6R1JHmkfiSD9Ibkia
+SSZJXEmdSdtKIEp4SttLJkuZTCBMfEz1TXdN7k5dTsVPAU9kT8VQLlCyUU5RmlHpUlRSw1M5U6lUNVTA
+VVJV7VZwVupXL1d1V+JYSlkFWcFaQVrBWxNbYVuWW7Jb6lwAXBZc6l1dXXhdk139XllezV79Xyhffl/U
+X+Bf7F/4YARgW2C+YRNhc2F/YYth1mJAYp9i/2OgZDlkRWRRZKJk5mTyZP5lTmWcZd5mUGbCZxtngGeM
+Z5hoEmiKaJZoomiuaLppJGmFaeBp72oDag9qG2ppas1rVWvHbDZsmmz8bWtt1m5gbuNvQG+Tb+ZwOHCv
+cLtwx3D2cPZw9nD2cPZw9nD2cPZw9nD2cPZw9nD2cPZw/nEGcRBxGnEycVZxenGdcbhxxHHQcghyR3Kp
+cs1y2XLpcwxz33P7dBh0K3Q/dIZ1EHWudj92S3crd494DXiseRB5i3nlelF7A3tqfAB8XnzCfNx89n0Q
+fSp9nH3Dffx+GH5NfuB/In+vf/CADoAsgGWAcoCcgL+Ay4E0gYeCFIKDgvaDw4PDhXaF4oYyhl6GqIcG
+h32HrogViHmIwIk+iZKJxIoSikuKe4rEixyLTIuKi7WMHIx1jNSNH41zjayN/Y4hjmSOmo61jvaPVo+O
+kAKQZ5DGkPCRJpGOkcCSDpJAkoCS55M/k6GUAJRylOiVXpWxlfGWSpailxaXkZfNmB2YZpismOeZKZlp
+mbOaDZoZmmea15tVm62b8Jx2nNidOZ2XniyePZ6YnuWfM591n+agSqCwoSGhtaI7otKjRaO1o/ikVaSv
+pNylWaW4pc+mNaZ6pyWniaftqD2og6jEqQapTqmjqgqqSqpkqrOrKKtwq7isGKyGrLOtAq1irXatiq2c
+rbCtwq3Zre2uSa67rwivaK/Rr/ywULCisOaxPbFksdWx67JvstKy/rMPsyCzM7NEs1WzaLN7s46zpLOs
+s7SzvLPNs9iz4LRItJe0xLUltXi12bZUtp63BLdmt8q4Q7hLuOa5M7mfue+6aLrWuye7J7svu5W7+7xa
+vJ29A70avTG9SL1fvXi9kb2dvam9wL3Xve6+B74evjW+TL5lvny+k76qvsG+2L7xvwi/H782v0+/Zr99
+v5S/qr/Av9m/8r/+wArAIcA4wE7AZ8B9wJPAqsDDwNnA8MEHwR3BM8FMwWPBesGQwanBwMHYwe/CBcIc
+wjPCl8Mvw0bDXcN0w4rDocO4w8/D5cP8xC3ERMRaxHHEiMSfxLbFIMWmxb3F08XqxgDGF8YuxkXGXMZo
+xn/Glsaoxr/G1sbtxwTHG8cyxz3HSMdfx2vHd8eOx6XHsce9x9TH68f3yAPIGMhNyFnIZch8yJPIn8ir
+yMLI2MjtyQTJGskxyUjJYcl6yZHJqMm0ycDJ18ntygTKG8oyykjKVMpgymzKeMqPyqXKscq9ysnK1crs
+ywLLGcsvy0bLXMtzy4rLo8u8y9XL7sxMzLPMyszhzPjNDs0nzT7NVc1szYPNms2wzcfN3s31zgzOL85X
+zmrOgc6Yzq7OxM7dzvbPAs8OzyXPPM9Sz2rPgM+Wz63Pxs/dz/TQC9Ai0DnQUtBp0IDQltCv0MbQ3NDz
+0VfRbtGE0ZvRstHI0d7R9NIL0nbSjNKi0rnS0NLc0vPTCtMh0zjTQ9NZ03DTfNOS057Ts9O/09bT4tP5
+1BDUJ9RA1FfUY9R51JDUptSy1MjU1NTq1PbVDNUi1TnVUtVr1cjV39X11g3WJNY71lHWXNZo1nTWgNaM
+1pjWpNbA1sjW0NbY1uDW6Nbw1vjXANcI1xDXGNcg1yjXMNdJ12LXedeQ16fXvdfY1+DX6Nfw1/jYY9h7
+2JPYqtjB2NjY8dkI2XTZfNmV2Z3Zpdm82dPZ29nj2evZ89oK2hLaGtoi2iraMto62kLaStpS2lracdp5
+2oHa1drd2uXa/tsV2x3bJds+20bbXdtz24rbodu428/b6NwB3BjcL9w33D/cS9xi3GrcgdyY3KTcsNzH
+3N7c9d0M3RTdHN013U7dWt1m3XLdft2K3Zbdnt2m3a7dxd3c3eTd+94S3iveRN5M3lTea96C3pveo968
+3tXe7t8H3x/fNt9M32Xfft+X37DfuN/A39nf8uAL4CPgOuBQ4GnggeCa4LPgzODk4QHhHuEm4TLhPuFV
+4WzhheGd4bbhzuHn4f/iGOIw4kviZeJ+4pfisOLJ4uLi++MU4y3jSONj42/je+OS46njwOPW4+/kB+Qg
+5DjkUeRp5ILkmuS15M/k5uT95QnlFeUh5S3lROVb5XTljOWl5b3l1uXu5gfmH+Y65lTma+aC5pnmsObH
+5t7m9ecL5xfnI+cv5zvnUudp54Dnl+eu58Xn3Ofz6AroIOgs6DjoROhQ6GfofuiV6KvowOjM6Njo5Ojw
+6PzpCOkU6SDpKOmI6ejqK+pr6s/rLut468jsIex47IDsjOyW7J7spuyu7LbsvuzG7M7s1uzt7QTtG+0y
+7UvtZO197Zbtr+3I7eHt+u4T7izuRe5e7mrudu6C7o7umu6r7rfuw+7P7ubu+O8E7xDvHO8o7zTvQO9M
+71jveu+R76jvtO/A78zv2O/k7/DwCPAf8DXwQfBN8FnwZfBx8H3wifCV8KHwrfC58MXw0fDd8OXw7fD1
+8P3xBfEN8RXxHfEl8S3xNfE98UXxTfFm8X7xlvGt8bXxvfHW8d7x9fIL8hPyG/Ij8ivyQvJK8lLyWvJi
+8mrycvJ68oLzDfNa87nzwfPN8+Tz+vQC9A70GvQm9DL0PvRK9Fb0YvRu9Hr0hvSS9J70qvS2AAAAAQAA
+AAIjEutvwDJfDzz1ABkIAAAAAADE8BEuAAAAANUBUvT6G/3VCTAIcwAAAAkAAgAAAAAAAAOMAGQAAAAA
+AAAAAAH7AAAB+wAAAg8AoAKPAIgE7QB3BH4AbgXcAGkE+QBlAWUAZwK8AIUCyAAmA3IAHASJAE4BkgAd
+AjUAJQIbAJADTAASBH4AcwR+AKoEfgBdBH4AXgR+ADUEfgCaBH4AhAR+AE0EfgBwBH4AZAHwAIYBsQAp
+BBEASARkAJgELgCGA8cASwcvAGoFOAAcBPsAqQU1AHcFPwCpBIwAqQRsAKkFcwB6BbQAqQItALcEagA1
+BQQAqQROAKkG/ACpBbQAqQWAAHYFDACpBYAAbQTtAKgEvwBQBMYAMQUwAIwFFwAcBxkAPQUEADkEzgAP
+BMoAVgIfAJIDSAAoAh8ACQNYAEADnAAEAnkAOQRaAG0EfQCMBDAAXASDAF8EPQBdAscAPAR9AGAEaACM
+AfEAjQHp/78EDgCNAfEAnAcDAIsEagCMBJAAWwR9AIwEjABfArUAjAQgAF8CnQAJBGkAiAPgACEGAwAr
+A/cAKQPJABYD9wBYArUAQAHzAK8CtQATBXEAgwHzAIsEYABpBKYAWwW0AGkEMwAPAesAkwToAFoDWABl
+BkkAWwOTAJMDwQBmBG4AfwZKAFoDqgCOAv0AggRGAGEC7wBCAu8APgKCAHsEiACaA+kAQwIWAJMB+wB0
+Au8AegOjAHoDwABmBdwAVQY1AFAGOQBvA8kARAd6//IERABZBYAAdgS6AKYEwgCLBsEATgSwAH4EkQBH
+BIgAWwScAJUExwBfBZoAHQH6AJsEcwCaBE8AIgIpACIFiwCiBIgAkQehAGgHRABhAfwAoAWHAF0Cuf/k
+BX4AZQSSAFsFkACMBPMAiAID/7QENwBiA8QAqQONAI0DqwCOA2oAgQHxAI0CrQB5AioAMgPGAHsC/ABe
+AloAfgAA/KcAAP1vAAD8iwAA/V4AAPwnAAD9OAINALcECwBxAhcAkwRzALEFpAAfBXEAZwU+ADIEkQB4
+BbUAsgSRAEUFuwBNBYkAWgVSAHEEhQBkBL0AoAQCAC4EiABgBFAAYwQlAG0EiACRBI4AegKXAMMEbgAl
+A+wAZQTEACkEiACRBE0AZQSIAGAELABRBF0AjwWjAFcFmgBfBpcAegShAHkEQv/aBkgASgX/ACoFZAB7
+CJEAMQikALEGggA+BbQAsAULAKIGBAAyB0MAGwS/AFAFtACxBakALwUHAE0GLABTBdkArwV6AJYHhwCw
+B8AAsAYSABAG6wCyBQUAowVkAJMHJwC3BRgAWQRsAGEEkgCdA1sAmgTUAC4GIAAVBBAAWASeAJwEUgCc
+BKAALAXvAJ0EnQCcBJ4AnAPYACgFzQBkBL0AnARZAGcGeACcBp4AkQT3AB4GNgCdBFgAnQRNAGQGhwCd
+BGQALwRo/+gETQBnBskAJwbkAJwEif/9BJ4AnAcIAJwGKwCBBFb/3AcrALcF+ACZBNIAKARGAA8HCwDJ
+BgsAvAbRAJMF4QCWCQQAtgfRAJsEIwBQA9sATAVxAGcEiwBbBQoAFgQDAC4FcQBnBIgAWwcBAJwGJAB+
+BwgAnAYrAIEFMgB1BEcAZAT9AHQAAPxnAAD8cQAA/WYAAP2kAAD6GwAA+iwGCQCxBO0AnARW/9wFGwCo
+BIkAjARjAKIDkACRBNsAsQQFAJEHogAbBmEAFQWaALIEuACcBQkAowR+AJoGjABEBYMAPgX/AKkE2QCc
+B88AqAW0AJEIMQCwBvQAkQXuAHEE0wBtBRgAOQQqACkHLAA0BVwAHwW8AJYElgBnBW8AlgRqAIMFbwCJ
+Bi8APwS9/94FCQCjBFoAmgX+AC8E7wAsBbIAsQSIAJEGEgCpBOwAnAdPAKkGPgCdBYcAXQSoAGgEqABp
+BLcAOgOrADsFLgA5BEAAKQT2AFcGlABZBuQAZAZWADYFKwAxBEkAUgQHAHkHwQBEBnUAPwf7AKkGoQCQ
+BPYAdgQdAGUFrQAjBSAARgVkAJYGAgAvBPIALAMgAG8EFAAACCkAAAQUAAAIKQAAArkAAAIKAAABXAAA
+BH8AAAIwAAABogAAAQAAAADRAAAAAAAAAjQAJQI0ACUFQACiBj8AkAOlAA0BmQBgAZkAMAGXACQBmQBP
+AtQAaALbADwCwQAkBGkARgSPAFcCsgCKA8QAlAVaAJQBfgBSB6oARAJmAGwCZgBZA6MAOwLvADYDYAB6
+BKYAWwZVAB8GkACnCHYAqAXrAB8GKwCMBH4AXwXaAB8EIgAqBHQAIAVIAF0FTwAfBecAegPOAGgIOgCi
+BQEAZwUXAJgGJgBUBtcAZAbPAGMGagBZBI8AagWOAKkErwBFBJIAqATFAD8IOgBiAgz/sASCAGUEZACY
+BBEAPgQvAIUECAArAkwAtQKPAG4CAwBcBPMAPARuAB8EiwA8BtQAPAbUADwE7gA8BpsAXwAAAAAIMwBb
+CDUAXALvAEIC7wB6Au8AUAQPAFUEDwBgBA8AQgQOAHIEDwCABA8AMAQPAE4EDwBOBA8AmAQPAGMEIwBH
+BCsADQRUACYGFQAxBGcAFAR8AHQEJgAoBCAAQwRKAIoEuwBZBFwAigS7AGAE4wCKBgIAigO0AIoEVACK
+A88AKwHoAJcE4wCKBKwAYwPLAIoEIABDBDMAMAOhAA0DrwCKBGcAFAS7AGAEZwAUA4kAPgTOAIoD7wA/
+BWcAYAUXAGAE8gB1BXIAJgR8AGAHQQAnB08AigV0ACgEzQCKBFkAigUkAC4GCwAfBD8ARwTsAIoETgCL
+BMEAJwQfACIFKACKBGoAPQZRAIoGrACKBR0ACAXxAIoETgCKBHsASwZ2AIoEhwBQBBEACwZHAB8EeQCL
+BQkAiwU3ACMFwgBgBF8ADQSoACYGYQAmBGoAPQRqAIoFwwACBMoAXgQ/AEcEuwBgBDMAMAPjAEIIIgCK
+BKsAKALvAD4C7wA2Au8AWwLvAFYC7wA6Au8ATwLvAEkDlgCPArUAngPmAIoEOgAeBMMAZAVMALEFJACy
+BBMAkgU9ALIEDwCSBIAAigR8AGAEUACKBIUAEwH9AJ8DpACBAAD8pAPvAG4D8/9eBA4AaQP0AGkDrwCK
+A58AgQOeAIEC7wBQAu8ANgLvAFsC7wBWAu8AOgLvAE8C7wBJBYEAfgWuAH4FkwCyBeAAfgXjAH4D1QCg
+BIIAgwRYAA8EzwA+BGsAZQQuAEoDpACDAZEAZwakAGAEuQCCAfz/tgR/ADsEfwBzBH8AIwR/AHcEfwB2
+BH8ANwR/AH4EfwBfBH8AcAR/APQCBv+0AgT/tAH7AJsB+//6AfsAmwRQAIoFAAB4BCAAOwR9AIwEMgBc
+BJMAWwSMAFsEngBaBI0AjAScAFsEPQBdBH0AYAN5AFcE1gBnA7QAAAY5AAkD+ACKBLsAYATjADAE4wCK
+AfsAAAI1ACUFXQAHBV0ABwSG/+IExgAxAp3/9AU4ABwFOAAcBTgAHAU4ABwFOAAcBTgAHAU4ABwFNQB3
+BIwAqQSMAKkEjACpBIwAqQIt/+ACLQCwAi3/6QIt/9UFtACpBYAAdgWAAHYFgAB2BYAAdgWAAHYFMACM
+BTAAjAUwAIwFMACMBM4ADwRaAG0EWgBtBFoAbQRaAG0EWgBtBFoAbQRaAG0EMABcBD0AXQQ9AF0EPQBd
+BD0AXQH6/8YB+gCWAfr/zwH6/7sEagCMBJAAWwSQAFsEkABbBJAAWwSQAFsEaQCIBGkAiARpAIgEaQCI
+A8kAFgPJABYFOAAcBFoAbQU4ABwEWgBtBTgAHARaAG0FNQB3BDAAXAU1AHcEMABcBTUAdwQwAFwFNQB3
+BDAAXAU/AKkFGQBfBIwAqQQ9AF0EjACpBD0AXQSMAKkEPQBdBIwAqQQ9AF0EjACpBD0AXQVzAHoEfQBg
+BXMAegR9AGAFcwB6BH0AYAVzAHoEfQBgBbQAqQRoAIwCLf+3Afr/nQIt/8wB+v+yAi3/7AH6/9ICLQAY
+AfH/+wItAKkGlwC3A9oAjQRqADUCA/+0BQQAqQQOAI0ETgChAfEAkwROAKkB8QBXBE4AqQKHAJwETgCp
+As0AnAW0AKkEagCMBbQAqQRqAIwFtACpBGoAjARq/7wFgAB2BJAAWwWAAHYEkABbBYAAdgSQAFsE7QCo
+ArUAjATtAKgCtQBTBO0AqAK1AGMEvwBQBCAAXwS/AFAEIABfBL8AUAQgAF8EvwBQBCAAXwS/AFAEIABf
+BMYAMQKdAAkExgAxAp0ACQTGADECxQAJBTAAjARpAIgFMACMBGkAiAUwAIwEaQCIBTAAjARpAIgFMACM
+BGkAiAUwAIwEaQCIBxkAPQYDACsEzgAPA8kAFgTOAA8EygBWA/cAWATKAFYD9wBYBMoAVgP3AFgHev/y
+BsEATgWAAHYEiABbBID/vgSA/74EJgAoBIUAEwSFABMEhQATBIUAEwSFABMEhQATBIUAEwR8AGAD5gCK
+A+YAigPmAIoD5gCKAej/vgHoAI4B6P/HAej/swTjAIoEuwBgBLsAYAS7AGAEuwBgBLsAYAR8AHQEfAB0
+BHwAdAR8AHQEKwANBIUAEwSFABMEhQATBHwAYAR8AGAEfABgBHwAYASAAIoD5gCKA+YAigPmAIoD5gCK
+A+YAigSsAGMErABjBKwAYwSsAGME4wCKAej/lQHo/6oB6P/KAegABgHoAIgDzwArBFQAigO0AIIDtACK
+A7QAigO0AIoE4wCKBOMAigTjAIoEuwBgBLsAYAS7AGAESgCKBEoAigRKAIoEIABDBCAAQwQgAEMEIABD
+BCYAKAQmACgEJgAoBHwAdAR8AHQEfAB0BHwAdAR8AHQEfAB0BhUAMQQrAA0EKwANBCMARwQjAEcEIwBH
+BTgAHASM/ykFtP83Ai3/PQWU/+YFMv8UBWb/6QKX/5sFOAAcBPsAqQSMAKkEygBWBbQAqQItALcFBACp
+BvwAqQW0AKkFgAB2BQwAqQTGADEEzgAPBQQAOQIt/9UEzgAPBIUAZARQAGMEiACRApcAwwRdAI8EcwCa
+BJAAWwSIAJoD4AAhA/cAKQKX/+UEXQCPBJAAWwRdAI8GlwB6BIwAqQRzALEEvwBQAi0AtwIt/9UEagA1
+BSQAsgUEAKkFBwBNBTgAHAT7AKkEcwCxBIwAqQW0ALEG/ACpBbQAqQWAAHYFtQCyBQwAqQU1AHcExgAx
+BQQAOQRaAG0EPQBdBJ4AnASQAFsEfQCMBDAAXAPJABYD9wApBD0AXQNbAJoEIABfAfEAjQH6/7sB6f+/
+BFIAnAPJABYHGQA9BgMAKwcZAD0GAwArBxkAPQYDACsEzgAPA8kAFgFlAGcCjwCIBB4AoAID/7QBmQAw
+BvwAqQcDAIsFOAAcBFoAbQSMAKkFtACxBD0AXQSeAJwFiQBaBZoAXwUKABYEA//7CFkAWwlJAHYEvwBQ
+BBAAWAU1AHcEMABcBM4ADwQCAC4CLQC3B0MAGwYgABUCLQC3BTgAHARaAG0FOAAcBFoAbQd6//IGwQBO
+BIwAqQQ9AF0FhwBdBDcAYgQ3AGIHQwAbBiAAFQS/AFAEEABYBbQAsQSeAJwFtACxBJ4AnAWAAHYEkABb
+BXEAZwSLAFsFcQBnBIsAWwVkAJMETQBkBQcATQPJABYFBwBNA8kAFgUHAE0DyQAWBXoAlgRZAGcG6wCy
+BjYAnQSDAF8FOAAcBFoAbQU4ABwEWgBtBTgAHARaAG0FOAAcBFr/ygU4ABwEWgBtBTgAHARaAG0FOAAc
+BFoAbQU4ABwEWgBtBTgAHARaAG0FOAAcBFoAbQU4ABwEWgBtBTgAHARaAG0EjACpBD0AXQSMAKkEPQBd
+BIwAqQQ9AF0EjACpBD0AXQSM//AEPf+6BIwAqQQ9AF0EjACpBD0AXQSMAKkEPQBdAi0AtwH6AJsCLQCj
+AfEAhQWAAHYEkABbBYAAdgSQAFsFgAB2BJAAWwWAAEcEkP/EBYAAdgSQAFsFgAB2BJAAWwWAAHYEkABb
+BX4AZQSSAFsFfgBlBJIAWwV+AGUEkgBbBX4AZQSSAFsFfgBlBJIAWwUwAIwEaQCIBTAAjARpAIgFkACM
+BPMAiAWQAIwE8wCIBZAAjATzAIgFkACMBPMAiAWQAIwE8wCIBM4ADwPJABYEzgAPA8kAFgTOAA8DyQAW
+BKEAXwTGADED2AAoBXoAlgRZAGcEcwCxA1sAmgYvAD8Evf/eBGgAjAUF/9QFBf/UBHMAAwNb//wFOP/3
+BCf/vwTOAA8EAgAuBQQAOQP3ACkEUABjBGwAEgY/AJAEfgBdBH4AXgR+ADUEfgCaBJIAmASmAIQEkgBk
+BKYAhwVzAHoEfQBgBbQAqQRqAIwFOAAcBFoAOQSMAF8EPQApAi3/CgH6/vAFgAB2BJAAMwTtAFUCtf+L
+BTAAjARpACsEpv7WBPsAqQR9AIwFPwCpBIMAXwU/AKkEgwBfBbQAqQRoAIwFBACpBA4AjQUEAKkEDgCN
+BE4AqQHxAIYG/ACpBwMAiwW0AKkEagCMBYAAdgUMAKkEfQCMBO0AqAK1AIIEvwBQBCAAXwTGADECnQAJ
+BTAAjAUXABwD4AAhBRcAHAPgACEHGQA9BgMAKwTKAFYD9wBYBcb+MgSFABMEIv9jBR//gAIk/4QExf/V
+BGf/GwT8/+4EhQATBFAAigPmAIoEIwBHBOMAigHoAJcEVACKBgIAigTjAIoEuwBgBFwAigQmACgEKwAN
+BFQAJgHo/7MEKwANA+YAigOvAIoEIABDAegAlwHo/7MDzwArBFQAigQfACIEhQATBFAAigOvAIoD5gCK
+BOwAigYCAIoE4wCKBLsAYATOAIoEXACKBHwAYAQmACgEVAAmBD8ARwTjAIoEfABgBCsADQXDAAIE7ACK
+BB8AIgVnAGAFtwCXBjkACQS7AGAEIABDBhUAMQYVADEGFQAxBCsADQU4ABwEWgBtBIwAqQQ9AF0EhQAT
+A+YAigH6AIUAAQAAB2z+DAAACUn6G/5KCTAAAQAAAAAAAAAAAAAAAAAABQ4AAwSGAZAABQAABZoFMwAA
+AR8FmgUzAAAD0QBmAgAAAAIAAAAAAAAAAADgAAL/UAAgWwAAACAAAAAAR09PRwBAAAD//QYA/gAAZgea
+AgAgAAGfAAAAAAQ6BbAAIAAgAAMAAAABAAAFEAkKBAAAAgICAwYFBwYCAwMEBQICAgQFBQUFBQUFBQUF
+AgIFBQUECAYGBgYFBQYGAgUGBQgGBgYGBgUFBgYIBgUFAgQCBAQDBQUFBQUDBQUCAgUCCAUFBQUDBQMF
+BAcEBAQDAgMGAgUFBgUCBgQHBAQFBwQDBQMDAwUEAgIDBAQHBwcECAUGBQUIBQUFBQUGAgUFAgYFCQgC
+BgMGBQYGAgUEBAQEAgMCBAMDAAAAAAAAAgUCBQYGBgUGBQYGBgUFBQUFBQUFAwUEBQUFBQUFBgYHBQUH
+BwYKCgcGBgcIBQYGBgcHBggJBwgGBggGBQUEBQcFBQUFBwUFBAcFBQcHBgcFBQcFBQUICAUFCAcFCAcF
+BQgHCAcKCQUEBgUGBQYFCAcIBwYFBgAAAAAAAAcGBQYFBQQFBQkHBgUGBQcGBwUJBgkIBwUGBQgGBgUG
+BQYHBQYFBwYGBQcGCAcGBQUFBAYFBgcIBwYFBQkHCQcGBQYGBgcGBAUJBQkDAgIFAgIBAQACAgYHBAIC
+AgIDAwMFBQMEBgIJAwMEAwQFBwcKBwcFBwUFBgYHBAkGBgcICAcFBgUFBQkCBQUFBQUDAwIGBQUICAYH
+AAkJAwMDBQUFBQUFBQUFBQUFBQcFBQUFBQUFBQYHBAUEAgYFBAUFBAQFBQUEBQQGBgYGBQgIBgUFBgcF
+BgUFBQYFBwgGBwUFBwUFBwUGBgYFBQcFBQYFBQUFBAkFAwMDAwMDAwQDBAUFBgYFBgUFBQUFAgQABAQF
+BAQEBAMDAwMDAwMGBgYHBwQFBQUFBQQCBwUCBQUFBQUFBQUFBQICAgICBQYFBQUFBQUFBQUFBAUEBwQF
+BgYCAgYGBQUDBgYGBgYGBgYFBQUFAgICAgYGBgYGBgYGBgYFBQUFBQUFBQUFBQUFAgICAgUFBQUFBQUF
+BQUEBAYFBgUGBQYFBgUGBQYFBgYFBQUFBQUFBQUFBgUGBQYFBgUGBQICAgICAgICAgcEBQIGBQUCBQIF
+AwUDBgUGBQYFBQYFBgUGBQYDBgMGAwUFBQUFBQUFBQUFAwUDBQMGBQYFBgUGBQYFBgUIBwUEBQUEBQQF
+BAgIBgUFBQUFBQUFBQUFBQQEBAQCAgICBgUFBQUFBQUFBQUFBQUFBQUFBQQEBAQEBQUFBQYCAgICAgQF
+BAQEBAYGBgUFBQUFBQUFBQUFBQUFBQUFBQUHBQUFBQUGBQYCBgYGAwYGBQUGAgYIBgYGBQUGAgUFBQUD
+BQUFBQQEAwUFBQcFBQUCAgUGBgYGBgUFBggGBgYGBgUGBQUFBQUFBAQFBAUCAgIFBAgHCAcIBwUEAgMF
+AgIICAYFBQYFBQYGBgUJCgUFBgUFBQIIBwIGBQYFCAgFBQYFBQgHBQUGBQYFBgUGBQYFBgUGBAYEBgQG
+BQgHBQYFBgUGBQYFBgUGBQYFBgUGBQYFBgUGBQUFBQUFBQUFBQUFBQUFBQUCAgICBgUGBQYFBgUGBQYF
+BgUGBQYFBgUGBQYFBgUGBQYGBgYGBgYGBgYFBAUEBQQFBQQGBQUEBwUFBgYFBAYFBQUGBAUFBwUFBQUF
+BQUFBgUGBQYFBQUCAgYFBgMGBQUGBQYFBgUGBQYFBgUFAggIBgUGBgUGAwUFBQMGBgQGBAgHBQQHBQUG
+AgUFBgUFBAUGAgUHBgUFBQUFAgUEBAUCAgQFBQUFBAQGBwYFBQUFBQUFBgUFBgYFBgYHBQUHBwcFBgUF
+BQUEAgAAAAMAAAADAAAAHAADAAEAAAAcAAMACgAABooABAZuAAAA9ACAAAYAdAAAAAIADQB+AKAArACt
+AL8AxgDPAOYA7wD+AQ8BEQElAScBMAFTAV8BZwF+AX8BjwGSAaEBsAHwAf8CGwI3AlkCvALHAskC3QLz
+AwEDAwMJAw8DIwOKA4wDkgOhA7ADuQPJA84D0gPWBCUELwRFBE8EYgRvBHkEhgSfBKkEsQS6BM4E1wTh
+BPUFAQUQBRMeAR4/HoUe8R7zHvkfTSAJIAsgESAVIB4gIiAnIDAgMyA6IDwgRCB0IH8gpCCqIKwgsSC6
+IL0hBSETIRYhIiEmIS4hXiICIgYiDyISIhoiHiIrIkgiYCJlJcruAvbD+wT+///9//8AAAAAAAIADQAg
+AKAAoQCtAK4AwADHANAA5wDwAP8BEAESASYBKAExAVQBYAFoAX8BjwGSAaABrwHwAfoCGAI3AlkCvALG
+AskC2ALzAwADAwMJAw8DIwOEA4wDjgOTA6MDsQO6A8oD0QPWBAAEJgQwBEYEUARjBHAEegSIBKAEqgSy
+BLsEzwTYBOIE9gUCBREeAB4+HoAeoB7yHvQfTSAAIAogECATIBcgICAlIDAgMiA5IDwgRCB0IH8goyCm
+IKsgsSC5ILwhBSETIRYhIiEmIS4hWyICIgYiDyIRIhoiHiIrIkgiYCJkJcruAfbD+wH+///8//8AAQAA
+//b/5AHY/8IBzP/BAAABvwAAAboAAAG2AAABtAAAAbIAAAGqAAABrP8W/wf/Bf74/usB7gAAAAD+Zf5E
+ASP92P3X/cn9tP2o/af9ov2d/YoAAP/+//0AAAAA/QoAAP/e/P78+wAA/LoAAPyyAAD8pwAA/KEAAPyZ
+AAD8kQAA/ygAAP8lAAD8XgAA5eLlouVT5X7k5+V85X3hcuFz4W8AAOFs4WvhaeFh46nhWeOh4VDhIeEX
+AADg8gAA4O3g5uDl4J7gkeCP4ITflOB54E3fqt6s357fnd+W35Pfh99r31TfUdvtE7cK9wa7AsMBxwAB
+AAAAAAAAAAAAAAAAAAAAAADkAAAA7gAAARgAAAEyAAABMgAAATIAAAF0AAAAAAAAAAAAAAAAAAABdAF+
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWwAAAAAAXQBkAAAAagAAAAAAAABwAAAAggAAAIwAAACUgAA
+AmIAAAKOAAACmgAAAr4AAALOAAAC4gAAAAAAAAAAAAAAAAAAAAAAAAAAAtIAAAAAAAAAAAAAAAAAAAAA
+AAAAAALCAAACwgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAJ/AoACgQKCAoMChACBAnsCjwKQApECkgKTApQAggCDApUClgKXApgCmQCEAIUCmgKbApwCnQKe
+Ap8AhgCHAqoCqwKsAq0CrgKvAIgAiQKwArECsgKzArQAigJ6AIsAjAJ8AI0C4wLkAuUC5gLnAugAjgLp
+AuoC6wLsAu0C7gLvAvAAjwCQAvEC8gLzAvQC9QL2AvcAkQCSAvgC+QL6AvsC/AL9AJMAlAMMAw0DEAMR
+AxIDEwJ9An4ChQKgAysDLAMtAy4DCgMLAw4DDwCuAK8DhgCwA4cDiAOJALEAsgOQA5EDkgCzA5MDlAC0
+A5UDlgC1A5cAtgOYALcDmQOaALgDmwC5ALoDnAOdA54DnwOgA6EDogOjAMQDpQOmAMUDpADGAMcAyADJ
+AMoAywDMA6cAzQDOA+QDrQDSA64A0wOvA7ADsQOyANQA1QDWA7QD5QO1ANcDtgDYA7cDuADZA7kA2gDb
+ANwDugOzAN0DuwO8A70DvgO/A8ADwQDeAN8DwgPDAOoA6wDsAO0DxADuAO8A8APFAPEA8gDzAPQDxgD1
+A8cDyAD2A8kA9wPKA+YDywECA8wBAwPNA84DzwPQAQQBBQEGA9ED5wPSAQcBCAEJBIED6APpARcBGAEZ
+ARoD6gPrA+0D7AEoASkBKgErBIABLAEtAS4BLwEwBIIEgwExATIBMwE0A+4D7wE1ATYBNwE4BIQEhQPw
+A/EEdwR4A/ID8wSGBIcEfwFMAU0EfQR+A/QD9QP2AU4BTwFQAVEBUgFTAVQBVQR5BHoBVgFXAVgEAQQA
+BAIEAwQEBAUEBgFZAVoEewR8BBsEHAFbAVwBXQFeBIgEiQFfBB0EigFvAXABgQGCBIwEiwGXBHYBnQAM
+AAAAAAu8AAAAAAAAAPkAAAAAAAAAAAAAAAEAAAACAAAAAgAAAAIAAAANAAAADQAAAAMAAAAgAAAAfgAA
+AAQAAACgAAAAoAAAAngAAAChAAAArAAAAGMAAACtAAAArQAAAnkAAACuAAAAvwAAAG8AAADAAAAAxQAA
+An8AAADGAAAAxgAAAIEAAADHAAAAzwAAAoYAAADQAAAA0AAAAnsAAADRAAAA1gAAAo8AAADXAAAA2AAA
+AIIAAADZAAAA3QAAApUAAADeAAAA3wAAAIQAAADgAAAA5QAAApoAAADmAAAA5gAAAIYAAADnAAAA7wAA
+AqEAAADwAAAA8AAAAIcAAADxAAAA9gAAAqoAAAD3AAAA+AAAAIgAAAD5AAAA/QAAArAAAAD+AAAA/gAA
+AIoAAAD/AAABDwAAArUAAAEQAAABEAAAAnoAAAERAAABEQAAAIsAAAESAAABJQAAAsYAAAEmAAABJgAA
+AIwAAAEnAAABJwAAAnwAAAEoAAABMAAAAtoAAAExAAABMQAAAI0AAAEyAAABNwAAAuMAAAE4AAABOAAA
+AI4AAAE5AAABQAAAAukAAAFBAAABQgAAAI8AAAFDAAABSQAAAvEAAAFKAAABSwAAAJEAAAFMAAABUQAA
+AvgAAAFSAAABUwAAAJMAAAFUAAABXwAAAv4AAAFgAAABYQAAAwwAAAFiAAABZQAAAxAAAAFmAAABZwAA
+An0AAAFoAAABfgAAAxQAAAF/AAABfwAAAJUAAAGPAAABjwAAAJYAAAGSAAABkgAAAJcAAAGgAAABoQAA
+AJgAAAGvAAABsAAAAJoAAAHwAAAB8AAAA94AAAH6AAAB+gAAAoUAAAH7AAAB+wAAAqAAAAH8AAAB/wAA
+AysAAAIYAAACGQAAAwoAAAIaAAACGwAAAw4AAAI3AAACNwAAAJwAAAJZAAACWQAAAJ0AAAK8AAACvAAA
+A98AAALGAAACxwAAAJ4AAALJAAACyQAAAKAAAALYAAAC3QAAAKEAAALzAAAC8wAAAKcAAAMAAAADAQAA
+AKgAAAMDAAADAwAAAKoAAAMJAAADCQAAAKsAAAMPAAADDwAAAKwAAAMjAAADIwAAAK0AAAOEAAADhQAA
+AK4AAAOGAAADhgAAA4YAAAOHAAADhwAAALAAAAOIAAADigAAA4cAAAOMAAADjAAAA4oAAAOOAAADkgAA
+A4sAAAOTAAADlAAAALEAAAOVAAADlwAAA5AAAAOYAAADmAAAALMAAAOZAAADmgAAA5MAAAObAAADmwAA
+ALQAAAOcAAADnQAAA5UAAAOeAAADngAAALUAAAOfAAADnwAAA5cAAAOgAAADoAAAALYAAAOhAAADoQAA
+A5gAAAOjAAADowAAALcAAAOkAAADpQAAA5kAAAOmAAADpgAAALgAAAOnAAADpwAAA5sAAAOoAAADqQAA
+ALkAAAOqAAADsAAAA5wAAAOxAAADuQAAALsAAAO6AAADugAAA6MAAAO7AAADuwAAAMQAAAO8AAADvQAA
+A6UAAAO+AAADvgAAAMUAAAO/AAADvwAAA6QAAAPAAAADxgAAAMYAAAPHAAADxwAAA6cAAAPIAAADyQAA
+AM0AAAPKAAADzgAAA6gAAAPRAAAD0gAAAM8AAAPWAAAD1gAAANEAAAQAAAAEAAAAA+QAAAQBAAAEAQAA
+A60AAAQCAAAEAgAAANIAAAQDAAAEAwAAA64AAAQEAAAEBAAAANMAAAQFAAAECAAAA68AAAQJAAAECwAA
+ANQAAAQMAAAEDAAAA7QAAAQNAAAEDQAAA+UAAAQOAAAEDgAAA7UAAAQPAAAEDwAAANcAAAQQAAAEEAAA
+A7YAAAQRAAAEEQAAANgAAAQSAAAEEwAAA7cAAAQUAAAEFAAAANkAAAQVAAAEFQAAA7kAAAQWAAAEGAAA
+ANoAAAQZAAAEGQAAA7oAAAQaAAAEGgAAA7MAAAQbAAAEGwAAAN0AAAQcAAAEIgAAA7sAAAQjAAAEJAAA
+AN4AAAQlAAAEJQAAA8IAAAQmAAAELwAAAOAAAAQwAAAEMAAAA8MAAAQxAAAENAAAAOoAAAQ1AAAENQAA
+A8QAAAQ2AAAEOAAAAO4AAAQ5AAAEOQAAA8UAAAQ6AAAEPQAAAPEAAAQ+AAAEPgAAA8YAAAQ/AAAEPwAA
+APUAAARAAAAEQQAAA8cAAARCAAAEQgAAAPYAAARDAAAEQwAAA8kAAAREAAAERAAAAPcAAARFAAAERQAA
+A8oAAARGAAAETwAAAPgAAARQAAAEUAAAA+YAAARRAAAEUQAAA8sAAARSAAAEUgAAAQIAAARTAAAEUwAA
+A8wAAARUAAAEVAAAAQMAAARVAAAEWAAAA80AAARZAAAEWwAAAQQAAARcAAAEXAAAA9EAAARdAAAEXQAA
+A+cAAAReAAAEXgAAA9IAAARfAAAEYQAAAQcAAARiAAAEYgAABIEAAARjAAAEbwAAAQoAAARwAAAEcQAA
+A+gAAARyAAAEdQAAARcAAAR2AAAEdwAAA+oAAAR4AAAEeAAAA+0AAAR5AAAEeQAAA+wAAAR6AAAEhgAA
+ARsAAASIAAAEiwAAASgAAASMAAAEjAAABIAAAASNAAAEkQAAASwAAASSAAAEkwAABIIAAASUAAAElwAA
+ATEAAASYAAAEmQAAA+4AAASaAAAEnQAAATUAAASeAAAEnwAABIQAAASgAAAEqQAAATkAAASqAAAEqwAA
+A/AAAASsAAAErQAABHcAAASuAAAErwAAA/IAAASwAAAEsQAABIYAAASyAAAEugAAAUMAAAS7AAAEuwAA
+BH8AAAS8AAAEvQAAAUwAAAS+AAAEvwAABH0AAATAAAAEwgAAA/QAAATDAAAEygAAAU4AAATLAAAEzAAA
+BHkAAATNAAAEzgAAAVYAAATPAAAE1wAAA/cAAATYAAAE2AAAAVgAAATZAAAE2QAABAEAAATaAAAE2gAA
+BAAAAATbAAAE3wAABAIAAATgAAAE4QAAAVkAAATiAAAE9QAABAcAAAT2AAAE9wAABHsAAAT4AAAE+QAA
+BBsAAAT6AAAE/QAAAVsAAAT+AAAE/wAABIgAAAUAAAAFAAAAAV8AAAUBAAAFAQAABB0AAAUCAAAFEAAA
+AWAAAAURAAAFEQAABIoAAAUSAAAFEwAAAW8AAB4AAAAeAQAAA+IAAB4+AAAePwAAA+AAAB6AAAAehQAA
+A9MAAB6gAAAe8QAABB4AAB7yAAAe8wAAA9kAAB70AAAe+QAABHAAAB9NAAAfTQAABMoAACAAAAAgCQAA
+AXIAACAKAAAgCwAAAX0AACAQAAAgEQAAAX8AACATAAAgFAAAAYEAACAVAAAgFQAABIwAACAXAAAgHgAA
+AYMAACAgAAAgIgAAAYsAACAlAAAgJwAAAY4AACAwAAAgMAAAAZEAACAyAAAgMwAAA9sAACA5AAAgOgAA
+AZIAACA8AAAgPAAAA90AACBEAAAgRAAAAZQAACB0AAAgdAAAAZUAACB/AAAgfwAAAZYAACCjAAAgowAA
+BIsAACCkAAAgpAAAAZcAACCmAAAgqgAAAZgAACCrAAAgqwAABHYAACCsAAAgrAAAAZ0AACCxAAAgsQAA
+AZ4AACC5AAAgugAAAZ8AACC8AAAgvQAAAaEAACEFAAAhBQAAAaMAACETAAAhEwAAAaQAACEWAAAhFgAA
+AaUAACEiAAAhIgAAAaYAACEmAAAhJgAAALoAACEuAAAhLgAAAacAACFbAAAhXgAAAagAACICAAAiAgAA
+AawAACIGAAAiBgAAALIAACIPAAAiDwAAAa0AACIRAAAiEgAAAa4AACIaAAAiGgAAAbAAACIeAAAiHgAA
+AbEAACIrAAAiKwAAAbIAACJIAAAiSAAAAbMAACJgAAAiYAAAAbQAACJkAAAiZQAAAbUAACXKAAAlygAA
+AbcAAO4BAADuAgAAAbgAAPbDAAD2wwAAAboAAPsBAAD7BAAAAbwAAP7/AAD+/wAAAcIAAP/8AAD//QAA
+AcMAALAALEuwCVBYsQEBjlm4Af+FsIQdsQkDX14tsAEsICBFaUSwAWAtsAIssAEqIS2wAywgRrADJUZS
+WCNZIIogiklkiiBGIGhhZLAEJUYgaGFkUlgjZYpZLyCwAFNYaSCwAFRYIbBAWRtpILAAVFghsEBlWVk6
+LbAELCBGsAQlRlJYI4pZIEYgamFksAQlRiBqYWRSWCOKWS/9LbAFLEsgsAMmUFhRWLCARBuwQERZGyEh
+IEWwwFBYsMBEGyFZWS2wBiwgIEVpRLABYCAgRX1pGESwAWAtsAcssAYqLbAILEsgsAMmU1iwQBuwAFmK
+iiCwAyZTWCMhsICKihuKI1kgsAMmU1gjIbDAioobiiNZILADJlNYIyG4AQCKihuKI1kgsAMmU1gjIbgB
+QIqKG4ojWSCwAyZTWLADJUW4AYBQWCMhuAGAIyEbsAMlRSMhIyFZGyFZRC2wCSxLU1hFRBshIVktsAos
+sChFLbALLLApRS2wDCyxJwGIIIpTWLlAAAQAY7gIAIhUWLkAKAPocFkbsCNTWLAgiLgQAFRYuQAoA+hw
+WVlZLbANLLBAiLggAFpYsSkARBu5ACkD6ERZLbAMK7AAKwCyARACKwGyEQECKwG3ETowJRsQAAgrALcB
+SDsuIRQACCu3AlhIOCgUAAgrtwNSQzQlFgAIK7cEXk08KxkACCu3BTYsIhkPAAgrtwZxXUYyGwAIK7cH
+kXdcOiMACCu3CH5nUDkaAAgrtwlURTYmFAAIK7cKdmBLNh0ACCu3C4NkTjojAAgrtwzZsopjPAAIK7cN
+FBAMCQYACCu3DjwyJxwRAAgrtw9ANCkdFAAIK7cQUEEuIRQACCsAshILByuwACBFfWkYRLI/GgFzsl8a
+AXOyfxoBc7IvGgF0sk8aAXSybxoBdLKPGgF0sq8aAXSy/xoBdLIfGgF1sj8aAXWyXxoBdbJ/GgF1sg8e
+AXOyfx4Bc7LvHgFzsh8eAXSyXx4BdLKPHgF0ss8eAXSy/x4BdLI/HgF1sm8eAXWyLyABc7JvIAFzAAAA
+ACoAnQCAAIoAeADUAGQATgBaAIcAYABWADQCPAC8ALIAjgDEAAAAFP5gABQCmwAgAyEACwQ6ABQEjQAQ
+BbAAFAYYABUBpgARBsAADgbZAAYAAAAAAAAADQCiAAMAAQQJAAAAXgAAAAMAAQQJAAEADABeAAMAAQQJ
+AAIADgBqAAMAAQQJAAMADABeAAMAAQQJAAQADABeAAMAAQQJAAUAJgB4AAMAAQQJAAYAHACeAAMAAQQJ
+AAcAQAC6AAMAAQQJAAkADAD6AAMAAQQJAAsAFAEGAAMAAQQJAAwAJgEaAAMAAQQJAA0AXAFAAAMAAQQJ
+AA4AVAGcAEMAbwBwAHkAcgBpAGcAaAB0ACAAMgAwADEAMQAgAEcAbwBvAGcAbABlACAASQBuAGMALgAg
+AEEAbABsACAAUgBpAGcAaAB0AHMAIABSAGUAcwBlAHIAdgBlAGQALgBSAG8AYgBvAHQAbwBSAGUAZwB1
+AGwAYQByAFYAZQByAHMAaQBvAG4AIAAyAC4AMQAzADcAOwAgADIAMAAxADcAUgBvAGIAbwB0AG8ALQBS
+AGUAZwB1AGwAYQByAFIAbwBiAG8AdABvACAAaQBzACAAYQAgAHQAcgBhAGQAZQBtAGEAcgBrACAAbwBm
+ACAARwBvAG8AZwBsAGUALgBHAG8AbwBnAGwAZQBHAG8AbwBnAGwAZQAuAGMAbwBtAEMAaAByAGkAcwB0
+AGkAYQBuACAAUgBvAGIAZQByAHQAcwBvAG4ATABpAGMAZQBuAHMAZQBkACAAdQBuAGQAZQByACAAdABo
+AGUAIABBAHAAYQBjAGgAZQAgAEwAaQBjAGUAbgBzAGUALAAgAFYAZQByAHMAaQBvAG4AIAAyAC4AMABo
+AHQAdABwADoALwAvAHcAdwB3AC4AYQBwAGEAYwBoAGUALgBvAHIAZwAvAGwAaQBjAGUAbgBzAGUAcwAv
+AEwASQBDAEUATgBTAEUALQAyAC4AMAAAAAMAAAAAAAD/agBkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAC
+AAgAAv//AA8AAQACAA4AAAAAAAACKAACAFkAJQA+AAEARQBeAAEAeQB5AAEAgQCBAAEAgwCDAAEAhgCG
+AAEAiQCJAAEAiwCWAAEAmACdAAEApACkAAEAqACtAAMAsQCxAAEAugC7AAEAvwC/AAEAwQDBAAEAwwDD
+AAEAxwDHAAEAywDLAAEAzQDOAAEA0ADRAAEA0wDTAAEA2gDeAAEA4QDhAAEA5QDlAAEA5wDpAAEA6wD7
+AAEA/QD9AAEA/wEBAAEBAwEDAAEBCAEJAAEBFgEaAAEBHAEcAAEBIAEiAAEBJAElAAMBKgErAAEBMwE0
+AAEBNgE2AAEBOwE8AAEBQQFEAAEBRwFIAAEBSwFNAAEBUQFRAAEBVAFYAAEBXQFeAAEBYgFiAAEBZAFk
+AAEBaAFoAAEBagFsAAEBbgFuAAEBcAFwAAEBugG6AAMBuwHBAAIB0gHmAAEB6gHqAAEB8wHzAAEB9QH1
+AAEB/AH+AAECAAIBAAECAwIDAAECBwIHAAECCQILAAECEQIRAAECFgIYAAECGgIaAAECKAIoAAECKwIr
+AAECLQItAAECMAIzAAECXwJjAAECegLiAAEC5QOLAAEDjQOkAAEDpgOyAAEDtAO9AAEDvwPaAAED3gPe
+AAED4APnAAED6QPrAAED7gPyAAED9AR8AAEEfwR/AAEEggSDAAEEhQSGAAEEiASLAAEElQTQAAEE0gTx
+AAEE8wT6AAEE/AT9AAEFBwUNAAEAAQACAAAADAAAACwAAQAOAKgAqACpAKkAqgCqAKsAqwCsAKwBJAEl
+ASYBJwABAAUAeQCkAK0ArQG6AAAAAQAAAAoAMgBMAARERkxUABpjeXJsABpncmVrABpsYXRuABoABAAA
+AAD//wACAAAAAQACY3BzcAAOa2VybgAUAAAAAQAAAAAAAQABAAIABgIQAAEAAAABAAgAAQAKAAUAJABI
+AAEA+gAIAAoAFAAVABYAFwAYABkAGgAbABwAHQAlACYAJwAoACkAKgArACwALQAuAC8AMAAxADIAMwA0
+ADUANgA3ADgAOQA6ADsAPAA9AD4AZQBnAIEAgwCEAIwAjwCRAJMAsQCyALMAtAC1ALYAtwC4ALkAugDS
+ANMA1ADVANYA1wDYANkA2gDbANwA3QDeAN8A4ADhAOIA4wDkAOUA5gDnAOgA6QEvATMBNQE3ATkBOwFB
+AUMBRQFJAUsBTAFYAVkBlwGdAaIBpQJ6AnsCfQJ/AoACgQKCAoMChAKFAoYChwKIAokCigKLAowCjQKO
+Ao8CkAKRApICkwKUApUClgKXApgCmQK2ArgCugK8Ar4CwALCAsQCxgLIAsoCzALOAtAC0gLUAtYC2ALa
+AtwC3gLgAuIC4wLlAucC6QLrAu0C7wLxAvMC9QL4AvoC/AL+AwADAgMEAwYDCAMKAwwDDgMQAxIDFAMW
+AxgDGgMcAx4DIAMiAyQDJQMnAykDKwMtA4YDhwOIA4kDigOLA4wDjgOPA5ADkQOSA5MDlAOVA5YDlwOY
+A5kDmgObA5wDnQOtA64DrwOwA7EDsgOzA7QDtQO2A7cDuAO5A7oDuwO8A70DvgO/A8ADwQPCA9MD1QPX
+A9kD7gPwA/IEBwQNBBMEfQSCBIYFBwUJAAIAAAACAAo6GAABA/IABAAAAfQHzjTGNMYH/AheNv43rjTM
+Ocw3eghkOBg4GDe4OAI4GDgYOcw4RAwCDNA4ijlYOZQ03jaEObINRjdcOGY1jA2MODoOwjg6ODo3iDhm
+OHwPxDl2ECY1PDl2EEA4ZjnMEIY1xjb+Ocw2/hEIEgYTCBPqFIw5dhSSFJw4OheGGXgaahtwG4YbjBuS
+Howekh7MHwIfjDWgNaAhvjgYImAjXjTeJcA4GDgYNUI4GDgYOBgmljWgOBg1oChAKQYpmCn6KuA1litu
+NTwzRiuYLXI4ZjEAMTozJDMkOGYycDL6MyQzJDMkNv43iDlYOXYzRjhmNcY1ljTeNTw3uDe4N7g4GDTe
+NTw4GDgYOcw1ljTeNTw0xjNwNMY0xjTGOgg0EjRgOgI0vDnqOfA6AjnwOeo56jnqOeo0rjnwNMw5zDnM
+Ocw5zDiKNv42/jb+Nv42/jb+Nv40zDd6N3o3ejd6OBg4GDgYOBg4GDnMOcw5zDnMOcw2hDdcN1w3XDdc
+N1w3XDdcNYw1jDWMNYw4OjeIN4g3iDeIN4g5djl2Nv43XDb+N1w2/jdcNMw0zDTMNMw5zDd6NYw3ejWM
+N3o1jDd6NYw3ejWMOBg4OjgYOBg4GDgYOBg3uDgCOAI4AjgCOBg4OjgYODo4GDg6ODo5zDeIOcw3iDnM
+N4g4fDh8OHw4ijiKOIo5lDaEOXY2hDmyObI5sjoCOgI6CDnwOfA58DnwOfA58DnwOgI6AjoCOgI6Ajnw
+OfA58DoCOeo0vDS8NLw0vDoCOgI6AjoINv43ejgYOBg5zDaENv43rjd6ObI4GDgYN7g4GDgYOcw4RDiK
+NoQ03jgYNoQ4OjeIOXY3iDd6NcY4GDgYN7g3uDVCNv43rjXGN3o4GDgYOcw4RDTMOIo03jdcNYw3iDhm
+OXY1PDWMNZY5djmUOZQ5lDaEOXY0xjTGNMY4GDg6Nv43XDd6NYw5WDl2NMw2hDl2OBg03jU8OBg2/jdc
+Nv43XDd6NYw1jDWMNN41PDnMN4g3iDhmNUI5djVCOXY1Qjl2Nv43XDb+N1w2/jdcNv43XDb+N1w2/jdc
+Nv43XDb+N1w2/jdcNv43XDb+N1w2/jdcN3o1jDd6NYw3ejWMN3o1jDd6NYw3ejWMN3o1jDd6NYw4GDgY
+Ocw3iDnMN4g5zDeIOcw3iDnMN4g5zDeIOcw3iDeINoQ5djaEOXY2hDl2OIo1xjWWODo1oDXGN7g2hDgY
+ODo2/jdcN3o4GDnMN4g4fDeuOGY5zDnMOBg4Oje4N7g4AjgYODo4GDg6Ocw4RDhmOHw4ijlYOXY5WDl2
+OZQ5sjnMOfA6AjnwOeo6CDnqOfA6AjoIAAIApAAEAAQAAAAGAAYAAQALAAwAAgATABMABAAlACoABQAs
+AC0ACwAvADYADQA4ADgAFQA6AD8AFgBFAEYAHABJAEoAHgBMAEwAIABPAE8AIQBRAFQAIgBWAFYAJgBY
+AFgAJwBaAF0AKABfAF8ALACKAIoALQCWAJYALgCdAJ0ALwCxALUAMAC3ALkANQC7ALsAOAC9AL4AOQDA
+AMEAOwDDAMUAPQDHAM4AQADSANIASADUAN4ASQDgAO8AVADxAPEAZAD2APgAZQD7APwAaAD+AQAAagED
+AQUAbQEKAQoAcAENAQ0AcQEYARoAcgEiASIAdQEuATAAdgEzATUAeQE3ATcAfAE5ATkAfQE7ATsAfgFD
+AUQAfwFUAVQAgQFWAVYAggFYAVgAgwFcAV4AhAGEAYUAhwGHAYkAiQHYAdgAjAHaAdsAjQHdAd0AjwHg
+AeEAkAHrAe0AkgH/Af8AlQIOAhAAlgIwAjAAmQIzAjMAmgJFAkUAmwJHAkgAnAJ6AnsAngJ9An0AoAJ/
+ApQAoQKZAqAAtwKiAqUAvwKqAq8AwwK0ArwAyQK+Ar4A0gLAAsAA0wLCAsIA1ALEAsQA1QLGAs8A1gLY
+AtoA4ALcAtwA4wLeAt4A5ALgAuAA5QLiAuIA5gLnAucA5wLpAukA6ALrAusA6QLtAu0A6gLvAu8A6wLx
+Av0A7AL/Av8A+QMBAwEA+gMDAwMA+wMOAw4A/AMQAxAA/QMSAxIA/gMgAyAA/wMiAyUBAAMnAycBBAMp
+AykBBQMvAzgBBgNDA0cBEANNA08BFQNUA1QBGANlA2kBGQNtA28BHgN4A3gBIQOGA4sBIgOOA50BKAOg
+A6ABOAOkA6QBOQOmA6YBOgOqA6oBOwOtA64BPAOwA7EBPgOzA7kBQAO7A70BRwO/A8QBSgPGA8cBUAPJ
+A8wBUgPSA9MBVgPVA9UBWAPXA9cBWQPZA9wBWgPfA+QBXgPmA+YBZAPqA+sBZQPwA/ABZwPyA/sBaAP+
+A/8BcgQBBAQBdAQLBAwBeAQQBBABegQSBBgBewQeBEYBggRIBEgBqwRKBFcBrARfBF8BugRwBHUBuwR3
+BHcBwQR7BHwBwgR/BH8BxASBBIIBxQSEBIQBxwSGBIYByASXBJsByQSdBJ0BzgSfBKABzwSiBKIB0QSm
+BKgB0gSqBKoB1QSsBK4B1gSwBLAB2QSyBLIB2gS0BLoB2wS8BLwB4gS/BL8B4wTCBMYB5ATIBMgB6QTK
+BMsB6gTPBM8B7ATSBNIB7QTYBNgB7gTdBN0B7wToBOgB8ATqBOoB8QTxBPEB8gT1BPUB8wALADj/2ADS
+/9gA1v/YATn/2AFF/9gDDv/YAxD/2AMS/9gDwf/YBHf/2AS//9gAGAA6ABQAOwASAD0AFgEZABQCmQAW
+AyAAEgMiABYDJAAWA4sAFgOaABYDnQAWA9MAEgPVABID1wASA9kAFgPqABQD8gAWBHAAFgRyABYEdAAW
+BIYAFgTCABQExAAUBMYAEgABABP/IADnABD/FgAS/xYAJf9WAC7++AA4ABQARf/eAEf/6wBI/+sASf/r
+AEv/6wBT/+sAVf/rAFb/5gBZ/+oAWv/oAF3/6ACU/+sAmf/rAJv/6gCy/1YAtP9WALv/6wC9/+gAyP/r
+AMn/6wDL/+oA0gAUANYAFAD3/+sBA//rAQ3/VgEY/+sBGv/oAR7/6wEi/+sBOQAUAUL/6wFFABQBYP/r
+AWH/6wFr/+sBhv8WAYr/FgGO/xYBj/8WAev/wAHt/8ACM//AAn//VgKA/1YCgf9WAoL/VgKD/1YChP9W
+AoX/VgKa/94Cm//eApz/3gKd/94Cnv/eAp//3gKg/94Cof/rAqL/6wKj/+sCpP/rAqX/6wKr/+sCrP/r
+Aq3/6wKu/+sCr//rArD/6gKx/+oCsv/qArP/6gK0/+gCtf/oArb/VgK3/94CuP9WArn/3gK6/1YCu//e
+Ar3/6wK//+sCwf/rAsP/6wLF/+sCx//rAsn/6wLL/+sCzf/rAs//6wLR/+sC0//rAtX/6wLX/+sC5f74
+Avn/6wL7/+sC/f/rAw4AFAMQABQDEgAUAxX/6gMX/+oDGf/qAxv/6gMd/+oDH//qAyP/6AMy/8ADM//A
+AzT/wAM1/8ADNv/AAzf/wAM4/8ADTf/AA07/wANP/8ADhv9WA47/VgOe/+sDov/qA6T/6wOm/+gDqf/q
+A6r/6wOr/+oDsv74A7b/VgPBABQDw//eA8T/6wPG/+sDyP/rA8n/6APL/+sD0v/oA9r/6APi/1YD4//e
+A+b/6wPr/+gD7P/rA/H/6wPz/+gD+P9WA/n/3gP6/1YD+//eA///6wQB/+sEAv/rBAz/6wQO/+sEEP/r
+BBT/6AQW/+gEGP/oBB3/6wQe/1YEH//eBCD/VgQh/94EIv9WBCP/3gQk/1YEJf/eBCb/VgQn/94EKP9W
+BCn/3gQq/1YEK//eBCz/VgQt/94ELv9WBC//3gQw/1YEMf/eBDL/VgQz/94ENP9WBDX/3gQ3/+sEOf/r
+BDv/6wQ9/+sEP//rBEH/6wRD/+sERf/rBEv/6wRN/+sET//rBFH/6wRT/+sEVf/rBFf/6wRZ/+sEW//r
+BF3/6wRf/+sEYf/rBGP/6gRl/+oEZ//qBGn/6gRr/+oEbf/qBG//6gRx/+gEc//oBHX/6AR3ABQEmf9W
+BJr/3gSc/+sEoP/rBKT/6gSp/+sEq//rBL8AFATD/+gExf/oBMv/wATS/8AE6v/AADMAOP/VADr/5AA7
+/+wAPf/dANL/1QDW/9UBGf/kATn/1QFF/9UB6wAOAe0ADgIzAA4Cmf/dAw7/1QMQ/9UDEv/VAyD/7AMi
+/90DJP/dAzIADgMzAA4DNAAOAzUADgM2AA4DNwAOAzgADgNNAA4DTgAOA08ADgOL/90Dmv/dA53/3QPB
+/9UD0//sA9X/7APX/+wD2f/dA+r/5APy/90EcP/dBHL/3QR0/90Ed//VBIb/3QS//9UEwv/kBMT/5ATG
+/+wEywAOBNIADgTqAA4AHQA4/7AAOv/tAD3/0ADS/7AA1v+wARn/7QE5/7ABRf+wApn/0AMO/7ADEP+w
+AxL/sAMi/9ADJP/QA4v/0AOa/9ADnf/QA8H/sAPZ/9AD6v/tA/L/0ARw/9AEcv/QBHT/0AR3/7AEhv/Q
+BL//sATC/+0ExP/tABEALv/uADn/7gKV/+4Clv/uApf/7gKY/+4C5f/uAxT/7gMW/+4DGP/uAxr/7gMc
+/+4DHv/uA7L/7gRi/+4EZP/uBMH/7gBNAAYAEAALABAADQAUAEEAEgBH/+gASP/oAEn/6ABL/+gAVf/o
+AGEAEwCU/+gAmf/oALv/6ADI/+gAyf/oAPf/6AED/+gBHv/oASL/6AFC/+gBYP/oAWH/6AFr/+gBhAAQ
+AYUAEAGHABABiAAQAYkAEAKh/+gCov/oAqP/6AKk/+gCpf/oAr3/6AK//+gCwf/oAsP/6ALF/+gCx//o
+Asn/6ALL/+gCzf/oAs//6ALR/+gC0//oAtX/6ALX/+gDnv/oA8T/6API/+gDy//oA9sAEAPcABAD3wAQ
+A+b/6APs/+gD8f/oA///6AQB/+gEAv/oBA7/6AQd/+gEN//oBDn/6AQ7/+gEPf/oBD//6ARB/+gEQ//o
+BEX/6ARZ/+gEW//oBF3/6ARh/+gEnP/oBKn/6ASr/+gAQABH/+wASP/sAEn/7ABL/+wAVf/sAJT/7ACZ
+/+wAu//sAMj/7ADJ/+wA9//sAQP/7AEe/+wBIv/sAUL/7AFg/+wBYf/sAWv/7AKh/+wCov/sAqP/7AKk
+/+wCpf/sAr3/7AK//+wCwf/sAsP/7ALF/+wCx//sAsn/7ALL/+wCzf/sAs//7ALR/+wC0//sAtX/7ALX
+/+wDnv/sA8T/7API/+wDy//sA+b/7APs/+wD8f/sA///7AQB/+wEAv/sBA7/7AQd/+wEN//sBDn/7AQ7
+/+wEPf/sBD//7ARB/+wEQ//sBEX/7ARZ/+wEW//sBF3/7ARh/+wEnP/sBKn/7ASr/+wAGABT/+wBGP/s
+Aqv/7AKs/+wCrf/sAq7/7AKv/+wC+f/sAvv/7AL9/+wDpP/sA6r/7APG/+wEDP/sBBD/7ARL/+wETf/s
+BE//7ARR/+wEU//sBFX/7ARX/+wEX//sBKD/7AAGABD/hAAS/4QBhv+EAYr/hAGO/4QBj/+EABEALv/s
+ADn/7AKV/+wClv/sApf/7AKY/+wC5f/sAxT/7AMW/+wDGP/sAxr/7AMc/+wDHv/sA7L/7ARi/+wEZP/s
+BMH/7AAgAAb/8gAL//IAWv/zAF3/8wC9//MA9v/1ARr/8wGE//IBhf/yAYf/8gGI//IBif/yArT/8wK1
+//MDI//zA6b/8wPJ//MD0v/zA9r/8wPb//ID3P/yA9//8gPr//MD8//zBBT/8wQW//MEGP/zBHH/8wRz
+//MEdf/zBMP/8wTF//MAPwAn//MAK//zADP/8wA1//MAg//zAJP/8wCY//MAs//zAMQADQDT//MBCP/z
+ARf/8wEb//MBHf/zAR//8wEh//MBQf/zAWr/8wJF//MCRv/zAkj/8wJJ//MChv/zApD/8wKR//MCkv/z
+ApP/8wKU//MCvP/zAr7/8wLA//MCwv/zAtD/8wLS//MC1P/zAtb/8wL4//MC+v/zAvz/8wMt//MDiv/z
+A5f/8wO9//MDwP/zA+3/8wPw//MEC//zBA3/8wQP//MESv/zBEz/8wRO//MEUP/zBFL/8wRU//MEVv/z
+BFj/8wRa//MEXP/zBF7/8wRg//MEn//zBLj/8wBAACf/5gAr/+YAM//mADX/5gCD/+YAk//mAJj/5gCz
+/+YAuP/CAMQAEADT/+YBCP/mARf/5gEb/+YBHf/mAR//5gEh/+YBQf/mAWr/5gJF/+YCRv/mAkj/5gJJ
+/+YChv/mApD/5gKR/+YCkv/mApP/5gKU/+YCvP/mAr7/5gLA/+YCwv/mAtD/5gLS/+YC1P/mAtb/5gL4
+/+YC+v/mAvz/5gMt/+YDiv/mA5f/5gO9/+YDwP/mA+3/5gPw/+YEC//mBA3/5gQP/+YESv/mBEz/5gRO
+/+YEUP/mBFL/5gRU/+YEVv/mBFj/5gRa/+YEXP/mBF7/5gRg/+YEn//mBLj/5gA4ACX/5AA8/9IAPf/T
+ALL/5AC0/+QAxP/iANr/0gEN/+QBM//SAUP/0gFd/9ICf//kAoD/5AKB/+QCgv/kAoP/5AKE/+QChf/k
+Apn/0wK2/+QCuP/kArr/5AMi/9MDJP/TA4b/5AOL/9MDjv/kA5r/0wOb/9IDnf/TA7b/5APC/9ID2f/T
+A+L/5APy/9MD9f/SA/j/5AP6/+QEA//SBB7/5AQg/+QEIv/kBCT/5AQm/+QEKP/kBCr/5AQs/+QELv/k
+BDD/5AQy/+QENP/kBHD/0wRy/9MEdP/TBIb/0wSZ/+QAKAAQ/x4AEv8eACX/zQCy/80AtP/NAMf/8gEN
+/80Bhv8eAYr/HgGO/x4Bj/8eAn//zQKA/80Cgf/NAoL/zQKD/80ChP/NAoX/zQK2/80CuP/NArr/zQOG
+/80Djv/NA7b/zQPi/80D+P/NA/r/zQQe/80EIP/NBCL/zQQk/80EJv/NBCj/zQQq/80ELP/NBC7/zQQw
+/80EMv/NBDT/zQSZ/80AAQDEAA4AAgDK/+0A9v/AALoAR//cAEj/3ABJ/9wAS//cAFH/8wBS//MAU//W
+AFT/8wBV/9wAWf/dAFr/4QBd/+EAlP/cAJn/3ACb/90Au//cAL3/4QC+/+4Av//mAMH/8wDC/+sAw//p
+AMX/8ADG/+cAyP/cAMn/3ADK/+MAy//dAMz/zgDN/9QAzv/bAOz/8wDw//MA8f/zAPP/8wD0//MA9f/z
+APf/3AD4//MA+v/zAPv/8wD+//MBAP/zAQP/3AEF//MBGP/WARr/4QEe/9wBIv/cASv/8wE2//MBPP/z
+AT7/8wFC/9wBU//zAVX/8wFX//MBXP/zAWD/3AFh/9wBa//cAqH/3AKi/9wCo//cAqT/3AKl/9wCqv/z
+Aqv/1gKs/9YCrf/WAq7/1gKv/9YCsP/dArH/3QKy/90Cs//dArT/4QK1/+ECvf/cAr//3ALB/9wCw//c
+AsX/3ALH/9wCyf/cAsv/3ALN/9wCz//cAtH/3ALT/9wC1f/cAtf/3ALy//MC9P/zAvb/8wL3//MC+f/W
+Avv/1gL9/9YDFf/dAxf/3QMZ/90DG//dAx3/3QMf/90DI//hA57/3AOg//MDov/dA6T/1gOm/+EDqf/d
+A6r/1gOr/90DxP/cA8X/8wPG/9YDx//zA8j/3APJ/+EDy//cA8z/8wPR//MD0v/hA9r/4QPh//MD5v/c
+A+f/8wPr/+ED7P/cA/H/3APz/+ED///cBAH/3AQC/9wECP/zBAr/8wQM/9YEDv/cBBD/1gQU/+EEFv/h
+BBj/4QQc//MEHf/cBDf/3AQ5/9wEO//cBD3/3AQ//9wEQf/cBEP/3ARF/9wES//WBE3/1gRP/9YEUf/W
+BFP/1gRV/9YEV//WBFn/3ARb/9wEXf/cBF//1gRh/9wEY//dBGX/3QRn/90Eaf/dBGv/3QRt/90Eb//d
+BHH/4QRz/+EEdf/hBHz/8wSY//MEnP/cBKD/1gSk/90Eqf/cBKv/3AS1//MEt//zBMP/4QTF/+EAfAAG
+/9oAC//aAEf/8ABI//AASf/wAEv/8ABV//AAWf/vAFr/3ABd/9wAlP/wAJn/8ACb/+8Au//wAL3/3ADC
+/+wAxAAPAMb/6gDI//AAyf/wAMr/xADL/+8AzP/nAPf/8AED//ABGv/cAR7/8AEi//ABQv/wAWD/8AFh
+//ABa//wAYT/2gGF/9oBh//aAYj/2gGJ/9oCof/wAqL/8AKj//ACpP/wAqX/8AKw/+8Csf/vArL/7wKz
+/+8CtP/cArX/3AK9//ACv//wAsH/8ALD//ACxf/wAsf/8ALJ//ACy//wAs3/8ALP//AC0f/wAtP/8ALV
+//AC1//wAxX/7wMX/+8DGf/vAxv/7wMd/+8DH//vAyP/3AOe//ADov/vA6b/3AOp/+8Dq//vA8T/8API
+//ADyf/cA8v/8APS/9wD2v/cA9v/2gPc/9oD3//aA+b/8APr/9wD7P/wA/H/8APz/9wD///wBAH/8AQC
+//AEDv/wBBT/3AQW/9wEGP/cBB3/8AQ3//AEOf/wBDv/8AQ9//AEP//wBEH/8ARD//AERf/wBFn/8ARb
+//AEXf/wBGH/8ARj/+8EZf/vBGf/7wRp/+8Ea//vBG3/7wRv/+8Ecf/cBHP/3AR1/9wEnP/wBKT/7wSp
+//AEq//wBMP/3ATF/9wAPAAG/6AAC/+gAEr/6QBZ//EAWv/FAF3/xQCb//EAvf/FAML/7gDEABAAxv/s
+AMr/IADL//EBGv/FAYT/oAGF/6ABh/+gAYj/oAGJ/6ACsP/xArH/8QKy//ECs//xArT/xQK1/8UDFf/x
+Axf/8QMZ//EDG//xAx3/8QMf//EDI//FA6L/8QOm/8UDqf/xA6v/8QPJ/8UD0v/FA9r/xQPb/6AD3P+g
+A9//oAPr/8UD8//FBBT/xQQW/8UEGP/FBGP/8QRl//EEZ//xBGn/8QRr//EEbf/xBG//8QRx/8UEc//F
+BHX/xQSk//EEw//FBMX/xQBBAEf/5wBI/+cASf/nAEv/5wBV/+cAlP/nAJn/5wC7/+cAxAAPAMj/5wDJ
+/+cA9//nAQP/5wEe/+cBIv/nAUL/5wFg/+cBYf/nAWv/5wKh/+cCov/nAqP/5wKk/+cCpf/nAr3/5wK/
+/+cCwf/nAsP/5wLF/+cCx//nAsn/5wLL/+cCzf/nAs//5wLR/+cC0//nAtX/5wLX/+cDnv/nA8T/5wPI
+/+cDy//nA+b/5wPs/+cD8f/nA///5wQB/+cEAv/nBA7/5wQd/+cEN//nBDn/5wQ7/+cEPf/nBD//5wRB
+/+cEQ//nBEX/5wRZ/+cEW//nBF3/5wRh/+cEnP/nBKn/5wSr/+cABQDK/+oA7f/uAPb/qwE6/+wBbf/s
+AAEA9v/VAAEAygALAL4ABgAMAAsADABH/+gASP/oAEn/6ABKAAwAS//oAFP/6gBV/+gAWgALAF0ACwCU
+/+gAmf/oALv/6AC9AAsAvv/tAMYACwDI/+gAyf/oAMoADAD3/+gBA//oARj/6gEaAAsBHv/oASL/6AFC
+/+gBYP/oAWH/6AFr/+gBhAAMAYUADAGHAAwBiAAMAYkADAHTAA0B1gANAdgADgHZ//UB2//sAd3/7QHl
+/+wB6/+/Aez/7QHt/78B9AAOAfX/7QH4AA4CEAAOAhH/7QISAA0CFAAOAhr/7QIx/+4CM/+/AqH/6AKi
+/+gCo//oAqT/6AKl/+gCq//qAqz/6gKt/+oCrv/qAq//6gK0AAsCtQALAr3/6AK//+gCwf/oAsP/6ALF
+/+gCx//oAsn/6ALL/+gCzf/oAs//6ALR/+gC0//oAtX/6ALX/+gC+f/qAvv/6gL9/+oDIwALAzL/vwMz
+/78DNP+/AzX/vwM2/78DN/+/Azj/vwM5/+0DQ//tA0T/7QNF/+0DRv/tA0f/7QNMAA0DTf+/A07/vwNP
+/78DUP/tA1H/7QNS/+0DU//tA1r/7QNb/+0DXP/tA13/7QNt/+0Dbv/tA2//7QNz//UDdP/1A3X/9QN2
+//UDeAAOA4EADQOCAA0Dnv/oA6T/6gOmAAsDqv/qA8T/6APG/+oDyP/oA8kACwPL/+gD0gALA9oACwPb
+AAwD3AAMA98ADAPm/+gD6wALA+z/6APx/+gD8wALA///6AQB/+gEAv/oBAz/6gQO/+gEEP/qBBQACwQW
+AAsEGAALBB3/6AQ3/+gEOf/oBDv/6AQ9/+gEP//oBEH/6ARD/+gERf/oBEv/6gRN/+oET//qBFH/6gRT
+/+oEVf/qBFf/6gRZ/+gEW//oBF3/6ARf/+oEYf/oBHEACwRzAAsEdQALBJz/6ASg/+oEqf/oBKv/6ATD
+AAsExQALBMv/vwTP/+0E0AANBNL/vwTeAA0E4QANBOr/vwTx/+0E9P/tBPUADgT5/+0E+gANAAEA9v/Y
+AA4AXP/tAF7/7QDu/+0A9v+qATT/7QFE/+0BXv/tAyb/7QMo/+0DKv/tA8r/7QP2/+0EBP/tBMn/7QAN
+AFz/8gBe//IA7v/yATT/8gFE//IBXv/yAyb/8gMo//IDKv/yA8r/8gP2//IEBP/yBMn/8gAiAFr/9ABc
+//IAXf/0AF7/8wC9//QA7v/yARr/9AE0//IBRP/yAV7/8gK0//QCtf/0AyP/9AMm//MDKP/zAyr/8wOm
+//QDyf/0A8r/8gPS//QD2v/0A+v/9APz//QD9v/yBAT/8gQU//QEFv/0BBj/9ARx//QEc//0BHX/9ATD
+//QExf/0BMn/8wCMAAb/ygAL/8oAOP/SADr/1AA8//QAPf/TAFH/0QBS/9EAVP/RAFr/5gBc/+8AXf/m
+AL3/5gDB/9EA0v/SANb/0gDa//QA3v/tAOH/4QDm/9QA7P/RAO7/7wDw/9EA8f/RAPP/0QD0/9EA9f/R
+APb/yQD4/9EA+v/RAPv/0QD+/9EBAP/RAQX/0QEJ/+UBGf/UARr/5gEg/+MBK//RATP/9AE0/+8BNv/R
+ATn/0gE6/8QBPP/RAT7/0QFD//QBRP/vAUX/0gFH/+EBSf/hAVP/0QFV/9EBV//RAVz/0QFd//QBXv/v
+AWL/1AFj//UBZP/nAWz/0gFt/8kBhP/KAYX/ygGH/8oBiP/KAYn/ygKZ/9MCqv/RArT/5gK1/+YC8v/R
+AvT/0QL2/9EC9//RAw7/0gMQ/9IDEv/SAyL/0wMj/+YDJP/TA4v/0wOa/9MDm//0A53/0wOg/9EDpv/m
+A7X/7QPB/9IDwv/0A8X/0QPH/9EDyf/mA8r/7wPM/9ED0f/RA9L/5gPZ/9MD2v/mA9v/ygPc/8oD3//K
+A+H/0QPn/9ED6v/UA+v/5gPy/9MD8//mA/X/9AP2/+8EA//0BAT/7wQI/9EECv/RBBP/7QQU/+YEFf/t
+BBb/5gQX/+0EGP/mBBn/4QQc/9EEcP/TBHH/5gRy/9MEc//mBHT/0wR1/+YEd//SBHn/4QR8/9EEhv/T
+BJj/0QS1/9EEt//RBL//0gTC/9QEw//mBMT/1ATF/+YAKAA4/74AWv/vAF3/7wC9/+8A0v++ANb/vgDm
+/8kA9v/fAQn/7QEa/+8BIP/rATn/vgE6/98BRf++AUz/6QFj//UBbf/gArT/7wK1/+8DDv++AxD/vgMS
+/74DI//vA6b/7wPB/74Dyf/vA9L/7wPa/+8D6//vA/P/7wQU/+8EFv/vBBj/7wRx/+8Ec//vBHX/7wR3
+/74Ev/++BMP/7wTF/+8APwA4/+YAOv/nADz/8gA9/+cAXP/xANL/5gDW/+YA2v/yAN7/7gDh/+gA5v/m
+AO7/8QD2/9ABGf/nATP/8gE0//EBOf/mATr/zgFD//IBRP/xAUX/5gFH/+gBSf/oAV3/8gFe//EBYv/n
+AWT/7QFs/+YBbf/QApn/5wMO/+YDEP/mAxL/5gMi/+cDJP/nA4v/5wOa/+cDm//yA53/5wO1/+4Dwf/m
+A8L/8gPK//ED2f/nA+r/5wPy/+cD9f/yA/b/8QQD//IEBP/xBBP/7gQV/+4EF//uBBn/6ARw/+cEcv/n
+BHT/5wR3/+YEef/oBIb/5wS//+YEwv/nBMT/5wCYACUAEAAn/+gAK//oADP/6AA1/+gAOP/gADr/4AA9
+/98Ag//oAJP/6ACY/+gAsgAQALP/6AC0ABAA0v/gANP/6ADUABAA1v/gANkAFADdABAA4f/hAOb/4ADt
+ABMA8gAQAPn/4AEEABABCP/oAQ0AEAEX/+gBGf/gARv/6AEd/+gBH//oASH/6AE5/+ABQf/oAUX/4AFH
+/+EBSP/gAUn/4QFK/+ABTf/hAVAAEAFRABABWP/pAWL/3wFk/94BZgAQAWr/6AFs/98Bbv/yAW8AEAFw
+ABACRf/oAkb/6AJI/+gCSf/oAn8AEAKAABACgQAQAoIAEAKDABAChAAQAoUAEAKG/+gCkP/oApH/6AKS
+/+gCk//oApT/6AKZ/98CtgAQArgAEAK6ABACvP/oAr7/6ALA/+gCwv/oAtD/6ALS/+gC1P/oAtb/6AL4
+/+gC+v/oAvz/6AMO/+ADEP/gAxL/4AMi/98DJP/fAy3/6AOGABADiv/oA4v/3wOOABADl//oA5r/3wOd
+/98DtgAQA73/6APA/+gDwf/gA9n/3wPiABAD6v/gA+3/6APw/+gD8v/fA/gAEAP6ABAEC//oBA3/6AQP
+/+gEGf/hBBr/4AQeABAEIAAQBCIAEAQkABAEJgAQBCgAEAQqABAELAAQBC4AEAQwABAEMgAQBDQAEARK
+/+gETP/oBE7/6ARQ/+gEUv/oBFT/6ARW/+gEWP/oBFr/6ARc/+gEXv/oBGD/6ARw/98Ecv/fBHT/3wR3
+/+AEef/hBHr/4ASG/98EmQAQBJ//6AS4/+gEv//gBML/4ATE/+AANQAb//IAOP/xADr/9AA8//QAPf/w
+ANL/8QDU//UA1v/xANr/9ADd//UA3v/zAOb/8QEZ//QBM//0ATn/8QFD//QBRf/xAVD/9QFd//QBYv/y
+AWT/8gFm//UBbP/yAW//9QKZ//ADDv/xAxD/8QMS//EDIv/wAyT/8AOL//ADmv/wA5v/9AOd//ADtf/z
+A8H/8QPC//QD2f/wA+r/9APy//AD9f/0BAP/9AQT//MEFf/zBBf/8wRw//AEcv/wBHT/8AR3//EEhv/w
+BL//8QTC//QExP/0AGoAJQAPADj/5gA6/+YAPAAOAD3/5gCyAA8AtAAPANL/5gDUAA4A1v/mANkAEwDa
+AA4A3QAOAN4ACwDh/+UA5v/mAOf/9ADtABIA8gAPAPb/5wD5/+gBBAAPAQ0ADwEZ/+YBMwAOATn/5gE6
+/+cBQwAOAUX/5gFH/+UBSP/oAUn/5QFK/+gBTP/kAVAADgFRAA8BXQAOAWL/5gFk/+YBZgAOAWz/5gFt
+/+cBbwAOAXAADwJ/AA8CgAAPAoEADwKCAA8CgwAPAoQADwKFAA8Cmf/mArYADwK4AA8CugAPAw7/5gMQ
+/+YDEv/mAyL/5gMk/+YDhgAPA4v/5gOOAA8Dmv/mA5sADgOd/+YDtQALA7YADwPB/+YDwgAOA9n/5gPi
+AA8D6v/mA/L/5gP1AA4D+AAPA/oADwQDAA4EEwALBBUACwQXAAsEGf/lBBr/6AQeAA8EIAAPBCIADwQk
+AA8EJgAPBCgADwQqAA8ELAAPBC4ADwQwAA8EMgAPBDQADwRw/+YEcv/mBHT/5gR3/+YEef/lBHr/6ASG
+/+YEmQAPBL//5gTC/+YExP/mADEAOP/jADz/5QA9/+QA0v/jANT/5QDW/+MA2f/iANr/5QDd/+UA3v/p
+APL/6gEE/+oBM//lATn/4wFD/+UBRf/jAVD/5QFR/+oBXf/lAWb/5QFs/+QBb//lAXD/6gKZ/+QDDv/j
+AxD/4wMS/+MDIv/kAyT/5AOL/+QDmv/kA5v/5QOd/+QDtf/pA8H/4wPC/+UD2f/kA/L/5AP1/+UEA//l
+BBP/6QQV/+kEF//pBHD/5ARy/+QEdP/kBHf/4wSG/+QEv//jACQAOP/iADz/5ADS/+IA1P/kANb/4gDZ
+/+EA2v/kAN3/5ADe/+kA7f/kAPL/6wEE/+sBM//kATn/4gFD/+QBRf/iAVD/5AFR/+sBXf/kAWb/5AFv
+/+QBcP/rAw7/4gMQ/+IDEv/iA5v/5AO1/+kDwf/iA8L/5AP1/+QEA//kBBP/6QQV/+kEF//pBHf/4gS/
+/+IAGAA4/+sAPf/zANL/6wDW/+sBOf/rAUX/6wKZ//MDDv/rAxD/6wMS/+sDIv/zAyT/8wOL//MDmv/z
+A53/8wPB/+sD2f/zA/L/8wRw//MEcv/zBHT/8wR3/+sEhv/zBL//6wA5AFH/7wBS/+8AVP/vAFz/8ADB
+/+8A7P/vAO3/7gDu//AA8P/vAPH/7wDz/+8A9P/vAPX/7wD2/+4A+P/vAPr/7wD7/+8A/v/vAQD/7wEF
+/+8BCf/0ASD/8QEr/+8BNP/wATb/7wE6/+8BPP/vAT7/7wFE//ABU//vAVX/7wFX/+8BXP/vAV7/8AFt
+/+8Cqv/vAvL/7wL0/+8C9v/vAvf/7wOg/+8Dxf/vA8f/7wPK//ADzP/vA9H/7wPh/+8D5//vA/b/8AQE
+//AECP/vBAr/7wQc/+8EfP/vBJj/7wS1/+8Et//vACMABv/yAAv/8gBa//UAXf/1AL3/9QD2//QBCf/1
+ARr/9QE6//UBbf/1AYT/8gGF//IBh//yAYj/8gGJ//ICtP/1ArX/9QMj//UDpv/1A8n/9QPS//UD2v/1
+A9v/8gPc//ID3//yA+v/9QPz//UEFP/1BBb/9QQY//UEcf/1BHP/9QR1//UEw//1BMX/9QAKAO0AFAD2
+/+0A+f/tAPz/4gE6/+0BSP/tAUr/7QFt/+0EGv/tBHr/7QB2AEf/8ABI//AASf/wAEv/8ABT/+sAVf/w
+AJT/8ACZ//AAu//wAMj/8ADJ//AA9//wAQP/8AEY/+sBHP/rAR7/8AEi//ABQv/wAWD/8AFh//ABa//w
+Adv/6wHd/+sB5f/pAez/6wH1/+sCEf/rAhr/6wIx/+sCof/wAqL/8AKj//ACpP/wAqX/8AKr/+sCrP/r
+Aq3/6wKu/+sCr//rAr3/8AK///ACwf/wAsP/8ALF//ACx//wAsn/8ALL//ACzf/wAs//8ALR//AC0//w
+AtX/8ALX//AC+f/rAvv/6wL9/+sDOf/rA0P/6wNE/+sDRf/rA0b/6wNH/+sDUP/rA1H/6wNS/+sDU//r
+A1r/6wNb/+sDXP/rA13/6wNt/+sDbv/rA2//6wOe//ADpP/rA6r/6wPE//ADxv/rA8j/8APL//AD5v/w
+A+z/8APx//AD///wBAH/8AQC//AEDP/rBA7/8AQQ/+sEHf/wBDf/8AQ5//AEO//wBD3/8AQ///AEQf/w
+BEP/8ARF//AES//rBE3/6wRP/+sEUf/rBFP/6wRV/+sEV//rBFn/8ARb//AEXf/wBF//6wRh//AEnP/w
+BKD/6wSp//AEq//wBM//6wTx/+sE9P/rBPn/6wDjAAYADQALAA0ARf/wAEf/sABI/7AASf+wAEoADQBL
+/7AAU//WAFX/sABaAAsAXQALAJT/sACZ/7AAu/+wAL0ACwC+/7AAx/+rAMj/wADJ/7AAzP/VAO3/qgDy
+/68A9/+wAQP/sAEE/68BGP/WARoACwEc/+IBHv+wASAADAEi/7ABQv+wAVH/rwFg/7ABYf+wAWMACwFl
+AAsBa/+wAXD/rwGEAA0BhQANAYcADQGIAA0BiQANAdMADQHWAA0B2AAOAdn/9QHb/+wB3f/tAeX/7AHr
+/78B7P/tAe3/vwH0AA4B9f/tAfgADgIQAA4CEf/tAhIADQIUAA4CGv/tAjH/7gIz/78Cmv/wApv/8AKc
+//ACnf/wAp7/8AKf//ACoP/wAqH/sAKi/7ACo/+wAqT/sAKl/7ACq//WAqz/1gKt/9YCrv/WAq//1gK0
+AAsCtQALArf/8AK5//ACu//wAr3/sAK//7ACwf+wAsP/sALF/7ACx/+wAsn/sALL/7ACzf+wAs//sALR
+/7AC0/+wAtX/sALX/7AC+f/WAvv/1gL9/9YDIwALAzL/vwMz/78DNP+/AzX/vwM2/78DN/+/Azj/vwM5
+/+0DQ//tA0T/7QNF/+0DRv/tA0f/7QNMAA0DTf+/A07/vwNP/78DUP/tA1H/7QNS/+0DU//tA1r/7QNb
+/+0DXP/tA13/7QNt/+0Dbv/tA2//7QNz//UDdP/1A3X/9QN2//UDeAAOA4EADQOCAA0Dnv+wA6T/1gOm
+AAsDqv/WA8P/8APE/7ADxv/WA8j/sAPJAAsDy/+wA9IACwPaAAsD2wANA9wADQPfAA0D4//wA+b/sAPr
+AAsD7P+wA/H/sAPzAAsD+f/wA/v/8AP//7AEAf+wBAL/sAQM/9YEDv+wBBD/1gQUAAsEFgALBBgACwQd
+/7AEH//wBCH/8AQj//AEJf/wBCf/8AQp//AEK//wBC3/8AQv//AEMf/wBDP/8AQ1//AEN/+wBDn/sAQ7
+/7AEPf+wBD//sARB/7AEQ/+wBEX/sARL/9YETf/WBE//1gRR/9YEU//WBFX/1gRX/9YEWf+wBFv/sARd
+/7AEX//WBGH/sARxAAsEcwALBHUACwSa//AEnP+wBKD/1gSp/7AEq/+wBMMACwTFAAsEy/+/BM//7QTQ
+AA0E0v+/BN4ADQThAA0E6v+/BPH/7QT0/+0E9QAOBPn/7QT6AA0ADgDtABQA8gAQAPb/8AD5//ABAQAM
+AQQAEAE6//ABSP/wAUr/5gFRABABbf/wAXAAEAQa//AEev/wAE0ARwAMAEgADABJAAwASwAMAFUADACU
+AAwAmQAMALsADADIAAwAyQAMAO0AOgDyABgA9v/jAPcADAD5//cBAwAMAQQAGAEeAAwBIgAMATr/4gFC
+AAwBSP/3AUr/4wFRABgBYAAMAWEADAFrAAwBbf/jAXAAGAKhAAwCogAMAqMADAKkAAwCpQAMAr0ADAK/
+AAwCwQAMAsMADALFAAwCxwAMAskADALLAAwCzQAMAs8ADALRAAwC0wAMAtUADALXAAwDngAMA8QADAPI
+AAwDywAMA+YADAPsAAwD8QAMA/8ADAQBAAwEAgAMBA4ADAQa//cEHQAMBDcADAQ5AAwEOwAMBD0ADAQ/
+AAwEQQAMBEMADARFAAwEWQAMBFsADARdAAwEYQAMBHr/9wScAAwEqQAMBKsADAAiAFr/9ABc//AAXf/0
+AL3/9ADt/+8A7v/wAPL/8wEE//MBGv/0ATT/8AFE//ABUf/zAV7/8AFw//MCtP/0ArX/9AMj//QDpv/0
+A8n/9APK//AD0v/0A9r/9APr//QD8//0A/b/8AQE//AEFP/0BBb/9AQY//QEcf/0BHP/9AR1//QEw//0
+BMX/9AAKAAb/1gAL/9YBhP/WAYX/1gGH/9YBiP/WAYn/1gPb/9YD3P/WA9//1gAIAPb/ugEJ/88BIP/b
+ATr/UAFK/50BY//wAWX/8gFt/0wACgAG//UAC//1AYT/9QGF//UBh//1AYj/9QGJ//UD2//1A9z/9QPf
+//UAKABMACAATwAgAFAAIABT/4AAV/+QAFsACwEY/4ABwf+QAqv/gAKs/4ACrf+AAq7/gAKv/4AC+f+A
+Avv/gAL9/4ADBf+QAwf/kAMJ/5ADC/+QAw3/kAOk/4ADqv+AA8b/gAPN/5AEDP+ABBD/gARL/4AETf+A
+BE//gARR/4AEU/+ABFX/gARX/4AEX/+ABKD/gAStACAErwAgBLEAIAS+/5AAEwHT/+4B1f/1Adb/8QHY
+//IB9P/yAfj/8gIQ//ICEv/uAhT/8gNM/+4DeP/yA4D/9QOB/+4Dgv/uBND/7gTe/+4E4f/uBPX/8gT6
+/+4AEwHT/+UB1f/xAdb/6wHY/+kB9P/pAfj/6QIQ/+kCEv/lAhT/6QNM/+UDeP/pA4D/8QOB/+UDgv/l
+BND/5QTe/+UE4f/lBPX/6QT6/+UAAwHV//UB1v/uA4D/9QACAdb/twHb//AAAQBbAAsABAAN/+YAQf/0
+AGH/7wFN/+0AFwC4/9QAvv/wAML/7QDEABEAyv/gAMz/5wDN/+UAzv/uANkAEgDq/+kA9v/XATr/1wFK
+/9MBTP/WAU3/xQFY/+cBYgANAWQADAFt/9YBbv/yAdv/6QHl/+cCMf/pAAEBHP/xABIA2f+uAOYAEgDr
+/+AA7f+tAO//1gD9/98BAf/SAQf/4AEc/84BLv/dATD/4gE4/+ABQP/gAUr/6QFN/9oBX/+9AWn/3wFs
+ABEAAgD2//UBhf+wAAIA7f/JARz/7gAJAOb/wwD2/88BOv/OAUn/5wFM/98BYv/RAWT/7AFs/6ABbf/R
+AC8AVv9tAFv/jABt/b8AfP59AIH+vACG/ysAif9LALj/YQC+/48Av/8PAMP+6ADG/x8Ax/7lAMr/RgDM
+/u0Azf79AM7+2QDZ/1IA5gAFAOr/vQDr/0kA7f7+AO//EwD2/2gA/f8OAP//EwEB/wcBB/8OAQn/EQEc
+/zwBIP+sAS7/FQEw/zwBOP8OATr/agFA/0kBSv8MAUz/PwFN/vEBWP/AAV/+7wFj/zEBZf9fAWn/CgFs
+AAUBbf8wAW7/1QAeAAr/4gANABQADv/PAEEAEgBK/+oAVv/YAFj/6gBhABMAbf+uAHz/zQCB/6AAhv/B
+AIn/wAC4/9AAvP/qAL7/7gC//8YAwAANAML/6QDD/9YAxv/oAMf/ugDK/+kAzP/LAM3/2gDO/8cBjf/T
+Adv/ywHl/8sCMf/NABcAI//DAFj/7wBb/98Amv/uALj/5QC5/9EAxAARAMr/yADZABMA5v/FAPb/ygE6
+/58BSf9RAUr/ewFM/8oBTf/dAVj/8gFi/3UBZP/KAWz/TwFt/4wB1v/NAeX/9QAHAPb/8AEJ//EBIP/z
+ATr/8QFj//MBZf/pAW3/0wADAEr/7gBb/+oB1v/wAAkAyv/qAO3/uAD2/+oBCf/wASD/8QE6/+sBY//1
+AW3/7AGF/7AAAgERAAsBbP/mABIAW//BALj/xQDK/7QA6v/XAPb/uQEJ/7IBHP/SASD/yAE6/6ABSv/F
+AVj/5AFj/8wBZf/MAW3/ywFu/+8B2//nAeX/5gIx/+gABQBb/6QB1v9UAdv/8QHl//ECMf/zAAgA2QAV
+AO0AFQFJ/+QBSv/lAUz/5AFi/+MBZP/iAWz/5AACAPb/wAGF/7AACABYAA4Agf+fAL7/9QDE/94Ax//l
+ANn/qADt/8oBX//jAAUAyv/qAO3/7gD2/7ABOv/sAW3/7AADAEoADwBYADIAWwARADMABP/YAFb/tQBb
+/8cAbf64AHz/KACB/00Ahv+OAIn/oQC4/64Avv/JAL//fgDD/2cAxv+HAMf/ZQDK/54AzP9qAM3/cwDO
+/14A2f+lAOYADwDq/+QA6/+gAO3/dADv/4AA9v+yAP3/fQD//4ABAf95AQf/fQEJ/38BHP+YASD/2gEu
+/4EBMP+YATj/fQE6/7MBQP+gAUr/fAFM/5oBTf9sAVj/5gFf/2sBY/+SAWX/rQFp/3sBbAAPAW3/kQFu
+//IB2/+5AeX/uQIx/7kABwANABQAQQARAFb/4gBhABMB2//ZAeX/2QIx/9kABwBKAA0Avv/1AMYACwDH
+/+oAygAMAO3/yAEc//EABwANAA8AQQAMAFb/6wBhAA4B2//nAeX/5wIx/+kABgBb/+UAuP/LAM3/5AHb
+/+wB5f/rAjH/7QAHAIH/3wC1//MAt//wAMT/6gDZ/98A5v/gAWz/4AABAdv/6wAEAdb/xwHb//IB5f/y
+AjH/8gABAdb/8QABAdYADQACCwwABAAADqwXaAAmACUAAAAAAAAAAAAAAAAAEgAAAAAAAAAA/+P/5AAA
+AAAAAAAAABEAAAAAAAAAAAAAAAAAAAARAAAAEQAAAAAAAAAA/+T/5QAAAAAAAAAAAAAAAAAAAAAAAP/r
+AAAAAAAAAAD/5f/V/+0AAAAAAAD/6gAA/+kAAAAAAAAAAAAA/+H/mgAA//X/6gAAAAAAAAAAAAAAAAAA
+AAAAAP/1AAD/9P/1AAAAAP/1/87/7/9//6IAAAAAAAwAAAAA//EAAP+IAAD/u//E/8cAEQAAABIAAP+p
+AAAAAP/J/48AAAAA/90AAAAAAAAAAAAAAAAAAAAAAAD/8QAAAAAAAAAAAAD/8AAAAAAAAAAA/3j/6wAA
+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
+AOwAPgDuAO4APwD3APcAQAD8APwAQQD+AP8AQgEEAQUARAEKAQoARgENAQ0ARwEYARoASAEuATAASwEz
+ATUATgE3ATcAUQE5ATkAUgE7ATsAUwFDAUQAVAFUAVQAVgFWAVYAVwFYAVgAWAFcAV4AWQGEAYoAXAGO
+AY8AYwHYAdgAZQHdAd0AZgHgAeEAZwHrAe0AaQH/Af8AbAIOAhAAbQIwAjAAcAIzAjMAcQJFAkUAcgJH
+AkgAcwJ6AnsAdQJ9An0AdwJ/AqUAeAKqAq8AnwK0AsQApQLGAs8AtgLYAtoAwALcAtwAwwLeAt4AxALg
+AuAAxQLiAuIAxgLlAuUAxwLnAucAyALpAukAyQLrAusAygLtAu0AywLvAu8AzALxAv0AzQL/Av8A2gMB
+AwEA2wMDAwMA3AMOAw4A3QMQAxAA3gMSAxIA3wMUAxQA4AMWAxYA4QMYAxgA4gMaAxoA4wMcAxwA5AMe
+Ax4A5QMgAyAA5gMiAyoA5wMvAzgA8ANDA0cA+gNNA08A/wNUA1QBAgNlA2kBAwNtA28BCAN4A3gBCwOG
+A4sBDAOOA50BEgOgA6ABIgOkA6QBIwOmA6YBJAOqA6oBJQOtA64BJgOwA7kBKAO7A70BMgO/A8QBNQPG
+A8wBOwPSA9MBQgPVA9UBRAPXA9cBRQPZA9wBRgPfA+QBSgPmA+YBUAPqA+sBUQPwA/sBUwP+A/8BXwQB
+BAQBYQQLBAwBZQQQBBABZwQSBBgBaAQeBEYBbwRIBEgBmARKBFcBmQRfBF8BpwRiBGIBqARkBGQBqQRw
+BHUBqgR3BHcBsAR7BHwBsQR/BH8BswSBBIIBtASEBIQBtgSGBIYBtwSXBJsBuASdBJ0BvQSfBKABvgSi
+BKIBwASmBKgBwQSqBKoBxASsBK4BxQSwBLAByASyBLIByQS0BLoBygS8BLwB0QS/BL8B0gTBBMYB0wTI
+BMsB2QTPBM8B3QTSBNIB3gTYBNgB3wTdBN0B4AToBOgB4QTqBOoB4gTxBPEB4wT1BPUB5AACAXQABgAG
+ABkACwALABkAEAAQACEAEgASACEAJQAlAAIAJgAmABwAJwAnABMAKAAoAAEAKQApAAUALgAuAAoALwAv
+AAsAMAAwABgAMwAzAAEANAA0ABYAOAA4AA4AOQA5AAoAOgA6AB0AOwA7ABsAPAA8ABIAPQA9AAwAPgA+
+ABEARQBFAAYARgBGAAcARwBHABcASQBJAAgATABMAAQAUQBSAAQAUwBTAAMAVABUAAcAVgBWABUAWgBa
+AAkAXABcABQAXQBdAAkAXgBeABAAigCKAAcAlgCWAAEAsQCxACIAsgCyAAIAswCzAAEAtAC0AAIAvQC9
+AAkAwQDBAAQAxwDHAAcA1ADVACAA2gDaABIA3gDeACUA5ADkACAA5gDmACAA7ADsABoA7gDuABQA9wD3
+AAcA/AD8AB8A/gD+AB8A/wD/AAcBBAEFAB8BCgEKAB8BDQENAAIBGAEYAAMBGQEZAB0BGgEaAAkBLgEu
+AAcBLwEvACIBMAEwABoBMwEzABIBNAE0ABQBNQE1AAsBNwE3AAsBOQE5AAsBQwFDABIBRAFEABQBWAFY
+AAEBXAFcABoBXQFdABIBXgFeABQBhAGFABkBhgGGACEBhwGJABkBigGKACEBjgGPACEB2AHYACMB3QHd
+AA0B4AHgACQB4QHhAB4B6wHrAA8B7AHsAA0B7QHtAA8B/wH/AB4CDgIQAB4CMAIwAA0CMwIzAA8CRQJF
+ABMCRwJIAAECegJ7AAECfQJ9AA4CfwKFAAIChgKGABMChwKKAAUCkAKUAAEClQKYAAoCmQKZAAwCmgKg
+AAYCoQKhABcCogKlAAgCqgKqAAQCqwKvAAMCtAK1AAkCtgK2AAICtwK3AAYCuAK4AAICuQK5AAYCugK6
+AAICuwK7AAYCvAK8ABMCvQK9ABcCvgK+ABMCvwK/ABcCwALAABMCwQLBABcCwgLCABMCwwLDABcCxALE
+AAECxgLGAAUCxwLHAAgCyALIAAUCyQLJAAgCygLKAAUCywLLAAgCzALMAAUCzQLNAAgCzgLOAAUCzwLP
+AAgC2QLZAAQC5QLlAAoC5wLnAAsC6QLpABgC6wLrABgC7QLtABgC7wLvABgC8gLyAAQC9AL0AAQC9gL3
+AAQC+AL4AAEC+QL5AAMC+gL6AAEC+wL7AAMC/AL8AAEC/QL9AAMC/wL/ABUDAQMBABUDAwMDABUDDgMO
+AA4DEAMQAA4DEgMSAA4DFAMUAAoDFgMWAAoDGAMYAAoDGgMaAAoDHAMcAAoDHgMeAAoDIAMgABsDIgMi
+AAwDIwMjAAkDJAMkAAwDJQMlABEDJgMmABADJwMnABEDKAMoABADKQMpABEDKgMqABADLwMwAA0DMQMx
+ACMDMgM4AA8DQwNHAA0DTQNPAA8DVANUAA0DZQNlAB4DZgNpACQDbQNvAA0DeAN4ACMDhgOGAAIDhwOH
+AAUDigOKAAEDiwOLAAwDjgOOAAIDjwOPABwDkAOQAAUDkQORABEDlAOUAAsDlwOXAAEDmAOYABYDmQOZ
+AA4DmgOaAAwDmwObABIDnQOdAAwDoAOgAAQDpAOkAAMDpgOmAAkDqgOqAAMDrQOtAAUDrgOuACIDsgOy
+AAoDswO0AAsDtQO1ACUDtgO2AAIDtwO3ABwDuAO4ACIDuQO5AAUDvQO9AAEDvwO/ABYDwAPAABMDwQPB
+AA4DwgPCABIDwwPDAAYDxAPEAAgDxgPGAAMDxwPHAAcDyAPIABcDyQPJAAkDygPKABQDywPLAAgDzAPM
+ABoD0gPSAAkD0wPTABsD1QPVABsD1wPXABsD2QPZAAwD2gPaAAkD2wPcABkD3wPfABkD4QPhAAQD4gPi
+AAID4wPjAAYD5APkAAUD5gPmAAgD6gPqAB0D6wPrAAkD8APwABMD8QPxABcD8gPyAAwD8wPzAAkD9QP1
+ABID9gP2ABQD+AP4AAID+QP5AAYD+gP6AAID+wP7AAYD/gP+AAUD/wP/AAgEAQQCAAgEAwQDABIEBAQE
+ABQECwQLAAEEDAQMAAMEEAQQAAMEEgQSAAcEEwQTACUEFAQUAAkEFQQVACUEFgQWAAkEFwQXACUEGAQY
+AAkEHgQeAAIEHwQfAAYEIAQgAAIEIQQhAAYEIgQiAAIEIwQjAAYEJAQkAAIEJQQlAAYEJgQmAAIEJwQn
+AAYEKAQoAAIEKQQpAAYEKgQqAAIEKwQrAAYELAQsAAIELQQtAAYELgQuAAIELwQvAAYEMAQwAAIEMQQx
+AAYEMgQyAAIEMwQzAAYENAQ0AAIENQQ1AAYENgQ2AAUENwQ3AAgEOAQ4AAUEOQQ5AAgEOgQ6AAUEOwQ7
+AAgEPAQ8AAUEPQQ9AAgEPgQ+AAUEPwQ/AAgEQARAAAUEQQRBAAgEQgRCAAUEQwRDAAgERAREAAUERQRF
+AAgESgRKAAEESwRLAAMETARMAAEETQRNAAMETgROAAEETwRPAAMEUARQAAEEUQRRAAMEUgRSAAEEUwRT
+AAMEVARUAAEEVQRVAAMEVgRWAAEEVwRXAAMEXwRfAAMEYgRiAAoEZARkAAoEcARwAAwEcQRxAAkEcgRy
+AAwEcwRzAAkEdAR0AAwEdQR1AAkEdwR3AA4EewR7ACIEfAR8ABoEfwR/AAQEgQSBACAEggSCACIEhASE
+AAsEhgSGAAwEmASYAAQEmQSZAAIEmgSaAAYEmwSbAAUEnwSfAAEEoASgAAMEogSiABUEpgSmABwEpwSn
+AAcEqASoAAEEqgSqAAEErQStAAQErgSuAAsEsASwAAsEsgSyABgEtQS1AAQEtwS3AAQEuAS4AAEEuQS5
+ABYEugS6AAcEvAS8ABUEvwS/AA4EwQTBAAoEwgTCAB0EwwTDAAkExATEAB0ExQTFAAkExgTGABsEyATI
+ABEEyQTJABAEygTKAAEEywTLAA8EzwTPAA0E0gTSAA8E2ATYAB4E3QTdACME6AToAB4E6gTqAA8E8QTx
+AA0E9QT1ACMAAQAGBPUAFAAAAAAAAAAAABQAAAAAAAAAAAAaAB8AGgAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAGAAAAAgAAAAAAAAACAAAAAAAjAAAAAAAAAAAAAgAAAAIAAAAQAAsACgAd
+ABYAEQAMABMAAAAAAAAAAAAAAAAABwAAAAEAAQABAAAAAQAAAAAAAAAAAAAAAwADAAQAAwABAAAADgAA
+AAUACQAAABUACQAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAB
+AAAAAAAAAAIAAQAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG
+AAIABgAAAAAAAAAAAAAAAAABAAAACQAAAAAAAAADAAAAAAAAAAAAAAAAAAEAAQAAAAUAAAAAAAAAAAAA
+AAAACwACABkAAAALAAAAAAAAABEAAAAAABkAIgAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAV
+AAAAAwADABsAAwADAAMAAAABAAMAIQADAAMAAAAAAAMAAAADAAAAAAABABsAAwAAAAAAAgAAAAAAAAAA
+AAYAAAAAAAAAAAAAAAAAAAAAAAAAAgAEAB0ACQACAAAAAgABAAIAAAACAAEAAAAAAAAAAAAAAAAAAAAA
+AAMAAAAAAAAAAAAAAAAAAAARABUAAAADAAAAAAALAAAAAAADAAAAAwAAAAAAAgABABEAFQALAAAAIAAh
+AAAAAAAAAAAAAAAAAAAAGQAbAAAAAwAAAAMAAAADAAAAAAAAAAAAAwARABUAAAABAAEAAAAAAAAAAAAZ
+AAAAAAAAAAIAAQAAAAAAAAAZABsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfAB8AAAAU
+ABQAGgAUABQAFAAaAAAAAAAAABoAGgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABcAHAAkAAAAEgAYAB4AAAAIAAAACAAA
+AAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAA0ACAANAAAAAAAAAAAAAAAAABgACAAAAAAAGAAAAAAAAAAc
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAAAAGAAIABcAHAAYAAAAAAAAAAAAAAAI
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAA0AAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAgAAAAIAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAHwAAAAAAAAAAAAAABgAGAAYABgAGAAYABgACAAAAAAAAAAAAAAAAAAAAAAAAAAIAAgAC
+AAIAAgAKAAoACgAKAAwABwAHAAcABwAHAAcABwABAAEAAQABAAEAAAAAAAAAAAADAAQABAAEAAQABAAF
+AAUABQAFAAkACQAGAAcABgAHAAYABwACAAEAAgABAAIAAQACAAEAAAABAAAAAQAAAAEAAAABAAAAAQAA
+AAEAAgABAAIAAQACAAEAAgABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIwAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAADAAAAAwAAAAMAAwACAAQAAgAEAAIABAAAAAAAAAAAAAAAAAAQAA4AEAAOABAADgAQ
+AA4AEAAOAAsAAAALAAAACwAAAAoABQAKAAUACgAFAAoABQAKAAUACgAFABYAAAAMAAkADAATAA8AEwAP
+ABMADwAAAAAAAgAAAAAAAAAAAA0ADQANAA0ADQANAA0ACAAAAAAAAAAAAAAAAAAAAAAAAAAIAAgACAAI
+AAgAEgASABIAEgAXAA0ADQANAAgACAAIAAgAAAAAAAAAAAAAAAAACAAIAAgACAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAIAAgACAAAAAAAAAAeAB4AHgAeAAAAGAAAABIAEgASABIAEgASACQAFwAX
+AAAAAAAAAAYAAAAAAAAAAgAMAAAAAAAGAAAAAAATAAAAAAAAAAAAAAACAAAAAAAMABEAAAAMAAEAAAAD
+AAAABQAAAAQAAAAJAAAAAAAFAAQABQAAAAAAAAAAAAAAAAAjAAAAAAAiAAYAAAAAAAAAAAAAAAAAAgAA
+AAAAAgALABEABwABAAMABAADAAEACQAVAAEAAwAOAAAAAAAAAAMACQAWAAAAFgAAABYAAAAMAAkAFAAU
+AAAAAAAUAAAAAwAGAAcAAAAAAAEAAwAAAAAAHQAJAAEAAgAAAAAAAgABAAwACQAAABEAFQAAAAYABwAG
+AAcAAAAAAAAAAQAAAAEAAQARABUAAAAAAAAAAwAAAAMAAgAEAAIAAQACAAQAAAAAACIACQAiAAkAIgAJ
+ACAAIQAAAAMAAQAGAAcABgAHAAYABwAGAAcABgAHAAYABwAGAAcABgAHAAYABwAGAAcABgAHAAYABwAA
+AAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAAAAAAAAAgAEAAIABAACAAQAAgAEAAIABAAC
+AAQAAgAEAAIAAQACAAEAAgABAAIABAACAAEACgAFAAoABQAAAAUAAAAFAAAABQAAAAUAAAAFAAwACQAM
+AAkADAAJAAAACwAAACAAIQAAAAMAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAHwAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAwAGAAcAAAABAAAAAAACAAQAAAAAAAAABQAAAAAAAAAAAAEAAAABAAAAAAAA
+AAAAAAAAAAAAAAAAAAMAAAADAAIAAAAAAAAAAAAQAA4ACwAAAAoAHQAJAB0ACQAWAAAAEwAPAAAADQAA
+AAAAAAAIABcAAAANAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXABwAAAAXAAAAAAAAAAAAAAAAAAAAAAAN
+AAAAAAAAAAAAAAAAAAgAAAAAAAgAGAAcAAAAAAAIABcAAQAAAAoBYgKSAARERkxUABpjeXJsABpncmVr
+ABpsYXRuAEgABAAAAAD//wASAAAAAQACAAMABAAIAAwADQAOAA8AEAARABIAEwAUABUAFgAXAC4AB0Fa
+RSAA5ENSVCAA5EZSQSAAWk1PTCAAtk5BViAAiFJPTSAAtlRSSyAA5AAA//8AEwAAAAEAAgADAAQABwAI
+AAwADQAOAA8AEAARABIAEwAUABUAFgAXAAD//wAUAAAAAQACAAMABAAGAAgACQAMAA0ADgAPABAAEQAS
+ABMAFAAVABYAFwAA//8AFAAAAAEAAgADAAQABgAIAAsADAANAA4ADwAQABEAEgATABQAFQAWABcAAP//
+ABQAAAABAAIAAwAEAAYACAAKAAwADQAOAA8AEAARABIAEwAUABUAFgAXAAD//wATAAAAAQACAAMABAAF
+AAgADAANAA4ADwAQABEAEgATABQAFQAWABcAGGMyc2MAkmNjbXAAmGRsaWcAoGRub20ApmZyYWMArGxp
+Z2EAtmxpZ2EAvGxpZ2EAyGxudW0A0GxvY2wA1mxvY2wA3GxvY2wA4m51bXIA6G9udW0A7nBudW0A9HNt
+Y3AA+nNzMDEBAHNzMDIBBnNzMDMBDHNzMDQBEnNzMDUBGHNzMDYBHnNzMDcBJHRudW0BKgAAAAEAAAAA
+AAIAAgAEAAAAAQAKAAAAAQAYAAAAAwAWABcAGQAAAAEACQAAAAQACAAJAAgACQAAAAIACAAJAAAAAQAV
+AAAAAQAHAAAAAQAFAAAAAQAGAAAAAQAZAAAAAQASAAAAAQATAAAAAQABAAAAAQALAAAAAQAMAAAAAQAN
+AAAAAQAOAAAAAQAPAAAAAQAQAAAAAQARAAAAAQAUABoANgQwB+4IoAjKD24PhA+uD8IP5hAQEEwQYBB0
+EIgQmhC0EPYRFBFmEawSDhJsEoASsBLSAAEAAAABAAgAAgH6APoB5wJxAdEB0AHPAc4BzQHMAcsBygHJ
+AcgCMwIyAjECMAIoAeYB5QHkAeMB4gHhAeAB3wHeAd0B3AHbAdoB2QHYAdcB1gHVAdQB0wHSAegB6QJz
+AnUCdAJ2AnICdwJSAeoB6wHsAe0B7gHvAfAB8QHyAfMB9AH1AfYB9wH4AfkB+gH7AfwB/QH+AgACAQT+
+AgICAwIEAgUCBgIHAggCCQIKAgsCOwINAg4CDwIQBPgCEQITAhQCFQIWAhcCGAIZAhsCHAIeAh0DLwMw
+AzEDMgMzAzQDNQM2AzcDOAM5AzoDOwM8Az0DPgM/A0ADQQNCA0MDRANFA0YDRwNIA0kDSgNLA0wDTQNO
+A08DUANRA1IDUwNUA1UDVgNXA1gDWQNaA1sDXANdA14DXwNgA2EDYgNjBP8DZANlA2YDZwNoA2kDagNr
+A2wDbQNuA28DcANxA3IDcwN0A3UFAgN2A3cDeQN4A3oDewN8A30DfgN/A4ADgQOCA4MDhAOFBQAFAQTL
+BMwEzQTOBM8E0ATRBNIE0wTUBNUE1gTXBNgE2QTaBNsE3ATdBN4E3wTgBOEE4gTjBOQE5QTmBOcB/wTo
+BOkE6gTrBOwE7QTuBO8E8ATxBPIE8wT0BPUE9gUDBQQFBQUGBPcE+QT6BPwCGgT9BPsCDAISBQsFDAAB
+APoACAAKABQAFQAWABcAGAAZABoAGwAcAB0AJQAmACcAKAApACoAKwAsAC0ALgAvADAAMQAyADMANAA1
+ADYANwA4ADkAOgA7ADwAPQA+AGUAZwCBAIMAhACMAI8AkQCTALEAsgCzALQAtQC2ALcAuAC5ALoA0gDT
+ANQA1QDWANcA2ADZANoA2wDcAN0A3gDfAOAA4QDiAOMA5ADlAOYA5wDoAOkBLwEzATUBNwE5ATsBQQFD
+AUUBSQFLAUwBWAFZAZcBnQGiAaUCegJ7An0CfwKAAoECggKDAoQChQKGAocCiAKJAooCiwKMAo0CjgKP
+ApACkQKSApMClAKVApYClwKYApkCtgK4AroCvAK+AsACwgLEAsYCyALKAswCzgLQAtIC1ALWAtgC2gLc
+At4C4ALiAuMC5QLnAukC6wLtAu8C8QLzAvUC+AL6AvwC/gMAAwIDBAMGAwgDCgMMAw4DEAMSAxQDFgMY
+AxoDHAMeAyADIgMkAyUDJwMpAysDLQOGA4cDiAOJA4oDiwOMA44DjwOQA5EDkgOTA5QDlQOWA5cDmAOZ
+A5oDmwOcA50DrQOuA68DsAOxA7IDswO0A7UDtgO3A7gDuQO6A7sDvAO9A74DvwPAA8EDwgPTA9UD1wPZ
+A+4D8APyBAcEDQQTBH0EggSGBQcFCQABAAAAAQAIAAIB3ADrAnECMwIyAjECMAIoAeYB5QHkAeMB4gHh
+AeAB3wHeAd0B3AHbAdoB2QHYAdcB1gHVAdQB0wHSAmQCcwMwAnUCdAMvAeMCcgJ3AlIE0gTTAeoB6wTU
+BNUE1gHsBNcB7QHuAe8E3AHwAfAE3QTeAfEB8gHzAfoE6wTsAfsB/AH9Af4B/wIABO8E8ATyBPUE/gIC
+AgMCBAIFAgYCBwIIAgkCCgILAfQB9QH2AfcB+AH5AjsCDQIOAg8CEAT4AhECEwIUAhUCFwIZAnYDMQMy
+AzMDNAM1AzYDNwM4AzkDOgM7AzwDPQM+Az8DQANBA0IDQwNEA0UDRgNHA0gDSQNKA0sDTAOCA00DTgNP
+A1ADUQNSA1MDVANVA1YDVwNYA1kDWgNbA1wDXQNeA18DYANhA2IE/wNkA2UDZgNnA2gDaQNqA2sDbANt
+A24DbwNwA3EDcgNzA3QDdQUCA3YDdwN5A3gDegN7A3wDfQN+A38DgAOBA4MDhAOFBQAFAQTLBMwEzQTO
+BNgE2wTZBNoE3wTgBOEEzwTQBNEE6gTtBO4E8QTzBPQCAQT2BOIE4wTkBOUE5gTnBOgE6QUDBQQFBQUG
+BPcE+QT6AhgE/AIaBP0E+wIWAgwCEgULBQwAAQDrAAoARQBGAEcASABJAEoASwBMAE0ATgBPAFAAUQBS
+AFMAVABVAFYAVwBYAFkAWgBbAFwAXQBeAIUAhgCHAIkAigCLAI0AkACSAJQAuwC8AL0AvgC/AMAAwQDC
+AMMAxADFAMYAxwDIAMkAygDLAMwAzQDOAOoA6wDsAO0A7gDvAPAA8QDyAPMA9AD1APYA9wD4APkA+gD7
+APwA/QD+AP8BAAEBAQIBAwEEAQUBBgEHATABNAE2ATgBOgE8AUIBRAFGAUoBTQFaAnwCfgKaApsCnAKd
+Ap4CnwKgAqECogKjAqQCpQKmAqcCqAKpAqoCqwKsAq0CrgKvArACsQKyArMCtAK1ArcCuQK7Ar0CvwLB
+AsMCxQLHAskCywLNAs8C0QLTAtUC1wLZAtsC3QLfAuEC5ALmAugC6gLsAu4C8ALyAvQC9gL5AvsC/QL/
+AwEDAwMFAwcDCQMLAw0DDwMRAxMDFQMXAxkDGwMdAx8DIQMjAyYDKAMqAywDLgOeA58DoAOhA6MDpAOl
+A6YDpwOoA6kDqgOrA6wDwwPEA8UDxgPHA8gDyQPKA8sDzAPNA84DzwPQA9ED0gPUA9YD2APaA+8D8QPz
+BAEECAQOBBQEfgR/BIMEhwUIBQoABgAAAAYAEgAqAEIAWgByAIoAAwAAAAEAEgABAJAAAQAAAAMAAQAB
+AE0AAwAAAAEAEgABAHgAAQAAAAMAAQABAE4AAwAAAAEAEgABAGAAAQAAAAMAAQABAuEAAwAAAAEAEgAB
+AEgAAQAAAAMAAQABA84AAwAAAAEAEgABADAAAQAAAAMAAQABA9AAAwAAAAEAEgABABgAAQAAAAMAAQAB
+BEkAAgACAKgArAAAASQBJwAFAAEAAAABAAgAAgASAAYCYQJfAmICYwJgBQ0AAQAGAE0ATgLhA84D0ARJ
+AAQAAAABAAgAAQYyADYAcgCkAK4AuADKAPwBDgEYAUoBZAF+AZABugH2AgACIgI8Ak4CigKcArYC4ALy
+AyQDLgM4A0oDfAOGA5ADmgO0A84D4AQKBDwERgRoBIIElATGBNgE8gUcBS4FOAVCBUwFVgWABaoF1AX+
+BigABgAOABQAGgAgACYALAKAAAIAqQQeAAIArQJ/AAIAqAQgAAIAqwKCAAIAqgSZAAIArAABAAQEpgAC
+AK0AAQAEArwAAgCpAAIABgAMBKoAAgG6BKgAAgCtAAYADgAUABoAIAAmACwCiAACAKkENgACAK0ChwAC
+AKgEOAACAKsEOgACAKoEmwACAKwAAgAGAAwElQACAKkC1gACAboAAQAEBKwAAgCtAAYADgAUABoAIAAm
+ACwCjAACAKkESAACAK0CiwACAKgERgACAKsC2gACAKoEnQACAKwAAwAIAA4AFASuAAIAqQLnAAIBugSw
+AAIArQADAAgADgAUAukAAgCpAusAAgG6BLIAAgCtAAIABgAMA+AAAgCpBLQAAgCtAAUADAASABgAHgAk
+AvEAAgCpAvMAAgG6BLYAAgCtBJcAAgCoAo8AAgCqAAcAEAAYAB4AJAAqADAANgS4AAMAqgCpApEAAgCp
+BEoAAgCtApAAAgCoBEwAAgCrApMAAgCqBJ8AAgCsAAEABAS5AAIAqQAEAAoAEAAWABwC/gACAKkDAAAC
+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
+''';
+
 String _dart_192_png;
 // dart_192_png md5 is '7d80a0adfe72aa9597d5e135b70b42c8'
 String _dart_192_png_base64 = '''
@@ -581,7 +7422,7 @@
 ''';
 
 String _index_html;
-// index_html md5 is '803a2ed6c6547e0b448d0e28c28cf385'
+// index_html md5 is '39097ee2371c204f0f1e3515a60a7203'
 String _index_html_base64 = '''
 PGh0bWw+CjxoZWFkPgogICAgPHRpdGxlPk51bGwgU2FmZXR5IFByZXZpZXc8L3RpdGxlPgogICAgPHNj
 cmlwdCBzcmM9Int7IGhpZ2hsaWdodEpzUGF0aCB9fSI+PC9zY3JpcHQ+CiAgICA8c2NyaXB0Pnt7IGRh
@@ -598,207 +7439,255 @@
 Ym90dG9tIiB0YXJnZXQ9Il9ibGFuayI+RmlsZSBvbiBHaXRIdWI8L2E+PCEtLSBwb3N0IHRvIGdpdGh1
 YiBwbGFjZWhvbGRlciBlbGVtZW50IC0tPgo8L2Rpdj4KPHAgY2xhc3M9InJvb3QiPnt7IHJvb3QgfX08
 L3A+CjxoZWFkZXIgY2xhc3M9ImVsZXZhdGlvbi16NCI+CiAgICA8aW1nIHNyYz0ie3sgZGFydExvZ29Q
-YXRoIH19IiBhbHQ9IkRhcnRQYWQgTG9nbyIgY2xhc3M9ImxvZ28iLz4KICAgIDxoMSBjbGFzcz0iYmVm
-b3JlLWFwcGx5Ij5Qcm9wb3NlZCBudWxsIHNhZmV0eSBjaGFuZ2VzPC9oMT4KICAgIDxoMSBjbGFzcz0i
-YWZ0ZXItYXBwbHkiPiYjMTAwMDM7IE51bGwgc2FmZXR5IG1pZ3JhdGlvbiBhcHBsaWVkPC9oMT4KICAg
-IDxoMiBpZD0idW5pdC1uYW1lIj4mbmJzcDs8L2gyPgogICAgPGJ1dHRvbiBjbGFzcz0iYXBwbHktbWln
-cmF0aW9uIj4mIzk5OTg7IEFwcGx5IE1pZ3JhdGlvbjwvYnV0dG9uPgogICAgPGJ1dHRvbiBjbGFzcz0i
-YXBwbHktbWlncmF0aW9uIiBkaXNhYmxlZD4mIzk5OTg7IEFwcGx5IE1pZ3JhdGlvbjwvYnV0dG9uPgog
-ICAgPGJ1dHRvbiBjbGFzcz0icmVydW4tbWlncmF0aW9uIGJlZm9yZS1hcHBseSI+CiAgICAgIDxzcGFu
-IGNsYXNzPSJvcHRpb25hbCI+JiM4NjM1OyBSZXJ1biBGcm9tIFNvdXJjZXM8L3NwYW4+CiAgICAgIDxz
-cGFuIGNsYXNzPSJyZXF1aXJlZCI+CiAgICAgICAgPHNwYW4gY2xhc3M9Imljb24iIAogICAgICAgICAg
-dGl0bGU9IkRpc2sgY29udGVudHMgaGF2ZSBjaGFuZ2VkLiBSZXJ1biB0byBnZXQgYW4gdXAtdG8tZGF0
-ZSBtaWdyYXRpb24uIj4hPC9zcGFuPgogICAgICAgIFJlcnVuIFdpdGggQ2hhbmdlcwogICAgICA8L3Nw
-YW4+CiAgICA8L2J1dHRvbj4KPC9oZWFkZXI+CjxkaXYgY2xhc3M9InBhbmVscyBob3Jpem9udGFsIj4K
-ICAgIDxkaXYgY2xhc3M9Im5hdi1wYW5lbCI+CiAgICAgICAgPGRpdiBjbGFzcz0ibmF2LWlubmVyIj4K
-ICAgICAgICAgICAgPGRpdiBjbGFzcz0icGFuZWwtaGVhZGluZyI+UHJvamVjdCBGaWxlczwvZGl2Pgog
-ICAgICAgICAgICA8ZGl2IGNsYXNzPSJuYXYtdHJlZSI+PC9kaXY+CiAgICAgICAgPC9kaXY+PCEtLSAv
-bmF2LWlubmVyIC0tPgogICAgPC9kaXY+PCEtLSAvbmF2IC0tPgogICAgPGRpdiBjbGFzcz0iY29udGVu
-dCI+CiAgICAgICAgPGRpdiBjbGFzcz0icmVnaW9ucyI+CiAgICAgICAgICAgIDwhLS0gVGhlIHJlZ2lv
-bnMgb3ZlcmxheSBjb2RlIGNvcHkgb2YgdGhlIGNvbnRlbnQgdG8gcHJvdmlkZSAtLT4KICAgICAgICAg
-ICAgPCEtLSB0b29sdGlwcyBmb3IgbW9kaWZpZWQgcmVnaW9ucy4gLS0+CiAgICAgICAgPC9kaXY+PCEt
-LSAvcmVnaW9ucyAtLT4KICAgICAgICA8ZGl2IGNsYXNzPSJjb2RlIj4KICAgICAgICAgICAgPCEtLSBD
-b21waWxhdGlvbiB1bml0IGNvbnRlbnQgaXMgd3JpdHRlbiBoZXJlLiAtLT4KICAgICAgICAgICAgPHAg
-Y2xhc3M9IndlbGNvbWUiPgogICAgICAgICAgICAgICAgU2VsZWN0IGEgc291cmNlIGZpbGUgb24gdGhl
-IGxlZnQgdG8gcHJldmlldyB0aGUgcHJvcG9zZWQgZWRpdHMuCiAgICAgICAgICAgIDwvcD4KICAgICAg
-ICA8L2Rpdj4KICAgIDwvZGl2PjwhLS0gL2NvbnRlbnQgLS0+CiAgICA8ZGl2IGNsYXNzPSJpbmZvLXBh
-bmVsIj4KICAgICAgICA8ZGl2IGNsYXNzPSJlZGl0LWxpc3QiPgogICAgICAgICAgICA8ZGl2IGNsYXNz
-PSJwYW5lbC1oZWFkaW5nIj5Qcm9wb3NlZCBFZGl0czwvZGl2PgogICAgICAgICAgICA8ZGl2IGNsYXNz
-PSJwYW5lbC1jb250ZW50Ij48L2Rpdj4KICAgICAgICA8L2Rpdj48IS0tIC9lZGl0LWxpc3QgLS0+CiAg
-ICAgICAgPGRpdiBjbGFzcz0iZWRpdC1wYW5lbCI+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9InBhbmVs
-LWhlYWRpbmciPkVkaXQgRGV0YWlsczwvZGl2PgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJwYW5lbC1j
-b250ZW50Ij4KICAgICAgICAgICAgICAgIDxwIGNsYXNzPSJwbGFjZWhvbGRlciI+U2VlIGRldGFpbHMg
-YWJvdXQgYSBwcm9wb3NlZCBlZGl0LjwvcD4KICAgICAgICAgICAgPC9kaXY+PCEtLSAvcGFuZWwtY29u
-dGVudCAtLT4KICAgICAgICA8L2Rpdj48IS0tIC9lZGl0LXBhbmVsIC0tPgogICAgPC9kaXY+PCEtLSAv
-aW5mby1wYW5lbCAtLT4KPC9kaXY+PCEtLSAvcGFuZWxzIC0tPgo8Zm9vdGVyPgogICAgPGEgdGFyZ2V0
-PSJfYmxhbmsiCiAgICAgIGhyZWY9Imh0dHBzOi8vZ29vLmdsZS9kYXJ0LW51bGwtc2FmZXR5LW1pZ3Jh
-dGlvbi10b29sIj5OdWxsIHNhZmV0eQogICAgICAgIG1pZ3JhdGlvbiBoZWxwPC9hPgogICAgPHNwYW4g
-Y2xhc3M9IndpZGUiPiA8L3NwYW4+CiAgICA8ZGl2PkJhc2VkIG9uIDxzcGFuIGlkPSJzZGstdmVyc2lv
-biI+e3sgc2RrVmVyc2lvbiB9fTwvc3Bhbj48L2Rpdj4KICAgIDxidXR0b24gY2xhc3M9InJlcG9ydC1w
-cm9ibGVtIj5SZXBvcnQgYSBQcm9ibGVtPC9idXR0b24+CjwvZm9vdGVyPgo8L2JvZHk+CjwvaHRtbD4K
+YXRoIH19IiBhbHQ9IkRhcnRQYWQgTG9nbyIgY2xhc3M9ImxvZ28iLz4KICAgIDxoMT5EYXJ0PC9oMT4K
+ICAgIDxoMiBjbGFzcz0iYmVmb3JlLWFwcGx5Ij5Qcm9wb3NlZCBudWxsIHNhZmV0eSBjaGFuZ2VzPC9o
+Mj4KICAgIDxoMiBjbGFzcz0iYWZ0ZXItYXBwbHkiPiYjMTAwMDM7IE51bGwgc2FmZXR5IG1pZ3JhdGlv
+biBhcHBsaWVkPC9oMj4KICAgIDxoMyBpZD0idW5pdC1uYW1lIj4mbmJzcDs8L2gzPgogICAgPGEgdGFy
+Z2V0PSJfYmxhbmsiCiAgICAgICBocmVmPSJodHRwczovL2dvby5nbGUvZGFydC1udWxsLXNhZmV0eS1t
+aWdyYXRpb24tdG9vbCI+CiAgICAgIDxidXR0b24gY2xhc3M9ImFjdGlvbi1idXR0b24iPgogICAgICAg
+IDxpIGNsYXNzPSJtYXRlcmlhbC1pY29ucyI+bGF1bmNoPC9pPgogICAgICAgIDxzcGFuPkhlbHA8L3Nw
+YW4+CiAgICAgIDwvYnV0dG9uPgogICAgPC9hPgogICAgPGJ1dHRvbiBjbGFzcz0iYWN0aW9uLWJ1dHRv
+biBhcHBseS1taWdyYXRpb24iPgogICAgICAgIDxpIGNsYXNzPSJtYXRlcmlhbC1pY29ucyI+ZWRpdDwv
+aT4KICAgICAgICA8c3BhbiBjbGFzcz0ibGFiZWwiPgogICAgICAgICAgQXBwbHkgTWlncmF0aW9uCiAg
+ICAgICAgPC9zcGFuPgogICAgPC9idXR0b24+CiAgICA8YnV0dG9uIGNsYXNzPSJhY3Rpb24tYnV0dG9u
+IGFwcGx5LW1pZ3JhdGlvbiIgZGlzYWJsZWQ+CiAgICAgICAgPGkgY2xhc3M9Im1hdGVyaWFsLWljb25z
+Ij5lZGl0PC9pPgogICAgICAgIDxzcGFuIGNsYXNzPSJsYWJlbCI+CiAgICAgICAgICBBcHBseSBNaWdy
+YXRpb24KICAgICAgICA8L3NwYW4+CiAgICA8L2J1dHRvbj4KICAgIDxidXR0b24gY2xhc3M9ImFjdGlv
+bi1idXR0b24gcmVydW4tbWlncmF0aW9uIGJlZm9yZS1hcHBseSI+CiAgICAgIDxzcGFuIGNsYXNzPSJv
+cHRpb25hbCI+CiAgICAgICAgPGkgY2xhc3M9Im1hdGVyaWFsLWljb25zIj5yZXBsYXk8L2k+CiAgICAg
+ICAgUmVydW4gRnJvbSBTb3VyY2VzCiAgICAgIDwvc3Bhbj4KICAgICAgPHNwYW4gY2xhc3M9InJlcXVp
+cmVkIj4KICAgICAgICA8aSBjbGFzcz0ibWF0ZXJpYWwtaWNvbnMiPndhcm5pbmc8L2k+CiAgICAgICAg
+UmVydW4gV2l0aCBDaGFuZ2VzCiAgICAgIDwvc3Bhbj4KICAgIDwvYnV0dG9uPgo8L2hlYWRlcj4KPGRp
+diBjbGFzcz0icGFuZWxzIGhvcml6b250YWwiPgogICAgPGRpdiBjbGFzcz0ibmF2LXBhbmVsIj4KICAg
+ICAgICA8ZGl2IGNsYXNzPSJuYXYtaW5uZXIiPgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJwYW5lbC1o
+ZWFkaW5nIj5Qcm9qZWN0IEZpbGVzPC9kaXY+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9Im5hdi10cmVl
+Ij48L2Rpdj4KICAgICAgICA8L2Rpdj48IS0tIC9uYXYtaW5uZXIgLS0+CiAgICA8L2Rpdj48IS0tIC9u
+YXYgLS0+CiAgICA8ZGl2IGNsYXNzPSJjb250ZW50Ij4KICAgICAgICA8ZGl2IGNsYXNzPSJyZWdpb25z
+Ij4KICAgICAgICAgICAgPCEtLSBUaGUgcmVnaW9ucyBvdmVybGF5IGNvZGUgY29weSBvZiB0aGUgY29u
+dGVudCB0byBwcm92aWRlIC0tPgogICAgICAgICAgICA8IS0tIHRvb2x0aXBzIGZvciBtb2RpZmllZCBy
+ZWdpb25zLiAtLT4KICAgICAgICA8L2Rpdj48IS0tIC9yZWdpb25zIC0tPgogICAgICAgIDxkaXYgY2xh
+c3M9ImNvZGUiPgogICAgICAgICAgICA8IS0tIENvbXBpbGF0aW9uIHVuaXQgY29udGVudCBpcyB3cml0
+dGVuIGhlcmUuIC0tPgogICAgICAgICAgICA8cCBjbGFzcz0id2VsY29tZSI+CiAgICAgICAgICAgICAg
+ICBTZWxlY3QgYSBzb3VyY2UgZmlsZSBvbiB0aGUgbGVmdCB0byBwcmV2aWV3IHRoZSBwcm9wb3NlZCBl
+ZGl0cy4KICAgICAgICAgICAgPC9wPgogICAgICAgIDwvZGl2PgogICAgPC9kaXY+PCEtLSAvY29udGVu
+dCAtLT4KICAgIDxkaXYgY2xhc3M9ImluZm8tcGFuZWwiPgogICAgICAgIDxkaXYgY2xhc3M9ImVkaXQt
+bGlzdCI+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9InBhbmVsLWhlYWRpbmciPlByb3Bvc2VkIEVkaXRz
+PC9kaXY+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9InBhbmVsLWNvbnRlbnQiPjwvZGl2PgogICAgICAg
+IDwvZGl2PjwhLS0gL2VkaXQtbGlzdCAtLT4KICAgICAgICA8ZGl2IGNsYXNzPSJlZGl0LXBhbmVsIj4K
+ICAgICAgICAgICAgPGRpdiBjbGFzcz0icGFuZWwtaGVhZGluZyI+RWRpdCBEZXRhaWxzPC9kaXY+CiAg
+ICAgICAgICAgIDxkaXYgY2xhc3M9InBhbmVsLWNvbnRlbnQiPgogICAgICAgICAgICAgICAgPHAgY2xh
+c3M9InBsYWNlaG9sZGVyIj5TZWUgZGV0YWlscyBhYm91dCBhIHByb3Bvc2VkIGVkaXQuPC9wPgogICAg
+ICAgICAgICA8L2Rpdj48IS0tIC9wYW5lbC1jb250ZW50IC0tPgogICAgICAgIDwvZGl2PjwhLS0gL2Vk
+aXQtcGFuZWwgLS0+CiAgICA8L2Rpdj48IS0tIC9pbmZvLXBhbmVsIC0tPgo8L2Rpdj48IS0tIC9wYW5l
+bHMgLS0+Cjxmb290ZXI+CiAgPGJ1dHRvbiBjbGFzcz0icmVwb3J0LXByb2JsZW0iPlNlbmQgRmVlZGJh
+Y2s8L2J1dHRvbj4KICAgIDxzcGFuIGNsYXNzPSJ3aWRlIj4gPC9zcGFuPgogICAgPGRpdiBjbGFzcz0i
+c2RrLXZlcnNpb24iPkJhc2VkIG9uIDxzcGFuIGlkPSJzZGstdmVyc2lvbiI+e3sgc2RrVmVyc2lvbiB9
+fTwvc3Bhbj48L2Rpdj4KPC9mb290ZXI+CjwvYm9keT4KPC9odG1sPgo=
 ''';
 
 String _migration_css;
-// migration_css md5 is 'e6730f8303d73cb852f1717cb20e6c98'
+// migration_css md5 is 'b0c95ec84cbd6de507ca2e6a7d6a45b7'
 String _migration_css_base64 = '''
 LyogQ29weXJpZ2h0IChjKSAyMDE5LCB0aGUgRGFydCBwcm9qZWN0IGF1dGhvcnMuIFBsZWFzZSBzZWUg
 dGhlIEFVVEhPUlMgZmlsZSAgKi8KLyogZm9yIGRldGFpbHMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuIFVz
 ZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGEgKi8KLyogQlNELXN0eWxlIGxpY2Vu
 c2UgdGhhdCBjYW4gYmUgZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZS4gICAgICAgICAgICAgICAgICAg
-Ki8KCmJvZHkgewogIGJhY2tncm91bmQtY29sb3I6ICMxMjIwMmY7CiAgY29sb3I6ICNjY2M7CiAgZm9u
-dC1mYW1pbHk6ICJSb2JvdG8iLCBzYW5zLXNlcmlmOwogIGZvbnQtc2l6ZTogMTRweDsKICBkaXNwbGF5
-OiBmbGV4OwogIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47CiAgcG9zaXRpb246IGFic29sdXRlOwogIHRv
-cDogMDsKICByaWdodDogMDsKICBib3R0b206IDA7CiAgbGVmdDogMDsKICBtYXJnaW46IDA7CiAgcGFk
-ZGluZzogMDsKICBvdmVyZmxvdzogaGlkZGVuOwp9CgoucHJvcG9zZWQgLmFmdGVyLWFwcGx5IHsKICBk
-aXNwbGF5OiBub25lOwp9CgouYXBwbGllZCAuYmVmb3JlLWFwcGx5IHsKICBkaXNwbGF5OiBub25lOwp9
-CgouYXBwbGllZCAuYXBwbHktbWlncmF0aW9uOm5vdChbZGlzYWJsZWRdKSwgLm5lZWRzLXJlcnVuIC5h
-cHBseS1taWdyYXRpb246bm90KFtkaXNhYmxlZF0pIHsKICBkaXNwbGF5OiBub25lOwp9CgoucHJvcG9z
-ZWQ6bm90KC5uZWVkcy1yZXJ1bikgLmFwcGx5LW1pZ3JhdGlvbltkaXNhYmxlZF0gewogIGRpc3BsYXk6
-IG5vbmU7Cn0KCmhlYWRlciB7CiAgYmFja2dyb3VuZC1jb2xvcjogIzFjMjgzNDsKICBoZWlnaHQ6IDQ4
-cHg7CiAgcGFkZGluZy1sZWZ0OiAyNHB4OwogIGFsaWduLWl0ZW1zOiBjZW50ZXI7CiAgei1pbmRleDog
-NDsKfQoKaGVhZGVyIGgxLApoZWFkZXIgaDIgewogIGRpc3BsYXk6IGlubGluZS1ibG9jazsKICBmb250
-LWZhbWlseTogIkdvb2dsZSBTYW5zIiwiUm9ib3RvIixzYW5zLXNlcmlmOwogIGZvbnQtd2VpZ2h0OiA0
-MDA7CiAgbWFyZ2luLXJpZ2h0OiAyNHB4Owp9CgpoMSB7CiAgZm9udC1zaXplOiAxLjVlbTsKfQoKaGVh
-ZGVyIGgyIHsKICBmb250LXNpemU6IDEuMmVtOwp9CgpoZWFkZXIgLmFwcGx5LW1pZ3JhdGlvbiwgLnJl
-cnVuLW1pZ3JhdGlvbiB7CiAgcmlnaHQ6IDBweDsKICBmbG9hdDogcmlnaHQ7CiAgbWFyZ2luOiAxMHB4
-Owp9CgpoZWFkZXIgaW1nLmxvZ28gewogIGhlaWdodDogMjRweDsKICB3aWR0aDogMjRweDsKICBtYXJn
-aW4tcmlnaHQ6IDhweDsKfQoKZm9vdGVyIC5yZXBvcnQtcHJvYmxlbSB7CiAgcmlnaHQ6IDBweDsKICBt
-YXJnaW46IDRweCA4cHg7Cn0KCi5yZXJ1bi1taWdyYXRpb24gLnJlcXVpcmVkIHsKICBkaXNwbGF5OiBu
-b25lOwp9CgoubmVlZHMtcmVydW4gLnJlcnVuLW1pZ3JhdGlvbiAucmVxdWlyZWQgewogIGRpc3BsYXk6
-IGluaXRpYWw7Cn0KCi5uZWVkcy1yZXJ1biAucmVydW4tbWlncmF0aW9uIC5vcHRpb25hbCB7CiAgZGlz
-cGxheTpub25lOwp9CgovKiBSZWQgdHJpYW5nbGUgKi8KLnJlcnVuLW1pZ3JhdGlvbiAucmVxdWlyZWQg
-Lmljb246OmJlZm9yZSB7CiAgdHJhbnNmb3JtOiB0cmFuc2xhdGUoLThweCwgLTExcHgpOwogIGNvbnRl
-bnQ6ICdcMjVCMyc7CiAgZm9udC1zaXplOiAyNXB4OwogIHBvc2l0aW9uOiBmaXhlZDsKICBjb2xvcjog
-I2U4MmMyYzsKICB0ZXh0LXNoYWRvdzogMHB4IDBweCA1cHggd2hpdGU7CiAgei1pbmRleDogLTM7Cn0K
-Ci8qIFJlZCB0cmlhbmdsZSBmaWxsICovCi5yZXJ1bi1taWdyYXRpb24gLnJlcXVpcmVkIC5pY29uOjph
-ZnRlciB7CiAgdHJhbnNmb3JtOiB0cmFuc2xhdGUoLTlweCwgLTEwcHgpOwogIGNvbnRlbnQ6ICdcMjVC
-NCc7CiAgZm9udC1zaXplOiAyNXB4OwogIHBvc2l0aW9uOiBmaXhlZDsKICBjb2xvcjogI2IzZWNmZjsK
-ICB6LWluZGV4OiAtMTsKfQoKLyogUmVkIHRyaWFuZ2xlIGV4Y2xhbWF0aW9uICovCi5yZXJ1bi1taWdy
-YXRpb24gLnJlcXVpcmVkIC5pY29uIHsKICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7CiAgbWFyZ2luLXJp
-Z2h0OiA4cHg7CiAgdHJhbnNmb3JtOiB0cmFuc2xhdGUoMHB4LCAycHgpOwogIG1hcmdpbi1sZWZ0OiAy
-cHg7CiAgY29sb3I6ICMyYjJiMmI7Cn0KCmZvb3RlciB7CiAgY29sb3I6ICNjY2M7CiAgYmFja2dyb3Vu
-ZC1jb2xvcjogIzI3MzIzYTsKICBkaXNwbGF5OiBmbGV4OwogIGZsZXgtZGlyZWN0aW9uOiByb3c7CiAg
-YWxpZ24taXRlbXM6IGNlbnRlcjsKICBwYWRkaW5nOiA4cHggMCA4cHggMjRweDsKfQoKZm9vdGVyIC53
-aWRlIHsKICBmbGV4OiAxOwp9CgouaG9yaXpvbnRhbCB7CiAgZGlzcGxheTogZmxleDsKfQoKLnBhbmVs
-cyB7CiAgYmFja2dyb3VuZC1jb2xvcjogIzEyMWEyNTsKICBmbGV4OiAxOwogIG92ZXJmbG93OiBoaWRk
-ZW47Cn0KCi5wYW5lbC1oZWFkaW5nIHsKICBjb2xvcjogZ3JheTsKICBtYXJnaW46IDhweDsKfQoKLm5h
-di1saW5rLAoucmVnaW9uIHsKICBjdXJzb3I6IHBvaW50ZXI7Cn0KCi5uYXYtcGFuZWwgewogIGJhY2tn
-cm91bmQtY29sb3I6ICMyODJiMmU7CiAgZmxleDogMSAyMDBweDsKICBtYXJnaW46IDA7CiAgb3ZlcmZs
-b3c6IHNjcm9sbDsKfQoKLm5hdi1pbm5lciB7CiAgcGFkZGluZzogMCAwIDdweCA3cHg7Cn0KCi5maXhl
-ZCB7CiAgcG9zaXRpb246IGZpeGVkOwogIHRvcDogMDsKfQoKLnJvb3QgewogIG1hcmdpbjogMDsKICBk
-aXNwbGF5OiBub25lOwp9CgoubmF2LXRyZWUgPiB1bCB7CiAgcGFkZGluZy1sZWZ0OiA2cHg7Cn0KCi5u
-YXYtaW5uZXIgdWwgewogIHBhZGRpbmctbGVmdDogMTJweDsKICBtYXJnaW46IDA7Cn0KCi5uYXYtaW5u
-ZXIgbGkgewogIGxpc3Qtc3R5bGUtdHlwZTogbm9uZTsKfQoKLm5hdi1pbm5lciBsaTpub3QoLmRpcikg
-ewogIG1hcmdpbi1sZWZ0OiAyMHB4OwogIG1hcmdpbi1ib3R0b206IDNweDsKfQoKLm5hdi1pbm5lciBs
-aS5kaXIgLmFycm93IHsKICBjdXJzb3I6IHBvaW50ZXI7CiAgZGlzcGxheTogaW5saW5lLWJsb2NrOwog
-IGZvbnQtc2l6ZTogMTBweDsKICBtYXJnaW4tcmlnaHQ6IDRweDsKICB0cmFuc2l0aW9uOiB0cmFuc2Zv
-cm0gMC41cyBlYXNlLW91dDsKfQoKLm5hdi1pbm5lciBsaS5kaXIgLmFycm93LmNvbGxhcHNlZCB7CiAg
-dHJhbnNmb3JtOiByb3RhdGUoLTkwZGVnKTsKfQoKLm5hdi1pbm5lciB1bCB7CiAgbWF4LWhlaWdodDog
-MjAwMHB4OwogIHRyYW5zaXRpb246IG1heC1oZWlnaHQgMC41cyBlYXNlLW91dDsKfQoKLm5hdi1pbm5l
-ciB1bC5jb2xsYXBzZWQgewogIG1heC1oZWlnaHQ6IDAgIWltcG9ydGFudDsKICBvdmVyZmxvdzogaGlk
-ZGVuOwp9CgoubmF2LWlubmVyIC5zZWxlY3RlZC1maWxlIHsKICBjb2xvcjogd2hpdGU7CiAgY3Vyc29y
-OiBpbmhlcml0OwogIGZvbnQtd2VpZ2h0OiA2MDA7CiAgdGV4dC1kZWNvcmF0aW9uOiBub25lOwp9Cgou
-ZWRpdC1jb3VudCB7CiAgYmFja2dyb3VuZC1jb2xvcjogIzM3YWVkYzsKICBib3JkZXItcmFkaXVzOiAx
-MHB4OwogIGNvbG9yOiAjMDAwMDAwOwogIGRpc3BsYXk6IGlubGluZS1ibG9jazsKICBmb250LXNpemU6
-IDExcHg7CiAgZm9udC13ZWlnaHQ6IDYwMDsKICBtYXJnaW4tbGVmdDogNXB4OwogIG1pbi13aWR0aDog
-MjVweDsKICBwYWRkaW5nOiA0cHggMCAycHggMDsKICB0ZXh0LWFsaWduOiBjZW50ZXI7CiAgbGluZS1o
-ZWlnaHQ6IDFlbTsKfQoKLmNvbnRlbnQgewogIGZsZXg6IDQgMzAwcHg7CiAgYmFja2dyb3VuZDogIzI4
-MmIyZTsKICBmb250LWZhbWlseTogbW9ub3NwYWNlOwogIG1hcmdpbjogMCA2cHg7CiAgcG9zaXRpb246
-IHJlbGF0aXZlOwogIHdoaXRlLXNwYWNlOiBwcmU7CiAgb3ZlcmZsb3c6IHNjcm9sbDsKfQoKLmNvZGUg
-ewogIHBhZGRpbmc6IDAuNWVtOwogIHBvc2l0aW9uOiBhYnNvbHV0ZTsKICBsZWZ0OiAwOwogIHRvcDog
-MDsKICBtYXJnaW4tbGVmdDogNTZweDsKfQoKLmhsanMgewogIGJhY2tncm91bmQtY29sb3I6ICMyODJi
-MmU7CiAgZGlzcGxheTogYmxvY2s7CiAgb3ZlcmZsb3cteDogYXV0bzsKICBwYWRkaW5nOiAwLjVlbTsK
-fQoKLmNvZGUgLndlbGNvbWUgewogIGZvbnQtZmFtaWx5OiAiR29vZ2xlIFNhbnMiLCJSb2JvdG8iLHNh
-bnMtc2VyaWY7CiAgZm9udC1zaXplOiAxOHB4OwogIG1hcmdpbi1yaWdodDogNjJweDsKICBjb2xvcjog
-Izc3NzsKfQoKLmNvZGUgLm5hdi1saW5rIHsKICBjb2xvcjogaW5oZXJpdDsKICB0ZXh0LWRlY29yYXRp
-b24tbGluZTogbm9uZTsKfQoKLmNvZGUgLm5hdi1saW5rOnZpc2l0ZWQgewogIGNvbG9yOiBpbmhlcml0
-OwogIHRleHQtZGVjb3JhdGlvbi1saW5lOiBub25lOwp9CgouY29kZSAubmF2LWxpbms6aG92ZXIgewog
-IHRleHQtZGVjb3JhdGlvbi1saW5lOiB1bmRlcmxpbmU7CiAgZm9udC13ZWlnaHQ6IDYwMDsKfQoKLnJl
-Z2lvbnMgewogIHBhZGRpbmc6IDAuNWVtOwogIHBvc2l0aW9uOiBhYnNvbHV0ZTsKICBsZWZ0OiAwOwog
-IHRvcDogMDsKfQoKLnJlZ2lvbnMgdGFibGUgewogIGJvcmRlci1zcGFjaW5nOiAwOwogIGZvbnQtc2l6
-ZTogaW5oZXJpdDsKfQoKLnJlZ2lvbnMgdGQgewogIGJvcmRlcjogbm9uZTsKICAvKiBUaGUgY29udGVu
-dCBvZiB0aGUgcmVnaW9ucyBpcyBub3QgdmlzaWJsZTsgdGhlIHVzZXIgaW5zdGVhZCB3aWxsIHNlZSB0
-aGUKICAgKiBoaWdobGlnaHRlZCBjb3B5IG9mIHRoZSBjb250ZW50LiAqLwogIGNvbG9yOiByZ2JhKDI1
-NSwgMjU1LCAyNTUsIDApOwogIHBhZGRpbmc6IDA7CiAgd2hpdGUtc3BhY2U6IHByZTsKfQoKLnJlZ2lv
-bnMgdGQ6ZW1wdHk6YWZ0ZXIgewogIGNvbnRlbnQ6ICJcMDBhMCI7Cn0KCi5yZWdpb25zIHRyLmhpZ2hs
-aWdodCB0ZDpsYXN0LWNoaWxkIHsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDQ0NDQ0OwogIGNvbG9yOiB3
-aGl0ZTsKfQoKLnJlZ2lvbnMgdGQubGluZS1ubyB7CiAgYm9yZGVyLXJpZ2h0OiBzb2xpZCAjMjgyYjJl
-IDJweDsKICBjb2xvcjogIzk5OTk5OTsKICBwYWRkaW5nLXJpZ2h0OiA0cHg7CiAgdGV4dC1hbGlnbjog
-cmlnaHQ7CiAgdmlzaWJpbGl0eTogdmlzaWJsZTsKICB3aWR0aDogNTBweDsKICBkaXNwbGF5OiBpbmxp
-bmUtYmxvY2s7Cn0KCi5yZWdpb25zIHRyLmhpZ2hsaWdodCB0ZC5saW5lLW5vIHsKICBib3JkZXItcmln
-aHQ6IHNvbGlkICNjY2MgMnB4Owp9CgoucmVnaW9uIHsKICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7CiAg
-cG9zaXRpb246IHJlbGF0aXZlOwogIHZpc2liaWxpdHk6IHZpc2libGU7CiAgei1pbmRleDogMjAwOwp9
-CgoucmVnaW9uLmFkZGVkLXJlZ2lvbiB7CiAgYmFja2dyb3VuZC1jb2xvcjogI2NjZmZjYzsKICBjb2xv
-cjogIzAwMzMwMDsKfQoKLnJlZ2lvbi5yZW1vdmVkLXJlZ2lvbiB7CiAgYmFja2dyb3VuZC1jb2xvcjog
-I2ZmNjY2NjsKICBjb2xvcjogIzAwMTEwMDsKfQoKLnJlZ2lvbi5pbmZvcm1hdGl2ZS1yZWdpb24gewog
-IGJhY2tncm91bmQtY29sb3I6ICM0MDQ1NDk7IC8qICMyODJiMmUsIGxpZ2h0ZW5lZCAxMCUgKi8KICBi
-b3JkZXItYm90dG9tOiBzb2xpZCByZ2JhKDI1NSwgMjU1LCAwLCAwLjcpIDFweDsKICBkaXNwbGF5OiBp
-bmxpbmUtYmxvY2s7CiAgaGVpZ2h0OiAxNHB4OyAKICBwb3NpdGlvbjogcmVsYXRpdmU7CiAgdG9wOiAx
-cHg7Cn0KCi50YXJnZXQgewogIGJhY2tncm91bmQtY29sb3I6ICM0NDQ7CiAgcG9zaXRpb246IHJlbGF0
-aXZlOwogIHZpc2liaWxpdHk6IHZpc2libGU7CiAgZm9udC13ZWlnaHQ6IDYwMDsKfQoKLmluZm8tcGFu
-ZWwgewogIGZsZXg6IDEgMjAwcHg7CiAgbWFyZ2luOiAwOwogIGhlaWdodDogMTAwJTsKICBkaXNwbGF5
-OiBmbGV4OwogIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47Cn0KCi5pbmZvLXBhbmVsIC5lZGl0LXBhbmVs
-IHsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjMjgyYjJlOwogIG92ZXJmbG93OiBhdXRvOwp9CgouaW5mby1w
-YW5lbCAucGFuZWwtY29udGVudCB7CiAgcGFkZGluZzogN3B4Owp9CgouaW5mby1wYW5lbCAucGFuZWwt
-Y29udGVudD4gOmZpcnN0LWNoaWxkIHsKICBtYXJnaW4tdG9wOiAwOwp9CgouaW5mby1wYW5lbCAubm93
-cmFwIHsKICB3aGl0ZS1zcGFjZTogbm93cmFwOwp9CgouaW5mby1wYW5lbCB1bCwKLmluZm8tcGFuZWwg
-b2wgewogIHBhZGRpbmctbGVmdDogMjBweDsKfQoKLmluZm8tcGFuZWwgbGkgewogIG1hcmdpbjogMCAw
-IDVweCAwOwp9CgouaW5mby1wYW5lbCBhIHsKICBjb2xvcjogIzMzY2NmZjsKfQoKLmluZm8tcGFuZWwg
-LmVkaXQtbGlzdCB7CiAgYmFja2dyb3VuZC1jb2xvcjogIzI4MmIyZTsKICBvdmVyZmxvdzogYXV0bzsK
-fQoKLmVkaXQtcGFuZWwgewogIG1hcmdpbi10b3A6IDZweDsKICBmbGV4OiAxIDEwMHB4Owp9CgouZWRp
-dC1saXN0IHsKICBmbGV4OiAyIDEwMHB4Owp9CgouZWRpdC1saXN0IC5lZGl0IHsKICBtYXJnaW46IDNw
-eCAwOwp9CgouZWRpdC1saXN0IC5lZGl0LWxpbmsgewogIGN1cnNvcjogcG9pbnRlcjsKfQoKLnBvcHVw
-LXBhbmUgewogIGRpc3BsYXk6IG5vbmU7CiAgcG9zaXRpb246IGZpeGVkOwogIHRvcDogMTUwcHg7CiAg
-bGVmdDogMTUwcHg7CiAgcmlnaHQ6IDE1MHB4OwogIGJvdHRvbTogMTUwcHg7CiAgYm9yZGVyOiAxcHgg
-c29saWQgYmxhY2s7CiAgYm9yZGVyLXRvcDogMnB4IHNvbGlkIGJsYWNrOwogIGJvcmRlci1yYWRpdXM6
-IDdweDsKICBib3gtc2hhZG93OiAwcHggMHB4IDIwcHggMnB4ICNiNGJmY2IyMjsKICB6LWluZGV4OiA0
-MDA7CiAgYmFja2dyb3VuZDogIzJiMzAzNjsKICBwYWRkaW5nOiAyMHB4Owp9CgoucG9wdXAtcGFuZSAu
-Y2xvc2UgewogIHBvc2l0aW9uOiBhYnNvbHV0ZTsKICByaWdodDogMTBweDsKICB0b3A6IDEwcHg7CiAg
-Y3Vyc29yOiBwb2ludGVyOwogIHRleHQtc2hhZG93OiAxcHggMXB4IDJweCAjODg4OwogIGJveC1zaGFk
-b3c6IDFweCAxcHggMnB4ICMxMTE7Cn0KCi5wb3B1cC1wYW5lIGgyIHsKICBwYWRkaW5nOiAyMXB4Owog
-IGhlaWdodDogMTAlOwogIG1hcmdpbjogMHB4OwogIGJveC1zaXppbmc6IGJvcmRlci1ib3g7Cn0KCi5w
-b3B1cC1wYW5lIHAgewogIGhlaWdodDogMTAlOwogIGJveC1zaXppbmc6IGJvcmRlci1ib3g7CiAgcGFk
-ZGluZzogMHB4IDIwcHg7Cn0KCi5wb3B1cC1wYW5lIHByZSB7CiAgYmFja2dyb3VuZDogIzI4MmIyZTsK
-ICBwYWRkaW5nOiAyMHB4OwogIGJvdHRvbTogMHB4OwogIG92ZXJmbG93OiBhdXRvIHNjcm9sbDsKICBo
-ZWlnaHQ6IDY1JTsKICBtYXJnaW46IDBweDsKICBib3gtc2l6aW5nOiBib3JkZXItYm94Owp9CgoucG9w
-dXAtcGFuZSAuYnV0dG9uLmJvdHRvbSB7CiAgbWFyZ2luOiAyMHB4IDBweDsKICBkaXNwbGF5OiBibG9j
-azsKICB0ZXh0LWFsaWduOiBjZW50ZXI7Cn0KCi5yZXJ1bm5pbmctcGFuZSB7CiAgZGlzcGxheTogbm9u
-ZTsKfQoKYm9keS5yZXJ1bm5pbmcgLnJlcnVubmluZy1wYW5lIHsKICBkaXNwbGF5OiBibG9jazsKICBw
-b3NpdGlvbjogZml4ZWQ7CiAgdG9wOiAwcHg7CiAgYm90dG9tOiAwcHg7CiAgbGVmdDogMHB4OwogIHJp
-Z2h0OiAwcHg7CiAgYmFja2dyb3VuZC1jb2xvcjogIzAwMDAwMEFBOyAvKiB0cmFuc2x1Y2VudCBibGFj
-ayAqLwogIHotaW5kZXg6IDQwMDsKfQoKLnJlcnVubmluZy1wYW5lIGgxIHsKICBwb3NpdGlvbjogYWJz
-b2x1dGU7CiAgdG9wOiA1MCU7CiAgbGVmdDogNTAlOwogIHRyYW5zZm9ybTogdHJhbnNsYXRlKC01MCUs
-IC01MCUpOwp9CgouZWRpdC1wYW5lbCAudHlwZS1kZXNjcmlwdGlvbiB7CiAgLyogRnJvbSBITEpTJ3Mg
-LmhsanMta2V5d29yZCwgLmhsanMtc2VsZWN0b3ItdGFnLCAuaGxqcy1kZWxldGlvbiAqLwogIGNvbG9y
-OiAjY2M3ODMyOwogIGZvbnQtZmFtaWx5OiBtb25vc3BhY2U7Cn0KCnVsLnRyYWNlIHsKICBmb250LXNp
-emU6IDEzcHg7CiAgbGlzdC1zdHlsZS10eXBlOiBub25lOwogIHBhZGRpbmctbGVmdDogMHB4Owp9Cgp1
-bC50cmFjZSBsaSB7CiAgY29sb3I6IHdoaXRlOwp9Cgp1bC50cmFjZSBsaSAuZnVuY3Rpb24gewogIC8q
-IEZyb20gSExKUydzIC5obGpzLXNlY3Rpb24sIC5obGpzLXRpdGxlLCAuaGxqcy10eXBlICovCiAgY29s
-b3I6ICNmZmM2NmQ7CiAgZm9udC1mYW1pbHk6IG1vbm9zcGFjZTsKICBmb250LXdlaWdodDogNjAwOwp9
-Cgp1bC50cmFjZSBsaSBwLmRyYXdlciB7CiAgbWFyZ2luOiAzcHggMHB4OwogIHBhZGRpbmc6IDBweCAw
-cHggMHB4IDE0cHg7Cn0KCnVsLnRyYWNlIGxpIHAuZHJhd2VyIGJ1dHRvbiB7CiAgbWFyZ2luLXJpZ2h0
-OiAzcHg7Cn0KCi5lbGV2YXRpb24tejQgewogIGJveC1zaGFkb3c6IDBweCAycHggNHB4IC0xcHggcmdi
-YSgwLCAwLCAwLCAwLjIpLAogICAgICAwcHggNHB4IDVweCAwcHggcmdiYSgwLCAwLCAwLCAwLjE0KSwK
-ICAgICAgMHB4IDFweCAxMHB4IDBweCByZ2JhKDAsIDAsIDAsIC4xMik7Cn0KCmEgewogIGNvbG9yOiAj
-Y2NjOwogIGZpbGw6ICNjY2M7CiAgdGV4dC1kZWNvcmF0aW9uOiBub25lOwp9CgphOmhvdmVyIHsKICBj
-b2xvcjogI2ZmZjsKICBmaWxsOiAjZmZmOwp9CgouYWRkLWhpbnQtbGluayB7CiAgZGlzcGxheTogaW5s
-aW5lLWJsb2NrOwogIG1hcmdpbjogM3B4Owp9CgovKiBDYXJlZnVsIGhlcmUuIGBhLmJ1dHRvbmAgaXMg
-cmVwZXRpdGl2ZSBidXQgcmVxdWlyZWQgdG8gZ2V0IGNvcnJlY3QKICogc3BlY2lmaWNpdHkgKi8KYnV0
-dG9uLCAuYnV0dG9uLCBhLmJ1dHRvbiB7CiAgYmFja2dyb3VuZC1jb2xvcjogIzMzY2NmZjsKICBib3Jk
-ZXI6IDJweCBzb2xpZCAjMzdhZWRjOwogIGJvcmRlci1yYWRpdXM6IDNweDsKICBwYWRkaW5nOiA2cHgg
-MTBweDsKICBmb250LXdlaWdodDogYm9sZDsKICBjb2xvcjogIzI4MjgyODsKfQoKYnV0dG9uOmhvdmVy
-LCAuYnV0dG9uOmhvdmVyIHsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjODBkZmZmOwogIGJvcmRlcjogMnB4
-IHNvbGlkICM1MmI4ZTA7CiAgY3Vyc29yOiBwb2ludGVyOwp9CgpidXR0b25bZGlzYWJsZWRdIHsKICBi
-YWNrZ3JvdW5kLWNvbG9yOiAjN2FhOGI4OwogIGNvbG9yOiAjNTA3MTc3OwogIGJvcmRlcjogMnB4IHNv
-bGlkICM1MDcxNzc7CiAgY3Vyc29yOiBub3QtYWxsb3dlZDsKfQoKLnBsYWNlaG9sZGVyIHsKICBjb2xv
-cjogIzc3NzsKICB0ZXh0LWFsaWduOiBjZW50ZXI7CiAgbWFyZ2luLXRvcDogM2VtICFpbXBvcnRhbnQ7
-Cn0KCi8qKgogKiBITEpTIE92ZXJyaWRlcwogKi8KLmhsanMgewogIC8qKgogICAqIFRoaXMgYWxsb3dz
-IHRoZSBwZXItbGluZSBoaWdobGlnaHRzIHRvIHNob3cuCiAgICovCiAgYmFja2dyb3VuZDogbm9uZTsK
-fQo=
+Ki8KCi8qCiAqIENvbG9ycyBtZW50aW9uZWQgaW4gdGhpcyBmaWxlLCBlLmcuICIkZGFyay10ZXh0LWNv
+bG9yIiBhcmUgZnJvbSBEYXJ0UGFkOgogKiBodHRwczovL2dpdGh1Yi5jb20vZGFydC1sYW5nL2RhcnQt
+cGFkL2Jsb2IvbWFzdGVyL2xpYi9zY3NzL2NvbG9ycy5zY3NzCiAqLwoKLyogVGV4dCBzZWxlY3Rpb24g
+Ki8KOjpzZWxlY3Rpb24gewogIGJhY2tncm91bmQ6ICM2ZThlYjE7IC8qICRkYXJrLXNlbGVjdGlvbi1j
+b2xvciAqLzsKfQoKLyogTWF0ZXJpYWwgaWNvbnMgY29uZmlndXJhdGlvbiAqLwpAZm9udC1mYWNlIHsK
+ICBmb250LWZhbWlseTogJ01hdGVyaWFsIEljb25zJzsKICBmb250LXN0eWxlOiBub3JtYWw7CiAgZm9u
+dC13ZWlnaHQ6IDQwMDsKICBzcmM6IGxvY2FsKCdNYXRlcmlhbCBJY29ucycpLAogIGxvY2FsKCdNYXRl
+cmlhbEljb25zLVJlZ3VsYXInKSwKICB1cmwoL01hdGVyaWFsSWNvbnNSZWd1bGFyLnR0ZikgZm9ybWF0
+KCd0cnVldHlwZScpOwp9CgovKgogKiBSZXF1aXJlZCBmb3IgTWF0ZXJpYWwgSWNvbnM6CiAqIGh0dHBz
+Oi8vZ29vZ2xlLmdpdGh1Yi5pby9tYXRlcmlhbC1kZXNpZ24taWNvbnMvCiAqLwoubWF0ZXJpYWwtaWNv
+bnMgewogIGZvbnQtZmFtaWx5OiAnTWF0ZXJpYWwgSWNvbnMnOwogIGZvbnQtd2VpZ2h0OiBub3JtYWw7
+CiAgZm9udC1zdHlsZTogbm9ybWFsOwogIGZvbnQtc2l6ZTogMjRweDsgIC8qIFByZWZlcnJlZCBpY29u
+IHNpemUgKi8KICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7CiAgbGluZS1oZWlnaHQ6IDE7CiAgdGV4dC10
+cmFuc2Zvcm06IG5vbmU7CiAgbGV0dGVyLXNwYWNpbmc6IG5vcm1hbDsKICB3b3JkLXdyYXA6IG5vcm1h
+bDsKICB3aGl0ZS1zcGFjZTogbm93cmFwOwogIGRpcmVjdGlvbjogbHRyOwoKICAvKiBTdXBwb3J0IGZv
+ciBhbGwgV2ViS2l0IGJyb3dzZXJzLiAqLwogIC13ZWJraXQtZm9udC1zbW9vdGhpbmc6IGFudGlhbGlh
+c2VkOwogIC8qIFN1cHBvcnQgZm9yIFNhZmFyaSBhbmQgQ2hyb21lLiAqLwogIHRleHQtcmVuZGVyaW5n
+OiBvcHRpbWl6ZUxlZ2liaWxpdHk7CgogIC8qIFN1cHBvcnQgZm9yIEZpcmVmb3guICovCiAgLW1vei1v
+c3gtZm9udC1zbW9vdGhpbmc6IGdyYXlzY2FsZTsKCiAgLyogU3VwcG9ydCBmb3IgSUUuICovCiAgZm9u
+dC1mZWF0dXJlLXNldHRpbmdzOiAnbGlnYSc7Cn0KCmJvZHkgewogIGJhY2tncm91bmQtY29sb3I6ICMx
+MjIwMmY7CiAgY29sb3I6ICNjY2M7CiAgZm9udC1mYW1pbHk6ICJSb2JvdG8iLCBzYW5zLXNlcmlmOwog
+IGZvbnQtc2l6ZTogMTRweDsKICBkaXNwbGF5OiBmbGV4OwogIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47
+CiAgcG9zaXRpb246IGFic29sdXRlOwogIHRvcDogMDsKICByaWdodDogMDsKICBib3R0b206IDA7CiAg
+bGVmdDogMDsKICBtYXJnaW46IDA7CiAgcGFkZGluZzogMDsKICBvdmVyZmxvdzogaGlkZGVuOwp9Cgou
+cHJvcG9zZWQgLmFmdGVyLWFwcGx5IHsKICBkaXNwbGF5OiBub25lOwp9CgouYXBwbGllZCAuYmVmb3Jl
+LWFwcGx5IHsKICBkaXNwbGF5OiBub25lOwp9CgouYXBwbGllZCAuYXBwbHktbWlncmF0aW9uOm5vdChb
+ZGlzYWJsZWRdKSwgLm5lZWRzLXJlcnVuIC5hcHBseS1taWdyYXRpb246bm90KFtkaXNhYmxlZF0pIHsK
+ICBkaXNwbGF5OiBub25lOwp9CgoucHJvcG9zZWQ6bm90KC5uZWVkcy1yZXJ1bikgLmFwcGx5LW1pZ3Jh
+dGlvbltkaXNhYmxlZF0gewogIGRpc3BsYXk6IG5vbmU7Cn0KCmhlYWRlciB7CiAgYmFja2dyb3VuZC1j
+b2xvcjogIzFjMjgzNDsKICBoZWlnaHQ6IDQ4cHg7CiAgcGFkZGluZy1sZWZ0OiAyNHB4OwogIGFsaWdu
+LWl0ZW1zOiBjZW50ZXI7CiAgei1pbmRleDogNDsKfQoKaGVhZGVyIGgxLApoZWFkZXIgaDIsCmhlYWRl
+ciBoMyB7CiAgZGlzcGxheTogaW5saW5lLWJsb2NrOwogIGZvbnQtZmFtaWx5OiAiR29vZ2xlIFNhbnMi
+LCJSb2JvdG8iLHNhbnMtc2VyaWY7CiAgZm9udC13ZWlnaHQ6IDQwMDsKICBtYXJnaW4tcmlnaHQ6IDI0
+cHg7Cn0KCmgxIHsKICBmb250LXNpemU6IDEuNWVtOwp9CgpoZWFkZXIgaDIgewogIGZvbnQtc2l6ZTog
+MS4yZW07CgogIC8qIFNoaWZ0IHRleHQgdXAgKi8KICBwb3NpdGlvbjogcmVsYXRpdmU7CiAgdG9wOiAt
+MnB4Owp9CgpoZWFkZXIgaDMgewogIC8qIFNoaWZ0IHRleHQgdXAgKi8KICBwb3NpdGlvbjogcmVsYXRp
+dmU7CiAgdG9wOiAtMnB4Owp9CgoKaGVhZGVyIC5hY3Rpb24tYnV0dG9uLCBoZWFkZXIgYSB7CiAgcmln
+aHQ6IDBweDsKICBmbG9hdDogcmlnaHQ7CiAgbWFyZ2luOiAxMHB4Owp9CgpoZWFkZXIgaW1nLmxvZ28g
+ewogIGhlaWdodDogMjRweDsKICB3aWR0aDogMjRweDsKICBtYXJnaW4tcmlnaHQ6IDhweDsKICBwb3Np
+dGlvbjogcmVsYXRpdmU7CiAgdG9wOiA0cHg7Cn0KCmZvb3RlciAucmVwb3J0LXByb2JsZW0gewogIHJp
+Z2h0OiAwcHg7CiAgbWFyZ2luOiA0cHggOHB4Owp9CgoucmVydW4tbWlncmF0aW9uIC5yZXF1aXJlZCB7
+CiAgZGlzcGxheTogbm9uZTsKfQoKLm5lZWRzLXJlcnVuIC5yZXJ1bi1taWdyYXRpb24gLnJlcXVpcmVk
+IHsKICBkaXNwbGF5OiBpbml0aWFsOwp9CgoubmVlZHMtcmVydW4gLnJlcnVuLW1pZ3JhdGlvbiAub3B0
+aW9uYWwgewogIGRpc3BsYXk6bm9uZTsKfQoKZm9vdGVyIHsKICBjb2xvcjogI2NjYzsKICBiYWNrZ3Jv
+dW5kLWNvbG9yOiAjMjczMjNhOwogIGRpc3BsYXk6IGZsZXg7CiAgZmxleC1kaXJlY3Rpb246IHJvdzsK
+ICBhbGlnbi1pdGVtczogY2VudGVyOwogIHBhZGRpbmc6IDhweCAwIDhweCAyNHB4Owp9Cgpmb290ZXIg
+LndpZGUgewogIGZsZXg6IDE7Cn0KCmZvb3RlciAuc2RrLXZlcnNpb24gewogIG1hcmdpbi1yaWdodDog
+MzJweDsKfQoKLmhvcml6b250YWwgewogIGRpc3BsYXk6IGZsZXg7Cn0KCi5wYW5lbHMgewogIGJhY2tn
+cm91bmQtY29sb3I6ICMxMjFhMjU7CiAgZmxleDogMTsKICBvdmVyZmxvdzogaGlkZGVuOwp9CgoucGFu
+ZWwtaGVhZGluZyB7CiAgY29sb3I6ICM2NzY3Njc7CiAgbWFyZ2luOiA4cHg7Cn0KCi5uYXYtbGluaywK
+LnJlZ2lvbiB7CiAgY3Vyc29yOiBwb2ludGVyOwp9CgoubmF2LXBhbmVsIHsKICBiYWNrZ3JvdW5kLWNv
+bG9yOiAjMTIyMDJmOwogIGZsZXg6IDEgMjAwcHg7CiAgbWFyZ2luOiAwOwogIG92ZXJmbG93OiBzY3Jv
+bGw7CiAgdXNlci1zZWxlY3Q6IG5vbmU7Cn0KCi5uYXYtaW5uZXIgewogIHBhZGRpbmc6IDAgMCA3cHgg
+N3B4Owp9CgouZml4ZWQgewogIHBvc2l0aW9uOiBmaXhlZDsKICB0b3A6IDA7Cn0KCi5yb290IHsKICBt
+YXJnaW46IDA7CiAgZGlzcGxheTogbm9uZTsKfQoKLm5hdi10cmVlID4gdWwgewogIHBhZGRpbmctbGVm
+dDogNnB4Owp9CgoubmF2LXRyZWUgLm1hdGVyaWFsLWljb25zIHsKICBmb250LXNpemU6IDIwcHg7CiAg
+cG9zaXRpb246IHJlbGF0aXZlOwogIHRvcDogNXB4OwogIG1hcmdpbi1yaWdodDogOHB4OwogIGNvbG9y
+OiAjNjc2NzY3Owp9CgoubmF2LWlubmVyIHVsIHsKICBwYWRkaW5nLWxlZnQ6IDEycHg7CiAgbWFyZ2lu
+OiAwOwp9CgoubmF2LWlubmVyIGxpIHsKICBsaXN0LXN0eWxlLXR5cGU6IG5vbmU7Cn0KCi5uYXYtaW5u
+ZXIgbGk6bm90KC5kaXIpIHsKICBtYXJnaW4tbGVmdDogMjBweDsKICBtYXJnaW4tYm90dG9tOiAzcHg7
+Cn0KCi5uYXYtaW5uZXIgbGkuZGlyIC5hcnJvdyB7CiAgY3Vyc29yOiBwb2ludGVyOwogIGRpc3BsYXk6
+IGlubGluZS1ibG9jazsKICBmb250LXNpemU6IDEwcHg7CiAgbWFyZ2luLXJpZ2h0OiA0cHg7CiAgdHJh
+bnNpdGlvbjogdHJhbnNmb3JtIDAuNXMgZWFzZS1vdXQ7Cn0KCi5uYXYtaW5uZXIgbGkuZGlyIC5hcnJv
+dy5jb2xsYXBzZWQgewogIHRyYW5zZm9ybTogcm90YXRlKC05MGRlZyk7Cn0KCi5uYXYtaW5uZXIgdWwg
+ewogIG1heC1oZWlnaHQ6IDIwMDBweDsKICB0cmFuc2l0aW9uOiBtYXgtaGVpZ2h0IDAuNXMgZWFzZS1v
+dXQ7Cn0KCi5uYXYtaW5uZXIgdWwuY29sbGFwc2VkIHsKICBtYXgtaGVpZ2h0OiAwICFpbXBvcnRhbnQ7
+CiAgb3ZlcmZsb3c6IGhpZGRlbjsKfQoKLm5hdi1pbm5lciAuc2VsZWN0ZWQtZmlsZSB7CiAgY29sb3I6
+IHdoaXRlOwogIGN1cnNvcjogaW5oZXJpdDsKICBmb250LXdlaWdodDogNjAwOwogIHRleHQtZGVjb3Jh
+dGlvbjogbm9uZTsKfQoKLmVkaXQtY291bnQgewogIGJhY2tncm91bmQtY29sb3I6ICM2NzY3Njc7CiAg
+Ym9yZGVyLXJhZGl1czogMTBweDsKICBjb2xvcjogI2ZmZjsKICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7
+CiAgZm9udC1zaXplOiAxMXB4OwogIGZvbnQtd2VpZ2h0OiA2MDA7CiAgbWFyZ2luLWxlZnQ6IDVweDsK
+ICBtaW4td2lkdGg6IDI1cHg7CiAgcGFkZGluZzogNHB4IDAgMnB4IDA7CiAgdGV4dC1hbGlnbjogY2Vu
+dGVyOwogIGxpbmUtaGVpZ2h0OiAxZW07Cn0KCi5jb250ZW50IHsKICBmbGV4OiA0IDMwMHB4OwogIGJh
+Y2tncm91bmQ6ICMxMjIwMmY7CiAgZm9udC1mYW1pbHk6ICJSb2JvdG8gTW9ubyIsIG1vbm9zcGFjZTsK
+ICBtYXJnaW46IDAgNnB4OwogIHBvc2l0aW9uOiByZWxhdGl2ZTsKICB3aGl0ZS1zcGFjZTogcHJlOwog
+IG92ZXJmbG93OiBzY3JvbGw7Cn0KCi5jb2RlIHsKICBwYWRkaW5nOiAwLjVlbTsKICBwb3NpdGlvbjog
+YWJzb2x1dGU7CiAgbGVmdDogMDsKICB0b3A6IDA7CiAgbWFyZ2luLWxlZnQ6IDU2cHg7Cn0KCi5jb2Rl
+IC53ZWxjb21lIHsKICBmb250LWZhbWlseTogIkdvb2dsZSBTYW5zIiwiUm9ib3RvIixzYW5zLXNlcmlm
+OwogIGZvbnQtc2l6ZTogMThweDsKICBtYXJnaW4tcmlnaHQ6IDYycHg7CiAgY29sb3I6ICM3Nzc7Cn0K
+Ci5jb2RlIC5uYXYtbGluayB7CiAgY29sb3I6ICMxNmFkY2E7CiAgdGV4dC1kZWNvcmF0aW9uLWxpbmU6
+IG5vbmU7Cn0KCi5jb2RlIC5uYXYtbGluazp2aXNpdGVkIHsKICBjb2xvcjogIzEzOWJiNTsgLyogIzE2
+YWRjYSBkYXJrZW5lZCAxMCUgKi8KICB0ZXh0LWRlY29yYXRpb24tbGluZTogbm9uZTsKfQoKLmNvZGUg
+Lm5hdi1saW5rOmhvdmVyIHsKICB0ZXh0LWRlY29yYXRpb24tbGluZTogdW5kZXJsaW5lOwogIGZvbnQt
+d2VpZ2h0OiA2MDA7Cn0KCi5yZWdpb25zIHsKICBwYWRkaW5nOiAwLjVlbTsKICBwb3NpdGlvbjogYWJz
+b2x1dGU7CiAgbGVmdDogMDsKICB0b3A6IDA7Cn0KCi5yZWdpb25zIHRhYmxlIHsKICBib3JkZXItc3Bh
+Y2luZzogMDsKICBmb250LXNpemU6IGluaGVyaXQ7Cn0KCi5yZWdpb25zIHRkIHsKICBib3JkZXI6IG5v
+bmU7CiAgLyogVGhlIGNvbnRlbnQgb2YgdGhlIHJlZ2lvbnMgaXMgbm90IHZpc2libGU7IHRoZSB1c2Vy
+IGluc3RlYWQgd2lsbCBzZWUgdGhlCiAgICogaGlnaGxpZ2h0ZWQgY29weSBvZiB0aGUgY29udGVudC4g
+Ki8KICBjb2xvcjogcmdiYSgyNTUsIDI1NSwgMjU1LCAwKTsKICBwYWRkaW5nOiAwOwogIHdoaXRlLXNw
+YWNlOiBwcmU7Cn0KCi5yZWdpb25zIHRkOmVtcHR5OmFmdGVyIHsKICBjb250ZW50OiAiXDAwYTAiOwp9
+CgoucmVnaW9ucyB0ci5oaWdobGlnaHQgdGQ6bGFzdC1jaGlsZCB7CiAgYmFja2dyb3VuZC1jb2xvcjog
+IzQ0NDQ0NDsKICBjb2xvcjogd2hpdGU7Cn0KCi5yZWdpb25zIHRkLmxpbmUtbm8gewogIGJvcmRlci1y
+aWdodDogc29saWQgIzEyMjAyZiAycHg7CiAgY29sb3I6ICM5OTk5OTk7CiAgcGFkZGluZy1yaWdodDog
+NHB4OwogIHRleHQtYWxpZ246IHJpZ2h0OwogIHZpc2liaWxpdHk6IHZpc2libGU7CiAgd2lkdGg6IDUw
+cHg7CiAgZGlzcGxheTogaW5saW5lLWJsb2NrOwp9CgoucmVnaW9ucyB0ci5oaWdobGlnaHQgdGQubGlu
+ZS1ubyB7CiAgYm9yZGVyLXJpZ2h0OiBzb2xpZCAjY2NjIDJweDsKfQoKLnJlZ2lvbiB7CiAgZGlzcGxh
+eTogaW5saW5lLWJsb2NrOwogIHBvc2l0aW9uOiByZWxhdGl2ZTsKICB2aXNpYmlsaXR5OiB2aXNpYmxl
+OwogIHotaW5kZXg6IDIwMDsKfQoKLnJlZ2lvbi5hZGRlZC1yZWdpb24gewogIGJhY2tncm91bmQtY29s
+b3I6ICMyNjM5NTI7IC8qICRkYXJrLXNlbGVjdGlvbi1jb2xvciAqLwogIGNvbG9yOiAjYzBjMmM1OyAv
+KiAkZGFyay1lZGl0b3ItdGV4dCAqLwp9CgoucmVnaW9uLnJlbW92ZWQtcmVnaW9uIHsKICBiYWNrZ3Jv
+dW5kLWNvbG9yOiAjRkE1NTdkOyAvKiAkZGFyay1waW5rICovCiAgY29sb3I6ICNmZmY7Cn0KCi5yZWdp
+b24uaW5mb3JtYXRpdmUtcmVnaW9uIHsKICBiYWNrZ3JvdW5kLWNvbG9yOiAjMTc4YWZkOyAvKiAkZGFy
+ay1zZWxlY3Rpb24tY29sb3IgKi8KICBjb2xvcjogI2ZmZjsKICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7
+CiAgaGVpZ2h0OiAxOHB4OwogIHBvc2l0aW9uOiByZWxhdGl2ZTsKICB0b3A6IDNweDsKfQoKLnRhcmdl
+dCB7CiAgYmFja2dyb3VuZC1jb2xvcjogIzQ0NDsKICBwb3NpdGlvbjogcmVsYXRpdmU7CiAgdmlzaWJp
+bGl0eTogdmlzaWJsZTsKICBmb250LXdlaWdodDogNjAwOwp9CgouaW5mby1wYW5lbCB7CiAgZmxleDog
+MSAyMDBweDsKICBtYXJnaW46IDA7CiAgaGVpZ2h0OiAxMDAlOwogIGRpc3BsYXk6IGZsZXg7CiAgZmxl
+eC1kaXJlY3Rpb246IGNvbHVtbjsKfQoKLmluZm8tcGFuZWwgLmVkaXQtcGFuZWwgewogIGJhY2tncm91
+bmQtY29sb3I6ICMxMjIwMmY7CiAgb3ZlcmZsb3c6IGF1dG87Cn0KCi5pbmZvLXBhbmVsIC5wYW5lbC1j
+b250ZW50IHsKICBwYWRkaW5nOiA3cHg7Cn0KCi5pbmZvLXBhbmVsIC5wYW5lbC1jb250ZW50PiA6Zmly
+c3QtY2hpbGQgewogIG1hcmdpbi10b3A6IDA7Cn0KCi5pbmZvLXBhbmVsIC5ub3dyYXAgewogIHdoaXRl
+LXNwYWNlOiBub3dyYXA7Cn0KCi5pbmZvLXBhbmVsIHVsLAouaW5mby1wYW5lbCBvbCB7CiAgcGFkZGlu
+Zy1sZWZ0OiAyMHB4Owp9CgouaW5mby1wYW5lbCBsaSB7CiAgbWFyZ2luOiAwIDAgNXB4IDA7Cn0KCi5p
+bmZvLXBhbmVsIGEgewogIGNvbG9yOiAjMTM5YmI1Owp9CgouaW5mby1wYW5lbCBhOmhvdmVyIHsKICBj
+b2xvcjogIzFlYzdlNzsgLyogIzEzOWJiNSBsaWdodGVuZWQgMjAlICovCn0KCi5pbmZvLXBhbmVsIC5l
+ZGl0LWxpc3QgewogIGJhY2tncm91bmQtY29sb3I6ICMxMjIwMmY7CiAgb3ZlcmZsb3c6IGF1dG87Cn0K
+Ci5lZGl0LXBhbmVsIHsKICBtYXJnaW4tdG9wOiA2cHg7CiAgZmxleDogMSAxMDBweDsKfQoKLmVkaXQt
+bGlzdCB7CiAgZmxleDogMiAxMDBweDsKfQoKLmVkaXQtbGlzdCAuZWRpdCB7CiAgbWFyZ2luOiAzcHgg
+MDsKfQoKLmVkaXQtbGlzdCAuZWRpdC1saW5rIHsKICBjdXJzb3I6IHBvaW50ZXI7Cn0KCi5wb3B1cC1w
+YW5lIHsKICBkaXNwbGF5OiBub25lOwogIHBvc2l0aW9uOiBmaXhlZDsKICB0b3A6IDE1MHB4OwogIGxl
+ZnQ6IDE1MHB4OwogIHJpZ2h0OiAxNTBweDsKICBib3R0b206IDE1MHB4OwogIGJvcmRlcjogMXB4IHNv
+bGlkIGJsYWNrOwogIGJvcmRlci10b3A6IDJweCBzb2xpZCBibGFjazsKICBib3JkZXItcmFkaXVzOiA3
+cHg7CiAgYm94LXNoYWRvdzogMHB4IDBweCAyMHB4IDJweCAjYjRiZmNiMjI7CiAgei1pbmRleDogNDAw
+OwogIGJhY2tncm91bmQ6ICMyYjMwMzY7CiAgcGFkZGluZzogMjBweDsKfQoKLnBvcHVwLXBhbmUgLmNs
+b3NlIHsKICBwb3NpdGlvbjogYWJzb2x1dGU7CiAgcmlnaHQ6IDEwcHg7CiAgdG9wOiAxMHB4OwogIGN1
+cnNvcjogcG9pbnRlcjsKICB0ZXh0LXNoYWRvdzogMXB4IDFweCAycHggIzg4ODsKICBib3gtc2hhZG93
+OiAxcHggMXB4IDJweCAjMTExOwp9CgoucG9wdXAtcGFuZSBoMiB7CiAgcGFkZGluZzogMjFweDsKICBo
+ZWlnaHQ6IDEwJTsKICBtYXJnaW46IDBweDsKICBib3gtc2l6aW5nOiBib3JkZXItYm94Owp9CgoucG9w
+dXAtcGFuZSBwIHsKICBoZWlnaHQ6IDEwJTsKICBib3gtc2l6aW5nOiBib3JkZXItYm94OwogIHBhZGRp
+bmc6IDBweCAyMHB4Owp9CgoucG9wdXAtcGFuZSBwcmUgewogIGJhY2tncm91bmQ6ICMxMjIwMmY7CiAg
+cGFkZGluZzogMjBweDsKICBib3R0b206IDBweDsKICBvdmVyZmxvdzogYXV0byBzY3JvbGw7CiAgaGVp
+Z2h0OiA2NSU7CiAgbWFyZ2luOiAwcHg7CiAgYm94LXNpemluZzogYm9yZGVyLWJveDsKfQoKLnBvcHVw
+LXBhbmUgLmJ1dHRvbi5ib3R0b20gewogIG1hcmdpbjogMjBweCAwcHg7CiAgZGlzcGxheTogYmxvY2s7
+CiAgdGV4dC1hbGlnbjogY2VudGVyOwp9CgoucmVydW5uaW5nLXBhbmUgewogIGRpc3BsYXk6IG5vbmU7
+Cn0KCmJvZHkucmVydW5uaW5nIC5yZXJ1bm5pbmctcGFuZSB7CiAgZGlzcGxheTogYmxvY2s7CiAgcG9z
+aXRpb246IGZpeGVkOwogIHRvcDogMHB4OwogIGJvdHRvbTogMHB4OwogIGxlZnQ6IDBweDsKICByaWdo
+dDogMHB4OwogIGJhY2tncm91bmQtY29sb3I6ICMwMDAwMDBBQTsgLyogdHJhbnNsdWNlbnQgYmxhY2sg
+Ki8KICB6LWluZGV4OiA0MDA7Cn0KCi5yZXJ1bm5pbmctcGFuZSBoMSB7CiAgcG9zaXRpb246IGFic29s
+dXRlOwogIHRvcDogNTAlOwogIGxlZnQ6IDUwJTsKICB0cmFuc2Zvcm06IHRyYW5zbGF0ZSgtNTAlLCAt
+NTAlKTsKfQoKLmVkaXQtcGFuZWwgLnR5cGUtZGVzY3JpcHRpb24gewogIC8qIEZyb20gRGFydFBhZCAk
+ZGFyay1vcmFuZ2UgKi8KICBjb2xvcjogI2ZmOTE2ZTsKICBmb250LWZhbWlseTogbW9ub3NwYWNlOwp9
+Cgp1bC50cmFjZSB7CiAgZm9udC1zaXplOiAxM3B4OwogIGxpc3Qtc3R5bGUtdHlwZTogbm9uZTsKICBw
+YWRkaW5nLWxlZnQ6IDBweDsKfQoKdWwudHJhY2UgbGkgewogIGNvbG9yOiB3aGl0ZTsKfQoKdWwudHJh
+Y2UgbGkgLmZ1bmN0aW9uIHsKICAvKiBmcm9tIC5obGpzLXZhcmlhYmxlICovCiAgY29sb3I6ICMxNmFk
+Y2E7CiAgZm9udC1mYW1pbHk6IG1vbm9zcGFjZTsKICBmb250LXdlaWdodDogNjAwOwp9Cgp1bC50cmFj
+ZSBsaSBwLmRyYXdlciB7CiAgbWFyZ2luOiAzcHggMHB4OwogIHBhZGRpbmc6IDBweCAwcHggMHB4IDE0
+cHg7Cn0KCnVsLnRyYWNlIGxpIHAuZHJhd2VyIGJ1dHRvbiB7CiAgbWFyZ2luLXJpZ2h0OiAzcHg7Cn0K
+Ci5lbGV2YXRpb24tejQgewogIGJveC1zaGFkb3c6IDBweCAycHggNHB4IC0xcHggcmdiYSgwLCAwLCAw
+LCAwLjIpLAogICAgICAwcHggNHB4IDVweCAwcHggcmdiYSgwLCAwLCAwLCAwLjE0KSwKICAgICAgMHB4
+IDFweCAxMHB4IDBweCByZ2JhKDAsIDAsIDAsIC4xMik7Cn0KCmEgewogIGNvbG9yOiAjY2NjOwogIGZp
+bGw6ICNjY2M7CiAgdGV4dC1kZWNvcmF0aW9uOiBub25lOwp9CgphOmhvdmVyIHsKICBjb2xvcjogI2Ri
+ZGJkYjsgLyogI2NjYyBsaWdodGVudGVkIDMwJSovCiAgZmlsbDogI2ZmZjsKfQoKLmFkZC1oaW50LWxp
+bmsgewogIGRpc3BsYXk6IGlubGluZS1ibG9jazsKICBtYXJnaW46IDNweDsKfQoKLmFkZC1oaW50LWxp
+bms6aG92ZXIgewogIGNvbG9yOiAjZmZmOwp9CgpoZWFkZXIgYnV0dG9uIHsKICB0ZXh0LXRyYW5zZm9y
+bTogdXBwZXJjYXNlOwp9CgpoZWFkZXIgYSB7CiAgbWFyZ2luOiAwOwp9CgovKiBDYXJlZnVsIGhlcmUu
+IGBhLmJ1dHRvbmAgaXMgcmVwZXRpdGl2ZSBidXQgcmVxdWlyZWQgdG8gZ2V0IGNvcnJlY3QKICogc3Bl
+Y2lmaWNpdHkgKi8KYnV0dG9uLCAuYnV0dG9uLCBhLmJ1dHRvbiB7CiAgYmFja2dyb3VuZC1jb2xvcjog
+cmdiYSgyMiwgMTM4LCAyNTMsIDAuMTUpOwogIGJvcmRlcjogbm9uZTsKICBib3JkZXItcmFkaXVzOiAz
+cHg7CiAgcGFkZGluZzogM3B4IDEwcHg7CiAgZm9udC13ZWlnaHQ6IDUwMDsKICBmb250LWZvbnQ6IFJv
+Ym90bywgc2Fucy1zZXJpZjsKICBjb2xvcjogI2ZmZjsKfQoKYnV0dG9uOmhvdmVyLCAuYnV0dG9uOmhv
+dmVyIHsKICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDIyLCAxMzgsIDI1MywgMC4yOSk7CiAgY3Vyc29y
+OiBwb2ludGVyOwp9CgpidXR0b25bZGlzYWJsZWRdIHsKICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDI1
+NSwyNTUsMjU1LC4xMik7CiAgY29sb3I6IHJnYmEoMjU1LDI1NSwyNTUsLjM3KTsKICBjdXJzb3I6IG5v
+dC1hbGxvd2VkOwp9CgovKiBDaGFuZ2UgZWRpdCBwYW5lbCBidXR0b24gY29sb3JzICovCi5lZGl0LXBh
+bmVsIC5idXR0b24sIC5lZGl0LXBhbmVsIGJ1dHRvbiB7CiAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSg2
+MywgMTA0LCAxNDgsIDAuNik7CiAgY29sb3I6IHdoaXRlOwp9Ci5lZGl0LXBhbmVsIC5idXR0b246aG92
+ZXIsIC5lZGl0LXBhbmVsIGJ1dHRvbjpob3ZlciB7CiAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSgxMDEs
+IDE1MywgMjA4LCAwLjYpOwogIGNvbG9yOiB3aGl0ZTsKfQoKLyoKICogQWRqdXN0bWVudHMgdG8gYWxp
+Z24gbWF0ZXJpYWwgaWNvbnMgaW4gdGhlIHRvb2xiYXIgYnV0dG9ucy4KKi8KLmFjdGlvbi1idXR0b24g
+PiBzcGFuIHsKICBwb3NpdGlvbjpyZWxhdGl2ZTsKICB0b3A6IC0zcHg7Cn0KCi5hY3Rpb24tYnV0dG9u
+IC5tYXRlcmlhbC1pY29ucyB7CiAgdG9wOiA0cHg7Cn0KCi8qIERvbid0IHNoaWZ0IHRoZSBpY29uIHdo
+ZW4gaXQncyBhIGRpcmVjdCBjaGlsZCBvZiB0aGUgYnV0dG9uICovCi5hY3Rpb24tYnV0dG9uID4gLm1h
+dGVyaWFsLWljb25zIHsKICB0b3A6IDFweDsKfQoKLyogU2hpZnQgdGhlIHRleHQgdG8gY2VudGVyIHdp
+dGggdGhlIGljb24uICovCi5hY3Rpb24tYnV0dG9uID4gc3Bhbi5sYWJlbCB7CiAgcG9zaXRpb246cmVs
+YXRpdmU7CiAgdG9wOiAtNHB4Owp9CgouYWN0aW9uLWJ1dHRvbiAubWF0ZXJpYWwtaWNvbnMgewogIGZv
+bnQtc2l6ZTogMjBweDsKICBwb3NpdGlvbjogcmVsYXRpdmU7Cn0KCi5wbGFjZWhvbGRlciB7CiAgY29s
+b3I6ICM3Nzc7CiAgdGV4dC1hbGlnbjogY2VudGVyOwogIG1hcmdpbi10b3A6IDNlbSAhaW1wb3J0YW50
+Owp9CgovKioKICogSExKUyBPdmVycmlkZXMKICovCi5obGpzIHsKICBiYWNrZ3JvdW5kLWNvbG9yOiAj
+MTIyMDJmOyAvKiAkZGFyay1jb2RlLWJhY2tncm91bmQtY29sb3IgKi8KICBjb2xvcjogI2MwYzJjNTsg
+LyogJGRhcmstZWRpdG9yLXRleHQgKi8KICBkaXNwbGF5OiBibG9jazsKICBvdmVyZmxvdy14OiBhdXRv
+OwogIHBhZGRpbmc6IDAuNWVtOwogIC8qKgogICAqIFRoaXMgYWxsb3dzIHRoZSBwZXItbGluZSBoaWdo
+bGlnaHRzIHRvIHNob3cuCiAgICovCiAgYmFja2dyb3VuZDogbm9uZTsKfQoKLmhsanMta2V5d29yZCwK
+LmhsanMtc2VsZWN0b3ItdGFnLAouaGxqcy1kZWxldGlvbiB7CiAgY29sb3I6ICM1MWM2ODY7IC8qIGNt
+LWtleXdvcmQgKi8KfQoKLmhsanMtbnVtYmVyIHsKICBjb2xvcjogIzYyNzk3ODsgLyogY20tbnVtYmVy
+ICovCn0KCi5obGpzLWNvbW1lbnQgewogIGNvbG9yOiAjOTE5OGI0OyAvKiBjbS1jb21tZW50ICovCn0K
+Ci5obGpzLWxpdGVyYWwgewogIGNvbG9yOiAjZWU4NjY2OyAvKiBjbS1hdG9tICovCn0KCi5obGpzLXN0
+cmluZyB7CiAgY29sb3I6ICNlNTUwNzQ7IC8qIGNtLXN0cmluZyAqLwp9CgouaGxqcy12YXJpYWJsZSB7
+CiAgY29sb3I6ICMxNmFkY2E7IC8qIGNtLXZhcmlhYmxlICovCn0KCi5obGpzLWxpbmsgewogIGNvbG9y
+OiAjZTU1MDc0OyAvKiBjbS1zdHJpbmcgKi8KfQouaGxqcy1zZWN0aW9uLAouaGxqcy10eXBlLAouaGxq
+cy1idWlsdF9pbiwKLmhsanMtdGl0bGUgewogIGNvbG9yOiAjZWU4NjY2OyAvKiBjbS12YXJpYWJsZS0y
+ICovCn0KCi5obGpzLWFkZGl0aW9uIHsKICBjb2xvcjogIzI2Mzk1MjsgLyogJGRhcmstc2VsZWN0aW9u
+LWNvbG9yICovCn0KCi5obGpzLW1ldGEgewogIGNvbG9yOiAjNjI3OTc4Owp9Cg==
 ''';
 
 String _migration_js;
-// migration_dart md5 is '7ab04e2be35dbf566710573204ca4c44'
+// migration_dart md5 is '8e9c1ed6d8e48865407a0185e2609d4c'
 String _migration_js_base64 = '''
 KGZ1bmN0aW9uIGRhcnRQcm9ncmFtKCl7ZnVuY3Rpb24gY29weVByb3BlcnRpZXMoYSxiKXt2YXIgdD1P
 YmplY3Qua2V5cyhhKQpmb3IodmFyIHM9MDtzPHQubGVuZ3RoO3MrKyl7dmFyIHI9dFtzXQpiW3JdPWFb
@@ -872,1188 +7761,1221 @@
 czpzZXRPclVwZGF0ZUxlYWZUYWdzfX0oKQpmdW5jdGlvbiBpbml0aWFsaXplRGVmZXJyZWRIdW5rKGEp
 e3g9di50eXBlcy5sZW5ndGgKYShodW5rSGVscGVycyx2LHcsJCl9ZnVuY3Rpb24gZ2V0R2xvYmFsRnJv
 bU5hbWUoYSl7Zm9yKHZhciB0PTA7dDx3Lmxlbmd0aDt0Kyspe2lmKHdbdF09PUMpY29udGludWUKaWYo
-d1t0XVthXSlyZXR1cm4gd1t0XVthXX19dmFyIEM9e30sSD17Rks6ZnVuY3Rpb24gRksoKXt9LApvbzpm
-dW5jdGlvbihhKXt2YXIgdCxzPWFeNDgKaWYoczw9OSlyZXR1cm4gcwp0PWF8MzIKaWYoOTc8PXQmJnQ8
-PTEwMilyZXR1cm4gdC04NwpyZXR1cm4tMX0sCnFDOmZ1bmN0aW9uKGEsYixjLGQpe1AuazEoYiwic3Rh
-cnQiKQppZihjIT1udWxsKXtQLmsxKGMsImVuZCIpCmlmKGI+YylILnZoKFAuVEUoYiwwLGMsInN0YXJ0
-IixudWxsKSl9cmV0dXJuIG5ldyBILm5IKGEsYixjLGQuQygibkg8MD4iKSl9LApLMTpmdW5jdGlvbihh
-LGIsYyxkKXtpZih1Lmd3LmIoYSkpcmV0dXJuIG5ldyBILnh5KGEsYixjLkMoIkA8MD4iKS5LcShkKS5D
-KCJ4eTwxLDI+IikpCnJldHVybiBuZXcgSC5pMShhLGIsYy5DKCJAPDA+IikuS3EoZCkuQygiaTE8MSwy
-PiIpKX0sCldwOmZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBQLmxqKCJObyBlbGVtZW50Iil9LApkVTpmdW5j
-dGlvbigpe3JldHVybiBuZXcgUC5saigiVG9vIG1hbnkgZWxlbWVudHMiKX0sCmFyOmZ1bmN0aW9uKCl7
-cmV0dXJuIG5ldyBQLmxqKCJUb28gZmV3IGVsZW1lbnRzIil9LApxajpmdW5jdGlvbiBxaihhKXt0aGlz
-LmE9YX0sCmJROmZ1bmN0aW9uIGJRKCl7fSwKYUw6ZnVuY3Rpb24gYUwoKXt9LApuSDpmdW5jdGlvbiBu
-SChhLGIsYyxkKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8uJHRpPWR9LAphNzpmdW5jdGlv
-biBhNyhhLGIsYyl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9MApfLmQ9bnVsbApfLiR0aT1jfSwK
-aTE6ZnVuY3Rpb24gaTEoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuJHRpPWN9LAp4eTpmdW5j
-dGlvbiB4eShhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy4kdGk9Y30sCk1IOmZ1bmN0aW9uIE1I
-KGEsYixjKXt2YXIgXz10aGlzCl8uYT1udWxsCl8uYj1hCl8uYz1iCl8uJHRpPWN9LApsSjpmdW5jdGlv
-biBsSihhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy4kdGk9Y30sClU1OmZ1bmN0aW9uIFU1KGEs
-YixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLiR0aT1jfSwKdkc6ZnVuY3Rpb24gdkcoYSxiLGMpe3Ro
-aXMuYT1hCnRoaXMuYj1iCnRoaXMuJHRpPWN9LApTVTpmdW5jdGlvbiBTVSgpe30sClJlOmZ1bmN0aW9u
-IFJlKCl7fSwKdzI6ZnVuY3Rpb24gdzIoKXt9LAp3djpmdW5jdGlvbiB3dihhKXt0aGlzLmE9YX0sCmRj
-OmZ1bmN0aW9uKCl7dGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBtb2RpZnkgdW5tb2RpZmlhYmxlIE1hcCIp
-KX0sCk5ROmZ1bmN0aW9uKGEpe3ZhciB0LHM9SC5KZyhhKQppZih0eXBlb2Ygcz09InN0cmluZyIpcmV0
-dXJuIHMKdD0ibWluaWZpZWQ6IithCnJldHVybiB0fSwKd1Y6ZnVuY3Rpb24oYSxiKXt2YXIgdAppZihi
-IT1udWxsKXt0PWIueAppZih0IT1udWxsKXJldHVybiB0fXJldHVybiB1LmFVLmIoYSl9LApkOmZ1bmN0
-aW9uKGEpe3ZhciB0CmlmKHR5cGVvZiBhPT0ic3RyaW5nIilyZXR1cm4gYQppZih0eXBlb2YgYT09Im51
-bWJlciIpe2lmKGEhPT0wKXJldHVybiIiK2F9ZWxzZSBpZighMD09PWEpcmV0dXJuInRydWUiCmVsc2Ug
-aWYoITE9PT1hKXJldHVybiJmYWxzZSIKZWxzZSBpZihhPT1udWxsKXJldHVybiJudWxsIgp0PUouQWMo
-YSkKaWYodHlwZW9mIHQhPSJzdHJpbmciKXRocm93IEguYihILkkoYSkpCnJldHVybiB0fSwKZVE6ZnVu
-Y3Rpb24oYSl7dmFyIHQ9YS4kaWRlbnRpdHlIYXNoCmlmKHQ9PW51bGwpe3Q9TWF0aC5yYW5kb20oKSow
-eDNmZmZmZmZmfDAKYS4kaWRlbnRpdHlIYXNoPXR9cmV0dXJuIHR9LApIcDpmdW5jdGlvbihhLGIpe3Zh
-ciB0LHMscixxLHAsbyxuPW51bGwKaWYodHlwZW9mIGEhPSJzdHJpbmciKUgudmgoSC5JKGEpKQp0PS9e
-XHMqWystXT8oKDB4W2EtZjAtOV0rKXwoXGQrKXwoW2EtejAtOV0rKSlccyokL2kuZXhlYyhhKQppZih0
-PT1udWxsKXJldHVybiBuCmlmKDM+PXQubGVuZ3RoKXJldHVybiBILmsodCwzKQpzPUguYyh0WzNdKQpp
-ZihiPT1udWxsKXtpZihzIT1udWxsKXJldHVybiBwYXJzZUludChhLDEwKQppZih0WzJdIT1udWxsKXJl
-dHVybiBwYXJzZUludChhLDE2KQpyZXR1cm4gbn1pZihiPDJ8fGI+MzYpdGhyb3cgSC5iKFAuVEUoYiwy
-LDM2LCJyYWRpeCIsbikpCmlmKGI9PT0xMCYmcyE9bnVsbClyZXR1cm4gcGFyc2VJbnQoYSwxMCkKaWYo
-YjwxMHx8cz09bnVsbCl7cj1iPD0xMD80NytiOjg2K2IKcT10WzFdCmZvcihwPXEubGVuZ3RoLG89MDtv
-PHA7KytvKWlmKChDLnhCLlcocSxvKXwzMik+cilyZXR1cm4gbn1yZXR1cm4gcGFyc2VJbnQoYSxiKX0s
-CmxoOmZ1bmN0aW9uKGEpe3ZhciB0PUguSDUoYSkKcmV0dXJuIHR9LApINTpmdW5jdGlvbihhKXt2YXIg
-dCxzLHIKaWYoYSBpbnN0YW5jZW9mIFAuTWgpcmV0dXJuIEguSihILnEoYSksbnVsbCkKaWYoSi5pYShh
-KT09PUMuT2t8fHUuYWsuYihhKSl7dD1DLndiKGEpCmlmKEguQmUodCkpcmV0dXJuIHQKcz1hLmNvbnN0
-cnVjdG9yCmlmKHR5cGVvZiBzPT0iZnVuY3Rpb24iKXtyPXMubmFtZQppZih0eXBlb2Ygcj09InN0cmlu
-ZyImJkguQmUocikpcmV0dXJuIHJ9fXJldHVybiBILkooSC5xKGEpLG51bGwpfSwKQmU6ZnVuY3Rpb24o
-YSl7dmFyIHQ9YSE9PSJPYmplY3QiJiZhIT09IiIKcmV0dXJuIHR9LApNMDpmdW5jdGlvbigpe2lmKCEh
-c2VsZi5sb2NhdGlvbilyZXR1cm4gc2VsZi5sb2NhdGlvbi5ocmVmCnJldHVybiBudWxsfSwKVks6ZnVu
-Y3Rpb24oYSl7dmFyIHQscyxyLHEscD1hLmxlbmd0aAppZihwPD01MDApcmV0dXJuIFN0cmluZy5mcm9t
-Q2hhckNvZGUuYXBwbHkobnVsbCxhKQpmb3IodD0iIixzPTA7czxwO3M9cil7cj1zKzUwMApxPXI8cD9y
-OnAKdCs9U3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShudWxsLGEuc2xpY2UocyxxKSl9cmV0dXJuIHR9
-LApDcTpmdW5jdGlvbihhKXt2YXIgdCxzLHIscT1ILlZNKFtdLHUudCkKZm9yKHQ9YS5sZW5ndGgscz0w
-O3M8YS5sZW5ndGg7YS5sZW5ndGg9PT10fHwoMCxILmxrKShhKSwrK3Mpe3I9YVtzXQppZighSC5vayhy
-KSl0aHJvdyBILmIoSC5JKHIpKQppZihyPD02NTUzNSlDLk5tLmkocSxyKQplbHNlIGlmKHI8PTExMTQx
-MTEpe0MuTm0uaShxLDU1Mjk2KyhDLmpuLndHKHItNjU1MzYsMTApJjEwMjMpKQpDLk5tLmkocSw1NjMy
-MCsociYxMDIzKSl9ZWxzZSB0aHJvdyBILmIoSC5JKHIpKX1yZXR1cm4gSC5WSyhxKX0sCmVUOmZ1bmN0
-aW9uKGEpe3ZhciB0LHMscgpmb3IodD1hLmxlbmd0aCxzPTA7czx0Oysrcyl7cj1hW3NdCmlmKCFILm9r
-KHIpKXRocm93IEguYihILkkocikpCmlmKHI8MCl0aHJvdyBILmIoSC5JKHIpKQppZihyPjY1NTM1KXJl
-dHVybiBILkNxKGEpfXJldHVybiBILlZLKGEpfSwKZnc6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixx
-CmlmKGM8PTUwMCYmYj09PTAmJmM9PT1hLmxlbmd0aClyZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZS5h
-cHBseShudWxsLGEpCmZvcih0PWIscz0iIjt0PGM7dD1yKXtyPXQrNTAwCnE9cjxjP3I6YwpzKz1TdHJp
-bmcuZnJvbUNoYXJDb2RlLmFwcGx5KG51bGwsYS5zdWJhcnJheSh0LHEpKX1yZXR1cm4gc30sCkx3OmZ1
-bmN0aW9uKGEpe3ZhciB0CmlmKDA8PWEpe2lmKGE8PTY1NTM1KXJldHVybiBTdHJpbmcuZnJvbUNoYXJD
-b2RlKGEpCmlmKGE8PTExMTQxMTEpe3Q9YS02NTUzNgpyZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZSgo
-NTUyOTZ8Qy5qbi53Ryh0LDEwKSk+Pj4wLDU2MzIwfHQmMTAyMyl9fXRocm93IEguYihQLlRFKGEsMCwx
-MTE0MTExLG51bGwsbnVsbCkpfSwKbzI6ZnVuY3Rpb24oYSl7aWYoYS5kYXRlPT09dm9pZCAwKWEuZGF0
-ZT1uZXcgRGF0ZShhLmEpCnJldHVybiBhLmRhdGV9LAp0SjpmdW5jdGlvbihhKXt2YXIgdD1ILm8yKGEp
-LmdldEZ1bGxZZWFyKCkrMApyZXR1cm4gdH0sCk5TOmZ1bmN0aW9uKGEpe3ZhciB0PUgubzIoYSkuZ2V0
-TW9udGgoKSsxCnJldHVybiB0fSwKakE6ZnVuY3Rpb24oYSl7dmFyIHQ9SC5vMihhKS5nZXREYXRlKCkr
-MApyZXR1cm4gdH0sCklYOmZ1bmN0aW9uKGEpe3ZhciB0PUgubzIoYSkuZ2V0SG91cnMoKSswCnJldHVy
-biB0fSwKY2g6ZnVuY3Rpb24oYSl7dmFyIHQ9SC5vMihhKS5nZXRNaW51dGVzKCkrMApyZXR1cm4gdH0s
-CkpkOmZ1bmN0aW9uKGEpe3ZhciB0PUgubzIoYSkuZ2V0U2Vjb25kcygpKzAKcmV0dXJuIHR9LApWYTpm
-dW5jdGlvbihhKXt2YXIgdD1ILm8yKGEpLmdldE1pbGxpc2Vjb25kcygpKzAKcmV0dXJuIHR9LAp6bzpm
-dW5jdGlvbihhLGIsYyl7dmFyIHQscyxyPXt9CnIuYT0wCnQ9W10Kcz1bXQpyLmE9Yi5sZW5ndGgKQy5O
-bS5GVih0LGIpCnIuYj0iIgppZihjIT1udWxsJiZjLmEhPT0wKWMuSygwLG5ldyBILkNqKHIscyx0KSkK
-IiIrci5hCnJldHVybiBKLkp5KGEsbmV3IEguTEkoQy5UZSwwLHQscywwKSl9LApFazpmdW5jdGlvbihh
-LGIsYyl7dmFyIHQscyxyLHEKaWYoYiBpbnN0YW5jZW9mIEFycmF5KXQ9Yz09bnVsbHx8Yy5hPT09MApl
-bHNlIHQ9ITEKaWYodCl7cz1iCnI9cy5sZW5ndGgKaWYocj09PTApe2lmKCEhYS4kMClyZXR1cm4gYS4k
-MCgpfWVsc2UgaWYocj09PTEpe2lmKCEhYS4kMSlyZXR1cm4gYS4kMShzWzBdKX1lbHNlIGlmKHI9PT0y
-KXtpZighIWEuJDIpcmV0dXJuIGEuJDIoc1swXSxzWzFdKX1lbHNlIGlmKHI9PT0zKXtpZighIWEuJDMp
-cmV0dXJuIGEuJDMoc1swXSxzWzFdLHNbMl0pfWVsc2UgaWYocj09PTQpe2lmKCEhYS4kNClyZXR1cm4g
-YS4kNChzWzBdLHNbMV0sc1syXSxzWzNdKX1lbHNlIGlmKHI9PT01KWlmKCEhYS4kNSlyZXR1cm4gYS4k
-NShzWzBdLHNbMV0sc1syXSxzWzNdLHNbNF0pCnE9YVsiIisiJCIrcl0KaWYocSE9bnVsbClyZXR1cm4g
-cS5hcHBseShhLHMpfXJldHVybiBILkV3KGEsYixjKX0sCkV3OmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxz
-LHIscSxwLG8sbixtLGwsaz1iIGluc3RhbmNlb2YgQXJyYXk/YjpQLkNIKGIsITAsdS56KSxqPWsubGVu
-Z3RoLGk9YS4kUgppZihqPGkpcmV0dXJuIEguem8oYSxrLGMpCnQ9YS4kRApzPXQ9PW51bGwKcj0hcz90
-KCk6bnVsbApxPUouaWEoYSkKcD1xLiRDCmlmKHR5cGVvZiBwPT0ic3RyaW5nIilwPXFbcF0KaWYocyl7
-aWYoYyE9bnVsbCYmYy5hIT09MClyZXR1cm4gSC56byhhLGssYykKaWYoaj09PWkpcmV0dXJuIHAuYXBw
-bHkoYSxrKQpyZXR1cm4gSC56byhhLGssYyl9aWYociBpbnN0YW5jZW9mIEFycmF5KXtpZihjIT1udWxs
-JiZjLmEhPT0wKXJldHVybiBILnpvKGEsayxjKQppZihqPmkrci5sZW5ndGgpcmV0dXJuIEguem8oYSxr
-LG51bGwpCkMuTm0uRlYoayxyLnNsaWNlKGotaSkpCnJldHVybiBwLmFwcGx5KGEsayl9ZWxzZXtpZihq
-PmkpcmV0dXJuIEguem8oYSxrLGMpCm89T2JqZWN0LmtleXMocikKaWYoYz09bnVsbClmb3Iocz1vLmxl
-bmd0aCxuPTA7bjxvLmxlbmd0aDtvLmxlbmd0aD09PXN8fCgwLEgubGspKG8pLCsrbilDLk5tLmkoayxy
-W0guYyhvW25dKV0pCmVsc2V7Zm9yKHM9by5sZW5ndGgsbT0wLG49MDtuPG8ubGVuZ3RoO28ubGVuZ3Ro
-PT09c3x8KDAsSC5saykobyksKytuKXtsPUguYyhvW25dKQppZihjLng0KGwpKXsrK20KQy5ObS5pKGss
-Yy5xKDAsbCkpfWVsc2UgQy5ObS5pKGsscltsXSl9aWYobSE9PWMuYSlyZXR1cm4gSC56byhhLGssYyl9
-cmV0dXJuIHAuYXBwbHkoYSxrKX19LApwWTpmdW5jdGlvbihhKXt0aHJvdyBILmIoSC5JKGEpKX0sCms6
-ZnVuY3Rpb24oYSxiKXtpZihhPT1udWxsKUouSChhKQp0aHJvdyBILmIoSC5IWShhLGIpKX0sCkhZOmZ1
-bmN0aW9uKGEsYil7dmFyIHQscyxyPSJpbmRleCIKaWYoIUgub2soYikpcmV0dXJuIG5ldyBQLkFUKCEw
-LGIscixudWxsKQp0PUguV1koSi5IKGEpKQppZighKGI8MCkpe2lmKHR5cGVvZiB0IT09Im51bWJlciIp
-cmV0dXJuIEgucFkodCkKcz1iPj10fWVsc2Ugcz0hMAppZihzKXJldHVybiBQLnQoYixhLHIsbnVsbCx0
-KQpyZXR1cm4gUC5PNyhiLHIpfSwKYXU6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0PSJJbnZhbGlkIHZhbHVl
-IgppZihhPmMpcmV0dXJuIG5ldyBQLmJKKDAsYywhMCxhLCJzdGFydCIsdCkKaWYoYiE9bnVsbCl7aWYo
-IUgub2soYikpcmV0dXJuIG5ldyBQLkFUKCEwLGIsImVuZCIsbnVsbCkKaWYoYjxhfHxiPmMpcmV0dXJu
-IG5ldyBQLmJKKGEsYywhMCxiLCJlbmQiLHQpfXJldHVybiBuZXcgUC5BVCghMCxiLCJlbmQiLG51bGwp
-fSwKSTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAuQVQoITAsYSxudWxsLG51bGwpfSwKYjpmdW5jdGlv
-bihhKXt2YXIgdAppZihhPT1udWxsKWE9bmV3IFAuTEsoKQp0PW5ldyBFcnJvcigpCnQuZGFydEV4Y2Vw
-dGlvbj1hCmlmKCJkZWZpbmVQcm9wZXJ0eSIgaW4gT2JqZWN0KXtPYmplY3QuZGVmaW5lUHJvcGVydHko
-dCwibWVzc2FnZSIse2dldDpILkp1fSkKdC5uYW1lPSIifWVsc2UgdC50b1N0cmluZz1ILkp1CnJldHVy
-biB0fSwKSnU6ZnVuY3Rpb24oKXtyZXR1cm4gSi5BYyh0aGlzLmRhcnRFeGNlcHRpb24pfSwKdmg6ZnVu
-Y3Rpb24oYSl7dGhyb3cgSC5iKGEpfSwKbGs6ZnVuY3Rpb24oYSl7dGhyb3cgSC5iKFAuYTQoYSkpfSwK
-Y006ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscCxvCmE9SC5lQShhLnJlcGxhY2UoU3RyaW5nKHt9KSwn
-JHJlY2VpdmVyJCcpKQp0PWEubWF0Y2goL1xcXCRbYS16QS1aXStcXFwkL2cpCmlmKHQ9PW51bGwpdD1I
-LlZNKFtdLHUucykKcz10LmluZGV4T2YoIlxcJGFyZ3VtZW50c1xcJCIpCnI9dC5pbmRleE9mKCJcXCRh
-cmd1bWVudHNFeHByXFwkIikKcT10LmluZGV4T2YoIlxcJGV4cHJcXCQiKQpwPXQuaW5kZXhPZigiXFwk
-bWV0aG9kXFwkIikKbz10LmluZGV4T2YoIlxcJHJlY2VpdmVyXFwkIikKcmV0dXJuIG5ldyBILmY5KGEu
-cmVwbGFjZShuZXcgUmVnRXhwKCdcXFxcXFwkYXJndW1lbnRzXFxcXFxcJCcsJ2cnKSwnKCg/Onh8W154
-XSkqKScpLnJlcGxhY2UobmV3IFJlZ0V4cCgnXFxcXFxcJGFyZ3VtZW50c0V4cHJcXFxcXFwkJywnZycp
-LCcoKD86eHxbXnhdKSopJykucmVwbGFjZShuZXcgUmVnRXhwKCdcXFxcXFwkZXhwclxcXFxcXCQnLCdn
-JyksJygoPzp4fFteeF0pKiknKS5yZXBsYWNlKG5ldyBSZWdFeHAoJ1xcXFxcXCRtZXRob2RcXFxcXFwk
-JywnZycpLCcoKD86eHxbXnhdKSopJykucmVwbGFjZShuZXcgUmVnRXhwKCdcXFxcXFwkcmVjZWl2ZXJc
-XFxcXFwkJywnZycpLCcoKD86eHxbXnhdKSopJykscyxyLHEscCxvKX0sClM3OmZ1bmN0aW9uKGEpe3Jl
-dHVybiBmdW5jdGlvbigkZXhwciQpe3ZhciAkYXJndW1lbnRzRXhwciQ9JyRhcmd1bWVudHMkJwp0cnl7
-JGV4cHIkLiRtZXRob2QkKCRhcmd1bWVudHNFeHByJCl9Y2F0Y2godCl7cmV0dXJuIHQubWVzc2FnZX19
-KGEpfSwKTWo6ZnVuY3Rpb24oYSl7cmV0dXJuIGZ1bmN0aW9uKCRleHByJCl7dHJ5eyRleHByJC4kbWV0
-aG9kJH1jYXRjaCh0KXtyZXR1cm4gdC5tZXNzYWdlfX0oYSl9LApJajpmdW5jdGlvbihhLGIpe3JldHVy
-biBuZXcgSC5XMChhLGI9PW51bGw/bnVsbDpiLm1ldGhvZCl9LApUMzpmdW5jdGlvbihhLGIpe3ZhciB0
-PWI9PW51bGwscz10P251bGw6Yi5tZXRob2QKcmV0dXJuIG5ldyBILmF6KGEscyx0P251bGw6Yi5yZWNl
-aXZlcil9LApSdTpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsayxqLGksaCxnLGY9bnVs
-bCxlPW5ldyBILkFtKGEpCmlmKGE9PW51bGwpcmV0dXJuIGYKaWYoYSBpbnN0YW5jZW9mIEguYnEpcmV0
-dXJuIGUuJDEoYS5hKQppZih0eXBlb2YgYSE9PSJvYmplY3QiKXJldHVybiBhCmlmKCJkYXJ0RXhjZXB0
-aW9uIiBpbiBhKXJldHVybiBlLiQxKGEuZGFydEV4Y2VwdGlvbikKZWxzZSBpZighKCJtZXNzYWdlIiBp
-biBhKSlyZXR1cm4gYQp0PWEubWVzc2FnZQppZigibnVtYmVyIiBpbiBhJiZ0eXBlb2YgYS5udW1iZXI9
-PSJudW1iZXIiKXtzPWEubnVtYmVyCnI9cyY2NTUzNQppZigoQy5qbi53RyhzLDE2KSY4MTkxKT09PTEw
-KXN3aXRjaChyKXtjYXNlIDQzODpyZXR1cm4gZS4kMShILlQzKEguZCh0KSsiIChFcnJvciAiK3IrIiki
-LGYpKQpjYXNlIDQ0NTpjYXNlIDUwMDc6cmV0dXJuIGUuJDEoSC5JaihILmQodCkrIiAoRXJyb3IgIity
-KyIpIixmKSl9fWlmKGEgaW5zdGFuY2VvZiBUeXBlRXJyb3Ipe3E9JC5TbigpCnA9JC5scSgpCm89JC5O
-OSgpCm49JC5pSSgpCm09JC5VTigpCmw9JC5aaCgpCms9JC5yTigpCiQuYzMoKQpqPSQuSEsoKQppPSQu
-cjEoKQpoPXEucVModCkKaWYoaCE9bnVsbClyZXR1cm4gZS4kMShILlQzKEguYyh0KSxoKSkKZWxzZXto
-PXAucVModCkKaWYoaCE9bnVsbCl7aC5tZXRob2Q9ImNhbGwiCnJldHVybiBlLiQxKEguVDMoSC5jKHQp
-LGgpKX1lbHNle2g9by5xUyh0KQppZihoPT1udWxsKXtoPW4ucVModCkKaWYoaD09bnVsbCl7aD1tLnFT
-KHQpCmlmKGg9PW51bGwpe2g9bC5xUyh0KQppZihoPT1udWxsKXtoPWsucVModCkKaWYoaD09bnVsbCl7
-aD1uLnFTKHQpCmlmKGg9PW51bGwpe2g9ai5xUyh0KQppZihoPT1udWxsKXtoPWkucVModCkKZz1oIT1u
-dWxsfWVsc2UgZz0hMH1lbHNlIGc9ITB9ZWxzZSBnPSEwfWVsc2UgZz0hMH1lbHNlIGc9ITB9ZWxzZSBn
-PSEwfWVsc2UgZz0hMAppZihnKXJldHVybiBlLiQxKEguSWooSC5jKHQpLGgpKX19cmV0dXJuIGUuJDEo
-bmV3IEgudlYodHlwZW9mIHQ9PSJzdHJpbmciP3Q6IiIpKX1pZihhIGluc3RhbmNlb2YgUmFuZ2VFcnJv
-cil7aWYodHlwZW9mIHQ9PSJzdHJpbmciJiZ0LmluZGV4T2YoImNhbGwgc3RhY2siKSE9PS0xKXJldHVy
-biBuZXcgUC5LWSgpCnQ9ZnVuY3Rpb24oYil7dHJ5e3JldHVybiBTdHJpbmcoYil9Y2F0Y2goZCl7fXJl
-dHVybiBudWxsfShhKQpyZXR1cm4gZS4kMShuZXcgUC5BVCghMSxmLGYsdHlwZW9mIHQ9PSJzdHJpbmci
-P3QucmVwbGFjZSgvXlJhbmdlRXJyb3I6XHMqLywiIik6dCkpfWlmKHR5cGVvZiBJbnRlcm5hbEVycm9y
-PT0iZnVuY3Rpb24iJiZhIGluc3RhbmNlb2YgSW50ZXJuYWxFcnJvcilpZih0eXBlb2YgdD09InN0cmlu
-ZyImJnQ9PT0idG9vIG11Y2ggcmVjdXJzaW9uIilyZXR1cm4gbmV3IFAuS1koKQpyZXR1cm4gYX0sCnRz
-OmZ1bmN0aW9uKGEpe3ZhciB0CmlmKGEgaW5zdGFuY2VvZiBILmJxKXJldHVybiBhLmIKaWYoYT09bnVs
-bClyZXR1cm4gbmV3IEguWE8oYSkKdD1hLiRjYWNoZWRUcmFjZQppZih0IT1udWxsKXJldHVybiB0CnJl
-dHVybiBhLiRjYWNoZWRUcmFjZT1uZXcgSC5YTyhhKX0sCkI3OmZ1bmN0aW9uKGEsYil7dmFyIHQscyxy
-LHE9YS5sZW5ndGgKZm9yKHQ9MDt0PHE7dD1yKXtzPXQrMQpyPXMrMQpiLlkoMCxhW3RdLGFbc10pfXJl
-dHVybiBifSwKZnQ6ZnVuY3Rpb24oYSxiLGMsZCxlLGYpe3UuWi5hKGEpCnN3aXRjaChILldZKGIpKXtj
-YXNlIDA6cmV0dXJuIGEuJDAoKQpjYXNlIDE6cmV0dXJuIGEuJDEoYykKY2FzZSAyOnJldHVybiBhLiQy
-KGMsZCkKY2FzZSAzOnJldHVybiBhLiQzKGMsZCxlKQpjYXNlIDQ6cmV0dXJuIGEuJDQoYyxkLGUsZil9
-dGhyb3cgSC5iKG5ldyBQLkNEKCJVbnN1cHBvcnRlZCBudW1iZXIgb2YgYXJndW1lbnRzIGZvciB3cmFw
-cGVkIGNsb3N1cmUiKSl9LAp0UjpmdW5jdGlvbihhLGIpe3ZhciB0CmlmKGE9PW51bGwpcmV0dXJuIG51
-bGwKdD1hLiRpZGVudGl0eQppZighIXQpcmV0dXJuIHQKdD1mdW5jdGlvbihjLGQsZSl7cmV0dXJuIGZ1
-bmN0aW9uKGYsZyxoLGkpe3JldHVybiBlKGMsZCxmLGcsaCxpKX19KGEsYixILmZ0KQphLiRpZGVudGl0
-eT10CnJldHVybiB0fSwKaUE6ZnVuY3Rpb24oYSxiLGMsZCxlLGYsZyl7dmFyIHQscyxyLHEscCxvLG4s
-bSxsPW51bGwsaz1iWzBdLGo9ay4kY2FsbE5hbWUsaT1lP09iamVjdC5jcmVhdGUobmV3IEguengoKS5j
-b25zdHJ1Y3Rvci5wcm90b3R5cGUpOk9iamVjdC5jcmVhdGUobmV3IEguankobCxsLGwsbCkuY29uc3Ry
-dWN0b3IucHJvdG90eXBlKQppLiRpbml0aWFsaXplPWkuY29uc3RydWN0b3IKaWYoZSl0PWZ1bmN0aW9u
-IHN0YXRpY190ZWFyX29mZigpe3RoaXMuJGluaXRpYWxpemUoKX0KZWxzZXtzPSQueWoKaWYodHlwZW9m
-IHMhPT0ibnVtYmVyIilyZXR1cm4gcy5oKCkKJC55aj1zKzEKcz1uZXcgRnVuY3Rpb24oImEsYixjLGQi
-K3MsInRoaXMuJGluaXRpYWxpemUoYSxiLGMsZCIrcysiKSIpCnQ9c31pLmNvbnN0cnVjdG9yPXQKdC5w
-cm90b3R5cGU9aQppZighZSl7cj1ILmJ4KGEsayxmKQpyLiRyZWZsZWN0aW9uSW5mbz1kfWVsc2V7aS4k
-c3RhdGljX25hbWU9ZwpyPWt9cT1ILmltKGQsZSxmKQppLiRTPXEKaVtqXT1yCmZvcihwPXIsbz0xO288
-Yi5sZW5ndGg7KytvKXtuPWJbb10KbT1uLiRjYWxsTmFtZQppZihtIT1udWxsKXtuPWU/bjpILmJ4KGEs
-bixmKQppW21dPW59aWYobz09PWMpe24uJHJlZmxlY3Rpb25JbmZvPWQKcD1ufX1pLiRDPXAKaS4kUj1r
-LiRSCmkuJEQ9ay4kRApyZXR1cm4gdH0sCmltOmZ1bmN0aW9uKGEsYixjKXt2YXIgdAppZih0eXBlb2Yg
-YT09Im51bWJlciIpcmV0dXJuIGZ1bmN0aW9uKGQsZSl7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIGQo
-ZSl9fShILkJwLGEpCmlmKHR5cGVvZiBhPT0ic3RyaW5nIil7aWYoYil0aHJvdyBILmIoIkNhbm5vdCBj
-b21wdXRlIHNpZ25hdHVyZSBmb3Igc3RhdGljIHRlYXJvZmYuIikKdD1jP0guUFc6SC5UbgpyZXR1cm4g
-ZnVuY3Rpb24oZCxlKXtyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gZSh0aGlzLGQpfX0oYSx0KX10aHJv
-dyBILmIoIkVycm9yIGluIGZ1bmN0aW9uVHlwZSBvZiB0ZWFyb2ZmIil9LAp2cTpmdW5jdGlvbihhLGIs
-YyxkKXt2YXIgdD1ILkRWCnN3aXRjaChiPy0xOmEpe2Nhc2UgMDpyZXR1cm4gZnVuY3Rpb24oZSxmKXty
-ZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gZih0aGlzKVtlXSgpfX0oYyx0KQpjYXNlIDE6cmV0dXJuIGZ1
-bmN0aW9uKGUsZil7cmV0dXJuIGZ1bmN0aW9uKGcpe3JldHVybiBmKHRoaXMpW2VdKGcpfX0oYyx0KQpj
-YXNlIDI6cmV0dXJuIGZ1bmN0aW9uKGUsZil7cmV0dXJuIGZ1bmN0aW9uKGcsaCl7cmV0dXJuIGYodGhp
-cylbZV0oZyxoKX19KGMsdCkKY2FzZSAzOnJldHVybiBmdW5jdGlvbihlLGYpe3JldHVybiBmdW5jdGlv
-bihnLGgsaSl7cmV0dXJuIGYodGhpcylbZV0oZyxoLGkpfX0oYyx0KQpjYXNlIDQ6cmV0dXJuIGZ1bmN0
-aW9uKGUsZil7cmV0dXJuIGZ1bmN0aW9uKGcsaCxpLGope3JldHVybiBmKHRoaXMpW2VdKGcsaCxpLGop
-fX0oYyx0KQpjYXNlIDU6cmV0dXJuIGZ1bmN0aW9uKGUsZil7cmV0dXJuIGZ1bmN0aW9uKGcsaCxpLGos
-ayl7cmV0dXJuIGYodGhpcylbZV0oZyxoLGksaixrKX19KGMsdCkKZGVmYXVsdDpyZXR1cm4gZnVuY3Rp
-b24oZSxmKXtyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gZS5hcHBseShmKHRoaXMpLGFyZ3VtZW50cyl9
-fShkLHQpfX0sCmJ4OmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscSxwLG8sbgppZihjKXJldHVybiBI
-LkhmKGEsYikKdD1iLiRzdHViTmFtZQpzPWIubGVuZ3RoCnI9YVt0XQpxPWI9PW51bGw/cj09bnVsbDpi
-PT09cgpwPSFxfHxzPj0yNwppZihwKXJldHVybiBILnZxKHMsIXEsdCxiKQppZihzPT09MCl7cT0kLnlq
-CmlmKHR5cGVvZiBxIT09Im51bWJlciIpcmV0dXJuIHEuaCgpCiQueWo9cSsxCm89InNlbGYiK3EKcT0i
-cmV0dXJuIGZ1bmN0aW9uKCl7dmFyICIrbysiID0gdGhpcy4iCnA9JC5tSgpyZXR1cm4gbmV3IEZ1bmN0
-aW9uKHErSC5kKHA9PW51bGw/JC5tSj1ILkUyKCJzZWxmIik6cCkrIjtyZXR1cm4gIitvKyIuIitILmQo
-dCkrIigpO30iKSgpfW49ImFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6Ii5zcGxpdCgiIikuc3BsaWNl
-KDAscykuam9pbigiLCIpCnE9JC55agppZih0eXBlb2YgcSE9PSJudW1iZXIiKXJldHVybiBxLmgoKQok
-LnlqPXErMQpuKz1xCnE9InJldHVybiBmdW5jdGlvbigiK24rIil7cmV0dXJuIHRoaXMuIgpwPSQubUoK
-cmV0dXJuIG5ldyBGdW5jdGlvbihxK0guZChwPT1udWxsPyQubUo9SC5FMigic2VsZiIpOnApKyIuIitI
-LmQodCkrIigiK24rIik7fSIpKCl9LApaNDpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdD1ILkRWLHM9SC55
-Uwpzd2l0Y2goYj8tMTphKXtjYXNlIDA6dGhyb3cgSC5iKEguRWYoIkludGVyY2VwdGVkIGZ1bmN0aW9u
-IHdpdGggbm8gYXJndW1lbnRzLiIpKQpjYXNlIDE6cmV0dXJuIGZ1bmN0aW9uKGUsZixnKXtyZXR1cm4g
-ZnVuY3Rpb24oKXtyZXR1cm4gZih0aGlzKVtlXShnKHRoaXMpKX19KGMsdCxzKQpjYXNlIDI6cmV0dXJu
-IGZ1bmN0aW9uKGUsZixnKXtyZXR1cm4gZnVuY3Rpb24oaCl7cmV0dXJuIGYodGhpcylbZV0oZyh0aGlz
-KSxoKX19KGMsdCxzKQpjYXNlIDM6cmV0dXJuIGZ1bmN0aW9uKGUsZixnKXtyZXR1cm4gZnVuY3Rpb24o
-aCxpKXtyZXR1cm4gZih0aGlzKVtlXShnKHRoaXMpLGgsaSl9fShjLHQscykKY2FzZSA0OnJldHVybiBm
-dW5jdGlvbihlLGYsZyl7cmV0dXJuIGZ1bmN0aW9uKGgsaSxqKXtyZXR1cm4gZih0aGlzKVtlXShnKHRo
-aXMpLGgsaSxqKX19KGMsdCxzKQpjYXNlIDU6cmV0dXJuIGZ1bmN0aW9uKGUsZixnKXtyZXR1cm4gZnVu
-Y3Rpb24oaCxpLGosayl7cmV0dXJuIGYodGhpcylbZV0oZyh0aGlzKSxoLGksaixrKX19KGMsdCxzKQpj
-YXNlIDY6cmV0dXJuIGZ1bmN0aW9uKGUsZixnKXtyZXR1cm4gZnVuY3Rpb24oaCxpLGosayxsKXtyZXR1
-cm4gZih0aGlzKVtlXShnKHRoaXMpLGgsaSxqLGssbCl9fShjLHQscykKZGVmYXVsdDpyZXR1cm4gZnVu
-Y3Rpb24oZSxmLGcsaCl7cmV0dXJuIGZ1bmN0aW9uKCl7aD1bZyh0aGlzKV0KQXJyYXkucHJvdG90eXBl
-LnB1c2guYXBwbHkoaCxhcmd1bWVudHMpCnJldHVybiBlLmFwcGx5KGYodGhpcyksaCl9fShkLHQscyl9
-fSwKSGY6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxwLG8sbixtPSQubUoKaWYobT09bnVsbCltPSQu
-bUo9SC5FMigic2VsZiIpCnQ9JC5QNAppZih0PT1udWxsKXQ9JC5QND1ILkUyKCJyZWNlaXZlciIpCnM9
-Yi4kc3R1Yk5hbWUKcj1iLmxlbmd0aApxPWFbc10KcD1iPT1udWxsP3E9PW51bGw6Yj09PXEKbz0hcHx8
-cj49MjgKaWYobylyZXR1cm4gSC5aNChyLCFwLHMsYikKaWYocj09PTEpe209InJldHVybiBmdW5jdGlv
-bigpe3JldHVybiB0aGlzLiIrSC5kKG0pKyIuIitILmQocykrIih0aGlzLiIrSC5kKHQpKyIpOyIKdD0k
-LnlqCmlmKHR5cGVvZiB0IT09Im51bWJlciIpcmV0dXJuIHQuaCgpCiQueWo9dCsxCnJldHVybiBuZXcg
-RnVuY3Rpb24obSt0KyJ9IikoKX1uPSJhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5eiIuc3BsaXQoIiIp
-LnNwbGljZSgwLHItMSkuam9pbigiLCIpCm09InJldHVybiBmdW5jdGlvbigiK24rIil7cmV0dXJuIHRo
-aXMuIitILmQobSkrIi4iK0guZChzKSsiKHRoaXMuIitILmQodCkrIiwgIituKyIpOyIKdD0kLnlqCmlm
-KHR5cGVvZiB0IT09Im51bWJlciIpcmV0dXJuIHQuaCgpCiQueWo9dCsxCnJldHVybiBuZXcgRnVuY3Rp
-b24obSt0KyJ9IikoKX0sCktxOmZ1bmN0aW9uKGEsYixjLGQsZSxmLGcpe3JldHVybiBILmlBKGEsYixj
-LGQsISFlLCEhZixnKX0sClRuOmZ1bmN0aW9uKGEsYil7cmV0dXJuIEguY0Uodi50eXBlVW5pdmVyc2Us
-SC5xKGEuYSksYil9LApQVzpmdW5jdGlvbihhLGIpe3JldHVybiBILmNFKHYudHlwZVVuaXZlcnNlLEgu
-cShhLmMpLGIpfSwKRFY6ZnVuY3Rpb24oYSl7cmV0dXJuIGEuYX0sCnlTOmZ1bmN0aW9uKGEpe3JldHVy
-biBhLmN9LApFMjpmdW5jdGlvbihhKXt2YXIgdCxzLHIscT1uZXcgSC5qeSgic2VsZiIsInRhcmdldCIs
-InJlY2VpdmVyIiwibmFtZSIpLHA9Si5FcChPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhxKSkKZm9y
-KHQ9cC5sZW5ndGgscz0wO3M8dDsrK3Mpe3I9cFtzXQppZihxW3JdPT09YSlyZXR1cm4gcn19LApvVDpm
-dW5jdGlvbihhKXtpZihhPT1udWxsKUguZk8oImJvb2xlYW4gZXhwcmVzc2lvbiBtdXN0IG5vdCBiZSBu
-dWxsIikKcmV0dXJuIGF9LApmTzpmdW5jdGlvbihhKXt0aHJvdyBILmIobmV3IEgua1koYSkpfSwKYWc6
-ZnVuY3Rpb24oYSl7dGhyb3cgSC5iKG5ldyBQLnQ3KGEpKX0sCkVmOmZ1bmN0aW9uKGEpe3JldHVybiBu
-ZXcgSC5FcShhKX0sCllnOmZ1bmN0aW9uKGEpe3JldHVybiB2LmdldElzb2xhdGVUYWcoYSl9LApWTTpm
-dW5jdGlvbihhLGIpe2Fbdi5hcnJheVJ0aV09YgpyZXR1cm4gYX0sCm9YOmZ1bmN0aW9uKGEpe2lmKGE9
-PW51bGwpcmV0dXJuIG51bGwKcmV0dXJuIGEuJHRpfSwKSU06ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBI
-Llk5KGFbIiRhIitILmQoYyldLEgub1goYikpfSwKWTk6ZnVuY3Rpb24oYSxiKXtpZihhPT1udWxsKXJl
-dHVybiBiCmE9YS5hcHBseShudWxsLGIpCmlmKGE9PW51bGwpcmV0dXJuIG51bGwKaWYoQXJyYXkuaXNB
-cnJheShhKSlyZXR1cm4gYQppZih0eXBlb2YgYT09ImZ1bmN0aW9uIilyZXR1cm4gYS5hcHBseShudWxs
-LGIpCnJldHVybiBifSwKSUc6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBhLmFwcGx5KGIsSC5ZOShKLmlh
-KGIpWyIkYSIrSC5kKGMpXSxILm9YKGIpKSl9LAppdzpmdW5jdGlvbihhLGIsYyl7T2JqZWN0LmRlZmlu
-ZVByb3BlcnR5KGEsYix7dmFsdWU6YyxlbnVtZXJhYmxlOmZhbHNlLHdyaXRhYmxlOnRydWUsY29uZmln
-dXJhYmxlOnRydWV9KX0sCkc6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscD1ILmMoJC55LiQxKGEpKSxv
-PSQualtwXQppZihvIT1udWxsKXtPYmplY3QuZGVmaW5lUHJvcGVydHkoYSx2LmRpc3BhdGNoUHJvcGVy
-dHlOYW1lLHt2YWx1ZTpvLGVudW1lcmFibGU6ZmFsc2Usd3JpdGFibGU6dHJ1ZSxjb25maWd1cmFibGU6
-dHJ1ZX0pCnJldHVybiBvLml9dD0kLnZbcF0KaWYodCE9bnVsbClyZXR1cm4gdApzPXYuaW50ZXJjZXB0
-b3JzQnlUYWdbcF0KaWYocz09bnVsbCl7cD1ILmMoJC51LiQyKGEscCkpCmlmKHAhPW51bGwpe289JC5q
-W3BdCmlmKG8hPW51bGwpe09iamVjdC5kZWZpbmVQcm9wZXJ0eShhLHYuZGlzcGF0Y2hQcm9wZXJ0eU5h
-bWUse3ZhbHVlOm8sZW51bWVyYWJsZTpmYWxzZSx3cml0YWJsZTp0cnVlLGNvbmZpZ3VyYWJsZTp0cnVl
-fSkKcmV0dXJuIG8uaX10PSQudltwXQppZih0IT1udWxsKXJldHVybiB0CnM9di5pbnRlcmNlcHRvcnNC
-eVRhZ1twXX19aWYocz09bnVsbClyZXR1cm4gbnVsbAp0PXMucHJvdG90eXBlCnI9cFswXQppZihyPT09
-IiEiKXtvPUgubCh0KQokLmpbcF09bwpPYmplY3QuZGVmaW5lUHJvcGVydHkoYSx2LmRpc3BhdGNoUHJv
-cGVydHlOYW1lLHt2YWx1ZTpvLGVudW1lcmFibGU6ZmFsc2Usd3JpdGFibGU6dHJ1ZSxjb25maWd1cmFi
-bGU6dHJ1ZX0pCnJldHVybiBvLml9aWYocj09PSJ+Iil7JC52W3BdPXQKcmV0dXJuIHR9aWYocj09PSIt
-Iil7cT1ILmwodCkKT2JqZWN0LmRlZmluZVByb3BlcnR5KE9iamVjdC5nZXRQcm90b3R5cGVPZihhKSx2
-LmRpc3BhdGNoUHJvcGVydHlOYW1lLHt2YWx1ZTpxLGVudW1lcmFibGU6ZmFsc2Usd3JpdGFibGU6dHJ1
-ZSxjb25maWd1cmFibGU6dHJ1ZX0pCnJldHVybiBxLml9aWYocj09PSIrIilyZXR1cm4gSC5MYyhhLHQp
-CmlmKHI9PT0iKiIpdGhyb3cgSC5iKFAubihwKSkKaWYodi5sZWFmVGFnc1twXT09PXRydWUpe3E9SC5s
-KHQpCk9iamVjdC5kZWZpbmVQcm9wZXJ0eShPYmplY3QuZ2V0UHJvdG90eXBlT2YoYSksdi5kaXNwYXRj
-aFByb3BlcnR5TmFtZSx7dmFsdWU6cSxlbnVtZXJhYmxlOmZhbHNlLHdyaXRhYmxlOnRydWUsY29uZmln
-dXJhYmxlOnRydWV9KQpyZXR1cm4gcS5pfWVsc2UgcmV0dXJuIEguTGMoYSx0KX0sCkxjOmZ1bmN0aW9u
-KGEsYil7dmFyIHQ9T2JqZWN0LmdldFByb3RvdHlwZU9mKGEpCk9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0
-LHYuZGlzcGF0Y2hQcm9wZXJ0eU5hbWUse3ZhbHVlOkouUXUoYix0LG51bGwsbnVsbCksZW51bWVyYWJs
-ZTpmYWxzZSx3cml0YWJsZTp0cnVlLGNvbmZpZ3VyYWJsZTp0cnVlfSkKcmV0dXJuIGJ9LApsOmZ1bmN0
-aW9uKGEpe3JldHVybiBKLlF1KGEsITEsbnVsbCwhIWEuJGlYail9LApWRjpmdW5jdGlvbihhLGIsYyl7
-dmFyIHQ9Yi5wcm90b3R5cGUKaWYodi5sZWFmVGFnc1thXT09PXRydWUpcmV0dXJuIEgubCh0KQplbHNl
-IHJldHVybiBKLlF1KHQsYyxudWxsLG51bGwpfSwKTTpmdW5jdGlvbigpe2lmKCEwPT09JC5LKXJldHVy
-bgokLks9ITAKSC5EKCl9LApEOmZ1bmN0aW9uKCl7dmFyIHQscyxyLHEscCxvLG4sbQokLmo9T2JqZWN0
-LmNyZWF0ZShudWxsKQokLnY9T2JqZWN0LmNyZWF0ZShudWxsKQpILmEoKQp0PXYuaW50ZXJjZXB0b3Jz
-QnlUYWcKcz1PYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyh0KQppZih0eXBlb2Ygd2luZG93IT0idW5k
-ZWZpbmVkIil7d2luZG93CnI9ZnVuY3Rpb24oKXt9CmZvcihxPTA7cTxzLmxlbmd0aDsrK3Epe3A9c1tx
-XQpvPSQueDcuJDEocCkKaWYobyE9bnVsbCl7bj1ILlZGKHAsdFtwXSxvKQppZihuIT1udWxsKXtPYmpl
-Y3QuZGVmaW5lUHJvcGVydHkobyx2LmRpc3BhdGNoUHJvcGVydHlOYW1lLHt2YWx1ZTpuLGVudW1lcmFi
-bGU6ZmFsc2Usd3JpdGFibGU6dHJ1ZSxjb25maWd1cmFibGU6dHJ1ZX0pCnIucHJvdG90eXBlPW99fX19
-Zm9yKHE9MDtxPHMubGVuZ3RoOysrcSl7cD1zW3FdCmlmKC9eW0EtWmEtel9dLy50ZXN0KHApKXttPXRb
-cF0KdFsiISIrcF09bQp0WyJ+IitwXT1tCnRbIi0iK3BdPW0KdFsiKyIrcF09bQp0WyIqIitwXT1tfX19
-LAphOmZ1bmN0aW9uKCl7dmFyIHQscyxyLHEscCxvLG49Qy5PNCgpCm49SC5GKEMuWXEsSC5GKEMuS1Us
-SC5GKEMuZlEsSC5GKEMuZlEsSC5GKEMuaTcsSC5GKEMueGksSC5GKEMuZGsoQy53YiksbikpKSkpKSkK
-aWYodHlwZW9mIGRhcnROYXRpdmVEaXNwYXRjaEhvb2tzVHJhbnNmb3JtZXIhPSJ1bmRlZmluZWQiKXt0
-PWRhcnROYXRpdmVEaXNwYXRjaEhvb2tzVHJhbnNmb3JtZXIKaWYodHlwZW9mIHQ9PSJmdW5jdGlvbiIp
-dD1bdF0KaWYodC5jb25zdHJ1Y3Rvcj09QXJyYXkpZm9yKHM9MDtzPHQubGVuZ3RoOysrcyl7cj10W3Nd
-CmlmKHR5cGVvZiByPT0iZnVuY3Rpb24iKW49cihuKXx8bn19cT1uLmdldFRhZwpwPW4uZ2V0VW5rbm93
-blRhZwpvPW4ucHJvdG90eXBlRm9yVGFnCiQueT1uZXcgSC5yKHEpCiQudT1uZXcgSC5kQyhwKQokLng3
-PW5ldyBILndOKG8pfSwKRjpmdW5jdGlvbihhLGIpe3JldHVybiBhKGIpfHxifSwKdjQ6ZnVuY3Rpb24o
-YSxiLGMsZCxlLGYpe3ZhciB0PWI/Im0iOiIiLHM9Yz8iIjoiaSIscj1kPyJ1IjoiIixxPWU/InMiOiIi
-LHA9Zj8iZyI6IiIsbz1mdW5jdGlvbihnLGgpe3RyeXtyZXR1cm4gbmV3IFJlZ0V4cChnLGgpfWNhdGNo
-KG4pe3JldHVybiBufX0oYSx0K3MrcitxK3ApCmlmKG8gaW5zdGFuY2VvZiBSZWdFeHApcmV0dXJuIG8K
-dGhyb3cgSC5iKFAucnIoIklsbGVnYWwgUmVnRXhwIHBhdHRlcm4gKCIrU3RyaW5nKG8pKyIpIixhLG51
-bGwpKX0sCm0yOmZ1bmN0aW9uKGEsYixjKXt2YXIgdAppZih0eXBlb2YgYj09InN0cmluZyIpcmV0dXJu
-IGEuaW5kZXhPZihiLGMpPj0wCmVsc2UgaWYoYiBpbnN0YW5jZW9mIEguVlIpe3Q9Qy54Qi5HKGEsYykK
-cmV0dXJuIGIuYi50ZXN0KHQpfWVsc2V7dD1KLkZMKGIsQy54Qi5HKGEsYykpCnJldHVybiF0LmdsMCh0
-KX19LApBNDpmdW5jdGlvbihhKXtpZihhLmluZGV4T2YoIiQiLDApPj0wKXJldHVybiBhLnJlcGxhY2Uo
-L1wkL2csIiQkJCQiKQpyZXR1cm4gYX0sCmVBOmZ1bmN0aW9uKGEpe2lmKC9bW1xde30oKSorPy5cXF4k
-fF0vLnRlc3QoYSkpcmV0dXJuIGEucmVwbGFjZSgvW1tcXXt9KCkqKz8uXFxeJHxdL2csIlxcJCYiKQpy
-ZXR1cm4gYX0sCnlzOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1ILm5NKGEsYixjKQpyZXR1cm4gdH0sCm5N
-OmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscQppZihiPT09IiIpe2lmKGE9PT0iIilyZXR1cm4gYwp0
-PWEubGVuZ3RoCmZvcihzPWMscj0wO3I8dDsrK3Ipcz1zK2Fbcl0rYwpyZXR1cm4gcy5jaGFyQ29kZUF0
-KDApPT0wP3M6c31xPWEuaW5kZXhPZihiLDApCmlmKHE8MClyZXR1cm4gYQppZihhLmxlbmd0aDw1MDB8
-fGMuaW5kZXhPZigiJCIsMCk+PTApcmV0dXJuIGEuc3BsaXQoYikuam9pbihjKQpyZXR1cm4gYS5yZXBs
-YWNlKG5ldyBSZWdFeHAoSC5lQShiKSwnZycpLEguQTQoYykpfSwKUEQ6ZnVuY3Rpb24gUEQoYSxiKXt0
-aGlzLmE9YQp0aGlzLiR0aT1ifSwKV1U6ZnVuY3Rpb24gV1UoKXt9LApMUDpmdW5jdGlvbiBMUChhLGIs
-YyxkKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8uJHRpPWR9LApYUjpmdW5jdGlvbiBYUihh
-LGIpe3RoaXMuYT1hCnRoaXMuJHRpPWJ9LApMSTpmdW5jdGlvbiBMSShhLGIsYyxkLGUpe3ZhciBfPXRo
-aXMKXy5hPWEKXy5jPWIKXy5kPWMKXy5lPWQKXy5mPWV9LApDajpmdW5jdGlvbiBDaihhLGIsYyl7dGhp
-cy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApmOTpmdW5jdGlvbiBmOShhLGIsYyxkLGUsZil7dmFyIF89
-dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9ZApfLmU9ZQpfLmY9Zn0sClcwOmZ1bmN0aW9uIFcwKGEs
-Yil7dGhpcy5hPWEKdGhpcy5iPWJ9LAphejpmdW5jdGlvbiBheihhLGIsYyl7dGhpcy5hPWEKdGhpcy5i
-PWIKdGhpcy5jPWN9LAp2VjpmdW5jdGlvbiB2VihhKXt0aGlzLmE9YX0sCmJxOmZ1bmN0aW9uIGJxKGEs
-Yil7dGhpcy5hPWEKdGhpcy5iPWJ9LApBbTpmdW5jdGlvbiBBbShhKXt0aGlzLmE9YX0sClhPOmZ1bmN0
-aW9uIFhPKGEpe3RoaXMuYT1hCnRoaXMuYj1udWxsfSwKVHA6ZnVuY3Rpb24gVHAoKXt9LApsYzpmdW5j
-dGlvbiBsYygpe30sCnp4OmZ1bmN0aW9uIHp4KCl7fSwKank6ZnVuY3Rpb24gankoYSxiLGMsZCl7dmFy
-IF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9ZH0sCkVxOmZ1bmN0aW9uIEVxKGEpe3RoaXMuYT1h
-fSwKa1k6ZnVuY3Rpb24ga1koYSl7dGhpcy5hPWF9LApONTpmdW5jdGlvbiBONShhKXt2YXIgXz10aGlz
-Cl8uYT0wCl8uZj1fLmU9Xy5kPV8uYz1fLmI9bnVsbApfLnI9MApfLiR0aT1hfSwKZGI6ZnVuY3Rpb24g
-ZGIoYSxiKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uZD1fLmM9bnVsbH0sCmk1OmZ1bmN0aW9uIGk1
-KGEsYil7dGhpcy5hPWEKdGhpcy4kdGk9Yn0sCk42OmZ1bmN0aW9uIE42KGEsYixjKXt2YXIgXz10aGlz
-Cl8uYT1hCl8uYj1iCl8uZD1fLmM9bnVsbApfLiR0aT1jfSwKcjpmdW5jdGlvbiByKGEpe3RoaXMuYT1h
-fSwKZEM6ZnVuY3Rpb24gZEMoYSl7dGhpcy5hPWF9LAp3TjpmdW5jdGlvbiB3TihhKXt0aGlzLmE9YX0s
-ClZSOmZ1bmN0aW9uIFZSKGEsYil7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmQ9Xy5jPW51bGx9LApF
-SzpmdW5jdGlvbiBFSyhhKXt0aGlzLmI9YX0sCktXOmZ1bmN0aW9uIEtXKGEsYixjKXt0aGlzLmE9YQp0
-aGlzLmI9Ygp0aGlzLmM9Y30sClBiOmZ1bmN0aW9uIFBiKGEsYixjKXt2YXIgXz10aGlzCl8uYT1hCl8u
-Yj1iCl8uYz1jCl8uZD1udWxsfSwKdFE6ZnVuY3Rpb24gdFEoYSxiKXt0aGlzLmE9YQp0aGlzLmM9Yn0s
-Ck5GOmZ1bmN0aW9uIE5GKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sClNkOmZ1bmN0
-aW9uIFNkKGEsYixjKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8uZD1udWxsfSwKWEY6ZnVu
-Y3Rpb24oYSl7cmV0dXJuIGF9LApEUTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IEludDhBcnJheShhKX0s
-Cm9kOmZ1bmN0aW9uKGEsYixjKXtpZihhPj4+MCE9PWF8fGE+PWMpdGhyb3cgSC5iKEguSFkoYixhKSl9
-LApyTTpmdW5jdGlvbihhLGIsYyl7dmFyIHQKaWYoIShhPj4+MCE9PWEpKXQ9Yj4+PjAhPT1ifHxhPmJ8
-fGI+YwplbHNlIHQ9ITAKaWYodCl0aHJvdyBILmIoSC5hdShhLGIsYykpCnJldHVybiBifSwKZUg6ZnVu
-Y3Rpb24gZUgoKXt9LApMWjpmdW5jdGlvbiBMWigpe30sCkRnOmZ1bmN0aW9uIERnKCl7fSwKUGc6ZnVu
-Y3Rpb24gUGcoKXt9LAp4ajpmdW5jdGlvbiB4aigpe30sCmRFOmZ1bmN0aW9uIGRFKCl7fSwKWkE6ZnVu
-Y3Rpb24gWkEoKXt9LAp3ZjpmdW5jdGlvbiB3Zigpe30sClBxOmZ1bmN0aW9uIFBxKCl7fSwKZUU6ZnVu
-Y3Rpb24gZUUoKXt9LApWNjpmdW5jdGlvbiBWNigpe30sClJHOmZ1bmN0aW9uIFJHKCl7fSwKVlA6ZnVu
-Y3Rpb24gVlAoKXt9LApXQjpmdW5jdGlvbiBXQigpe30sClpHOmZ1bmN0aW9uIFpHKCl7fSwKY3o6ZnVu
-Y3Rpb24oYSxiKXt2YXIgdD1iLmMKcmV0dXJuIHQ9PW51bGw/Yi5jPUguQmMoYSxiLnosITApOnR9LAp4
-WjpmdW5jdGlvbihhLGIpe3ZhciB0PWIuYwpyZXR1cm4gdD09bnVsbD9iLmM9SC5RMihhLCJiOCIsW2Iu
-el0pOnR9LApRMTpmdW5jdGlvbihhKXt2YXIgdD1hLnkKaWYodD09PTZ8fHQ9PT03fHx0PT09OClyZXR1
-cm4gSC5RMShhLnopCnJldHVybiB0PT09MTF8fHQ9PT0xMn0sCm1EOmZ1bmN0aW9uKGEpe3JldHVybiBh
-LmN5fSwKTjA6ZnVuY3Rpb24oYSl7cmV0dXJuIEguRSh2LnR5cGVVbml2ZXJzZSxhLCExKX0sClBMOmZ1
-bmN0aW9uKGEsYixjLGEwKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsayxqLGksaCxnLGYsZSxkPWIueQpz
-d2l0Y2goZCl7Y2FzZSA1OmNhc2UgMTpjYXNlIDI6Y2FzZSAzOmNhc2UgNDpyZXR1cm4gYgpjYXNlIDY6
-dD1iLnoKcz1ILlBMKGEsdCxjLGEwKQppZihzPT09dClyZXR1cm4gYgpyZXR1cm4gSC5TTyhhLHMsITAp
-CmNhc2UgNzp0PWIuegpzPUguUEwoYSx0LGMsYTApCmlmKHM9PT10KXJldHVybiBiCnJldHVybiBILkJj
-KGEscywhMCkKY2FzZSA4OnQ9Yi56CnM9SC5QTChhLHQsYyxhMCkKaWYocz09PXQpcmV0dXJuIGIKcmV0
-dXJuIEguTE4oYSxzLCEwKQpjYXNlIDk6cj1iLlEKcT1ILmJaKGEscixjLGEwKQppZihxPT09cilyZXR1
-cm4gYgpyZXR1cm4gSC5RMihhLGIueixxKQpjYXNlIDEwOnA9Yi56Cm89SC5QTChhLHAsYyxhMCkKbj1i
-LlEKbT1ILmJaKGEsbixjLGEwKQppZihvPT09cCYmbT09PW4pcmV0dXJuIGIKcmV0dXJuIEguYXAoYSxv
-LG0pCmNhc2UgMTE6bD1iLnoKaz1ILlBMKGEsbCxjLGEwKQpqPWIuUQppPUgucVQoYSxqLGMsYTApCmlm
-KGs9PT1sJiZpPT09ailyZXR1cm4gYgpyZXR1cm4gSC5OZihhLGssaSkKY2FzZSAxMjpoPWIuUQphMCs9
-aC5sZW5ndGgKZz1ILmJaKGEsaCxjLGEwKQpwPWIuegpvPUguUEwoYSxwLGMsYTApCmlmKGc9PT1oJiZv
-PT09cClyZXR1cm4gYgpyZXR1cm4gSC5EUyhhLG8sZywhMCkKY2FzZSAxMzpmPWIuegppZihmPGEwKXJl
-dHVybiBiCmU9Y1tmLWEwXQppZihlPT1udWxsKXJldHVybiBiCnJldHVybiBlCmRlZmF1bHQ6dGhyb3cg
-SC5iKFAuaFYoIkF0dGVtcHRlZCB0byBzdWJzdGl0dXRlIHVuZXhwZWN0ZWQgUlRJIGtpbmQgIitkKSl9
-fSwKYlo6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscyxyLHEscD1iLmxlbmd0aCxvPVtdCmZvcih0PSEx
-LHM9MDtzPHA7KytzKXtyPWJbc10KcT1ILlBMKGEscixjLGQpCmlmKHEhPT1yKXQ9ITAKby5wdXNoKHEp
-fXJldHVybiB0P286Yn0sCnZPOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0LHMscixxLHAsbz1iLmxlbmd0
-aCxuPVtdCmZvcih0PSExLHM9MDtzPG87cys9Mil7cj1iW3NdCnE9YltzKzFdCnA9SC5QTChhLHEsYyxk
-KQppZihwIT09cSl0PSEwCm4ucHVzaChyKQpuLnB1c2gocCl9cmV0dXJuIHQ/bjpifSwKcVQ6ZnVuY3Rp
-b24oYSxiLGMsZCl7dmFyIHQscz1iLmEscj1ILmJaKGEscyxjLGQpLHE9Yi5iLHA9SC5iWihhLHEsYyxk
-KSxvPWIuYyxuPUgudk8oYSxvLGMsZCkKaWYocj09PXMmJnA9PT1xJiZuPT09bylyZXR1cm4gYgp0PW5l
-dyBILkVUKCkKdC5hPXIKdC5iPXAKdC5jPW4KcmV0dXJuIHR9LApKUzpmdW5jdGlvbihhKXt2YXIgdD1h
-LiRTCmlmKHQhPW51bGwpe2lmKHR5cGVvZiB0PT0ibnVtYmVyIilyZXR1cm4gSC5CcCh0KQpyZXR1cm4g
-YS4kUygpfXJldHVybiBudWxsfSwKVWU6ZnVuY3Rpb24oYSxiKXt2YXIgdAppZihILlExKGIpKWlmKGEg
-aW5zdGFuY2VvZiBILlRwKXt0PUguSlMoYSkKaWYodCE9bnVsbClyZXR1cm4gdH1yZXR1cm4gSC5xKGEp
-fSwKcTpmdW5jdGlvbihhKXt2YXIgdAppZihhIGluc3RhbmNlb2YgUC5NaCl7dD1hLiR0aQpyZXR1cm4g
-dCE9bnVsbD90OkguVlUoYSl9aWYoQXJyYXkuaXNBcnJheShhKSlyZXR1cm4gSC50NihhKQpyZXR1cm4g
-SC5WVShKLmlhKGEpKX0sCnQ2OmZ1bmN0aW9uKGEpe3ZhciB0PWFbdi5hcnJheVJ0aV0scz11LmIKaWYo
-dD09bnVsbClyZXR1cm4gcwppZih0LmNvbnN0cnVjdG9yIT09cy5jb25zdHJ1Y3RvcilyZXR1cm4gcwpy
-ZXR1cm4gdH0sCkxoOmZ1bmN0aW9uKGEpe3ZhciB0PWEuJHRpCnJldHVybiB0IT1udWxsP3Q6SC5WVShh
-KX0sClZVOmZ1bmN0aW9uKGEpe3ZhciB0PWEuY29uc3RydWN0b3Iscz10LiRjY2FjaGUKaWYocyE9bnVs
-bClyZXR1cm4gcwpyZXR1cm4gSC5yOShhLHQpfSwKcjk6ZnVuY3Rpb24oYSxiKXt2YXIgdD1hIGluc3Rh
-bmNlb2YgSC5UcD9hLl9fcHJvdG9fXy5fX3Byb3RvX18uY29uc3RydWN0b3I6YixzPUguYWkodi50eXBl
-VW5pdmVyc2UsdC5uYW1lKQpiLiRjY2FjaGU9cwpyZXR1cm4gc30sCkJwOmZ1bmN0aW9uKGEpe3ZhciB0
-LHM9YSxyPXYudHlwZXMscT1yW3NdCmlmKHR5cGVvZiBxPT0ic3RyaW5nIil7dD1ILkUodi50eXBlVW5p
-dmVyc2UscSwhMSkKcltzXT10CnJldHVybiB0fXJldHVybiBxfSwKSko6ZnVuY3Rpb24oYSl7dmFyIHQ9
-dGhpcyxzPUguWU8scj11LksKaWYodD09PXIpe3M9SC5rZQp0LmE9SC5UaX1lbHNlIGlmKEguQTgodCl8
-fHQ9PT1yKXtzPUguSXcKdC5hPUguaG59ZWxzZSBpZih0PT09dS5wKXM9SC5vawplbHNlIGlmKHQ9PT11
-LmdSKXM9SC5LSAplbHNlIGlmKHQ9PT11LmRpKXM9SC5LSAplbHNlIGlmKHQ9PT11Lk4pcz1ILk1NCmVs
-c2UgaWYodD09PXUueSlzPUguclEKZWxzZSBpZih0Lnk9PT05KXtyPXQuegppZih0LlEuZXZlcnkoSC5j
-Yykpe3Qucj0iJGkiK3IKcz1ILnQ0fX10LmI9cwpyZXR1cm4gdC5iKGEpfSwKWU86ZnVuY3Rpb24oYSl7
-dmFyIHQ9dGhpcwpyZXR1cm4gSC5XZSh2LnR5cGVVbml2ZXJzZSxILlVlKGEsdCksbnVsbCx0LG51bGwp
-fSwKdDQ6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcyxzPXQucgppZihhIGluc3RhbmNlb2YgUC5NaClyZXR1
-cm4hIWFbc10KcmV0dXJuISFKLmlhKGEpW3NdfSwKT3o6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcwppZihh
-PT1udWxsKXJldHVybiBhCmVsc2UgaWYodC5iKGEpKXJldHVybiBhCnRocm93IEguYihILlpjKEgucChh
-LEguVWUoYSx0KSxILkoodCxudWxsKSkpKX0sCkRoOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0PW51bGwK
-aWYoSC5XZSh2LnR5cGVVbml2ZXJzZSxhLHQsYix0KSlyZXR1cm4gYQp0aHJvdyBILmIoSC5aYygiVGhl
-IHR5cGUgYXJndW1lbnQgJyIrSC5kKEguSihhLHQpKSsiJyBpcyBub3QgYSBzdWJ0eXBlIG9mIHRoZSB0
-eXBlIHZhcmlhYmxlIGJvdW5kICciK0guZChILkooYix0KSkrIicgb2YgdHlwZSB2YXJpYWJsZSAnIitj
-KyInIGluICciK0guZChkKSsiJy4iKSl9LApwOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1QLmgoYSkscz1I
-LkooYj09bnVsbD9ILnEoYSk6YixudWxsKQpyZXR1cm4gdCsiOiB0eXBlICciK0guZChzKSsiJyBpcyBu
-b3QgYSBzdWJ0eXBlIG9mIHR5cGUgJyIrSC5kKGMpKyInIn0sClpjOmZ1bmN0aW9uKGEpe3JldHVybiBu
-ZXcgSC54KCJUeXBlRXJyb3I6ICIrYSl9LApCOmZ1bmN0aW9uKGEsYil7cmV0dXJuIG5ldyBILngoIlR5
-cGVFcnJvcjogIitILnAoYSxudWxsLGIpKX0sCmtlOmZ1bmN0aW9uKGEpe3JldHVybiEwfSwKVGk6ZnVu
-Y3Rpb24oYSl7cmV0dXJuIGF9LApJdzpmdW5jdGlvbihhKXtyZXR1cm4hMH0sCmhuOmZ1bmN0aW9uKGEp
-e3JldHVybiBhfSwKclE6ZnVuY3Rpb24oYSl7cmV0dXJuITA9PT1hfHwhMT09PWF9LApFOTpmdW5jdGlv
-bihhKXtpZighMD09PWF8fCExPT09YSlyZXR1cm4gYQppZihhPT1udWxsKXJldHVybiBhCnRocm93IEgu
-YihILkIoYSwiYm9vbCIpKX0sCmRqOmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0ibnVtYmVyIilyZXR1
-cm4gYQppZihhPT1udWxsKXJldHVybiBhCnRocm93IEguYihILkIoYSwiZG91YmxlIikpfSwKb2s6ZnVu
-Y3Rpb24oYSl7cmV0dXJuIHR5cGVvZiBhPT0ibnVtYmVyIiYmTWF0aC5mbG9vcihhKT09PWF9LApXWTpm
-dW5jdGlvbihhKXtpZih0eXBlb2YgYT09Im51bWJlciImJk1hdGguZmxvb3IoYSk9PT1hKXJldHVybiBh
-CmlmKGE9PW51bGwpcmV0dXJuIGEKdGhyb3cgSC5iKEguQihhLCJpbnQiKSl9LApLSDpmdW5jdGlvbihh
-KXtyZXR1cm4gdHlwZW9mIGE9PSJudW1iZXIifSwKdVU6ZnVuY3Rpb24oYSl7aWYodHlwZW9mIGE9PSJu
-dW1iZXIiKXJldHVybiBhCmlmKGE9PW51bGwpcmV0dXJuIGEKdGhyb3cgSC5iKEguQihhLCJudW0iKSl9
-LApNTTpmdW5jdGlvbihhKXtyZXR1cm4gdHlwZW9mIGE9PSJzdHJpbmcifSwKYzpmdW5jdGlvbihhKXtp
-Zih0eXBlb2YgYT09InN0cmluZyIpcmV0dXJuIGEKaWYoYT09bnVsbClyZXR1cm4gYQp0aHJvdyBILmIo
-SC5CKGEsIlN0cmluZyIpKX0sCnc6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIKZm9yKHQ9IiIscz0iIixy
-PTA7cjxhLmxlbmd0aDsrK3Iscz0iLCAiKXQrPUMueEIuaChzLEguSihhW3JdLGIpKQpyZXR1cm4gdH0s
-CmY6ZnVuY3Rpb24oYTEsYTIsYTMpe3ZhciB0LHMscixxLHAsbyxuLG0sbCxrLGosaSxoLGcsZixlLGQs
-YyxiLGEsYTA9IiwgIgppZihhMyE9bnVsbCl7dD1hMy5sZW5ndGgKaWYoYTI9PW51bGwpe2EyPUguVk0o
-W10sdS5zKQpzPW51bGx9ZWxzZSBzPWEyLmxlbmd0aApyPWEyLmxlbmd0aApmb3IocT10O3E+MDstLXEp
-Qy5ObS5pKGEyLCJUIisocitxKSkKZm9yKHA9dS5LLG89IjwiLG49IiIscT0wO3E8dDsrK3Esbj1hMCl7
-bys9bgptPWEyLmxlbmd0aApsPW0tMS1xCmlmKGw8MClyZXR1cm4gSC5rKGEyLGwpCm89Qy54Qi5oKG8s
-YTJbbF0pCms9YTNbcV0KaWYoIShILkE4KGspfHxrPT09cCkpbT0hKGs9PT1wKQplbHNlIG09ITEKaWYo
-bSlvKz1DLnhCLmgoIiBleHRlbmRzICIsSC5KKGssYTIpKX1vKz0iPiJ9ZWxzZXtvPSIiCnM9bnVsbH1w
-PWExLnoKaj1hMS5RCmk9ai5hCmg9aS5sZW5ndGgKZz1qLmIKZj1nLmxlbmd0aAplPWouYwpkPWUubGVu
-Z3RoCmM9SC5KKHAsYTIpCmZvcihiPSIiLGE9IiIscT0wO3E8aDsrK3EsYT1hMCliKz1DLnhCLmgoYSxI
-LkooaVtxXSxhMikpCmlmKGY+MCl7Yis9YSsiWyIKZm9yKGE9IiIscT0wO3E8ZjsrK3EsYT1hMCliKz1D
-LnhCLmgoYSxILkooZ1txXSxhMikpCmIrPSJdIn1pZihkPjApe2IrPWErInsiCmZvcihhPSIiLHE9MDtx
-PGQ7cSs9MixhPWEwKWIrPUMueEIuaChhLEguSihlW3ErMV0sYTIpKSsiICIrZVtxXQpiKz0ifSJ9aWYo
-cyE9bnVsbClhMi5sZW5ndGg9cwpyZXR1cm4gbysiKCIrYisiKSA9PiAiK0guZChjKX0sCko6ZnVuY3Rp
-b24oYSxiKXt2YXIgdCxzLHIscSxwLG8sbixtPWEueQppZihtPT09NSlyZXR1cm4iZXJhc2VkIgppZiht
-PT09MilyZXR1cm4iZHluYW1pYyIKaWYobT09PTMpcmV0dXJuInZvaWQiCmlmKG09PT0xKXJldHVybiJO
-ZXZlciIKaWYobT09PTQpcmV0dXJuImFueSIKaWYobT09PTYpe3Q9SC5KKGEueixiKQpyZXR1cm4gdH1p
-ZihtPT09Nyl7cz1hLnoKdD1ILkoocyxiKQpyPXMueQpyZXR1cm4gSi5tKHI9PT0xMXx8cj09PTEyP0Mu
-eEIuaCgiKCIsdCkrIikiOnQsIj8iKX1pZihtPT09OClyZXR1cm4iRnV0dXJlT3I8IitILmQoSC5KKGEu
-eixiKSkrIj4iCmlmKG09PT05KXtxPUguQyhhLnopCnA9YS5RCnJldHVybiBwLmxlbmd0aCE9PTA/cSso
-IjwiK0gudyhwLGIpKyI+Iik6cX1pZihtPT09MTEpcmV0dXJuIEguZihhLGIsbnVsbCkKaWYobT09PTEy
-KXJldHVybiBILmYoYS56LGIsYS5RKQppZihtPT09MTMpe289YS56Cm49Yi5sZW5ndGgKbz1uLTEtbwpp
-ZihvPDB8fG8+PW4pcmV0dXJuIEguayhiLG8pCnJldHVybiBiW29dfXJldHVybiI/In0sCkM6ZnVuY3Rp
-b24oYSl7dmFyIHQscz1ILkpnKGEpCmlmKHMhPW51bGwpcmV0dXJuIHMKdD0ibWluaWZpZWQ6IithCnJl
-dHVybiB0fSwKUW86ZnVuY3Rpb24oYSxiKXt2YXIgdD1hLnRSW2JdCmZvcig7dHlwZW9mIHQ9PSJzdHJp
-bmciOyl0PWEudFJbdF0KcmV0dXJuIHR9LAphaTpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHAsbz1h
-LmVULG49b1tiXQppZihuPT1udWxsKXJldHVybiBILkUoYSxiLCExKQplbHNlIGlmKHR5cGVvZiBuPT0i
-bnVtYmVyIil7dD1uCnM9SC5tWihhLDUsIiMiKQpyPVtdCmZvcihxPTA7cTx0OysrcSlyLnB1c2gocykK
-cD1ILlEyKGEsYixyKQpvW2JdPXAKcmV0dXJuIHB9ZWxzZSByZXR1cm4gbn0sCnhiOmZ1bmN0aW9uKGEs
-Yil7cmV0dXJuIEguSXgoYS50UixiKX0sCkZGOmZ1bmN0aW9uKGEsYil7cmV0dXJuIEguSXgoYS5lVCxi
-KX0sCkU6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHM9YS5lQyxyPXMuZ2V0KGIpCmlmKHIhPW51bGwpcmV0
-dXJuIHIKdD1ILnooYSxudWxsLGIsYykKcy5zZXQoYix0KQpyZXR1cm4gdH0sCmNFOmZ1bmN0aW9uKGEs
-YixjKXt2YXIgdCxzLHI9Yi5jaAppZihyPT1udWxsKXI9Yi5jaD1uZXcgTWFwKCkKdD1yLmdldChjKQpp
-Zih0IT1udWxsKXJldHVybiB0CnM9SC56KGEsYixjLCEwKQpyLnNldChjLHMpCnJldHVybiBzfSwKdjU6
-ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixxPWIuY3gKaWYocT09bnVsbClxPWIuY3g9bmV3IE1hcCgp
-CnQ9Yy5jeQpzPXEuZ2V0KHQpCmlmKHMhPW51bGwpcmV0dXJuIHMKcj1ILmFwKGEsYixjLnk9PT0xMD9j
-LlE6W2NdKQpxLnNldCh0LHIpCnJldHVybiByfSwKejpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdD1ILmko
-SC5vKGEsYixjLGQpKQppZih0IT1udWxsKXJldHVybiB0CnRocm93IEguYihQLm4oJ19Vbml2ZXJzZS5f
-cGFyc2VSZWNpcGUoIicrSC5kKGMpKyciKScpKX0sCkJEOmZ1bmN0aW9uKGEsYil7Yi5hPUguT3oKYi5i
-PUguSkoKcmV0dXJuIGJ9LAptWjpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyPWEuZUMuZ2V0KGMpCmlm
-KHIhPW51bGwpcmV0dXJuIHIKdD1uZXcgSC5KYyhudWxsLG51bGwpCnQueT1iCnQuY3k9YwpzPUguQkQo
-YSx0KQphLmVDLnNldChjLHMpCnJldHVybiBzfSwKU086ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHM9Yi5j
-eSsiKiIscj1hLmVDLmdldChzKQppZihyIT1udWxsKXJldHVybiByCnQ9SC5aNyhhLGIscyxjKQphLmVD
-LnNldChzLHQpCnJldHVybiB0fSwKWjc6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscwppZihkKXt0PWIu
-eQppZihILkE4KGIpfHxiPT09dS5LfHxiPT09dS5QfHx0PT09N3x8dD09PTYpcmV0dXJuIGJ9cz1uZXcg
-SC5KYyhudWxsLG51bGwpCnMueT02CnMuej1iCnMuY3k9YwpyZXR1cm4gSC5CRChhLHMpfSwKQmM6ZnVu
-Y3Rpb24oYSxiLGMpe3ZhciB0LHM9Yi5jeSsiPyIscj1hLmVDLmdldChzKQppZihyIT1udWxsKXJldHVy
-biByCnQ9SC5sbChhLGIscyxjKQphLmVDLnNldChzLHQpCnJldHVybiB0fSwKbGw6ZnVuY3Rpb24oYSxi
-LGMsZCl7dmFyIHQscyxyLHEscAppZihkKXt0PWIueQppZighSC5BOChiKSlpZighKGI9PT11LlApKWlm
-KHQhPT03KXM9dD09PTgmJkgubFIoYi56KQplbHNlIHM9ITAKZWxzZSBzPSEwCmVsc2Ugcz0hMAppZihz
-KXJldHVybiBiCmVsc2UgaWYodD09PTEpcmV0dXJuIHUuUAplbHNlIGlmKHQ9PT02KXtyPWIuegpxPXIu
-eQppZihxPT09MSlyZXR1cm4gdS5QCmVsc2UgaWYocT09PTgmJkgubFIoci56KSlyZXR1cm4gcgplbHNl
-IHJldHVybiBILmN6KGEsYil9fXA9bmV3IEguSmMobnVsbCxudWxsKQpwLnk9NwpwLno9YgpwLmN5PWMK
-cmV0dXJuIEguQkQoYSxwKX0sCkxOOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzPWIuY3krIi8iLHI9YS5l
-Qy5nZXQocykKaWYociE9bnVsbClyZXR1cm4gcgp0PUguZVYoYSxiLHMsYykKYS5lQy5zZXQocyx0KQpy
-ZXR1cm4gdH0sCmVWOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0LHMKaWYoZCl7dD1iLnkKaWYoSC5BOChi
-KXx8Yj09PXUuS3x8Yj09PXUuSylyZXR1cm4gYgplbHNlIGlmKHQ9PT0xKXJldHVybiBILlEyKGEsImI4
-IixbYl0pCmVsc2UgaWYoYj09PXUuUClyZXR1cm4gdS5hUX1zPW5ldyBILkpjKG51bGwsbnVsbCkKcy55
-PTgKcy56PWIKcy5jeT1jCnJldHVybiBILkJEKGEscyl9LApIYzpmdW5jdGlvbihhLGIpe3ZhciB0LHMs
-cj0iIitiKyJeIixxPWEuZUMuZ2V0KHIpCmlmKHEhPW51bGwpcmV0dXJuIHEKdD1uZXcgSC5KYyhudWxs
-LG51bGwpCnQueT0xMwp0Lno9Ygp0LmN5PXIKcz1ILkJEKGEsdCkKYS5lQy5zZXQocixzKQpyZXR1cm4g
-c30sClV4OmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxPWEubGVuZ3RoCmZvcih0PSIiLHM9IiIscj0wO3I8
-cTsrK3Iscz0iLCIpdCs9cythW3JdLmN5CnJldHVybiB0fSwKUzQ6ZnVuY3Rpb24oYSl7dmFyIHQscyxy
-LHEscCxvPWEubGVuZ3RoCmZvcih0PSIiLHM9IiIscj0wO3I8bztyKz0yLHM9IiwiKXtxPWFbcl0KcD1h
-W3IrMV0uY3kKdCs9cytxKyI6IitwfXJldHVybiB0fSwKUTI6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMs
-cixxPWIKaWYoYy5sZW5ndGghPT0wKXErPSI8IitILlV4KGMpKyI+Igp0PWEuZUMuZ2V0KHEpCmlmKHQh
-PW51bGwpcmV0dXJuIHQKcz1uZXcgSC5KYyhudWxsLG51bGwpCnMueT05CnMuej1iCnMuUT1jCmlmKGMu
-bGVuZ3RoPjApcy5jPWNbMF0Kcy5jeT1xCnI9SC5CRChhLHMpCmEuZUMuc2V0KHEscikKcmV0dXJuIHJ9
-LAphcDpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHEscCxvCmlmKGIueT09PTEwKXt0PWIuegpzPWIu
-US5jb25jYXQoYyl9ZWxzZXtzPWMKdD1ifXI9dC5jeSsiOyIrKCI8IitILlV4KHMpKyI+IikKcT1hLmVD
-LmdldChyKQppZihxIT1udWxsKXJldHVybiBxCnA9bmV3IEguSmMobnVsbCxudWxsKQpwLnk9MTAKcC56
-PXQKcC5RPXMKcC5jeT1yCm89SC5CRChhLHApCmEuZUMuc2V0KHIsbykKcmV0dXJuIG99LApOZjpmdW5j
-dGlvbihhLGIsYyl7dmFyIHQscyxyLHEscD1iLmN5LG89Yy5hLG49by5sZW5ndGgsbT1jLmIsbD1tLmxl
-bmd0aCxrPWMuYyxqPWsubGVuZ3RoLGk9IigiK0guVXgobykKaWYobD4wKWkrPShuPjA/IiwiOiIiKSsi
-WyIrSC5VeChtKSsiXSIKaWYoaj4wKWkrPShuPjA/IiwiOiIiKSsieyIrSC5TNChrKSsifSIKdD1wKyhp
-KyIpIikKcz1hLmVDLmdldCh0KQppZihzIT1udWxsKXJldHVybiBzCnI9bmV3IEguSmMobnVsbCxudWxs
-KQpyLnk9MTEKci56PWIKci5RPWMKci5jeT10CnE9SC5CRChhLHIpCmEuZUMuc2V0KHQscSkKcmV0dXJu
-IHF9LApEUzpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzPWIuY3krIjwiK0guVXgoYykrIj4iLHI9YS5l
-Qy5nZXQocykKaWYociE9bnVsbClyZXR1cm4gcgp0PUguaHcoYSxiLGMscyxkKQphLmVDLnNldChzLHQp
-CnJldHVybiB0fSwKaHc6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgdCxzLHIscSxwLG8sbixtCmlmKGUp
-e3Q9Yy5sZW5ndGgKcz1uZXcgQXJyYXkodCkKZm9yKHI9MCxxPTA7cTx0OysrcSl7cD1jW3FdCmlmKHAu
-eT09PTEpe3NbcV09cDsrK3J9fWlmKHI+MCl7bz1ILlBMKGEsYixzLDApCm49SC5iWihhLGMscywwKQpy
-ZXR1cm4gSC5EUyhhLG8sbixjIT09bil9fW09bmV3IEguSmMobnVsbCxudWxsKQptLnk9MTIKbS56PWIK
-bS5RPWMKbS5jeT1kCnJldHVybiBILkJEKGEsbSl9LApvOmZ1bmN0aW9uKGEsYixjLGQpe3JldHVybnt1
-OmEsZTpiLHI6YyxzOltdLHA6MCxuOmR9fSwKaTpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwLG8sbixt
-LGwsayxqLGksaD1hLnIsZz1hLnMKZm9yKHQ9aC5sZW5ndGgscz0wO3M8dDspe3I9aC5jaGFyQ29kZUF0
-KHMpCmlmKHI+PTQ4JiZyPD01NylzPUguQWwocysxLHIsaCxnKQplbHNlIGlmKCgoKHJ8MzIpPj4+MCkt
-OTcmNjU1MzUpPDI2fHxyPT09OTV8fHI9PT0zNilzPUguUjgoYSxzLGgsZywhMSkKZWxzZSBpZihyPT09
-NDYpcz1ILlI4KGEscyxoLGcsITApCmVsc2V7KytzCnN3aXRjaChyKXtjYXNlIDQ0OmJyZWFrCmNhc2Ug
-NTg6YnJlYWsKY2FzZSA1OTpnLnB1c2goSC5LUShhLnUsYS5lLGcucG9wKCkpKQpicmVhawpjYXNlIDk0
-OmcucHVzaChILkhjKGEudSxnLnBvcCgpKSkKYnJlYWsKY2FzZSAzNTpnLnB1c2goSC5tWihhLnUsNSwi
-IyIpKQpicmVhawpjYXNlIDY0OmcucHVzaChILm1aKGEudSwyLCJAIikpCmJyZWFrCmNhc2UgMTI2Omcu
-cHVzaChILm1aKGEudSwzLCJ+IikpCmJyZWFrCmNhc2UgNjA6Zy5wdXNoKGEucCkKYS5wPWcubGVuZ3Ro
-CmJyZWFrCmNhc2UgNjI6cT1hLnUKcD1nLnNwbGljZShhLnApCkguclQoYS51LGEuZSxwKQphLnA9Zy5w
-b3AoKQpvPWcucG9wKCkKaWYodHlwZW9mIG89PSJzdHJpbmciKWcucHVzaChILlEyKHEsbyxwKSkKZWxz
-ZXtuPUguS1EocSxhLmUsbykKc3dpdGNoKG4ueSl7Y2FzZSAxMTpnLnB1c2goSC5EUyhxLG4scCxhLm4p
-KQpicmVhawpkZWZhdWx0OmcucHVzaChILmFwKHEsbixwKSkKYnJlYWt9fWJyZWFrCmNhc2UgMzg6SC5J
-MyhhLGcpCmJyZWFrCmNhc2UgNDI6bT1hLnUKZy5wdXNoKEguU08obSxILktRKG0sYS5lLGcucG9wKCkp
-LGEubikpCmJyZWFrCmNhc2UgNjM6bT1hLnUKZy5wdXNoKEguQmMobSxILktRKG0sYS5lLGcucG9wKCkp
-LGEubikpCmJyZWFrCmNhc2UgNDc6bT1hLnUKZy5wdXNoKEguTE4obSxILktRKG0sYS5lLGcucG9wKCkp
-LGEubikpCmJyZWFrCmNhc2UgNDA6Zy5wdXNoKGEucCkKYS5wPWcubGVuZ3RoCmJyZWFrCmNhc2UgNDE6
-cT1hLnUKbD1uZXcgSC5FVCgpCms9cS5zRUEKaj1xLnNFQQpvPWcucG9wKCkKaWYodHlwZW9mIG89PSJu
-dW1iZXIiKXN3aXRjaChvKXtjYXNlLTE6az1nLnBvcCgpCmJyZWFrCmNhc2UtMjpqPWcucG9wKCkKYnJl
-YWsKZGVmYXVsdDpnLnB1c2gobykKYnJlYWt9ZWxzZSBnLnB1c2gobykKcD1nLnNwbGljZShhLnApCkgu
-clQoYS51LGEuZSxwKQphLnA9Zy5wb3AoKQpsLmE9cApsLmI9awpsLmM9agpnLnB1c2goSC5OZihxLEgu
-S1EocSxhLmUsZy5wb3AoKSksbCkpCmJyZWFrCmNhc2UgOTE6Zy5wdXNoKGEucCkKYS5wPWcubGVuZ3Ro
-CmJyZWFrCmNhc2UgOTM6cD1nLnNwbGljZShhLnApCkguclQoYS51LGEuZSxwKQphLnA9Zy5wb3AoKQpn
-LnB1c2gocCkKZy5wdXNoKC0xKQpicmVhawpjYXNlIDEyMzpnLnB1c2goYS5wKQphLnA9Zy5sZW5ndGgK
-YnJlYWsKY2FzZSAxMjU6cD1nLnNwbGljZShhLnApCkguV1MoYS51LGEuZSxwKQphLnA9Zy5wb3AoKQpn
-LnB1c2gocCkKZy5wdXNoKC0yKQpicmVhawpkZWZhdWx0OnRocm93IkJhZCBjaGFyYWN0ZXIgIityfX19
-aT1nLnBvcCgpCnJldHVybiBILktRKGEudSxhLmUsaSl9LApBbDpmdW5jdGlvbihhLGIsYyxkKXt2YXIg
-dCxzLHI9Yi00OApmb3IodD1jLmxlbmd0aDthPHQ7KythKXtzPWMuY2hhckNvZGVBdChhKQppZighKHM+
-PTQ4JiZzPD01NykpYnJlYWsKcj1yKjEwKyhzLTQ4KX1kLnB1c2gocikKcmV0dXJuIGF9LApSODpmdW5j
-dGlvbihhLGIsYyxkLGUpe3ZhciB0LHMscixxLHAsbyxuPWIrMQpmb3IodD1jLmxlbmd0aDtuPHQ7Kytu
-KXtzPWMuY2hhckNvZGVBdChuKQppZihzPT09NDYpe2lmKGUpYnJlYWsKZT0hMH1lbHNle2lmKCEoKCgo
-c3wzMik+Pj4wKS05NyY2NTUzNSk8MjZ8fHM9PT05NXx8cz09PTM2KSlyPXM+PTQ4JiZzPD01NwplbHNl
-IHI9ITAKaWYoIXIpYnJlYWt9fXE9Yy5zdWJzdHJpbmcoYixuKQppZihlKXt0PWEudQpwPWEuZQppZihw
-Lnk9PT0xMClwPXAuegpvPUguUW8odCxwLnopW3FdCmlmKG89PW51bGwpSC52aCgnTm8gIicrcSsnIiBp
-biAiJytILm1EKHApKyciJykKZC5wdXNoKEguY0UodCxwLG8pKX1lbHNlIGQucHVzaChxKQpyZXR1cm4g
-bn0sCkkzOmZ1bmN0aW9uKGEsYil7dmFyIHQ9Yi5wb3AoKQppZigwPT09dCl7Yi5wdXNoKEgubVooYS51
-LDEsIjAmIikpCnJldHVybn1pZigxPT09dCl7Yi5wdXNoKEgubVooYS51LDQsIjEmIikpCnJldHVybn10
-aHJvdyBILmIoUC5oVigiVW5leHBlY3RlZCBleHRlbmRlZCBvcGVyYXRpb24gIitILmQodCkpKX0sCktR
-OmZ1bmN0aW9uKGEsYixjKXtpZih0eXBlb2YgYz09InN0cmluZyIpcmV0dXJuIEguUTIoYSxjLGEuc0VB
-KQplbHNlIGlmKHR5cGVvZiBjPT0ibnVtYmVyIilyZXR1cm4gSC5UVihhLGIsYykKZWxzZSByZXR1cm4g
-Y30sCnJUOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzPWMubGVuZ3RoCmZvcih0PTA7dDxzOysrdCljW3Rd
-PUguS1EoYSxiLGNbdF0pfSwKV1M6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHM9Yy5sZW5ndGgKZm9yKHQ9
-MTt0PHM7dCs9MiljW3RdPUguS1EoYSxiLGNbdF0pfSwKVFY6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMs
-cj1iLnkKaWYocj09PTEwKXtpZihjPT09MClyZXR1cm4gYi56CnQ9Yi5RCnM9dC5sZW5ndGgKaWYoYzw9
-cylyZXR1cm4gdFtjLTFdCmMtPXMKYj1iLnoKcj1iLnl9ZWxzZSBpZihjPT09MClyZXR1cm4gYgppZihy
-IT09OSl0aHJvdyBILmIoUC5oVigiSW5kZXhlZCBiYXNlIG11c3QgYmUgYW4gaW50ZXJmYWNlIHR5cGUi
-KSkKdD1iLlEKaWYoYzw9dC5sZW5ndGgpcmV0dXJuIHRbYy0xXQp0aHJvdyBILmIoUC5oVigiQmFkIGlu
-ZGV4ICIrYysiIGZvciAiK2IuWigwKSkpfSwKV2U6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgdCxzLHIs
-cSxwLG8sbixtLGwsawppZihiPT09ZClyZXR1cm4hMAppZihILkE4KGQpfHxkPT09dS5LKXJldHVybiEw
-CnQ9Yi55CmlmKHQ9PT00KXJldHVybiEwCmlmKEguQTgoYikpcmV0dXJuITEKaWYoYj09PXUuUClyZXR1
-cm4hMApzPXQ9PT0xMwppZihzKWlmKEguV2UoYSxjW2Iuel0sYyxkLGUpKXJldHVybiEwCnI9ZC55Cmlm
-KHQ9PT02KXJldHVybiBILldlKGEsYi56LGMsZCxlKQppZihyPT09Nil7cT1kLnoKcmV0dXJuIEguV2Uo
-YSxiLGMscSxlKX1pZih0PT09OCl7aWYoIUguV2UoYSxiLnosYyxkLGUpKXJldHVybiExCnJldHVybiBI
-LldlKGEsSC54WihhLGIpLGMsZCxlKX1pZih0PT09Nyl7cT1ILldlKGEsYi56LGMsZCxlKQpyZXR1cm4g
-cX1pZihyPT09OCl7aWYoSC5XZShhLGIsYyxkLnosZSkpcmV0dXJuITAKcmV0dXJuIEguV2UoYSxiLGMs
-SC54WihhLGQpLGUpfWlmKHI9PT03KXtxPUguV2UoYSxiLGMsZC56LGUpCnJldHVybiBxfWlmKHMpcmV0
-dXJuITEKcT10IT09MTEKaWYoKCFxfHx0PT09MTIpJiZkPT09dS5aKXJldHVybiEwCmlmKHI9PT0xMil7
-aWYoYj09PXUuZylyZXR1cm4hMAppZih0IT09MTIpcmV0dXJuITEKcD1iLlEKbz1kLlEKbj1wLmxlbmd0
-aAppZihuIT09by5sZW5ndGgpcmV0dXJuITEKYz1jPT1udWxsP3A6cC5jb25jYXQoYykKZT1lPT1udWxs
-P286by5jb25jYXQoZSkKZm9yKHE9dS5hdixtPTA7bTxuOysrbSl7bD1wW21dCms9b1ttXQpxLmEobCkK
-cS5hKGspCmlmKCFILldlKGEsbCxjLGssZSl8fCFILldlKGEsayxlLGwsYykpcmV0dXJuITF9cmV0dXJu
-IEguYk8oYSxiLnosYyxkLnosZSl9aWYocj09PTExKXtpZihiPT09dS5nKXJldHVybiEwCmlmKHEpcmV0
-dXJuITEKcmV0dXJuIEguYk8oYSxiLGMsZCxlKX1pZih0PT09OSl7aWYociE9PTkpcmV0dXJuITEKcmV0
-dXJuIEgucEcoYSxiLGMsZCxlKX1yZXR1cm4hMX0sCmJPOmZ1bmN0aW9uKGEwLGExLGEyLGEzLGE0KXt2
-YXIgdCxzLHIscSxwLG8sbixtLGwsayxqLGksaCxnLGYsZSxkLGMsYixhCmlmKCFILldlKGEwLGExLnos
-YTIsYTMueixhNCkpcmV0dXJuITEKdD1hMS5RCnM9YTMuUQpyPXQuYQpxPXMuYQpwPXIubGVuZ3RoCm89
-cS5sZW5ndGgKaWYocD5vKXJldHVybiExCm49by1wCm09dC5iCmw9cy5iCms9bS5sZW5ndGgKaj1sLmxl
-bmd0aAppZihwK2s8bytqKXJldHVybiExCmZvcihpPTA7aTxwOysraSl7aD1yW2ldCmlmKCFILldlKGEw
-LHFbaV0sYTQsaCxhMikpcmV0dXJuITF9Zm9yKGk9MDtpPG47KytpKXtoPW1baV0KaWYoIUguV2UoYTAs
-cVtwK2ldLGE0LGgsYTIpKXJldHVybiExfWZvcihpPTA7aTxqOysraSl7aD1tW24raV0KaWYoIUguV2Uo
-YTAsbFtpXSxhNCxoLGEyKSlyZXR1cm4hMX1nPXQuYwpmPXMuYwplPWcubGVuZ3RoCmQ9Zi5sZW5ndGgK
-Zm9yKGk9MCxjPTA7YzxkO2MrPTIpe2I9ZltjXQpkb3tpZihpPj1lKXJldHVybiExCmE9Z1tpXQppKz0y
-fXdoaWxlKGE8YikKaWYoYjxhKXJldHVybiExCmg9Z1tpLTFdCmlmKCFILldlKGEwLGZbYysxXSxhNCxo
-LGEyKSlyZXR1cm4hMX1yZXR1cm4hMH0sCnBHOmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHQscyxyLHEs
-cCxvLG4sbSxsPWIueixrPWQuegppZihsPT09ayl7dD1iLlEKcz1kLlEKcj10Lmxlbmd0aApmb3IocT0w
-O3E8cjsrK3Epe3A9dFtxXQpvPXNbcV0KaWYoIUguV2UoYSxwLGMsbyxlKSlyZXR1cm4hMX1yZXR1cm4h
-MH1pZihkPT09dS5LKXJldHVybiEwCm49SC5RbyhhLGwpCmlmKG49PW51bGwpcmV0dXJuITEKbT1uW2td
-CmlmKG09PW51bGwpcmV0dXJuITEKcj1tLmxlbmd0aApzPWQuUQpmb3IocT0wO3E8cjsrK3EpaWYoIUgu
-V2UoYSxILmNFKGEsYixtW3FdKSxjLHNbcV0sZSkpcmV0dXJuITEKcmV0dXJuITB9LApsUjpmdW5jdGlv
-bihhKXt2YXIgdCxzPWEueQppZighKGE9PT11LlApKWlmKCFILkE4KGEpKWlmKHMhPT03KWlmKCEocz09
-PTYmJkgubFIoYS56KSkpdD1zPT09OCYmSC5sUihhLnopCmVsc2UgdD0hMAplbHNlIHQ9ITAKZWxzZSB0
-PSEwCmVsc2UgdD0hMApyZXR1cm4gdH0sCmNjOmZ1bmN0aW9uKGEpe3JldHVybiBILkE4KGEpfHxhPT09
-dS5LfSwKQTg6ZnVuY3Rpb24oYSl7dmFyIHQscz1hLnkscj1zCmlmKHIhPT0yKWlmKHIhPT0zKWlmKHIh
-PT00KWlmKHIhPT01KXt0PXUuSwppZighKGE9PT10KSlzPXM9PT03JiZhLno9PT10CmVsc2Ugcz0hMH1l
-bHNlIHM9ITAKZWxzZSBzPSEwCmVsc2Ugcz0hMAplbHNlIHM9ITAKcmV0dXJuIHN9LApJeDpmdW5jdGlv
-bihhLGIpe3ZhciB0LHMscj1PYmplY3Qua2V5cyhiKSxxPXIubGVuZ3RoCmZvcih0PTA7dDxxOysrdCl7
-cz1yW3RdCmFbc109YltzXX19LApKYzpmdW5jdGlvbiBKYyhhLGIpe3ZhciBfPXRoaXMKXy5hPWEKXy5i
-PWIKXy54PV8ucj1fLmM9bnVsbApfLnk9MApfLmN5PV8uY3g9Xy5jaD1fLlE9Xy56PW51bGx9LApFVDpm
-dW5jdGlvbiBFVCgpe3RoaXMuYz10aGlzLmI9dGhpcy5hPW51bGx9LAp1OTpmdW5jdGlvbiB1OSgpe30s
-Cng6ZnVuY3Rpb24geChhKXt0aGlzLmE9YX0sClI5OmZ1bmN0aW9uKGEpe3JldHVybiB1LmQuYihhKXx8
-dS5CLmIoYSl8fHUuZHouYihhKXx8dS5JLmIoYSl8fHUuQS5iKGEpfHx1Lmc0LmIoYSl8fHUuZzIuYihh
-KX0sCkpnOmZ1bmN0aW9uKGEpe3JldHVybiB2Lm1hbmdsZWRHbG9iYWxOYW1lc1thXX19LEo9ewpRdTpm
-dW5jdGlvbihhLGIsYyxkKXtyZXR1cm57aTphLHA6YixlOmMseDpkfX0sCmtzOmZ1bmN0aW9uKGEpe3Zh
-ciB0LHMscixxLHA9YVt2LmRpc3BhdGNoUHJvcGVydHlOYW1lXQppZihwPT1udWxsKWlmKCQuSz09bnVs
-bCl7SC5NKCkKcD1hW3YuZGlzcGF0Y2hQcm9wZXJ0eU5hbWVdfWlmKHAhPW51bGwpe3Q9cC5wCmlmKCEx
-PT09dClyZXR1cm4gcC5pCmlmKCEwPT09dClyZXR1cm4gYQpzPU9iamVjdC5nZXRQcm90b3R5cGVPZihh
-KQppZih0PT09cylyZXR1cm4gcC5pCmlmKHAuZT09PXMpdGhyb3cgSC5iKFAubigiUmV0dXJuIGludGVy
-Y2VwdG9yIGZvciAiK0guZCh0KGEscCkpKSl9cj1hLmNvbnN0cnVjdG9yCnE9cj09bnVsbD9udWxsOnJb
-JC5BKCldCmlmKHEhPW51bGwpcmV0dXJuIHEKcT1ILkcoYSkKaWYocSE9bnVsbClyZXR1cm4gcQppZih0
-eXBlb2YgYT09ImZ1bmN0aW9uIilyZXR1cm4gQy5ERwp0PU9iamVjdC5nZXRQcm90b3R5cGVPZihhKQpp
-Zih0PT1udWxsKXJldHVybiBDLlpRCmlmKHQ9PT1PYmplY3QucHJvdG90eXBlKXJldHVybiBDLlpRCmlm
-KHR5cGVvZiByPT0iZnVuY3Rpb24iKXtPYmplY3QuZGVmaW5lUHJvcGVydHkociwkLkEoKSx7dmFsdWU6
-Qy52QixlbnVtZXJhYmxlOmZhbHNlLHdyaXRhYmxlOnRydWUsY29uZmlndXJhYmxlOnRydWV9KQpyZXR1
-cm4gQy52Qn1yZXR1cm4gQy52Qn0sClFpOmZ1bmN0aW9uKGEsYil7aWYoYTwwfHxhPjQyOTQ5NjcyOTUp
-dGhyb3cgSC5iKFAuVEUoYSwwLDQyOTQ5NjcyOTUsImxlbmd0aCIsbnVsbCkpCnJldHVybiBKLnB5KG5l
-dyBBcnJheShhKSxiKX0sCnB5OmZ1bmN0aW9uKGEsYil7cmV0dXJuIEouRXAoSC5WTShhLGIuQygiamQ8
-MD4iKSkpfSwKRXA6ZnVuY3Rpb24oYSl7YS5maXhlZCRsZW5ndGg9QXJyYXkKcmV0dXJuIGF9LAp1bjpm
-dW5jdGlvbihhKXthLmZpeGVkJGxlbmd0aD1BcnJheQphLmltbXV0YWJsZSRsaXN0PUFycmF5CnJldHVy
-biBhfSwKR2E6ZnVuY3Rpb24oYSl7aWYoYTwyNTYpc3dpdGNoKGEpe2Nhc2UgOTpjYXNlIDEwOmNhc2Ug
-MTE6Y2FzZSAxMjpjYXNlIDEzOmNhc2UgMzI6Y2FzZSAxMzM6Y2FzZSAxNjA6cmV0dXJuITAKZGVmYXVs
-dDpyZXR1cm4hMX1zd2l0Y2goYSl7Y2FzZSA1NzYwOmNhc2UgODE5MjpjYXNlIDgxOTM6Y2FzZSA4MTk0
-OmNhc2UgODE5NTpjYXNlIDgxOTY6Y2FzZSA4MTk3OmNhc2UgODE5ODpjYXNlIDgxOTk6Y2FzZSA4MjAw
-OmNhc2UgODIwMTpjYXNlIDgyMDI6Y2FzZSA4MjMyOmNhc2UgODIzMzpjYXNlIDgyMzk6Y2FzZSA4Mjg3
-OmNhc2UgMTIyODg6Y2FzZSA2NTI3OTpyZXR1cm4hMApkZWZhdWx0OnJldHVybiExfX0sCm1tOmZ1bmN0
-aW9uKGEsYil7dmFyIHQscwpmb3IodD1hLmxlbmd0aDtiPHQ7KXtzPUMueEIuVyhhLGIpCmlmKHMhPT0z
-MiYmcyE9PTEzJiYhSi5HYShzKSlicmVhazsrK2J9cmV0dXJuIGJ9LApjMTpmdW5jdGlvbihhLGIpe3Zh
-ciB0LHMKZm9yKDtiPjA7Yj10KXt0PWItMQpzPUMueEIubShhLHQpCmlmKHMhPT0zMiYmcyE9PTEzJiYh
-Si5HYShzKSlicmVha31yZXR1cm4gYn0sClJFOmZ1bmN0aW9uKGEpe2lmKGE9PW51bGwpcmV0dXJuIGEK
-aWYodHlwZW9mIGEhPSJvYmplY3QiKXtpZih0eXBlb2YgYT09ImZ1bmN0aW9uIilyZXR1cm4gSi5jNS5w
-cm90b3R5cGUKcmV0dXJuIGF9aWYoYSBpbnN0YW5jZW9mIFAuTWgpcmV0dXJuIGEKcmV0dXJuIEoua3Mo
-YSl9LApUSjpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09Im51bWJlciIpcmV0dXJuIEoucUkucHJvdG90
-eXBlCmlmKHR5cGVvZiBhPT0ic3RyaW5nIilyZXR1cm4gSi5Eci5wcm90b3R5cGUKaWYoYT09bnVsbCly
-ZXR1cm4gYQppZihhLmNvbnN0cnVjdG9yPT1BcnJheSlyZXR1cm4gSi5qZC5wcm90b3R5cGUKaWYodHlw
-ZW9mIGEhPSJvYmplY3QiKXtpZih0eXBlb2YgYT09ImZ1bmN0aW9uIilyZXR1cm4gSi5jNS5wcm90b3R5
-cGUKcmV0dXJuIGF9aWYoYSBpbnN0YW5jZW9mIFAuTWgpcmV0dXJuIGEKcmV0dXJuIEoua3MoYSl9LApV
-NjpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09InN0cmluZyIpcmV0dXJuIEouRHIucHJvdG90eXBlCmlm
-KGE9PW51bGwpcmV0dXJuIGEKaWYoYS5jb25zdHJ1Y3Rvcj09QXJyYXkpcmV0dXJuIEouamQucHJvdG90
-eXBlCmlmKHR5cGVvZiBhIT0ib2JqZWN0Iil7aWYodHlwZW9mIGE9PSJmdW5jdGlvbiIpcmV0dXJuIEou
-YzUucHJvdG90eXBlCnJldHVybiBhfWlmKGEgaW5zdGFuY2VvZiBQLk1oKXJldHVybiBhCnJldHVybiBK
-LmtzKGEpfSwKaWE6ZnVuY3Rpb24oYSl7aWYodHlwZW9mIGE9PSJudW1iZXIiKXtpZihNYXRoLmZsb29y
-KGEpPT1hKXJldHVybiBKLmJVLnByb3RvdHlwZQpyZXR1cm4gSi5WQS5wcm90b3R5cGV9aWYodHlwZW9m
-IGE9PSJzdHJpbmciKXJldHVybiBKLkRyLnByb3RvdHlwZQppZihhPT1udWxsKXJldHVybiBKLllFLnBy
-b3RvdHlwZQppZih0eXBlb2YgYT09ImJvb2xlYW4iKXJldHVybiBKLnlFLnByb3RvdHlwZQppZihhLmNv
-bnN0cnVjdG9yPT1BcnJheSlyZXR1cm4gSi5qZC5wcm90b3R5cGUKaWYodHlwZW9mIGEhPSJvYmplY3Qi
-KXtpZih0eXBlb2YgYT09ImZ1bmN0aW9uIilyZXR1cm4gSi5jNS5wcm90b3R5cGUKcmV0dXJuIGF9aWYo
-YSBpbnN0YW5jZW9mIFAuTWgpcmV0dXJuIGEKcmV0dXJuIEoua3MoYSl9LApyWTpmdW5jdGlvbihhKXtp
-Zih0eXBlb2YgYT09InN0cmluZyIpcmV0dXJuIEouRHIucHJvdG90eXBlCmlmKGE9PW51bGwpcmV0dXJu
-IGEKaWYoIShhIGluc3RhbmNlb2YgUC5NaCkpcmV0dXJuIEoua2QucHJvdG90eXBlCnJldHVybiBhfSwK
-dzE6ZnVuY3Rpb24oYSl7aWYoYT09bnVsbClyZXR1cm4gYQppZihhLmNvbnN0cnVjdG9yPT1BcnJheSly
-ZXR1cm4gSi5qZC5wcm90b3R5cGUKaWYodHlwZW9mIGEhPSJvYmplY3QiKXtpZih0eXBlb2YgYT09ImZ1
-bmN0aW9uIilyZXR1cm4gSi5jNS5wcm90b3R5cGUKcmV0dXJuIGF9aWYoYSBpbnN0YW5jZW9mIFAuTWgp
-cmV0dXJuIGEKcmV0dXJuIEoua3MoYSl9LApBYzpmdW5jdGlvbihhKXtyZXR1cm4gSi5pYShhKS5aKGEp
-fSwKQ006ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJuIEouUkUoYSkuZHUoYSxiLGMsZCl9LApDaTpmdW5j
-dGlvbihhKXtyZXR1cm4gSi5VNihhKS5nbDAoYSl9LApGTDpmdW5jdGlvbihhLGIpe3JldHVybiBKLnJZ
-KGEpLmRkKGEsYil9LApHQTpmdW5jdGlvbihhLGIpe3JldHVybiBKLncxKGEpLkUoYSxiKX0sCkdyOmZ1
-bmN0aW9uKGEpe3JldHVybiBKLlJFKGEpLmdtVyhhKX0sCkg6ZnVuY3Rpb24oYSl7cmV0dXJuIEouVTYo
-YSkuZ0EoYSl9LApJVDpmdW5jdGlvbihhKXtyZXR1cm4gSi53MShhKS5na3ooYSl9LApKeTpmdW5jdGlv
-bihhLGIpe3JldHVybiBKLmlhKGEpLmU3KGEsYil9LApLVjpmdW5jdGlvbihhLGIpe3JldHVybiBKLnJZ
-KGEpLkcoYSxiKX0sCkx0OmZ1bmN0aW9uKGEpe3JldHVybiBKLlJFKGEpLndnKGEpfSwKTTE6ZnVuY3Rp
-b24oYSxiLGMpe3JldHVybiBKLncxKGEpLkUyKGEsYixjKX0sCk11OmZ1bmN0aW9uKGEsYil7cmV0dXJu
-IEouUkUoYSkuc1AoYSxiKX0sClF6OmZ1bmN0aW9uKGEsYil7cmV0dXJuIEouclkoYSkuVyhhLGIpfSwK
-Uk06ZnVuY3Rpb24oYSxiKXtpZihhPT1udWxsKXJldHVybiBiPT1udWxsCmlmKHR5cGVvZiBhIT0ib2Jq
-ZWN0IilyZXR1cm4gYiE9bnVsbCYmYT09PWIKcmV0dXJuIEouaWEoYSkuRE4oYSxiKX0sClQwOmZ1bmN0
-aW9uKGEpe3JldHVybiBKLnJZKGEpLmJTKGEpfSwKYTY6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSi5yWShh
-KS5tKGEsYil9LApiVDpmdW5jdGlvbihhKXtyZXR1cm4gSi5SRShhKS5ENChhKX0sCmNIOmZ1bmN0aW9u
-KGEpe3JldHVybiBKLnJZKGEpLmhjKGEpfSwKZFI6ZnVuY3Rpb24oYSl7cmV0dXJuIEouUkUoYSkuZ1Ao
-YSl9LApkWjpmdW5jdGlvbihhLGIsYyxkKXtyZXR1cm4gSi5SRShhKS5PbihhLGIsYyxkKX0sCmRnOmZ1
-bmN0aW9uKGEsYixjLGQpe3JldHVybiBKLnJZKGEpLmk3KGEsYixjLGQpfSwKZGg6ZnVuY3Rpb24oYSl7
-cmV0dXJuIEouUkUoYSkuRkYoYSl9LApoZjpmdW5jdGlvbihhKXtyZXR1cm4gSi5pYShhKS5naU8oYSl9
-LAppZzpmdW5jdGlvbihhKXtyZXR1cm4gSi5SRShhKS5nUWcoYSl9LApsNTpmdW5jdGlvbihhLGIpe3Jl
-dHVybiBKLlJFKGEpLnNoZihhLGIpfSwKbGQ6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBKLnJZKGEpLk5q
-KGEsYixjKX0sCm06ZnVuY3Rpb24oYSxiKXtpZih0eXBlb2YgYT09Im51bWJlciImJnR5cGVvZiBiPT0i
-bnVtYmVyIilyZXR1cm4gYStiCnJldHVybiBKLlRKKGEpLmgoYSxiKX0sCnEwOmZ1bmN0aW9uKGEsYixj
-KXtyZXR1cm4gSi5yWShhKS5RaShhLGIsYyl9LApxRjpmdW5jdGlvbihhKXtyZXR1cm4gSi5SRShhKS5n
-VmwoYSl9LAp0SDpmdW5jdGlvbihhLGIsYyl7cmV0dXJuIEouUkUoYSkucGsoYSxiLGMpfSwKeDk6ZnVu
-Y3Rpb24oYSxiKXtpZih0eXBlb2YgYj09PSJudW1iZXIiKWlmKGEuY29uc3RydWN0b3I9PUFycmF5fHx0
-eXBlb2YgYT09InN0cmluZyJ8fEgud1YoYSxhW3YuZGlzcGF0Y2hQcm9wZXJ0eU5hbWVdKSlpZihiPj4+
-MD09PWImJmI8YS5sZW5ndGgpcmV0dXJuIGFbYl0KcmV0dXJuIEouVTYoYSkucShhLGIpfSwKemw6ZnVu
-Y3Rpb24oYSxiKXtyZXR1cm4gSi5VNihhKS50ZyhhLGIpfSwKdkI6ZnVuY3Rpb24gdkIoKXt9LAp5RTpm
-dW5jdGlvbiB5RSgpe30sCllFOmZ1bmN0aW9uIFlFKCl7fSwKTUY6ZnVuY3Rpb24gTUYoKXt9LAppQzpm
-dW5jdGlvbiBpQygpe30sCmtkOmZ1bmN0aW9uIGtkKCl7fSwKYzU6ZnVuY3Rpb24gYzUoKXt9LApqZDpm
-dW5jdGlvbiBqZChhKXt0aGlzLiR0aT1hfSwKUG86ZnVuY3Rpb24gUG8oYSl7dGhpcy4kdGk9YX0sCm0x
-OmZ1bmN0aW9uIG0xKGEsYixjKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz0wCl8uZD1udWxsCl8u
-JHRpPWN9LApxSTpmdW5jdGlvbiBxSSgpe30sCmJVOmZ1bmN0aW9uIGJVKCl7fSwKVkE6ZnVuY3Rpb24g
-VkEoKXt9LApEcjpmdW5jdGlvbiBEcigpe319LFA9ewpPajpmdW5jdGlvbigpe3ZhciB0LHMscj17fQpp
-ZihzZWxmLnNjaGVkdWxlSW1tZWRpYXRlIT1udWxsKXJldHVybiBQLkVYKCkKaWYoc2VsZi5NdXRhdGlv
-bk9ic2VydmVyIT1udWxsJiZzZWxmLmRvY3VtZW50IT1udWxsKXt0PXNlbGYuZG9jdW1lbnQuY3JlYXRl
-RWxlbWVudCgiZGl2IikKcz1zZWxmLmRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoInNwYW4iKQpyLmE9bnVs
-bApuZXcgc2VsZi5NdXRhdGlvbk9ic2VydmVyKEgudFIobmV3IFAudGgociksMSkpLm9ic2VydmUodCx7
-Y2hpbGRMaXN0OnRydWV9KQpyZXR1cm4gbmV3IFAuaGEocix0LHMpfWVsc2UgaWYoc2VsZi5zZXRJbW1l
-ZGlhdGUhPW51bGwpcmV0dXJuIFAueXQoKQpyZXR1cm4gUC5xVygpfSwKWlY6ZnVuY3Rpb24oYSl7c2Vs
-Zi5zY2hlZHVsZUltbWVkaWF0ZShILnRSKG5ldyBQLlZzKHUuTS5hKGEpKSwwKSl9LApvQTpmdW5jdGlv
-bihhKXtzZWxmLnNldEltbWVkaWF0ZShILnRSKG5ldyBQLkZ0KHUuTS5hKGEpKSwwKSl9LApCejpmdW5j
-dGlvbihhKXt1Lk0uYShhKQpQLlFOKDAsYSl9LApRTjpmdW5jdGlvbihhLGIpe3ZhciB0PW5ldyBQLlcz
-KCkKdC5DWShhLGIpCnJldHVybiB0fSwKRlg6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLmloKG5ldyBQ
-LnZzKCQuWDMsYS5DKCJ2czwwPiIpKSxhLkMoImloPDA+IikpfSwKREk6ZnVuY3Rpb24oYSxiKXthLiQy
-KDAsbnVsbCkKYi5iPSEwCnJldHVybiBiLmF9LApqUTpmdW5jdGlvbihhLGIpe1AuSmUoYSxiKX0sCnlD
-OmZ1bmN0aW9uKGEsYil7Yi5hTSgwLGEpfSwKZjM6ZnVuY3Rpb24oYSxiKXtiLncwKEguUnUoYSksSC50
-cyhhKSl9LApKZTpmdW5jdGlvbihhLGIpe3ZhciB0LHMscj1uZXcgUC5XTShiKSxxPW5ldyBQLlNYKGIp
-CmlmKGEgaW5zdGFuY2VvZiBQLnZzKWEuUWQocixxLHUueikKZWxzZXt0PXUuegppZih1LmMuYihhKSlh
-LlNxKHIscSx0KQplbHNle3M9bmV3IFAudnMoJC5YMyx1Ll8pCnMuYT00CnMuYz1hCnMuUWQocixxLHQp
-fX19LApsejpmdW5jdGlvbihhKXt2YXIgdD1mdW5jdGlvbihiLGMpe3JldHVybiBmdW5jdGlvbihkLGUp
-e3doaWxlKHRydWUpdHJ5e2IoZCxlKQpicmVha31jYXRjaChzKXtlPXMKZD1jfX19KGEsMSkKcmV0dXJu
-ICQuWDMuTGoobmV3IFAuR3ModCksdS5QLHUucCx1LnopfSwKR1E6ZnVuY3Rpb24oYSl7cmV0dXJuIG5l
-dyBQLkZ5KGEsMSl9LApUaDpmdW5jdGlvbigpe3JldHVybiBDLndRfSwKWW06ZnVuY3Rpb24oYSl7cmV0
-dXJuIG5ldyBQLkZ5KGEsMyl9LApsMDpmdW5jdGlvbihhLGIpe3JldHVybiBuZXcgUC5xNChhLGIuQygi
-cTQ8MD4iKSl9LAprMzpmdW5jdGlvbihhLGIpe3ZhciB0LHMscgpiLmE9MQp0cnl7YS5TcShuZXcgUC5w
-VihiKSxuZXcgUC5VNyhiKSx1LlApfWNhdGNoKHIpe3Q9SC5SdShyKQpzPUgudHMocikKUC5yYihuZXcg
-UC52cihiLHQscykpfX0sCkE5OmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyCmZvcih0PXUuXztzPWEuYSxz
-PT09MjspYT10LmEoYS5jKQppZihzPj00KXtyPWIuYWgoKQpiLmE9YS5hCmIuYz1hLmMKUC5IWihiLHIp
-fWVsc2V7cj11LnguYShiLmMpCmIuYT0yCmIuYz1hCmEualEocil9fSwKSFo6ZnVuY3Rpb24oYSxiKXt2
-YXIgdCxzLHIscSxwLG8sbixtLGwsayxqLGksaCxnLGYsZT1udWxsLGQ9e30sYz1kLmE9YQpmb3IodD11
-Lm4scz11Lngscj11LmM7ITA7KXtxPXt9CnA9Yy5hPT09OAppZihiPT1udWxsKXtpZihwKXtvPXQuYShj
-LmMpClAuTDIoZSxlLGMuYixvLmEsby5iKX1yZXR1cm59Zm9yKDtuPWIuYSxuIT1udWxsO2I9bil7Yi5h
-PW51bGwKUC5IWihkLmEsYil9Yz1kLmEKbT1jLmMKcS5hPXAKcS5iPW0KbD0hcAppZihsKXtrPWIuYwpr
-PShrJjEpIT09MHx8KGsmMTUpPT09OH1lbHNlIGs9ITAKaWYoayl7az1iLmIKaj1rLmIKaWYocCl7aT1j
-LmI9PT1qCmk9IShpfHxpKX1lbHNlIGk9ITEKaWYoaSl7dC5hKG0pClAuTDIoZSxlLGMuYixtLmEsbS5i
-KQpyZXR1cm59aD0kLlgzCmlmKGghPT1qKSQuWDM9agplbHNlIGg9ZQpjPWIuYwppZigoYyYxNSk9PT04
-KW5ldyBQLlJUKGQscSxiLHApLiQwKCkKZWxzZSBpZihsKXtpZigoYyYxKSE9PTApbmV3IFAucnEocSxi
-LG0pLiQwKCl9ZWxzZSBpZigoYyYyKSE9PTApbmV3IFAuUlcoZCxxLGIpLiQwKCkKaWYoaCE9bnVsbCkk
-LlgzPWgKYz1xLmIKaWYoci5iKGMpKXtpZihjLmE+PTQpe2c9cy5hKGsuYykKay5jPW51bGwKYj1rLk44
-KGcpCmsuYT1jLmEKay5jPWMuYwpkLmE9Ywpjb250aW51ZX1lbHNlIFAuQTkoYyxrKQpyZXR1cm59fWY9
-Yi5iCmc9cy5hKGYuYykKZi5jPW51bGwKYj1mLk44KGcpCmM9cS5hCmw9cS5iCmlmKCFjKXtmLiR0aS5j
-LmEobCkKZi5hPTQKZi5jPWx9ZWxzZXt0LmEobCkKZi5hPTgKZi5jPWx9ZC5hPWYKYz1mfX0sClZIOmZ1
-bmN0aW9uKGEsYil7dmFyIHQKaWYodS5hZy5iKGEpKXJldHVybiBiLkxqKGEsdS56LHUuSyx1LmwpCnQ9
-dS5iSQppZih0LmIoYSkpcmV0dXJuIHQuYShhKQp0aHJvdyBILmIoUC5MMyhhLCJvbkVycm9yIiwiRXJy
-b3IgaGFuZGxlciBtdXN0IGFjY2VwdCBvbmUgT2JqZWN0IG9yIG9uZSBPYmplY3QgYW5kIGEgU3RhY2tU
-cmFjZSBhcyBhcmd1bWVudHMsIGFuZCByZXR1cm4gYSBhIHZhbGlkIHJlc3VsdCIpKX0sCnB1OmZ1bmN0
-aW9uKCl7dmFyIHQscwpmb3IoO3Q9JC5TNix0IT1udWxsOyl7JC5tZz1udWxsCnM9dC5iCiQuUzY9cwpp
-ZihzPT1udWxsKSQuazg9bnVsbAp0LmEuJDAoKX19LAplTjpmdW5jdGlvbigpeyQuVUQ9ITAKdHJ5e1Au
-cHUoKX1maW5hbGx5eyQubWc9bnVsbAokLlVEPSExCmlmKCQuUzYhPW51bGwpJC51dCgpLiQxKFAuVjko
-KSl9fSwKZVc6ZnVuY3Rpb24oYSl7dmFyIHQ9bmV3IFAuT00oYSkKaWYoJC5TNj09bnVsbCl7JC5TNj0k
-Lms4PXQKaWYoISQuVUQpJC51dCgpLiQxKFAuVjkoKSl9ZWxzZSAkLms4PSQuazguYj10fSwKclI6ZnVu
-Y3Rpb24oYSl7dmFyIHQscyxyPSQuUzYKaWYocj09bnVsbCl7UC5lVyhhKQokLm1nPSQuazgKcmV0dXJu
-fXQ9bmV3IFAuT00oYSkKcz0kLm1nCmlmKHM9PW51bGwpe3QuYj1yCiQuUzY9JC5tZz10fWVsc2V7dC5i
-PXMuYgokLm1nPXMuYj10CmlmKHQuYj09bnVsbCkkLms4PXR9fSwKcmI6ZnVuY3Rpb24oYSl7dmFyIHQ9
-bnVsbCxzPSQuWDMKaWYoQy5OVT09PXMpe1AuVGsodCx0LEMuTlUsYSkKcmV0dXJufVAuVGsodCx0LHMs
-dS5NLmEocy5HWShhKSkpfSwKUXc6ZnVuY3Rpb24oYSxiKXtpZihhPT1udWxsKUgudmgoUC5FZSgic3Ry
-ZWFtIikpCnJldHVybiBuZXcgUC54SShiLkMoInhJPDA+IikpfSwKVGw6ZnVuY3Rpb24oYSxiKXt2YXIg
-dD1iPT1udWxsP1AudjAoYSk6YgpQLlVJKGEsImVycm9yIix1LkspCnJldHVybiBuZXcgUC5PSChhLHQp
-fSwKdjA6ZnVuY3Rpb24oYSl7dmFyIHQKaWYodS5XLmIoYSkpe3Q9YS5nSUkoKQppZih0IT1udWxsKXJl
-dHVybiB0fXJldHVybiBDLnBkfSwKTDI6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgdD17fQp0LmE9ZAp0
-LmI9ZQppZihkPT1udWxsKXt0LmE9bmV3IFAuQVQoITEsbnVsbCwiZXJyb3IiLCJNdXN0IG5vdCBiZSBu
-dWxsIikKdC5iPVAuWmIoKX1QLnJSKG5ldyBQLnBLKHQpKX0sClQ4OmZ1bmN0aW9uKGEsYixjLGQsZSl7
-dmFyIHQscz0kLlgzCmlmKHM9PT1jKXJldHVybiBkLiQwKCkKJC5YMz1jCnQ9cwp0cnl7cz1kLiQwKCkK
-cmV0dXJuIHN9ZmluYWxseXskLlgzPXR9fSwKeXY6ZnVuY3Rpb24oYSxiLGMsZCxlLGYsZyl7dmFyIHQs
-cz0kLlgzCmlmKHM9PT1jKXJldHVybiBkLiQxKGUpCiQuWDM9Ywp0PXMKdHJ5e3M9ZC4kMShlKQpyZXR1
-cm4gc31maW5hbGx5eyQuWDM9dH19LApReDpmdW5jdGlvbihhLGIsYyxkLGUsZixnLGgsaSl7dmFyIHQs
-cz0kLlgzCmlmKHM9PT1jKXJldHVybiBkLiQyKGUsZikKJC5YMz1jCnQ9cwp0cnl7cz1kLiQyKGUsZikK
-cmV0dXJuIHN9ZmluYWxseXskLlgzPXR9fSwKVGs6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQKdS5NLmEo
-ZCkKdD1DLk5VIT09YwppZih0KWQ9ISghdHx8ITEpP2MuR1koZCk6Yy5SVChkLHUuSCkKUC5lVyhkKX0s
-CnRoOmZ1bmN0aW9uIHRoKGEpe3RoaXMuYT1hfSwKaGE6ZnVuY3Rpb24gaGEoYSxiLGMpe3RoaXMuYT1h
-CnRoaXMuYj1iCnRoaXMuYz1jfSwKVnM6ZnVuY3Rpb24gVnMoYSl7dGhpcy5hPWF9LApGdDpmdW5jdGlv
-biBGdChhKXt0aGlzLmE9YX0sClczOmZ1bmN0aW9uIFczKCl7fSwKeUg6ZnVuY3Rpb24geUgoYSxiKXt0
-aGlzLmE9YQp0aGlzLmI9Yn0sCmloOmZ1bmN0aW9uIGloKGEsYil7dGhpcy5hPWEKdGhpcy5iPSExCnRo
-aXMuJHRpPWJ9LApXTTpmdW5jdGlvbiBXTShhKXt0aGlzLmE9YX0sClNYOmZ1bmN0aW9uIFNYKGEpe3Ro
-aXMuYT1hfSwKR3M6ZnVuY3Rpb24gR3MoYSl7dGhpcy5hPWF9LApGeTpmdW5jdGlvbiBGeShhLGIpe3Ro
-aXMuYT1hCnRoaXMuYj1ifSwKR1Y6ZnVuY3Rpb24gR1YoYSxiKXt2YXIgXz10aGlzCl8uYT1hCl8uZD1f
-LmM9Xy5iPW51bGwKXy4kdGk9Yn0sCnE0OmZ1bmN0aW9uIHE0KGEsYil7dGhpcy5hPWEKdGhpcy4kdGk9
-Yn0sCmI4OmZ1bmN0aW9uIGI4KCl7fSwKUGY6ZnVuY3Rpb24gUGYoKXt9LApaZjpmdW5jdGlvbiBaZihh
-LGIpe3RoaXMuYT1hCnRoaXMuJHRpPWJ9LApGZTpmdW5jdGlvbiBGZShhLGIsYyxkLGUpe3ZhciBfPXRo
-aXMKXy5hPW51bGwKXy5iPWEKXy5jPWIKXy5kPWMKXy5lPWQKXy4kdGk9ZX0sCnZzOmZ1bmN0aW9uIHZz
-KGEsYil7dmFyIF89dGhpcwpfLmE9MApfLmI9YQpfLmM9bnVsbApfLiR0aT1ifSwKZGE6ZnVuY3Rpb24g
-ZGEoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCm9ROmZ1bmN0aW9uIG9RKGEsYil7dGhpcy5hPWEKdGhp
-cy5iPWJ9LApwVjpmdW5jdGlvbiBwVihhKXt0aGlzLmE9YX0sClU3OmZ1bmN0aW9uIFU3KGEpe3RoaXMu
-YT1hfSwKdnI6ZnVuY3Rpb24gdnIoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKckg6
-ZnVuY3Rpb24gckgoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCktGOmZ1bmN0aW9uIEtGKGEsYil7dGhp
-cy5hPWEKdGhpcy5iPWJ9LApaTDpmdW5jdGlvbiBaTChhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhp
-cy5jPWN9LApSVDpmdW5jdGlvbiBSVChhLGIsYyxkKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1j
-Cl8uZD1kfSwKalo6ZnVuY3Rpb24galooYSl7dGhpcy5hPWF9LApycTpmdW5jdGlvbiBycShhLGIsYyl7
-dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApSVzpmdW5jdGlvbiBSVyhhLGIsYyl7dGhpcy5hPWEK
-dGhpcy5iPWIKdGhpcy5jPWN9LApPTTpmdW5jdGlvbiBPTShhKXt0aGlzLmE9YQp0aGlzLmI9bnVsbH0s
-CnFoOmZ1bmN0aW9uIHFoKCl7fSwKQjU6ZnVuY3Rpb24gQjUoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0s
-CnVPOmZ1bmN0aW9uIHVPKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApNTzpmdW5jdGlvbiBNTygpe30s
-CmtUOmZ1bmN0aW9uIGtUKCl7fSwKeEk6ZnVuY3Rpb24geEkoYSl7dGhpcy4kdGk9YX0sCk9IOmZ1bmN0
-aW9uIE9IKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LAptMDpmdW5jdGlvbiBtMCgpe30sCnBLOmZ1bmN0
-aW9uIHBLKGEpe3RoaXMuYT1hfSwKSmk6ZnVuY3Rpb24gSmkoKXt9LApoajpmdW5jdGlvbiBoaihhLGIs
-Yyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApWcDpmdW5jdGlvbiBWcChhLGIpe3RoaXMuYT1h
-CnRoaXMuYj1ifSwKT1I6ZnVuY3Rpb24gT1IoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1j
-fSwKRUY6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBiLkMoIkA8MD4iKS5LcShjKS5DKCJGbzwxLDI+Iiku
-YShILkI3KGEsbmV3IEguTjUoYi5DKCJAPDA+IikuS3EoYykuQygiTjU8MSwyPiIpKSkpfSwKRmw6ZnVu
-Y3Rpb24oYSxiKXtyZXR1cm4gbmV3IEguTjUoYS5DKCJAPDA+IikuS3EoYikuQygiTjU8MSwyPiIpKX0s
-CkxzOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC5iNihhLkMoImI2PDA+IikpfSwKVDI6ZnVuY3Rpb24o
-KXt2YXIgdD1PYmplY3QuY3JlYXRlKG51bGwpCnRbIjxub24taWRlbnRpZmllci1rZXk+Il09dApkZWxl
-dGUgdFsiPG5vbi1pZGVudGlmaWVyLWtleT4iXQpyZXR1cm4gdH0sCnJqOmZ1bmN0aW9uKGEsYixjKXt2
-YXIgdD1uZXcgUC5sbShhLGIsYy5DKCJsbTwwPiIpKQp0LmM9YS5lCnJldHVybiB0fSwKRVA6ZnVuY3Rp
-b24oYSxiLGMpe3ZhciB0LHMKaWYoUC5oQihhKSl7aWYoYj09PSIoIiYmYz09PSIpIilyZXR1cm4iKC4u
-LikiCnJldHVybiBiKyIuLi4iK2N9dD1ILlZNKFtdLHUucykKQy5ObS5pKCQueGcsYSkKdHJ5e1AuVnIo
-YSx0KX1maW5hbGx5e2lmKDA+PSQueGcubGVuZ3RoKXJldHVybiBILmsoJC54ZywtMSkKJC54Zy5wb3Ao
-KX1zPVAudmcoYix1LlIuYSh0KSwiLCAiKStjCnJldHVybiBzLmNoYXJDb2RlQXQoMCk9PTA/czpzfSwK
-V0U6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMKaWYoUC5oQihhKSlyZXR1cm4gYisiLi4uIitjCnQ9bmV3
-IFAuUm4oYikKQy5ObS5pKCQueGcsYSkKdHJ5e3M9dApzLmE9UC52ZyhzLmEsYSwiLCAiKX1maW5hbGx5
-e2lmKDA+PSQueGcubGVuZ3RoKXJldHVybiBILmsoJC54ZywtMSkKJC54Zy5wb3AoKX10LmErPWMKcz10
-LmEKcmV0dXJuIHMuY2hhckNvZGVBdCgwKT09MD9zOnN9LApoQjpmdW5jdGlvbihhKXt2YXIgdCxzCmZv
-cih0PSQueGcubGVuZ3RoLHM9MDtzPHQ7KytzKWlmKGE9PT0kLnhnW3NdKXJldHVybiEwCnJldHVybiEx
-fSwKVnI6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxwLG8sbixtPWEuZ2t6KGEpLGw9MCxrPTAKd2hp
-bGUoITApe2lmKCEobDw4MHx8azwzKSlicmVhawppZighbS5GKCkpcmV0dXJuCnQ9SC5kKG0uZ2woKSkK
-Qy5ObS5pKGIsdCkKbCs9dC5sZW5ndGgrMjsrK2t9aWYoIW0uRigpKXtpZihrPD01KXJldHVybgppZigw
-Pj1iLmxlbmd0aClyZXR1cm4gSC5rKGIsLTEpCnM9Yi5wb3AoKQppZigwPj1iLmxlbmd0aClyZXR1cm4g
-SC5rKGIsLTEpCnI9Yi5wb3AoKX1lbHNle3E9bS5nbCgpOysrawppZighbS5GKCkpe2lmKGs8PTQpe0Mu
-Tm0uaShiLEguZChxKSkKcmV0dXJufXM9SC5kKHEpCmlmKDA+PWIubGVuZ3RoKXJldHVybiBILmsoYiwt
+d1t0XVthXSlyZXR1cm4gd1t0XVthXX19dmFyIEM9e30sSD17Rks6ZnVuY3Rpb24gRksoKXt9LAp5Ujpm
+dW5jdGlvbihhKXtyZXR1cm4gbmV3IEgubmQoYSl9LApvbzpmdW5jdGlvbihhKXt2YXIgdCxzPWFeNDgK
+aWYoczw9OSlyZXR1cm4gcwp0PWF8MzIKaWYoOTc8PXQmJnQ8PTEwMilyZXR1cm4gdC04NwpyZXR1cm4t
+MX0sCnFDOmZ1bmN0aW9uKGEsYixjLGQpe1AuazEoYiwic3RhcnQiKQppZihjIT1udWxsKXtQLmsxKGMs
+ImVuZCIpCmlmKGI+YylILnZoKFAuVEUoYiwwLGMsInN0YXJ0IixudWxsKSl9cmV0dXJuIG5ldyBILm5I
+KGEsYixjLGQuQygibkg8MD4iKSl9LApLMTpmdW5jdGlvbihhLGIsYyxkKXtpZih1Lmd3LmIoYSkpcmV0
+dXJuIG5ldyBILnh5KGEsYixjLkMoIkA8MD4iKS5LcShkKS5DKCJ4eTwxLDI+IikpCnJldHVybiBuZXcg
+SC5pMShhLGIsYy5DKCJAPDA+IikuS3EoZCkuQygiaTE8MSwyPiIpKX0sCldwOmZ1bmN0aW9uKCl7cmV0
+dXJuIG5ldyBQLmxqKCJObyBlbGVtZW50Iil9LApBbTpmdW5jdGlvbigpe3JldHVybiBuZXcgUC5saigi
+VG9vIG1hbnkgZWxlbWVudHMiKX0sCmFyOmZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBQLmxqKCJUb28gZmV3
+IGVsZW1lbnRzIil9LApuZDpmdW5jdGlvbiBuZChhKXt0aGlzLmE9YX0sCnFqOmZ1bmN0aW9uIHFqKGEp
+e3RoaXMuYT1hfSwKYlE6ZnVuY3Rpb24gYlEoKXt9LAphTDpmdW5jdGlvbiBhTCgpe30sCm5IOmZ1bmN0
+aW9uIG5IKGEsYixjLGQpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPWMKXy4kdGk9ZH0sCmE3OmZ1
+bmN0aW9uIGE3KGEsYixjKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz0wCl8uZD1udWxsCl8uJHRp
+PWN9LAppMTpmdW5jdGlvbiBpMShhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy4kdGk9Y30sCnh5
+OmZ1bmN0aW9uIHh5KGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLiR0aT1jfSwKTUg6ZnVuY3Rp
+b24gTUgoYSxiLGMpe3ZhciBfPXRoaXMKXy5hPW51bGwKXy5iPWEKXy5jPWIKXy4kdGk9Y30sCmxKOmZ1
+bmN0aW9uIGxKKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLiR0aT1jfSwKVTU6ZnVuY3Rpb24g
+VTUoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuJHRpPWN9LApTTzpmdW5jdGlvbiBTTyhhLGIs
+Yyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy4kdGk9Y30sClNVOmZ1bmN0aW9uIFNVKCl7fSwKUmU6ZnVu
+Y3Rpb24gUmUoKXt9LAp3MjpmdW5jdGlvbiB3Migpe30sCnd2OmZ1bmN0aW9uIHd2KGEpe3RoaXMuYT1h
+fSwKZGM6ZnVuY3Rpb24oKXt0aHJvdyBILmIoUC5MNCgiQ2Fubm90IG1vZGlmeSB1bm1vZGlmaWFibGUg
+TWFwIikpfSwKTlE6ZnVuY3Rpb24oYSl7dmFyIHQscz1ILkpnKGEpCmlmKHMhPW51bGwpcmV0dXJuIHMK
+dD0ibWluaWZpZWQ6IithCnJldHVybiB0fSwKd1Y6ZnVuY3Rpb24oYSxiKXt2YXIgdAppZihiIT1udWxs
+KXt0PWIueAppZih0IT1udWxsKXJldHVybiB0fXJldHVybiB1LmFVLmIoYSl9LApFajpmdW5jdGlvbihh
+KXt2YXIgdAppZih0eXBlb2YgYT09InN0cmluZyIpcmV0dXJuIGEKaWYodHlwZW9mIGE9PSJudW1iZXIi
+KXtpZihhIT09MClyZXR1cm4iIithfWVsc2UgaWYoITA9PT1hKXJldHVybiJ0cnVlIgplbHNlIGlmKCEx
+PT09YSlyZXR1cm4iZmFsc2UiCmVsc2UgaWYoYT09bnVsbClyZXR1cm4ibnVsbCIKdD1KLmooYSkKaWYo
+dHlwZW9mIHQhPSJzdHJpbmciKXRocm93IEguYihILnRMKGEpKQpyZXR1cm4gdH0sCmVROmZ1bmN0aW9u
+KGEpe3ZhciB0PWEuJGlkZW50aXR5SGFzaAppZih0PT1udWxsKXt0PU1hdGgucmFuZG9tKCkqMHgzZmZm
+ZmZmZnwwCmEuJGlkZW50aXR5SGFzaD10fXJldHVybiB0fSwKSHA6ZnVuY3Rpb24oYSxiKXt2YXIgdCxz
+LHIscSxwLG8sbj1udWxsCmlmKHR5cGVvZiBhIT0ic3RyaW5nIilILnZoKEgudEwoYSkpCnQ9L15ccypb
+Ky1dPygoMHhbYS1mMC05XSspfChcZCspfChbYS16MC05XSspKVxzKiQvaS5leGVjKGEpCmlmKHQ9PW51
+bGwpcmV0dXJuIG4KaWYoMz49dC5sZW5ndGgpcmV0dXJuIEguT0godCwzKQpzPXRbM10KaWYoYj09bnVs
+bCl7aWYocyE9bnVsbClyZXR1cm4gcGFyc2VJbnQoYSwxMCkKaWYodFsyXSE9bnVsbClyZXR1cm4gcGFy
+c2VJbnQoYSwxNikKcmV0dXJuIG59aWYoYjwyfHxiPjM2KXRocm93IEguYihQLlRFKGIsMiwzNiwicmFk
+aXgiLG4pKQppZihiPT09MTAmJnMhPW51bGwpcmV0dXJuIHBhcnNlSW50KGEsMTApCmlmKGI8MTB8fHM9
+PW51bGwpe3I9Yjw9MTA/NDcrYjo4NitiCnE9dFsxXQpmb3IocD1xLmxlbmd0aCxvPTA7bzxwOysrbylp
+ZigoQy54Qi5XKHEsbyl8MzIpPnIpcmV0dXJuIG59cmV0dXJuIHBhcnNlSW50KGEsYil9LApNOmZ1bmN0
+aW9uKGEpe3JldHVybiBILkg1KGEpfSwKSDU6ZnVuY3Rpb24oYSl7dmFyIHQscyxyCmlmKGEgaW5zdGFu
+Y2VvZiBQLk1oKXJldHVybiBILmRtKEgueihhKSxudWxsKQppZihKLmlhKGEpPT09Qy5Pa3x8dS5hay5i
+KGEpKXt0PUMuTzQoYSkKaWYoSC5CZSh0KSlyZXR1cm4gdApzPWEuY29uc3RydWN0b3IKaWYodHlwZW9m
+IHM9PSJmdW5jdGlvbiIpe3I9cy5uYW1lCmlmKHR5cGVvZiByPT0ic3RyaW5nIiYmSC5CZShyKSlyZXR1
+cm4gcn19cmV0dXJuIEguZG0oSC56KGEpLG51bGwpfSwKQmU6ZnVuY3Rpb24oYSl7dmFyIHQ9YSE9PSJP
+YmplY3QiJiZhIT09IiIKcmV0dXJuIHR9LApNMDpmdW5jdGlvbigpe2lmKCEhc2VsZi5sb2NhdGlvbily
+ZXR1cm4gc2VsZi5sb2NhdGlvbi5ocmVmCnJldHVybiBudWxsfSwKVks6ZnVuY3Rpb24oYSl7dmFyIHQs
+cyxyLHEscD1hLmxlbmd0aAppZihwPD01MDApcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHko
+bnVsbCxhKQpmb3IodD0iIixzPTA7czxwO3M9cil7cj1zKzUwMApxPXI8cD9yOnAKdCs9U3RyaW5nLmZy
+b21DaGFyQ29kZS5hcHBseShudWxsLGEuc2xpY2UocyxxKSl9cmV0dXJuIHR9LApDcTpmdW5jdGlvbihh
+KXt2YXIgdCxzLHIscT1ILlZNKFtdLHUuYSkKZm9yKHQ9YS5sZW5ndGgscz0wO3M8YS5sZW5ndGg7YS5s
+ZW5ndGg9PT10fHwoMCxILmxrKShhKSwrK3Mpe3I9YVtzXQppZighSC5vayhyKSl0aHJvdyBILmIoSC50
+TChyKSkKaWYocjw9NjU1MzUpQy5ObS5pKHEscikKZWxzZSBpZihyPD0xMTE0MTExKXtDLk5tLmkocSw1
+NTI5NisoQy5qbi53RyhyLTY1NTM2LDEwKSYxMDIzKSkKQy5ObS5pKHEsNTYzMjArKHImMTAyMykpfWVs
+c2UgdGhyb3cgSC5iKEgudEwocikpfXJldHVybiBILlZLKHEpfSwKZVQ6ZnVuY3Rpb24oYSl7dmFyIHQs
+cyxyCmZvcih0PWEubGVuZ3RoLHM9MDtzPHQ7KytzKXtyPWFbc10KaWYoIUgub2socikpdGhyb3cgSC5i
+KEgudEwocikpCmlmKHI8MCl0aHJvdyBILmIoSC50TChyKSkKaWYocj42NTUzNSlyZXR1cm4gSC5DcShh
+KX1yZXR1cm4gSC5WSyhhKX0sCmZ3OmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscQppZihjPD01MDAm
+JmI9PT0wJiZjPT09YS5sZW5ndGgpcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkobnVsbCxh
+KQpmb3IodD1iLHM9IiI7dDxjO3Q9cil7cj10KzUwMApxPXI8Yz9yOmMKcys9U3RyaW5nLmZyb21DaGFy
+Q29kZS5hcHBseShudWxsLGEuc3ViYXJyYXkodCxxKSl9cmV0dXJuIHN9LApMdzpmdW5jdGlvbihhKXt2
+YXIgdAppZigwPD1hKXtpZihhPD02NTUzNSlyZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZShhKQppZihh
+PD0xMTE0MTExKXt0PWEtNjU1MzYKcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoKDU1Mjk2fEMuam4u
+d0codCwxMCkpPj4+MCw1NjMyMHx0JjEwMjMpfX10aHJvdyBILmIoUC5URShhLDAsMTExNDExMSxudWxs
+LG51bGwpKX0sCm8yOmZ1bmN0aW9uKGEpe2lmKGEuZGF0ZT09PXZvaWQgMClhLmRhdGU9bmV3IERhdGUo
+YS5hKQpyZXR1cm4gYS5kYXRlfSwKdEo6ZnVuY3Rpb24oYSl7dmFyIHQ9SC5vMihhKS5nZXRGdWxsWWVh
+cigpKzAKcmV0dXJuIHR9LApOUzpmdW5jdGlvbihhKXt2YXIgdD1ILm8yKGEpLmdldE1vbnRoKCkrMQpy
+ZXR1cm4gdH0sCmpBOmZ1bmN0aW9uKGEpe3ZhciB0PUgubzIoYSkuZ2V0RGF0ZSgpKzAKcmV0dXJuIHR9
+LApJWDpmdW5jdGlvbihhKXt2YXIgdD1ILm8yKGEpLmdldEhvdXJzKCkrMApyZXR1cm4gdH0sCmNoOmZ1
+bmN0aW9uKGEpe3ZhciB0PUgubzIoYSkuZ2V0TWludXRlcygpKzAKcmV0dXJuIHR9LApKZDpmdW5jdGlv
+bihhKXt2YXIgdD1ILm8yKGEpLmdldFNlY29uZHMoKSswCnJldHVybiB0fSwKbzE6ZnVuY3Rpb24oYSl7
+dmFyIHQ9SC5vMihhKS5nZXRNaWxsaXNlY29uZHMoKSswCnJldHVybiB0fSwKem86ZnVuY3Rpb24oYSxi
+LGMpe3ZhciB0LHMscj17fQpyLmE9MAp0PVtdCnM9W10Kci5hPWIubGVuZ3RoCkMuTm0uRlYodCxiKQpy
+LmI9IiIKaWYoYyE9bnVsbCYmYy5hIT09MCljLksoMCxuZXcgSC5DaihyLHMsdCkpCiIiK3IuYQpyZXR1
+cm4gSi5KeShhLG5ldyBILkxJKEMuVGUsMCx0LHMsMCkpfSwKRWs6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0
+LHMscixxCmlmKGIgaW5zdGFuY2VvZiBBcnJheSl0PWM9PW51bGx8fGMuYT09PTAKZWxzZSB0PSExCmlm
+KHQpe3M9YgpyPXMubGVuZ3RoCmlmKHI9PT0wKXtpZighIWEuJDApcmV0dXJuIGEuJDAoKX1lbHNlIGlm
+KHI9PT0xKXtpZighIWEuJDEpcmV0dXJuIGEuJDEoc1swXSl9ZWxzZSBpZihyPT09Mil7aWYoISFhLiQy
+KXJldHVybiBhLiQyKHNbMF0sc1sxXSl9ZWxzZSBpZihyPT09Myl7aWYoISFhLiQzKXJldHVybiBhLiQz
+KHNbMF0sc1sxXSxzWzJdKX1lbHNlIGlmKHI9PT00KXtpZighIWEuJDQpcmV0dXJuIGEuJDQoc1swXSxz
+WzFdLHNbMl0sc1szXSl9ZWxzZSBpZihyPT09NSlpZighIWEuJDUpcmV0dXJuIGEuJDUoc1swXSxzWzFd
+LHNbMl0sc1szXSxzWzRdKQpxPWFbIiIrIiQiK3JdCmlmKHEhPW51bGwpcmV0dXJuIHEuYXBwbHkoYSxz
+KX1yZXR1cm4gSC5lMShhLGIsYyl9LAplMTpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHEscCxvLG4s
+bSxsLGssaj1iIGluc3RhbmNlb2YgQXJyYXk/YjpQLkNIKGIsITAsdS56KSxpPWoubGVuZ3RoLGg9YS4k
+UgppZihpPGgpcmV0dXJuIEguem8oYSxqLGMpCnQ9YS4kRApzPXQ9PW51bGwKcj0hcz90KCk6bnVsbApx
+PUouaWEoYSkKcD1xLiRDCmlmKHR5cGVvZiBwPT0ic3RyaW5nIilwPXFbcF0KaWYocyl7aWYoYyE9bnVs
+bCYmYy5hIT09MClyZXR1cm4gSC56byhhLGosYykKaWYoaT09PWgpcmV0dXJuIHAuYXBwbHkoYSxqKQpy
+ZXR1cm4gSC56byhhLGosYyl9aWYociBpbnN0YW5jZW9mIEFycmF5KXtpZihjIT1udWxsJiZjLmEhPT0w
+KXJldHVybiBILnpvKGEsaixjKQppZihpPmgrci5sZW5ndGgpcmV0dXJuIEguem8oYSxqLG51bGwpCkMu
+Tm0uRlYoaixyLnNsaWNlKGktaCkpCnJldHVybiBwLmFwcGx5KGEsail9ZWxzZXtpZihpPmgpcmV0dXJu
+IEguem8oYSxqLGMpCm89T2JqZWN0LmtleXMocikKaWYoYz09bnVsbClmb3Iocz1vLmxlbmd0aCxuPTA7
+bjxvLmxlbmd0aDtvLmxlbmd0aD09PXN8fCgwLEgubGspKG8pLCsrbil7bT1yW0guaChvW25dKV0KaWYo
+Qy5Odj09PW0pcmV0dXJuIEguem8oYSxqLGMpCkMuTm0uaShqLG0pfWVsc2V7Zm9yKHM9by5sZW5ndGgs
+bD0wLG49MDtuPG8ubGVuZ3RoO28ubGVuZ3RoPT09c3x8KDAsSC5saykobyksKytuKXtrPUguaChvW25d
+KQppZihjLng0KGspKXsrK2wKQy5ObS5pKGosYy5xKDAsaykpfWVsc2V7bT1yW2tdCmlmKEMuTnY9PT1t
+KXJldHVybiBILnpvKGEsaixjKQpDLk5tLmkoaixtKX19aWYobCE9PWMuYSlyZXR1cm4gSC56byhhLGos
+Yyl9cmV0dXJuIHAuYXBwbHkoYSxqKX19LApwWTpmdW5jdGlvbihhKXt0aHJvdyBILmIoSC50TChhKSl9
+LApPSDpmdW5jdGlvbihhLGIpe2lmKGE9PW51bGwpSi5IbShhKQp0aHJvdyBILmIoSC5IWShhLGIpKX0s
+CkhZOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyPSJpbmRleCIKaWYoIUgub2soYikpcmV0dXJuIG5ldyBQ
+LnUoITAsYixyLG51bGwpCnQ9SC51UChKLkhtKGEpKQppZighKGI8MCkpe2lmKHR5cGVvZiB0IT09Im51
+bWJlciIpcmV0dXJuIEgucFkodCkKcz1iPj10fWVsc2Ugcz0hMAppZihzKXJldHVybiBQLkNmKGIsYSxy
+LG51bGwsdCkKcmV0dXJuIFAuTzcoYixyKX0sCmF1OmZ1bmN0aW9uKGEsYixjKXtpZihhPmMpcmV0dXJu
+IFAuVEUoYSwwLGMsInN0YXJ0IixudWxsKQppZihiIT1udWxsKWlmKGI8YXx8Yj5jKXJldHVybiBQLlRF
+KGIsYSxjLCJlbmQiLG51bGwpCnJldHVybiBuZXcgUC51KCEwLGIsImVuZCIsbnVsbCl9LAp0TDpmdW5j
+dGlvbihhKXtyZXR1cm4gbmV3IFAudSghMCxhLG51bGwsbnVsbCl9LApiOmZ1bmN0aW9uKGEpe3ZhciB0
+LHMKaWYoYT09bnVsbClhPW5ldyBQLm4oKQp0PW5ldyBFcnJvcigpCnQuZGFydEV4Y2VwdGlvbj1hCnM9
+SC54CmlmKCJkZWZpbmVQcm9wZXJ0eSIgaW4gT2JqZWN0KXtPYmplY3QuZGVmaW5lUHJvcGVydHkodCwi
+bWVzc2FnZSIse2dldDpzfSkKdC5uYW1lPSIifWVsc2UgdC50b1N0cmluZz1zCnJldHVybiB0fSwKeDpm
+dW5jdGlvbigpe3JldHVybiBKLmoodGhpcy5kYXJ0RXhjZXB0aW9uKX0sCnZoOmZ1bmN0aW9uKGEpe3Ro
+cm93IEguYihhKX0sCmxrOmZ1bmN0aW9uKGEpe3Rocm93IEguYihQLmE0KGEpKX0sCmNNOmZ1bmN0aW9u
+KGEpe3ZhciB0LHMscixxLHAsbwphPUguZUEoYS5yZXBsYWNlKFN0cmluZyh7fSksJyRyZWNlaXZlciQn
+KSkKdD1hLm1hdGNoKC9cXFwkW2EtekEtWl0rXFxcJC9nKQppZih0PT1udWxsKXQ9SC5WTShbXSx1LnMp
+CnM9dC5pbmRleE9mKCJcXCRhcmd1bWVudHNcXCQiKQpyPXQuaW5kZXhPZigiXFwkYXJndW1lbnRzRXhw
+clxcJCIpCnE9dC5pbmRleE9mKCJcXCRleHByXFwkIikKcD10LmluZGV4T2YoIlxcJG1ldGhvZFxcJCIp
+Cm89dC5pbmRleE9mKCJcXCRyZWNlaXZlclxcJCIpCnJldHVybiBuZXcgSC5mOShhLnJlcGxhY2UobmV3
+IFJlZ0V4cCgnXFxcXFxcJGFyZ3VtZW50c1xcXFxcXCQnLCdnJyksJygoPzp4fFteeF0pKiknKS5yZXBs
+YWNlKG5ldyBSZWdFeHAoJ1xcXFxcXCRhcmd1bWVudHNFeHByXFxcXFxcJCcsJ2cnKSwnKCg/Onh8W154
+XSkqKScpLnJlcGxhY2UobmV3IFJlZ0V4cCgnXFxcXFxcJGV4cHJcXFxcXFwkJywnZycpLCcoKD86eHxb
+XnhdKSopJykucmVwbGFjZShuZXcgUmVnRXhwKCdcXFxcXFwkbWV0aG9kXFxcXFxcJCcsJ2cnKSwnKCg/
+Onh8W154XSkqKScpLnJlcGxhY2UobmV3IFJlZ0V4cCgnXFxcXFxcJHJlY2VpdmVyXFxcXFxcJCcsJ2cn
+KSwnKCg/Onh8W154XSkqKScpLHMscixxLHAsbyl9LApTNzpmdW5jdGlvbihhKXtyZXR1cm4gZnVuY3Rp
+b24oJGV4cHIkKXt2YXIgJGFyZ3VtZW50c0V4cHIkPSckYXJndW1lbnRzJCcKdHJ5eyRleHByJC4kbWV0
+aG9kJCgkYXJndW1lbnRzRXhwciQpfWNhdGNoKHQpe3JldHVybiB0Lm1lc3NhZ2V9fShhKX0sCk1qOmZ1
+bmN0aW9uKGEpe3JldHVybiBmdW5jdGlvbigkZXhwciQpe3RyeXskZXhwciQuJG1ldGhvZCR9Y2F0Y2go
+dCl7cmV0dXJuIHQubWVzc2FnZX19KGEpfSwKSWo6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gbmV3IEguVzAo
+YSxiPT1udWxsP251bGw6Yi5tZXRob2QpfSwKVDM6ZnVuY3Rpb24oYSxiKXt2YXIgdD1iPT1udWxsLHM9
+dD9udWxsOmIubWV0aG9kCnJldHVybiBuZXcgSC5heihhLHMsdD9udWxsOmIucmVjZWl2ZXIpfSwKUnU6
+ZnVuY3Rpb24oYSl7aWYoYT09bnVsbClyZXR1cm4gbmV3IEgudGUoYSkKaWYoYSBpbnN0YW5jZW9mIEgu
+YnEpcmV0dXJuIEgudFcoYSxhLmEpCmlmKHR5cGVvZiBhIT09Im9iamVjdCIpcmV0dXJuIGEKaWYoImRh
+cnRFeGNlcHRpb24iIGluIGEpcmV0dXJuIEgudFcoYSxhLmRhcnRFeGNlcHRpb24pCnJldHVybiBILnRs
+KGEpfSwKdFc6ZnVuY3Rpb24oYSxiKXtpZih1Lm0uYihiKSlpZihiLiR0aHJvd25Kc0Vycm9yPT1udWxs
+KWIuJHRocm93bkpzRXJyb3I9YQpyZXR1cm4gYn0sCnRsOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHAs
+byxuLG0sbCxrLGosaSxoLGcsZj1udWxsCmlmKCEoIm1lc3NhZ2UiIGluIGEpKXJldHVybiBhCnQ9YS5t
+ZXNzYWdlCmlmKCJudW1iZXIiIGluIGEmJnR5cGVvZiBhLm51bWJlcj09Im51bWJlciIpe3M9YS5udW1i
+ZXIKcj1zJjY1NTM1CmlmKChDLmpuLndHKHMsMTYpJjgxOTEpPT09MTApc3dpdGNoKHIpe2Nhc2UgNDM4
+OnJldHVybiBILnRXKGEsSC5UMyhILkVqKHQpKyIgKEVycm9yICIrcisiKSIsZikpCmNhc2UgNDQ1OmNh
+c2UgNTAwNzpyZXR1cm4gSC50VyhhLEguSWooSC5Faih0KSsiIChFcnJvciAiK3IrIikiLGYpKX19aWYo
+YSBpbnN0YW5jZW9mIFR5cGVFcnJvcil7cT0kLlNuKCkKcD0kLmxxKCkKbz0kLk45KCkKbj0kLmlJKCkK
+bT0kLlVOKCkKbD0kLlpoKCkKaz0kLnJOKCkKJC5jMygpCmo9JC5ISygpCmk9JC5yMSgpCmg9cS5xUyh0
+KQppZihoIT1udWxsKXJldHVybiBILnRXKGEsSC5UMyhILmgodCksaCkpCmVsc2V7aD1wLnFTKHQpCmlm
+KGghPW51bGwpe2gubWV0aG9kPSJjYWxsIgpyZXR1cm4gSC50VyhhLEguVDMoSC5oKHQpLGgpKX1lbHNl
+e2g9by5xUyh0KQppZihoPT1udWxsKXtoPW4ucVModCkKaWYoaD09bnVsbCl7aD1tLnFTKHQpCmlmKGg9
+PW51bGwpe2g9bC5xUyh0KQppZihoPT1udWxsKXtoPWsucVModCkKaWYoaD09bnVsbCl7aD1uLnFTKHQp
+CmlmKGg9PW51bGwpe2g9ai5xUyh0KQppZihoPT1udWxsKXtoPWkucVModCkKZz1oIT1udWxsfWVsc2Ug
+Zz0hMH1lbHNlIGc9ITB9ZWxzZSBnPSEwfWVsc2UgZz0hMH1lbHNlIGc9ITB9ZWxzZSBnPSEwfWVsc2Ug
+Zz0hMAppZihnKXJldHVybiBILnRXKGEsSC5JaihILmgodCksaCkpfX1yZXR1cm4gSC50VyhhLG5ldyBI
+LnZWKHR5cGVvZiB0PT0ic3RyaW5nIj90OiIiKSl9aWYoYSBpbnN0YW5jZW9mIFJhbmdlRXJyb3Ipe2lm
+KHR5cGVvZiB0PT0ic3RyaW5nIiYmdC5pbmRleE9mKCJjYWxsIHN0YWNrIikhPT0tMSlyZXR1cm4gbmV3
+IFAuS1koKQp0PWZ1bmN0aW9uKGIpe3RyeXtyZXR1cm4gU3RyaW5nKGIpfWNhdGNoKGUpe31yZXR1cm4g
+bnVsbH0oYSkKcmV0dXJuIEgudFcoYSxuZXcgUC51KCExLGYsZix0eXBlb2YgdD09InN0cmluZyI/dC5y
+ZXBsYWNlKC9eUmFuZ2VFcnJvcjpccyovLCIiKTp0KSl9aWYodHlwZW9mIEludGVybmFsRXJyb3I9PSJm
+dW5jdGlvbiImJmEgaW5zdGFuY2VvZiBJbnRlcm5hbEVycm9yKWlmKHR5cGVvZiB0PT0ic3RyaW5nIiYm
+dD09PSJ0b28gbXVjaCByZWN1cnNpb24iKXJldHVybiBuZXcgUC5LWSgpCnJldHVybiBhfSwKdHM6ZnVu
+Y3Rpb24oYSl7dmFyIHQKaWYoYSBpbnN0YW5jZW9mIEguYnEpcmV0dXJuIGEuYgppZihhPT1udWxsKXJl
+dHVybiBuZXcgSC5YTyhhKQp0PWEuJGNhY2hlZFRyYWNlCmlmKHQhPW51bGwpcmV0dXJuIHQKcmV0dXJu
+IGEuJGNhY2hlZFRyYWNlPW5ldyBILlhPKGEpfSwKQjc6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscT1h
+Lmxlbmd0aApmb3IodD0wO3Q8cTt0PXIpe3M9dCsxCnI9cysxCmIuWSgwLGFbdF0sYVtzXSl9cmV0dXJu
+IGJ9LApmdDpmdW5jdGlvbihhLGIsYyxkLGUsZil7dS5ZLmEoYSkKc3dpdGNoKEgudVAoYikpe2Nhc2Ug
+MDpyZXR1cm4gYS4kMCgpCmNhc2UgMTpyZXR1cm4gYS4kMShjKQpjYXNlIDI6cmV0dXJuIGEuJDIoYyxk
+KQpjYXNlIDM6cmV0dXJuIGEuJDMoYyxkLGUpCmNhc2UgNDpyZXR1cm4gYS4kNChjLGQsZSxmKX10aHJv
+dyBILmIobmV3IFAuQ0QoIlVuc3VwcG9ydGVkIG51bWJlciBvZiBhcmd1bWVudHMgZm9yIHdyYXBwZWQg
+Y2xvc3VyZSIpKX0sCnRSOmZ1bmN0aW9uKGEsYil7dmFyIHQKaWYoYT09bnVsbClyZXR1cm4gbnVsbAp0
+PWEuJGlkZW50aXR5CmlmKCEhdClyZXR1cm4gdAp0PWZ1bmN0aW9uKGMsZCxlKXtyZXR1cm4gZnVuY3Rp
+b24oZixnLGgsaSl7cmV0dXJuIGUoYyxkLGYsZyxoLGkpfX0oYSxiLEguZnQpCmEuJGlkZW50aXR5PXQK
+cmV0dXJuIHR9LAppQTpmdW5jdGlvbihhLGIsYyxkLGUsZixnKXt2YXIgdCxzLHIscSxwLG8sbixtPWJb
+MF0sbD1tLiRjYWxsTmFtZSxrPWU/T2JqZWN0LmNyZWF0ZShuZXcgSC56eCgpLmNvbnN0cnVjdG9yLnBy
+b3RvdHlwZSk6T2JqZWN0LmNyZWF0ZShuZXcgSC5yVChudWxsLG51bGwsbnVsbCwiIikuY29uc3RydWN0
+b3IucHJvdG90eXBlKQprLiRpbml0aWFsaXplPWsuY29uc3RydWN0b3IKaWYoZSl0PWZ1bmN0aW9uIHN0
+YXRpY190ZWFyX29mZigpe3RoaXMuJGluaXRpYWxpemUoKX0KZWxzZXtzPSQueWoKaWYodHlwZW9mIHMh
+PT0ibnVtYmVyIilyZXR1cm4gcy5oKCkKJC55aj1zKzEKcz1uZXcgRnVuY3Rpb24oImEsYixjLGQiK3Ms
+InRoaXMuJGluaXRpYWxpemUoYSxiLGMsZCIrcysiKSIpCnQ9c31rLmNvbnN0cnVjdG9yPXQKdC5wcm90
+b3R5cGU9awppZighZSl7cj1ILmJ4KGEsbSxmKQpyLiRyZWZsZWN0aW9uSW5mbz1kfWVsc2V7ay4kc3Rh
+dGljX25hbWU9ZwpyPW19ay4kUz1ILmltKGQsZSxmKQprW2xdPXIKZm9yKHE9cixwPTE7cDxiLmxlbmd0
+aDsrK3Ape289YltwXQpuPW8uJGNhbGxOYW1lCmlmKG4hPW51bGwpe289ZT9vOkguYngoYSxvLGYpCmtb
+bl09b31pZihwPT09Yyl7by4kcmVmbGVjdGlvbkluZm89ZApxPW99fWsuJEM9cQprLiRSPW0uJFIKay4k
+RD1tLiRECnJldHVybiB0fSwKaW06ZnVuY3Rpb24oYSxiLGMpe3ZhciB0CmlmKHR5cGVvZiBhPT0ibnVt
+YmVyIilyZXR1cm4gZnVuY3Rpb24oZCxlKXtyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gZChlKX19KEgu
+QnAsYSkKaWYodHlwZW9mIGE9PSJzdHJpbmciKXtpZihiKXRocm93IEguYigiQ2Fubm90IGNvbXB1dGUg
+c2lnbmF0dXJlIGZvciBzdGF0aWMgdGVhcm9mZi4iKQp0PWM/SC5QVzpILlRuCnJldHVybiBmdW5jdGlv
+bihkLGUpe3JldHVybiBmdW5jdGlvbigpe3JldHVybiBlKHRoaXMsZCl9fShhLHQpfXRocm93IEguYigi
+RXJyb3IgaW4gZnVuY3Rpb25UeXBlIG9mIHRlYXJvZmYiKX0sCnZxOmZ1bmN0aW9uKGEsYixjLGQpe3Zh
+ciB0PUguRFYKc3dpdGNoKGI/LTE6YSl7Y2FzZSAwOnJldHVybiBmdW5jdGlvbihlLGYpe3JldHVybiBm
+dW5jdGlvbigpe3JldHVybiBmKHRoaXMpW2VdKCl9fShjLHQpCmNhc2UgMTpyZXR1cm4gZnVuY3Rpb24o
+ZSxmKXtyZXR1cm4gZnVuY3Rpb24oZyl7cmV0dXJuIGYodGhpcylbZV0oZyl9fShjLHQpCmNhc2UgMjpy
+ZXR1cm4gZnVuY3Rpb24oZSxmKXtyZXR1cm4gZnVuY3Rpb24oZyxoKXtyZXR1cm4gZih0aGlzKVtlXShn
+LGgpfX0oYyx0KQpjYXNlIDM6cmV0dXJuIGZ1bmN0aW9uKGUsZil7cmV0dXJuIGZ1bmN0aW9uKGcsaCxp
+KXtyZXR1cm4gZih0aGlzKVtlXShnLGgsaSl9fShjLHQpCmNhc2UgNDpyZXR1cm4gZnVuY3Rpb24oZSxm
+KXtyZXR1cm4gZnVuY3Rpb24oZyxoLGksail7cmV0dXJuIGYodGhpcylbZV0oZyxoLGksail9fShjLHQp
+CmNhc2UgNTpyZXR1cm4gZnVuY3Rpb24oZSxmKXtyZXR1cm4gZnVuY3Rpb24oZyxoLGksaixrKXtyZXR1
+cm4gZih0aGlzKVtlXShnLGgsaSxqLGspfX0oYyx0KQpkZWZhdWx0OnJldHVybiBmdW5jdGlvbihlLGYp
+e3JldHVybiBmdW5jdGlvbigpe3JldHVybiBlLmFwcGx5KGYodGhpcyksYXJndW1lbnRzKX19KGQsdCl9
+fSwKYng6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixxLHAsbyxuCmlmKGMpcmV0dXJuIEguSGYoYSxi
+KQp0PWIuJHN0dWJOYW1lCnM9Yi5sZW5ndGgKcj1hW3RdCnE9Yj09bnVsbD9yPT1udWxsOmI9PT1yCnA9
+IXF8fHM+PTI3CmlmKHApcmV0dXJuIEgudnEocywhcSx0LGIpCmlmKHM9PT0wKXtxPSQueWoKaWYodHlw
+ZW9mIHEhPT0ibnVtYmVyIilyZXR1cm4gcS5oKCkKJC55aj1xKzEKbz0ic2VsZiIrcQpyZXR1cm4gbmV3
+IEZ1bmN0aW9uKCJyZXR1cm4gZnVuY3Rpb24oKXt2YXIgIitvKyIgPSB0aGlzLiIrSC5FaihILm9OKCkp
+KyI7cmV0dXJuICIrbysiLiIrSC5Faih0KSsiKCk7fSIpKCl9bj0iYWJjZGVmZ2hpamtsbW5vcHFyc3R1
+dnd4eXoiLnNwbGl0KCIiKS5zcGxpY2UoMCxzKS5qb2luKCIsIikKcT0kLnlqCmlmKHR5cGVvZiBxIT09
+Im51bWJlciIpcmV0dXJuIHEuaCgpCiQueWo9cSsxCm4rPXEKcmV0dXJuIG5ldyBGdW5jdGlvbigicmV0
+dXJuIGZ1bmN0aW9uKCIrbisiKXtyZXR1cm4gdGhpcy4iK0guRWooSC5vTigpKSsiLiIrSC5Faih0KSsi
+KCIrbisiKTt9IikoKX0sClo0OmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0PUguRFYscz1ILnlTCnN3aXRj
+aChiPy0xOmEpe2Nhc2UgMDp0aHJvdyBILmIoSC5FZigiSW50ZXJjZXB0ZWQgZnVuY3Rpb24gd2l0aCBu
+byBhcmd1bWVudHMuIikpCmNhc2UgMTpyZXR1cm4gZnVuY3Rpb24oZSxmLGcpe3JldHVybiBmdW5jdGlv
+bigpe3JldHVybiBmKHRoaXMpW2VdKGcodGhpcykpfX0oYyx0LHMpCmNhc2UgMjpyZXR1cm4gZnVuY3Rp
+b24oZSxmLGcpe3JldHVybiBmdW5jdGlvbihoKXtyZXR1cm4gZih0aGlzKVtlXShnKHRoaXMpLGgpfX0o
+Yyx0LHMpCmNhc2UgMzpyZXR1cm4gZnVuY3Rpb24oZSxmLGcpe3JldHVybiBmdW5jdGlvbihoLGkpe3Jl
+dHVybiBmKHRoaXMpW2VdKGcodGhpcyksaCxpKX19KGMsdCxzKQpjYXNlIDQ6cmV0dXJuIGZ1bmN0aW9u
+KGUsZixnKXtyZXR1cm4gZnVuY3Rpb24oaCxpLGope3JldHVybiBmKHRoaXMpW2VdKGcodGhpcyksaCxp
+LGopfX0oYyx0LHMpCmNhc2UgNTpyZXR1cm4gZnVuY3Rpb24oZSxmLGcpe3JldHVybiBmdW5jdGlvbiho
+LGksaixrKXtyZXR1cm4gZih0aGlzKVtlXShnKHRoaXMpLGgsaSxqLGspfX0oYyx0LHMpCmNhc2UgNjpy
+ZXR1cm4gZnVuY3Rpb24oZSxmLGcpe3JldHVybiBmdW5jdGlvbihoLGksaixrLGwpe3JldHVybiBmKHRo
+aXMpW2VdKGcodGhpcyksaCxpLGosayxsKX19KGMsdCxzKQpkZWZhdWx0OnJldHVybiBmdW5jdGlvbihl
+LGYsZyxoKXtyZXR1cm4gZnVuY3Rpb24oKXtoPVtnKHRoaXMpXQpBcnJheS5wcm90b3R5cGUucHVzaC5h
+cHBseShoLGFyZ3VtZW50cykKcmV0dXJuIGUuYXBwbHkoZih0aGlzKSxoKX19KGQsdCxzKX19LApIZjpm
+dW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHAsbyxuPUgub04oKSxtPSQuUDQKaWYobT09bnVsbCltPSQu
+UDQ9SC5FMigicmVjZWl2ZXIiKQp0PWIuJHN0dWJOYW1lCnM9Yi5sZW5ndGgKcj1hW3RdCnE9Yj09bnVs
+bD9yPT1udWxsOmI9PT1yCnA9IXF8fHM+PTI4CmlmKHApcmV0dXJuIEguWjQocywhcSx0LGIpCmlmKHM9
+PT0xKXtxPSJyZXR1cm4gZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy4iK0guRWoobikrIi4iK0guRWoodCkr
+Iih0aGlzLiIrbSsiKTsiCnA9JC55agppZih0eXBlb2YgcCE9PSJudW1iZXIiKXJldHVybiBwLmgoKQok
+LnlqPXArMQpyZXR1cm4gbmV3IEZ1bmN0aW9uKHErcCsifSIpKCl9bz0iYWJjZGVmZ2hpamtsbW5vcHFy
+c3R1dnd4eXoiLnNwbGl0KCIiKS5zcGxpY2UoMCxzLTEpLmpvaW4oIiwiKQpxPSJyZXR1cm4gZnVuY3Rp
+b24oIitvKyIpe3JldHVybiB0aGlzLiIrSC5FaihuKSsiLiIrSC5Faih0KSsiKHRoaXMuIittKyIsICIr
+bysiKTsiCnA9JC55agppZih0eXBlb2YgcCE9PSJudW1iZXIiKXJldHVybiBwLmgoKQokLnlqPXArMQpy
+ZXR1cm4gbmV3IEZ1bmN0aW9uKHErcCsifSIpKCl9LApLcTpmdW5jdGlvbihhLGIsYyxkLGUsZixnKXty
+ZXR1cm4gSC5pQShhLGIsYyxkLCEhZSwhIWYsZyl9LApUbjpmdW5jdGlvbihhLGIpe3JldHVybiBILmNF
+KHYudHlwZVVuaXZlcnNlLEgueihhLmEpLGIpfSwKUFc6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSC5jRSh2
+LnR5cGVVbml2ZXJzZSxILnooYS5jKSxiKX0sCkRWOmZ1bmN0aW9uKGEpe3JldHVybiBhLmF9LAp5Uzpm
+dW5jdGlvbihhKXtyZXR1cm4gYS5jfSwKb046ZnVuY3Rpb24oKXt2YXIgdD0kLm1KCnJldHVybiB0PT1u
+dWxsPyQubUo9SC5FMigic2VsZiIpOnR9LApFMjpmdW5jdGlvbihhKXt2YXIgdCxzLHIscT1uZXcgSC5y
+VCgic2VsZiIsInRhcmdldCIsInJlY2VpdmVyIiwibmFtZSIpLHA9Si5FcChPYmplY3QuZ2V0T3duUHJv
+cGVydHlOYW1lcyhxKSx1LnopCmZvcih0PXAubGVuZ3RoLHM9MDtzPHQ7KytzKXtyPXBbc10KaWYocVty
+XT09PWEpcmV0dXJuIHJ9dGhyb3cgSC5iKFAueFkoIkZpZWxkIG5hbWUgIithKyIgbm90IGZvdW5kLiIp
+KX0sCm9UOmZ1bmN0aW9uKGEpe2lmKGE9PW51bGwpSC5mTygiYm9vbGVhbiBleHByZXNzaW9uIG11c3Qg
+bm90IGJlIG51bGwiKQpyZXR1cm4gYX0sCmZPOmZ1bmN0aW9uKGEpe3Rocm93IEguYihuZXcgSC5rWShh
+KSl9LAphZzpmdW5jdGlvbihhKXt0aHJvdyBILmIobmV3IFAuYyhhKSl9LApFZjpmdW5jdGlvbihhKXty
+ZXR1cm4gbmV3IEguRXEoYSl9LApZZzpmdW5jdGlvbihhKXtyZXR1cm4gdi5nZXRJc29sYXRlVGFnKGEp
+fSwKVk06ZnVuY3Rpb24oYSxiKXthW3YuYXJyYXlSdGldPWIKcmV0dXJuIGF9LApvWDpmdW5jdGlvbihh
+KXtpZihhPT1udWxsKXJldHVybiBudWxsCnJldHVybiBhLiR0aX0sCklNOmZ1bmN0aW9uKGEsYixjKXty
+ZXR1cm4gSC5ZOShhWyIkYSIrSC5FaihjKV0sSC5vWChiKSl9LApZOTpmdW5jdGlvbihhLGIpe2lmKGE9
+PW51bGwpcmV0dXJuIGIKYT1hLmFwcGx5KG51bGwsYikKaWYoYT09bnVsbClyZXR1cm4gbnVsbAppZihB
+cnJheS5pc0FycmF5KGEpKXJldHVybiBhCmlmKHR5cGVvZiBhPT0iZnVuY3Rpb24iKXJldHVybiBhLmFw
+cGx5KG51bGwsYikKcmV0dXJuIGJ9LApJRzpmdW5jdGlvbihhLGIsYyl7cmV0dXJuIGEuYXBwbHkoYixI
+Llk5KEouaWEoYilbIiRhIitILkVqKGMpXSxILm9YKGIpKSl9LAppdzpmdW5jdGlvbihhLGIsYyl7T2Jq
+ZWN0LmRlZmluZVByb3BlcnR5KGEsYix7dmFsdWU6YyxlbnVtZXJhYmxlOmZhbHNlLHdyaXRhYmxlOnRy
+dWUsY29uZmlndXJhYmxlOnRydWV9KX0sCnczOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHAsbz1ILmgo
+JC5ORi4kMShhKSksbj0kLm53W29dCmlmKG4hPW51bGwpe09iamVjdC5kZWZpbmVQcm9wZXJ0eShhLHYu
+ZGlzcGF0Y2hQcm9wZXJ0eU5hbWUse3ZhbHVlOm4sZW51bWVyYWJsZTpmYWxzZSx3cml0YWJsZTp0cnVl
+LGNvbmZpZ3VyYWJsZTp0cnVlfSkKcmV0dXJuIG4uaX10PSQudnZbb10KaWYodCE9bnVsbClyZXR1cm4g
+dApzPXYuaW50ZXJjZXB0b3JzQnlUYWdbb10KaWYocz09bnVsbCl7cj1ILmsoJC5UWC4kMihhLG8pKQpp
+ZihyIT1udWxsKXtuPSQubndbcl0KaWYobiE9bnVsbCl7T2JqZWN0LmRlZmluZVByb3BlcnR5KGEsdi5k
+aXNwYXRjaFByb3BlcnR5TmFtZSx7dmFsdWU6bixlbnVtZXJhYmxlOmZhbHNlLHdyaXRhYmxlOnRydWUs
+Y29uZmlndXJhYmxlOnRydWV9KQpyZXR1cm4gbi5pfXQ9JC52dltyXQppZih0IT1udWxsKXJldHVybiB0
+CnM9di5pbnRlcmNlcHRvcnNCeVRhZ1tyXQpvPXJ9fWlmKHM9PW51bGwpcmV0dXJuIG51bGwKdD1zLnBy
+b3RvdHlwZQpxPW9bMF0KaWYocT09PSIhIil7bj1ILlZhKHQpCiQubndbb109bgpPYmplY3QuZGVmaW5l
+UHJvcGVydHkoYSx2LmRpc3BhdGNoUHJvcGVydHlOYW1lLHt2YWx1ZTpuLGVudW1lcmFibGU6ZmFsc2Us
+d3JpdGFibGU6dHJ1ZSxjb25maWd1cmFibGU6dHJ1ZX0pCnJldHVybiBuLml9aWYocT09PSJ+Iil7JC52
+dltvXT10CnJldHVybiB0fWlmKHE9PT0iLSIpe3A9SC5WYSh0KQpPYmplY3QuZGVmaW5lUHJvcGVydHko
+T2JqZWN0LmdldFByb3RvdHlwZU9mKGEpLHYuZGlzcGF0Y2hQcm9wZXJ0eU5hbWUse3ZhbHVlOnAsZW51
+bWVyYWJsZTpmYWxzZSx3cml0YWJsZTp0cnVlLGNvbmZpZ3VyYWJsZTp0cnVlfSkKcmV0dXJuIHAuaX1p
+ZihxPT09IisiKXJldHVybiBILkxjKGEsdCkKaWYocT09PSIqIil0aHJvdyBILmIoUC5TWShvKSkKaWYo
+di5sZWFmVGFnc1tvXT09PXRydWUpe3A9SC5WYSh0KQpPYmplY3QuZGVmaW5lUHJvcGVydHkoT2JqZWN0
+LmdldFByb3RvdHlwZU9mKGEpLHYuZGlzcGF0Y2hQcm9wZXJ0eU5hbWUse3ZhbHVlOnAsZW51bWVyYWJs
+ZTpmYWxzZSx3cml0YWJsZTp0cnVlLGNvbmZpZ3VyYWJsZTp0cnVlfSkKcmV0dXJuIHAuaX1lbHNlIHJl
+dHVybiBILkxjKGEsdCl9LApMYzpmdW5jdGlvbihhLGIpe3ZhciB0PU9iamVjdC5nZXRQcm90b3R5cGVP
+ZihhKQpPYmplY3QuZGVmaW5lUHJvcGVydHkodCx2LmRpc3BhdGNoUHJvcGVydHlOYW1lLHt2YWx1ZTpK
+LlF1KGIsdCxudWxsLG51bGwpLGVudW1lcmFibGU6ZmFsc2Usd3JpdGFibGU6dHJ1ZSxjb25maWd1cmFi
+bGU6dHJ1ZX0pCnJldHVybiBifSwKVmE6ZnVuY3Rpb24oYSl7cmV0dXJuIEouUXUoYSwhMSxudWxsLCEh
+YS4kaVhqKX0sClZGOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1iLnByb3RvdHlwZQppZih2LmxlYWZUYWdz
+W2FdPT09dHJ1ZSlyZXR1cm4gSC5WYSh0KQplbHNlIHJldHVybiBKLlF1KHQsYyxudWxsLG51bGwpfSwK
+WEQ6ZnVuY3Rpb24oKXtpZighMD09PSQuQnYpcmV0dXJuCiQuQnY9ITAKSC5aMSgpfSwKWjE6ZnVuY3Rp
+b24oKXt2YXIgdCxzLHIscSxwLG8sbixtCiQubnc9T2JqZWN0LmNyZWF0ZShudWxsKQokLnZ2PU9iamVj
+dC5jcmVhdGUobnVsbCkKSC5rTygpCnQ9di5pbnRlcmNlcHRvcnNCeVRhZwpzPU9iamVjdC5nZXRPd25Q
+cm9wZXJ0eU5hbWVzKHQpCmlmKHR5cGVvZiB3aW5kb3chPSJ1bmRlZmluZWQiKXt3aW5kb3cKcj1mdW5j
+dGlvbigpe30KZm9yKHE9MDtxPHMubGVuZ3RoOysrcSl7cD1zW3FdCm89JC54Ny4kMShwKQppZihvIT1u
+dWxsKXtuPUguVkYocCx0W3BdLG8pCmlmKG4hPW51bGwpe09iamVjdC5kZWZpbmVQcm9wZXJ0eShvLHYu
+ZGlzcGF0Y2hQcm9wZXJ0eU5hbWUse3ZhbHVlOm4sZW51bWVyYWJsZTpmYWxzZSx3cml0YWJsZTp0cnVl
+LGNvbmZpZ3VyYWJsZTp0cnVlfSkKci5wcm90b3R5cGU9b319fX1mb3IocT0wO3E8cy5sZW5ndGg7Kytx
+KXtwPXNbcV0KaWYoL15bQS1aYS16X10vLnRlc3QocCkpe209dFtwXQp0WyIhIitwXT1tCnRbIn4iK3Bd
+PW0KdFsiLSIrcF09bQp0WyIrIitwXT1tCnRbIioiK3BdPW19fX0sCmtPOmZ1bmN0aW9uKCl7dmFyIHQs
+cyxyLHEscCxvLG49Qy5ZcSgpCm49SC51ZChDLktVLEgudWQoQy5mUSxILnVkKEMuaTcsSC51ZChDLmk3
+LEgudWQoQy54aSxILnVkKEMuZGssSC51ZChDLndiKEMuTzQpLG4pKSkpKSkpCmlmKHR5cGVvZiBkYXJ0
+TmF0aXZlRGlzcGF0Y2hIb29rc1RyYW5zZm9ybWVyIT0idW5kZWZpbmVkIil7dD1kYXJ0TmF0aXZlRGlz
+cGF0Y2hIb29rc1RyYW5zZm9ybWVyCmlmKHR5cGVvZiB0PT0iZnVuY3Rpb24iKXQ9W3RdCmlmKHQuY29u
+c3RydWN0b3I9PUFycmF5KWZvcihzPTA7czx0Lmxlbmd0aDsrK3Mpe3I9dFtzXQppZih0eXBlb2Ygcj09
+ImZ1bmN0aW9uIiluPXIobil8fG59fXE9bi5nZXRUYWcKcD1uLmdldFVua25vd25UYWcKbz1uLnByb3Rv
+dHlwZUZvclRhZwokLk5GPW5ldyBILmRDKHEpCiQuVFg9bmV3IEgud04ocCkKJC54Nz1uZXcgSC5WWChv
+KX0sCnVkOmZ1bmN0aW9uKGEsYil7cmV0dXJuIGEoYil8fGJ9LAp2NDpmdW5jdGlvbihhLGIsYyxkLGUs
+Zil7dmFyIHQ9Yj8ibSI6IiIscz1jPyIiOiJpIixyPWQ/InUiOiIiLHE9ZT8icyI6IiIscD1mPyJnIjoi
+IixvPWZ1bmN0aW9uKGcsaCl7dHJ5e3JldHVybiBuZXcgUmVnRXhwKGcsaCl9Y2F0Y2gobil7cmV0dXJu
+IG59fShhLHQrcytyK3ErcCkKaWYobyBpbnN0YW5jZW9mIFJlZ0V4cClyZXR1cm4gbwp0aHJvdyBILmIo
+UC5ycigiSWxsZWdhbCBSZWdFeHAgcGF0dGVybiAoIitTdHJpbmcobykrIikiLGEsbnVsbCkpfSwKbTI6
+ZnVuY3Rpb24oYSxiLGMpe3ZhciB0CmlmKHR5cGVvZiBiPT0ic3RyaW5nIilyZXR1cm4gYS5pbmRleE9m
+KGIsYyk+PTAKZWxzZSBpZihiIGluc3RhbmNlb2YgSC5WUil7dD1DLnhCLkcoYSxjKQpyZXR1cm4gYi5i
+LnRlc3QodCl9ZWxzZXt0PUouRkwoYixDLnhCLkcoYSxjKSkKcmV0dXJuIXQuZ2wwKHQpfX0sCkE0OmZ1
+bmN0aW9uKGEpe2lmKGEuaW5kZXhPZigiJCIsMCk+PTApcmV0dXJuIGEucmVwbGFjZSgvXCQvZywiJCQk
+JCIpCnJldHVybiBhfSwKZUE6ZnVuY3Rpb24oYSl7aWYoL1tbXF17fSgpKis/LlxcXiR8XS8udGVzdChh
+KSlyZXR1cm4gYS5yZXBsYWNlKC9bW1xde30oKSorPy5cXF4kfF0vZywiXFwkJiIpCnJldHVybiBhfSwK
+eXM6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0PUgubk0oYSxiLGMpCnJldHVybiB0fSwKbk06ZnVuY3Rpb24o
+YSxiLGMpe3ZhciB0LHMscixxCmlmKGI9PT0iIil7aWYoYT09PSIiKXJldHVybiBjCnQ9YS5sZW5ndGgK
+Zm9yKHM9YyxyPTA7cjx0OysrcilzPXMrYVtyXStjCnJldHVybiBzLmNoYXJDb2RlQXQoMCk9PTA/czpz
+fXE9YS5pbmRleE9mKGIsMCkKaWYocTwwKXJldHVybiBhCmlmKGEubGVuZ3RoPDUwMHx8Yy5pbmRleE9m
+KCIkIiwwKT49MClyZXR1cm4gYS5zcGxpdChiKS5qb2luKGMpCnJldHVybiBhLnJlcGxhY2UobmV3IFJl
+Z0V4cChILmVBKGIpLCdnJyksSC5BNChjKSl9LApQRDpmdW5jdGlvbiBQRChhLGIpe3RoaXMuYT1hCnRo
+aXMuJHRpPWJ9LApXVTpmdW5jdGlvbiBXVSgpe30sCkxQOmZ1bmN0aW9uIExQKGEsYixjLGQpe3ZhciBf
+PXRoaXMKXy5hPWEKXy5iPWIKXy5jPWMKXy4kdGk9ZH0sClhSOmZ1bmN0aW9uIFhSKGEsYil7dGhpcy5h
+PWEKdGhpcy4kdGk9Yn0sCkxJOmZ1bmN0aW9uIExJKGEsYixjLGQsZSl7dmFyIF89dGhpcwpfLmE9YQpf
+LmM9YgpfLmQ9YwpfLmU9ZApfLmY9ZX0sCkNqOmZ1bmN0aW9uIENqKGEsYixjKXt0aGlzLmE9YQp0aGlz
+LmI9Ygp0aGlzLmM9Y30sCmY5OmZ1bmN0aW9uIGY5KGEsYixjLGQsZSxmKXt2YXIgXz10aGlzCl8uYT1h
+Cl8uYj1iCl8uYz1jCl8uZD1kCl8uZT1lCl8uZj1mfSwKVzA6ZnVuY3Rpb24gVzAoYSxiKXt0aGlzLmE9
+YQp0aGlzLmI9Yn0sCmF6OmZ1bmN0aW9uIGF6KGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9
+Y30sCnZWOmZ1bmN0aW9uIHZWKGEpe3RoaXMuYT1hfSwKdGU6ZnVuY3Rpb24gdGUoYSl7dGhpcy5hPWF9
+LApicTpmdW5jdGlvbiBicShhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKWE86ZnVuY3Rpb24gWE8oYSl7
+dGhpcy5hPWEKdGhpcy5iPW51bGx9LAp2OmZ1bmN0aW9uIHYoKXt9LApsYzpmdW5jdGlvbiBsYygpe30s
+Cnp4OmZ1bmN0aW9uIHp4KCl7fSwKclQ6ZnVuY3Rpb24gclQoYSxiLGMsZCl7dmFyIF89dGhpcwpfLmE9
+YQpfLmI9YgpfLmM9YwpfLmQ9ZH0sCkVxOmZ1bmN0aW9uIEVxKGEpe3RoaXMuYT1hfSwKa1k6ZnVuY3Rp
+b24ga1koYSl7dGhpcy5hPWF9LAprcjpmdW5jdGlvbiBrcigpe30sCk41OmZ1bmN0aW9uIE41KGEpe3Zh
+ciBfPXRoaXMKXy5hPTAKXy5mPV8uZT1fLmQ9Xy5jPV8uYj1udWxsCl8ucj0wCl8uJHRpPWF9LApkYjpm
+dW5jdGlvbiBkYihhLGIpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5kPV8uYz1udWxsfSwKaTU6ZnVu
+Y3Rpb24gaTUoYSxiKXt0aGlzLmE9YQp0aGlzLiR0aT1ifSwKTjY6ZnVuY3Rpb24gTjYoYSxiLGMpe3Zh
+ciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5kPV8uYz1udWxsCl8uJHRpPWN9LApkQzpmdW5jdGlvbiBkQyhh
+KXt0aGlzLmE9YX0sCndOOmZ1bmN0aW9uIHdOKGEpe3RoaXMuYT1hfSwKVlg6ZnVuY3Rpb24gVlgoYSl7
+dGhpcy5hPWF9LApWUjpmdW5jdGlvbiBWUihhLGIpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5kPV8u
+Yz1udWxsfSwKRUs6ZnVuY3Rpb24gRUsoYSl7dGhpcy5iPWF9LApLVzpmdW5jdGlvbiBLVyhhLGIsYyl7
+dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApQYjpmdW5jdGlvbiBQYihhLGIsYyl7dmFyIF89dGhp
+cwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9bnVsbH0sCnRROmZ1bmN0aW9uIHRRKGEsYil7dGhpcy5hPWEK
+dGhpcy5jPWJ9LAp1bjpmdW5jdGlvbiB1bihhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9
+LApTZDpmdW5jdGlvbiBTZChhLGIsYyl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9bnVs
+bH0sClhGOmZ1bmN0aW9uKGEpe3JldHVybiBhfSwKb2Q6ZnVuY3Rpb24oYSxiLGMpe2lmKGE+Pj4wIT09
+YXx8YT49Yyl0aHJvdyBILmIoSC5IWShiLGEpKX0sCnJNOmZ1bmN0aW9uKGEsYixjKXt2YXIgdAppZigh
+KGE+Pj4wIT09YSkpdD1iPj4+MCE9PWJ8fGE+Ynx8Yj5jCmVsc2UgdD0hMAppZih0KXRocm93IEguYihI
+LmF1KGEsYixjKSkKcmV0dXJuIGJ9LApFVDpmdW5jdGlvbiBFVCgpe30sCkxaOmZ1bmN0aW9uIExaKCl7
+fSwKRGc6ZnVuY3Rpb24gRGcoKXt9LApQZzpmdW5jdGlvbiBQZygpe30sCnhqOmZ1bmN0aW9uIHhqKCl7
+fSwKZEU6ZnVuY3Rpb24gZEUoKXt9LApaQTpmdW5jdGlvbiBaQSgpe30sCmRUOmZ1bmN0aW9uIGRUKCl7
+fSwKUHE6ZnVuY3Rpb24gUHEoKXt9LAplRTpmdW5jdGlvbiBlRSgpe30sClY2OmZ1bmN0aW9uIFY2KCl7
+fSwKUkc6ZnVuY3Rpb24gUkcoKXt9LApWUDpmdW5jdGlvbiBWUCgpe30sCldCOmZ1bmN0aW9uIFdCKCl7
+fSwKWkc6ZnVuY3Rpb24gWkcoKXt9LApjejpmdW5jdGlvbihhLGIpe3ZhciB0PWIuYwpyZXR1cm4gdD09
+bnVsbD9iLmM9SC5CKGEsYi56LCEwKTp0fSwKeFo6ZnVuY3Rpb24oYSxiKXt2YXIgdD1iLmMKcmV0dXJu
+IHQ9PW51bGw/Yi5jPUguSihhLCJiOCIsW2Iuel0pOnR9LApRMTpmdW5jdGlvbihhKXt2YXIgdD1hLnkK
+aWYodD09PTZ8fHQ9PT03fHx0PT09OClyZXR1cm4gSC5RMShhLnopCnJldHVybiB0PT09MTF8fHQ9PT0x
+Mn0sCm1EOmZ1bmN0aW9uKGEpe3JldHVybiBhLmN5fSwKTjA6ZnVuY3Rpb24oYSl7cmV0dXJuIEguRSh2
+LnR5cGVVbml2ZXJzZSxhLCExKX0sClBMOmZ1bmN0aW9uKGEsYixjLGEwKXt2YXIgdCxzLHIscSxwLG8s
+bixtLGwsayxqLGksaCxnLGYsZSxkPWIueQpzd2l0Y2goZCl7Y2FzZSA1OmNhc2UgMTpjYXNlIDI6Y2Fz
+ZSAzOmNhc2UgNDpyZXR1cm4gYgpjYXNlIDY6dD1iLnoKcz1ILlBMKGEsdCxjLGEwKQppZihzPT09dCly
+ZXR1cm4gYgpyZXR1cm4gSC5DKGEscywhMCkKY2FzZSA3OnQ9Yi56CnM9SC5QTChhLHQsYyxhMCkKaWYo
+cz09PXQpcmV0dXJuIGIKcmV0dXJuIEguQihhLHMsITApCmNhc2UgODp0PWIuegpzPUguUEwoYSx0LGMs
+YTApCmlmKHM9PT10KXJldHVybiBiCnJldHVybiBILmYoYSxzLCEwKQpjYXNlIDk6cj1iLlEKcT1ILmJa
+KGEscixjLGEwKQppZihxPT09cilyZXR1cm4gYgpyZXR1cm4gSC5KKGEsYi56LHEpCmNhc2UgMTA6cD1i
+LnoKbz1ILlBMKGEscCxjLGEwKQpuPWIuUQptPUguYlooYSxuLGMsYTApCmlmKG89PT1wJiZtPT09bily
+ZXR1cm4gYgpyZXR1cm4gSC5hKGEsbyxtKQpjYXNlIDExOmw9Yi56Cms9SC5QTChhLGwsYyxhMCkKaj1i
+LlEKaT1ILnFUKGEsaixjLGEwKQppZihrPT09bCYmaT09PWopcmV0dXJuIGIKcmV0dXJuIEguZChhLGss
+aSkKY2FzZSAxMjpoPWIuUQphMCs9aC5sZW5ndGgKZz1ILmJaKGEsaCxjLGEwKQpwPWIuegpvPUguUEwo
+YSxwLGMsYTApCmlmKGc9PT1oJiZvPT09cClyZXR1cm4gYgpyZXR1cm4gSC5EKGEsbyxnLCEwKQpjYXNl
+IDEzOmY9Yi56CmlmKGY8YTApcmV0dXJuIGIKZT1jW2YtYTBdCmlmKGU9PW51bGwpcmV0dXJuIGIKcmV0
+dXJuIGUKZGVmYXVsdDp0aHJvdyBILmIoUC5oVigiQXR0ZW1wdGVkIHRvIHN1YnN0aXR1dGUgdW5leHBl
+Y3RlZCBSVEkga2luZCAiK2QpKX19LApiWjpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzLHIscSxwPWIu
+bGVuZ3RoLG89W10KZm9yKHQ9ITEscz0wO3M8cDsrK3Mpe3I9YltzXQpxPUguUEwoYSxyLGMsZCkKaWYo
+cSE9PXIpdD0hMApvLnB1c2gocSl9cmV0dXJuIHQ/bzpifSwKdk86ZnVuY3Rpb24oYSxiLGMsZCl7dmFy
+IHQscyxyLHEscCxvLG49Yi5sZW5ndGgsbT1bXQpmb3IodD0hMSxzPTA7czxuO3MrPTMpe3I9YltzXQpx
+PWJbcysxXQpwPWJbcysyXQpvPUguUEwoYSxwLGMsZCkKaWYobyE9PXApdD0hMAptLnB1c2gocikKbS5w
+dXNoKHEpCm0ucHVzaChvKX1yZXR1cm4gdD9tOmJ9LApxVDpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxz
+PWIuYSxyPUguYlooYSxzLGMsZCkscT1iLmIscD1ILmJaKGEscSxjLGQpLG89Yi5jLG49SC52TyhhLG8s
+YyxkKQppZihyPT09cyYmcD09PXEmJm49PT1vKXJldHVybiBiCnQ9bmV3IEguRygpCnQuYT1yCnQuYj1w
+CnQuYz1uCnJldHVybiB0fSwKSlM6ZnVuY3Rpb24oYSl7dmFyIHQ9YS4kUwppZih0IT1udWxsKXtpZih0
+eXBlb2YgdD09Im51bWJlciIpcmV0dXJuIEguQnAodCkKcmV0dXJuIGEuJFMoKX1yZXR1cm4gbnVsbH0s
+ClVlOmZ1bmN0aW9uKGEsYil7dmFyIHQKaWYoSC5RMShiKSlpZihhIGluc3RhbmNlb2YgSC52KXt0PUgu
+SlMoYSkKaWYodCE9bnVsbClyZXR1cm4gdH1yZXR1cm4gSC56KGEpfSwKejpmdW5jdGlvbihhKXt2YXIg
+dAppZihhIGluc3RhbmNlb2YgUC5NaCl7dD1hLiR0aQpyZXR1cm4gdCE9bnVsbD90OkguVlUoYSl9aWYo
+QXJyYXkuaXNBcnJheShhKSlyZXR1cm4gSC50NihhKQpyZXR1cm4gSC5WVShKLmlhKGEpKX0sCnQ2OmZ1
+bmN0aW9uKGEpe3ZhciB0PWFbdi5hcnJheVJ0aV0scz11LnUKaWYodD09bnVsbClyZXR1cm4gcwppZih0
+LmNvbnN0cnVjdG9yIT09cy5jb25zdHJ1Y3RvcilyZXR1cm4gcwpyZXR1cm4gdH0sCkxoOmZ1bmN0aW9u
+KGEpe3ZhciB0PWEuJHRpCnJldHVybiB0IT1udWxsP3Q6SC5WVShhKX0sClZVOmZ1bmN0aW9uKGEpe3Zh
+ciB0PWEuY29uc3RydWN0b3Iscz10LiRjY2FjaGUKaWYocyE9bnVsbClyZXR1cm4gcwpyZXR1cm4gSC5y
+OShhLHQpfSwKcjk6ZnVuY3Rpb24oYSxiKXt2YXIgdD1hIGluc3RhbmNlb2YgSC52P2EuX19wcm90b19f
+Ll9fcHJvdG9fXy5jb25zdHJ1Y3RvcjpiLHM9SC5haSh2LnR5cGVVbml2ZXJzZSx0Lm5hbWUpCmIuJGNj
+YWNoZT1zCnJldHVybiBzfSwKQnA6ZnVuY3Rpb24oYSl7dmFyIHQscyxyCkgudVAoYSkKdD12LnR5cGVz
+CnM9dFthXQppZih0eXBlb2Ygcz09InN0cmluZyIpe3I9SC5FKHYudHlwZVVuaXZlcnNlLHMsITEpCnRb
+YV09cgpyZXR1cm4gcn1yZXR1cm4gc30sCkpKOmZ1bmN0aW9uKGEpe3ZhciB0LHMscj10aGlzLHE9dS5L
+CmlmKHI9PT1xKXJldHVybiBILlJFKHIsYSxILmtlKQppZighSC5BOChyKSlpZighKHI9PT11Ll8pKXE9
+cj09PXEKZWxzZSBxPSEwCmVsc2UgcT0hMAppZihxKXJldHVybiBILlJFKHIsYSxILkl3KQpxPXIueQp0
+PXE9PT02P3IuejpyCmlmKHQ9PT11LlMpcz1ILm9rCmVsc2UgaWYodD09PXUuZ1J8fHQ9PT11LmRpKXM9
+SC5LSAplbHNlIGlmKHQ9PT11Lk4pcz1ILk1NCmVsc2Ugcz10PT09dS55P0gubDpudWxsCmlmKHMhPW51
+bGwpcmV0dXJuIEguUkUocixhLHMpCmlmKHQueT09PTkpe3E9dC56CmlmKHQuUS5ldmVyeShILmNjKSl7
+ci5yPSIkaSIrcQpyZXR1cm4gSC5SRShyLGEsSC50NCl9fWVsc2UgaWYocT09PTcpcmV0dXJuIEguUkUo
+cixhLEguQVEpCnJldHVybiBILlJFKHIsYSxILllPKX0sClJFOmZ1bmN0aW9uKGEsYixjKXthLmI9Ywpy
+ZXR1cm4gYS5iKGIpfSwKQXU6ZnVuY3Rpb24oYSl7dmFyIHQscyxyPXRoaXMKaWYoIUguQTgocikpaWYo
+IShyPT09dS5fKSl0PXI9PT11LksKZWxzZSB0PSEwCmVsc2UgdD0hMAppZih0KXM9SC5obgplbHNlIGlm
+KHI9PT11Lkspcz1ILlRpCmVsc2Ugcz1ILmw0CnIuYT1zCnJldHVybiByLmEoYSl9LApRajpmdW5jdGlv
+bihhKXt2YXIgdCxzPWEueQppZighSC5BOChhKSlpZighKGE9PT11Ll8pKXQ9YT09PXUuSwplbHNlIHQ9
+ITAKZWxzZSB0PSEwCnJldHVybiB0fHxhPT09dS5hd3x8cz09PTd8fGE9PT11LlB8fGE9PT11LlR9LApZ
+TzpmdW5jdGlvbihhKXt2YXIgdD10aGlzCmlmKGE9PW51bGwpcmV0dXJuIEguUWoodCkKcmV0dXJuIEgu
+V2Uodi50eXBlVW5pdmVyc2UsSC5VZShhLHQpLG51bGwsdCxudWxsKX0sCkFROmZ1bmN0aW9uKGEpe2lm
+KGE9PW51bGwpcmV0dXJuITAKcmV0dXJuIHRoaXMuei5iKGEpfSwKdDQ6ZnVuY3Rpb24oYSl7dmFyIHQ9
+dGhpcyxzPXQucgppZihhIGluc3RhbmNlb2YgUC5NaClyZXR1cm4hIWFbc10KcmV0dXJuISFKLmlhKGEp
+W3NdfSwKT3o6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcwppZihhPT1udWxsKXJldHVybiBhCmVsc2UgaWYo
+dC5iKGEpKXJldHVybiBhCkgubTQoYSx0KX0sCmw0OmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMKaWYoYT09
+bnVsbClyZXR1cm4gYQplbHNlIGlmKHQuYihhKSlyZXR1cm4gYQpILm00KGEsdCl9LAptNDpmdW5jdGlv
+bihhLGIpe3Rocm93IEguYihILlpjKEguV0soYSxILlVlKGEsYiksSC5kbShiLG51bGwpKSkpfSwKRGg6
+ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQ9bnVsbAppZihILldlKHYudHlwZVVuaXZlcnNlLGEsdCxiLHQp
+KXJldHVybiBhCnRocm93IEguYihILlpjKCJUaGUgdHlwZSBhcmd1bWVudCAnIitILkVqKEguZG0oYSx0
+KSkrIicgaXMgbm90IGEgc3VidHlwZSBvZiB0aGUgdHlwZSB2YXJpYWJsZSBib3VuZCAnIitILkVqKEgu
+ZG0oYix0KSkrIicgb2YgdHlwZSB2YXJpYWJsZSAnIitILkVqKGMpKyInIGluICciK0guRWooZCkrIicu
+IikpfSwKV0s6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0PVAucChhKSxzPUguZG0oYj09bnVsbD9ILnooYSk6
+YixudWxsKQpyZXR1cm4gdCsiOiB0eXBlICciK0guRWoocykrIicgaXMgbm90IGEgc3VidHlwZSBvZiB0
+eXBlICciK0guRWooYykrIicifSwKWmM6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBILmlNKCJUeXBlRXJy
+b3I6ICIrYSl9LApxOmZ1bmN0aW9uKGEsYil7cmV0dXJuIG5ldyBILmlNKCJUeXBlRXJyb3I6ICIrSC5X
+SyhhLG51bGwsYikpfSwKa2U6ZnVuY3Rpb24oYSl7cmV0dXJuIGEhPW51bGx9LApUaTpmdW5jdGlvbihh
+KXtyZXR1cm4gYX0sCkl3OmZ1bmN0aW9uKGEpe3JldHVybiEwfSwKaG46ZnVuY3Rpb24oYSl7cmV0dXJu
+IGF9LApsOmZ1bmN0aW9uKGEpe3JldHVybiEwPT09YXx8ITE9PT1hfSwKcDg6ZnVuY3Rpb24oYSl7aWYo
+ITA9PT1hKXJldHVybiEwCmlmKCExPT09YSlyZXR1cm4hMQp0aHJvdyBILmIoSC5xKGEsImJvb2wiKSl9
+LAp5ODpmdW5jdGlvbihhKXtpZighMD09PWEpcmV0dXJuITAKaWYoITE9PT1hKXJldHVybiExCmlmKGE9
+PW51bGwpcmV0dXJuIGEKdGhyb3cgSC5iKEgucShhLCJib29sIikpfSwKQlI6ZnVuY3Rpb24oYSl7aWYo
+ITA9PT1hKXJldHVybiEwCmlmKCExPT09YSlyZXR1cm4hMQppZihhPT1udWxsKXJldHVybiBhCnRocm93
+IEguYihILnEoYSwiYm9vbD8iKSl9LApGRzpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09Im51bWJlciIp
+cmV0dXJuIGEKdGhyb3cgSC5iKEgucShhLCJkb3VibGUiKSl9LApHSDpmdW5jdGlvbihhKXtpZih0eXBl
+b2YgYT09Im51bWJlciIpcmV0dXJuIGEKaWYoYT09bnVsbClyZXR1cm4gYQp0aHJvdyBILmIoSC5xKGEs
+ImRvdWJsZSIpKX0sClFrOmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0ibnVtYmVyIilyZXR1cm4gYQpp
+ZihhPT1udWxsKXJldHVybiBhCnRocm93IEguYihILnEoYSwiZG91YmxlPyIpKX0sCm9rOmZ1bmN0aW9u
+KGEpe3JldHVybiB0eXBlb2YgYT09Im51bWJlciImJk1hdGguZmxvb3IoYSk9PT1hfSwKSVo6ZnVuY3Rp
+b24oYSl7aWYodHlwZW9mIGE9PSJudW1iZXIiJiZNYXRoLmZsb29yKGEpPT09YSlyZXR1cm4gYQp0aHJv
+dyBILmIoSC5xKGEsImludCIpKX0sCnVQOmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0ibnVtYmVyIiYm
+TWF0aC5mbG9vcihhKT09PWEpcmV0dXJuIGEKaWYoYT09bnVsbClyZXR1cm4gYQp0aHJvdyBILmIoSC5x
+KGEsImludCIpKX0sClVjOmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0ibnVtYmVyIiYmTWF0aC5mbG9v
+cihhKT09PWEpcmV0dXJuIGEKaWYoYT09bnVsbClyZXR1cm4gYQp0aHJvdyBILmIoSC5xKGEsImludD8i
+KSl9LApLSDpmdW5jdGlvbihhKXtyZXR1cm4gdHlwZW9mIGE9PSJudW1iZXIifSwKejU6ZnVuY3Rpb24o
+YSl7aWYodHlwZW9mIGE9PSJudW1iZXIiKXJldHVybiBhCnRocm93IEguYihILnEoYSwibnVtIikpfSwK
+b0k6ZnVuY3Rpb24oYSl7aWYodHlwZW9mIGE9PSJudW1iZXIiKXJldHVybiBhCmlmKGE9PW51bGwpcmV0
+dXJuIGEKdGhyb3cgSC5iKEgucShhLCJudW0iKSl9LApjVTpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09
+Im51bWJlciIpcmV0dXJuIGEKaWYoYT09bnVsbClyZXR1cm4gYQp0aHJvdyBILmIoSC5xKGEsIm51bT8i
+KSl9LApNTTpmdW5jdGlvbihhKXtyZXR1cm4gdHlwZW9mIGE9PSJzdHJpbmcifSwKQnQ6ZnVuY3Rpb24o
+YSl7aWYodHlwZW9mIGE9PSJzdHJpbmciKXJldHVybiBhCnRocm93IEguYihILnEoYSwiU3RyaW5nIikp
+fSwKaDpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09InN0cmluZyIpcmV0dXJuIGEKaWYoYT09bnVsbCly
+ZXR1cm4gYQp0aHJvdyBILmIoSC5xKGEsIlN0cmluZyIpKX0sCms6ZnVuY3Rpb24oYSl7aWYodHlwZW9m
+IGE9PSJzdHJpbmciKXJldHVybiBhCmlmKGE9PW51bGwpcmV0dXJuIGEKdGhyb3cgSC5iKEgucShhLCJT
+dHJpbmc/IikpfSwKaW86ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIKZm9yKHQ9IiIscz0iIixyPTA7cjxh
+Lmxlbmd0aDsrK3Iscz0iLCAiKXQrPUMueEIuaChzLEguZG0oYVtyXSxiKSkKcmV0dXJuIHR9LApiSTpm
+dW5jdGlvbihhNCxhNSxhNil7dmFyIHQscyxyLHEscCxvLG4sbSxsLGssaixpLGgsZyxmLGUsZCxjLGIs
+YSxhMCxhMSxhMixhMz0iLCAiCmlmKGE2IT1udWxsKXt0PWE2Lmxlbmd0aAppZihhNT09bnVsbCl7YTU9
+SC5WTShbXSx1LnMpCnM9bnVsbH1lbHNlIHM9YTUubGVuZ3RoCnI9YTUubGVuZ3RoCmZvcihxPXQ7cT4w
+Oy0tcSlDLk5tLmkoYTUsIlQiKyhyK3EpKQpmb3IocD11Llcsbz11Ll8sbj11LkssbT0iPCIsbD0iIixx
+PTA7cTx0OysrcSxsPWEzKXttKz1sCms9YTUubGVuZ3RoCmo9ay0xLXEKaWYoajwwKXJldHVybiBILk9I
+KGE1LGopCm09Qy54Qi5oKG0sYTVbal0pCmk9YTZbcV0KaD1pLnkKaWYoIShoPT09Mnx8aD09PTN8fGg9
+PT00fHxoPT09NXx8aT09PXApKWlmKCEoaT09PW8pKWs9aT09PW4KZWxzZSBrPSEwCmVsc2Ugaz0hMApp
+ZighayltKz1DLnhCLmgoIiBleHRlbmRzICIsSC5kbShpLGE1KSl9bSs9Ij4ifWVsc2V7bT0iIgpzPW51
+bGx9cD1hNC56Cmc9YTQuUQpmPWcuYQplPWYubGVuZ3RoCmQ9Zy5iCmM9ZC5sZW5ndGgKYj1nLmMKYT1i
+Lmxlbmd0aAphMD1ILmRtKHAsYTUpCmZvcihhMT0iIixhMj0iIixxPTA7cTxlOysrcSxhMj1hMylhMSs9
+Qy54Qi5oKGEyLEguZG0oZltxXSxhNSkpCmlmKGM+MCl7YTErPWEyKyJbIgpmb3IoYTI9IiIscT0wO3E8
+YzsrK3EsYTI9YTMpYTErPUMueEIuaChhMixILmRtKGRbcV0sYTUpKQphMSs9Il0ifWlmKGE+MCl7YTEr
+PWEyKyJ7Igpmb3IoYTI9IiIscT0wO3E8YTtxKz0zLGEyPWEzKXthMSs9YTIKaWYoYltxKzFdKWExKz0i
+cmVxdWlyZWQgIgphMSs9Si5iYihILmRtKGJbcSsyXSxhNSksIiAiKStiW3FdfWExKz0ifSJ9aWYocyE9
+bnVsbCl7YTUudG9TdHJpbmcKYTUubGVuZ3RoPXN9cmV0dXJuIG0rIigiK2ExKyIpID0+ICIrSC5Faihh
+MCl9LApkbTpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHAsbyxuLG09YS55CmlmKG09PT01KXJldHVy
+biJlcmFzZWQiCmlmKG09PT0yKXJldHVybiJkeW5hbWljIgppZihtPT09MylyZXR1cm4idm9pZCIKaWYo
+bT09PTEpcmV0dXJuIk5ldmVyIgppZihtPT09NClyZXR1cm4iYW55IgppZihtPT09Nil7dD1ILmRtKGEu
+eixiKQpyZXR1cm4gdH1pZihtPT09Nyl7cz1hLnoKdD1ILmRtKHMsYikKcj1zLnkKcmV0dXJuIEouYmIo
+cj09PTExfHxyPT09MTI/Qy54Qi5oKCIoIix0KSsiKSI6dCwiPyIpfWlmKG09PT04KXJldHVybiJGdXR1
+cmVPcjwiK0guRWooSC5kbShhLnosYikpKyI+IgppZihtPT09OSl7cT1ILm8zKGEueikKcD1hLlEKcmV0
+dXJuIHAubGVuZ3RoIT09MD9xKygiPCIrSC5pbyhwLGIpKyI+Iik6cX1pZihtPT09MTEpcmV0dXJuIEgu
+YkkoYSxiLG51bGwpCmlmKG09PT0xMilyZXR1cm4gSC5iSShhLnosYixhLlEpCmlmKG09PT0xMyl7Yi50
+b1N0cmluZwpvPWEuegpuPWIubGVuZ3RoCm89bi0xLW8KaWYobzwwfHxvPj1uKXJldHVybiBILk9IKGIs
+bykKcmV0dXJuIGJbb119cmV0dXJuIj8ifSwKbzM6ZnVuY3Rpb24oYSl7dmFyIHQscz1ILkpnKGEpCmlm
+KHMhPW51bGwpcmV0dXJuIHMKdD0ibWluaWZpZWQ6IithCnJldHVybiB0fSwKUW86ZnVuY3Rpb24oYSxi
+KXt2YXIgdD1hLnRSW2JdCmZvcig7dHlwZW9mIHQ9PSJzdHJpbmciOyl0PWEudFJbdF0KcmV0dXJuIHR9
+LAphaTpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHAsbz1hLmVULG49b1tiXQppZihuPT1udWxsKXJl
+dHVybiBILkUoYSxiLCExKQplbHNlIGlmKHR5cGVvZiBuPT0ibnVtYmVyIil7dD1uCnM9SC5tKGEsNSwi
+IyIpCnI9W10KZm9yKHE9MDtxPHQ7KytxKXIucHVzaChzKQpwPUguSihhLGIscikKb1tiXT1wCnJldHVy
+biBwfWVsc2UgcmV0dXJuIG59LAp4YjpmdW5jdGlvbihhLGIpe3JldHVybiBILkl4KGEudFIsYil9LApG
+RjpmdW5jdGlvbihhLGIpe3JldHVybiBILkl4KGEuZVQsYil9LApFOmZ1bmN0aW9uKGEsYixjKXt2YXIg
+dCxzPWEuZUMscj1zLmdldChiKQppZihyIT1udWxsKXJldHVybiByCnQ9SC5pKEgubyhhLG51bGwsYixj
+KSkKcy5zZXQoYix0KQpyZXR1cm4gdH0sCmNFOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHI9Yi5jaApp
+ZihyPT1udWxsKXI9Yi5jaD1uZXcgTWFwKCkKdD1yLmdldChjKQppZih0IT1udWxsKXJldHVybiB0CnM9
+SC5pKEgubyhhLGIsYywhMCkpCnIuc2V0KGMscykKcmV0dXJuIHN9LAp2NTpmdW5jdGlvbihhLGIsYyl7
+dmFyIHQscyxyLHE9Yi5jeAppZihxPT1udWxsKXE9Yi5jeD1uZXcgTWFwKCkKdD1jLmN5CnM9cS5nZXQo
+dCkKaWYocyE9bnVsbClyZXR1cm4gcwpyPUguYShhLGIsYy55PT09MTA/Yy5ROltjXSkKcS5zZXQodCxy
+KQpyZXR1cm4gcn0sCkJEOmZ1bmN0aW9uKGEsYil7Yi5hPUguQXUKYi5iPUguSkoKcmV0dXJuIGJ9LApt
+OmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHI9YS5lQy5nZXQoYykKaWYociE9bnVsbClyZXR1cm4gcgp0
+PW5ldyBILkpjKG51bGwsbnVsbCkKdC55PWIKdC5jeT1jCnM9SC5CRChhLHQpCmEuZUMuc2V0KGMscykK
+cmV0dXJuIHN9LApDOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzPWIuY3krIioiLHI9YS5lQy5nZXQocykK
+aWYociE9bnVsbClyZXR1cm4gcgp0PUguWjcoYSxiLHMsYykKYS5lQy5zZXQocyx0KQpyZXR1cm4gdH0s
+Clo3OmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0LHMscgppZihkKXt0PWIueQppZighSC5BOChiKSlzPWI9
+PT11LlB8fGI9PT11LlR8fHQ9PT03fHx0PT09NgplbHNlIHM9ITAKaWYocylyZXR1cm4gYn1yPW5ldyBI
+LkpjKG51bGwsbnVsbCkKci55PTYKci56PWIKci5jeT1jCnJldHVybiBILkJEKGEscil9LApCOmZ1bmN0
+aW9uKGEsYixjKXt2YXIgdCxzPWIuY3krIj8iLHI9YS5lQy5nZXQocykKaWYociE9bnVsbClyZXR1cm4g
+cgp0PUgubGwoYSxiLHMsYykKYS5lQy5zZXQocyx0KQpyZXR1cm4gdH0sCmxsOmZ1bmN0aW9uKGEsYixj
+LGQpe3ZhciB0LHMscixxCmlmKGQpe3Q9Yi55CmlmKCFILkE4KGIpKWlmKCEoYj09PXUuUHx8Yj09PXUu
+VCkpaWYodCE9PTcpcz10PT09OCYmSC5sUihiLnopCmVsc2Ugcz0hMAplbHNlIHM9ITAKZWxzZSBzPSEw
+CmlmKHMpcmV0dXJuIGIKZWxzZSBpZih0PT09MXx8Yj09PXUuYXcpcmV0dXJuIHUuUAplbHNlIGlmKHQ9
+PT02KXtyPWIuegppZihyLnk9PT04JiZILmxSKHIueikpcmV0dXJuIHIKZWxzZSByZXR1cm4gSC5jeihh
+LGIpfX1xPW5ldyBILkpjKG51bGwsbnVsbCkKcS55PTcKcS56PWIKcS5jeT1jCnJldHVybiBILkJEKGEs
+cSl9LApmOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzPWIuY3krIi8iLHI9YS5lQy5nZXQocykKaWYociE9
+bnVsbClyZXR1cm4gcgp0PUguZVYoYSxiLHMsYykKYS5lQy5zZXQocyx0KQpyZXR1cm4gdH0sCmVWOmZ1
+bmN0aW9uKGEsYixjLGQpe3ZhciB0LHMscgppZihkKXt0PWIueQppZighSC5BOChiKSlpZighKGI9PT11
+Ll8pKXM9Yj09PXUuSwplbHNlIHM9ITAKZWxzZSBzPSEwCmlmKHN8fGI9PT11LkspcmV0dXJuIGIKZWxz
+ZSBpZih0PT09MSlyZXR1cm4gSC5KKGEsImI4IixbYl0pCmVsc2UgaWYoYj09PXUuUHx8Yj09PXUuVCly
+ZXR1cm4gdS5iR31yPW5ldyBILkpjKG51bGwsbnVsbCkKci55PTgKci56PWIKci5jeT1jCnJldHVybiBI
+LkJEKGEscil9LApIOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyPSIiK2IrIl4iLHE9YS5lQy5nZXQocikK
+aWYocSE9bnVsbClyZXR1cm4gcQp0PW5ldyBILkpjKG51bGwsbnVsbCkKdC55PTEzCnQuej1iCnQuY3k9
+cgpzPUguQkQoYSx0KQphLmVDLnNldChyLHMpCnJldHVybiBzfSwKVXg6ZnVuY3Rpb24oYSl7dmFyIHQs
+cyxyLHE9YS5sZW5ndGgKZm9yKHQ9IiIscz0iIixyPTA7cjxxOysrcixzPSIsIil0Kz1zK2Fbcl0uY3kK
+cmV0dXJuIHR9LApTNDpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwLG8sbj1hLmxlbmd0aApmb3IodD0i
+IixzPSIiLHI9MDtyPG47cis9MyxzPSIsIil7cT1hW3JdCnA9YVtyKzFdPyIhIjoiOiIKbz1hW3IrMl0u
+Y3kKdCs9cytxK3Arb31yZXR1cm4gdH0sCko6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixxPWIKaWYo
+Yy5sZW5ndGghPT0wKXErPSI8IitILlV4KGMpKyI+Igp0PWEuZUMuZ2V0KHEpCmlmKHQhPW51bGwpcmV0
+dXJuIHQKcz1uZXcgSC5KYyhudWxsLG51bGwpCnMueT05CnMuej1iCnMuUT1jCmlmKGMubGVuZ3RoPjAp
+cy5jPWNbMF0Kcy5jeT1xCnI9SC5CRChhLHMpCmEuZUMuc2V0KHEscikKcmV0dXJuIHJ9LAphOmZ1bmN0
+aW9uKGEsYixjKXt2YXIgdCxzLHIscSxwLG8KaWYoYi55PT09MTApe3Q9Yi56CnM9Yi5RLmNvbmNhdChj
+KX1lbHNle3M9Ywp0PWJ9cj10LmN5KygiOzwiK0guVXgocykrIj4iKQpxPWEuZUMuZ2V0KHIpCmlmKHEh
+PW51bGwpcmV0dXJuIHEKcD1uZXcgSC5KYyhudWxsLG51bGwpCnAueT0xMApwLno9dApwLlE9cwpwLmN5
+PXIKbz1ILkJEKGEscCkKYS5lQy5zZXQocixvKQpyZXR1cm4gb30sCmQ6ZnVuY3Rpb24oYSxiLGMpe3Zh
+ciB0LHMscixxLHAsbz1iLmN5LG49Yy5hLG09bi5sZW5ndGgsbD1jLmIsaz1sLmxlbmd0aCxqPWMuYyxp
+PWoubGVuZ3RoLGg9IigiK0guVXgobikKaWYoaz4wKXt0PW0+MD8iLCI6IiIKcz1ILlV4KGwpCmgrPXQr
+IlsiK3MrIl0ifWlmKGk+MCl7dD1tPjA/IiwiOiIiCnM9SC5TNChqKQpoKz10KyJ7IitzKyJ9In1yPW8r
+KGgrIikiKQpxPWEuZUMuZ2V0KHIpCmlmKHEhPW51bGwpcmV0dXJuIHEKcD1uZXcgSC5KYyhudWxsLG51
+bGwpCnAueT0xMQpwLno9YgpwLlE9YwpwLmN5PXIKcz1ILkJEKGEscCkKYS5lQy5zZXQocixzKQpyZXR1
+cm4gc30sCkQ6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscz1iLmN5KygiPCIrSC5VeChjKSsiPiIpLHI9
+YS5lQy5nZXQocykKaWYociE9bnVsbClyZXR1cm4gcgp0PUguaHcoYSxiLGMscyxkKQphLmVDLnNldChz
+LHQpCnJldHVybiB0fSwKaHc6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgdCxzLHIscSxwLG8sbixtCmlm
+KGUpe3Q9Yy5sZW5ndGgKcz1uZXcgQXJyYXkodCkKZm9yKHI9MCxxPTA7cTx0OysrcSl7cD1jW3FdCmlm
+KHAueT09PTEpe3NbcV09cDsrK3J9fWlmKHI+MCl7bz1ILlBMKGEsYixzLDApCm49SC5iWihhLGMscyww
+KQpyZXR1cm4gSC5EKGEsbyxuLGMhPT1uKX19bT1uZXcgSC5KYyhudWxsLG51bGwpCm0ueT0xMgptLno9
+YgptLlE9YwptLmN5PWQKcmV0dXJuIEguQkQoYSxtKX0sCm86ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJu
+e3U6YSxlOmIscjpjLHM6W10scDowLG46ZH19LAppOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHAsbyxu
+LG0sbCxrLGosaSxoPWEucixnPWEucwpmb3IodD1oLmxlbmd0aCxzPTA7czx0Oyl7cj1oLmNoYXJDb2Rl
+QXQocykKaWYocj49NDgmJnI8PTU3KXM9SC5BKHMrMSxyLGgsZykKZWxzZSBpZigoKChyfDMyKT4+PjAp
+LTk3JjY1NTM1KTwyNnx8cj09PTk1fHxyPT09MzYpcz1ILnQoYSxzLGgsZywhMSkKZWxzZSBpZihyPT09
+NDYpcz1ILnQoYSxzLGgsZywhMCkKZWxzZXsrK3MKc3dpdGNoKHIpe2Nhc2UgNDQ6YnJlYWsKY2FzZSA1
+ODpnLnB1c2goITEpCmJyZWFrCmNhc2UgMzM6Zy5wdXNoKCEwKQpicmVhawpjYXNlIDU5OmcucHVzaChI
+LksoYS51LGEuZSxnLnBvcCgpKSkKYnJlYWsKY2FzZSA5NDpnLnB1c2goSC5IKGEudSxnLnBvcCgpKSkK
+YnJlYWsKY2FzZSAzNTpnLnB1c2goSC5tKGEudSw1LCIjIikpCmJyZWFrCmNhc2UgNjQ6Zy5wdXNoKEgu
+bShhLnUsMiwiQCIpKQpicmVhawpjYXNlIDEyNjpnLnB1c2goSC5tKGEudSwzLCJ+IikpCmJyZWFrCmNh
+c2UgNjA6Zy5wdXNoKGEucCkKYS5wPWcubGVuZ3RoCmJyZWFrCmNhc2UgNjI6cT1hLnUKcD1nLnNwbGlj
+ZShhLnApCkgucihhLnUsYS5lLHApCmEucD1nLnBvcCgpCm89Zy5wb3AoKQppZih0eXBlb2Ygbz09InN0
+cmluZyIpZy5wdXNoKEguSihxLG8scCkpCmVsc2V7bj1ILksocSxhLmUsbykKc3dpdGNoKG4ueSl7Y2Fz
+ZSAxMTpnLnB1c2goSC5EKHEsbixwLGEubikpCmJyZWFrCmRlZmF1bHQ6Zy5wdXNoKEguYShxLG4scCkp
+CmJyZWFrfX1icmVhawpjYXNlIDM4OkguSShhLGcpCmJyZWFrCmNhc2UgNDI6bT1hLnUKZy5wdXNoKEgu
+QyhtLEguSyhtLGEuZSxnLnBvcCgpKSxhLm4pKQpicmVhawpjYXNlIDYzOm09YS51CmcucHVzaChILkIo
+bSxILksobSxhLmUsZy5wb3AoKSksYS5uKSkKYnJlYWsKY2FzZSA0NzptPWEudQpnLnB1c2goSC5mKG0s
+SC5LKG0sYS5lLGcucG9wKCkpLGEubikpCmJyZWFrCmNhc2UgNDA6Zy5wdXNoKGEucCkKYS5wPWcubGVu
+Z3RoCmJyZWFrCmNhc2UgNDE6cT1hLnUKbD1uZXcgSC5HKCkKaz1xLnNFQQpqPXEuc0VBCm89Zy5wb3Ao
+KQppZih0eXBlb2Ygbz09Im51bWJlciIpc3dpdGNoKG8pe2Nhc2UtMTprPWcucG9wKCkKYnJlYWsKY2Fz
+ZS0yOmo9Zy5wb3AoKQpicmVhawpkZWZhdWx0OmcucHVzaChvKQpicmVha31lbHNlIGcucHVzaChvKQpw
+PWcuc3BsaWNlKGEucCkKSC5yKGEudSxhLmUscCkKYS5wPWcucG9wKCkKbC5hPXAKbC5iPWsKbC5jPWoK
+Zy5wdXNoKEguZChxLEguSyhxLGEuZSxnLnBvcCgpKSxsKSkKYnJlYWsKY2FzZSA5MTpnLnB1c2goYS5w
+KQphLnA9Zy5sZW5ndGgKYnJlYWsKY2FzZSA5MzpwPWcuc3BsaWNlKGEucCkKSC5yKGEudSxhLmUscCkK
+YS5wPWcucG9wKCkKZy5wdXNoKHApCmcucHVzaCgtMSkKYnJlYWsKY2FzZSAxMjM6Zy5wdXNoKGEucCkK
+YS5wPWcubGVuZ3RoCmJyZWFrCmNhc2UgMTI1OnA9Zy5zcGxpY2UoYS5wKQpILnkoYS51LGEuZSxwKQph
+LnA9Zy5wb3AoKQpnLnB1c2gocCkKZy5wdXNoKC0yKQpicmVhawpkZWZhdWx0OnRocm93IkJhZCBjaGFy
+YWN0ZXIgIityfX19aT1nLnBvcCgpCnJldHVybiBILksoYS51LGEuZSxpKX0sCkE6ZnVuY3Rpb24oYSxi
+LGMsZCl7dmFyIHQscyxyPWItNDgKZm9yKHQ9Yy5sZW5ndGg7YTx0OysrYSl7cz1jLmNoYXJDb2RlQXQo
+YSkKaWYoIShzPj00OCYmczw9NTcpKWJyZWFrCnI9cioxMCsocy00OCl9ZC5wdXNoKHIpCnJldHVybiBh
+fSwKdDpmdW5jdGlvbihhLGIsYyxkLGUpe3ZhciB0LHMscixxLHAsbyxuPWIrMQpmb3IodD1jLmxlbmd0
+aDtuPHQ7KytuKXtzPWMuY2hhckNvZGVBdChuKQppZihzPT09NDYpe2lmKGUpYnJlYWsKZT0hMH1lbHNl
+e2lmKCEoKCgoc3wzMik+Pj4wKS05NyY2NTUzNSk8MjZ8fHM9PT05NXx8cz09PTM2KSlyPXM+PTQ4JiZz
+PD01NwplbHNlIHI9ITAKaWYoIXIpYnJlYWt9fXE9Yy5zdWJzdHJpbmcoYixuKQppZihlKXt0PWEudQpw
+PWEuZQppZihwLnk9PT0xMClwPXAuegpvPUguUW8odCxwLnopW3FdCmlmKG89PW51bGwpSC52aCgnTm8g
+IicrcSsnIiBpbiAiJytILm1EKHApKyciJykKZC5wdXNoKEguY0UodCxwLG8pKX1lbHNlIGQucHVzaChx
+KQpyZXR1cm4gbn0sCkk6ZnVuY3Rpb24oYSxiKXt2YXIgdD1iLnBvcCgpCmlmKDA9PT10KXtiLnB1c2go
+SC5tKGEudSwxLCIwJiIpKQpyZXR1cm59aWYoMT09PXQpe2IucHVzaChILm0oYS51LDQsIjEmIikpCnJl
+dHVybn10aHJvdyBILmIoUC5oVigiVW5leHBlY3RlZCBleHRlbmRlZCBvcGVyYXRpb24gIitILkVqKHQp
+KSl9LApLOmZ1bmN0aW9uKGEsYixjKXtpZih0eXBlb2YgYz09InN0cmluZyIpcmV0dXJuIEguSihhLGMs
+YS5zRUEpCmVsc2UgaWYodHlwZW9mIGM9PSJudW1iZXIiKXJldHVybiBILlRWKGEsYixjKQplbHNlIHJl
+dHVybiBjfSwKcjpmdW5jdGlvbihhLGIsYyl7dmFyIHQscz1jLmxlbmd0aApmb3IodD0wO3Q8czsrK3Qp
+Y1t0XT1ILksoYSxiLGNbdF0pfSwKeTpmdW5jdGlvbihhLGIsYyl7dmFyIHQscz1jLmxlbmd0aApmb3Io
+dD0yO3Q8czt0Kz0zKWNbdF09SC5LKGEsYixjW3RdKX0sClRWOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxz
+LHI9Yi55CmlmKHI9PT0xMCl7aWYoYz09PTApcmV0dXJuIGIuegp0PWIuUQpzPXQubGVuZ3RoCmlmKGM8
+PXMpcmV0dXJuIHRbYy0xXQpjLT1zCmI9Yi56CnI9Yi55fWVsc2UgaWYoYz09PTApcmV0dXJuIGIKaWYo
+ciE9PTkpdGhyb3cgSC5iKFAuaFYoIkluZGV4ZWQgYmFzZSBtdXN0IGJlIGFuIGludGVyZmFjZSB0eXBl
+IikpCnQ9Yi5RCmlmKGM8PXQubGVuZ3RoKXJldHVybiB0W2MtMV0KdGhyb3cgSC5iKFAuaFYoIkJhZCBp
+bmRleCAiK2MrIiBmb3IgIitiLncoMCkpKX0sCldlOmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHQscyxy
+LHEscCxvLG4sbSxsLGsKaWYoYj09PWQpcmV0dXJuITAKaWYoIUguQTgoZCkpaWYoIShkPT09dS5fKSl0
+PWQ9PT11LksKZWxzZSB0PSEwCmVsc2UgdD0hMAppZih0KXJldHVybiEwCnM9Yi55CmlmKHM9PT00KXJl
+dHVybiEwCmlmKEguQTgoYikpcmV0dXJuITEKaWYoYi55IT09MSl0PWI9PT11LlB8fGI9PT11LlQKZWxz
+ZSB0PSEwCmlmKHQpcmV0dXJuITAKcj1zPT09MTMKaWYocilpZihILldlKGEsY1tiLnpdLGMsZCxlKSly
+ZXR1cm4hMApxPWQueQppZihzPT09NilyZXR1cm4gSC5XZShhLGIueixjLGQsZSkKaWYocT09PTYpe3Q9
+ZC56CnJldHVybiBILldlKGEsYixjLHQsZSl9aWYocz09PTgpe2lmKCFILldlKGEsYi56LGMsZCxlKSly
+ZXR1cm4hMQpyZXR1cm4gSC5XZShhLEgueFooYSxiKSxjLGQsZSl9aWYocz09PTcpe3Q9SC5XZShhLGIu
+eixjLGQsZSkKcmV0dXJuIHR9aWYocT09PTgpe2lmKEguV2UoYSxiLGMsZC56LGUpKXJldHVybiEwCnJl
+dHVybiBILldlKGEsYixjLEgueFooYSxkKSxlKX1pZihxPT09Nyl7dD1ILldlKGEsYixjLGQueixlKQpy
+ZXR1cm4gdH1pZihyKXJldHVybiExCnQ9cyE9PTExCmlmKCghdHx8cz09PTEyKSYmZD09PXUuWSlyZXR1
+cm4hMAppZihxPT09MTIpe2lmKGI9PT11LnYpcmV0dXJuITAKaWYocyE9PTEyKXJldHVybiExCnA9Yi5R
+Cm89ZC5RCm49cC5sZW5ndGgKaWYobiE9PW8ubGVuZ3RoKXJldHVybiExCmM9Yz09bnVsbD9wOnAuY29u
+Y2F0KGMpCmU9ZT09bnVsbD9vOm8uY29uY2F0KGUpCmZvcihtPTA7bTxuOysrbSl7bD1wW21dCms9b1tt
+XQppZighSC5XZShhLGwsYyxrLGUpfHwhSC5XZShhLGssZSxsLGMpKXJldHVybiExfXJldHVybiBILmJP
+KGEsYi56LGMsZC56LGUpfWlmKHE9PT0xMSl7aWYoYj09PXUudilyZXR1cm4hMAppZih0KXJldHVybiEx
+CnJldHVybiBILmJPKGEsYixjLGQsZSl9aWYocz09PTkpe2lmKHEhPT05KXJldHVybiExCnJldHVybiBI
+LnBHKGEsYixjLGQsZSl9cmV0dXJuITF9LApiTzpmdW5jdGlvbihhMixhMyxhNCxhNSxhNil7dmFyIHQs
+cyxyLHEscCxvLG4sbSxsLGssaixpLGgsZyxmLGUsZCxjLGIsYSxhMCxhMQppZighSC5XZShhMixhMy56
+LGE0LGE1LnosYTYpKXJldHVybiExCnQ9YTMuUQpzPWE1LlEKcj10LmEKcT1zLmEKcD1yLmxlbmd0aApv
+PXEubGVuZ3RoCmlmKHA+bylyZXR1cm4hMQpuPW8tcAptPXQuYgpsPXMuYgprPW0ubGVuZ3RoCmo9bC5s
+ZW5ndGgKaWYocCtrPG8railyZXR1cm4hMQpmb3IoaT0wO2k8cDsrK2kpe2g9cltpXQppZighSC5XZShh
+MixxW2ldLGE2LGgsYTQpKXJldHVybiExfWZvcihpPTA7aTxuOysraSl7aD1tW2ldCmlmKCFILldlKGEy
+LHFbcCtpXSxhNixoLGE0KSlyZXR1cm4hMX1mb3IoaT0wO2k8ajsrK2kpe2g9bVtuK2ldCmlmKCFILldl
+KGEyLGxbaV0sYTYsaCxhNCkpcmV0dXJuITF9Zz10LmMKZj1zLmMKZT1nLmxlbmd0aApkPWYubGVuZ3Ro
+CmZvcihjPTAsYj0wO2I8ZDtiKz0zKXthPWZbYl0KZm9yKDshMDspe2lmKGM+PWUpcmV0dXJuITEKYTA9
+Z1tjXQpjKz0zCmlmKGE8YTApcmV0dXJuITEKYTE9Z1tjLTJdCmlmKGEwPGEpe2lmKGExKXJldHVybiEx
+CmNvbnRpbnVlfWg9ZltiKzFdCmlmKGExJiYhaClyZXR1cm4hMQpoPWdbYy0xXQppZighSC5XZShhMixm
+W2IrMl0sYTYsaCxhNCkpcmV0dXJuITEKYnJlYWt9fWZvcig7YzxlOyl7aWYoZ1tjKzFdKXJldHVybiEx
+CmMrPTN9cmV0dXJuITB9LApwRzpmdW5jdGlvbihhLGIsYyxkLGUpe3ZhciB0LHMscixxLHAsbyxuLG0s
+bD1iLnosaz1kLnoKaWYobD09PWspe3Q9Yi5RCnM9ZC5RCnI9dC5sZW5ndGgKZm9yKHE9MDtxPHI7Kytx
+KXtwPXRbcV0Kbz1zW3FdCmlmKCFILldlKGEscCxjLG8sZSkpcmV0dXJuITF9cmV0dXJuITB9aWYoZD09
+PXUuSylyZXR1cm4hMApuPUguUW8oYSxsKQppZihuPT1udWxsKXJldHVybiExCm09bltrXQppZihtPT1u
+dWxsKXJldHVybiExCnI9bS5sZW5ndGgKcz1kLlEKZm9yKHE9MDtxPHI7KytxKWlmKCFILldlKGEsSC5j
+RShhLGIsbVtxXSksYyxzW3FdLGUpKXJldHVybiExCnJldHVybiEwfSwKbFI6ZnVuY3Rpb24oYSl7dmFy
+IHQscz1hLnkKaWYoIShhPT09dS5QfHxhPT09dS5UKSlpZighSC5BOChhKSlpZihzIT09NylpZighKHM9
+PT02JiZILmxSKGEueikpKXQ9cz09PTgmJkgubFIoYS56KQplbHNlIHQ9ITAKZWxzZSB0PSEwCmVsc2Ug
+dD0hMAplbHNlIHQ9ITAKcmV0dXJuIHR9LApjYzpmdW5jdGlvbihhKXt2YXIgdAppZighSC5BOChhKSlp
+ZighKGE9PT11Ll8pKXQ9YT09PXUuSwplbHNlIHQ9ITAKZWxzZSB0PSEwCnJldHVybiB0fSwKQTg6ZnVu
+Y3Rpb24oYSl7dmFyIHQ9YS55CnJldHVybiB0PT09Mnx8dD09PTN8fHQ9PT00fHx0PT09NXx8YT09PXUu
+V30sCkl4OmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyPU9iamVjdC5rZXlzKGIpLHE9ci5sZW5ndGgKZm9y
+KHQ9MDt0PHE7Kyt0KXtzPXJbdF0KYVtzXT1iW3NdfX0sCkpjOmZ1bmN0aW9uIEpjKGEsYil7dmFyIF89
+dGhpcwpfLmE9YQpfLmI9YgpfLng9Xy5yPV8uYz1udWxsCl8ueT0wCl8uY3k9Xy5jeD1fLmNoPV8uUT1f
+Lno9bnVsbH0sCkc6ZnVuY3Rpb24gRygpe3RoaXMuYz10aGlzLmI9dGhpcy5hPW51bGx9LAp1OTpmdW5j
+dGlvbiB1OSgpe30sCmlNOmZ1bmN0aW9uIGlNKGEpe3RoaXMuYT1hfSwKUjk6ZnVuY3Rpb24oYSl7cmV0
+dXJuIHUudy5iKGEpfHx1LkIuYihhKXx8dS5kei5iKGEpfHx1LkkuYihhKXx8dS5BLmIoYSl8fHUuZzQu
+YihhKXx8dS5nMi5iKGEpfSwKSmc6ZnVuY3Rpb24oYSl7cmV0dXJuIHYubWFuZ2xlZEdsb2JhbE5hbWVz
+W2FdfX0sSj17ClF1OmZ1bmN0aW9uKGEsYixjLGQpe3JldHVybntpOmEscDpiLGU6Yyx4OmR9fSwKa3M6
+ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscD1hW3YuZGlzcGF0Y2hQcm9wZXJ0eU5hbWVdCmlmKHA9PW51
+bGwpaWYoJC5Cdj09bnVsbCl7SC5YRCgpCnA9YVt2LmRpc3BhdGNoUHJvcGVydHlOYW1lXX1pZihwIT1u
+dWxsKXt0PXAucAppZighMT09PXQpcmV0dXJuIHAuaQppZighMD09PXQpcmV0dXJuIGEKcz1PYmplY3Qu
+Z2V0UHJvdG90eXBlT2YoYSkKaWYodD09PXMpcmV0dXJuIHAuaQppZihwLmU9PT1zKXRocm93IEguYihQ
+LlNZKCJSZXR1cm4gaW50ZXJjZXB0b3IgZm9yICIrSC5Faih0KGEscCkpKSl9cj1hLmNvbnN0cnVjdG9y
+CnE9cj09bnVsbD9udWxsOnJbSi5SUCgpXQppZihxIT1udWxsKXJldHVybiBxCnE9SC53MyhhKQppZihx
+IT1udWxsKXJldHVybiBxCmlmKHR5cGVvZiBhPT0iZnVuY3Rpb24iKXJldHVybiBDLkRHCnQ9T2JqZWN0
+LmdldFByb3RvdHlwZU9mKGEpCmlmKHQ9PW51bGwpcmV0dXJuIEMuWlEKaWYodD09PU9iamVjdC5wcm90
+b3R5cGUpcmV0dXJuIEMuWlEKaWYodHlwZW9mIHI9PSJmdW5jdGlvbiIpe09iamVjdC5kZWZpbmVQcm9w
+ZXJ0eShyLEouUlAoKSx7dmFsdWU6Qy52QixlbnVtZXJhYmxlOmZhbHNlLHdyaXRhYmxlOnRydWUsY29u
+ZmlndXJhYmxlOnRydWV9KQpyZXR1cm4gQy52Qn1yZXR1cm4gQy52Qn0sClJQOmZ1bmN0aW9uKCl7dmFy
+IHQ9JC56bQpyZXR1cm4gdD09bnVsbD8kLnptPXYuZ2V0SXNvbGF0ZVRhZygiXyRkYXJ0X2pzIik6dH0s
+ClFpOmZ1bmN0aW9uKGEsYil7aWYoYTwwfHxhPjQyOTQ5NjcyOTUpdGhyb3cgSC5iKFAuVEUoYSwwLDQy
+OTQ5NjcyOTUsImxlbmd0aCIsbnVsbCkpCnJldHVybiBKLnB5KG5ldyBBcnJheShhKSxiKX0sCktoOmZ1
+bmN0aW9uKGEsYil7aWYoYTwwKXRocm93IEguYihQLnhZKCJMZW5ndGggbXVzdCBiZSBhIG5vbi1uZWdh
+dGl2ZSBpbnRlZ2VyOiAiK2EpKQpyZXR1cm4gSC5WTShuZXcgQXJyYXkoYSksYi5DKCJqZDwwPiIpKX0s
+CnB5OmZ1bmN0aW9uKGEsYil7cmV0dXJuIEouRXAoSC5WTShhLGIuQygiamQ8MD4iKSksYil9LApFcDpm
+dW5jdGlvbihhLGIpe2EuZml4ZWQkbGVuZ3RoPUFycmF5CnJldHVybiBhfSwKekM6ZnVuY3Rpb24oYSl7
+YS5maXhlZCRsZW5ndGg9QXJyYXkKYS5pbW11dGFibGUkbGlzdD1BcnJheQpyZXR1cm4gYX0sCkdhOmZ1
+bmN0aW9uKGEpe2lmKGE8MjU2KXN3aXRjaChhKXtjYXNlIDk6Y2FzZSAxMDpjYXNlIDExOmNhc2UgMTI6
+Y2FzZSAxMzpjYXNlIDMyOmNhc2UgMTMzOmNhc2UgMTYwOnJldHVybiEwCmRlZmF1bHQ6cmV0dXJuITF9
+c3dpdGNoKGEpe2Nhc2UgNTc2MDpjYXNlIDgxOTI6Y2FzZSA4MTkzOmNhc2UgODE5NDpjYXNlIDgxOTU6
+Y2FzZSA4MTk2OmNhc2UgODE5NzpjYXNlIDgxOTg6Y2FzZSA4MTk5OmNhc2UgODIwMDpjYXNlIDgyMDE6
+Y2FzZSA4MjAyOmNhc2UgODIzMjpjYXNlIDgyMzM6Y2FzZSA4MjM5OmNhc2UgODI4NzpjYXNlIDEyMjg4
+OmNhc2UgNjUyNzk6cmV0dXJuITAKZGVmYXVsdDpyZXR1cm4hMX19LAptbTpmdW5jdGlvbihhLGIpe3Zh
+ciB0LHMKZm9yKHQ9YS5sZW5ndGg7Yjx0Oyl7cz1DLnhCLlcoYSxiKQppZihzIT09MzImJnMhPT0xMyYm
+IUouR2EocykpYnJlYWs7KytifXJldHVybiBifSwKYzE6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzCmZvcig7
+Yj4wO2I9dCl7dD1iLTEKcz1DLnhCLm0oYSx0KQppZihzIT09MzImJnMhPT0xMyYmIUouR2EocykpYnJl
+YWt9cmV0dXJuIGJ9LApUSjpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09Im51bWJlciIpcmV0dXJuIEou
+cUkucHJvdG90eXBlCmlmKHR5cGVvZiBhPT0ic3RyaW5nIilyZXR1cm4gSi5Eci5wcm90b3R5cGUKaWYo
+YT09bnVsbClyZXR1cm4gYQppZihhLmNvbnN0cnVjdG9yPT1BcnJheSlyZXR1cm4gSi5qZC5wcm90b3R5
+cGUKaWYodHlwZW9mIGEhPSJvYmplY3QiKXtpZih0eXBlb2YgYT09ImZ1bmN0aW9uIilyZXR1cm4gSi5j
+NS5wcm90b3R5cGUKcmV0dXJuIGF9aWYoYSBpbnN0YW5jZW9mIFAuTWgpcmV0dXJuIGEKcmV0dXJuIEou
+a3MoYSl9LApVNjpmdW5jdGlvbihhKXtpZih0eXBlb2YgYT09InN0cmluZyIpcmV0dXJuIEouRHIucHJv
+dG90eXBlCmlmKGE9PW51bGwpcmV0dXJuIGEKaWYoYS5jb25zdHJ1Y3Rvcj09QXJyYXkpcmV0dXJuIEou
+amQucHJvdG90eXBlCmlmKHR5cGVvZiBhIT0ib2JqZWN0Iil7aWYodHlwZW9mIGE9PSJmdW5jdGlvbiIp
+cmV0dXJuIEouYzUucHJvdG90eXBlCnJldHVybiBhfWlmKGEgaW5zdGFuY2VvZiBQLk1oKXJldHVybiBh
+CnJldHVybiBKLmtzKGEpfSwKWUU6ZnVuY3Rpb24oYSl7aWYoYT09bnVsbClyZXR1cm4gYQppZih0eXBl
+b2YgYSE9Im9iamVjdCIpe2lmKHR5cGVvZiBhPT0iZnVuY3Rpb24iKXJldHVybiBKLmM1LnByb3RvdHlw
+ZQpyZXR1cm4gYX1pZihhIGluc3RhbmNlb2YgUC5NaClyZXR1cm4gYQpyZXR1cm4gSi5rcyhhKX0sCmlh
+OmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0ibnVtYmVyIil7aWYoTWF0aC5mbG9vcihhKT09YSlyZXR1
+cm4gSi5iVS5wcm90b3R5cGUKcmV0dXJuIEouVkEucHJvdG90eXBlfWlmKHR5cGVvZiBhPT0ic3RyaW5n
+IilyZXR1cm4gSi5Eci5wcm90b3R5cGUKaWYoYT09bnVsbClyZXR1cm4gSi53ZS5wcm90b3R5cGUKaWYo
+dHlwZW9mIGE9PSJib29sZWFuIilyZXR1cm4gSi55RS5wcm90b3R5cGUKaWYoYS5jb25zdHJ1Y3Rvcj09
+QXJyYXkpcmV0dXJuIEouamQucHJvdG90eXBlCmlmKHR5cGVvZiBhIT0ib2JqZWN0Iil7aWYodHlwZW9m
+IGE9PSJmdW5jdGlvbiIpcmV0dXJuIEouYzUucHJvdG90eXBlCnJldHVybiBhfWlmKGEgaW5zdGFuY2Vv
+ZiBQLk1oKXJldHVybiBhCnJldHVybiBKLmtzKGEpfSwKclk6ZnVuY3Rpb24oYSl7aWYodHlwZW9mIGE9
+PSJzdHJpbmciKXJldHVybiBKLkRyLnByb3RvdHlwZQppZihhPT1udWxsKXJldHVybiBhCmlmKCEoYSBp
+bnN0YW5jZW9mIFAuTWgpKXJldHVybiBKLmtkLnByb3RvdHlwZQpyZXR1cm4gYX0sCncxOmZ1bmN0aW9u
+KGEpe2lmKGE9PW51bGwpcmV0dXJuIGEKaWYoYS5jb25zdHJ1Y3Rvcj09QXJyYXkpcmV0dXJuIEouamQu
+cHJvdG90eXBlCmlmKHR5cGVvZiBhIT0ib2JqZWN0Iil7aWYodHlwZW9mIGE9PSJmdW5jdGlvbiIpcmV0
+dXJuIEouYzUucHJvdG90eXBlCnJldHVybiBhfWlmKGEgaW5zdGFuY2VvZiBQLk1oKXJldHVybiBhCnJl
+dHVybiBKLmtzKGEpfSwKQ006ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJuIEouWUUoYSkuZHUoYSxiLGMs
+ZCl9LApFaDpmdW5jdGlvbihhLGIsYyl7cmV0dXJuIEouWUUoYSkubUsoYSxiLGMpfSwKRkw6ZnVuY3Rp
+b24oYSxiKXtyZXR1cm4gSi5yWShhKS5kZChhLGIpfSwKR0E6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSi53
+MShhKS5FKGEsYil9LApHcjpmdW5jdGlvbihhKXtyZXR1cm4gSi5ZRShhKS5nbVcoYSl9LApIbTpmdW5j
+dGlvbihhKXtyZXR1cm4gSi5VNihhKS5nQShhKX0sCklUOmZ1bmN0aW9uKGEpe3JldHVybiBKLncxKGEp
+LmdreihhKX0sCkp5OmZ1bmN0aW9uKGEsYil7cmV0dXJuIEouaWEoYSkuZTcoYSxiKX0sCktWOmZ1bmN0
+aW9uKGEsYil7cmV0dXJuIEouclkoYSkuRyhhLGIpfSwKTHQ6ZnVuY3Rpb24oYSl7cmV0dXJuIEouWUUo
+YSkud2coYSl9LApNMTpmdW5jdGlvbihhLGIsYyl7cmV0dXJuIEoudzEoYSkuRTIoYSxiLGMpfSwKTXU6
+ZnVuY3Rpb24oYSxiKXtyZXR1cm4gSi5ZRShhKS5zUChhLGIpfSwKUXo6ZnVuY3Rpb24oYSxiKXtyZXR1
+cm4gSi5yWShhKS5XKGEsYil9LApSTTpmdW5jdGlvbihhLGIpe2lmKGE9PW51bGwpcmV0dXJuIGI9PW51
+bGwKaWYodHlwZW9mIGEhPSJvYmplY3QiKXJldHVybiBiIT1udWxsJiZhPT09YgpyZXR1cm4gSi5pYShh
+KS5ETihhLGIpfSwKVDA6ZnVuY3Rpb24oYSl7cmV0dXJuIEouclkoYSkuYlMoYSl9LAphNjpmdW5jdGlv
+bihhLGIpe3JldHVybiBKLnJZKGEpLm0oYSxiKX0sCmJUOmZ1bmN0aW9uKGEpe3JldHVybiBKLllFKGEp
+LkQ0KGEpfSwKYmI6ZnVuY3Rpb24oYSxiKXtpZih0eXBlb2YgYT09Im51bWJlciImJnR5cGVvZiBiPT0i
+bnVtYmVyIilyZXR1cm4gYStiCnJldHVybiBKLlRKKGEpLmgoYSxiKX0sCmNIOmZ1bmN0aW9uKGEpe3Jl
+dHVybiBKLnJZKGEpLmhjKGEpfSwKZFI6ZnVuY3Rpb24oYSl7cmV0dXJuIEouWUUoYSkuZ1AoYSl9LApk
+WjpmdW5jdGlvbihhLGIsYyxkKXtyZXR1cm4gSi5ZRShhKS5PbihhLGIsYyxkKX0sCmRnOmZ1bmN0aW9u
+KGEsYixjLGQpe3JldHVybiBKLnJZKGEpLmk3KGEsYixjLGQpfSwKZGg6ZnVuY3Rpb24oYSl7cmV0dXJu
+IEouWUUoYSkuRkYoYSl9LApkcjpmdW5jdGlvbihhLGIpe3JldHVybiBKLllFKGEpLnNhNChhLGIpfSwK
+aGY6ZnVuY3Rpb24oYSl7cmV0dXJuIEouaWEoYSkuZ2lPKGEpfSwKaWc6ZnVuY3Rpb24oYSl7cmV0dXJu
+IEouWUUoYSkuZ1FnKGEpfSwKajpmdW5jdGlvbihhKXtyZXR1cm4gSi5pYShhKS53KGEpfSwKbDU6ZnVu
+Y3Rpb24oYSxiKXtyZXR1cm4gSi5ZRShhKS5zaGYoYSxiKX0sCmxkOmZ1bmN0aW9uKGEsYixjKXtyZXR1
+cm4gSi5yWShhKS5OaihhLGIsYyl9LApxMDpmdW5jdGlvbihhLGIsYyl7cmV0dXJuIEouclkoYSkuUWko
+YSxiLGMpfSwKcUY6ZnVuY3Rpb24oYSl7cmV0dXJuIEouWUUoYSkuZ1ZsKGEpfSwKdEg6ZnVuY3Rpb24o
+YSxiLGMpe3JldHVybiBKLllFKGEpLnBrKGEsYixjKX0sCnVVOmZ1bmN0aW9uKGEpe3JldHVybiBKLlU2
+KGEpLmdsMChhKX0sCndmOmZ1bmN0aW9uKGEsYil7cmV0dXJuIEouWUUoYSkuc1JOKGEsYil9LAp4OTpm
+dW5jdGlvbihhLGIpe2lmKHR5cGVvZiBiPT09Im51bWJlciIpaWYoYS5jb25zdHJ1Y3Rvcj09QXJyYXl8
+fHR5cGVvZiBhPT0ic3RyaW5nInx8SC53VihhLGFbdi5kaXNwYXRjaFByb3BlcnR5TmFtZV0pKWlmKGI+
+Pj4wPT09YiYmYjxhLmxlbmd0aClyZXR1cm4gYVtiXQpyZXR1cm4gSi5VNihhKS5xKGEsYil9LAp6bDpm
+dW5jdGlvbihhLGIpe3JldHVybiBKLlU2KGEpLnRnKGEsYil9LAp2QjpmdW5jdGlvbiB2Qigpe30sCnlF
+OmZ1bmN0aW9uIHlFKCl7fSwKd2U6ZnVuY3Rpb24gd2UoKXt9LApNRjpmdW5jdGlvbiBNRigpe30sCmlD
+OmZ1bmN0aW9uIGlDKCl7fSwKa2Q6ZnVuY3Rpb24ga2QoKXt9LApjNTpmdW5jdGlvbiBjNSgpe30sCmpk
+OmZ1bmN0aW9uIGpkKGEpe3RoaXMuJHRpPWF9LApQbzpmdW5jdGlvbiBQbyhhKXt0aGlzLiR0aT1hfSwK
+bTE6ZnVuY3Rpb24gbTEoYSxiLGMpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPTAKXy5kPW51bGwK
+Xy4kdGk9Y30sCnFJOmZ1bmN0aW9uIHFJKCl7fSwKYlU6ZnVuY3Rpb24gYlUoKXt9LApWQTpmdW5jdGlv
+biBWQSgpe30sCkRyOmZ1bmN0aW9uIERyKCl7fX0sUD17Ck9qOmZ1bmN0aW9uKCl7dmFyIHQscyxyPXt9
+CmlmKHNlbGYuc2NoZWR1bGVJbW1lZGlhdGUhPW51bGwpcmV0dXJuIFAuRVgoKQppZihzZWxmLk11dGF0
+aW9uT2JzZXJ2ZXIhPW51bGwmJnNlbGYuZG9jdW1lbnQhPW51bGwpe3Q9c2VsZi5kb2N1bWVudC5jcmVh
+dGVFbGVtZW50KCJkaXYiKQpzPXNlbGYuZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgic3BhbiIpCnIuYT1u
+dWxsCm5ldyBzZWxmLk11dGF0aW9uT2JzZXJ2ZXIoSC50UihuZXcgUC50aChyKSwxKSkub2JzZXJ2ZSh0
+LHtjaGlsZExpc3Q6dHJ1ZX0pCnJldHVybiBuZXcgUC5oYShyLHQscyl9ZWxzZSBpZihzZWxmLnNldElt
+bWVkaWF0ZSE9bnVsbClyZXR1cm4gUC55dCgpCnJldHVybiBQLnFXKCl9LApaVjpmdW5jdGlvbihhKXtz
+ZWxmLnNjaGVkdWxlSW1tZWRpYXRlKEgudFIobmV3IFAuVnModS5NLmEoYSkpLDApKX0sCm9BOmZ1bmN0
+aW9uKGEpe3NlbGYuc2V0SW1tZWRpYXRlKEgudFIobmV3IFAuRnQodS5NLmEoYSkpLDApKX0sCkJ6OmZ1
+bmN0aW9uKGEpe3UuTS5hKGEpClAuUU4oMCxhKX0sClFOOmZ1bmN0aW9uKGEsYil7dmFyIHQ9bmV3IFAu
+VzMoKQp0LkNZKGEsYikKcmV0dXJuIHR9LApGWDpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAuaWgobmV3
+IFAudnMoJC5YMyxhLkMoInZzPDA+IikpLGEuQygiaWg8MD4iKSl9LApESTpmdW5jdGlvbihhLGIpe2Eu
+JDIoMCxudWxsKQpiLmI9ITAKcmV0dXJuIGIuYX0sCmpROmZ1bmN0aW9uKGEsYil7UC5KZShhLGIpfSwK
+eUM6ZnVuY3Rpb24oYSxiKXtiLmFNKDAsYSl9LApmMzpmdW5jdGlvbihhLGIpe2IudzAoSC5SdShhKSxI
+LnRzKGEpKX0sCkplOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyPW5ldyBQLldNKGIpLHE9bmV3IFAuU1go
+YikKaWYoYSBpbnN0YW5jZW9mIFAudnMpYS5RZChyLHEsdS56KQplbHNle3Q9dS56CmlmKHUuZC5iKGEp
+KWEuU3EocixxLHQpCmVsc2V7cz1uZXcgUC52cygkLlgzLHUuYykKcy5hPTQKcy5jPWEKcy5RZChyLHEs
+dCl9fX0sCmx6OmZ1bmN0aW9uKGEpe3ZhciB0PWZ1bmN0aW9uKGIsYyl7cmV0dXJuIGZ1bmN0aW9uKGQs
+ZSl7d2hpbGUodHJ1ZSl0cnl7YihkLGUpCmJyZWFrfWNhdGNoKHMpe2U9cwpkPWN9fX0oYSwxKQpyZXR1
+cm4gJC5YMy5MaihuZXcgUC5Hcyh0KSx1LlAsdS5TLHUueil9LApHUTpmdW5jdGlvbihhKXtyZXR1cm4g
+bmV3IFAuRnkoYSwxKX0sClRoOmZ1bmN0aW9uKCl7cmV0dXJuIEMud1F9LApZbTpmdW5jdGlvbihhKXty
+ZXR1cm4gbmV3IFAuRnkoYSwzKX0sCmwwOmZ1bmN0aW9uKGEsYil7cmV0dXJuIG5ldyBQLnE0KGEsYi5D
+KCJxNDwwPiIpKX0sCmszOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyCmIuYT0xCnRyeXthLlNxKG5ldyBQ
+LnBWKGIpLG5ldyBQLlU3KGIpLHUuUCl9Y2F0Y2gocil7dD1ILlJ1KHIpCnM9SC50cyhyKQpQLnJiKG5l
+dyBQLnZyKGIsdCxzKSl9fSwKQTk6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIKZm9yKHQ9dS5jO3M9YS5h
+LHM9PT0yOylhPXQuYShhLmMpCmlmKHM+PTQpe3I9Yi5haCgpCmIuYT1hLmEKYi5jPWEuYwpQLkhaKGIs
+cil9ZWxzZXtyPXUuRi5hKGIuYykKYi5hPTIKYi5jPWEKYS5qUShyKX19LApIWjpmdW5jdGlvbihhLGEw
+KXt2YXIgdCxzLHIscSxwLG8sbixtLGwsayxqLGksaCxnLGYsZSxkPW51bGwsYz17fSxiPWMuYT1hCmZv
+cih0PXUubixzPXUuRixyPXUuZDshMDspe3E9e30KcD1iLmE9PT04CmlmKGEwPT1udWxsKXtpZihwKXtv
+PXQuYShiLmMpClAuTDIoZCxkLGIuYixvLmEsby5iKX1yZXR1cm59cS5hPWEwCm49YTAuYQpmb3IoYj1h
+MDtuIT1udWxsO2I9bixuPW0pe2IuYT1udWxsClAuSFooYy5hLGIpCnEuYT1uCm09bi5hfWw9Yy5hCms9
+bC5jCnEuYj1wCnEuYz1rCmo9IXAKaWYoail7aT1iLmMKaT0oaSYxKSE9PTB8fChpJjE1KT09PTh9ZWxz
+ZSBpPSEwCmlmKGkpe2g9Yi5iLmIKaWYocCl7aT1sLmI9PT1oCmk9IShpfHxpKX1lbHNlIGk9ITEKaWYo
+aSl7dC5hKGspClAuTDIoZCxkLGwuYixrLmEsay5iKQpyZXR1cm59Zz0kLlgzCmlmKGchPT1oKSQuWDM9
+aAplbHNlIGc9ZApiPWIuYwppZigoYiYxNSk9PT04KW5ldyBQLlJUKHEsYyxwKS4kMCgpCmVsc2UgaWYo
+ail7aWYoKGImMSkhPT0wKW5ldyBQLnJxKHEsaykuJDAoKX1lbHNlIGlmKChiJjIpIT09MCluZXcgUC5S
+VyhjLHEpLiQwKCkKaWYoZyE9bnVsbCkkLlgzPWcKYj1xLmMKaWYoci5iKGIpKXtmPXEuYS5iCmlmKGIu
+YT49NCl7ZT1zLmEoZi5jKQpmLmM9bnVsbAphMD1mLk44KGUpCmYuYT1iLmEKZi5jPWIuYwpjLmE9Ygpj
+b250aW51ZX1lbHNlIFAuQTkoYixmKQpyZXR1cm59fWY9cS5hLmIKZT1zLmEoZi5jKQpmLmM9bnVsbAph
+MD1mLk44KGUpCmI9cS5iCmw9cS5jCmlmKCFiKXtmLiR0aS5jLmEobCkKZi5hPTQKZi5jPWx9ZWxzZXt0
+LmEobCkKZi5hPTgKZi5jPWx9Yy5hPWYKYj1mfX0sClZIOmZ1bmN0aW9uKGEsYil7dmFyIHQKaWYodS5h
+Zy5iKGEpKXJldHVybiBiLkxqKGEsdS56LHUuSyx1LmwpCnQ9dS5iSQppZih0LmIoYSkpcmV0dXJuIHQu
+YShhKQp0aHJvdyBILmIoUC5MMyhhLCJvbkVycm9yIiwiRXJyb3IgaGFuZGxlciBtdXN0IGFjY2VwdCBv
+bmUgT2JqZWN0IG9yIG9uZSBPYmplY3QgYW5kIGEgU3RhY2tUcmFjZSBhcyBhcmd1bWVudHMsIGFuZCBy
+ZXR1cm4gYSBhIHZhbGlkIHJlc3VsdCIpKX0sCnB1OmZ1bmN0aW9uKCl7dmFyIHQscwpmb3IodD0kLlM2
+O3QhPW51bGw7dD0kLlM2KXskLm1nPW51bGwKcz10LmIKJC5TNj1zCmlmKHM9PW51bGwpJC5rOD1udWxs
+CnQuYS4kMCgpfX0sCmVOOmZ1bmN0aW9uKCl7JC5VRD0hMAp0cnl7UC5wdSgpfWZpbmFsbHl7JC5tZz1u
+dWxsCiQuVUQ9ITEKaWYoJC5TNiE9bnVsbCkkLnV0KCkuJDEoUC5WOSgpKX19LAplVzpmdW5jdGlvbihh
+KXt2YXIgdD1uZXcgUC5PTShhKSxzPSQuazgKaWYocz09bnVsbCl7JC5TNj0kLms4PXQKaWYoISQuVUQp
+JC51dCgpLiQxKFAuVjkoKSl9ZWxzZSAkLms4PXMuYj10fSwKclI6ZnVuY3Rpb24oYSl7dmFyIHQscyxy
+LHE9JC5TNgppZihxPT1udWxsKXtQLmVXKGEpCiQubWc9JC5rOApyZXR1cm59dD1uZXcgUC5PTShhKQpz
+PSQubWcKaWYocz09bnVsbCl7dC5iPXEKJC5TNj0kLm1nPXR9ZWxzZXtyPXMuYgp0LmI9cgokLm1nPXMu
+Yj10CmlmKHI9PW51bGwpJC5rOD10fX0sCnJiOmZ1bmN0aW9uKGEpe3ZhciB0PW51bGwscz0kLlgzCmlm
+KEMuTlU9PT1zKXtQLlRrKHQsdCxDLk5VLGEpCnJldHVybn1QLlRrKHQsdCxzLHUuTS5hKHMuR1koYSkp
+KX0sClF3OmZ1bmN0aW9uKGEsYil7UC5VSShhLCJzdHJlYW0iLGIuQygicWg8MD4iKSkKcmV0dXJuIG5l
+dyBQLnhJKGIuQygieEk8MD4iKSl9LApUbDpmdW5jdGlvbihhLGIpe3ZhciB0PWI9PW51bGw/UC52MChh
+KTpiClAuVUkoYSwiZXJyb3IiLHUuSykKcmV0dXJuIG5ldyBQLkN3KGEsdCl9LAp2MDpmdW5jdGlvbihh
+KXt2YXIgdAppZih1Lm0uYihhKSl7dD1hLmdJSSgpCmlmKHQhPW51bGwpcmV0dXJuIHR9cmV0dXJuIEMu
+cGR9LApMMjpmdW5jdGlvbihhLGIsYyxkLGUpe1AuclIobmV3IFAucEsoZCxlKSl9LApUODpmdW5jdGlv
+bihhLGIsYyxkLGUpe3ZhciB0LHM9JC5YMwppZihzPT09YylyZXR1cm4gZC4kMCgpCiQuWDM9Ywp0PXMK
+dHJ5e3M9ZC4kMCgpCnJldHVybiBzfWZpbmFsbHl7JC5YMz10fX0sCnl2OmZ1bmN0aW9uKGEsYixjLGQs
+ZSxmLGcpe3ZhciB0LHM9JC5YMwppZihzPT09YylyZXR1cm4gZC4kMShlKQokLlgzPWMKdD1zCnRyeXtz
+PWQuJDEoZSkKcmV0dXJuIHN9ZmluYWxseXskLlgzPXR9fSwKUXg6ZnVuY3Rpb24oYSxiLGMsZCxlLGYs
+ZyxoLGkpe3ZhciB0LHM9JC5YMwppZihzPT09YylyZXR1cm4gZC4kMihlLGYpCiQuWDM9Ywp0PXMKdHJ5
+e3M9ZC4kMihlLGYpCnJldHVybiBzfWZpbmFsbHl7JC5YMz10fX0sClRrOmZ1bmN0aW9uKGEsYixjLGQp
+e3ZhciB0CnUuTS5hKGQpCnQ9Qy5OVSE9PWMKaWYodClkPSEoIXR8fCExKT9jLkdZKGQpOmMuUlQoZCx1
+LkgpClAuZVcoZCl9LAp0aDpmdW5jdGlvbiB0aChhKXt0aGlzLmE9YX0sCmhhOmZ1bmN0aW9uIGhhKGEs
+YixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sClZzOmZ1bmN0aW9uIFZzKGEpe3RoaXMuYT1h
+fSwKRnQ6ZnVuY3Rpb24gRnQoYSl7dGhpcy5hPWF9LApXMzpmdW5jdGlvbiBXMygpe30sCnlIOmZ1bmN0
+aW9uIHlIKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LAppaDpmdW5jdGlvbiBpaChhLGIpe3RoaXMuYT1h
+CnRoaXMuYj0hMQp0aGlzLiR0aT1ifSwKV006ZnVuY3Rpb24gV00oYSl7dGhpcy5hPWF9LApTWDpmdW5j
+dGlvbiBTWChhKXt0aGlzLmE9YX0sCkdzOmZ1bmN0aW9uIEdzKGEpe3RoaXMuYT1hfSwKRnk6ZnVuY3Rp
+b24gRnkoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCkdWOmZ1bmN0aW9uIEdWKGEsYil7dmFyIF89dGhp
+cwpfLmE9YQpfLmQ9Xy5jPV8uYj1udWxsCl8uJHRpPWJ9LApxNDpmdW5jdGlvbiBxNChhLGIpe3RoaXMu
+YT1hCnRoaXMuJHRpPWJ9LApiODpmdW5jdGlvbiBiOCgpe30sClBmOmZ1bmN0aW9uIFBmKCl7fSwKWmY6
+ZnVuY3Rpb24gWmYoYSxiKXt0aGlzLmE9YQp0aGlzLiR0aT1ifSwKRmU6ZnVuY3Rpb24gRmUoYSxiLGMs
+ZCxlKXt2YXIgXz10aGlzCl8uYT1udWxsCl8uYj1hCl8uYz1iCl8uZD1jCl8uZT1kCl8uJHRpPWV9LAp2
+czpmdW5jdGlvbiB2cyhhLGIpe3ZhciBfPXRoaXMKXy5hPTAKXy5iPWEKXy5jPW51bGwKXy4kdGk9Yn0s
+CmRhOmZ1bmN0aW9uIGRhKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApvUTpmdW5jdGlvbiBvUShhLGIp
+e3RoaXMuYT1hCnRoaXMuYj1ifSwKcFY6ZnVuY3Rpb24gcFYoYSl7dGhpcy5hPWF9LApVNzpmdW5jdGlv
+biBVNyhhKXt0aGlzLmE9YX0sCnZyOmZ1bmN0aW9uIHZyKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0
+aGlzLmM9Y30sCnJ0OmZ1bmN0aW9uIHJ0KGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApLRjpmdW5jdGlv
+biBLRihhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKWkw6ZnVuY3Rpb24gWkwoYSxiLGMpe3RoaXMuYT1h
+CnRoaXMuYj1iCnRoaXMuYz1jfSwKUlQ6ZnVuY3Rpb24gUlQoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1i
+CnRoaXMuYz1jfSwKalo6ZnVuY3Rpb24galooYSl7dGhpcy5hPWF9LApycTpmdW5jdGlvbiBycShhLGIp
+e3RoaXMuYT1hCnRoaXMuYj1ifSwKUlc6ZnVuY3Rpb24gUlcoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0s
+Ck9NOmZ1bmN0aW9uIE9NKGEpe3RoaXMuYT1hCnRoaXMuYj1udWxsfSwKcWg6ZnVuY3Rpb24gcWgoKXt9
+LApCNTpmdW5jdGlvbiBCNShhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKdU86ZnVuY3Rpb24gdU8oYSxi
+KXt0aGlzLmE9YQp0aGlzLmI9Yn0sCk1POmZ1bmN0aW9uIE1PKCl7fSwKa1Q6ZnVuY3Rpb24ga1QoKXt9
+LAp4STpmdW5jdGlvbiB4SShhKXt0aGlzLiR0aT1hfSwKQ3c6ZnVuY3Rpb24gQ3coYSxiKXt0aGlzLmE9
+YQp0aGlzLmI9Yn0sCm0wOmZ1bmN0aW9uIG0wKCl7fSwKcEs6ZnVuY3Rpb24gcEsoYSxiKXt0aGlzLmE9
+YQp0aGlzLmI9Yn0sCkppOmZ1bmN0aW9uIEppKCl7fSwKaGo6ZnVuY3Rpb24gaGooYSxiLGMpe3RoaXMu
+YT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKVnA6ZnVuY3Rpb24gVnAoYSxiKXt0aGlzLmE9YQp0aGlzLmI9
+Yn0sCk9SOmZ1bmN0aW9uIE9SKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sCkVGOmZ1
+bmN0aW9uKGEsYixjKXtyZXR1cm4gYi5DKCJAPDA+IikuS3EoYykuQygiRm88MSwyPiIpLmEoSC5CNyhh
+LG5ldyBILk41KGIuQygiQDwwPiIpLktxKGMpLkMoIk41PDEsMj4iKSkpKX0sCkZsOmZ1bmN0aW9uKGEs
+Yil7cmV0dXJuIG5ldyBILk41KGEuQygiQDwwPiIpLktxKGIpLkMoIk41PDEsMj4iKSl9LApMczpmdW5j
+dGlvbihhKXtyZXR1cm4gbmV3IFAuYjYoYS5DKCJiNjwwPiIpKX0sClQyOmZ1bmN0aW9uKCl7dmFyIHQ9
+T2JqZWN0LmNyZWF0ZShudWxsKQp0WyI8bm9uLWlkZW50aWZpZXIta2V5PiJdPXQKZGVsZXRlIHRbIjxu
+b24taWRlbnRpZmllci1rZXk+Il0KcmV0dXJuIHR9LApyajpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9bmV3
+IFAubG0oYSxiLGMuQygibG08MD4iKSkKdC5jPWEuZQpyZXR1cm4gdH0sCkVQOmZ1bmN0aW9uKGEsYixj
+KXt2YXIgdCxzCmlmKFAuaEIoYSkpe2lmKGI9PT0iKCImJmM9PT0iKSIpcmV0dXJuIiguLi4pIgpyZXR1
+cm4gYisiLi4uIitjfXQ9SC5WTShbXSx1LnMpCkMuTm0uaSgkLnhnLGEpCnRyeXtQLlZyKGEsdCl9Zmlu
+YWxseXtpZigwPj0kLnhnLmxlbmd0aClyZXR1cm4gSC5PSCgkLnhnLC0xKQokLnhnLnBvcCgpfXM9UC52
+ZyhiLHUucC5hKHQpLCIsICIpK2MKcmV0dXJuIHMuY2hhckNvZGVBdCgwKT09MD9zOnN9LApXRTpmdW5j
+dGlvbihhLGIsYyl7dmFyIHQscwppZihQLmhCKGEpKXJldHVybiBiKyIuLi4iK2MKdD1uZXcgUC5Sbihi
+KQpDLk5tLmkoJC54ZyxhKQp0cnl7cz10CnMuYT1QLnZnKHMuYSxhLCIsICIpfWZpbmFsbHl7aWYoMD49
+JC54Zy5sZW5ndGgpcmV0dXJuIEguT0goJC54ZywtMSkKJC54Zy5wb3AoKX10LmErPWMKcz10LmEKcmV0
+dXJuIHMuY2hhckNvZGVBdCgwKT09MD9zOnN9LApoQjpmdW5jdGlvbihhKXt2YXIgdCxzCmZvcih0PSQu
+eGcubGVuZ3RoLHM9MDtzPHQ7KytzKWlmKGE9PT0kLnhnW3NdKXJldHVybiEwCnJldHVybiExfSwKVnI6
+ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxwLG8sbixtPWEuZ2t6KGEpLGw9MCxrPTAKd2hpbGUoITAp
+e2lmKCEobDw4MHx8azwzKSlicmVhawppZighbS5GKCkpcmV0dXJuCnQ9SC5FaihtLmdsKCkpCkMuTm0u
+aShiLHQpCmwrPXQubGVuZ3RoKzI7KytrfWlmKCFtLkYoKSl7aWYoazw9NSlyZXR1cm4KaWYoMD49Yi5s
+ZW5ndGgpcmV0dXJuIEguT0goYiwtMSkKcz1iLnBvcCgpCmlmKDA+PWIubGVuZ3RoKXJldHVybiBILk9I
+KGIsLTEpCnI9Yi5wb3AoKX1lbHNle3E9bS5nbCgpOysrawppZighbS5GKCkpe2lmKGs8PTQpe0MuTm0u
+aShiLEguRWoocSkpCnJldHVybn1zPUguRWoocSkKaWYoMD49Yi5sZW5ndGgpcmV0dXJuIEguT0goYiwt
 MSkKcj1iLnBvcCgpCmwrPXMubGVuZ3RoKzJ9ZWxzZXtwPW0uZ2woKTsrK2sKZm9yKDttLkYoKTtxPXAs
 cD1vKXtvPW0uZ2woKTsrK2sKaWYoaz4xMDApe3doaWxlKCEwKXtpZighKGw+NzUmJms+MykpYnJlYWsK
-aWYoMD49Yi5sZW5ndGgpcmV0dXJuIEguayhiLC0xKQpsLT1iLnBvcCgpLmxlbmd0aCsyOy0ta31DLk5t
-LmkoYiwiLi4uIikKcmV0dXJufX1yPUguZChxKQpzPUguZChwKQpsKz1zLmxlbmd0aCtyLmxlbmd0aCs0
-fX1pZihrPmIubGVuZ3RoKzIpe2wrPTUKbj0iLi4uIn1lbHNlIG49bnVsbAp3aGlsZSghMCl7aWYoIShs
-PjgwJiZiLmxlbmd0aD4zKSlicmVhawppZigwPj1iLmxlbmd0aClyZXR1cm4gSC5rKGIsLTEpCmwtPWIu
-cG9wKCkubGVuZ3RoKzIKaWYobj09bnVsbCl7bCs9NQpuPSIuLi4ifX1pZihuIT1udWxsKUMuTm0uaShi
-LG4pCkMuTm0uaShiLHIpCkMuTm0uaShiLHMpfSwKdE06ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHI9UC5M
-cyhiKQpmb3IodD1hLmxlbmd0aCxzPTA7czxhLmxlbmd0aDthLmxlbmd0aD09PXR8fCgwLEgubGspKGEp
-LCsrcylyLmkoMCxiLmEoYVtzXSkpCnJldHVybiByfSwKbk86ZnVuY3Rpb24oYSl7dmFyIHQscz17fQpp
-ZihQLmhCKGEpKXJldHVybiJ7Li4ufSIKdD1uZXcgUC5SbigiIikKdHJ5e0MuTm0uaSgkLnhnLGEpCnQu
-YSs9InsiCnMuYT0hMAphLksoMCxuZXcgUC5yYShzLHQpKQp0LmErPSJ9In1maW5hbGx5e2lmKDA+PSQu
-eGcubGVuZ3RoKXJldHVybiBILmsoJC54ZywtMSkKJC54Zy5wb3AoKX1zPXQuYQpyZXR1cm4gcy5jaGFy
-Q29kZUF0KDApPT0wP3M6c30sCmI2OmZ1bmN0aW9uIGI2KGEpe3ZhciBfPXRoaXMKXy5hPTAKXy5mPV8u
-ZT1fLmQ9Xy5jPV8uYj1udWxsCl8ucj0wCl8uJHRpPWF9LApibjpmdW5jdGlvbiBibihhKXt0aGlzLmE9
-YQp0aGlzLmM9dGhpcy5iPW51bGx9LApsbTpmdW5jdGlvbiBsbShhLGIsYyl7dmFyIF89dGhpcwpfLmE9
-YQpfLmI9YgpfLmQ9Xy5jPW51bGwKXy4kdGk9Y30sCm1XOmZ1bmN0aW9uIG1XKCl7fSwKdXk6ZnVuY3Rp
-b24gdXkoKXt9LApsRDpmdW5jdGlvbiBsRCgpe30sCmlsOmZ1bmN0aW9uIGlsKCl7fSwKcmE6ZnVuY3Rp
-b24gcmEoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCllrOmZ1bmN0aW9uIFlrKCl7fSwKeVE6ZnVuY3Rp
-b24geVEoYSl7dGhpcy5hPWF9LApLUDpmdW5jdGlvbiBLUCgpe30sClBuOmZ1bmN0aW9uIFBuKCl7fSwK
-R2o6ZnVuY3Rpb24gR2ooYSxiKXt0aGlzLmE9YQp0aGlzLiR0aT1ifSwKTWE6ZnVuY3Rpb24gTWEoKXt9
-LApWajpmdW5jdGlvbiBWaigpe30sClh2OmZ1bmN0aW9uIFh2KCl7fSwKblk6ZnVuY3Rpb24gblkoKXt9
-LApUQzpmdW5jdGlvbiBUQygpe30sClJVOmZ1bmN0aW9uIFJVKCl7fSwKQlM6ZnVuY3Rpb24oYSxiKXt2
-YXIgdCxzLHIscQppZih0eXBlb2YgYSE9InN0cmluZyIpdGhyb3cgSC5iKEguSShhKSkKdD1udWxsCnRy
-eXt0PUpTT04ucGFyc2UoYSl9Y2F0Y2gocil7cz1ILlJ1KHIpCnE9UC5ycihTdHJpbmcocyksbnVsbCxu
-dWxsKQp0aHJvdyBILmIocSl9cT1QLlFlKHQpCnJldHVybiBxfSwKUWU6ZnVuY3Rpb24oYSl7dmFyIHQK
-aWYoYT09bnVsbClyZXR1cm4gbnVsbAppZih0eXBlb2YgYSE9Im9iamVjdCIpcmV0dXJuIGEKaWYoT2Jq
-ZWN0LmdldFByb3RvdHlwZU9mKGEpIT09QXJyYXkucHJvdG90eXBlKXJldHVybiBuZXcgUC51dyhhLE9i
-amVjdC5jcmVhdGUobnVsbCkpCmZvcih0PTA7dDxhLmxlbmd0aDsrK3QpYVt0XT1QLlFlKGFbdF0pCnJl
-dHVybiBhfSwKa3k6ZnVuY3Rpb24oYSxiLGMsZCl7aWYoYiBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpcmV0
-dXJuIFAuUlAoITEsYixjLGQpCnJldHVybiBudWxsfSwKUlA6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQs
-cyxyPSQudEwoKQppZihyPT1udWxsKXJldHVybiBudWxsCnQ9MD09PWMKaWYodCYmITApcmV0dXJuIFAu
-T1EocixiKQpzPWIubGVuZ3RoCmQ9UC5qQihjLGQscykKaWYodCYmZD09PXMpcmV0dXJuIFAuT1Eocixi
-KQpyZXR1cm4gUC5PUShyLGIuc3ViYXJyYXkoYyxkKSl9LApPUTpmdW5jdGlvbihhLGIpe2lmKFAuQWoo
-YikpcmV0dXJuIG51bGwKcmV0dXJuIFAuSmgoYSxiKX0sCkpoOmZ1bmN0aW9uKGEsYil7dmFyIHQscwp0
-cnl7dD1hLmRlY29kZShiKQpyZXR1cm4gdH1jYXRjaChzKXtILlJ1KHMpfXJldHVybiBudWxsfSwKQWo6
-ZnVuY3Rpb24oYSl7dmFyIHQscz1hLmxlbmd0aC0yCmZvcih0PTA7dDxzOysrdClpZihhW3RdPT09MjM3
-KWlmKChhW3QrMV0mMjI0KT09PTE2MClyZXR1cm4hMApyZXR1cm4hMX0sCldJOmZ1bmN0aW9uKCl7dmFy
-IHQscwp0cnl7dD1uZXcgVGV4dERlY29kZXIoInV0Zi04Iix7ZmF0YWw6dHJ1ZX0pCnJldHVybiB0fWNh
-dGNoKHMpe0guUnUocyl9cmV0dXJuIG51bGx9LApjUDpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyCmZv
-cih0PUouVTYoYSkscz1iO3M8YzsrK3Mpe3I9dC5xKGEscykKaWYodHlwZW9mIHIhPT0ibnVtYmVyIily
-ZXR1cm4gci56TSgpCmlmKChyJjEyNykhPT1yKXJldHVybiBzLWJ9cmV0dXJuIGMtYn0sCnhNOmZ1bmN0
-aW9uKGEsYixjLGQsZSxmKXtpZihDLmpuLnpZKGYsNCkhPT0wKXRocm93IEguYihQLnJyKCJJbnZhbGlk
-IGJhc2U2NCBwYWRkaW5nLCBwYWRkZWQgbGVuZ3RoIG11c3QgYmUgbXVsdGlwbGUgb2YgZm91ciwgaXMg
-IitmLGEsYykpCmlmKGQrZSE9PWYpdGhyb3cgSC5iKFAucnIoIkludmFsaWQgYmFzZTY0IHBhZGRpbmcs
-ICc9JyBub3QgYXQgdGhlIGVuZCIsYSxiKSkKaWYoZT4yKXRocm93IEguYihQLnJyKCJJbnZhbGlkIGJh
-c2U2NCBwYWRkaW5nLCBtb3JlIHRoYW4gdHdvICc9JyBjaGFyYWN0ZXJzIixhLGIpKX0sCkd5OmZ1bmN0
-aW9uKGEsYixjKXtyZXR1cm4gbmV3IFAuVWQoYSxiKX0sCk5DOmZ1bmN0aW9uKGEpe3JldHVybiBhLkx0
-KCl9LAp1WDpmdW5jdGlvbihhLGIsYyl7dmFyIHQscz1uZXcgUC5SbigiIikscj1uZXcgUC50dShzLFtd
-LFAuQ3koKSkKci5pVShhKQp0PXMuYQpyZXR1cm4gdC5jaGFyQ29kZUF0KDApPT0wP3Q6dH0sCnV3OmZ1
-bmN0aW9uIHV3KGEsYil7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPW51bGx9LAppODpmdW5jdGlvbiBp
-OChhKXt0aGlzLmE9YX0sCkNWOmZ1bmN0aW9uIENWKCl7fSwKVTg6ZnVuY3Rpb24gVTgoKXt9LApVazpm
-dW5jdGlvbiBVaygpe30sCndJOmZ1bmN0aW9uIHdJKCl7fSwKWmk6ZnVuY3Rpb24gWmkoKXt9LApVZDpm
-dW5jdGlvbiBVZChhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKSzg6ZnVuY3Rpb24gSzgoYSxiKXt0aGlz
-LmE9YQp0aGlzLmI9Yn0sCmJ5OmZ1bmN0aW9uIGJ5KCl7fSwKb2o6ZnVuY3Rpb24gb2ooYSl7dGhpcy5i
-PWF9LApNeDpmdW5jdGlvbiBNeChhKXt0aGlzLmE9YX0sClNoOmZ1bmN0aW9uIFNoKCl7fSwKdGk6ZnVu
-Y3Rpb24gdGkoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCnR1OmZ1bmN0aW9uIHR1KGEsYixjKXt0aGlz
-LmM9YQp0aGlzLmE9Ygp0aGlzLmI9Y30sCnU1OmZ1bmN0aW9uIHU1KCl7fSwKRTM6ZnVuY3Rpb24gRTMo
-KXt9LApSdzpmdW5jdGlvbiBSdyhhKXt0aGlzLmI9MAp0aGlzLmM9YX0sCkdZOmZ1bmN0aW9uIEdZKGEp
-e3RoaXMuYT1hfSwKYno6ZnVuY3Rpb24gYnooYSxiKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz0h
-MApfLmY9Xy5lPV8uZD0wfSwKUUE6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0PUguSHAoYSxjKQppZih0IT1u
-dWxsKXJldHVybiB0CmlmKGIhPW51bGwpcmV0dXJuIGIuJDEoYSkKdGhyb3cgSC5iKFAucnIoYSxudWxs
-LG51bGwpKX0sCm9zOmZ1bmN0aW9uKGEpe2lmKGEgaW5zdGFuY2VvZiBILlRwKXJldHVybiBhLlooMCkK
-cmV0dXJuIkluc3RhbmNlIG9mICciK0guZChILmxoKGEpKSsiJyJ9LApPODpmdW5jdGlvbihhLGIsYyxk
-KXt2YXIgdCxzCmlmKGMpdD1ILlZNKG5ldyBBcnJheShhKSxkLkMoImpkPDA+IikpCmVsc2UgdD1KLlFp
-KGEsZCkKaWYoYSE9PTAmJiEwKWZvcihzPTA7czx0Lmxlbmd0aDsrK3MpQy5ObS5ZKHQscyxiKQpyZXR1
-cm4gdH0sCkNIOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzPUguVk0oW10sYy5DKCJqZDwwPiIpKQpmb3Io
-dD1KLklUKGEpO3QuRigpOylDLk5tLmkocyxjLmEodC5nbCgpKSkKaWYoYilyZXR1cm4gcwpyZXR1cm4g
-Yy5DKCJ6TTwwPiIpLmEoSi5FcChzKSl9LApBRjpmdW5jdGlvbihhLGIpe3JldHVybiBiLkMoInpNPDA+
-IikuYShKLnVuKFAuQ0goYSwhMSxiKSkpfSwKSE06ZnVuY3Rpb24oYSxiLGMpe3ZhciB0CmlmKEFycmF5
-LmlzQXJyYXkoYSkpe3UudC5hKGEpCnQ9YS5sZW5ndGgKYz1QLmpCKGIsYyx0KQpyZXR1cm4gSC5lVChi
-PjB8fGM8dD9DLk5tLkQ2KGEsYixjKTphKX1pZih1LmJtLmIoYSkpcmV0dXJuIEguZncoYSxiLFAuakIo
-YixjLGEubGVuZ3RoKSkKcmV0dXJuIFAuYncoYSxiLGMpfSwKT286ZnVuY3Rpb24oYSl7cmV0dXJuIEgu
-THcoYSl9LApidzpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHEscD1udWxsCmlmKGI8MCl0aHJvdyBI
-LmIoUC5URShiLDAsSi5IKGEpLHAscCkpCnQ9Yz09bnVsbAppZighdCYmYzxiKXRocm93IEguYihQLlRF
-KGMsYixKLkgoYSkscCxwKSkKcz1KLklUKGEpCmZvcihyPTA7cjxiOysrcilpZighcy5GKCkpdGhyb3cg
-SC5iKFAuVEUoYiwwLHIscCxwKSkKcT1bXQppZih0KWZvcig7cy5GKCk7KXEucHVzaChzLmdsKCkpCmVs
-c2UgZm9yKHI9YjtyPGM7KytyKXtpZighcy5GKCkpdGhyb3cgSC5iKFAuVEUoYyxiLHIscCxwKSkKcS5w
-dXNoKHMuZ2woKSl9cmV0dXJuIEguZVQocSl9LApudTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IEguVlIo
-YSxILnY0KGEsITEsITAsITEsITEsITEpKX0sCnZnOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1KLklUKGIp
-CmlmKCF0LkYoKSlyZXR1cm4gYQppZihjLmxlbmd0aD09PTApe2RvIGErPUguZCh0LmdsKCkpCndoaWxl
-KHQuRigpKX1lbHNle2ErPUguZCh0LmdsKCkpCmZvcig7dC5GKCk7KWE9YStjK0guZCh0LmdsKCkpfXJl
-dHVybiBhfSwKbHI6ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJuIG5ldyBQLm1wKGEsYixjLGQpfSwKdW86
-ZnVuY3Rpb24oKXt2YXIgdD1ILk0wKCkKaWYodCE9bnVsbClyZXR1cm4gUC5oSyh0KQp0aHJvdyBILmIo
-UC5MNCgiJ1VyaS5iYXNlJyBpcyBub3Qgc3VwcG9ydGVkIikpfSwKZVA6ZnVuY3Rpb24oYSxiLGMsZCl7
-dmFyIHQscyxyLHEscCxvLG49IjAxMjM0NTY3ODlBQkNERUYiCmlmKGM9PT1DLnhNKXt0PSQuejQoKS5i
-CmlmKHR5cGVvZiBiIT0ic3RyaW5nIilILnZoKEguSShiKSkKdD10LnRlc3QoYil9ZWxzZSB0PSExCmlm
-KHQpcmV0dXJuIGIKSC5MaChjKS5DKCJVay5TIikuYShiKQpzPWMuZ1pFKCkuV0ooYikKZm9yKHQ9cy5s
-ZW5ndGgscj0wLHE9IiI7cjx0Oysrcil7cD1zW3JdCmlmKHA8MTI4KXtvPXA+Pj40CmlmKG8+PTgpcmV0
-dXJuIEguayhhLG8pCm89KGFbb10mMTw8KHAmMTUpKSE9PTB9ZWxzZSBvPSExCmlmKG8pcSs9SC5Mdyhw
-KQplbHNlIHE9ZCYmcD09PTMyP3ErIisiOnErIiUiK25bcD4+PjQmMTVdK25bcCYxNV19cmV0dXJuIHEu
-Y2hhckNvZGVBdCgwKT09MD9xOnF9LApaYjpmdW5jdGlvbigpe3ZhciB0LHMKaWYoSC5vVCgkLnA2KCkp
-KXJldHVybiBILnRzKG5ldyBFcnJvcigpKQp0cnl7dGhyb3cgSC5iKCIiKX1jYXRjaChzKXtILlJ1KHMp
-CnQ9SC50cyhzKQpyZXR1cm4gdH19LApHcTpmdW5jdGlvbihhKXt2YXIgdD1NYXRoLmFicyhhKSxzPWE8
-MD8iLSI6IiIKaWYodD49MTAwMClyZXR1cm4iIithCmlmKHQ+PTEwMClyZXR1cm4gcysiMCIrdAppZih0
-Pj0xMClyZXR1cm4gcysiMDAiK3QKcmV0dXJuIHMrIjAwMCIrdH0sClZ4OmZ1bmN0aW9uKGEpe2lmKGE+
-PTEwMClyZXR1cm4iIithCmlmKGE+PTEwKXJldHVybiIwIithCnJldHVybiIwMCIrYX0sCmgwOmZ1bmN0
-aW9uKGEpe2lmKGE+PTEwKXJldHVybiIiK2EKcmV0dXJuIjAiK2F9LApoOmZ1bmN0aW9uKGEpe2lmKHR5
-cGVvZiBhPT0ibnVtYmVyInx8SC5yUShhKXx8bnVsbD09YSlyZXR1cm4gSi5BYyhhKQppZih0eXBlb2Yg
-YT09InN0cmluZyIpcmV0dXJuIEpTT04uc3RyaW5naWZ5KGEpCnJldHVybiBQLm9zKGEpfSwKaFY6ZnVu
-Y3Rpb24oYSl7cmV0dXJuIG5ldyBQLkM2KGEpfSwKeFk6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLkFU
-KCExLG51bGwsbnVsbCxhKX0sCkwzOmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gbmV3IFAuQVQoITAsYSxi
-LGMpfSwKRWU6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLkFUKCExLG51bGwsYSwiTXVzdCBub3QgYmUg
-bnVsbCIpfSwKVUk6ZnVuY3Rpb24oYSxiLGMpe2lmKGE9PW51bGwpdGhyb3cgSC5iKFAuRWUoYikpCnJl
-dHVybiBhfSwKTzc6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gbmV3IFAuYkoobnVsbCxudWxsLCEwLGEsYiwi
-VmFsdWUgbm90IGluIHJhbmdlIil9LApURTpmdW5jdGlvbihhLGIsYyxkLGUpe3JldHVybiBuZXcgUC5i
-SihiLGMsITAsYSxkLCJJbnZhbGlkIHZhbHVlIil9LAp3QTpmdW5jdGlvbihhLGIsYyxkKXtpZihhPGJ8
-fGE+Yyl0aHJvdyBILmIoUC5URShhLGIsYyxkLG51bGwpKQpyZXR1cm4gYX0sCmpCOmZ1bmN0aW9uKGEs
-YixjKXtpZigwPmF8fGE+Yyl0aHJvdyBILmIoUC5URShhLDAsYywic3RhcnQiLG51bGwpKQppZihiIT1u
-dWxsKXtpZihhPmJ8fGI+Yyl0aHJvdyBILmIoUC5URShiLGEsYywiZW5kIixudWxsKSkKcmV0dXJuIGJ9
-cmV0dXJuIGN9LAprMTpmdW5jdGlvbihhLGIpe2lmKHR5cGVvZiBhIT09Im51bWJlciIpcmV0dXJuIGEu
-SigpCmlmKGE8MCl0aHJvdyBILmIoUC5URShhLDAsbnVsbCxiLG51bGwpKQpyZXR1cm4gYX0sCnQ6ZnVu
-Y3Rpb24oYSxiLGMsZCxlKXt2YXIgdD1ILldZKGU9PW51bGw/Si5IKGIpOmUpCnJldHVybiBuZXcgUC5l
-WSh0LCEwLGEsYywiSW5kZXggb3V0IG9mIHJhbmdlIil9LApMNDpmdW5jdGlvbihhKXtyZXR1cm4gbmV3
-IFAudWIoYSl9LApuOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC5kcyhhKX0sClBWOmZ1bmN0aW9uKGEp
-e3JldHVybiBuZXcgUC5saihhKX0sCmE0OmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC5VVihhKX0sCnJy
-OmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gbmV3IFAuYUUoYSxiLGMpfSwKZEg6ZnVuY3Rpb24oYSxiLGMp
-e3ZhciB0LHM9SC5WTShbXSxjLkMoImpkPDA+IikpCkMuTm0uc0EocyxhKQpmb3IodD0wO3Q8YTsrK3Qp
-Qy5ObS5ZKHMsdCxiLiQxKHQpKQpyZXR1cm4gc30sCmhLOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHAs
-byxuLG0sbCxrLGosaSxoLGcsZixlPW51bGwsZD1hLmxlbmd0aAppZihkPj01KXt0PSgoSi5ReihhLDQp
-XjU4KSozfEMueEIuVyhhLDApXjEwMHxDLnhCLlcoYSwxKV45N3xDLnhCLlcoYSwyKV4xMTZ8Qy54Qi5X
-KGEsMyleOTcpPj4+MAppZih0PT09MClyZXR1cm4gUC5LRChkPGQ/Qy54Qi5OaihhLDAsZCk6YSw1LGUp
-LmdsUigpCmVsc2UgaWYodD09PTMyKXJldHVybiBQLktEKEMueEIuTmooYSw1LGQpLDAsZSkuZ2xSKCl9
-cz1uZXcgQXJyYXkoOCkKcy5maXhlZCRsZW5ndGg9QXJyYXkKcj1ILlZNKHMsdS50KQpDLk5tLlkociww
-LDApCkMuTm0uWShyLDEsLTEpCkMuTm0uWShyLDIsLTEpCkMuTm0uWShyLDcsLTEpCkMuTm0uWShyLDMs
-MCkKQy5ObS5ZKHIsNCwwKQpDLk5tLlkociw1LGQpCkMuTm0uWShyLDYsZCkKaWYoUC5VQihhLDAsZCww
-LHIpPj0xNClDLk5tLlkociw3LGQpCnE9clsxXQppZih0eXBlb2YgcSE9PSJudW1iZXIiKXJldHVybiBx
-LnRCKCkKaWYocT49MClpZihQLlVCKGEsMCxxLDIwLHIpPT09MjApcls3XT1xCnM9clsyXQppZih0eXBl
-b2YgcyE9PSJudW1iZXIiKXJldHVybiBzLmgoKQpwPXMrMQpvPXJbM10Kbj1yWzRdCm09cls1XQpsPXJb
-Nl0KaWYodHlwZW9mIGwhPT0ibnVtYmVyIilyZXR1cm4gbC5KKCkKaWYodHlwZW9mIG0hPT0ibnVtYmVy
-IilyZXR1cm4gSC5wWShtKQppZihsPG0pbT1sCmlmKHR5cGVvZiBuIT09Im51bWJlciIpcmV0dXJuIG4u
-SigpCmlmKG48cCluPW0KZWxzZSBpZihuPD1xKW49cSsxCmlmKHR5cGVvZiBvIT09Im51bWJlciIpcmV0
-dXJuIG8uSigpCmlmKG88cClvPW4Kcz1yWzddCmlmKHR5cGVvZiBzIT09Im51bWJlciIpcmV0dXJuIHMu
-SigpCms9czwwCmlmKGspaWYocD5xKzMpe2o9ZQprPSExfWVsc2V7cz1vPjAKaWYocyYmbysxPT09bil7
-aj1lCms9ITF9ZWxzZXtpZighKG08ZCYmbT09PW4rMiYmSi5xMChhLCIuLiIsbikpKWk9bT5uKzImJkou
-cTAoYSwiLy4uIixtLTMpCmVsc2UgaT0hMAppZihpKXtqPWUKaz0hMX1lbHNle2lmKHE9PT00KWlmKEou
-cTAoYSwiZmlsZSIsMCkpe2lmKHA8PTApe2lmKCFDLnhCLlFpKGEsIi8iLG4pKXtoPSJmaWxlOi8vLyIK
-dD0zfWVsc2V7aD0iZmlsZTovLyIKdD0yfWE9aCtDLnhCLk5qKGEsbixkKQpxLT0wCnM9dC0wCm0rPXMK
-bCs9cwpkPWEubGVuZ3RoCnA9NwpvPTcKbj03fWVsc2UgaWYobj09PW0pe2c9bSsxOysrbAphPUMueEIu
-aTcoYSxuLG0sIi8iKTsrK2QKbT1nfWo9ImZpbGUifWVsc2UgaWYoQy54Qi5RaShhLCJodHRwIiwwKSl7
-aWYocyYmbyszPT09biYmQy54Qi5RaShhLCI4MCIsbysxKSl7Zj1uLTMKbS09MwpsLT0zCmE9Qy54Qi5p
-NyhhLG8sbiwiIikKZC09MwpuPWZ9aj0iaHR0cCJ9ZWxzZSBqPWUKZWxzZSBpZihxPT09NSYmSi5xMChh
-LCJodHRwcyIsMCkpe2lmKHMmJm8rND09PW4mJkoucTAoYSwiNDQzIixvKzEpKXtmPW4tNAptLT00Cmwt
-PTQKYT1KLmRnKGEsbyxuLCIiKQpkLT0zCm49Zn1qPSJodHRwcyJ9ZWxzZSBqPWUKaz0hMH19fWVsc2Ug
-aj1lCmlmKGspe3M9YS5sZW5ndGgKaWYoZDxzKXthPUoubGQoYSwwLGQpCnEtPTAKcC09MApvLT0wCm4t
-PTAKbS09MApsLT0wfXJldHVybiBuZXcgUC5VZihhLHEscCxvLG4sbSxsLGopfXJldHVybiBQLmp2KGEs
-MCxkLHEscCxvLG4sbSxsLGopfSwKTXQ6ZnVuY3Rpb24oYSl7SC5jKGEpCnJldHVybiBQLmt1KGEsMCxh
-Lmxlbmd0aCxDLnhNLCExKX0sCldYOmZ1bmN0aW9uKGEpe3ZhciB0PXUuTgpyZXR1cm4gQy5ObS5OMChI
-LlZNKGEuc3BsaXQoIiYiKSx1LnMpLFAuRmwodCx0KSxuZXcgUC5uMShDLnhNKSx1LmYpfSwKSGg6ZnVu
-Y3Rpb24oYSxiLGMpe3ZhciB0LHMscixxLHAsbyxuLG09bnVsbCxsPSJJUHY0IGFkZHJlc3Mgc2hvdWxk
-IGNvbnRhaW4gZXhhY3RseSA0IHBhcnRzIixrPSJlYWNoIHBhcnQgbXVzdCBiZSBpbiB0aGUgcmFuZ2Ug
-MC4uMjU1IixqPW5ldyBQLmNTKGEpLGk9bmV3IFVpbnQ4QXJyYXkoNCkKZm9yKHQ9aS5sZW5ndGgscz1i
-LHI9cyxxPTA7czxjOysrcyl7cD1DLnhCLm0oYSxzKQppZihwIT09NDYpe2lmKChwXjQ4KT45KWouJDIo
-ImludmFsaWQgY2hhcmFjdGVyIixzKX1lbHNle2lmKHE9PT0zKWouJDIobCxzKQpvPVAuUUEoQy54Qi5O
-aihhLHIscyksbSxtKQppZih0eXBlb2YgbyE9PSJudW1iZXIiKXJldHVybiBvLm9zKCkKaWYobz4yNTUp
-ai4kMihrLHIpCm49cSsxCmlmKHE+PXQpcmV0dXJuIEguayhpLHEpCmlbcV09bwpyPXMrMQpxPW59fWlm
-KHEhPT0zKWouJDIobCxjKQpvPVAuUUEoQy54Qi5OaihhLHIsYyksbSxtKQppZih0eXBlb2YgbyE9PSJu
-dW1iZXIiKXJldHVybiBvLm9zKCkKaWYobz4yNTUpai4kMihrLHIpCmlmKHE+PXQpcmV0dXJuIEguayhp
-LHEpCmlbcV09bwpyZXR1cm4gaX0sCmVnOmZ1bmN0aW9uKGEsYixhMCl7dmFyIHQscyxyLHEscCxvLG4s
-bSxsLGssaixpLGgsZyxmLGUsZD1uZXcgUC5WQyhhKSxjPW5ldyBQLkpUKGQsYSkKaWYoYS5sZW5ndGg8
-MilkLiQxKCJhZGRyZXNzIGlzIHRvbyBzaG9ydCIpCnQ9SC5WTShbXSx1LnQpCmZvcihzPWIscj1zLHE9
-ITEscD0hMTtzPGEwOysrcyl7bz1DLnhCLm0oYSxzKQppZihvPT09NTgpe2lmKHM9PT1iKXsrK3MKaWYo
-Qy54Qi5tKGEscykhPT01OClkLiQyKCJpbnZhbGlkIHN0YXJ0IGNvbG9uLiIscykKcj1zfWlmKHM9PT1y
-KXtpZihxKWQuJDIoIm9ubHkgb25lIHdpbGRjYXJkIGA6OmAgaXMgYWxsb3dlZCIscykKQy5ObS5pKHQs
-LTEpCnE9ITB9ZWxzZSBDLk5tLmkodCxjLiQyKHIscykpCnI9cysxfWVsc2UgaWYobz09PTQ2KXA9ITB9
-aWYodC5sZW5ndGg9PT0wKWQuJDEoInRvbyBmZXcgcGFydHMiKQpuPXI9PT1hMAptPUMuTm0uZ3JaKHQp
-CmlmKG4mJm0hPT0tMSlkLiQyKCJleHBlY3RlZCBhIHBhcnQgYWZ0ZXIgbGFzdCBgOmAiLGEwKQppZigh
-bilpZighcClDLk5tLmkodCxjLiQyKHIsYTApKQplbHNle2w9UC5IaChhLHIsYTApCkMuTm0uaSh0LChs
-WzBdPDw4fGxbMV0pPj4+MCkKQy5ObS5pKHQsKGxbMl08PDh8bFszXSk+Pj4wKX1pZihxKXtpZih0Lmxl
-bmd0aD43KWQuJDEoImFuIGFkZHJlc3Mgd2l0aCBhIHdpbGRjYXJkIG11c3QgaGF2ZSBsZXNzIHRoYW4g
-NyBwYXJ0cyIpfWVsc2UgaWYodC5sZW5ndGghPT04KWQuJDEoImFuIGFkZHJlc3Mgd2l0aG91dCBhIHdp
-bGRjYXJkIG11c3QgY29udGFpbiBleGFjdGx5IDggcGFydHMiKQprPW5ldyBVaW50OEFycmF5KDE2KQpm
-b3IobT10Lmxlbmd0aCxqPWsubGVuZ3RoLGk9OS1tLHM9MCxoPTA7czxtOysrcyl7Zz10W3NdCmlmKGc9
-PT0tMSlmb3IoZj0wO2Y8aTsrK2Ype2lmKGg8MHx8aD49ailyZXR1cm4gSC5rKGssaCkKa1toXT0wCmU9
-aCsxCmlmKGU+PWopcmV0dXJuIEguayhrLGUpCmtbZV09MApoKz0yfWVsc2V7ZT1DLmpuLndHKGcsOCkK
-aWYoaDwwfHxoPj1qKXJldHVybiBILmsoayxoKQprW2hdPWUKZT1oKzEKaWYoZT49ailyZXR1cm4gSC5r
-KGssZSkKa1tlXT1nJjI1NQpoKz0yfX1yZXR1cm4ga30sCmp2OmZ1bmN0aW9uKGEsYixjLGQsZSxmLGcs
-aCxpLGope3ZhciB0LHMscixxLHAsbyxuLG09bnVsbAppZihqPT1udWxsKWlmKGQ+YilqPVAuUGkoYSxi
-LGQpCmVsc2V7aWYoZD09PWIpUC5SMyhhLGIsIkludmFsaWQgZW1wdHkgc2NoZW1lIikKaj0iIn1pZihl
-PmIpe3Q9ZCszCnM9dDxlP1AuelIoYSx0LGUtMSk6IiIKcj1QLk9lKGEsZSxmLCExKQppZih0eXBlb2Yg
-ZiE9PSJudW1iZXIiKXJldHVybiBmLmgoKQpxPWYrMQppZih0eXBlb2YgZyE9PSJudW1iZXIiKXJldHVy
-biBILnBZKGcpCnA9cTxnP1Aud0IoUC5RQShKLmxkKGEscSxnKSxuZXcgUC5lMShhLGYpLG0pLGopOm19
-ZWxzZXtwPW0Kcj1wCnM9IiJ9bz1QLmthKGEsZyxoLG0saixyIT1udWxsKQppZih0eXBlb2YgaCE9PSJu
-dW1iZXIiKXJldHVybiBoLkooKQpuPWg8aT9QLmxlKGEsaCsxLGksbSk6bQpyZXR1cm4gbmV3IFAuRG4o
-aixzLHIscCxvLG4saTxjP1AudEcoYSxpKzEsYyk6bSl9LApLTDpmdW5jdGlvbihhLGIsYyxkLGUsZixn
-KXt2YXIgdCxzLHIscSxwLG8KZj1QLlBpKGYsMCxmPT1udWxsPzA6Zi5sZW5ndGgpCmc9UC56UihnLDAs
-Zz09bnVsbD8wOmcubGVuZ3RoKQphPVAuT2UoYSwwLGE9PW51bGw/MDphLmxlbmd0aCwhMSkKdD1QLmxl
-KG51bGwsMCwwLGUpCnM9UC50RyhudWxsLDAsMCkKZD1QLndCKGQsZikKcj1mPT09ImZpbGUiCmlmKGE9
-PW51bGwpcT1nLmxlbmd0aCE9PTB8fGQhPW51bGx8fHIKZWxzZSBxPSExCmlmKHEpYT0iIgpxPWE9PW51
-bGwKcD0hcQpiPVAua2EoYiwwLGI9PW51bGw/MDpiLmxlbmd0aCxjLGYscCkKbz1mLmxlbmd0aD09PTAK
-aWYobyYmcSYmIUMueEIubihiLCIvIikpYj1QLndGKGIsIW98fHApCmVsc2UgYj1QLnhlKGIpCnJldHVy
-biBuZXcgUC5EbihmLGcscSYmQy54Qi5uKGIsIi8vIik/IiI6YSxkLGIsdCxzKX0sCndLOmZ1bmN0aW9u
-KGEpe2lmKGE9PT0iaHR0cCIpcmV0dXJuIDgwCmlmKGE9PT0iaHR0cHMiKXJldHVybiA0NDMKcmV0dXJu
-IDB9LApSMzpmdW5jdGlvbihhLGIsYyl7dGhyb3cgSC5iKFAucnIoYyxhLGIpKX0sClhkOmZ1bmN0aW9u
-KGEsYixjLGQpe3ZhciB0LHMscixxLHAsbyxuLG0sbCxrLGosaT1udWxsLGg9Yi5sZW5ndGgKaWYoaCE9
-PTApe3I9MAp3aGlsZSghMCl7aWYoIShyPGgpKXt0PSIiCnM9MApicmVha31pZihDLnhCLlcoYixyKT09
-PTY0KXt0PUMueEIuTmooYiwwLHIpCnM9cisxCmJyZWFrfSsrcn1pZihzPGgmJkMueEIuVyhiLHMpPT09
-OTEpe2ZvcihxPXMscD0tMTtxPGg7KytxKXtvPUMueEIuVyhiLHEpCmlmKG89PT0zNyYmcDwwKXtuPUMu
-eEIuUWkoYiwiMjUiLHErMSk/cSsyOnEKcD1xCnE9bn1lbHNlIGlmKG89PT05MylicmVha31pZihxPT09
-aCl0aHJvdyBILmIoUC5ycigiSW52YWxpZCBJUHY2IGhvc3QgZW50cnkuIixiLHMpKQptPXA8MD9xOnAK
-UC5lZyhiLHMrMSxtKTsrK3EKaWYocSE9PWgmJkMueEIuVyhiLHEpIT09NTgpdGhyb3cgSC5iKFAucnIo
-IkludmFsaWQgZW5kIG9mIGF1dGhvcml0eSIsYixxKSl9ZWxzZSBxPXMKd2hpbGUoITApe2lmKCEocTxo
-KSl7bD1pCmJyZWFrfWlmKEMueEIuVyhiLHEpPT09NTgpe2s9Qy54Qi5HKGIscSsxKQpsPWsubGVuZ3Ro
-IT09MD9QLlFBKGssaSxpKTppCmJyZWFrfSsrcX1qPUMueEIuTmooYixzLHEpfWVsc2V7bD1pCmo9bAp0
-PSIifXJldHVybiBQLktMKGosaSxILlZNKGMuc3BsaXQoIi8iKSx1LnMpLGwsZCxhLHQpfSwKa0U6ZnVu
-Y3Rpb24oYSxiKXtDLk5tLksoYSxuZXcgUC5OWSghMSkpfSwKSE46ZnVuY3Rpb24oYSxiLGMpe3ZhciB0
-LHMscgpmb3IodD1ILnFDKGEsYyxudWxsLEgudDYoYSkuYyksdD1uZXcgSC5hNyh0LHQuZ0EodCksdC4k
-dGkuQygiYTc8YUwuRT4iKSk7dC5GKCk7KXtzPXQuZApyPVAubnUoJ1siKi86PD4/XFxcXHxdJykKcy50
-b1N0cmluZwppZihILm0yKHMsciwwKSl7dD1QLkw0KCJJbGxlZ2FsIGNoYXJhY3RlciBpbiBwYXRoOiAi
-K3MpCnRocm93IEguYih0KX19fSwKcmc6ZnVuY3Rpb24oYSxiKXt2YXIgdAppZighKDY1PD1hJiZhPD05
-MCkpdD05Nzw9YSYmYTw9MTIyCmVsc2UgdD0hMAppZih0KXJldHVybgp0PVAuTDQoIklsbGVnYWwgZHJp
-dmUgbGV0dGVyICIrUC5PbyhhKSkKdGhyb3cgSC5iKHQpfSwKd0I6ZnVuY3Rpb24oYSxiKXtpZihhIT1u
-dWxsJiZhPT09UC53SyhiKSlyZXR1cm4gbnVsbApyZXR1cm4gYX0sCk9lOmZ1bmN0aW9uKGEsYixjLGQp
-e3ZhciB0LHMscixxLHAsbwppZihhPT1udWxsKXJldHVybiBudWxsCmlmKGI9PT1jKXJldHVybiIiCmlm
-KEMueEIubShhLGIpPT09OTEpe2lmKHR5cGVvZiBjIT09Im51bWJlciIpcmV0dXJuIGMuSE4oKQp0PWMt
-MQppZihDLnhCLm0oYSx0KSE9PTkzKVAuUjMoYSxiLCJNaXNzaW5nIGVuZCBgXWAgdG8gbWF0Y2ggYFtg
-IGluIGhvc3QiKQpzPWIrMQpyPVAudG8oYSxzLHQpCmlmKHR5cGVvZiByIT09Im51bWJlciIpcmV0dXJu
-IHIuSigpCmlmKHI8dCl7cT1yKzEKcD1QLk9BKGEsQy54Qi5RaShhLCIyNSIscSk/ciszOnEsdCwiJTI1
-Iil9ZWxzZSBwPSIiClAuZWcoYSxzLHIpCnJldHVybiBDLnhCLk5qKGEsYixyKS50b0xvd2VyQ2FzZSgp
-K3ArIl0ifWlmKHR5cGVvZiBjIT09Im51bWJlciIpcmV0dXJuIEgucFkoYykKbz1iCmZvcig7bzxjOysr
-bylpZihDLnhCLm0oYSxvKT09PTU4KXtyPUMueEIuWFUoYSwiJSIsYikKaWYoIShyPj1iJiZyPGMpKXI9
-YwppZihyPGMpe3E9cisxCnA9UC5PQShhLEMueEIuUWkoYSwiMjUiLHEpP3IrMzpxLGMsIiUyNSIpfWVs
-c2UgcD0iIgpQLmVnKGEsYixyKQpyZXR1cm4iWyIrQy54Qi5OaihhLGIscikrcCsiXSJ9cmV0dXJuIFAu
-T0woYSxiLGMpfSwKdG86ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHM9Qy54Qi5YVShhLCIlIixiKQppZihz
-Pj1iKXtpZih0eXBlb2YgYyE9PSJudW1iZXIiKXJldHVybiBILnBZKGMpCnQ9czxjfWVsc2UgdD0hMQpy
-ZXR1cm4gdD9zOmN9LApPQTpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsaz1k
-IT09IiI/bmV3IFAuUm4oZCk6bnVsbAppZih0eXBlb2YgYyE9PSJudW1iZXIiKXJldHVybiBILnBZKGMp
-CnQ9YgpzPXQKcj0hMApmb3IoO3Q8Yzspe3E9Qy54Qi5tKGEsdCkKaWYocT09PTM3KXtwPVAucnYoYSx0
-LCEwKQpvPXA9PW51bGwKaWYobyYmcil7dCs9Mwpjb250aW51ZX1pZihrPT1udWxsKWs9bmV3IFAuUm4o
-IiIpCm49ay5hKz1DLnhCLk5qKGEscyx0KQppZihvKXA9Qy54Qi5OaihhLHQsdCszKQplbHNlIGlmKHA9
-PT0iJSIpUC5SMyhhLHQsIlpvbmVJRCBzaG91bGQgbm90IGNvbnRhaW4gJSBhbnltb3JlIikKay5hPW4r
-cAp0Kz0zCnM9dApyPSEwfWVsc2V7aWYocTwxMjcpe289cT4+PjQKaWYobz49OClyZXR1cm4gSC5rKEMu
-RjMsbykKbz0oQy5GM1tvXSYxPDwocSYxNSkpIT09MH1lbHNlIG89ITEKaWYobyl7aWYociYmNjU8PXEm
-JjkwPj1xKXtpZihrPT1udWxsKWs9bmV3IFAuUm4oIiIpCmlmKHM8dCl7ay5hKz1DLnhCLk5qKGEscyx0
-KQpzPXR9cj0hMX0rK3R9ZWxzZXtpZigocSY2NDUxMik9PT01NTI5NiYmdCsxPGMpe209Qy54Qi5tKGEs
-dCsxKQppZigobSY2NDUxMik9PT01NjMyMCl7cT02NTUzNnwocSYxMDIzKTw8MTB8bSYxMDIzCmw9Mn1l
-bHNlIGw9MX1lbHNlIGw9MQppZihrPT1udWxsKWs9bmV3IFAuUm4oIiIpCmsuYSs9Qy54Qi5OaihhLHMs
-dCkKay5hKz1QLnpYKHEpCnQrPWwKcz10fX19aWYoaz09bnVsbClyZXR1cm4gQy54Qi5OaihhLGIsYykK
-aWYoczxjKWsuYSs9Qy54Qi5OaihhLHMsYykKbz1rLmEKcmV0dXJuIG8uY2hhckNvZGVBdCgwKT09MD9v
-Om99LApPTDpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHEscCxvLG4sbSxsLGssagppZih0eXBlb2Yg
-YyE9PSJudW1iZXIiKXJldHVybiBILnBZKGMpCnQ9YgpzPXQKcj1udWxsCnE9ITAKZm9yKDt0PGM7KXtw
-PUMueEIubShhLHQpCmlmKHA9PT0zNyl7bz1QLnJ2KGEsdCwhMCkKbj1vPT1udWxsCmlmKG4mJnEpe3Qr
-PTMKY29udGludWV9aWYocj09bnVsbClyPW5ldyBQLlJuKCIiKQptPUMueEIuTmooYSxzLHQpCmw9ci5h
-Kz0hcT9tLnRvTG93ZXJDYXNlKCk6bQppZihuKXtvPUMueEIuTmooYSx0LHQrMykKaz0zfWVsc2UgaWYo
-bz09PSIlIil7bz0iJTI1IgprPTF9ZWxzZSBrPTMKci5hPWwrbwp0Kz1rCnM9dApxPSEwfWVsc2V7aWYo
-cDwxMjcpe249cD4+PjQKaWYobj49OClyZXR1cm4gSC5rKEMuZWEsbikKbj0oQy5lYVtuXSYxPDwocCYx
-NSkpIT09MH1lbHNlIG49ITEKaWYobil7aWYocSYmNjU8PXAmJjkwPj1wKXtpZihyPT1udWxsKXI9bmV3
-IFAuUm4oIiIpCmlmKHM8dCl7ci5hKz1DLnhCLk5qKGEscyx0KQpzPXR9cT0hMX0rK3R9ZWxzZXtpZihw
-PD05Myl7bj1wPj4+NAppZihuPj04KXJldHVybiBILmsoQy5hayxuKQpuPShDLmFrW25dJjE8PChwJjE1
-KSkhPT0wfWVsc2Ugbj0hMQppZihuKVAuUjMoYSx0LCJJbnZhbGlkIGNoYXJhY3RlciIpCmVsc2V7aWYo
-KHAmNjQ1MTIpPT09NTUyOTYmJnQrMTxjKXtqPUMueEIubShhLHQrMSkKaWYoKGomNjQ1MTIpPT09NTYz
-MjApe3A9NjU1MzZ8KHAmMTAyMyk8PDEwfGomMTAyMwprPTJ9ZWxzZSBrPTF9ZWxzZSBrPTEKaWYocj09
-bnVsbClyPW5ldyBQLlJuKCIiKQptPUMueEIuTmooYSxzLHQpCnIuYSs9IXE/bS50b0xvd2VyQ2FzZSgp
-Om0Kci5hKz1QLnpYKHApCnQrPWsKcz10fX19fWlmKHI9PW51bGwpcmV0dXJuIEMueEIuTmooYSxiLGMp
-CmlmKHM8Yyl7bT1DLnhCLk5qKGEscyxjKQpyLmErPSFxP20udG9Mb3dlckNhc2UoKTptfW49ci5hCnJl
-dHVybiBuLmNoYXJDb2RlQXQoMCk9PTA/bjpufSwKUGk6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixx
-CmlmKGI9PT1jKXJldHVybiIiCmlmKCFQLkV0KEouclkoYSkuVyhhLGIpKSlQLlIzKGEsYiwiU2NoZW1l
-IG5vdCBzdGFydGluZyB3aXRoIGFscGhhYmV0aWMgY2hhcmFjdGVyIikKZm9yKHQ9YixzPSExO3Q8Yzsr
-K3Qpe3I9Qy54Qi5XKGEsdCkKaWYocjwxMjgpe3E9cj4+PjQKaWYocT49OClyZXR1cm4gSC5rKEMubUss
-cSkKcT0oQy5tS1txXSYxPDwociYxNSkpIT09MH1lbHNlIHE9ITEKaWYoIXEpUC5SMyhhLHQsIklsbGVn
-YWwgc2NoZW1lIGNoYXJhY3RlciIpCmlmKDY1PD1yJiZyPD05MClzPSEwfWE9Qy54Qi5OaihhLGIsYykK
-cmV0dXJuIFAuWWEocz9hLnRvTG93ZXJDYXNlKCk6YSl9LApZYTpmdW5jdGlvbihhKXtpZihhPT09Imh0
-dHAiKXJldHVybiJodHRwIgppZihhPT09ImZpbGUiKXJldHVybiJmaWxlIgppZihhPT09Imh0dHBzIily
-ZXR1cm4iaHR0cHMiCmlmKGE9PT0icGFja2FnZSIpcmV0dXJuInBhY2thZ2UiCnJldHVybiBhfSwKelI6
-ZnVuY3Rpb24oYSxiLGMpe2lmKGE9PW51bGwpcmV0dXJuIiIKcmV0dXJuIFAuUEkoYSxiLGMsQy50bywh
-MSl9LAprYTpmdW5jdGlvbihhLGIsYyxkLGUsZil7dmFyIHQscz1lPT09ImZpbGUiLHI9c3x8ZixxPWE9
-PW51bGwKaWYocSYmZD09bnVsbClyZXR1cm4gcz8iLyI6IiIKcT0hcQppZihxJiZkIT1udWxsKXRocm93
-IEguYihQLnhZKCJCb3RoIHBhdGggYW5kIHBhdGhTZWdtZW50cyBzcGVjaWZpZWQiKSkKaWYocSl0PVAu
-UEkoYSxiLGMsQy5XZCwhMCkKZWxzZXtkLnRvU3RyaW5nCnE9SC50NihkKQp0PW5ldyBILmxKKGQscS5D
-KCJxVSgxKSIpLmEobmV3IFAuUlooKSkscS5DKCJsSjwxLHFVPiIpKS5IKDAsIi8iKX1pZih0Lmxlbmd0
-aD09PTApe2lmKHMpcmV0dXJuIi8ifWVsc2UgaWYociYmIUMueEIubih0LCIvIikpdD0iLyIrdApyZXR1
-cm4gUC5Kcih0LGUsZil9LApKcjpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9Yi5sZW5ndGg9PT0wCmlmKHQm
-JiFjJiYhQy54Qi5uKGEsIi8iKSlyZXR1cm4gUC53RihhLCF0fHxjKQpyZXR1cm4gUC54ZShhKX0sCmxl
-OmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0LHM9e30KaWYoYSE9bnVsbCl7aWYoZCE9bnVsbCl0aHJvdyBI
-LmIoUC54WSgiQm90aCBxdWVyeSBhbmQgcXVlcnlQYXJhbWV0ZXJzIHNwZWNpZmllZCIpKQpyZXR1cm4g
-UC5QSShhLGIsYyxDLlZDLCEwKX1pZihkPT1udWxsKXJldHVybiBudWxsCnQ9bmV3IFAuUm4oIiIpCnMu
-YT0iIgpkLksoMCxuZXcgUC55NShuZXcgUC5NRShzLHQpKSkKcz10LmEKcmV0dXJuIHMuY2hhckNvZGVB
-dCgwKT09MD9zOnN9LAp0RzpmdW5jdGlvbihhLGIsYyl7aWYoYT09bnVsbClyZXR1cm4gbnVsbApyZXR1
-cm4gUC5QSShhLGIsYyxDLlZDLCEwKX0sCnJ2OmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscSxwLG89
-YisyCmlmKG8+PWEubGVuZ3RoKXJldHVybiIlIgp0PUMueEIubShhLGIrMSkKcz1DLnhCLm0oYSxvKQpy
-PUgub28odCkKcT1ILm9vKHMpCmlmKHI8MHx8cTwwKXJldHVybiIlIgpwPXIqMTYrcQppZihwPDEyNyl7
-bz1DLmpuLndHKHAsNCkKaWYobz49OClyZXR1cm4gSC5rKEMuRjMsbykKbz0oQy5GM1tvXSYxPDwocCYx
-NSkpIT09MH1lbHNlIG89ITEKaWYobylyZXR1cm4gSC5MdyhjJiY2NTw9cCYmOTA+PXA/KHB8MzIpPj4+
-MDpwKQppZih0Pj05N3x8cz49OTcpcmV0dXJuIEMueEIuTmooYSxiLGIrMykudG9VcHBlckNhc2UoKQpy
-ZXR1cm4gbnVsbH0sCnpYOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHAsbyxuPSIwMTIzNDU2Nzg5QUJD
-REVGIgppZihhPDEyOCl7dD1uZXcgQXJyYXkoMykKdC5maXhlZCRsZW5ndGg9QXJyYXkKcz1ILlZNKHQs
-dS50KQpDLk5tLlkocywwLDM3KQpDLk5tLlkocywxLEMueEIuVyhuLGE+Pj40KSkKQy5ObS5ZKHMsMixD
-LnhCLlcobixhJjE1KSl9ZWxzZXtpZihhPjIwNDcpaWYoYT42NTUzNSl7cj0yNDAKcT00fWVsc2V7cj0y
-MjQKcT0zfWVsc2V7cj0xOTIKcT0yfXQ9bmV3IEFycmF5KDMqcSkKdC5maXhlZCRsZW5ndGg9QXJyYXkK
-cz1ILlZNKHQsdS50KQpmb3IocD0wOy0tcSxxPj0wO3I9MTI4KXtvPUMuam4uYmYoYSw2KnEpJjYzfHIK
-Qy5ObS5ZKHMscCwzNykKQy5ObS5ZKHMscCsxLEMueEIuVyhuLG8+Pj40KSkKQy5ObS5ZKHMscCsyLEMu
-eEIuVyhuLG8mMTUpKQpwKz0zfX1yZXR1cm4gUC5ITShzLDAsbnVsbCl9LApQSTpmdW5jdGlvbihhLGIs
-YyxkLGUpe3ZhciB0PVAuVWwoYSxiLGMsZCxlKQpyZXR1cm4gdD09bnVsbD9DLnhCLk5qKGEsYixjKTp0
-fSwKVWw6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgdCxzLHIscSxwLG89bnVsbCxuPSFlLG09YixsPW0s
-az1vCndoaWxlKCEwKXtpZih0eXBlb2YgbSE9PSJudW1iZXIiKXJldHVybiBtLkooKQppZih0eXBlb2Yg
-YyE9PSJudW1iZXIiKXJldHVybiBILnBZKGMpCmlmKCEobTxjKSlicmVhawpjJDA6e3Q9Qy54Qi5tKGEs
-bSkKaWYodDwxMjcpe3M9dD4+PjQKaWYocz49OClyZXR1cm4gSC5rKGQscykKcz0oZFtzXSYxPDwodCYx
-NSkpIT09MH1lbHNlIHM9ITEKaWYocykrK20KZWxzZXtpZih0PT09Mzcpe3I9UC5ydihhLG0sITEpCmlm
-KHI9PW51bGwpe20rPTMKYnJlYWsgYyQwfWlmKCIlIj09PXIpe3I9IiUyNSIKcT0xfWVsc2UgcT0zfWVs
-c2V7aWYobilpZih0PD05Myl7cz10Pj4+NAppZihzPj04KXJldHVybiBILmsoQy5hayxzKQpzPShDLmFr
-W3NdJjE8PCh0JjE1KSkhPT0wfWVsc2Ugcz0hMQplbHNlIHM9ITEKaWYocyl7UC5SMyhhLG0sIkludmFs
-aWQgY2hhcmFjdGVyIikKcT1vCnI9cX1lbHNle2lmKCh0JjY0NTEyKT09PTU1Mjk2KXtzPW0rMQppZihz
-PGMpe3A9Qy54Qi5tKGEscykKaWYoKHAmNjQ1MTIpPT09NTYzMjApe3Q9NjU1MzZ8KHQmMTAyMyk8PDEw
-fHAmMTAyMwpxPTJ9ZWxzZSBxPTF9ZWxzZSBxPTF9ZWxzZSBxPTEKcj1QLnpYKHQpfX1pZihrPT1udWxs
-KWs9bmV3IFAuUm4oIiIpCmsuYSs9Qy54Qi5OaihhLGwsbSkKay5hKz1ILmQocikKaWYodHlwZW9mIHEh
-PT0ibnVtYmVyIilyZXR1cm4gSC5wWShxKQptKz1xCmw9bX19fWlmKGs9PW51bGwpcmV0dXJuIG8KaWYo
-dHlwZW9mIGwhPT0ibnVtYmVyIilyZXR1cm4gbC5KKCkKaWYobDxjKWsuYSs9Qy54Qi5OaihhLGwsYykK
-bj1rLmEKcmV0dXJuIG4uY2hhckNvZGVBdCgwKT09MD9uOm59LAp5QjpmdW5jdGlvbihhKXtpZihDLnhC
-Lm4oYSwiLiIpKXJldHVybiEwCnJldHVybiBDLnhCLk9ZKGEsIi8uIikhPT0tMX0sCnhlOmZ1bmN0aW9u
-KGEpe3ZhciB0LHMscixxLHAsbyxuCmlmKCFQLnlCKGEpKXJldHVybiBhCnQ9SC5WTShbXSx1LnMpCmZv
-cihzPWEuc3BsaXQoIi8iKSxyPXMubGVuZ3RoLHE9ITEscD0wO3A8cjsrK3Ape289c1twXQppZihKLlJN
-KG8sIi4uIikpe249dC5sZW5ndGgKaWYobiE9PTApe2lmKDA+PW4pcmV0dXJuIEguayh0LC0xKQp0LnBv
+aWYoMD49Yi5sZW5ndGgpcmV0dXJuIEguT0goYiwtMSkKbC09Yi5wb3AoKS5sZW5ndGgrMjstLWt9Qy5O
+bS5pKGIsIi4uLiIpCnJldHVybn19cj1ILkVqKHEpCnM9SC5FaihwKQpsKz1zLmxlbmd0aCtyLmxlbmd0
+aCs0fX1pZihrPmIubGVuZ3RoKzIpe2wrPTUKbj0iLi4uIn1lbHNlIG49bnVsbAp3aGlsZSghMCl7aWYo
+IShsPjgwJiZiLmxlbmd0aD4zKSlicmVhawppZigwPj1iLmxlbmd0aClyZXR1cm4gSC5PSChiLC0xKQps
+LT1iLnBvcCgpLmxlbmd0aCsyCmlmKG49PW51bGwpe2wrPTUKbj0iLi4uIn19aWYobiE9bnVsbClDLk5t
+LmkoYixuKQpDLk5tLmkoYixyKQpDLk5tLmkoYixzKX0sCnRNOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxy
+PVAuTHMoYikKZm9yKHQ9YS5sZW5ndGgscz0wO3M8YS5sZW5ndGg7YS5sZW5ndGg9PT10fHwoMCxILmxr
+KShhKSwrK3Mpci5pKDAsYi5hKGFbc10pKQpyZXR1cm4gcn0sCm5POmZ1bmN0aW9uKGEpe3ZhciB0LHM9
+e30KaWYoUC5oQihhKSlyZXR1cm4iey4uLn0iCnQ9bmV3IFAuUm4oIiIpCnRyeXtDLk5tLmkoJC54Zyxh
+KQp0LmErPSJ7IgpzLmE9ITAKYS5LKDAsbmV3IFAucmEocyx0KSkKdC5hKz0ifSJ9ZmluYWxseXtpZigw
+Pj0kLnhnLmxlbmd0aClyZXR1cm4gSC5PSCgkLnhnLC0xKQokLnhnLnBvcCgpfXM9dC5hCnJldHVybiBz
+LmNoYXJDb2RlQXQoMCk9PTA/czpzfSwKYjY6ZnVuY3Rpb24gYjYoYSl7dmFyIF89dGhpcwpfLmE9MApf
+LmY9Xy5lPV8uZD1fLmM9Xy5iPW51bGwKXy5yPTAKXy4kdGk9YX0sCmJuOmZ1bmN0aW9uIGJuKGEpe3Ro
+aXMuYT1hCnRoaXMuYz10aGlzLmI9bnVsbH0sCmxtOmZ1bmN0aW9uIGxtKGEsYixjKXt2YXIgXz10aGlz
+Cl8uYT1hCl8uYj1iCl8uZD1fLmM9bnVsbApfLiR0aT1jfSwKbVc6ZnVuY3Rpb24gbVcoKXt9LAp1eTpm
+dW5jdGlvbiB1eSgpe30sCmxEOmZ1bmN0aW9uIGxEKCl7fSwKaWw6ZnVuY3Rpb24gaWwoKXt9LApyYTpm
+dW5jdGlvbiByYShhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKWWs6ZnVuY3Rpb24gWWsoKXt9LAp5UTpm
+dW5jdGlvbiB5UShhKXt0aGlzLmE9YX0sCktQOmZ1bmN0aW9uIEtQKCl7fSwKUG46ZnVuY3Rpb24gUG4o
+KXt9LApHajpmdW5jdGlvbiBHaihhLGIpe3RoaXMuYT1hCnRoaXMuJHRpPWJ9LApNYTpmdW5jdGlvbiBN
+YSgpe30sClZqOmZ1bmN0aW9uIFZqKCl7fSwKWHY6ZnVuY3Rpb24gWHYoKXt9LApuWTpmdW5jdGlvbiBu
+WSgpe30sCldZOmZ1bmN0aW9uIFdZKCl7fSwKUlU6ZnVuY3Rpb24gUlUoKXt9LApCUzpmdW5jdGlvbihh
+LGIpe3ZhciB0LHMscixxCmlmKHR5cGVvZiBhIT0ic3RyaW5nIil0aHJvdyBILmIoSC50TChhKSkKdD1u
+dWxsCnRyeXt0PUpTT04ucGFyc2UoYSl9Y2F0Y2gocil7cz1ILlJ1KHIpCnE9UC5ycihTdHJpbmcocyks
+bnVsbCxudWxsKQp0aHJvdyBILmIocSl9cT1QLlFlKHQpCnJldHVybiBxfSwKUWU6ZnVuY3Rpb24oYSl7
+dmFyIHQKaWYoYT09bnVsbClyZXR1cm4gbnVsbAppZih0eXBlb2YgYSE9Im9iamVjdCIpcmV0dXJuIGEK
+aWYoT2JqZWN0LmdldFByb3RvdHlwZU9mKGEpIT09QXJyYXkucHJvdG90eXBlKXJldHVybiBuZXcgUC51
+dyhhLE9iamVjdC5jcmVhdGUobnVsbCkpCmZvcih0PTA7dDxhLmxlbmd0aDsrK3QpYVt0XT1QLlFlKGFb
+dF0pCnJldHVybiBhfSwKa3k6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscwppZihiIGluc3RhbmNlb2Yg
+VWludDhBcnJheSl7dD1iCmQ9dC5sZW5ndGgKaWYoZC1jPDE1KXJldHVybiBudWxsCnM9UC5DRyhhLHQs
+YyxkKQppZihzIT1udWxsJiZhKWlmKHMuaW5kZXhPZigiXHVmZmZkIik+PTApcmV0dXJuIG51bGwKcmV0
+dXJuIHN9cmV0dXJuIG51bGx9LApDRzpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdD1hPyQuSEcoKTokLnJm
+KCkKaWYodD09bnVsbClyZXR1cm4gbnVsbAppZigwPT09YyYmZD09PWIubGVuZ3RoKXJldHVybiBQLlJi
+KHQsYikKcmV0dXJuIFAuUmIodCxiLnN1YmFycmF5KGMsUC5qQihjLGQsYi5sZW5ndGgpKSl9LApSYjpm
+dW5jdGlvbihhLGIpe3ZhciB0LHMKdHJ5e3Q9YS5kZWNvZGUoYikKcmV0dXJuIHR9Y2F0Y2gocyl7SC5S
+dShzKX1yZXR1cm4gbnVsbH0sCnhNOmZ1bmN0aW9uKGEsYixjLGQsZSxmKXtpZihDLmpuLnpZKGYsNCkh
+PT0wKXRocm93IEguYihQLnJyKCJJbnZhbGlkIGJhc2U2NCBwYWRkaW5nLCBwYWRkZWQgbGVuZ3RoIG11
+c3QgYmUgbXVsdGlwbGUgb2YgZm91ciwgaXMgIitmLGEsYykpCmlmKGQrZSE9PWYpdGhyb3cgSC5iKFAu
+cnIoIkludmFsaWQgYmFzZTY0IHBhZGRpbmcsICc9JyBub3QgYXQgdGhlIGVuZCIsYSxiKSkKaWYoZT4y
+KXRocm93IEguYihQLnJyKCJJbnZhbGlkIGJhc2U2NCBwYWRkaW5nLCBtb3JlIHRoYW4gdHdvICc9JyBj
+aGFyYWN0ZXJzIixhLGIpKX0sCkd5OmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gbmV3IFAuVWQoYSxiKX0s
+Ck5DOmZ1bmN0aW9uKGEpe3JldHVybiBhLkx0KCl9LAp1WDpmdW5jdGlvbihhLGIsYyl7dmFyIHQscz1u
+ZXcgUC5SbigiIikscj1uZXcgUC50dShzLFtdLFAuQ3koKSkKci5pVShhKQp0PXMuYQpyZXR1cm4gdC5j
+aGFyQ29kZUF0KDApPT0wP3Q6dH0sCmo0OmZ1bmN0aW9uKGEpe3N3aXRjaChhKXtjYXNlIDY1OnJldHVy
+biJNaXNzaW5nIGV4dGVuc2lvbiBieXRlIgpjYXNlIDY3OnJldHVybiJVbmV4cGVjdGVkIGV4dGVuc2lv
+biBieXRlIgpjYXNlIDY5OnJldHVybiJJbnZhbGlkIFVURi04IGJ5dGUiCmNhc2UgNzE6cmV0dXJuIk92
+ZXJsb25nIGVuY29kaW5nIgpjYXNlIDczOnJldHVybiJPdXQgb2YgdW5pY29kZSByYW5nZSIKY2FzZSA3
+NTpyZXR1cm4iRW5jb2RlZCBzdXJyb2dhdGUiCmNhc2UgNzc6cmV0dXJuIlVuZmluaXNoZWQgVVRGLTgg
+b2N0ZXQgc2VxdWVuY2UiCmRlZmF1bHQ6cmV0dXJuIiJ9fSwKank6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0
+LHMscixxLHA9Yy1iLG89bmV3IFVpbnQ4QXJyYXkocCkKZm9yKHQ9by5sZW5ndGgscz1KLlU2KGEpLHI9
+MDtyPHA7KytyKXtxPXMucShhLGIrcikKaWYodHlwZW9mIHEhPT0ibnVtYmVyIilyZXR1cm4gcS56TSgp
+CmlmKChxJjQyOTQ5NjcwNDApPj4+MCE9PTApcT0yNTUKaWYocj49dClyZXR1cm4gSC5PSChvLHIpCm9b
+cl09cX1yZXR1cm4gb30sCnV3OmZ1bmN0aW9uIHV3KGEsYil7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5j
+PW51bGx9LAppODpmdW5jdGlvbiBpOChhKXt0aGlzLmE9YX0sCnBnOmZ1bmN0aW9uIHBnKCl7fSwKYzI6
+ZnVuY3Rpb24gYzIoKXt9LApDVjpmdW5jdGlvbiBDVigpe30sClU4OmZ1bmN0aW9uIFU4KCl7fSwKVWs6
+ZnVuY3Rpb24gVWsoKXt9LAp3STpmdW5jdGlvbiB3SSgpe30sClppOmZ1bmN0aW9uIFppKCl7fSwKVWQ6
+ZnVuY3Rpb24gVWQoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCks4OmZ1bmN0aW9uIEs4KGEsYil7dGhp
+cy5hPWEKdGhpcy5iPWJ9LApieTpmdW5jdGlvbiBieSgpe30sCm9qOmZ1bmN0aW9uIG9qKGEpe3RoaXMu
+Yj1hfSwKTXg6ZnVuY3Rpb24gTXgoYSl7dGhpcy5hPWF9LApTaDpmdW5jdGlvbiBTaCgpe30sCnRpOmZ1
+bmN0aW9uIHRpKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LAp0dTpmdW5jdGlvbiB0dShhLGIsYyl7dGhp
+cy5jPWEKdGhpcy5hPWIKdGhpcy5iPWN9LAp1NTpmdW5jdGlvbiB1NSgpe30sCkUzOmZ1bmN0aW9uIEUz
+KCl7fSwKUnc6ZnVuY3Rpb24gUncoYSl7dGhpcy5iPTAKdGhpcy5jPWF9LApHWTpmdW5jdGlvbiBHWShh
+KXt0aGlzLmE9YX0sCmJ6OmZ1bmN0aW9uIGJ6KGEpe3RoaXMuYT1hCnRoaXMuYj0xNgp0aGlzLmM9MH0s
+ClFBOmZ1bmN0aW9uKGEsYil7dmFyIHQ9SC5IcChhLGIpCmlmKHQhPW51bGwpcmV0dXJuIHQKdGhyb3cg
+SC5iKFAucnIoYSxudWxsLG51bGwpKX0sCkY6ZnVuY3Rpb24oYSl7aWYoYSBpbnN0YW5jZW9mIEgudily
+ZXR1cm4gYS53KDApCnJldHVybiJJbnN0YW5jZSBvZiAnIitILkVqKEguTShhKSkrIicifSwKTzg6ZnVu
+Y3Rpb24oYSxiLGMsZCl7dmFyIHQscz1jP0ouS2goYSxkKTpKLlFpKGEsZCkKaWYoYSE9PTAmJmIhPW51
+bGwpZm9yKHQ9MDt0PHMubGVuZ3RoOysrdClzW3RdPWIKcmV0dXJuIHN9LApDSDpmdW5jdGlvbihhLGIs
+Yyl7dmFyIHQscz1ILlZNKFtdLGMuQygiamQ8MD4iKSkKZm9yKHQ9Si5JVChhKTt0LkYoKTspQy5ObS5p
+KHMsYy5hKHQuZ2woKSkpCmlmKGIpcmV0dXJuIHMKcmV0dXJuIEouRXAocyxjKX0sCmRIOmZ1bmN0aW9u
+KGEsYixjKXt2YXIgdCxzPUouS2goYSxjKQpmb3IodD0wO3Q8YTsrK3QpQy5ObS5ZKHMsdCxiLiQxKHQp
+KQpyZXR1cm4gc30sCkFGOmZ1bmN0aW9uKGEsYil7cmV0dXJuIEouekMoUC5DSChhLCExLGIpKX0sCkhN
+OmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzCmlmKEFycmF5LmlzQXJyYXkoYSkpe3Q9YQpzPXQubGVuZ3Ro
+CmM9UC5qQihiLGMscykKcmV0dXJuIEguZVQoYj4wfHxjPHM/dC5zbGljZShiLGMpOnQpfWlmKHUuYm0u
+YihhKSlyZXR1cm4gSC5mdyhhLGIsUC5qQihiLGMsYS5sZW5ndGgpKQpyZXR1cm4gUC5idyhhLGIsYyl9
+LApPbzpmdW5jdGlvbihhKXtyZXR1cm4gSC5MdyhhKX0sCmJ3OmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxz
+LHIscSxwLG89bnVsbAppZihiPDApdGhyb3cgSC5iKFAuVEUoYiwwLGEubGVuZ3RoLG8sbykpCnQ9Yz09
+bnVsbAppZighdCYmYzxiKXRocm93IEguYihQLlRFKGMsYixhLmxlbmd0aCxvLG8pKQpzPW5ldyBILmE3
+KGEsYS5sZW5ndGgsSC56KGEpLkMoImE3PGxELkU+IikpCmZvcihyPTA7cjxiOysrcilpZighcy5GKCkp
+dGhyb3cgSC5iKFAuVEUoYiwwLHIsbyxvKSkKcT1bXQppZih0KWZvcig7cy5GKCk7KXtwPXMuZApxLnB1
+c2gocCl9ZWxzZSBmb3Iocj1iO3I8YzsrK3Ipe2lmKCFzLkYoKSl0aHJvdyBILmIoUC5URShjLGIscixv
+LG8pKQpwPXMuZApxLnB1c2gocCl9cmV0dXJuIEguZVQocSl9LApudTpmdW5jdGlvbihhKXtyZXR1cm4g
+bmV3IEguVlIoYSxILnY0KGEsITEsITAsITEsITEsITEpKX0sCnZnOmZ1bmN0aW9uKGEsYixjKXt2YXIg
+dD1KLklUKGIpCmlmKCF0LkYoKSlyZXR1cm4gYQppZihjLmxlbmd0aD09PTApe2RvIGErPUguRWoodC5n
+bCgpKQp3aGlsZSh0LkYoKSl9ZWxzZXthKz1ILkVqKHQuZ2woKSkKZm9yKDt0LkYoKTspYT1hK2MrSC5F
+aih0LmdsKCkpfXJldHVybiBhfSwKbHI6ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJuIG5ldyBQLm1wKGEs
+YixjLGQpfSwKdW86ZnVuY3Rpb24oKXt2YXIgdD1ILk0wKCkKaWYodCE9bnVsbClyZXR1cm4gUC5oSyh0
+KQp0aHJvdyBILmIoUC5MNCgiJ1VyaS5iYXNlJyBpcyBub3Qgc3VwcG9ydGVkIikpfSwKZVA6ZnVuY3Rp
+b24oYSxiLGMsZCl7dmFyIHQscyxyLHEscCxvLG49IjAxMjM0NTY3ODlBQkNERUYiCmlmKGM9PT1DLnhN
+KXt0PSQuejQoKS5iCmlmKHR5cGVvZiBiIT0ic3RyaW5nIilILnZoKEgudEwoYikpCnQ9dC50ZXN0KGIp
+fWVsc2UgdD0hMQppZih0KXJldHVybiBiCkguTGgoYykuQygiVWsuUyIpLmEoYikKcz1jLmdaRSgpLldK
+KGIpCmZvcih0PXMubGVuZ3RoLHI9MCxxPSIiO3I8dDsrK3Ipe3A9c1tyXQppZihwPDEyOCl7bz1wPj4+
+NAppZihvPj04KXJldHVybiBILk9IKGEsbykKbz0oYVtvXSYxPDwocCYxNSkpIT09MH1lbHNlIG89ITEK
+aWYobylxKz1ILkx3KHApCmVsc2UgcT1kJiZwPT09MzI/cSsiKyI6cSsiJSIrbltwPj4+NCYxNV0rbltw
+JjE1XX1yZXR1cm4gcS5jaGFyQ29kZUF0KDApPT0wP3E6cX0sCkdxOmZ1bmN0aW9uKGEpe3ZhciB0PU1h
+dGguYWJzKGEpLHM9YTwwPyItIjoiIgppZih0Pj0xMDAwKXJldHVybiIiK2EKaWYodD49MTAwKXJldHVy
+biBzKyIwIit0CmlmKHQ+PTEwKXJldHVybiBzKyIwMCIrdApyZXR1cm4gcysiMDAwIit0fSwKVng6ZnVu
+Y3Rpb24oYSl7aWYoYT49MTAwKXJldHVybiIiK2EKaWYoYT49MTApcmV0dXJuIjAiK2EKcmV0dXJuIjAw
+IithfSwKaDA6ZnVuY3Rpb24oYSl7aWYoYT49MTApcmV0dXJuIiIrYQpyZXR1cm4iMCIrYX0sCnA6ZnVu
+Y3Rpb24oYSl7aWYodHlwZW9mIGE9PSJudW1iZXIifHxILmwoYSl8fG51bGw9PWEpcmV0dXJuIEouaihh
+KQppZih0eXBlb2YgYT09InN0cmluZyIpcmV0dXJuIEpTT04uc3RyaW5naWZ5KGEpCnJldHVybiBQLkYo
+YSl9LApoVjpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAuQzYoYSl9LAp4WTpmdW5jdGlvbihhKXtyZXR1
+cm4gbmV3IFAudSghMSxudWxsLG51bGwsYSl9LApMMzpmdW5jdGlvbihhLGIsYyl7cmV0dXJuIG5ldyBQ
+LnUoITAsYSxiLGMpfSwKVUk6ZnVuY3Rpb24oYSxiLGMpe2lmKGE9PW51bGwpdGhyb3cgSC5iKG5ldyBQ
+LnUoITEsbnVsbCxiLCJNdXN0IG5vdCBiZSBudWxsIikpCnJldHVybiBhfSwKTzc6ZnVuY3Rpb24oYSxi
+KXtyZXR1cm4gbmV3IFAuYkoobnVsbCxudWxsLCEwLGEsYiwiVmFsdWUgbm90IGluIHJhbmdlIil9LApU
+RTpmdW5jdGlvbihhLGIsYyxkLGUpe3JldHVybiBuZXcgUC5iSihiLGMsITAsYSxkLCJJbnZhbGlkIHZh
+bHVlIil9LAp3QTpmdW5jdGlvbihhLGIsYyxkKXtpZihhPGJ8fGE+Yyl0aHJvdyBILmIoUC5URShhLGIs
+YyxkLG51bGwpKQpyZXR1cm4gYX0sCmpCOmZ1bmN0aW9uKGEsYixjKXtpZigwPmF8fGE+Yyl0aHJvdyBI
+LmIoUC5URShhLDAsYywic3RhcnQiLG51bGwpKQppZihiIT1udWxsKXtpZihhPmJ8fGI+Yyl0aHJvdyBI
+LmIoUC5URShiLGEsYywiZW5kIixudWxsKSkKcmV0dXJuIGJ9cmV0dXJuIGN9LAprMTpmdW5jdGlvbihh
+LGIpe2lmKGE8MCl0aHJvdyBILmIoUC5URShhLDAsbnVsbCxiLG51bGwpKQpyZXR1cm4gYX0sCkNmOmZ1
+bmN0aW9uKGEsYixjLGQsZSl7dmFyIHQ9SC51UChlPT1udWxsP0ouSG0oYik6ZSkKcmV0dXJuIG5ldyBQ
+LmVZKHQsITAsYSxjLCJJbmRleCBvdXQgb2YgcmFuZ2UiKX0sCkw0OmZ1bmN0aW9uKGEpe3JldHVybiBu
+ZXcgUC51YihhKX0sClNZOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC5kcyhhKX0sClBWOmZ1bmN0aW9u
+KGEpe3JldHVybiBuZXcgUC5saihhKX0sCmE0OmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC5VVihhKX0s
+CnJyOmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gbmV3IFAuYUUoYSxiLGMpfSwKaEs6ZnVuY3Rpb24oYTQp
+e3ZhciB0LHMscixxLHAsbyxuLG0sbCxrLGosaSxoLGcsZixlLGQsYyxiLGEsYTAsYTEsYTI9bnVsbCxh
+Mz1hNC5sZW5ndGgKaWYoYTM+PTUpe3Q9KChKLlF6KGE0LDQpXjU4KSozfEMueEIuVyhhNCwwKV4xMDB8
+Qy54Qi5XKGE0LDEpXjk3fEMueEIuVyhhNCwyKV4xMTZ8Qy54Qi5XKGE0LDMpXjk3KT4+PjAKaWYodD09
+PTApcmV0dXJuIFAuS0QoYTM8YTM/Qy54Qi5OaihhNCwwLGEzKTphNCw1LGEyKS5nbFIoKQplbHNlIGlm
+KHQ9PT0zMilyZXR1cm4gUC5LRChDLnhCLk5qKGE0LDUsYTMpLDAsYTIpLmdsUigpfXM9UC5POCg4LDAs
+ITEsdS5TKQpDLk5tLlkocywwLDApCkMuTm0uWShzLDEsLTEpCkMuTm0uWShzLDIsLTEpCkMuTm0uWShz
+LDcsLTEpCkMuTm0uWShzLDMsMCkKQy5ObS5ZKHMsNCwwKQpDLk5tLlkocyw1LGEzKQpDLk5tLlkocyw2
+LGEzKQppZihQLlVCKGE0LDAsYTMsMCxzKT49MTQpQy5ObS5ZKHMsNyxhMykKaWYoMT49cy5sZW5ndGgp
+cmV0dXJuIEguT0gocywxKQpyPXNbMV0KaWYocj49MClpZihQLlVCKGE0LDAsciwyMCxzKT09PTIwKXtp
+Zig3Pj1zLmxlbmd0aClyZXR1cm4gSC5PSChzLDcpCnNbN109cn1xPXMubGVuZ3RoCmlmKDI+PXEpcmV0
+dXJuIEguT0gocywyKQpwPXNbMl0rMQppZigzPj1xKXJldHVybiBILk9IKHMsMykKbz1zWzNdCmlmKDQ+
+PXEpcmV0dXJuIEguT0gocyw0KQpuPXNbNF0KaWYoNT49cSlyZXR1cm4gSC5PSChzLDUpCm09c1s1XQpp
+Zig2Pj1xKXJldHVybiBILk9IKHMsNikKbD1zWzZdCmlmKGw8bSltPWwKaWYobjxwKW49bQplbHNlIGlm
+KG48PXIpbj1yKzEKaWYobzxwKW89bgppZig3Pj1xKXJldHVybiBILk9IKHMsNykKaz1zWzddPDAKaWYo
+aylpZihwPnIrMyl7aj1hMgprPSExfWVsc2V7cT1vPjAKaWYocSYmbysxPT09bil7aj1hMgprPSExfWVs
+c2V7aWYoIShtPGEzJiZtPT09bisyJiZKLnEwKGE0LCIuLiIsbikpKWk9bT5uKzImJkoucTAoYTQsIi8u
+LiIsbS0zKQplbHNlIGk9ITAKaWYoaSl7aj1hMgprPSExfWVsc2V7aWYocj09PTQpaWYoSi5xMChhNCwi
+ZmlsZSIsMCkpe2lmKHA8PTApe2lmKCFDLnhCLlFpKGE0LCIvIixuKSl7aD0iZmlsZTovLy8iCnQ9M31l
+bHNle2g9ImZpbGU6Ly8iCnQ9Mn1hND1oK0MueEIuTmooYTQsbixhMykKci09MApxPXQtMAptKz1xCmwr
+PXEKYTM9YTQubGVuZ3RoCnA9NwpvPTcKbj03fWVsc2UgaWYobj09PW0peysrbApnPW0rMQphND1DLnhC
+Lmk3KGE0LG4sbSwiLyIpOysrYTMKbT1nfWo9ImZpbGUifWVsc2UgaWYoQy54Qi5RaShhNCwiaHR0cCIs
+MCkpe2lmKHEmJm8rMz09PW4mJkMueEIuUWkoYTQsIjgwIixvKzEpKXtsLT0zCmY9bi0zCm0tPTMKYTQ9
+Qy54Qi5pNyhhNCxvLG4sIiIpCmEzLT0zCm49Zn1qPSJodHRwIn1lbHNlIGo9YTIKZWxzZSBpZihyPT09
+NSYmSi5xMChhNCwiaHR0cHMiLDApKXtpZihxJiZvKzQ9PT1uJiZKLnEwKGE0LCI0NDMiLG8rMSkpe2wt
+PTQKZj1uLTQKbS09NAphND1KLmRnKGE0LG8sbiwiIikKYTMtPTMKbj1mfWo9Imh0dHBzIn1lbHNlIGo9
+YTIKaz0hMH19fWVsc2Ugaj1hMgppZihrKXtxPWE0Lmxlbmd0aAppZihhMzxxKXthND1KLmxkKGE0LDAs
+YTMpCnItPTAKcC09MApvLT0wCm4tPTAKbS09MApsLT0wfXJldHVybiBuZXcgUC5VZihhNCxyLHAsbyxu
+LG0sbCxqKX1pZihqPT1udWxsKWlmKHI+MClqPVAuUGkoYTQsMCxyKQplbHNle2lmKHI9PT0wKVAuUjMo
+YTQsMCwiSW52YWxpZCBlbXB0eSBzY2hlbWUiKQpqPSIifWlmKHA+MCl7ZT1yKzMKZD1lPHA/UC56Uihh
+NCxlLHAtMSk6IiIKYz1QLk9lKGE0LHAsbywhMSkKcT1vKzEKaWYocTxuKXtiPUguSHAoSi5sZChhNCxx
+LG4pLGEyKQphPVAud0IoYj09bnVsbD9ILnZoKFAucnIoIkludmFsaWQgcG9ydCIsYTQscSkpOmIsail9
+ZWxzZSBhPWEyfWVsc2V7YT1hMgpjPWEKZD0iIn1hMD1QLmthKGE0LG4sbSxhMixqLGMhPW51bGwpCmEx
+PW08bD9QLmxlKGE0LG0rMSxsLGEyKTphMgpyZXR1cm4gbmV3IFAuRG4oaixkLGMsYSxhMCxhMSxsPGEz
+P1AudEcoYTQsbCsxLGEzKTphMil9LApNdDpmdW5jdGlvbihhKXtILmgoYSkKcmV0dXJuIFAua3UoYSww
+LGEubGVuZ3RoLEMueE0sITEpfSwKV1g6ZnVuY3Rpb24oYSl7dmFyIHQ9dS5OCnJldHVybiBDLk5tLk4w
+KEguVk0oYS5zcGxpdCgiJiIpLHUucyksUC5GbCh0LHQpLG5ldyBQLm4xKEMueE0pLHUuSil9LApIaDpm
+dW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHEscCxvLG4sbT0iSVB2NCBhZGRyZXNzIHNob3VsZCBjb250
+YWluIGV4YWN0bHkgNCBwYXJ0cyIsbD0iZWFjaCBwYXJ0IG11c3QgYmUgaW4gdGhlIHJhbmdlIDAuLjI1
+NSIsaz1uZXcgUC5jUyhhKSxqPW5ldyBVaW50OEFycmF5KDQpCmZvcih0PWoubGVuZ3RoLHM9YixyPXMs
+cT0wO3M8YzsrK3Mpe3A9Qy54Qi5tKGEscykKaWYocCE9PTQ2KXtpZigocF40OCk+OSlrLiQyKCJpbnZh
+bGlkIGNoYXJhY3RlciIscyl9ZWxzZXtpZihxPT09MylrLiQyKG0scykKbz1QLlFBKEMueEIuTmooYSxy
+LHMpLG51bGwpCmlmKHR5cGVvZiBvIT09Im51bWJlciIpcmV0dXJuIG8ub3MoKQppZihvPjI1NSlrLiQy
+KGwscikKbj1xKzEKaWYocT49dClyZXR1cm4gSC5PSChqLHEpCmpbcV09bwpyPXMrMQpxPW59fWlmKHEh
+PT0zKWsuJDIobSxjKQpvPVAuUUEoQy54Qi5OaihhLHIsYyksbnVsbCkKaWYodHlwZW9mIG8hPT0ibnVt
+YmVyIilyZXR1cm4gby5vcygpCmlmKG8+MjU1KWsuJDIobCxyKQppZihxPj10KXJldHVybiBILk9IKGos
+cSkKaltxXT1vCnJldHVybiBqfSwKZWc6ZnVuY3Rpb24oYSxiLGEwKXt2YXIgdCxzLHIscSxwLG8sbixt
+LGwsayxqLGksaCxnLGYsZSxkPW5ldyBQLlZDKGEpLGM9bmV3IFAuSlQoZCxhKQppZihhLmxlbmd0aDwy
+KWQuJDEoImFkZHJlc3MgaXMgdG9vIHNob3J0IikKdD1ILlZNKFtdLHUuYSkKZm9yKHM9YixyPXMscT0h
+MSxwPSExO3M8YTA7KytzKXtvPUMueEIubShhLHMpCmlmKG89PT01OCl7aWYocz09PWIpeysrcwppZihD
+LnhCLm0oYSxzKSE9PTU4KWQuJDIoImludmFsaWQgc3RhcnQgY29sb24uIixzKQpyPXN9aWYocz09PXIp
+e2lmKHEpZC4kMigib25seSBvbmUgd2lsZGNhcmQgYDo6YCBpcyBhbGxvd2VkIixzKQpDLk5tLmkodCwt
+MSkKcT0hMH1lbHNlIEMuTm0uaSh0LGMuJDIocixzKSkKcj1zKzF9ZWxzZSBpZihvPT09NDYpcD0hMH1p
+Zih0Lmxlbmd0aD09PTApZC4kMSgidG9vIGZldyBwYXJ0cyIpCm49cj09PWEwCm09Qy5ObS5ncloodCkK
+aWYobiYmbSE9PS0xKWQuJDIoImV4cGVjdGVkIGEgcGFydCBhZnRlciBsYXN0IGA6YCIsYTApCmlmKCFu
+KWlmKCFwKUMuTm0uaSh0LGMuJDIocixhMCkpCmVsc2V7bD1QLkhoKGEscixhMCkKQy5ObS5pKHQsKGxb
+MF08PDh8bFsxXSk+Pj4wKQpDLk5tLmkodCwobFsyXTw8OHxsWzNdKT4+PjApfWlmKHEpe2lmKHQubGVu
+Z3RoPjcpZC4kMSgiYW4gYWRkcmVzcyB3aXRoIGEgd2lsZGNhcmQgbXVzdCBoYXZlIGxlc3MgdGhhbiA3
+IHBhcnRzIil9ZWxzZSBpZih0Lmxlbmd0aCE9PTgpZC4kMSgiYW4gYWRkcmVzcyB3aXRob3V0IGEgd2ls
+ZGNhcmQgbXVzdCBjb250YWluIGV4YWN0bHkgOCBwYXJ0cyIpCms9bmV3IFVpbnQ4QXJyYXkoMTYpCmZv
+cihtPXQubGVuZ3RoLGo9ay5sZW5ndGgsaT05LW0scz0wLGg9MDtzPG07KytzKXtnPXRbc10KaWYoZz09
+PS0xKWZvcihmPTA7ZjxpOysrZil7aWYoaDwwfHxoPj1qKXJldHVybiBILk9IKGssaCkKa1toXT0wCmU9
+aCsxCmlmKGU+PWopcmV0dXJuIEguT0goayxlKQprW2VdPTAKaCs9Mn1lbHNle2U9Qy5qbi53RyhnLDgp
+CmlmKGg8MHx8aD49ailyZXR1cm4gSC5PSChrLGgpCmtbaF09ZQplPWgrMQppZihlPj1qKXJldHVybiBI
+Lk9IKGssZSkKa1tlXT1nJjI1NQpoKz0yfX1yZXR1cm4ga30sCktMOmZ1bmN0aW9uKGEsYixjLGQsZSxm
+LGcpe3ZhciB0LHMscixxLHAsbwpmPWY9PW51bGw/IiI6UC5QaShmLDAsZi5sZW5ndGgpCmc9UC56Uihn
+LDAsZz09bnVsbD8wOmcubGVuZ3RoKQphPVAuT2UoYSwwLGE9PW51bGw/MDphLmxlbmd0aCwhMSkKdD1Q
+LmxlKG51bGwsMCwwLGUpCnM9UC50RyhudWxsLDAsMCkKZD1QLndCKGQsZikKcj1mPT09ImZpbGUiCmlm
+KGE9PW51bGwpcT1nLmxlbmd0aCE9PTB8fGQhPW51bGx8fHIKZWxzZSBxPSExCmlmKHEpYT0iIgpxPWE9
+PW51bGwKcD0hcQpiPVAua2EoYiwwLGI9PW51bGw/MDpiLmxlbmd0aCxjLGYscCkKbz1mLmxlbmd0aD09
+PTAKaWYobyYmcSYmIUMueEIubihiLCIvIikpYj1QLndGKGIsIW98fHApCmVsc2UgYj1QLnhlKGIpCnJl
+dHVybiBuZXcgUC5EbihmLGcscSYmQy54Qi5uKGIsIi8vIik/IiI6YSxkLGIsdCxzKX0sCndLOmZ1bmN0
+aW9uKGEpe2lmKGE9PT0iaHR0cCIpcmV0dXJuIDgwCmlmKGE9PT0iaHR0cHMiKXJldHVybiA0NDMKcmV0
+dXJuIDB9LApSMzpmdW5jdGlvbihhLGIsYyl7dGhyb3cgSC5iKFAucnIoYyxhLGIpKX0sClhkOmZ1bmN0
+aW9uKGEsYixjLGQpe3ZhciB0LHMscixxLHAsbyxuLG0sbCxrLGosaT1udWxsLGg9Yi5sZW5ndGgKaWYo
+aCE9PTApe3I9MAp3aGlsZSghMCl7aWYoIShyPGgpKXt0PSIiCnM9MApicmVha31pZihDLnhCLlcoYixy
+KT09PTY0KXt0PUMueEIuTmooYiwwLHIpCnM9cisxCmJyZWFrfSsrcn1pZihzPGgmJkMueEIuVyhiLHMp
+PT09OTEpe2ZvcihxPXMscD0tMTtxPGg7KytxKXtvPUMueEIuVyhiLHEpCmlmKG89PT0zNyYmcDwwKXtu
+PUMueEIuUWkoYiwiMjUiLHErMSk/cSsyOnEKcD1xCnE9bn1lbHNlIGlmKG89PT05MylicmVha31pZihx
+PT09aCl0aHJvdyBILmIoUC5ycigiSW52YWxpZCBJUHY2IGhvc3QgZW50cnkuIixiLHMpKQptPXA8MD9x
+OnAKUC5lZyhiLHMrMSxtKTsrK3EKaWYocSE9PWgmJkMueEIuVyhiLHEpIT09NTgpdGhyb3cgSC5iKFAu
+cnIoIkludmFsaWQgZW5kIG9mIGF1dGhvcml0eSIsYixxKSl9ZWxzZSBxPXMKd2hpbGUoITApe2lmKCEo
+cTxoKSl7bD1pCmJyZWFrfWlmKEMueEIuVyhiLHEpPT09NTgpe2s9Qy54Qi5HKGIscSsxKQpsPWsubGVu
+Z3RoIT09MD9QLlFBKGssaSk6aQpicmVha30rK3F9aj1DLnhCLk5qKGIscyxxKX1lbHNle2w9aQpqPWwK
+dD0iIn1yZXR1cm4gUC5LTChqLGksSC5WTShjLnNwbGl0KCIvIiksdS5zKSxsLGQsYSx0KX0sCmtFOmZ1
+bmN0aW9uKGEsYil7dmFyIHQscyxyLHEscApmb3IodD1hLmxlbmd0aCxzPTA7czx0Oysrcyl7cj1hW3Nd
+CnIudG9TdHJpbmcKcT1KLlU2KHIpCnA9cS5nQShyKQppZigwPnApSC52aChQLlRFKDAsMCxxLmdBKHIp
+LG51bGwsbnVsbCkpCmlmKEgubTIociwiLyIsMCkpe3Q9UC5MNCgiSWxsZWdhbCBwYXRoIGNoYXJhY3Rl
+ciAiK0guRWoocikpCnRocm93IEguYih0KX19fSwKSE46ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscgpm
+b3IodD1ILnFDKGEsYyxudWxsLEgudDYoYSkuYyksdD1uZXcgSC5hNyh0LHQuZ0EodCksdC4kdGkuQygi
+YTc8YUwuRT4iKSk7dC5GKCk7KXtzPXQuZApyPVAubnUoJ1siKi86PD4/XFxcXHxdJykKcy50b1N0cmlu
+ZwppZihILm0yKHMsciwwKSl7dD1QLkw0KCJJbGxlZ2FsIGNoYXJhY3RlciBpbiBwYXRoOiAiK3MpCnRo
+cm93IEguYih0KX19fSwKcmc6ZnVuY3Rpb24oYSxiKXt2YXIgdAppZighKDY1PD1hJiZhPD05MCkpdD05
+Nzw9YSYmYTw9MTIyCmVsc2UgdD0hMAppZih0KXJldHVybgp0PVAuTDQoIklsbGVnYWwgZHJpdmUgbGV0
+dGVyICIrUC5PbyhhKSkKdGhyb3cgSC5iKHQpfSwKd0I6ZnVuY3Rpb24oYSxiKXtpZihhIT1udWxsJiZh
+PT09UC53SyhiKSlyZXR1cm4gbnVsbApyZXR1cm4gYX0sCk9lOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0
+LHMscixxLHAsbwppZihhPT1udWxsKXJldHVybiBudWxsCmlmKGI9PT1jKXJldHVybiIiCmlmKEMueEIu
+bShhLGIpPT09OTEpe3Q9Yy0xCmlmKEMueEIubShhLHQpIT09OTMpUC5SMyhhLGIsIk1pc3NpbmcgZW5k
+IGBdYCB0byBtYXRjaCBgW2AgaW4gaG9zdCIpCnM9YisxCnI9UC50byhhLHMsdCkKaWYocjx0KXtxPXIr
+MQpwPVAuT0EoYSxDLnhCLlFpKGEsIjI1IixxKT9yKzM6cSx0LCIlMjUiKX1lbHNlIHA9IiIKUC5lZyhh
+LHMscikKcmV0dXJuIEMueEIuTmooYSxiLHIpLnRvTG93ZXJDYXNlKCkrcCsiXSJ9Zm9yKG89YjtvPGM7
+KytvKWlmKEMueEIubShhLG8pPT09NTgpe3I9Qy54Qi5YVShhLCIlIixiKQpyPXI+PWImJnI8Yz9yOmMK
+aWYocjxjKXtxPXIrMQpwPVAuT0EoYSxDLnhCLlFpKGEsIjI1IixxKT9yKzM6cSxjLCIlMjUiKX1lbHNl
+IHA9IiIKUC5lZyhhLGIscikKcmV0dXJuIlsiK0MueEIuTmooYSxiLHIpK3ArIl0ifXJldHVybiBQLk9M
+KGEsYixjKX0sCnRvOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1DLnhCLlhVKGEsIiUiLGIpCnJldHVybiB0
+Pj1iJiZ0PGM/dDpjfSwKT0E6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscyxyLHEscCxvLG4sbSxsLGss
+aj1kIT09IiI/bmV3IFAuUm4oZCk6bnVsbApmb3IodD1iLHM9dCxyPSEwO3Q8Yzspe3E9Qy54Qi5tKGEs
+dCkKaWYocT09PTM3KXtwPVAucnYoYSx0LCEwKQpvPXA9PW51bGwKaWYobyYmcil7dCs9Mwpjb250aW51
+ZX1pZihqPT1udWxsKWo9bmV3IFAuUm4oIiIpCm49ai5hKz1DLnhCLk5qKGEscyx0KQppZihvKXA9Qy54
+Qi5OaihhLHQsdCszKQplbHNlIGlmKHA9PT0iJSIpUC5SMyhhLHQsIlpvbmVJRCBzaG91bGQgbm90IGNv
+bnRhaW4gJSBhbnltb3JlIikKai5hPW4rcAp0Kz0zCnM9dApyPSEwfWVsc2V7aWYocTwxMjcpe289cT4+
+PjQKaWYobz49OClyZXR1cm4gSC5PSChDLkYzLG8pCm89KEMuRjNbb10mMTw8KHEmMTUpKSE9PTB9ZWxz
+ZSBvPSExCmlmKG8pe2lmKHImJjY1PD1xJiY5MD49cSl7aWYoaj09bnVsbClqPW5ldyBQLlJuKCIiKQpp
+ZihzPHQpe2ouYSs9Qy54Qi5OaihhLHMsdCkKcz10fXI9ITF9Kyt0fWVsc2V7aWYoKHEmNjQ1MTIpPT09
+NTUyOTYmJnQrMTxjKXttPUMueEIubShhLHQrMSkKaWYoKG0mNjQ1MTIpPT09NTYzMjApe3E9NjU1MzZ8
+KHEmMTAyMyk8PDEwfG0mMTAyMwpsPTJ9ZWxzZSBsPTF9ZWxzZSBsPTEKaz1DLnhCLk5qKGEscyx0KQpp
+ZihqPT1udWxsKXtqPW5ldyBQLlJuKCIiKQpvPWp9ZWxzZSBvPWoKby5hKz1rCm8uYSs9UC56WChxKQp0
+Kz1sCnM9dH19fWlmKGo9PW51bGwpcmV0dXJuIEMueEIuTmooYSxiLGMpCmlmKHM8YylqLmErPUMueEIu
+TmooYSxzLGMpCm89ai5hCnJldHVybiBvLmNoYXJDb2RlQXQoMCk9PTA/bzpvfSwKT0w6ZnVuY3Rpb24o
+YSxiLGMpe3ZhciB0LHMscixxLHAsbyxuLG0sbCxrLGoKZm9yKHQ9YixzPXQscj1udWxsLHE9ITA7dDxj
+Oyl7cD1DLnhCLm0oYSx0KQppZihwPT09Mzcpe289UC5ydihhLHQsITApCm49bz09bnVsbAppZihuJiZx
+KXt0Kz0zCmNvbnRpbnVlfWlmKHI9PW51bGwpcj1uZXcgUC5SbigiIikKbT1DLnhCLk5qKGEscyx0KQps
+PXIuYSs9IXE/bS50b0xvd2VyQ2FzZSgpOm0KaWYobil7bz1DLnhCLk5qKGEsdCx0KzMpCms9M31lbHNl
+IGlmKG89PT0iJSIpe289IiUyNSIKaz0xfWVsc2Ugaz0zCnIuYT1sK28KdCs9awpzPXQKcT0hMH1lbHNl
+e2lmKHA8MTI3KXtuPXA+Pj40CmlmKG4+PTgpcmV0dXJuIEguT0goQy5lYSxuKQpuPShDLmVhW25dJjE8
+PChwJjE1KSkhPT0wfWVsc2Ugbj0hMQppZihuKXtpZihxJiY2NTw9cCYmOTA+PXApe2lmKHI9PW51bGwp
+cj1uZXcgUC5SbigiIikKaWYoczx0KXtyLmErPUMueEIuTmooYSxzLHQpCnM9dH1xPSExfSsrdH1lbHNl
+e2lmKHA8PTkzKXtuPXA+Pj40CmlmKG4+PTgpcmV0dXJuIEguT0goQy5hayxuKQpuPShDLmFrW25dJjE8
+PChwJjE1KSkhPT0wfWVsc2Ugbj0hMQppZihuKVAuUjMoYSx0LCJJbnZhbGlkIGNoYXJhY3RlciIpCmVs
+c2V7aWYoKHAmNjQ1MTIpPT09NTUyOTYmJnQrMTxjKXtqPUMueEIubShhLHQrMSkKaWYoKGomNjQ1MTIp
+PT09NTYzMjApe3A9NjU1MzZ8KHAmMTAyMyk8PDEwfGomMTAyMwprPTJ9ZWxzZSBrPTF9ZWxzZSBrPTEK
+bT1DLnhCLk5qKGEscyx0KQppZighcSltPW0udG9Mb3dlckNhc2UoKQppZihyPT1udWxsKXtyPW5ldyBQ
+LlJuKCIiKQpuPXJ9ZWxzZSBuPXIKbi5hKz1tCm4uYSs9UC56WChwKQp0Kz1rCnM9dH19fX1pZihyPT1u
+dWxsKXJldHVybiBDLnhCLk5qKGEsYixjKQppZihzPGMpe209Qy54Qi5OaihhLHMsYykKci5hKz0hcT9t
+LnRvTG93ZXJDYXNlKCk6bX1uPXIuYQpyZXR1cm4gbi5jaGFyQ29kZUF0KDApPT0wP246bn0sClBpOmZ1
+bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscQppZihiPT09YylyZXR1cm4iIgppZighUC5FdChKLnJZKGEp
+LlcoYSxiKSkpUC5SMyhhLGIsIlNjaGVtZSBub3Qgc3RhcnRpbmcgd2l0aCBhbHBoYWJldGljIGNoYXJh
+Y3RlciIpCmZvcih0PWIscz0hMTt0PGM7Kyt0KXtyPUMueEIuVyhhLHQpCmlmKHI8MTI4KXtxPXI+Pj40
+CmlmKHE+PTgpcmV0dXJuIEguT0goQy5tSyxxKQpxPShDLm1LW3FdJjE8PChyJjE1KSkhPT0wfWVsc2Ug
+cT0hMQppZighcSlQLlIzKGEsdCwiSWxsZWdhbCBzY2hlbWUgY2hhcmFjdGVyIikKaWYoNjU8PXImJnI8
+PTkwKXM9ITB9YT1DLnhCLk5qKGEsYixjKQpyZXR1cm4gUC5ZYShzP2EudG9Mb3dlckNhc2UoKTphKX0s
+CllhOmZ1bmN0aW9uKGEpe2lmKGE9PT0iaHR0cCIpcmV0dXJuImh0dHAiCmlmKGE9PT0iZmlsZSIpcmV0
+dXJuImZpbGUiCmlmKGE9PT0iaHR0cHMiKXJldHVybiJodHRwcyIKaWYoYT09PSJwYWNrYWdlIilyZXR1
+cm4icGFja2FnZSIKcmV0dXJuIGF9LAp6UjpmdW5jdGlvbihhLGIsYyl7aWYoYT09bnVsbClyZXR1cm4i
+IgpyZXR1cm4gUC5QSShhLGIsYyxDLnRvLCExKX0sCmthOmZ1bmN0aW9uKGEsYixjLGQsZSxmKXt2YXIg
+dCxzLHI9ZT09PSJmaWxlIixxPXJ8fGYKaWYoYT09bnVsbCl7aWYoZD09bnVsbClyZXR1cm4gcj8iLyI6
+IiIKdD1ILnQ2KGQpCnM9bmV3IEgubEooZCx0LkMoInFVKDEpIikuYShuZXcgUC5SWigpKSx0LkMoImxK
+PDEscVU+IikpLkgoMCwiLyIpfWVsc2UgaWYoZCE9bnVsbCl0aHJvdyBILmIoUC54WSgiQm90aCBwYXRo
+IGFuZCBwYXRoU2VnbWVudHMgc3BlY2lmaWVkIikpCmVsc2Ugcz1QLlBJKGEsYixjLEMuV2QsITApCmlm
+KHMubGVuZ3RoPT09MCl7aWYocilyZXR1cm4iLyJ9ZWxzZSBpZihxJiYhQy54Qi5uKHMsIi8iKSlzPSIv
+IitzCnJldHVybiBQLkpyKHMsZSxmKX0sCkpyOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1iLmxlbmd0aD09
+PTAKaWYodCYmIWMmJiFDLnhCLm4oYSwiLyIpKXJldHVybiBQLndGKGEsIXR8fGMpCnJldHVybiBQLnhl
+KGEpfSwKbGU6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscz17fQppZihhIT1udWxsKXtpZihkIT1udWxs
+KXRocm93IEguYihQLnhZKCJCb3RoIHF1ZXJ5IGFuZCBxdWVyeVBhcmFtZXRlcnMgc3BlY2lmaWVkIikp
+CnJldHVybiBQLlBJKGEsYixjLEMuVkMsITApfWlmKGQ9PW51bGwpcmV0dXJuIG51bGwKdD1uZXcgUC5S
+bigiIikKcy5hPSIiCmQuSygwLG5ldyBQLnk1KG5ldyBQLk1FKHMsdCkpKQpzPXQuYQpyZXR1cm4gcy5j
+aGFyQ29kZUF0KDApPT0wP3M6c30sCnRHOmZ1bmN0aW9uKGEsYixjKXtpZihhPT1udWxsKXJldHVybiBu
+dWxsCnJldHVybiBQLlBJKGEsYixjLEMuVkMsITApfSwKcnY6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMs
+cixxLHAsbz1iKzIKaWYobz49YS5sZW5ndGgpcmV0dXJuIiUiCnQ9Qy54Qi5tKGEsYisxKQpzPUMueEIu
+bShhLG8pCnI9SC5vbyh0KQpxPUgub28ocykKaWYocjwwfHxxPDApcmV0dXJuIiUiCnA9cioxNitxCmlm
+KHA8MTI3KXtvPUMuam4ud0cocCw0KQppZihvPj04KXJldHVybiBILk9IKEMuRjMsbykKbz0oQy5GM1tv
+XSYxPDwocCYxNSkpIT09MH1lbHNlIG89ITEKaWYobylyZXR1cm4gSC5MdyhjJiY2NTw9cCYmOTA+PXA/
+KHB8MzIpPj4+MDpwKQppZih0Pj05N3x8cz49OTcpcmV0dXJuIEMueEIuTmooYSxiLGIrMykudG9VcHBl
+ckNhc2UoKQpyZXR1cm4gbnVsbH0sCnpYOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHAsbyxuLG0sbD0i
+MDEyMzQ1Njc4OUFCQ0RFRiIKaWYoYTwxMjgpe3Q9bmV3IFVpbnQ4QXJyYXkoMykKcz10Lmxlbmd0aApp
+ZigwPj1zKXJldHVybiBILk9IKHQsMCkKdFswXT0zNwpyPUMueEIuVyhsLGE+Pj40KQppZigxPj1zKXJl
+dHVybiBILk9IKHQsMSkKdFsxXT1yCnI9Qy54Qi5XKGwsYSYxNSkKaWYoMj49cylyZXR1cm4gSC5PSCh0
+LDIpCnRbMl09cn1lbHNle2lmKGE+MjA0NylpZihhPjY1NTM1KXtxPTI0MApwPTR9ZWxzZXtxPTIyNApw
+PTN9ZWxzZXtxPTE5MgpwPTJ9dD1uZXcgVWludDhBcnJheSgzKnApCmZvcihzPXQubGVuZ3RoLG89MDst
+LXAscD49MDtxPTEyOCl7bj1DLmpuLmJmKGEsNipwKSY2M3xxCmlmKG8+PXMpcmV0dXJuIEguT0godCxv
+KQp0W29dPTM3CnI9bysxCm09Qy54Qi5XKGwsbj4+PjQpCmlmKHI+PXMpcmV0dXJuIEguT0godCxyKQp0
+W3JdPW0KbT1vKzIKcj1DLnhCLlcobCxuJjE1KQppZihtPj1zKXJldHVybiBILk9IKHQsbSkKdFttXT1y
+Cm8rPTN9fXJldHVybiBQLkhNKHQsMCxudWxsKX0sClBJOmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHQ9
+UC5VbChhLGIsYyxkLGUpCnJldHVybiB0PT1udWxsP0MueEIuTmooYSxiLGMpOnR9LApVbDpmdW5jdGlv
+bihhLGIsYyxkLGUpe3ZhciB0LHMscixxLHAsbyxuLG0sbCxrPW51bGwKZm9yKHQ9IWUscz1iLHI9cyxx
+PWs7czxjOyl7cD1DLnhCLm0oYSxzKQppZihwPDEyNyl7bz1wPj4+NAppZihvPj04KXJldHVybiBILk9I
+KGQsbykKbz0oZFtvXSYxPDwocCYxNSkpIT09MH1lbHNlIG89ITEKaWYobykrK3MKZWxzZXtpZihwPT09
+Mzcpe249UC5ydihhLHMsITEpCmlmKG49PW51bGwpe3MrPTMKY29udGludWV9aWYoIiUiPT09bil7bj0i
+JTI1IgptPTF9ZWxzZSBtPTN9ZWxzZXtpZih0KWlmKHA8PTkzKXtvPXA+Pj40CmlmKG8+PTgpcmV0dXJu
+IEguT0goQy5hayxvKQpvPShDLmFrW29dJjE8PChwJjE1KSkhPT0wfWVsc2Ugbz0hMQplbHNlIG89ITEK
+aWYobyl7UC5SMyhhLHMsIkludmFsaWQgY2hhcmFjdGVyIikKbT1rCm49bX1lbHNle2lmKChwJjY0NTEy
+KT09PTU1Mjk2KXtvPXMrMQppZihvPGMpe2w9Qy54Qi5tKGEsbykKaWYoKGwmNjQ1MTIpPT09NTYzMjAp
+e3A9NjU1MzZ8KHAmMTAyMyk8PDEwfGwmMTAyMwptPTJ9ZWxzZSBtPTF9ZWxzZSBtPTF9ZWxzZSBtPTEK
+bj1QLnpYKHApfX1pZihxPT1udWxsKXtxPW5ldyBQLlJuKCIiKQpvPXF9ZWxzZSBvPXEKby5hKz1DLnhC
+Lk5qKGEscixzKQpvLmErPUguRWoobikKaWYodHlwZW9mIG0hPT0ibnVtYmVyIilyZXR1cm4gSC5wWSht
+KQpzKz1tCnI9c319aWYocT09bnVsbClyZXR1cm4gawppZihyPGMpcS5hKz1DLnhCLk5qKGEscixjKQp0
+PXEuYQpyZXR1cm4gdC5jaGFyQ29kZUF0KDApPT0wP3Q6dH0sCnlCOmZ1bmN0aW9uKGEpe2lmKEMueEIu
+bihhLCIuIikpcmV0dXJuITAKcmV0dXJuIEMueEIuT1koYSwiLy4iKSE9PS0xfSwKeGU6ZnVuY3Rpb24o
+YSl7dmFyIHQscyxyLHEscCxvLG4KaWYoIVAueUIoYSkpcmV0dXJuIGEKdD1ILlZNKFtdLHUucykKZm9y
+KHM9YS5zcGxpdCgiLyIpLHI9cy5sZW5ndGgscT0hMSxwPTA7cDxyOysrcCl7bz1zW3BdCmlmKEouUk0o
+bywiLi4iKSl7bj10Lmxlbmd0aAppZihuIT09MCl7aWYoMD49bilyZXR1cm4gSC5PSCh0LC0xKQp0LnBv
 cCgpCmlmKHQubGVuZ3RoPT09MClDLk5tLmkodCwiIil9cT0hMH1lbHNlIGlmKCIuIj09PW8pcT0hMApl
 bHNle0MuTm0uaSh0LG8pCnE9ITF9fWlmKHEpQy5ObS5pKHQsIiIpCnJldHVybiBDLk5tLkgodCwiLyIp
 fSwKd0Y6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxwLG8KaWYoIVAueUIoYSkpcmV0dXJuIWI/UC5D
 MShhKTphCnQ9SC5WTShbXSx1LnMpCmZvcihzPWEuc3BsaXQoIi8iKSxyPXMubGVuZ3RoLHE9ITEscD0w
 O3A8cjsrK3Ape289c1twXQppZigiLi4iPT09bylpZih0Lmxlbmd0aCE9PTAmJkMuTm0uZ3JaKHQpIT09
-Ii4uIil7aWYoMD49dC5sZW5ndGgpcmV0dXJuIEguayh0LC0xKQp0LnBvcCgpCnE9ITB9ZWxzZXtDLk5t
-LmkodCwiLi4iKQpxPSExfWVsc2UgaWYoIi4iPT09bylxPSEwCmVsc2V7Qy5ObS5pKHQsbykKcT0hMX19
-cz10Lmxlbmd0aAppZihzIT09MClpZihzPT09MSl7aWYoMD49cylyZXR1cm4gSC5rKHQsMCkKcz10WzBd
-Lmxlbmd0aD09PTB9ZWxzZSBzPSExCmVsc2Ugcz0hMAppZihzKXJldHVybiIuLyIKaWYocXx8Qy5ObS5n
-cloodCk9PT0iLi4iKUMuTm0uaSh0LCIiKQppZighYil7aWYoMD49dC5sZW5ndGgpcmV0dXJuIEguayh0
-LDApCkMuTm0uWSh0LDAsUC5DMSh0WzBdKSl9cmV0dXJuIEMuTm0uSCh0LCIvIil9LApDMTpmdW5jdGlv
-bihhKXt2YXIgdCxzLHIscT1hLmxlbmd0aAppZihxPj0yJiZQLkV0KEouUXooYSwwKSkpZm9yKHQ9MTt0
-PHE7Kyt0KXtzPUMueEIuVyhhLHQpCmlmKHM9PT01OClyZXR1cm4gQy54Qi5OaihhLDAsdCkrIiUzQSIr
-Qy54Qi5HKGEsdCsxKQppZihzPD0xMjcpe3I9cz4+PjQKaWYocj49OClyZXR1cm4gSC5rKEMubUsscikK
-cj0oQy5tS1tyXSYxPDwocyYxNSkpPT09MH1lbHNlIHI9ITAKaWYocilicmVha31yZXR1cm4gYX0sCm1u
-OmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxPWEuZ0ZqKCkscD1xLmxlbmd0aAppZihwPjAmJkouSChxWzBd
-KT09PTImJkouYTYocVswXSwxKT09PTU4KXtpZigwPj1wKXJldHVybiBILmsocSwwKQpQLnJnKEouYTYo
-cVswXSwwKSwhMSkKUC5ITihxLCExLDEpCnQ9ITB9ZWxzZXtQLkhOKHEsITEsMCkKdD0hMX1zPWEuZ3RU
-KCkmJiF0PyJcXCI6IiIKaWYoYS5nY2ooKSl7cj1hLmdKZihhKQppZihyLmxlbmd0aCE9PTApcz1zKyJc
-XCIrcisiXFwifXM9UC52ZyhzLHEsIlxcIikKcD10JiZwPT09MT9zKyJcXCI6cwpyZXR1cm4gcC5jaGFy
-Q29kZUF0KDApPT0wP3A6cH0sCkloOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyCmZvcih0PTAscz0wO3M8
-MjsrK3Mpe3I9Qy54Qi5XKGEsYitzKQppZig0ODw9ciYmcjw9NTcpdD10KjE2K3ItNDgKZWxzZXtyfD0z
-MgppZig5Nzw9ciYmcjw9MTAyKXQ9dCoxNityLTg3CmVsc2UgdGhyb3cgSC5iKFAueFkoIkludmFsaWQg
-VVJMIGVuY29kaW5nIikpfX1yZXR1cm4gdH0sCmt1OmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHQscyxy
-LHEscD1KLnJZKGEpLG89Ygp3aGlsZSghMCl7aWYoIShvPGMpKXt0PSEwCmJyZWFrfXM9cC5XKGEsbykK
-aWYoczw9MTI3KWlmKHMhPT0zNylyPWUmJnM9PT00MwplbHNlIHI9ITAKZWxzZSByPSEwCmlmKHIpe3Q9
-ITEKYnJlYWt9KytvfWlmKHQpe2lmKEMueE0hPT1kKXI9ITEKZWxzZSByPSEwCmlmKHIpcmV0dXJuIHAu
-TmooYSxiLGMpCmVsc2UgcT1uZXcgSC5xaihwLk5qKGEsYixjKSl9ZWxzZXtxPUguVk0oW10sdS50KQpm
-b3Iobz1iO288YzsrK28pe3M9cC5XKGEsbykKaWYocz4xMjcpdGhyb3cgSC5iKFAueFkoIklsbGVnYWwg
-cGVyY2VudCBlbmNvZGluZyBpbiBVUkkiKSkKaWYocz09PTM3KXtpZihvKzM+YS5sZW5ndGgpdGhyb3cg
-SC5iKFAueFkoIlRydW5jYXRlZCBVUkkiKSkKQy5ObS5pKHEsUC5JaChhLG8rMSkpCm8rPTJ9ZWxzZSBp
-ZihlJiZzPT09NDMpQy5ObS5pKHEsMzIpCmVsc2UgQy5ObS5pKHEscyl9fXUuTC5hKHEpCnJldHVybiBu
-ZXcgUC5HWSghMSkuV0oocSl9LApFdDpmdW5jdGlvbihhKXt2YXIgdD1hfDMyCnJldHVybiA5Nzw9dCYm
-dDw9MTIyfSwKS0Q6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixxLHAsbyxuLG0sbD0iSW52YWxpZCBN
-SU1FIHR5cGUiLGs9SC5WTShbYi0xXSx1LnQpCmZvcih0PWEubGVuZ3RoLHM9YixyPS0xLHE9bnVsbDtz
-PHQ7KytzKXtxPUMueEIuVyhhLHMpCmlmKHE9PT00NHx8cT09PTU5KWJyZWFrCmlmKHE9PT00Nyl7aWYo
-cjwwKXtyPXMKY29udGludWV9dGhyb3cgSC5iKFAucnIobCxhLHMpKX19aWYocjwwJiZzPmIpdGhyb3cg
-SC5iKFAucnIobCxhLHMpKQpmb3IoO3EhPT00NDspe0MuTm0uaShrLHMpOysrcwpmb3IocD0tMTtzPHQ7
-KytzKXtxPUMueEIuVyhhLHMpCmlmKHE9PT02MSl7aWYocDwwKXA9c31lbHNlIGlmKHE9PT01OXx8cT09
-PTQ0KWJyZWFrfWlmKHA+PTApQy5ObS5pKGsscCkKZWxzZXtvPUMuTm0uZ3JaKGspCmlmKHEhPT00NHx8
-cyE9PW8rN3x8IUMueEIuUWkoYSwiYmFzZTY0IixvKzEpKXRocm93IEguYihQLnJyKCJFeHBlY3Rpbmcg
-Jz0nIixhLHMpKQpicmVha319Qy5ObS5pKGsscykKbj1zKzEKaWYoKGsubGVuZ3RoJjEpPT09MSlhPUMu
-aDkueXIoYSxuLHQpCmVsc2V7bT1QLlVsKGEsbix0LEMuVkMsITApCmlmKG0hPW51bGwpYT1DLnhCLmk3
-KGEsbix0LG0pfXJldHVybiBuZXcgUC5QRShhLGssYyl9LApLTjpmdW5jdGlvbigpe3ZhciB0PSIwMTIz
-NDU2Nzg5QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ei0u
-X34hJCYnKCkqKyw7PSIscz0iLiIscj0iOiIscT0iLyIscD0iPyIsbz0iIyIsbj11LmdjLG09UC5kSCgy
-MixuZXcgUC5xMygpLG4pLGw9bmV3IFAueUkobSksaz1uZXcgUC5jNigpLGo9bmV3IFAucWQoKSxpPW4u
-YShsLiQyKDAsMjI1KSkKay4kMyhpLHQsMSkKay4kMyhpLHMsMTQpCmsuJDMoaSxyLDM0KQprLiQzKGks
-cSwzKQprLiQzKGkscCwxNzIpCmsuJDMoaSxvLDIwNSkKaT1uLmEobC4kMigxNCwyMjUpKQprLiQzKGks
-dCwxKQprLiQzKGkscywxNSkKay4kMyhpLHIsMzQpCmsuJDMoaSxxLDIzNCkKay4kMyhpLHAsMTcyKQpr
-LiQzKGksbywyMDUpCmk9bi5hKGwuJDIoMTUsMjI1KSkKay4kMyhpLHQsMSkKay4kMyhpLCIlIiwyMjUp
-CmsuJDMoaSxyLDM0KQprLiQzKGkscSw5KQprLiQzKGkscCwxNzIpCmsuJDMoaSxvLDIwNSkKaT1uLmEo
-bC4kMigxLDIyNSkpCmsuJDMoaSx0LDEpCmsuJDMoaSxyLDM0KQprLiQzKGkscSwxMCkKay4kMyhpLHAs
-MTcyKQprLiQzKGksbywyMDUpCmk9bi5hKGwuJDIoMiwyMzUpKQprLiQzKGksdCwxMzkpCmsuJDMoaSxx
-LDEzMSkKay4kMyhpLHMsMTQ2KQprLiQzKGkscCwxNzIpCmsuJDMoaSxvLDIwNSkKaT1uLmEobC4kMigz
-LDIzNSkpCmsuJDMoaSx0LDExKQprLiQzKGkscSw2OCkKay4kMyhpLHMsMTgpCmsuJDMoaSxwLDE3MikK
-ay4kMyhpLG8sMjA1KQppPW4uYShsLiQyKDQsMjI5KSkKay4kMyhpLHQsNSkKai4kMyhpLCJBWiIsMjI5
-KQprLiQzKGksciwxMDIpCmsuJDMoaSwiQCIsNjgpCmsuJDMoaSwiWyIsMjMyKQprLiQzKGkscSwxMzgp
-CmsuJDMoaSxwLDE3MikKay4kMyhpLG8sMjA1KQppPW4uYShsLiQyKDUsMjI5KSkKay4kMyhpLHQsNSkK
-ai4kMyhpLCJBWiIsMjI5KQprLiQzKGksciwxMDIpCmsuJDMoaSwiQCIsNjgpCmsuJDMoaSxxLDEzOCkK
-ay4kMyhpLHAsMTcyKQprLiQzKGksbywyMDUpCmk9bi5hKGwuJDIoNiwyMzEpKQpqLiQzKGksIjE5Iiw3
-KQprLiQzKGksIkAiLDY4KQprLiQzKGkscSwxMzgpCmsuJDMoaSxwLDE3MikKay4kMyhpLG8sMjA1KQpp
-PW4uYShsLiQyKDcsMjMxKSkKai4kMyhpLCIwOSIsNykKay4kMyhpLCJAIiw2OCkKay4kMyhpLHEsMTM4
-KQprLiQzKGkscCwxNzIpCmsuJDMoaSxvLDIwNSkKay4kMyhuLmEobC4kMig4LDgpKSwiXSIsNSkKaT1u
-LmEobC4kMig5LDIzNSkpCmsuJDMoaSx0LDExKQprLiQzKGkscywxNikKay4kMyhpLHEsMjM0KQprLiQz
-KGkscCwxNzIpCmsuJDMoaSxvLDIwNSkKaT1uLmEobC4kMigxNiwyMzUpKQprLiQzKGksdCwxMSkKay4k
-MyhpLHMsMTcpCmsuJDMoaSxxLDIzNCkKay4kMyhpLHAsMTcyKQprLiQzKGksbywyMDUpCmk9bi5hKGwu
-JDIoMTcsMjM1KSkKay4kMyhpLHQsMTEpCmsuJDMoaSxxLDkpCmsuJDMoaSxwLDE3MikKay4kMyhpLG8s
-MjA1KQppPW4uYShsLiQyKDEwLDIzNSkpCmsuJDMoaSx0LDExKQprLiQzKGkscywxOCkKay4kMyhpLHEs
-MjM0KQprLiQzKGkscCwxNzIpCmsuJDMoaSxvLDIwNSkKaT1uLmEobC4kMigxOCwyMzUpKQprLiQzKGks
-dCwxMSkKay4kMyhpLHMsMTkpCmsuJDMoaSxxLDIzNCkKay4kMyhpLHAsMTcyKQprLiQzKGksbywyMDUp
-Cmk9bi5hKGwuJDIoMTksMjM1KSkKay4kMyhpLHQsMTEpCmsuJDMoaSxxLDIzNCkKay4kMyhpLHAsMTcy
-KQprLiQzKGksbywyMDUpCmk9bi5hKGwuJDIoMTEsMjM1KSkKay4kMyhpLHQsMTEpCmsuJDMoaSxxLDEw
-KQprLiQzKGkscCwxNzIpCmsuJDMoaSxvLDIwNSkKaT1uLmEobC4kMigxMiwyMzYpKQprLiQzKGksdCwx
-MikKay4kMyhpLHAsMTIpCmsuJDMoaSxvLDIwNSkKaT1uLmEobC4kMigxMywyMzcpKQprLiQzKGksdCwx
-MykKay4kMyhpLHAsMTMpCmouJDMobi5hKGwuJDIoMjAsMjQ1KSksImF6IiwyMSkKbD1uLmEobC4kMigy
-MSwyNDUpKQpqLiQzKGwsImF6IiwyMSkKai4kMyhsLCIwOSIsMjEpCmsuJDMobCwiKy0uIiwyMSkKcmV0
-dXJuIG19LApVQjpmdW5jdGlvbihhLGIsYyxkLGUpe3ZhciB0LHMscixxLHAsbz0kLnZaKCkKZm9yKHQ9
-Si5yWShhKSxzPWI7czxjOysrcyl7aWYoZDwwfHxkPj1vLmxlbmd0aClyZXR1cm4gSC5rKG8sZCkKcj1v
-W2RdCnE9dC5XKGEscyleOTYKaWYocT45NSlxPTMxCmlmKHE+PXIubGVuZ3RoKXJldHVybiBILmsocixx
-KQpwPXJbcV0KZD1wJjMxCkMuTm0uWShlLHA+Pj41LHMpfXJldHVybiBkfSwKV0Y6ZnVuY3Rpb24gV0Yo
-YSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCmEyOmZ1bmN0aW9uIGEyKCl7fSwKaVA6ZnVuY3Rpb24gaVAo
-YSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCkNQOmZ1bmN0aW9uIENQKCl7fSwKWFM6ZnVuY3Rpb24gWFMo
-KXt9LApDNjpmdW5jdGlvbiBDNihhKXt0aGlzLmE9YX0sCkxLOmZ1bmN0aW9uIExLKCl7fSwKQVQ6ZnVu
-Y3Rpb24gQVQoYSxiLGMsZCl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9ZH0sCmJKOmZ1
-bmN0aW9uIGJKKGEsYixjLGQsZSxmKXt2YXIgXz10aGlzCl8uZT1hCl8uZj1iCl8uYT1jCl8uYj1kCl8u
-Yz1lCl8uZD1mfSwKZVk6ZnVuY3Rpb24gZVkoYSxiLGMsZCxlKXt2YXIgXz10aGlzCl8uZj1hCl8uYT1i
-Cl8uYj1jCl8uYz1kCl8uZD1lfSwKbXA6ZnVuY3Rpb24gbXAoYSxiLGMsZCl7dmFyIF89dGhpcwpfLmE9
-YQpfLmI9YgpfLmM9YwpfLmQ9ZH0sCnViOmZ1bmN0aW9uIHViKGEpe3RoaXMuYT1hfSwKZHM6ZnVuY3Rp
-b24gZHMoYSl7dGhpcy5hPWF9LApsajpmdW5jdGlvbiBsaihhKXt0aGlzLmE9YX0sClVWOmZ1bmN0aW9u
-IFVWKGEpe3RoaXMuYT1hfSwKazU6ZnVuY3Rpb24gazUoKXt9LApLWTpmdW5jdGlvbiBLWSgpe30sCnQ3
-OmZ1bmN0aW9uIHQ3KGEpe3RoaXMuYT1hfSwKQ0Q6ZnVuY3Rpb24gQ0QoYSl7dGhpcy5hPWF9LAphRTpm
+Ii4uIil7aWYoMD49dC5sZW5ndGgpcmV0dXJuIEguT0godCwtMSkKdC5wb3AoKQpxPSEwfWVsc2V7Qy5O
+bS5pKHQsIi4uIikKcT0hMX1lbHNlIGlmKCIuIj09PW8pcT0hMAplbHNle0MuTm0uaSh0LG8pCnE9ITF9
+fXM9dC5sZW5ndGgKaWYocyE9PTApaWYocz09PTEpe2lmKDA+PXMpcmV0dXJuIEguT0godCwwKQpzPXRb
+MF0ubGVuZ3RoPT09MH1lbHNlIHM9ITEKZWxzZSBzPSEwCmlmKHMpcmV0dXJuIi4vIgppZihxfHxDLk5t
+LmdyWih0KT09PSIuLiIpQy5ObS5pKHQsIiIpCmlmKCFiKXtpZigwPj10Lmxlbmd0aClyZXR1cm4gSC5P
+SCh0LDApCkMuTm0uWSh0LDAsUC5DMSh0WzBdKSl9cmV0dXJuIEMuTm0uSCh0LCIvIil9LApDMTpmdW5j
+dGlvbihhKXt2YXIgdCxzLHIscT1hLmxlbmd0aAppZihxPj0yJiZQLkV0KEouUXooYSwwKSkpZm9yKHQ9
+MTt0PHE7Kyt0KXtzPUMueEIuVyhhLHQpCmlmKHM9PT01OClyZXR1cm4gQy54Qi5OaihhLDAsdCkrIiUz
+QSIrQy54Qi5HKGEsdCsxKQppZihzPD0xMjcpe3I9cz4+PjQKaWYocj49OClyZXR1cm4gSC5PSChDLm1L
+LHIpCnI9KEMubUtbcl0mMTw8KHMmMTUpKT09PTB9ZWxzZSByPSEwCmlmKHIpYnJlYWt9cmV0dXJuIGF9
+LAptbjpmdW5jdGlvbihhKXt2YXIgdCxzLHIscT1hLmdGaigpLHA9cS5sZW5ndGgKaWYocD4wJiZKLkht
+KHFbMF0pPT09MiYmSi5hNihxWzBdLDEpPT09NTgpe2lmKDA+PXApcmV0dXJuIEguT0gocSwwKQpQLnJn
+KEouYTYocVswXSwwKSwhMSkKUC5ITihxLCExLDEpCnQ9ITB9ZWxzZXtQLkhOKHEsITEsMCkKdD0hMX1z
+PWEuZ3RUKCkmJiF0PyJcXCI6IiIKaWYoYS5nY2ooKSl7cj1hLmdKZihhKQppZihyLmxlbmd0aCE9PTAp
+cz1zKyJcXCIrcisiXFwifXM9UC52ZyhzLHEsIlxcIikKcD10JiZwPT09MT9zKyJcXCI6cwpyZXR1cm4g
+cC5jaGFyQ29kZUF0KDApPT0wP3A6cH0sCkloOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyCmZvcih0PTAs
+cz0wO3M8MjsrK3Mpe3I9Qy54Qi5XKGEsYitzKQppZig0ODw9ciYmcjw9NTcpdD10KjE2K3ItNDgKZWxz
+ZXtyfD0zMgppZig5Nzw9ciYmcjw9MTAyKXQ9dCoxNityLTg3CmVsc2UgdGhyb3cgSC5iKFAueFkoIklu
+dmFsaWQgVVJMIGVuY29kaW5nIikpfX1yZXR1cm4gdH0sCmt1OmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFy
+IHQscyxyLHEscD1KLnJZKGEpLG89Ygp3aGlsZSghMCl7aWYoIShvPGMpKXt0PSEwCmJyZWFrfXM9cC5X
+KGEsbykKaWYoczw9MTI3KWlmKHMhPT0zNylyPWUmJnM9PT00MwplbHNlIHI9ITAKZWxzZSByPSEwCmlm
+KHIpe3Q9ITEKYnJlYWt9KytvfWlmKHQpe2lmKEMueE0hPT1kKXI9ITEKZWxzZSByPSEwCmlmKHIpcmV0
+dXJuIHAuTmooYSxiLGMpCmVsc2UgcT1uZXcgSC5xaihwLk5qKGEsYixjKSl9ZWxzZXtxPUguVk0oW10s
+dS5hKQpmb3Iobz1iO288YzsrK28pe3M9cC5XKGEsbykKaWYocz4xMjcpdGhyb3cgSC5iKFAueFkoIkls
+bGVnYWwgcGVyY2VudCBlbmNvZGluZyBpbiBVUkkiKSkKaWYocz09PTM3KXtpZihvKzM+YS5sZW5ndGgp
+dGhyb3cgSC5iKFAueFkoIlRydW5jYXRlZCBVUkkiKSkKQy5ObS5pKHEsUC5JaChhLG8rMSkpCm8rPTJ9
+ZWxzZSBpZihlJiZzPT09NDMpQy5ObS5pKHEsMzIpCmVsc2UgQy5ObS5pKHEscyl9fXUuTC5hKHEpCnJl
+dHVybiBDLm9FLldKKHEpfSwKRXQ6ZnVuY3Rpb24oYSl7dmFyIHQ9YXwzMgpyZXR1cm4gOTc8PXQmJnQ8
+PTEyMn0sCktEOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscSxwLG8sbixtLGw9IkludmFsaWQgTUlN
+RSB0eXBlIixrPUguVk0oW2ItMV0sdS5hKQpmb3IodD1hLmxlbmd0aCxzPWIscj0tMSxxPW51bGw7czx0
+Oysrcyl7cT1DLnhCLlcoYSxzKQppZihxPT09NDR8fHE9PT01OSlicmVhawppZihxPT09NDcpe2lmKHI8
+MCl7cj1zCmNvbnRpbnVlfXRocm93IEguYihQLnJyKGwsYSxzKSl9fWlmKHI8MCYmcz5iKXRocm93IEgu
+YihQLnJyKGwsYSxzKSkKZm9yKDtxIT09NDQ7KXtDLk5tLmkoayxzKTsrK3MKZm9yKHA9LTE7czx0Oysr
+cyl7cT1DLnhCLlcoYSxzKQppZihxPT09NjEpe2lmKHA8MClwPXN9ZWxzZSBpZihxPT09NTl8fHE9PT00
+NClicmVha31pZihwPj0wKUMuTm0uaShrLHApCmVsc2V7bz1DLk5tLmdyWihrKQppZihxIT09NDR8fHMh
+PT1vKzd8fCFDLnhCLlFpKGEsImJhc2U2NCIsbysxKSl0aHJvdyBILmIoUC5ycigiRXhwZWN0aW5nICc9
+JyIsYSxzKSkKYnJlYWt9fUMuTm0uaShrLHMpCm49cysxCmlmKChrLmxlbmd0aCYxKT09PTEpYT1DLmg5
+LnlyKGEsbix0KQplbHNle209UC5VbChhLG4sdCxDLlZDLCEwKQppZihtIT1udWxsKWE9Qy54Qi5pNyhh
+LG4sdCxtKX1yZXR1cm4gbmV3IFAuUEUoYSxrLGMpfSwKS046ZnVuY3Rpb24oKXt2YXIgdD0iMDEyMzQ1
+Njc4OUFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXotLl9+
+ISQmJygpKissOz0iLHM9Ii4iLHI9IjoiLHE9Ii8iLHA9Ij8iLG89IiMiLG49UC5kSCgyMixuZXcgUC5x
+MygpLHUuZ2MpLG09bmV3IFAueUkobiksbD1uZXcgUC5jNigpLGs9bmV3IFAucWQoKSxqPW0uJDIoMCwy
+MjUpCmwuJDMoaix0LDEpCmwuJDMoaixzLDE0KQpsLiQzKGosciwzNCkKbC4kMyhqLHEsMykKbC4kMyhq
+LHAsMTcyKQpsLiQzKGosbywyMDUpCmo9bS4kMigxNCwyMjUpCmwuJDMoaix0LDEpCmwuJDMoaixzLDE1
+KQpsLiQzKGosciwzNCkKbC4kMyhqLHEsMjM0KQpsLiQzKGoscCwxNzIpCmwuJDMoaixvLDIwNSkKaj1t
+LiQyKDE1LDIyNSkKbC4kMyhqLHQsMSkKbC4kMyhqLCIlIiwyMjUpCmwuJDMoaixyLDM0KQpsLiQzKGos
+cSw5KQpsLiQzKGoscCwxNzIpCmwuJDMoaixvLDIwNSkKaj1tLiQyKDEsMjI1KQpsLiQzKGosdCwxKQps
+LiQzKGosciwzNCkKbC4kMyhqLHEsMTApCmwuJDMoaixwLDE3MikKbC4kMyhqLG8sMjA1KQpqPW0uJDIo
+MiwyMzUpCmwuJDMoaix0LDEzOSkKbC4kMyhqLHEsMTMxKQpsLiQzKGoscywxNDYpCmwuJDMoaixwLDE3
+MikKbC4kMyhqLG8sMjA1KQpqPW0uJDIoMywyMzUpCmwuJDMoaix0LDExKQpsLiQzKGoscSw2OCkKbC4k
+MyhqLHMsMTgpCmwuJDMoaixwLDE3MikKbC4kMyhqLG8sMjA1KQpqPW0uJDIoNCwyMjkpCmwuJDMoaix0
+LDUpCmsuJDMoaiwiQVoiLDIyOSkKbC4kMyhqLHIsMTAyKQpsLiQzKGosIkAiLDY4KQpsLiQzKGosIlsi
+LDIzMikKbC4kMyhqLHEsMTM4KQpsLiQzKGoscCwxNzIpCmwuJDMoaixvLDIwNSkKaj1tLiQyKDUsMjI5
+KQpsLiQzKGosdCw1KQprLiQzKGosIkFaIiwyMjkpCmwuJDMoaixyLDEwMikKbC4kMyhqLCJAIiw2OCkK
+bC4kMyhqLHEsMTM4KQpsLiQzKGoscCwxNzIpCmwuJDMoaixvLDIwNSkKaj1tLiQyKDYsMjMxKQprLiQz
+KGosIjE5Iiw3KQpsLiQzKGosIkAiLDY4KQpsLiQzKGoscSwxMzgpCmwuJDMoaixwLDE3MikKbC4kMyhq
+LG8sMjA1KQpqPW0uJDIoNywyMzEpCmsuJDMoaiwiMDkiLDcpCmwuJDMoaiwiQCIsNjgpCmwuJDMoaixx
+LDEzOCkKbC4kMyhqLHAsMTcyKQpsLiQzKGosbywyMDUpCmwuJDMobS4kMig4LDgpLCJdIiw1KQpqPW0u
+JDIoOSwyMzUpCmwuJDMoaix0LDExKQpsLiQzKGoscywxNikKbC4kMyhqLHEsMjM0KQpsLiQzKGoscCwx
+NzIpCmwuJDMoaixvLDIwNSkKaj1tLiQyKDE2LDIzNSkKbC4kMyhqLHQsMTEpCmwuJDMoaixzLDE3KQps
+LiQzKGoscSwyMzQpCmwuJDMoaixwLDE3MikKbC4kMyhqLG8sMjA1KQpqPW0uJDIoMTcsMjM1KQpsLiQz
+KGosdCwxMSkKbC4kMyhqLHEsOSkKbC4kMyhqLHAsMTcyKQpsLiQzKGosbywyMDUpCmo9bS4kMigxMCwy
+MzUpCmwuJDMoaix0LDExKQpsLiQzKGoscywxOCkKbC4kMyhqLHEsMjM0KQpsLiQzKGoscCwxNzIpCmwu
+JDMoaixvLDIwNSkKaj1tLiQyKDE4LDIzNSkKbC4kMyhqLHQsMTEpCmwuJDMoaixzLDE5KQpsLiQzKGos
+cSwyMzQpCmwuJDMoaixwLDE3MikKbC4kMyhqLG8sMjA1KQpqPW0uJDIoMTksMjM1KQpsLiQzKGosdCwx
+MSkKbC4kMyhqLHEsMjM0KQpsLiQzKGoscCwxNzIpCmwuJDMoaixvLDIwNSkKaj1tLiQyKDExLDIzNSkK
+bC4kMyhqLHQsMTEpCmwuJDMoaixxLDEwKQpsLiQzKGoscCwxNzIpCmwuJDMoaixvLDIwNSkKaj1tLiQy
+KDEyLDIzNikKbC4kMyhqLHQsMTIpCmwuJDMoaixwLDEyKQpsLiQzKGosbywyMDUpCmo9bS4kMigxMywy
+MzcpCmwuJDMoaix0LDEzKQpsLiQzKGoscCwxMykKay4kMyhtLiQyKDIwLDI0NSksImF6IiwyMSkKaj1t
+LiQyKDIxLDI0NSkKay4kMyhqLCJheiIsMjEpCmsuJDMoaiwiMDkiLDIxKQpsLiQzKGosIistLiIsMjEp
+CnJldHVybiBufSwKVUI6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgdCxzLHIscSxwLG89JC52WigpCmZv
+cih0PUouclkoYSkscz1iO3M8YzsrK3Mpe2lmKGQ8MHx8ZD49by5sZW5ndGgpcmV0dXJuIEguT0gobyxk
+KQpyPW9bZF0KcT10LlcoYSxzKV45NgppZihxPjk1KXE9MzEKaWYocT49ci5sZW5ndGgpcmV0dXJuIEgu
+T0gocixxKQpwPXJbcV0KZD1wJjMxCkMuTm0uWShlLHA+Pj41LHMpfXJldHVybiBkfSwKV0Y6ZnVuY3Rp
+b24gV0YoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCmEyOmZ1bmN0aW9uIGEyKCl7fSwKaVA6ZnVuY3Rp
+b24gaVAoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCkNQOmZ1bmN0aW9uIENQKCl7fSwKWFM6ZnVuY3Rp
+b24gWFMoKXt9LApDNjpmdW5jdGlvbiBDNihhKXt0aGlzLmE9YX0sCm46ZnVuY3Rpb24gbigpe30sCnU6
+ZnVuY3Rpb24gdShhLGIsYyxkKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8uZD1kfSwKYko6
+ZnVuY3Rpb24gYkooYSxiLGMsZCxlLGYpe3ZhciBfPXRoaXMKXy5lPWEKXy5mPWIKXy5hPWMKXy5iPWQK
+Xy5jPWUKXy5kPWZ9LAplWTpmdW5jdGlvbiBlWShhLGIsYyxkLGUpe3ZhciBfPXRoaXMKXy5mPWEKXy5h
+PWIKXy5iPWMKXy5jPWQKXy5kPWV9LAptcDpmdW5jdGlvbiBtcChhLGIsYyxkKXt2YXIgXz10aGlzCl8u
+YT1hCl8uYj1iCl8uYz1jCl8uZD1kfSwKdWI6ZnVuY3Rpb24gdWIoYSl7dGhpcy5hPWF9LApkczpmdW5j
+dGlvbiBkcyhhKXt0aGlzLmE9YX0sCmxqOmZ1bmN0aW9uIGxqKGEpe3RoaXMuYT1hfSwKVVY6ZnVuY3Rp
+b24gVVYoYSl7dGhpcy5hPWF9LAprNTpmdW5jdGlvbiBrNSgpe30sCktZOmZ1bmN0aW9uIEtZKCl7fSwK
+YzpmdW5jdGlvbiBjKGEpe3RoaXMuYT1hfSwKQ0Q6ZnVuY3Rpb24gQ0QoYSl7dGhpcy5hPWF9LAphRTpm
 dW5jdGlvbiBhRShhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApFSDpmdW5jdGlvbiBF
 SCgpe30sCklmOmZ1bmN0aW9uIElmKCl7fSwKY1g6ZnVuY3Rpb24gY1goKXt9LApBbjpmdW5jdGlvbiBB
 bigpe30sCnpNOmZ1bmN0aW9uIHpNKCl7fSwKWjA6ZnVuY3Rpb24gWjAoKXt9LApOMzpmdW5jdGlvbiBO
@@ -2065,2596 +8987,2596 @@
 OmZ1bmN0aW9uIGNTKGEpe3RoaXMuYT1hfSwKVkM6ZnVuY3Rpb24gVkMoYSl7dGhpcy5hPWF9LApKVDpm
 dW5jdGlvbiBKVChhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKRG46ZnVuY3Rpb24gRG4oYSxiLGMsZCxl
 LGYsZyl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9ZApfLmU9ZQpfLmY9ZgpfLnI9Zwpf
-LlE9Xy56PV8ueT1fLng9bnVsbH0sCmUxOmZ1bmN0aW9uIGUxKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9
-LApOWTpmdW5jdGlvbiBOWShhKXt0aGlzLmE9YX0sClJaOmZ1bmN0aW9uIFJaKCl7fSwKTUU6ZnVuY3Rp
-b24gTUUoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCnk1OmZ1bmN0aW9uIHk1KGEpe3RoaXMuYT1hfSwK
-UEU6ZnVuY3Rpb24gUEUoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKcTM6ZnVuY3Rp
-b24gcTMoKXt9LAp5STpmdW5jdGlvbiB5SShhKXt0aGlzLmE9YX0sCmM2OmZ1bmN0aW9uIGM2KCl7fSwK
-cWQ6ZnVuY3Rpb24gcWQoKXt9LApVZjpmdW5jdGlvbiBVZihhLGIsYyxkLGUsZixnLGgpe3ZhciBfPXRo
-aXMKXy5hPWEKXy5iPWIKXy5jPWMKXy5kPWQKXy5lPWUKXy5mPWYKXy5yPWcKXy54PWgKXy55PW51bGx9
-LApxZTpmdW5jdGlvbiBxZShhLGIsYyxkLGUsZixnKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1j
-Cl8uZD1kCl8uZT1lCl8uZj1mCl8ucj1nCl8uUT1fLno9Xy55PV8ueD1udWxsfSwKaUo6ZnVuY3Rpb24g
-aUooKXt9LApqZzpmdW5jdGlvbiBqZyhhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKVGE6ZnVuY3Rpb24g
-VGEoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCkJmOmZ1bmN0aW9uIEJmKGEsYil7dGhpcy5hPWEKdGhp
-cy5iPWJ9LApBczpmdW5jdGlvbiBBcygpe30sCkdFOmZ1bmN0aW9uIEdFKGEpe3RoaXMuYT1hfSwKTjc6
-ZnVuY3Rpb24gTjcoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCnVROmZ1bmN0aW9uIHVRKCl7fSwKaEY6
-ZnVuY3Rpb24gaEYoKXt9LApSNDpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzLHIKSC5FOShiKQp1Lmou
-YShkKQppZihILm9UKGIpKXt0PVtjXQpDLk5tLkZWKHQsZCkKZD10fXM9dS56CnI9UC5DSChKLk0xKGQs
-UC53MCgpLHMpLCEwLHMpCnUuWi5hKGEpCnJldHVybiBQLndZKEguRWsoYSxyLG51bGwpKX0sCkRtOmZ1
-bmN0aW9uKGEsYixjKXt2YXIgdAp0cnl7aWYoT2JqZWN0LmlzRXh0ZW5zaWJsZShhKSYmIU9iamVjdC5w
-cm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChhLGIpKXtPYmplY3QuZGVmaW5lUHJvcGVydHkoYSxi
-LHt2YWx1ZTpjfSkKcmV0dXJuITB9fWNhdGNoKHQpe0guUnUodCl9cmV0dXJuITF9LApPbTpmdW5jdGlv
-bihhLGIpe2lmKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChhLGIpKXJldHVybiBh
-W2JdCnJldHVybiBudWxsfSwKd1k6ZnVuY3Rpb24oYSl7aWYoYT09bnVsbHx8dHlwZW9mIGE9PSJzdHJp
-bmcifHx0eXBlb2YgYT09Im51bWJlciJ8fEguclEoYSkpcmV0dXJuIGEKaWYoYSBpbnN0YW5jZW9mIFAu
-RTQpcmV0dXJuIGEuYQppZihILlI5KGEpKXJldHVybiBhCmlmKHUudS5iKGEpKXJldHVybiBhCmlmKGEg
-aW5zdGFuY2VvZiBQLmlQKXJldHVybiBILm8yKGEpCmlmKHUuWi5iKGEpKXJldHVybiBQLmhFKGEsIiRk
-YXJ0X2pzRnVuY3Rpb24iLG5ldyBQLlBDKCkpCnJldHVybiBQLmhFKGEsIl8kZGFydF9qc09iamVjdCIs
-bmV3IFAubXQoJC5rSSgpKSl9LApoRTpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9UC5PbShhLGIpCmlmKHQ9
-PW51bGwpe3Q9Yy4kMShhKQpQLkRtKGEsYix0KX1yZXR1cm4gdH0sCkw3OmZ1bmN0aW9uKGEpe3ZhciB0
-LHMKaWYoYT09bnVsbHx8dHlwZW9mIGE9PSJzdHJpbmcifHx0eXBlb2YgYT09Im51bWJlciJ8fHR5cGVv
-ZiBhPT0iYm9vbGVhbiIpcmV0dXJuIGEKZWxzZSBpZihhIGluc3RhbmNlb2YgT2JqZWN0JiZILlI5KGEp
-KXJldHVybiBhCmVsc2UgaWYoYSBpbnN0YW5jZW9mIE9iamVjdCYmdS51LmIoYSkpcmV0dXJuIGEKZWxz
-ZSBpZihhIGluc3RhbmNlb2YgRGF0ZSl7dD1ILldZKGEuZ2V0VGltZSgpKQppZihNYXRoLmFicyh0KTw9
-ODY0ZTEzKXM9ITEKZWxzZSBzPSEwCmlmKHMpSC52aChQLnhZKCJEYXRlVGltZSBpcyBvdXRzaWRlIHZh
-bGlkIHJhbmdlOiAiK3QpKQpQLlVJKCExLCJpc1V0YyIsdS55KQpyZXR1cm4gbmV3IFAuaVAodCwhMSl9
-ZWxzZSBpZihhLmNvbnN0cnVjdG9yPT09JC5rSSgpKXJldHVybiBhLm8KZWxzZSByZXR1cm4gUC5ORChh
-KX0sCk5EOmZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBhPT0iZnVuY3Rpb24iKXJldHVybiBQLmlRKGEsJC53
-USgpLG5ldyBQLk56KCkpCmlmKGEgaW5zdGFuY2VvZiBBcnJheSlyZXR1cm4gUC5pUShhLCQuQ3IoKSxu
-ZXcgUC5RUygpKQpyZXR1cm4gUC5pUShhLCQuQ3IoKSxuZXcgUC5ucCgpKX0sCmlROmZ1bmN0aW9uKGEs
-YixjKXt2YXIgdD1QLk9tKGEsYikKaWYodD09bnVsbHx8IShhIGluc3RhbmNlb2YgT2JqZWN0KSl7dD1j
-LiQxKGEpClAuRG0oYSxiLHQpfXJldHVybiB0fSwKUEM6ZnVuY3Rpb24gUEMoKXt9LAptdDpmdW5jdGlv
-biBtdChhKXt0aGlzLmE9YX0sCk56OmZ1bmN0aW9uIE56KCl7fSwKUVM6ZnVuY3Rpb24gUVMoKXt9LApu
-cDpmdW5jdGlvbiBucCgpe30sCkU0OmZ1bmN0aW9uIEU0KGEpe3RoaXMuYT1hfSwKcjc6ZnVuY3Rpb24g
-cjcoYSl7dGhpcy5hPWF9LApUejpmdW5jdGlvbiBUeihhLGIpe3RoaXMuYT1hCnRoaXMuJHRpPWJ9LApj
-bzpmdW5jdGlvbiBjbygpe30sCm5kOmZ1bmN0aW9uIG5kKCl7fSwKS2U6ZnVuY3Rpb24gS2UoYSl7dGhp
-cy5hPWF9LApkNTpmdW5jdGlvbiBkNSgpe30sCm42OmZ1bmN0aW9uIG42KCl7fX0sVz17CngzOmZ1bmN0
-aW9uKCl7cmV0dXJuIHdpbmRvd30sClpyOmZ1bmN0aW9uKCl7cmV0dXJuIGRvY3VtZW50fSwKSjY6ZnVu
-Y3Rpb24oYSl7dmFyIHQ9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgiYSIpCmlmKGEhPW51bGwpdC5ocmVm
-PWEKcmV0dXJuIHR9LApVOTpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9ZG9jdW1lbnQuYm9keSxzPSh0JiZD
-LlJZKS5yNih0LGEsYixjKQpzLnRvU3RyaW5nCnQ9dS5hYwp0PW5ldyBILlU1KG5ldyBXLmU3KHMpLHQu
-QygiYTIobEQuRSkiKS5hKG5ldyBXLkN2KCkpLHQuQygiVTU8bEQuRT4iKSkKcmV0dXJuIHUuaC5hKHQu
-Z3I4KHQpKX0sCnJTOmZ1bmN0aW9uKGEpe3ZhciB0LHMscj0iZWxlbWVudCB0YWcgdW5hdmFpbGFibGUi
-CnRyeXt0PUouUkUoYSkKaWYodHlwZW9mIHQuZ25zKGEpPT0ic3RyaW5nIilyPXQuZ25zKGEpfWNhdGNo
-KHMpe0guUnUocyl9cmV0dXJuIHJ9LApDMDpmdW5jdGlvbihhLGIpe2E9NTM2ODcwOTExJmErYgphPTUz
-Njg3MDkxMSZhKygoNTI0Mjg3JmEpPDwxMCkKcmV0dXJuIGFeYT4+PjZ9LApyRTpmdW5jdGlvbihhLGIs
-YyxkKXt2YXIgdD1XLkMwKFcuQzAoVy5DMChXLkMwKDAsYSksYiksYyksZCkscz01MzY4NzA5MTEmdCso
-KDY3MTA4ODYzJnQpPDwzKQpzXj1zPj4+MTEKcmV0dXJuIDUzNjg3MDkxMSZzKygoMTYzODMmcyk8PDE1
-KX0sClROOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyPWEuY2xhc3NMaXN0CmZvcih0PWIubGVuZ3RoLHM9
-MDtzPGIubGVuZ3RoO2IubGVuZ3RoPT09dHx8KDAsSC5saykoYiksKytzKXIuYWRkKGJbc10pfSwKSkU6
-ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgdD1XLmFGKG5ldyBXLnZOKGMpLHUuQikKaWYodCE9bnVsbCYm
-ITApSi5kWihhLGIsdCwhMSkKcmV0dXJuIG5ldyBXLnhDKGEsYix0LCExLGUuQygieEM8MD4iKSl9LApU
-dzpmdW5jdGlvbihhKXt2YXIgdD1XLko2KG51bGwpLHM9d2luZG93LmxvY2F0aW9uCnQ9bmV3IFcuSlEo
-bmV3IFcubWsodCxzKSkKdC5DWShhKQpyZXR1cm4gdH0sCnFEOmZ1bmN0aW9uKGEsYixjLGQpe3UuaC5h
-KGEpCkguYyhiKQpILmMoYykKdS5PLmEoZCkKcmV0dXJuITB9LApRVzpmdW5jdGlvbihhLGIsYyxkKXt2
-YXIgdCxzLHIKdS5oLmEoYSkKSC5jKGIpCkguYyhjKQp0PXUuTy5hKGQpLmEKcz10LmEKcy5ocmVmPWMK
-cj1zLmhvc3RuYW1lCnQ9dC5iCmlmKCEocj09dC5ob3N0bmFtZSYmcy5wb3J0PT10LnBvcnQmJnMucHJv
-dG9jb2w9PXQucHJvdG9jb2wpKWlmKHI9PT0iIilpZihzLnBvcnQ9PT0iIil7dD1zLnByb3RvY29sCnQ9
-dD09PSI6Inx8dD09PSIifWVsc2UgdD0hMQplbHNlIHQ9ITEKZWxzZSB0PSEwCnJldHVybiB0fSwKQmw6
-ZnVuY3Rpb24oKXt2YXIgdD11Lk4scz1QLnRNKEMuUXgsdCkscj11LmRHLmEobmV3IFcuSUEoKSkscT1I
-LlZNKFsiVEVNUExBVEUiXSx1LnMpCnQ9bmV3IFcuY3QocyxQLkxzKHQpLFAuTHModCksUC5Mcyh0KSxu
-dWxsKQp0LkNZKG51bGwsbmV3IEgubEooQy5ReCxyLHUuZHYpLHEsbnVsbCkKcmV0dXJuIHR9LApQdjpm
-dW5jdGlvbihhKXtpZihhPT1udWxsKXJldHVybiBudWxsCnJldHVybiBXLlAxKGEpfSwKcWM6ZnVuY3Rp
-b24oYSl7dmFyIHQKaWYoYT09bnVsbClyZXR1cm4gbnVsbAppZigicG9zdE1lc3NhZ2UiIGluIGEpe3Q9
-Vy5QMShhKQppZih1LnIuYih0KSlyZXR1cm4gdApyZXR1cm4gbnVsbH1lbHNlIHJldHVybiB1LnIuYShh
-KX0sClAxOmZ1bmN0aW9uKGEpe2lmKGE9PT13aW5kb3cpcmV0dXJuIHUuY2kuYShhKQplbHNlIHJldHVy
-biBuZXcgVy5kVyhhKX0sCkhIOmZ1bmN0aW9uKGEpe2lmKGE9PT13aW5kb3cubG9jYXRpb24pcmV0dXJu
-IGEKZWxzZSByZXR1cm4gbmV3IFcuRmIoKX0sCmFGOmZ1bmN0aW9uKGEsYil7dmFyIHQ9JC5YMwppZih0
-PT09Qy5OVSlyZXR1cm4gYQpyZXR1cm4gdC5QeShhLGIpfSwKcUU6ZnVuY3Rpb24gcUUoKXt9LApHaDpm
-dW5jdGlvbiBHaCgpe30sCmZZOmZ1bmN0aW9uIGZZKCl7fSwKbkI6ZnVuY3Rpb24gbkIoKXt9LApBejpm
-dW5jdGlvbiBBeigpe30sClFQOmZ1bmN0aW9uIFFQKCl7fSwKbng6ZnVuY3Rpb24gbngoKXt9LApvSjpm
-dW5jdGlvbiBvSigpe30sCmlkOmZ1bmN0aW9uIGlkKCl7fSwKUUY6ZnVuY3Rpb24gUUYoKXt9LApOaDpm
-dW5jdGlvbiBOaCgpe30sCklCOmZ1bmN0aW9uIElCKCl7fSwKbjc6ZnVuY3Rpb24gbjcoKXt9LAp3ejpm
-dW5jdGlvbiB3eihhLGIpe3RoaXMuYT1hCnRoaXMuJHRpPWJ9LApjdjpmdW5jdGlvbiBjdigpe30sCkN2
-OmZ1bmN0aW9uIEN2KCl7fSwKZWE6ZnVuY3Rpb24gZWEoKXt9LApEMDpmdW5jdGlvbiBEMCgpe30sCmhI
-OmZ1bmN0aW9uIGhIKCl7fSwKaDQ6ZnVuY3Rpb24gaDQoKXt9LApicjpmdW5jdGlvbiBicigpe30sClZi
-OmZ1bmN0aW9uIFZiKCl7fSwKZko6ZnVuY3Rpb24gZkooKXt9LAp3YTpmdW5jdGlvbiB3YSgpe30sClNn
-OmZ1bmN0aW9uIFNnKCl7fSwKdTg6ZnVuY3Rpb24gdTgoKXt9LApPSzpmdW5jdGlvbiBPSygpe30sCmU3
-OmZ1bmN0aW9uIGU3KGEpe3RoaXMuYT1hfSwKdUg6ZnVuY3Rpb24gdUgoKXt9LApCSDpmdW5jdGlvbiBC
-SCgpe30sClNOOmZ1bmN0aW9uIFNOKCl7fSwKZXc6ZnVuY3Rpb24gZXcoKXt9LApscDpmdW5jdGlvbiBs
-cCgpe30sClRiOmZ1bmN0aW9uIFRiKCl7fSwKSXY6ZnVuY3Rpb24gSXYoKXt9LApXUDpmdW5jdGlvbiBX
-UCgpe30sCnlZOmZ1bmN0aW9uIHlZKCl7fSwKdzY6ZnVuY3Rpb24gdzYoKXt9LApLNTpmdW5jdGlvbiBL
-NSgpe30sCkNtOmZ1bmN0aW9uIENtKCl7fSwKQ1E6ZnVuY3Rpb24gQ1EoKXt9LAp3NDpmdW5jdGlvbiB3
-NCgpe30sCnJoOmZ1bmN0aW9uIHJoKCl7fSwKY2Y6ZnVuY3Rpb24gY2YoKXt9LAppNzpmdW5jdGlvbiBp
-NyhhKXt0aGlzLmE9YX0sClN5OmZ1bmN0aW9uIFN5KGEpe3RoaXMuYT1hfSwKS1M6ZnVuY3Rpb24gS1Mo
-YSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCkEzOmZ1bmN0aW9uIEEzKGEsYil7dGhpcy5hPWEKdGhpcy5i
-PWJ9LApJNDpmdW5jdGlvbiBJNChhKXt0aGlzLmE9YX0sCkZrOmZ1bmN0aW9uIEZrKGEsYil7dGhpcy5h
-PWEKdGhpcy4kdGk9Yn0sClJPOmZ1bmN0aW9uIFJPKGEsYixjLGQpe3ZhciBfPXRoaXMKXy5hPWEKXy5i
-PWIKXy5jPWMKXy4kdGk9ZH0sCmV1OmZ1bmN0aW9uIGV1KGEsYixjLGQpe3ZhciBfPXRoaXMKXy5hPWEK
-Xy5iPWIKXy5jPWMKXy4kdGk9ZH0sCnhDOmZ1bmN0aW9uIHhDKGEsYixjLGQsZSl7dmFyIF89dGhpcwpf
-LmI9YQpfLmM9YgpfLmQ9YwpfLmU9ZApfLiR0aT1lfSwKdk46ZnVuY3Rpb24gdk4oYSl7dGhpcy5hPWF9
-LApKUTpmdW5jdGlvbiBKUShhKXt0aGlzLmE9YX0sCkdtOmZ1bmN0aW9uIEdtKCl7fSwKdkQ6ZnVuY3Rp
-b24gdkQoYSl7dGhpcy5hPWF9LApVdjpmdW5jdGlvbiBVdihhKXt0aGlzLmE9YX0sCkVnOmZ1bmN0aW9u
-IEVnKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sCm02OmZ1bmN0aW9uIG02KCl7fSwK
-RW86ZnVuY3Rpb24gRW8oKXt9LApXazpmdW5jdGlvbiBXaygpe30sCmN0OmZ1bmN0aW9uIGN0KGEsYixj
-LGQsZSl7dmFyIF89dGhpcwpfLmU9YQpfLmE9YgpfLmI9YwpfLmM9ZApfLmQ9ZX0sCklBOmZ1bmN0aW9u
-IElBKCl7fSwKT3c6ZnVuY3Rpb24gT3coKXt9LApXOTpmdW5jdGlvbiBXOShhLGIsYyl7dmFyIF89dGhp
-cwpfLmE9YQpfLmI9YgpfLmM9LTEKXy5kPW51bGwKXy4kdGk9Y30sCmRXOmZ1bmN0aW9uIGRXKGEpe3Ro
-aXMuYT1hfSwKRmI6ZnVuY3Rpb24gRmIoKXt9LAprRjpmdW5jdGlvbiBrRigpe30sCm1rOmZ1bmN0aW9u
-IG1rKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApLbzpmdW5jdGlvbiBLbyhhKXt0aGlzLmE9YQp0aGlz
-LmI9ITF9LApmbTpmdW5jdGlvbiBmbShhKXt0aGlzLmE9YX0sCkxlOmZ1bmN0aW9uIExlKCl7fSwKSzc6
-ZnVuY3Rpb24gSzcoKXt9LApyQjpmdW5jdGlvbiByQigpe30sClhXOmZ1bmN0aW9uIFhXKCl7fSwKb2E6
-ZnVuY3Rpb24gb2EoKXt9fSxNPXsKT1g6ZnVuY3Rpb24oYSl7c3dpdGNoKGEpe2Nhc2UgQy5BZDpyZXR1
-cm4iQWRkIC8qPyovIGhpbnQiCmNhc2UgQy5uZTpyZXR1cm4iQWRkIC8qISovIGhpbnQiCmNhc2UgQy53
-VjpyZXR1cm4iUmVtb3ZlIC8qPyovIGhpbnQiCmNhc2UgQy5mUjpyZXR1cm4iUmVtb3ZlIC8qISovIGhp
-bnQiCmNhc2UgQy5teTpyZXR1cm4iQ2hhbmdlIHRvIC8qPyovIGhpbnQiCmNhc2UgQy5yeDpyZXR1cm4i
-Q2hhbmdlIHRvIC8qISovIGhpbnQifXJldHVybiBudWxsfSwKSDc6ZnVuY3Rpb24gSDcoYSxiKXt0aGlz
-LmE9YQp0aGlzLmI9Yn0sCllGOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEscCxvLG4KZm9yKHQ9Yi5s
-ZW5ndGgscz0xO3M8dDsrK3Mpe2lmKGJbc109PW51bGx8fGJbcy0xXSE9bnVsbCljb250aW51ZQpmb3Io
-O3Q+PTE7dD1yKXtyPXQtMQppZihiW3JdIT1udWxsKWJyZWFrfXE9bmV3IFAuUm4oIiIpCnA9YSsiKCIK
-cS5hPXAKbz1ILnFDKGIsMCx0LEgudDYoYikuYykKbj1vLiR0aQpuPXArbmV3IEgubEoobyxuLkMoInFV
-KGFMLkUpIikuYShuZXcgTS5ObygpKSxuLkMoImxKPGFMLkUscVU+IikpLkgoMCwiLCAiKQpxLmE9bgpx
-LmE9bisoIik6IHBhcnQgIisocy0xKSsiIHdhcyBudWxsLCBidXQgcGFydCAiK3MrIiB3YXMgbm90LiIp
-CnRocm93IEguYihQLnhZKHEuWigwKSkpfX0sCmxJOmZ1bmN0aW9uIGxJKGEpe3RoaXMuYT1hfSwKTWk6
-ZnVuY3Rpb24gTWkoKXt9LApxNzpmdW5jdGlvbiBxNygpe30sCk5vOmZ1bmN0aW9uIE5vKCl7fX0sVT17
-Cm56OmZ1bmN0aW9uKGEpe3ZhciB0PUguV1koYS5xKDAsIm5vZGVJZCIpKQpyZXR1cm4gbmV3IFUuTEwo
-Qy5ObS5IdChDLnJrLG5ldyBVLk1EKGEpKSx0KX0sCkxMOmZ1bmN0aW9uIExMKGEsYil7dGhpcy5hPWEK
-dGhpcy5iPWJ9LApNRDpmdW5jdGlvbiBNRChhKXt0aGlzLmE9YX0sCmpmOmZ1bmN0aW9uKGEpe3ZhciB0
-LHMscixxCmlmKGE9PW51bGwpdD1udWxsCmVsc2V7dD1ILlZNKFtdLHUuZkEpCmZvcihzPUouSVQodS5S
-LmEoYSkpO3MuRigpOyl7cj1zLmdsKCkKcT1KLlU2KHIpCkMuTm0uaSh0LG5ldyBVLlNlKEguYyhxLnEo
-ciwiZGVzY3JpcHRpb24iKSksSC5jKHEucShyLCJocmVmIikpKSl9fXJldHVybiB0fSwKTmQ6ZnVuY3Rp
-b24oYSl7dmFyIHQscwppZihhPT1udWxsKXQ9bnVsbAplbHNle3Q9SC5WTShbXSx1LmhoKQpmb3Iocz1K
-LklUKHUuUi5hKGEpKTtzLkYoKTspQy5ObS5pKHQsVS5KaihzLmdsKCkpKX1yZXR1cm4gdH0sCkpqOmZ1
-bmN0aW9uKGEpe3ZhciB0PUouVTYoYSkscz1ILmModC5xKGEsImRlc2NyaXB0aW9uIikpLHI9SC5WTShb
-XSx1LmFKKQpmb3IodD1KLklUKHUuUi5hKHQucShhLCJlbnRyaWVzIikpKTt0LkYoKTspQy5ObS5pKHIs
-VS5Saih0LmdsKCkpKQpyZXR1cm4gbmV3IFUueUQocyxyKX0sClJqOmZ1bmN0aW9uKGEpe3ZhciB0LHM9
-Si5VNihhKSxyPUguYyhzLnEoYSwiZGVzY3JpcHRpb24iKSkscT1ILmMocy5xKGEsImZ1bmN0aW9uIikp
-LHA9cy5xKGEsImxpbmsiKQppZihwPT1udWxsKXA9bnVsbAplbHNle3Q9Si5VNihwKQpwPW5ldyBVLk1s
-KEguYyh0LnEocCwiaHJlZiIpKSxILldZKHQucShwLCJsaW5lIikpLEguYyh0LnEocCwicGF0aCIpKSl9
-cz11LmouYShzLnEoYSwiaGludEFjdGlvbnMiKSkKcz1zPT1udWxsP251bGw6Si5NMShzLG5ldyBVLmFO
-KCksdS5FKQpzPXM9PW51bGw/bnVsbDpzLmJyKDApCnJldHVybiBuZXcgVS53YihyLHEscCxzPT1udWxs
-P0MuZG46cyl9LApkMjpmdW5jdGlvbiBkMihhLGIsYyxkLGUsZil7dmFyIF89dGhpcwpfLmE9YQpfLmI9
-YgpfLmM9YwpfLmQ9ZApfLmU9ZQpfLmY9Zn0sClNlOmZ1bmN0aW9uIFNlKGEsYil7dGhpcy5hPWEKdGhp
-cy5iPWJ9LApNbDpmdW5jdGlvbiBNbChhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LAp5
-RDpmdW5jdGlvbiB5RChhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKd2I6ZnVuY3Rpb24gd2IoYSxiLGMs
-ZCl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9YwpfLmQ9ZH0sCmFOOmZ1bmN0aW9uIGFOKCl7fSwK
-YjA6ZnVuY3Rpb24gYjAoKXt9fSxCPXsKWWY6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscCxvLG4sbSxs
-PUguYyhhLnEoMCwicmVnaW9ucyIpKSxrPUguYyhhLnEoMCwibmF2aWdhdGlvbkNvbnRlbnQiKSksaj1I
-LmMoYS5xKDAsInNvdXJjZUNvZGUiKSksaT1QLkZsKHUuTix1LmY0KQpmb3IodD11LlMuYShhLnEoMCwi
-ZWRpdHMiKSksdD10LmdQdSh0KSx0PXQuZ2t6KHQpLHM9dS5SLHI9dS5naTt0LkYoKTspe3E9dC5nbCgp
-CnA9cS5hCm89SC5WTShbXSxyKQpmb3IocT1KLklUKHMuYShxLmIpKTtxLkYoKTspe249cS5nbCgpCm09
-Si5VNihuKQpDLk5tLmkobyxuZXcgQi5qOChILldZKG0ucShuLCJsaW5lIikpLEguYyhtLnEobiwiZXhw
-bGFuYXRpb24iKSksSC5XWShtLnEobiwib2Zmc2V0IikpKSl9aS5ZKDAscCxvKX1yZXR1cm4gbmV3IEIu
-cXAobCxrLGosaSl9LApqODpmdW5jdGlvbiBqOChhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5j
-PWN9LApxcDpmdW5jdGlvbiBxcChhLGIsYyxkKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8u
-ZD1kfSwKZnY6ZnVuY3Rpb24gZnYoKXt9LApPUzpmdW5jdGlvbihhKXt2YXIgdAppZighKGE+PTY1JiZh
-PD05MCkpdD1hPj05NyYmYTw9MTIyCmVsc2UgdD0hMApyZXR1cm4gdH0sCll1OmZ1bmN0aW9uKGEsYil7
-dmFyIHQ9YS5sZW5ndGgscz1iKzIKaWYodDxzKXJldHVybiExCmlmKCFCLk9TKEMueEIubShhLGIpKSly
-ZXR1cm4hMQppZihDLnhCLm0oYSxiKzEpIT09NTgpcmV0dXJuITEKaWYodD09PXMpcmV0dXJuITAKcmV0
-dXJuIEMueEIubShhLHMpPT09NDd9fSxUPXttUTpmdW5jdGlvbiBtUSgpe319LEw9ewpJcTpmdW5jdGlv
-bigpe0MuQlouQihkb2N1bWVudCwiRE9NQ29udGVudExvYWRlZCIsbmV3IEwuZSgpKQpDLm9sLkIod2lu
-ZG93LCJwb3BzdGF0ZSIsbmV3IEwuTCgpKX0sCmt6OmZ1bmN0aW9uKGEpe3ZhciB0LHM9dS5oLmEoYS5w
-YXJlbnROb2RlKS5xdWVyeVNlbGVjdG9yKCI6c2NvcGUgPiB1bCIpLHI9cy5zdHlsZSxxPSIiK0MuQ0Qu
-elEocy5vZmZzZXRIZWlnaHQpKjIrInB4IgpyLm1heEhlaWdodD1xCnI9Si5xRihhKQpxPXIuJHRpCnQ9
-cS5DKCJ+KDEpIikuYShuZXcgTC5XeChzLGEpKQp1Lk0uYShudWxsKQpXLkpFKHIuYSxyLmIsdCwhMSxx
-LmMpfSwKeVg6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxwLG89InF1ZXJ5U2VsZWN0b3JBbGwiLG49
-ZG9jdW1lbnQucXVlcnlTZWxlY3RvcihhKSxtPXUuaApuLnRvU3RyaW5nCkguRGgobSxtLCJUIixvKQp0
-PXUuVApzPW5ldyBXLnd6KG4ucXVlcnlTZWxlY3RvckFsbCgiLm5hdi1saW5rIiksdCkKcy5LKHMsbmV3
-IEwuQU8oYikpCkguRGgobSxtLCJUIixvKQpyPW5ldyBXLnd6KG4ucXVlcnlTZWxlY3RvckFsbCgiLnJl
-Z2lvbiIpLHQpCmlmKHIuZ0EocikhPT0wKXtxPW4ucXVlcnlTZWxlY3RvcigidGFibGVbZGF0YS1wYXRo
-XSIpCnEudG9TdHJpbmcKci5LKHIsbmV3IEwuSG8ocS5nZXRBdHRyaWJ1dGUoImRhdGEtIituZXcgVy5T
-eShuZXcgVy5pNyhxKSkuTygicGF0aCIpKSkpfUguRGgobSxtLCJUIixvKQpwPW5ldyBXLnd6KG4ucXVl
-cnlTZWxlY3RvckFsbCgiLmFkZC1oaW50LWxpbmsiKSx0KQpwLksocCxuZXcgTC5JQygpKX0sClE2OmZ1
-bmN0aW9uKGEsYixjKXt2YXIgdD1uZXcgWE1MSHR0cFJlcXVlc3QoKQpDLkR0LmVvKHQsIkdFVCIsTC5R
-NChhLGIpLCEwKQp0LnNldFJlcXVlc3RIZWFkZXIoIkNvbnRlbnQtVHlwZSIsImFwcGxpY2F0aW9uL2pz
-b247IGNoYXJzZXQ9VVRGLTgiKQpyZXR1cm4gTC5MVSh0LG51bGwsYyl9LAp0eTpmdW5jdGlvbihhLGIp
-e3ZhciB0PW5ldyBYTUxIdHRwUmVxdWVzdCgpLHM9dS5OCkMuRHQuZW8odCwiUE9TVCIsTC5RNChhLFAu
-RmwocyxzKSksITApCnQuc2V0UmVxdWVzdEhlYWRlcigiQ29udGVudC1UeXBlIiwiYXBwbGljYXRpb24v
-anNvbjsgY2hhcnNldD1VVEYtOCIpCnJldHVybiBMLkxVKHQsYix1LlMpfSwKTFU6ZnVuY3Rpb24oYSxi
-LGMpe3JldHVybiBMLlRnKGEsYixjLGMpfSwKVGc6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQ9MCxzPVAu
-RlgoZCkscixxPTIscCxvPVtdLG4sbSxsLGssaixpLGgsZwp2YXIgJGFzeW5jJExVPVAubHooZnVuY3Rp
-b24oZSxmKXtpZihlPT09MSl7cD1mCnQ9cX13aGlsZSh0cnVlKXN3aXRjaCh0KXtjYXNlIDA6aj1uZXcg
-UC5aZihuZXcgUC52cygkLlgzLHUuYW8pLHUuYmopCmk9dS5hbgpoPWkuYShuZXcgTC5mQyhqLGEpKQp1
-Lk0uYShudWxsKQptPXUuRgpXLkpFKGEsImxvYWQiLGgsITEsbSkKVy5KRShhLCJlcnJvciIsaS5hKGou
-Z1lKKCkpLCExLG0pCmEuc2VuZChiPT1udWxsP251bGw6Qy5DdC5PQihiLG51bGwpKQpxPTQKdD03CnJl
-dHVybiBQLmpRKGouYSwkYXN5bmMkTFUpCmNhc2UgNzpxPTIKdD02CmJyZWFrCmNhc2UgNDpxPTMKZz1w
-CkguUnUoZykKbj1ILnRzKGcpCmk9UC5UbCgiRXJyb3IgcmVhY2hpbmcgbWlncmF0aW9uIHByZXZpZXcg
-c2VydmVyLiIsbikKdGhyb3cgSC5iKGkpCnQ9NgpicmVhawpjYXNlIDM6dD0yCmJyZWFrCmNhc2UgNjpr
-PUMuQ3QucFcoMCxhLnJlc3BvbnNlVGV4dCxudWxsKQppZihhLnN0YXR1cz09PTIwMCl7cj1jLmEoaykK
-dD0xCmJyZWFrfWVsc2UgdGhyb3cgSC5iKGspCmNhc2UgMTpyZXR1cm4gUC55QyhyLHMpCmNhc2UgMjpy
-ZXR1cm4gUC5mMyhwLHMpfX0pCnJldHVybiBQLkRJKCRhc3luYyRMVSxzKX0sCmFLOmZ1bmN0aW9uKGEp
-e3ZhciB0PVAuaEsoYSkuZ2hZKCkucSgwLCJsaW5lIikKcmV0dXJuIHQ9PW51bGw/bnVsbDpILkhwKHQs
-bnVsbCl9LApHNjpmdW5jdGlvbihhKXt2YXIgdD1QLmhLKGEpLmdoWSgpLnEoMCwib2Zmc2V0IikKcmV0
-dXJuIHQ9PW51bGw/bnVsbDpILkhwKHQsbnVsbCl9LAppNjpmdW5jdGlvbihhKXtyZXR1cm4gTC5uVyh1
-LlYuYShhKSl9LApuVzpmdW5jdGlvbihhKXt2YXIgdD0wLHM9UC5GWCh1LnopLHI9MSxxLHA9W10sbyxu
-LG0sbCxrCnZhciAkYXN5bmMkaTY9UC5seihmdW5jdGlvbihiLGMpe2lmKGI9PT0xKXtxPWMKdD1yfXdo
-aWxlKHRydWUpc3dpdGNoKHQpe2Nhc2UgMDpsPXUuaC5hKFcucWMoYS5jdXJyZW50VGFyZ2V0KSkuZ2V0
-QXR0cmlidXRlKCJocmVmIikKYS5wcmV2ZW50RGVmYXVsdCgpCnI9Mwp0PTYKcmV0dXJuIFAualEoTC50
-eShsLG51bGwpLCRhc3luYyRpNikKY2FzZSA2OnUuYV8uYShKLkdyKFcuUHYoZG9jdW1lbnQuZGVmYXVs
-dFZpZXcpKSkucmVsb2FkKCkKcj0xCnQ9NQpicmVhawpjYXNlIDM6cj0yCms9cQpvPUguUnUoaykKbj1I
-LnRzKGspCkwuQzIoIkNvdWxkIG5vdCBhZGQvcmVtb3ZlIGhpbnQiLG8sbikKdD01CmJyZWFrCmNhc2Ug
-Mjp0PTEKYnJlYWsKY2FzZSA1OnJldHVybiBQLnlDKG51bGwscykKY2FzZSAxOnJldHVybiBQLmYzKHEs
-cyl9fSkKcmV0dXJuIFAuREkoJGFzeW5jJGk2LHMpfSwKQzI6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMs
-cj0iZXhjZXB0aW9uIixxPSJzdGFja1RyYWNlIixwPXUuUy5iKGIpJiZKLlJNKGIucSgwLCJzdWNjZXNz
-IiksITEpJiZILm9UKGIueDQocikpJiZILm9UKGIueDQocSkpLG89Si5pYShiKQppZihwKXt0PUguYyhv
-LnEoYixyKSkKYz1vLnEoYixxKX1lbHNlIHQ9by5aKGIpCnA9ZG9jdW1lbnQKcz1wLnF1ZXJ5U2VsZWN0
-b3IoIi5wb3B1cC1wYW5lIikKcy5xdWVyeVNlbGVjdG9yKCJoMiIpLmlubmVyVGV4dD1hCnMucXVlcnlT
-ZWxlY3RvcigicCIpLmlubmVyVGV4dD10CnMucXVlcnlTZWxlY3RvcigicHJlIikuaW5uZXJUZXh0PUou
-QWMoYykKbz11Lk4KdS5icS5hKHMucXVlcnlTZWxlY3RvcigiYS5ib3R0b20iKSkuaHJlZj1QLlhkKCJo
-dHRwcyIsImdpdGh1Yi5jb20iLCJkYXJ0LWxhbmcvc2RrL2lzc3Vlcy9uZXciLFAuRUYoWyJ0aXRsZSIs
-IkN1c3RvbWVyLXJlcG9ydGVkIGlzc3VlIHdpdGggTk5CRCBtaWdyYXRpb24gdG9vbDogIithLCJsYWJl
-bHMiLCJhcmVhLWFuYWx5emVyLGFuYWx5emVyLW5uYmQtbWlncmF0aW9uLHR5cGUtYnVnIiwiYm9keSIs
-YSsiXG5cbkVycm9yOiAiK0guZCh0KSsiXG5cblBsZWFzZSBmaWxsIGluIHRoZSBmb2xsb3dpbmc6XG5c
-bioqTmFtZSBvZiBwYWNrYWdlIGJlaW5nIG1pZ3JhdGVkIChpZiBwdWJsaWMpKio6XG4qKldoYXQgSSB3
-YXMgZG9pbmcgd2hlbiB0aGlzIGlzc3VlIG9jY3VycmVkKio6XG4qKklzIGl0IHBvc3NpYmxlIHRvIHdv
-cmsgYXJvdW5kIHRoaXMgaXNzdWUqKjpcbioqSGFzIHRoaXMgaXNzdWUgaGFwcGVuZWQgYmVmb3JlLCBh
-bmQgaWYgc28sIGhvdyBvZnRlbioqOlxuKipEYXJ0IFNESyB2ZXJzaW9uKio6ICIrSC5kKHAuZ2V0RWxl
-bWVudEJ5SWQoInNkay12ZXJzaW9uIikudGV4dENvbnRlbnQpKyJcbioqQWRkaXRpb25hbCBkZXRhaWxz
-Kio6XG5cblRoYW5rcyBmb3IgZmlsaW5nIVxuXG5TdGFja3RyYWNlOiBfYXV0byBwb3B1bGF0ZWQgYnkg
-bWlncmF0aW9uIHByZXZpZXcgdG9vbC5fXG5cbmBgYFxuIitILmQoYykrIlxuYGBgXG4iXSxvLG8pKS5a
-KDApCm89cy5zdHlsZQpvLmRpc3BsYXk9ImluaXRpYWwiCnA9YSsiOiAiK0guZChiKQp3aW5kb3cKaWYo
-dHlwZW9mIGNvbnNvbGUhPSJ1bmRlZmluZWQiKXdpbmRvdy5jb25zb2xlLmVycm9yKHApCndpbmRvdwpw
-PUguZChjKQppZih0eXBlb2YgY29uc29sZSE9InVuZGVmaW5lZCIpd2luZG93LmNvbnNvbGUuZXJyb3Io
-cCl9LAp0MjpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHEscD17fSxvPXUuaC5hKFcucWMoYS5jdXJy
-ZW50VGFyZ2V0KSkKYS5wcmV2ZW50RGVmYXVsdCgpCnQ9cC5hPW8uZ2V0QXR0cmlidXRlKCJocmVmIikK
-cz1KLnpsKHQsIj8iKT9wLmE9Qy54Qi5Oaih0LDAsQy54Qi5PWSh0LCI/IikpOnQKcj1MLkc2KHQpCnE9
-TC5hSyh0KQppZihyIT1udWxsKUwuYWYocyxyLHEsYixuZXcgTC5uVChwLHIscSkpCmVsc2UgTC5hZihz
-LG51bGwsbnVsbCxiLG5ldyBMLkJaKHApKX0sCnZVOmZ1bmN0aW9uKCl7dmFyIHQ9ZG9jdW1lbnQscz11
-LmgKSC5EaChzLHMsIlQiLCJxdWVyeVNlbGVjdG9yQWxsIikKdD1uZXcgVy53eih0LnF1ZXJ5U2VsZWN0
-b3JBbGwoIi5jb2RlIiksdS5UKQp0LksodCxuZXcgTC5HSCgpKX0sCmhYOmZ1bmN0aW9uKGEsYixjKXty
-ZXR1cm4gTC5ZdyhhLGIsYyl9LApZdzpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9MCxzPVAuRlgodS56KSxy
-PTEscSxwPVtdLG8sbixtLGwsayxqLGksaAp2YXIgJGFzeW5jJGhYPVAubHooZnVuY3Rpb24oZCxlKXtp
-ZihkPT09MSl7cT1lCnQ9cn13aGlsZSh0cnVlKXN3aXRjaCh0KXtjYXNlIDA6cj0zCms9dS5OCnQ9Ngpy
-ZXR1cm4gUC5qUShMLlE2KGEsUC5FRihbInJlZ2lvbiIsInJlZ2lvbiIsIm9mZnNldCIsSC5kKGIpXSxr
-LGspLHUuUyksJGFzeW5jJGhYKQpjYXNlIDY6bz1lCms9bwpqPUouVTYoaykKbj1uZXcgVS5kMihVLmpm
-KGoucShrLCJlZGl0cyIpKSxILmMoai5xKGssImV4cGxhbmF0aW9uIikpLEguV1koai5xKGssImxpbmUi
-KSksSC5jKGoucShrLCJkaXNwbGF5UGF0aCIpKSxILmMoai5xKGssInVyaVBhdGgiKSksVS5OZChqLnEo
-aywidHJhY2VzIikpKQpMLlQxKG4pCkwuRnIoYSxiLGMpCkwueVgoIi5lZGl0LXBhbmVsIC5wYW5lbC1j
-b250ZW50IiwhMSkKcj0xCnQ9NQpicmVhawpjYXNlIDM6cj0yCmg9cQptPUguUnUoaCkKbD1ILnRzKGgp
-CkwuQzIoIkNvdWxkIG5vdCBsb2FkIGVkaXQgZGV0YWlscyIsbSxsKQp0PTUKYnJlYWsKY2FzZSAyOnQ9
-MQpicmVhawpjYXNlIDU6cmV0dXJuIFAueUMobnVsbCxzKQpjYXNlIDE6cmV0dXJuIFAuZjMocSxzKX19
-KQpyZXR1cm4gUC5ESSgkYXN5bmMkaFgscyl9LApHNzpmdW5jdGlvbihhLGIsYyxkLGUpe3JldHVybiBM
-Lkw1KGEsYixjLGQsZSl9LApMNTpmdW5jdGlvbihhLGIsYyxkLGUpe3ZhciB0PTAscz1QLkZYKHUueiks
-cixxPTIscCxvPVtdLG4sbSxsLGssaixpLGgKdmFyICRhc3luYyRHNz1QLmx6KGZ1bmN0aW9uKGYsZyl7
-aWYoZj09PTEpe3A9Zwp0PXF9d2hpbGUodHJ1ZSlzd2l0Y2godCl7Y2FzZSAwOmlmKCFKLnJZKGEpLlRj
-KGEsIi5kYXJ0Iikpe0wuQkUoYSxuZXcgQi5xcCgiIiwiIiwiIixDLkNNKSxkKQpMLkJYKGEsbnVsbCkK
-aWYoZSE9bnVsbCllLiQwKCkKdD0xCmJyZWFrfXE9NApqPXUuTgp0PTcKcmV0dXJuIFAualEoTC5RNihh
-LFAuRUYoWyJpbmxpbmUiLCJ0cnVlIl0saixqKSx1LlMpLCRhc3luYyRHNykKY2FzZSA3Om49ZwpMLkJF
-KGEsQi5ZZihuKSxkKQpMLmZHKGIsYykKbT1DLnhCLnRnKGEsIj8iKT9DLnhCLk5qKGEsMCxDLnhCLk9Z
-KGEsIj8iKSk6YQpMLkJYKG0sYikKaWYoZSE9bnVsbCllLiQwKCkKcT0yCnQ9NgpicmVhawpjYXNlIDQ6
-cT0zCmg9cApsPUguUnUoaCkKaz1ILnRzKGgpCkwuQzIoIkNvdWxkIG5vdCBsb2FkIGRhcnQgZmlsZSAi
-K2EsbCxrKQp0PTYKYnJlYWsKY2FzZSAzOnQ9MgpicmVhawpjYXNlIDY6Y2FzZSAxOnJldHVybiBQLnlD
-KHIscykKY2FzZSAyOnJldHVybiBQLmYzKHAscyl9fSkKcmV0dXJuIFAuREkoJGFzeW5jJEc3LHMpfSwK
-R2U6ZnVuY3Rpb24oKXt2YXIgdD0wLHM9UC5GWCh1LnopLHI9MSxxLHA9W10sbyxuLG0sbCxrLGosaQp2
-YXIgJGFzeW5jJEdlPVAubHooZnVuY3Rpb24oYSxiKXtpZihhPT09MSl7cT1iCnQ9cn13aGlsZSh0cnVl
-KXN3aXRjaCh0KXtjYXNlIDA6aj0iL19wcmV2aWV3L25hdmlnYXRpb25UcmVlLmpzb24iCnI9Mwp0PTYK
-cmV0dXJuIFAualEoTC5RNihqLEMuV08sdS5ldyksJGFzeW5jJEdlKQpjYXNlIDY6bz1iCm49ZG9jdW1l
-bnQucXVlcnlTZWxlY3RvcigiLm5hdi10cmVlIikKSi5sNShuLCIiKQpMLnRYKG4sTC5tSyhvKSkKcj0x
-CnQ9NQpicmVhawpjYXNlIDM6cj0yCmk9cQptPUguUnUoaSkKbD1ILnRzKGkpCkwuQzIoIkNvdWxkIG5v
-dCBsb2FkIG5hdmlnYXRpb24gdHJlZSIsbSxsKQp0PTUKYnJlYWsKY2FzZSAyOnQ9MQpicmVhawpjYXNl
-IDU6cmV0dXJuIFAueUMobnVsbCxzKQpjYXNlIDE6cmV0dXJuIFAuZjMocSxzKX19KQpyZXR1cm4gUC5E
-SSgkYXN5bmMkR2Uscyl9LApxTzpmdW5jdGlvbihhKXt2YXIgdCxzPWEuZ2V0Qm91bmRpbmdDbGllbnRS
-ZWN0KCkscj1DLkNELnpRKCQuZmkoKS5vZmZzZXRIZWlnaHQpLHE9d2luZG93LmlubmVySGVpZ2h0LHA9
-Qy5DRC56USgkLkRXKCkub2Zmc2V0SGVpZ2h0KQppZih0eXBlb2YgcSE9PSJudW1iZXIiKXJldHVybiBx
-LkhOKCkKdD1zLmJvdHRvbQppZih0eXBlb2YgdCE9PSJudW1iZXIiKXJldHVybiB0Lm9zKCkKaWYodD5x
-LShwKzE0KSlKLmRoKGEpCmVsc2V7cT1zLnRvcAppZih0eXBlb2YgcSE9PSJudW1iZXIiKXJldHVybiBx
-LkooKQppZihxPHIrMTQpSi5kaChhKX19LApmRzpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHAKaWYo
-YSE9bnVsbCl7dD1kb2N1bWVudApzPXQuZ2V0RWxlbWVudEJ5SWQoIm8iK0guZChhKSkKcj10LnF1ZXJ5
-U2VsZWN0b3IoIi5saW5lLSIrSC5kKGIpKQppZihzIT1udWxsKXtMLnFPKHMpCkouZFIocykuaSgwLCJ0
-YXJnZXQiKX1lbHNlIGlmKHIhPW51bGwpTC5xTyhyLnBhcmVudEVsZW1lbnQpCmlmKHIhPW51bGwpSi5k
-Uih1LmguYShyLnBhcmVudE5vZGUpKS5pKDAsImhpZ2hsaWdodCIpfWVsc2V7dD1kb2N1bWVudApxPXUu
-aApILkRoKHEscSwiVCIsInF1ZXJ5U2VsZWN0b3JBbGwiKQp0PXQucXVlcnlTZWxlY3RvckFsbCgiLmxp
-bmUtbm8iKQpwPW5ldyBXLnd6KHQsdS5UKQppZihwLmdBKHApPT09MClyZXR1cm4KTC5xTyhxLmEoQy50
-NS5ndEgodCkpKX19LAphZjpmdW5jdGlvbihhLGIsYyxkLGUpe3ZhciB0LHMscj1MLkc2KHdpbmRvdy5s
-b2NhdGlvbi5ocmVmKSxxPUwuYUsod2luZG93LmxvY2F0aW9uLmhyZWYpCmlmKHIhPW51bGwpe3Q9ZG9j
-dW1lbnQuZ2V0RWxlbWVudEJ5SWQoIm8iK0guZChyKSkKaWYodCE9bnVsbClKLmRSKHQpLlIoMCwidGFy
-Z2V0Iil9aWYocSE9bnVsbCl7cz1kb2N1bWVudC5xdWVyeVNlbGVjdG9yKCIubGluZS0iK0guZChxKSkK
-aWYocyE9bnVsbClKLmRSKHMucGFyZW50RWxlbWVudCkuUigwLCJoaWdobGlnaHQiKX1pZihhPT13aW5k
-b3cubG9jYXRpb24ucGF0aG5hbWUpe0wuZkcoYixjKQplLiQwKCl9ZWxzZSBMLkc3KGEsYixjLGQsZSl9
-LApRNDpmdW5jdGlvbihhLGIpe3ZhciB0LHMscj1QLmhLKGEpLHE9dS5OCnE9UC5GbChxLHEpCmZvcih0
-PXIuZ2hZKCksdD10LmdQdSh0KSx0PXQuZ2t6KHQpO3QuRigpOyl7cz10LmdsKCkKcS5ZKDAscy5hLHMu
-Yil9Zm9yKHQ9Yi5nUHUoYiksdD10Lmdreih0KTt0LkYoKTspe3M9dC5nbCgpCnEuWSgwLHMuYSxzLmIp
-fXEuWSgwLCJhdXRoVG9rZW4iLCQuVUUoKSkKcmV0dXJuIHIubm0oMCxxKS5aKDApfSwKVDE6ZnVuY3Rp
-b24oYSl7dmFyIHQscyxyLHEscCxvLG4sbSxsLGs9JC5oTCgpCkoubDUoaywiIikKaWYoYT09bnVsbCl7
-dD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCJwIikKdC50ZXh0Q29udGVudD0iU2VlIGRldGFpbHMgYWJv
-dXQgYSBwcm9wb3NlZCBlZGl0LiIKQy5MdC5zUCh0LEguVk0oWyJwbGFjZWhvbGRlciJdLHUucykpCmsu
-YXBwZW5kQ2hpbGQodCkKQy5MdC5GRih0KQpyZXR1cm59cz1hLmQKcj0kLm5VKCkKcT1yLnpmKHMpCnA9
-YS5iCm89ZG9jdW1lbnQKbj1yLkhQKHMsSi5UMChvLnF1ZXJ5U2VsZWN0b3IoIi5yb290IikudGV4dENv
-bnRlbnQpKQptPWEuYwpsPW8uY3JlYXRlRWxlbWVudCgicCIpCmsuYXBwZW5kQ2hpbGQobCkKbC5hcHBl
-bmRDaGlsZChvLmNyZWF0ZVRleHROb2RlKEguZChwKSsiIGF0ICIpKQpyPXUuTgpyPVcuSjYoTC5RNChh
-LmUsUC5FRihbImxpbmUiLEouQWMobSldLHIscikpKQpyLmFwcGVuZENoaWxkKG8uY3JlYXRlVGV4dE5v
-ZGUoSC5kKG4pKyI6IitILmQobSkrIi4iKSkKbC5hcHBlbmRDaGlsZChyKQpKLmRoKGwpCkwuQ0MoYSxr
-LHEpCkwuRnooYSxrKX0sCkxIOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsayxq
-LGksaCxnPSQueVAoKQpKLmw1KGcsIiIpCmlmKGIuZ0EoYik9PT0wKXt0PWRvY3VtZW50CnM9dC5jcmVh
-dGVFbGVtZW50KCJwIikKZy5hcHBlbmRDaGlsZChzKQpzLmFwcGVuZENoaWxkKHQuY3JlYXRlVGV4dE5v
-ZGUoIk5vIHByb3Bvc2VkIGVkaXRzIikpfWVsc2UgZm9yKGc9Yi5nUHUoYiksZz1nLmdreihnKSx0PXUu
-USxyPXQuQygifigxKSIpLHE9dS5NLHQ9dC5jO2cuRigpOyl7cD1nLmdsKCkKbz1kb2N1bWVudApzPW8u
-Y3JlYXRlRWxlbWVudCgicCIpCm49JC55UCgpCm4uYXBwZW5kQ2hpbGQocykKcy5hcHBlbmRDaGlsZChv
-LmNyZWF0ZVRleHROb2RlKEguZChwLmEpKyI6IikpCm09by5jcmVhdGVFbGVtZW50KCJ1bCIpCm4uYXBw
-ZW5kQ2hpbGQobSkKZm9yKHA9Si5JVChwLmIpO3AuRigpOyl7bj1wLmdsKCkKbD1vLmNyZWF0ZUVsZW1l
-bnQoImxpIikKbS5hcHBlbmRDaGlsZChsKQpKLmRSKGwpLmkoMCwiZWRpdCIpCms9by5jcmVhdGVFbGVt
-ZW50KCJhIikKbC5hcHBlbmRDaGlsZChrKQprLmNsYXNzTGlzdC5hZGQoImVkaXQtbGluayIpCmo9bi5j
-Cmk9SC5kKGopCmsuc2V0QXR0cmlidXRlKCJkYXRhLSIrbmV3IFcuU3kobmV3IFcuaTcoaykpLk8oIm9m
-ZnNldCIpLGkpCmg9bi5hCmk9SC5kKGgpCmsuc2V0QXR0cmlidXRlKCJkYXRhLSIrbmV3IFcuU3kobmV3
-IFcuaTcoaykpLk8oImxpbmUiKSxpKQprLmFwcGVuZENoaWxkKG8uY3JlYXRlVGV4dE5vZGUoImxpbmUg
-IitILmQoaCkpKQppPXIuYShuZXcgTC5FRShqLGgsYSkpCnEuYShudWxsKQpXLkpFKGssImNsaWNrIixp
-LCExLHQpCmwuYXBwZW5kQ2hpbGQoby5jcmVhdGVUZXh0Tm9kZSgiOiAiK0guZChuLmIpKSl9fWlmKGMp
-TC5UMShudWxsKX0sCkZyOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHI9d2luZG93LmxvY2F0aW9uLHE9
-UC5oSygociYmQy5FeCkuZ0RyKHIpK0guZChhKSkKcj11Lk4Kcj1QLkZsKHIscikKaWYoYiE9bnVsbCly
-LlkoMCwib2Zmc2V0IixILmQoYikpCmlmKGMhPW51bGwpci5ZKDAsImxpbmUiLEguZChjKSkKci5ZKDAs
-ImF1dGhUb2tlbiIsJC5VRSgpKQpxPXEubm0oMCxyKQpyPXdpbmRvdy5oaXN0b3J5CnQ9dS56CnM9cS5a
-KDApCnIudG9TdHJpbmcKci5wdXNoU3RhdGUobmV3IFAuQmYoW10sW10pLlB2KFAuRmwodCx0KSksIiIs
-cyl9LApFbjpmdW5jdGlvbihhKXt2YXIgdD1KLm0oZG9jdW1lbnQucXVlcnlTZWxlY3RvcigiLnJvb3Qi
-KS50ZXh0Q29udGVudCwiLyIpCmlmKEMueEIubihhLHQpKXJldHVybiBDLnhCLkcoYSx0Lmxlbmd0aCkK
-ZWxzZSByZXR1cm4gYX0sCkJYOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyPXt9CnIuYT1hCmE9TC5Fbihh
-KQpyLmE9YQokLkQ5KCkudGV4dENvbnRlbnQ9YQp0PWRvY3VtZW50CnM9dS5oCkguRGgocyxzLCJUIiwi
-cXVlcnlTZWxlY3RvckFsbCIpCnQ9bmV3IFcud3oodC5xdWVyeVNlbGVjdG9yQWxsKCIubmF2LXBhbmVs
-IC5uYXYtbGluayIpLHUuVCkKdC5LKHQsbmV3IEwuVlMocikpfSwKQkU6ZnVuY3Rpb24oYSxiLGMpe3Zh
-ciB0PSIucmVnaW9ucyIscz1kb2N1bWVudCxyPXMucXVlcnlTZWxlY3Rvcih0KSxxPXMucXVlcnlTZWxl
-Y3RvcigiLmNvZGUiKQpKLnRIKHIsYi5hLCQuS0coKSkKSi50SChxLGIuYiwkLktHKCkpCkwuTEgoYSxi
-LmQsYykKTC52VSgpCkwueVgoIi5jb2RlIiwhMCkKTC55WCh0LCEwKX0sCnRYOmZ1bmN0aW9uKGEsYil7
-dmFyIHQscyxyLHEscCxvLG4sbSxsLGssaixpLGgsZz1kb2N1bWVudCxmPWcuY3JlYXRlRWxlbWVudCgi
-dWwiKQphLmFwcGVuZENoaWxkKGYpCmZvcih0PWIubGVuZ3RoLHM9dS5NLHI9MDtyPGIubGVuZ3RoO2Iu
-bGVuZ3RoPT09dHx8KDAsSC5saykoYiksKytyKXtxPWJbcl0KcD1nLmNyZWF0ZUVsZW1lbnQoImxpIikK
-Zi5hcHBlbmRDaGlsZChwKQpvPUouUkUocCkKaWYocS5hPT09Qy5ZMil7by5nUChwKS5pKDAsImRpciIp
-Cm49Zy5jcmVhdGVFbGVtZW50KCJzcGFuIikKcC5hcHBlbmRDaGlsZChuKQpvPUouUkUobikKby5nUChu
-KS5pKDAsImFycm93IikKby5zaGYobiwiJiN4MjVCQzsiKQptPWcuY3JlYXRlRWxlbWVudCgic3BhbiIp
-CnAuYXBwZW5kQ2hpbGQobSkKSi5sNShtLCImI3gxRjRDMTsiKQpwLmFwcGVuZENoaWxkKGcuY3JlYXRl
-VGV4dE5vZGUocS5iKSkKTC50WChwLHEuYykKTC5reihuKX1lbHNle28uc2hmKHAsIiYjeDFGNEM0OyIp
-Cmw9Zy5jcmVhdGVFbGVtZW50KCJhIikKcC5hcHBlbmRDaGlsZChsKQpvPUouUkUobCkKby5nUChsKS5p
-KDAsIm5hdi1saW5rIikKbC5zZXRBdHRyaWJ1dGUoImRhdGEtIituZXcgVy5TeShuZXcgVy5pNyhsKSku
-TygibmFtZSIpLHEuZCkKbC5zZXRBdHRyaWJ1dGUoImhyZWYiLHEuZSkKbC5hcHBlbmRDaGlsZChnLmNy
-ZWF0ZVRleHROb2RlKHEuYikpCm89by5nVmwobCkKaz1vLiR0aQpqPWsuQygifigxKSIpLmEobmV3IEwu
-VEQoKSkKcy5hKG51bGwpClcuSkUoby5hLG8uYixqLCExLGsuYykKaT1xLmYKaWYodHlwZW9mIGkhPT0i
-bnVtYmVyIilyZXR1cm4gaS5vcygpCmlmKGk+MCl7aD1nLmNyZWF0ZUVsZW1lbnQoInNwYW4iKQpwLmFw
-cGVuZENoaWxkKGgpCkouZFIoaCkuaSgwLCJlZGl0LWNvdW50IikKbz0iIitpKyIgIgppZihpPT09MSlr
-PSJlZGl0IgplbHNlIGs9ImVkaXRzIgpoLnNldEF0dHJpYnV0ZSgidGl0bGUiLG8raykKaC5hcHBlbmRD
-aGlsZChnLmNyZWF0ZVRleHROb2RlKEMuam4uWihpKSkpfX19fSwKRno6ZnVuY3Rpb24oYSxiKXt2YXIg
-dCxzLHIscSxwLG8sbixtLGwsayxqLGk9YS5hCmlmKGk9PW51bGwpcmV0dXJuCnQ9ZG9jdW1lbnQKcz10
-LmNyZWF0ZUVsZW1lbnQoInAiKQpyPWIuYXBwZW5kQ2hpbGQocykKcz10LmNyZWF0ZUVsZW1lbnQoInNw
-YW4iKQpxPXUucwpKLk11KHMsSC5WTShbInR5cGUtZGVzY3JpcHRpb24iXSxxKSkKcy5hcHBlbmRDaGls
-ZCh0LmNyZWF0ZVRleHROb2RlKCJBY3Rpb25zIikpCnIuYXBwZW5kQ2hpbGQocykKci5hcHBlbmRDaGls
-ZCh0LmNyZWF0ZVRleHROb2RlKCI6IikpCnA9dC5jcmVhdGVFbGVtZW50KCJwIikKYi5hcHBlbmRDaGls
-ZChwKQpmb3Iocz1pLmxlbmd0aCxvPXUuWCxuPTA7bjxpLmxlbmd0aDtpLmxlbmd0aD09PXN8fCgwLEgu
-bGspKGkpLCsrbil7bT1pW25dCmw9dC5jcmVhdGVFbGVtZW50KCJhIikKcC5hcHBlbmRDaGlsZChsKQps
-LmFwcGVuZENoaWxkKHQuY3JlYXRlVGV4dE5vZGUobS5hKSkKbC5zZXRBdHRyaWJ1dGUoImhyZWYiLG0u
-YikKaz1vLmEoSC5WTShbImFkZC1oaW50LWxpbmsiLCJiZWZvcmUtYXBwbHkiLCJidXR0b24iXSxxKSkK
-aj1KLmRSKGwpCmouVjEoMCkKai5GVigwLGspfX0sCkNDOmZ1bmN0aW9uKGE4LGE5LGIwKXt2YXIgdCxz
-LHIscSxwLG8sbixtLGwsayxqLGksaCxnLGYsZSxkLGMsYixhLGEwLGExLGEyLGEzLGE0LGE1LGE2LGE3
-CmZvcih0PWE4LmYscz10Lmxlbmd0aCxyPXUucyxxPXUuWCxwPXUuUSxvPXAuQygifigxKSIpLG49dS5N
-LHA9cC5jLG09MDttPHQubGVuZ3RoO3QubGVuZ3RoPT09c3x8KDAsSC5saykodCksKyttKXtsPXRbbV0K
-az1kb2N1bWVudApqPWsuY3JlYXRlRWxlbWVudCgicCIpCmk9cS5hKEguVk0oWyJ0cmFjZSJdLHIpKQpo
-PUouZFIoaikKaC5WMSgwKQpoLkZWKDAsaSkKZz1hOS5hcHBlbmRDaGlsZChqKQpqPWsuY3JlYXRlRWxl
-bWVudCgic3BhbiIpCmk9cS5hKEguVk0oWyJ0eXBlLWRlc2NyaXB0aW9uIl0scikpCmg9Si5kUihqKQpo
-LlYxKDApCmguRlYoMCxpKQpqLmFwcGVuZENoaWxkKGsuY3JlYXRlVGV4dE5vZGUobC5hKSkKZy5hcHBl
-bmRDaGlsZChqKQpnLmFwcGVuZENoaWxkKGsuY3JlYXRlVGV4dE5vZGUoIjoiKSkKaj1rLmNyZWF0ZUVs
-ZW1lbnQoInVsIikKaT1xLmEoSC5WTShbInRyYWNlIl0scikpCmg9Si5kUihqKQpoLlYxKDApCmguRlYo
-MCxpKQpmPWcuYXBwZW5kQ2hpbGQoaikKZm9yKGo9bC5iLGk9ai5sZW5ndGgsZT0wO2U8ai5sZW5ndGg7
-ai5sZW5ndGg9PT1pfHwoMCxILmxrKShqKSwrK2Upe2Q9altlXQpjPWsuY3JlYXRlRWxlbWVudCgibGki
-KQpmLmFwcGVuZENoaWxkKGMpCmI9ay5jcmVhdGVFbGVtZW50KCJzcGFuIikKYT1xLmEoSC5WTShbImZ1
-bmN0aW9uIl0scikpCmg9Si5kUihiKQpoLlYxKDApCmguRlYoMCxhKQphPWQuYgpMLmtEKGIsYT09bnVs
-bD8idW5rbm93biI6YSkKYy5hcHBlbmRDaGlsZChiKQphMD1kLmMKaWYoYTAhPW51bGwpe2MuYXBwZW5k
-Q2hpbGQoay5jcmVhdGVUZXh0Tm9kZSgiICgiKSkKYTE9YTAuYgphMj1rLmNyZWF0ZUVsZW1lbnQoImEi
-KQphMi5hcHBlbmRDaGlsZChrLmNyZWF0ZVRleHROb2RlKEguZChhMC5jKSsiOiIrSC5kKGExKSkpCmEy
-LnNldEF0dHJpYnV0ZSgiaHJlZiIsYTAuYSkKYTIuY2xhc3NMaXN0LmFkZCgibmF2LWxpbmsiKQpjLmFw
-cGVuZENoaWxkKGEyKQpjLmFwcGVuZENoaWxkKGsuY3JlYXRlVGV4dE5vZGUoIikiKSl9Yy5hcHBlbmRD
-aGlsZChrLmNyZWF0ZVRleHROb2RlKCI6ICIpKQpiPWQuYQpMLmtEKGMsYj09bnVsbD8idW5rbm93biI6
-YikKYj1kLmQKaWYoYi5sZW5ndGghPT0wKXthPWsuY3JlYXRlRWxlbWVudCgicCIpCmEzPXEuYShILlZN
-KFsiZHJhd2VyIiwiYmVmb3JlLWFwcGx5Il0scikpCmg9Si5kUihhKQpoLlYxKDApCmguRlYoMCxhMykK
-YTQ9Yy5hcHBlbmRDaGlsZChhKQpmb3IoYT1iLmxlbmd0aCxhNT0wO2E1PGIubGVuZ3RoO2IubGVuZ3Ro
-PT09YXx8KDAsSC5saykoYiksKythNSl7YTY9YlthNV0KYTM9ay5jcmVhdGVFbGVtZW50KCJidXR0b24i
-KQphNz1vLmEobmV3IEwuQVMoYTYsYTApKQpuLmEobnVsbCkKVy5KRShhMywiY2xpY2siLGE3LCExLHAp
-CmEzLmFwcGVuZENoaWxkKGsuY3JlYXRlVGV4dE5vZGUoTS5PWChhNi5hKSkpCmE0LmFwcGVuZENoaWxk
-KGEzKX19fX19LAprRDpmdW5jdGlvbihhLGIpe3ZhciB0LHMscj1ILlZNKGIuc3BsaXQoIi4iKSx1LnMp
-LHE9Qy5ObS5ndEgocikscD1kb2N1bWVudAphLmFwcGVuZENoaWxkKHAuY3JlYXRlVGV4dE5vZGUocSkp
-CmZvcihxPUgucUMociwxLG51bGwsdS5OKSxxPW5ldyBILmE3KHEscS5nQShxKSxxLiR0aS5DKCJhNzxh
-TC5FPiIpKSx0PUouUkUoYSk7cS5GKCk7KXtzPXEuZAp0Lm56KGEsImJlZm9yZWVuZCIsIiYjODIwMzsu
-IixudWxsLG51bGwpCmEuYXBwZW5kQ2hpbGQocC5jcmVhdGVUZXh0Tm9kZShzKSl9fSwKZTpmdW5jdGlv
-biBlKCl7fSwKVlc6ZnVuY3Rpb24gVlcoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwK
-b1o6ZnVuY3Rpb24gb1ooKXt9LApqcjpmdW5jdGlvbiBqcigpe30sCnFsOmZ1bmN0aW9uIHFsKCl7fSwK
-eTg6ZnVuY3Rpb24geTgoKXt9LApIaTpmdW5jdGlvbiBIaSgpe30sCkJUOmZ1bmN0aW9uIEJUKCl7fSwK
-TDpmdW5jdGlvbiBMKCl7fSwKV3g6ZnVuY3Rpb24gV3goYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCkFP
-OmZ1bmN0aW9uIEFPKGEpe3RoaXMuYT1hfSwKZE46ZnVuY3Rpb24gZE4oYSl7dGhpcy5hPWF9LApIbzpm
-dW5jdGlvbiBIbyhhKXt0aGlzLmE9YX0sCnh6OmZ1bmN0aW9uIHh6KGEsYil7dGhpcy5hPWEKdGhpcy5i
-PWJ9LApJQzpmdW5jdGlvbiBJQygpe30sCmZDOmZ1bmN0aW9uIGZDKGEsYil7dGhpcy5hPWEKdGhpcy5i
-PWJ9LApuVDpmdW5jdGlvbiBuVChhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApCWjpm
-dW5jdGlvbiBCWihhKXt0aGlzLmE9YX0sCkdIOmZ1bmN0aW9uIEdIKCl7fSwKRUU6ZnVuY3Rpb24gRUUo
-YSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKUUw6ZnVuY3Rpb24gUUwoYSxiKXt0aGlz
-LmE9YQp0aGlzLmI9Yn0sClZTOmZ1bmN0aW9uIFZTKGEpe3RoaXMuYT1hfSwKVEQ6ZnVuY3Rpb24gVEQo
-KXt9LApBUzpmdW5jdGlvbiBBUyhhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKWEE6ZnVuY3Rpb24gWEEo
-KXt9LAptSzpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwLG8sbj1ILlZNKFtdLHUuZmgpCmZvcih0PUou
-SVQodS5SLmEoYSkpO3QuRigpOyl7cz10LmdsKCkKcj1KLlU2KHMpCnE9TC5wMihILmMoci5xKHMsInR5
-cGUiKSkpCnA9SC5jKHIucShzLCJuYW1lIikpCm89ci5xKHMsInN1YnRyZWUiKQpvPW89PW51bGw/bnVs
-bDpMLm1LKG8pCkMuTm0uaShuLG5ldyBMLlpaKHEscCxvLEguYyhyLnEocywicGF0aCIpKSxILmMoci5x
-KHMsImhyZWYiKSksSC5XWShyLnEocywiZWRpdENvdW50IikpKSl9cmV0dXJuIG59LApWRDpmdW5jdGlv
-bihhKXt2YXIgdCxzLHI9SC5WTShbXSx1LkopCmZvcih0PWEubGVuZ3RoLHM9MDtzPGEubGVuZ3RoO2Eu
-bGVuZ3RoPT09dHx8KDAsSC5saykoYSksKytzKUMuTm0uaShyLGFbc10uTHQoKSkKcmV0dXJuIHJ9LApw
-MjpmdW5jdGlvbihhKXtzd2l0Y2goYSl7Y2FzZSJkaXJlY3RvcnkiOnJldHVybiBDLlkyCmNhc2UiZmls
-ZSI6cmV0dXJuIEMucmYKZGVmYXVsdDp0aHJvdyBILmIoUC5QVigiVW5yZWNvZ25pemVkIG5hdmlnYXRp
-b24gdHJlZSBub2RlIHR5cGU6ICIrSC5kKGEpKSl9fSwKdnk6ZnVuY3Rpb24oYSl7c3dpdGNoKGEpe2Nh
-c2UgQy5ZMjpyZXR1cm4iZGlyZWN0b3J5IgpjYXNlIEMucmY6cmV0dXJuImZpbGUifXRocm93IEguYihQ
-LlBWKCJVbnJlY29nbml6ZWQgbmF2aWdhdGlvbiB0cmVlIG5vZGUgdHlwZTogIithLlooMCkpKX0sClpa
-OmZ1bmN0aW9uIFpaKGEsYixjLGQsZSxmKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8uZD1k
-Cl8uZT1lCl8uZj1mfSwKTzk6ZnVuY3Rpb24gTzkoYSl7dGhpcy5iPWF9LApJVjpmdW5jdGlvbiBJVihh
-LGIsYyxkKXt2YXIgXz10aGlzCl8uZD1hCl8uZT1iCl8uZj1jCl8ucj1kfX0sWD17CkNMOmZ1bmN0aW9u
-KGEsYil7dmFyIHQscyxyLHEscCxvPWIueFooYSkKYi5oSyhhKQppZihvIT1udWxsKWE9Si5LVihhLG8u
-bGVuZ3RoKQp0PXUucwpzPUguVk0oW10sdCkKcj1ILlZNKFtdLHQpCnQ9YS5sZW5ndGgKaWYodCE9PTAm
-JmIucjQoQy54Qi5XKGEsMCkpKXtpZigwPj10KXJldHVybiBILmsoYSwwKQpDLk5tLmkocixhWzBdKQpx
-PTF9ZWxzZXtDLk5tLmkociwiIikKcT0wfWZvcihwPXE7cDx0OysrcClpZihiLnI0KEMueEIuVyhhLHAp
-KSl7Qy5ObS5pKHMsQy54Qi5OaihhLHEscCkpCkMuTm0uaShyLGFbcF0pCnE9cCsxfWlmKHE8dCl7Qy5O
-bS5pKHMsQy54Qi5HKGEscSkpCkMuTm0uaShyLCIiKX1yZXR1cm4gbmV3IFguV0QoYixvLHMscil9LApX
-RDpmdW5jdGlvbiBXRChhLGIsYyxkKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uZD1jCl8uZT1kfSwK
-STc6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBYLmR2KGEpfSwKZHY6ZnVuY3Rpb24gZHYoYSl7dGhpcy5h
-PWF9fSxPPXsKUmg6ZnVuY3Rpb24oKXt2YXIgdCxzPW51bGwKaWYoUC51bygpLmdGaSgpIT09ImZpbGUi
-KXJldHVybiAkLkViKCkKdD1QLnVvKCkKaWYoIUMueEIuVGModC5nSWkodCksIi8iKSlyZXR1cm4gJC5F
-YigpCmlmKFAuS0wocywiYS9iIixzLHMscyxzLHMpLnQ0KCk9PT0iYVxcYiIpcmV0dXJuICQuS2soKQpy
-ZXR1cm4gJC5iRCgpfSwKekw6ZnVuY3Rpb24gekwoKXt9fSxFPXtPRjpmdW5jdGlvbiBPRihhLGIsYyl7
-dGhpcy5kPWEKdGhpcy5lPWIKdGhpcy5mPWN9fSxGPXtydTpmdW5jdGlvbiBydShhLGIsYyxkKXt2YXIg
-Xz10aGlzCl8uZD1hCl8uZT1iCl8uZj1jCl8ucj1kfX0sRD17ClJYOmZ1bmN0aW9uKCl7dmFyIHQscyxy
-LHEscD1udWxsCnRyeXtwPVAudW8oKX1jYXRjaCh0KXtpZih1Lmc4LmIoSC5SdSh0KSkpe3M9JC5GZgpp
-ZihzIT1udWxsKXJldHVybiBzCnRocm93IHR9ZWxzZSB0aHJvdyB0fWlmKEouUk0ocCwkLkk2KSlyZXR1
-cm4gJC5GZgokLkk2PXAKaWYoJC5IaygpPT0kLkViKCkpcz0kLkZmPXAuWkkoIi4iKS5aKDApCmVsc2V7
-cj1wLnQ0KCkKcT1yLmxlbmd0aC0xCnM9JC5GZj1xPT09MD9yOkMueEIuTmoociwwLHEpfXJldHVybiBz
-fX0KdmFyIHc9W0MsSCxKLFAsVyxNLFUsQixULEwsWCxPLEUsRixEXQpodW5rSGVscGVycy5zZXRGdW5j
-dGlvbk5hbWVzSWZOZWNlc3NhcnkodykKdmFyICQ9e30KSC5GSy5wcm90b3R5cGU9e30KSi52Qi5wcm90
-b3R5cGU9ewpETjpmdW5jdGlvbihhLGIpe3JldHVybiBhPT09Yn0sCmdpTzpmdW5jdGlvbihhKXtyZXR1
-cm4gSC5lUShhKX0sClo6ZnVuY3Rpb24oYSl7cmV0dXJuIkluc3RhbmNlIG9mICciK0guZChILmxoKGEp
-KSsiJyJ9LAplNzpmdW5jdGlvbihhLGIpe3Uuby5hKGIpCnRocm93IEguYihQLmxyKGEsYi5nV2EoKSxi
-LmduZCgpLGIuZ1ZtKCkpKX19CkoueUUucHJvdG90eXBlPXsKWjpmdW5jdGlvbihhKXtyZXR1cm4gU3Ry
-aW5nKGEpfSwKZ2lPOmZ1bmN0aW9uKGEpe3JldHVybiBhPzUxOTAxODoyMTgxNTl9LAokaWEyOjF9Ckou
-WUUucHJvdG90eXBlPXsKRE46ZnVuY3Rpb24oYSxiKXtyZXR1cm4gbnVsbD09Yn0sClo6ZnVuY3Rpb24o
-YSl7cmV0dXJuIm51bGwifSwKZ2lPOmZ1bmN0aW9uKGEpe3JldHVybiAwfSwKZTc6ZnVuY3Rpb24oYSxi
-KXtyZXR1cm4gdGhpcy5TaihhLHUuby5hKGIpKX0sCiRpYzg6MX0KSi5NRi5wcm90b3R5cGU9ewpnaU86
-ZnVuY3Rpb24oYSl7cmV0dXJuIDB9LApaOmZ1bmN0aW9uKGEpe3JldHVybiBTdHJpbmcoYSl9LAokaXZt
-OjF9CkouaUMucHJvdG90eXBlPXt9Ckoua2QucHJvdG90eXBlPXt9CkouYzUucHJvdG90eXBlPXsKWjpm
-dW5jdGlvbihhKXt2YXIgdD1hWyQud1EoKV0KaWYodD09bnVsbClyZXR1cm4gdGhpcy50KGEpCnJldHVy
-biJKYXZhU2NyaXB0IGZ1bmN0aW9uIGZvciAiK0guZChKLkFjKHQpKX0sCiRTOmZ1bmN0aW9uKCl7cmV0
-dXJue2Z1bmM6MSxvcHQ6WywsLCwsLCwsLCwsLCwsLCxdfX0sCiRpRUg6MX0KSi5qZC5wcm90b3R5cGU9
-ewppOmZ1bmN0aW9uKGEsYil7SC50NihhKS5jLmEoYikKaWYoISFhLmZpeGVkJGxlbmd0aClILnZoKFAu
-TDQoImFkZCIpKQphLnB1c2goYil9LApXNDpmdW5jdGlvbihhLGIpe3ZhciB0CmlmKCEhYS5maXhlZCRs
-ZW5ndGgpSC52aChQLkw0KCJyZW1vdmVBdCIpKQp0PWEubGVuZ3RoCmlmKGI+PXQpdGhyb3cgSC5iKFAu
-TzcoYixudWxsKSkKcmV0dXJuIGEuc3BsaWNlKGIsMSlbMF19LApVRzpmdW5jdGlvbihhLGIsYyl7dmFy
-IHQscyxyCkgudDYoYSkuQygiY1g8MT4iKS5hKGMpCmlmKCEhYS5maXhlZCRsZW5ndGgpSC52aChQLkw0
-KCJpbnNlcnRBbGwiKSkKdD1hLmxlbmd0aApQLndBKGIsMCx0LCJpbmRleCIpCnM9Yy5sZW5ndGgKdGhp
-cy5zQShhLHQrcykKcj1iK3MKdGhpcy5ZVyhhLHIsYS5sZW5ndGgsYSxiKQp0aGlzLnZnKGEsYixyLGMp
-fSwKbXY6ZnVuY3Rpb24oYSl7aWYoISFhLmZpeGVkJGxlbmd0aClILnZoKFAuTDQoInJlbW92ZUxhc3Qi
-KSkKaWYoYS5sZW5ndGg9PT0wKXRocm93IEguYihILkhZKGEsLTEpKQpyZXR1cm4gYS5wb3AoKX0sCkZW
-OmZ1bmN0aW9uKGEsYil7dmFyIHQKSC50NihhKS5DKCJjWDwxPiIpLmEoYikKaWYoISFhLmZpeGVkJGxl
-bmd0aClILnZoKFAuTDQoImFkZEFsbCIpKQpmb3IodD1KLklUKGIpO3QuRigpOylhLnB1c2godC5nbCgp
-KX0sCks6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzCkgudDYoYSkuQygifigxKSIpLmEoYikKdD1hLmxlbmd0
-aApmb3Iocz0wO3M8dDsrK3Mpe2IuJDEoYVtzXSkKaWYoYS5sZW5ndGghPT10KXRocm93IEguYihQLmE0
-KGEpKX19LApFMjpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9SC50NihhKQpyZXR1cm4gbmV3IEgubEooYSx0
-LktxKGMpLkMoIjEoMikiKS5hKGIpLHQuQygiQDwxPiIpLktxKGMpLkMoImxKPDEsMj4iKSl9LApIOmZ1
-bmN0aW9uKGEsYil7dmFyIHQscz1uZXcgQXJyYXkoYS5sZW5ndGgpCnMuZml4ZWQkbGVuZ3RoPUFycmF5
-CmZvcih0PTA7dDxhLmxlbmd0aDsrK3QpdGhpcy5ZKHMsdCxILmQoYVt0XSkpCnJldHVybiBzLmpvaW4o
-Yil9LApOMDpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzLHIKZC5hKGIpCkgudDYoYSkuS3EoZCkuQygi
-MSgxLDIpIikuYShjKQp0PWEubGVuZ3RoCmZvcihzPWIscj0wO3I8dDsrK3Ipe3M9Yy4kMihzLGFbcl0p
-CmlmKGEubGVuZ3RoIT09dCl0aHJvdyBILmIoUC5hNChhKSl9cmV0dXJuIHN9LApIdDpmdW5jdGlvbihh
-LGIpe3ZhciB0LHMscixxLHAsbz1ILnQ2KGEpCm8uQygiYTIoMSkiKS5hKGIpCm8uQygiMSgpIikuYShu
-dWxsKQp0PWEubGVuZ3RoCmZvcihzPW51bGwscj0hMSxxPTA7cTx0OysrcSl7cD1hW3FdCmlmKEgub1Qo
-Yi4kMShwKSkpe2lmKHIpdGhyb3cgSC5iKEguZFUoKSkKcz1wCnI9ITB9aWYodCE9PWEubGVuZ3RoKXRo
-cm93IEguYihQLmE0KGEpKX1pZihyKXJldHVybiBzCnRocm93IEguYihILldwKCkpfSwKRTpmdW5jdGlv
-bihhLGIpe2lmKGI8MHx8Yj49YS5sZW5ndGgpcmV0dXJuIEguayhhLGIpCnJldHVybiBhW2JdfSwKRDY6
-ZnVuY3Rpb24oYSxiLGMpe2lmKGI8MHx8Yj5hLmxlbmd0aCl0aHJvdyBILmIoUC5URShiLDAsYS5sZW5n
-dGgsInN0YXJ0IixudWxsKSkKaWYoYzxifHxjPmEubGVuZ3RoKXRocm93IEguYihQLlRFKGMsYixhLmxl
-bmd0aCwiZW5kIixudWxsKSkKaWYoYj09PWMpcmV0dXJuIEguVk0oW10sSC50NihhKSkKcmV0dXJuIEgu
-Vk0oYS5zbGljZShiLGMpLEgudDYoYSkpfSwKZ3RIOmZ1bmN0aW9uKGEpe2lmKGEubGVuZ3RoPjApcmV0
-dXJuIGFbMF0KdGhyb3cgSC5iKEguV3AoKSl9LApnclo6ZnVuY3Rpb24oYSl7dmFyIHQ9YS5sZW5ndGgK
-aWYodD4wKXJldHVybiBhW3QtMV0KdGhyb3cgSC5iKEguV3AoKSl9LApZVzpmdW5jdGlvbihhLGIsYyxk
-LGUpe3ZhciB0LHMscj1ILnQ2KGEpCnIuQygiY1g8MT4iKS5hKGQpCmlmKCEhYS5pbW11dGFibGUkbGlz
-dClILnZoKFAuTDQoInNldFJhbmdlIikpClAuakIoYixjLGEubGVuZ3RoKQp0PWMtYgppZih0PT09MCly
-ZXR1cm4KUC5rMShlLCJza2lwQ291bnQiKQpyLkMoInpNPDE+IikuYShkKQpyPUouVTYoZCkKaWYoZSt0
-PnIuZ0EoZCkpdGhyb3cgSC5iKEguYXIoKSkKaWYoZTxiKWZvcihzPXQtMTtzPj0wOy0tcylhW2Irc109
-ci5xKGQsZStzKQplbHNlIGZvcihzPTA7czx0OysrcylhW2Irc109ci5xKGQsZStzKX0sCnZnOmZ1bmN0
-aW9uKGEsYixjLGQpe3JldHVybiB0aGlzLllXKGEsYixjLGQsMCl9LApWcjpmdW5jdGlvbihhLGIpe3Zh
-ciB0LHMKSC50NihhKS5DKCJhMigxKSIpLmEoYikKdD1hLmxlbmd0aApmb3Iocz0wO3M8dDsrK3Mpe2lm
-KEgub1QoYi4kMShhW3NdKSkpcmV0dXJuITAKaWYoYS5sZW5ndGghPT10KXRocm93IEguYihQLmE0KGEp
-KX1yZXR1cm4hMX0sCnRnOmZ1bmN0aW9uKGEsYil7dmFyIHQKZm9yKHQ9MDt0PGEubGVuZ3RoOysrdClp
-ZihKLlJNKGFbdF0sYikpcmV0dXJuITAKcmV0dXJuITF9LApnbDA6ZnVuY3Rpb24oYSl7cmV0dXJuIGEu
-bGVuZ3RoPT09MH0sCmdvcjpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGghPT0wfSwKWjpmdW5jdGlv
-bihhKXtyZXR1cm4gUC5XRShhLCJbIiwiXSIpfSwKZ2t6OmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgSi5t
-MShhLGEubGVuZ3RoLEgudDYoYSkuQygibTE8MT4iKSl9LApnaU86ZnVuY3Rpb24oYSl7cmV0dXJuIEgu
-ZVEoYSl9LApnQTpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9LApzQTpmdW5jdGlvbihhLGIpe2lm
-KCEhYS5maXhlZCRsZW5ndGgpSC52aChQLkw0KCJzZXQgbGVuZ3RoIikpCmlmKGI8MCl0aHJvdyBILmIo
-UC5URShiLDAsbnVsbCwibmV3TGVuZ3RoIixudWxsKSkKYS5sZW5ndGg9Yn0sCnE6ZnVuY3Rpb24oYSxi
-KXtILldZKGIpCmlmKGI+PWEubGVuZ3RofHxiPDApdGhyb3cgSC5iKEguSFkoYSxiKSkKcmV0dXJuIGFb
-Yl19LApZOmZ1bmN0aW9uKGEsYixjKXtILnQ2KGEpLmMuYShjKQppZighIWEuaW1tdXRhYmxlJGxpc3Qp
-SC52aChQLkw0KCJpbmRleGVkIHNldCIpKQppZihiPj1hLmxlbmd0aHx8YjwwKXRocm93IEguYihILkhZ
-KGEsYikpCmFbYl09Y30sCiRpYlE6MSwKJGljWDoxLAokaXpNOjF9CkouUG8ucHJvdG90eXBlPXt9Ckou
-bTEucHJvdG90eXBlPXsKZ2w6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5kfSwKRjpmdW5jdGlvbigpe3Zh
-ciB0LHM9dGhpcyxyPXMuYSxxPXIubGVuZ3RoCmlmKHMuYiE9PXEpdGhyb3cgSC5iKEgubGsocikpCnQ9
-cy5jCmlmKHQ+PXEpe3Muc00obnVsbCkKcmV0dXJuITF9cy5zTShyW3RdKTsrK3MuYwpyZXR1cm4hMH0s
-CnNNOmZ1bmN0aW9uKGEpe3RoaXMuZD10aGlzLiR0aS5jLmEoYSl9LAokaUFuOjF9CkoucUkucHJvdG90
-eXBlPXsKeXU6ZnVuY3Rpb24oYSl7dmFyIHQKaWYoYT49LTIxNDc0ODM2NDgmJmE8PTIxNDc0ODM2NDcp
-cmV0dXJuIGF8MAppZihpc0Zpbml0ZShhKSl7dD1hPDA/TWF0aC5jZWlsKGEpOk1hdGguZmxvb3IoYSkK
-cmV0dXJuIHQrMH10aHJvdyBILmIoUC5MNCgiIithKyIudG9JbnQoKSIpKX0sCnpROmZ1bmN0aW9uKGEp
-e2lmKGE+MCl7aWYoYSE9PTEvMClyZXR1cm4gTWF0aC5yb3VuZChhKX1lbHNlIGlmKGE+LTEvMClyZXR1
-cm4gMC1NYXRoLnJvdW5kKDAtYSkKdGhyb3cgSC5iKFAuTDQoIiIrYSsiLnJvdW5kKCkiKSl9LApXWjpm
-dW5jdGlvbihhLGIpe3ZhciB0LHMscixxCmlmKGI8Mnx8Yj4zNil0aHJvdyBILmIoUC5URShiLDIsMzYs
-InJhZGl4IixudWxsKSkKdD1hLnRvU3RyaW5nKGIpCmlmKEMueEIubSh0LHQubGVuZ3RoLTEpIT09NDEp
-cmV0dXJuIHQKcz0vXihbXGRhLXpdKykoPzpcLihbXGRhLXpdKykpP1woZVwrKFxkKylcKSQvLmV4ZWMo
-dCkKaWYocz09bnVsbClILnZoKFAuTDQoIlVuZXhwZWN0ZWQgdG9TdHJpbmcgcmVzdWx0OiAiK3QpKQpy
-PXMubGVuZ3RoCmlmKDE+PXIpcmV0dXJuIEguayhzLDEpCnQ9c1sxXQppZigzPj1yKXJldHVybiBILmso
-cywzKQpxPStzWzNdCnI9c1syXQppZihyIT1udWxsKXt0Kz1yCnEtPXIubGVuZ3RofXJldHVybiB0K0Mu
-eEIuSXgoIjAiLHEpfSwKWjpmdW5jdGlvbihhKXtpZihhPT09MCYmMS9hPDApcmV0dXJuIi0wLjAiCmVs
-c2UgcmV0dXJuIiIrYX0sCmdpTzpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwPWF8MAppZihhPT09cCly
-ZXR1cm4gNTM2ODcwOTExJnAKdD1NYXRoLmFicyhhKQpzPU1hdGgubG9nKHQpLzAuNjkzMTQ3MTgwNTU5
-OTQ1M3wwCnI9TWF0aC5wb3coMixzKQpxPXQ8MT90L3I6ci90CnJldHVybiA1MzY4NzA5MTEmKChxKjkw
-MDcxOTkyNTQ3NDA5OTJ8MCkrKHEqMzU0MjI0MzE4MTE3NjUyMXwwKSkqNTk5MTk3K3MqMTI1OX0sCnpZ
-OmZ1bmN0aW9uKGEsYil7dmFyIHQ9YSViCmlmKHQ9PT0wKXJldHVybiAwCmlmKHQ+MClyZXR1cm4gdApp
-ZihiPDApcmV0dXJuIHQtYgplbHNlIHJldHVybiB0K2J9LAp3RzpmdW5jdGlvbihhLGIpe3ZhciB0Cmlm
-KGE+MCl0PXRoaXMucDMoYSxiKQplbHNle3Q9Yj4zMT8zMTpiCnQ9YT4+dD4+PjB9cmV0dXJuIHR9LApi
-ZjpmdW5jdGlvbihhLGIpe2lmKGI8MCl0aHJvdyBILmIoSC5JKGIpKQpyZXR1cm4gdGhpcy5wMyhhLGIp
-fSwKcDM6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gYj4zMT8wOmE+Pj5ifSwKJGlDUDoxLAokaWxmOjF9Ckou
-YlUucHJvdG90eXBlPXskaUlmOjF9CkouVkEucHJvdG90eXBlPXt9CkouRHIucHJvdG90eXBlPXsKbTpm
-dW5jdGlvbihhLGIpe2lmKGI8MCl0aHJvdyBILmIoSC5IWShhLGIpKQppZihiPj1hLmxlbmd0aClILnZo
-KEguSFkoYSxiKSkKcmV0dXJuIGEuY2hhckNvZGVBdChiKX0sClc6ZnVuY3Rpb24oYSxiKXtpZihiPj1h
-Lmxlbmd0aCl0aHJvdyBILmIoSC5IWShhLGIpKQpyZXR1cm4gYS5jaGFyQ29kZUF0KGIpfSwKZGQ6ZnVu
-Y3Rpb24oYSxiKXtyZXR1cm4gbmV3IEguTkYoYixhLDApfSwKaDpmdW5jdGlvbihhLGIpe2lmKHR5cGVv
-ZiBiIT0ic3RyaW5nIil0aHJvdyBILmIoUC5MMyhiLG51bGwsbnVsbCkpCnJldHVybiBhK2J9LApUYzpm
-dW5jdGlvbihhLGIpe3ZhciB0PWIubGVuZ3RoLHM9YS5sZW5ndGgKaWYodD5zKXJldHVybiExCnJldHVy
-biBiPT09dGhpcy5HKGEscy10KX0sCmk3OmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0LHMKYz1QLmpCKGIs
-YyxhLmxlbmd0aCkKdD1hLnN1YnN0cmluZygwLGIpCnM9YS5zdWJzdHJpbmcoYykKcmV0dXJuIHQrZCtz
-fSwKUWk6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0CmlmKCFILm9rKGMpKUgudmgoSC5JKGMpKQppZih0eXBl
-b2YgYyE9PSJudW1iZXIiKXJldHVybiBjLkooKQppZihjPDB8fGM+YS5sZW5ndGgpdGhyb3cgSC5iKFAu
-VEUoYywwLGEubGVuZ3RoLG51bGwsbnVsbCkpCnQ9YytiLmxlbmd0aAppZih0PmEubGVuZ3RoKXJldHVy
-biExCnJldHVybiBiPT09YS5zdWJzdHJpbmcoYyx0KX0sCm46ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhp
-cy5RaShhLGIsMCl9LApOajpmdW5jdGlvbihhLGIsYyl7aWYoIUgub2soYikpSC52aChILkkoYikpCmlm
-KGM9PW51bGwpYz1hLmxlbmd0aAppZih0eXBlb2YgYiE9PSJudW1iZXIiKXJldHVybiBiLkooKQppZihi
-PDApdGhyb3cgSC5iKFAuTzcoYixudWxsKSkKaWYoYj5jKXRocm93IEguYihQLk83KGIsbnVsbCkpCmlm
-KGM+YS5sZW5ndGgpdGhyb3cgSC5iKFAuTzcoYyxudWxsKSkKcmV0dXJuIGEuc3Vic3RyaW5nKGIsYyl9
-LApHOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuTmooYSxiLG51bGwpfSwKaGM6ZnVuY3Rpb24oYSl7
-cmV0dXJuIGEudG9Mb3dlckNhc2UoKX0sCmJTOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxPWEudHJpbSgp
-LHA9cS5sZW5ndGgKaWYocD09PTApcmV0dXJuIHEKaWYodGhpcy5XKHEsMCk9PT0xMzMpe3Q9Si5tbShx
-LDEpCmlmKHQ9PT1wKXJldHVybiIifWVsc2UgdD0wCnM9cC0xCnI9dGhpcy5tKHEscyk9PT0xMzM/Si5j
-MShxLHMpOnAKaWYodD09PTAmJnI9PT1wKXJldHVybiBxCnJldHVybiBxLnN1YnN0cmluZyh0LHIpfSwK
-SXg6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzCmlmKDA+PWIpcmV0dXJuIiIKaWYoYj09PTF8fGEubGVuZ3Ro
-PT09MClyZXR1cm4gYQppZihiIT09Yj4+PjApdGhyb3cgSC5iKEMuRXEpCmZvcih0PWEscz0iIjshMDsp
-e2lmKChiJjEpPT09MSlzPXQrcwpiPWI+Pj4xCmlmKGI9PT0wKWJyZWFrCnQrPXR9cmV0dXJuIHN9LApY
-VTpmdW5jdGlvbihhLGIsYyl7dmFyIHQKaWYoYzwwfHxjPmEubGVuZ3RoKXRocm93IEguYihQLlRFKGMs
-MCxhLmxlbmd0aCxudWxsLG51bGwpKQp0PWEuaW5kZXhPZihiLGMpCnJldHVybiB0fSwKT1k6ZnVuY3Rp
-b24oYSxiKXtyZXR1cm4gdGhpcy5YVShhLGIsMCl9LApQazpmdW5jdGlvbihhLGIsYyl7dmFyIHQscwpp
-ZihjPT1udWxsKWM9YS5sZW5ndGgKZWxzZSBpZihjPDB8fGM+YS5sZW5ndGgpdGhyb3cgSC5iKFAuVEUo
-YywwLGEubGVuZ3RoLG51bGwsbnVsbCkpCnQ9Yi5sZW5ndGgKcz1hLmxlbmd0aAppZihjK3Q+cyljPXMt
-dApyZXR1cm4gYS5sYXN0SW5kZXhPZihiLGMpfSwKY246ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5Q
-ayhhLGIsbnVsbCl9LApJczpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9YS5sZW5ndGgKaWYoYz50KXRocm93
-IEguYihQLlRFKGMsMCx0LG51bGwsbnVsbCkpCnJldHVybiBILm0yKGEsYixjKX0sCnRnOmZ1bmN0aW9u
-KGEsYil7cmV0dXJuIHRoaXMuSXMoYSxiLDApfSwKWjpmdW5jdGlvbihhKXtyZXR1cm4gYX0sCmdpTzpm
-dW5jdGlvbihhKXt2YXIgdCxzLHIKZm9yKHQ9YS5sZW5ndGgscz0wLHI9MDtyPHQ7KytyKXtzPTUzNjg3
-MDkxMSZzK2EuY2hhckNvZGVBdChyKQpzPTUzNjg3MDkxMSZzKygoNTI0Mjg3JnMpPDwxMCkKc149cz4+
-Nn1zPTUzNjg3MDkxMSZzKygoNjcxMDg4NjMmcyk8PDMpCnNePXM+PjExCnJldHVybiA1MzY4NzA5MTEm
-cysoKDE2MzgzJnMpPDwxNSl9LApnQTpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9LApxOmZ1bmN0
-aW9uKGEsYil7SC5XWShiKQppZihiPj1hLmxlbmd0aHx8ITEpdGhyb3cgSC5iKEguSFkoYSxiKSkKcmV0
-dXJuIGFbYl19LAokaXZYOjEsCiRpcVU6MX0KSC5xai5wcm90b3R5cGU9ewpnQTpmdW5jdGlvbihhKXty
-ZXR1cm4gdGhpcy5hLmxlbmd0aH0sCnE6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gQy54Qi5tKHRoaXMuYSxI
-LldZKGIpKX19CkguYlEucHJvdG90eXBlPXt9CkguYUwucHJvdG90eXBlPXsKZ2t6OmZ1bmN0aW9uKGEp
-e3ZhciB0PXRoaXMKcmV0dXJuIG5ldyBILmE3KHQsdC5nQSh0KSxILkxoKHQpLkMoImE3PGFMLkU+Iikp
-fSwKZ2wwOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmdBKHRoaXMpPT09MH0sCkg6ZnVuY3Rpb24oYSxi
-KXt2YXIgdCxzLHIscT10aGlzLHA9cS5nQShxKQppZihiLmxlbmd0aCE9PTApe2lmKHA9PT0wKXJldHVy
-biIiCnQ9SC5kKHEuRSgwLDApKQppZihwIT09cS5nQShxKSl0aHJvdyBILmIoUC5hNChxKSkKZm9yKHM9
-dCxyPTE7cjxwOysrcil7cz1zK2IrSC5kKHEuRSgwLHIpKQppZihwIT09cS5nQShxKSl0aHJvdyBILmIo
-UC5hNChxKSl9cmV0dXJuIHMuY2hhckNvZGVBdCgwKT09MD9zOnN9ZWxzZXtmb3Iocj0wLHM9IiI7cjxw
-Oysrcil7cys9SC5kKHEuRSgwLHIpKQppZihwIT09cS5nQShxKSl0aHJvdyBILmIoUC5hNChxKSl9cmV0
-dXJuIHMuY2hhckNvZGVBdCgwKT09MD9zOnN9fSwKZXY6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5H
-RygwLEguTGgodGhpcykuQygiYTIoYUwuRSkiKS5hKGIpKX0sCkUyOmZ1bmN0aW9uKGEsYixjKXt2YXIg
-dD1ILkxoKHRoaXMpCnJldHVybiBuZXcgSC5sSih0aGlzLHQuS3EoYykuQygiMShhTC5FKSIpLmEoYiks
-dC5DKCJAPGFMLkU+IikuS3EoYykuQygibEo8MSwyPiIpKX0sCnR0OmZ1bmN0aW9uKGEsYil7dmFyIHQs
-cz10aGlzLHI9SC5WTShbXSxILkxoKHMpLkMoImpkPGFMLkU+IikpCkMuTm0uc0EocixzLmdBKHMpKQpm
-b3IodD0wO3Q8cy5nQShzKTsrK3QpQy5ObS5ZKHIsdCxzLkUoMCx0KSkKcmV0dXJuIHJ9LApicjpmdW5j
-dGlvbihhKXtyZXR1cm4gdGhpcy50dChhLCEwKX19CkgubkgucHJvdG90eXBlPXsKZ1VEOmZ1bmN0aW9u
-KCl7dmFyIHQ9Si5IKHRoaXMuYSkscz10aGlzLmMKaWYocz09bnVsbHx8cz50KXJldHVybiB0CnJldHVy
-biBzfSwKZ0FzOmZ1bmN0aW9uKCl7dmFyIHQ9Si5IKHRoaXMuYSkscz10aGlzLmIKaWYocz50KXJldHVy
-biB0CnJldHVybiBzfSwKZ0E6ZnVuY3Rpb24oYSl7dmFyIHQscz1KLkgodGhpcy5hKSxyPXRoaXMuYgpp
-ZihyPj1zKXJldHVybiAwCnQ9dGhpcy5jCmlmKHQ9PW51bGx8fHQ+PXMpcmV0dXJuIHMtcgppZih0eXBl
-b2YgdCE9PSJudW1iZXIiKXJldHVybiB0LkhOKCkKcmV0dXJuIHQtcn0sCkU6ZnVuY3Rpb24oYSxiKXt2
-YXIgdCxzPXRoaXMscj1zLmdBcygpK2IKaWYoYj49MCl7dD1zLmdVRCgpCmlmKHR5cGVvZiB0IT09Im51
-bWJlciIpcmV0dXJuIEgucFkodCkKdD1yPj10fWVsc2UgdD0hMAppZih0KXRocm93IEguYihQLnQoYixz
-LCJpbmRleCIsbnVsbCxudWxsKSkKcmV0dXJuIEouR0Eocy5hLHIpfX0KSC5hNy5wcm90b3R5cGU9ewpn
-bDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmR9LApGOmZ1bmN0aW9uKCl7dmFyIHQscz10aGlzLHI9cy5h
-LHE9Si5VNihyKSxwPXEuZ0EocikKaWYocy5iIT09cCl0aHJvdyBILmIoUC5hNChyKSkKdD1zLmMKaWYo
-dD49cCl7cy5zSShudWxsKQpyZXR1cm4hMX1zLnNJKHEuRShyLHQpKTsrK3MuYwpyZXR1cm4hMH0sCnNJ
-OmZ1bmN0aW9uKGEpe3RoaXMuZD10aGlzLiR0aS5jLmEoYSl9LAokaUFuOjF9CkguaTEucHJvdG90eXBl
-PXsKZ2t6OmZ1bmN0aW9uKGEpe3ZhciB0PUguTGgodGhpcykKcmV0dXJuIG5ldyBILk1IKEouSVQodGhp
-cy5hKSx0aGlzLmIsdC5DKCJAPDE+IikuS3EodC5RWzFdKS5DKCJNSDwxLDI+IikpfSwKZ0E6ZnVuY3Rp
-b24oYSl7cmV0dXJuIEouSCh0aGlzLmEpfX0KSC54eS5wcm90b3R5cGU9eyRpYlE6MX0KSC5NSC5wcm90
-b3R5cGU9ewpGOmZ1bmN0aW9uKCl7dmFyIHQ9dGhpcyxzPXQuYgppZihzLkYoKSl7dC5zSSh0LmMuJDEo
-cy5nbCgpKSkKcmV0dXJuITB9dC5zSShudWxsKQpyZXR1cm4hMX0sCmdsOmZ1bmN0aW9uKCl7cmV0dXJu
-IHRoaXMuYX0sCnNJOmZ1bmN0aW9uKGEpe3RoaXMuYT10aGlzLiR0aS5RWzFdLmEoYSl9fQpILmxKLnBy
-b3RvdHlwZT17CmdBOmZ1bmN0aW9uKGEpe3JldHVybiBKLkgodGhpcy5hKX0sCkU6ZnVuY3Rpb24oYSxi
-KXtyZXR1cm4gdGhpcy5iLiQxKEouR0EodGhpcy5hLGIpKX19CkguVTUucHJvdG90eXBlPXsKZ2t6OmZ1
-bmN0aW9uKGEpe3JldHVybiBuZXcgSC52RyhKLklUKHRoaXMuYSksdGhpcy5iLHRoaXMuJHRpLkMoInZH
-PDE+IikpfX0KSC52Ry5wcm90b3R5cGU9ewpGOmZ1bmN0aW9uKCl7dmFyIHQscwpmb3IodD10aGlzLmEs
-cz10aGlzLmI7dC5GKCk7KWlmKEgub1Qocy4kMSh0LmdsKCkpKSlyZXR1cm4hMApyZXR1cm4hMX0sCmds
-OmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuYS5nbCgpfX0KSC5TVS5wcm90b3R5cGU9e30KSC5SZS5wcm90
-b3R5cGU9ewpZOmZ1bmN0aW9uKGEsYixjKXtILkxoKHRoaXMpLkMoIlJlLkUiKS5hKGMpCnRocm93IEgu
-YihQLkw0KCJDYW5ub3QgbW9kaWZ5IGFuIHVubW9kaWZpYWJsZSBsaXN0IikpfX0KSC53Mi5wcm90b3R5
-cGU9e30KSC53di5wcm90b3R5cGU9ewpnaU86ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5faGFzaENvZGUK
-aWYodCE9bnVsbClyZXR1cm4gdAp0PTUzNjg3MDkxMSY2NjQ1OTcqSi5oZih0aGlzLmEpCnRoaXMuX2hh
-c2hDb2RlPXQKcmV0dXJuIHR9LApaOmZ1bmN0aW9uKGEpe3JldHVybidTeW1ib2woIicrSC5kKHRoaXMu
-YSkrJyIpJ30sCkROOmZ1bmN0aW9uKGEsYil7aWYoYj09bnVsbClyZXR1cm4hMQpyZXR1cm4gYiBpbnN0
-YW5jZW9mIEgud3YmJnRoaXMuYT09Yi5hfSwKJGlHRDoxfQpILlBELnByb3RvdHlwZT17fQpILldVLnBy
-b3RvdHlwZT17CmdsMDpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5nQSh0aGlzKT09PTB9LApaOmZ1bmN0
-aW9uKGEpe3JldHVybiBQLm5PKHRoaXMpfSwKWTpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9SC5MaCh0aGlz
-KQp0LmMuYShiKQp0LlFbMV0uYShjKQpyZXR1cm4gSC5kYygpfSwKZ1B1OmZ1bmN0aW9uKGEpe3JldHVy
-biB0aGlzLnE0KGEsSC5MaCh0aGlzKS5DKCJOMzwxLDI+IikpfSwKcTQ6ZnVuY3Rpb24oYSxiKXt2YXIg
-dD10aGlzCnJldHVybiBQLmwwKGZ1bmN0aW9uKCl7dmFyIHM9YQp2YXIgcj0wLHE9MSxwLG8sbixtCnJl
-dHVybiBmdW5jdGlvbiAkYXN5bmMkZ1B1KGMsZCl7aWYoYz09PTEpe3A9ZApyPXF9d2hpbGUodHJ1ZSlz
-d2l0Y2gocil7Y2FzZSAwOm89dC5nVigpLG89by5na3oobyksbj1ILkxoKHQpLG49bi5DKCJAPDE+Iiku
-S3Eobi5RWzFdKS5DKCJOMzwxLDI+IikKY2FzZSAyOmlmKCFvLkYoKSl7cj0zCmJyZWFrfW09by5nbCgp
-CnI9NApyZXR1cm4gbmV3IFAuTjMobSx0LnEoMCxtKSxuKQpjYXNlIDQ6cj0yCmJyZWFrCmNhc2UgMzpy
-ZXR1cm4gUC5UaCgpCmNhc2UgMTpyZXR1cm4gUC5ZbShwKX19fSxiKX0sCiRpWjA6MX0KSC5MUC5wcm90
-b3R5cGU9ewpnQTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hfSwKeDQ6ZnVuY3Rpb24oYSl7aWYodHlw
-ZW9mIGEhPSJzdHJpbmciKXJldHVybiExCmlmKCJfX3Byb3RvX18iPT09YSlyZXR1cm4hMQpyZXR1cm4g
-dGhpcy5iLmhhc093blByb3BlcnR5KGEpfSwKcTpmdW5jdGlvbihhLGIpe2lmKCF0aGlzLng0KGIpKXJl
-dHVybiBudWxsCnJldHVybiB0aGlzLkQoYil9LApEOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmJbSC5j
-KGEpXX0sCks6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxwPUguTGgodGhpcykKcC5DKCJ+KDEsMiki
-KS5hKGIpCnQ9dGhpcy5jCmZvcihzPXQubGVuZ3RoLHA9cC5RWzFdLHI9MDtyPHM7KytyKXtxPXRbcl0K
-Yi4kMihxLHAuYSh0aGlzLkQocSkpKX19LApnVjpmdW5jdGlvbigpe3JldHVybiBuZXcgSC5YUih0aGlz
-LEguTGgodGhpcykuQygiWFI8MT4iKSl9fQpILlhSLnByb3RvdHlwZT17CmdrejpmdW5jdGlvbihhKXt2
-YXIgdD10aGlzLmEuYwpyZXR1cm4gbmV3IEoubTEodCx0Lmxlbmd0aCxILnQ2KHQpLkMoIm0xPDE+Iikp
-fSwKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYS5jLmxlbmd0aH19CkguTEkucHJvdG90eXBlPXsK
-Z1dhOmZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5hCnJldHVybiB0fSwKZ25kOmZ1bmN0aW9uKCl7dmFyIHQs
-cyxyLHEscD10aGlzCmlmKHAuYz09PTEpcmV0dXJuIEMuaFUKdD1wLmQKcz10Lmxlbmd0aC1wLmUubGVu
-Z3RoLXAuZgppZihzPT09MClyZXR1cm4gQy5oVQpyPVtdCmZvcihxPTA7cTxzOysrcSl7aWYocT49dC5s
-ZW5ndGgpcmV0dXJuIEguayh0LHEpCnIucHVzaCh0W3FdKX1yZXR1cm4gSi51bihyKX0sCmdWbTpmdW5j
-dGlvbigpe3ZhciB0LHMscixxLHAsbyxuLG0sbD10aGlzCmlmKGwuYyE9PTApcmV0dXJuIEMuRHgKdD1s
-LmUKcz10Lmxlbmd0aApyPWwuZApxPXIubGVuZ3RoLXMtbC5mCmlmKHM9PT0wKXJldHVybiBDLkR4CnA9
-bmV3IEguTjUodS5lbykKZm9yKG89MDtvPHM7KytvKXtpZihvPj10Lmxlbmd0aClyZXR1cm4gSC5rKHQs
-bykKbj10W29dCm09cStvCmlmKG08MHx8bT49ci5sZW5ndGgpcmV0dXJuIEguayhyLG0pCnAuWSgwLG5l
-dyBILnd2KG4pLHJbbV0pfXJldHVybiBuZXcgSC5QRChwLHUuZ0YpfSwKJGl2UToxfQpILkNqLnByb3Rv
-dHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dmFyIHQKSC5jKGEpCnQ9dGhpcy5hCnQuYj10LmIrIiQiK0gu
-ZChhKQpDLk5tLmkodGhpcy5iLGEpCkMuTm0uaSh0aGlzLmMsYik7Kyt0LmF9LAokUzoxMn0KSC5mOS5w
-cm90b3R5cGU9ewpxUzpmdW5jdGlvbihhKXt2YXIgdCxzLHI9dGhpcyxxPW5ldyBSZWdFeHAoci5hKS5l
-eGVjKGEpCmlmKHE9PW51bGwpcmV0dXJuIG51bGwKdD1PYmplY3QuY3JlYXRlKG51bGwpCnM9ci5iCmlm
-KHMhPT0tMSl0LmFyZ3VtZW50cz1xW3MrMV0Kcz1yLmMKaWYocyE9PS0xKXQuYXJndW1lbnRzRXhwcj1x
-W3MrMV0Kcz1yLmQKaWYocyE9PS0xKXQuZXhwcj1xW3MrMV0Kcz1yLmUKaWYocyE9PS0xKXQubWV0aG9k
-PXFbcysxXQpzPXIuZgppZihzIT09LTEpdC5yZWNlaXZlcj1xW3MrMV0KcmV0dXJuIHR9fQpILlcwLnBy
-b3RvdHlwZT17Clo6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5iCmlmKHQ9PW51bGwpcmV0dXJuIk5vU3Vj
-aE1ldGhvZEVycm9yOiAiK0guZCh0aGlzLmEpCnJldHVybiJOb1N1Y2hNZXRob2RFcnJvcjogbWV0aG9k
-IG5vdCBmb3VuZDogJyIrdCsiJyBvbiBudWxsIn19CkguYXoucHJvdG90eXBlPXsKWjpmdW5jdGlvbihh
-KXt2YXIgdCxzPXRoaXMscj0iTm9TdWNoTWV0aG9kRXJyb3I6IG1ldGhvZCBub3QgZm91bmQ6ICciLHE9
-cy5iCmlmKHE9PW51bGwpcmV0dXJuIk5vU3VjaE1ldGhvZEVycm9yOiAiK0guZChzLmEpCnQ9cy5jCmlm
-KHQ9PW51bGwpcmV0dXJuIHIrcSsiJyAoIitILmQocy5hKSsiKSIKcmV0dXJuIHIrcSsiJyBvbiAnIit0
-KyInICgiK0guZChzLmEpKyIpIn19CkgudlYucHJvdG90eXBlPXsKWjpmdW5jdGlvbihhKXt2YXIgdD10
-aGlzLmEKcmV0dXJuIHQubGVuZ3RoPT09MD8iRXJyb3IiOiJFcnJvcjogIit0fX0KSC5icS5wcm90b3R5
-cGU9e30KSC5BbS5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtpZih1LlcuYihhKSlpZihhLiR0aHJv
-d25Kc0Vycm9yPT1udWxsKWEuJHRocm93bkpzRXJyb3I9dGhpcy5hCnJldHVybiBhfSwKJFM6MX0KSC5Y
-Ty5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3ZhciB0LHM9dGhpcy5iCmlmKHMhPW51bGwpcmV0dXJu
-IHMKcz10aGlzLmEKdD1zIT09bnVsbCYmdHlwZW9mIHM9PT0ib2JqZWN0Ij9zLnN0YWNrOm51bGwKcmV0
-dXJuIHRoaXMuYj10PT1udWxsPyIiOnR9LAokaUd6OjF9CkguVHAucHJvdG90eXBlPXsKWjpmdW5jdGlv
-bihhKXt2YXIgdD10aGlzLmNvbnN0cnVjdG9yLHM9dD09bnVsbD9udWxsOnQubmFtZQpyZXR1cm4iQ2xv
-c3VyZSAnIitILk5RKHM9PW51bGw/InVua25vd24iOnMpKyInIn0sCiRpRUg6MSwKZ1FsOmZ1bmN0aW9u
-KCl7cmV0dXJuIHRoaXN9LAokQzoiJDEiLAokUjoxLAokRDpudWxsfQpILmxjLnByb3RvdHlwZT17fQpI
-Lnp4LnByb3RvdHlwZT17Clo6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy4kc3RhdGljX25hbWUKaWYodD09
-bnVsbClyZXR1cm4iQ2xvc3VyZSBvZiB1bmtub3duIHN0YXRpYyBtZXRob2QiCnJldHVybiJDbG9zdXJl
-ICciK0guTlEodCkrIicifX0KSC5qeS5wcm90b3R5cGU9ewpETjpmdW5jdGlvbihhLGIpe3ZhciB0PXRo
-aXMKaWYoYj09bnVsbClyZXR1cm4hMQppZih0PT09YilyZXR1cm4hMAppZighKGIgaW5zdGFuY2VvZiBI
-Lmp5KSlyZXR1cm4hMQpyZXR1cm4gdC5hPT09Yi5hJiZ0LmI9PT1iLmImJnQuYz09PWIuY30sCmdpTzpm
-dW5jdGlvbihhKXt2YXIgdCxzPXRoaXMuYwppZihzPT1udWxsKXQ9SC5lUSh0aGlzLmEpCmVsc2UgdD10
-eXBlb2YgcyE9PSJvYmplY3QiP0ouaGYocyk6SC5lUShzKQpyZXR1cm4odF5ILmVRKHRoaXMuYikpPj4+
-MH0sClo6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5jCmlmKHQ9PW51bGwpdD10aGlzLmEKcmV0dXJuIkNs
-b3N1cmUgJyIrSC5kKHRoaXMuZCkrIicgb2YgIisoIkluc3RhbmNlIG9mICciK0guZChILmxoKHQpKSsi
-JyIpfX0KSC5FcS5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3JldHVybiJSdW50aW1lRXJyb3I6ICIr
-SC5kKHRoaXMuYSl9fQpILmtZLnByb3RvdHlwZT17Clo6ZnVuY3Rpb24oYSl7cmV0dXJuIkFzc2VydGlv
-biBmYWlsZWQ6ICIrUC5oKHRoaXMuYSl9fQpILk41LnByb3RvdHlwZT17CmdBOmZ1bmN0aW9uKGEpe3Jl
-dHVybiB0aGlzLmF9LApnbDA6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYT09PTB9LApnVjpmdW5jdGlv
-bigpe3JldHVybiBuZXcgSC5pNSh0aGlzLEguTGgodGhpcykuQygiaTU8MT4iKSl9LAp4NDpmdW5jdGlv
-bihhKXt2YXIgdCxzCmlmKHR5cGVvZiBhPT0ic3RyaW5nIil7dD10aGlzLmIKaWYodD09bnVsbClyZXR1
-cm4hMQpyZXR1cm4gdGhpcy5YdSh0LGEpfWVsc2V7cz10aGlzLkNYKGEpCnJldHVybiBzfX0sCkNYOmZ1
-bmN0aW9uKGEpe3ZhciB0PXRoaXMuZAppZih0PT1udWxsKXJldHVybiExCnJldHVybiB0aGlzLkZoKHRo
-aXMuQnQodCxKLmhmKGEpJjB4M2ZmZmZmZiksYSk+PTB9LApxOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxy
-LHEscD10aGlzLG89bnVsbAppZih0eXBlb2YgYj09InN0cmluZyIpe3Q9cC5iCmlmKHQ9PW51bGwpcmV0
-dXJuIG8Kcz1wLmoyKHQsYikKcj1zPT1udWxsP286cy5iCnJldHVybiByfWVsc2UgaWYodHlwZW9mIGI9
-PSJudW1iZXIiJiYoYiYweDNmZmZmZmYpPT09Yil7cT1wLmMKaWYocT09bnVsbClyZXR1cm4gbwpzPXAu
-ajIocSxiKQpyPXM9PW51bGw/bzpzLmIKcmV0dXJuIHJ9ZWxzZSByZXR1cm4gcC5hYShiKX0sCmFhOmZ1
-bmN0aW9uKGEpe3ZhciB0LHMscj10aGlzLmQKaWYocj09bnVsbClyZXR1cm4gbnVsbAp0PXRoaXMuQnQo
-cixKLmhmKGEpJjB4M2ZmZmZmZikKcz10aGlzLkZoKHQsYSkKaWYoczwwKXJldHVybiBudWxsCnJldHVy
-biB0W3NdLmJ9LApZOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscSxwLG8sbj10aGlzLG09SC5MaChu
-KQptLmMuYShiKQptLlFbMV0uYShjKQppZih0eXBlb2YgYj09InN0cmluZyIpe3Q9bi5iCm4uRUgodD09
-bnVsbD9uLmI9bi56SygpOnQsYixjKX1lbHNlIGlmKHR5cGVvZiBiPT0ibnVtYmVyIiYmKGImMHgzZmZm
-ZmZmKT09PWIpe3M9bi5jCm4uRUgocz09bnVsbD9uLmM9bi56SygpOnMsYixjKX1lbHNle3I9bi5kCmlm
-KHI9PW51bGwpcj1uLmQ9bi56SygpCnE9Si5oZihiKSYweDNmZmZmZmYKcD1uLkJ0KHIscSkKaWYocD09
-bnVsbCluLkVJKHIscSxbbi5IbihiLGMpXSkKZWxzZXtvPW4uRmgocCxiKQppZihvPj0wKXBbb10uYj1j
-CmVsc2UgcC5wdXNoKG4uSG4oYixjKSl9fX0sCks6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHI9dGhpcwpI
-LkxoKHIpLkMoIn4oMSwyKSIpLmEoYikKdD1yLmUKcz1yLnIKZm9yKDt0IT1udWxsOyl7Yi4kMih0LmEs
-dC5iKQppZihzIT09ci5yKXRocm93IEguYihQLmE0KHIpKQp0PXQuY319LApFSDpmdW5jdGlvbihhLGIs
-Yyl7dmFyIHQscz10aGlzLHI9SC5MaChzKQpyLmMuYShiKQpyLlFbMV0uYShjKQp0PXMuajIoYSxiKQpp
-Zih0PT1udWxsKXMuRUkoYSxiLHMuSG4oYixjKSkKZWxzZSB0LmI9Y30sCmtzOmZ1bmN0aW9uKCl7dGhp
-cy5yPXRoaXMucisxJjY3MTA4ODYzfSwKSG46ZnVuY3Rpb24oYSxiKXt2YXIgdCxzPXRoaXMscj1ILkxo
-KHMpLHE9bmV3IEguZGIoci5jLmEoYSksci5RWzFdLmEoYikpCmlmKHMuZT09bnVsbClzLmU9cy5mPXEK
-ZWxzZXt0PXMuZgpxLmQ9dApzLmY9dC5jPXF9KytzLmEKcy5rcygpCnJldHVybiBxfSwKRmg6ZnVuY3Rp
-b24oYSxiKXt2YXIgdCxzCmlmKGE9PW51bGwpcmV0dXJuLTEKdD1hLmxlbmd0aApmb3Iocz0wO3M8dDsr
-K3MpaWYoSi5STShhW3NdLmEsYikpcmV0dXJuIHMKcmV0dXJuLTF9LApaOmZ1bmN0aW9uKGEpe3JldHVy
-biBQLm5PKHRoaXMpfSwKajI6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gYVtiXX0sCkJ0OmZ1bmN0aW9uKGEs
-Yil7cmV0dXJuIGFbYl19LApFSTpmdW5jdGlvbihhLGIsYyl7YVtiXT1jfSwKcm46ZnVuY3Rpb24oYSxi
-KXtkZWxldGUgYVtiXX0sClh1OmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuajIoYSxiKSE9bnVsbH0s
-CnpLOmZ1bmN0aW9uKCl7dmFyIHQ9Ijxub24taWRlbnRpZmllci1rZXk+IixzPU9iamVjdC5jcmVhdGUo
-bnVsbCkKdGhpcy5FSShzLHQscykKdGhpcy5ybihzLHQpCnJldHVybiBzfSwKJGlGbzoxfQpILmRiLnBy
-b3RvdHlwZT17fQpILmk1LnByb3RvdHlwZT17CmdBOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEuYX0s
-CmdsMDpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hLmE9PT0wfSwKZ2t6OmZ1bmN0aW9uKGEpe3ZhciB0
-PXRoaXMuYSxzPW5ldyBILk42KHQsdC5yLHRoaXMuJHRpLkMoIk42PDE+IikpCnMuYz10LmUKcmV0dXJu
-IHN9LAp0ZzpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLmEueDQoYil9fQpILk42LnByb3RvdHlwZT17
-CmdsOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuZH0sCkY6ZnVuY3Rpb24oKXt2YXIgdD10aGlzLHM9dC5h
-CmlmKHQuYiE9PXMucil0aHJvdyBILmIoUC5hNChzKSkKZWxzZXtzPXQuYwppZihzPT1udWxsKXt0LnNx
-WShudWxsKQpyZXR1cm4hMX1lbHNle3Quc3FZKHMuYSkKdC5jPXQuYy5jCnJldHVybiEwfX19LApzcVk6
-ZnVuY3Rpb24oYSl7dGhpcy5kPXRoaXMuJHRpLmMuYShhKX0sCiRpQW46MX0KSC5yLnByb3RvdHlwZT17
-CiQxOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEoYSl9LAokUzoxfQpILmRDLnByb3RvdHlwZT17CiQy
-OmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuYShhLGIpfSwKJFM6NDR9Ckgud04ucHJvdG90eXBlPXsK
-JDE6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYShILmMoYSkpfSwKJFM6NDB9CkguVlIucHJvdG90eXBl
-PXsKWjpmdW5jdGlvbihhKXtyZXR1cm4iUmVnRXhwLyIrdGhpcy5hKyIvIit0aGlzLmIuZmxhZ3N9LApn
-SGM6ZnVuY3Rpb24oKXt2YXIgdD10aGlzLHM9dC5jCmlmKHMhPW51bGwpcmV0dXJuIHMKcz10LmIKcmV0
-dXJuIHQuYz1ILnY0KHQuYSxzLm11bHRpbGluZSwhcy5pZ25vcmVDYXNlLHMudW5pY29kZSxzLmRvdEFs
-bCwhMCl9LApkZDpmdW5jdGlvbihhLGIpe3JldHVybiBuZXcgSC5LVyh0aGlzLGIsMCl9LApVWjpmdW5j
-dGlvbihhLGIpe3ZhciB0LHM9dGhpcy5nSGMoKQpzLmxhc3RJbmRleD1iCnQ9cy5leGVjKGEpCmlmKHQ9
-PW51bGwpcmV0dXJuIG51bGwKcmV0dXJuIG5ldyBILkVLKHQpfSwKJGl2WDoxLAokaXdMOjF9CkguRUsu
-cHJvdG90eXBlPXsKcTpmdW5jdGlvbihhLGIpe3ZhciB0CkguV1koYikKdD10aGlzLmIKaWYoYj49dC5s
-ZW5ndGgpcmV0dXJuIEguayh0LGIpCnJldHVybiB0W2JdfSwKJGlPZDoxLAokaWliOjF9CkguS1cucHJv
-dG90eXBlPXsKZ2t6OmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgSC5QYih0aGlzLmEsdGhpcy5iLHRoaXMu
-Yyl9fQpILlBiLnByb3RvdHlwZT17CmdsOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuZH0sCkY6ZnVuY3Rp
-b24oKXt2YXIgdCxzLHIscSxwPXRoaXMsbz1wLmIKaWYobz09bnVsbClyZXR1cm4hMQp0PXAuYwppZih0
-PD1vLmxlbmd0aCl7cz1wLmEKcj1zLlVaKG8sdCkKaWYociE9bnVsbCl7cC5kPXIKbz1yLmIKdD1vLmlu
-ZGV4CnE9dCtvWzBdLmxlbmd0aAppZih0PT09cSl7aWYocy5iLnVuaWNvZGUpe289cC5jCnQ9bysxCnM9
-cC5iCmlmKHQ8cy5sZW5ndGgpe289Si5yWShzKS5tKHMsbykKaWYobz49NTUyOTYmJm88PTU2MzE5KXtv
-PUMueEIubShzLHQpCm89bz49NTYzMjAmJm88PTU3MzQzfWVsc2Ugbz0hMX1lbHNlIG89ITF9ZWxzZSBv
-PSExCnE9KG8/cSsxOnEpKzF9cC5jPXEKcmV0dXJuITB9fXAuYj1wLmQ9bnVsbApyZXR1cm4hMX0sCiRp
-QW46MX0KSC50US5wcm90b3R5cGU9ewpxOmZ1bmN0aW9uKGEsYil7SC5XWShiKQppZihiIT09MClILnZo
-KFAuTzcoYixudWxsKSkKcmV0dXJuIHRoaXMuY30sCiRpT2Q6MX0KSC5ORi5wcm90b3R5cGU9ewpna3o6
-ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBILlNkKHRoaXMuYSx0aGlzLmIsdGhpcy5jKX19CkguU2QucHJv
-dG90eXBlPXsKRjpmdW5jdGlvbigpe3ZhciB0LHMscj10aGlzLHE9ci5jLHA9ci5iLG89cC5sZW5ndGgs
-bj1yLmEsbT1uLmxlbmd0aAppZihxK28+bSl7ci5kPW51bGwKcmV0dXJuITF9dD1uLmluZGV4T2YocCxx
-KQppZih0PDApe3IuYz1tKzEKci5kPW51bGwKcmV0dXJuITF9cz10K28Kci5kPW5ldyBILnRRKHQscCkK
-ci5jPXM9PT1yLmM/cysxOnMKcmV0dXJuITB9LApnbDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmR9LAok
-aUFuOjF9CkguZUgucHJvdG90eXBlPXskaWVIOjEsJGllcToxfQpILkxaLnByb3RvdHlwZT17CmdBOmZ1
-bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH0sCiRpWGo6MX0KSC5EZy5wcm90b3R5cGU9ewpxOmZ1bmN0
-aW9uKGEsYil7SC5XWShiKQpILm9kKGIsYSxhLmxlbmd0aCkKcmV0dXJuIGFbYl19LApZOmZ1bmN0aW9u
-KGEsYixjKXtILmRqKGMpCkgub2QoYixhLGEubGVuZ3RoKQphW2JdPWN9LAokaWJROjEsCiRpY1g6MSwK
-JGl6TToxfQpILlBnLnByb3RvdHlwZT17Clk6ZnVuY3Rpb24oYSxiLGMpe0guV1koYykKSC5vZChiLGEs
-YS5sZW5ndGgpCmFbYl09Y30sCiRpYlE6MSwKJGljWDoxLAokaXpNOjF9CkgueGoucHJvdG90eXBlPXsK
-cTpmdW5jdGlvbihhLGIpe0guV1koYikKSC5vZChiLGEsYS5sZW5ndGgpCnJldHVybiBhW2JdfX0KSC5k
-RS5wcm90b3R5cGU9ewpxOmZ1bmN0aW9uKGEsYil7SC5XWShiKQpILm9kKGIsYSxhLmxlbmd0aCkKcmV0
-dXJuIGFbYl19fQpILlpBLnByb3RvdHlwZT17CnE6ZnVuY3Rpb24oYSxiKXtILldZKGIpCkgub2QoYixh
-LGEubGVuZ3RoKQpyZXR1cm4gYVtiXX19Ckgud2YucHJvdG90eXBlPXsKcTpmdW5jdGlvbihhLGIpe0gu
-V1koYikKSC5vZChiLGEsYS5sZW5ndGgpCnJldHVybiBhW2JdfX0KSC5QcS5wcm90b3R5cGU9ewpxOmZ1
-bmN0aW9uKGEsYil7SC5XWShiKQpILm9kKGIsYSxhLmxlbmd0aCkKcmV0dXJuIGFbYl19fQpILmVFLnBy
-b3RvdHlwZT17CmdBOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH0sCnE6ZnVuY3Rpb24oYSxiKXtI
-LldZKGIpCkgub2QoYixhLGEubGVuZ3RoKQpyZXR1cm4gYVtiXX19CkguVjYucHJvdG90eXBlPXsKZ0E6
-ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofSwKcTpmdW5jdGlvbihhLGIpe0guV1koYikKSC5vZChi
-LGEsYS5sZW5ndGgpCnJldHVybiBhW2JdfSwKJGlWNjoxLAokaW42OjF9CkguUkcucHJvdG90eXBlPXt9
-CkguVlAucHJvdG90eXBlPXt9CkguV0IucHJvdG90eXBlPXt9CkguWkcucHJvdG90eXBlPXt9CkguSmMu
-cHJvdG90eXBlPXsKQzpmdW5jdGlvbihhKXtyZXR1cm4gSC5jRSh2LnR5cGVVbml2ZXJzZSx0aGlzLGEp
-fSwKS3E6ZnVuY3Rpb24oYSl7cmV0dXJuIEgudjUodi50eXBlVW5pdmVyc2UsdGhpcyxhKX19CkguRVQu
-cHJvdG90eXBlPXt9CkgudTkucHJvdG90eXBlPXsKWjpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hfX0K
-SC54LnByb3RvdHlwZT17fQpQLnRoLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMu
-YSxzPXQuYQp0LmE9bnVsbApzLiQwKCl9LAokUzoxMH0KUC5oYS5wcm90b3R5cGU9ewokMTpmdW5jdGlv
-bihhKXt2YXIgdCxzCnRoaXMuYS5hPXUuTS5hKGEpCnQ9dGhpcy5iCnM9dGhpcy5jCnQuZmlyc3RDaGls
-ZD90LnJlbW92ZUNoaWxkKHMpOnQuYXBwZW5kQ2hpbGQocyl9LAokUzoyMH0KUC5Wcy5wcm90b3R5cGU9
-ewokMDpmdW5jdGlvbigpe3RoaXMuYS4kMCgpfSwKJEM6IiQwIiwKJFI6MCwKJFM6MH0KUC5GdC5wcm90
-b3R5cGU9ewokMDpmdW5jdGlvbigpe3RoaXMuYS4kMCgpfSwKJEM6IiQwIiwKJFI6MCwKJFM6MH0KUC5X
-My5wcm90b3R5cGU9ewpDWTpmdW5jdGlvbihhLGIpe2lmKHNlbGYuc2V0VGltZW91dCE9bnVsbClzZWxm
-LnNldFRpbWVvdXQoSC50UihuZXcgUC55SCh0aGlzLGIpLDApLGEpCmVsc2UgdGhyb3cgSC5iKFAuTDQo
-ImBzZXRUaW1lb3V0KClgIG5vdCBmb3VuZC4iKSl9fQpQLnlILnByb3RvdHlwZT17CiQwOmZ1bmN0aW9u
-KCl7dGhpcy5iLiQwKCl9LAokQzoiJDAiLAokUjowLAokUzoyfQpQLmloLnByb3RvdHlwZT17CmFNOmZ1
-bmN0aW9uKGEsYil7dmFyIHQscyxyPXRoaXMuJHRpCnIuQygiMS8iKS5hKGIpCnQ9IXRoaXMuYnx8ci5D
-KCJiODwxPiIpLmIoYikKcz10aGlzLmEKaWYodClzLlhmKGIpCmVsc2Ugcy5YMihyLmMuYShiKSl9LAp3
-MDpmdW5jdGlvbihhLGIpe3ZhciB0CmlmKGI9PW51bGwpYj1QLnYwKGEpCnQ9dGhpcy5hCmlmKHRoaXMu
-Yil0LlpMKGEsYikKZWxzZSB0Lk5rKGEsYil9fQpQLldNLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEp
-e3JldHVybiB0aGlzLmEuJDIoMCxhKX0sCiRTOjQ5fQpQLlNYLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9u
-KGEsYil7dGhpcy5hLiQyKDEsbmV3IEguYnEoYSx1LmwuYShiKSkpfSwKJEM6IiQyIiwKJFI6MiwKJFM6
-MjF9ClAuR3MucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt0aGlzLmEoSC5XWShhKSxiKX0sCiRT
-OjI2fQpQLkZ5LnByb3RvdHlwZT17Clo6ZnVuY3Rpb24oYSl7cmV0dXJuIkl0ZXJhdGlvbk1hcmtlcigi
-K3RoaXMuYisiLCAiK0guZCh0aGlzLmEpKyIpIn19ClAuR1YucHJvdG90eXBlPXsKZ2w6ZnVuY3Rpb24o
-KXt2YXIgdD10aGlzLmMKaWYodD09bnVsbClyZXR1cm4gdGhpcy5iCnJldHVybiB0aGlzLiR0aS5jLmEo
-dC5nbCgpKX0sCkY6ZnVuY3Rpb24oKXt2YXIgdCxzLHIscSxwPXRoaXMKZm9yKDshMDspe3Q9cC5jCmlm
-KHQhPW51bGwpaWYodC5GKCkpcmV0dXJuITAKZWxzZSBwLmM9bnVsbApzPWZ1bmN0aW9uKGEsYixjKXt2
-YXIgbyxuPWIKd2hpbGUodHJ1ZSl0cnl7cmV0dXJuIGEobixvKX1jYXRjaChtKXtvPW0Kbj1jfX0ocC5h
-LDAsMSkKaWYocyBpbnN0YW5jZW9mIFAuRnkpe3I9cy5iCmlmKHI9PT0yKXt0PXAuZAppZih0PT1udWxs
-fHx0Lmxlbmd0aD09PTApe3Auc0VDKG51bGwpCnJldHVybiExfWlmKDA+PXQubGVuZ3RoKXJldHVybiBI
-LmsodCwtMSkKcC5hPXQucG9wKCkKY29udGludWV9ZWxzZXt0PXMuYQppZihyPT09Myl0aHJvdyB0CmVs
-c2V7cT1KLklUKHQpCmlmKHEgaW5zdGFuY2VvZiBQLkdWKXt0PXAuZAppZih0PT1udWxsKXQ9cC5kPVtd
-CkMuTm0uaSh0LHAuYSkKcC5hPXEuYQpjb250aW51ZX1lbHNle3AuYz1xCmNvbnRpbnVlfX19fWVsc2V7
-cC5zRUMocykKcmV0dXJuITB9fXJldHVybiExfSwKc0VDOmZ1bmN0aW9uKGEpe3RoaXMuYj10aGlzLiR0
-aS5jLmEoYSl9LAokaUFuOjF9ClAucTQucHJvdG90eXBlPXsKZ2t6OmZ1bmN0aW9uKGEpe3JldHVybiBu
-ZXcgUC5HVih0aGlzLmEoKSx0aGlzLiR0aS5DKCJHVjwxPiIpKX19ClAuYjgucHJvdG90eXBlPXt9ClAu
-UGYucHJvdG90eXBlPXsKdzA6ZnVuY3Rpb24oYSxiKXt2YXIgdApQLlVJKGEsImVycm9yIix1LkspCnQ9
-dGhpcy5hCmlmKHQuYSE9PTApdGhyb3cgSC5iKFAuUFYoIkZ1dHVyZSBhbHJlYWR5IGNvbXBsZXRlZCIp
-KQp0Lk5rKGEsYj09bnVsbD9QLnYwKGEpOmIpfSwKcG06ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMudzAo
-YSxudWxsKX19ClAuWmYucHJvdG90eXBlPXsKYU06ZnVuY3Rpb24oYSxiKXt2YXIgdAp0aGlzLiR0aS5D
-KCIxLyIpLmEoYikKdD10aGlzLmEKaWYodC5hIT09MCl0aHJvdyBILmIoUC5QVigiRnV0dXJlIGFscmVh
-ZHkgY29tcGxldGVkIikpCnQuWGYoYil9fQpQLkZlLnByb3RvdHlwZT17CkhSOmZ1bmN0aW9uKGEpe2lm
-KCh0aGlzLmMmMTUpIT09NilyZXR1cm4hMApyZXR1cm4gdGhpcy5iLmIuYnYodS5hbC5hKHRoaXMuZCks
-YS5hLHUueSx1LkspfSwKS3c6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5lLHM9dS56LHI9dS5LLHE9dGhp
-cy4kdGkuQygiMi8iKSxwPXRoaXMuYi5iCmlmKHUuYWcuYih0KSlyZXR1cm4gcS5hKHAucnAodCxhLmEs
-YS5iLHMscix1LmwpKQplbHNlIHJldHVybiBxLmEocC5idih1LmJJLmEodCksYS5hLHMscikpfX0KUC52
-cy5wcm90b3R5cGU9ewpTcTpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHE9dGhpcy4kdGkKcS5LcShj
-KS5DKCIxLygyKSIpLmEoYSkKdD0kLlgzCmlmKHQhPT1DLk5VKXtjLkMoIkA8MC8+IikuS3EocS5jKS5D
-KCIxKDIpIikuYShhKQppZihiIT1udWxsKWI9UC5WSChiLHQpfXM9bmV3IFAudnMoJC5YMyxjLkMoInZz
-PDA+IikpCnI9Yj09bnVsbD8xOjMKdGhpcy54ZihuZXcgUC5GZShzLHIsYSxiLHEuQygiQDwxPiIpLktx
-KGMpLkMoIkZlPDEsMj4iKSkpCnJldHVybiBzfSwKVzc6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5T
-cShhLG51bGwsYil9LApRZDpmdW5jdGlvbihhLGIsYyl7dmFyIHQscz10aGlzLiR0aQpzLktxKGMpLkMo
-IjEvKDIpIikuYShhKQp0PW5ldyBQLnZzKCQuWDMsYy5DKCJ2czwwPiIpKQp0aGlzLnhmKG5ldyBQLkZl
-KHQsMTksYSxiLHMuQygiQDwxPiIpLktxKGMpLkMoIkZlPDEsMj4iKSkpCnJldHVybiB0fSwKeGY6ZnVu
-Y3Rpb24oYSl7dmFyIHQscz10aGlzLHI9cy5hCmlmKHI8PTEpe2EuYT11LnguYShzLmMpCnMuYz1hfWVs
-c2V7aWYocj09PTIpe3Q9dS5fLmEocy5jKQpyPXQuYQppZihyPDQpe3QueGYoYSkKcmV0dXJufXMuYT1y
-CnMuYz10LmN9UC5UayhudWxsLG51bGwscy5iLHUuTS5hKG5ldyBQLmRhKHMsYSkpKX19LApqUTpmdW5j
-dGlvbihhKXt2YXIgdCxzLHIscSxwLG89dGhpcyxuPXt9Cm4uYT1hCmlmKGE9PW51bGwpcmV0dXJuCnQ9
-by5hCmlmKHQ8PTEpe3M9dS54LmEoby5jKQpyPW8uYz1hCmlmKHMhPW51bGwpe2Zvcig7cT1yLmEscSE9
-bnVsbDtyPXEpO3IuYT1zfX1lbHNle2lmKHQ9PT0yKXtwPXUuXy5hKG8uYykKdD1wLmEKaWYodDw0KXtw
-LmpRKGEpCnJldHVybn1vLmE9dApvLmM9cC5jfW4uYT1vLk44KGEpClAuVGsobnVsbCxudWxsLG8uYix1
-Lk0uYShuZXcgUC5vUShuLG8pKSl9fSwKYWg6ZnVuY3Rpb24oKXt2YXIgdD11LnguYSh0aGlzLmMpCnRo
-aXMuYz1udWxsCnJldHVybiB0aGlzLk44KHQpfSwKTjg6ZnVuY3Rpb24oYSl7dmFyIHQscyxyCmZvcih0
-PWEscz1udWxsO3QhPW51bGw7cz10LHQ9cil7cj10LmEKdC5hPXN9cmV0dXJuIHN9LApISDpmdW5jdGlv
-bihhKXt2YXIgdCxzPXRoaXMscj1zLiR0aQpyLkMoIjEvIikuYShhKQppZihyLkMoImI4PDE+IikuYihh
-KSlpZihyLmIoYSkpUC5BOShhLHMpCmVsc2UgUC5rMyhhLHMpCmVsc2V7dD1zLmFoKCkKci5jLmEoYSkK
-cy5hPTQKcy5jPWEKUC5IWihzLHQpfX0sClgyOmZ1bmN0aW9uKGEpe3ZhciB0LHM9dGhpcwpzLiR0aS5j
-LmEoYSkKdD1zLmFoKCkKcy5hPTQKcy5jPWEKUC5IWihzLHQpfSwKWkw6ZnVuY3Rpb24oYSxiKXt2YXIg
-dCxzLHI9dGhpcwp1LmwuYShiKQp0PXIuYWgoKQpzPVAuVGwoYSxiKQpyLmE9OApyLmM9cwpQLkhaKHIs
-dCl9LApYZjpmdW5jdGlvbihhKXt2YXIgdD10aGlzLHM9dC4kdGkKcy5DKCIxLyIpLmEoYSkKaWYocy5D
-KCJiODwxPiIpLmIoYSkpe3QuY1UoYSkKcmV0dXJufXQuYT0xClAuVGsobnVsbCxudWxsLHQuYix1Lk0u
-YShuZXcgUC5ySCh0LGEpKSl9LApjVTpmdW5jdGlvbihhKXt2YXIgdD10aGlzLHM9dC4kdGkKcy5DKCJi
-ODwxPiIpLmEoYSkKaWYocy5iKGEpKXtpZihhLmE9PT04KXt0LmE9MQpQLlRrKG51bGwsbnVsbCx0LmIs
-dS5NLmEobmV3IFAuS0YodCxhKSkpfWVsc2UgUC5BOShhLHQpCnJldHVybn1QLmszKGEsdCl9LApOazpm
-dW5jdGlvbihhLGIpe3RoaXMuYT0xClAuVGsobnVsbCxudWxsLHRoaXMuYix1Lk0uYShuZXcgUC5aTCh0
-aGlzLGEsYikpKX0sCiRpYjg6MX0KUC5kYS5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigpe1AuSFoodGhp
-cy5hLHRoaXMuYil9LAokUzowfQpQLm9RLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7UC5IWih0aGlz
-LmIsdGhpcy5hLmEpfSwKJFM6MH0KUC5wVi5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgdD10
-aGlzLmEKdC5hPTAKdC5ISChhKX0sCiRTOjEwfQpQLlU3LnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEs
-Yil7dS5sLmEoYikKdGhpcy5hLlpMKGEsYil9LAokMTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy4kMihh
-LG51bGwpfSwKJEM6IiQyIiwKJEQ6ZnVuY3Rpb24oKXtyZXR1cm5bbnVsbF19LAokUzoyOX0KUC52ci5w
-cm90b3R5cGU9ewokMDpmdW5jdGlvbigpe3RoaXMuYS5aTCh0aGlzLmIsdGhpcy5jKX0sCiRTOjB9ClAu
-ckgucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXt2YXIgdD10aGlzLmEKdC5YMih0LiR0aS5jLmEodGhp
-cy5iKSl9LAokUzowfQpQLktGLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7UC5BOSh0aGlzLmIsdGhp
-cy5hKX0sCiRTOjB9ClAuWkwucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXt0aGlzLmEuWkwodGhpcy5i
-LHRoaXMuYyl9LAokUzowfQpQLlJULnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7dmFyIHQscyxyLHEs
-cCxvLG49dGhpcyxtPW51bGwKdHJ5e3I9bi5jCm09ci5iLmIuenoodS5mTy5hKHIuZCksdS56KX1jYXRj
-aChxKXt0PUguUnUocSkKcz1ILnRzKHEpCmlmKG4uZCl7cj11Lm4uYShuLmEuYS5jKS5hCnA9dApwPXI9
-PW51bGw/cD09bnVsbDpyPT09cApyPXB9ZWxzZSByPSExCnA9bi5iCmlmKHIpcC5iPXUubi5hKG4uYS5h
-LmMpCmVsc2UgcC5iPVAuVGwodCxzKQpwLmE9ITAKcmV0dXJufWlmKHUuYy5iKG0pKXtpZihtIGluc3Rh
-bmNlb2YgUC52cyYmbS5hPj00KXtpZihtLmE9PT04KXtyPW4uYgpyLmI9dS5uLmEobS5jKQpyLmE9ITB9
-cmV0dXJufW89bi5hLmEKcj1uLmIKci5iPW0uVzcobmV3IFAualoobyksdS56KQpyLmE9ITF9fSwKJFM6
-Mn0KUC5qWi5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hfSwKJFM6Mzl9ClAu
-cnEucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXt2YXIgdCxzLHIscSxwLG8sbixtPXRoaXMKdHJ5e3I9
-bS5iCnE9ci4kdGkKcD1xLmMKbz1wLmEobS5jKQptLmEuYj1yLmIuYi5idihxLkMoIjIvKDEpIikuYShy
-LmQpLG8scS5DKCIyLyIpLHApfWNhdGNoKG4pe3Q9SC5SdShuKQpzPUgudHMobikKcj1tLmEKci5iPVAu
-VGwodCxzKQpyLmE9ITB9fSwKJFM6Mn0KUC5SVy5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigpe3ZhciB0
-LHMscixxLHAsbyxuLG0sbD10aGlzCnRyeXt0PXUubi5hKGwuYS5hLmMpCnE9bC5jCmlmKEgub1QocS5I
-Uih0KSkmJnEuZSE9bnVsbCl7cD1sLmIKcC5iPXEuS3codCkKcC5hPSExfX1jYXRjaChvKXtzPUguUnUo
-bykKcj1ILnRzKG8pCnE9dS5uLmEobC5hLmEuYykKcD1xLmEKbj1zCm09bC5iCmlmKHA9PW51bGw/bj09
-bnVsbDpwPT09biltLmI9cQplbHNlIG0uYj1QLlRsKHMscikKbS5hPSEwfX0sCiRTOjJ9ClAuT00ucHJv
-dG90eXBlPXt9ClAucWgucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7dmFyIHQscyxyPXRoaXMscT17
-fSxwPW5ldyBQLnZzKCQuWDMsdS5mSikKcS5hPTAKdD1ILkxoKHIpCnM9dC5DKCJ+KDEpIikuYShuZXcg
-UC5CNShxLHIpKQp1Lk0uYShuZXcgUC51TyhxLHApKQpXLkpFKHIuYSxyLmIscywhMSx0LmMpCnJldHVy
-biBwfX0KUC5CNS5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtILkxoKHRoaXMuYikuYy5hKGEpOysr
-dGhpcy5hLmF9LAokUzpmdW5jdGlvbigpe3JldHVybiBILkxoKHRoaXMuYikuQygiYzgoMSkiKX19ClAu
-dU8ucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXt0aGlzLmIuSEgodGhpcy5hLmEpfSwKJFM6MH0KUC5N
-Ty5wcm90b3R5cGU9e30KUC5rVC5wcm90b3R5cGU9e30KUC54SS5wcm90b3R5cGU9e30KUC5PSC5wcm90
-b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3JldHVybiBILmQodGhpcy5hKX0sCiRpWFM6MSwKZ0lJOmZ1bmN0
-aW9uKCl7cmV0dXJuIHRoaXMuYn19ClAubTAucHJvdG90eXBlPXskaUpCOjF9ClAucEsucHJvdG90eXBl
-PXsKJDA6ZnVuY3Rpb24oKXt2YXIgdCxzPXRoaXMuYSxyPXMuYgppZihyPT1udWxsKXRocm93IEguYihz
-LmEpCnQ9SC5iKHMuYSkKdC5zdGFjaz1yLlooMCkKdGhyb3cgdH0sCiRTOjB9ClAuSmkucHJvdG90eXBl
-PXsKYkg6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHE9bnVsbAp1Lk0uYShhKQp0cnl7aWYoQy5OVT09PSQu
-WDMpe2EuJDAoKQpyZXR1cm59UC5UOChxLHEsdGhpcyxhLHUuSCl9Y2F0Y2gocil7dD1ILlJ1KHIpCnM9
-SC50cyhyKQpQLkwyKHEscSx0aGlzLHQsdS5sLmEocykpfX0sCkRsOmZ1bmN0aW9uKGEsYixjKXt2YXIg
-dCxzLHIscT1udWxsCmMuQygifigwKSIpLmEoYSkKYy5hKGIpCnRyeXtpZihDLk5VPT09JC5YMyl7YS4k
-MShiKQpyZXR1cm59UC55dihxLHEsdGhpcyxhLGIsdS5ILGMpfWNhdGNoKHIpe3Q9SC5SdShyKQpzPUgu
-dHMocikKUC5MMihxLHEsdGhpcyx0LHUubC5hKHMpKX19LApSVDpmdW5jdGlvbihhLGIpe3JldHVybiBu
-ZXcgUC5oaih0aGlzLGIuQygiMCgpIikuYShhKSxiKX0sCkdZOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcg
-UC5WcCh0aGlzLHUuTS5hKGEpKX0sClB5OmZ1bmN0aW9uKGEsYil7cmV0dXJuIG5ldyBQLk9SKHRoaXMs
-Yi5DKCJ+KDApIikuYShhKSxiKX0sCnE6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gbnVsbH0sCnp6OmZ1bmN0
-aW9uKGEsYil7Yi5DKCIwKCkiKS5hKGEpCmlmKCQuWDM9PT1DLk5VKXJldHVybiBhLiQwKCkKcmV0dXJu
-IFAuVDgobnVsbCxudWxsLHRoaXMsYSxiKX0sCmJ2OmZ1bmN0aW9uKGEsYixjLGQpe2MuQygiQDwwPiIp
-LktxKGQpLkMoIjEoMikiKS5hKGEpCmQuYShiKQppZigkLlgzPT09Qy5OVSlyZXR1cm4gYS4kMShiKQpy
-ZXR1cm4gUC55dihudWxsLG51bGwsdGhpcyxhLGIsYyxkKX0sCnJwOmZ1bmN0aW9uKGEsYixjLGQsZSxm
-KXtkLkMoIkA8MD4iKS5LcShlKS5LcShmKS5DKCIxKDIsMykiKS5hKGEpCmUuYShiKQpmLmEoYykKaWYo
-JC5YMz09PUMuTlUpcmV0dXJuIGEuJDIoYixjKQpyZXR1cm4gUC5ReChudWxsLG51bGwsdGhpcyxhLGIs
-YyxkLGUsZil9LApMajpmdW5jdGlvbihhLGIsYyxkKXtyZXR1cm4gYi5DKCJAPDA+IikuS3EoYykuS3Eo
-ZCkuQygiMSgyLDMpIikuYShhKX19ClAuaGoucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXtyZXR1cm4g
-dGhpcy5hLnp6KHRoaXMuYix0aGlzLmMpfSwKJFM6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5jLkMoIjAo
-KSIpfX0KUC5WcC5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmEuYkgodGhpcy5i
-KX0sCiRTOjJ9ClAuT1IucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5jCnJldHVy
-biB0aGlzLmEuRGwodGhpcy5iLHQuYShhKSx0KX0sCiRTOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuYy5D
-KCJ+KDApIil9fQpQLmI2LnByb3RvdHlwZT17CmdrejpmdW5jdGlvbihhKXt2YXIgdD10aGlzLHM9bmV3
-IFAubG0odCx0LnIsSC5MaCh0KS5DKCJsbTwxPiIpKQpzLmM9dC5lCnJldHVybiBzfSwKZ0E6ZnVuY3Rp
-b24oYSl7cmV0dXJuIHRoaXMuYX0sCnRnOmZ1bmN0aW9uKGEsYil7dmFyIHQscwppZih0eXBlb2YgYj09
-InN0cmluZyImJmIhPT0iX19wcm90b19fIil7dD10aGlzLmIKaWYodD09bnVsbClyZXR1cm4hMQpyZXR1
-cm4gdS5ELmEodFtiXSkhPW51bGx9ZWxzZXtzPXRoaXMuUFIoYikKcmV0dXJuIHN9fSwKUFI6ZnVuY3Rp
-b24oYSl7dmFyIHQ9dGhpcy5kCmlmKHQ9PW51bGwpcmV0dXJuITEKcmV0dXJuIHRoaXMuREYodFt0aGlz
-Lk4oYSldLGEpPj0wfSwKaTpmdW5jdGlvbihhLGIpe3ZhciB0LHMscj10aGlzCkguTGgocikuYy5hKGIp
-CmlmKHR5cGVvZiBiPT0ic3RyaW5nIiYmYiE9PSJfX3Byb3RvX18iKXt0PXIuYgpyZXR1cm4gci5iUSh0
-PT1udWxsP3IuYj1QLlQyKCk6dCxiKX1lbHNlIGlmKHR5cGVvZiBiPT0ibnVtYmVyIiYmKGImMTA3Mzc0
-MTgyMyk9PT1iKXtzPXIuYwpyZXR1cm4gci5iUShzPT1udWxsP3IuYz1QLlQyKCk6cyxiKX1lbHNlIHJl
-dHVybiByLkI3KGIpfSwKQjc6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHE9dGhpcwpILkxoKHEpLmMuYShh
-KQp0PXEuZAppZih0PT1udWxsKXQ9cS5kPVAuVDIoKQpzPXEuTihhKQpyPXRbc10KaWYocj09bnVsbCl0
-W3NdPVtxLnlvKGEpXQplbHNle2lmKHEuREYocixhKT49MClyZXR1cm4hMQpyLnB1c2gocS55byhhKSl9
-cmV0dXJuITB9LApSOmZ1bmN0aW9uKGEsYil7dmFyIHQ9dGhpcwppZih0eXBlb2YgYj09InN0cmluZyIm
-JmIhPT0iX19wcm90b19fIilyZXR1cm4gdC5INCh0LmIsYikKZWxzZSBpZih0eXBlb2YgYj09Im51bWJl
-ciImJihiJjEwNzM3NDE4MjMpPT09YilyZXR1cm4gdC5INCh0LmMsYikKZWxzZSByZXR1cm4gdC5xZyhi
-KX0sCnFnOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHA9dGhpcyxvPXAuZAppZihvPT1udWxsKXJldHVy
-biExCnQ9cC5OKGEpCnM9b1t0XQpyPXAuREYocyxhKQppZihyPDApcmV0dXJuITEKcT1zLnNwbGljZShy
-LDEpWzBdCmlmKDA9PT1zLmxlbmd0aClkZWxldGUgb1t0XQpwLkdTKHEpCnJldHVybiEwfSwKYlE6ZnVu
-Y3Rpb24oYSxiKXtILkxoKHRoaXMpLmMuYShiKQppZih1LkQuYShhW2JdKSE9bnVsbClyZXR1cm4hMQph
-W2JdPXRoaXMueW8oYikKcmV0dXJuITB9LApINDpmdW5jdGlvbihhLGIpe3ZhciB0CmlmKGE9PW51bGwp
-cmV0dXJuITEKdD11LkQuYShhW2JdKQppZih0PT1udWxsKXJldHVybiExCnRoaXMuR1ModCkKZGVsZXRl
-IGFbYl0KcmV0dXJuITB9LApTOmZ1bmN0aW9uKCl7dGhpcy5yPTEwNzM3NDE4MjMmdGhpcy5yKzF9LAp5
-bzpmdW5jdGlvbihhKXt2YXIgdCxzPXRoaXMscj1uZXcgUC5ibihILkxoKHMpLmMuYShhKSkKaWYocy5l
-PT1udWxsKXMuZT1zLmY9cgplbHNle3Q9cy5mCnIuYz10CnMuZj10LmI9cn0rK3MuYQpzLlMoKQpyZXR1
-cm4gcn0sCkdTOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMscz1hLmMscj1hLmIKaWYocz09bnVsbCl0LmU9
-cgplbHNlIHMuYj1yCmlmKHI9PW51bGwpdC5mPXMKZWxzZSByLmM9czstLXQuYQp0LlMoKX0sCk46ZnVu
-Y3Rpb24oYSl7cmV0dXJuIEouaGYoYSkmMTA3Mzc0MTgyM30sCkRGOmZ1bmN0aW9uKGEsYil7dmFyIHQs
-cwppZihhPT1udWxsKXJldHVybi0xCnQ9YS5sZW5ndGgKZm9yKHM9MDtzPHQ7KytzKWlmKEouUk0oYVtz
-XS5hLGIpKXJldHVybiBzCnJldHVybi0xfX0KUC5ibi5wcm90b3R5cGU9e30KUC5sbS5wcm90b3R5cGU9
-ewpnbDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmR9LApGOmZ1bmN0aW9uKCl7dmFyIHQ9dGhpcyxzPXQu
-YQppZih0LmIhPT1zLnIpdGhyb3cgSC5iKFAuYTQocykpCmVsc2V7cz10LmMKaWYocz09bnVsbCl7dC5z
-aihudWxsKQpyZXR1cm4hMX1lbHNle3Quc2oodC4kdGkuYy5hKHMuYSkpCnQuYz10LmMuYgpyZXR1cm4h
-MH19fSwKc2o6ZnVuY3Rpb24oYSl7dGhpcy5kPXRoaXMuJHRpLmMuYShhKX0sCiRpQW46MX0KUC5tVy5w
-cm90b3R5cGU9e30KUC51eS5wcm90b3R5cGU9eyRpYlE6MSwkaWNYOjEsJGl6TToxfQpQLmxELnByb3Rv
-dHlwZT17CmdrejpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IEguYTcoYSx0aGlzLmdBKGEpLEgucShhKS5D
-KCJhNzxsRC5FPiIpKX0sCkU6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5xKGEsYil9LApLOmZ1bmN0
-aW9uKGEsYil7dmFyIHQscwpILnEoYSkuQygifihsRC5FKSIpLmEoYikKdD10aGlzLmdBKGEpCmZvcihz
-PTA7czx0Oysrcyl7Yi4kMSh0aGlzLnEoYSxzKSkKaWYodCE9PXRoaXMuZ0EoYSkpdGhyb3cgSC5iKFAu
-YTQoYSkpfX0sCmdvcjpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5nQShhKSE9PTB9LApFMjpmdW5jdGlv
-bihhLGIsYyl7dmFyIHQ9SC5xKGEpCnJldHVybiBuZXcgSC5sSihhLHQuS3EoYykuQygiMShsRC5FKSIp
-LmEoYiksdC5DKCJAPGxELkU+IikuS3EoYykuQygibEo8MSwyPiIpKX0sCmR1OmZ1bmN0aW9uKGEsYixj
-LGQpe3ZhciB0CkgucShhKS5DKCJsRC5FIikuYShkKQpQLmpCKGIsYyx0aGlzLmdBKGEpKQpmb3IodD1i
-O3Q8YzsrK3QpdGhpcy5ZKGEsdCxkKX0sClo6ZnVuY3Rpb24oYSl7cmV0dXJuIFAuV0UoYSwiWyIsIl0i
-KX19ClAuaWwucHJvdG90eXBlPXt9ClAucmEucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt2YXIg
-dCxzPXRoaXMuYQppZighcy5hKXRoaXMuYi5hKz0iLCAiCnMuYT0hMQpzPXRoaXMuYgp0PXMuYSs9SC5k
-KGEpCnMuYT10KyI6ICIKcy5hKz1ILmQoYil9LAokUzo0fQpQLllrLnByb3RvdHlwZT17Cks6ZnVuY3Rp
-b24oYSxiKXt2YXIgdCxzCkguTGgodGhpcykuQygifihZay5LLFlrLlYpIikuYShiKQpmb3IodD1KLklU
-KHRoaXMuZ1YoKSk7dC5GKCk7KXtzPXQuZ2woKQpiLiQyKHMsdGhpcy5xKDAscykpfX0sCmdQdTpmdW5j
-dGlvbihhKXtyZXR1cm4gSi5NMSh0aGlzLmdWKCksbmV3IFAueVEodGhpcyksSC5MaCh0aGlzKS5DKCJO
-MzxZay5LLFlrLlY+IikpfSwKeDQ6ZnVuY3Rpb24oYSl7cmV0dXJuIEouemwodGhpcy5nVigpLGEpfSwK
-Z0E6ZnVuY3Rpb24oYSl7cmV0dXJuIEouSCh0aGlzLmdWKCkpfSwKZ2wwOmZ1bmN0aW9uKGEpe3JldHVy
-biBKLkNpKHRoaXMuZ1YoKSl9LApaOmZ1bmN0aW9uKGEpe3JldHVybiBQLm5PKHRoaXMpfSwKJGlaMDox
-fQpQLnlRLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuYSxzPUguTGgodCkKcy5D
-KCJZay5LIikuYShhKQpyZXR1cm4gbmV3IFAuTjMoYSx0LnEoMCxhKSxzLkMoIkA8WWsuSz4iKS5LcShz
-LkMoIllrLlYiKSkuQygiTjM8MSwyPiIpKX0sCiRTOmZ1bmN0aW9uKCl7cmV0dXJuIEguTGgodGhpcy5h
-KS5DKCJOMzxZay5LLFlrLlY+KFlrLkspIil9fQpQLktQLnByb3RvdHlwZT17Clk6ZnVuY3Rpb24oYSxi
-LGMpe3ZhciB0PUguTGgodGhpcykKdC5jLmEoYikKdC5RWzFdLmEoYykKdGhyb3cgSC5iKFAuTDQoIkNh
-bm5vdCBtb2RpZnkgdW5tb2RpZmlhYmxlIG1hcCIpKX19ClAuUG4ucHJvdG90eXBlPXsKcTpmdW5jdGlv
-bihhLGIpe3JldHVybiB0aGlzLmEucSgwLGIpfSwKWTpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9SC5MaCh0
-aGlzKQp0aGlzLmEuWSgwLHQuYy5hKGIpLHQuUVsxXS5hKGMpKX0sCng0OmZ1bmN0aW9uKGEpe3JldHVy
-biB0aGlzLmEueDQoYSl9LApLOmZ1bmN0aW9uKGEsYil7dGhpcy5hLksoMCxILkxoKHRoaXMpLkMoIn4o
-MSwyKSIpLmEoYikpfSwKZ2wwOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuYQpyZXR1cm4gdC5nbDAodCl9
-LApnQTpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmEKcmV0dXJuIHQuZ0EodCl9LApaOmZ1bmN0aW9uKGEp
-e3JldHVybiBKLkFjKHRoaXMuYSl9LApnUHU6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5hCnJldHVybiB0
-LmdQdSh0KX0sCiRpWjA6MX0KUC5Hai5wcm90b3R5cGU9e30KUC5NYS5wcm90b3R5cGU9ewpaOmZ1bmN0
-aW9uKGEpe3JldHVybiBQLldFKHRoaXMsInsiLCJ9Iil9fQpQLlZqLnByb3RvdHlwZT17JGliUToxLCRp
-Y1g6MSwkaXh1OjF9ClAuWHYucHJvdG90eXBlPXsKRlY6ZnVuY3Rpb24oYSxiKXt2YXIgdApmb3IodD1K
-LklUKEguTGgodGhpcykuQygiY1g8MT4iKS5hKGIpKTt0LkYoKTspdGhpcy5pKDAsdC5nbCgpKX0sClo6
-ZnVuY3Rpb24oYSl7cmV0dXJuIFAuV0UodGhpcywieyIsIn0iKX0sCkg6ZnVuY3Rpb24oYSxiKXt2YXIg
-dCxzPVAucmoodGhpcyx0aGlzLnIsSC5MaCh0aGlzKS5jKQppZighcy5GKCkpcmV0dXJuIiIKaWYoYj09
-PSIiKXt0PSIiCmRvIHQrPUguZChzLmQpCndoaWxlKHMuRigpKX1lbHNle3Q9SC5kKHMuZCkKZm9yKDtz
-LkYoKTspdD10K2IrSC5kKHMuZCl9cmV0dXJuIHQuY2hhckNvZGVBdCgwKT09MD90OnR9LAokaWJROjEs
-CiRpY1g6MSwKJGl4dToxfQpQLm5ZLnByb3RvdHlwZT17fQpQLlRDLnByb3RvdHlwZT17fQpQLlJVLnBy
-b3RvdHlwZT17fQpQLnV3LnByb3RvdHlwZT17CnE6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzPXRoaXMuYgpp
-ZihzPT1udWxsKXJldHVybiB0aGlzLmMucSgwLGIpCmVsc2UgaWYodHlwZW9mIGIhPSJzdHJpbmciKXJl
-dHVybiBudWxsCmVsc2V7dD1zW2JdCnJldHVybiB0eXBlb2YgdD09InVuZGVmaW5lZCI/dGhpcy5mYihi
-KTp0fX0sCmdBOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmI9PW51bGw/dGhpcy5jLmE6dGhpcy5DZigp
-Lmxlbmd0aH0sCmdsMDpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5nQSh0aGlzKT09PTB9LApnVjpmdW5j
-dGlvbigpe2lmKHRoaXMuYj09bnVsbCl7dmFyIHQ9dGhpcy5jCnJldHVybiBuZXcgSC5pNSh0LEguTGgo
-dCkuQygiaTU8MT4iKSl9cmV0dXJuIG5ldyBQLmk4KHRoaXMpfSwKWTpmdW5jdGlvbihhLGIsYyl7dmFy
-IHQscyxyPXRoaXMKaWYoci5iPT1udWxsKXIuYy5ZKDAsYixjKQplbHNlIGlmKHIueDQoYikpe3Q9ci5i
-CnRbYl09YwpzPXIuYQppZihzPT1udWxsP3QhPW51bGw6cyE9PXQpc1tiXT1udWxsfWVsc2Ugci5YSygp
-LlkoMCxiLGMpfSwKeDQ6ZnVuY3Rpb24oYSl7aWYodGhpcy5iPT1udWxsKXJldHVybiB0aGlzLmMueDQo
-YSkKcmV0dXJuIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0aGlzLmEsYSl9LApL
-OmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEscD10aGlzCnUuY0EuYShiKQppZihwLmI9PW51bGwpcmV0
-dXJuIHAuYy5LKDAsYikKdD1wLkNmKCkKZm9yKHM9MDtzPHQubGVuZ3RoOysrcyl7cj10W3NdCnE9cC5i
-W3JdCmlmKHR5cGVvZiBxPT0idW5kZWZpbmVkIil7cT1QLlFlKHAuYVtyXSkKcC5iW3JdPXF9Yi4kMihy
-LHEpCmlmKHQhPT1wLmMpdGhyb3cgSC5iKFAuYTQocCkpfX0sCkNmOmZ1bmN0aW9uKCl7dmFyIHQ9dS5q
-LmEodGhpcy5jKQppZih0PT1udWxsKXQ9dGhpcy5jPUguVk0oT2JqZWN0LmtleXModGhpcy5hKSx1LnMp
-CnJldHVybiB0fSwKWEs6ZnVuY3Rpb24oKXt2YXIgdCxzLHIscSxwLG89dGhpcwppZihvLmI9PW51bGwp
-cmV0dXJuIG8uYwp0PVAuRmwodS5OLHUueikKcz1vLkNmKCkKZm9yKHI9MDtxPXMubGVuZ3RoLHI8cTsr
-K3Ipe3A9c1tyXQp0LlkoMCxwLG8ucSgwLHApKX1pZihxPT09MClDLk5tLmkocyxudWxsKQplbHNlIEMu
-Tm0uc0EocywwKQpvLmE9by5iPW51bGwKcmV0dXJuIG8uYz10fSwKZmI6ZnVuY3Rpb24oYSl7dmFyIHQK
-aWYoIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0aGlzLmEsYSkpcmV0dXJuIG51
-bGwKdD1QLlFlKHRoaXMuYVthXSkKcmV0dXJuIHRoaXMuYlthXT10fX0KUC5pOC5wcm90b3R5cGU9ewpn
-QTpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmEKcmV0dXJuIHQuZ0EodCl9LApFOmZ1bmN0aW9uKGEsYil7
-dmFyIHQ9dGhpcy5hCmlmKHQuYj09bnVsbCl0PXQuZ1YoKS5FKDAsYikKZWxzZXt0PXQuQ2YoKQppZihi
-PDB8fGI+PXQubGVuZ3RoKXJldHVybiBILmsodCxiKQp0PXRbYl19cmV0dXJuIHR9LApna3o6ZnVuY3Rp
-b24oYSl7dmFyIHQ9dGhpcy5hCmlmKHQuYj09bnVsbCl7dD10LmdWKCkKdD10Lmdreih0KX1lbHNle3Q9
-dC5DZigpCnQ9bmV3IEoubTEodCx0Lmxlbmd0aCxILnQ2KHQpLkMoIm0xPDE+IikpfXJldHVybiB0fSwK
-dGc6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5hLng0KGIpfX0KUC5DVi5wcm90b3R5cGU9ewp5cjpm
+LlE9Xy56PV8ueT1fLng9bnVsbH0sClJaOmZ1bmN0aW9uIFJaKCl7fSwKTUU6ZnVuY3Rpb24gTUUoYSxi
+KXt0aGlzLmE9YQp0aGlzLmI9Yn0sCnk1OmZ1bmN0aW9uIHk1KGEpe3RoaXMuYT1hfSwKUEU6ZnVuY3Rp
+b24gUEUoYSxiLGMpe3RoaXMuYT1hCnRoaXMuYj1iCnRoaXMuYz1jfSwKcTM6ZnVuY3Rpb24gcTMoKXt9
+LAp5STpmdW5jdGlvbiB5SShhKXt0aGlzLmE9YX0sCmM2OmZ1bmN0aW9uIGM2KCl7fSwKcWQ6ZnVuY3Rp
+b24gcWQoKXt9LApVZjpmdW5jdGlvbiBVZihhLGIsYyxkLGUsZixnLGgpe3ZhciBfPXRoaXMKXy5hPWEK
+Xy5iPWIKXy5jPWMKXy5kPWQKXy5lPWUKXy5mPWYKXy5yPWcKXy54PWgKXy55PW51bGx9LApxZTpmdW5j
+dGlvbiBxZShhLGIsYyxkLGUsZixnKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8uZD1kCl8u
+ZT1lCl8uZj1mCl8ucj1nCl8uUT1fLno9Xy55PV8ueD1udWxsfSwKaUo6ZnVuY3Rpb24gaUooKXt9LApq
+ZzpmdW5jdGlvbiBqZyhhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKVGE6ZnVuY3Rpb24gVGEoYSxiKXt0
+aGlzLmE9YQp0aGlzLmI9Yn0sCkJmOmZ1bmN0aW9uIEJmKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApB
+czpmdW5jdGlvbiBBcygpe30sCkdFOmZ1bmN0aW9uIEdFKGEpe3RoaXMuYT1hfSwKTjc6ZnVuY3Rpb24g
+TjcoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCnVROmZ1bmN0aW9uIHVRKCl7fSwKaEY6ZnVuY3Rpb24g
+aEYoKXt9LApSNDpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzLHIKSC55OChiKQp1LmIuYShkKQppZihI
+Lm9UKGIpKXt0PVtjXQpDLk5tLkZWKHQsZCkKZD10fXM9dS56CnI9UC5DSChKLk0xKGQsUC53MCgpLHMp
+LCEwLHMpCnUuWS5hKGEpCnJldHVybiBQLndZKEguRWsoYSxyLG51bGwpKX0sCkRtOmZ1bmN0aW9uKGEs
+YixjKXt2YXIgdAp0cnl7aWYoT2JqZWN0LmlzRXh0ZW5zaWJsZShhKSYmIU9iamVjdC5wcm90b3R5cGUu
+aGFzT3duUHJvcGVydHkuY2FsbChhLGIpKXtPYmplY3QuZGVmaW5lUHJvcGVydHkoYSxiLHt2YWx1ZTpj
+fSkKcmV0dXJuITB9fWNhdGNoKHQpe0guUnUodCl9cmV0dXJuITF9LApPbTpmdW5jdGlvbihhLGIpe2lm
+KE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChhLGIpKXJldHVybiBhW2JdCnJldHVy
+biBudWxsfSwKd1k6ZnVuY3Rpb24oYSl7aWYoYT09bnVsbHx8dHlwZW9mIGE9PSJzdHJpbmcifHx0eXBl
+b2YgYT09Im51bWJlciJ8fEgubChhKSlyZXR1cm4gYQppZihhIGluc3RhbmNlb2YgUC5FNClyZXR1cm4g
+YS5hCmlmKEguUjkoYSkpcmV0dXJuIGEKaWYodS54LmIoYSkpcmV0dXJuIGEKaWYoYSBpbnN0YW5jZW9m
+IFAuaVApcmV0dXJuIEgubzIoYSkKaWYodS5ZLmIoYSkpcmV0dXJuIFAuaEUoYSwiJGRhcnRfanNGdW5j
+dGlvbiIsbmV3IFAuUEMoKSkKcmV0dXJuIFAuaEUoYSwiXyRkYXJ0X2pzT2JqZWN0IixuZXcgUC5tdCgk
+LmtJKCkpKX0sCmhFOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1QLk9tKGEsYikKaWYodD09bnVsbCl7dD1j
+LiQxKGEpClAuRG0oYSxiLHQpfXJldHVybiB0fSwKZFU6ZnVuY3Rpb24oYSl7dmFyIHQscwppZihhPT1u
+dWxsfHx0eXBlb2YgYT09InN0cmluZyJ8fHR5cGVvZiBhPT0ibnVtYmVyInx8dHlwZW9mIGE9PSJib29s
+ZWFuIilyZXR1cm4gYQplbHNlIGlmKGEgaW5zdGFuY2VvZiBPYmplY3QmJkguUjkoYSkpcmV0dXJuIGEK
+ZWxzZSBpZihhIGluc3RhbmNlb2YgT2JqZWN0JiZ1LnguYihhKSlyZXR1cm4gYQplbHNlIGlmKGEgaW5z
+dGFuY2VvZiBEYXRlKXt0PUgudVAoYS5nZXRUaW1lKCkpCmlmKE1hdGguYWJzKHQpPD04NjRlMTMpcz0h
+MQplbHNlIHM9ITAKaWYocylILnZoKFAueFkoIkRhdGVUaW1lIGlzIG91dHNpZGUgdmFsaWQgcmFuZ2U6
+ICIrdCkpClAuVUkoITEsImlzVXRjIix1LnkpCnJldHVybiBuZXcgUC5pUCh0LCExKX1lbHNlIGlmKGEu
+Y29uc3RydWN0b3I9PT0kLmtJKCkpcmV0dXJuIGEubwplbHNlIHJldHVybiBQLk5EKGEpfSwKTkQ6ZnVu
+Y3Rpb24oYSl7aWYodHlwZW9mIGE9PSJmdW5jdGlvbiIpcmV0dXJuIFAuaVEoYSwkLncoKSxuZXcgUC5O
+eigpKQppZihhIGluc3RhbmNlb2YgQXJyYXkpcmV0dXJuIFAuaVEoYSwkLlI4KCksbmV3IFAuUVMoKSkK
+cmV0dXJuIFAuaVEoYSwkLlI4KCksbmV3IFAubnAoKSl9LAppUTpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9
+UC5PbShhLGIpCmlmKHQ9PW51bGx8fCEoYSBpbnN0YW5jZW9mIE9iamVjdCkpe3Q9Yy4kMShhKQpQLkRt
+KGEsYix0KX1yZXR1cm4gdH0sClBDOmZ1bmN0aW9uIFBDKCl7fSwKbXQ6ZnVuY3Rpb24gbXQoYSl7dGhp
+cy5hPWF9LApOejpmdW5jdGlvbiBOeigpe30sClFTOmZ1bmN0aW9uIFFTKCl7fSwKbnA6ZnVuY3Rpb24g
+bnAoKXt9LApFNDpmdW5jdGlvbiBFNChhKXt0aGlzLmE9YX0sCnI3OmZ1bmN0aW9uIHI3KGEpe3RoaXMu
+YT1hfSwKVHo6ZnVuY3Rpb24gVHooYSxiKXt0aGlzLmE9YQp0aGlzLiR0aT1ifSwKY286ZnVuY3Rpb24g
+Y28oKXt9LApiQjpmdW5jdGlvbiBiQigpe30sCktlOmZ1bmN0aW9uIEtlKGEpe3RoaXMuYT1hfSwKZDU6
+ZnVuY3Rpb24gZDUoKXt9LApuNjpmdW5jdGlvbiBuNigpe319LFc9ewp4MzpmdW5jdGlvbigpe3JldHVy
+biB3aW5kb3d9LApacjpmdW5jdGlvbigpe3JldHVybiBkb2N1bWVudH0sCko2OmZ1bmN0aW9uKGEpe3Zh
+ciB0PWRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoImEiKQppZihhIT1udWxsKXQuaHJlZj1hCnJldHVybiB0
+fSwKVTk6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHM9ZG9jdW1lbnQuYm9keQpzLnRvU3RyaW5nCnQ9Qy5S
+WS5yNihzLGEsYixjKQp0LnRvU3RyaW5nCnM9dS5hYwpzPW5ldyBILlU1KG5ldyBXLmU3KHQpLHMuQygi
+YTIobEQuRSkiKS5hKG5ldyBXLkN2KCkpLHMuQygiVTU8bEQuRT4iKSkKcmV0dXJuIHUuaC5hKHMuZ3I4
+KHMpKX0sCnJTOmZ1bmN0aW9uKGEpe3ZhciB0LHMscj0iZWxlbWVudCB0YWcgdW5hdmFpbGFibGUiCnRy
+eXt0PUouWUUoYSkKaWYodHlwZW9mIHQuZ25zKGEpPT0ic3RyaW5nIilyPXQuZ25zKGEpfWNhdGNoKHMp
+e0guUnUocyl9cmV0dXJuIHJ9LApDMDpmdW5jdGlvbihhLGIpe2E9NTM2ODcwOTExJmErYgphPTUzNjg3
+MDkxMSZhKygoNTI0Mjg3JmEpPDwxMCkKcmV0dXJuIGFeYT4+PjZ9LApyRTpmdW5jdGlvbihhLGIsYyxk
+KXt2YXIgdD1XLkMwKFcuQzAoVy5DMChXLkMwKDAsYSksYiksYyksZCkscz01MzY4NzA5MTEmdCsoKDY3
+MTA4ODYzJnQpPDwzKQpzXj1zPj4+MTEKcmV0dXJuIDUzNjg3MDkxMSZzKygoMTYzODMmcyk8PDE1KX0s
+ClROOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyPWEuY2xhc3NMaXN0CmZvcih0PWIubGVuZ3RoLHM9MDtz
+PGIubGVuZ3RoO2IubGVuZ3RoPT09dHx8KDAsSC5saykoYiksKytzKXIuYWRkKGJbc10pfSwKSkU6ZnVu
+Y3Rpb24oYSxiLGMsZCxlKXt2YXIgdD1XLmFGKG5ldyBXLnZOKGMpLHUuQikKaWYodCE9bnVsbCYmITAp
+Si5kWihhLGIsdCwhMSkKcmV0dXJuIG5ldyBXLnhDKGEsYix0LCExLGUuQygieEM8MD4iKSl9LApUdzpm
+dW5jdGlvbihhKXt2YXIgdD1XLko2KG51bGwpLHM9d2luZG93LmxvY2F0aW9uCnQ9bmV3IFcuSlEobmV3
+IFcubWsodCxzKSkKdC5DWShhKQpyZXR1cm4gdH0sCnFEOmZ1bmN0aW9uKGEsYixjLGQpe3UuaC5hKGEp
+CkguaChiKQpILmgoYykKdS5jci5hKGQpCnJldHVybiEwfSwKUVc6ZnVuY3Rpb24oYSxiLGMsZCl7dmFy
+IHQscyxyCnUuaC5hKGEpCkguaChiKQpILmgoYykKdD11LmNyLmEoZCkuYQpzPXQuYQpzLmhyZWY9Ywpy
+PXMuaG9zdG5hbWUKdD10LmIKaWYoIShyPT10Lmhvc3RuYW1lJiZzLnBvcnQ9PXQucG9ydCYmcy5wcm90
+b2NvbD09dC5wcm90b2NvbCkpaWYocj09PSIiKWlmKHMucG9ydD09PSIiKXt0PXMucHJvdG9jb2wKdD10
+PT09IjoifHx0PT09IiJ9ZWxzZSB0PSExCmVsc2UgdD0hMQplbHNlIHQ9ITAKcmV0dXJuIHR9LApCbDpm
+dW5jdGlvbigpe3ZhciB0PXUuTixzPVAudE0oQy5ReCx0KSxyPXUuZDAuYShuZXcgVy5JQSgpKSxxPUgu
+Vk0oWyJURU1QTEFURSJdLHUucykKdD1uZXcgVy5jdChzLFAuTHModCksUC5Mcyh0KSxQLkxzKHQpLG51
+bGwpCnQuQ1kobnVsbCxuZXcgSC5sSihDLlF4LHIsdS5maikscSxudWxsKQpyZXR1cm4gdH0sClB2OmZ1
+bmN0aW9uKGEpe2lmKGE9PW51bGwpcmV0dXJuIG51bGwKcmV0dXJuIFcuUDEoYSl9LApxYzpmdW5jdGlv
+bihhKXt2YXIgdAppZihhPT1udWxsKXJldHVybiBudWxsCmlmKCJwb3N0TWVzc2FnZSIgaW4gYSl7dD1X
+LlAxKGEpCmlmKHUuYVMuYih0KSlyZXR1cm4gdApyZXR1cm4gbnVsbH1lbHNlIHJldHVybiB1LmNoLmEo
+YSl9LApQMTpmdW5jdGlvbihhKXtpZihhPT09d2luZG93KXJldHVybiB1LmNpLmEoYSkKZWxzZSByZXR1
+cm4gbmV3IFcuZFcoYSl9LApISDpmdW5jdGlvbihhKXtpZihhPT09d2luZG93LmxvY2F0aW9uKXJldHVy
+biBhCmVsc2UgcmV0dXJuIG5ldyBXLkZiKCl9LAphRjpmdW5jdGlvbihhLGIpe3ZhciB0PSQuWDMKaWYo
+dD09PUMuTlUpcmV0dXJuIGEKcmV0dXJuIHQuUHkoYSxiKX0sCnFFOmZ1bmN0aW9uIHFFKCl7fSwKR2g6
+ZnVuY3Rpb24gR2goKXt9LApmWTpmdW5jdGlvbiBmWSgpe30sCm5COmZ1bmN0aW9uIG5CKCl7fSwKQXo6
+ZnVuY3Rpb24gQXooKXt9LApRUDpmdW5jdGlvbiBRUCgpe30sCm54OmZ1bmN0aW9uIG54KCl7fSwKb0o6
+ZnVuY3Rpb24gb0ooKXt9LAppZDpmdW5jdGlvbiBpZCgpe30sClFGOmZ1bmN0aW9uIFFGKCl7fSwKTmg6
+ZnVuY3Rpb24gTmgoKXt9LAphZTpmdW5jdGlvbiBhZSgpe30sCklCOmZ1bmN0aW9uIElCKCl7fSwKbjc6
+ZnVuY3Rpb24gbjcoKXt9LAp3ejpmdW5jdGlvbiB3eihhLGIpe3RoaXMuYT1hCnRoaXMuJHRpPWJ9LApj
+djpmdW5jdGlvbiBjdigpe30sCkN2OmZ1bmN0aW9uIEN2KCl7fSwKZWE6ZnVuY3Rpb24gZWEoKXt9LApE
+MDpmdW5jdGlvbiBEMCgpe30sCmhIOmZ1bmN0aW9uIGhIKCl7fSwKaDQ6ZnVuY3Rpb24gaDQoKXt9LApi
+cjpmdW5jdGlvbiBicigpe30sClZiOmZ1bmN0aW9uIFZiKCl7fSwKZko6ZnVuY3Rpb24gZkooKXt9LAp3
+YTpmdW5jdGlvbiB3YSgpe30sClNnOmZ1bmN0aW9uIFNnKCl7fSwKdTg6ZnVuY3Rpb24gdTgoKXt9LApB
+ajpmdW5jdGlvbiBBaigpe30sCmU3OmZ1bmN0aW9uIGU3KGEpe3RoaXMuYT1hfSwKdUg6ZnVuY3Rpb24g
+dUgoKXt9LApCSDpmdW5jdGlvbiBCSCgpe30sClNOOmZ1bmN0aW9uIFNOKCl7fSwKZXc6ZnVuY3Rpb24g
+ZXcoKXt9LApscDpmdW5jdGlvbiBscCgpe30sClRiOmZ1bmN0aW9uIFRiKCl7fSwKSXY6ZnVuY3Rpb24g
+SXYoKXt9LApXUDpmdW5jdGlvbiBXUCgpe30sCnlZOmZ1bmN0aW9uIHlZKCl7fSwKdzY6ZnVuY3Rpb24g
+dzYoKXt9LApLNTpmdW5jdGlvbiBLNSgpe30sCkNtOmZ1bmN0aW9uIENtKCl7fSwKQ1E6ZnVuY3Rpb24g
+Q1EoKXt9LAp3NDpmdW5jdGlvbiB3NCgpe30sCnJoOmZ1bmN0aW9uIHJoKCl7fSwKY2Y6ZnVuY3Rpb24g
+Y2YoKXt9LAppNzpmdW5jdGlvbiBpNyhhKXt0aGlzLmE9YX0sClN5OmZ1bmN0aW9uIFN5KGEpe3RoaXMu
+YT1hfSwKS1M6ZnVuY3Rpb24gS1MoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCkEzOmZ1bmN0aW9uIEEz
+KGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApJNDpmdW5jdGlvbiBJNChhKXt0aGlzLmE9YX0sCkZrOmZ1
+bmN0aW9uIEZrKGEsYil7dGhpcy5hPWEKdGhpcy4kdGk9Yn0sClJPOmZ1bmN0aW9uIFJPKGEsYixjLGQp
+e3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPWMKXy4kdGk9ZH0sCmV1OmZ1bmN0aW9uIGV1KGEsYixj
+LGQpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPWMKXy4kdGk9ZH0sCnhDOmZ1bmN0aW9uIHhDKGEs
+YixjLGQsZSl7dmFyIF89dGhpcwpfLmI9YQpfLmM9YgpfLmQ9YwpfLmU9ZApfLiR0aT1lfSwKdk46ZnVu
+Y3Rpb24gdk4oYSl7dGhpcy5hPWF9LApKUTpmdW5jdGlvbiBKUShhKXt0aGlzLmE9YX0sCkdtOmZ1bmN0
+aW9uIEdtKCl7fSwKdkQ6ZnVuY3Rpb24gdkQoYSl7dGhpcy5hPWF9LApVdjpmdW5jdGlvbiBVdihhKXt0
+aGlzLmE9YX0sCkVnOmZ1bmN0aW9uIEVnKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30s
+Cm02OmZ1bmN0aW9uIG02KCl7fSwKRW86ZnVuY3Rpb24gRW8oKXt9LApXazpmdW5jdGlvbiBXaygpe30s
+CmN0OmZ1bmN0aW9uIGN0KGEsYixjLGQsZSl7dmFyIF89dGhpcwpfLmU9YQpfLmE9YgpfLmI9YwpfLmM9
+ZApfLmQ9ZX0sCklBOmZ1bmN0aW9uIElBKCl7fSwKT3c6ZnVuY3Rpb24gT3coKXt9LApXOTpmdW5jdGlv
+biBXOShhLGIsYyl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmM9LTEKXy5kPW51bGwKXy4kdGk9Y30s
+CmRXOmZ1bmN0aW9uIGRXKGEpe3RoaXMuYT1hfSwKRmI6ZnVuY3Rpb24gRmIoKXt9LAprRjpmdW5jdGlv
+biBrRigpe30sCm1rOmZ1bmN0aW9uIG1rKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApLbzpmdW5jdGlv
+biBLbyhhKXt0aGlzLmE9YQp0aGlzLmI9ITF9LApmbTpmdW5jdGlvbiBmbShhKXt0aGlzLmE9YX0sCkxl
+OmZ1bmN0aW9uIExlKCl7fSwKSzc6ZnVuY3Rpb24gSzcoKXt9LApyQjpmdW5jdGlvbiByQigpe30sClhX
+OmZ1bmN0aW9uIFhXKCl7fSwKb2E6ZnVuY3Rpb24gb2EoKXt9fSxNPXsKT1g6ZnVuY3Rpb24oYSl7c3dp
+dGNoKGEpe2Nhc2UgQy5BZDpyZXR1cm4iQWRkIC8qPyovIGhpbnQiCmNhc2UgQy5uZTpyZXR1cm4iQWRk
+IC8qISovIGhpbnQiCmNhc2UgQy53VjpyZXR1cm4iUmVtb3ZlIC8qPyovIGhpbnQiCmNhc2UgQy5mUjpy
+ZXR1cm4iUmVtb3ZlIC8qISovIGhpbnQiCmNhc2UgQy5teTpyZXR1cm4iQ2hhbmdlIHRvIC8qPyovIGhp
+bnQiCmNhc2UgQy5yeDpyZXR1cm4iQ2hhbmdlIHRvIC8qISovIGhpbnQifXJldHVybiBudWxsfSwKSDc6
+ZnVuY3Rpb24gSDcoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCllGOmZ1bmN0aW9uKGEsYil7dmFyIHQs
+cyxyLHEscCxvLG4KZm9yKHQ9Yi5sZW5ndGgscz0xO3M8dDsrK3Mpe2lmKGJbc109PW51bGx8fGJbcy0x
+XSE9bnVsbCljb250aW51ZQpmb3IoO3Q+PTE7dD1yKXtyPXQtMQppZihiW3JdIT1udWxsKWJyZWFrfXE9
+bmV3IFAuUm4oIiIpCnA9YSsiKCIKcS5hPXAKbz1ILnFDKGIsMCx0LEgudDYoYikuYykKbj1vLiR0aQpu
+PXArbmV3IEgubEoobyxuLkMoInFVKihhTC5FKSIpLmEobmV3IE0uTm8oKSksbi5DKCJsSjxhTC5FLHFV
+Kj4iKSkuSCgwLCIsICIpCnEuYT1uCnEuYT1uKygiKTogcGFydCAiKyhzLTEpKyIgd2FzIG51bGwsIGJ1
+dCBwYXJ0ICIrcysiIHdhcyBub3QuIikKdGhyb3cgSC5iKFAueFkocS53KDApKSl9fSwKbEk6ZnVuY3Rp
+b24gbEkoYSl7dGhpcy5hPWF9LApNaTpmdW5jdGlvbiBNaSgpe30sCnE3OmZ1bmN0aW9uIHE3KCl7fSwK
+Tm86ZnVuY3Rpb24gTm8oKXt9fSxVPXsKbno6ZnVuY3Rpb24oYSl7dmFyIHQ9SC51UChhLnEoMCwibm9k
+ZUlkIikpCnJldHVybiBuZXcgVS5MTChDLk5tLkh0KEMucmssbmV3IFUuTUQoYSkpLHQpfSwKTEw6ZnVu
+Y3Rpb24gTEwoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCk1EOmZ1bmN0aW9uIE1EKGEpe3RoaXMuYT1h
+fSwKamY6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEKaWYoYT09bnVsbCl0PW51bGwKZWxzZXt0PUguVk0o
+W10sdS5kNykKZm9yKHM9Si5JVCh1LlUuYShhKSk7cy5GKCk7KXtyPXMuZ2woKQpxPUouVTYocikKQy5O
+bS5pKHQsbmV3IFUuU2UoSC5oKHEucShyLCJkZXNjcmlwdGlvbiIpKSxILmgocS5xKHIsImhyZWYiKSkp
+KX19cmV0dXJuIHR9LApOZDpmdW5jdGlvbihhKXt2YXIgdCxzCmlmKGE9PW51bGwpdD1udWxsCmVsc2V7
+dD1ILlZNKFtdLHUuYUEpCmZvcihzPUouSVQodS5VLmEoYSkpO3MuRigpOylDLk5tLmkodCxVLk5mKHMu
+Z2woKSkpfXJldHVybiB0fSwKTmY6ZnVuY3Rpb24oYSl7dmFyIHQ9Si5VNihhKSxzPUguaCh0LnEoYSwi
+ZGVzY3JpcHRpb24iKSkscj1ILlZNKFtdLHUuYUopCmZvcih0PUouSVQodS5VLmEodC5xKGEsImVudHJp
+ZXMiKSkpO3QuRigpOylDLk5tLmkocixVLlJqKHQuZ2woKSkpCnJldHVybiBuZXcgVS55RChzLHIpfSwK
+Umo6ZnVuY3Rpb24oYSl7dmFyIHQscz1KLlU2KGEpLHI9SC5oKHMucShhLCJkZXNjcmlwdGlvbiIpKSxx
+PUguaChzLnEoYSwiZnVuY3Rpb24iKSkscD1zLnEoYSwibGluayIpCmlmKHA9PW51bGwpcD1udWxsCmVs
+c2V7dD1KLlU2KHApCnA9bmV3IFUuTWwoSC5oKHQucShwLCJocmVmIikpLEgudVAodC5xKHAsImxpbmUi
+KSksSC5oKHQucShwLCJwYXRoIikpKX1zPXUuZksuYShzLnEoYSwiaGludEFjdGlvbnMiKSkKcz1zPT1u
+dWxsP251bGw6Si5NMShzLG5ldyBVLmFOKCksdS5hWCkKcz1zPT1udWxsP251bGw6UC5DSChzLCEwLHMu
+JHRpLkMoImFMLkUiKSkKcmV0dXJuIG5ldyBVLndiKHIscSxwLHM9PW51bGw/Qy5kbjpzKX0sCmQyOmZ1
+bmN0aW9uIGQyKGEsYixjLGQsZSxmKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8uZD1kCl8u
+ZT1lCl8uZj1mfSwKU2U6ZnVuY3Rpb24gU2UoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCk1sOmZ1bmN0
+aW9uIE1sKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sCnlEOmZ1bmN0aW9uIHlEKGEs
+Yil7dGhpcy5hPWEKdGhpcy5iPWJ9LAp3YjpmdW5jdGlvbiB3YihhLGIsYyxkKXt2YXIgXz10aGlzCl8u
+YT1hCl8uYj1iCl8uYz1jCl8uZD1kfSwKYU46ZnVuY3Rpb24gYU4oKXt9LApiMDpmdW5jdGlvbiBiMCgp
+e319LEI9ewpZZjpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwLG8sbixtLGw9SC5oKGEucSgwLCJyZWdp
+b25zIikpLGs9SC5oKGEucSgwLCJuYXZpZ2F0aW9uQ29udGVudCIpKSxqPUguaChhLnEoMCwic291cmNl
+Q29kZSIpKSxpPVAuRmwodS5YLHUuZF8pCmZvcih0PXUudC5hKGEucSgwLCJlZGl0cyIpKSx0PXQuZ1B1
+KHQpLHQ9dC5na3oodCkscz11LlUscj11Lmg0O3QuRigpOyl7cT10LmdsKCkKcD1xLmEKbz1ILlZNKFtd
+LHIpCmZvcihxPUouSVQocy5hKHEuYikpO3EuRigpOyl7bj1xLmdsKCkKbT1KLlU2KG4pCkMuTm0uaShv
+LG5ldyBCLmo4KEgudVAobS5xKG4sImxpbmUiKSksSC5oKG0ucShuLCJleHBsYW5hdGlvbiIpKSxILnVQ
+KG0ucShuLCJvZmZzZXQiKSkpKX1pLlkoMCxwLG8pfXJldHVybiBuZXcgQi5xcChsLGssaixpKX0sCmo4
+OmZ1bmN0aW9uIGo4KGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sCnFwOmZ1bmN0aW9u
+IHFwKGEsYixjLGQpe3ZhciBfPXRoaXMKXy5hPWEKXy5iPWIKXy5jPWMKXy5kPWR9LApmdjpmdW5jdGlv
+biBmdigpe30sCk9TOmZ1bmN0aW9uKGEpe3ZhciB0CmlmKCEoYT49NjUmJmE8PTkwKSl0PWE+PTk3JiZh
+PD0xMjIKZWxzZSB0PSEwCnJldHVybiB0fSwKWXU6ZnVuY3Rpb24oYSxiKXt2YXIgdD1hLmxlbmd0aCxz
+PWIrMgppZih0PHMpcmV0dXJuITEKaWYoIUIuT1MoQy54Qi5tKGEsYikpKXJldHVybiExCmlmKEMueEIu
+bShhLGIrMSkhPT01OClyZXR1cm4hMQppZih0PT09cylyZXR1cm4hMApyZXR1cm4gQy54Qi5tKGEscyk9
+PT00N319LFQ9e21ROmZ1bmN0aW9uIG1RKCl7fX0sTD17CklxOmZ1bmN0aW9uKCl7Qy5CWi5CKGRvY3Vt
+ZW50LCJET01Db250ZW50TG9hZGVkIixuZXcgTC5lKCkpCkMub2wuQih3aW5kb3csInBvcHN0YXRlIixu
+ZXcgTC5MKCkpfSwKa3o6ZnVuY3Rpb24oYSl7dmFyIHQscz11LmcuYShhLnBhcmVudE5vZGUpLnF1ZXJ5
+U2VsZWN0b3IoIjpzY29wZSA+IHVsIikscj1zLnN0eWxlLHE9IiIrQy5DRC56UShzLm9mZnNldEhlaWdo
+dCkqMisicHgiCnIubWF4SGVpZ2h0PXEKcj1KLnFGKGEpCnE9ci4kdGkKdD1xLkMoIn4oMSk/IikuYShu
+ZXcgTC5XeChzLGEpKQp1LlouYShudWxsKQpXLkpFKHIuYSxyLmIsdCwhMSxxLmMpfSwKeVg6ZnVuY3Rp
+b24oYSxiKXt2YXIgdCxzLHIscSxwLG8sbj0icXVlcnlTZWxlY3RvckFsbCIsbT1kb2N1bWVudC5xdWVy
+eVNlbGVjdG9yKGEpLGw9dS5nCm0udG9TdHJpbmcKdD11LmgKSC5EaChsLHQsIlQiLG4pCnM9dS5SCnI9
+bmV3IFcud3oobS5xdWVyeVNlbGVjdG9yQWxsKCIubmF2LWxpbmsiKSxzKQpyLksocixuZXcgTC5BTyhi
+KSkKSC5EaChsLHQsIlQiLG4pCnE9bmV3IFcud3oobS5xdWVyeVNlbGVjdG9yQWxsKCIucmVnaW9uIiks
+cykKaWYocS5nQShxKSE9PTApe3A9bS5xdWVyeVNlbGVjdG9yKCJ0YWJsZVtkYXRhLXBhdGhdIikKcC50
+b1N0cmluZwpxLksocSxuZXcgTC5IbyhwLmdldEF0dHJpYnV0ZSgiZGF0YS0iK25ldyBXLlN5KG5ldyBX
+Lmk3KHApKS5PKCJwYXRoIikpKSl9SC5EaChsLHQsIlQiLG4pCm89bmV3IFcud3oobS5xdWVyeVNlbGVj
+dG9yQWxsKCIuYWRkLWhpbnQtbGluayIpLHMpCm8uSyhvLG5ldyBMLklDKCkpfSwKUTY6ZnVuY3Rpb24o
+YSxiLGMpe3ZhciB0PW5ldyBYTUxIdHRwUmVxdWVzdCgpCkMuRHQuZW8odCwiR0VUIixMLlE0KGEsYiks
+ITApCnQuc2V0UmVxdWVzdEhlYWRlcigiQ29udGVudC1UeXBlIiwiYXBwbGljYXRpb24vanNvbjsgY2hh
+cnNldD1VVEYtOCIpCnJldHVybiBMLkxVKHQsbnVsbCxjLkMoIjAqIikpfSwKdHk6ZnVuY3Rpb24oYSxi
+KXt2YXIgdD1uZXcgWE1MSHR0cFJlcXVlc3QoKSxzPXUuWApDLkR0LmVvKHQsIlBPU1QiLEwuUTQoYSxQ
+LkZsKHMscykpLCEwKQp0LnNldFJlcXVlc3RIZWFkZXIoIkNvbnRlbnQtVHlwZSIsImFwcGxpY2F0aW9u
+L2pzb247IGNoYXJzZXQ9VVRGLTgiKQpyZXR1cm4gTC5MVSh0LGIsdS50KX0sCkxVOmZ1bmN0aW9uKGEs
+YixjKXtyZXR1cm4gTC5UZyhhLGIsYyxjLkMoIjAqIikpfSwKVGc6ZnVuY3Rpb24oYSxiLGMsZCl7dmFy
+IHQ9MCxzPVAuRlgoZCkscixxPTIscCxvPVtdLG4sbSxsLGssaixpLGgsZwp2YXIgJGFzeW5jJExVPVAu
+bHooZnVuY3Rpb24oZSxmKXtpZihlPT09MSl7cD1mCnQ9cX13aGlsZSh0cnVlKXN3aXRjaCh0KXtjYXNl
+IDA6aj1uZXcgUC5aZihuZXcgUC52cygkLlgzLHUuZ1YpLHUuYkMpCmk9dS5lYgpoPWkuYShuZXcgTC5m
+QyhqLGEpKQp1LlouYShudWxsKQptPXUuZVEKVy5KRShhLCJsb2FkIixoLCExLG0pClcuSkUoYSwiZXJy
+b3IiLGkuYShqLmdZSigpKSwhMSxtKQphLnNlbmQoYj09bnVsbD9udWxsOkMuQ3QuT0IoYixudWxsKSkK
+cT00CnQ9NwpyZXR1cm4gUC5qUShqLmEsJGFzeW5jJExVKQpjYXNlIDc6cT0yCnQ9NgpicmVhawpjYXNl
+IDQ6cT0zCmc9cApILlJ1KGcpCm49SC50cyhnKQppPVAuVGwoIkVycm9yIHJlYWNoaW5nIG1pZ3JhdGlv
+biBwcmV2aWV3IHNlcnZlci4iLG4pCnRocm93IEguYihpKQp0PTYKYnJlYWsKY2FzZSAzOnQ9MgpicmVh
+awpjYXNlIDY6az1DLkN0LnBXKDAsYS5yZXNwb25zZVRleHQsbnVsbCkKaWYoYS5zdGF0dXM9PT0yMDAp
+e3I9Yy5DKCIwKiIpLmEoaykKdD0xCmJyZWFrfWVsc2UgdGhyb3cgSC5iKGspCmNhc2UgMTpyZXR1cm4g
+UC55QyhyLHMpCmNhc2UgMjpyZXR1cm4gUC5mMyhwLHMpfX0pCnJldHVybiBQLkRJKCRhc3luYyRMVSxz
+KX0sCmFLOmZ1bmN0aW9uKGEpe3ZhciB0PVAuaEsoYSkuZ2hZKCkucSgwLCJsaW5lIikKcmV0dXJuIHQ9
+PW51bGw/bnVsbDpILkhwKHQsbnVsbCl9LApHNjpmdW5jdGlvbihhKXt2YXIgdD1QLmhLKGEpLmdoWSgp
+LnEoMCwib2Zmc2V0IikKcmV0dXJuIHQ9PW51bGw/bnVsbDpILkhwKHQsbnVsbCl9LAppNjpmdW5jdGlv
+bihhKXtyZXR1cm4gTC5uVyh1Lk8uYShhKSl9LApuVzpmdW5jdGlvbihhKXt2YXIgdD0wLHM9UC5GWCh1
+LnopLHI9MSxxLHA9W10sbyxuLG0sbCxrCnZhciAkYXN5bmMkaTY9UC5seihmdW5jdGlvbihiLGMpe2lm
+KGI9PT0xKXtxPWMKdD1yfXdoaWxlKHRydWUpc3dpdGNoKHQpe2Nhc2UgMDpsPXUuZy5hKFcucWMoYS5j
+dXJyZW50VGFyZ2V0KSkuZ2V0QXR0cmlidXRlKCJocmVmIikKYS5wcmV2ZW50RGVmYXVsdCgpCnI9Mwp0
+PTYKcmV0dXJuIFAualEoTC50eShsLG51bGwpLCRhc3luYyRpNikKY2FzZSA2OnUuYlouYShKLkdyKFcu
+UHYoZG9jdW1lbnQuZGVmYXVsdFZpZXcpKSkucmVsb2FkKCkKcj0xCnQ9NQpicmVhawpjYXNlIDM6cj0y
+Cms9cQpvPUguUnUoaykKbj1ILnRzKGspCkwuQzIoIkNvdWxkIG5vdCBhZGQvcmVtb3ZlIGhpbnQiLG8s
+bikKdD01CmJyZWFrCmNhc2UgMjp0PTEKYnJlYWsKY2FzZSA1OnJldHVybiBQLnlDKG51bGwscykKY2Fz
+ZSAxOnJldHVybiBQLmYzKHEscyl9fSkKcmV0dXJuIFAuREkoJGFzeW5jJGk2LHMpfSwKQzI6ZnVuY3Rp
+b24oYSxiLGMpe3ZhciB0LHMscj0iZXhjZXB0aW9uIixxPSJzdGFja1RyYWNlIixwPXUudC5iKGIpJiZK
+LlJNKGIucSgwLCJzdWNjZXNzIiksITEpJiZiLng0KHIpJiZiLng0KHEpLG89Si5pYShiKQppZihwKXt0
+PUguaChvLnEoYixyKSkKYz1vLnEoYixxKX1lbHNlIHQ9by53KGIpCnA9ZG9jdW1lbnQKcz1wLnF1ZXJ5
+U2VsZWN0b3IoIi5wb3B1cC1wYW5lIikKcy5xdWVyeVNlbGVjdG9yKCJoMiIpLmlubmVyVGV4dD1hCnMu
+cXVlcnlTZWxlY3RvcigicCIpLmlubmVyVGV4dD10CnMucXVlcnlTZWxlY3RvcigicHJlIikuaW5uZXJU
+ZXh0PUouaihjKQpvPXUuWAp1LmRkLmEocy5xdWVyeVNlbGVjdG9yKCJhLmJvdHRvbSIpKS5ocmVmPVAu
+WGQoImh0dHBzIiwiZ2l0aHViLmNvbSIsImRhcnQtbGFuZy9zZGsvaXNzdWVzL25ldyIsUC5FRihbInRp
+dGxlIiwiQ3VzdG9tZXItcmVwb3J0ZWQgaXNzdWUgd2l0aCBOTkJEIG1pZ3JhdGlvbiB0b29sOiAiK2Es
+ImxhYmVscyIsImFyZWEtYW5hbHl6ZXIsYW5hbHl6ZXItbm5iZC1taWdyYXRpb24sdHlwZS1idWciLCJi
+b2R5IixhKyJcblxuRXJyb3I6ICIrSC5Faih0KSsiXG5cblBsZWFzZSBmaWxsIGluIHRoZSBmb2xsb3dp
+bmc6XG5cbioqTmFtZSBvZiBwYWNrYWdlIGJlaW5nIG1pZ3JhdGVkIChpZiBwdWJsaWMpKio6XG4qKldo
+YXQgSSB3YXMgZG9pbmcgd2hlbiB0aGlzIGlzc3VlIG9jY3VycmVkKio6XG4qKklzIGl0IHBvc3NpYmxl
+IHRvIHdvcmsgYXJvdW5kIHRoaXMgaXNzdWUqKjpcbioqSGFzIHRoaXMgaXNzdWUgaGFwcGVuZWQgYmVm
+b3JlLCBhbmQgaWYgc28sIGhvdyBvZnRlbioqOlxuKipEYXJ0IFNESyB2ZXJzaW9uKio6ICIrSC5Faihw
+LmdldEVsZW1lbnRCeUlkKCJzZGstdmVyc2lvbiIpLnRleHRDb250ZW50KSsiXG4qKkFkZGl0aW9uYWwg
+ZGV0YWlscyoqOlxuXG5UaGFua3MgZm9yIGZpbGluZyFcblxuU3RhY2t0cmFjZTogX2F1dG8gcG9wdWxh
+dGVkIGJ5IG1pZ3JhdGlvbiBwcmV2aWV3IHRvb2wuX1xuXG5gYGBcbiIrSC5FaihjKSsiXG5gYGBcbiJd
+LG8sbykpLmduRCgpCm89cy5zdHlsZQpvLmRpc3BsYXk9ImluaXRpYWwiCnA9YSsiOiAiK0guRWooYikK
+d2luZG93CmlmKHR5cGVvZiBjb25zb2xlIT0idW5kZWZpbmVkIil3aW5kb3cuY29uc29sZS5lcnJvcihw
+KQp3aW5kb3cKcD1ILkVqKGMpCmlmKHR5cGVvZiBjb25zb2xlIT0idW5kZWZpbmVkIil3aW5kb3cuY29u
+c29sZS5lcnJvcihwKX0sCnQyOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscSxwPXt9LG89dS5nLmEo
+Vy5xYyhhLmN1cnJlbnRUYXJnZXQpKQphLnByZXZlbnREZWZhdWx0KCkKdD1wLmE9by5nZXRBdHRyaWJ1
+dGUoImhyZWYiKQpzPUouemwodCwiPyIpP3AuYT1DLnhCLk5qKHQsMCxDLnhCLk9ZKHQsIj8iKSk6dApy
+PUwuRzYodCkKcT1MLmFLKHQpCmlmKHIhPW51bGwpTC5hZihzLHIscSxiLG5ldyBMLm5UKHAscixxKSkK
+ZWxzZSBMLmFmKHMsbnVsbCxudWxsLGIsbmV3IEwuTlkocCkpfSwKdlU6ZnVuY3Rpb24oKXt2YXIgdD1k
+b2N1bWVudApILkRoKHUuZyx1LmgsIlQiLCJxdWVyeVNlbGVjdG9yQWxsIikKdD1uZXcgVy53eih0LnF1
+ZXJ5U2VsZWN0b3JBbGwoIi5jb2RlIiksdS5SKQp0LksodCxuZXcgTC5lWCgpKX0sCmhYOmZ1bmN0aW9u
+KGEsYixjKXtyZXR1cm4gTC5ZdyhhLGIsYyl9LApZdzpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9MCxzPVAu
+RlgodS56KSxyPTEscSxwPVtdLG8sbixtLGwsayxqLGksaAp2YXIgJGFzeW5jJGhYPVAubHooZnVuY3Rp
+b24oZCxlKXtpZihkPT09MSl7cT1lCnQ9cn13aGlsZSh0cnVlKXN3aXRjaCh0KXtjYXNlIDA6cj0zCms9
+dS5YCnQ9NgpyZXR1cm4gUC5qUShMLlE2KGEsUC5FRihbInJlZ2lvbiIsInJlZ2lvbiIsIm9mZnNldCIs
+SC5FaihiKV0sayxrKSx1LnQpLCRhc3luYyRoWCkKY2FzZSA2Om89ZQprPW8Kaj1KLlU2KGspCm49bmV3
+IFUuZDIoVS5qZihqLnEoaywiZWRpdHMiKSksSC5oKGoucShrLCJleHBsYW5hdGlvbiIpKSxILnVQKGou
+cShrLCJsaW5lIikpLEguaChqLnEoaywiZGlzcGxheVBhdGgiKSksSC5oKGoucShrLCJ1cmlQYXRoIikp
+LFUuTmQoai5xKGssInRyYWNlcyIpKSkKTC5UMShuKQpMLkZyKGEsYixjKQpMLnlYKCIuZWRpdC1wYW5l
+bCAucGFuZWwtY29udGVudCIsITEpCnI9MQp0PTUKYnJlYWsKY2FzZSAzOnI9MgpoPXEKbT1ILlJ1KGgp
+Cmw9SC50cyhoKQpMLkMyKCJDb3VsZCBub3QgbG9hZCBlZGl0IGRldGFpbHMiLG0sbCkKdD01CmJyZWFr
+CmNhc2UgMjp0PTEKYnJlYWsKY2FzZSA1OnJldHVybiBQLnlDKG51bGwscykKY2FzZSAxOnJldHVybiBQ
+LmYzKHEscyl9fSkKcmV0dXJuIFAuREkoJGFzeW5jJGhYLHMpfSwKRzc6ZnVuY3Rpb24oYSxiLGMsZCxl
+KXtyZXR1cm4gTC5MNShhLGIsYyxkLGUpfSwKTDU6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgdD0wLHM9
+UC5GWCh1LnopLHIscT0yLHAsbz1bXSxuLG0sbCxrLGosaSxoCnZhciAkYXN5bmMkRzc9UC5seihmdW5j
+dGlvbihmLGcpe2lmKGY9PT0xKXtwPWcKdD1xfXdoaWxlKHRydWUpc3dpdGNoKHQpe2Nhc2UgMDppZigh
+Si5yWShhKS5UYyhhLCIuZGFydCIpKXtMLkJFKGEsbmV3IEIucXAoIiIsIiIsIiIsQy5DTSksZCkKTC5C
+WChhLG51bGwpCmlmKGUhPW51bGwpZS4kMCgpCnQ9MQpicmVha31xPTQKaj11LlgKdD03CnJldHVybiBQ
+LmpRKEwuUTYoYSxQLkVGKFsiaW5saW5lIiwidHJ1ZSJdLGosaiksdS50KSwkYXN5bmMkRzcpCmNhc2Ug
+NzpuPWcKTC5CRShhLEIuWWYobiksZCkKTC5mRyhiLGMpCm09Qy54Qi50ZyhhLCI/Iik/Qy54Qi5Oaihh
+LDAsQy54Qi5PWShhLCI/IikpOmEKTC5CWChtLGIpCmlmKGUhPW51bGwpZS4kMCgpCnE9Mgp0PTYKYnJl
+YWsKY2FzZSA0OnE9MwpoPXAKbD1ILlJ1KGgpCms9SC50cyhoKQpMLkMyKCJDb3VsZCBub3QgbG9hZCBk
+YXJ0IGZpbGUgIithLGwsaykKdD02CmJyZWFrCmNhc2UgMzp0PTIKYnJlYWsKY2FzZSA2OmNhc2UgMTpy
+ZXR1cm4gUC55QyhyLHMpCmNhc2UgMjpyZXR1cm4gUC5mMyhwLHMpfX0pCnJldHVybiBQLkRJKCRhc3lu
+YyRHNyxzKX0sCkdlOmZ1bmN0aW9uKCl7dmFyIHQ9MCxzPVAuRlgodS56KSxyPTEscSxwPVtdLG8sbixt
+LGwsayxqLGkKdmFyICRhc3luYyRHZT1QLmx6KGZ1bmN0aW9uKGEsYil7aWYoYT09PTEpe3E9Ygp0PXJ9
+d2hpbGUodHJ1ZSlzd2l0Y2godCl7Y2FzZSAwOmo9Ii9fcHJldmlldy9uYXZpZ2F0aW9uVHJlZS5qc29u
+IgpyPTMKdD02CnJldHVybiBQLmpRKEwuUTYoaixDLldPLHUuZUUpLCRhc3luYyRHZSkKY2FzZSA2Om89
+YgpuPWRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoIi5uYXYtdHJlZSIpCkoubDUobiwiIikKTC50WChuLEwu
+bUsobykpCnI9MQp0PTUKYnJlYWsKY2FzZSAzOnI9MgppPXEKbT1ILlJ1KGkpCmw9SC50cyhpKQpMLkMy
+KCJDb3VsZCBub3QgbG9hZCBuYXZpZ2F0aW9uIHRyZWUiLG0sbCkKdD01CmJyZWFrCmNhc2UgMjp0PTEK
+YnJlYWsKY2FzZSA1OnJldHVybiBQLnlDKG51bGwscykKY2FzZSAxOnJldHVybiBQLmYzKHEscyl9fSkK
+cmV0dXJuIFAuREkoJGFzeW5jJEdlLHMpfSwKcU86ZnVuY3Rpb24oYSl7dmFyIHQscz1hLmdldEJvdW5k
+aW5nQ2xpZW50UmVjdCgpLHI9Qy5DRC56USgkLmZpKCkub2Zmc2V0SGVpZ2h0KSxxPXdpbmRvdy5pbm5l
+ckhlaWdodCxwPUMuQ0QuelEoJC5EVygpLm9mZnNldEhlaWdodCkKaWYodHlwZW9mIHEhPT0ibnVtYmVy
+IilyZXR1cm4gcS5ITigpCnQ9cy5ib3R0b20KaWYodHlwZW9mIHQhPT0ibnVtYmVyIilyZXR1cm4gdC5v
+cygpCmlmKHQ+cS0ocCsxNCkpSi5kaChhKQplbHNle3E9cy50b3AKaWYodHlwZW9mIHEhPT0ibnVtYmVy
+IilyZXR1cm4gcS5KKCkKaWYocTxyKzE0KUouZGgoYSl9fSwKZkc6ZnVuY3Rpb24oYSxiKXt2YXIgdCxz
+LHIscSxwCmlmKGEhPW51bGwpe3Q9ZG9jdW1lbnQKcz10LmdldEVsZW1lbnRCeUlkKCJvIitILkVqKGEp
+KQpyPXQucXVlcnlTZWxlY3RvcigiLmxpbmUtIitILkVqKGIpKQppZihzIT1udWxsKXtMLnFPKHMpCkou
+ZFIocykuaSgwLCJ0YXJnZXQiKX1lbHNlIGlmKHIhPW51bGwpTC5xTyhyLnBhcmVudEVsZW1lbnQpCmlm
+KHIhPW51bGwpSi5kUih1LmcuYShyLnBhcmVudE5vZGUpKS5pKDAsImhpZ2hsaWdodCIpfWVsc2V7dD1k
+b2N1bWVudApxPXUuZwpILkRoKHEsdS5oLCJUIiwicXVlcnlTZWxlY3RvckFsbCIpCnQ9dC5xdWVyeVNl
+bGVjdG9yQWxsKCIubGluZS1ubyIpCnA9bmV3IFcud3oodCx1LlIpCmlmKHAuZ0EocCk9PT0wKXJldHVy
+bgpMLnFPKHEuYShDLnQ1Lmd0SCh0KSkpfX0sCmFmOmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHQscyxy
+PUwuRzYod2luZG93LmxvY2F0aW9uLmhyZWYpLHE9TC5hSyh3aW5kb3cubG9jYXRpb24uaHJlZikKaWYo
+ciE9bnVsbCl7dD1kb2N1bWVudC5nZXRFbGVtZW50QnlJZCgibyIrSC5FaihyKSkKaWYodCE9bnVsbClK
+LmRSKHQpLlIoMCwidGFyZ2V0Iil9aWYocSE9bnVsbCl7cz1kb2N1bWVudC5xdWVyeVNlbGVjdG9yKCIu
+bGluZS0iK0guRWoocSkpCmlmKHMhPW51bGwpSi5kUihzLnBhcmVudEVsZW1lbnQpLlIoMCwiaGlnaGxp
+Z2h0Iil9aWYoYT09d2luZG93LmxvY2F0aW9uLnBhdGhuYW1lKXtMLmZHKGIsYykKZS4kMCgpfWVsc2Ug
+TC5HNyhhLGIsYyxkLGUpfSwKUTQ6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHI9UC5oSyhhKSxxPXUuWApx
+PVAuRmwocSxxKQpmb3IodD1yLmdoWSgpLHQ9dC5nUHUodCksdD10Lmdreih0KTt0LkYoKTspe3M9dC5n
+bCgpCnEuWSgwLHMuYSxzLmIpfWZvcih0PWIuZ1B1KGIpLHQ9dC5na3oodCk7dC5GKCk7KXtzPXQuZ2wo
+KQpxLlkoMCxzLmEscy5iKX1xLlkoMCwiYXV0aFRva2VuIiwkLlVFKCkpCnJldHVybiByLm5tKDAscSku
+Z25EKCl9LApUMTpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsaz0kLmhMKCkKSi5sNShr
+LCIiKQppZihhPT1udWxsKXt0PWRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoInAiKQpDLkx0LnNhNCh0LCJT
+ZWUgZGV0YWlscyBhYm91dCBhIHByb3Bvc2VkIGVkaXQuIikKQy5MdC5zUCh0LEguVk0oWyJwbGFjZWhv
+bGRlciJdLHUuaSkpCmsuYXBwZW5kQ2hpbGQodCkKQy5MdC5GRih0KQpyZXR1cm59cz1hLmQKcj0kLm5V
+KCkKcT1yLnpmKHMpCnA9YS5iCm89ZG9jdW1lbnQKbj1yLkhQKHMsSi5UMChvLnF1ZXJ5U2VsZWN0b3Io
+Ii5yb290IikudGV4dENvbnRlbnQpKQptPWEuYwpsPW8uY3JlYXRlRWxlbWVudCgicCIpCmsuYXBwZW5k
+Q2hpbGQobCkKbC5hcHBlbmRDaGlsZChvLmNyZWF0ZVRleHROb2RlKEguRWoocCkrIiBhdCAiKSkKcj11
+LlgKcj1XLko2KEwuUTQoYS5lLFAuRUYoWyJsaW5lIixKLmoobSldLHIscikpKQpyLmFwcGVuZENoaWxk
+KG8uY3JlYXRlVGV4dE5vZGUoSC5FaihuKSsiOiIrSC5FaihtKSsiLiIpKQpsLmFwcGVuZENoaWxkKHIp
+CkouZGgobCkKTC5DQyhhLGsscSkKTC5GeihhLGspfSwKTEg6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMs
+cixxLHAsbyxuLG0sbCxrLGosaSxoLGc9JC55UCgpCkoubDUoZywiIikKaWYoYi5nQShiKT09PTApe3Q9
+ZG9jdW1lbnQKcz10LmNyZWF0ZUVsZW1lbnQoInAiKQpnLmFwcGVuZENoaWxkKHMpCnMuYXBwZW5kQ2hp
+bGQodC5jcmVhdGVUZXh0Tm9kZSgiTm8gcHJvcG9zZWQgZWRpdHMiKSl9ZWxzZSBmb3IoZz1iLmdQdShi
+KSxnPWcuZ2t6KGcpLHQ9dS5qLHI9dC5DKCJ+KDEpPyIpLHE9dS5aLHQ9dC5jO2cuRigpOyl7cD1nLmds
+KCkKbz1kb2N1bWVudApzPW8uY3JlYXRlRWxlbWVudCgicCIpCm49JC55UCgpCm4uYXBwZW5kQ2hpbGQo
+cykKcy5hcHBlbmRDaGlsZChvLmNyZWF0ZVRleHROb2RlKEguRWoocC5hKSsiOiIpKQptPW8uY3JlYXRl
+RWxlbWVudCgidWwiKQpuLmFwcGVuZENoaWxkKG0pCmZvcihwPUouSVQocC5iKTtwLkYoKTspe249cC5n
+bCgpCmw9by5jcmVhdGVFbGVtZW50KCJsaSIpCm0uYXBwZW5kQ2hpbGQobCkKSi5kUihsKS5pKDAsImVk
+aXQiKQprPW8uY3JlYXRlRWxlbWVudCgiYSIpCmwuYXBwZW5kQ2hpbGQoaykKay5jbGFzc0xpc3QuYWRk
+KCJlZGl0LWxpbmsiKQpqPW4uYwppPUguRWooaikKay5zZXRBdHRyaWJ1dGUoImRhdGEtIituZXcgVy5T
+eShuZXcgVy5pNyhrKSkuTygib2Zmc2V0IiksaSkKaD1uLmEKaT1ILkVqKGgpCmsuc2V0QXR0cmlidXRl
+KCJkYXRhLSIrbmV3IFcuU3kobmV3IFcuaTcoaykpLk8oImxpbmUiKSxpKQprLmFwcGVuZENoaWxkKG8u
+Y3JlYXRlVGV4dE5vZGUoImxpbmUgIitILkVqKGgpKSkKaT1yLmEobmV3IEwuRUUoaixoLGEpKQpxLmEo
+bnVsbCkKVy5KRShrLCJjbGljayIsaSwhMSx0KQpsLmFwcGVuZENoaWxkKG8uY3JlYXRlVGV4dE5vZGUo
+IjogIitILkVqKG4uYikpKX19aWYoYylMLlQxKG51bGwpfSwKRnI6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0
+LHMscj13aW5kb3cubG9jYXRpb24scT1QLmhLKChyJiZDLkV4KS5nRHIocikrSC5FaihhKSkKcj11LlgK
+cj1QLkZsKHIscikKaWYoYiE9bnVsbClyLlkoMCwib2Zmc2V0IixILkVqKGIpKQppZihjIT1udWxsKXIu
+WSgwLCJsaW5lIixILkVqKGMpKQpyLlkoMCwiYXV0aFRva2VuIiwkLlVFKCkpCnE9cS5ubSgwLHIpCnI9
+d2luZG93Lmhpc3RvcnkKdD11LnoKcz1xLmduRCgpCnIudG9TdHJpbmcKci5wdXNoU3RhdGUobmV3IFAu
+QmYoW10sW10pLlB2KFAuRmwodCx0KSksIiIscyl9LApFbjpmdW5jdGlvbihhKXt2YXIgdD1KLmJiKGRv
+Y3VtZW50LnF1ZXJ5U2VsZWN0b3IoIi5yb290IikudGV4dENvbnRlbnQsIi8iKQppZihDLnhCLm4oYSx0
+KSlyZXR1cm4gQy54Qi5HKGEsdC5sZW5ndGgpCmVsc2UgcmV0dXJuIGF9LApCWDpmdW5jdGlvbihhLGIp
+e3ZhciB0LHM9e30Kcy5hPWEKYT1MLkVuKGEpCnMuYT1hCkouZHIoJC5EOSgpLGEpCnQ9ZG9jdW1lbnQK
+SC5EaCh1LmcsdS5oLCJUIiwicXVlcnlTZWxlY3RvckFsbCIpCnQ9bmV3IFcud3oodC5xdWVyeVNlbGVj
+dG9yQWxsKCIubmF2LXBhbmVsIC5uYXYtbGluayIpLHUuUikKdC5LKHQsbmV3IEwuVlMocykpfSwKQkU6
+ZnVuY3Rpb24oYSxiLGMpe3ZhciB0PSIucmVnaW9ucyIscz1kb2N1bWVudCxyPXMucXVlcnlTZWxlY3Rv
+cih0KSxxPXMucXVlcnlTZWxlY3RvcigiLmNvZGUiKQpKLnRIKHIsYi5hLCQuS0coKSkKSi50SChxLGIu
+YiwkLktHKCkpCkwuTEgoYSxiLmQsYykKTC52VSgpCkwueVgoIi5jb2RlIiwhMCkKTC55WCh0LCEwKX0s
+CnRYOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEscCxvLG4sbSxsLGssaixpLGgsZz1kb2N1bWVudCxm
+PWcuY3JlYXRlRWxlbWVudCgidWwiKQphLmFwcGVuZENoaWxkKGYpCmZvcih0PWIubGVuZ3RoLHM9dS5a
+LHI9MDtyPGIubGVuZ3RoO2IubGVuZ3RoPT09dHx8KDAsSC5saykoYiksKytyKXtxPWJbcl0KcD1nLmNy
+ZWF0ZUVsZW1lbnQoImxpIikKZi5hcHBlbmRDaGlsZChwKQpvPUouWUUocCkKaWYocS5hPT09Qy5ZMil7
+by5nUChwKS5pKDAsImRpciIpCm49Zy5jcmVhdGVFbGVtZW50KCJzcGFuIikKcC5hcHBlbmRDaGlsZChu
+KQpvPUouWUUobikKby5nUChuKS5pKDAsImFycm93IikKby5zaGYobiwiJiN4MjVCQzsiKQptPWcuY3Jl
+YXRlRWxlbWVudCgic3BhbiIpCnAuYXBwZW5kQ2hpbGQobSkKSi5sNShtLCc8c3BhbiBjbGFzcz0ibWF0
+ZXJpYWwtaWNvbnMiPmZvbGRlcl9vcGVuPC9zcGFuPicpCnAuYXBwZW5kQ2hpbGQoZy5jcmVhdGVUZXh0
+Tm9kZShxLmIpKQpMLnRYKHAscS5jKQpMLmt6KG4pfWVsc2V7by5zaGYocCwnPHNwYW4gY2xhc3M9Im1h
+dGVyaWFsLWljb25zIj5pbnNlcnRfZHJpdmVfZmlsZTwvc3Bhbj4nKQpsPWcuY3JlYXRlRWxlbWVudCgi
+YSIpCnAuYXBwZW5kQ2hpbGQobCkKbz1KLllFKGwpCm8uZ1AobCkuaSgwLCJuYXYtbGluayIpCmwuc2V0
+QXR0cmlidXRlKCJkYXRhLSIrbmV3IFcuU3kobmV3IFcuaTcobCkpLk8oIm5hbWUiKSxxLmQpCmwuc2V0
+QXR0cmlidXRlKCJocmVmIixxLmUpCmwuYXBwZW5kQ2hpbGQoZy5jcmVhdGVUZXh0Tm9kZShxLmIpKQpv
+PW8uZ1ZsKGwpCms9by4kdGkKaj1rLkMoIn4oMSk/IikuYShuZXcgTC5URCgpKQpzLmEobnVsbCkKVy5K
+RShvLmEsby5iLGosITEsay5jKQppPXEuZgppZih0eXBlb2YgaSE9PSJudW1iZXIiKXJldHVybiBpLm9z
+KCkKaWYoaT4wKXtoPWcuY3JlYXRlRWxlbWVudCgic3BhbiIpCnAuYXBwZW5kQ2hpbGQoaCkKSi5kUiho
+KS5pKDAsImVkaXQtY291bnQiKQpvPSIiK2krIiAiCmlmKGk9PT0xKWs9ImVkaXQiCmVsc2Ugaz0iZWRp
+dHMiCmguc2V0QXR0cmlidXRlKCJ0aXRsZSIsbytrKQpoLmFwcGVuZENoaWxkKGcuY3JlYXRlVGV4dE5v
+ZGUoQy5qbi53KGkpKSl9fX19LApGejpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHAsbyxuLG0sbCxr
+LGosaT1hLmEKaWYoaT09bnVsbClyZXR1cm4KdD1kb2N1bWVudApzPXQuY3JlYXRlRWxlbWVudCgicCIp
+CnI9Yi5hcHBlbmRDaGlsZChzKQpzPXQuY3JlYXRlRWxlbWVudCgic3BhbiIpCnE9dS5pCkouTXUocyxI
+LlZNKFsidHlwZS1kZXNjcmlwdGlvbiJdLHEpKQpzLmFwcGVuZENoaWxkKHQuY3JlYXRlVGV4dE5vZGUo
+IkFjdGlvbnMiKSkKci5hcHBlbmRDaGlsZChzKQpyLmFwcGVuZENoaWxkKHQuY3JlYXRlVGV4dE5vZGUo
+IjoiKSkKcD10LmNyZWF0ZUVsZW1lbnQoInAiKQpiLmFwcGVuZENoaWxkKHApCmZvcihzPWkubGVuZ3Ro
+LG89dS5RLG49MDtuPGkubGVuZ3RoO2kubGVuZ3RoPT09c3x8KDAsSC5saykoaSksKytuKXttPWlbbl0K
+bD10LmNyZWF0ZUVsZW1lbnQoImEiKQpwLmFwcGVuZENoaWxkKGwpCmwuYXBwZW5kQ2hpbGQodC5jcmVh
+dGVUZXh0Tm9kZShtLmEpKQpsLnNldEF0dHJpYnV0ZSgiaHJlZiIsbS5iKQprPW8uYShILlZNKFsiYWRk
+LWhpbnQtbGluayIsImJlZm9yZS1hcHBseSIsImJ1dHRvbiJdLHEpKQpqPUouZFIobCkKai5WMSgwKQpq
+LkZWKDAsayl9fSwKQ0M6ZnVuY3Rpb24oYTgsYTksYjApe3ZhciB0LHMscixxLHAsbyxuLG0sbCxrLGos
+aSxoLGcsZixlLGQsYyxiLGEsYTAsYTEsYTIsYTMsYTQsYTUsYTYsYTcKZm9yKHQ9YTguZixzPXQubGVu
+Z3RoLHI9dS5pLHE9dS5RLHA9dS5qLG89cC5DKCJ+KDEpPyIpLG49dS5aLHA9cC5jLG09MDttPHQubGVu
+Z3RoO3QubGVuZ3RoPT09c3x8KDAsSC5saykodCksKyttKXtsPXRbbV0Kaz1kb2N1bWVudApqPWsuY3Jl
+YXRlRWxlbWVudCgicCIpCmk9cS5hKEguVk0oWyJ0cmFjZSJdLHIpKQpoPUouZFIoaikKaC5WMSgwKQpo
+LkZWKDAsaSkKZz1hOS5hcHBlbmRDaGlsZChqKQpqPWsuY3JlYXRlRWxlbWVudCgic3BhbiIpCmk9cS5h
+KEguVk0oWyJ0eXBlLWRlc2NyaXB0aW9uIl0scikpCmg9Si5kUihqKQpoLlYxKDApCmguRlYoMCxpKQpq
+LmFwcGVuZENoaWxkKGsuY3JlYXRlVGV4dE5vZGUobC5hKSkKZy5hcHBlbmRDaGlsZChqKQpnLmFwcGVu
+ZENoaWxkKGsuY3JlYXRlVGV4dE5vZGUoIjoiKSkKaj1rLmNyZWF0ZUVsZW1lbnQoInVsIikKaT1xLmEo
+SC5WTShbInRyYWNlIl0scikpCmg9Si5kUihqKQpoLlYxKDApCmguRlYoMCxpKQpmPWcuYXBwZW5kQ2hp
+bGQoaikKZm9yKGo9bC5iLGk9ai5sZW5ndGgsZT0wO2U8ai5sZW5ndGg7ai5sZW5ndGg9PT1pfHwoMCxI
+LmxrKShqKSwrK2Upe2Q9altlXQpjPWsuY3JlYXRlRWxlbWVudCgibGkiKQpmLmFwcGVuZENoaWxkKGMp
+CmI9ay5jcmVhdGVFbGVtZW50KCJzcGFuIikKYT1xLmEoSC5WTShbImZ1bmN0aW9uIl0scikpCmg9Si5k
+UihiKQpoLlYxKDApCmguRlYoMCxhKQphPWQuYgpMLmtEKGIsYT09bnVsbD8idW5rbm93biI6YSkKYy5h
+cHBlbmRDaGlsZChiKQphMD1kLmMKaWYoYTAhPW51bGwpe2MuYXBwZW5kQ2hpbGQoay5jcmVhdGVUZXh0
+Tm9kZSgiICgiKSkKYTE9YTAuYgphMj1rLmNyZWF0ZUVsZW1lbnQoImEiKQphMi5hcHBlbmRDaGlsZChr
+LmNyZWF0ZVRleHROb2RlKEguRWooYTAuYykrIjoiK0guRWooYTEpKSkKYTIuc2V0QXR0cmlidXRlKCJo
+cmVmIixhMC5hKQphMi5jbGFzc0xpc3QuYWRkKCJuYXYtbGluayIpCmMuYXBwZW5kQ2hpbGQoYTIpCmMu
+YXBwZW5kQ2hpbGQoay5jcmVhdGVUZXh0Tm9kZSgiKSIpKX1jLmFwcGVuZENoaWxkKGsuY3JlYXRlVGV4
+dE5vZGUoIjogIikpCmI9ZC5hCkwua0QoYyxiPT1udWxsPyJ1bmtub3duIjpiKQpiPWQuZAppZihiLmxl
+bmd0aCE9PTApe2E9ay5jcmVhdGVFbGVtZW50KCJwIikKYTM9cS5hKEguVk0oWyJkcmF3ZXIiLCJiZWZv
+cmUtYXBwbHkiXSxyKSkKaD1KLmRSKGEpCmguVjEoMCkKaC5GVigwLGEzKQphND1jLmFwcGVuZENoaWxk
+KGEpCmZvcihhPWIubGVuZ3RoLGE1PTA7YTU8Yi5sZW5ndGg7Yi5sZW5ndGg9PT1hfHwoMCxILmxrKShi
+KSwrK2E1KXthNj1iW2E1XQphMz1rLmNyZWF0ZUVsZW1lbnQoImJ1dHRvbiIpCmE3PW8uYShuZXcgTC5B
+UyhhNixhMCkpCm4uYShudWxsKQpXLkpFKGEzLCJjbGljayIsYTcsITEscCkKYTMuYXBwZW5kQ2hpbGQo
+ay5jcmVhdGVUZXh0Tm9kZShNLk9YKGE2LmEpKSkKYTQuYXBwZW5kQ2hpbGQoYTMpfX19fX0sCmtEOmZ1
+bmN0aW9uKGEsYil7dmFyIHQscyxyPUguVk0oYi5zcGxpdCgiLiIpLHUucykscT1DLk5tLmd0SChyKSxw
+PWRvY3VtZW50CmEuYXBwZW5kQ2hpbGQocC5jcmVhdGVUZXh0Tm9kZShxKSkKZm9yKHE9SC5xQyhyLDEs
+bnVsbCx1Lk4pLHE9bmV3IEguYTcocSxxLmdBKHEpLHEuJHRpLkMoImE3PGFMLkU+IikpLHQ9Si5ZRShh
+KTtxLkYoKTspe3M9cS5kCnQubnooYSwiYmVmb3JlZW5kIiwiJiM4MjAzOy4iLG51bGwsbnVsbCkKYS5h
+cHBlbmRDaGlsZChwLmNyZWF0ZVRleHROb2RlKHMpKX19LAplOmZ1bmN0aW9uIGUoKXt9LApWVzpmdW5j
+dGlvbiBWVyhhLGIsYyl7dGhpcy5hPWEKdGhpcy5iPWIKdGhpcy5jPWN9LApvWjpmdW5jdGlvbiBvWigp
+e30sCmpyOmZ1bmN0aW9uIGpyKCl7fSwKcWw6ZnVuY3Rpb24gcWwoKXt9LApIaTpmdW5jdGlvbiBIaSgp
+e30sCkJUOmZ1bmN0aW9uIEJUKCl7fSwKUFk6ZnVuY3Rpb24gUFkoKXt9LApMOmZ1bmN0aW9uIEwoKXt9
+LApXeDpmdW5jdGlvbiBXeChhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwKQU86ZnVuY3Rpb24gQU8oYSl7
+dGhpcy5hPWF9LApkTjpmdW5jdGlvbiBkTihhKXt0aGlzLmE9YX0sCkhvOmZ1bmN0aW9uIEhvKGEpe3Ro
+aXMuYT1hfSwKeHo6ZnVuY3Rpb24geHooYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCklDOmZ1bmN0aW9u
+IElDKCl7fSwKZkM6ZnVuY3Rpb24gZkMoYSxiKXt0aGlzLmE9YQp0aGlzLmI9Yn0sCm5UOmZ1bmN0aW9u
+IG5UKGEsYixjKXt0aGlzLmE9YQp0aGlzLmI9Ygp0aGlzLmM9Y30sCk5ZOmZ1bmN0aW9uIE5ZKGEpe3Ro
+aXMuYT1hfSwKZVg6ZnVuY3Rpb24gZVgoKXt9LApFRTpmdW5jdGlvbiBFRShhLGIsYyl7dGhpcy5hPWEK
+dGhpcy5iPWIKdGhpcy5jPWN9LApRTDpmdW5jdGlvbiBRTChhLGIpe3RoaXMuYT1hCnRoaXMuYj1ifSwK
+VlM6ZnVuY3Rpb24gVlMoYSl7dGhpcy5hPWF9LApURDpmdW5jdGlvbiBURCgpe30sCkFTOmZ1bmN0aW9u
+IEFTKGEsYil7dGhpcy5hPWEKdGhpcy5iPWJ9LApYQTpmdW5jdGlvbiBYQSgpe30sCm1LOmZ1bmN0aW9u
+KGEpe3ZhciB0LHMscixxLHAsbyxuPUguVk0oW10sdS5jUSkKZm9yKHQ9Si5JVCh1LlUuYShhKSk7dC5G
+KCk7KXtzPXQuZ2woKQpyPUouVTYocykKcT1MLnAyKEguaChyLnEocywidHlwZSIpKSkKcD1ILmgoci5x
+KHMsIm5hbWUiKSkKbz1yLnEocywic3VidHJlZSIpCm89bz09bnVsbD9udWxsOkwubUsobykKQy5ObS5p
+KG4sbmV3IEwuWloocSxwLG8sSC5oKHIucShzLCJwYXRoIikpLEguaChyLnEocywiaHJlZiIpKSxILnVQ
+KHIucShzLCJlZGl0Q291bnQiKSkpKX1yZXR1cm4gbn0sClZEOmZ1bmN0aW9uKGEpe3ZhciB0LHMscj1I
+LlZNKFtdLHUuRykKZm9yKHQ9YS5sZW5ndGgscz0wO3M8YS5sZW5ndGg7YS5sZW5ndGg9PT10fHwoMCxI
+LmxrKShhKSwrK3MpQy5ObS5pKHIsYVtzXS5MdCgpKQpyZXR1cm4gcn0sCnAyOmZ1bmN0aW9uKGEpe3N3
+aXRjaChhKXtjYXNlImRpcmVjdG9yeSI6cmV0dXJuIEMuWTIKY2FzZSJmaWxlIjpyZXR1cm4gQy5yZgpk
+ZWZhdWx0OnRocm93IEguYihQLlBWKCJVbnJlY29nbml6ZWQgbmF2aWdhdGlvbiB0cmVlIG5vZGUgdHlw
+ZTogIitILkVqKGEpKSl9fSwKdnk6ZnVuY3Rpb24oYSl7c3dpdGNoKGEpe2Nhc2UgQy5ZMjpyZXR1cm4i
+ZGlyZWN0b3J5IgpjYXNlIEMucmY6cmV0dXJuImZpbGUifXRocm93IEguYihQLlBWKCJVbnJlY29nbml6
+ZWQgbmF2aWdhdGlvbiB0cmVlIG5vZGUgdHlwZTogIithLncoMCkpKX0sClpaOmZ1bmN0aW9uIFpaKGEs
+YixjLGQsZSxmKXt2YXIgXz10aGlzCl8uYT1hCl8uYj1iCl8uYz1jCl8uZD1kCl8uZT1lCl8uZj1mfSwK
+Tzk6ZnVuY3Rpb24gTzkoYSl7dGhpcy5iPWF9LApJVjpmdW5jdGlvbiBJVihhLGIsYyxkKXt2YXIgXz10
+aGlzCl8uZD1hCl8uZT1iCl8uZj1jCl8ucj1kfX0sWD17CkNMOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxy
+LHEscCxvPWIueFooYSkKYi5oSyhhKQppZihvIT1udWxsKWE9Si5LVihhLG8ubGVuZ3RoKQp0PXUuaQpz
+PUguVk0oW10sdCkKcj1ILlZNKFtdLHQpCnQ9YS5sZW5ndGgKaWYodCE9PTAmJmIucjQoQy54Qi5XKGEs
+MCkpKXtpZigwPj10KXJldHVybiBILk9IKGEsMCkKQy5ObS5pKHIsYVswXSkKcT0xfWVsc2V7Qy5ObS5p
+KHIsIiIpCnE9MH1mb3IocD1xO3A8dDsrK3ApaWYoYi5yNChDLnhCLlcoYSxwKSkpe0MuTm0uaShzLEMu
+eEIuTmooYSxxLHApKQpDLk5tLmkocixhW3BdKQpxPXArMX1pZihxPHQpe0MuTm0uaShzLEMueEIuRyhh
+LHEpKQpDLk5tLmkociwiIil9cmV0dXJuIG5ldyBYLldEKGIsbyxzLHIpfSwKV0Q6ZnVuY3Rpb24gV0Qo
+YSxiLGMsZCl7dmFyIF89dGhpcwpfLmE9YQpfLmI9YgpfLmQ9YwpfLmU9ZH0sCkk3OmZ1bmN0aW9uKGEp
+e3JldHVybiBuZXcgWC5kdihhKX0sCmR2OmZ1bmN0aW9uIGR2KGEpe3RoaXMuYT1hfX0sTz17ClJoOmZ1
+bmN0aW9uKCl7dmFyIHQscz1udWxsCmlmKFAudW8oKS5nRmkoKSE9PSJmaWxlIilyZXR1cm4gJC5FYigp
+CnQ9UC51bygpCmlmKCFDLnhCLlRjKHQuZ0lpKHQpLCIvIikpcmV0dXJuICQuRWIoKQppZihQLktMKHMs
+ImEvYiIscyxzLHMscyxzKS50NCgpPT09ImFcXGIiKXJldHVybiAkLktrKCkKcmV0dXJuICQuYkQoKX0s
+CnpMOmZ1bmN0aW9uIHpMKCl7fX0sRT17T0Y6ZnVuY3Rpb24gT0YoYSxiLGMpe3RoaXMuZD1hCnRoaXMu
+ZT1iCnRoaXMuZj1jfX0sRj17cnU6ZnVuY3Rpb24gcnUoYSxiLGMsZCl7dmFyIF89dGhpcwpfLmQ9YQpf
+LmU9YgpfLmY9YwpfLnI9ZH19LEQ9ewpSWDpmdW5jdGlvbigpe3ZhciB0LHMscixxLHA9bnVsbAp0cnl7
+cD1QLnVvKCl9Y2F0Y2godCl7aWYodS5lai5iKEguUnUodCkpKXtzPSQuRmYKaWYocyE9bnVsbClyZXR1
+cm4gcwp0aHJvdyB0fWVsc2UgdGhyb3cgdH1pZihKLlJNKHAsJC5JNikpcmV0dXJuICQuRmYKJC5JNj1w
+CmlmKCQuSGsoKT09JC5FYigpKXM9JC5GZj1wLlpJKCIuIikudygwKQplbHNle3I9cC50NCgpCnE9ci5s
+ZW5ndGgtMQpzPSQuRmY9cT09PTA/cjpDLnhCLk5qKHIsMCxxKX1yZXR1cm4gc319CnZhciB3PVtDLEgs
+SixQLFcsTSxVLEIsVCxMLFgsTyxFLEYsRF0KaHVua0hlbHBlcnMuc2V0RnVuY3Rpb25OYW1lc0lmTmVj
+ZXNzYXJ5KHcpCnZhciAkPXt9CkguRksucHJvdG90eXBlPXt9CkoudkIucHJvdG90eXBlPXsKRE46ZnVu
+Y3Rpb24oYSxiKXtyZXR1cm4gYT09PWJ9LApnaU86ZnVuY3Rpb24oYSl7cmV0dXJuIEguZVEoYSl9LAp3
+OmZ1bmN0aW9uKGEpe3JldHVybiJJbnN0YW5jZSBvZiAnIitILkVqKEguTShhKSkrIicifSwKZTc6ZnVu
+Y3Rpb24oYSxiKXt1Lm8uYShiKQp0aHJvdyBILmIoUC5scihhLGIuZ1dhKCksYi5nbmQoKSxiLmdWbSgp
+KSl9fQpKLnlFLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIFN0cmluZyhhKX0sCmdpTzpm
+dW5jdGlvbihhKXtyZXR1cm4gYT81MTkwMTg6MjE4MTU5fSwKJGlhMjoxfQpKLndlLnByb3RvdHlwZT17
+CkROOmZ1bmN0aW9uKGEsYil7cmV0dXJuIG51bGw9PWJ9LAp3OmZ1bmN0aW9uKGEpe3JldHVybiJudWxs
+In0sCmdpTzpmdW5jdGlvbihhKXtyZXR1cm4gMH0sCmU3OmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMu
+U2ooYSx1Lm8uYShiKSl9LAokaWM4OjF9CkouTUYucHJvdG90eXBlPXsKZ2lPOmZ1bmN0aW9uKGEpe3Jl
+dHVybiAwfSwKdzpmdW5jdGlvbihhKXtyZXR1cm4gU3RyaW5nKGEpfSwKJGl2bToxfQpKLmlDLnByb3Rv
+dHlwZT17fQpKLmtkLnByb3RvdHlwZT17fQpKLmM1LnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7dmFy
+IHQ9YVskLncoKV0KaWYodD09bnVsbClyZXR1cm4gdGhpcy50KGEpCnJldHVybiJKYXZhU2NyaXB0IGZ1
+bmN0aW9uIGZvciAiK0guRWooSi5qKHQpKX0sCiRTOmZ1bmN0aW9uKCl7cmV0dXJue2Z1bmM6MSxvcHQ6
+WywsLCwsLCwsLCwsLCwsLCxdfX0sCiRpRUg6MX0KSi5qZC5wcm90b3R5cGU9ewppOmZ1bmN0aW9uKGEs
+Yil7SC50NihhKS5jLmEoYikKaWYoISFhLmZpeGVkJGxlbmd0aClILnZoKFAuTDQoImFkZCIpKQphLnB1
+c2goYil9LApXNDpmdW5jdGlvbihhLGIpe3ZhciB0CmlmKCEhYS5maXhlZCRsZW5ndGgpSC52aChQLkw0
+KCJyZW1vdmVBdCIpKQp0PWEubGVuZ3RoCmlmKGI+PXQpdGhyb3cgSC5iKFAuTzcoYixudWxsKSkKcmV0
+dXJuIGEuc3BsaWNlKGIsMSlbMF19LApVRzpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyCkgudDYoYSku
+QygiY1g8MT4iKS5hKGMpCmlmKCEhYS5maXhlZCRsZW5ndGgpSC52aChQLkw0KCJpbnNlcnRBbGwiKSkK
+dD1hLmxlbmd0aApQLndBKGIsMCx0LCJpbmRleCIpCnM9Yy5sZW5ndGgKdGhpcy5zQShhLHQrcykKcj1i
+K3MKdGhpcy5ZVyhhLHIsYS5sZW5ndGgsYSxiKQp0aGlzLnZnKGEsYixyLGMpfSwKbXY6ZnVuY3Rpb24o
+YSl7aWYoISFhLmZpeGVkJGxlbmd0aClILnZoKFAuTDQoInJlbW92ZUxhc3QiKSkKaWYoYS5sZW5ndGg9
+PT0wKXRocm93IEguYihILkhZKGEsLTEpKQpyZXR1cm4gYS5wb3AoKX0sCkZWOmZ1bmN0aW9uKGEsYil7
+dmFyIHQKSC50NihhKS5DKCJjWDwxPiIpLmEoYikKaWYoISFhLmZpeGVkJGxlbmd0aClILnZoKFAuTDQo
+ImFkZEFsbCIpKQpmb3IodD1KLklUKGIpO3QuRigpOylhLnB1c2godC5nbCgpKX0sCkUyOmZ1bmN0aW9u
+KGEsYixjKXt2YXIgdD1ILnQ2KGEpCnJldHVybiBuZXcgSC5sSihhLHQuS3EoYykuQygiMSgyKSIpLmEo
+YiksdC5DKCJAPDE+IikuS3EoYykuQygibEo8MSwyPiIpKX0sCkg6ZnVuY3Rpb24oYSxiKXt2YXIgdCxz
+PVAuTzgoYS5sZW5ndGgsIiIsITEsdS5OKQpmb3IodD0wO3Q8YS5sZW5ndGg7Kyt0KXRoaXMuWShzLHQs
+SC5FaihhW3RdKSkKcmV0dXJuIHMuam9pbihiKX0sCk4wOmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0LHMs
+cgpkLmEoYikKSC50NihhKS5LcShkKS5DKCIxKDEsMikiKS5hKGMpCnQ9YS5sZW5ndGgKZm9yKHM9Yixy
+PTA7cjx0Oysrcil7cz1jLiQyKHMsYVtyXSkKaWYoYS5sZW5ndGghPT10KXRocm93IEguYihQLmE0KGEp
+KX1yZXR1cm4gc30sCkh0OmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEscApILnQ2KGEpLkMoImEyKDEp
+IikuYShiKQp0PWEubGVuZ3RoCmZvcihzPW51bGwscj0hMSxxPTA7cTx0OysrcSl7cD1hW3FdCmlmKEgu
+b1QoYi4kMShwKSkpe2lmKHIpdGhyb3cgSC5iKEguQW0oKSkKcz1wCnI9ITB9aWYodCE9PWEubGVuZ3Ro
+KXRocm93IEguYihQLmE0KGEpKX1pZihyKXJldHVybiBzCnRocm93IEguYihILldwKCkpfSwKRTpmdW5j
+dGlvbihhLGIpe2lmKGI8MHx8Yj49YS5sZW5ndGgpcmV0dXJuIEguT0goYSxiKQpyZXR1cm4gYVtiXX0s
+Cmd0SDpmdW5jdGlvbihhKXtpZihhLmxlbmd0aD4wKXJldHVybiBhWzBdCnRocm93IEguYihILldwKCkp
+fSwKZ3JaOmZ1bmN0aW9uKGEpe3ZhciB0PWEubGVuZ3RoCmlmKHQ+MClyZXR1cm4gYVt0LTFdCnRocm93
+IEguYihILldwKCkpfSwKWVc6ZnVuY3Rpb24oYSxiLGMsZCxlKXt2YXIgdCxzLHIscQpILnQ2KGEpLkMo
+ImNYPDE+IikuYShkKQppZighIWEuaW1tdXRhYmxlJGxpc3QpSC52aChQLkw0KCJzZXRSYW5nZSIpKQpQ
+LmpCKGIsYyxhLmxlbmd0aCkKdD1jLWIKaWYodD09PTApcmV0dXJuClAuazEoZSwic2tpcENvdW50IikK
+cz1kCnI9Si5VNihzKQppZihlK3Q+ci5nQShzKSl0aHJvdyBILmIoSC5hcigpKQppZihlPGIpZm9yKHE9
+dC0xO3E+PTA7LS1xKWFbYitxXT1yLnEocyxlK3EpCmVsc2UgZm9yKHE9MDtxPHQ7KytxKWFbYitxXT1y
+LnEocyxlK3EpfSwKdmc6ZnVuY3Rpb24oYSxiLGMsZCl7cmV0dXJuIHRoaXMuWVcoYSxiLGMsZCwwKX0s
+ClZyOmZ1bmN0aW9uKGEsYil7dmFyIHQscwpILnQ2KGEpLkMoImEyKDEpIikuYShiKQp0PWEubGVuZ3Ro
+CmZvcihzPTA7czx0Oysrcyl7aWYoSC5vVChiLiQxKGFbc10pKSlyZXR1cm4hMAppZihhLmxlbmd0aCE9
+PXQpdGhyb3cgSC5iKFAuYTQoYSkpfXJldHVybiExfSwKdGc6ZnVuY3Rpb24oYSxiKXt2YXIgdApmb3Io
+dD0wO3Q8YS5sZW5ndGg7Kyt0KWlmKEouUk0oYVt0XSxiKSlyZXR1cm4hMApyZXR1cm4hMX0sCmdsMDpm
+dW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGg9PT0wfSwKZ29yOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxl
+bmd0aCE9PTB9LAp3OmZ1bmN0aW9uKGEpe3JldHVybiBQLldFKGEsIlsiLCJdIil9LApna3o6ZnVuY3Rp
+b24oYSl7cmV0dXJuIG5ldyBKLm0xKGEsYS5sZW5ndGgsSC50NihhKS5DKCJtMTwxPiIpKX0sCmdpTzpm
+dW5jdGlvbihhKXtyZXR1cm4gSC5lUShhKX0sCmdBOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH0s
+CnNBOmZ1bmN0aW9uKGEsYil7aWYoISFhLmZpeGVkJGxlbmd0aClILnZoKFAuTDQoInNldCBsZW5ndGgi
+KSkKYS5sZW5ndGg9Yn0sCnE6ZnVuY3Rpb24oYSxiKXtILnVQKGIpCmlmKGI+PWEubGVuZ3RofHxiPDAp
+dGhyb3cgSC5iKEguSFkoYSxiKSkKcmV0dXJuIGFbYl19LApZOmZ1bmN0aW9uKGEsYixjKXtILnQ2KGEp
+LmMuYShjKQppZighIWEuaW1tdXRhYmxlJGxpc3QpSC52aChQLkw0KCJpbmRleGVkIHNldCIpKQppZihi
+Pj1hLmxlbmd0aHx8YjwwKXRocm93IEguYihILkhZKGEsYikpCmFbYl09Y30sCiRpYlE6MSwKJGljWDox
+LAokaXpNOjF9CkouUG8ucHJvdG90eXBlPXt9CkoubTEucHJvdG90eXBlPXsKZ2w6ZnVuY3Rpb24oKXty
+ZXR1cm4gdGhpcy5kfSwKRjpmdW5jdGlvbigpe3ZhciB0LHM9dGhpcyxyPXMuYSxxPXIubGVuZ3RoCmlm
+KHMuYiE9PXEpdGhyb3cgSC5iKEgubGsocikpCnQ9cy5jCmlmKHQ+PXEpe3Muc00obnVsbCkKcmV0dXJu
+ITF9cy5zTShyW3RdKTsrK3MuYwpyZXR1cm4hMH0sCnNNOmZ1bmN0aW9uKGEpe3RoaXMuZD10aGlzLiR0
+aS5DKCIxPyIpLmEoYSl9LAokaUFuOjF9CkoucUkucHJvdG90eXBlPXsKelE6ZnVuY3Rpb24oYSl7aWYo
+YT4wKXtpZihhIT09MS8wKXJldHVybiBNYXRoLnJvdW5kKGEpfWVsc2UgaWYoYT4tMS8wKXJldHVybiAw
+LU1hdGgucm91bmQoMC1hKQp0aHJvdyBILmIoUC5MNCgiIithKyIucm91bmQoKSIpKX0sCnc6ZnVuY3Rp
+b24oYSl7aWYoYT09PTAmJjEvYTwwKXJldHVybiItMC4wIgplbHNlIHJldHVybiIiK2F9LApnaU86ZnVu
+Y3Rpb24oYSl7dmFyIHQscyxyLHEscD1hfDAKaWYoYT09PXApcmV0dXJuIDUzNjg3MDkxMSZwCnQ9TWF0
+aC5hYnMoYSkKcz1NYXRoLmxvZyh0KS8wLjY5MzE0NzE4MDU1OTk0NTN8MApyPU1hdGgucG93KDIscykK
+cT10PDE/dC9yOnIvdApyZXR1cm4gNTM2ODcwOTExJigocSo5MDA3MTk5MjU0NzQwOTkyfDApKyhxKjM1
+NDIyNDMxODExNzY1MjF8MCkpKjU5OTE5NytzKjEyNTl9LAp6WTpmdW5jdGlvbihhLGIpe3ZhciB0PWEl
+YgppZih0PT09MClyZXR1cm4gMAppZih0PjApcmV0dXJuIHQKaWYoYjwwKXJldHVybiB0LWIKZWxzZSBy
+ZXR1cm4gdCtifSwKQlU6ZnVuY3Rpb24oYSxiKXtyZXR1cm4oYXwwKT09PWE/YS9ifDA6dGhpcy5ESihh
+LGIpfSwKREo6ZnVuY3Rpb24oYSxiKXt2YXIgdD1hL2IKaWYodD49LTIxNDc0ODM2NDgmJnQ8PTIxNDc0
+ODM2NDcpcmV0dXJuIHR8MAppZih0PjApe2lmKHQhPT0xLzApcmV0dXJuIE1hdGguZmxvb3IodCl9ZWxz
+ZSBpZih0Pi0xLzApcmV0dXJuIE1hdGguY2VpbCh0KQp0aHJvdyBILmIoUC5MNCgiUmVzdWx0IG9mIHRy
+dW5jYXRpbmcgZGl2aXNpb24gaXMgIitILkVqKHQpKyI6ICIrSC5FaihhKSsiIH4vICIrYikpfSwKd0c6
+ZnVuY3Rpb24oYSxiKXt2YXIgdAppZihhPjApdD10aGlzLnAzKGEsYikKZWxzZXt0PWI+MzE/MzE6Ygp0
+PWE+PnQ+Pj4wfXJldHVybiB0fSwKYmY6ZnVuY3Rpb24oYSxiKXtpZihiPDApdGhyb3cgSC5iKEgudEwo
+YikpCnJldHVybiB0aGlzLnAzKGEsYil9LApwMzpmdW5jdGlvbihhLGIpe3JldHVybiBiPjMxPzA6YT4+
+PmJ9LAokaUNQOjEsCiRpbGY6MX0KSi5iVS5wcm90b3R5cGU9eyRpSWY6MX0KSi5WQS5wcm90b3R5cGU9
+e30KSi5Eci5wcm90b3R5cGU9ewptOmZ1bmN0aW9uKGEsYil7aWYoYjwwKXRocm93IEguYihILkhZKGEs
+YikpCmlmKGI+PWEubGVuZ3RoKUgudmgoSC5IWShhLGIpKQpyZXR1cm4gYS5jaGFyQ29kZUF0KGIpfSwK
+VzpmdW5jdGlvbihhLGIpe2lmKGI+PWEubGVuZ3RoKXRocm93IEguYihILkhZKGEsYikpCnJldHVybiBh
+LmNoYXJDb2RlQXQoYil9LApkZDpmdW5jdGlvbihhLGIpe3JldHVybiBuZXcgSC51bihiLGEsMCl9LApo
+OmZ1bmN0aW9uKGEsYil7aWYodHlwZW9mIGIhPSJzdHJpbmciKXRocm93IEguYihQLkwzKGIsbnVsbCxu
+dWxsKSkKcmV0dXJuIGErYn0sClRjOmZ1bmN0aW9uKGEsYil7dmFyIHQ9Yi5sZW5ndGgscz1hLmxlbmd0
+aAppZih0PnMpcmV0dXJuITEKcmV0dXJuIGI9PT10aGlzLkcoYSxzLXQpfSwKaTc6ZnVuY3Rpb24oYSxi
+LGMsZCl7dmFyIHQ9UC5qQihiLGMsYS5sZW5ndGgpLHM9YS5zdWJzdHJpbmcoMCxiKSxyPWEuc3Vic3Ry
+aW5nKHQpCnJldHVybiBzK2Qrcn0sClFpOmZ1bmN0aW9uKGEsYixjKXt2YXIgdAppZihjPDB8fGM+YS5s
+ZW5ndGgpdGhyb3cgSC5iKFAuVEUoYywwLGEubGVuZ3RoLG51bGwsbnVsbCkpCnQ9YytiLmxlbmd0aApp
+Zih0PmEubGVuZ3RoKXJldHVybiExCnJldHVybiBiPT09YS5zdWJzdHJpbmcoYyx0KX0sCm46ZnVuY3Rp
+b24oYSxiKXtyZXR1cm4gdGhpcy5RaShhLGIsMCl9LApOajpmdW5jdGlvbihhLGIsYyl7aWYoYz09bnVs
+bCljPWEubGVuZ3RoCmlmKGI8MCl0aHJvdyBILmIoUC5PNyhiLG51bGwpKQppZihiPmMpdGhyb3cgSC5i
+KFAuTzcoYixudWxsKSkKaWYoYz5hLmxlbmd0aCl0aHJvdyBILmIoUC5PNyhjLG51bGwpKQpyZXR1cm4g
+YS5zdWJzdHJpbmcoYixjKX0sCkc6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5OaihhLGIsbnVsbCl9
+LApoYzpmdW5jdGlvbihhKXtyZXR1cm4gYS50b0xvd2VyQ2FzZSgpfSwKYlM6ZnVuY3Rpb24oYSl7dmFy
+IHQscyxyLHE9YS50cmltKCkscD1xLmxlbmd0aAppZihwPT09MClyZXR1cm4gcQppZih0aGlzLlcocSww
+KT09PTEzMyl7dD1KLm1tKHEsMSkKaWYodD09PXApcmV0dXJuIiJ9ZWxzZSB0PTAKcz1wLTEKcj10aGlz
+Lm0ocSxzKT09PTEzMz9KLmMxKHEscyk6cAppZih0PT09MCYmcj09PXApcmV0dXJuIHEKcmV0dXJuIHEu
+c3Vic3RyaW5nKHQscil9LApJeDpmdW5jdGlvbihhLGIpe3ZhciB0LHMKaWYoMD49YilyZXR1cm4iIgpp
+ZihiPT09MXx8YS5sZW5ndGg9PT0wKXJldHVybiBhCmlmKGIhPT1iPj4+MCl0aHJvdyBILmIoQy5FcSkK
+Zm9yKHQ9YSxzPSIiOyEwOyl7aWYoKGImMSk9PT0xKXM9dCtzCmI9Yj4+PjEKaWYoYj09PTApYnJlYWsK
+dCs9dH1yZXR1cm4gc30sClhVOmZ1bmN0aW9uKGEsYixjKXt2YXIgdAppZihjPDB8fGM+YS5sZW5ndGgp
+dGhyb3cgSC5iKFAuVEUoYywwLGEubGVuZ3RoLG51bGwsbnVsbCkpCnQ9YS5pbmRleE9mKGIsYykKcmV0
+dXJuIHR9LApPWTpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLlhVKGEsYiwwKX0sClBrOmZ1bmN0aW9u
+KGEsYixjKXt2YXIgdCxzCmlmKGM9PW51bGwpYz1hLmxlbmd0aAplbHNlIGlmKGM8MHx8Yz5hLmxlbmd0
+aCl0aHJvdyBILmIoUC5URShjLDAsYS5sZW5ndGgsbnVsbCxudWxsKSkKdD1iLmxlbmd0aApzPWEubGVu
+Z3RoCmlmKGMrdD5zKWM9cy10CnJldHVybiBhLmxhc3RJbmRleE9mKGIsYyl9LApjbjpmdW5jdGlvbihh
+LGIpe3JldHVybiB0aGlzLlBrKGEsYixudWxsKX0sCklzOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1hLmxl
+bmd0aAppZihjPnQpdGhyb3cgSC5iKFAuVEUoYywwLHQsbnVsbCxudWxsKSkKcmV0dXJuIEgubTIoYSxi
+LGMpfSwKdGc6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5JcyhhLGIsMCl9LAp3OmZ1bmN0aW9uKGEp
+e3JldHVybiBhfSwKZ2lPOmZ1bmN0aW9uKGEpe3ZhciB0LHMscgpmb3IodD1hLmxlbmd0aCxzPTAscj0w
+O3I8dDsrK3Ipe3M9NTM2ODcwOTExJnMrYS5jaGFyQ29kZUF0KHIpCnM9NTM2ODcwOTExJnMrKCg1MjQy
+ODcmcyk8PDEwKQpzXj1zPj42fXM9NTM2ODcwOTExJnMrKCg2NzEwODg2MyZzKTw8MykKc149cz4+MTEK
+cmV0dXJuIDUzNjg3MDkxMSZzKygoMTYzODMmcyk8PDE1KX0sCmdBOmZ1bmN0aW9uKGEpe3JldHVybiBh
+Lmxlbmd0aH0sCnE6ZnVuY3Rpb24oYSxiKXtILnVQKGIpCmlmKGI+PWEubGVuZ3RofHwhMSl0aHJvdyBI
+LmIoSC5IWShhLGIpKQpyZXR1cm4gYVtiXX0sCiRpdlg6MSwKJGlxVToxfQpILm5kLnByb3RvdHlwZT17
+Cnc6ZnVuY3Rpb24oYSl7dmFyIHQ9IkxhdGVJbml0aWFsaXphdGlvbkVycm9yOiAiK3RoaXMuYQpyZXR1
+cm4gdH19CkgucWoucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYS5sZW5ndGh9
+LApxOmZ1bmN0aW9uKGEsYil7cmV0dXJuIEMueEIubSh0aGlzLmEsSC51UChiKSl9fQpILmJRLnByb3Rv
+dHlwZT17fQpILmFMLnByb3RvdHlwZT17CmdrejpmdW5jdGlvbihhKXt2YXIgdD10aGlzCnJldHVybiBu
+ZXcgSC5hNyh0LHQuZ0EodCksSC5MaCh0KS5DKCJhNzxhTC5FPiIpKX0sCmdsMDpmdW5jdGlvbihhKXty
+ZXR1cm4gdGhpcy5nQSh0aGlzKT09PTB9LApIOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHE9dGhpcyxw
+PXEuZ0EocSkKaWYoYi5sZW5ndGghPT0wKXtpZihwPT09MClyZXR1cm4iIgp0PUguRWoocS5FKDAsMCkp
+CmlmKHAhPT1xLmdBKHEpKXRocm93IEguYihQLmE0KHEpKQpmb3Iocz10LHI9MTtyPHA7KytyKXtzPXMr
+YitILkVqKHEuRSgwLHIpKQppZihwIT09cS5nQShxKSl0aHJvdyBILmIoUC5hNChxKSl9cmV0dXJuIHMu
+Y2hhckNvZGVBdCgwKT09MD9zOnN9ZWxzZXtmb3Iocj0wLHM9IiI7cjxwOysrcil7cys9SC5FaihxLkUo
+MCxyKSkKaWYocCE9PXEuZ0EocSkpdGhyb3cgSC5iKFAuYTQocSkpfXJldHVybiBzLmNoYXJDb2RlQXQo
+MCk9PTA/czpzfX0sCmV2OmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuR0coMCxILkxoKHRoaXMpLkMo
+ImEyKGFMLkUpIikuYShiKSl9LApFMjpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9SC5MaCh0aGlzKQpyZXR1
+cm4gbmV3IEgubEoodGhpcyx0LktxKGMpLkMoIjEoYUwuRSkiKS5hKGIpLHQuQygiQDxhTC5FPiIpLktx
+KGMpLkMoImxKPDEsMj4iKSl9fQpILm5ILnByb3RvdHlwZT17CmdVRDpmdW5jdGlvbigpe3ZhciB0PUou
+SG0odGhpcy5hKSxzPXRoaXMuYwppZihzPT1udWxsfHxzPnQpcmV0dXJuIHQKcmV0dXJuIHN9LApnQXM6
+ZnVuY3Rpb24oKXt2YXIgdD1KLkhtKHRoaXMuYSkscz10aGlzLmIKaWYocz50KXJldHVybiB0CnJldHVy
+biBzfSwKZ0E6ZnVuY3Rpb24oYSl7dmFyIHQscz1KLkhtKHRoaXMuYSkscj10aGlzLmIKaWYocj49cyly
+ZXR1cm4gMAp0PXRoaXMuYwppZih0PT1udWxsfHx0Pj1zKXJldHVybiBzLXIKaWYodHlwZW9mIHQhPT0i
+bnVtYmVyIilyZXR1cm4gdC5ITigpCnJldHVybiB0LXJ9LApFOmZ1bmN0aW9uKGEsYil7dmFyIHQ9dGhp
+cyxzPXQuZ0FzKCkrYgppZihiPDB8fHM+PXQuZ1VEKCkpdGhyb3cgSC5iKFAuQ2YoYix0LCJpbmRleCIs
+bnVsbCxudWxsKSkKcmV0dXJuIEouR0EodC5hLHMpfX0KSC5hNy5wcm90b3R5cGU9ewpnbDpmdW5jdGlv
+bigpe3ZhciB0PXRoaXMuZApyZXR1cm4gdH0sCkY6ZnVuY3Rpb24oKXt2YXIgdCxzPXRoaXMscj1zLmEs
+cT1KLlU2KHIpLHA9cS5nQShyKQppZihzLmIhPT1wKXRocm93IEguYihQLmE0KHIpKQp0PXMuYwppZih0
+Pj1wKXtzLnNJKG51bGwpCnJldHVybiExfXMuc0kocS5FKHIsdCkpOysrcy5jCnJldHVybiEwfSwKc0k6
+ZnVuY3Rpb24oYSl7dGhpcy5kPXRoaXMuJHRpLkMoIjE/IikuYShhKX0sCiRpQW46MX0KSC5pMS5wcm90
+b3R5cGU9ewpna3o6ZnVuY3Rpb24oYSl7dmFyIHQ9SC5MaCh0aGlzKQpyZXR1cm4gbmV3IEguTUgoSi5J
+VCh0aGlzLmEpLHRoaXMuYix0LkMoIkA8MT4iKS5LcSh0LlFbMV0pLkMoIk1IPDEsMj4iKSl9LApnQTpm
+dW5jdGlvbihhKXtyZXR1cm4gSi5IbSh0aGlzLmEpfX0KSC54eS5wcm90b3R5cGU9eyRpYlE6MX0KSC5N
+SC5wcm90b3R5cGU9ewpGOmZ1bmN0aW9uKCl7dmFyIHQ9dGhpcyxzPXQuYgppZihzLkYoKSl7dC5zSSh0
+LmMuJDEocy5nbCgpKSkKcmV0dXJuITB9dC5zSShudWxsKQpyZXR1cm4hMX0sCmdsOmZ1bmN0aW9uKCl7
+dmFyIHQ9dGhpcy5hCnJldHVybiB0fSwKc0k6ZnVuY3Rpb24oYSl7dGhpcy5hPXRoaXMuJHRpLkMoIjI/
+IikuYShhKX19CkgubEoucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIEouSG0odGhpcy5h
+KX0sCkU6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5iLiQxKEouR0EodGhpcy5hLGIpKX19CkguVTUu
+cHJvdG90eXBlPXsKZ2t6OmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgSC5TTyhKLklUKHRoaXMuYSksdGhp
+cy5iLHRoaXMuJHRpLkMoIlNPPDE+IikpfX0KSC5TTy5wcm90b3R5cGU9ewpGOmZ1bmN0aW9uKCl7dmFy
+IHQscwpmb3IodD10aGlzLmEscz10aGlzLmI7dC5GKCk7KWlmKEgub1Qocy4kMSh0LmdsKCkpKSlyZXR1
+cm4hMApyZXR1cm4hMX0sCmdsOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuYS5nbCgpfX0KSC5TVS5wcm90
+b3R5cGU9e30KSC5SZS5wcm90b3R5cGU9ewpZOmZ1bmN0aW9uKGEsYixjKXtILkxoKHRoaXMpLkMoIlJl
+LkUiKS5hKGMpCnRocm93IEguYihQLkw0KCJDYW5ub3QgbW9kaWZ5IGFuIHVubW9kaWZpYWJsZSBsaXN0
+IikpfX0KSC53Mi5wcm90b3R5cGU9e30KSC53di5wcm90b3R5cGU9ewpnaU86ZnVuY3Rpb24oYSl7dmFy
+IHQ9dGhpcy5faGFzaENvZGUKaWYodCE9bnVsbClyZXR1cm4gdAp0PTUzNjg3MDkxMSY2NjQ1OTcqSi5o
+Zih0aGlzLmEpCnRoaXMuX2hhc2hDb2RlPXQKcmV0dXJuIHR9LAp3OmZ1bmN0aW9uKGEpe3JldHVybidT
+eW1ib2woIicrSC5Faih0aGlzLmEpKyciKSd9LApETjpmdW5jdGlvbihhLGIpe2lmKGI9PW51bGwpcmV0
+dXJuITEKcmV0dXJuIGIgaW5zdGFuY2VvZiBILnd2JiZ0aGlzLmE9PWIuYX0sCiRpR0Q6MX0KSC5QRC5w
+cm90b3R5cGU9e30KSC5XVS5wcm90b3R5cGU9ewpnbDA6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuZ0Eo
+dGhpcyk9PT0wfSwKdzpmdW5jdGlvbihhKXtyZXR1cm4gUC5uTyh0aGlzKX0sClk6ZnVuY3Rpb24oYSxi
+LGMpe3ZhciB0PUguTGgodGhpcykKdC5jLmEoYikKdC5RWzFdLmEoYykKSC5kYygpfSwKZ1B1OmZ1bmN0
+aW9uKGEpe3JldHVybiB0aGlzLnE0KGEsSC5MaCh0aGlzKS5DKCJOMzwxLDI+IikpfSwKcTQ6ZnVuY3Rp
+b24oYSxiKXt2YXIgdD10aGlzCnJldHVybiBQLmwwKGZ1bmN0aW9uKCl7dmFyIHM9YQp2YXIgcj0wLHE9
+MSxwLG8sbixtLGwKcmV0dXJuIGZ1bmN0aW9uICRhc3luYyRnUHUoYyxkKXtpZihjPT09MSl7cD1kCnI9
+cX13aGlsZSh0cnVlKXN3aXRjaChyKXtjYXNlIDA6bz10LmdWKCksbz1vLmdreihvKSxuPUguTGgodCks
+bj1uLkMoIkA8MT4iKS5LcShuLlFbMV0pLkMoIk4zPDEsMj4iKQpjYXNlIDI6aWYoIW8uRigpKXtyPTMK
+YnJlYWt9bT1vLmdsKCkKbD10LnEoMCxtKQpsLnRvU3RyaW5nCnI9NApyZXR1cm4gbmV3IFAuTjMobSxs
+LG4pCmNhc2UgNDpyPTIKYnJlYWsKY2FzZSAzOnJldHVybiBQLlRoKCkKY2FzZSAxOnJldHVybiBQLllt
+KHApfX19LGIpfSwKJGlaMDoxfQpILkxQLnByb3RvdHlwZT17CmdBOmZ1bmN0aW9uKGEpe3JldHVybiB0
+aGlzLmF9LAp4NDpmdW5jdGlvbihhKXtpZih0eXBlb2YgYSE9InN0cmluZyIpcmV0dXJuITEKaWYoIl9f
+cHJvdG9fXyI9PT1hKXJldHVybiExCnJldHVybiB0aGlzLmIuaGFzT3duUHJvcGVydHkoYSl9LApxOmZ1
+bmN0aW9uKGEsYil7aWYoIXRoaXMueDQoYikpcmV0dXJuIG51bGwKcmV0dXJuIHRoaXMuRChiKX0sCkQ6
+ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYltILmgoYSldfSwKSzpmdW5jdGlvbihhLGIpe3ZhciB0LHMs
+cixxLHA9SC5MaCh0aGlzKQpwLkMoIn4oMSwyKSIpLmEoYikKdD10aGlzLmMKZm9yKHM9dC5sZW5ndGgs
+cD1wLlFbMV0scj0wO3I8czsrK3Ipe3E9dFtyXQpiLiQyKHEscC5hKHRoaXMuRChxKSkpfX0sCmdWOmZ1
+bmN0aW9uKCl7cmV0dXJuIG5ldyBILlhSKHRoaXMsSC5MaCh0aGlzKS5DKCJYUjwxPiIpKX19CkguWFIu
+cHJvdG90eXBlPXsKZ2t6OmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuYS5jCnJldHVybiBuZXcgSi5tMSh0
+LHQubGVuZ3RoLEgudDYodCkuQygibTE8MT4iKSl9LApnQTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5h
+LmMubGVuZ3RofX0KSC5MSS5wcm90b3R5cGU9ewpnV2E6ZnVuY3Rpb24oKXt2YXIgdD10aGlzLmEKcmV0
+dXJuIHR9LApnbmQ6ZnVuY3Rpb24oKXt2YXIgdCxzLHIscSxwPXRoaXMKaWYocC5jPT09MSlyZXR1cm4g
+Qy5oVQp0PXAuZApzPXQubGVuZ3RoLXAuZS5sZW5ndGgtcC5mCmlmKHM9PT0wKXJldHVybiBDLmhVCnI9
+W10KZm9yKHE9MDtxPHM7KytxKXtpZihxPj10Lmxlbmd0aClyZXR1cm4gSC5PSCh0LHEpCnIucHVzaCh0
+W3FdKX1yZXR1cm4gSi56QyhyKX0sCmdWbTpmdW5jdGlvbigpe3ZhciB0LHMscixxLHAsbyxuLG0sbD10
+aGlzCmlmKGwuYyE9PTApcmV0dXJuIEMuRHgKdD1sLmUKcz10Lmxlbmd0aApyPWwuZApxPXIubGVuZ3Ro
+LXMtbC5mCmlmKHM9PT0wKXJldHVybiBDLkR4CnA9bmV3IEguTjUodS5lbykKZm9yKG89MDtvPHM7Kytv
+KXtpZihvPj10Lmxlbmd0aClyZXR1cm4gSC5PSCh0LG8pCm49dFtvXQptPXErbwppZihtPDB8fG0+PXIu
+bGVuZ3RoKXJldHVybiBILk9IKHIsbSkKcC5ZKDAsbmV3IEgud3YobiksclttXSl9cmV0dXJuIG5ldyBI
+LlBEKHAsdS5nRil9LAokaXZROjF9CkguQ2oucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt2YXIg
+dApILmgoYSkKdD10aGlzLmEKdC5iPXQuYisiJCIrSC5FaihhKQpDLk5tLmkodGhpcy5iLGEpCkMuTm0u
+aSh0aGlzLmMsYik7Kyt0LmF9LAokUzoxM30KSC5mOS5wcm90b3R5cGU9ewpxUzpmdW5jdGlvbihhKXt2
+YXIgdCxzLHI9dGhpcyxxPW5ldyBSZWdFeHAoci5hKS5leGVjKGEpCmlmKHE9PW51bGwpcmV0dXJuIG51
+bGwKdD1PYmplY3QuY3JlYXRlKG51bGwpCnM9ci5iCmlmKHMhPT0tMSl0LmFyZ3VtZW50cz1xW3MrMV0K
+cz1yLmMKaWYocyE9PS0xKXQuYXJndW1lbnRzRXhwcj1xW3MrMV0Kcz1yLmQKaWYocyE9PS0xKXQuZXhw
+cj1xW3MrMV0Kcz1yLmUKaWYocyE9PS0xKXQubWV0aG9kPXFbcysxXQpzPXIuZgppZihzIT09LTEpdC5y
+ZWNlaXZlcj1xW3MrMV0KcmV0dXJuIHR9fQpILlcwLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7dmFy
+IHQ9dGhpcy5iCmlmKHQ9PW51bGwpcmV0dXJuIk5vU3VjaE1ldGhvZEVycm9yOiAiK0guRWoodGhpcy5h
+KQpyZXR1cm4iTm9TdWNoTWV0aG9kRXJyb3I6IG1ldGhvZCBub3QgZm91bmQ6ICciK3QrIicgb24gbnVs
+bCJ9fQpILmF6LnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7dmFyIHQscz10aGlzLHI9Ik5vU3VjaE1l
+dGhvZEVycm9yOiBtZXRob2Qgbm90IGZvdW5kOiAnIixxPXMuYgppZihxPT1udWxsKXJldHVybiJOb1N1
+Y2hNZXRob2RFcnJvcjogIitILkVqKHMuYSkKdD1zLmMKaWYodD09bnVsbClyZXR1cm4gcitxKyInICgi
+K0guRWoocy5hKSsiKSIKcmV0dXJuIHIrcSsiJyBvbiAnIit0KyInICgiK0guRWoocy5hKSsiKSJ9fQpI
+LnZWLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5hCnJldHVybiB0Lmxlbmd0aD09
+PTA/IkVycm9yIjoiRXJyb3I6ICIrdH19CkgudGUucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1
+cm4iVGhyb3cgb2YgbnVsbCAoJyIrKHRoaXMuYT09PW51bGw/Im51bGwiOiJ1bmRlZmluZWQiKSsiJyBm
+cm9tIEphdmFTY3JpcHQpIn0sCiRpUno6MX0KSC5icS5wcm90b3R5cGU9e30KSC5YTy5wcm90b3R5cGU9
+ewp3OmZ1bmN0aW9uKGEpe3ZhciB0LHM9dGhpcy5iCmlmKHMhPW51bGwpcmV0dXJuIHMKcz10aGlzLmEK
+dD1zIT09bnVsbCYmdHlwZW9mIHM9PT0ib2JqZWN0Ij9zLnN0YWNrOm51bGwKcmV0dXJuIHRoaXMuYj10
+PT1udWxsPyIiOnR9LAokaUd6OjF9Ckgudi5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3ZhciB0PXRo
+aXMuY29uc3RydWN0b3Iscz10PT1udWxsP251bGw6dC5uYW1lCnJldHVybiJDbG9zdXJlICciK0guTlEo
+cz09bnVsbD8idW5rbm93biI6cykrIicifSwKJGlFSDoxLApnS3U6ZnVuY3Rpb24oKXtyZXR1cm4gdGhp
+c30sCiRDOiIkMSIsCiRSOjEsCiREOm51bGx9CkgubGMucHJvdG90eXBlPXt9CkguengucHJvdG90eXBl
+PXsKdzpmdW5jdGlvbihhKXt2YXIgdD10aGlzLiRzdGF0aWNfbmFtZQppZih0PT1udWxsKXJldHVybiJD
+bG9zdXJlIG9mIHVua25vd24gc3RhdGljIG1ldGhvZCIKcmV0dXJuIkNsb3N1cmUgJyIrSC5OUSh0KSsi
+JyJ9fQpILnJULnByb3RvdHlwZT17CkROOmZ1bmN0aW9uKGEsYil7dmFyIHQ9dGhpcwppZihiPT1udWxs
+KXJldHVybiExCmlmKHQ9PT1iKXJldHVybiEwCmlmKCEoYiBpbnN0YW5jZW9mIEguclQpKXJldHVybiEx
+CnJldHVybiB0LmE9PT1iLmEmJnQuYj09PWIuYiYmdC5jPT09Yi5jfSwKZ2lPOmZ1bmN0aW9uKGEpe3Zh
+ciB0LHM9dGhpcy5jCmlmKHM9PW51bGwpdD1ILmVRKHRoaXMuYSkKZWxzZSB0PXR5cGVvZiBzIT09Im9i
+amVjdCI/Si5oZihzKTpILmVRKHMpCnJldHVybih0XkguZVEodGhpcy5iKSk+Pj4wfSwKdzpmdW5jdGlv
+bihhKXt2YXIgdD10aGlzLmMKaWYodD09bnVsbCl0PXRoaXMuYQpyZXR1cm4iQ2xvc3VyZSAnIitILkVq
+KHRoaXMuZCkrIicgb2YgIisoIkluc3RhbmNlIG9mICciK0guRWooSC5NKHQpKSsiJyIpfX0KSC5FcS5w
+cm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiJSdW50aW1lRXJyb3I6ICIrSC5Faih0aGlzLmEp
+fX0KSC5rWS5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiJBc3NlcnRpb24gZmFpbGVkOiAi
+K1AucCh0aGlzLmEpfX0KSC5rci5wcm90b3R5cGU9e30KSC5ONS5wcm90b3R5cGU9ewpnQTpmdW5jdGlv
+bihhKXtyZXR1cm4gdGhpcy5hfSwKZ2wwOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmE9PT0wfSwKZ1Y6
+ZnVuY3Rpb24oKXtyZXR1cm4gbmV3IEguaTUodGhpcyxILkxoKHRoaXMpLkMoImk1PDE+IikpfSwKeDQ6
+ZnVuY3Rpb24oYSl7dmFyIHQscwppZih0eXBlb2YgYT09InN0cmluZyIpe3Q9dGhpcy5iCmlmKHQ9PW51
+bGwpcmV0dXJuITEKcmV0dXJuIHRoaXMuWHUodCxhKX1lbHNle3M9dGhpcy5DWChhKQpyZXR1cm4gc319
+LApDWDpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmQKaWYodD09bnVsbClyZXR1cm4hMQpyZXR1cm4gdGhp
+cy5GaCh0aGlzLkJ0KHQsSi5oZihhKSYweDNmZmZmZmYpLGEpPj0wfSwKcTpmdW5jdGlvbihhLGIpe3Zh
+ciB0LHMscixxLHA9dGhpcyxvPW51bGwKaWYodHlwZW9mIGI9PSJzdHJpbmciKXt0PXAuYgppZih0PT1u
+dWxsKXJldHVybiBvCnM9cC5qMih0LGIpCnI9cz09bnVsbD9vOnMuYgpyZXR1cm4gcn1lbHNlIGlmKHR5
+cGVvZiBiPT0ibnVtYmVyIiYmKGImMHgzZmZmZmZmKT09PWIpe3E9cC5jCmlmKHE9PW51bGwpcmV0dXJu
+IG8Kcz1wLmoyKHEsYikKcj1zPT1udWxsP286cy5iCnJldHVybiByfWVsc2UgcmV0dXJuIHAuYWEoYil9
+LAphYTpmdW5jdGlvbihhKXt2YXIgdCxzLHI9dGhpcy5kCmlmKHI9PW51bGwpcmV0dXJuIG51bGwKdD10
+aGlzLkJ0KHIsSi5oZihhKSYweDNmZmZmZmYpCnM9dGhpcy5GaCh0LGEpCmlmKHM8MClyZXR1cm4gbnVs
+bApyZXR1cm4gdFtzXS5ifSwKWTpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHEscCxvLG49dGhpcyxt
+PUguTGgobikKbS5jLmEoYikKbS5RWzFdLmEoYykKaWYodHlwZW9mIGI9PSJzdHJpbmciKXt0PW4uYgpu
+LkVIKHQ9PW51bGw/bi5iPW4ueksoKTp0LGIsYyl9ZWxzZSBpZih0eXBlb2YgYj09Im51bWJlciImJihi
+JjB4M2ZmZmZmZik9PT1iKXtzPW4uYwpuLkVIKHM9PW51bGw/bi5jPW4ueksoKTpzLGIsYyl9ZWxzZXty
+PW4uZAppZihyPT1udWxsKXI9bi5kPW4ueksoKQpxPUouaGYoYikmMHgzZmZmZmZmCnA9bi5CdChyLHEp
+CmlmKHA9PW51bGwpbi5FSShyLHEsW24uSG4oYixjKV0pCmVsc2V7bz1uLkZoKHAsYikKaWYobz49MClw
+W29dLmI9YwplbHNlIHAucHVzaChuLkhuKGIsYykpfX19LApLOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxy
+PXRoaXMKSC5MaChyKS5DKCJ+KDEsMikiKS5hKGIpCnQ9ci5lCnM9ci5yCmZvcig7dCE9bnVsbDspe2Iu
+JDIodC5hLHQuYikKaWYocyE9PXIucil0aHJvdyBILmIoUC5hNChyKSkKdD10LmN9fSwKRUg6ZnVuY3Rp
+b24oYSxiLGMpe3ZhciB0LHM9dGhpcyxyPUguTGgocykKci5jLmEoYikKci5RWzFdLmEoYykKdD1zLmoy
+KGEsYikKaWYodD09bnVsbClzLkVJKGEsYixzLkhuKGIsYykpCmVsc2UgdC5iPWN9LAprczpmdW5jdGlv
+bigpe3RoaXMucj10aGlzLnIrMSY2NzEwODg2M30sCkhuOmZ1bmN0aW9uKGEsYil7dmFyIHQ9dGhpcyxz
+PUguTGgodCkscj1uZXcgSC5kYihzLmMuYShhKSxzLlFbMV0uYShiKSkKaWYodC5lPT1udWxsKXQuZT10
+LmY9cgplbHNle3M9dC5mCnMudG9TdHJpbmcKci5kPXMKdC5mPXMuYz1yfSsrdC5hCnQua3MoKQpyZXR1
+cm4gcn0sCkZoOmZ1bmN0aW9uKGEsYil7dmFyIHQscwppZihhPT1udWxsKXJldHVybi0xCnQ9YS5sZW5n
+dGgKZm9yKHM9MDtzPHQ7KytzKWlmKEouUk0oYVtzXS5hLGIpKXJldHVybiBzCnJldHVybi0xfSwKdzpm
+dW5jdGlvbihhKXtyZXR1cm4gUC5uTyh0aGlzKX0sCmoyOmZ1bmN0aW9uKGEsYil7cmV0dXJuIGFbYl19
+LApCdDpmdW5jdGlvbihhLGIpe3JldHVybiBhW2JdfSwKRUk6ZnVuY3Rpb24oYSxiLGMpe2FbYl09Y30s
+CnJuOmZ1bmN0aW9uKGEsYil7ZGVsZXRlIGFbYl19LApYdTpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlz
+LmoyKGEsYikhPW51bGx9LAp6SzpmdW5jdGlvbigpe3ZhciB0PSI8bm9uLWlkZW50aWZpZXIta2V5PiIs
+cz1PYmplY3QuY3JlYXRlKG51bGwpCnRoaXMuRUkocyx0LHMpCnRoaXMucm4ocyx0KQpyZXR1cm4gc30s
+CiRpRm86MX0KSC5kYi5wcm90b3R5cGU9e30KSC5pNS5wcm90b3R5cGU9ewpnQTpmdW5jdGlvbihhKXty
+ZXR1cm4gdGhpcy5hLmF9LApnbDA6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYS5hPT09MH0sCmdrejpm
+dW5jdGlvbihhKXt2YXIgdD10aGlzLmEscz1uZXcgSC5ONih0LHQucix0aGlzLiR0aS5DKCJONjwxPiIp
+KQpzLmM9dC5lCnJldHVybiBzfSwKdGc6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5hLng0KGIpfX0K
+SC5ONi5wcm90b3R5cGU9ewpnbDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmR9LApGOmZ1bmN0aW9uKCl7
+dmFyIHQscz10aGlzLHI9cy5hCmlmKHMuYiE9PXIucil0aHJvdyBILmIoUC5hNChyKSkKdD1zLmMKaWYo
+dD09bnVsbCl7cy5zcVkobnVsbCkKcmV0dXJuITF9ZWxzZXtzLnNxWSh0LmEpCnMuYz10LmMKcmV0dXJu
+ITB9fSwKc3FZOmZ1bmN0aW9uKGEpe3RoaXMuZD10aGlzLiR0aS5DKCIxPyIpLmEoYSl9LAokaUFuOjF9
+CkguZEMucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYShhKX0sCiRTOjR9Ckgu
+d04ucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5hKGEsYil9LAokUzo0MX0K
+SC5WWC5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hKEguaChhKSl9LAokUzo0
+MH0KSC5WUi5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiJSZWdFeHAvIit0aGlzLmErIi8i
+K3RoaXMuYi5mbGFnc30sCmdIYzpmdW5jdGlvbigpe3ZhciB0PXRoaXMscz10LmMKaWYocyE9bnVsbCly
+ZXR1cm4gcwpzPXQuYgpyZXR1cm4gdC5jPUgudjQodC5hLHMubXVsdGlsaW5lLCFzLmlnbm9yZUNhc2Us
+cy51bmljb2RlLHMuZG90QWxsLCEwKX0sCmRkOmZ1bmN0aW9uKGEsYil7cmV0dXJuIG5ldyBILktXKHRo
+aXMsYiwwKX0sClVaOmZ1bmN0aW9uKGEsYil7dmFyIHQscz10aGlzLmdIYygpCnMubGFzdEluZGV4PWIK
+dD1zLmV4ZWMoYSkKaWYodD09bnVsbClyZXR1cm4gbnVsbApyZXR1cm4gbmV3IEguRUsodCl9LAokaXZY
+OjEsCiRpd0w6MX0KSC5FSy5wcm90b3R5cGU9ewpxOmZ1bmN0aW9uKGEsYil7dmFyIHQKSC51UChiKQp0
+PXRoaXMuYgppZihiPj10Lmxlbmd0aClyZXR1cm4gSC5PSCh0LGIpCnJldHVybiB0W2JdfSwKJGlPZDox
+LAokaWliOjF9CkguS1cucHJvdG90eXBlPXsKZ2t6OmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgSC5QYih0
+aGlzLmEsdGhpcy5iLHRoaXMuYyl9fQpILlBiLnByb3RvdHlwZT17CmdsOmZ1bmN0aW9uKCl7dmFyIHQ9
+dGhpcy5kCnQudG9TdHJpbmcKcmV0dXJuIHR9LApGOmZ1bmN0aW9uKCl7dmFyIHQscyxyLHEscCxvLG49
+dGhpcyxtPW4uYgppZihtPT1udWxsKXJldHVybiExCnQ9bi5jCnM9bS5sZW5ndGgKaWYodDw9cyl7cj1u
+LmEKcT1yLlVaKG0sdCkKaWYocSE9bnVsbCl7bi5kPXEKdD1xLmIKcD10LmluZGV4Cm89cCt0WzBdLmxl
+bmd0aAppZihwPT09byl7aWYoci5iLnVuaWNvZGUpe3Q9bi5jCnI9dCsxCmlmKHI8cyl7dD1DLnhCLm0o
+bSx0KQppZih0Pj01NTI5NiYmdDw9NTYzMTkpe3Q9Qy54Qi5tKG0scikKdD10Pj01NjMyMCYmdDw9NTcz
+NDN9ZWxzZSB0PSExfWVsc2UgdD0hMX1lbHNlIHQ9ITEKbz0odD9vKzE6bykrMX1uLmM9bwpyZXR1cm4h
+MH19bi5iPW4uZD1udWxsCnJldHVybiExfSwKJGlBbjoxfQpILnRRLnByb3RvdHlwZT17CnE6ZnVuY3Rp
+b24oYSxiKXtILnVQKGIpCmlmKGIhPT0wKUgudmgoUC5PNyhiLG51bGwpKQpyZXR1cm4gdGhpcy5jfSwK
+JGlPZDoxfQpILnVuLnByb3RvdHlwZT17CmdrejpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IEguU2QodGhp
+cy5hLHRoaXMuYix0aGlzLmMpfX0KSC5TZC5wcm90b3R5cGU9ewpGOmZ1bmN0aW9uKCl7dmFyIHQscyxy
+PXRoaXMscT1yLmMscD1yLmIsbz1wLmxlbmd0aCxuPXIuYSxtPW4ubGVuZ3RoCmlmKHErbz5tKXtyLmQ9
+bnVsbApyZXR1cm4hMX10PW4uaW5kZXhPZihwLHEpCmlmKHQ8MCl7ci5jPW0rMQpyLmQ9bnVsbApyZXR1
+cm4hMX1zPXQrbwpyLmQ9bmV3IEgudFEodCxwKQpyLmM9cz09PXIuYz9zKzE6cwpyZXR1cm4hMH0sCmds
+OmZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5kCnQudG9TdHJpbmcKcmV0dXJuIHR9LAokaUFuOjF9CkguRVQu
+cHJvdG90eXBlPXskaUVUOjEsJGllcToxfQpILkxaLnByb3RvdHlwZT17CmdBOmZ1bmN0aW9uKGEpe3Jl
+dHVybiBhLmxlbmd0aH0sCiRpWGo6MX0KSC5EZy5wcm90b3R5cGU9ewpxOmZ1bmN0aW9uKGEsYil7SC51
+UChiKQpILm9kKGIsYSxhLmxlbmd0aCkKcmV0dXJuIGFbYl19LApZOmZ1bmN0aW9uKGEsYixjKXtILkdI
+KGMpCkgub2QoYixhLGEubGVuZ3RoKQphW2JdPWN9LAokaWJROjEsCiRpY1g6MSwKJGl6TToxfQpILlBn
+LnByb3RvdHlwZT17Clk6ZnVuY3Rpb24oYSxiLGMpe0gudVAoYykKSC5vZChiLGEsYS5sZW5ndGgpCmFb
+Yl09Y30sCiRpYlE6MSwKJGljWDoxLAokaXpNOjF9CkgueGoucHJvdG90eXBlPXsKcTpmdW5jdGlvbihh
+LGIpe0gudVAoYikKSC5vZChiLGEsYS5sZW5ndGgpCnJldHVybiBhW2JdfX0KSC5kRS5wcm90b3R5cGU9
+ewpxOmZ1bmN0aW9uKGEsYil7SC51UChiKQpILm9kKGIsYSxhLmxlbmd0aCkKcmV0dXJuIGFbYl19fQpI
+LlpBLnByb3RvdHlwZT17CnE6ZnVuY3Rpb24oYSxiKXtILnVQKGIpCkgub2QoYixhLGEubGVuZ3RoKQpy
+ZXR1cm4gYVtiXX19CkguZFQucHJvdG90eXBlPXsKcTpmdW5jdGlvbihhLGIpe0gudVAoYikKSC5vZChi
+LGEsYS5sZW5ndGgpCnJldHVybiBhW2JdfX0KSC5QcS5wcm90b3R5cGU9ewpxOmZ1bmN0aW9uKGEsYil7
+SC51UChiKQpILm9kKGIsYSxhLmxlbmd0aCkKcmV0dXJuIGFbYl19fQpILmVFLnByb3RvdHlwZT17CmdB
+OmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH0sCnE6ZnVuY3Rpb24oYSxiKXtILnVQKGIpCkgub2Qo
+YixhLGEubGVuZ3RoKQpyZXR1cm4gYVtiXX19CkguVjYucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7
+cmV0dXJuIGEubGVuZ3RofSwKcTpmdW5jdGlvbihhLGIpe0gudVAoYikKSC5vZChiLGEsYS5sZW5ndGgp
+CnJldHVybiBhW2JdfSwKJGlWNjoxLAokaW42OjF9CkguUkcucHJvdG90eXBlPXt9CkguVlAucHJvdG90
+eXBlPXt9CkguV0IucHJvdG90eXBlPXt9CkguWkcucHJvdG90eXBlPXt9CkguSmMucHJvdG90eXBlPXsK
+QzpmdW5jdGlvbihhKXtyZXR1cm4gSC5jRSh2LnR5cGVVbml2ZXJzZSx0aGlzLGEpfSwKS3E6ZnVuY3Rp
+b24oYSl7cmV0dXJuIEgudjUodi50eXBlVW5pdmVyc2UsdGhpcyxhKX19CkguRy5wcm90b3R5cGU9e30K
+SC51OS5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmF9fQpILmlNLnByb3RvdHlw
+ZT17fQpQLnRoLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuYSxzPXQuYQp0LmE9
+bnVsbApzLiQwKCl9LAokUzo5fQpQLmhhLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0LHMK
+dGhpcy5hLmE9dS5NLmEoYSkKdD10aGlzLmIKcz10aGlzLmMKdC5maXJzdENoaWxkP3QucmVtb3ZlQ2hp
+bGQocyk6dC5hcHBlbmRDaGlsZChzKX0sCiRTOjUxfQpQLlZzLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9u
+KCl7dGhpcy5hLiQwKCl9LAokQzoiJDAiLAokUjowLAokUzowfQpQLkZ0LnByb3RvdHlwZT17CiQwOmZ1
+bmN0aW9uKCl7dGhpcy5hLiQwKCl9LAokQzoiJDAiLAokUjowLAokUzowfQpQLlczLnByb3RvdHlwZT17
+CkNZOmZ1bmN0aW9uKGEsYil7aWYoc2VsZi5zZXRUaW1lb3V0IT1udWxsKXNlbGYuc2V0VGltZW91dChI
+LnRSKG5ldyBQLnlIKHRoaXMsYiksMCksYSkKZWxzZSB0aHJvdyBILmIoUC5MNCgiYHNldFRpbWVvdXQo
+KWAgbm90IGZvdW5kLiIpKX19ClAueUgucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXt0aGlzLmIuJDAo
+KX0sCiRDOiIkMCIsCiRSOjAsCiRTOjF9ClAuaWgucHJvdG90eXBlPXsKYU06ZnVuY3Rpb24oYSxiKXt2
+YXIgdCxzPXRoaXMscj1zLiR0aQpyLkMoIjEvPyIpLmEoYikKaWYoIXMuYilzLmEuWGYoYikKZWxzZXt0
+PXMuYQppZihyLkMoImI4PDE+IikuYihiKSl0LmNVKGIpCmVsc2UgdC5YMihyLmMuYShiKSl9fSwKdzA6
+ZnVuY3Rpb24oYSxiKXt2YXIgdAppZihiPT1udWxsKWI9UC52MChhKQp0PXRoaXMuYQppZih0aGlzLmIp
+dC5aTChhLGIpCmVsc2UgdC5OayhhLGIpfX0KUC5XTS5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXty
+ZXR1cm4gdGhpcy5hLiQyKDAsYSl9LAokUzo0NX0KUC5TWC5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihh
+LGIpe3RoaXMuYS4kMigxLG5ldyBILmJxKGEsdS5sLmEoYikpKX0sCiRDOiIkMiIsCiRSOjIsCiRTOjI2
+fQpQLkdzLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dGhpcy5hKEgudVAoYSksYil9LAokUzoy
+OH0KUC5GeS5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiJJdGVyYXRpb25NYXJrZXIoIit0
+aGlzLmIrIiwgIitILkVqKHRoaXMuYSkrIikifX0KUC5HVi5wcm90b3R5cGU9ewpnbDpmdW5jdGlvbigp
+e3ZhciB0PXRoaXMuYwppZih0PT1udWxsKXJldHVybiB0aGlzLiR0aS5jLmEodGhpcy5iKQpyZXR1cm4g
+dC5nbCgpfSwKRjpmdW5jdGlvbigpe3ZhciB0LHMscixxLHAsbyxuPXRoaXMKZm9yKHQ9bi4kdGkuQygi
+QW48MT4iKTshMDspe3M9bi5jCmlmKHMhPW51bGwpaWYocy5GKCkpcmV0dXJuITAKZWxzZSBuLnNYOShu
+dWxsKQpyPWZ1bmN0aW9uKGEsYixjKXt2YXIgbSxsPWIKd2hpbGUodHJ1ZSl0cnl7cmV0dXJuIGEobCxt
+KX1jYXRjaChrKXttPWsKbD1jfX0obi5hLDAsMSkKaWYociBpbnN0YW5jZW9mIFAuRnkpe3E9ci5iCmlm
+KHE9PT0yKXtwPW4uZAppZihwPT1udWxsfHxwLmxlbmd0aD09PTApe24uc0VDKG51bGwpCnJldHVybiEx
+fWlmKDA+PXAubGVuZ3RoKXJldHVybiBILk9IKHAsLTEpCm4uYT1wLnBvcCgpCmNvbnRpbnVlfWVsc2V7
+cz1yLmEKaWYocT09PTMpdGhyb3cgcwplbHNle289dC5hKEouSVQocykpCmlmKG8gaW5zdGFuY2VvZiBQ
+LkdWKXtzPW4uZAppZihzPT1udWxsKXM9bi5kPVtdCkMuTm0uaShzLG4uYSkKbi5hPW8uYQpjb250aW51
+ZX1lbHNle24uc1g5KG8pCmNvbnRpbnVlfX19fWVsc2V7bi5zRUMocikKcmV0dXJuITB9fXJldHVybiEx
+fSwKc0VDOmZ1bmN0aW9uKGEpe3RoaXMuYj10aGlzLiR0aS5DKCIxPyIpLmEoYSl9LApzWDk6ZnVuY3Rp
+b24oYSl7dGhpcy5jPXRoaXMuJHRpLkMoIkFuPDE+PyIpLmEoYSl9LAokaUFuOjF9ClAucTQucHJvdG90
+eXBlPXsKZ2t6OmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC5HVih0aGlzLmEoKSx0aGlzLiR0aS5DKCJH
+VjwxPiIpKX19ClAuYjgucHJvdG90eXBlPXt9ClAuUGYucHJvdG90eXBlPXsKdzA6ZnVuY3Rpb24oYSxi
+KXt2YXIgdApQLlVJKGEsImVycm9yIix1LkspCnQ9dGhpcy5hCmlmKHQuYSE9PTApdGhyb3cgSC5iKFAu
+UFYoIkZ1dHVyZSBhbHJlYWR5IGNvbXBsZXRlZCIpKQppZihiPT1udWxsKWI9UC52MChhKQp0Lk5rKGEs
+Yil9LApwbTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy53MChhLG51bGwpfX0KUC5aZi5wcm90b3R5cGU9
+ewphTTpmdW5jdGlvbihhLGIpe3ZhciB0LHM9dGhpcy4kdGkKcy5DKCIxLz8iKS5hKGIpCnQ9dGhpcy5h
+CmlmKHQuYSE9PTApdGhyb3cgSC5iKFAuUFYoIkZ1dHVyZSBhbHJlYWR5IGNvbXBsZXRlZCIpKQp0Llhm
+KHMuQygiMS8iKS5hKGIpKX19ClAuRmUucHJvdG90eXBlPXsKSFI6ZnVuY3Rpb24oYSl7aWYoKHRoaXMu
+YyYxNSkhPT02KXJldHVybiEwCnJldHVybiB0aGlzLmIuYi5idih1LmFsLmEodGhpcy5kKSxhLmEsdS55
+LHUuSyl9LApLdzpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmUscz11Lnoscj11LksscT10aGlzLiR0aS5D
+KCIyLyIpLHA9dGhpcy5iLmIKaWYodS5hZy5iKHQpKXJldHVybiBxLmEocC5ycCh0LGEuYSxhLmIscyxy
+LHUubCkpCmVsc2UgcmV0dXJuIHEuYShwLmJ2KHUuYkkuYSh0KSxhLmEscyxyKSl9fQpQLnZzLnByb3Rv
+dHlwZT17ClNxOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzLHIscT10aGlzLiR0aQpxLktxKGMpLkMoIjEv
+KDIpIikuYShhKQp0PSQuWDMKaWYodCE9PUMuTlUpe2MuQygiQDwwLz4iKS5LcShxLmMpLkMoIjEoMiki
+KS5hKGEpCmlmKGIhPW51bGwpYj1QLlZIKGIsdCl9cz1uZXcgUC52cygkLlgzLGMuQygidnM8MD4iKSkK
+cj1iPT1udWxsPzE6Mwp0aGlzLnhmKG5ldyBQLkZlKHMscixhLGIscS5DKCJAPDE+IikuS3EoYykuQygi
+RmU8MSwyPiIpKSkKcmV0dXJuIHN9LApXNzpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLlNxKGEsbnVs
+bCxiKX0sClFkOmZ1bmN0aW9uKGEsYixjKXt2YXIgdCxzPXRoaXMuJHRpCnMuS3EoYykuQygiMS8oMiki
+KS5hKGEpCnQ9bmV3IFAudnMoJC5YMyxjLkMoInZzPDA+IikpCnRoaXMueGYobmV3IFAuRmUodCwxOSxh
+LGIscy5DKCJAPDE+IikuS3EoYykuQygiRmU8MSwyPiIpKSkKcmV0dXJuIHR9LAp4ZjpmdW5jdGlvbihh
+KXt2YXIgdCxzPXRoaXMscj1zLmEKaWYocjw9MSl7YS5hPXUuRi5hKHMuYykKcy5jPWF9ZWxzZXtpZihy
+PT09Mil7dD11LmMuYShzLmMpCnI9dC5hCmlmKHI8NCl7dC54ZihhKQpyZXR1cm59cy5hPXIKcy5jPXQu
+Y31QLlRrKG51bGwsbnVsbCxzLmIsdS5NLmEobmV3IFAuZGEocyxhKSkpfX0sCmpROmZ1bmN0aW9uKGEp
+e3ZhciB0LHMscixxLHAsbyxuPXRoaXMsbT17fQptLmE9YQppZihhPT1udWxsKXJldHVybgp0PW4uYQpp
+Zih0PD0xKXtzPXUuRi5hKG4uYykKbi5jPWEKaWYocyE9bnVsbCl7cj1hLmEKZm9yKHE9YTtyIT1udWxs
+O3E9cixyPXApcD1yLmEKcS5hPXN9fWVsc2V7aWYodD09PTIpe289dS5jLmEobi5jKQp0PW8uYQppZih0
+PDQpe28ualEoYSkKcmV0dXJufW4uYT10Cm4uYz1vLmN9bS5hPW4uTjgoYSkKUC5UayhudWxsLG51bGws
+bi5iLHUuTS5hKG5ldyBQLm9RKG0sbikpKX19LAphaDpmdW5jdGlvbigpe3ZhciB0PXUuRi5hKHRoaXMu
+YykKdGhpcy5jPW51bGwKcmV0dXJuIHRoaXMuTjgodCl9LApOODpmdW5jdGlvbihhKXt2YXIgdCxzLHIK
+Zm9yKHQ9YSxzPW51bGw7dCE9bnVsbDtzPXQsdD1yKXtyPXQuYQp0LmE9c31yZXR1cm4gc30sCkhIOmZ1
+bmN0aW9uKGEpe3ZhciB0LHM9dGhpcyxyPXMuJHRpCnIuQygiMS8iKS5hKGEpCmlmKHIuQygiYjg8MT4i
+KS5iKGEpKWlmKHIuYihhKSlQLkE5KGEscykKZWxzZSBQLmszKGEscykKZWxzZXt0PXMuYWgoKQpyLmMu
+YShhKQpzLmE9NApzLmM9YQpQLkhaKHMsdCl9fSwKWDI6ZnVuY3Rpb24oYSl7dmFyIHQscz10aGlzCnMu
+JHRpLmMuYShhKQp0PXMuYWgoKQpzLmE9NApzLmM9YQpQLkhaKHMsdCl9LApaTDpmdW5jdGlvbihhLGIp
+e3ZhciB0LHMscj10aGlzCnUubC5hKGIpCnQ9ci5haCgpCnM9UC5UbChhLGIpCnIuYT04CnIuYz1zClAu
+SFoocix0KX0sClhmOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuJHRpCnQuQygiMS8iKS5hKGEpCmlmKHQu
+QygiYjg8MT4iKS5iKGEpKXt0aGlzLmNVKGEpCnJldHVybn10aGlzLndVKHQuYy5hKGEpKX0sCndVOmZ1
+bmN0aW9uKGEpe3ZhciB0PXRoaXMKdC4kdGkuYy5hKGEpCnQuYT0xClAuVGsobnVsbCxudWxsLHQuYix1
+Lk0uYShuZXcgUC5ydCh0LGEpKSl9LApjVTpmdW5jdGlvbihhKXt2YXIgdD10aGlzLHM9dC4kdGkKcy5D
+KCJiODwxPiIpLmEoYSkKaWYocy5iKGEpKXtpZihhLmE9PT04KXt0LmE9MQpQLlRrKG51bGwsbnVsbCx0
+LmIsdS5NLmEobmV3IFAuS0YodCxhKSkpfWVsc2UgUC5BOShhLHQpCnJldHVybn1QLmszKGEsdCl9LApO
+azpmdW5jdGlvbihhLGIpe3RoaXMuYT0xClAuVGsobnVsbCxudWxsLHRoaXMuYix1Lk0uYShuZXcgUC5a
+TCh0aGlzLGEsYikpKX0sCiRpYjg6MX0KUC5kYS5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigpe1AuSFoo
+dGhpcy5hLHRoaXMuYil9LAokUzowfQpQLm9RLnByb3RvdHlwZT17CiQwOmZ1bmN0aW9uKCl7UC5IWih0
+aGlzLmIsdGhpcy5hLmEpfSwKJFM6MH0KUC5wVi5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIg
+dD10aGlzLmEKdC5hPTAKdC5ISChhKX0sCiRTOjl9ClAuVTcucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24o
+YSxiKXt0aGlzLmEuWkwoYSx1LmwuYShiKSl9LAokQzoiJDIiLAokUjoyLAokUzozMX0KUC52ci5wcm90
+b3R5cGU9ewokMDpmdW5jdGlvbigpe3RoaXMuYS5aTCh0aGlzLmIsdGhpcy5jKX0sCiRTOjB9ClAucnQu
+cHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXt0aGlzLmEuWDIodGhpcy5iKX0sCiRTOjB9ClAuS0YucHJv
+dG90eXBlPXsKJDA6ZnVuY3Rpb24oKXtQLkE5KHRoaXMuYix0aGlzLmEpfSwKJFM6MH0KUC5aTC5wcm90
+b3R5cGU9ewokMDpmdW5jdGlvbigpe3RoaXMuYS5aTCh0aGlzLmIsdGhpcy5jKX0sCiRTOjB9ClAuUlQu
+cHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXt2YXIgdCxzLHIscSxwLG8sbj10aGlzLG09bnVsbAp0cnl7
+cj1uLmEuYQptPXIuYi5iLnp6KHUuZk8uYShyLmQpLHUueil9Y2F0Y2gocSl7dD1ILlJ1KHEpCnM9SC50
+cyhxKQppZihuLmMpe3I9dS5uLmEobi5iLmEuYykuYQpwPXQKcD1yPT1udWxsP3A9PW51bGw6cj09PXAK
+cj1wfWVsc2Ugcj0hMQpwPW4uYQppZihyKXAuYz11Lm4uYShuLmIuYS5jKQplbHNlIHAuYz1QLlRsKHQs
+cykKcC5iPSEwCnJldHVybn1pZihtIGluc3RhbmNlb2YgUC52cyYmbS5hPj00KXtpZihtLmE9PT04KXty
+PW4uYQpyLmM9dS5uLmEobS5jKQpyLmI9ITB9cmV0dXJufWlmKHUuZC5iKG0pKXtvPW4uYi5hCnI9bi5h
+CnIuYz1tLlc3KG5ldyBQLmpaKG8pLHUueikKci5iPSExfX0sCiRTOjF9ClAualoucHJvdG90eXBlPXsK
+JDE6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYX0sCiRTOjMzfQpQLnJxLnByb3RvdHlwZT17CiQwOmZ1
+bmN0aW9uKCl7dmFyIHQscyxyLHEscCxvLG4sbQp0cnl7cj10aGlzLmEKcT1yLmEKcD1xLiR0aQpvPXAu
+YwpuPW8uYSh0aGlzLmIpCnIuYz1xLmIuYi5idihwLkMoIjIvKDEpIikuYShxLmQpLG4scC5DKCIyLyIp
+LG8pfWNhdGNoKG0pe3Q9SC5SdShtKQpzPUgudHMobSkKcj10aGlzLmEKci5jPVAuVGwodCxzKQpyLmI9
+ITB9fSwKJFM6MX0KUC5SVy5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigpe3ZhciB0LHMscixxLHAsbyxu
+LG0sbD10aGlzCnRyeXt0PXUubi5hKGwuYS5hLmMpCnE9bC5iCmlmKEgub1QocS5hLkhSKHQpKSYmcS5h
+LmUhPW51bGwpe3EuYz1xLmEuS3codCkKcS5iPSExfX1jYXRjaChwKXtzPUguUnUocCkKcj1ILnRzKHAp
+CnE9dS5uLmEobC5hLmEuYykKbz1xLmEKbj1zCm09bC5iCmlmKG89PW51bGw/bj09bnVsbDpvPT09bilt
+LmM9cQplbHNlIG0uYz1QLlRsKHMscikKbS5iPSEwfX0sCiRTOjF9ClAuT00ucHJvdG90eXBlPXt9ClAu
+cWgucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7dmFyIHQscyxyPXRoaXMscT17fSxwPW5ldyBQLnZz
+KCQuWDMsdS5mSikKcS5hPTAKdD1ILkxoKHIpCnM9dC5DKCJ+KDEpPyIpLmEobmV3IFAuQjUocSxyKSkK
+dS5aLmEobmV3IFAudU8ocSxwKSkKVy5KRShyLmEsci5iLHMsITEsdC5jKQpyZXR1cm4gcH19ClAuQjUu
+cHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7SC5MaCh0aGlzLmIpLmMuYShhKTsrK3RoaXMuYS5hfSwK
+JFM6ZnVuY3Rpb24oKXtyZXR1cm4gSC5MaCh0aGlzLmIpLkMoImM4KDEpIil9fQpQLnVPLnByb3RvdHlw
+ZT17CiQwOmZ1bmN0aW9uKCl7dGhpcy5iLkhIKHRoaXMuYS5hKX0sCiRTOjB9ClAuTU8ucHJvdG90eXBl
+PXt9ClAua1QucHJvdG90eXBlPXt9ClAueEkucHJvdG90eXBlPXt9ClAuQ3cucHJvdG90eXBlPXsKdzpm
+dW5jdGlvbihhKXtyZXR1cm4gSC5Faih0aGlzLmEpfSwKJGlYUzoxLApnSUk6ZnVuY3Rpb24oKXtyZXR1
+cm4gdGhpcy5ifX0KUC5tMC5wcm90b3R5cGU9eyRpSkI6MX0KUC5wSy5wcm90b3R5cGU9ewokMDpmdW5j
+dGlvbigpe3ZhciB0PUguYih0aGlzLmEpCnQuc3RhY2s9Si5qKHRoaXMuYikKdGhyb3cgdH0sCiRTOjB9
+ClAuSmkucHJvdG90eXBlPXsKYkg6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHE9bnVsbAp1Lk0uYShhKQp0
+cnl7aWYoQy5OVT09PSQuWDMpe2EuJDAoKQpyZXR1cm59UC5UOChxLHEsdGhpcyxhLHUuSCl9Y2F0Y2go
+cil7dD1ILlJ1KHIpCnM9SC50cyhyKQpQLkwyKHEscSx0aGlzLHQsdS5sLmEocykpfX0sCkRsOmZ1bmN0
+aW9uKGEsYixjKXt2YXIgdCxzLHIscT1udWxsCmMuQygifigwKSIpLmEoYSkKYy5hKGIpCnRyeXtpZihD
+Lk5VPT09JC5YMyl7YS4kMShiKQpyZXR1cm59UC55dihxLHEsdGhpcyxhLGIsdS5ILGMpfWNhdGNoKHIp
+e3Q9SC5SdShyKQpzPUgudHMocikKUC5MMihxLHEsdGhpcyx0LHUubC5hKHMpKX19LApSVDpmdW5jdGlv
+bihhLGIpe3JldHVybiBuZXcgUC5oaih0aGlzLGIuQygiMCgpIikuYShhKSxiKX0sCkdZOmZ1bmN0aW9u
+KGEpe3JldHVybiBuZXcgUC5WcCh0aGlzLHUuTS5hKGEpKX0sClB5OmZ1bmN0aW9uKGEsYil7cmV0dXJu
+IG5ldyBQLk9SKHRoaXMsYi5DKCJ+KDApIikuYShhKSxiKX0sCnE6ZnVuY3Rpb24oYSxiKXtyZXR1cm4g
+bnVsbH0sCnp6OmZ1bmN0aW9uKGEsYil7Yi5DKCIwKCkiKS5hKGEpCmlmKCQuWDM9PT1DLk5VKXJldHVy
+biBhLiQwKCkKcmV0dXJuIFAuVDgobnVsbCxudWxsLHRoaXMsYSxiKX0sCmJ2OmZ1bmN0aW9uKGEsYixj
+LGQpe2MuQygiQDwwPiIpLktxKGQpLkMoIjEoMikiKS5hKGEpCmQuYShiKQppZigkLlgzPT09Qy5OVSly
+ZXR1cm4gYS4kMShiKQpyZXR1cm4gUC55dihudWxsLG51bGwsdGhpcyxhLGIsYyxkKX0sCnJwOmZ1bmN0
+aW9uKGEsYixjLGQsZSxmKXtkLkMoIkA8MD4iKS5LcShlKS5LcShmKS5DKCIxKDIsMykiKS5hKGEpCmUu
+YShiKQpmLmEoYykKaWYoJC5YMz09PUMuTlUpcmV0dXJuIGEuJDIoYixjKQpyZXR1cm4gUC5ReChudWxs
+LG51bGwsdGhpcyxhLGIsYyxkLGUsZil9LApMajpmdW5jdGlvbihhLGIsYyxkKXtyZXR1cm4gYi5DKCJA
+PDA+IikuS3EoYykuS3EoZCkuQygiMSgyLDMpIikuYShhKX19ClAuaGoucHJvdG90eXBlPXsKJDA6ZnVu
+Y3Rpb24oKXtyZXR1cm4gdGhpcy5hLnp6KHRoaXMuYix0aGlzLmMpfSwKJFM6ZnVuY3Rpb24oKXtyZXR1
+cm4gdGhpcy5jLkMoIjAoKSIpfX0KUC5WcC5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigpe3JldHVybiB0
+aGlzLmEuYkgodGhpcy5iKX0sCiRTOjF9ClAuT1IucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFy
+IHQ9dGhpcy5jCnJldHVybiB0aGlzLmEuRGwodGhpcy5iLHQuYShhKSx0KX0sCiRTOmZ1bmN0aW9uKCl7
+cmV0dXJuIHRoaXMuYy5DKCJ+KDApIil9fQpQLmI2LnByb3RvdHlwZT17CmdrejpmdW5jdGlvbihhKXt2
+YXIgdD10aGlzLHM9bmV3IFAubG0odCx0LnIsSC5MaCh0KS5DKCJsbTwxPiIpKQpzLmM9dC5lCnJldHVy
+biBzfSwKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYX0sCnRnOmZ1bmN0aW9uKGEsYil7dmFyIHQs
+cwppZih0eXBlb2YgYj09InN0cmluZyImJmIhPT0iX19wcm90b19fIil7dD10aGlzLmIKaWYodD09bnVs
+bClyZXR1cm4hMQpyZXR1cm4gdS5lLmEodFtiXSkhPW51bGx9ZWxzZXtzPXRoaXMuUFIoYikKcmV0dXJu
+IHN9fSwKUFI6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5kCmlmKHQ9PW51bGwpcmV0dXJuITEKcmV0dXJu
+IHRoaXMuREYodFt0aGlzLk4oYSldLGEpPj0wfSwKaTpmdW5jdGlvbihhLGIpe3ZhciB0LHMscj10aGlz
+CkguTGgocikuYy5hKGIpCmlmKHR5cGVvZiBiPT0ic3RyaW5nIiYmYiE9PSJfX3Byb3RvX18iKXt0PXIu
+YgpyZXR1cm4gci5iUSh0PT1udWxsP3IuYj1QLlQyKCk6dCxiKX1lbHNlIGlmKHR5cGVvZiBiPT0ibnVt
+YmVyIiYmKGImMTA3Mzc0MTgyMyk9PT1iKXtzPXIuYwpyZXR1cm4gci5iUShzPT1udWxsP3IuYz1QLlQy
+KCk6cyxiKX1lbHNlIHJldHVybiByLkI3KGIpfSwKQjc6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHE9dGhp
+cwpILkxoKHEpLmMuYShhKQp0PXEuZAppZih0PT1udWxsKXQ9cS5kPVAuVDIoKQpzPXEuTihhKQpyPXRb
+c10KaWYocj09bnVsbCl0W3NdPVtxLnlvKGEpXQplbHNle2lmKHEuREYocixhKT49MClyZXR1cm4hMQpy
+LnB1c2gocS55byhhKSl9cmV0dXJuITB9LApSOmZ1bmN0aW9uKGEsYil7dmFyIHQ9dGhpcwppZih0eXBl
+b2YgYj09InN0cmluZyImJmIhPT0iX19wcm90b19fIilyZXR1cm4gdC5MKHQuYixiKQplbHNlIGlmKHR5
+cGVvZiBiPT0ibnVtYmVyIiYmKGImMTA3Mzc0MTgyMyk9PT1iKXJldHVybiB0LkwodC5jLGIpCmVsc2Ug
+cmV0dXJuIHQucWcoYil9LApxZzpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwPXRoaXMsbz1wLmQKaWYo
+bz09bnVsbClyZXR1cm4hMQp0PXAuTihhKQpzPW9bdF0Kcj1wLkRGKHMsYSkKaWYocjwwKXJldHVybiEx
+CnE9cy5zcGxpY2UociwxKVswXQppZigwPT09cy5sZW5ndGgpZGVsZXRlIG9bdF0KcC5HUyhxKQpyZXR1
+cm4hMH0sCmJROmZ1bmN0aW9uKGEsYil7SC5MaCh0aGlzKS5jLmEoYikKaWYodS5lLmEoYVtiXSkhPW51
+bGwpcmV0dXJuITEKYVtiXT10aGlzLnlvKGIpCnJldHVybiEwfSwKTDpmdW5jdGlvbihhLGIpe3ZhciB0
+CmlmKGE9PW51bGwpcmV0dXJuITEKdD11LmUuYShhW2JdKQppZih0PT1udWxsKXJldHVybiExCnRoaXMu
+R1ModCkKZGVsZXRlIGFbYl0KcmV0dXJuITB9LApTOmZ1bmN0aW9uKCl7dGhpcy5yPTEwNzM3NDE4MjMm
+dGhpcy5yKzF9LAp5bzpmdW5jdGlvbihhKXt2YXIgdCxzPXRoaXMscj1uZXcgUC5ibihILkxoKHMpLmMu
+YShhKSkKaWYocy5lPT1udWxsKXMuZT1zLmY9cgplbHNle3Q9cy5mCnQudG9TdHJpbmcKci5jPXQKcy5m
+PXQuYj1yfSsrcy5hCnMuUygpCnJldHVybiByfSwKR1M6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcyxzPWEu
+YyxyPWEuYgppZihzPT1udWxsKXQuZT1yCmVsc2Ugcy5iPXIKaWYocj09bnVsbCl0LmY9cwplbHNlIHIu
+Yz1zOy0tdC5hCnQuUygpfSwKTjpmdW5jdGlvbihhKXtyZXR1cm4gSi5oZihhKSYxMDczNzQxODIzfSwK
+REY6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzCmlmKGE9PW51bGwpcmV0dXJuLTEKdD1hLmxlbmd0aApmb3Io
+cz0wO3M8dDsrK3MpaWYoSi5STShhW3NdLmEsYikpcmV0dXJuIHMKcmV0dXJuLTF9fQpQLmJuLnByb3Rv
+dHlwZT17fQpQLmxtLnByb3RvdHlwZT17CmdsOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuZH0sCkY6ZnVu
+Y3Rpb24oKXt2YXIgdD10aGlzLHM9dC5jLHI9dC5hCmlmKHQuYiE9PXIucil0aHJvdyBILmIoUC5hNChy
+KSkKZWxzZSBpZihzPT1udWxsKXt0LnNqKG51bGwpCnJldHVybiExfWVsc2V7dC5zaih0LiR0aS5DKCIx
+PyIpLmEocy5hKSkKdC5jPXMuYgpyZXR1cm4hMH19LApzajpmdW5jdGlvbihhKXt0aGlzLmQ9dGhpcy4k
+dGkuQygiMT8iKS5hKGEpfSwKJGlBbjoxfQpQLm1XLnByb3RvdHlwZT17fQpQLnV5LnByb3RvdHlwZT17
+JGliUToxLCRpY1g6MSwkaXpNOjF9ClAubEQucHJvdG90eXBlPXsKZ2t6OmZ1bmN0aW9uKGEpe3JldHVy
+biBuZXcgSC5hNyhhLHRoaXMuZ0EoYSksSC56KGEpLkMoImE3PGxELkU+IikpfSwKRTpmdW5jdGlvbihh
+LGIpe3JldHVybiB0aGlzLnEoYSxiKX0sCks6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzCkgueihhKS5DKCJ+
+KGxELkUpIikuYShiKQp0PXRoaXMuZ0EoYSkKZm9yKHM9MDtzPHQ7KytzKXtiLiQxKHRoaXMucShhLHMp
+KQppZih0IT09dGhpcy5nQShhKSl0aHJvdyBILmIoUC5hNChhKSl9fSwKZ29yOmZ1bmN0aW9uKGEpe3Jl
+dHVybiB0aGlzLmdBKGEpIT09MH0sCkUyOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1ILnooYSkKcmV0dXJu
+IG5ldyBILmxKKGEsdC5LcShjKS5DKCIxKGxELkUpIikuYShiKSx0LkMoIkA8bEQuRT4iKS5LcShjKS5D
+KCJsSjwxLDI+IikpfSwKZHU6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQKSC56KGEpLkMoImxELkU/Iiku
+YShkKQpQLmpCKGIsYyx0aGlzLmdBKGEpKQpmb3IodD1iO3Q8YzsrK3QpdGhpcy5ZKGEsdCxkKX0sCnc6
+ZnVuY3Rpb24oYSl7cmV0dXJuIFAuV0UoYSwiWyIsIl0iKX19ClAuaWwucHJvdG90eXBlPXt9ClAucmEu
+cHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzPXRoaXMuYQppZighcy5hKXRoaXMuYi5h
+Kz0iLCAiCnMuYT0hMQpzPXRoaXMuYgp0PXMuYSs9SC5FaihhKQpzLmE9dCsiOiAiCnMuYSs9SC5Faihi
+KX0sCiRTOjExfQpQLllrLnByb3RvdHlwZT17Cks6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzCkguTGgodGhp
+cykuQygifihZay5LLFlrLlYpIikuYShiKQpmb3IodD1KLklUKHRoaXMuZ1YoKSk7dC5GKCk7KXtzPXQu
+Z2woKQpiLiQyKHMsdGhpcy5xKDAscykpfX0sCmdQdTpmdW5jdGlvbihhKXtyZXR1cm4gSi5NMSh0aGlz
+LmdWKCksbmV3IFAueVEodGhpcyksSC5MaCh0aGlzKS5DKCJOMzxZay5LLFlrLlY+IikpfSwKeDQ6ZnVu
+Y3Rpb24oYSl7cmV0dXJuIEouemwodGhpcy5nVigpLGEpfSwKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIEou
+SG0odGhpcy5nVigpKX0sCmdsMDpmdW5jdGlvbihhKXtyZXR1cm4gSi51VSh0aGlzLmdWKCkpfSwKdzpm
+dW5jdGlvbihhKXtyZXR1cm4gUC5uTyh0aGlzKX0sCiRpWjA6MX0KUC55US5wcm90b3R5cGU9ewokMTpm
+dW5jdGlvbihhKXt2YXIgdD10aGlzLmEscz1ILkxoKHQpCnMuQygiWWsuSyIpLmEoYSkKcmV0dXJuIG5l
+dyBQLk4zKGEsdC5xKDAsYSkscy5DKCJAPFlrLks+IikuS3Eocy5DKCJZay5WIikpLkMoIk4zPDEsMj4i
+KSl9LAokUzpmdW5jdGlvbigpe3JldHVybiBILkxoKHRoaXMuYSkuQygiTjM8WWsuSyxZay5WPihZay5L
+KSIpfX0KUC5LUC5wcm90b3R5cGU9ewpZOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1ILkxoKHRoaXMpCnQu
+Yy5hKGIpCnQuUVsxXS5hKGMpCnRocm93IEguYihQLkw0KCJDYW5ub3QgbW9kaWZ5IHVubW9kaWZpYWJs
+ZSBtYXAiKSl9fQpQLlBuLnByb3RvdHlwZT17CnE6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5hLnEo
+MCxiKX0sClk6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0PUguTGgodGhpcykKdGhpcy5hLlkoMCx0LmMuYShi
+KSx0LlFbMV0uYShjKSl9LAp4NDpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hLng0KGEpfSwKSzpmdW5j
+dGlvbihhLGIpe3RoaXMuYS5LKDAsSC5MaCh0aGlzKS5DKCJ+KDEsMikiKS5hKGIpKX0sCmdsMDpmdW5j
+dGlvbihhKXt2YXIgdD10aGlzLmEKcmV0dXJuIHQuZ2wwKHQpfSwKZ0E6ZnVuY3Rpb24oYSl7dmFyIHQ9
+dGhpcy5hCnJldHVybiB0LmdBKHQpfSwKdzpmdW5jdGlvbihhKXtyZXR1cm4gSi5qKHRoaXMuYSl9LApn
+UHU6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5hCnJldHVybiB0LmdQdSh0KX0sCiRpWjA6MX0KUC5Hai5w
+cm90b3R5cGU9e30KUC5NYS5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiBQLldFKHRoaXMs
+InsiLCJ9Iil9fQpQLlZqLnByb3RvdHlwZT17JGliUToxLCRpY1g6MSwkaXh1OjF9ClAuWHYucHJvdG90
+eXBlPXsKRlY6ZnVuY3Rpb24oYSxiKXt2YXIgdApmb3IodD1KLklUKEguTGgodGhpcykuQygiY1g8MT4i
+KS5hKGIpKTt0LkYoKTspdGhpcy5pKDAsdC5nbCgpKX0sCnc6ZnVuY3Rpb24oYSl7cmV0dXJuIFAuV0Uo
+dGhpcywieyIsIn0iKX0sCkg6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzPVAucmoodGhpcyx0aGlzLnIsSC5M
+aCh0aGlzKS5jKQppZighcy5GKCkpcmV0dXJuIiIKaWYoYj09PSIiKXt0PSIiCmRvIHQrPUguRWoocy5k
+KQp3aGlsZShzLkYoKSl9ZWxzZXt0PUguRWoocy5kKQpmb3IoO3MuRigpOyl0PXQrYitILkVqKHMuZCl9
+cmV0dXJuIHQuY2hhckNvZGVBdCgwKT09MD90OnR9LAokaWJROjEsCiRpY1g6MSwKJGl4dToxfQpQLm5Z
+LnByb3RvdHlwZT17fQpQLldZLnByb3RvdHlwZT17fQpQLlJVLnByb3RvdHlwZT17fQpQLnV3LnByb3Rv
+dHlwZT17CnE6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzPXRoaXMuYgppZihzPT1udWxsKXJldHVybiB0aGlz
+LmMucSgwLGIpCmVsc2UgaWYodHlwZW9mIGIhPSJzdHJpbmciKXJldHVybiBudWxsCmVsc2V7dD1zW2Jd
+CnJldHVybiB0eXBlb2YgdD09InVuZGVmaW5lZCI/dGhpcy5mYihiKTp0fX0sCmdBOmZ1bmN0aW9uKGEp
+e3JldHVybiB0aGlzLmI9PW51bGw/dGhpcy5jLmE6dGhpcy5DZigpLmxlbmd0aH0sCmdsMDpmdW5jdGlv
+bihhKXtyZXR1cm4gdGhpcy5nQSh0aGlzKT09PTB9LApnVjpmdW5jdGlvbigpe2lmKHRoaXMuYj09bnVs
+bCl7dmFyIHQ9dGhpcy5jCnJldHVybiBuZXcgSC5pNSh0LEguTGgodCkuQygiaTU8MT4iKSl9cmV0dXJu
+IG5ldyBQLmk4KHRoaXMpfSwKWTpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyPXRoaXMKaWYoci5iPT1u
+dWxsKXIuYy5ZKDAsYixjKQplbHNlIGlmKHIueDQoYikpe3Q9ci5iCnRbYl09YwpzPXIuYQppZihzPT1u
+dWxsP3QhPW51bGw6cyE9PXQpc1tiXT1udWxsfWVsc2Ugci5YSygpLlkoMCxiLGMpfSwKeDQ6ZnVuY3Rp
+b24oYSl7aWYodGhpcy5iPT1udWxsKXJldHVybiB0aGlzLmMueDQoYSkKcmV0dXJuIE9iamVjdC5wcm90
+b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0aGlzLmEsYSl9LApLOmZ1bmN0aW9uKGEsYil7dmFyIHQs
+cyxyLHEscD10aGlzCnUuY0EuYShiKQppZihwLmI9PW51bGwpcmV0dXJuIHAuYy5LKDAsYikKdD1wLkNm
+KCkKZm9yKHM9MDtzPHQubGVuZ3RoOysrcyl7cj10W3NdCnE9cC5iW3JdCmlmKHR5cGVvZiBxPT0idW5k
+ZWZpbmVkIil7cT1QLlFlKHAuYVtyXSkKcC5iW3JdPXF9Yi4kMihyLHEpCmlmKHQhPT1wLmMpdGhyb3cg
+SC5iKFAuYTQocCkpfX0sCkNmOmZ1bmN0aW9uKCl7dmFyIHQ9dS5iTS5hKHRoaXMuYykKaWYodD09bnVs
+bCl0PXRoaXMuYz1ILlZNKE9iamVjdC5rZXlzKHRoaXMuYSksdS5zKQpyZXR1cm4gdH0sClhLOmZ1bmN0
+aW9uKCl7dmFyIHQscyxyLHEscCxvPXRoaXMKaWYoby5iPT1udWxsKXJldHVybiBvLmMKdD1QLkZsKHUu
+Tix1LnopCnM9by5DZigpCmZvcihyPTA7cT1zLmxlbmd0aCxyPHE7KytyKXtwPXNbcl0KdC5ZKDAscCxv
+LnEoMCxwKSl9aWYocT09PTApQy5ObS5pKHMsIiIpCmVsc2UgQy5ObS5zQShzLDApCm8uYT1vLmI9bnVs
+bApyZXR1cm4gby5jPXR9LApmYjpmdW5jdGlvbihhKXt2YXIgdAppZighT2JqZWN0LnByb3RvdHlwZS5o
+YXNPd25Qcm9wZXJ0eS5jYWxsKHRoaXMuYSxhKSlyZXR1cm4gbnVsbAp0PVAuUWUodGhpcy5hW2FdKQpy
+ZXR1cm4gdGhpcy5iW2FdPXR9fQpQLmk4LnByb3RvdHlwZT17CmdBOmZ1bmN0aW9uKGEpe3ZhciB0PXRo
+aXMuYQpyZXR1cm4gdC5nQSh0KX0sCkU6ZnVuY3Rpb24oYSxiKXt2YXIgdD10aGlzLmEKaWYodC5iPT1u
+dWxsKXQ9dC5nVigpLkUoMCxiKQplbHNle3Q9dC5DZigpCmlmKGI8MHx8Yj49dC5sZW5ndGgpcmV0dXJu
+IEguT0godCxiKQp0PXRbYl19cmV0dXJuIHR9LApna3o6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5hCmlm
+KHQuYj09bnVsbCl7dD10LmdWKCkKdD10Lmdreih0KX1lbHNle3Q9dC5DZigpCnQ9bmV3IEoubTEodCx0
+Lmxlbmd0aCxILnQ2KHQpLkMoIm0xPDE+IikpfXJldHVybiB0fSwKdGc6ZnVuY3Rpb24oYSxiKXtyZXR1
+cm4gdGhpcy5hLng0KGIpfX0KUC5wZy5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigpe3ZhciB0LHMKdHJ5
+e3Q9bmV3IFRleHREZWNvZGVyKCJ1dGYtOCIse2ZhdGFsOnRydWV9KQpyZXR1cm4gdH1jYXRjaChzKXtI
+LlJ1KHMpfXJldHVybiBudWxsfSwKJFM6MTJ9ClAuYzIucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXt2
+YXIgdCxzCnRyeXt0PW5ldyBUZXh0RGVjb2RlcigidXRmLTgiLHtmYXRhbDpmYWxzZX0pCnJldHVybiB0
+fWNhdGNoKHMpe0guUnUocyl9cmV0dXJuIG51bGx9LAokUzoxMn0KUC5DVi5wcm90b3R5cGU9ewp5cjpm
 dW5jdGlvbihhLGEwLGExKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsayxqLGksaCxnLGYsZSxkLGMsYj0i
 SW52YWxpZCBiYXNlNjQgZW5jb2RpbmcgbGVuZ3RoICIKYTE9UC5qQihhMCxhMSxhLmxlbmd0aCkKdD0k
 LlY3KCkKZm9yKHM9YTAscj1zLHE9bnVsbCxwPS0xLG89LTEsbj0wO3M8YTE7cz1tKXttPXMrMQpsPUMu
 eEIuVyhhLHMpCmlmKGw9PT0zNyl7az1tKzIKaWYoazw9YTEpe2o9SC5vbyhDLnhCLlcoYSxtKSkKaT1I
 Lm9vKEMueEIuVyhhLG0rMSkpCmg9aioxNitpLShpJjI1NikKaWYoaD09PTM3KWg9LTEKbT1rfWVsc2Ug
 aD0tMX1lbHNlIGg9bAppZigwPD1oJiZoPD0xMjcpe2lmKGg8MHx8aD49dC5sZW5ndGgpcmV0dXJuIEgu
-ayh0LGgpCmc9dFtoXQppZihnPj0wKXtoPUMueEIubSgiQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVph
-YmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODkrLyIsZykKaWYoaD09PWwpY29udGludWUK
-bD1ofWVsc2V7aWYoZz09PS0xKXtpZihwPDApe2Y9cT09bnVsbD9udWxsOnEuYS5sZW5ndGgKaWYoZj09
-bnVsbClmPTAKcD1mKyhzLXIpCm89c30rK24KaWYobD09PTYxKWNvbnRpbnVlfWw9aH1pZihnIT09LTIp
-e2lmKHE9PW51bGwpcT1uZXcgUC5SbigiIikKcS5hKz1DLnhCLk5qKGEscixzKQpxLmErPUguTHcobCkK
-cj1tCmNvbnRpbnVlfX10aHJvdyBILmIoUC5ycigiSW52YWxpZCBiYXNlNjQgZGF0YSIsYSxzKSl9aWYo
-cSE9bnVsbCl7Zj1xLmErPUMueEIuTmooYSxyLGExKQplPWYubGVuZ3RoCmlmKHA+PTApUC54TShhLG8s
-YTEscCxuLGUpCmVsc2V7ZD1DLmpuLnpZKGUtMSw0KSsxCmlmKGQ9PT0xKXRocm93IEguYihQLnJyKGIs
-YSxhMSkpCmZvcig7ZDw0Oyl7Zis9Ij0iCnEuYT1mOysrZH19Zj1xLmEKcmV0dXJuIEMueEIuaTcoYSxh
-MCxhMSxmLmNoYXJDb2RlQXQoMCk9PTA/ZjpmKX1jPWExLWEwCmlmKHA+PTApUC54TShhLG8sYTEscCxu
-LGMpCmVsc2V7ZD1DLmpuLnpZKGMsNCkKaWYoZD09PTEpdGhyb3cgSC5iKFAucnIoYixhLGExKSkKaWYo
-ZD4xKWE9Qy54Qi5pNyhhLGExLGExLGQ9PT0yPyI9PSI6Ij0iKX1yZXR1cm4gYX19ClAuVTgucHJvdG90
-eXBlPXt9ClAuVWsucHJvdG90eXBlPXt9ClAud0kucHJvdG90eXBlPXt9ClAuWmkucHJvdG90eXBlPXt9
-ClAuVWQucHJvdG90eXBlPXsKWjpmdW5jdGlvbihhKXt2YXIgdD1QLmgodGhpcy5hKQpyZXR1cm4odGhp
-cy5iIT1udWxsPyJDb252ZXJ0aW5nIG9iamVjdCB0byBhbiBlbmNvZGFibGUgb2JqZWN0IGZhaWxlZDoi
-OiJDb252ZXJ0aW5nIG9iamVjdCBkaWQgbm90IHJldHVybiBhbiBlbmNvZGFibGUgb2JqZWN0OiIpKyIg
-Iit0fX0KUC5LOC5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3JldHVybiJDeWNsaWMgZXJyb3IgaW4g
-SlNPTiBzdHJpbmdpZnkifX0KUC5ieS5wcm90b3R5cGU9ewpwVzpmdW5jdGlvbihhLGIsYyl7dmFyIHQK
-dS5lcC5hKGMpCnQ9UC5CUyhiLHRoaXMuZ0hlKCkuYSkKcmV0dXJuIHR9LApPQjpmdW5jdGlvbihhLGIp
-e3ZhciB0CnUuYmMuYShiKQp0PVAudVgoYSx0aGlzLmdaRSgpLmIsbnVsbCkKcmV0dXJuIHR9LApnWkU6
-ZnVuY3Rpb24oKXtyZXR1cm4gQy5uWH0sCmdIZTpmdW5jdGlvbigpe3JldHVybiBDLkEzfX0KUC5vai5w
-cm90b3R5cGU9e30KUC5NeC5wcm90b3R5cGU9e30KUC5TaC5wcm90b3R5cGU9ewp2cDpmdW5jdGlvbihh
-KXt2YXIgdCxzLHIscSxwLG8sbj1hLmxlbmd0aApmb3IodD1KLnJZKGEpLHM9dGhpcy5jLHI9MCxxPTA7
-cTxuOysrcSl7cD10LlcoYSxxKQppZihwPjkyKWNvbnRpbnVlCmlmKHA8MzIpe2lmKHE+cilzLmErPUMu
-eEIuTmooYSxyLHEpCnI9cSsxCnMuYSs9SC5Mdyg5MikKc3dpdGNoKHApe2Nhc2UgODpzLmErPUguTHco
-OTgpCmJyZWFrCmNhc2UgOTpzLmErPUguTHcoMTE2KQpicmVhawpjYXNlIDEwOnMuYSs9SC5MdygxMTAp
-CmJyZWFrCmNhc2UgMTI6cy5hKz1ILkx3KDEwMikKYnJlYWsKY2FzZSAxMzpzLmErPUguTHcoMTE0KQpi
-cmVhawpkZWZhdWx0OnMuYSs9SC5MdygxMTcpCnMuYSs9SC5Mdyg0OCkKcy5hKz1ILkx3KDQ4KQpvPXA+
-Pj40JjE1CnMuYSs9SC5MdyhvPDEwPzQ4K286ODcrbykKbz1wJjE1CnMuYSs9SC5MdyhvPDEwPzQ4K286
-ODcrbykKYnJlYWt9fWVsc2UgaWYocD09PTM0fHxwPT09OTIpe2lmKHE+cilzLmErPUMueEIuTmooYSxy
-LHEpCnI9cSsxCnMuYSs9SC5Mdyg5MikKcy5hKz1ILkx3KHApfX1pZihyPT09MClzLmErPUguZChhKQpl
-bHNlIGlmKHI8bilzLmErPXQuTmooYSxyLG4pfSwKSm46ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEKZm9y
-KHQ9dGhpcy5hLHM9dC5sZW5ndGgscj0wO3I8czsrK3Ipe3E9dFtyXQppZihhPT1udWxsP3E9PW51bGw6
-YT09PXEpdGhyb3cgSC5iKG5ldyBQLks4KGEsbnVsbCkpfUMuTm0uaSh0LGEpfSwKaVU6ZnVuY3Rpb24o
-YSl7dmFyIHQscyxyLHEscD10aGlzCmlmKHAudE0oYSkpcmV0dXJuCnAuSm4oYSkKdHJ5e3Q9cC5iLiQx
-KGEpCmlmKCFwLnRNKHQpKXtyPVAuR3koYSxudWxsLHAuZ1ZLKCkpCnRocm93IEguYihyKX1yPXAuYQpp
-ZigwPj1yLmxlbmd0aClyZXR1cm4gSC5rKHIsLTEpCnIucG9wKCl9Y2F0Y2gocSl7cz1ILlJ1KHEpCnI9
-UC5HeShhLHMscC5nVksoKSkKdGhyb3cgSC5iKHIpfX0sCnRNOmZ1bmN0aW9uKGEpe3ZhciB0LHMscj10
-aGlzCmlmKHR5cGVvZiBhPT0ibnVtYmVyIil7aWYoIWlzRmluaXRlKGEpKXJldHVybiExCnIuYy5hKz1D
-LkNELlooYSkKcmV0dXJuITB9ZWxzZSBpZihhPT09ITApe3IuYy5hKz0idHJ1ZSIKcmV0dXJuITB9ZWxz
-ZSBpZihhPT09ITEpe3IuYy5hKz0iZmFsc2UiCnJldHVybiEwfWVsc2UgaWYoYT09bnVsbCl7ci5jLmEr
-PSJudWxsIgpyZXR1cm4hMH1lbHNlIGlmKHR5cGVvZiBhPT0ic3RyaW5nIil7dD1yLmMKdC5hKz0nIicK
-ci52cChhKQp0LmErPSciJwpyZXR1cm4hMH1lbHNlIGlmKHUuai5iKGEpKXtyLkpuKGEpCnIubEsoYSkK
-dD1yLmEKaWYoMD49dC5sZW5ndGgpcmV0dXJuIEguayh0LC0xKQp0LnBvcCgpCnJldHVybiEwfWVsc2Ug
-aWYodS5HLmIoYSkpe3IuSm4oYSkKcz1yLmp3KGEpCnQ9ci5hCmlmKDA+PXQubGVuZ3RoKXJldHVybiBI
-LmsodCwtMSkKdC5wb3AoKQpyZXR1cm4gc31lbHNlIHJldHVybiExfSwKbEs6ZnVuY3Rpb24oYSl7dmFy
-IHQscyxyPXRoaXMuYwpyLmErPSJbIgp0PUouVTYoYSkKaWYodC5nb3IoYSkpe3RoaXMuaVUodC5xKGEs
-MCkpCmZvcihzPTE7czx0LmdBKGEpOysrcyl7ci5hKz0iLCIKdGhpcy5pVSh0LnEoYSxzKSl9fXIuYSs9
-Il0ifSwKanc6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscCxvLG49dGhpcyxtPXt9CmlmKGEuZ2wwKGEp
-KXtuLmMuYSs9Int9IgpyZXR1cm4hMH10PWEuZ0EoYSkqMgpzPW5ldyBBcnJheSh0KQpzLmZpeGVkJGxl
-bmd0aD1BcnJheQpyPW0uYT0wCm0uYj0hMAphLksoMCxuZXcgUC50aShtLHMpKQppZighbS5iKXJldHVy
-biExCnE9bi5jCnEuYSs9InsiCmZvcihwPSciJztyPHQ7cis9MixwPScsIicpe3EuYSs9cApuLnZwKEgu
-YyhzW3JdKSkKcS5hKz0nIjonCm89cisxCmlmKG8+PXQpcmV0dXJuIEguayhzLG8pCm4uaVUoc1tvXSl9
-cS5hKz0ifSIKcmV0dXJuITB9fQpQLnRpLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dmFyIHQs
-cwppZih0eXBlb2YgYSE9InN0cmluZyIpdGhpcy5hLmI9ITEKdD10aGlzLmIKcz10aGlzLmEKQy5ObS5Z
-KHQscy5hKyssYSkKQy5ObS5ZKHQscy5hKyssYil9LAokUzo0fQpQLnR1LnByb3RvdHlwZT17CmdWSzpm
-dW5jdGlvbigpe3ZhciB0PXRoaXMuYy5hCnJldHVybiB0LmNoYXJDb2RlQXQoMCk9PTA/dDp0fX0KUC51
-NS5wcm90b3R5cGU9ewpnWkU6ZnVuY3Rpb24oKXtyZXR1cm4gQy5Ra319ClAuRTMucHJvdG90eXBlPXsK
-V0o6ZnVuY3Rpb24oYSl7dmFyIHQscyxyPVAuakIoMCxudWxsLGEubGVuZ3RoKSxxPXItMAppZihxPT09
-MClyZXR1cm4gbmV3IFVpbnQ4QXJyYXkoMCkKdD1uZXcgVWludDhBcnJheShxKjMpCnM9bmV3IFAuUnco
-dCkKaWYocy5HeChhLDAscikhPT1yKXMuTzYoSi5hNihhLHItMSksMCkKcmV0dXJuIG5ldyBVaW50OEFy
-cmF5KHQuc3ViYXJyYXkoMCxILnJNKDAscy5iLHQubGVuZ3RoKSkpfX0KUC5Sdy5wcm90b3R5cGU9ewpP
-NjpmdW5jdGlvbihhLGIpe3ZhciB0LHM9dGhpcyxyPXMuYyxxPXMuYixwPXErMSxvPXIubGVuZ3RoCmlm
-KChiJjY0NTEyKT09PTU2MzIwKXt0PTY1NTM2KygoYSYxMDIzKTw8MTApfGImMTAyMwpzLmI9cAppZihx
-Pj1vKXJldHVybiBILmsocixxKQpyW3FdPTI0MHx0Pj4+MTgKcT1zLmI9cCsxCmlmKHA+PW8pcmV0dXJu
-IEguayhyLHApCnJbcF09MTI4fHQ+Pj4xMiY2MwpwPXMuYj1xKzEKaWYocT49bylyZXR1cm4gSC5rKHIs
-cSkKcltxXT0xMjh8dD4+PjYmNjMKcy5iPXArMQppZihwPj1vKXJldHVybiBILmsocixwKQpyW3BdPTEy
-OHx0JjYzCnJldHVybiEwfWVsc2V7cy5iPXAKaWYocT49bylyZXR1cm4gSC5rKHIscSkKcltxXT0yMjR8
-YT4+PjEyCnE9cy5iPXArMQppZihwPj1vKXJldHVybiBILmsocixwKQpyW3BdPTEyOHxhPj4+NiY2Mwpz
-LmI9cSsxCmlmKHE+PW8pcmV0dXJuIEguayhyLHEpCnJbcV09MTI4fGEmNjMKcmV0dXJuITF9fSwKR3g6
-ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixxLHAsbyxuLG09dGhpcwppZihiIT09YyYmKEMueEIubShh
-LGMtMSkmNjQ1MTIpPT09NTUyOTYpLS1jCmZvcih0PW0uYyxzPXQubGVuZ3RoLHI9YjtyPGM7KytyKXtx
-PUMueEIuVyhhLHIpCmlmKHE8PTEyNyl7cD1tLmIKaWYocD49cylicmVhawptLmI9cCsxCnRbcF09cX1l
-bHNlIGlmKChxJjY0NTEyKT09PTU1Mjk2KXtpZihtLmIrMz49cylicmVhawpvPXIrMQppZihtLk82KHEs
-Qy54Qi5XKGEsbykpKXI9b31lbHNlIGlmKHE8PTIwNDcpe3A9bS5iCm49cCsxCmlmKG4+PXMpYnJlYWsK
-bS5iPW4KaWYocD49cylyZXR1cm4gSC5rKHQscCkKdFtwXT0xOTJ8cT4+PjYKbS5iPW4rMQp0W25dPTEy
-OHxxJjYzfWVsc2V7cD1tLmIKaWYocCsyPj1zKWJyZWFrCm49bS5iPXArMQppZihwPj1zKXJldHVybiBI
-LmsodCxwKQp0W3BdPTIyNHxxPj4+MTIKcD1tLmI9bisxCmlmKG4+PXMpcmV0dXJuIEguayh0LG4pCnRb
-bl09MTI4fHE+Pj42JjYzCm0uYj1wKzEKaWYocD49cylyZXR1cm4gSC5rKHQscCkKdFtwXT0xMjh8cSY2
-M319cmV0dXJuIHJ9fQpQLkdZLnByb3RvdHlwZT17CldKOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHAs
-byxuLG0sbAp1LkwuYShhKQp0PVAua3koITEsYSwwLG51bGwpCmlmKHQhPW51bGwpcmV0dXJuIHQKcz1Q
-LmpCKDAsbnVsbCxKLkgoYSkpCnI9UC5jUChhLDAscykKaWYocj4wKXtxPVAuSE0oYSwwLHIpCmlmKHI9
-PT1zKXJldHVybiBxCnA9bmV3IFAuUm4ocSkKbz1yCm49ITF9ZWxzZXtvPTAKcD1udWxsCm49ITB9aWYo
-cD09bnVsbClwPW5ldyBQLlJuKCIiKQptPW5ldyBQLmJ6KCExLHApCm0uYz1uCm0uTUUoYSxvLHMpCmlm
-KG0uZT4wKXtILnZoKFAucnIoIlVuZmluaXNoZWQgVVRGLTggb2N0ZXQgc2VxdWVuY2UiLGEscykpCnAu
-YSs9SC5Mdyg2NTUzMykKbS5mPW0uZT1tLmQ9MH1sPXAuYQpyZXR1cm4gbC5jaGFyQ29kZUF0KDApPT0w
-P2w6bH19ClAuYnoucHJvdG90eXBlPXsKTUU6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixxLHAsbyxu
-LG0sbCxrLGosaSxoPXRoaXMsZz0iQmFkIFVURi04IGVuY29kaW5nIDB4Igp1LkwuYShhKQp0PWguZApz
-PWguZQpyPWguZgpoLmY9aC5lPWguZD0wCiRsYWJlbDAkMDpmb3IocT1KLlU2KGEpLHA9aC5iLG89Yjsh
-MDtvPWopeyRsYWJlbDEkMTppZihzPjApe2Rve2lmKG89PT1jKWJyZWFrICRsYWJlbDAkMApuPXEucShh
-LG8pCmlmKHR5cGVvZiBuIT09Im51bWJlciIpcmV0dXJuIG4uek0oKQppZigobiYxOTIpIT09MTI4KXtt
-PVAucnIoZytDLmpuLldaKG4sMTYpLGEsbykKdGhyb3cgSC5iKG0pfWVsc2V7dD0odDw8NnxuJjYzKT4+
-PjA7LS1zOysrb319d2hpbGUocz4wKQptPXItMQppZihtPDB8fG0+PTQpcmV0dXJuIEguayhDLkdiLG0p
-CmlmKHQ8PUMuR2JbbV0pe209UC5ycigiT3ZlcmxvbmcgZW5jb2Rpbmcgb2YgMHgiK0Muam4uV1oodCwx
-NiksYSxvLXItMSkKdGhyb3cgSC5iKG0pfWlmKHQ+MTExNDExMSl7bT1QLnJyKCJDaGFyYWN0ZXIgb3V0
-c2lkZSB2YWxpZCBVbmljb2RlIHJhbmdlOiAweCIrQy5qbi5XWih0LDE2KSxhLG8tci0xKQp0aHJvdyBI
-LmIobSl9aWYoIWguY3x8dCE9PTY1Mjc5KXAuYSs9SC5Mdyh0KQpoLmM9ITF9Zm9yKG09bzxjO207KXts
-PVAuY1AoYSxvLGMpCmlmKGw+MCl7aC5jPSExCms9bytsCnAuYSs9UC5ITShhLG8saykKaWYoaz09PWMp
-YnJlYWt9ZWxzZSBrPW8Kaj1rKzEKbj1xLnEoYSxrKQppZih0eXBlb2YgbiE9PSJudW1iZXIiKXJldHVy
-biBuLkooKQppZihuPDApe2k9UC5ycigiTmVnYXRpdmUgVVRGLTggY29kZSB1bml0OiAtMHgiK0Muam4u
-V1ooLW4sMTYpLGEsai0xKQp0aHJvdyBILmIoaSl9ZWxzZXtpZigobiYyMjQpPT09MTkyKXt0PW4mMzEK
-cz0xCnI9MQpjb250aW51ZSAkbGFiZWwwJDB9aWYoKG4mMjQwKT09PTIyNCl7dD1uJjE1CnM9MgpyPTIK
-Y29udGludWUgJGxhYmVsMCQwfWlmKChuJjI0OCk9PT0yNDAmJm48MjQ1KXt0PW4mNwpzPTMKcj0zCmNv
-bnRpbnVlICRsYWJlbDAkMH1pPVAucnIoZytDLmpuLldaKG4sMTYpLGEsai0xKQp0aHJvdyBILmIoaSl9
-fWJyZWFrICRsYWJlbDAkMH1pZihzPjApe2guZD10CmguZT1zCmguZj1yfX19ClAuV0YucHJvdG90eXBl
-PXsKJDI6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIKdS5mby5hKGEpCnQ9dGhpcy5iCnM9dGhpcy5hCnQu
-YSs9cy5hCnI9dC5hKz1ILmQoYS5hKQp0LmE9cisiOiAiCnQuYSs9UC5oKGIpCnMuYT0iLCAifSwKJFM6
-NDJ9ClAuYTIucHJvdG90eXBlPXt9ClAuaVAucHJvdG90eXBlPXsKRE46ZnVuY3Rpb24oYSxiKXtpZihi
-PT1udWxsKXJldHVybiExCnJldHVybiBiIGluc3RhbmNlb2YgUC5pUCYmdGhpcy5hPT09Yi5hJiYhMH0s
-CmdpTzpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmEKcmV0dXJuKHReQy5qbi53Ryh0LDMwKSkmMTA3Mzc0
-MTgyM30sClo6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcyxzPVAuR3EoSC50Sih0KSkscj1QLmgwKEguTlMo
-dCkpLHE9UC5oMChILmpBKHQpKSxwPVAuaDAoSC5JWCh0KSksbz1QLmgwKEguY2godCkpLG49UC5oMChI
-LkpkKHQpKSxtPVAuVngoSC5WYSh0KSksbD1zKyItIityKyItIitxKyIgIitwKyI6IitvKyI6IituKyIu
-IittCnJldHVybiBsfX0KUC5DUC5wcm90b3R5cGU9e30KUC5YUy5wcm90b3R5cGU9ewpnSUk6ZnVuY3Rp
-b24oKXtyZXR1cm4gSC50cyh0aGlzLiR0aHJvd25Kc0Vycm9yKX19ClAuQzYucHJvdG90eXBlPXsKWjpm
-dW5jdGlvbihhKXt2YXIgdD10aGlzLmEKaWYodCE9bnVsbClyZXR1cm4iQXNzZXJ0aW9uIGZhaWxlZDog
-IitQLmgodCkKcmV0dXJuIkFzc2VydGlvbiBmYWlsZWQifX0KUC5MSy5wcm90b3R5cGU9ewpaOmZ1bmN0
-aW9uKGEpe3JldHVybiJUaHJvdyBvZiBudWxsLiJ9fQpQLkFULnByb3RvdHlwZT17CmdMOmZ1bmN0aW9u
-KCl7cmV0dXJuIkludmFsaWQgYXJndW1lbnQiKyghdGhpcy5hPyIocykiOiIiKX0sCmd1OmZ1bmN0aW9u
-KCl7cmV0dXJuIiJ9LApaOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHA9dGhpcyxvPXAuYyxuPW8hPW51
-bGw/IiAoIitvKyIpIjoiIgpvPXAuZAp0PW89PW51bGw/IiI6IjogIitILmQobykKcz1wLmdMKCkrbit0
-CmlmKCFwLmEpcmV0dXJuIHMKcj1wLmd1KCkKcT1QLmgocC5iKQpyZXR1cm4gcytyKyI6ICIrcX19ClAu
-YkoucHJvdG90eXBlPXsKZ0w6ZnVuY3Rpb24oKXtyZXR1cm4iUmFuZ2VFcnJvciJ9LApndTpmdW5jdGlv
-bigpe3ZhciB0LHMscj10aGlzLmUKaWYocj09bnVsbCl7cj10aGlzLmYKdD1yIT1udWxsPyI6IE5vdCBs
-ZXNzIHRoYW4gb3IgZXF1YWwgdG8gIitILmQocik6IiJ9ZWxzZXtzPXRoaXMuZgppZihzPT1udWxsKXQ9
-IjogTm90IGdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0byAiK0guZChyKQplbHNlIGlmKHM+cil0PSI6IE5v
-dCBpbiByYW5nZSAiK0guZChyKSsiLi4iK0guZChzKSsiLCBpbmNsdXNpdmUiCmVsc2UgdD1zPHI/Ijog
-VmFsaWQgdmFsdWUgcmFuZ2UgaXMgZW1wdHkiOiI6IE9ubHkgdmFsaWQgdmFsdWUgaXMgIitILmQocil9
-cmV0dXJuIHR9fQpQLmVZLnByb3RvdHlwZT17CmdMOmZ1bmN0aW9uKCl7cmV0dXJuIlJhbmdlRXJyb3Ii
-fSwKZ3U6ZnVuY3Rpb24oKXt2YXIgdCxzPUguV1kodGhpcy5iKQppZih0eXBlb2YgcyE9PSJudW1iZXIi
-KXJldHVybiBzLkooKQppZihzPDApcmV0dXJuIjogaW5kZXggbXVzdCBub3QgYmUgbmVnYXRpdmUiCnQ9
-dGhpcy5mCmlmKHQ9PT0wKXJldHVybiI6IG5vIGluZGljZXMgYXJlIHZhbGlkIgpyZXR1cm4iOiBpbmRl
-eCBzaG91bGQgYmUgbGVzcyB0aGFuICIrSC5kKHQpfSwKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMu
-Zn19ClAubXAucHJvdG90eXBlPXsKWjpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwLG8sbixtLGw9dGhp
-cyxrPXt9LGo9bmV3IFAuUm4oIiIpCmsuYT0iIgpmb3IodD1sLmMscz10Lmxlbmd0aCxyPTAscT0iIixw
-PSIiO3I8czsrK3IscD0iLCAiKXtvPXRbcl0Kai5hPXErcApxPWouYSs9UC5oKG8pCmsuYT0iLCAifWwu
-ZC5LKDAsbmV3IFAuV0YoayxqKSkKbj1QLmgobC5hKQptPWouWigwKQp0PSJOb1N1Y2hNZXRob2RFcnJv
-cjogbWV0aG9kIG5vdCBmb3VuZDogJyIrSC5kKGwuYi5hKSsiJ1xuUmVjZWl2ZXI6ICIrbisiXG5Bcmd1
-bWVudHM6IFsiK20rIl0iCnJldHVybiB0fX0KUC51Yi5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3Jl
-dHVybiJVbnN1cHBvcnRlZCBvcGVyYXRpb246ICIrdGhpcy5hfX0KUC5kcy5wcm90b3R5cGU9ewpaOmZ1
-bmN0aW9uKGEpe3ZhciB0PXRoaXMuYQpyZXR1cm4gdCE9bnVsbD8iVW5pbXBsZW1lbnRlZEVycm9yOiAi
-K3Q6IlVuaW1wbGVtZW50ZWRFcnJvciJ9fQpQLmxqLnByb3RvdHlwZT17Clo6ZnVuY3Rpb24oYSl7cmV0
-dXJuIkJhZCBzdGF0ZTogIit0aGlzLmF9fQpQLlVWLnByb3RvdHlwZT17Clo6ZnVuY3Rpb24oYSl7dmFy
-IHQ9dGhpcy5hCmlmKHQ9PW51bGwpcmV0dXJuIkNvbmN1cnJlbnQgbW9kaWZpY2F0aW9uIGR1cmluZyBp
-dGVyYXRpb24uIgpyZXR1cm4iQ29uY3VycmVudCBtb2RpZmljYXRpb24gZHVyaW5nIGl0ZXJhdGlvbjog
-IitQLmgodCkrIi4ifX0KUC5rNS5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3JldHVybiJPdXQgb2Yg
-TWVtb3J5In0sCmdJSTpmdW5jdGlvbigpe3JldHVybiBudWxsfSwKJGlYUzoxfQpQLktZLnByb3RvdHlw
-ZT17Clo6ZnVuY3Rpb24oYSl7cmV0dXJuIlN0YWNrIE92ZXJmbG93In0sCmdJSTpmdW5jdGlvbigpe3Jl
-dHVybiBudWxsfSwKJGlYUzoxfQpQLnQ3LnByb3RvdHlwZT17Clo6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhp
-cy5hCnJldHVybiB0PT1udWxsPyJSZWFkaW5nIHN0YXRpYyB2YXJpYWJsZSBkdXJpbmcgaXRzIGluaXRp
-YWxpemF0aW9uIjoiUmVhZGluZyBzdGF0aWMgdmFyaWFibGUgJyIrdCsiJyBkdXJpbmcgaXRzIGluaXRp
-YWxpemF0aW9uIn19ClAuQ0QucHJvdG90eXBlPXsKWjpmdW5jdGlvbihhKXtyZXR1cm4iRXhjZXB0aW9u
-OiAiK3RoaXMuYX0sCiRpUno6MX0KUC5hRS5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3ZhciB0LHMs
-cixxLHAsbyxuLG0sbCxrLGosaSxoPXRoaXMuYSxnPWghPW51bGwmJiIiIT09aD8iRm9ybWF0RXhjZXB0
-aW9uOiAiK0guZChoKToiRm9ybWF0RXhjZXB0aW9uIixmPXRoaXMuYyxlPXRoaXMuYgppZih0eXBlb2Yg
-ZT09InN0cmluZyIpe2lmKGYhPW51bGwpaD1mPDB8fGY+ZS5sZW5ndGgKZWxzZSBoPSExCmlmKGgpZj1u
-dWxsCmlmKGY9PW51bGwpe3Q9ZS5sZW5ndGg+Nzg/Qy54Qi5OaihlLDAsNzUpKyIuLi4iOmUKcmV0dXJu
-IGcrIlxuIit0fWZvcihzPTEscj0wLHE9ITEscD0wO3A8ZjsrK3Ape289Qy54Qi5XKGUscCkKaWYobz09
-PTEwKXtpZihyIT09cHx8IXEpKytzCnI9cCsxCnE9ITF9ZWxzZSBpZihvPT09MTMpeysrcwpyPXArMQpx
-PSEwfX1nPXM+MT9nKygiIChhdCBsaW5lICIrcysiLCBjaGFyYWN0ZXIgIisoZi1yKzEpKyIpXG4iKTpn
-KygiIChhdCBjaGFyYWN0ZXIgIisoZisxKSsiKVxuIikKbj1lLmxlbmd0aApmb3IocD1mO3A8bjsrK3Ap
-e289Qy54Qi5tKGUscCkKaWYobz09PTEwfHxvPT09MTMpe249cApicmVha319aWYobi1yPjc4KWlmKGYt
-cjw3NSl7bT1yKzc1Cmw9cgprPSIiCmo9Ii4uLiJ9ZWxzZXtpZihuLWY8NzUpe2w9bi03NQptPW4Kaj0i
-In1lbHNle2w9Zi0zNgptPWYrMzYKaj0iLi4uIn1rPSIuLi4ifWVsc2V7bT1uCmw9cgprPSIiCmo9IiJ9
-aT1DLnhCLk5qKGUsbCxtKQpyZXR1cm4gZytrK2kraisiXG4iK0MueEIuSXgoIiAiLGYtbCtrLmxlbmd0
-aCkrIl5cbiJ9ZWxzZSByZXR1cm4gZiE9bnVsbD9nKygiIChhdCBvZmZzZXQgIitILmQoZikrIikiKTpn
-fSwKJGlSejoxfQpQLkVILnByb3RvdHlwZT17fQpQLklmLnByb3RvdHlwZT17fQpQLmNYLnByb3RvdHlw
-ZT17CkUyOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD1ILkxoKHRoaXMpCnJldHVybiBILksxKHRoaXMsdC5L
-cShjKS5DKCIxKGNYLkUpIikuYShiKSx0LkMoImNYLkUiKSxjKX0sCmV2OmZ1bmN0aW9uKGEsYil7dmFy
-IHQ9SC5MaCh0aGlzKQpyZXR1cm4gbmV3IEguVTUodGhpcyx0LkMoImEyKGNYLkUpIikuYShiKSx0LkMo
-IlU1PGNYLkU+IikpfSwKZ0E6ZnVuY3Rpb24oYSl7dmFyIHQscz10aGlzLmdreih0aGlzKQpmb3IodD0w
-O3MuRigpOykrK3QKcmV0dXJuIHR9LApnbDA6ZnVuY3Rpb24oYSl7cmV0dXJuIXRoaXMuZ2t6KHRoaXMp
-LkYoKX0sCmdyODpmdW5jdGlvbihhKXt2YXIgdCxzPXRoaXMuZ2t6KHRoaXMpCmlmKCFzLkYoKSl0aHJv
-dyBILmIoSC5XcCgpKQp0PXMuZ2woKQppZihzLkYoKSl0aHJvdyBILmIoSC5kVSgpKQpyZXR1cm4gdH0s
-CkU6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscT0iaW5kZXgiClAuVUkoYixxLHUucCkKUC5rMShiLHEp
-CmZvcih0PXRoaXMuZ2t6KHRoaXMpLHM9MDt0LkYoKTspe3I9dC5nbCgpCmlmKGI9PT1zKXJldHVybiBy
-Oysrc310aHJvdyBILmIoUC50KGIsdGhpcyxxLG51bGwscykpfSwKWjpmdW5jdGlvbihhKXtyZXR1cm4g
-UC5FUCh0aGlzLCIoIiwiKSIpfX0KUC5Bbi5wcm90b3R5cGU9e30KUC56TS5wcm90b3R5cGU9eyRpYlE6
-MSwkaWNYOjF9ClAuWjAucHJvdG90eXBlPXt9ClAuTjMucHJvdG90eXBlPXsKWjpmdW5jdGlvbihhKXty
-ZXR1cm4iTWFwRW50cnkoIitILmQodGhpcy5hKSsiOiAiK0guZCh0aGlzLmIpKyIpIn19ClAuYzgucHJv
-dG90eXBlPXsKZ2lPOmZ1bmN0aW9uKGEpe3JldHVybiBQLk1oLnByb3RvdHlwZS5naU8uY2FsbCh0aGlz
-LHRoaXMpfSwKWjpmdW5jdGlvbihhKXtyZXR1cm4ibnVsbCJ9fQpQLmxmLnByb3RvdHlwZT17fQpQLk1o
-LnByb3RvdHlwZT17Y29uc3RydWN0b3I6UC5NaCwkaU1oOjEsCkROOmZ1bmN0aW9uKGEsYil7cmV0dXJu
-IHRoaXM9PT1ifSwKZ2lPOmZ1bmN0aW9uKGEpe3JldHVybiBILmVRKHRoaXMpfSwKWjpmdW5jdGlvbihh
-KXtyZXR1cm4iSW5zdGFuY2Ugb2YgJyIrSC5kKEgubGgodGhpcykpKyInIn0sCmU3OmZ1bmN0aW9uKGEs
-Yil7dS5vLmEoYikKdGhyb3cgSC5iKFAubHIodGhpcyxiLmdXYSgpLGIuZ25kKCksYi5nVm0oKSkpfSwK
-dG9TdHJpbmc6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5aKHRoaXMpfX0KUC5PZC5wcm90b3R5cGU9e30K
-UC5pYi5wcm90b3R5cGU9eyRpT2Q6MX0KUC54dS5wcm90b3R5cGU9e30KUC5Hei5wcm90b3R5cGU9e30K
-UC5aZC5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3JldHVybiIifSwKJGlHejoxfQpQLnFVLnByb3Rv
-dHlwZT17JGl2WDoxfQpQLlJuLnByb3RvdHlwZT17CmdBOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEu
-bGVuZ3RofSwKWjpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmEKcmV0dXJuIHQuY2hhckNvZGVBdCgwKT09
-MD90OnR9LAokaUJMOjF9ClAuR0QucHJvdG90eXBlPXt9ClAubjEucHJvdG90eXBlPXsKJDI6ZnVuY3Rp
-b24oYSxiKXt2YXIgdCxzLHIscQp1LmYuYShhKQpILmMoYikKdD1KLnJZKGIpLk9ZKGIsIj0iKQppZih0
-PT09LTEpe2lmKGIhPT0iIilhLlkoMCxQLmt1KGIsMCxiLmxlbmd0aCx0aGlzLmEsITApLCIiKX1lbHNl
-IGlmKHQhPT0wKXtzPUMueEIuTmooYiwwLHQpCnI9Qy54Qi5HKGIsdCsxKQpxPXRoaXMuYQphLlkoMCxQ
-Lmt1KHMsMCxzLmxlbmd0aCxxLCEwKSxQLmt1KHIsMCxyLmxlbmd0aCxxLCEwKSl9cmV0dXJuIGF9LAok
-UzoxOX0KUC5jUy5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3Rocm93IEguYihQLnJyKCJJbGxl
-Z2FsIElQdjQgYWRkcmVzcywgIithLHRoaXMuYSxiKSl9LAokUzo0Nn0KUC5WQy5wcm90b3R5cGU9ewok
-MjpmdW5jdGlvbihhLGIpe3Rocm93IEguYihQLnJyKCJJbGxlZ2FsIElQdjYgYWRkcmVzcywgIithLHRo
-aXMuYSxiKSl9LAokMTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy4kMihhLG51bGwpfSwKJFM6NDd9ClAu
-SlQucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt2YXIgdAppZihiLWE+NCl0aGlzLmEuJDIoImFu
-IElQdjYgcGFydCBjYW4gb25seSBjb250YWluIGEgbWF4aW11bSBvZiA0IGhleCBkaWdpdHMiLGEpCnQ9
-UC5RQShDLnhCLk5qKHRoaXMuYixhLGIpLG51bGwsMTYpCmlmKHR5cGVvZiB0IT09Im51bWJlciIpcmV0
-dXJuIHQuSigpCmlmKHQ8MHx8dD42NTUzNSl0aGlzLmEuJDIoImVhY2ggcGFydCBtdXN0IGJlIGluIHRo
-ZSByYW5nZSBvZiBgMHgwLi4weEZGRkZgIixhKQpyZXR1cm4gdH0sCiRTOjQ4fQpQLkRuLnByb3RvdHlw
-ZT17CmdrdTpmdW5jdGlvbigpe3JldHVybiB0aGlzLmJ9LApnSmY6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhp
-cy5jCmlmKHQ9PW51bGwpcmV0dXJuIiIKaWYoQy54Qi5uKHQsIlsiKSlyZXR1cm4gQy54Qi5Oaih0LDEs
-dC5sZW5ndGgtMSkKcmV0dXJuIHR9LApndHA6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5kCmlmKHQ9PW51
-bGwpcmV0dXJuIFAud0sodGhpcy5hKQpyZXR1cm4gdH0sCmd0UDpmdW5jdGlvbigpe3ZhciB0PXRoaXMu
-ZgpyZXR1cm4gdD09bnVsbD8iIjp0fSwKZ0thOmZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5yCnJldHVybiB0
-PT1udWxsPyIiOnR9LApubTpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHAsbyxuLG0sbD10aGlzCnUu
-WC5hKG51bGwpCnUuay5hKGIpCnQ9bC5hCnM9dD09PSJmaWxlIgpyPWwuYgpxPWwuZApwPWwuYwppZigh
-KHAhPW51bGwpKXA9ci5sZW5ndGghPT0wfHxxIT1udWxsfHxzPyIiOm51bGwKbz1sLmUKaWYoIXMpbj1w
-IT1udWxsJiZvLmxlbmd0aCE9PTAKZWxzZSBuPSEwCmlmKG4mJiFDLnhCLm4obywiLyIpKW89Ii8iK28K
-bT1QLmxlKG51bGwsMCwwLGIpCnJldHVybiBuZXcgUC5Ebih0LHIscCxxLG8sbSxsLnIpfSwKZ0ZqOmZ1
-bmN0aW9uKCl7dmFyIHQscz10aGlzLngKaWYocyE9bnVsbClyZXR1cm4gcwp0PXRoaXMuZQppZih0Lmxl
-bmd0aCE9PTAmJkMueEIuVyh0LDApPT09NDcpdD1DLnhCLkcodCwxKQpzPXQ9PT0iIj9DLnhEOlAuQUYo
-bmV3IEgubEooSC5WTSh0LnNwbGl0KCIvIiksdS5zKSx1LmRPLmEoUC5QSCgpKSx1LmRvKSx1Lk4pCnRo
-aXMuc282KHMpCnJldHVybiBzfSwKZ2hZOmZ1bmN0aW9uKCl7dmFyIHQscz10aGlzCmlmKHMuUT09bnVs
-bCl7dD1zLmYKcy5zUkgobmV3IFAuR2ooUC5XWCh0PT1udWxsPyIiOnQpLHUudikpfXJldHVybiBzLlF9
-LApKaDpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHAsbwpmb3IodD0wLHM9MDtDLnhCLlFpKGIsIi4u
-LyIscyk7KXtzKz0zOysrdH1yPUMueEIuY24oYSwiLyIpCndoaWxlKCEwKXtpZighKHI+MCYmdD4wKSli
-cmVhawpxPUMueEIuUGsoYSwiLyIsci0xKQppZihxPDApYnJlYWsKcD1yLXEKbz1wIT09MgppZighb3x8
-cD09PTMpaWYoQy54Qi5tKGEscSsxKT09PTQ2KW89IW98fEMueEIubShhLHErMik9PT00NgplbHNlIG89
-ITEKZWxzZSBvPSExCmlmKG8pYnJlYWs7LS10CnI9cX1yZXR1cm4gQy54Qi5pNyhhLHIrMSxudWxsLEMu
-eEIuRyhiLHMtMyp0KSl9LApaSTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5tUyhQLmhLKGEpKX0sCm1T
-OmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHAsbyxuLG0sbCxrPXRoaXMsaj1udWxsCmlmKGEuZ0ZpKCku
-bGVuZ3RoIT09MCl7dD1hLmdGaSgpCmlmKGEuZ2NqKCkpe3M9YS5na3UoKQpyPWEuZ0pmKGEpCnE9YS5n
-eEEoKT9hLmd0cChhKTpqfWVsc2V7cT1qCnI9cQpzPSIifXA9UC54ZShhLmdJaShhKSkKbz1hLmdRRCgp
-P2EuZ3RQKCk6an1lbHNle3Q9ay5hCmlmKGEuZ2NqKCkpe3M9YS5na3UoKQpyPWEuZ0pmKGEpCnE9UC53
-QihhLmd4QSgpP2EuZ3RwKGEpOmosdCkKcD1QLnhlKGEuZ0lpKGEpKQpvPWEuZ1FEKCk/YS5ndFAoKTpq
-fWVsc2V7cz1rLmIKcj1rLmMKcT1rLmQKaWYoYS5nSWkoYSk9PT0iIil7cD1rLmUKbz1hLmdRRCgpP2Eu
-Z3RQKCk6ay5mfWVsc2V7aWYoYS5ndFQoKSlwPVAueGUoYS5nSWkoYSkpCmVsc2V7bj1rLmUKaWYobi5s
-ZW5ndGg9PT0wKWlmKHI9PW51bGwpcD10Lmxlbmd0aD09PTA/YS5nSWkoYSk6UC54ZShhLmdJaShhKSkK
-ZWxzZSBwPVAueGUoIi8iK2EuZ0lpKGEpKQplbHNle209ay5KaChuLGEuZ0lpKGEpKQpsPXQubGVuZ3Ro
-PT09MAppZighbHx8ciE9bnVsbHx8Qy54Qi5uKG4sIi8iKSlwPVAueGUobSkKZWxzZSBwPVAud0YobSwh
-bHx8ciE9bnVsbCl9fW89YS5nUUQoKT9hLmd0UCgpOmp9fX1yZXR1cm4gbmV3IFAuRG4odCxzLHIscSxw
-LG8sYS5nWjgoKT9hLmdLYSgpOmopfSwKZ2NqOmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuYyE9bnVsbH0s
-Cmd4QTpmdW5jdGlvbigpe3JldHVybiB0aGlzLmQhPW51bGx9LApnUUQ6ZnVuY3Rpb24oKXtyZXR1cm4g
-dGhpcy5mIT1udWxsfSwKZ1o4OmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuciE9bnVsbH0sCmd0VDpmdW5j
-dGlvbigpe3JldHVybiBDLnhCLm4odGhpcy5lLCIvIil9LAp0NDpmdW5jdGlvbigpe3ZhciB0LHMscj10
-aGlzLHE9ci5hCmlmKHEhPT0iIiYmcSE9PSJmaWxlIil0aHJvdyBILmIoUC5MNCgiQ2Fubm90IGV4dHJh
-Y3QgYSBmaWxlIHBhdGggZnJvbSBhICIrSC5kKHEpKyIgVVJJIikpCnE9ci5mCmlmKChxPT1udWxsPyIi
-OnEpIT09IiIpdGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBleHRyYWN0IGEgZmlsZSBwYXRoIGZyb20gYSBV
-Ukkgd2l0aCBhIHF1ZXJ5IGNvbXBvbmVudCIpKQpxPXIucgppZigocT09bnVsbD8iIjpxKSE9PSIiKXRo
-cm93IEguYihQLkw0KCJDYW5ub3QgZXh0cmFjdCBhIGZpbGUgcGF0aCBmcm9tIGEgVVJJIHdpdGggYSBm
-cmFnbWVudCBjb21wb25lbnQiKSkKdD0kLk94KCkKaWYoSC5vVCh0KSlxPVAubW4ocikKZWxzZXtpZihy
-LmMhPW51bGwmJnIuZ0pmKHIpIT09IiIpSC52aChQLkw0KCJDYW5ub3QgZXh0cmFjdCBhIG5vbi1XaW5k
-b3dzIGZpbGUgcGF0aCBmcm9tIGEgZmlsZSBVUkkgd2l0aCBhbiBhdXRob3JpdHkiKSkKcz1yLmdGaigp
-ClAua0UocywhMSkKcT1QLnZnKEMueEIubihyLmUsIi8iKT8iLyI6IiIscywiLyIpCnE9cS5jaGFyQ29k
-ZUF0KDApPT0wP3E6cX1yZXR1cm4gcX0sClo6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHE9dGhpcyxwPXEu
-eQppZihwPT1udWxsKXtwPXEuYQp0PXAubGVuZ3RoIT09MD9wKyI6IjoiIgpzPXEuYwpyPXM9PW51bGwK
-aWYoIXJ8fHA9PT0iZmlsZSIpe3A9dCsiLy8iCnQ9cS5iCmlmKHQubGVuZ3RoIT09MClwPXArdCsiQCIK
-aWYoIXIpcCs9cwp0PXEuZAppZih0IT1udWxsKXA9cCsiOiIrSC5kKHQpfWVsc2UgcD10CnArPXEuZQp0
-PXEuZgppZih0IT1udWxsKXA9cCsiPyIrdAp0PXEucgppZih0IT1udWxsKXA9cCsiIyIrdApwPXEueT1w
-LmNoYXJDb2RlQXQoMCk9PTA/cDpwfXJldHVybiBwfSwKRE46ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHI9
-dGhpcwppZihiPT1udWxsKXJldHVybiExCmlmKHI9PT1iKXJldHVybiEwCmlmKHUudy5iKGIpKWlmKHIu
-YT09Yi5nRmkoKSlpZihyLmMhPW51bGw9PT1iLmdjaigpKWlmKHIuYj09Yi5na3UoKSlpZihyLmdKZihy
-KT09Yi5nSmYoYikpaWYoci5ndHAocik9PWIuZ3RwKGIpKWlmKHIuZT09PWIuZ0lpKGIpKXt0PXIuZgpz
-PXQ9PW51bGwKaWYoIXM9PT1iLmdRRCgpKXtpZihzKXQ9IiIKaWYodD09PWIuZ3RQKCkpe3Q9ci5yCnM9
-dD09bnVsbAppZighcz09PWIuZ1o4KCkpe2lmKHMpdD0iIgp0PXQ9PT1iLmdLYSgpfWVsc2UgdD0hMX1l
-bHNlIHQ9ITF9ZWxzZSB0PSExfWVsc2UgdD0hMQplbHNlIHQ9ITEKZWxzZSB0PSExCmVsc2UgdD0hMQpl
-bHNlIHQ9ITEKZWxzZSB0PSExCmVsc2UgdD0hMQpyZXR1cm4gdH0sCmdpTzpmdW5jdGlvbihhKXt2YXIg
-dD10aGlzLnoKcmV0dXJuIHQ9PW51bGw/dGhpcy56PUMueEIuZ2lPKHRoaXMuWigwKSk6dH0sCnNvNjpm
-dW5jdGlvbihhKXt0aGlzLng9dS5hLmEoYSl9LApzUkg6ZnVuY3Rpb24oYSl7dGhpcy5RPXUuZi5hKGEp
-fSwKJGlpRDoxLApnRmk6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5hfSwKZ0lpOmZ1bmN0aW9uKGEpe3Jl
-dHVybiB0aGlzLmV9fQpQLmUxLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3Rocm93IEguYihQLnJy
-KCJJbnZhbGlkIHBvcnQiLHRoaXMuYSx0aGlzLmIrMSkpfSwKJFM6MTN9ClAuTlkucHJvdG90eXBlPXsK
-JDE6ZnVuY3Rpb24oYSl7dmFyIHQ9IklsbGVnYWwgcGF0aCBjaGFyYWN0ZXIgIgpILmMoYSkKaWYoSi56
-bChhLCIvIikpaWYodGhpcy5hKXRocm93IEguYihQLnhZKHQrYSkpCmVsc2UgdGhyb3cgSC5iKFAuTDQo
-dCthKSl9LAokUzoxM30KUC5SWi5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gUC5lUChD
-LlpKLEguYyhhKSxDLnhNLCExKX0sCiRTOjV9ClAuTUUucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxi
-KXt2YXIgdD10aGlzLmIscz10aGlzLmEKdC5hKz1zLmEKcy5hPSImIgpzPXQuYSs9SC5kKFAuZVAoQy5G
-MyxhLEMueE0sITApKQppZihiIT1udWxsJiZiLmxlbmd0aCE9PTApe3QuYT1zKyI9Igp0LmErPUguZChQ
-LmVQKEMuRjMsYixDLnhNLCEwKSl9fSwKJFM6MjJ9ClAueTUucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24o
-YSxiKXt2YXIgdCxzCkguYyhhKQppZihiPT1udWxsfHx0eXBlb2YgYj09InN0cmluZyIpdGhpcy5hLiQy
-KGEsSC5jKGIpKQplbHNlIGZvcih0PUouSVQodS5SLmEoYikpLHM9dGhpcy5hO3QuRigpOylzLiQyKGEs
-SC5jKHQuZ2woKSkpfSwKJFM6MTJ9ClAuUEUucHJvdG90eXBlPXsKZ2xSOmZ1bmN0aW9uKCl7dmFyIHQs
-cyxyLHEscD10aGlzLG89bnVsbCxuPXAuYwppZihuIT1udWxsKXJldHVybiBuCm49cC5iCmlmKDA+PW4u
-bGVuZ3RoKXJldHVybiBILmsobiwwKQp0PXAuYQpuPW5bMF0rMQpzPUMueEIuWFUodCwiPyIsbikKcj10
-Lmxlbmd0aAppZihzPj0wKXtxPVAuUEkodCxzKzEscixDLlZDLCExKQpyPXN9ZWxzZSBxPW8KcmV0dXJu
-IHAuYz1uZXcgUC5xZSgiZGF0YSIsbyxvLG8sUC5QSSh0LG4scixDLldkLCExKSxxLG8pfSwKWjpmdW5j
-dGlvbihhKXt2YXIgdCxzPXRoaXMuYgppZigwPj1zLmxlbmd0aClyZXR1cm4gSC5rKHMsMCkKdD10aGlz
-LmEKcmV0dXJuIHNbMF09PT0tMT8iZGF0YToiK3Q6dH19ClAucTMucHJvdG90eXBlPXsKJDE6ZnVuY3Rp
-b24oYSl7cmV0dXJuIG5ldyBVaW50OEFycmF5KDk2KX0sCiRTOjIzfQpQLnlJLnByb3RvdHlwZT17CiQy
-OmZ1bmN0aW9uKGEsYil7dmFyIHQ9dGhpcy5hCmlmKGE+PXQubGVuZ3RoKXJldHVybiBILmsodCxhKQp0
-PXRbYV0KSi5DTSh0LDAsOTYsYikKcmV0dXJuIHR9LAokUzoyNH0KUC5jNi5wcm90b3R5cGU9ewokMzpm
-dW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHEKZm9yKHQ9Yi5sZW5ndGgscz1hLmxlbmd0aCxyPTA7cjx0
-Oysrcil7cT1DLnhCLlcoYixyKV45NgppZihxPj1zKXJldHVybiBILmsoYSxxKQphW3FdPWN9fX0KUC5x
-ZC5wcm90b3R5cGU9ewokMzpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHEKZm9yKHQ9Qy54Qi5XKGIs
-MCkscz1DLnhCLlcoYiwxKSxyPWEubGVuZ3RoO3Q8PXM7Kyt0KXtxPSh0Xjk2KT4+PjAKaWYocT49cily
-ZXR1cm4gSC5rKGEscSkKYVtxXT1jfX19ClAuVWYucHJvdG90eXBlPXsKZ2NqOmZ1bmN0aW9uKCl7cmV0
-dXJuIHRoaXMuYz4wfSwKZ3hBOmZ1bmN0aW9uKCl7dmFyIHQscwppZih0aGlzLmM+MCl7dD10aGlzLmQK
-aWYodHlwZW9mIHQhPT0ibnVtYmVyIilyZXR1cm4gdC5oKCkKcz10aGlzLmUKaWYodHlwZW9mIHMhPT0i
-bnVtYmVyIilyZXR1cm4gSC5wWShzKQpzPXQrMTxzCnQ9c31lbHNlIHQ9ITEKcmV0dXJuIHR9LApnUUQ6
-ZnVuY3Rpb24oKXt2YXIgdD10aGlzLmYKaWYodHlwZW9mIHQhPT0ibnVtYmVyIilyZXR1cm4gdC5KKCkK
-cmV0dXJuIHQ8dGhpcy5yfSwKZ1o4OmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMucjx0aGlzLmEubGVuZ3Ro
-fSwKZ053OmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuYj09PTQmJkMueEIubih0aGlzLmEsImZpbGUiKX0s
-Cmd2aDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmI9PT00JiZDLnhCLm4odGhpcy5hLCJodHRwIil9LApn
-UmU6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5iPT09NSYmQy54Qi5uKHRoaXMuYSwiaHR0cHMiKX0sCmd0
-VDpmdW5jdGlvbigpe3JldHVybiBDLnhCLlFpKHRoaXMuYSwiLyIsdGhpcy5lKX0sCmdGaTpmdW5jdGlv
-bigpe3ZhciB0LHM9dGhpcyxyPSJwYWNrYWdlIixxPXMuYgppZihxPD0wKXJldHVybiIiCnQ9cy54Cmlm
-KHQhPW51bGwpcmV0dXJuIHQKaWYocy5ndmgoKSlxPXMueD0iaHR0cCIKZWxzZSBpZihzLmdSZSgpKXtz
-Lng9Imh0dHBzIgpxPSJodHRwcyJ9ZWxzZSBpZihzLmdOdygpKXtzLng9ImZpbGUiCnE9ImZpbGUifWVs
-c2UgaWYocT09PTcmJkMueEIubihzLmEscikpe3MueD1yCnE9cn1lbHNle3E9Qy54Qi5OaihzLmEsMCxx
-KQpzLng9cX1yZXR1cm4gcX0sCmdrdTpmdW5jdGlvbigpe3ZhciB0PXRoaXMuYyxzPXRoaXMuYiszCnJl
-dHVybiB0PnM/Qy54Qi5Oaih0aGlzLmEscyx0LTEpOiIifSwKZ0pmOmZ1bmN0aW9uKGEpe3ZhciB0PXRo
-aXMuYwpyZXR1cm4gdD4wP0MueEIuTmoodGhpcy5hLHQsdGhpcy5kKToiIn0sCmd0cDpmdW5jdGlvbihh
-KXt2YXIgdCxzPXRoaXMKaWYocy5neEEoKSl7dD1zLmQKaWYodHlwZW9mIHQhPT0ibnVtYmVyIilyZXR1
-cm4gdC5oKCkKcmV0dXJuIFAuUUEoQy54Qi5OaihzLmEsdCsxLHMuZSksbnVsbCxudWxsKX1pZihzLmd2
-aCgpKXJldHVybiA4MAppZihzLmdSZSgpKXJldHVybiA0NDMKcmV0dXJuIDB9LApnSWk6ZnVuY3Rpb24o
-YSl7cmV0dXJuIEMueEIuTmoodGhpcy5hLHRoaXMuZSx0aGlzLmYpfSwKZ3RQOmZ1bmN0aW9uKCl7dmFy
-IHQ9dGhpcy5mLHM9dGhpcy5yCmlmKHR5cGVvZiB0IT09Im51bWJlciIpcmV0dXJuIHQuSigpCnJldHVy
-biB0PHM/Qy54Qi5Oaih0aGlzLmEsdCsxLHMpOiIifSwKZ0thOmZ1bmN0aW9uKCl7dmFyIHQ9dGhpcy5y
-LHM9dGhpcy5hCnJldHVybiB0PHMubGVuZ3RoP0MueEIuRyhzLHQrMSk6IiJ9LApnRmo6ZnVuY3Rpb24o
-KXt2YXIgdCxzLHI9dGhpcy5lLHE9dGhpcy5mLHA9dGhpcy5hCmlmKEMueEIuUWkocCwiLyIscikpe2lm
-KHR5cGVvZiByIT09Im51bWJlciIpcmV0dXJuIHIuaCgpOysrcn1pZihyPT1xKXJldHVybiBDLnhECnQ9
-SC5WTShbXSx1LnMpCnM9cgp3aGlsZSghMCl7aWYodHlwZW9mIHMhPT0ibnVtYmVyIilyZXR1cm4gcy5K
-KCkKaWYodHlwZW9mIHEhPT0ibnVtYmVyIilyZXR1cm4gSC5wWShxKQppZighKHM8cSkpYnJlYWsKaWYo
-Qy54Qi5tKHAscyk9PT00Nyl7Qy5ObS5pKHQsQy54Qi5OaihwLHIscykpCnI9cysxfSsrc31DLk5tLmko
-dCxDLnhCLk5qKHAscixxKSkKcmV0dXJuIFAuQUYodCx1Lk4pfSwKZ2hZOmZ1bmN0aW9uKCl7dmFyIHQ9
-dGhpcy5mCmlmKHR5cGVvZiB0IT09Im51bWJlciIpcmV0dXJuIHQuSigpCmlmKHQ+PXRoaXMucilyZXR1
-cm4gQy5XTwpyZXR1cm4gbmV3IFAuR2ooUC5XWCh0aGlzLmd0UCgpKSx1LnYpfSwKa1g6ZnVuY3Rpb24o
-YSl7dmFyIHQscz10aGlzLmQKaWYodHlwZW9mIHMhPT0ibnVtYmVyIilyZXR1cm4gcy5oKCkKdD1zKzEK
-cmV0dXJuIHQrYS5sZW5ndGg9PT10aGlzLmUmJkMueEIuUWkodGhpcy5hLGEsdCl9LApOOTpmdW5jdGlv
-bigpe3ZhciB0PXRoaXMscz10LnIscj10LmEKaWYocz49ci5sZW5ndGgpcmV0dXJuIHQKcmV0dXJuIG5l
-dyBQLlVmKEMueEIuTmoociwwLHMpLHQuYix0LmMsdC5kLHQuZSx0LmYscyx0LngpfSwKbm06ZnVuY3Rp
-b24oYSxiKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsayxqPXRoaXMsaT1udWxsCnUuWC5hKG51bGwpCnUu
-ay5hKGIpCnQ9ai5nRmkoKQpzPXQ9PT0iZmlsZSIKcj1qLmMKcT1yPjA/Qy54Qi5OaihqLmEsai5iKzMs
-cik6IiIKcD1qLmd4QSgpP2ouZ3RwKGopOmkKcj1qLmMKaWYocj4wKW89Qy54Qi5OaihqLmEscixqLmQp
-CmVsc2Ugbz1xLmxlbmd0aCE9PTB8fHAhPW51bGx8fHM/IiI6aQpyPWouYQpuPUMueEIuTmoocixqLmUs
-ai5mKQppZighcyltPW8hPW51bGwmJm4ubGVuZ3RoIT09MAplbHNlIG09ITAKaWYobSYmIUMueEIubihu
-LCIvIikpbj0iLyIrbgpsPVAubGUoaSwwLDAsYikKbT1qLnIKaz1tPHIubGVuZ3RoP0MueEIuRyhyLG0r
-MSk6aQpyZXR1cm4gbmV3IFAuRG4odCxxLG8scCxuLGwsayl9LApaSTpmdW5jdGlvbihhKXtyZXR1cm4g
-dGhpcy5tUyhQLmhLKGEpKX0sCm1TOmZ1bmN0aW9uKGEpe2lmKGEgaW5zdGFuY2VvZiBQLlVmKXJldHVy
-biB0aGlzLnUxKHRoaXMsYSkKcmV0dXJuIHRoaXMudnMoKS5tUyhhKX0sCnUxOmZ1bmN0aW9uKGEsYil7
-dmFyIHQscyxyLHEscCxvLG4sbSxsLGssaixpLGgsZyxmLGU9Yi5iCmlmKGU+MClyZXR1cm4gYgp0PWIu
-YwppZih0PjApe3M9YS5iCmlmKHM8PTApcmV0dXJuIGIKaWYoYS5nTncoKSlyPWIuZSE9Yi5mCmVsc2Ug
-aWYoYS5ndmgoKSlyPSFiLmtYKCI4MCIpCmVsc2Ugcj0hYS5nUmUoKXx8IWIua1goIjQ0MyIpCmlmKHIp
-e3E9cysxCnA9Qy54Qi5OaihhLmEsMCxxKStDLnhCLkcoYi5hLGUrMSkKZT1iLmQKaWYodHlwZW9mIGUh
-PT0ibnVtYmVyIilyZXR1cm4gZS5oKCkKbz1iLmUKaWYodHlwZW9mIG8hPT0ibnVtYmVyIilyZXR1cm4g
-by5oKCkKbj1iLmYKaWYodHlwZW9mIG4hPT0ibnVtYmVyIilyZXR1cm4gbi5oKCkKcmV0dXJuIG5ldyBQ
-LlVmKHAscyx0K3EsZStxLG8rcSxuK3EsYi5yK3EsYS54KX1lbHNlIHJldHVybiB0aGlzLnZzKCkubVMo
-Yil9bT1iLmUKZT1iLmYKaWYobT09ZSl7dD1iLnIKaWYodHlwZW9mIGUhPT0ibnVtYmVyIilyZXR1cm4g
-ZS5KKCkKaWYoZTx0KXtzPWEuZgppZih0eXBlb2YgcyE9PSJudW1iZXIiKXJldHVybiBzLkhOKCkKcT1z
-LWUKcmV0dXJuIG5ldyBQLlVmKEMueEIuTmooYS5hLDAscykrQy54Qi5HKGIuYSxlKSxhLmIsYS5jLGEu
-ZCxhLmUsZStxLHQrcSxhLngpfWU9Yi5hCmlmKHQ8ZS5sZW5ndGgpe3M9YS5yCnJldHVybiBuZXcgUC5V
-ZihDLnhCLk5qKGEuYSwwLHMpK0MueEIuRyhlLHQpLGEuYixhLmMsYS5kLGEuZSxhLmYsdCsocy10KSxh
-LngpfXJldHVybiBhLk45KCl9dD1iLmEKaWYoQy54Qi5RaSh0LCIvIixtKSl7cz1hLmUKaWYodHlwZW9m
-IHMhPT0ibnVtYmVyIilyZXR1cm4gcy5ITigpCmlmKHR5cGVvZiBtIT09Im51bWJlciIpcmV0dXJuIEgu
-cFkobSkKcT1zLW0KcD1DLnhCLk5qKGEuYSwwLHMpK0MueEIuRyh0LG0pCmlmKHR5cGVvZiBlIT09Im51
-bWJlciIpcmV0dXJuIGUuaCgpCnJldHVybiBuZXcgUC5VZihwLGEuYixhLmMsYS5kLHMsZStxLGIucitx
-LGEueCl9bD1hLmUKaz1hLmYKaWYobD09ayYmYS5jPjApe2Zvcig7Qy54Qi5RaSh0LCIuLi8iLG0pOyl7
-aWYodHlwZW9mIG0hPT0ibnVtYmVyIilyZXR1cm4gbS5oKCkKbSs9M31pZih0eXBlb2YgbCE9PSJudW1i
-ZXIiKXJldHVybiBsLkhOKCkKaWYodHlwZW9mIG0hPT0ibnVtYmVyIilyZXR1cm4gSC5wWShtKQpxPWwt
-bSsxCnA9Qy54Qi5OaihhLmEsMCxsKSsiLyIrQy54Qi5HKHQsbSkKaWYodHlwZW9mIGUhPT0ibnVtYmVy
-IilyZXR1cm4gZS5oKCkKcmV0dXJuIG5ldyBQLlVmKHAsYS5iLGEuYyxhLmQsbCxlK3EsYi5yK3EsYS54
-KX1qPWEuYQpmb3IoaT1sO0MueEIuUWkoaiwiLi4vIixpKTspe2lmKHR5cGVvZiBpIT09Im51bWJlciIp
-cmV0dXJuIGkuaCgpCmkrPTN9aD0wCndoaWxlKCEwKXtpZih0eXBlb2YgbSE9PSJudW1iZXIiKXJldHVy
-biBtLmgoKQpnPW0rMwppZih0eXBlb2YgZSE9PSJudW1iZXIiKXJldHVybiBILnBZKGUpCmlmKCEoZzw9
-ZSYmQy54Qi5RaSh0LCIuLi8iLG0pKSlicmVhazsrK2gKbT1nfWY9IiIKd2hpbGUoITApe2lmKHR5cGVv
-ZiBrIT09Im51bWJlciIpcmV0dXJuIGsub3MoKQppZih0eXBlb2YgaSE9PSJudW1iZXIiKXJldHVybiBI
-LnBZKGkpCmlmKCEoaz5pKSlicmVhazstLWsKaWYoQy54Qi5tKGosayk9PT00Nyl7aWYoaD09PTApe2Y9
-Ii8iCmJyZWFrfS0taApmPSIvIn19aWYoaz09PWkmJmEuYjw9MCYmIUMueEIuUWkoaiwiLyIsbCkpe20t
-PWgqMwpmPSIifXE9ay1tK2YubGVuZ3RoCnJldHVybiBuZXcgUC5VZihDLnhCLk5qKGosMCxrKStmK0Mu
-eEIuRyh0LG0pLGEuYixhLmMsYS5kLGwsZStxLGIucitxLGEueCl9LAp0NDpmdW5jdGlvbigpe3ZhciB0
-LHMscixxLHA9dGhpcwppZihwLmI+PTAmJiFwLmdOdygpKXRocm93IEguYihQLkw0KCJDYW5ub3QgZXh0
-cmFjdCBhIGZpbGUgcGF0aCBmcm9tIGEgIitILmQocC5nRmkoKSkrIiBVUkkiKSkKdD1wLmYKcz1wLmEK
-aWYodHlwZW9mIHQhPT0ibnVtYmVyIilyZXR1cm4gdC5KKCkKaWYodDxzLmxlbmd0aCl7aWYodDxwLnIp
-dGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBleHRyYWN0IGEgZmlsZSBwYXRoIGZyb20gYSBVUkkgd2l0aCBh
-IHF1ZXJ5IGNvbXBvbmVudCIpKQp0aHJvdyBILmIoUC5MNCgiQ2Fubm90IGV4dHJhY3QgYSBmaWxlIHBh
-dGggZnJvbSBhIFVSSSB3aXRoIGEgZnJhZ21lbnQgY29tcG9uZW50IikpfXI9JC5PeCgpCmlmKEgub1Qo
-cikpdD1QLm1uKHApCmVsc2V7cT1wLmQKaWYodHlwZW9mIHEhPT0ibnVtYmVyIilyZXR1cm4gSC5wWShx
-KQppZihwLmM8cSlILnZoKFAuTDQoIkNhbm5vdCBleHRyYWN0IGEgbm9uLVdpbmRvd3MgZmlsZSBwYXRo
-IGZyb20gYSBmaWxlIFVSSSB3aXRoIGFuIGF1dGhvcml0eSIpKQp0PUMueEIuTmoocyxwLmUsdCl9cmV0
-dXJuIHR9LApnaU86ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy55CnJldHVybiB0PT1udWxsP3RoaXMueT1D
-LnhCLmdpTyh0aGlzLmEpOnR9LApETjpmdW5jdGlvbihhLGIpe2lmKGI9PW51bGwpcmV0dXJuITEKaWYo
-dGhpcz09PWIpcmV0dXJuITAKcmV0dXJuIHUudy5iKGIpJiZ0aGlzLmE9PT1iLlooMCl9LAp2czpmdW5j
-dGlvbigpe3ZhciB0PXRoaXMscz1udWxsLHI9dC5nRmkoKSxxPXQuZ2t1KCkscD10LmM+MD90LmdKZih0
-KTpzLG89dC5neEEoKT90Lmd0cCh0KTpzLG49dC5hLG09dC5mLGw9Qy54Qi5OaihuLHQuZSxtKSxrPXQu
-cgppZih0eXBlb2YgbSE9PSJudW1iZXIiKXJldHVybiBtLkooKQptPW08az90Lmd0UCgpOnMKcmV0dXJu
-IG5ldyBQLkRuKHIscSxwLG8sbCxtLGs8bi5sZW5ndGg/dC5nS2EoKTpzKX0sClo6ZnVuY3Rpb24oYSl7
-cmV0dXJuIHRoaXMuYX0sCiRpaUQ6MX0KUC5xZS5wcm90b3R5cGU9e30KVy5xRS5wcm90b3R5cGU9e30K
-Vy5HaC5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3JldHVybiBTdHJpbmcoYSl9LAokaUdoOjF9Clcu
-ZlkucHJvdG90eXBlPXsKWjpmdW5jdGlvbihhKXtyZXR1cm4gU3RyaW5nKGEpfX0KVy5uQi5wcm90b3R5
-cGU9eyRpbkI6MX0KVy5Bei5wcm90b3R5cGU9eyRpQXo6MX0KVy5RUC5wcm90b3R5cGU9eyRpUVA6MX0K
-Vy5ueC5wcm90b3R5cGU9ewpnQTpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9fQpXLm9KLnByb3Rv
-dHlwZT17CmdBOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH19ClcuaWQucHJvdG90eXBlPXt9Clcu
-UUYucHJvdG90eXBlPXt9ClcuTmgucHJvdG90eXBlPXsKWjpmdW5jdGlvbihhKXtyZXR1cm4gU3RyaW5n
-KGEpfX0KVy5JQi5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3JldHVybiJSZWN0YW5nbGUgKCIrSC5k
-KGEubGVmdCkrIiwgIitILmQoYS50b3ApKyIpICIrSC5kKGEud2lkdGgpKyIgeCAiK0guZChhLmhlaWdo
-dCl9LApETjpmdW5jdGlvbihhLGIpe2lmKGI9PW51bGwpcmV0dXJuITEKcmV0dXJuIHUucS5iKGIpJiZh
-LmxlZnQ9PWIubGVmdCYmYS50b3A9PWIudG9wJiZhLndpZHRoPT1iLndpZHRoJiZhLmhlaWdodD09Yi5o
-ZWlnaHR9LApnaU86ZnVuY3Rpb24oYSl7cmV0dXJuIFcuckUoSi5oZihhLmxlZnQpLEouaGYoYS50b3Ap
-LEouaGYoYS53aWR0aCksSi5oZihhLmhlaWdodCkpfSwKJGl0bjoxfQpXLm43LnByb3RvdHlwZT17CmdB
-OmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH19Clcud3oucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24o
-YSl7cmV0dXJuIHRoaXMuYS5sZW5ndGh9LApxOmZ1bmN0aW9uKGEsYil7dmFyIHQKSC5XWShiKQp0PXRo
-aXMuYQppZihiPDB8fGI+PXQubGVuZ3RoKXJldHVybiBILmsodCxiKQpyZXR1cm4gdGhpcy4kdGkuYy5h
-KHRbYl0pfSwKWTpmdW5jdGlvbihhLGIsYyl7dGhpcy4kdGkuYy5hKGMpCnRocm93IEguYihQLkw0KCJD
-YW5ub3QgbW9kaWZ5IGxpc3QiKSl9fQpXLmN2LnByb3RvdHlwZT17CmdRZzpmdW5jdGlvbihhKXtyZXR1
-cm4gbmV3IFcuaTcoYSl9LApnUDpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFcuSTQoYSl9LApzUDpmdW5j
-dGlvbihhLGIpe3ZhciB0CnUuWC5hKGIpCnQ9dGhpcy5nUChhKQp0LlYxKDApCnQuRlYoMCxiKX0sClo6
-ZnVuY3Rpb24oYSl7cmV0dXJuIGEubG9jYWxOYW1lfSwKRkY6ZnVuY3Rpb24oYSl7dmFyIHQ9ISFhLnNj
-cm9sbEludG9WaWV3SWZOZWVkZWQKaWYodClhLnNjcm9sbEludG9WaWV3SWZOZWVkZWQoKQplbHNlIGEu
-c2Nyb2xsSW50b1ZpZXcoKX0sCm56OmZ1bmN0aW9uKGEsYixjLGQsZSl7dmFyIHQscz10aGlzLnI2KGEs
-YyxkLGUpCnN3aXRjaChiLnRvTG93ZXJDYXNlKCkpe2Nhc2UiYmVmb3JlYmVnaW4iOmEucGFyZW50Tm9k
-ZS5pbnNlcnRCZWZvcmUocyxhKQpicmVhawpjYXNlImFmdGVyYmVnaW4iOnQ9YS5jaGlsZE5vZGVzCmEu
-aW5zZXJ0QmVmb3JlKHMsdC5sZW5ndGg+MD90WzBdOm51bGwpCmJyZWFrCmNhc2UiYmVmb3JlZW5kIjph
-LmFwcGVuZENoaWxkKHMpCmJyZWFrCmNhc2UiYWZ0ZXJlbmQiOmEucGFyZW50Tm9kZS5pbnNlcnRCZWZv
-cmUocyxhLm5leHRTaWJsaW5nKQpicmVhawpkZWZhdWx0OkgudmgoUC54WSgiSW52YWxpZCBwb3NpdGlv
-biAiK2IpKX19LApyNjpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzLHIscQppZihjPT1udWxsKXtpZihk
-PT1udWxsKXt0PSQubHQKaWYodD09bnVsbCl7dD1ILlZNKFtdLHUuaSkKcz1uZXcgVy52RCh0KQpDLk5t
-LmkodCxXLlR3KG51bGwpKQpDLk5tLmkodCxXLkJsKCkpCiQubHQ9cwpkPXN9ZWxzZSBkPXR9dD0kLkVV
-CmlmKHQ9PW51bGwpe3Q9bmV3IFcuS28oZCkKJC5FVT10CmM9dH1lbHNle3QuYT1kCmM9dH19ZWxzZSBp
-ZihkIT1udWxsKXRocm93IEguYihQLnhZKCJ2YWxpZGF0b3IgY2FuIG9ubHkgYmUgcGFzc2VkIGlmIHRy
-ZWVTYW5pdGl6ZXIgaXMgbnVsbCIpKQppZigkLnhvPT1udWxsKXt0PWRvY3VtZW50CnM9dC5pbXBsZW1l
-bnRhdGlvbi5jcmVhdGVIVE1MRG9jdW1lbnQoIiIpCiQueG89cwokLkJPPXMuY3JlYXRlUmFuZ2UoKQpz
-PSQueG8uY3JlYXRlRWxlbWVudCgiYmFzZSIpCnUuY1IuYShzKQpzLmhyZWY9dC5iYXNlVVJJCiQueG8u
-aGVhZC5hcHBlbmRDaGlsZChzKX10PSQueG8KaWYodC5ib2R5PT1udWxsKXtzPXQuY3JlYXRlRWxlbWVu
-dCgiYm9keSIpCnQuYm9keT11LlkuYShzKX10PSQueG8KaWYodS5ZLmIoYSkpcj10LmJvZHkKZWxzZXty
-PXQuY3JlYXRlRWxlbWVudChhLnRhZ05hbWUpCiQueG8uYm9keS5hcHBlbmRDaGlsZChyKX1pZigiY3Jl
-YXRlQ29udGV4dHVhbEZyYWdtZW50IiBpbiB3aW5kb3cuUmFuZ2UucHJvdG90eXBlJiYhQy5ObS50ZyhD
-LlNxLGEudGFnTmFtZSkpeyQuQk8uc2VsZWN0Tm9kZUNvbnRlbnRzKHIpCnE9JC5CTy5jcmVhdGVDb250
-ZXh0dWFsRnJhZ21lbnQoYil9ZWxzZXtyLmlubmVySFRNTD1iCnE9JC54by5jcmVhdGVEb2N1bWVudEZy
-YWdtZW50KCkKZm9yKDt0PXIuZmlyc3RDaGlsZCx0IT1udWxsOylxLmFwcGVuZENoaWxkKHQpfXQ9JC54
-by5ib2R5CmlmKHI9PW51bGw/dCE9bnVsbDpyIT09dClKLkx0KHIpCmMuUG4ocSkKZG9jdW1lbnQuYWRv
-cHROb2RlKHEpCnJldHVybiBxfSwKQUg6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiB0aGlzLnI2KGEsYixj
-LG51bGwpfSwKc2hmOmZ1bmN0aW9uKGEsYil7dGhpcy5ZQyhhLGIpfSwKcGs6ZnVuY3Rpb24oYSxiLGMp
-e2EudGV4dENvbnRlbnQ9bnVsbAphLmFwcGVuZENoaWxkKHRoaXMucjYoYSxiLG51bGwsYykpfSwKWUM6
-ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5wayhhLGIsbnVsbCl9LApnbnM6ZnVuY3Rpb24oYSl7cmV0
-dXJuIGEudGFnTmFtZX0sCmdWbDpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFcuZXUoYSwiY2xpY2siLCEx
-LHUuUSl9LAokaWN2OjF9ClcuQ3YucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIHUuaC5i
-KHUuQS5hKGEpKX0sCiRTOjI1fQpXLmVhLnByb3RvdHlwZT17JGllYToxfQpXLkQwLnByb3RvdHlwZT17
-Ck9uOmZ1bmN0aW9uKGEsYixjLGQpe3UuVS5hKGMpCmlmKGMhPW51bGwpdGhpcy52KGEsYixjLGQpfSwK
-QjpmdW5jdGlvbihhLGIsYyl7cmV0dXJuIHRoaXMuT24oYSxiLGMsbnVsbCl9LAp2OmZ1bmN0aW9uKGEs
-YixjLGQpe3JldHVybiBhLmFkZEV2ZW50TGlzdGVuZXIoYixILnRSKHUuVS5hKGMpLDEpLGQpfSwKJGlE
-MDoxfQpXLmhILnByb3RvdHlwZT17JGloSDoxfQpXLmg0LnByb3RvdHlwZT17CmdBOmZ1bmN0aW9uKGEp
-e3JldHVybiBhLmxlbmd0aH19ClcuYnIucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIGEu
-bGVuZ3RofX0KVy5WYi5wcm90b3R5cGU9e30KVy5mSi5wcm90b3R5cGU9ewplbzpmdW5jdGlvbihhLGIs
-YyxkKXtyZXR1cm4gYS5vcGVuKGIsYywhMCl9LAokaWZKOjF9Clcud2EucHJvdG90eXBlPXt9ClcuU2cu
-cHJvdG90eXBlPXskaVNnOjF9ClcudTgucHJvdG90eXBlPXsKZ0RyOmZ1bmN0aW9uKGEpe2lmKCJvcmln
-aW4iIGluIGEpcmV0dXJuIGEub3JpZ2luCnJldHVybiBILmQoYS5wcm90b2NvbCkrIi8vIitILmQoYS5o
-b3N0KX0sClo6ZnVuY3Rpb24oYSl7cmV0dXJuIFN0cmluZyhhKX0sCiRpdTg6MX0KVy5PSy5wcm90b3R5
-cGU9eyRpT0s6MX0KVy5lNy5wcm90b3R5cGU9ewpncjg6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5hLHM9
-dC5jaGlsZE5vZGVzLmxlbmd0aAppZihzPT09MCl0aHJvdyBILmIoUC5QVigiTm8gZWxlbWVudHMiKSkK
-aWYocz4xKXRocm93IEguYihQLlBWKCJNb3JlIHRoYW4gb25lIGVsZW1lbnQiKSkKcmV0dXJuIHQuZmly
-c3RDaGlsZH0sCkZWOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEKdS5laC5hKGIpCnQ9Yi5hCnM9dGhp
-cy5hCmlmKHQhPT1zKWZvcihyPXQuY2hpbGROb2Rlcy5sZW5ndGgscT0wO3E8cjsrK3Epcy5hcHBlbmRD
-aGlsZCh0LmZpcnN0Q2hpbGQpCnJldHVybn0sClk6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMKdS5BLmEo
-YykKdD10aGlzLmEKcz10LmNoaWxkTm9kZXMKaWYoYjwwfHxiPj1zLmxlbmd0aClyZXR1cm4gSC5rKHMs
-YikKdC5yZXBsYWNlQ2hpbGQoYyxzW2JdKX0sCmdrejpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmEuY2hp
-bGROb2RlcwpyZXR1cm4gbmV3IFcuVzkodCx0Lmxlbmd0aCxILnEodCkuQygiVzk8R20uRT4iKSl9LApn
-QTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hLmNoaWxkTm9kZXMubGVuZ3RofSwKcTpmdW5jdGlvbihh
-LGIpe3ZhciB0CkguV1koYikKdD10aGlzLmEuY2hpbGROb2RlcwppZihiPDB8fGI+PXQubGVuZ3RoKXJl
-dHVybiBILmsodCxiKQpyZXR1cm4gdFtiXX19ClcudUgucHJvdG90eXBlPXsKd2c6ZnVuY3Rpb24oYSl7
-dmFyIHQ9YS5wYXJlbnROb2RlCmlmKHQhPW51bGwpdC5yZW1vdmVDaGlsZChhKX0sCkQ0OmZ1bmN0aW9u
-KGEpe3ZhciB0CmZvcig7dD1hLmZpcnN0Q2hpbGQsdCE9bnVsbDspYS5yZW1vdmVDaGlsZCh0KX0sClo6
-ZnVuY3Rpb24oYSl7dmFyIHQ9YS5ub2RlVmFsdWUKcmV0dXJuIHQ9PW51bGw/dGhpcy5VKGEpOnR9LAok
-aXVIOjF9ClcuQkgucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofSwKcTpm
-dW5jdGlvbihhLGIpe0guV1koYikKaWYoYj4+PjAhPT1ifHxiPj1hLmxlbmd0aCl0aHJvdyBILmIoUC50
-KGIsYSxudWxsLG51bGwsbnVsbCkpCnJldHVybiBhW2JdfSwKWTpmdW5jdGlvbihhLGIsYyl7dS5BLmEo
-YykKdGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBhc3NpZ24gZWxlbWVudCBvZiBpbW11dGFibGUgTGlzdC4i
-KSl9LApndEg6ZnVuY3Rpb24oYSl7aWYoYS5sZW5ndGg+MClyZXR1cm4gYVswXQp0aHJvdyBILmIoUC5Q
-VigiTm8gZWxlbWVudHMiKSl9LApFOmZ1bmN0aW9uKGEsYil7aWYoYjwwfHxiPj1hLmxlbmd0aClyZXR1
-cm4gSC5rKGEsYikKcmV0dXJuIGFbYl19LAokaWJROjEsCiRpWGo6MSwKJGljWDoxLAokaXpNOjF9Clcu
-U04ucHJvdG90eXBlPXt9ClcuZXcucHJvdG90eXBlPXskaWV3OjF9ClcubHAucHJvdG90eXBlPXsKZ0E6
-ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofX0KVy5UYi5wcm90b3R5cGU9ewpyNjpmdW5jdGlvbihh
-LGIsYyxkKXt2YXIgdCxzCmlmKCJjcmVhdGVDb250ZXh0dWFsRnJhZ21lbnQiIGluIHdpbmRvdy5SYW5n
-ZS5wcm90b3R5cGUpcmV0dXJuIHRoaXMuRFcoYSxiLGMsZCkKdD1XLlU5KCI8dGFibGU+IitILmQoYikr
-IjwvdGFibGU+IixjLGQpCnM9ZG9jdW1lbnQuY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgpCnMudG9TdHJp
-bmcKdC50b1N0cmluZwpuZXcgVy5lNyhzKS5GVigwLG5ldyBXLmU3KHQpKQpyZXR1cm4gc319ClcuSXYu
-cHJvdG90eXBlPXsKcjY6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscyxyLHEKaWYoImNyZWF0ZUNvbnRl
-eHR1YWxGcmFnbWVudCIgaW4gd2luZG93LlJhbmdlLnByb3RvdHlwZSlyZXR1cm4gdGhpcy5EVyhhLGIs
-YyxkKQp0PWRvY3VtZW50CnM9dC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCkKdD1DLkllLnI2KHQuY3Jl
-YXRlRWxlbWVudCgidGFibGUiKSxiLGMsZCkKdC50b1N0cmluZwp0PW5ldyBXLmU3KHQpCnI9dC5ncjgo
-dCkKci50b1N0cmluZwp0PW5ldyBXLmU3KHIpCnE9dC5ncjgodCkKcy50b1N0cmluZwpxLnRvU3RyaW5n
-Cm5ldyBXLmU3KHMpLkZWKDAsbmV3IFcuZTcocSkpCnJldHVybiBzfX0KVy5XUC5wcm90b3R5cGU9ewpy
-NjpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzLHIKaWYoImNyZWF0ZUNvbnRleHR1YWxGcmFnbWVudCIg
-aW4gd2luZG93LlJhbmdlLnByb3RvdHlwZSlyZXR1cm4gdGhpcy5EVyhhLGIsYyxkKQp0PWRvY3VtZW50
-CnM9dC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCkKdD1DLkllLnI2KHQuY3JlYXRlRWxlbWVudCgidGFi
-bGUiKSxiLGMsZCkKdC50b1N0cmluZwp0PW5ldyBXLmU3KHQpCnI9dC5ncjgodCkKcy50b1N0cmluZwpy
-LnRvU3RyaW5nCm5ldyBXLmU3KHMpLkZWKDAsbmV3IFcuZTcocikpCnJldHVybiBzfX0KVy55WS5wcm90
-b3R5cGU9ewpwazpmdW5jdGlvbihhLGIsYyl7dmFyIHQscwphLnRleHRDb250ZW50PW51bGwKdD1hLmNv
-bnRlbnQKdC50b1N0cmluZwpKLmJUKHQpCnM9dGhpcy5yNihhLGIsbnVsbCxjKQphLmNvbnRlbnQuYXBw
-ZW5kQ2hpbGQocyl9LApZQzpmdW5jdGlvbihhLGIpe3JldHVybiB0aGlzLnBrKGEsYixudWxsKX0sCiRp
-eVk6MX0KVy53Ni5wcm90b3R5cGU9e30KVy5LNS5wcm90b3R5cGU9ewpQbzpmdW5jdGlvbihhLGIsYyl7
-dmFyIHQ9Vy5QMShhLm9wZW4oYixjKSkKcmV0dXJuIHR9LApnbVc6ZnVuY3Rpb24oYSl7cmV0dXJuIGEu
-bG9jYXRpb259LAokaUs1OjEsCiRpdjY6MX0KVy5DbS5wcm90b3R5cGU9eyRpQ206MX0KVy5DUS5wcm90
-b3R5cGU9eyRpQ1E6MX0KVy53NC5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3JldHVybiJSZWN0YW5n
-bGUgKCIrSC5kKGEubGVmdCkrIiwgIitILmQoYS50b3ApKyIpICIrSC5kKGEud2lkdGgpKyIgeCAiK0gu
-ZChhLmhlaWdodCl9LApETjpmdW5jdGlvbihhLGIpe2lmKGI9PW51bGwpcmV0dXJuITEKcmV0dXJuIHUu
-cS5iKGIpJiZhLmxlZnQ9PWIubGVmdCYmYS50b3A9PWIudG9wJiZhLndpZHRoPT1iLndpZHRoJiZhLmhl
-aWdodD09Yi5oZWlnaHR9LApnaU86ZnVuY3Rpb24oYSl7cmV0dXJuIFcuckUoSi5oZihhLmxlZnQpLEou
-aGYoYS50b3ApLEouaGYoYS53aWR0aCksSi5oZihhLmhlaWdodCkpfX0KVy5yaC5wcm90b3R5cGU9ewpn
-QTpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9LApxOmZ1bmN0aW9uKGEsYil7SC5XWShiKQppZihi
-Pj4+MCE9PWJ8fGI+PWEubGVuZ3RoKXRocm93IEguYihQLnQoYixhLG51bGwsbnVsbCxudWxsKSkKcmV0
-dXJuIGFbYl19LApZOmZ1bmN0aW9uKGEsYixjKXt1LkEuYShjKQp0aHJvdyBILmIoUC5MNCgiQ2Fubm90
-IGFzc2lnbiBlbGVtZW50IG9mIGltbXV0YWJsZSBMaXN0LiIpKX0sCkU6ZnVuY3Rpb24oYSxiKXtpZihi
-PDB8fGI+PWEubGVuZ3RoKXJldHVybiBILmsoYSxiKQpyZXR1cm4gYVtiXX0sCiRpYlE6MSwKJGlYajox
-LAokaWNYOjEsCiRpek06MX0KVy5jZi5wcm90b3R5cGU9ewpLOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxy
-LHEscAp1LmVBLmEoYikKZm9yKHQ9dGhpcy5nVigpLHM9dC5sZW5ndGgscj10aGlzLmEscT0wO3E8dC5s
-ZW5ndGg7dC5sZW5ndGg9PT1zfHwoMCxILmxrKSh0KSwrK3Epe3A9dFtxXQpiLiQyKHAsci5nZXRBdHRy
-aWJ1dGUocCkpfX0sCmdWOmZ1bmN0aW9uKCl7dmFyIHQscyxyLHEscD10aGlzLmEuYXR0cmlidXRlcyxv
-PUguVk0oW10sdS5zKQpmb3IodD1wLmxlbmd0aCxzPXUuaDkscj0wO3I8dDsrK3Ipe2lmKHI+PXAubGVu
-Z3RoKXJldHVybiBILmsocCxyKQpxPXMuYShwW3JdKQppZihxLm5hbWVzcGFjZVVSST09bnVsbClDLk5t
-LmkobyxxLm5hbWUpfXJldHVybiBvfSwKZ2wwOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmdWKCkubGVu
-Z3RoPT09MH19ClcuaTcucHJvdG90eXBlPXsKeDQ6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYS5oYXNB
-dHRyaWJ1dGUoYSl9LApxOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuYS5nZXRBdHRyaWJ1dGUoSC5j
-KGIpKX0sClk6ZnVuY3Rpb24oYSxiLGMpe3RoaXMuYS5zZXRBdHRyaWJ1dGUoYixjKX0sCmdBOmZ1bmN0
-aW9uKGEpe3JldHVybiB0aGlzLmdWKCkubGVuZ3RofX0KVy5TeS5wcm90b3R5cGU9ewp4NDpmdW5jdGlv
-bihhKXtyZXR1cm4gdGhpcy5hLmEuaGFzQXR0cmlidXRlKCJkYXRhLSIrdGhpcy5PKGEpKX0sCnE6ZnVu
-Y3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5hLmEuZ2V0QXR0cmlidXRlKCJkYXRhLSIrdGhpcy5PKEguYyhi
-KSkpfSwKWTpmdW5jdGlvbihhLGIsYyl7dGhpcy5hLmEuc2V0QXR0cmlidXRlKCJkYXRhLSIrdGhpcy5P
-KGIpLGMpfSwKSzpmdW5jdGlvbihhLGIpe3RoaXMuYS5LKDAsbmV3IFcuS1ModGhpcyx1LmVBLmEoYikp
-KX0sCmdWOmZ1bmN0aW9uKCl7dmFyIHQ9SC5WTShbXSx1LnMpCnRoaXMuYS5LKDAsbmV3IFcuQTModGhp
-cyx0KSkKcmV0dXJuIHR9LApnQTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5nVigpLmxlbmd0aH0sCmds
-MDpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5nVigpLmxlbmd0aD09PTB9LAprOmZ1bmN0aW9uKGEpe3Zh
-ciB0LHMscj1ILlZNKGEuc3BsaXQoIi0iKSx1LnMpCmZvcih0PTE7dDxyLmxlbmd0aDsrK3Qpe3M9clt0
-XQppZihzLmxlbmd0aD4wKUMuTm0uWShyLHQsc1swXS50b1VwcGVyQ2FzZSgpK0ouS1YocywxKSl9cmV0
-dXJuIEMuTm0uSChyLCIiKX0sCk86ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscApmb3IodD1hLmxlbmd0
-aCxzPTAscj0iIjtzPHQ7KytzKXtxPWFbc10KcD1xLnRvTG93ZXJDYXNlKCkKcj0ocSE9PXAmJnM+MD9y
-KyItIjpyKStwfXJldHVybiByLmNoYXJDb2RlQXQoMCk9PTA/cjpyfX0KVy5LUy5wcm90b3R5cGU9ewok
-MjpmdW5jdGlvbihhLGIpe2lmKEouclkoYSkubihhLCJkYXRhLSIpKXRoaXMuYi4kMih0aGlzLmEuayhD
-LnhCLkcoYSw1KSksYil9LAokUzoxNH0KVy5BMy5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe2lm
-KEouclkoYSkubihhLCJkYXRhLSIpKUMuTm0uaSh0aGlzLmIsdGhpcy5hLmsoQy54Qi5HKGEsNSkpKX0s
-CiRTOjE0fQpXLkk0LnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oKXt2YXIgdCxzLHIscSxwPVAuTHModS5O
-KQpmb3IodD10aGlzLmEuY2xhc3NOYW1lLnNwbGl0KCIgIikscz10Lmxlbmd0aCxyPTA7cjxzOysrcil7
-cT1KLlQwKHRbcl0pCmlmKHEubGVuZ3RoIT09MClwLmkoMCxxKX1yZXR1cm4gcH0sClg6ZnVuY3Rpb24o
-YSl7dGhpcy5hLmNsYXNzTmFtZT11LkMuYShhKS5IKDAsIiAiKX0sCmdBOmZ1bmN0aW9uKGEpe3JldHVy
-biB0aGlzLmEuY2xhc3NMaXN0Lmxlbmd0aH0sClYxOmZ1bmN0aW9uKGEpe3RoaXMuYS5jbGFzc05hbWU9
-IiJ9LAp0ZzpmdW5jdGlvbihhLGIpe3ZhciB0PXRoaXMuYS5jbGFzc0xpc3QuY29udGFpbnMoYikKcmV0
-dXJuIHR9LAppOmZ1bmN0aW9uKGEsYil7dmFyIHQ9dGhpcy5hLmNsYXNzTGlzdCxzPXQuY29udGFpbnMo
-YikKdC5hZGQoYikKcmV0dXJuIXN9LApSOmZ1bmN0aW9uKGEsYil7dmFyIHQ9dGhpcy5hLmNsYXNzTGlz
-dCxzPXQuY29udGFpbnMoYikKdC5yZW1vdmUoYikKcmV0dXJuIHN9LApGVjpmdW5jdGlvbihhLGIpe1cu
-VE4odGhpcy5hLHUuWC5hKGIpKX19ClcuRmsucHJvdG90eXBlPXt9ClcuUk8ucHJvdG90eXBlPXt9Clcu
-ZXUucHJvdG90eXBlPXt9ClcueEMucHJvdG90eXBlPXt9Clcudk4ucHJvdG90eXBlPXsKJDE6ZnVuY3Rp
-b24oYSl7cmV0dXJuIHRoaXMuYS4kMSh1LkIuYShhKSl9LAokUzoyN30KVy5KUS5wcm90b3R5cGU9ewpD
-WTpmdW5jdGlvbihhKXt2YXIgdAppZigkLm9yLmE9PT0wKXtmb3IodD0wO3Q8MjYyOysrdCkkLm9yLlko
-MCxDLmNtW3RdLFcucFMoKSkKZm9yKHQ9MDt0PDEyOysrdCkkLm9yLlkoMCxDLkJJW3RdLFcuVjQoKSl9
-fSwKaTA6ZnVuY3Rpb24oYSl7cmV0dXJuICQuQU4oKS50ZygwLFcuclMoYSkpfSwKRWI6ZnVuY3Rpb24o
-YSxiLGMpe3ZhciB0PSQub3IucSgwLEguZChXLnJTKGEpKSsiOjoiK2IpCmlmKHQ9PW51bGwpdD0kLm9y
-LnEoMCwiKjo6IitiKQppZih0PT1udWxsKXJldHVybiExCnJldHVybiBILkU5KHQuJDQoYSxiLGMsdGhp
-cykpfSwKJGlrRjoxfQpXLkdtLnByb3RvdHlwZT17CmdrejpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFcu
-VzkoYSx0aGlzLmdBKGEpLEgucShhKS5DKCJXOTxHbS5FPiIpKX19ClcudkQucHJvdG90eXBlPXsKaTA6
-ZnVuY3Rpb24oYSl7cmV0dXJuIEMuTm0uVnIodGhpcy5hLG5ldyBXLlV2KGEpKX0sCkViOmZ1bmN0aW9u
-KGEsYixjKXtyZXR1cm4gQy5ObS5Wcih0aGlzLmEsbmV3IFcuRWcoYSxiLGMpKX0sCiRpa0Y6MX0KVy5V
-di5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gdS5lLmEoYSkuaTAodGhpcy5hKX0sCiRT
-OjE1fQpXLkVnLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiB1LmUuYShhKS5FYih0aGlz
-LmEsdGhpcy5iLHRoaXMuYyl9LAokUzoxNX0KVy5tNi5wcm90b3R5cGU9ewpDWTpmdW5jdGlvbihhLGIs
-YyxkKXt2YXIgdCxzLHIKdGhpcy5hLkZWKDAsYykKdD1iLmV2KDAsbmV3IFcuRW8oKSkKcz1iLmV2KDAs
-bmV3IFcuV2soKSkKdGhpcy5iLkZWKDAsdCkKcj10aGlzLmMKci5GVigwLEMueEQpCnIuRlYoMCxzKX0s
-CmkwOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEudGcoMCxXLnJTKGEpKX0sCkViOmZ1bmN0aW9uKGEs
-YixjKXt2YXIgdD10aGlzLHM9Vy5yUyhhKSxyPXQuYwppZihyLnRnKDAsSC5kKHMpKyI6OiIrYikpcmV0
-dXJuIHQuZC5EdChjKQplbHNlIGlmKHIudGcoMCwiKjo6IitiKSlyZXR1cm4gdC5kLkR0KGMpCmVsc2V7
-cj10LmIKaWYoci50ZygwLEguZChzKSsiOjoiK2IpKXJldHVybiEwCmVsc2UgaWYoci50ZygwLCIqOjoi
-K2IpKXJldHVybiEwCmVsc2UgaWYoci50ZygwLEguZChzKSsiOjoqIikpcmV0dXJuITAKZWxzZSBpZihy
-LnRnKDAsIio6OioiKSlyZXR1cm4hMH1yZXR1cm4hMX0sCiRpa0Y6MX0KVy5Fby5wcm90b3R5cGU9ewok
-MTpmdW5jdGlvbihhKXtyZXR1cm4hQy5ObS50ZyhDLkJJLEguYyhhKSl9LAokUzo3fQpXLldrLnByb3Rv
-dHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiBDLk5tLnRnKEMuQkksSC5jKGEpKX0sCiRTOjd9Clcu
-Y3QucHJvdG90eXBlPXsKRWI6ZnVuY3Rpb24oYSxiLGMpe2lmKHRoaXMuakYoYSxiLGMpKXJldHVybiEw
-CmlmKGI9PT0idGVtcGxhdGUiJiZjPT09IiIpcmV0dXJuITAKaWYoYS5nZXRBdHRyaWJ1dGUoInRlbXBs
-YXRlIik9PT0iIilyZXR1cm4gdGhpcy5lLnRnKDAsYikKcmV0dXJuITF9fQpXLklBLnByb3RvdHlwZT17
-CiQxOmZ1bmN0aW9uKGEpe3JldHVybiJURU1QTEFURTo6IitILmQoSC5jKGEpKX0sCiRTOjV9ClcuT3cu
-cHJvdG90eXBlPXsKaTA6ZnVuY3Rpb24oYSl7dmFyIHQKaWYodS5hTy5iKGEpKXJldHVybiExCnQ9dS5n
-Ny5iKGEpCmlmKHQmJlcuclMoYSk9PT0iZm9yZWlnbk9iamVjdCIpcmV0dXJuITEKaWYodClyZXR1cm4h
-MApyZXR1cm4hMX0sCkViOmZ1bmN0aW9uKGEsYixjKXtpZihiPT09ImlzInx8Qy54Qi5uKGIsIm9uIikp
-cmV0dXJuITEKcmV0dXJuIHRoaXMuaTAoYSl9LAokaWtGOjF9ClcuVzkucHJvdG90eXBlPXsKRjpmdW5j
-dGlvbigpe3ZhciB0PXRoaXMscz10LmMrMSxyPXQuYgppZihzPHIpe3Quc3AoSi54OSh0LmEscykpCnQu
-Yz1zCnJldHVybiEwfXQuc3AobnVsbCkKdC5jPXIKcmV0dXJuITF9LApnbDpmdW5jdGlvbigpe3JldHVy
-biB0aGlzLmR9LApzcDpmdW5jdGlvbihhKXt0aGlzLmQ9dGhpcy4kdGkuYy5hKGEpfSwKJGlBbjoxfQpX
-LmRXLnByb3RvdHlwZT17CmdtVzpmdW5jdGlvbihhKXtyZXR1cm4gVy5ISCh0aGlzLmEubG9jYXRpb24p
-fSwKJGlEMDoxLAokaXY2OjF9ClcuRmIucHJvdG90eXBlPXt9Clcua0YucHJvdG90eXBlPXt9ClcubWsu
-cHJvdG90eXBlPXskaXkwOjF9ClcuS28ucHJvdG90eXBlPXsKUG46ZnVuY3Rpb24oYSl7dmFyIHQ9dGhp
-cyxzPW5ldyBXLmZtKHQpCnQuYj0hMQpzLiQyKGEsbnVsbCkKZm9yKDt0LmI7KXt0LmI9ITEKcy4kMihh
-LG51bGwpfX0sCkVQOmZ1bmN0aW9uKGEsYil7dmFyIHQ9dGhpcy5iPSEwCmlmKGIhPW51bGw/YiE9PWEu
-cGFyZW50Tm9kZTp0KUouTHQoYSkKZWxzZSBiLnJlbW92ZUNoaWxkKGEpfSwKSTQ6ZnVuY3Rpb24oYSxi
-KXt2YXIgdCxzLHIscSxwLG89ITAsbj1udWxsLG09bnVsbAp0cnl7bj1KLmlnKGEpCm09bi5hLmdldEF0
-dHJpYnV0ZSgiaXMiKQp1LmguYShhKQp0PWZ1bmN0aW9uKGMpe2lmKCEoYy5hdHRyaWJ1dGVzIGluc3Rh
-bmNlb2YgTmFtZWROb2RlTWFwKSlyZXR1cm4gdHJ1ZQppZihjLmlkPT0nbGFzdENoaWxkJ3x8Yy5uYW1l
-PT0nbGFzdENoaWxkJ3x8Yy5pZD09J3ByZXZpb3VzU2libGluZyd8fGMubmFtZT09J3ByZXZpb3VzU2li
-bGluZyd8fGMuaWQ9PSdjaGlsZHJlbid8fGMubmFtZT09J2NoaWxkcmVuJylyZXR1cm4gdHJ1ZQp2YXIg
-bD1jLmNoaWxkTm9kZXMKaWYoYy5sYXN0Q2hpbGQmJmMubGFzdENoaWxkIT09bFtsLmxlbmd0aC0xXSly
-ZXR1cm4gdHJ1ZQppZihjLmNoaWxkcmVuKWlmKCEoYy5jaGlsZHJlbiBpbnN0YW5jZW9mIEhUTUxDb2xs
-ZWN0aW9ufHxjLmNoaWxkcmVuIGluc3RhbmNlb2YgTm9kZUxpc3QpKXJldHVybiB0cnVlCnZhciBrPTAK
-aWYoYy5jaGlsZHJlbilrPWMuY2hpbGRyZW4ubGVuZ3RoCmZvcih2YXIgaj0wO2o8aztqKyspe3ZhciBp
-PWMuY2hpbGRyZW5bal0KaWYoaS5pZD09J2F0dHJpYnV0ZXMnfHxpLm5hbWU9PSdhdHRyaWJ1dGVzJ3x8
-aS5pZD09J2xhc3RDaGlsZCd8fGkubmFtZT09J2xhc3RDaGlsZCd8fGkuaWQ9PSdwcmV2aW91c1NpYmxp
-bmcnfHxpLm5hbWU9PSdwcmV2aW91c1NpYmxpbmcnfHxpLmlkPT0nY2hpbGRyZW4nfHxpLm5hbWU9PSdj
-aGlsZHJlbicpcmV0dXJuIHRydWV9cmV0dXJuIGZhbHNlfShhKQpvPUgub1QodCk/ITA6IShhLmF0dHJp
-YnV0ZXMgaW5zdGFuY2VvZiBOYW1lZE5vZGVNYXApfWNhdGNoKHEpe0guUnUocSl9cz0iZWxlbWVudCB1
-bnByaW50YWJsZSIKdHJ5e3M9Si5BYyhhKX1jYXRjaChxKXtILlJ1KHEpfXRyeXtyPVcuclMoYSkKdGhp
-cy5rUih1LmguYShhKSxiLG8scyxyLHUuRy5hKG4pLEguYyhtKSl9Y2F0Y2gocSl7aWYoSC5SdShxKSBp
-bnN0YW5jZW9mIFAuQVQpdGhyb3cgcQplbHNle3RoaXMuRVAoYSxiKQp3aW5kb3cKcD0iUmVtb3Zpbmcg
-Y29ycnVwdGVkIGVsZW1lbnQgIitILmQocykKaWYodHlwZW9mIGNvbnNvbGUhPSJ1bmRlZmluZWQiKXdp
-bmRvdy5jb25zb2xlLndhcm4ocCl9fX0sCmtSOmZ1bmN0aW9uKGEsYixjLGQsZSxmLGcpe3ZhciB0LHMs
-cixxLHAsbyxuPXRoaXMKaWYoYyl7bi5FUChhLGIpCndpbmRvdwp0PSJSZW1vdmluZyBlbGVtZW50IGR1
-ZSB0byBjb3JydXB0ZWQgYXR0cmlidXRlcyBvbiA8IitkKyI+IgppZih0eXBlb2YgY29uc29sZSE9InVu
-ZGVmaW5lZCIpd2luZG93LmNvbnNvbGUud2Fybih0KQpyZXR1cm59aWYoIW4uYS5pMChhKSl7bi5FUChh
-LGIpCndpbmRvdwp0PSJSZW1vdmluZyBkaXNhbGxvd2VkIGVsZW1lbnQgPCIrSC5kKGUpKyI+IGZyb20g
-IitILmQoYikKaWYodHlwZW9mIGNvbnNvbGUhPSJ1bmRlZmluZWQiKXdpbmRvdy5jb25zb2xlLndhcm4o
-dCkKcmV0dXJufWlmKGchPW51bGwpaWYoIW4uYS5FYihhLCJpcyIsZykpe24uRVAoYSxiKQp3aW5kb3cK
-dD0iUmVtb3ZpbmcgZGlzYWxsb3dlZCB0eXBlIGV4dGVuc2lvbiA8IitILmQoZSkrJyBpcz0iJytnKyci
-PicKaWYodHlwZW9mIGNvbnNvbGUhPSJ1bmRlZmluZWQiKXdpbmRvdy5jb25zb2xlLndhcm4odCkKcmV0
-dXJufXQ9Zi5nVigpCnM9SC5WTSh0LnNsaWNlKDApLEgudDYodCkuQygiamQ8MT4iKSkKZm9yKHI9Zi5n
-VigpLmxlbmd0aC0xLHQ9Zi5hO3I+PTA7LS1yKXtpZihyPj1zLmxlbmd0aClyZXR1cm4gSC5rKHMscikK
-cT1zW3JdCnA9bi5hCm89Si5jSChxKQpILmMocSkKaWYoIXAuRWIoYSxvLHQuZ2V0QXR0cmlidXRlKHEp
-KSl7d2luZG93CnA9IlJlbW92aW5nIGRpc2FsbG93ZWQgYXR0cmlidXRlIDwiK0guZChlKSsiICIrcSsn
-PSInK0guZCh0LmdldEF0dHJpYnV0ZShxKSkrJyI+JwppZih0eXBlb2YgY29uc29sZSE9InVuZGVmaW5l
-ZCIpd2luZG93LmNvbnNvbGUud2FybihwKQp0LnJlbW92ZUF0dHJpYnV0ZShxKX19aWYodS5hVy5iKGEp
-KW4uUG4oYS5jb250ZW50KX0sCiRpb246MX0KVy5mbS5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIp
-e3ZhciB0LHMscixxLHAsbyxuPXRoaXMuYQpzd2l0Y2goYS5ub2RlVHlwZSl7Y2FzZSAxOm4uSTQoYSxi
-KQpicmVhawpjYXNlIDg6Y2FzZSAxMTpjYXNlIDM6Y2FzZSA0OmJyZWFrCmRlZmF1bHQ6bi5FUChhLGIp
-fXQ9YS5sYXN0Q2hpbGQKZm9yKHI9dS5BO251bGwhPXQ7KXtzPW51bGwKdHJ5e3M9dC5wcmV2aW91c1Np
-YmxpbmcKaWYocyE9bnVsbCl7cT1zLm5leHRTaWJsaW5nCnA9dApwPXE9PW51bGw/cCE9bnVsbDpxIT09
-cApxPXB9ZWxzZSBxPSExCmlmKHEpe3E9UC5QVigiQ29ycnVwdCBIVE1MIikKdGhyb3cgSC5iKHEpfX1j
-YXRjaChvKXtILlJ1KG8pCnE9ci5hKHQpCm4uYj0hMApwPXEucGFyZW50Tm9kZQpwPWE9PW51bGw/cCE9
-bnVsbDphIT09cAppZihwKXtwPXEucGFyZW50Tm9kZQppZihwIT1udWxsKXAucmVtb3ZlQ2hpbGQocSl9
-ZWxzZSBhLnJlbW92ZUNoaWxkKHEpCnQ9bnVsbApzPWEubGFzdENoaWxkfWlmKHQhPW51bGwpdGhpcy4k
-Mih0LGEpCnQ9c319LAokUzozMH0KVy5MZS5wcm90b3R5cGU9e30KVy5LNy5wcm90b3R5cGU9e30KVy5y
-Qi5wcm90b3R5cGU9e30KVy5YVy5wcm90b3R5cGU9e30KVy5vYS5wcm90b3R5cGU9e30KUC5pSi5wcm90
-b3R5cGU9ewpWSDpmdW5jdGlvbihhKXt2YXIgdCxzPXRoaXMuYSxyPXMubGVuZ3RoCmZvcih0PTA7dDxy
-OysrdClpZihzW3RdPT09YSlyZXR1cm4gdApDLk5tLmkocyxhKQpDLk5tLmkodGhpcy5iLG51bGwpCnJl
-dHVybiByfSwKUHY6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHE9dGhpcyxwPXt9CmlmKGE9PW51bGwpcmV0
-dXJuIGEKaWYoSC5yUShhKSlyZXR1cm4gYQppZih0eXBlb2YgYT09Im51bWJlciIpcmV0dXJuIGEKaWYo
-dHlwZW9mIGE9PSJzdHJpbmciKXJldHVybiBhCmlmKGEgaW5zdGFuY2VvZiBQLmlQKXJldHVybiBuZXcg
-RGF0ZShhLmEpCmlmKHUuZnYuYihhKSl0aHJvdyBILmIoUC5uKCJzdHJ1Y3R1cmVkIGNsb25lIG9mIFJl
-Z0V4cCIpKQppZih1LmM4LmIoYSkpcmV0dXJuIGEKaWYodS5kLmIoYSkpcmV0dXJuIGEKaWYodS5JLmIo
-YSkpcmV0dXJuIGEKdD11LmRELmIoYSl8fCExCmlmKHQpcmV0dXJuIGEKaWYodS5HLmIoYSkpe3M9cS5W
-SChhKQp0PXEuYgppZihzPj10Lmxlbmd0aClyZXR1cm4gSC5rKHQscykKcj1wLmE9dFtzXQppZihyIT1u
-dWxsKXJldHVybiByCnI9e30KcC5hPXIKQy5ObS5ZKHQscyxyKQphLksoMCxuZXcgUC5qZyhwLHEpKQpy
-ZXR1cm4gcC5hfWlmKHUuai5iKGEpKXtzPXEuVkgoYSkKcD1xLmIKaWYocz49cC5sZW5ndGgpcmV0dXJu
-IEguayhwLHMpCnI9cFtzXQppZihyIT1udWxsKXJldHVybiByCnJldHVybiBxLmVrKGEscyl9aWYodS5l
-SC5iKGEpKXtzPXEuVkgoYSkKdD1xLmIKaWYocz49dC5sZW5ndGgpcmV0dXJuIEguayh0LHMpCnI9cC5i
-PXRbc10KaWYociE9bnVsbClyZXR1cm4gcgpyPXt9CnAuYj1yCkMuTm0uWSh0LHMscikKcS5pbShhLG5l
-dyBQLlRhKHAscSkpCnJldHVybiBwLmJ9dGhyb3cgSC5iKFAubigic3RydWN0dXJlZCBjbG9uZSBvZiBv
-dGhlciB0eXBlIikpfSwKZWs6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzPUouVTYoYSkscj1zLmdBKGEpLHE9
-bmV3IEFycmF5KHIpCkMuTm0uWSh0aGlzLmIsYixxKQpmb3IodD0wO3Q8cjsrK3QpQy5ObS5ZKHEsdCx0
-aGlzLlB2KHMucShhLHQpKSkKcmV0dXJuIHF9fQpQLmpnLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEs
-Yil7dGhpcy5hLmFbYV09dGhpcy5iLlB2KGIpfSwKJFM6NH0KUC5UYS5wcm90b3R5cGU9ewokMjpmdW5j
-dGlvbihhLGIpe3RoaXMuYS5iW2FdPXRoaXMuYi5QdihiKX0sCiRTOjR9ClAuQmYucHJvdG90eXBlPXsK
-aW06ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscQp1LmI4LmEoYikKZm9yKHQ9T2JqZWN0LmtleXMoYSks
-cz10Lmxlbmd0aCxyPTA7cjxzOysrcil7cT10W3JdCmIuJDIocSxhW3FdKX19fQpQLkFzLnByb3RvdHlw
-ZT17ClQ6ZnVuY3Rpb24oYSl7dmFyIHQKSC5jKGEpCnQ9JC5oRygpLmIKaWYodHlwZW9mIGEhPSJzdHJp
-bmciKUgudmgoSC5JKGEpKQppZih0LnRlc3QoYSkpcmV0dXJuIGEKdGhyb3cgSC5iKFAuTDMoYSwidmFs
-dWUiLCJOb3QgYSB2YWxpZCBjbGFzcyB0b2tlbiIpKX0sClo6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMu
-dygpLkgoMCwiICIpfSwKZ2t6OmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMudygpCnJldHVybiBQLnJqKHQs
-dC5yLEguTGgodCkuYyl9LApnQTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy53KCkuYX0sCnRnOmZ1bmN0
-aW9uKGEsYil7dGhpcy5UKGIpCnJldHVybiB0aGlzLncoKS50ZygwLGIpfSwKaTpmdW5jdGlvbihhLGIp
-e3RoaXMuVChiKQpyZXR1cm4gSC5FOSh0aGlzLk9TKG5ldyBQLkdFKGIpKSl9LApSOmZ1bmN0aW9uKGEs
-Yil7dmFyIHQscwp0aGlzLlQoYikKdD10aGlzLncoKQpzPXQuUigwLGIpCnRoaXMuWCh0KQpyZXR1cm4g
-c30sCkZWOmZ1bmN0aW9uKGEsYil7dGhpcy5PUyhuZXcgUC5ONyh0aGlzLHUuWC5hKGIpKSl9LApWMTpm
-dW5jdGlvbihhKXt0aGlzLk9TKG5ldyBQLnVRKCkpfSwKT1M6ZnVuY3Rpb24oYSl7dmFyIHQscwp1LmJV
-LmEoYSkKdD10aGlzLncoKQpzPWEuJDEodCkKdGhpcy5YKHQpCnJldHVybiBzfX0KUC5HRS5wcm90b3R5
-cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gdS5DLmEoYSkuaSgwLHRoaXMuYSl9LAokUzozMX0KUC5O
-Ny5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmIscz1ILnQ2KHQpCnJldHVybiB1
-LkMuYShhKS5GVigwLG5ldyBILmxKKHQscy5DKCJxVSgxKSIpLmEodGhpcy5hLmd1TSgpKSxzLkMoImxK
-PDEscVU+IikpKX0sCiRTOjExfQpQLnVRLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3UuQy5hKGEp
-CmlmKGEuYT4wKXthLmI9YS5jPWEuZD1hLmU9YS5mPW51bGwKYS5hPTAKYS5TKCl9cmV0dXJuIG51bGx9
-LAokUzoxMX0KUC5oRi5wcm90b3R5cGU9eyRpaEY6MX0KUC5QQy5wcm90b3R5cGU9ewokMTpmdW5jdGlv
-bihhKXt2YXIgdAp1LlouYShhKQp0PWZ1bmN0aW9uKGIsYyxkKXtyZXR1cm4gZnVuY3Rpb24oKXtyZXR1
-cm4gYihjLGQsdGhpcyxBcnJheS5wcm90b3R5cGUuc2xpY2UuYXBwbHkoYXJndW1lbnRzKSl9fShQLlI0
-LGEsITEpClAuRG0odCwkLndRKCksYSkKcmV0dXJuIHR9LAokUzoxfQpQLm10LnByb3RvdHlwZT17CiQx
-OmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgdGhpcy5hKGEpfSwKJFM6MX0KUC5Oei5wcm90b3R5cGU9ewok
-MTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAucjcoYSl9LAokUzozM30KUC5RUy5wcm90b3R5cGU9ewok
-MTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAuVHooYSx1LmFtKX0sCiRTOjM0fQpQLm5wLnByb3RvdHlw
-ZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC5FNChhKX0sCiRTOjM1fQpQLkU0LnByb3RvdHlw
-ZT17CnE6ZnVuY3Rpb24oYSxiKXtpZih0eXBlb2YgYiE9InN0cmluZyImJnR5cGVvZiBiIT0ibnVtYmVy
-Iil0aHJvdyBILmIoUC54WSgicHJvcGVydHkgaXMgbm90IGEgU3RyaW5nIG9yIG51bSIpKQpyZXR1cm4g
-UC5MNyh0aGlzLmFbYl0pfSwKWTpmdW5jdGlvbihhLGIsYyl7aWYodHlwZW9mIGIhPSJzdHJpbmciJiZ0
-eXBlb2YgYiE9Im51bWJlciIpdGhyb3cgSC5iKFAueFkoInByb3BlcnR5IGlzIG5vdCBhIFN0cmluZyBv
-ciBudW0iKSkKdGhpcy5hW2JdPVAud1koYyl9LApETjpmdW5jdGlvbihhLGIpe2lmKGI9PW51bGwpcmV0
-dXJuITEKcmV0dXJuIGIgaW5zdGFuY2VvZiBQLkU0JiZ0aGlzLmE9PT1iLmF9LApaOmZ1bmN0aW9uKGEp
-e3ZhciB0LHMKdHJ5e3Q9U3RyaW5nKHRoaXMuYSkKcmV0dXJuIHR9Y2F0Y2gocyl7SC5SdShzKQp0PXRo
-aXMueGIoMCkKcmV0dXJuIHR9fSwKVjc6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzPXRoaXMuYQppZihiPT1u
-dWxsKXQ9bnVsbAplbHNle3Q9SC50NihiKQp0PVAuQ0gobmV3IEgubEooYix0LkMoIkAoMSkiKS5hKFAu
-aUcoKSksdC5DKCJsSjwxLEA+IikpLCEwLHUueil9cmV0dXJuIFAuTDcoc1thXS5hcHBseShzLHQpKX0s
-CmdpTzpmdW5jdGlvbihhKXtyZXR1cm4gMH19ClAucjcucHJvdG90eXBlPXt9ClAuVHoucHJvdG90eXBl
-PXsKY1A6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcyxzPWE8MHx8YT49dC5nQSh0KQppZihzKXRocm93IEgu
-YihQLlRFKGEsMCx0LmdBKHQpLG51bGwsbnVsbCkpfSwKcTpmdW5jdGlvbihhLGIpe2lmKHR5cGVvZiBi
-PT0ibnVtYmVyIiYmYj09PUMuam4ueXUoYikpdGhpcy5jUChILldZKGIpKQpyZXR1cm4gdGhpcy4kdGku
-Yy5hKHRoaXMuVXIoMCxiKSl9LApZOmZ1bmN0aW9uKGEsYixjKXt2YXIgdAp0aGlzLiR0aS5jLmEoYykK
-dD1DLmpuLnl1KGIpCmlmKGI9PT10KXRoaXMuY1AoYikKdGhpcy5lNCgwLGIsYyl9LApnQTpmdW5jdGlv
-bihhKXt2YXIgdD10aGlzLmEubGVuZ3RoCmlmKHR5cGVvZiB0PT09Im51bWJlciImJnQ+Pj4wPT09dCly
-ZXR1cm4gdAp0aHJvdyBILmIoUC5QVigiQmFkIEpzQXJyYXkgbGVuZ3RoIikpfSwKJGliUToxLAokaWNY
-OjEsCiRpek06MX0KUC5jby5wcm90b3R5cGU9e30KUC5uZC5wcm90b3R5cGU9eyRpbmQ6MX0KUC5LZS5w
-cm90b3R5cGU9ewp3OmZ1bmN0aW9uKCl7dmFyIHQscyxyLHEscD10aGlzLmEuZ2V0QXR0cmlidXRlKCJj
-bGFzcyIpLG89UC5Mcyh1Lk4pCmlmKHA9PW51bGwpcmV0dXJuIG8KZm9yKHQ9cC5zcGxpdCgiICIpLHM9
-dC5sZW5ndGgscj0wO3I8czsrK3Ipe3E9Si5UMCh0W3JdKQppZihxLmxlbmd0aCE9PTApby5pKDAscSl9
-cmV0dXJuIG99LApYOmZ1bmN0aW9uKGEpe3RoaXMuYS5zZXRBdHRyaWJ1dGUoImNsYXNzIixhLkgoMCwi
-ICIpKX19ClAuZDUucHJvdG90eXBlPXsKZ1A6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQLktlKGEpfSwK
-c2hmOmZ1bmN0aW9uKGEsYil7dGhpcy5ZQyhhLGIpfSwKcjY6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQs
-cyxyLHEscCxvCmlmKGQ9PW51bGwpe3Q9SC5WTShbXSx1LmkpCmQ9bmV3IFcudkQodCkKQy5ObS5pKHQs
-Vy5UdyhudWxsKSkKQy5ObS5pKHQsVy5CbCgpKQpDLk5tLmkodCxuZXcgVy5PdygpKX1jPW5ldyBXLktv
-KGQpCnM9JzxzdmcgdmVyc2lvbj0iMS4xIj4nK0guZChiKSsiPC9zdmc+Igp0PWRvY3VtZW50CnI9dC5i
-b2R5CnE9KHImJkMuUlkpLkFIKHIscyxjKQpwPXQuY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgpCnEudG9T
+T0godCxoKQpnPXRbaF0KaWYoZz49MCl7aD1DLnhCLm0oIkFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFla
+YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5Ky8iLGcpCmlmKGg9PT1sKWNvbnRpbnVl
+Cmw9aH1lbHNle2lmKGc9PT0tMSl7aWYocDwwKXtmPXE9PW51bGw/bnVsbDpxLmEubGVuZ3RoCmlmKGY9
+PW51bGwpZj0wCnA9Zisocy1yKQpvPXN9KytuCmlmKGw9PT02MSljb250aW51ZX1sPWh9aWYoZyE9PS0y
+KXtpZihxPT1udWxsKXtxPW5ldyBQLlJuKCIiKQpmPXF9ZWxzZSBmPXEKZi5hKz1DLnhCLk5qKGEscixz
+KQpmLmErPUguTHcobCkKcj1tCmNvbnRpbnVlfX10aHJvdyBILmIoUC5ycigiSW52YWxpZCBiYXNlNjQg
+ZGF0YSIsYSxzKSl9aWYocSE9bnVsbCl7Zj1xLmErPUMueEIuTmooYSxyLGExKQplPWYubGVuZ3RoCmlm
+KHA+PTApUC54TShhLG8sYTEscCxuLGUpCmVsc2V7ZD1DLmpuLnpZKGUtMSw0KSsxCmlmKGQ9PT0xKXRo
+cm93IEguYihQLnJyKGIsYSxhMSkpCmZvcig7ZDw0Oyl7Zis9Ij0iCnEuYT1mOysrZH19Zj1xLmEKcmV0
+dXJuIEMueEIuaTcoYSxhMCxhMSxmLmNoYXJDb2RlQXQoMCk9PTA/ZjpmKX1jPWExLWEwCmlmKHA+PTAp
+UC54TShhLG8sYTEscCxuLGMpCmVsc2V7ZD1DLmpuLnpZKGMsNCkKaWYoZD09PTEpdGhyb3cgSC5iKFAu
+cnIoYixhLGExKSkKaWYoZD4xKWE9Qy54Qi5pNyhhLGExLGExLGQ9PT0yPyI9PSI6Ij0iKX1yZXR1cm4g
+YX19ClAuVTgucHJvdG90eXBlPXt9ClAuVWsucHJvdG90eXBlPXt9ClAud0kucHJvdG90eXBlPXt9ClAu
+WmkucHJvdG90eXBlPXt9ClAuVWQucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXt2YXIgdD1QLnAodGhp
+cy5hKQpyZXR1cm4odGhpcy5iIT1udWxsPyJDb252ZXJ0aW5nIG9iamVjdCB0byBhbiBlbmNvZGFibGUg
+b2JqZWN0IGZhaWxlZDoiOiJDb252ZXJ0aW5nIG9iamVjdCBkaWQgbm90IHJldHVybiBhbiBlbmNvZGFi
+bGUgb2JqZWN0OiIpKyIgIit0fX0KUC5LOC5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiJD
+eWNsaWMgZXJyb3IgaW4gSlNPTiBzdHJpbmdpZnkifX0KUC5ieS5wcm90b3R5cGU9ewpwVzpmdW5jdGlv
+bihhLGIsYyl7dmFyIHQKdS5mVi5hKGMpCnQ9UC5CUyhiLHRoaXMuZ0hlKCkuYSkKcmV0dXJuIHR9LApP
+QjpmdW5jdGlvbihhLGIpe3ZhciB0CnUuZEEuYShiKQp0PVAudVgoYSx0aGlzLmdaRSgpLmIsbnVsbCkK
+cmV0dXJuIHR9LApnWkU6ZnVuY3Rpb24oKXtyZXR1cm4gQy5uWH0sCmdIZTpmdW5jdGlvbigpe3JldHVy
+biBDLkEzfX0KUC5vai5wcm90b3R5cGU9e30KUC5NeC5wcm90b3R5cGU9e30KUC5TaC5wcm90b3R5cGU9
+ewp2cDpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwLG8sbixtPWEubGVuZ3RoCmZvcih0PUouclkoYSks
+cz10aGlzLmMscj0wLHE9MDtxPG07KytxKXtwPXQuVyhhLHEpCmlmKHA+OTIpe2lmKHA+PTU1Mjk2KXtv
+PXAmNjQ1MTIKaWYobz09PTU1Mjk2KXtuPXErMQpuPSEobjxtJiYoQy54Qi5XKGEsbikmNjQ1MTIpPT09
+NTYzMjApfWVsc2Ugbj0hMQppZighbilpZihvPT09NTYzMjApe289cS0xCm89IShvPj0wJiYoQy54Qi5t
+KGEsbykmNjQ1MTIpPT09NTUyOTYpfWVsc2Ugbz0hMQplbHNlIG89ITAKaWYobyl7aWYocT5yKXMuYSs9
+Qy54Qi5OaihhLHIscSkKcj1xKzEKcy5hKz1ILkx3KDkyKQpzLmErPUguTHcoMTE3KQpzLmErPUguTHco
+MTAwKQpvPXA+Pj44JjE1CnMuYSs9SC5MdyhvPDEwPzQ4K286ODcrbykKbz1wPj4+NCYxNQpzLmErPUgu
+THcobzwxMD80OCtvOjg3K28pCm89cCYxNQpzLmErPUguTHcobzwxMD80OCtvOjg3K28pfX1jb250aW51
+ZX1pZihwPDMyKXtpZihxPnIpcy5hKz1DLnhCLk5qKGEscixxKQpyPXErMQpzLmErPUguTHcoOTIpCnN3
+aXRjaChwKXtjYXNlIDg6cy5hKz1ILkx3KDk4KQpicmVhawpjYXNlIDk6cy5hKz1ILkx3KDExNikKYnJl
+YWsKY2FzZSAxMDpzLmErPUguTHcoMTEwKQpicmVhawpjYXNlIDEyOnMuYSs9SC5MdygxMDIpCmJyZWFr
+CmNhc2UgMTM6cy5hKz1ILkx3KDExNCkKYnJlYWsKZGVmYXVsdDpzLmErPUguTHcoMTE3KQpzLmErPUgu
+THcoNDgpCnMuYSs9SC5Mdyg0OCkKbz1wPj4+NCYxNQpzLmErPUguTHcobzwxMD80OCtvOjg3K28pCm89
+cCYxNQpzLmErPUguTHcobzwxMD80OCtvOjg3K28pCmJyZWFrfX1lbHNlIGlmKHA9PT0zNHx8cD09PTky
+KXtpZihxPnIpcy5hKz1DLnhCLk5qKGEscixxKQpyPXErMQpzLmErPUguTHcoOTIpCnMuYSs9SC5Mdyhw
+KX19aWYocj09PTApcy5hKz1ILkVqKGEpCmVsc2UgaWYocjxtKXMuYSs9dC5OaihhLHIsbSl9LApKbjpm
+dW5jdGlvbihhKXt2YXIgdCxzLHIscQpmb3IodD10aGlzLmEscz10Lmxlbmd0aCxyPTA7cjxzOysrcil7
+cT10W3JdCmlmKGE9PW51bGw/cT09bnVsbDphPT09cSl0aHJvdyBILmIobmV3IFAuSzgoYSxudWxsKSl9
+Qy5ObS5pKHQsYSl9LAppVTpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwPXRoaXMKaWYocC50TShhKSly
+ZXR1cm4KcC5KbihhKQp0cnl7dD1wLmIuJDEoYSkKaWYoIXAudE0odCkpe3I9UC5HeShhLG51bGwscC5n
+VksoKSkKdGhyb3cgSC5iKHIpfXI9cC5hCmlmKDA+PXIubGVuZ3RoKXJldHVybiBILk9IKHIsLTEpCnIu
+cG9wKCl9Y2F0Y2gocSl7cz1ILlJ1KHEpCnI9UC5HeShhLHMscC5nVksoKSkKdGhyb3cgSC5iKHIpfX0s
+CnRNOmZ1bmN0aW9uKGEpe3ZhciB0LHMscj10aGlzCmlmKHR5cGVvZiBhPT0ibnVtYmVyIil7aWYoIWlz
+RmluaXRlKGEpKXJldHVybiExCnIuYy5hKz1DLkNELncoYSkKcmV0dXJuITB9ZWxzZSBpZihhPT09ITAp
+e3IuYy5hKz0idHJ1ZSIKcmV0dXJuITB9ZWxzZSBpZihhPT09ITEpe3IuYy5hKz0iZmFsc2UiCnJldHVy
+biEwfWVsc2UgaWYoYT09bnVsbCl7ci5jLmErPSJudWxsIgpyZXR1cm4hMH1lbHNlIGlmKHR5cGVvZiBh
+PT0ic3RyaW5nIil7dD1yLmMKdC5hKz0nIicKci52cChhKQp0LmErPSciJwpyZXR1cm4hMH1lbHNlIGlm
+KHUuYi5iKGEpKXtyLkpuKGEpCnIubEsoYSkKdD1yLmEKaWYoMD49dC5sZW5ndGgpcmV0dXJuIEguT0go
+dCwtMSkKdC5wb3AoKQpyZXR1cm4hMH1lbHNlIGlmKHUuZi5iKGEpKXtyLkpuKGEpCnM9ci5qdyhhKQp0
+PXIuYQppZigwPj10Lmxlbmd0aClyZXR1cm4gSC5PSCh0LC0xKQp0LnBvcCgpCnJldHVybiBzfWVsc2Ug
+cmV0dXJuITF9LApsSzpmdW5jdGlvbihhKXt2YXIgdCxzLHI9dGhpcy5jCnIuYSs9IlsiCnQ9Si5VNihh
+KQppZih0LmdvcihhKSl7dGhpcy5pVSh0LnEoYSwwKSkKZm9yKHM9MTtzPHQuZ0EoYSk7KytzKXtyLmEr
+PSIsIgp0aGlzLmlVKHQucShhLHMpKX19ci5hKz0iXSJ9LApqdzpmdW5jdGlvbihhKXt2YXIgdCxzLHIs
+cSxwLG89dGhpcyxuPXt9CmlmKGEuZ2wwKGEpKXtvLmMuYSs9Int9IgpyZXR1cm4hMH10PVAuTzgoYS5n
+QShhKSoyLG51bGwsITEsdS5XKQpzPW4uYT0wCm4uYj0hMAphLksoMCxuZXcgUC50aShuLHQpKQppZigh
+bi5iKXJldHVybiExCnI9by5jCnIuYSs9InsiCmZvcihxPSciJztzPHQubGVuZ3RoO3MrPTIscT0nLCIn
+KXtyLmErPXEKby52cChILmgodFtzXSkpCnIuYSs9JyI6JwpwPXMrMQppZihwPj10Lmxlbmd0aClyZXR1
+cm4gSC5PSCh0LHApCm8uaVUodFtwXSl9ci5hKz0ifSIKcmV0dXJuITB9fQpQLnRpLnByb3RvdHlwZT17
+CiQyOmZ1bmN0aW9uKGEsYil7dmFyIHQscwppZih0eXBlb2YgYSE9InN0cmluZyIpdGhpcy5hLmI9ITEK
+dD10aGlzLmIKcz10aGlzLmEKQy5ObS5ZKHQscy5hKyssYSkKQy5ObS5ZKHQscy5hKyssYil9LAokUzox
+MX0KUC50dS5wcm90b3R5cGU9ewpnVks6ZnVuY3Rpb24oKXt2YXIgdD10aGlzLmMuYQpyZXR1cm4gdC5j
+aGFyQ29kZUF0KDApPT0wP3Q6dH19ClAudTUucHJvdG90eXBlPXsKZ1pFOmZ1bmN0aW9uKCl7cmV0dXJu
+IEMuUWt9fQpQLkUzLnByb3RvdHlwZT17CldKOmZ1bmN0aW9uKGEpe3ZhciB0LHMscj1QLmpCKDAsbnVs
+bCxhLmxlbmd0aCkscT1yLTAKaWYocT09PTApcmV0dXJuIG5ldyBVaW50OEFycmF5KDApCnQ9bmV3IFVp
+bnQ4QXJyYXkocSozKQpzPW5ldyBQLlJ3KHQpCmlmKHMuR3goYSwwLHIpIT09cil7Si5hNihhLHItMSkK
+cy5STygpfXJldHVybiBuZXcgVWludDhBcnJheSh0LnN1YmFycmF5KDAsSC5yTSgwLHMuYix0Lmxlbmd0
+aCkpKX19ClAuUncucHJvdG90eXBlPXsKUk86ZnVuY3Rpb24oKXt2YXIgdD10aGlzLHM9dC5jLHI9dC5i
+LHE9dC5iPXIrMSxwPXMubGVuZ3RoCmlmKHI+PXApcmV0dXJuIEguT0gocyxyKQpzW3JdPTIzOQpyPXQu
+Yj1xKzEKaWYocT49cClyZXR1cm4gSC5PSChzLHEpCnNbcV09MTkxCnQuYj1yKzEKaWYocj49cClyZXR1
+cm4gSC5PSChzLHIpCnNbcl09MTg5fSwKTzY6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxwLG89dGhp
+cwppZigoYiY2NDUxMik9PT01NjMyMCl7dD02NTUzNisoKGEmMTAyMyk8PDEwKXxiJjEwMjMKcz1vLmMK
+cj1vLmIKcT1vLmI9cisxCnA9cy5sZW5ndGgKaWYocj49cClyZXR1cm4gSC5PSChzLHIpCnNbcl09MjQw
+fHQ+Pj4xOApyPW8uYj1xKzEKaWYocT49cClyZXR1cm4gSC5PSChzLHEpCnNbcV09MTI4fHQ+Pj4xMiY2
+MwpxPW8uYj1yKzEKaWYocj49cClyZXR1cm4gSC5PSChzLHIpCnNbcl09MTI4fHQ+Pj42JjYzCm8uYj1x
+KzEKaWYocT49cClyZXR1cm4gSC5PSChzLHEpCnNbcV09MTI4fHQmNjMKcmV0dXJuITB9ZWxzZXtvLlJP
+KCkKcmV0dXJuITF9fSwKR3g6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixxLHAsbyxuLG09dGhpcwpp
+ZihiIT09YyYmKEMueEIubShhLGMtMSkmNjQ1MTIpPT09NTUyOTYpLS1jCmZvcih0PW0uYyxzPXQubGVu
+Z3RoLHI9YjtyPGM7KytyKXtxPUMueEIuVyhhLHIpCmlmKHE8PTEyNyl7cD1tLmIKaWYocD49cylicmVh
+awptLmI9cCsxCnRbcF09cX1lbHNle3A9cSY2NDUxMgppZihwPT09NTUyOTYpe2lmKG0uYis0PnMpYnJl
+YWsKbz1yKzEKaWYobS5PNihxLEMueEIuVyhhLG8pKSlyPW99ZWxzZSBpZihwPT09NTYzMjApe2lmKG0u
+YiszPnMpYnJlYWsKbS5STygpfWVsc2UgaWYocTw9MjA0Nyl7cD1tLmIKbj1wKzEKaWYobj49cylicmVh
+awptLmI9bgppZihwPj1zKXJldHVybiBILk9IKHQscCkKdFtwXT0xOTJ8cT4+PjYKbS5iPW4rMQp0W25d
+PTEyOHxxJjYzfWVsc2V7cD1tLmIKaWYocCsyPj1zKWJyZWFrCm49bS5iPXArMQppZihwPj1zKXJldHVy
+biBILk9IKHQscCkKdFtwXT0yMjR8cT4+PjEyCnA9bS5iPW4rMQppZihuPj1zKXJldHVybiBILk9IKHQs
+bikKdFtuXT0xMjh8cT4+PjYmNjMKbS5iPXArMQppZihwPj1zKXJldHVybiBILk9IKHQscCkKdFtwXT0x
+Mjh8cSY2M319fXJldHVybiByfX0KUC5HWS5wcm90b3R5cGU9ewpXSjpmdW5jdGlvbihhKXt2YXIgdCxz
+CnUuTC5hKGEpCnQ9dGhpcy5hCnM9UC5reSh0LGEsMCxudWxsKQppZihzIT1udWxsKXJldHVybiBzCnJl
+dHVybiBuZXcgUC5ieih0KS5OZShhLDAsbnVsbCwhMCl9fQpQLmJ6LnByb3RvdHlwZT17Ck5lOmZ1bmN0
+aW9uKGEsYixjLGQpe3ZhciB0LHMscixxLHAsbz10aGlzCnUuTC5hKGEpCnQ9UC5qQihiLGMsSi5IbShh
+KSkKaWYoYj09PXQpcmV0dXJuIiIKcz1QLmp5KGEsYix0KQpyPW8uaE8ocywwLHQtYiwhMCkKcT1vLmIK
+aWYoKHEmMSkhPT0wKXtwPVAuajQocSkKby5iPTAKdGhyb3cgSC5iKFAucnIocCxhLGIrby5jKSl9cmV0
+dXJuIHJ9LApoTzpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzLHI9dGhpcwppZihjLWI+MTAwMCl7dD1D
+LmpuLkJVKGIrYywyKQpzPXIuaE8oYSxiLHQsITEpCmlmKChyLmImMSkhPT0wKXJldHVybiBzCnJldHVy
+biBzK3IuaE8oYSx0LGMsZCl9cmV0dXJuIHIuRWgoYSxiLGMsZCl9LApFaDpmdW5jdGlvbihhLGIsYyxk
+KXt2YXIgdCxzLHIscSxwLG8sbixtLGw9dGhpcyxrPTY1NTMzLGo9bC5iLGk9bC5jLGg9bmV3IFAuUm4o
+IiIpLGc9YisxLGY9YS5sZW5ndGgKaWYoYjwwfHxiPj1mKXJldHVybiBILk9IKGEsYikKdD1hW2JdCiRs
+YWJlbDAkMDpmb3Iocz1sLmE7ITA7KXtmb3IoOyEwO2c9cCl7cj1DLnhCLlcoIkFBQUFBQUFBQUFBQUFB
+QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFB
+QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBRkZGRkZG
+RkZGRkZGRkZGRkdHR0dHR0dHR0dHR0dHR0dISEhISEhISEhISEhISEhISEhISEhISEhISEhJSEhISkVF
+QkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCS0NDQ0NDQ0NDQ0NDQ0RDTE9OTk5NRUVFRUVFRUVF
+RUUiLHQpJjMxCmk9ajw9MzI/dCY2MTY5ND4+PnI6KHQmNjN8aTw8Nik+Pj4wCmo9Qy54Qi5XKCIgXHgw
+MDA6WEVDQ0NDQ046bERiIFx4MDAwOlhFQ0NDQ0NOdmxEYiBceDAwMDpYRUNDQ0NDTjpsRGIgQUFBQUFc
+eDAwXHgwMFx4MDBceDAwXHgwMEFBQUFBMDAwMDBBQUFBQTo6Ojo6QUFBQUFHRzAwMEFBQUFBMDBLS0tB
+QUFBQUc6Ojo6QUFBQUE6SUlJSUFBQUFBMDAwXHg4MDBBQUFBQVx4MDBceDAwXHgwMFx4MDAgQUFBQUEi
+LGorcikKaWYoaj09PTApe2guYSs9SC5MdyhpKQppZihnPT09YylicmVhayAkbGFiZWwwJDAKYnJlYWt9
+ZWxzZSBpZigoaiYxKSE9PTApe2lmKHMpc3dpdGNoKGope2Nhc2UgNjk6Y2FzZSA2NzpoLmErPUguTHco
+aykKYnJlYWsKY2FzZSA2NTpoLmErPUguTHcoayk7LS1nCmJyZWFrCmRlZmF1bHQ6cT1oLmErPUguTHco
+aykKaC5hPXErSC5MdyhrKQpicmVha31lbHNle2wuYj1qCmwuYz1nLTEKcmV0dXJuIiJ9aj0wfWlmKGc9
+PT1jKWJyZWFrICRsYWJlbDAkMApwPWcrMQppZihnPDB8fGc+PWYpcmV0dXJuIEguT0goYSxnKQp0PWFb
+Z119cD1nKzEKaWYoZzwwfHxnPj1mKXJldHVybiBILk9IKGEsZykKdD1hW2ddCmlmKHQ8MTI4KXt3aGls
+ZSghMCl7aWYoIShwPGMpKXtvPWMKYnJlYWt9bj1wKzEKaWYocDwwfHxwPj1mKXJldHVybiBILk9IKGEs
+cCkKdD1hW3BdCmlmKHQ+PTEyOCl7bz1uLTEKcD1uCmJyZWFrfXA9bn1pZihvLWc8MjApZm9yKG09Zztt
+PG87KyttKXtpZihtPj1mKXJldHVybiBILk9IKGEsbSkKaC5hKz1ILkx3KGFbbV0pfWVsc2UgaC5hKz1Q
+LkhNKGEsZyxvKQppZihvPT09YylicmVhayAkbGFiZWwwJDAKZz1wfWVsc2UgZz1wfWlmKGQmJmo+MzIp
+aWYocyloLmErPUguTHcoaykKZWxzZXtsLmI9NzcKbC5jPWMKcmV0dXJuIiJ9bC5iPWoKbC5jPWkKZj1o
+LmEKcmV0dXJuIGYuY2hhckNvZGVBdCgwKT09MD9mOmZ9fQpQLldGLnByb3RvdHlwZT17CiQyOmZ1bmN0
+aW9uKGEsYil7dmFyIHQscyxyCnUuZm8uYShhKQp0PXRoaXMuYgpzPXRoaXMuYQp0LmErPXMuYQpyPXQu
+YSs9SC5FaihhLmEpCnQuYT1yKyI6ICIKdC5hKz1QLnAoYikKcy5hPSIsICJ9LAokUzo0M30KUC5hMi5w
+cm90b3R5cGU9e30KUC5pUC5wcm90b3R5cGU9ewpETjpmdW5jdGlvbihhLGIpe2lmKGI9PW51bGwpcmV0
+dXJuITEKcmV0dXJuIGIgaW5zdGFuY2VvZiBQLmlQJiZ0aGlzLmE9PT1iLmEmJiEwfSwKZ2lPOmZ1bmN0
+aW9uKGEpe3ZhciB0PXRoaXMuYQpyZXR1cm4odF5DLmpuLndHKHQsMzApKSYxMDczNzQxODIzfSwKdzpm
+dW5jdGlvbihhKXt2YXIgdD10aGlzLHM9UC5HcShILnRKKHQpKSxyPVAuaDAoSC5OUyh0KSkscT1QLmgw
+KEguakEodCkpLHA9UC5oMChILklYKHQpKSxvPVAuaDAoSC5jaCh0KSksbj1QLmgwKEguSmQodCkpLG09
+UC5WeChILm8xKHQpKSxsPXMrIi0iK3IrIi0iK3ErIiAiK3ArIjoiK28rIjoiK24rIi4iK20KcmV0dXJu
+IGx9fQpQLkNQLnByb3RvdHlwZT17fQpQLlhTLnByb3RvdHlwZT17CmdJSTpmdW5jdGlvbigpe3JldHVy
+biBILnRzKHRoaXMuJHRocm93bkpzRXJyb3IpfX0KUC5DNi5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEp
+e3ZhciB0PXRoaXMuYQppZih0IT1udWxsKXJldHVybiJBc3NlcnRpb24gZmFpbGVkOiAiK1AucCh0KQpy
+ZXR1cm4iQXNzZXJ0aW9uIGZhaWxlZCJ9fQpQLm4ucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1
+cm4iVGhyb3cgb2YgbnVsbC4ifX0KUC51LnByb3RvdHlwZT17CmdaOmZ1bmN0aW9uKCl7cmV0dXJuIklu
+dmFsaWQgYXJndW1lbnQiKyghdGhpcy5hPyIocykiOiIiKX0sCmd1OmZ1bmN0aW9uKCl7cmV0dXJuIiJ9
+LAp3OmZ1bmN0aW9uKGEpe3ZhciB0LHMscj10aGlzLHE9ci5jLHA9cT09bnVsbD8iIjoiICgiK3ErIiki
+LG89ci5kLG49bz09bnVsbD8iIjoiOiAiK0guRWoobyksbT1yLmdaKCkrcCtuCmlmKCFyLmEpcmV0dXJu
+IG0KdD1yLmd1KCkKcz1QLnAoci5iKQpyZXR1cm4gbSt0KyI6ICIrc319ClAuYkoucHJvdG90eXBlPXsK
+Z1o6ZnVuY3Rpb24oKXtyZXR1cm4iUmFuZ2VFcnJvciJ9LApndTpmdW5jdGlvbigpe3ZhciB0LHM9dGhp
+cy5lLHI9dGhpcy5mCmlmKHM9PW51bGwpdD1yIT1udWxsPyI6IE5vdCBsZXNzIHRoYW4gb3IgZXF1YWwg
+dG8gIitILkVqKHIpOiIiCmVsc2UgaWYocj09bnVsbCl0PSI6IE5vdCBncmVhdGVyIHRoYW4gb3IgZXF1
+YWwgdG8gIitILkVqKHMpCmVsc2UgaWYocj5zKXQ9IjogTm90IGluIGluY2x1c2l2ZSByYW5nZSAiK0gu
+RWoocykrIi4uIitILkVqKHIpCmVsc2UgdD1yPHM/IjogVmFsaWQgdmFsdWUgcmFuZ2UgaXMgZW1wdHki
+OiI6IE9ubHkgdmFsaWQgdmFsdWUgaXMgIitILkVqKHMpCnJldHVybiB0fX0KUC5lWS5wcm90b3R5cGU9
+ewpnWjpmdW5jdGlvbigpe3JldHVybiJSYW5nZUVycm9yIn0sCmd1OmZ1bmN0aW9uKCl7dmFyIHQscz1I
+LnVQKHRoaXMuYikKaWYodHlwZW9mIHMhPT0ibnVtYmVyIilyZXR1cm4gcy5KKCkKaWYoczwwKXJldHVy
+biI6IGluZGV4IG11c3Qgbm90IGJlIG5lZ2F0aXZlIgp0PXRoaXMuZgppZih0PT09MClyZXR1cm4iOiBu
+byBpbmRpY2VzIGFyZSB2YWxpZCIKcmV0dXJuIjogaW5kZXggc2hvdWxkIGJlIGxlc3MgdGhhbiAiK0gu
+RWoodCl9LApnQTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5mfX0KUC5tcC5wcm90b3R5cGU9ewp3OmZ1
+bmN0aW9uKGEpe3ZhciB0LHMscixxLHAsbyxuLG0sbD10aGlzLGs9e30saj1uZXcgUC5SbigiIikKay5h
+PSIiCnQ9bC5jCmZvcihzPXQubGVuZ3RoLHI9MCxxPSIiLHA9IiI7cjxzOysrcixwPSIsICIpe289dFty
+XQpqLmE9cStwCnE9ai5hKz1QLnAobykKay5hPSIsICJ9bC5kLksoMCxuZXcgUC5XRihrLGopKQpuPVAu
+cChsLmEpCm09ai53KDApCnM9Ik5vU3VjaE1ldGhvZEVycm9yOiBtZXRob2Qgbm90IGZvdW5kOiAnIitI
+LkVqKGwuYi5hKSsiJ1xuUmVjZWl2ZXI6ICIrbisiXG5Bcmd1bWVudHM6IFsiK20rIl0iCnJldHVybiBz
+fX0KUC51Yi5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiJVbnN1cHBvcnRlZCBvcGVyYXRp
+b246ICIrdGhpcy5hfX0KUC5kcy5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMuYQpy
+ZXR1cm4gdCE9bnVsbD8iVW5pbXBsZW1lbnRlZEVycm9yOiAiK3Q6IlVuaW1wbGVtZW50ZWRFcnJvciJ9
+fQpQLmxqLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIkJhZCBzdGF0ZTogIit0aGlzLmF9
+fQpQLlVWLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5hCmlmKHQ9PW51bGwpcmV0
+dXJuIkNvbmN1cnJlbnQgbW9kaWZpY2F0aW9uIGR1cmluZyBpdGVyYXRpb24uIgpyZXR1cm4iQ29uY3Vy
+cmVudCBtb2RpZmljYXRpb24gZHVyaW5nIGl0ZXJhdGlvbjogIitQLnAodCkrIi4ifX0KUC5rNS5wcm90
+b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiJPdXQgb2YgTWVtb3J5In0sCmdJSTpmdW5jdGlvbigp
+e3JldHVybiBudWxsfSwKJGlYUzoxfQpQLktZLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJu
+IlN0YWNrIE92ZXJmbG93In0sCmdJSTpmdW5jdGlvbigpe3JldHVybiBudWxsfSwKJGlYUzoxfQpQLmMu
+cHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmEKcmV0dXJuIHQ9PW51bGw/IlJlYWRp
+bmcgc3RhdGljIHZhcmlhYmxlIGR1cmluZyBpdHMgaW5pdGlhbGl6YXRpb24iOiJSZWFkaW5nIHN0YXRp
+YyB2YXJpYWJsZSAnIit0KyInIGR1cmluZyBpdHMgaW5pdGlhbGl6YXRpb24ifX0KUC5DRC5wcm90b3R5
+cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiJFeGNlcHRpb246ICIrdGhpcy5hfSwKJGlSejoxfQpQLmFF
+LnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscCxvLG4sbSxsLGssaixpLGg9dGhp
+cy5hLGc9aCE9bnVsbCYmIiIhPT1oPyJGb3JtYXRFeGNlcHRpb246ICIrSC5FaihoKToiRm9ybWF0RXhj
+ZXB0aW9uIixmPXRoaXMuYyxlPXRoaXMuYgppZih0eXBlb2YgZT09InN0cmluZyIpe2lmKGYhPW51bGwp
+dD1mPDB8fGY+ZS5sZW5ndGgKZWxzZSB0PSExCmlmKHQpZj1udWxsCmlmKGY9PW51bGwpe2lmKGUubGVu
+Z3RoPjc4KWU9Qy54Qi5OaihlLDAsNzUpKyIuLi4iCnJldHVybiBnKyJcbiIrZX1mb3Iocz0xLHI9MCxx
+PSExLHA9MDtwPGY7KytwKXtvPUMueEIuVyhlLHApCmlmKG89PT0xMCl7aWYociE9PXB8fCFxKSsrcwpy
+PXArMQpxPSExfWVsc2UgaWYobz09PTEzKXsrK3MKcj1wKzEKcT0hMH19Zz1zPjE/ZysoIiAoYXQgbGlu
+ZSAiK3MrIiwgY2hhcmFjdGVyICIrKGYtcisxKSsiKVxuIik6ZysoIiAoYXQgY2hhcmFjdGVyICIrKGYr
+MSkrIilcbiIpCm49ZS5sZW5ndGgKZm9yKHA9ZjtwPG47KytwKXtvPUMueEIubShlLHApCmlmKG89PT0x
+MHx8bz09PTEzKXtuPXAKYnJlYWt9fWlmKG4tcj43OClpZihmLXI8NzUpe209cis3NQpsPXIKaz0iIgpq
+PSIuLi4ifWVsc2V7aWYobi1mPDc1KXtsPW4tNzUKbT1uCmo9IiJ9ZWxzZXtsPWYtMzYKbT1mKzM2Cmo9
+Ii4uLiJ9az0iLi4uIn1lbHNle209bgpsPXIKaz0iIgpqPSIifWk9Qy54Qi5OaihlLGwsbSkKcmV0dXJu
+IGcraytpK2orIlxuIitDLnhCLkl4KCIgIixmLWwray5sZW5ndGgpKyJeXG4ifWVsc2UgcmV0dXJuIGYh
+PW51bGw/ZysoIiAoYXQgb2Zmc2V0ICIrSC5FaihmKSsiKSIpOmd9LAokaVJ6OjF9ClAuRUgucHJvdG90
+eXBlPXt9ClAuSWYucHJvdG90eXBlPXt9ClAuY1gucHJvdG90eXBlPXsKRTI6ZnVuY3Rpb24oYSxiLGMp
+e3ZhciB0PUguTGgodGhpcykKcmV0dXJuIEguSzEodGhpcyx0LktxKGMpLkMoIjEoY1guRSkiKS5hKGIp
+LHQuQygiY1guRSIpLGMpfSwKZXY6ZnVuY3Rpb24oYSxiKXt2YXIgdD1ILkxoKHRoaXMpCnJldHVybiBu
+ZXcgSC5VNSh0aGlzLHQuQygiYTIoY1guRSkiKS5hKGIpLHQuQygiVTU8Y1guRT4iKSl9LApnQTpmdW5j
+dGlvbihhKXt2YXIgdCxzPXRoaXMuZ2t6KHRoaXMpCmZvcih0PTA7cy5GKCk7KSsrdApyZXR1cm4gdH0s
+CmdsMDpmdW5jdGlvbihhKXtyZXR1cm4hdGhpcy5na3oodGhpcykuRigpfSwKZ3I4OmZ1bmN0aW9uKGEp
+e3ZhciB0LHM9dGhpcy5na3oodGhpcykKaWYoIXMuRigpKXRocm93IEguYihILldwKCkpCnQ9cy5nbCgp
+CmlmKHMuRigpKXRocm93IEguYihILkFtKCkpCnJldHVybiB0fSwKRTpmdW5jdGlvbihhLGIpe3ZhciB0
+LHMscgpQLmsxKGIsImluZGV4IikKZm9yKHQ9dGhpcy5na3oodGhpcykscz0wO3QuRigpOyl7cj10Lmds
+KCkKaWYoYj09PXMpcmV0dXJuIHI7KytzfXRocm93IEguYihQLkNmKGIsdGhpcywiaW5kZXgiLG51bGws
+cykpfSwKdzpmdW5jdGlvbihhKXtyZXR1cm4gUC5FUCh0aGlzLCIoIiwiKSIpfX0KUC5Bbi5wcm90b3R5
+cGU9e30KUC56TS5wcm90b3R5cGU9eyRpYlE6MSwkaWNYOjF9ClAuWjAucHJvdG90eXBlPXt9ClAuTjMu
+cHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1cm4iTWFwRW50cnkoIitILkVqKEouaih0aGlzLmEp
+KSsiOiAiK0guRWooSi5qKHRoaXMuYikpKyIpIn19ClAuYzgucHJvdG90eXBlPXsKZ2lPOmZ1bmN0aW9u
+KGEpe3JldHVybiBQLk1oLnByb3RvdHlwZS5naU8uY2FsbChDLmpOLHRoaXMpfSwKdzpmdW5jdGlvbihh
+KXtyZXR1cm4ibnVsbCJ9fQpQLmxmLnByb3RvdHlwZT17fQpQLk1oLnByb3RvdHlwZT17Y29uc3RydWN0
+b3I6UC5NaCwkaU1oOjEsCkROOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXM9PT1ifSwKZ2lPOmZ1bmN0
+aW9uKGEpe3JldHVybiBILmVRKHRoaXMpfSwKdzpmdW5jdGlvbihhKXtyZXR1cm4iSW5zdGFuY2Ugb2Yg
+JyIrSC5FaihILk0odGhpcykpKyInIn0sCmU3OmZ1bmN0aW9uKGEsYil7dS5vLmEoYikKdGhyb3cgSC5i
+KFAubHIodGhpcyxiLmdXYSgpLGIuZ25kKCksYi5nVm0oKSkpfSwKdG9TdHJpbmc6ZnVuY3Rpb24oKXty
+ZXR1cm4gdGhpcy53KHRoaXMpfX0KUC5PZC5wcm90b3R5cGU9e30KUC5pYi5wcm90b3R5cGU9eyRpT2Q6
+MX0KUC54dS5wcm90b3R5cGU9e30KUC5Hei5wcm90b3R5cGU9e30KUC5aZC5wcm90b3R5cGU9ewp3OmZ1
+bmN0aW9uKGEpe3JldHVybiIifSwKJGlHejoxfQpQLnFVLnByb3RvdHlwZT17JGl2WDoxfQpQLlJuLnBy
+b3RvdHlwZT17CmdBOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEubGVuZ3RofSwKdzpmdW5jdGlvbihh
+KXt2YXIgdD10aGlzLmEKcmV0dXJuIHQuY2hhckNvZGVBdCgwKT09MD90OnR9LAokaUJMOjF9ClAuR0Qu
+cHJvdG90eXBlPXt9ClAubjEucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscQp1
+LkouYShhKQpILmgoYikKdD1KLnJZKGIpLk9ZKGIsIj0iKQppZih0PT09LTEpe2lmKGIhPT0iIilhLlko
+MCxQLmt1KGIsMCxiLmxlbmd0aCx0aGlzLmEsITApLCIiKX1lbHNlIGlmKHQhPT0wKXtzPUMueEIuTmoo
+YiwwLHQpCnI9Qy54Qi5HKGIsdCsxKQpxPXRoaXMuYQphLlkoMCxQLmt1KHMsMCxzLmxlbmd0aCxxLCEw
+KSxQLmt1KHIsMCxyLmxlbmd0aCxxLCEwKSl9cmV0dXJuIGF9LAokUzoyMX0KUC5jUy5wcm90b3R5cGU9
+ewokMjpmdW5jdGlvbihhLGIpe3Rocm93IEguYihQLnJyKCJJbGxlZ2FsIElQdjQgYWRkcmVzcywgIith
+LHRoaXMuYSxiKSl9LAokUzo0N30KUC5WQy5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3Rocm93
+IEguYihQLnJyKCJJbGxlZ2FsIElQdjYgYWRkcmVzcywgIithLHRoaXMuYSxiKSl9LAokMTpmdW5jdGlv
+bihhKXtyZXR1cm4gdGhpcy4kMihhLG51bGwpfSwKJFM6NDh9ClAuSlQucHJvdG90eXBlPXsKJDI6ZnVu
+Y3Rpb24oYSxiKXt2YXIgdAppZihiLWE+NCl0aGlzLmEuJDIoImFuIElQdjYgcGFydCBjYW4gb25seSBj
+b250YWluIGEgbWF4aW11bSBvZiA0IGhleCBkaWdpdHMiLGEpCnQ9UC5RQShDLnhCLk5qKHRoaXMuYixh
+LGIpLDE2KQppZih0eXBlb2YgdCE9PSJudW1iZXIiKXJldHVybiB0LkooKQppZih0PDB8fHQ+NjU1MzUp
+dGhpcy5hLiQyKCJlYWNoIHBhcnQgbXVzdCBiZSBpbiB0aGUgcmFuZ2Ugb2YgYDB4MC4uMHhGRkZGYCIs
+YSkKcmV0dXJuIHR9LAokUzo1MH0KUC5Ebi5wcm90b3R5cGU9ewpnbkQ6ZnVuY3Rpb24oKXt2YXIgdCxz
+LHIscT10aGlzLHA9cS54CmlmKHA9PW51bGwpe3A9cS5hCnQ9cC5sZW5ndGghPT0wP3ArIjoiOiIiCnM9
+cS5jCnI9cz09bnVsbAppZighcnx8cD09PSJmaWxlIil7cD10KyIvLyIKdD1xLmIKaWYodC5sZW5ndGgh
+PT0wKXA9cCt0KyJAIgppZighcilwKz1zCnQ9cS5kCmlmKHQhPW51bGwpcD1wKyI6IitILkVqKHQpfWVs
+c2UgcD10CnArPXEuZQp0PXEuZgppZih0IT1udWxsKXA9cCsiPyIrdAp0PXEucgppZih0IT1udWxsKXA9
+cCsiIyIrdApwPXAuY2hhckNvZGVBdCgwKT09MD9wOnAKaWYocS54PT1udWxsKXEueD1wCmVsc2UgcD1I
+LnZoKEgueVIoIkZpZWxkICdfdGV4dCcgaGFzIGJlZW4gYXNzaWduZWQgZHVyaW5nIGluaXRpYWxpemF0
+aW9uLiIpKX1yZXR1cm4gcH0sCmdGajpmdW5jdGlvbigpe3ZhciB0LHM9dGhpcyxyPXMueQppZihyPT1u
+dWxsKXt0PXMuZQppZih0Lmxlbmd0aCE9PTAmJkMueEIuVyh0LDApPT09NDcpdD1DLnhCLkcodCwxKQpy
+PXQubGVuZ3RoPT09MD9DLnhEOlAuQUYobmV3IEgubEooSC5WTSh0LnNwbGl0KCIvIiksdS5zKSx1LmRP
+LmEoUC5QSCgpKSx1LmRvKSx1Lk4pCmlmKHMueT09bnVsbClzLnNLcChyKQplbHNlIHI9SC52aChILnlS
+KCJGaWVsZCAncGF0aFNlZ21lbnRzJyBoYXMgYmVlbiBhc3NpZ25lZCBkdXJpbmcgaW5pdGlhbGl6YXRp
+b24uIikpfXJldHVybiByfSwKZ2lPOmZ1bmN0aW9uKGEpe3ZhciB0PXRoaXMscz10LnoKaWYocz09bnVs
+bCl7cz1DLnhCLmdpTyh0LmduRCgpKQppZih0Lno9PW51bGwpdC56PXMKZWxzZSBzPUgudmgoSC55Uigi
+RmllbGQgJ2hhc2hDb2RlJyBoYXMgYmVlbiBhc3NpZ25lZCBkdXJpbmcgaW5pdGlhbGl6YXRpb24uIikp
+fXJldHVybiBzfSwKZ2hZOmZ1bmN0aW9uKCl7dmFyIHQ9dGhpcyxzPXQuUQppZihzPT1udWxsKXtzPW5l
+dyBQLkdqKFAuV1godC5ndFAoKSksdS5FKQppZih0LlE9PW51bGwpdC5zTk0ocykKZWxzZSBzPUgudmgo
+SC55UigiRmllbGQgJ3F1ZXJ5UGFyYW1ldGVycycgaGFzIGJlZW4gYXNzaWduZWQgZHVyaW5nIGluaXRp
+YWxpemF0aW9uLiIpKX1yZXR1cm4gc30sCmdrdTpmdW5jdGlvbigpe3JldHVybiB0aGlzLmJ9LApnSmY6
+ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5jCmlmKHQ9PW51bGwpcmV0dXJuIiIKaWYoQy54Qi5uKHQsIlsi
+KSlyZXR1cm4gQy54Qi5Oaih0LDEsdC5sZW5ndGgtMSkKcmV0dXJuIHR9LApndHA6ZnVuY3Rpb24oYSl7
+dmFyIHQ9dGhpcy5kCnJldHVybiB0PT1udWxsP1Aud0sodGhpcy5hKTp0fSwKZ3RQOmZ1bmN0aW9uKCl7
+dmFyIHQ9dGhpcy5mCnJldHVybiB0PT1udWxsPyIiOnR9LApnS2E6ZnVuY3Rpb24oKXt2YXIgdD10aGlz
+LnIKcmV0dXJuIHQ9PW51bGw/IiI6dH0sCm5tOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEscCxvLG4s
+bSxsLGs9dGhpcwp1LmM5LmEoYikKdD1rLmEKcz10PT09ImZpbGUiCnI9ay5iCnE9ay5kCnA9ay5jCmlm
+KCEocCE9bnVsbCkpcD1yLmxlbmd0aCE9PTB8fHEhPW51bGx8fHM/IiI6bnVsbApvPWsuZQppZighcylu
+PXAhPW51bGwmJm8ubGVuZ3RoIT09MAplbHNlIG49ITAKaWYobiYmIUMueEIubihvLCIvIikpbz0iLyIr
+bwptPW8KbD1QLmxlKG51bGwsMCwwLGIpCnJldHVybiBuZXcgUC5Ebih0LHIscCxxLG0sbCxrLnIpfSwK
+Smg6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxwLG8KZm9yKHQ9MCxzPTA7Qy54Qi5RaShiLCIuLi8i
+LHMpOyl7cys9MzsrK3R9cj1DLnhCLmNuKGEsIi8iKQp3aGlsZSghMCl7aWYoIShyPjAmJnQ+MCkpYnJl
+YWsKcT1DLnhCLlBrKGEsIi8iLHItMSkKaWYocTwwKWJyZWFrCnA9ci1xCm89cCE9PTIKaWYoIW98fHA9
+PT0zKWlmKEMueEIubShhLHErMSk9PT00NilvPSFvfHxDLnhCLm0oYSxxKzIpPT09NDYKZWxzZSBvPSEx
+CmVsc2Ugbz0hMQppZihvKWJyZWFrOy0tdApyPXF9cmV0dXJuIEMueEIuaTcoYSxyKzEsbnVsbCxDLnhC
+LkcoYixzLTMqdCkpfSwKWkk6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMubVMoUC5oSyhhKSl9LAptUzpm
+dW5jdGlvbihhKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsaz10aGlzLGo9bnVsbAppZihhLmdGaSgpLmxl
+bmd0aCE9PTApe3Q9YS5nRmkoKQppZihhLmdjaigpKXtzPWEuZ2t1KCkKcj1hLmdKZihhKQpxPWEuZ3hB
+KCk/YS5ndHAoYSk6an1lbHNle3E9agpyPXEKcz0iIn1wPVAueGUoYS5nSWkoYSkpCm89YS5nUUQoKT9h
+Lmd0UCgpOmp9ZWxzZXt0PWsuYQppZihhLmdjaigpKXtzPWEuZ2t1KCkKcj1hLmdKZihhKQpxPVAud0Io
+YS5neEEoKT9hLmd0cChhKTpqLHQpCnA9UC54ZShhLmdJaShhKSkKbz1hLmdRRCgpP2EuZ3RQKCk6an1l
+bHNle3M9ay5iCnI9ay5jCnE9ay5kCmlmKGEuZ0lpKGEpPT09IiIpe3A9ay5lCm89YS5nUUQoKT9hLmd0
+UCgpOmsuZn1lbHNle2lmKGEuZ3RUKCkpcD1QLnhlKGEuZ0lpKGEpKQplbHNle249ay5lCmlmKG4ubGVu
+Z3RoPT09MClpZihyPT1udWxsKXA9dC5sZW5ndGg9PT0wP2EuZ0lpKGEpOlAueGUoYS5nSWkoYSkpCmVs
+c2UgcD1QLnhlKCIvIithLmdJaShhKSkKZWxzZXttPWsuSmgobixhLmdJaShhKSkKbD10Lmxlbmd0aD09
+PTAKaWYoIWx8fHIhPW51bGx8fEMueEIubihuLCIvIikpcD1QLnhlKG0pCmVsc2UgcD1QLndGKG0sIWx8
+fHIhPW51bGwpfX1vPWEuZ1FEKCk/YS5ndFAoKTpqfX19cmV0dXJuIG5ldyBQLkRuKHQscyxyLHEscCxv
+LGEuZ1o4KCk/YS5nS2EoKTpqKX0sCmdjajpmdW5jdGlvbigpe3JldHVybiB0aGlzLmMhPW51bGx9LApn
+eEE6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5kIT1udWxsfSwKZ1FEOmZ1bmN0aW9uKCl7cmV0dXJuIHRo
+aXMuZiE9bnVsbH0sCmdaODpmdW5jdGlvbigpe3JldHVybiB0aGlzLnIhPW51bGx9LApndFQ6ZnVuY3Rp
+b24oKXtyZXR1cm4gQy54Qi5uKHRoaXMuZSwiLyIpfSwKdDQ6ZnVuY3Rpb24oKXt2YXIgdCxzPXRoaXMs
+cj1zLmEKaWYociE9PSIiJiZyIT09ImZpbGUiKXRocm93IEguYihQLkw0KCJDYW5ub3QgZXh0cmFjdCBh
+IGZpbGUgcGF0aCBmcm9tIGEgIityKyIgVVJJIikpCmlmKHMuZ3RQKCkhPT0iIil0aHJvdyBILmIoUC5M
+NCgiQ2Fubm90IGV4dHJhY3QgYSBmaWxlIHBhdGggZnJvbSBhIFVSSSB3aXRoIGEgcXVlcnkgY29tcG9u
+ZW50IikpCmlmKHMuZ0thKCkhPT0iIil0aHJvdyBILmIoUC5MNCgiQ2Fubm90IGV4dHJhY3QgYSBmaWxl
+IHBhdGggZnJvbSBhIFVSSSB3aXRoIGEgZnJhZ21lbnQgY29tcG9uZW50IikpCnI9JC53USgpCmlmKEgu
+b1Qocikpcj1QLm1uKHMpCmVsc2V7aWYocy5jIT1udWxsJiZzLmdKZihzKSE9PSIiKUgudmgoUC5MNCgi
+Q2Fubm90IGV4dHJhY3QgYSBub24tV2luZG93cyBmaWxlIHBhdGggZnJvbSBhIGZpbGUgVVJJIHdpdGgg
+YW4gYXV0aG9yaXR5IikpCnQ9cy5nRmooKQpQLmtFKHQsITEpCnI9UC52ZyhDLnhCLm4ocy5lLCIvIik/
+Ii8iOiIiLHQsIi8iKQpyPXIuY2hhckNvZGVBdCgwKT09MD9yOnJ9cmV0dXJuIHJ9LAp3OmZ1bmN0aW9u
+KGEpe3JldHVybiB0aGlzLmduRCgpfSwKRE46ZnVuY3Rpb24oYSxiKXt2YXIgdD10aGlzCmlmKGI9PW51
+bGwpcmV0dXJuITEKaWYodD09PWIpcmV0dXJuITAKcmV0dXJuIHUuZEQuYihiKSYmdC5hPT09Yi5nRmko
+KSYmdC5jIT1udWxsPT09Yi5nY2ooKSYmdC5iPT09Yi5na3UoKSYmdC5nSmYodCk9PT1iLmdKZihiKSYm
+dC5ndHAodCk9PT1iLmd0cChiKSYmdC5lPT09Yi5nSWkoYikmJnQuZiE9bnVsbD09PWIuZ1FEKCkmJnQu
+Z3RQKCk9PT1iLmd0UCgpJiZ0LnIhPW51bGw9PT1iLmdaOCgpJiZ0LmdLYSgpPT09Yi5nS2EoKX0sCnNL
+cDpmdW5jdGlvbihhKXt0aGlzLnk9dS5iay5hKGEpfSwKc05NOmZ1bmN0aW9uKGEpe3RoaXMuUT11LmNa
+LmEoYSl9LAokaWlEOjEsCmdGaTpmdW5jdGlvbigpe3JldHVybiB0aGlzLmF9LApnSWk6ZnVuY3Rpb24o
+YSl7cmV0dXJuIHRoaXMuZX19ClAuUloucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIFAu
+ZVAoQy5aSixILmgoYSksQy54TSwhMSl9LAokUzo1fQpQLk1FLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9u
+KGEsYil7dmFyIHQ9dGhpcy5iLHM9dGhpcy5hCnQuYSs9cy5hCnMuYT0iJiIKcz10LmErPUguRWooUC5l
+UChDLkYzLGEsQy54TSwhMCkpCmlmKGIhPW51bGwmJmIubGVuZ3RoIT09MCl7dC5hPXMrIj0iCnQuYSs9
+SC5FaihQLmVQKEMuRjMsYixDLnhNLCEwKSl9fSwKJFM6MjJ9ClAueTUucHJvdG90eXBlPXsKJDI6ZnVu
+Y3Rpb24oYSxiKXt2YXIgdCxzCkguaChhKQppZihiPT1udWxsfHx0eXBlb2YgYj09InN0cmluZyIpdGhp
+cy5hLiQyKGEsSC5rKGIpKQplbHNlIGZvcih0PUouSVQodS5wLmEoYikpLHM9dGhpcy5hO3QuRigpOylz
+LiQyKGEsSC5oKHQuZ2woKSkpfSwKJFM6MTN9ClAuUEUucHJvdG90eXBlPXsKZ2xSOmZ1bmN0aW9uKCl7
+dmFyIHQscyxyLHEscD10aGlzLG89bnVsbCxuPXAuYwppZihuPT1udWxsKXtuPXAuYgppZigwPj1uLmxl
+bmd0aClyZXR1cm4gSC5PSChuLDApCnQ9cC5hCm49blswXSsxCnM9Qy54Qi5YVSh0LCI/IixuKQpyPXQu
+bGVuZ3RoCmlmKHM+PTApe3E9UC5QSSh0LHMrMSxyLEMuVkMsITEpCnI9c31lbHNlIHE9bwpuPXAuYz1u
+ZXcgUC5xZSgiZGF0YSIsIiIsbyxvLFAuUEkodCxuLHIsQy5XZCwhMSkscSxvKX1yZXR1cm4gbn0sCnc6
+ZnVuY3Rpb24oYSl7dmFyIHQscz10aGlzLmIKaWYoMD49cy5sZW5ndGgpcmV0dXJuIEguT0gocywwKQp0
+PXRoaXMuYQpyZXR1cm4gc1swXT09PS0xPyJkYXRhOiIrdDp0fX0KUC5xMy5wcm90b3R5cGU9ewokMTpm
+dW5jdGlvbihhKXtyZXR1cm4gbmV3IFVpbnQ4QXJyYXkoOTYpfSwKJFM6MjN9ClAueUkucHJvdG90eXBl
+PXsKJDI6ZnVuY3Rpb24oYSxiKXt2YXIgdD10aGlzLmEKaWYoYT49dC5sZW5ndGgpcmV0dXJuIEguT0go
+dCxhKQp0PXRbYV0KSi5DTSh0LDAsOTYsYikKcmV0dXJuIHR9LAokUzoyNH0KUC5jNi5wcm90b3R5cGU9
+ewokMzpmdW5jdGlvbihhLGIsYyl7dmFyIHQscyxyLHEKZm9yKHQ9Yi5sZW5ndGgscz1hLmxlbmd0aCxy
+PTA7cjx0Oysrcil7cT1DLnhCLlcoYixyKV45NgppZihxPj1zKXJldHVybiBILk9IKGEscSkKYVtxXT1j
+fX19ClAucWQucHJvdG90eXBlPXsKJDM6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMscixxCmZvcih0PUMu
+eEIuVyhiLDApLHM9Qy54Qi5XKGIsMSkscj1hLmxlbmd0aDt0PD1zOysrdCl7cT0odF45Nik+Pj4wCmlm
+KHE+PXIpcmV0dXJuIEguT0goYSxxKQphW3FdPWN9fX0KUC5VZi5wcm90b3R5cGU9ewpnY2o6ZnVuY3Rp
+b24oKXtyZXR1cm4gdGhpcy5jPjB9LApneEE6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5jPjAmJnRoaXMu
+ZCsxPHRoaXMuZX0sCmdRRDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmY8dGhpcy5yfSwKZ1o4OmZ1bmN0
+aW9uKCl7cmV0dXJuIHRoaXMucjx0aGlzLmEubGVuZ3RofSwKZ053OmZ1bmN0aW9uKCl7cmV0dXJuIHRo
+aXMuYj09PTQmJkMueEIubih0aGlzLmEsImZpbGUiKX0sCmdXWjpmdW5jdGlvbigpe3JldHVybiB0aGlz
+LmI9PT00JiZDLnhCLm4odGhpcy5hLCJodHRwIil9LApnUmU6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5i
+PT09NSYmQy54Qi5uKHRoaXMuYSwiaHR0cHMiKX0sCmd0VDpmdW5jdGlvbigpe3JldHVybiBDLnhCLlFp
+KHRoaXMuYSwiLyIsdGhpcy5lKX0sCmdGaTpmdW5jdGlvbigpe3ZhciB0PXRoaXMueApyZXR1cm4gdD09
+bnVsbD90aGlzLng9dGhpcy5VMigpOnR9LApVMjpmdW5jdGlvbigpe3ZhciB0PXRoaXMscz10LmIKaWYo
+czw9MClyZXR1cm4iIgppZih0LmdXWigpKXJldHVybiJodHRwIgppZih0LmdSZSgpKXJldHVybiJodHRw
+cyIKaWYodC5nTncoKSlyZXR1cm4iZmlsZSIKaWYocz09PTcmJkMueEIubih0LmEsInBhY2thZ2UiKSly
+ZXR1cm4icGFja2FnZSIKcmV0dXJuIEMueEIuTmoodC5hLDAscyl9LApna3U6ZnVuY3Rpb24oKXt2YXIg
+dD10aGlzLmMscz10aGlzLmIrMwpyZXR1cm4gdD5zP0MueEIuTmoodGhpcy5hLHMsdC0xKToiIn0sCmdK
+ZjpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmMKcmV0dXJuIHQ+MD9DLnhCLk5qKHRoaXMuYSx0LHRoaXMu
+ZCk6IiJ9LApndHA6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcwppZih0Lmd4QSgpKXJldHVybiBQLlFBKEMu
+eEIuTmoodC5hLHQuZCsxLHQuZSksbnVsbCkKaWYodC5nV1ooKSlyZXR1cm4gODAKaWYodC5nUmUoKSly
+ZXR1cm4gNDQzCnJldHVybiAwfSwKZ0lpOmZ1bmN0aW9uKGEpe3JldHVybiBDLnhCLk5qKHRoaXMuYSx0
+aGlzLmUsdGhpcy5mKX0sCmd0UDpmdW5jdGlvbigpe3ZhciB0PXRoaXMuZixzPXRoaXMucgpyZXR1cm4g
+dDxzP0MueEIuTmoodGhpcy5hLHQrMSxzKToiIn0sCmdLYTpmdW5jdGlvbigpe3ZhciB0PXRoaXMucixz
+PXRoaXMuYQpyZXR1cm4gdDxzLmxlbmd0aD9DLnhCLkcocyx0KzEpOiIifSwKZ0ZqOmZ1bmN0aW9uKCl7
+dmFyIHQscyxyPXRoaXMuZSxxPXRoaXMuZixwPXRoaXMuYQppZihDLnhCLlFpKHAsIi8iLHIpKSsrcgpp
+ZihyPT09cSlyZXR1cm4gQy54RAp0PUguVk0oW10sdS5zKQpmb3Iocz1yO3M8cTsrK3MpaWYoQy54Qi5t
+KHAscyk9PT00Nyl7Qy5ObS5pKHQsQy54Qi5OaihwLHIscykpCnI9cysxfUMuTm0uaSh0LEMueEIuTmoo
+cCxyLHEpKQpyZXR1cm4gUC5BRih0LHUuTil9LApnaFk6ZnVuY3Rpb24oKXtpZih0aGlzLmY+PXRoaXMu
+cilyZXR1cm4gQy5XTwpyZXR1cm4gbmV3IFAuR2ooUC5XWCh0aGlzLmd0UCgpKSx1LkUpfSwKa1g6ZnVu
+Y3Rpb24oYSl7dmFyIHQ9dGhpcy5kKzEKcmV0dXJuIHQrYS5sZW5ndGg9PT10aGlzLmUmJkMueEIuUWko
+dGhpcy5hLGEsdCl9LApOOTpmdW5jdGlvbigpe3ZhciB0PXRoaXMscz10LnIscj10LmEKaWYocz49ci5s
+ZW5ndGgpcmV0dXJuIHQKcmV0dXJuIG5ldyBQLlVmKEMueEIuTmoociwwLHMpLHQuYix0LmMsdC5kLHQu
+ZSx0LmYscyx0LngpfSwKbm06ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsayxqPXRo
+aXMsaT1udWxsCnUuYzkuYShiKQp0PWouZ0ZpKCkKcz10PT09ImZpbGUiCnI9ai5jCnE9cj4wP0MueEIu
+Tmooai5hLGouYiszLHIpOiIiCnA9ai5neEEoKT9qLmd0cChqKTppCnI9ai5jCmlmKHI+MClvPUMueEIu
+Tmooai5hLHIsai5kKQplbHNlIG89cS5sZW5ndGghPT0wfHxwIT1udWxsfHxzPyIiOmkKcj1qLmEKbj1D
+LnhCLk5qKHIsai5lLGouZikKaWYoIXMpbT1vIT1udWxsJiZuLmxlbmd0aCE9PTAKZWxzZSBtPSEwCmlm
+KG0mJiFDLnhCLm4obiwiLyIpKW49Ii8iK24KbD1QLmxlKGksMCwwLGIpCm09ai5yCms9bTxyLmxlbmd0
+aD9DLnhCLkcocixtKzEpOmkKcmV0dXJuIG5ldyBQLkRuKHQscSxvLHAsbixsLGspfSwKWkk6ZnVuY3Rp
+b24oYSl7cmV0dXJuIHRoaXMubVMoUC5oSyhhKSl9LAptUzpmdW5jdGlvbihhKXtpZihhIGluc3RhbmNl
+b2YgUC5VZilyZXR1cm4gdGhpcy51MSh0aGlzLGEpCnJldHVybiB0aGlzLnZzKCkubVMoYSl9LAp1MTpm
+dW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHAsbyxuLG0sbCxrLGosaSxoPWIuYgppZihoPjApcmV0dXJu
+IGIKdD1iLmMKaWYodD4wKXtzPWEuYgppZihzPD0wKXJldHVybiBiCmlmKGEuZ053KCkpcj1iLmUhPT1i
+LmYKZWxzZSBpZihhLmdXWigpKXI9IWIua1goIjgwIikKZWxzZSByPSFhLmdSZSgpfHwhYi5rWCgiNDQz
+IikKaWYocil7cT1zKzEKcmV0dXJuIG5ldyBQLlVmKEMueEIuTmooYS5hLDAscSkrQy54Qi5HKGIuYSxo
+KzEpLHMsdCtxLGIuZCtxLGIuZStxLGIuZitxLGIucitxLGEueCl9ZWxzZSByZXR1cm4gdGhpcy52cygp
+Lm1TKGIpfXA9Yi5lCmg9Yi5mCmlmKHA9PT1oKXt0PWIucgppZihoPHQpe3M9YS5mCnE9cy1oCnJldHVy
+biBuZXcgUC5VZihDLnhCLk5qKGEuYSwwLHMpK0MueEIuRyhiLmEsaCksYS5iLGEuYyxhLmQsYS5lLGgr
+cSx0K3EsYS54KX1oPWIuYQppZih0PGgubGVuZ3RoKXtzPWEucgpyZXR1cm4gbmV3IFAuVWYoQy54Qi5O
+aihhLmEsMCxzKStDLnhCLkcoaCx0KSxhLmIsYS5jLGEuZCxhLmUsYS5mLHQrKHMtdCksYS54KX1yZXR1
+cm4gYS5OOSgpfXQ9Yi5hCmlmKEMueEIuUWkodCwiLyIscCkpe3M9YS5lCnE9cy1wCnJldHVybiBuZXcg
+UC5VZihDLnhCLk5qKGEuYSwwLHMpK0MueEIuRyh0LHApLGEuYixhLmMsYS5kLHMsaCtxLGIucitxLGEu
+eCl9bz1hLmUKbj1hLmYKaWYobz09PW4mJmEuYz4wKXtmb3IoO0MueEIuUWkodCwiLi4vIixwKTspcCs9
+MwpxPW8tcCsxCnJldHVybiBuZXcgUC5VZihDLnhCLk5qKGEuYSwwLG8pKyIvIitDLnhCLkcodCxwKSxh
+LmIsYS5jLGEuZCxvLGgrcSxiLnIrcSxhLngpfW09YS5hCmZvcihsPW87Qy54Qi5RaShtLCIuLi8iLGwp
+OylsKz0zCms9MAp3aGlsZSghMCl7aj1wKzMKaWYoIShqPD1oJiZDLnhCLlFpKHQsIi4uLyIscCkpKWJy
+ZWFrOysrawpwPWp9Zm9yKGk9IiI7bj5sOyl7LS1uCmlmKEMueEIubShtLG4pPT09NDcpe2lmKGs9PT0w
+KXtpPSIvIgpicmVha30tLWsKaT0iLyJ9fWlmKG49PT1sJiZhLmI8PTAmJiFDLnhCLlFpKG0sIi8iLG8p
+KXtwLT1rKjMKaT0iIn1xPW4tcCtpLmxlbmd0aApyZXR1cm4gbmV3IFAuVWYoQy54Qi5OaihtLDAsbikr
+aStDLnhCLkcodCxwKSxhLmIsYS5jLGEuZCxvLGgrcSxiLnIrcSxhLngpfSwKdDQ6ZnVuY3Rpb24oKXt2
+YXIgdCxzLHIscT10aGlzCmlmKHEuYj49MCYmIXEuZ053KCkpdGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBl
+eHRyYWN0IGEgZmlsZSBwYXRoIGZyb20gYSAiK3EuZ0ZpKCkrIiBVUkkiKSkKdD1xLmYKcz1xLmEKaWYo
+dDxzLmxlbmd0aCl7aWYodDxxLnIpdGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBleHRyYWN0IGEgZmlsZSBw
+YXRoIGZyb20gYSBVUkkgd2l0aCBhIHF1ZXJ5IGNvbXBvbmVudCIpKQp0aHJvdyBILmIoUC5MNCgiQ2Fu
+bm90IGV4dHJhY3QgYSBmaWxlIHBhdGggZnJvbSBhIFVSSSB3aXRoIGEgZnJhZ21lbnQgY29tcG9uZW50
+IikpfXI9JC53USgpCmlmKEgub1QocikpdD1QLm1uKHEpCmVsc2V7aWYocS5jPHEuZClILnZoKFAuTDQo
+IkNhbm5vdCBleHRyYWN0IGEgbm9uLVdpbmRvd3MgZmlsZSBwYXRoIGZyb20gYSBmaWxlIFVSSSB3aXRo
+IGFuIGF1dGhvcml0eSIpKQp0PUMueEIuTmoocyxxLmUsdCl9cmV0dXJuIHR9LApnaU86ZnVuY3Rpb24o
+YSl7dmFyIHQ9dGhpcy55CnJldHVybiB0PT1udWxsP3RoaXMueT1DLnhCLmdpTyh0aGlzLmEpOnR9LApE
+TjpmdW5jdGlvbihhLGIpe2lmKGI9PW51bGwpcmV0dXJuITEKaWYodGhpcz09PWIpcmV0dXJuITAKcmV0
+dXJuIHUuZEQuYihiKSYmdGhpcy5hPT09Yi53KDApfSwKdnM6ZnVuY3Rpb24oKXt2YXIgdD10aGlzLHM9
+bnVsbCxyPXQuZ0ZpKCkscT10LmdrdSgpLHA9dC5jPjA/dC5nSmYodCk6cyxvPXQuZ3hBKCk/dC5ndHAo
+dCk6cyxuPXQuYSxtPXQuZixsPUMueEIuTmoobix0LmUsbSksaz10LnIKbT1tPGs/dC5ndFAoKTpzCnJl
+dHVybiBuZXcgUC5EbihyLHEscCxvLGwsbSxrPG4ubGVuZ3RoP3QuZ0thKCk6cyl9LAp3OmZ1bmN0aW9u
+KGEpe3JldHVybiB0aGlzLmF9LAokaWlEOjF9ClAucWUucHJvdG90eXBlPXt9ClcucUUucHJvdG90eXBl
+PXt9ClcuR2gucHJvdG90eXBlPXsKdzpmdW5jdGlvbihhKXtyZXR1cm4gU3RyaW5nKGEpfSwKJGlHaDox
+fQpXLmZZLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIFN0cmluZyhhKX19ClcubkIucHJv
+dG90eXBlPXskaW5COjF9ClcuQXoucHJvdG90eXBlPXskaUF6OjF9ClcuUVAucHJvdG90eXBlPXskaVFQ
+OjF9ClcubngucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofX0KVy5vSi5w
+cm90b3R5cGU9ewpnQTpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9fQpXLmlkLnByb3RvdHlwZT17
+fQpXLlFGLnByb3RvdHlwZT17fQpXLk5oLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIFN0
+cmluZyhhKX19ClcuYWUucHJvdG90eXBlPXsKRGM6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gYS5jcmVhdGVI
+VE1MRG9jdW1lbnQoYil9fQpXLklCLnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIlJlY3Rh
+bmdsZSAoIitILkVqKGEubGVmdCkrIiwgIitILkVqKGEudG9wKSsiKSAiK0guRWooYS53aWR0aCkrIiB4
+ICIrSC5FaihhLmhlaWdodCl9LApETjpmdW5jdGlvbihhLGIpe2lmKGI9PW51bGwpcmV0dXJuITEKcmV0
+dXJuIHUucS5iKGIpJiZhLmxlZnQ9PWIubGVmdCYmYS50b3A9PWIudG9wJiZhLndpZHRoPT1iLndpZHRo
+JiZhLmhlaWdodD09Yi5oZWlnaHR9LApnaU86ZnVuY3Rpb24oYSl7cmV0dXJuIFcuckUoSi5oZihhLmxl
+ZnQpLEouaGYoYS50b3ApLEouaGYoYS53aWR0aCksSi5oZihhLmhlaWdodCkpfSwKJGl0bjoxfQpXLm43
+LnByb3RvdHlwZT17CmdBOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH19Clcud3oucHJvdG90eXBl
+PXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYS5sZW5ndGh9LApxOmZ1bmN0aW9uKGEsYil7dmFy
+IHQKSC51UChiKQp0PXRoaXMuYQppZihiPDB8fGI+PXQubGVuZ3RoKXJldHVybiBILk9IKHQsYikKcmV0
+dXJuIHRoaXMuJHRpLmMuYSh0W2JdKX0sClk6ZnVuY3Rpb24oYSxiLGMpe3RoaXMuJHRpLmMuYShjKQp0
+aHJvdyBILmIoUC5MNCgiQ2Fubm90IG1vZGlmeSBsaXN0IikpfX0KVy5jdi5wcm90b3R5cGU9ewpnUWc6
+ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBXLmk3KGEpfSwKZ1A6ZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBX
+Lkk0KGEpfSwKc1A6ZnVuY3Rpb24oYSxiKXt2YXIgdAp1LlEuYShiKQp0PXRoaXMuZ1AoYSkKdC5WMSgw
+KQp0LkZWKDAsYil9LAp3OmZ1bmN0aW9uKGEpe3JldHVybiBhLmxvY2FsTmFtZX0sCkZGOmZ1bmN0aW9u
+KGEpe3ZhciB0PSEhYS5zY3JvbGxJbnRvVmlld0lmTmVlZGVkCmlmKHQpYS5zY3JvbGxJbnRvVmlld0lm
+TmVlZGVkKCkKZWxzZSBhLnNjcm9sbEludG9WaWV3KCl9LApuejpmdW5jdGlvbihhLGIsYyxkLGUpe3Zh
+ciB0LHM9dGhpcy5yNihhLGMsZCxlKQpzd2l0Y2goYi50b0xvd2VyQ2FzZSgpKXtjYXNlImJlZm9yZWJl
+Z2luIjp0PWEucGFyZW50Tm9kZQp0LnRvU3RyaW5nCkouRWgodCxzLGEpCmJyZWFrCmNhc2UiYWZ0ZXJi
+ZWdpbiI6dD1hLmNoaWxkTm9kZXMKdGhpcy5tSyhhLHMsdC5sZW5ndGg+MD90WzBdOm51bGwpCmJyZWFr
+CmNhc2UiYmVmb3JlZW5kIjphLmFwcGVuZENoaWxkKHMpCmJyZWFrCmNhc2UiYWZ0ZXJlbmQiOnQ9YS5w
+YXJlbnROb2RlCnQudG9TdHJpbmcKSi5FaCh0LHMsYS5uZXh0U2libGluZykKYnJlYWsKZGVmYXVsdDpI
+LnZoKFAueFkoIkludmFsaWQgcG9zaXRpb24gIitiKSl9fSwKcjY6ZnVuY3Rpb24oYSxiLGMsZCl7dmFy
+IHQscyxyLHEKaWYoYz09bnVsbCl7aWYoZD09bnVsbCl7dD0kLmx0CmlmKHQ9PW51bGwpe3Q9SC5WTShb
+XSx1LnIpCnM9bmV3IFcudkQodCkKQy5ObS5pKHQsVy5UdyhudWxsKSkKQy5ObS5pKHQsVy5CbCgpKQok
+Lmx0PXMKZD1zfWVsc2UgZD10fXQ9JC5FVQppZih0PT1udWxsKXt0PW5ldyBXLktvKGQpCiQuRVU9dApj
+PXR9ZWxzZXt0LmE9ZApjPXR9fWVsc2UgaWYoZCE9bnVsbCl0aHJvdyBILmIoUC54WSgidmFsaWRhdG9y
+IGNhbiBvbmx5IGJlIHBhc3NlZCBpZiB0cmVlU2FuaXRpemVyIGlzIG51bGwiKSkKaWYoJC54bz09bnVs
+bCl7dD1kb2N1bWVudApzPXQuaW1wbGVtZW50YXRpb24Kcz0ocyYmQy5tSCkuRGMocywiIikKJC54bz1z
+CiQuQk89cy5jcmVhdGVSYW5nZSgpCnM9JC54by5jcmVhdGVFbGVtZW50KCJiYXNlIikKdS5jUi5hKHMp
+CnMuaHJlZj10LmJhc2VVUkkKJC54by5oZWFkLmFwcGVuZENoaWxkKHMpfXQ9JC54bwppZih0LmJvZHk9
+PW51bGwpe3M9dC5jcmVhdGVFbGVtZW50KCJib2R5IikKQy5CWi5zWEcodCx1LmsuYShzKSl9dD0kLnhv
+CmlmKHUuay5iKGEpKXt0PXQuYm9keQp0LnRvU3RyaW5nCnI9dH1lbHNle3QudG9TdHJpbmcKcj10LmNy
+ZWF0ZUVsZW1lbnQoYS50YWdOYW1lKQokLnhvLmJvZHkuYXBwZW5kQ2hpbGQocil9aWYoImNyZWF0ZUNv
+bnRleHR1YWxGcmFnbWVudCIgaW4gd2luZG93LlJhbmdlLnByb3RvdHlwZSYmIUMuTm0udGcoQy5TcSxh
+LnRhZ05hbWUpKXskLkJPLnNlbGVjdE5vZGVDb250ZW50cyhyKQp0PSQuQk8KdC50b1N0cmluZwpxPXQu
+Y3JlYXRlQ29udGV4dHVhbEZyYWdtZW50KGI9PW51bGw/Im51bGwiOmIpfWVsc2V7Si53ZihyLGIpCnE9
+JC54by5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCkKZm9yKDt0PXIuZmlyc3RDaGlsZCx0IT1udWxsOylx
+LmFwcGVuZENoaWxkKHQpfWlmKHIhPT0kLnhvLmJvZHkpSi5MdChyKQpjLlBuKHEpCmRvY3VtZW50LmFk
+b3B0Tm9kZShxKQpyZXR1cm4gcX0sCkFIOmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gdGhpcy5yNihhLGIs
+YyxudWxsKX0sCnNoZjpmdW5jdGlvbihhLGIpe3RoaXMuWUMoYSxiKX0sCnBrOmZ1bmN0aW9uKGEsYixj
+KXt0aGlzLnNhNChhLG51bGwpCmEuYXBwZW5kQ2hpbGQodGhpcy5yNihhLGIsbnVsbCxjKSl9LApZQzpm
+dW5jdGlvbihhLGIpe3JldHVybiB0aGlzLnBrKGEsYixudWxsKX0sCnNSTjpmdW5jdGlvbihhLGIpe2Eu
+aW5uZXJIVE1MPWJ9LApnbnM6ZnVuY3Rpb24oYSl7cmV0dXJuIGEudGFnTmFtZX0sCmdWbDpmdW5jdGlv
+bihhKXtyZXR1cm4gbmV3IFcuZXUoYSwiY2xpY2siLCExLHUuail9LAokaWN2OjF9ClcuQ3YucHJvdG90
+eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIHUuaC5iKHUuQS5hKGEpKX0sCiRTOjI1fQpXLmVhLnBy
+b3RvdHlwZT17JGllYToxfQpXLkQwLnByb3RvdHlwZT17Ck9uOmZ1bmN0aW9uKGEsYixjLGQpe3UuYncu
+YShjKQppZihjIT1udWxsKXRoaXMudihhLGIsYyxkKX0sCkI6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiB0
+aGlzLk9uKGEsYixjLG51bGwpfSwKdjpmdW5jdGlvbihhLGIsYyxkKXtyZXR1cm4gYS5hZGRFdmVudExp
+c3RlbmVyKGIsSC50Uih1LmJ3LmEoYyksMSksZCl9LAokaUQwOjF9ClcuaEgucHJvdG90eXBlPXskaWhI
+OjF9ClcuaDQucHJvdG90eXBlPXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofX0KVy5ici5w
+cm90b3R5cGU9ewpnQTpmdW5jdGlvbihhKXtyZXR1cm4gYS5sZW5ndGh9fQpXLlZiLnByb3RvdHlwZT17
+CnNYRzpmdW5jdGlvbihhLGIpe2EuYm9keT1ifX0KVy5mSi5wcm90b3R5cGU9ewplbzpmdW5jdGlvbihh
+LGIsYyxkKXtyZXR1cm4gYS5vcGVuKGIsYywhMCl9LAokaWZKOjF9Clcud2EucHJvdG90eXBlPXt9Clcu
+U2cucHJvdG90eXBlPXskaVNnOjF9ClcudTgucHJvdG90eXBlPXsKZ0RyOmZ1bmN0aW9uKGEpe2lmKCJv
+cmlnaW4iIGluIGEpcmV0dXJuIGEub3JpZ2luCnJldHVybiBILkVqKGEucHJvdG9jb2wpKyIvLyIrSC5F
+aihhLmhvc3QpfSwKdzpmdW5jdGlvbihhKXtyZXR1cm4gU3RyaW5nKGEpfSwKJGl1ODoxfQpXLkFqLnBy
+b3RvdHlwZT17JGlBajoxfQpXLmU3LnByb3RvdHlwZT17CmdyODpmdW5jdGlvbihhKXt2YXIgdD10aGlz
+LmEscz10LmNoaWxkTm9kZXMubGVuZ3RoCmlmKHM9PT0wKXRocm93IEguYihQLlBWKCJObyBlbGVtZW50
+cyIpKQppZihzPjEpdGhyb3cgSC5iKFAuUFYoIk1vcmUgdGhhbiBvbmUgZWxlbWVudCIpKQp0PXQuZmly
+c3RDaGlsZAp0LnRvU3RyaW5nCnJldHVybiB0fSwKRlY6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxw
+CnUuZWguYShiKQp0PWIuYQpzPXRoaXMuYQppZih0IT09cylmb3Iocj10LmNoaWxkTm9kZXMubGVuZ3Ro
+LHE9MDtxPHI7KytxKXtwPXQuZmlyc3RDaGlsZApwLnRvU3RyaW5nCnMuYXBwZW5kQ2hpbGQocCl9cmV0
+dXJufSwKWTpmdW5jdGlvbihhLGIsYyl7dmFyIHQscwp1LkEuYShjKQp0PXRoaXMuYQpzPXQuY2hpbGRO
+b2RlcwppZihiPDB8fGI+PXMubGVuZ3RoKXJldHVybiBILk9IKHMsYikKdC5yZXBsYWNlQ2hpbGQoYyxz
+W2JdKX0sCmdrejpmdW5jdGlvbihhKXt2YXIgdD10aGlzLmEuY2hpbGROb2RlcwpyZXR1cm4gbmV3IFcu
+VzkodCx0Lmxlbmd0aCxILnoodCkuQygiVzk8R20uRT4iKSl9LApnQTpmdW5jdGlvbihhKXtyZXR1cm4g
+dGhpcy5hLmNoaWxkTm9kZXMubGVuZ3RofSwKcTpmdW5jdGlvbihhLGIpe3ZhciB0CkgudVAoYikKdD10
+aGlzLmEuY2hpbGROb2RlcwppZihiPDB8fGI+PXQubGVuZ3RoKXJldHVybiBILk9IKHQsYikKcmV0dXJu
+IHRbYl19fQpXLnVILnByb3RvdHlwZT17CndnOmZ1bmN0aW9uKGEpe3ZhciB0PWEucGFyZW50Tm9kZQpp
+Zih0IT1udWxsKXQucmVtb3ZlQ2hpbGQoYSl9LApENDpmdW5jdGlvbihhKXt2YXIgdApmb3IoO3Q9YS5m
+aXJzdENoaWxkLHQhPW51bGw7KWEucmVtb3ZlQ2hpbGQodCl9LAp3OmZ1bmN0aW9uKGEpe3ZhciB0PWEu
+bm9kZVZhbHVlCnJldHVybiB0PT1udWxsP3RoaXMuVShhKTp0fSwKc2E0OmZ1bmN0aW9uKGEsYil7YS50
+ZXh0Q29udGVudD1ifSwKbUs6ZnVuY3Rpb24oYSxiLGMpe3JldHVybiBhLmluc2VydEJlZm9yZShiLGMp
+fSwKJGl1SDoxfQpXLkJILnByb3RvdHlwZT17CmdBOmZ1bmN0aW9uKGEpe3JldHVybiBhLmxlbmd0aH0s
+CnE6ZnVuY3Rpb24oYSxiKXtILnVQKGIpCmlmKGI+Pj4wIT09Ynx8Yj49YS5sZW5ndGgpdGhyb3cgSC5i
+KFAuQ2YoYixhLG51bGwsbnVsbCxudWxsKSkKcmV0dXJuIGFbYl19LApZOmZ1bmN0aW9uKGEsYixjKXt1
+LkEuYShjKQp0aHJvdyBILmIoUC5MNCgiQ2Fubm90IGFzc2lnbiBlbGVtZW50IG9mIGltbXV0YWJsZSBM
+aXN0LiIpKX0sCmd0SDpmdW5jdGlvbihhKXtpZihhLmxlbmd0aD4wKXJldHVybiBhWzBdCnRocm93IEgu
+YihQLlBWKCJObyBlbGVtZW50cyIpKX0sCkU6ZnVuY3Rpb24oYSxiKXtpZihiPDB8fGI+PWEubGVuZ3Ro
+KXJldHVybiBILk9IKGEsYikKcmV0dXJuIGFbYl19LAokaWJROjEsCiRpWGo6MSwKJGljWDoxLAokaXpN
+OjF9ClcuU04ucHJvdG90eXBlPXt9ClcuZXcucHJvdG90eXBlPXskaWV3OjF9ClcubHAucHJvdG90eXBl
+PXsKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIGEubGVuZ3RofX0KVy5UYi5wcm90b3R5cGU9ewpyNjpmdW5j
+dGlvbihhLGIsYyxkKXt2YXIgdCxzCmlmKCJjcmVhdGVDb250ZXh0dWFsRnJhZ21lbnQiIGluIHdpbmRv
+dy5SYW5nZS5wcm90b3R5cGUpcmV0dXJuIHRoaXMuRFcoYSxiLGMsZCkKdD1XLlU5KCI8dGFibGU+IitI
+LkVqKGIpKyI8L3RhYmxlPiIsYyxkKQpzPWRvY3VtZW50LmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKQpz
+LnRvU3RyaW5nCnQudG9TdHJpbmcKbmV3IFcuZTcocykuRlYoMCxuZXcgVy5lNyh0KSkKcmV0dXJuIHN9
+fQpXLkl2LnByb3RvdHlwZT17CnI2OmZ1bmN0aW9uKGEsYixjLGQpe3ZhciB0LHMscixxCmlmKCJjcmVh
+dGVDb250ZXh0dWFsRnJhZ21lbnQiIGluIHdpbmRvdy5SYW5nZS5wcm90b3R5cGUpcmV0dXJuIHRoaXMu
+RFcoYSxiLGMsZCkKdD1kb2N1bWVudApzPXQuY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgpCnQ9Qy5JZS5y
+Nih0LmNyZWF0ZUVsZW1lbnQoInRhYmxlIiksYixjLGQpCnQudG9TdHJpbmcKdD1uZXcgVy5lNyh0KQpy
+PXQuZ3I4KHQpCnIudG9TdHJpbmcKdD1uZXcgVy5lNyhyKQpxPXQuZ3I4KHQpCnMudG9TdHJpbmcKcS50
+b1N0cmluZwpuZXcgVy5lNyhzKS5GVigwLG5ldyBXLmU3KHEpKQpyZXR1cm4gc319ClcuV1AucHJvdG90
+eXBlPXsKcjY6ZnVuY3Rpb24oYSxiLGMsZCl7dmFyIHQscyxyCmlmKCJjcmVhdGVDb250ZXh0dWFsRnJh
+Z21lbnQiIGluIHdpbmRvdy5SYW5nZS5wcm90b3R5cGUpcmV0dXJuIHRoaXMuRFcoYSxiLGMsZCkKdD1k
+b2N1bWVudApzPXQuY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgpCnQ9Qy5JZS5yNih0LmNyZWF0ZUVsZW1l
+bnQoInRhYmxlIiksYixjLGQpCnQudG9TdHJpbmcKdD1uZXcgVy5lNyh0KQpyPXQuZ3I4KHQpCnMudG9T
+dHJpbmcKci50b1N0cmluZwpuZXcgVy5lNyhzKS5GVigwLG5ldyBXLmU3KHIpKQpyZXR1cm4gc319Clcu
+eVkucHJvdG90eXBlPXsKcGs6ZnVuY3Rpb24oYSxiLGMpe3ZhciB0LHMKdGhpcy5zYTQoYSxudWxsKQp0
+PWEuY29udGVudAp0LnRvU3RyaW5nCkouYlQodCkKcz10aGlzLnI2KGEsYixudWxsLGMpCmEuY29udGVu
+dC5hcHBlbmRDaGlsZChzKX0sCllDOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMucGsoYSxiLG51bGwp
+fSwKJGl5WToxfQpXLnc2LnByb3RvdHlwZT17fQpXLks1LnByb3RvdHlwZT17ClBvOmZ1bmN0aW9uKGEs
+YixjKXt2YXIgdD1XLlAxKGEub3BlbihiLGMpKQpyZXR1cm4gdH0sCmdtVzpmdW5jdGlvbihhKXtyZXR1
+cm4gYS5sb2NhdGlvbn0sCnVzOmZ1bmN0aW9uKGEsYil7cmV0dXJuIGEuY29uZmlybShiKX0sCiRpSzU6
+MSwKJGl2NjoxfQpXLkNtLnByb3RvdHlwZT17JGlDbToxfQpXLkNRLnByb3RvdHlwZT17JGlDUToxfQpX
+Lnc0LnByb3RvdHlwZT17Cnc6ZnVuY3Rpb24oYSl7cmV0dXJuIlJlY3RhbmdsZSAoIitILkVqKGEubGVm
+dCkrIiwgIitILkVqKGEudG9wKSsiKSAiK0guRWooYS53aWR0aCkrIiB4ICIrSC5FaihhLmhlaWdodCl9
+LApETjpmdW5jdGlvbihhLGIpe2lmKGI9PW51bGwpcmV0dXJuITEKcmV0dXJuIHUucS5iKGIpJiZhLmxl
+ZnQ9PWIubGVmdCYmYS50b3A9PWIudG9wJiZhLndpZHRoPT1iLndpZHRoJiZhLmhlaWdodD09Yi5oZWln
+aHR9LApnaU86ZnVuY3Rpb24oYSl7cmV0dXJuIFcuckUoSi5oZihhLmxlZnQpLEouaGYoYS50b3ApLEou
+aGYoYS53aWR0aCksSi5oZihhLmhlaWdodCkpfX0KVy5yaC5wcm90b3R5cGU9ewpnQTpmdW5jdGlvbihh
+KXtyZXR1cm4gYS5sZW5ndGh9LApxOmZ1bmN0aW9uKGEsYil7SC51UChiKQppZihiPj4+MCE9PWJ8fGI+
+PWEubGVuZ3RoKXRocm93IEguYihQLkNmKGIsYSxudWxsLG51bGwsbnVsbCkpCnJldHVybiBhW2JdfSwK
+WTpmdW5jdGlvbihhLGIsYyl7dS5BLmEoYykKdGhyb3cgSC5iKFAuTDQoIkNhbm5vdCBhc3NpZ24gZWxl
+bWVudCBvZiBpbW11dGFibGUgTGlzdC4iKSl9LApFOmZ1bmN0aW9uKGEsYil7aWYoYjwwfHxiPj1hLmxl
+bmd0aClyZXR1cm4gSC5PSChhLGIpCnJldHVybiBhW2JdfSwKJGliUToxLAokaVhqOjEsCiRpY1g6MSwK
+JGl6TToxfQpXLmNmLnByb3RvdHlwZT17Cks6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxwCnUuZUEu
+YShiKQpmb3IodD10aGlzLmdWKCkscz10Lmxlbmd0aCxyPXRoaXMuYSxxPTA7cTx0Lmxlbmd0aDt0Lmxl
+bmd0aD09PXN8fCgwLEgubGspKHQpLCsrcSl7cD10W3FdCmIuJDIocCxyLmdldEF0dHJpYnV0ZShwKSl9
+fSwKZ1Y6ZnVuY3Rpb24oKXt2YXIgdCxzLHIscSxwPXRoaXMuYS5hdHRyaWJ1dGVzLG89SC5WTShbXSx1
+LnMpCmZvcih0PXAubGVuZ3RoLHM9dS5oOSxyPTA7cjx0Oysrcil7aWYocj49cC5sZW5ndGgpcmV0dXJu
+IEguT0gocCxyKQpxPXMuYShwW3JdKQppZihxLm5hbWVzcGFjZVVSST09bnVsbClDLk5tLmkobyxxLm5h
+bWUpfXJldHVybiBvfSwKZ2wwOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmdWKCkubGVuZ3RoPT09MH19
+ClcuaTcucHJvdG90eXBlPXsKeDQ6ZnVuY3Rpb24oYSl7dmFyIHQ9SC5vVCh0aGlzLmEuaGFzQXR0cmli
+dXRlKGEpKQpyZXR1cm4gdH0sCnE6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gdGhpcy5hLmdldEF0dHJpYnV0
+ZShILmgoYikpfSwKWTpmdW5jdGlvbihhLGIsYyl7dGhpcy5hLnNldEF0dHJpYnV0ZShiLGMpfSwKZ0E6
+ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuZ1YoKS5sZW5ndGh9fQpXLlN5LnByb3RvdHlwZT17Cng0OmZ1
+bmN0aW9uKGEpe3ZhciB0PUgub1QodGhpcy5hLmEuaGFzQXR0cmlidXRlKCJkYXRhLSIrdGhpcy5PKGEp
+KSkKcmV0dXJuIHR9LApxOmZ1bmN0aW9uKGEsYil7cmV0dXJuIHRoaXMuYS5hLmdldEF0dHJpYnV0ZSgi
+ZGF0YS0iK3RoaXMuTyhILmgoYikpKX0sClk6ZnVuY3Rpb24oYSxiLGMpe3RoaXMuYS5hLnNldEF0dHJp
+YnV0ZSgiZGF0YS0iK3RoaXMuTyhiKSxjKX0sCks6ZnVuY3Rpb24oYSxiKXt0aGlzLmEuSygwLG5ldyBX
+LktTKHRoaXMsdS5lQS5hKGIpKSl9LApnVjpmdW5jdGlvbigpe3ZhciB0PUguVk0oW10sdS5zKQp0aGlz
+LmEuSygwLG5ldyBXLkEzKHRoaXMsdCkpCnJldHVybiB0fSwKZ0E6ZnVuY3Rpb24oYSl7cmV0dXJuIHRo
+aXMuZ1YoKS5sZW5ndGh9LApnbDA6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuZ1YoKS5sZW5ndGg9PT0w
+fSwKazpmdW5jdGlvbihhKXt2YXIgdCxzLHI9SC5WTShhLnNwbGl0KCItIiksdS5zKQpmb3IodD0xO3Q8
+ci5sZW5ndGg7Kyt0KXtzPXJbdF0KaWYocy5sZW5ndGg+MClDLk5tLlkocix0LHNbMF0udG9VcHBlckNh
+c2UoKStKLktWKHMsMSkpfXJldHVybiBDLk5tLkgociwiIil9LApPOmZ1bmN0aW9uKGEpe3ZhciB0LHMs
+cixxLHAKZm9yKHQ9YS5sZW5ndGgscz0wLHI9IiI7czx0Oysrcyl7cT1hW3NdCnA9cS50b0xvd2VyQ2Fz
+ZSgpCnI9KHEhPT1wJiZzPjA/cisiLSI6cikrcH1yZXR1cm4gci5jaGFyQ29kZUF0KDApPT0wP3I6cn19
+ClcuS1MucHJvdG90eXBlPXsKJDI6ZnVuY3Rpb24oYSxiKXtpZihKLnJZKGEpLm4oYSwiZGF0YS0iKSl0
+aGlzLmIuJDIodGhpcy5hLmsoQy54Qi5HKGEsNSkpLGIpfSwKJFM6MTB9ClcuQTMucHJvdG90eXBlPXsK
+JDI6ZnVuY3Rpb24oYSxiKXtpZihKLnJZKGEpLm4oYSwiZGF0YS0iKSlDLk5tLmkodGhpcy5iLHRoaXMu
+YS5rKEMueEIuRyhhLDUpKSl9LAokUzoxMH0KVy5JNC5wcm90b3R5cGU9ewpERzpmdW5jdGlvbigpe3Zh
+ciB0LHMscixxLHA9UC5Mcyh1Lk4pCmZvcih0PXRoaXMuYS5jbGFzc05hbWUuc3BsaXQoIiAiKSxzPXQu
+bGVuZ3RoLHI9MDtyPHM7KytyKXtxPUouVDAodFtyXSkKaWYocS5sZW5ndGghPT0wKXAuaSgwLHEpfXJl
+dHVybiBwfSwKWDpmdW5jdGlvbihhKXt0aGlzLmEuY2xhc3NOYW1lPXUuQy5hKGEpLkgoMCwiICIpfSwK
+Z0E6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuYS5jbGFzc0xpc3QubGVuZ3RofSwKVjE6ZnVuY3Rpb24o
+YSl7dGhpcy5hLmNsYXNzTmFtZT0iIn0sCnRnOmZ1bmN0aW9uKGEsYil7dmFyIHQ9dGhpcy5hLmNsYXNz
+TGlzdC5jb250YWlucyhiKQpyZXR1cm4gdH0sCmk6ZnVuY3Rpb24oYSxiKXt2YXIgdD10aGlzLmEuY2xh
+c3NMaXN0LHM9dC5jb250YWlucyhiKQp0LmFkZChiKQpyZXR1cm4hc30sClI6ZnVuY3Rpb24oYSxiKXt2
+YXIgdD10aGlzLmEuY2xhc3NMaXN0LHM9dC5jb250YWlucyhiKQp0LnJlbW92ZShiKQpyZXR1cm4gc30s
+CkZWOmZ1bmN0aW9uKGEsYil7Vy5UTih0aGlzLmEsdS5RLmEoYikpfX0KVy5Gay5wcm90b3R5cGU9e30K
+Vy5STy5wcm90b3R5cGU9e30KVy5ldS5wcm90b3R5cGU9e30KVy54Qy5wcm90b3R5cGU9e30KVy52Ti5w
+cm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5hLiQxKHUuQi5hKGEpKX0sCiRTOjI3
+fQpXLkpRLnByb3RvdHlwZT17CkNZOmZ1bmN0aW9uKGEpe3ZhciB0CmlmKCQub3IuYT09PTApe2Zvcih0
+PTA7dDwyNjI7Kyt0KSQub3IuWSgwLEMuY21bdF0sVy5wUygpKQpmb3IodD0wO3Q8MTI7Kyt0KSQub3Iu
+WSgwLEMuQklbdF0sVy5WNCgpKX19LAppMDpmdW5jdGlvbihhKXtyZXR1cm4gJC5BTigpLnRnKDAsVy5y
+UyhhKSl9LApFYjpmdW5jdGlvbihhLGIsYyl7dmFyIHQ9JC5vci5xKDAsSC5FaihXLnJTKGEpKSsiOjoi
+K2IpCmlmKHQ9PW51bGwpdD0kLm9yLnEoMCwiKjo6IitiKQppZih0PT1udWxsKXJldHVybiExCnJldHVy
+biBILnk4KHQuJDQoYSxiLGMsdGhpcykpfSwKJGlrRjoxfQpXLkdtLnByb3RvdHlwZT17CmdrejpmdW5j
+dGlvbihhKXtyZXR1cm4gbmV3IFcuVzkoYSx0aGlzLmdBKGEpLEgueihhKS5DKCJXOTxHbS5FPiIpKX19
+ClcudkQucHJvdG90eXBlPXsKaTA6ZnVuY3Rpb24oYSl7cmV0dXJuIEMuTm0uVnIodGhpcy5hLG5ldyBX
+LlV2KGEpKX0sCkViOmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4gQy5ObS5Wcih0aGlzLmEsbmV3IFcuRWco
+YSxiLGMpKX0sCiRpa0Y6MX0KVy5Vdi5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gdS5E
+LmEoYSkuaTAodGhpcy5hKX0sCiRTOjE0fQpXLkVnLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3Jl
+dHVybiB1LkQuYShhKS5FYih0aGlzLmEsdGhpcy5iLHRoaXMuYyl9LAokUzoxNH0KVy5tNi5wcm90b3R5
+cGU9ewpDWTpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzLHIKdGhpcy5hLkZWKDAsYykKdD1iLmV2KDAs
+bmV3IFcuRW8oKSkKcz1iLmV2KDAsbmV3IFcuV2soKSkKdGhpcy5iLkZWKDAsdCkKcj10aGlzLmMKci5G
+VigwLEMueEQpCnIuRlYoMCxzKX0sCmkwOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmEudGcoMCxXLnJT
+KGEpKX0sCkViOmZ1bmN0aW9uKGEsYixjKXt2YXIgdD10aGlzLHM9Vy5yUyhhKSxyPXQuYwppZihyLnRn
+KDAsSC5FaihzKSsiOjoiK2IpKXJldHVybiB0LmQuRHQoYykKZWxzZSBpZihyLnRnKDAsIio6OiIrYikp
+cmV0dXJuIHQuZC5EdChjKQplbHNle3I9dC5iCmlmKHIudGcoMCxILkVqKHMpKyI6OiIrYikpcmV0dXJu
+ITAKZWxzZSBpZihyLnRnKDAsIio6OiIrYikpcmV0dXJuITAKZWxzZSBpZihyLnRnKDAsSC5FaihzKSsi
+OjoqIikpcmV0dXJuITAKZWxzZSBpZihyLnRnKDAsIio6OioiKSlyZXR1cm4hMH1yZXR1cm4hMX0sCiRp
+a0Y6MX0KVy5Fby5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4hQy5ObS50ZyhDLkJJLEgu
+aChhKSl9LAokUzoxNX0KVy5Xay5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gQy5ObS50
+ZyhDLkJJLEguaChhKSl9LAokUzoxNX0KVy5jdC5wcm90b3R5cGU9ewpFYjpmdW5jdGlvbihhLGIsYyl7
+aWYodGhpcy5qRihhLGIsYykpcmV0dXJuITAKaWYoYj09PSJ0ZW1wbGF0ZSImJmM9PT0iIilyZXR1cm4h
+MAppZihhLmdldEF0dHJpYnV0ZSgidGVtcGxhdGUiKT09PSIiKXJldHVybiB0aGlzLmUudGcoMCxiKQpy
+ZXR1cm4hMX19ClcuSUEucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIlRFTVBMQVRFOjoi
+K0guRWooSC5oKGEpKX0sCiRTOjV9ClcuT3cucHJvdG90eXBlPXsKaTA6ZnVuY3Rpb24oYSl7dmFyIHQK
+aWYodS5ldy5iKGEpKXJldHVybiExCnQ9dS5nNy5iKGEpCmlmKHQmJlcuclMoYSk9PT0iZm9yZWlnbk9i
+amVjdCIpcmV0dXJuITEKaWYodClyZXR1cm4hMApyZXR1cm4hMX0sCkViOmZ1bmN0aW9uKGEsYixjKXtp
+ZihiPT09ImlzInx8Qy54Qi5uKGIsIm9uIikpcmV0dXJuITEKcmV0dXJuIHRoaXMuaTAoYSl9LAokaWtG
+OjF9ClcuVzkucHJvdG90eXBlPXsKRjpmdW5jdGlvbigpe3ZhciB0PXRoaXMscz10LmMrMSxyPXQuYgpp
+ZihzPHIpe3Quc3AoSi54OSh0LmEscykpCnQuYz1zCnJldHVybiEwfXQuc3AobnVsbCkKdC5jPXIKcmV0
+dXJuITF9LApnbDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmR9LApzcDpmdW5jdGlvbihhKXt0aGlzLmQ9
+dGhpcy4kdGkuQygiMT8iKS5hKGEpfSwKJGlBbjoxfQpXLmRXLnByb3RvdHlwZT17CmdtVzpmdW5jdGlv
+bihhKXtyZXR1cm4gVy5ISCh0aGlzLmEubG9jYXRpb24pfSwKJGlEMDoxLAokaXY2OjF9ClcuRmIucHJv
+dG90eXBlPXt9Clcua0YucHJvdG90eXBlPXt9ClcubWsucHJvdG90eXBlPXskaXkwOjF9ClcuS28ucHJv
+dG90eXBlPXsKUG46ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcyxzPW5ldyBXLmZtKHQpCnQuYj0hMQpzLiQy
+KGEsbnVsbCkKZm9yKDt0LmI7KXt0LmI9ITEKcy4kMihhLG51bGwpfX0sCkVQOmZ1bmN0aW9uKGEsYil7
+dmFyIHQ9dGhpcy5iPSEwCmlmKGIhPW51bGw/YiE9PWEucGFyZW50Tm9kZTp0KUouTHQoYSkKZWxzZSBi
+LnJlbW92ZUNoaWxkKGEpfSwKSTQ6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxwLG89ITAsbj1udWxs
+LG09bnVsbAp0cnl7bj1KLmlnKGEpCm09bi5hLmdldEF0dHJpYnV0ZSgiaXMiKQp1LmguYShhKQp0PWZ1
+bmN0aW9uKGMpe2lmKCEoYy5hdHRyaWJ1dGVzIGluc3RhbmNlb2YgTmFtZWROb2RlTWFwKSlyZXR1cm4g
+dHJ1ZQppZihjLmlkPT0nbGFzdENoaWxkJ3x8Yy5uYW1lPT0nbGFzdENoaWxkJ3x8Yy5pZD09J3ByZXZp
+b3VzU2libGluZyd8fGMubmFtZT09J3ByZXZpb3VzU2libGluZyd8fGMuaWQ9PSdjaGlsZHJlbid8fGMu
+bmFtZT09J2NoaWxkcmVuJylyZXR1cm4gdHJ1ZQp2YXIgbD1jLmNoaWxkTm9kZXMKaWYoYy5sYXN0Q2hp
+bGQmJmMubGFzdENoaWxkIT09bFtsLmxlbmd0aC0xXSlyZXR1cm4gdHJ1ZQppZihjLmNoaWxkcmVuKWlm
+KCEoYy5jaGlsZHJlbiBpbnN0YW5jZW9mIEhUTUxDb2xsZWN0aW9ufHxjLmNoaWxkcmVuIGluc3RhbmNl
+b2YgTm9kZUxpc3QpKXJldHVybiB0cnVlCnZhciBrPTAKaWYoYy5jaGlsZHJlbilrPWMuY2hpbGRyZW4u
+bGVuZ3RoCmZvcih2YXIgaj0wO2o8aztqKyspe3ZhciBpPWMuY2hpbGRyZW5bal0KaWYoaS5pZD09J2F0
+dHJpYnV0ZXMnfHxpLm5hbWU9PSdhdHRyaWJ1dGVzJ3x8aS5pZD09J2xhc3RDaGlsZCd8fGkubmFtZT09
+J2xhc3RDaGlsZCd8fGkuaWQ9PSdwcmV2aW91c1NpYmxpbmcnfHxpLm5hbWU9PSdwcmV2aW91c1NpYmxp
+bmcnfHxpLmlkPT0nY2hpbGRyZW4nfHxpLm5hbWU9PSdjaGlsZHJlbicpcmV0dXJuIHRydWV9cmV0dXJu
+IGZhbHNlfShhKQpvPUgub1QodCk/ITA6IShhLmF0dHJpYnV0ZXMgaW5zdGFuY2VvZiBOYW1lZE5vZGVN
+YXApfWNhdGNoKHEpe0guUnUocSl9cz0iZWxlbWVudCB1bnByaW50YWJsZSIKdHJ5e3M9Si5qKGEpfWNh
+dGNoKHEpe0guUnUocSl9dHJ5e3I9Vy5yUyhhKQp0aGlzLmtSKHUuaC5hKGEpLGIsbyxzLHIsdS5mLmEo
+biksSC5rKG0pKX1jYXRjaChxKXtpZihILlJ1KHEpIGluc3RhbmNlb2YgUC51KXRocm93IHEKZWxzZXt0
+aGlzLkVQKGEsYikKd2luZG93CnA9IlJlbW92aW5nIGNvcnJ1cHRlZCBlbGVtZW50ICIrSC5FaihzKQpp
+Zih0eXBlb2YgY29uc29sZSE9InVuZGVmaW5lZCIpd2luZG93LmNvbnNvbGUud2FybihwKX19fSwKa1I6
+ZnVuY3Rpb24oYSxiLGMsZCxlLGYsZyl7dmFyIHQscyxyLHEscCxvLG49dGhpcwppZihjKXtuLkVQKGEs
+YikKd2luZG93CnQ9IlJlbW92aW5nIGVsZW1lbnQgZHVlIHRvIGNvcnJ1cHRlZCBhdHRyaWJ1dGVzIG9u
+IDwiK2QrIj4iCmlmKHR5cGVvZiBjb25zb2xlIT0idW5kZWZpbmVkIil3aW5kb3cuY29uc29sZS53YXJu
+KHQpCnJldHVybn1pZighbi5hLmkwKGEpKXtuLkVQKGEsYikKd2luZG93CnQ9IlJlbW92aW5nIGRpc2Fs
+bG93ZWQgZWxlbWVudCA8IitILkVqKGUpKyI+IGZyb20gIitILkVqKGIpCmlmKHR5cGVvZiBjb25zb2xl
+IT0idW5kZWZpbmVkIil3aW5kb3cuY29uc29sZS53YXJuKHQpCnJldHVybn1pZihnIT1udWxsKWlmKCFu
+LmEuRWIoYSwiaXMiLGcpKXtuLkVQKGEsYikKd2luZG93CnQ9IlJlbW92aW5nIGRpc2FsbG93ZWQgdHlw
+ZSBleHRlbnNpb24gPCIrSC5FaihlKSsnIGlzPSInK2crJyI+JwppZih0eXBlb2YgY29uc29sZSE9InVu
+ZGVmaW5lZCIpd2luZG93LmNvbnNvbGUud2Fybih0KQpyZXR1cm59dD1mLmdWKCkKcz1ILlZNKHQuc2xp
+Y2UoMCksSC50Nih0KS5DKCJqZDwxPiIpKQpmb3Iocj1mLmdWKCkubGVuZ3RoLTEsdD1mLmE7cj49MDst
+LXIpe2lmKHI+PXMubGVuZ3RoKXJldHVybiBILk9IKHMscikKcT1zW3JdCnA9bi5hCm89Si5jSChxKQpI
+LmgocSkKaWYoIXAuRWIoYSxvLHQuZ2V0QXR0cmlidXRlKHEpKSl7d2luZG93CnA9IlJlbW92aW5nIGRp
+c2FsbG93ZWQgYXR0cmlidXRlIDwiK0guRWooZSkrIiAiK3ErJz0iJytILkVqKHQuZ2V0QXR0cmlidXRl
+KHEpKSsnIj4nCmlmKHR5cGVvZiBjb25zb2xlIT0idW5kZWZpbmVkIil3aW5kb3cuY29uc29sZS53YXJu
+KHApCnQucmVtb3ZlQXR0cmlidXRlKHEpfX1pZih1LmFXLmIoYSkpbi5QbihhLmNvbnRlbnQpfSwKJGlv
+bjoxfQpXLmZtLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dmFyIHQscyxyLHEscCxvLG49dGhp
+cy5hCnN3aXRjaChhLm5vZGVUeXBlKXtjYXNlIDE6bi5JNChhLGIpCmJyZWFrCmNhc2UgODpjYXNlIDEx
+OmNhc2UgMzpjYXNlIDQ6YnJlYWsKZGVmYXVsdDpuLkVQKGEsYil9dD1hLmxhc3RDaGlsZApmb3Iocj11
+LkE7bnVsbCE9dDspe3M9bnVsbAp0cnl7cz10LnByZXZpb3VzU2libGluZwppZihzIT1udWxsKXtxPXMu
+bmV4dFNpYmxpbmcKcD10CnA9cT09bnVsbD9wIT1udWxsOnEhPT1wCnE9cH1lbHNlIHE9ITEKaWYocSl7
+cT1QLlBWKCJDb3JydXB0IEhUTUwiKQp0aHJvdyBILmIocSl9fWNhdGNoKG8pe0guUnUobykKcT1yLmEo
+dCkKbi5iPSEwCnA9cS5wYXJlbnROb2RlCnA9YT09bnVsbD9wIT1udWxsOmEhPT1wCmlmKHApe3A9cS5w
+YXJlbnROb2RlCmlmKHAhPW51bGwpcC5yZW1vdmVDaGlsZChxKX1lbHNlIGEucmVtb3ZlQ2hpbGQocSkK
+dD1udWxsCnM9YS5sYXN0Q2hpbGR9aWYodCE9bnVsbCl0aGlzLiQyKHQsYSkKdD1zfX0sCiRTOjMwfQpX
+LkxlLnByb3RvdHlwZT17fQpXLks3LnByb3RvdHlwZT17fQpXLnJCLnByb3RvdHlwZT17fQpXLlhXLnBy
+b3RvdHlwZT17fQpXLm9hLnByb3RvdHlwZT17fQpQLmlKLnByb3RvdHlwZT17ClZIOmZ1bmN0aW9uKGEp
+e3ZhciB0LHM9dGhpcy5hLHI9cy5sZW5ndGgKZm9yKHQ9MDt0PHI7Kyt0KWlmKHNbdF09PT1hKXJldHVy
+biB0CkMuTm0uaShzLGEpCkMuTm0uaSh0aGlzLmIsbnVsbCkKcmV0dXJuIHJ9LApQdjpmdW5jdGlvbihh
+KXt2YXIgdCxzLHIscT10aGlzLHA9e30KaWYoYT09bnVsbClyZXR1cm4gYQppZihILmwoYSkpcmV0dXJu
+IGEKaWYodHlwZW9mIGE9PSJudW1iZXIiKXJldHVybiBhCmlmKHR5cGVvZiBhPT0ic3RyaW5nIilyZXR1
+cm4gYQppZihhIGluc3RhbmNlb2YgUC5pUClyZXR1cm4gbmV3IERhdGUoYS5hKQppZih1LmZ2LmIoYSkp
+dGhyb3cgSC5iKFAuU1koInN0cnVjdHVyZWQgY2xvbmUgb2YgUmVnRXhwIikpCmlmKHUuYzguYihhKSly
+ZXR1cm4gYQppZih1LncuYihhKSlyZXR1cm4gYQppZih1LkkuYihhKSlyZXR1cm4gYQp0PXUuZEUuYihh
+KXx8ITEKaWYodClyZXR1cm4gYQppZih1LmYuYihhKSl7cz1xLlZIKGEpCnQ9cS5iCmlmKHM+PXQubGVu
+Z3RoKXJldHVybiBILk9IKHQscykKcj1wLmE9dFtzXQppZihyIT1udWxsKXJldHVybiByCnI9e30KcC5h
+PXIKQy5ObS5ZKHQscyxyKQphLksoMCxuZXcgUC5qZyhwLHEpKQpyZXR1cm4gcC5hfWlmKHUuYi5iKGEp
+KXtzPXEuVkgoYSkKcD1xLmIKaWYocz49cC5sZW5ndGgpcmV0dXJuIEguT0gocCxzKQpyPXBbc10KaWYo
+ciE9bnVsbClyZXR1cm4gcgpyZXR1cm4gcS5layhhLHMpfWlmKHUuZUguYihhKSl7cz1xLlZIKGEpCnQ9
+cS5iCmlmKHM+PXQubGVuZ3RoKXJldHVybiBILk9IKHQscykKcj1wLmI9dFtzXQppZihyIT1udWxsKXJl
+dHVybiByCnI9e30KcC5iPXIKQy5ObS5ZKHQscyxyKQpxLmltKGEsbmV3IFAuVGEocCxxKSkKcmV0dXJu
+IHAuYn10aHJvdyBILmIoUC5TWSgic3RydWN0dXJlZCBjbG9uZSBvZiBvdGhlciB0eXBlIikpfSwKZWs6
+ZnVuY3Rpb24oYSxiKXt2YXIgdCxzPUouVTYoYSkscj1zLmdBKGEpLHE9bmV3IEFycmF5KHIpCkMuTm0u
+WSh0aGlzLmIsYixxKQpmb3IodD0wO3Q8cjsrK3QpQy5ObS5ZKHEsdCx0aGlzLlB2KHMucShhLHQpKSkK
+cmV0dXJuIHF9fQpQLmpnLnByb3RvdHlwZT17CiQyOmZ1bmN0aW9uKGEsYil7dGhpcy5hLmFbYV09dGhp
+cy5iLlB2KGIpfSwKJFM6Nn0KUC5UYS5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe3RoaXMuYS5i
+W2FdPXRoaXMuYi5QdihiKX0sCiRTOjZ9ClAuQmYucHJvdG90eXBlPXsKaW06ZnVuY3Rpb24oYSxiKXt2
+YXIgdCxzLHIscQp1LmI4LmEoYikKZm9yKHQ9T2JqZWN0LmtleXMoYSkscz10Lmxlbmd0aCxyPTA7cjxz
+Oysrcil7cT10W3JdCmIuJDIocSxhW3FdKX19fQpQLkFzLnByb3RvdHlwZT17ClQ6ZnVuY3Rpb24oYSl7
+dmFyIHQKSC5oKGEpCnQ9JC5oRygpLmIKaWYodHlwZW9mIGEhPSJzdHJpbmciKUgudmgoSC50TChhKSkK
+aWYodC50ZXN0KGEpKXJldHVybiBhCnRocm93IEguYihQLkwzKGEsInZhbHVlIiwiTm90IGEgdmFsaWQg
+Y2xhc3MgdG9rZW4iKSl9LAp3OmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLkRHKCkuSCgwLCIgIil9LApn
+a3o6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5ERygpCnJldHVybiBQLnJqKHQsdC5yLEguTGgodCkuYyl9
+LApnQTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5ERygpLmF9LAp0ZzpmdW5jdGlvbihhLGIpe3RoaXMu
+VChiKQpyZXR1cm4gdGhpcy5ERygpLnRnKDAsYil9LAppOmZ1bmN0aW9uKGEsYil7dmFyIHQKdGhpcy5U
+KGIpCnQ9dGhpcy5PUyhuZXcgUC5HRShiKSkKcmV0dXJuIEgueTgodD09bnVsbD8hMTp0KX0sClI6ZnVu
+Y3Rpb24oYSxiKXt2YXIgdCxzCnRoaXMuVChiKQp0PXRoaXMuREcoKQpzPXQuUigwLGIpCnRoaXMuWCh0
+KQpyZXR1cm4gc30sCkZWOmZ1bmN0aW9uKGEsYil7dGhpcy5PUyhuZXcgUC5ONyh0aGlzLHUuUS5hKGIp
+KSl9LApWMTpmdW5jdGlvbihhKXt0aGlzLk9TKG5ldyBQLnVRKCkpfSwKT1M6ZnVuY3Rpb24oYSl7dmFy
+IHQscwp1LmJVLmEoYSkKdD10aGlzLkRHKCkKcz1hLiQxKHQpCnRoaXMuWCh0KQpyZXR1cm4gc319ClAu
+R0UucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIHUuQy5hKGEpLmkoMCx0aGlzLmEpfSwK
+JFM6MzJ9ClAuTjcucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcy5iLHM9SC50Nih0
+KQpyZXR1cm4gdS5DLmEoYSkuRlYoMCxuZXcgSC5sSih0LHMuQygicVUoMSkiKS5hKHRoaXMuYS5ndU0o
+KSkscy5DKCJsSjwxLHFVPiIpKSl9LAokUzoxNn0KUC51US5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihh
+KXt1LkMuYShhKQppZihhLmE+MCl7YS5iPWEuYz1hLmQ9YS5lPWEuZj1udWxsCmEuYT0wCmEuUygpfXJl
+dHVybiBudWxsfSwKJFM6MTZ9ClAuaEYucHJvdG90eXBlPXskaWhGOjF9ClAuUEMucHJvdG90eXBlPXsK
+JDE6ZnVuY3Rpb24oYSl7dmFyIHQKdS5ZLmEoYSkKdD1mdW5jdGlvbihiLGMsZCl7cmV0dXJuIGZ1bmN0
+aW9uKCl7cmV0dXJuIGIoYyxkLHRoaXMsQXJyYXkucHJvdG90eXBlLnNsaWNlLmFwcGx5KGFyZ3VtZW50
+cykpfX0oUC5SNCxhLCExKQpQLkRtKHQsJC53KCksYSkKcmV0dXJuIHR9LAokUzo0fQpQLm10LnByb3Rv
+dHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgdGhpcy5hKGEpfSwKJFM6NH0KUC5Oei5wcm90
+b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAucjcoYSl9LAokUzozNH0KUC5RUy5wcm90
+b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAuVHooYSx1LmFtKX0sCiRTOjUzfQpQLm5w
+LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiBuZXcgUC5FNChhKX0sCiRTOjM2fQpQLkU0
+LnByb3RvdHlwZT17CnE6ZnVuY3Rpb24oYSxiKXtpZih0eXBlb2YgYiE9InN0cmluZyImJnR5cGVvZiBi
+IT0ibnVtYmVyIil0aHJvdyBILmIoUC54WSgicHJvcGVydHkgaXMgbm90IGEgU3RyaW5nIG9yIG51bSIp
+KQpyZXR1cm4gUC5kVSh0aGlzLmFbYl0pfSwKWTpmdW5jdGlvbihhLGIsYyl7aWYodHlwZW9mIGIhPSJz
+dHJpbmciJiZ0eXBlb2YgYiE9Im51bWJlciIpdGhyb3cgSC5iKFAueFkoInByb3BlcnR5IGlzIG5vdCBh
+IFN0cmluZyBvciBudW0iKSkKdGhpcy5hW2JdPVAud1koYyl9LApETjpmdW5jdGlvbihhLGIpe2lmKGI9
+PW51bGwpcmV0dXJuITEKcmV0dXJuIGIgaW5zdGFuY2VvZiBQLkU0JiZ0aGlzLmE9PT1iLmF9LAp3OmZ1
+bmN0aW9uKGEpe3ZhciB0LHMKdHJ5e3Q9U3RyaW5nKHRoaXMuYSkKcmV0dXJuIHR9Y2F0Y2gocyl7SC5S
+dShzKQp0PXRoaXMueGIoMCkKcmV0dXJuIHR9fSwKVjc6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzPXRoaXMu
+YQppZihiPT1udWxsKXQ9bnVsbAplbHNle3Q9SC50NihiKQp0PVAuQ0gobmV3IEgubEooYix0LkMoIkAo
+MSkiKS5hKFAuaUcoKSksdC5DKCJsSjwxLEA+IikpLCEwLHUueil9cmV0dXJuIFAuZFUoc1thXS5hcHBs
+eShzLHQpKX0sCmdpTzpmdW5jdGlvbihhKXtyZXR1cm4gMH19ClAucjcucHJvdG90eXBlPXt9ClAuVHou
+cHJvdG90eXBlPXsKY1A6ZnVuY3Rpb24oYSl7dmFyIHQ9dGhpcyxzPWE8MHx8YT49dC5nQSh0KQppZihz
+KXRocm93IEguYihQLlRFKGEsMCx0LmdBKHQpLG51bGwsbnVsbCkpfSwKcTpmdW5jdGlvbihhLGIpe2lm
+KEgub2soYikpdGhpcy5jUChiKQpyZXR1cm4gdGhpcy4kdGkuYy5hKHRoaXMuVXIoMCxiKSl9LApZOmZ1
+bmN0aW9uKGEsYixjKXt0aGlzLmNQKGIpCnRoaXMuZTQoMCxiLGMpfSwKZ0E6ZnVuY3Rpb24oYSl7dmFy
+IHQ9dGhpcy5hLmxlbmd0aAppZih0eXBlb2YgdD09PSJudW1iZXIiJiZ0Pj4+MD09PXQpcmV0dXJuIHQK
+dGhyb3cgSC5iKFAuUFYoIkJhZCBKc0FycmF5IGxlbmd0aCIpKX0sCiRpYlE6MSwKJGljWDoxLAokaXpN
+OjF9ClAuY28ucHJvdG90eXBlPXt9ClAuYkIucHJvdG90eXBlPXskaWJCOjF9ClAuS2UucHJvdG90eXBl
+PXsKREc6ZnVuY3Rpb24oKXt2YXIgdCxzLHIscSxwPXRoaXMuYS5nZXRBdHRyaWJ1dGUoImNsYXNzIiks
+bz1QLkxzKHUuTikKaWYocD09bnVsbClyZXR1cm4gbwpmb3IodD1wLnNwbGl0KCIgIikscz10Lmxlbmd0
+aCxyPTA7cjxzOysrcil7cT1KLlQwKHRbcl0pCmlmKHEubGVuZ3RoIT09MClvLmkoMCxxKX1yZXR1cm4g
+b30sClg6ZnVuY3Rpb24oYSl7dGhpcy5hLnNldEF0dHJpYnV0ZSgiY2xhc3MiLGEuSCgwLCIgIikpfX0K
+UC5kNS5wcm90b3R5cGU9ewpnUDpmdW5jdGlvbihhKXtyZXR1cm4gbmV3IFAuS2UoYSl9LApzaGY6ZnVu
+Y3Rpb24oYSxiKXt0aGlzLllDKGEsYil9LApyNjpmdW5jdGlvbihhLGIsYyxkKXt2YXIgdCxzLHIscSxw
+LG8KaWYoZD09bnVsbCl7dD1ILlZNKFtdLHUucikKZD1uZXcgVy52RCh0KQpDLk5tLmkodCxXLlR3KG51
+bGwpKQpDLk5tLmkodCxXLkJsKCkpCkMuTm0uaSh0LG5ldyBXLk93KCkpfWM9bmV3IFcuS28oZCkKcz0n
+PHN2ZyB2ZXJzaW9uPSIxLjEiPicrSC5FaihiKSsiPC9zdmc+Igp0PWRvY3VtZW50CnI9dC5ib2R5CnIu
+dG9TdHJpbmcKcT1DLlJZLkFIKHIscyxjKQpwPXQuY3JlYXRlRG9jdW1lbnRGcmFnbWVudCgpCnEudG9T
 dHJpbmcKdD1uZXcgVy5lNyhxKQpvPXQuZ3I4KHQpCmZvcig7dD1vLmZpcnN0Q2hpbGQsdCE9bnVsbDsp
 cC5hcHBlbmRDaGlsZCh0KQpyZXR1cm4gcH0sCm56OmZ1bmN0aW9uKGEsYixjLGQsZSl7dGhyb3cgSC5i
 KFAuTDQoIkNhbm5vdCBpbnZva2UgaW5zZXJ0QWRqYWNlbnRIdG1sIG9uIFNWRy4iKSl9LApnVmw6ZnVu
-Y3Rpb24oYSl7cmV0dXJuIG5ldyBXLmV1KGEsImNsaWNrIiwhMSx1LlEpfSwKJGlkNToxfQpQLm42LnBy
-b3RvdHlwZT17JGliUToxLCRpY1g6MSwkaXpNOjEsJGllcToxfQpNLkg3LnByb3RvdHlwZT17Clo6ZnVu
+Y3Rpb24oYSl7cmV0dXJuIG5ldyBXLmV1KGEsImNsaWNrIiwhMSx1LmopfSwKJGlkNToxfQpQLm42LnBy
+b3RvdHlwZT17JGliUToxLCRpY1g6MSwkaXpNOjEsJGllcToxfQpNLkg3LnByb3RvdHlwZT17Cnc6ZnVu
 Y3Rpb24oYSl7cmV0dXJuIHRoaXMuYn19ClUuTEwucHJvdG90eXBlPXsKTHQ6ZnVuY3Rpb24oKXtyZXR1
-cm4gUC5FRihbIm5vZGVJZCIsdGhpcy5iLCJraW5kIix0aGlzLmEuYV0sdS5OLHUuSyl9fQpVLk1ELnBy
-b3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiB1LmdwLmEoYSkuYT09PXRoaXMuYS5xKDAsImtp
-bmQiKX0sCiRTOjM2fQpVLmQyLnByb3RvdHlwZT17Ckx0OmZ1bmN0aW9uKCl7dmFyIHQscyxyLHEscD10
-aGlzLG89dS5OLG49dS5LLG09UC5GbChvLG4pLGw9cC5hCmlmKGwhPW51bGwpe3Q9SC5WTShbXSx1Lkop
+cm4gUC5FRihbIm5vZGVJZCIsdGhpcy5iLCJraW5kIix0aGlzLmEuYV0sdS5YLHUuXyl9fQpVLk1ELnBy
+b3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiB1LmZFLmEoYSkuYT09PXRoaXMuYS5xKDAsImtp
+bmQiKX0sCiRTOjM3fQpVLmQyLnByb3RvdHlwZT17Ckx0OmZ1bmN0aW9uKCl7dmFyIHQscyxyLHEscD10
+aGlzLG89dS5YLG49dS5fLG09UC5GbChvLG4pLGw9cC5hCmlmKGwhPW51bGwpe3Q9SC5WTShbXSx1Lkcp
 CmZvcihzPWwubGVuZ3RoLHI9MDtyPGwubGVuZ3RoO2wubGVuZ3RoPT09c3x8KDAsSC5saykobCksKyty
 KXtxPWxbcl0KQy5ObS5pKHQsUC5FRihbImRlc2NyaXB0aW9uIixxLmEsImhyZWYiLHEuYl0sbyxuKSl9
 bS5ZKDAsImVkaXRzIix0KX1tLlkoMCwiZXhwbGFuYXRpb24iLHAuYikKbS5ZKDAsImxpbmUiLHAuYykK
 bS5ZKDAsImRpc3BsYXlQYXRoIixwLmQpCm0uWSgwLCJ1cmlQYXRoIixwLmUpCm89cC5mCmlmKG8hPW51
-bGwpe249SC5WTShbXSx1LkopCmZvcihsPW8ubGVuZ3RoLHI9MDtyPG8ubGVuZ3RoO28ubGVuZ3RoPT09
+bGwpe249SC5WTShbXSx1LkcpCmZvcihsPW8ubGVuZ3RoLHI9MDtyPG8ubGVuZ3RoO28ubGVuZ3RoPT09
 bHx8KDAsSC5saykobyksKytyKUMuTm0uaShuLG9bcl0uTHQoKSkKbS5ZKDAsInRyYWNlcyIsbil9cmV0
 dXJuIG19fQpVLlNlLnByb3RvdHlwZT17Ckx0OmZ1bmN0aW9uKCl7cmV0dXJuIFAuRUYoWyJkZXNjcmlw
-dGlvbiIsdGhpcy5hLCJocmVmIix0aGlzLmJdLHUuTix1LkspfX0KVS5NbC5wcm90b3R5cGU9ewpMdDpm
+dGlvbiIsdGhpcy5hLCJocmVmIix0aGlzLmJdLHUuWCx1Ll8pfX0KVS5NbC5wcm90b3R5cGU9ewpMdDpm
 dW5jdGlvbigpe3JldHVybiBQLkVGKFsiaHJlZiIsdGhpcy5hLCJsaW5lIix0aGlzLmIsInBhdGgiLHRo
-aXMuY10sdS5OLHUuSyl9fQpVLnlELnByb3RvdHlwZT17Ckx0OmZ1bmN0aW9uKCl7dmFyIHQscyxyLHE9
-SC5WTShbXSx1LkopCmZvcih0PXRoaXMuYixzPXQubGVuZ3RoLHI9MDtyPHQubGVuZ3RoO3QubGVuZ3Ro
+aXMuY10sdS5YLHUuXyl9fQpVLnlELnByb3RvdHlwZT17Ckx0OmZ1bmN0aW9uKCl7dmFyIHQscyxyLHE9
+SC5WTShbXSx1LkcpCmZvcih0PXRoaXMuYixzPXQubGVuZ3RoLHI9MDtyPHQubGVuZ3RoO3QubGVuZ3Ro
 PT09c3x8KDAsSC5saykodCksKytyKUMuTm0uaShxLHRbcl0uTHQoKSkKcmV0dXJuIFAuRUYoWyJkZXNj
-cmlwdGlvbiIsdGhpcy5hLCJlbnRyaWVzIixxXSx1Lk4sdS5LKX19ClUud2IucHJvdG90eXBlPXsKTHQ6
-ZnVuY3Rpb24oKXt2YXIgdCxzLHI9dGhpcyxxPVAuRmwodS5OLHUuSykKcS5ZKDAsImRlc2NyaXB0aW9u
-IixyLmEpCnQ9ci5iCmlmKHQhPW51bGwpcS5ZKDAsImZ1bmN0aW9uIix0KQp0PXIuYwppZih0IT1udWxs
-KXEuWSgwLCJsaW5rIix0Lkx0KCkpCnQ9ci5kCmlmKHQubGVuZ3RoIT09MCl7cz1ILnQ2KHQpCnEuWSgw
-LCJoaW50QWN0aW9ucyIsbmV3IEgubEoodCxzLkMoIlowPHFVLE1oPigxKSIpLmEobmV3IFUuYjAoKSks
-cy5DKCJsSjwxLFowPHFVLE1oPj4iKSkuYnIoMCkpfXJldHVybiBxfX0KVS5hTi5wcm90b3R5cGU9ewok
-MTpmdW5jdGlvbihhKXtyZXR1cm4gVS5ueih1LlMuYShhKSl9LAokUzozN30KVS5iMC5wcm90b3R5cGU9
-ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gdS5FLmEoYSkuTHQoKX0sCiRTOjM4fQpCLmo4LnByb3RvdHlw
-ZT17Ckx0OmZ1bmN0aW9uKCl7cmV0dXJuIFAuRUYoWyJsaW5lIix0aGlzLmEsImV4cGxhbmF0aW9uIix0
-aGlzLmIsIm9mZnNldCIsdGhpcy5jXSx1Lk4sdS5LKX19CkIucXAucHJvdG90eXBlPXsKTHQ6ZnVuY3Rp
-b24oKXt2YXIgdCxzLHIscSxwLG8sbixtPXRoaXMsbD11Lk4saz1QLkZsKGwsdS5kMykKZm9yKHQ9bS5k
-LHQ9dC5nUHUodCksdD10Lmdreih0KSxzPXUuSyxyPXUuSjt0LkYoKTspe3E9dC5nbCgpCnA9cS5hCm89
-SC5WTShbXSxyKQpmb3IocT1KLklUKHEuYik7cS5GKCk7KXtuPXEuZ2woKQpDLk5tLmkobyxQLkVGKFsi
-bGluZSIsbi5hLCJleHBsYW5hdGlvbiIsbi5iLCJvZmZzZXQiLG4uY10sbCxzKSl9ay5ZKDAscCxvKX1y
-ZXR1cm4gUC5FRihbInJlZ2lvbnMiLG0uYSwibmF2aWdhdGlvbkNvbnRlbnQiLG0uYiwic291cmNlQ29k
-ZSIsbS5jLCJlZGl0cyIsa10sbCxzKX19ClQubVEucHJvdG90eXBlPXt9CkwuZS5wcm90b3R5cGU9ewok
-MTpmdW5jdGlvbihhKXt2YXIgdCxzLHIscSxwLG8sbgp1LkIuYShhKQp0PXdpbmRvdy5sb2NhdGlvbi5w
-YXRobmFtZQpzPUwuRzYod2luZG93LmxvY2F0aW9uLmhyZWYpCnI9TC5hSyh3aW5kb3cubG9jYXRpb24u
-aHJlZikKTC5HZSgpCmlmKHQhPT0iLyImJnQhPT1KLlQwKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoIi5y
-b290IikudGV4dENvbnRlbnQpKUwuRzcodCxzLHIsITAsbmV3IEwuVlcodCxzLHIpKQpxPWRvY3VtZW50
-CnA9Si5xRihxLnF1ZXJ5U2VsZWN0b3IoIi5hcHBseS1taWdyYXRpb24iKSkKbz1wLiR0aQpuPW8uQygi
-figxKSIpLmEobmV3IEwub1ooKSkKdS5NLmEobnVsbCkKVy5KRShwLmEscC5iLG4sITEsby5jKQpvPUou
-cUYocS5xdWVyeVNlbGVjdG9yKCIucmVydW4tbWlncmF0aW9uIikpCm49by4kdGkKVy5KRShvLmEsby5i
-LG4uQygifigxKSIpLmEobmV3IEwueTgoKSksITEsbi5jKQpuPUoucUYocS5xdWVyeVNlbGVjdG9yKCIu
-cmVwb3J0LXByb2JsZW0iKSkKbz1uLiR0aQpXLkpFKG4uYSxuLmIsby5DKCJ+KDEpIikuYShuZXcgTC5I
-aSgpKSwhMSxvLmMpCnE9Si5xRihxLnF1ZXJ5U2VsZWN0b3IoIi5wb3B1cC1wYW5lIC5jbG9zZSIpKQpv
-PXEuJHRpClcuSkUocS5hLHEuYixvLkMoIn4oMSkiKS5hKG5ldyBMLkJUKCkpLCExLG8uYyl9LAokUzox
-Nn0KTC5WVy5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigpe0wuRnIodGhpcy5hLHRoaXMuYix0aGlzLmMp
-fSwKJFM6MH0KTC5vWi5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgdCxzLHIscQp1LlYuYShh
-KQppZihILm9UKHdpbmRvdy5jb25maXJtKCJUaGlzIHdpbGwgYXBwbHkgdGhlIGNoYW5nZXMgeW91J3Zl
-IHByZXZpZXdlZCB0byB5b3VyIHdvcmtpbmcgZGlyZWN0b3J5LiBJdCBpcyByZWNvbW1lbmRlZCB5b3Ug
-Y29tbWl0IGFueSBjaGFuZ2VzIHlvdSBtYWRlIGJlZm9yZSBkb2luZyB0aGlzLiIpKSl7dD1MLnR5KCIv
-YXBwbHktbWlncmF0aW9uIixudWxsKS5XNyhuZXcgTC5qcigpLHUuUCkKcz1uZXcgTC5xbCgpCnUuYmYu
-YShudWxsKQpyPXQuJHRpCnE9JC5YMwppZihxIT09Qy5OVSlzPVAuVkgocyxxKQp0LnhmKG5ldyBQLkZl
-KG5ldyBQLnZzKHEsciksMixudWxsLHMsci5DKCJAPDE+IikuS3Eoci5jKS5DKCJGZTwxLDI+IikpKX19
-LAokUzozfQpMLmpyLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0CnUuUy5hKGEpCnQ9ZG9j
-dW1lbnQuYm9keQp0LmNsYXNzTGlzdC5yZW1vdmUoInByb3Bvc2VkIikKdC5jbGFzc0xpc3QuYWRkKCJh
-cHBsaWVkIil9LAokUzo0MX0KTC5xbC5wcm90b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe0wuQzIoIkNv
-dWxkIG5vdCBhcHBseSBtaWdyYXRpb24iLGEsYil9LAokQzoiJDIiLAokUjoyLAokUzo0fQpMLnk4LnBy
-b3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLnhuKHUuVi5hKGEpKX0sCnhuOmZ1bmN0
-aW9uKGEpe3ZhciB0PTAscz1QLkZYKHUuUCkscj0xLHEscD1bXSxvLG4sbSxsCnZhciAkYXN5bmMkJDE9
-UC5seihmdW5jdGlvbihiLGMpe2lmKGI9PT0xKXtxPWMKdD1yfXdoaWxlKHRydWUpc3dpdGNoKHQpe2Nh
-c2UgMDpyPTMKZG9jdW1lbnQuYm9keS5jbGFzc0xpc3QuYWRkKCJyZXJ1bm5pbmciKQp0PTYKcmV0dXJu
-IFAualEoTC50eSgiL3JlcnVuLW1pZ3JhdGlvbiIsbnVsbCksJGFzeW5jJCQxKQpjYXNlIDY6d2luZG93
-LmxvY2F0aW9uLnJlbG9hZCgpCnAucHVzaCg1KQp0PTQKYnJlYWsKY2FzZSAzOnI9MgpsPXEKbz1ILlJ1
-KGwpCm49SC50cyhsKQpMLkMyKCJGYWlsZWQgdG8gcmVydW4gbWlncmF0aW9uIixvLG4pCnAucHVzaCg1
-KQp0PTQKYnJlYWsKY2FzZSAyOnA9WzFdCmNhc2UgNDpyPTEKZG9jdW1lbnQuYm9keS5jbGFzc0xpc3Qu
-cmVtb3ZlKCJyZXJ1bm5pbmciKQp0PXAucG9wKCkKYnJlYWsKY2FzZSA1OnJldHVybiBQLnlDKG51bGws
-cykKY2FzZSAxOnJldHVybiBQLmYzKHEscyl9fSkKcmV0dXJuIFAuREkoJGFzeW5jJCQxLHMpfSwKJFM6
-MTd9CkwuSGkucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHQKdS5WLmEoYSkKdD11Lk4KQy5v
-bC5Qbyh3aW5kb3csUC5YZCgiaHR0cHMiLCJnaXRodWIuY29tIiwiZGFydC1sYW5nL3Nkay9pc3N1ZXMv
-bmV3IixQLkVGKFsidGl0bGUiLCJDdXN0b21lci1yZXBvcnRlZCBpc3N1ZSB3aXRoIE5OQkQgbWlncmF0
-aW9uIHRvb2wiLCJsYWJlbHMiLCJhcmVhLWFuYWx5emVyLGFuYWx5emVyLW5uYmQtbWlncmF0aW9uLHR5
-cGUtYnVnIiwiYm9keSIsIiMjIyMgU3RlcHMgdG8gcmVwcm9kdWNlXG5cbiMjIyMgV2hhdCBkaWQgeW91
-IGV4cGVjdCB0byBoYXBwZW4/XG5cbiMjIyMgV2hhdCBhY3R1YWxseSBoYXBwZW5lZD9cblxuX1NjcmVl
-bnNob3RzIGFyZSBhcHByZWNpYXRlZF9cblxuKipEYXJ0IFNESyB2ZXJzaW9uKio6ICIrSC5kKGRvY3Vt
-ZW50LmdldEVsZW1lbnRCeUlkKCJzZGstdmVyc2lvbiIpLnRleHRDb250ZW50KSsiXG5cblRoYW5rcyBm
-b3IgZmlsaW5nIVxuIl0sdCx0KSkuWigwKSwicmVwb3J0LXByb2JsZW0iKX0sCiRTOjN9CkwuQlQucHJv
-dG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHQKdS5WLmEoYSkKdD1kb2N1bWVudC5xdWVyeVNlbGVj
-dG9yKCIucG9wdXAtcGFuZSIpLnN0eWxlCnQuZGlzcGxheT0ibm9uZSIKcmV0dXJuIm5vbmUifSwKJFM6
-NDN9CkwuTC5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgdCxzLHIKdS5CLmEoYSkKdD13aW5k
-b3cubG9jYXRpb24ucGF0aG5hbWUKcz1MLkc2KHdpbmRvdy5sb2NhdGlvbi5ocmVmKQpyPUwuYUsod2lu
-ZG93LmxvY2F0aW9uLmhyZWYpCmlmKHQubGVuZ3RoPjEpTC5HNyh0LHMsciwhMSxudWxsKQplbHNle0wu
-QkUodCxuZXcgQi5xcCgiIiwiIiwiIixDLkNNKSwhMCkKTC5CWCgiJm5ic3A7IixudWxsKX19LAokUzox
-Nn0KTC5XeC5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgdCxzLHIscT0iY29sbGFwc2VkIgp1
-LlYuYShhKQp0PXRoaXMuYQpzPUouUkUodCkKcj10aGlzLmIKaWYoIXMuZ1AodCkudGcoMCxxKSl7cy5n
-UCh0KS5pKDAscSkKSi5kUihyKS5pKDAscSl9ZWxzZXtzLmdQKHQpLlIoMCxxKQpKLmRSKHIpLlIoMCxx
-KX19LAokUzozfQpMLkFPLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0PUoucUYodS5oLmEo
-YSkpLHM9dC4kdGkscj1zLkMoIn4oMSkiKS5hKG5ldyBMLmROKHRoaXMuYSkpCnUuTS5hKG51bGwpClcu
-SkUodC5hLHQuYixyLCExLHMuYyl9LAokUzo2fQpMLmROLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEp
-e3ZhciB0CnUuVi5hKGEpCnQ9ZG9jdW1lbnQucXVlcnlTZWxlY3RvcigidGFibGVbZGF0YS1wYXRoXSIp
-CnQudG9TdHJpbmcKTC50MihhLHRoaXMuYSx0LmdldEF0dHJpYnV0ZSgiZGF0YS0iK25ldyBXLlN5KG5l
-dyBXLmk3KHQpKS5PKCJwYXRoIikpKX0sCiRTOjN9CkwuSG8ucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24o
-YSl7dmFyIHQscyxyCnUuaC5hKGEpCnQ9Si5xRihhKQpzPXQuJHRpCnI9cy5DKCJ+KDEpIikuYShuZXcg
-TC54eihhLHRoaXMuYSkpCnUuTS5hKG51bGwpClcuSkUodC5hLHQuYixyLCExLHMuYyl9LAokUzo2fQpM
-Lnh6LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0LHM9bnVsbAp1LlYuYShhKQp0PXRoaXMu
-YQpMLmhYKHRoaXMuYixQLlFBKHQuZ2V0QXR0cmlidXRlKCJkYXRhLSIrbmV3IFcuU3kobmV3IFcuaTco
-dCkpLk8oIm9mZnNldCIpKSxzLHMpLFAuUUEodC5nZXRBdHRyaWJ1dGUoImRhdGEtIituZXcgVy5TeShu
-ZXcgVy5pNyh0KSkuTygibGluZSIpKSxzLHMpKX0sCiRTOjN9CkwuSUMucHJvdG90eXBlPXsKJDE6ZnVu
-Y3Rpb24oYSl7dmFyIHQ9Si5xRih1LmguYShhKSkscz10LiR0aQpzLkMoIn4oMSkiKS5hKEwuaVMoKSkK
-dS5NLmEobnVsbCkKVy5KRSh0LmEsdC5iLEwuaVMoKSwhMSxzLmMpfSwKJFM6Nn0KTC5mQy5wcm90b3R5
-cGU9ewokMTpmdW5jdGlvbihhKXt1LkYuYShhKQp0aGlzLmEuYU0oMCx0aGlzLmIpfSwKJFM6NDV9Ckwu
-blQucHJvdG90eXBlPXsKJDA6ZnVuY3Rpb24oKXtMLkZyKHRoaXMuYS5hLHRoaXMuYix0aGlzLmMpfSwK
-JFM6MH0KTC5CWi5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigpe0wuRnIodGhpcy5hLmEsbnVsbCxudWxs
-KX0sCiRTOjB9CkwuR0gucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dS5oLmEoYSkKJC56QigpLnRv
-U3RyaW5nCnUubS5hKCQub3coKS5xKDAsImhsanMiKSkuVjcoImhpZ2hsaWdodEJsb2NrIixbYV0pfSwK
-JFM6Nn0KTC5FRS5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgdCxzCnUuVi5hKGEpCnQ9dGhp
-cy5hCnM9dGhpcy5iCkwuYWYod2luZG93LmxvY2F0aW9uLnBhdGhuYW1lLHQscywhMCxuZXcgTC5RTCh0
-LHMpKQpMLmhYKHRoaXMuYyx0LHMpfSwKJFM6M30KTC5RTC5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigp
-e0wuRnIod2luZG93LmxvY2F0aW9uLnBhdGhuYW1lLHRoaXMuYSx0aGlzLmIpfSwKJFM6MH0KTC5WUy5w
-cm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgdCxzPSJzZWxlY3RlZC1maWxlIgp1LmguYShhKQph
-LnRvU3RyaW5nCnQ9Si5SRShhKQppZihhLmdldEF0dHJpYnV0ZSgiZGF0YS0iK25ldyBXLlN5KG5ldyBX
-Lmk3KGEpKS5PKCJuYW1lIikpPT09dGhpcy5hLmEpdC5nUChhKS5pKDAscykKZWxzZSB0LmdQKGEpLlIo
-MCxzKX0sCiRTOjZ9CkwuVEQucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIEwudDIodS5W
-LmEoYSksITAsbnVsbCl9LAokUzoxOH0KTC5BUy5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1
-cm4gdGhpcy5QTCh1LlYuYShhKSl9LApQTDpmdW5jdGlvbihhKXt2YXIgdD0wLHM9UC5GWCh1LlApLHI9
-MSxxLHA9W10sbz10aGlzLG4sbSxsLGssagp2YXIgJGFzeW5jJCQxPVAubHooZnVuY3Rpb24oYixjKXtp
-ZihiPT09MSl7cT1jCnQ9cn13aGlsZSh0cnVlKXN3aXRjaCh0KXtjYXNlIDA6cj0zCmw9dS5OCnQ9Ngpy
-ZXR1cm4gUC5qUShMLnR5KEwuUTQoIi9hcHBseS1oaW50IixQLkZsKGwsbCkpLG8uYS5MdCgpKSwkYXN5
-bmMkJDEpCmNhc2UgNjpsPW8uYgpMLkc3KGwuYyxudWxsLGwuYiwhMSxudWxsKQpkb2N1bWVudC5ib2R5
-LmNsYXNzTGlzdC5hZGQoIm5lZWRzLXJlcnVuIikKcj0xCnQ9NQpicmVhawpjYXNlIDM6cj0yCmo9cQpu
-PUguUnUoaikKbT1ILnRzKGopCkwuQzIoIkNvdWxkIG5vdCBhcHBseSBoaW50IixuLG0pCnQ9NQpicmVh
-awpjYXNlIDI6dD0xCmJyZWFrCmNhc2UgNTpyZXR1cm4gUC55QyhudWxsLHMpCmNhc2UgMTpyZXR1cm4g
-UC5mMyhxLHMpfX0pCnJldHVybiBQLkRJKCRhc3luYyQkMSxzKX0sCiRTOjE3fQpMLlhBLnByb3RvdHlw
-ZT17CkViOmZ1bmN0aW9uKGEsYixjKXtyZXR1cm4hMH0sCmkwOmZ1bmN0aW9uKGEpe3JldHVybiEwfSwK
-JGlrRjoxfQpMLlpaLnByb3RvdHlwZT17Ckx0OmZ1bmN0aW9uKCl7dmFyIHQscz10aGlzLHI9UC5GbCh1
-Lk4sdS5LKQpyLlkoMCwidHlwZSIsTC52eShzLmEpKQpyLlkoMCwibmFtZSIscy5iKQp0PXMuYwppZih0
-IT1udWxsKXIuWSgwLCJzdWJ0cmVlIixMLlZEKHQpKQp0PXMuZAppZih0IT1udWxsKXIuWSgwLCJwYXRo
-Iix0KQp0PXMuZQppZih0IT1udWxsKXIuWSgwLCJocmVmIix0KQp0PXMuZgppZih0IT1udWxsKXIuWSgw
-LCJlZGl0Q291bnQiLHQpCnJldHVybiByfX0KTC5POS5wcm90b3R5cGU9ewpaOmZ1bmN0aW9uKGEpe3Jl
-dHVybiB0aGlzLmJ9fQpNLmxJLnByb3RvdHlwZT17CldPOmZ1bmN0aW9uKGEsYil7dmFyIHQscz1udWxs
-Ck0uWUYoImFic29sdXRlIixILlZNKFtiLG51bGwsbnVsbCxudWxsLG51bGwsbnVsbCxudWxsXSx1LnMp
-KQp0PXRoaXMuYQp0PXQuWXIoYik+MCYmIXQuaEsoYikKaWYodClyZXR1cm4gYgp0PUQuUlgoKQpyZXR1
-cm4gdGhpcy5xNygwLHQsYixzLHMscyxzLHMscyl9LAp6ZjpmdW5jdGlvbihhKXt2YXIgdCxzLHI9WC5D
-TChhLHRoaXMuYSkKci5JVigpCnQ9ci5kCnM9dC5sZW5ndGgKaWYocz09PTApe3Q9ci5iCnJldHVybiB0
-PT1udWxsPyIuIjp0fWlmKHM9PT0xKXt0PXIuYgpyZXR1cm4gdD09bnVsbD8iLiI6dH1pZigwPj1zKXJl
-dHVybiBILmsodCwtMSkKdC5wb3AoKQpDLk5tLm12KHIuZSkKci5JVigpCnJldHVybiByLlooMCl9LApx
-NzpmdW5jdGlvbihhLGIsYyxkLGUsZixnLGgsaSl7dmFyIHQ9SC5WTShbYixjLGQsZSxmLGcsaCxpXSx1
-LnMpCk0uWUYoImpvaW4iLHQpCnJldHVybiB0aGlzLklQKG5ldyBILlU1KHQsdS5iQi5hKG5ldyBNLk1p
-KCkpLHUuY2MpKX0sCklQOmZ1bmN0aW9uKGEpe3ZhciB0LHMscixxLHAsbyxuLG0sbCxrCnUuWC5hKGEp
-CmZvcih0PWEuJHRpLHM9dC5DKCJhMihjWC5FKSIpLmEobmV3IE0ucTcoKSkscj1hLmdreihhKSx0PW5l
-dyBILnZHKHIscyx0LkMoInZHPGNYLkU+IikpLHM9dGhpcy5hLHE9ITEscD0hMSxvPSIiO3QuRigpOyl7
-bj1yLmdsKCkKaWYocy5oSyhuKSYmcCl7bT1YLkNMKG4scykKbD1vLmNoYXJDb2RlQXQoMCk9PTA/bzpv
-Cm89Qy54Qi5OaihsLDAscy5TcChsLCEwKSkKbS5iPW8KaWYocy5kcyhvKSlDLk5tLlkobS5lLDAscy5n
-bUkoKSkKbz1tLlooMCl9ZWxzZSBpZihzLllyKG4pPjApe3A9IXMuaEsobikKbz1ILmQobil9ZWxzZXtr
-PW4ubGVuZ3RoCmlmKGshPT0wKXtpZigwPj1rKXJldHVybiBILmsobiwwKQprPXMuVWQoblswXSl9ZWxz
-ZSBrPSExCmlmKCFrKWlmKHEpbys9cy5nbUkoKQpvKz1ufXE9cy5kcyhuKX1yZXR1cm4gby5jaGFyQ29k
-ZUF0KDApPT0wP286b30sCm81OmZ1bmN0aW9uKGEpe3ZhciB0CmlmKCF0aGlzLnkzKGEpKXJldHVybiBh
-CnQ9WC5DTChhLHRoaXMuYSkKdC5yUigpCnJldHVybiB0LlooMCl9LAp5MzpmdW5jdGlvbihhKXt2YXIg
-dCxzLHIscSxwLG8sbixtLGwsawphLnRvU3RyaW5nCnQ9dGhpcy5hCnM9dC5ZcihhKQppZihzIT09MCl7
-aWYodD09PSQuS2soKSlmb3Iocj0wO3I8czsrK3IpaWYoQy54Qi5XKGEscik9PT00NylyZXR1cm4hMApx
-PXMKcD00N31lbHNle3E9MApwPW51bGx9Zm9yKG89bmV3IEgucWooYSkuYSxuPW8ubGVuZ3RoLHI9cSxt
-PW51bGw7cjxuOysrcixtPXAscD1sKXtsPUMueEIubShvLHIpCmlmKHQucjQobCkpe2lmKHQ9PT0kLktr
-KCkmJmw9PT00NylyZXR1cm4hMAppZihwIT1udWxsJiZ0LnI0KHApKXJldHVybiEwCmlmKHA9PT00Nilr
-PW09PW51bGx8fG09PT00Nnx8dC5yNChtKQplbHNlIGs9ITEKaWYoaylyZXR1cm4hMH19aWYocD09bnVs
-bClyZXR1cm4hMAppZih0LnI0KHApKXJldHVybiEwCmlmKHA9PT00Nil0PW09PW51bGx8fHQucjQobSl8
-fG09PT00NgplbHNlIHQ9ITEKaWYodClyZXR1cm4hMApyZXR1cm4hMX0sCkhQOmZ1bmN0aW9uKGEsYil7
-dmFyIHQscyxyLHEscCxvLG4sbT10aGlzLGw9J1VuYWJsZSB0byBmaW5kIGEgcGF0aCB0byAiJwpiPW0u
-V08oMCxiKQp0PW0uYQppZih0LllyKGIpPD0wJiZ0LllyKGEpPjApcmV0dXJuIG0ubzUoYSkKaWYodC5Z
-cihhKTw9MHx8dC5oSyhhKSlhPW0uV08oMCxhKQppZih0LllyKGEpPD0wJiZ0LllyKGIpPjApdGhyb3cg
-SC5iKFguSTcobCtILmQoYSkrJyIgZnJvbSAiJytILmQoYikrJyIuJykpCnM9WC5DTChiLHQpCnMuclIo
-KQpyPVguQ0woYSx0KQpyLnJSKCkKcT1zLmQKcD1xLmxlbmd0aAppZihwIT09MCl7aWYoMD49cClyZXR1
-cm4gSC5rKHEsMCkKcT1KLlJNKHFbMF0sIi4iKX1lbHNlIHE9ITEKaWYocSlyZXR1cm4gci5aKDApCnE9
-cy5iCnA9ci5iCmlmKHEhPXApcT1xPT1udWxsfHxwPT1udWxsfHwhdC5OYyhxLHApCmVsc2UgcT0hMQpp
-ZihxKXJldHVybiByLlooMCkKd2hpbGUoITApe3E9cy5kCnA9cS5sZW5ndGgKaWYocCE9PTApe289ci5k
-Cm49by5sZW5ndGgKaWYobiE9PTApe2lmKDA+PXApcmV0dXJuIEguayhxLDApCnE9cVswXQppZigwPj1u
-KXJldHVybiBILmsobywwKQpvPXQuTmMocSxvWzBdKQpxPW99ZWxzZSBxPSExfWVsc2UgcT0hMQppZigh
-cSlicmVhawpDLk5tLlc0KHMuZCwwKQpDLk5tLlc0KHMuZSwxKQpDLk5tLlc0KHIuZCwwKQpDLk5tLlc0
-KHIuZSwxKX1xPXMuZApwPXEubGVuZ3RoCmlmKHAhPT0wKXtpZigwPj1wKXJldHVybiBILmsocSwwKQpx
-PUouUk0ocVswXSwiLi4iKX1lbHNlIHE9ITEKaWYocSl0aHJvdyBILmIoWC5JNyhsK0guZChhKSsnIiBm
-cm9tICInK0guZChiKSsnIi4nKSkKcT11Lk4KQy5ObS5VRyhyLmQsMCxQLk84KHMuZC5sZW5ndGgsIi4u
-IiwhMSxxKSkKQy5ObS5ZKHIuZSwwLCIiKQpDLk5tLlVHKHIuZSwxLFAuTzgocy5kLmxlbmd0aCx0Lmdt
-SSgpLCExLHEpKQp0PXIuZApxPXQubGVuZ3RoCmlmKHE9PT0wKXJldHVybiIuIgppZihxPjEmJkouUk0o
-Qy5ObS5ncloodCksIi4iKSl7dD1yLmQKaWYoMD49dC5sZW5ndGgpcmV0dXJuIEguayh0LC0xKQp0LnBv
-cCgpCnQ9ci5lCkMuTm0ubXYodCkKQy5ObS5tdih0KQpDLk5tLmkodCwiIil9ci5iPSIiCnIuSVYoKQpy
-ZXR1cm4gci5aKDApfX0KTS5NaS5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gSC5jKGEp
-IT1udWxsfSwKJFM6N30KTS5xNy5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gSC5jKGEp
-IT09IiJ9LAokUzo3fQpNLk5vLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe0guYyhhKQpyZXR1cm4g
-YT09bnVsbD8ibnVsbCI6JyInK2ErJyInfSwKJFM6NX0KQi5mdi5wcm90b3R5cGU9ewp4WjpmdW5jdGlv
-bihhKXt2YXIgdCxzPXRoaXMuWXIoYSkKaWYocz4wKXJldHVybiBKLmxkKGEsMCxzKQppZih0aGlzLmhL
-KGEpKXtpZigwPj1hLmxlbmd0aClyZXR1cm4gSC5rKGEsMCkKdD1hWzBdfWVsc2UgdD1udWxsCnJldHVy
-biB0fSwKTmM6ZnVuY3Rpb24oYSxiKXtyZXR1cm4gYT09Yn19ClguV0QucHJvdG90eXBlPXsKSVY6ZnVu
-Y3Rpb24oKXt2YXIgdCxzLHI9dGhpcwp3aGlsZSghMCl7dD1yLmQKaWYoISh0Lmxlbmd0aCE9PTAmJkou
-Uk0oQy5ObS5ncloodCksIiIpKSlicmVhawp0PXIuZAppZigwPj10Lmxlbmd0aClyZXR1cm4gSC5rKHQs
-LTEpCnQucG9wKCkKQy5ObS5tdihyLmUpfXQ9ci5lCnM9dC5sZW5ndGgKaWYocyE9PTApQy5ObS5ZKHQs
-cy0xLCIiKX0sCnJSOmZ1bmN0aW9uKCl7dmFyIHQscyxyLHEscCxvLG49dGhpcyxtPUguVk0oW10sdS5z
-KQpmb3IodD1uLmQscz10Lmxlbmd0aCxyPTAscT0wO3E8dC5sZW5ndGg7dC5sZW5ndGg9PT1zfHwoMCxI
-LmxrKSh0KSwrK3Epe3A9dFtxXQpvPUouaWEocCkKaWYoIShvLkROKHAsIi4iKXx8by5ETihwLCIiKSkp
-aWYoby5ETihwLCIuLiIpKXtvPW0ubGVuZ3RoCmlmKG8hPT0wKXtpZigwPj1vKXJldHVybiBILmsobSwt
-MSkKbS5wb3AoKX1lbHNlICsrcn1lbHNlIEMuTm0uaShtLHApfWlmKG4uYj09bnVsbClDLk5tLlVHKG0s
-MCxQLk84KHIsIi4uIiwhMSx1Lk4pKQppZihtLmxlbmd0aD09PTAmJm4uYj09bnVsbClDLk5tLmkobSwi
-LiIpCm4uc25KKG0pCnQ9bi5hCm4uc1BoKFAuTzgobS5sZW5ndGgrMSx0LmdtSSgpLCEwLHUuTikpCnM9
-bi5iCmlmKHM9PW51bGx8fG0ubGVuZ3RoPT09MHx8IXQuZHMocykpQy5ObS5ZKG4uZSwwLCIiKQpzPW4u
-YgppZihzIT1udWxsJiZ0PT09JC5LaygpKXtzLnRvU3RyaW5nCm4uYj1ILnlzKHMsIi8iLCJcXCIpfW4u
-SVYoKX0sClo6ZnVuY3Rpb24oYSl7dmFyIHQscyxyPXRoaXMscT1yLmIKcT1xIT1udWxsP3E6IiIKZm9y
-KHQ9MDt0PHIuZC5sZW5ndGg7Kyt0KXtzPXIuZQppZih0Pj1zLmxlbmd0aClyZXR1cm4gSC5rKHMsdCkK
-cz1xK0guZChzW3RdKQpxPXIuZAppZih0Pj1xLmxlbmd0aClyZXR1cm4gSC5rKHEsdCkKcT1zK0guZChx
-W3RdKX1xKz1ILmQoQy5ObS5nclooci5lKSkKcmV0dXJuIHEuY2hhckNvZGVBdCgwKT09MD9xOnF9LApz
-bko6ZnVuY3Rpb24oYSl7dGhpcy5kPXUuYS5hKGEpfSwKc1BoOmZ1bmN0aW9uKGEpe3RoaXMuZT11LmEu
-YShhKX19ClguZHYucHJvdG90eXBlPXsKWjpmdW5jdGlvbihhKXtyZXR1cm4iUGF0aEV4Y2VwdGlvbjog
-Iit0aGlzLmF9LAokaVJ6OjF9Ck8uekwucHJvdG90eXBlPXsKWjpmdW5jdGlvbihhKXtyZXR1cm4gdGhp
-cy5nb2ModGhpcyl9fQpFLk9GLnByb3RvdHlwZT17ClVkOmZ1bmN0aW9uKGEpe3JldHVybiBDLnhCLnRn
-KGEsIi8iKX0sCnI0OmZ1bmN0aW9uKGEpe3JldHVybiBhPT09NDd9LApkczpmdW5jdGlvbihhKXt2YXIg
-dD1hLmxlbmd0aApyZXR1cm4gdCE9PTAmJkMueEIubShhLHQtMSkhPT00N30sClNwOmZ1bmN0aW9uKGEs
-Yil7aWYoYS5sZW5ndGghPT0wJiZDLnhCLlcoYSwwKT09PTQ3KXJldHVybiAxCnJldHVybiAwfSwKWXI6
-ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuU3AoYSwhMSl9LApoSzpmdW5jdGlvbihhKXtyZXR1cm4hMX0s
-CmdvYzpmdW5jdGlvbigpe3JldHVybiJwb3NpeCJ9LApnbUk6ZnVuY3Rpb24oKXtyZXR1cm4iLyJ9fQpG
-LnJ1LnByb3RvdHlwZT17ClVkOmZ1bmN0aW9uKGEpe3JldHVybiBDLnhCLnRnKGEsIi8iKX0sCnI0OmZ1
-bmN0aW9uKGEpe3JldHVybiBhPT09NDd9LApkczpmdW5jdGlvbihhKXt2YXIgdD1hLmxlbmd0aAppZih0
-PT09MClyZXR1cm4hMQppZihDLnhCLm0oYSx0LTEpIT09NDcpcmV0dXJuITAKcmV0dXJuIEMueEIuVGMo
-YSwiOi8vIikmJnRoaXMuWXIoYSk9PT10fSwKU3A6ZnVuY3Rpb24oYSxiKXt2YXIgdCxzLHIscSxwPWEu
-bGVuZ3RoCmlmKHA9PT0wKXJldHVybiAwCmlmKEMueEIuVyhhLDApPT09NDcpcmV0dXJuIDEKZm9yKHQ9
-MDt0PHA7Kyt0KXtzPUMueEIuVyhhLHQpCmlmKHM9PT00NylyZXR1cm4gMAppZihzPT09NTgpe2lmKHQ9
-PT0wKXJldHVybiAwCnI9Qy54Qi5YVShhLCIvIixDLnhCLlFpKGEsIi8vIix0KzEpP3QrMzp0KQppZihy
-PD0wKXJldHVybiBwCmlmKCFifHxwPHIrMylyZXR1cm4gcgppZighQy54Qi5uKGEsImZpbGU6Ly8iKSly
-ZXR1cm4gcgppZighQi5ZdShhLHIrMSkpcmV0dXJuIHIKcT1yKzMKcmV0dXJuIHA9PT1xP3E6cis0fX1y
-ZXR1cm4gMH0sCllyOmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLlNwKGEsITEpfSwKaEs6ZnVuY3Rpb24o
-YSl7cmV0dXJuIGEubGVuZ3RoIT09MCYmQy54Qi5XKGEsMCk9PT00N30sCmdvYzpmdW5jdGlvbigpe3Jl
-dHVybiJ1cmwifSwKZ21JOmZ1bmN0aW9uKCl7cmV0dXJuIi8ifX0KTC5JVi5wcm90b3R5cGU9ewpVZDpm
-dW5jdGlvbihhKXtyZXR1cm4gQy54Qi50ZyhhLCIvIil9LApyNDpmdW5jdGlvbihhKXtyZXR1cm4gYT09
-PTQ3fHxhPT09OTJ9LApkczpmdW5jdGlvbihhKXt2YXIgdD1hLmxlbmd0aAppZih0PT09MClyZXR1cm4h
-MQp0PUMueEIubShhLHQtMSkKcmV0dXJuISh0PT09NDd8fHQ9PT05Mil9LApTcDpmdW5jdGlvbihhLGIp
-e3ZhciB0LHMscj1hLmxlbmd0aAppZihyPT09MClyZXR1cm4gMAp0PUMueEIuVyhhLDApCmlmKHQ9PT00
-NylyZXR1cm4gMQppZih0PT09OTIpe2lmKHI8Mnx8Qy54Qi5XKGEsMSkhPT05MilyZXR1cm4gMQpzPUMu
-eEIuWFUoYSwiXFwiLDIpCmlmKHM+MCl7cz1DLnhCLlhVKGEsIlxcIixzKzEpCmlmKHM+MClyZXR1cm4g
-c31yZXR1cm4gcn1pZihyPDMpcmV0dXJuIDAKaWYoIUIuT1ModCkpcmV0dXJuIDAKaWYoQy54Qi5XKGEs
-MSkhPT01OClyZXR1cm4gMApyPUMueEIuVyhhLDIpCmlmKCEocj09PTQ3fHxyPT09OTIpKXJldHVybiAw
-CnJldHVybiAzfSwKWXI6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuU3AoYSwhMSl9LApoSzpmdW5jdGlv
-bihhKXtyZXR1cm4gdGhpcy5ZcihhKT09PTF9LApPdDpmdW5jdGlvbihhLGIpe3ZhciB0CmlmKGE9PT1i
-KXJldHVybiEwCmlmKGE9PT00NylyZXR1cm4gYj09PTkyCmlmKGE9PT05MilyZXR1cm4gYj09PTQ3Cmlm
-KChhXmIpIT09MzIpcmV0dXJuITEKdD1hfDMyCnJldHVybiB0Pj05NyYmdDw9MTIyfSwKTmM6ZnVuY3Rp
-b24oYSxiKXt2YXIgdCxzLHIKaWYoYT09YilyZXR1cm4hMAp0PWEubGVuZ3RoCmlmKHQhPT1iLmxlbmd0
-aClyZXR1cm4hMQpmb3Iocz1KLnJZKGIpLHI9MDtyPHQ7KytyKWlmKCF0aGlzLk90KEMueEIuVyhhLHIp
-LHMuVyhiLHIpKSlyZXR1cm4hMQpyZXR1cm4hMH0sCmdvYzpmdW5jdGlvbigpe3JldHVybiJ3aW5kb3dz
-In0sCmdtSTpmdW5jdGlvbigpe3JldHVybiJcXCJ9fTsoZnVuY3Rpb24gYWxpYXNlcygpe3ZhciB0PUou
-dkIucHJvdG90eXBlCnQuVT10LloKdC5Taj10LmU3CnQ9Si5NRi5wcm90b3R5cGUKdC50PXQuWgp0PVAu
-Y1gucHJvdG90eXBlCnQuR0c9dC5ldgp0PVAuTWgucHJvdG90eXBlCnQueGI9dC5aCnQ9Vy5jdi5wcm90
-b3R5cGUKdC5EVz10LnI2CnQ9Vy5tNi5wcm90b3R5cGUKdC5qRj10LkViCnQ9UC5FNC5wcm90b3R5cGUK
-dC5Vcj10LnEKdC5lND10Lll9KSgpOyhmdW5jdGlvbiBpbnN0YWxsVGVhck9mZnMoKXt2YXIgdD1odW5r
-SGVscGVycy5fc3RhdGljXzEscz1odW5rSGVscGVycy5fc3RhdGljXzAscj1odW5rSGVscGVycy5pbnN0
-YWxsSW5zdGFuY2VUZWFyT2ZmLHE9aHVua0hlbHBlcnMuaW5zdGFsbFN0YXRpY1RlYXJPZmYscD1odW5r
-SGVscGVycy5faW5zdGFuY2VfMXUKdChQLCJFWCIsIlpWIiw4KQp0KFAsInl0Iiwib0EiLDgpCnQoUCwi
-cVciLCJCeiIsOCkKcyhQLCJWOSIsImVOIiwyKQpyKFAuUGYucHJvdG90eXBlLCJnWUoiLDAsMSxudWxs
-LFsiJDIiLCIkMSJdLFsidzAiLCJwbSJdLDI4LDApCnQoUCwiQ3kiLCJOQyIsMSkKdChQLCJQSCIsIk10
-Iiw1KQpxKFcsInBTIiw0LG51bGwsWyIkNCJdLFsicUQiXSw5LDApCnEoVywiVjQiLDQsbnVsbCxbIiQ0
-Il0sWyJRVyJdLDksMCkKcChQLkFzLnByb3RvdHlwZSwiZ3VNIiwiVCIsNSkKdChQLCJpRyIsIndZIiwx
-KQp0KFAsIncwIiwiTDciLDMyKQp0KEwsImlTIiwiaTYiLDE4KX0pKCk7KGZ1bmN0aW9uIGluaGVyaXRh
-bmNlKCl7dmFyIHQ9aHVua0hlbHBlcnMubWl4aW4scz1odW5rSGVscGVycy5pbmhlcml0LHI9aHVua0hl
-bHBlcnMuaW5oZXJpdE1hbnkKcyhQLk1oLG51bGwpCnIoUC5NaCxbSC5GSyxKLnZCLEoubTEsUC5uWSxQ
-LmNYLEguYTcsUC5BbixILlNVLEguUmUsSC53dixQLlBuLEguV1UsSC5MSSxILlRwLEguZjksUC5YUyxI
-LmJxLEguWE8sUC5ZayxILmRiLEguTjYsSC5WUixILkVLLEguUGIsSC50USxILlNkLEguSmMsSC5FVCxQ
-LlczLFAuaWgsUC5GeSxQLkdWLFAuYjgsUC5QZixQLkZlLFAudnMsUC5PTSxQLnFoLFAuTU8sUC5rVCxQ
-LnhJLFAuT0gsUC5tMCxQLlh2LFAuYm4sUC5sbSxQLmxELFAuS1AsUC5NYSxQLlRDLFAuVWssUC5TaCxQ
-LlJ3LFAuYnosUC5hMixQLmlQLFAubGYsUC5rNSxQLktZLFAuQ0QsUC5hRSxQLkVILFAuek0sUC5aMCxQ
-Lk4zLFAuYzgsUC5PZCxQLmliLFAuR3osUC5aZCxQLnFVLFAuUm4sUC5HRCxQLkRuLFAuUEUsUC5VZixX
-LmlkLFcuRmssVy5KUSxXLkdtLFcudkQsVy5tNixXLk93LFcuVzksVy5kVyxXLkZiLFcua0YsVy5tayxX
-LktvLFAuaUosUC5FNCxQLm42LE0uSDcsVS5MTCxVLmQyLFUuU2UsVS5NbCxVLnlELFUud2IsQi5qOCxC
-LnFwLFQubVEsTC5YQSxMLlpaLEwuTzksTS5sSSxPLnpMLFguV0QsWC5kdl0pCnIoSi52QixbSi55RSxK
-LllFLEouTUYsSi5qZCxKLnFJLEouRHIsSC5lSCxXLkQwLFcuQXosVy5MZSxXLk5oLFcuSUIsVy5uNyxX
-LmVhLFcuYnIsVy5TZyxXLnU4LFcuSzcsVy5YVyxQLmhGXSkKcihKLk1GLFtKLmlDLEoua2QsSi5jNV0p
-CnMoSi5QbyxKLmpkKQpyKEoucUksW0ouYlUsSi5WQV0pCnMoUC51eSxQLm5ZKQpyKFAudXksW0gudzIs
-Vy53eixXLmU3XSkKcyhILnFqLEgudzIpCnIoUC5jWCxbSC5iUSxILmkxLEguVTUsSC5YUixQLm1XLEgu
-TkZdKQpyKEguYlEsW0guYUwsSC5pNSxQLnh1XSkKcihILmFMLFtILm5ILEgubEosUC5pOF0pCnMoSC54
-eSxILmkxKQpyKFAuQW4sW0guTUgsSC52R10pCnMoUC5SVSxQLlBuKQpzKFAuR2osUC5SVSkKcyhILlBE
-LFAuR2opCnMoSC5MUCxILldVKQpyKEguVHAsW0guQ2osSC5BbSxILmxjLEgucixILmRDLEgud04sUC50
-aCxQLmhhLFAuVnMsUC5GdCxQLnlILFAuV00sUC5TWCxQLkdzLFAuZGEsUC5vUSxQLnBWLFAuVTcsUC52
-cixQLnJILFAuS0YsUC5aTCxQLlJULFAualosUC5ycSxQLlJXLFAuQjUsUC51TyxQLnBLLFAuaGosUC5W
-cCxQLk9SLFAucmEsUC55USxQLnRpLFAuV0YsUC5uMSxQLmNTLFAuVkMsUC5KVCxQLmUxLFAuTlksUC5S
-WixQLk1FLFAueTUsUC5xMyxQLnlJLFAuYzYsUC5xZCxXLkN2LFcuS1MsVy5BMyxXLnZOLFcuVXYsVy5F
-ZyxXLkVvLFcuV2ssVy5JQSxXLmZtLFAuamcsUC5UYSxQLkdFLFAuTjcsUC51USxQLlBDLFAubXQsUC5O
-eixQLlFTLFAubnAsVS5NRCxVLmFOLFUuYjAsTC5lLEwuVlcsTC5vWixMLmpyLEwucWwsTC55OCxMLkhp
-LEwuQlQsTC5MLEwuV3gsTC5BTyxMLmROLEwuSG8sTC54eixMLklDLEwuZkMsTC5uVCxMLkJaLEwuR0gs
-TC5FRSxMLlFMLEwuVlMsTC5URCxMLkFTLE0uTWksTS5xNyxNLk5vXSkKcihQLlhTLFtILlcwLEguYXos
-SC52VixILkVxLFAuQzYsSC51OSxQLlVkLFAuTEssUC5BVCxQLm1wLFAudWIsUC5kcyxQLmxqLFAuVVYs
-UC50N10pCnIoSC5sYyxbSC56eCxILmp5XSkKcyhILmtZLFAuQzYpCnMoUC5pbCxQLllrKQpyKFAuaWws
-W0guTjUsUC51dyxXLmNmLFcuU3ldKQpyKFAubVcsW0guS1csUC5xNF0pCnMoSC5MWixILmVIKQpyKEgu
-TFosW0guUkcsSC5XQl0pCnMoSC5WUCxILlJHKQpzKEguRGcsSC5WUCkKcyhILlpHLEguV0IpCnMoSC5Q
-ZyxILlpHKQpyKEguUGcsW0gueGosSC5kRSxILlpBLEgud2YsSC5QcSxILmVFLEguVjZdKQpzKEgueCxI
-LnU5KQpzKFAuWmYsUC5QZikKcyhQLkppLFAubTApCnMoUC5iNixQLlh2KQpzKFAuVmosUC5UQykKcihQ
-LlVrLFtQLkNWLFAuWmksUC5ieV0pCnMoUC53SSxQLmtUKQpyKFAud0ksW1AuVTgsUC5vaixQLk14LFAu
-RTMsUC5HWV0pCnMoUC5LOCxQLlVkKQpzKFAudHUsUC5TaCkKcyhQLnU1LFAuWmkpCnIoUC5sZixbUC5D
-UCxQLklmXSkKcihQLkFULFtQLmJKLFAuZVldKQpzKFAucWUsUC5EbikKcihXLkQwLFtXLnVILFcud2Es
-Vy5LNSxXLkNtXSkKcihXLnVILFtXLmN2LFcubngsVy5RRixXLkNRXSkKcihXLmN2LFtXLnFFLFAuZDVd
-KQpyKFcucUUsW1cuR2gsVy5mWSxXLm5CLFcuUVAsVy5oNCxXLlNOLFcubHAsVy5UYixXLkl2LFcuV1As
-Vy55WV0pCnMoVy5vSixXLkxlKQpzKFcuaEgsVy5BeikKcyhXLlZiLFcuUUYpCnMoVy5mSixXLndhKQpy
-KFcuZWEsW1cudzYsVy5ld10pCnMoVy5PSyxXLnc2KQpzKFcuckIsVy5LNykKcyhXLkJILFcuckIpCnMo
-Vy53NCxXLklCKQpzKFcub2EsVy5YVykKcyhXLnJoLFcub2EpCnMoVy5pNyxXLmNmKQpzKFAuQXMsUC5W
-aikKcihQLkFzLFtXLkk0LFAuS2VdKQpzKFcuUk8sUC5xaCkKcyhXLmV1LFcuUk8pCnMoVy54QyxQLk1P
-KQpzKFcuY3QsVy5tNikKcyhQLkJmLFAuaUopCnIoUC5FNCxbUC5yNyxQLmNvXSkKcyhQLlR6LFAuY28p
-CnMoUC5uZCxQLmQ1KQpzKEIuZnYsTy56TCkKcihCLmZ2LFtFLk9GLEYucnUsTC5JVl0pCnQoSC53MixI
-LlJlKQp0KEguUkcsUC5sRCkKdChILlZQLEguU1UpCnQoSC5XQixQLmxEKQp0KEguWkcsSC5TVSkKdChQ
-Lm5ZLFAubEQpCnQoUC5UQyxQLk1hKQp0KFAuUlUsUC5LUCkKdChXLkxlLFcuaWQpCnQoVy5LNyxQLmxE
-KQp0KFcuckIsVy5HbSkKdChXLlhXLFAubEQpCnQoVy5vYSxXLkdtKQp0KFAuY28sUC5sRCl9KSgpCnZh
-ciB2PXt0eXBlVW5pdmVyc2U6e2VDOm5ldyBNYXAoKSx0Ujp7fSxlVDp7fSx0UFY6e30sc0VBOltdfSxt
-YW5nbGVkR2xvYmFsTmFtZXM6e0lmOiJpbnQiLENQOiJkb3VibGUiLGxmOiJudW0iLHFVOiJTdHJpbmci
-LGEyOiJib29sIixjODoiTnVsbCIsek06Ikxpc3QifSxtYW5nbGVkTmFtZXM6e30sZ2V0VHlwZUZyb21O
-YW1lOmdldEdsb2JhbEZyb21OYW1lLG1ldGFkYXRhOltdLHR5cGVzOlsiYzgoKSIsIkAoQCkiLCJ+KCki
-LCJjOChPSykiLCJjOChALEApIiwicVUocVUpIiwiYzgoY3YpIiwiYTIocVUpIiwifih+KCkpIiwiYTIo
-Y3YscVUscVUsSlEpIiwiYzgoQCkiLCJ+KHh1PHFVPikiLCJjOChxVSxAKSIsImM4KHFVKSIsImM4KHFV
-LHFVKSIsImEyKGtGKSIsImM4KGVhKSIsImI4PGM4PihPSykiLCJ+KE9LKSIsIlowPHFVLHFVPihaMDxx
-VSxxVT4scVUpIiwiYzgofigpKSIsImM4KEAsR3opIiwifihxVSxxVSkiLCJuNihJZikiLCJuNihALEAp
-IiwiYTIodUgpIiwiYzgoSWYsQCkiLCJAKGVhKSIsIn4oTWhbR3pdKSIsImM4KEBbR3pdKSIsIn4odUgs
-dUgpIiwiYTIoeHU8cVU+KSIsIk1oKEApIiwicjcoQCkiLCJUejxAPihAKSIsIkU0KEApIiwiYTIoSDcp
-IiwiTEwoQCkiLCJaMDxxVSxNaD4oTEwpIiwidnM8QD4oQCkiLCJAKHFVKSIsImM4KFowPHFVLE1oPiki
-LCJjOChHRCxAKSIsInFVKE9LKSIsIkAoQCxxVSkiLCJjOChldykiLCJ+KHFVLElmKSIsIn4ocVVbQF0p
-IiwiSWYoSWYsSWYpIiwifihAKSJdLGludGVyY2VwdG9yc0J5VGFnOm51bGwsbGVhZlRhZ3M6bnVsbCxh
-cnJheVJ0aTp0eXBlb2YgU3ltYm9sPT0iZnVuY3Rpb24iJiZ0eXBlb2YgU3ltYm9sKCk9PSJzeW1ib2wi
-P1N5bWJvbCgiJHRpIik6IiR0aSJ9CkgueGIodi50eXBlVW5pdmVyc2UsSlNPTi5wYXJzZSgneyJjNSI6
-Ik1GIiwiaUMiOiJNRiIsImtkIjoiTUYiLCJyeCI6ImVhIiwiZTUiOiJlYSIsIlkwIjoiZDUiLCJ0cCI6
-ImQ1IiwiRzgiOiJldyIsIk1yIjoicUUiLCJlTCI6InFFIiwiSTAiOiJ1SCIsImhzIjoidUgiLCJYZyI6
-IlFGIiwibnIiOiJPSyIsInk0IjoidzYiLCJhUCI6IkNtIiwieGMiOiJueCIsImtKIjoibngiLCJ6VSI6
-IkRnIiwiZGYiOiJlSCIsInlFIjp7ImEyIjpbXX0sIllFIjp7ImM4IjpbXX0sIk1GIjp7InZtIjpbXSwi
-RUgiOltdfSwiamQiOnsiek0iOlsiMSJdLCJiUSI6WyIxIl0sImNYIjpbIjEiXX0sIlBvIjp7ImpkIjpb
-IjEiXSwiek0iOlsiMSJdLCJiUSI6WyIxIl0sImNYIjpbIjEiXX0sIm0xIjp7IkFuIjpbIjEiXX0sInFJ
-Ijp7IkNQIjpbXSwibGYiOltdfSwiYlUiOnsiSWYiOltdLCJDUCI6W10sImxmIjpbXX0sIlZBIjp7IkNQ
-IjpbXSwibGYiOltdfSwiRHIiOnsicVUiOltdLCJ2WCI6W119LCJxaiI6eyJSZSI6WyJJZiJdLCJsRCI6
-WyJJZiJdLCJ6TSI6WyJJZiJdLCJiUSI6WyJJZiJdLCJjWCI6WyJJZiJdLCJsRC5FIjoiSWYiLCJSZS5F
-IjoiSWYifSwiYlEiOnsiY1giOlsiMSJdfSwiYUwiOnsiYlEiOlsiMSJdLCJjWCI6WyIxIl19LCJuSCI6
-eyJhTCI6WyIxIl0sImJRIjpbIjEiXSwiY1giOlsiMSJdLCJhTC5FIjoiMSIsImNYLkUiOiIxIn0sImE3
-Ijp7IkFuIjpbIjEiXX0sImkxIjp7ImNYIjpbIjIiXSwiY1guRSI6IjIifSwieHkiOnsiaTEiOlsiMSIs
-IjIiXSwiYlEiOlsiMiJdLCJjWCI6WyIyIl0sImNYLkUiOiIyIn0sIk1IIjp7IkFuIjpbIjIiXX0sImxK
-Ijp7ImFMIjpbIjIiXSwiYlEiOlsiMiJdLCJjWCI6WyIyIl0sImFMLkUiOiIyIiwiY1guRSI6IjIifSwi
-VTUiOnsiY1giOlsiMSJdLCJjWC5FIjoiMSJ9LCJ2RyI6eyJBbiI6WyIxIl19LCJ3MiI6eyJSZSI6WyIx
-Il0sImxEIjpbIjEiXSwiek0iOlsiMSJdLCJiUSI6WyIxIl0sImNYIjpbIjEiXX0sInd2Ijp7IkdEIjpb
-XX0sIlBEIjp7IkdqIjpbIjEiLCIyIl0sIlJVIjpbIjEiLCIyIl0sIlBuIjpbIjEiLCIyIl0sIktQIjpb
-IjEiLCIyIl0sIlowIjpbIjEiLCIyIl19LCJXVSI6eyJaMCI6WyIxIiwiMiJdfSwiTFAiOnsiV1UiOlsi
-MSIsIjIiXSwiWjAiOlsiMSIsIjIiXX0sIlhSIjp7ImNYIjpbIjEiXSwiY1guRSI6IjEifSwiTEkiOnsi
-dlEiOltdfSwiVzAiOnsiWFMiOltdfSwiYXoiOnsiWFMiOltdfSwidlYiOnsiWFMiOltdfSwiWE8iOnsi
-R3oiOltdfSwiVHAiOnsiRUgiOltdfSwibGMiOnsiRUgiOltdfSwiengiOnsiRUgiOltdfSwiankiOnsi
-RUgiOltdfSwiRXEiOnsiWFMiOltdfSwia1kiOnsiWFMiOltdfSwiTjUiOnsiRm8iOlsiMSIsIjIiXSwi
-WWsiOlsiMSIsIjIiXSwiWjAiOlsiMSIsIjIiXSwiWWsuSyI6IjEiLCJZay5WIjoiMiJ9LCJpNSI6eyJi
-USI6WyIxIl0sImNYIjpbIjEiXSwiY1guRSI6IjEifSwiTjYiOnsiQW4iOlsiMSJdfSwiVlIiOnsid0wi
-OltdLCJ2WCI6W119LCJFSyI6eyJpYiI6W10sIk9kIjpbXX0sIktXIjp7ImNYIjpbImliIl0sImNYLkUi
-OiJpYiJ9LCJQYiI6eyJBbiI6WyJpYiJdfSwidFEiOnsiT2QiOltdfSwiTkYiOnsiY1giOlsiT2QiXSwi
-Y1guRSI6Ik9kIn0sIlNkIjp7IkFuIjpbIk9kIl19LCJlSCI6eyJlcSI6W119LCJMWiI6eyJYaiI6WyJA
-Il0sImVIIjpbXSwiZXEiOltdfSwiRGciOnsibEQiOlsiQ1AiXSwiWGoiOlsiQCJdLCJ6TSI6WyJDUCJd
-LCJlSCI6W10sImJRIjpbIkNQIl0sIlNVIjpbIkNQIl0sImVxIjpbXSwiY1giOlsiQ1AiXSwibEQuRSI6
-IkNQIn0sIlBnIjp7ImxEIjpbIklmIl0sInpNIjpbIklmIl0sIlhqIjpbIkAiXSwiZUgiOltdLCJiUSI6
-WyJJZiJdLCJTVSI6WyJJZiJdLCJlcSI6W10sImNYIjpbIklmIl19LCJ4aiI6eyJsRCI6WyJJZiJdLCJ6
-TSI6WyJJZiJdLCJYaiI6WyJAIl0sImVIIjpbXSwiYlEiOlsiSWYiXSwiU1UiOlsiSWYiXSwiZXEiOltd
-LCJjWCI6WyJJZiJdLCJsRC5FIjoiSWYifSwiZEUiOnsibEQiOlsiSWYiXSwiek0iOlsiSWYiXSwiWGoi
-OlsiQCJdLCJlSCI6W10sImJRIjpbIklmIl0sIlNVIjpbIklmIl0sImVxIjpbXSwiY1giOlsiSWYiXSwi
-bEQuRSI6IklmIn0sIlpBIjp7ImxEIjpbIklmIl0sInpNIjpbIklmIl0sIlhqIjpbIkAiXSwiZUgiOltd
-LCJiUSI6WyJJZiJdLCJTVSI6WyJJZiJdLCJlcSI6W10sImNYIjpbIklmIl0sImxELkUiOiJJZiJ9LCJ3
-ZiI6eyJsRCI6WyJJZiJdLCJ6TSI6WyJJZiJdLCJYaiI6WyJAIl0sImVIIjpbXSwiYlEiOlsiSWYiXSwi
-U1UiOlsiSWYiXSwiZXEiOltdLCJjWCI6WyJJZiJdLCJsRC5FIjoiSWYifSwiUHEiOnsibEQiOlsiSWYi
-XSwiek0iOlsiSWYiXSwiWGoiOlsiQCJdLCJlSCI6W10sImJRIjpbIklmIl0sIlNVIjpbIklmIl0sImVx
-IjpbXSwiY1giOlsiSWYiXSwibEQuRSI6IklmIn0sImVFIjp7ImxEIjpbIklmIl0sInpNIjpbIklmIl0s
-IlhqIjpbIkAiXSwiZUgiOltdLCJiUSI6WyJJZiJdLCJTVSI6WyJJZiJdLCJlcSI6W10sImNYIjpbIklm
-Il0sImxELkUiOiJJZiJ9LCJWNiI6eyJuNiI6W10sImxEIjpbIklmIl0sInpNIjpbIklmIl0sIlhqIjpb
-IkAiXSwiZUgiOltdLCJiUSI6WyJJZiJdLCJTVSI6WyJJZiJdLCJlcSI6W10sImNYIjpbIklmIl0sImxE
-LkUiOiJJZiJ9LCJ1OSI6eyJYUyI6W119LCJ4Ijp7IlhTIjpbXX0sIkdWIjp7IkFuIjpbIjEiXX0sInE0
-Ijp7ImNYIjpbIjEiXSwiY1guRSI6IjEifSwiWmYiOnsiUGYiOlsiMSJdfSwidnMiOnsiYjgiOlsiMSJd
-fSwiT0giOnsiWFMiOltdfSwibTAiOnsiSkIiOltdfSwiSmkiOnsiSkIiOltdfSwiYjYiOnsiWHYiOlsi
-MSJdLCJ4dSI6WyIxIl0sImJRIjpbIjEiXSwiY1giOlsiMSJdfSwibG0iOnsiQW4iOlsiMSJdfSwibVci
-OnsiY1giOlsiMSJdfSwidXkiOnsibEQiOlsiMSJdLCJ6TSI6WyIxIl0sImJRIjpbIjEiXSwiY1giOlsi
-MSJdfSwiaWwiOnsiWWsiOlsiMSIsIjIiXSwiWjAiOlsiMSIsIjIiXX0sIllrIjp7IlowIjpbIjEiLCIy
-Il19LCJQbiI6eyJaMCI6WyIxIiwiMiJdfSwiR2oiOnsiUlUiOlsiMSIsIjIiXSwiUG4iOlsiMSIsIjIi
-XSwiS1AiOlsiMSIsIjIiXSwiWjAiOlsiMSIsIjIiXX0sIlZqIjp7Ik1hIjpbIjEiXSwieHUiOlsiMSJd
-LCJiUSI6WyIxIl0sImNYIjpbIjEiXX0sIlh2Ijp7Inh1IjpbIjEiXSwiYlEiOlsiMSJdLCJjWCI6WyIx
-Il19LCJ1dyI6eyJZayI6WyJxVSIsIkAiXSwiWjAiOlsicVUiLCJAIl0sIllrLksiOiJxVSIsIllrLlYi
-OiJAIn0sImk4Ijp7ImFMIjpbInFVIl0sImJRIjpbInFVIl0sImNYIjpbInFVIl0sImFMLkUiOiJxVSIs
-ImNYLkUiOiJxVSJ9LCJDViI6eyJVayI6WyJ6TTxJZj4iLCJxVSJdLCJVay5TIjoiek08SWY+In0sIlU4
-Ijp7IndJIjpbInpNPElmPiIsInFVIl19LCJaaSI6eyJVayI6WyJxVSIsInpNPElmPiJdfSwiVWQiOnsi
-WFMiOltdfSwiSzgiOnsiWFMiOltdfSwiYnkiOnsiVWsiOlsiTWgiLCJxVSJdLCJVay5TIjoiTWgifSwi
-b2oiOnsid0kiOlsiTWgiLCJxVSJdfSwiTXgiOnsid0kiOlsicVUiLCJNaCJdfSwidTUiOnsiVWsiOlsi
-cVUiLCJ6TTxJZj4iXSwiVWsuUyI6InFVIn0sIkUzIjp7IndJIjpbInFVIiwiek08SWY+Il19LCJHWSI6
-eyJ3SSI6WyJ6TTxJZj4iLCJxVSJdfSwiQ1AiOnsibGYiOltdfSwiQzYiOnsiWFMiOltdfSwiTEsiOnsi
-WFMiOltdfSwiQVQiOnsiWFMiOltdfSwiYkoiOnsiWFMiOltdfSwiZVkiOnsiWFMiOltdfSwibXAiOnsi
-WFMiOltdfSwidWIiOnsiWFMiOltdfSwiZHMiOnsiWFMiOltdfSwibGoiOnsiWFMiOltdfSwiVVYiOnsi
-WFMiOltdfSwiazUiOnsiWFMiOltdfSwiS1kiOnsiWFMiOltdfSwidDciOnsiWFMiOltdfSwiQ0QiOnsi
-UnoiOltdfSwiYUUiOnsiUnoiOltdfSwiSWYiOnsibGYiOltdfSwiek0iOnsiYlEiOlsiMSJdLCJjWCI6
-WyIxIl19LCJpYiI6eyJPZCI6W119LCJ4dSI6eyJiUSI6WyIxIl0sImNYIjpbIjEiXX0sIlpkIjp7Ikd6
-IjpbXX0sInFVIjp7InZYIjpbXX0sIlJuIjp7IkJMIjpbXX0sIkRuIjp7ImlEIjpbXX0sIlVmIjp7ImlE
-IjpbXX0sInFlIjp7ImlEIjpbXX0sInFFIjp7ImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJHaCI6eyJj
-diI6W10sInVIIjpbXSwiRDAiOltdfSwiZlkiOnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sIm5CIjp7
-ImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJRUCI6eyJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwibngi
-OnsidUgiOltdLCJEMCI6W119LCJRRiI6eyJ1SCI6W10sIkQwIjpbXX0sIklCIjp7InRuIjpbImxmIl19
-LCJ3eiI6eyJsRCI6WyIxIl0sInpNIjpbIjEiXSwiYlEiOlsiMSJdLCJjWCI6WyIxIl0sImxELkUiOiIx
-In0sImN2Ijp7InVIIjpbXSwiRDAiOltdfSwiaEgiOnsiQXoiOltdfSwiaDQiOnsiY3YiOltdLCJ1SCI6
-W10sIkQwIjpbXX0sIlZiIjp7InVIIjpbXSwiRDAiOltdfSwiZkoiOnsiRDAiOltdfSwid2EiOnsiRDAi
-OltdfSwiT0siOnsiZWEiOltdfSwiZTciOnsibEQiOlsidUgiXSwiek0iOlsidUgiXSwiYlEiOlsidUgi
-XSwiY1giOlsidUgiXSwibEQuRSI6InVIIn0sInVIIjp7IkQwIjpbXX0sIkJIIjp7IkdtIjpbInVIIl0s
-ImxEIjpbInVIIl0sInpNIjpbInVIIl0sIlhqIjpbInVIIl0sImJRIjpbInVIIl0sImNYIjpbInVIIl0s
-ImxELkUiOiJ1SCIsIkdtLkUiOiJ1SCJ9LCJTTiI6eyJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwiZXci
-OnsiZWEiOltdfSwibHAiOnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sIlRiIjp7ImN2IjpbXSwidUgi
-OltdLCJEMCI6W119LCJJdiI6eyJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwiV1AiOnsiY3YiOltdLCJ1
-SCI6W10sIkQwIjpbXX0sInlZIjp7ImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJ3NiI6eyJlYSI6W119
-LCJLNSI6eyJ2NiI6W10sIkQwIjpbXX0sIkNtIjp7IkQwIjpbXX0sIkNRIjp7InVIIjpbXSwiRDAiOltd
-fSwidzQiOnsidG4iOlsibGYiXX0sInJoIjp7IkdtIjpbInVIIl0sImxEIjpbInVIIl0sInpNIjpbInVI
-Il0sIlhqIjpbInVIIl0sImJRIjpbInVIIl0sImNYIjpbInVIIl0sImxELkUiOiJ1SCIsIkdtLkUiOiJ1
-SCJ9LCJjZiI6eyJZayI6WyJxVSIsInFVIl0sIlowIjpbInFVIiwicVUiXX0sImk3Ijp7IllrIjpbInFV
-IiwicVUiXSwiWjAiOlsicVUiLCJxVSJdLCJZay5LIjoicVUiLCJZay5WIjoicVUifSwiU3kiOnsiWWsi
-OlsicVUiLCJxVSJdLCJaMCI6WyJxVSIsInFVIl0sIllrLksiOiJxVSIsIllrLlYiOiJxVSJ9LCJJNCI6
-eyJNYSI6WyJxVSJdLCJ4dSI6WyJxVSJdLCJiUSI6WyJxVSJdLCJjWCI6WyJxVSJdfSwiUk8iOnsicWgi
-OlsiMSJdfSwiZXUiOnsiUk8iOlsiMSJdLCJxaCI6WyIxIl19LCJ4QyI6eyJNTyI6WyIxIl19LCJKUSI6
-eyJrRiI6W119LCJ2RCI6eyJrRiI6W119LCJtNiI6eyJrRiI6W119LCJjdCI6eyJrRiI6W119LCJPdyI6
-eyJrRiI6W119LCJXOSI6eyJBbiI6WyIxIl19LCJkVyI6eyJ2NiI6W10sIkQwIjpbXX0sIm1rIjp7Inkw
-IjpbXX0sIktvIjp7Im9uIjpbXX0sIkFzIjp7Ik1hIjpbInFVIl0sInh1IjpbInFVIl0sImJRIjpbInFV
-Il0sImNYIjpbInFVIl19LCJyNyI6eyJFNCI6W119LCJUeiI6eyJsRCI6WyIxIl0sInpNIjpbIjEiXSwi
-YlEiOlsiMSJdLCJFNCI6W10sImNYIjpbIjEiXSwibEQuRSI6IjEifSwibmQiOnsiZDUiOltdLCJjdiI6
-W10sInVIIjpbXSwiRDAiOltdfSwiS2UiOnsiTWEiOlsicVUiXSwieHUiOlsicVUiXSwiYlEiOlsicVUi
-XSwiY1giOlsicVUiXX0sImQ1Ijp7ImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJuNiI6eyJ6TSI6WyJJ
-ZiJdLCJiUSI6WyJJZiJdLCJlcSI6W10sImNYIjpbIklmIl19LCJYQSI6eyJrRiI6W119LCJkdiI6eyJS
-eiI6W119LCJPRiI6eyJmdiI6W119LCJydSI6eyJmdiI6W119LCJJViI6eyJmdiI6W119fScpKQpILkZG
-KHYudHlwZVVuaXZlcnNlLEpTT04ucGFyc2UoJ3siYlEiOjEsIncyIjoxLCJNTyI6MSwia1QiOjIsIm1X
-IjoxLCJ1eSI6MSwiaWwiOjIsIlZqIjoxLCJuWSI6MSwiVEMiOjEsImNvIjoxfScpKQp2YXIgdT0oZnVu
-Y3Rpb24gcnRpaSgpe3ZhciB0PUguTjAKcmV0dXJue2JxOnQoIkdoIiksbjp0KCJPSCIpLGNSOnQoIm5C
-IiksZDp0KCJBeiIpLFk6dCgiUVAiKSxnRjp0KCJQRDxHRCxAPiIpLGd3OnQoImJRPEA+IiksaDp0KCJj
-diIpLFc6dCgiWFMiKSxCOnQoImVhIikscjp0KCJEMCIpLGc4OnQoIlJ6IiksYzg6dCgiaEgiKSxaOnQo
-IkVIIiksYVE6dCgiYjg8Yzg+IiksYzp0KCJiODxAPiIpLEU6dCgiTEwiKSxncDp0KCJINyIpLEk6dCgi
-U2ciKSxvOnQoInZRIiksZWg6dCgiY1g8dUg+IiksWDp0KCJjWDxxVT4iKSxSOnQoImNYPEA+IiksZkE6
-dCgiamQ8U2U+IiksZ2k6dCgiamQ8ajg+IiksSjp0KCJqZDxaMDxxVSxNaD4+IiksZmg6dCgiamQ8Wlo+
-IiksaTp0KCJqZDxrRj4iKSxzOnQoImpkPHFVPiIpLGhoOnQoImpkPHlEPiIpLGFKOnQoImpkPHdiPiIp
-LGI6dCgiamQ8QD4iKSx0OnQoImpkPElmPiIpLGVIOnQoInZtIiksZzp0KCJjNSIpLGFVOnQoIlhqPEA+
-IiksYW06dCgiVHo8QD4iKSxlbzp0KCJONTxHRCxAPiIpLG06dCgiRTQiKSxkejp0KCJoRiIpLGY0OnQo
-InpNPGo4PiIpLGQzOnQoInpNPFowPHFVLE1oPj4iKSxldzp0KCJ6TTxNaD4iKSxhOnQoInpNPHFVPiIp
-LGo6dCgiek08QD4iKSxMOnQoInpNPElmPiIpLGFfOnQoInU4IiksUzp0KCJaMDxxVSxNaD4iKSxmOnQo
-IlowPHFVLHFVPiIpLGs6dCgiWjA8cVUsQD4iKSxHOnQoIlowPEAsQD4iKSxkdjp0KCJsSjxxVSxxVT4i
-KSxkbzp0KCJsSjxxVSxAPiIpLFY6dCgiT0siKSxkRDp0KCJlSCIpLGJtOnQoIlY2IiksQTp0KCJ1SCIp
-LGU6dCgia0YiKSxQOnQoImM4IiksSzp0KCJNaCIpLEY6dCgiZXciKSxxOnQoInRuPGxmPiIpLGZ2OnQo
-IndMIiksYXY6dCgiSmMiKSxhTzp0KCJuZCIpLEM6dCgieHU8cVU+IiksbDp0KCJHeiIpLE46dCgicVUi
-KSxkRzp0KCJxVShxVSkiKSxnNzp0KCJkNSIpLGZvOnQoIkdEIiksYVc6dCgieVkiKSx1OnQoImVxIiks
-Z2M6dCgibjYiKSxhazp0KCJrZCIpLHY6dCgiR2o8cVUscVU+Iiksdzp0KCJpRCIpLGNjOnQoIlU1PHFV
-PiIpLGc0OnQoIks1IiksY2k6dCgidjYiKSxnMjp0KCJDbSIpLGJqOnQoIlpmPGZKPiIpLGg5OnQoIkNR
-IiksYWM6dCgiZTciKSxROnQoImV1PE9LPiIpLFQ6dCgid3o8Y3Y+IikseDp0KCJGZTxALEA+IiksYW86
-dCgidnM8Zko+IiksXzp0KCJ2czxAPiIpLGZKOnQoInZzPElmPiIpLE86dCgiSlEiKSxEOnQoImJuIiks
-eTp0KCJhMiIpLGFsOnQoImEyKE1oKSIpLGJCOnQoImEyKHFVKSIpLGJmOnQoImEyKEApIiksZ1I6dCgi
-Q1AiKSx6OnQoIkAiKSxmTzp0KCJAKCkiKSxVOnQoIkAoZWEpIiksYkk6dCgiQChNaCkiKSxlcDp0KCJA
-KE1oLE1oKSIpLGFnOnQoIkAoTWgsR3opIiksYlU6dCgiQCh4dTxxVT4pIiksZE86dCgiQChxVSkiKSxi
-Yzp0KCJAKEApIiksYjg6dCgiQChALEApIikscDp0KCJJZiIpLGRpOnQoImxmIiksSDp0KCJ+IiksTTp0
-KCJ+KCkiKSxhbjp0KCJ+KGV3KSIpLGVBOnQoIn4ocVUscVUpIiksY0E6dCgifihxVSxAKSIpfX0pKCk7
-KGZ1bmN0aW9uIGNvbnN0YW50cygpe3ZhciB0PWh1bmtIZWxwZXJzLm1ha2VDb25zdExpc3QKQy5SWT1X
-LlFQLnByb3RvdHlwZQpDLkJaPVcuVmIucHJvdG90eXBlCkMuRHQ9Vy5mSi5wcm90b3R5cGUKQy5Paz1K
-LnZCLnByb3RvdHlwZQpDLk5tPUouamQucHJvdG90eXBlCkMuam49Si5iVS5wcm90b3R5cGUKQy5DRD1K
-LnFJLnByb3RvdHlwZQpDLnhCPUouRHIucHJvdG90eXBlCkMuREc9Si5jNS5wcm90b3R5cGUKQy5FeD1X
-LnU4LnByb3RvdHlwZQpDLnQ1PVcuQkgucHJvdG90eXBlCkMuTHQ9Vy5TTi5wcm90b3R5cGUKQy5aUT1K
-LmlDLnByb3RvdHlwZQpDLkllPVcuVGIucHJvdG90eXBlCkMudkI9Si5rZC5wcm90b3R5cGUKQy5vbD1X
-Lks1LnByb3RvdHlwZQpDLnk4PW5ldyBQLlU4KCkKQy5oOT1uZXcgUC5DVigpCkMud2I9ZnVuY3Rpb24g
-Z2V0VGFnRmFsbGJhY2sobykgewogIHZhciBzID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxs
-KG8pOwogIHJldHVybiBzLnN1YnN0cmluZyg4LCBzLmxlbmd0aCAtIDEpOwp9CkMuTzQ9ZnVuY3Rpb24o
-KSB7CiAgdmFyIHRvU3RyaW5nRnVuY3Rpb24gPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nOwogIGZ1
-bmN0aW9uIGdldFRhZyhvKSB7CiAgICB2YXIgcyA9IHRvU3RyaW5nRnVuY3Rpb24uY2FsbChvKTsKICAg
-IHJldHVybiBzLnN1YnN0cmluZyg4LCBzLmxlbmd0aCAtIDEpOwogIH0KICBmdW5jdGlvbiBnZXRVbmtu
-b3duVGFnKG9iamVjdCwgdGFnKSB7CiAgICBpZiAoL15IVE1MW0EtWl0uKkVsZW1lbnQkLy50ZXN0KHRh
-ZykpIHsKICAgICAgdmFyIG5hbWUgPSB0b1N0cmluZ0Z1bmN0aW9uLmNhbGwob2JqZWN0KTsKICAgICAg
-aWYgKG5hbWUgPT0gIltvYmplY3QgT2JqZWN0XSIpIHJldHVybiBudWxsOwogICAgICByZXR1cm4gIkhU
-TUxFbGVtZW50IjsKICAgIH0KICB9CiAgZnVuY3Rpb24gZ2V0VW5rbm93blRhZ0dlbmVyaWNCcm93c2Vy
-KG9iamVjdCwgdGFnKSB7CiAgICBpZiAoc2VsZi5IVE1MRWxlbWVudCAmJiBvYmplY3QgaW5zdGFuY2Vv
-ZiBIVE1MRWxlbWVudCkgcmV0dXJuICJIVE1MRWxlbWVudCI7CiAgICByZXR1cm4gZ2V0VW5rbm93blRh
-ZyhvYmplY3QsIHRhZyk7CiAgfQogIGZ1bmN0aW9uIHByb3RvdHlwZUZvclRhZyh0YWcpIHsKICAgIGlm
-ICh0eXBlb2Ygd2luZG93ID09ICJ1bmRlZmluZWQiKSByZXR1cm4gbnVsbDsKICAgIGlmICh0eXBlb2Yg
-d2luZG93W3RhZ10gPT0gInVuZGVmaW5lZCIpIHJldHVybiBudWxsOwogICAgdmFyIGNvbnN0cnVjdG9y
-ID0gd2luZG93W3RhZ107CiAgICBpZiAodHlwZW9mIGNvbnN0cnVjdG9yICE9ICJmdW5jdGlvbiIpIHJl
-dHVybiBudWxsOwogICAgcmV0dXJuIGNvbnN0cnVjdG9yLnByb3RvdHlwZTsKICB9CiAgZnVuY3Rpb24g
-ZGlzY3JpbWluYXRvcih0YWcpIHsgcmV0dXJuIG51bGw7IH0KICB2YXIgaXNCcm93c2VyID0gdHlwZW9m
-IG5hdmlnYXRvciA9PSAib2JqZWN0IjsKICByZXR1cm4gewogICAgZ2V0VGFnOiBnZXRUYWcsCiAgICBn
-ZXRVbmtub3duVGFnOiBpc0Jyb3dzZXIgPyBnZXRVbmtub3duVGFnR2VuZXJpY0Jyb3dzZXIgOiBnZXRV
-bmtub3duVGFnLAogICAgcHJvdG90eXBlRm9yVGFnOiBwcm90b3R5cGVGb3JUYWcsCiAgICBkaXNjcmlt
-aW5hdG9yOiBkaXNjcmltaW5hdG9yIH07Cn0KQy5kaz1mdW5jdGlvbihnZXRUYWdGYWxsYmFjaykgewog
-IHJldHVybiBmdW5jdGlvbihob29rcykgewogICAgaWYgKHR5cGVvZiBuYXZpZ2F0b3IgIT0gIm9iamVj
-dCIpIHJldHVybiBob29rczsKICAgIHZhciB1YSA9IG5hdmlnYXRvci51c2VyQWdlbnQ7CiAgICBpZiAo
-dWEuaW5kZXhPZigiRHVtcFJlbmRlclRyZWUiKSA+PSAwKSByZXR1cm4gaG9va3M7CiAgICBpZiAodWEu
-aW5kZXhPZigiQ2hyb21lIikgPj0gMCkgewogICAgICBmdW5jdGlvbiBjb25maXJtKHApIHsKICAgICAg
-ICByZXR1cm4gdHlwZW9mIHdpbmRvdyA9PSAib2JqZWN0IiAmJiB3aW5kb3dbcF0gJiYgd2luZG93W3Bd
-Lm5hbWUgPT0gcDsKICAgICAgfQogICAgICBpZiAoY29uZmlybSgiV2luZG93IikgJiYgY29uZmlybSgi
-SFRNTEVsZW1lbnQiKSkgcmV0dXJuIGhvb2tzOwogICAgfQogICAgaG9va3MuZ2V0VGFnID0gZ2V0VGFn
-RmFsbGJhY2s7CiAgfTsKfQpDLllxPWZ1bmN0aW9uKGhvb2tzKSB7CiAgaWYgKHR5cGVvZiBkYXJ0RXhw
-ZXJpbWVudGFsRml4dXBHZXRUYWcgIT0gImZ1bmN0aW9uIikgcmV0dXJuIGhvb2tzOwogIGhvb2tzLmdl
-dFRhZyA9IGRhcnRFeHBlcmltZW50YWxGaXh1cEdldFRhZyhob29rcy5nZXRUYWcpOwp9CkMuS1U9ZnVu
-Y3Rpb24oaG9va3MpIHsKICB2YXIgZ2V0VGFnID0gaG9va3MuZ2V0VGFnOwogIHZhciBwcm90b3R5cGVG
-b3JUYWcgPSBob29rcy5wcm90b3R5cGVGb3JUYWc7CiAgZnVuY3Rpb24gZ2V0VGFnRml4ZWQobykgewog
-ICAgdmFyIHRhZyA9IGdldFRhZyhvKTsKICAgIGlmICh0YWcgPT0gIkRvY3VtZW50IikgewogICAgICBp
-ZiAoISFvLnhtbFZlcnNpb24pIHJldHVybiAiIURvY3VtZW50IjsKICAgICAgcmV0dXJuICIhSFRNTERv
-Y3VtZW50IjsKICAgIH0KICAgIHJldHVybiB0YWc7CiAgfQogIGZ1bmN0aW9uIHByb3RvdHlwZUZvclRh
-Z0ZpeGVkKHRhZykgewogICAgaWYgKHRhZyA9PSAiRG9jdW1lbnQiKSByZXR1cm4gbnVsbDsKICAgIHJl
-dHVybiBwcm90b3R5cGVGb3JUYWcodGFnKTsKICB9CiAgaG9va3MuZ2V0VGFnID0gZ2V0VGFnRml4ZWQ7
-CiAgaG9va3MucHJvdG90eXBlRm9yVGFnID0gcHJvdG90eXBlRm9yVGFnRml4ZWQ7Cn0KQy54aT1mdW5j
-dGlvbihob29rcykgewogIHZhciB1c2VyQWdlbnQgPSB0eXBlb2YgbmF2aWdhdG9yID09ICJvYmplY3Qi
-ID8gbmF2aWdhdG9yLnVzZXJBZ2VudCA6ICIiOwogIGlmICh1c2VyQWdlbnQuaW5kZXhPZigiRmlyZWZv
-eCIpID09IC0xKSByZXR1cm4gaG9va3M7CiAgdmFyIGdldFRhZyA9IGhvb2tzLmdldFRhZzsKICB2YXIg
-cXVpY2tNYXAgPSB7CiAgICAiQmVmb3JlVW5sb2FkRXZlbnQiOiAiRXZlbnQiLAogICAgIkRhdGFUcmFu
-c2ZlciI6ICJDbGlwYm9hcmQiLAogICAgIkdlb0dlb2xvY2F0aW9uIjogIkdlb2xvY2F0aW9uIiwKICAg
-ICJMb2NhdGlvbiI6ICIhTG9jYXRpb24iLAogICAgIldvcmtlck1lc3NhZ2VFdmVudCI6ICJNZXNzYWdl
-RXZlbnQiLAogICAgIlhNTERvY3VtZW50IjogIiFEb2N1bWVudCJ9OwogIGZ1bmN0aW9uIGdldFRhZ0Zp
-cmVmb3gobykgewogICAgdmFyIHRhZyA9IGdldFRhZyhvKTsKICAgIHJldHVybiBxdWlja01hcFt0YWdd
-IHx8IHRhZzsKICB9CiAgaG9va3MuZ2V0VGFnID0gZ2V0VGFnRmlyZWZveDsKfQpDLmk3PWZ1bmN0aW9u
-KGhvb2tzKSB7CiAgdmFyIHVzZXJBZ2VudCA9IHR5cGVvZiBuYXZpZ2F0b3IgPT0gIm9iamVjdCIgPyBu
-YXZpZ2F0b3IudXNlckFnZW50IDogIiI7CiAgaWYgKHVzZXJBZ2VudC5pbmRleE9mKCJUcmlkZW50LyIp
-ID09IC0xKSByZXR1cm4gaG9va3M7CiAgdmFyIGdldFRhZyA9IGhvb2tzLmdldFRhZzsKICB2YXIgcXVp
-Y2tNYXAgPSB7CiAgICAiQmVmb3JlVW5sb2FkRXZlbnQiOiAiRXZlbnQiLAogICAgIkRhdGFUcmFuc2Zl
-ciI6ICJDbGlwYm9hcmQiLAogICAgIkhUTUxEREVsZW1lbnQiOiAiSFRNTEVsZW1lbnQiLAogICAgIkhU
-TUxEVEVsZW1lbnQiOiAiSFRNTEVsZW1lbnQiLAogICAgIkhUTUxQaHJhc2VFbGVtZW50IjogIkhUTUxF
-bGVtZW50IiwKICAgICJQb3NpdGlvbiI6ICJHZW9wb3NpdGlvbiIKICB9OwogIGZ1bmN0aW9uIGdldFRh
-Z0lFKG8pIHsKICAgIHZhciB0YWcgPSBnZXRUYWcobyk7CiAgICB2YXIgbmV3VGFnID0gcXVpY2tNYXBb
-dGFnXTsKICAgIGlmIChuZXdUYWcpIHJldHVybiBuZXdUYWc7CiAgICBpZiAodGFnID09ICJPYmplY3Qi
-KSB7CiAgICAgIGlmICh3aW5kb3cuRGF0YVZpZXcgJiYgKG8gaW5zdGFuY2VvZiB3aW5kb3cuRGF0YVZp
-ZXcpKSByZXR1cm4gIkRhdGFWaWV3IjsKICAgIH0KICAgIHJldHVybiB0YWc7CiAgfQogIGZ1bmN0aW9u
-IHByb3RvdHlwZUZvclRhZ0lFKHRhZykgewogICAgdmFyIGNvbnN0cnVjdG9yID0gd2luZG93W3RhZ107
-CiAgICBpZiAoY29uc3RydWN0b3IgPT0gbnVsbCkgcmV0dXJuIG51bGw7CiAgICByZXR1cm4gY29uc3Ry
-dWN0b3IucHJvdG90eXBlOwogIH0KICBob29rcy5nZXRUYWcgPSBnZXRUYWdJRTsKICBob29rcy5wcm90
-b3R5cGVGb3JUYWcgPSBwcm90b3R5cGVGb3JUYWdJRTsKfQpDLmZRPWZ1bmN0aW9uKGhvb2tzKSB7IHJl
-dHVybiBob29rczsgfQoKQy5DdD1uZXcgUC5ieSgpCkMuRXE9bmV3IFAuazUoKQpDLnhNPW5ldyBQLnU1
-KCkKQy5Raz1uZXcgUC5FMygpCkMuTlU9bmV3IFAuSmkoKQpDLnBkPW5ldyBQLlpkKCkKQy5BZD1uZXcg
-TS5INygwLCJIaW50QWN0aW9uS2luZC5hZGROdWxsYWJsZUhpbnQiKQpDLm5lPW5ldyBNLkg3KDEsIkhp
-bnRBY3Rpb25LaW5kLmFkZE5vbk51bGxhYmxlSGludCIpCkMubXk9bmV3IE0uSDcoMiwiSGludEFjdGlv
-bktpbmQuY2hhbmdlVG9OdWxsYWJsZUhpbnQiKQpDLnJ4PW5ldyBNLkg3KDMsIkhpbnRBY3Rpb25LaW5k
-LmNoYW5nZVRvTm9uTnVsbGFibGVIaW50IikKQy53Vj1uZXcgTS5INyg0LCJIaW50QWN0aW9uS2luZC5y
-ZW1vdmVOdWxsYWJsZUhpbnQiKQpDLmZSPW5ldyBNLkg3KDUsIkhpbnRBY3Rpb25LaW5kLnJlbW92ZU5v
-bk51bGxhYmxlSGludCIpCkMuQTM9bmV3IFAuTXgobnVsbCkKQy5uWD1uZXcgUC5vaihudWxsKQpDLkdi
-PUguVk0odChbMTI3LDIwNDcsNjU1MzUsMTExNDExMV0pLHUudCkKQy5haz1ILlZNKHQoWzAsMCwzMjc3
-NiwzMzc5MiwxLDEwMjQwLDAsMF0pLHUudCkKQy5jbT1ILlZNKHQoWyIqOjpjbGFzcyIsIio6OmRpciIs
-Iio6OmRyYWdnYWJsZSIsIio6OmhpZGRlbiIsIio6OmlkIiwiKjo6aW5lcnQiLCIqOjppdGVtcHJvcCIs
-Iio6Oml0ZW1yZWYiLCIqOjppdGVtc2NvcGUiLCIqOjpsYW5nIiwiKjo6c3BlbGxjaGVjayIsIio6OnRp
-dGxlIiwiKjo6dHJhbnNsYXRlIiwiQTo6YWNjZXNza2V5IiwiQTo6Y29vcmRzIiwiQTo6aHJlZmxhbmci
-LCJBOjpuYW1lIiwiQTo6c2hhcGUiLCJBOjp0YWJpbmRleCIsIkE6OnRhcmdldCIsIkE6OnR5cGUiLCJB
-UkVBOjphY2Nlc3NrZXkiLCJBUkVBOjphbHQiLCJBUkVBOjpjb29yZHMiLCJBUkVBOjpub2hyZWYiLCJB
-UkVBOjpzaGFwZSIsIkFSRUE6OnRhYmluZGV4IiwiQVJFQTo6dGFyZ2V0IiwiQVVESU86OmNvbnRyb2xz
-IiwiQVVESU86Omxvb3AiLCJBVURJTzo6bWVkaWFncm91cCIsIkFVRElPOjptdXRlZCIsIkFVRElPOjpw
-cmVsb2FkIiwiQkRPOjpkaXIiLCJCT0RZOjphbGluayIsIkJPRFk6OmJnY29sb3IiLCJCT0RZOjpsaW5r
-IiwiQk9EWTo6dGV4dCIsIkJPRFk6OnZsaW5rIiwiQlI6OmNsZWFyIiwiQlVUVE9OOjphY2Nlc3NrZXki
-LCJCVVRUT046OmRpc2FibGVkIiwiQlVUVE9OOjpuYW1lIiwiQlVUVE9OOjp0YWJpbmRleCIsIkJVVFRP
-Tjo6dHlwZSIsIkJVVFRPTjo6dmFsdWUiLCJDQU5WQVM6OmhlaWdodCIsIkNBTlZBUzo6d2lkdGgiLCJD
-QVBUSU9OOjphbGlnbiIsIkNPTDo6YWxpZ24iLCJDT0w6OmNoYXIiLCJDT0w6OmNoYXJvZmYiLCJDT0w6
-OnNwYW4iLCJDT0w6OnZhbGlnbiIsIkNPTDo6d2lkdGgiLCJDT0xHUk9VUDo6YWxpZ24iLCJDT0xHUk9V
-UDo6Y2hhciIsIkNPTEdST1VQOjpjaGFyb2ZmIiwiQ09MR1JPVVA6OnNwYW4iLCJDT0xHUk9VUDo6dmFs
-aWduIiwiQ09MR1JPVVA6OndpZHRoIiwiQ09NTUFORDo6Y2hlY2tlZCIsIkNPTU1BTkQ6OmNvbW1hbmQi
-LCJDT01NQU5EOjpkaXNhYmxlZCIsIkNPTU1BTkQ6OmxhYmVsIiwiQ09NTUFORDo6cmFkaW9ncm91cCIs
-IkNPTU1BTkQ6OnR5cGUiLCJEQVRBOjp2YWx1ZSIsIkRFTDo6ZGF0ZXRpbWUiLCJERVRBSUxTOjpvcGVu
-IiwiRElSOjpjb21wYWN0IiwiRElWOjphbGlnbiIsIkRMOjpjb21wYWN0IiwiRklFTERTRVQ6OmRpc2Fi
-bGVkIiwiRk9OVDo6Y29sb3IiLCJGT05UOjpmYWNlIiwiRk9OVDo6c2l6ZSIsIkZPUk06OmFjY2VwdCIs
-IkZPUk06OmF1dG9jb21wbGV0ZSIsIkZPUk06OmVuY3R5cGUiLCJGT1JNOjptZXRob2QiLCJGT1JNOjpu
-YW1lIiwiRk9STTo6bm92YWxpZGF0ZSIsIkZPUk06OnRhcmdldCIsIkZSQU1FOjpuYW1lIiwiSDE6OmFs
-aWduIiwiSDI6OmFsaWduIiwiSDM6OmFsaWduIiwiSDQ6OmFsaWduIiwiSDU6OmFsaWduIiwiSDY6OmFs
-aWduIiwiSFI6OmFsaWduIiwiSFI6Om5vc2hhZGUiLCJIUjo6c2l6ZSIsIkhSOjp3aWR0aCIsIkhUTUw6
-OnZlcnNpb24iLCJJRlJBTUU6OmFsaWduIiwiSUZSQU1FOjpmcmFtZWJvcmRlciIsIklGUkFNRTo6aGVp
-Z2h0IiwiSUZSQU1FOjptYXJnaW5oZWlnaHQiLCJJRlJBTUU6Om1hcmdpbndpZHRoIiwiSUZSQU1FOjp3
-aWR0aCIsIklNRzo6YWxpZ24iLCJJTUc6OmFsdCIsIklNRzo6Ym9yZGVyIiwiSU1HOjpoZWlnaHQiLCJJ
-TUc6OmhzcGFjZSIsIklNRzo6aXNtYXAiLCJJTUc6Om5hbWUiLCJJTUc6OnVzZW1hcCIsIklNRzo6dnNw
-YWNlIiwiSU1HOjp3aWR0aCIsIklOUFVUOjphY2NlcHQiLCJJTlBVVDo6YWNjZXNza2V5IiwiSU5QVVQ6
-OmFsaWduIiwiSU5QVVQ6OmFsdCIsIklOUFVUOjphdXRvY29tcGxldGUiLCJJTlBVVDo6YXV0b2ZvY3Vz
-IiwiSU5QVVQ6OmNoZWNrZWQiLCJJTlBVVDo6ZGlzYWJsZWQiLCJJTlBVVDo6aW5wdXRtb2RlIiwiSU5Q
-VVQ6OmlzbWFwIiwiSU5QVVQ6Omxpc3QiLCJJTlBVVDo6bWF4IiwiSU5QVVQ6Om1heGxlbmd0aCIsIklO
-UFVUOjptaW4iLCJJTlBVVDo6bXVsdGlwbGUiLCJJTlBVVDo6bmFtZSIsIklOUFVUOjpwbGFjZWhvbGRl
-ciIsIklOUFVUOjpyZWFkb25seSIsIklOUFVUOjpyZXF1aXJlZCIsIklOUFVUOjpzaXplIiwiSU5QVVQ6
-OnN0ZXAiLCJJTlBVVDo6dGFiaW5kZXgiLCJJTlBVVDo6dHlwZSIsIklOUFVUOjp1c2VtYXAiLCJJTlBV
-VDo6dmFsdWUiLCJJTlM6OmRhdGV0aW1lIiwiS0VZR0VOOjpkaXNhYmxlZCIsIktFWUdFTjo6a2V5dHlw
-ZSIsIktFWUdFTjo6bmFtZSIsIkxBQkVMOjphY2Nlc3NrZXkiLCJMQUJFTDo6Zm9yIiwiTEVHRU5EOjph
-Y2Nlc3NrZXkiLCJMRUdFTkQ6OmFsaWduIiwiTEk6OnR5cGUiLCJMSTo6dmFsdWUiLCJMSU5LOjpzaXpl
-cyIsIk1BUDo6bmFtZSIsIk1FTlU6OmNvbXBhY3QiLCJNRU5VOjpsYWJlbCIsIk1FTlU6OnR5cGUiLCJN
-RVRFUjo6aGlnaCIsIk1FVEVSOjpsb3ciLCJNRVRFUjo6bWF4IiwiTUVURVI6Om1pbiIsIk1FVEVSOjp2
-YWx1ZSIsIk9CSkVDVDo6dHlwZW11c3RtYXRjaCIsIk9MOjpjb21wYWN0IiwiT0w6OnJldmVyc2VkIiwi
-T0w6OnN0YXJ0IiwiT0w6OnR5cGUiLCJPUFRHUk9VUDo6ZGlzYWJsZWQiLCJPUFRHUk9VUDo6bGFiZWwi
-LCJPUFRJT046OmRpc2FibGVkIiwiT1BUSU9OOjpsYWJlbCIsIk9QVElPTjo6c2VsZWN0ZWQiLCJPUFRJ
-T046OnZhbHVlIiwiT1VUUFVUOjpmb3IiLCJPVVRQVVQ6Om5hbWUiLCJQOjphbGlnbiIsIlBSRTo6d2lk
-dGgiLCJQUk9HUkVTUzo6bWF4IiwiUFJPR1JFU1M6Om1pbiIsIlBST0dSRVNTOjp2YWx1ZSIsIlNFTEVD
-VDo6YXV0b2NvbXBsZXRlIiwiU0VMRUNUOjpkaXNhYmxlZCIsIlNFTEVDVDo6bXVsdGlwbGUiLCJTRUxF
-Q1Q6Om5hbWUiLCJTRUxFQ1Q6OnJlcXVpcmVkIiwiU0VMRUNUOjpzaXplIiwiU0VMRUNUOjp0YWJpbmRl
-eCIsIlNPVVJDRTo6dHlwZSIsIlRBQkxFOjphbGlnbiIsIlRBQkxFOjpiZ2NvbG9yIiwiVEFCTEU6OmJv
-cmRlciIsIlRBQkxFOjpjZWxscGFkZGluZyIsIlRBQkxFOjpjZWxsc3BhY2luZyIsIlRBQkxFOjpmcmFt
-ZSIsIlRBQkxFOjpydWxlcyIsIlRBQkxFOjpzdW1tYXJ5IiwiVEFCTEU6OndpZHRoIiwiVEJPRFk6OmFs
-aWduIiwiVEJPRFk6OmNoYXIiLCJUQk9EWTo6Y2hhcm9mZiIsIlRCT0RZOjp2YWxpZ24iLCJURDo6YWJi
-ciIsIlREOjphbGlnbiIsIlREOjpheGlzIiwiVEQ6OmJnY29sb3IiLCJURDo6Y2hhciIsIlREOjpjaGFy
-b2ZmIiwiVEQ6OmNvbHNwYW4iLCJURDo6aGVhZGVycyIsIlREOjpoZWlnaHQiLCJURDo6bm93cmFwIiwi
-VEQ6OnJvd3NwYW4iLCJURDo6c2NvcGUiLCJURDo6dmFsaWduIiwiVEQ6OndpZHRoIiwiVEVYVEFSRUE6
-OmFjY2Vzc2tleSIsIlRFWFRBUkVBOjphdXRvY29tcGxldGUiLCJURVhUQVJFQTo6Y29scyIsIlRFWFRB
-UkVBOjpkaXNhYmxlZCIsIlRFWFRBUkVBOjppbnB1dG1vZGUiLCJURVhUQVJFQTo6bmFtZSIsIlRFWFRB
-UkVBOjpwbGFjZWhvbGRlciIsIlRFWFRBUkVBOjpyZWFkb25seSIsIlRFWFRBUkVBOjpyZXF1aXJlZCIs
-IlRFWFRBUkVBOjpyb3dzIiwiVEVYVEFSRUE6OnRhYmluZGV4IiwiVEVYVEFSRUE6OndyYXAiLCJURk9P
-VDo6YWxpZ24iLCJURk9PVDo6Y2hhciIsIlRGT09UOjpjaGFyb2ZmIiwiVEZPT1Q6OnZhbGlnbiIsIlRI
-OjphYmJyIiwiVEg6OmFsaWduIiwiVEg6OmF4aXMiLCJUSDo6Ymdjb2xvciIsIlRIOjpjaGFyIiwiVEg6
-OmNoYXJvZmYiLCJUSDo6Y29sc3BhbiIsIlRIOjpoZWFkZXJzIiwiVEg6OmhlaWdodCIsIlRIOjpub3dy
-YXAiLCJUSDo6cm93c3BhbiIsIlRIOjpzY29wZSIsIlRIOjp2YWxpZ24iLCJUSDo6d2lkdGgiLCJUSEVB
-RDo6YWxpZ24iLCJUSEVBRDo6Y2hhciIsIlRIRUFEOjpjaGFyb2ZmIiwiVEhFQUQ6OnZhbGlnbiIsIlRS
-OjphbGlnbiIsIlRSOjpiZ2NvbG9yIiwiVFI6OmNoYXIiLCJUUjo6Y2hhcm9mZiIsIlRSOjp2YWxpZ24i
-LCJUUkFDSzo6ZGVmYXVsdCIsIlRSQUNLOjpraW5kIiwiVFJBQ0s6OmxhYmVsIiwiVFJBQ0s6OnNyY2xh
-bmciLCJVTDo6Y29tcGFjdCIsIlVMOjp0eXBlIiwiVklERU86OmNvbnRyb2xzIiwiVklERU86OmhlaWdo
-dCIsIlZJREVPOjpsb29wIiwiVklERU86Om1lZGlhZ3JvdXAiLCJWSURFTzo6bXV0ZWQiLCJWSURFTzo6
-cHJlbG9hZCIsIlZJREVPOjp3aWR0aCJdKSx1LnMpCkMuVkM9SC5WTSh0KFswLDAsNjU0OTAsNDUwNTUs
-NjU1MzUsMzQ4MTUsNjU1MzQsMTg0MzFdKSx1LnQpCkMubUs9SC5WTSh0KFswLDAsMjY2MjQsMTAyMyw2
-NTUzNCwyMDQ3LDY1NTM0LDIwNDddKSx1LnQpCkMuU3E9SC5WTSh0KFsiSEVBRCIsIkFSRUEiLCJCQVNF
-IiwiQkFTRUZPTlQiLCJCUiIsIkNPTCIsIkNPTEdST1VQIiwiRU1CRUQiLCJGUkFNRSIsIkZSQU1FU0VU
-IiwiSFIiLCJJTUFHRSIsIklNRyIsIklOUFVUIiwiSVNJTkRFWCIsIkxJTksiLCJNRVRBIiwiUEFSQU0i
-LCJTT1VSQ0UiLCJTVFlMRSIsIlRJVExFIiwiV0JSIl0pLHUucykKQy5kbj1ILlZNKHQoW10pLEguTjAo
-ImpkPExMPiIpKQpDLnhEPUguVk0odChbXSksdS5zKQpDLmhVPUguVk0odChbXSksdS5iKQpDLnRvPUgu
-Vk0odChbMCwwLDMyNzIyLDEyMjg3LDY1NTM0LDM0ODE1LDY1NTM0LDE4NDMxXSksdS50KQpDLnJrPUgu
-Vk0odChbQy5BZCxDLm5lLEMubXksQy5yeCxDLndWLEMuZlJdKSxILk4wKCJqZDxINz4iKSkKQy5GMz1I
-LlZNKHQoWzAsMCwyNDU3NiwxMDIzLDY1NTM0LDM0ODE1LDY1NTM0LDE4NDMxXSksdS50KQpDLmVhPUgu
-Vk0odChbMCwwLDMyNzU0LDExMjYzLDY1NTM0LDM0ODE1LDY1NTM0LDE4NDMxXSksdS50KQpDLlpKPUgu
-Vk0odChbMCwwLDMyNzIyLDEyMjg3LDY1NTM1LDM0ODE1LDY1NTM0LDE4NDMxXSksdS50KQpDLldkPUgu
-Vk0odChbMCwwLDY1NDkwLDEyMjg3LDY1NTM1LDM0ODE1LDY1NTM0LDE4NDMxXSksdS50KQpDLlF4PUgu
-Vk0odChbImJpbmQiLCJpZiIsInJlZiIsInJlcGVhdCIsInN5bnRheCJdKSx1LnMpCkMuQkk9SC5WTSh0
-KFsiQTo6aHJlZiIsIkFSRUE6OmhyZWYiLCJCTE9DS1FVT1RFOjpjaXRlIiwiQk9EWTo6YmFja2dyb3Vu
-ZCIsIkNPTU1BTkQ6Omljb24iLCJERUw6OmNpdGUiLCJGT1JNOjphY3Rpb24iLCJJTUc6OnNyYyIsIklO
-UFVUOjpzcmMiLCJJTlM6OmNpdGUiLCJROjpjaXRlIiwiVklERU86OnBvc3RlciJdKSx1LnMpCkMuQ009
-bmV3IEguTFAoMCx7fSxDLnhELEguTjAoIkxQPHFVLHpNPGo4Pj4iKSkKQy5XTz1uZXcgSC5MUCgwLHt9
-LEMueEQsSC5OMCgiTFA8cVUscVU+IikpCkMuaUg9SC5WTSh0KFtdKSxILk4wKCJqZDxHRD4iKSkKQy5E
-eD1uZXcgSC5MUCgwLHt9LEMuaUgsSC5OMCgiTFA8R0QsQD4iKSkKQy5ZMj1uZXcgTC5POSgiTmF2aWdh
-dGlvblRyZWVOb2RlVHlwZS5kaXJlY3RvcnkiKQpDLnJmPW5ldyBMLk85KCJOYXZpZ2F0aW9uVHJlZU5v
-ZGVUeXBlLmZpbGUiKQpDLlRlPW5ldyBILnd2KCJjYWxsIikKQy53UT1uZXcgUC5GeShudWxsLDIpfSko
-KTsoZnVuY3Rpb24gc3RhdGljRmllbGRzKCl7JC55aj0wCiQubUo9bnVsbAokLlA0PW51bGwKJC55PW51
-bGwKJC51PW51bGwKJC54Nz1udWxsCiQuaj1udWxsCiQudj1udWxsCiQuSz1udWxsCiQuUzY9bnVsbAok
-Lms4PW51bGwKJC5tZz1udWxsCiQuVUQ9ITEKJC5YMz1DLk5VCiQueGc9W10KJC54bz1udWxsCiQuQk89
-bnVsbAokLmx0PW51bGwKJC5FVT1udWxsCiQub3I9UC5GbCh1Lk4sdS5aKQokLkk2PW51bGwKJC5GZj1u
-dWxsfSkoKTsoZnVuY3Rpb24gbGF6eUluaXRpYWxpemVycygpe3ZhciB0PWh1bmtIZWxwZXJzLmxhenkK
-dCgkLCJmYSIsIndRIixmdW5jdGlvbigpe3JldHVybiBILllnKCJfJGRhcnRfZGFydENsb3N1cmUiKX0p
-CnQoJCwiWTIiLCJBIixmdW5jdGlvbigpe3JldHVybiBILllnKCJfJGRhcnRfanMiKX0pCnQoJCwiVTIi
-LCJTbiIsZnVuY3Rpb24oKXtyZXR1cm4gSC5jTShILlM3KHsKdG9TdHJpbmc6ZnVuY3Rpb24oKXtyZXR1
-cm4iJHJlY2VpdmVyJCJ9fSkpfSkKdCgkLCJ4cSIsImxxIixmdW5jdGlvbigpe3JldHVybiBILmNNKEgu
-UzcoeyRtZXRob2QkOm51bGwsCnRvU3RyaW5nOmZ1bmN0aW9uKCl7cmV0dXJuIiRyZWNlaXZlciQifX0p
-KX0pCnQoJCwiUjEiLCJOOSIsZnVuY3Rpb24oKXtyZXR1cm4gSC5jTShILlM3KG51bGwpKX0pCnQoJCwi
-Zk4iLCJpSSIsZnVuY3Rpb24oKXtyZXR1cm4gSC5jTShmdW5jdGlvbigpe3ZhciAkYXJndW1lbnRzRXhw
-ciQ9JyRhcmd1bWVudHMkJwp0cnl7bnVsbC4kbWV0aG9kJCgkYXJndW1lbnRzRXhwciQpfWNhdGNoKHMp
-e3JldHVybiBzLm1lc3NhZ2V9fSgpKX0pCnQoJCwicWkiLCJVTiIsZnVuY3Rpb24oKXtyZXR1cm4gSC5j
-TShILlM3KHZvaWQgMCkpfSkKdCgkLCJyWiIsIlpoIixmdW5jdGlvbigpe3JldHVybiBILmNNKGZ1bmN0
-aW9uKCl7dmFyICRhcmd1bWVudHNFeHByJD0nJGFyZ3VtZW50cyQnCnRyeXsodm9pZCAwKS4kbWV0aG9k
-JCgkYXJndW1lbnRzRXhwciQpfWNhdGNoKHMpe3JldHVybiBzLm1lc3NhZ2V9fSgpKX0pCnQoJCwia3Ei
-LCJyTiIsZnVuY3Rpb24oKXtyZXR1cm4gSC5jTShILk1qKG51bGwpKX0pCnQoJCwidHQiLCJjMyIsZnVu
-Y3Rpb24oKXtyZXR1cm4gSC5jTShmdW5jdGlvbigpe3RyeXtudWxsLiRtZXRob2QkfWNhdGNoKHMpe3Jl
-dHVybiBzLm1lc3NhZ2V9fSgpKX0pCnQoJCwiZHQiLCJISyIsZnVuY3Rpb24oKXtyZXR1cm4gSC5jTShI
-Lk1qKHZvaWQgMCkpfSkKdCgkLCJBNyIsInIxIixmdW5jdGlvbigpe3JldHVybiBILmNNKGZ1bmN0aW9u
-KCl7dHJ5eyh2b2lkIDApLiRtZXRob2QkfWNhdGNoKHMpe3JldHVybiBzLm1lc3NhZ2V9fSgpKX0pCnQo
-JCwiV2MiLCJ1dCIsZnVuY3Rpb24oKXtyZXR1cm4gUC5PaigpfSkKdCgkLCJraCIsInRMIixmdW5jdGlv
-bigpe3JldHVybiBQLldJKCl9KQp0KCQsImJ0IiwiVjciLGZ1bmN0aW9uKCl7cmV0dXJuIEguRFEoSC5Y
-RihILlZNKFstMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwt
-MiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwtMiwt
-MSwtMiwtMiwtMiwtMiwtMiw2MiwtMiw2MiwtMiw2Myw1Miw1Myw1NCw1NSw1Niw1Nyw1OCw1OSw2MCw2
-MSwtMiwtMiwtMiwtMSwtMiwtMiwtMiwwLDEsMiwzLDQsNSw2LDcsOCw5LDEwLDExLDEyLDEzLDE0LDE1
-LDE2LDE3LDE4LDE5LDIwLDIxLDIyLDIzLDI0LDI1LC0yLC0yLC0yLC0yLDYzLC0yLDI2LDI3LDI4LDI5
-LDMwLDMxLDMyLDMzLDM0LDM1LDM2LDM3LDM4LDM5LDQwLDQxLDQyLDQzLDQ0LDQ1LDQ2LDQ3LDQ4LDQ5
-LDUwLDUxLC0yLC0yLC0yLC0yLC0yXSx1LnQpKSl9KQp0KCQsIk01IiwiT3giLGZ1bmN0aW9uKCl7cmV0
-dXJuIHR5cGVvZiBwcm9jZXNzIT0idW5kZWZpbmVkIiYmT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5j
-YWxsKHByb2Nlc3MpPT0iW29iamVjdCBwcm9jZXNzXSImJnByb2Nlc3MucGxhdGZvcm09PSJ3aW4zMiJ9
-KQp0KCQsIm1mIiwiejQiLGZ1bmN0aW9uKCl7cmV0dXJuIFAubnUoIl5bXFwtXFwuMC05QS1aX2Eten5d
-KiQiKX0pCnQoJCwiQXYiLCJwNiIsZnVuY3Rpb24oKXtyZXR1cm4gbmV3IEVycm9yKCkuc3RhY2shPXZv
-aWQgMH0pCnQoJCwiSkciLCJ2WiIsZnVuY3Rpb24oKXtyZXR1cm4gUC5LTigpfSkKdCgkLCJTQyIsIkFO
-IixmdW5jdGlvbigpe3JldHVybiBQLnRNKFsiQSIsIkFCQlIiLCJBQ1JPTllNIiwiQUREUkVTUyIsIkFS
-RUEiLCJBUlRJQ0xFIiwiQVNJREUiLCJBVURJTyIsIkIiLCJCREkiLCJCRE8iLCJCSUciLCJCTE9DS1FV
-T1RFIiwiQlIiLCJCVVRUT04iLCJDQU5WQVMiLCJDQVBUSU9OIiwiQ0VOVEVSIiwiQ0lURSIsIkNPREUi
-LCJDT0wiLCJDT0xHUk9VUCIsIkNPTU1BTkQiLCJEQVRBIiwiREFUQUxJU1QiLCJERCIsIkRFTCIsIkRF
-VEFJTFMiLCJERk4iLCJESVIiLCJESVYiLCJETCIsIkRUIiwiRU0iLCJGSUVMRFNFVCIsIkZJR0NBUFRJ
-T04iLCJGSUdVUkUiLCJGT05UIiwiRk9PVEVSIiwiRk9STSIsIkgxIiwiSDIiLCJIMyIsIkg0IiwiSDUi
-LCJINiIsIkhFQURFUiIsIkhHUk9VUCIsIkhSIiwiSSIsIklGUkFNRSIsIklNRyIsIklOUFVUIiwiSU5T
-IiwiS0JEIiwiTEFCRUwiLCJMRUdFTkQiLCJMSSIsIk1BUCIsIk1BUksiLCJNRU5VIiwiTUVURVIiLCJO
-QVYiLCJOT0JSIiwiT0wiLCJPUFRHUk9VUCIsIk9QVElPTiIsIk9VVFBVVCIsIlAiLCJQUkUiLCJQUk9H
-UkVTUyIsIlEiLCJTIiwiU0FNUCIsIlNFQ1RJT04iLCJTRUxFQ1QiLCJTTUFMTCIsIlNPVVJDRSIsIlNQ
-QU4iLCJTVFJJS0UiLCJTVFJPTkciLCJTVUIiLCJTVU1NQVJZIiwiU1VQIiwiVEFCTEUiLCJUQk9EWSIs
-IlREIiwiVEVYVEFSRUEiLCJURk9PVCIsIlRIIiwiVEhFQUQiLCJUSU1FIiwiVFIiLCJUUkFDSyIsIlRU
-IiwiVSIsIlVMIiwiVkFSIiwiVklERU8iLCJXQlIiXSx1Lk4pfSkKdCgkLCJYNCIsImhHIixmdW5jdGlv
-bigpe3JldHVybiBQLm51KCJeXFxTKyQiKX0pCnQoJCwid08iLCJvdyIsZnVuY3Rpb24oKXtyZXR1cm4g
-dS5tLmEoUC5ORChzZWxmKSl9KQp0KCQsImt0IiwiQ3IiLGZ1bmN0aW9uKCl7cmV0dXJuIEguWWcoIl8k
-ZGFydF9kYXJ0T2JqZWN0Iil9KQp0KCQsImZLIiwia0kiLGZ1bmN0aW9uKCl7cmV0dXJuIGZ1bmN0aW9u
-IERhcnRPYmplY3QoYSl7dGhpcy5vPWF9fSkKdCgkLCJxdCIsInpCIixmdW5jdGlvbigpe3JldHVybiBu
-ZXcgVC5tUSgpfSkKdCgkLCJPbCIsIlVFIixmdW5jdGlvbigpe3JldHVybiBQLmhLKEMub2wuZ21XKFcu
-eDMoKSkuaHJlZikuZ2hZKCkucSgwLCJhdXRoVG9rZW4iKX0pCnQoJCwiaFQiLCJ5UCIsZnVuY3Rpb24o
-KXtyZXR1cm4gVy5acigpLnF1ZXJ5U2VsZWN0b3IoIi5lZGl0LWxpc3QgLnBhbmVsLWNvbnRlbnQiKX0p
-CnQoJCwiVzYiLCJoTCIsZnVuY3Rpb24oKXtyZXR1cm4gVy5acigpLnF1ZXJ5U2VsZWN0b3IoIi5lZGl0
-LXBhbmVsIC5wYW5lbC1jb250ZW50Iil9KQp0KCQsIlRSIiwiRFciLGZ1bmN0aW9uKCl7cmV0dXJuIFcu
-WnIoKS5xdWVyeVNlbGVjdG9yKCJmb290ZXIiKX0pCnQoJCwiRVkiLCJmaSIsZnVuY3Rpb24oKXtyZXR1
-cm4gVy5acigpLnF1ZXJ5U2VsZWN0b3IoImhlYWRlciIpfSkKdCgkLCJhdiIsIkQ5IixmdW5jdGlvbigp
-e3JldHVybiBXLlpyKCkucXVlcnlTZWxlY3RvcigiI3VuaXQtbmFtZSIpfSkKdCgkLCJmZSIsIktHIixm
-dW5jdGlvbigpe3JldHVybiBuZXcgTC5YQSgpfSkKdCgkLCJlbyIsIm5VIixmdW5jdGlvbigpe3JldHVy
-biBuZXcgTS5sSSgkLkhrKCkpfSkKdCgkLCJ5ciIsImJEIixmdW5jdGlvbigpe3JldHVybiBuZXcgRS5P
-RihQLm51KCIvIiksUC5udSgiW14vXSQiKSxQLm51KCJeLyIpKX0pCnQoJCwiTWsiLCJLayIsZnVuY3Rp
-b24oKXtyZXR1cm4gbmV3IEwuSVYoUC5udSgiWy9cXFxcXSIpLFAubnUoIlteL1xcXFxdJCIpLFAubnUo
-Il4oXFxcXFxcXFxbXlxcXFxdK1xcXFxbXlxcXFwvXSt8W2EtekEtWl06Wy9cXFxcXSkiKSxQLm51KCJe
-Wy9cXFxcXSg/IVsvXFxcXF0pIikpfSkKdCgkLCJhayIsIkViIixmdW5jdGlvbigpe3JldHVybiBuZXcg
-Ri5ydShQLm51KCIvIiksUC5udSgiKF5bYS16QS1aXVstKy5hLXpBLVpcXGRdKjovL3xbXi9dKSQiKSxQ
-Lm51KCJbYS16QS1aXVstKy5hLXpBLVpcXGRdKjovL1teL10qIiksUC5udSgiXi8iKSl9KQp0KCQsImxz
-IiwiSGsiLGZ1bmN0aW9uKCl7cmV0dXJuIE8uUmgoKX0pfSkoKTsoZnVuY3Rpb24gbmF0aXZlU3VwcG9y
-dCgpeyFmdW5jdGlvbigpe3ZhciB0PWZ1bmN0aW9uKGEpe3ZhciBuPXt9Cm5bYV09MQpyZXR1cm4gT2Jq
-ZWN0LmtleXMoaHVua0hlbHBlcnMuY29udmVydFRvRmFzdE9iamVjdChuKSlbMF19CnYuZ2V0SXNvbGF0
-ZVRhZz1mdW5jdGlvbihhKXtyZXR1cm4gdCgiX19fZGFydF8iK2Erdi5pc29sYXRlVGFnKX0KdmFyIHM9
-Il9fX2RhcnRfaXNvbGF0ZV90YWdzXyIKdmFyIHI9T2JqZWN0W3NdfHwoT2JqZWN0W3NdPU9iamVjdC5j
-cmVhdGUobnVsbCkpCnZhciBxPSJfWnhZeFgiCmZvcih2YXIgcD0wOztwKyspe3ZhciBvPXQocSsiXyIr
-cCsiXyIpCmlmKCEobyBpbiByKSl7cltvXT0xCnYuaXNvbGF0ZVRhZz1vCmJyZWFrfX12LmRpc3BhdGNo
-UHJvcGVydHlOYW1lPXYuZ2V0SXNvbGF0ZVRhZygiZGlzcGF0Y2hfcmVjb3JkIil9KCkKaHVua0hlbHBl
-cnMuc2V0T3JVcGRhdGVJbnRlcmNlcHRvcnNCeVRhZyh7RE9NRXJyb3I6Si52QixET01JbXBsZW1lbnRh
-dGlvbjpKLnZCLE1lZGlhRXJyb3I6Si52QixOYXZpZ2F0b3I6Si52QixOYXZpZ2F0b3JDb25jdXJyZW50
-SGFyZHdhcmU6Si52QixOYXZpZ2F0b3JVc2VyTWVkaWFFcnJvcjpKLnZCLE92ZXJjb25zdHJhaW5lZEVy
-cm9yOkoudkIsUG9zaXRpb25FcnJvcjpKLnZCLFJhbmdlOkoudkIsU1FMRXJyb3I6Si52QixEYXRhVmll
-dzpILmVILEFycmF5QnVmZmVyVmlldzpILmVILEZsb2F0MzJBcnJheTpILkRnLEZsb2F0NjRBcnJheTpI
-LkRnLEludDE2QXJyYXk6SC54aixJbnQzMkFycmF5OkguZEUsSW50OEFycmF5OkguWkEsVWludDE2QXJy
-YXk6SC53ZixVaW50MzJBcnJheTpILlBxLFVpbnQ4Q2xhbXBlZEFycmF5OkguZUUsQ2FudmFzUGl4ZWxB
-cnJheTpILmVFLFVpbnQ4QXJyYXk6SC5WNixIVE1MQXVkaW9FbGVtZW50OlcucUUsSFRNTEJSRWxlbWVu
-dDpXLnFFLEhUTUxCdXR0b25FbGVtZW50OlcucUUsSFRNTENhbnZhc0VsZW1lbnQ6Vy5xRSxIVE1MQ29u
-dGVudEVsZW1lbnQ6Vy5xRSxIVE1MRExpc3RFbGVtZW50OlcucUUsSFRNTERhdGFFbGVtZW50OlcucUUs
-SFRNTERhdGFMaXN0RWxlbWVudDpXLnFFLEhUTUxEZXRhaWxzRWxlbWVudDpXLnFFLEhUTUxEaWFsb2dF
-bGVtZW50OlcucUUsSFRNTERpdkVsZW1lbnQ6Vy5xRSxIVE1MRW1iZWRFbGVtZW50OlcucUUsSFRNTEZp
-ZWxkU2V0RWxlbWVudDpXLnFFLEhUTUxIUkVsZW1lbnQ6Vy5xRSxIVE1MSGVhZEVsZW1lbnQ6Vy5xRSxI
-VE1MSGVhZGluZ0VsZW1lbnQ6Vy5xRSxIVE1MSHRtbEVsZW1lbnQ6Vy5xRSxIVE1MSUZyYW1lRWxlbWVu
-dDpXLnFFLEhUTUxJbWFnZUVsZW1lbnQ6Vy5xRSxIVE1MSW5wdXRFbGVtZW50OlcucUUsSFRNTExJRWxl
-bWVudDpXLnFFLEhUTUxMYWJlbEVsZW1lbnQ6Vy5xRSxIVE1MTGVnZW5kRWxlbWVudDpXLnFFLEhUTUxM
-aW5rRWxlbWVudDpXLnFFLEhUTUxNYXBFbGVtZW50OlcucUUsSFRNTE1lZGlhRWxlbWVudDpXLnFFLEhU
-TUxNZW51RWxlbWVudDpXLnFFLEhUTUxNZXRhRWxlbWVudDpXLnFFLEhUTUxNZXRlckVsZW1lbnQ6Vy5x
-RSxIVE1MTW9kRWxlbWVudDpXLnFFLEhUTUxPTGlzdEVsZW1lbnQ6Vy5xRSxIVE1MT2JqZWN0RWxlbWVu
-dDpXLnFFLEhUTUxPcHRHcm91cEVsZW1lbnQ6Vy5xRSxIVE1MT3B0aW9uRWxlbWVudDpXLnFFLEhUTUxP
-dXRwdXRFbGVtZW50OlcucUUsSFRNTFBhcmFtRWxlbWVudDpXLnFFLEhUTUxQaWN0dXJlRWxlbWVudDpX
-LnFFLEhUTUxQcmVFbGVtZW50OlcucUUsSFRNTFByb2dyZXNzRWxlbWVudDpXLnFFLEhUTUxRdW90ZUVs
-ZW1lbnQ6Vy5xRSxIVE1MU2NyaXB0RWxlbWVudDpXLnFFLEhUTUxTaGFkb3dFbGVtZW50OlcucUUsSFRN
-TFNsb3RFbGVtZW50OlcucUUsSFRNTFNvdXJjZUVsZW1lbnQ6Vy5xRSxIVE1MU3BhbkVsZW1lbnQ6Vy5x
-RSxIVE1MU3R5bGVFbGVtZW50OlcucUUsSFRNTFRhYmxlQ2FwdGlvbkVsZW1lbnQ6Vy5xRSxIVE1MVGFi
-bGVDZWxsRWxlbWVudDpXLnFFLEhUTUxUYWJsZURhdGFDZWxsRWxlbWVudDpXLnFFLEhUTUxUYWJsZUhl
-YWRlckNlbGxFbGVtZW50OlcucUUsSFRNTFRhYmxlQ29sRWxlbWVudDpXLnFFLEhUTUxUZXh0QXJlYUVs
-ZW1lbnQ6Vy5xRSxIVE1MVGltZUVsZW1lbnQ6Vy5xRSxIVE1MVGl0bGVFbGVtZW50OlcucUUsSFRNTFRy
-YWNrRWxlbWVudDpXLnFFLEhUTUxVTGlzdEVsZW1lbnQ6Vy5xRSxIVE1MVW5rbm93bkVsZW1lbnQ6Vy5x
-RSxIVE1MVmlkZW9FbGVtZW50OlcucUUsSFRNTERpcmVjdG9yeUVsZW1lbnQ6Vy5xRSxIVE1MRm9udEVs
-ZW1lbnQ6Vy5xRSxIVE1MRnJhbWVFbGVtZW50OlcucUUsSFRNTEZyYW1lU2V0RWxlbWVudDpXLnFFLEhU
-TUxNYXJxdWVlRWxlbWVudDpXLnFFLEhUTUxFbGVtZW50OlcucUUsSFRNTEFuY2hvckVsZW1lbnQ6Vy5H
-aCxIVE1MQXJlYUVsZW1lbnQ6Vy5mWSxIVE1MQmFzZUVsZW1lbnQ6Vy5uQixCbG9iOlcuQXosSFRNTEJv
-ZHlFbGVtZW50OlcuUVAsQ0RBVEFTZWN0aW9uOlcubngsQ2hhcmFjdGVyRGF0YTpXLm54LENvbW1lbnQ6
-Vy5ueCxQcm9jZXNzaW5nSW5zdHJ1Y3Rpb246Vy5ueCxUZXh0OlcubngsQ1NTU3R5bGVEZWNsYXJhdGlv
-bjpXLm9KLE1TU3R5bGVDU1NQcm9wZXJ0aWVzOlcub0osQ1NTMlByb3BlcnRpZXM6Vy5vSixYTUxEb2N1
-bWVudDpXLlFGLERvY3VtZW50OlcuUUYsRE9NRXhjZXB0aW9uOlcuTmgsRE9NUmVjdFJlYWRPbmx5Olcu
-SUIsRE9NVG9rZW5MaXN0OlcubjcsRWxlbWVudDpXLmN2LEFib3J0UGF5bWVudEV2ZW50OlcuZWEsQW5p
-bWF0aW9uRXZlbnQ6Vy5lYSxBbmltYXRpb25QbGF5YmFja0V2ZW50OlcuZWEsQXBwbGljYXRpb25DYWNo
-ZUVycm9yRXZlbnQ6Vy5lYSxCYWNrZ3JvdW5kRmV0Y2hDbGlja0V2ZW50OlcuZWEsQmFja2dyb3VuZEZl
-dGNoRXZlbnQ6Vy5lYSxCYWNrZ3JvdW5kRmV0Y2hGYWlsRXZlbnQ6Vy5lYSxCYWNrZ3JvdW5kRmV0Y2hl
-ZEV2ZW50OlcuZWEsQmVmb3JlSW5zdGFsbFByb21wdEV2ZW50OlcuZWEsQmVmb3JlVW5sb2FkRXZlbnQ6
-Vy5lYSxCbG9iRXZlbnQ6Vy5lYSxDYW5NYWtlUGF5bWVudEV2ZW50OlcuZWEsQ2xpcGJvYXJkRXZlbnQ6
-Vy5lYSxDbG9zZUV2ZW50OlcuZWEsQ3VzdG9tRXZlbnQ6Vy5lYSxEZXZpY2VNb3Rpb25FdmVudDpXLmVh
-LERldmljZU9yaWVudGF0aW9uRXZlbnQ6Vy5lYSxFcnJvckV2ZW50OlcuZWEsRXh0ZW5kYWJsZUV2ZW50
-OlcuZWEsRXh0ZW5kYWJsZU1lc3NhZ2VFdmVudDpXLmVhLEZldGNoRXZlbnQ6Vy5lYSxGb250RmFjZVNl
-dExvYWRFdmVudDpXLmVhLEZvcmVpZ25GZXRjaEV2ZW50OlcuZWEsR2FtZXBhZEV2ZW50OlcuZWEsSGFz
-aENoYW5nZUV2ZW50OlcuZWEsSW5zdGFsbEV2ZW50OlcuZWEsTWVkaWFFbmNyeXB0ZWRFdmVudDpXLmVh
-LE1lZGlhS2V5TWVzc2FnZUV2ZW50OlcuZWEsTWVkaWFRdWVyeUxpc3RFdmVudDpXLmVhLE1lZGlhU3Ry
-ZWFtRXZlbnQ6Vy5lYSxNZWRpYVN0cmVhbVRyYWNrRXZlbnQ6Vy5lYSxNZXNzYWdlRXZlbnQ6Vy5lYSxN
-SURJQ29ubmVjdGlvbkV2ZW50OlcuZWEsTUlESU1lc3NhZ2VFdmVudDpXLmVhLE11dGF0aW9uRXZlbnQ6
-Vy5lYSxOb3RpZmljYXRpb25FdmVudDpXLmVhLFBhZ2VUcmFuc2l0aW9uRXZlbnQ6Vy5lYSxQYXltZW50
-UmVxdWVzdEV2ZW50OlcuZWEsUGF5bWVudFJlcXVlc3RVcGRhdGVFdmVudDpXLmVhLFBvcFN0YXRlRXZl
-bnQ6Vy5lYSxQcmVzZW50YXRpb25Db25uZWN0aW9uQXZhaWxhYmxlRXZlbnQ6Vy5lYSxQcmVzZW50YXRp
-b25Db25uZWN0aW9uQ2xvc2VFdmVudDpXLmVhLFByb21pc2VSZWplY3Rpb25FdmVudDpXLmVhLFB1c2hF
-dmVudDpXLmVhLFJUQ0RhdGFDaGFubmVsRXZlbnQ6Vy5lYSxSVENEVE1GVG9uZUNoYW5nZUV2ZW50Olcu
-ZWEsUlRDUGVlckNvbm5lY3Rpb25JY2VFdmVudDpXLmVhLFJUQ1RyYWNrRXZlbnQ6Vy5lYSxTZWN1cml0
-eVBvbGljeVZpb2xhdGlvbkV2ZW50OlcuZWEsU2Vuc29yRXJyb3JFdmVudDpXLmVhLFNwZWVjaFJlY29n
-bml0aW9uRXJyb3I6Vy5lYSxTcGVlY2hSZWNvZ25pdGlvbkV2ZW50OlcuZWEsU3BlZWNoU3ludGhlc2lz
-RXZlbnQ6Vy5lYSxTdG9yYWdlRXZlbnQ6Vy5lYSxTeW5jRXZlbnQ6Vy5lYSxUcmFja0V2ZW50OlcuZWEs
-VHJhbnNpdGlvbkV2ZW50OlcuZWEsV2ViS2l0VHJhbnNpdGlvbkV2ZW50OlcuZWEsVlJEZXZpY2VFdmVu
-dDpXLmVhLFZSRGlzcGxheUV2ZW50OlcuZWEsVlJTZXNzaW9uRXZlbnQ6Vy5lYSxNb2pvSW50ZXJmYWNl
-UmVxdWVzdEV2ZW50OlcuZWEsVVNCQ29ubmVjdGlvbkV2ZW50OlcuZWEsSURCVmVyc2lvbkNoYW5nZUV2
-ZW50OlcuZWEsQXVkaW9Qcm9jZXNzaW5nRXZlbnQ6Vy5lYSxPZmZsaW5lQXVkaW9Db21wbGV0aW9uRXZl
-bnQ6Vy5lYSxXZWJHTENvbnRleHRFdmVudDpXLmVhLEV2ZW50OlcuZWEsSW5wdXRFdmVudDpXLmVhLFN1
-Ym1pdEV2ZW50OlcuZWEsRXZlbnRUYXJnZXQ6Vy5EMCxGaWxlOlcuaEgsSFRNTEZvcm1FbGVtZW50Olcu
-aDQsSGlzdG9yeTpXLmJyLEhUTUxEb2N1bWVudDpXLlZiLFhNTEh0dHBSZXF1ZXN0OlcuZkosWE1MSHR0
-cFJlcXVlc3RFdmVudFRhcmdldDpXLndhLEltYWdlRGF0YTpXLlNnLExvY2F0aW9uOlcudTgsTW91c2VF
-dmVudDpXLk9LLERyYWdFdmVudDpXLk9LLFBvaW50ZXJFdmVudDpXLk9LLFdoZWVsRXZlbnQ6Vy5PSyxE
-b2N1bWVudEZyYWdtZW50OlcudUgsU2hhZG93Um9vdDpXLnVILERvY3VtZW50VHlwZTpXLnVILE5vZGU6
-Vy51SCxOb2RlTGlzdDpXLkJILFJhZGlvTm9kZUxpc3Q6Vy5CSCxIVE1MUGFyYWdyYXBoRWxlbWVudDpX
-LlNOLFByb2dyZXNzRXZlbnQ6Vy5ldyxSZXNvdXJjZVByb2dyZXNzRXZlbnQ6Vy5ldyxIVE1MU2VsZWN0
-RWxlbWVudDpXLmxwLEhUTUxUYWJsZUVsZW1lbnQ6Vy5UYixIVE1MVGFibGVSb3dFbGVtZW50OlcuSXYs
-SFRNTFRhYmxlU2VjdGlvbkVsZW1lbnQ6Vy5XUCxIVE1MVGVtcGxhdGVFbGVtZW50OlcueVksQ29tcG9z
-aXRpb25FdmVudDpXLnc2LEZvY3VzRXZlbnQ6Vy53NixLZXlib2FyZEV2ZW50OlcudzYsVGV4dEV2ZW50
-OlcudzYsVG91Y2hFdmVudDpXLnc2LFVJRXZlbnQ6Vy53NixXaW5kb3c6Vy5LNSxET01XaW5kb3c6Vy5L
-NSxEZWRpY2F0ZWRXb3JrZXJHbG9iYWxTY29wZTpXLkNtLFNlcnZpY2VXb3JrZXJHbG9iYWxTY29wZTpX
-LkNtLFNoYXJlZFdvcmtlckdsb2JhbFNjb3BlOlcuQ20sV29ya2VyR2xvYmFsU2NvcGU6Vy5DbSxBdHRy
-OlcuQ1EsQ2xpZW50UmVjdDpXLnc0LERPTVJlY3Q6Vy53NCxOYW1lZE5vZGVNYXA6Vy5yaCxNb3pOYW1l
-ZEF0dHJNYXA6Vy5yaCxJREJLZXlSYW5nZTpQLmhGLFNWR1NjcmlwdEVsZW1lbnQ6UC5uZCxTVkdBRWxl
-bWVudDpQLmQ1LFNWR0FuaW1hdGVFbGVtZW50OlAuZDUsU1ZHQW5pbWF0ZU1vdGlvbkVsZW1lbnQ6UC5k
-NSxTVkdBbmltYXRlVHJhbnNmb3JtRWxlbWVudDpQLmQ1LFNWR0FuaW1hdGlvbkVsZW1lbnQ6UC5kNSxT
-VkdDaXJjbGVFbGVtZW50OlAuZDUsU1ZHQ2xpcFBhdGhFbGVtZW50OlAuZDUsU1ZHRGVmc0VsZW1lbnQ6
-UC5kNSxTVkdEZXNjRWxlbWVudDpQLmQ1LFNWR0Rpc2NhcmRFbGVtZW50OlAuZDUsU1ZHRWxsaXBzZUVs
-ZW1lbnQ6UC5kNSxTVkdGRUJsZW5kRWxlbWVudDpQLmQ1LFNWR0ZFQ29sb3JNYXRyaXhFbGVtZW50OlAu
-ZDUsU1ZHRkVDb21wb25lbnRUcmFuc2ZlckVsZW1lbnQ6UC5kNSxTVkdGRUNvbXBvc2l0ZUVsZW1lbnQ6
-UC5kNSxTVkdGRUNvbnZvbHZlTWF0cml4RWxlbWVudDpQLmQ1LFNWR0ZFRGlmZnVzZUxpZ2h0aW5nRWxl
-bWVudDpQLmQ1LFNWR0ZFRGlzcGxhY2VtZW50TWFwRWxlbWVudDpQLmQ1LFNWR0ZFRGlzdGFudExpZ2h0
-RWxlbWVudDpQLmQ1LFNWR0ZFRmxvb2RFbGVtZW50OlAuZDUsU1ZHRkVGdW5jQUVsZW1lbnQ6UC5kNSxT
-VkdGRUZ1bmNCRWxlbWVudDpQLmQ1LFNWR0ZFRnVuY0dFbGVtZW50OlAuZDUsU1ZHRkVGdW5jUkVsZW1l
-bnQ6UC5kNSxTVkdGRUdhdXNzaWFuQmx1ckVsZW1lbnQ6UC5kNSxTVkdGRUltYWdlRWxlbWVudDpQLmQ1
-LFNWR0ZFTWVyZ2VFbGVtZW50OlAuZDUsU1ZHRkVNZXJnZU5vZGVFbGVtZW50OlAuZDUsU1ZHRkVNb3Jw
-aG9sb2d5RWxlbWVudDpQLmQ1LFNWR0ZFT2Zmc2V0RWxlbWVudDpQLmQ1LFNWR0ZFUG9pbnRMaWdodEVs
-ZW1lbnQ6UC5kNSxTVkdGRVNwZWN1bGFyTGlnaHRpbmdFbGVtZW50OlAuZDUsU1ZHRkVTcG90TGlnaHRF
-bGVtZW50OlAuZDUsU1ZHRkVUaWxlRWxlbWVudDpQLmQ1LFNWR0ZFVHVyYnVsZW5jZUVsZW1lbnQ6UC5k
-NSxTVkdGaWx0ZXJFbGVtZW50OlAuZDUsU1ZHRm9yZWlnbk9iamVjdEVsZW1lbnQ6UC5kNSxTVkdHRWxl
-bWVudDpQLmQ1LFNWR0dlb21ldHJ5RWxlbWVudDpQLmQ1LFNWR0dyYXBoaWNzRWxlbWVudDpQLmQ1LFNW
-R0ltYWdlRWxlbWVudDpQLmQ1LFNWR0xpbmVFbGVtZW50OlAuZDUsU1ZHTGluZWFyR3JhZGllbnRFbGVt
-ZW50OlAuZDUsU1ZHTWFya2VyRWxlbWVudDpQLmQ1LFNWR01hc2tFbGVtZW50OlAuZDUsU1ZHTWV0YWRh
-dGFFbGVtZW50OlAuZDUsU1ZHUGF0aEVsZW1lbnQ6UC5kNSxTVkdQYXR0ZXJuRWxlbWVudDpQLmQ1LFNW
-R1BvbHlnb25FbGVtZW50OlAuZDUsU1ZHUG9seWxpbmVFbGVtZW50OlAuZDUsU1ZHUmFkaWFsR3JhZGll
-bnRFbGVtZW50OlAuZDUsU1ZHUmVjdEVsZW1lbnQ6UC5kNSxTVkdTZXRFbGVtZW50OlAuZDUsU1ZHU3Rv
-cEVsZW1lbnQ6UC5kNSxTVkdTdHlsZUVsZW1lbnQ6UC5kNSxTVkdTVkdFbGVtZW50OlAuZDUsU1ZHU3dp
-dGNoRWxlbWVudDpQLmQ1LFNWR1N5bWJvbEVsZW1lbnQ6UC5kNSxTVkdUU3BhbkVsZW1lbnQ6UC5kNSxT
-VkdUZXh0Q29udGVudEVsZW1lbnQ6UC5kNSxTVkdUZXh0RWxlbWVudDpQLmQ1LFNWR1RleHRQYXRoRWxl
-bWVudDpQLmQ1LFNWR1RleHRQb3NpdGlvbmluZ0VsZW1lbnQ6UC5kNSxTVkdUaXRsZUVsZW1lbnQ6UC5k
-NSxTVkdVc2VFbGVtZW50OlAuZDUsU1ZHVmlld0VsZW1lbnQ6UC5kNSxTVkdHcmFkaWVudEVsZW1lbnQ6
-UC5kNSxTVkdDb21wb25lbnRUcmFuc2ZlckZ1bmN0aW9uRWxlbWVudDpQLmQ1LFNWR0ZFRHJvcFNoYWRv
-d0VsZW1lbnQ6UC5kNSxTVkdNUGF0aEVsZW1lbnQ6UC5kNSxTVkdFbGVtZW50OlAuZDV9KQpodW5rSGVs
-cGVycy5zZXRPclVwZGF0ZUxlYWZUYWdzKHtET01FcnJvcjp0cnVlLERPTUltcGxlbWVudGF0aW9uOnRy
-dWUsTWVkaWFFcnJvcjp0cnVlLE5hdmlnYXRvcjp0cnVlLE5hdmlnYXRvckNvbmN1cnJlbnRIYXJkd2Fy
-ZTp0cnVlLE5hdmlnYXRvclVzZXJNZWRpYUVycm9yOnRydWUsT3ZlcmNvbnN0cmFpbmVkRXJyb3I6dHJ1
-ZSxQb3NpdGlvbkVycm9yOnRydWUsUmFuZ2U6dHJ1ZSxTUUxFcnJvcjp0cnVlLERhdGFWaWV3OnRydWUs
-QXJyYXlCdWZmZXJWaWV3OmZhbHNlLEZsb2F0MzJBcnJheTp0cnVlLEZsb2F0NjRBcnJheTp0cnVlLElu
-dDE2QXJyYXk6dHJ1ZSxJbnQzMkFycmF5OnRydWUsSW50OEFycmF5OnRydWUsVWludDE2QXJyYXk6dHJ1
-ZSxVaW50MzJBcnJheTp0cnVlLFVpbnQ4Q2xhbXBlZEFycmF5OnRydWUsQ2FudmFzUGl4ZWxBcnJheTp0
-cnVlLFVpbnQ4QXJyYXk6ZmFsc2UsSFRNTEF1ZGlvRWxlbWVudDp0cnVlLEhUTUxCUkVsZW1lbnQ6dHJ1
-ZSxIVE1MQnV0dG9uRWxlbWVudDp0cnVlLEhUTUxDYW52YXNFbGVtZW50OnRydWUsSFRNTENvbnRlbnRF
-bGVtZW50OnRydWUsSFRNTERMaXN0RWxlbWVudDp0cnVlLEhUTUxEYXRhRWxlbWVudDp0cnVlLEhUTUxE
-YXRhTGlzdEVsZW1lbnQ6dHJ1ZSxIVE1MRGV0YWlsc0VsZW1lbnQ6dHJ1ZSxIVE1MRGlhbG9nRWxlbWVu
-dDp0cnVlLEhUTUxEaXZFbGVtZW50OnRydWUsSFRNTEVtYmVkRWxlbWVudDp0cnVlLEhUTUxGaWVsZFNl
-dEVsZW1lbnQ6dHJ1ZSxIVE1MSFJFbGVtZW50OnRydWUsSFRNTEhlYWRFbGVtZW50OnRydWUsSFRNTEhl
-YWRpbmdFbGVtZW50OnRydWUsSFRNTEh0bWxFbGVtZW50OnRydWUsSFRNTElGcmFtZUVsZW1lbnQ6dHJ1
-ZSxIVE1MSW1hZ2VFbGVtZW50OnRydWUsSFRNTElucHV0RWxlbWVudDp0cnVlLEhUTUxMSUVsZW1lbnQ6
-dHJ1ZSxIVE1MTGFiZWxFbGVtZW50OnRydWUsSFRNTExlZ2VuZEVsZW1lbnQ6dHJ1ZSxIVE1MTGlua0Vs
-ZW1lbnQ6dHJ1ZSxIVE1MTWFwRWxlbWVudDp0cnVlLEhUTUxNZWRpYUVsZW1lbnQ6dHJ1ZSxIVE1MTWVu
-dUVsZW1lbnQ6dHJ1ZSxIVE1MTWV0YUVsZW1lbnQ6dHJ1ZSxIVE1MTWV0ZXJFbGVtZW50OnRydWUsSFRN
-TE1vZEVsZW1lbnQ6dHJ1ZSxIVE1MT0xpc3RFbGVtZW50OnRydWUsSFRNTE9iamVjdEVsZW1lbnQ6dHJ1
-ZSxIVE1MT3B0R3JvdXBFbGVtZW50OnRydWUsSFRNTE9wdGlvbkVsZW1lbnQ6dHJ1ZSxIVE1MT3V0cHV0
-RWxlbWVudDp0cnVlLEhUTUxQYXJhbUVsZW1lbnQ6dHJ1ZSxIVE1MUGljdHVyZUVsZW1lbnQ6dHJ1ZSxI
-VE1MUHJlRWxlbWVudDp0cnVlLEhUTUxQcm9ncmVzc0VsZW1lbnQ6dHJ1ZSxIVE1MUXVvdGVFbGVtZW50
-OnRydWUsSFRNTFNjcmlwdEVsZW1lbnQ6dHJ1ZSxIVE1MU2hhZG93RWxlbWVudDp0cnVlLEhUTUxTbG90
-RWxlbWVudDp0cnVlLEhUTUxTb3VyY2VFbGVtZW50OnRydWUsSFRNTFNwYW5FbGVtZW50OnRydWUsSFRN
-TFN0eWxlRWxlbWVudDp0cnVlLEhUTUxUYWJsZUNhcHRpb25FbGVtZW50OnRydWUsSFRNTFRhYmxlQ2Vs
-bEVsZW1lbnQ6dHJ1ZSxIVE1MVGFibGVEYXRhQ2VsbEVsZW1lbnQ6dHJ1ZSxIVE1MVGFibGVIZWFkZXJD
-ZWxsRWxlbWVudDp0cnVlLEhUTUxUYWJsZUNvbEVsZW1lbnQ6dHJ1ZSxIVE1MVGV4dEFyZWFFbGVtZW50
-OnRydWUsSFRNTFRpbWVFbGVtZW50OnRydWUsSFRNTFRpdGxlRWxlbWVudDp0cnVlLEhUTUxUcmFja0Vs
-ZW1lbnQ6dHJ1ZSxIVE1MVUxpc3RFbGVtZW50OnRydWUsSFRNTFVua25vd25FbGVtZW50OnRydWUsSFRN
-TFZpZGVvRWxlbWVudDp0cnVlLEhUTUxEaXJlY3RvcnlFbGVtZW50OnRydWUsSFRNTEZvbnRFbGVtZW50
-OnRydWUsSFRNTEZyYW1lRWxlbWVudDp0cnVlLEhUTUxGcmFtZVNldEVsZW1lbnQ6dHJ1ZSxIVE1MTWFy
-cXVlZUVsZW1lbnQ6dHJ1ZSxIVE1MRWxlbWVudDpmYWxzZSxIVE1MQW5jaG9yRWxlbWVudDp0cnVlLEhU
-TUxBcmVhRWxlbWVudDp0cnVlLEhUTUxCYXNlRWxlbWVudDp0cnVlLEJsb2I6ZmFsc2UsSFRNTEJvZHlF
-bGVtZW50OnRydWUsQ0RBVEFTZWN0aW9uOnRydWUsQ2hhcmFjdGVyRGF0YTp0cnVlLENvbW1lbnQ6dHJ1
-ZSxQcm9jZXNzaW5nSW5zdHJ1Y3Rpb246dHJ1ZSxUZXh0OnRydWUsQ1NTU3R5bGVEZWNsYXJhdGlvbjp0
-cnVlLE1TU3R5bGVDU1NQcm9wZXJ0aWVzOnRydWUsQ1NTMlByb3BlcnRpZXM6dHJ1ZSxYTUxEb2N1bWVu
-dDp0cnVlLERvY3VtZW50OmZhbHNlLERPTUV4Y2VwdGlvbjp0cnVlLERPTVJlY3RSZWFkT25seTpmYWxz
-ZSxET01Ub2tlbkxpc3Q6dHJ1ZSxFbGVtZW50OmZhbHNlLEFib3J0UGF5bWVudEV2ZW50OnRydWUsQW5p
-bWF0aW9uRXZlbnQ6dHJ1ZSxBbmltYXRpb25QbGF5YmFja0V2ZW50OnRydWUsQXBwbGljYXRpb25DYWNo
-ZUVycm9yRXZlbnQ6dHJ1ZSxCYWNrZ3JvdW5kRmV0Y2hDbGlja0V2ZW50OnRydWUsQmFja2dyb3VuZEZl
-dGNoRXZlbnQ6dHJ1ZSxCYWNrZ3JvdW5kRmV0Y2hGYWlsRXZlbnQ6dHJ1ZSxCYWNrZ3JvdW5kRmV0Y2hl
-ZEV2ZW50OnRydWUsQmVmb3JlSW5zdGFsbFByb21wdEV2ZW50OnRydWUsQmVmb3JlVW5sb2FkRXZlbnQ6
-dHJ1ZSxCbG9iRXZlbnQ6dHJ1ZSxDYW5NYWtlUGF5bWVudEV2ZW50OnRydWUsQ2xpcGJvYXJkRXZlbnQ6
-dHJ1ZSxDbG9zZUV2ZW50OnRydWUsQ3VzdG9tRXZlbnQ6dHJ1ZSxEZXZpY2VNb3Rpb25FdmVudDp0cnVl
-LERldmljZU9yaWVudGF0aW9uRXZlbnQ6dHJ1ZSxFcnJvckV2ZW50OnRydWUsRXh0ZW5kYWJsZUV2ZW50
-OnRydWUsRXh0ZW5kYWJsZU1lc3NhZ2VFdmVudDp0cnVlLEZldGNoRXZlbnQ6dHJ1ZSxGb250RmFjZVNl
-dExvYWRFdmVudDp0cnVlLEZvcmVpZ25GZXRjaEV2ZW50OnRydWUsR2FtZXBhZEV2ZW50OnRydWUsSGFz
-aENoYW5nZUV2ZW50OnRydWUsSW5zdGFsbEV2ZW50OnRydWUsTWVkaWFFbmNyeXB0ZWRFdmVudDp0cnVl
-LE1lZGlhS2V5TWVzc2FnZUV2ZW50OnRydWUsTWVkaWFRdWVyeUxpc3RFdmVudDp0cnVlLE1lZGlhU3Ry
-ZWFtRXZlbnQ6dHJ1ZSxNZWRpYVN0cmVhbVRyYWNrRXZlbnQ6dHJ1ZSxNZXNzYWdlRXZlbnQ6dHJ1ZSxN
-SURJQ29ubmVjdGlvbkV2ZW50OnRydWUsTUlESU1lc3NhZ2VFdmVudDp0cnVlLE11dGF0aW9uRXZlbnQ6
-dHJ1ZSxOb3RpZmljYXRpb25FdmVudDp0cnVlLFBhZ2VUcmFuc2l0aW9uRXZlbnQ6dHJ1ZSxQYXltZW50
-UmVxdWVzdEV2ZW50OnRydWUsUGF5bWVudFJlcXVlc3RVcGRhdGVFdmVudDp0cnVlLFBvcFN0YXRlRXZl
-bnQ6dHJ1ZSxQcmVzZW50YXRpb25Db25uZWN0aW9uQXZhaWxhYmxlRXZlbnQ6dHJ1ZSxQcmVzZW50YXRp
-b25Db25uZWN0aW9uQ2xvc2VFdmVudDp0cnVlLFByb21pc2VSZWplY3Rpb25FdmVudDp0cnVlLFB1c2hF
-dmVudDp0cnVlLFJUQ0RhdGFDaGFubmVsRXZlbnQ6dHJ1ZSxSVENEVE1GVG9uZUNoYW5nZUV2ZW50OnRy
-dWUsUlRDUGVlckNvbm5lY3Rpb25JY2VFdmVudDp0cnVlLFJUQ1RyYWNrRXZlbnQ6dHJ1ZSxTZWN1cml0
-eVBvbGljeVZpb2xhdGlvbkV2ZW50OnRydWUsU2Vuc29yRXJyb3JFdmVudDp0cnVlLFNwZWVjaFJlY29n
-bml0aW9uRXJyb3I6dHJ1ZSxTcGVlY2hSZWNvZ25pdGlvbkV2ZW50OnRydWUsU3BlZWNoU3ludGhlc2lz
-RXZlbnQ6dHJ1ZSxTdG9yYWdlRXZlbnQ6dHJ1ZSxTeW5jRXZlbnQ6dHJ1ZSxUcmFja0V2ZW50OnRydWUs
-VHJhbnNpdGlvbkV2ZW50OnRydWUsV2ViS2l0VHJhbnNpdGlvbkV2ZW50OnRydWUsVlJEZXZpY2VFdmVu
-dDp0cnVlLFZSRGlzcGxheUV2ZW50OnRydWUsVlJTZXNzaW9uRXZlbnQ6dHJ1ZSxNb2pvSW50ZXJmYWNl
-UmVxdWVzdEV2ZW50OnRydWUsVVNCQ29ubmVjdGlvbkV2ZW50OnRydWUsSURCVmVyc2lvbkNoYW5nZUV2
-ZW50OnRydWUsQXVkaW9Qcm9jZXNzaW5nRXZlbnQ6dHJ1ZSxPZmZsaW5lQXVkaW9Db21wbGV0aW9uRXZl
-bnQ6dHJ1ZSxXZWJHTENvbnRleHRFdmVudDp0cnVlLEV2ZW50OmZhbHNlLElucHV0RXZlbnQ6ZmFsc2Us
-U3VibWl0RXZlbnQ6ZmFsc2UsRXZlbnRUYXJnZXQ6ZmFsc2UsRmlsZTp0cnVlLEhUTUxGb3JtRWxlbWVu
-dDp0cnVlLEhpc3Rvcnk6dHJ1ZSxIVE1MRG9jdW1lbnQ6dHJ1ZSxYTUxIdHRwUmVxdWVzdDp0cnVlLFhN
-TEh0dHBSZXF1ZXN0RXZlbnRUYXJnZXQ6ZmFsc2UsSW1hZ2VEYXRhOnRydWUsTG9jYXRpb246dHJ1ZSxN
-b3VzZUV2ZW50OnRydWUsRHJhZ0V2ZW50OnRydWUsUG9pbnRlckV2ZW50OnRydWUsV2hlZWxFdmVudDp0
-cnVlLERvY3VtZW50RnJhZ21lbnQ6dHJ1ZSxTaGFkb3dSb290OnRydWUsRG9jdW1lbnRUeXBlOnRydWUs
-Tm9kZTpmYWxzZSxOb2RlTGlzdDp0cnVlLFJhZGlvTm9kZUxpc3Q6dHJ1ZSxIVE1MUGFyYWdyYXBoRWxl
-bWVudDp0cnVlLFByb2dyZXNzRXZlbnQ6dHJ1ZSxSZXNvdXJjZVByb2dyZXNzRXZlbnQ6dHJ1ZSxIVE1M
-U2VsZWN0RWxlbWVudDp0cnVlLEhUTUxUYWJsZUVsZW1lbnQ6dHJ1ZSxIVE1MVGFibGVSb3dFbGVtZW50
-OnRydWUsSFRNTFRhYmxlU2VjdGlvbkVsZW1lbnQ6dHJ1ZSxIVE1MVGVtcGxhdGVFbGVtZW50OnRydWUs
-Q29tcG9zaXRpb25FdmVudDp0cnVlLEZvY3VzRXZlbnQ6dHJ1ZSxLZXlib2FyZEV2ZW50OnRydWUsVGV4
-dEV2ZW50OnRydWUsVG91Y2hFdmVudDp0cnVlLFVJRXZlbnQ6ZmFsc2UsV2luZG93OnRydWUsRE9NV2lu
-ZG93OnRydWUsRGVkaWNhdGVkV29ya2VyR2xvYmFsU2NvcGU6dHJ1ZSxTZXJ2aWNlV29ya2VyR2xvYmFs
-U2NvcGU6dHJ1ZSxTaGFyZWRXb3JrZXJHbG9iYWxTY29wZTp0cnVlLFdvcmtlckdsb2JhbFNjb3BlOnRy
-dWUsQXR0cjp0cnVlLENsaWVudFJlY3Q6dHJ1ZSxET01SZWN0OnRydWUsTmFtZWROb2RlTWFwOnRydWUs
-TW96TmFtZWRBdHRyTWFwOnRydWUsSURCS2V5UmFuZ2U6dHJ1ZSxTVkdTY3JpcHRFbGVtZW50OnRydWUs
-U1ZHQUVsZW1lbnQ6dHJ1ZSxTVkdBbmltYXRlRWxlbWVudDp0cnVlLFNWR0FuaW1hdGVNb3Rpb25FbGVt
-ZW50OnRydWUsU1ZHQW5pbWF0ZVRyYW5zZm9ybUVsZW1lbnQ6dHJ1ZSxTVkdBbmltYXRpb25FbGVtZW50
-OnRydWUsU1ZHQ2lyY2xlRWxlbWVudDp0cnVlLFNWR0NsaXBQYXRoRWxlbWVudDp0cnVlLFNWR0RlZnNF
-bGVtZW50OnRydWUsU1ZHRGVzY0VsZW1lbnQ6dHJ1ZSxTVkdEaXNjYXJkRWxlbWVudDp0cnVlLFNWR0Vs
-bGlwc2VFbGVtZW50OnRydWUsU1ZHRkVCbGVuZEVsZW1lbnQ6dHJ1ZSxTVkdGRUNvbG9yTWF0cml4RWxl
-bWVudDp0cnVlLFNWR0ZFQ29tcG9uZW50VHJhbnNmZXJFbGVtZW50OnRydWUsU1ZHRkVDb21wb3NpdGVF
-bGVtZW50OnRydWUsU1ZHRkVDb252b2x2ZU1hdHJpeEVsZW1lbnQ6dHJ1ZSxTVkdGRURpZmZ1c2VMaWdo
-dGluZ0VsZW1lbnQ6dHJ1ZSxTVkdGRURpc3BsYWNlbWVudE1hcEVsZW1lbnQ6dHJ1ZSxTVkdGRURpc3Rh
-bnRMaWdodEVsZW1lbnQ6dHJ1ZSxTVkdGRUZsb29kRWxlbWVudDp0cnVlLFNWR0ZFRnVuY0FFbGVtZW50
-OnRydWUsU1ZHRkVGdW5jQkVsZW1lbnQ6dHJ1ZSxTVkdGRUZ1bmNHRWxlbWVudDp0cnVlLFNWR0ZFRnVu
-Y1JFbGVtZW50OnRydWUsU1ZHRkVHYXVzc2lhbkJsdXJFbGVtZW50OnRydWUsU1ZHRkVJbWFnZUVsZW1l
-bnQ6dHJ1ZSxTVkdGRU1lcmdlRWxlbWVudDp0cnVlLFNWR0ZFTWVyZ2VOb2RlRWxlbWVudDp0cnVlLFNW
-R0ZFTW9ycGhvbG9neUVsZW1lbnQ6dHJ1ZSxTVkdGRU9mZnNldEVsZW1lbnQ6dHJ1ZSxTVkdGRVBvaW50
-TGlnaHRFbGVtZW50OnRydWUsU1ZHRkVTcGVjdWxhckxpZ2h0aW5nRWxlbWVudDp0cnVlLFNWR0ZFU3Bv
-dExpZ2h0RWxlbWVudDp0cnVlLFNWR0ZFVGlsZUVsZW1lbnQ6dHJ1ZSxTVkdGRVR1cmJ1bGVuY2VFbGVt
-ZW50OnRydWUsU1ZHRmlsdGVyRWxlbWVudDp0cnVlLFNWR0ZvcmVpZ25PYmplY3RFbGVtZW50OnRydWUs
-U1ZHR0VsZW1lbnQ6dHJ1ZSxTVkdHZW9tZXRyeUVsZW1lbnQ6dHJ1ZSxTVkdHcmFwaGljc0VsZW1lbnQ6
-dHJ1ZSxTVkdJbWFnZUVsZW1lbnQ6dHJ1ZSxTVkdMaW5lRWxlbWVudDp0cnVlLFNWR0xpbmVhckdyYWRp
-ZW50RWxlbWVudDp0cnVlLFNWR01hcmtlckVsZW1lbnQ6dHJ1ZSxTVkdNYXNrRWxlbWVudDp0cnVlLFNW
-R01ldGFkYXRhRWxlbWVudDp0cnVlLFNWR1BhdGhFbGVtZW50OnRydWUsU1ZHUGF0dGVybkVsZW1lbnQ6
-dHJ1ZSxTVkdQb2x5Z29uRWxlbWVudDp0cnVlLFNWR1BvbHlsaW5lRWxlbWVudDp0cnVlLFNWR1JhZGlh
-bEdyYWRpZW50RWxlbWVudDp0cnVlLFNWR1JlY3RFbGVtZW50OnRydWUsU1ZHU2V0RWxlbWVudDp0cnVl
-LFNWR1N0b3BFbGVtZW50OnRydWUsU1ZHU3R5bGVFbGVtZW50OnRydWUsU1ZHU1ZHRWxlbWVudDp0cnVl
-LFNWR1N3aXRjaEVsZW1lbnQ6dHJ1ZSxTVkdTeW1ib2xFbGVtZW50OnRydWUsU1ZHVFNwYW5FbGVtZW50
-OnRydWUsU1ZHVGV4dENvbnRlbnRFbGVtZW50OnRydWUsU1ZHVGV4dEVsZW1lbnQ6dHJ1ZSxTVkdUZXh0
-UGF0aEVsZW1lbnQ6dHJ1ZSxTVkdUZXh0UG9zaXRpb25pbmdFbGVtZW50OnRydWUsU1ZHVGl0bGVFbGVt
-ZW50OnRydWUsU1ZHVXNlRWxlbWVudDp0cnVlLFNWR1ZpZXdFbGVtZW50OnRydWUsU1ZHR3JhZGllbnRF
-bGVtZW50OnRydWUsU1ZHQ29tcG9uZW50VHJhbnNmZXJGdW5jdGlvbkVsZW1lbnQ6dHJ1ZSxTVkdGRURy
-b3BTaGFkb3dFbGVtZW50OnRydWUsU1ZHTVBhdGhFbGVtZW50OnRydWUsU1ZHRWxlbWVudDpmYWxzZX0p
-CkguTFouJG5hdGl2ZVN1cGVyY2xhc3NUYWc9IkFycmF5QnVmZmVyVmlldyIKSC5SRy4kbmF0aXZlU3Vw
-ZXJjbGFzc1RhZz0iQXJyYXlCdWZmZXJWaWV3IgpILlZQLiRuYXRpdmVTdXBlcmNsYXNzVGFnPSJBcnJh
-eUJ1ZmZlclZpZXciCkguRGcuJG5hdGl2ZVN1cGVyY2xhc3NUYWc9IkFycmF5QnVmZmVyVmlldyIKSC5X
-Qi4kbmF0aXZlU3VwZXJjbGFzc1RhZz0iQXJyYXlCdWZmZXJWaWV3IgpILlpHLiRuYXRpdmVTdXBlcmNs
-YXNzVGFnPSJBcnJheUJ1ZmZlclZpZXciCkguUGcuJG5hdGl2ZVN1cGVyY2xhc3NUYWc9IkFycmF5QnVm
-ZmVyVmlldyJ9KSgpCmNvbnZlcnRBbGxUb0Zhc3RPYmplY3QodykKY29udmVydFRvRmFzdE9iamVjdCgk
-KTsoZnVuY3Rpb24oYSl7aWYodHlwZW9mIGRvY3VtZW50PT09InVuZGVmaW5lZCIpe2EobnVsbCkKcmV0
-dXJufWlmKHR5cGVvZiBkb2N1bWVudC5jdXJyZW50U2NyaXB0IT0ndW5kZWZpbmVkJyl7YShkb2N1bWVu
-dC5jdXJyZW50U2NyaXB0KQpyZXR1cm59dmFyIHQ9ZG9jdW1lbnQuc2NyaXB0cwpmdW5jdGlvbiBvbkxv
-YWQoYil7Zm9yKHZhciByPTA7cjx0Lmxlbmd0aDsrK3IpdFtyXS5yZW1vdmVFdmVudExpc3RlbmVyKCJs
-b2FkIixvbkxvYWQsZmFsc2UpCmEoYi50YXJnZXQpfWZvcih2YXIgcz0wO3M8dC5sZW5ndGg7KytzKXRb
-c10uYWRkRXZlbnRMaXN0ZW5lcigibG9hZCIsb25Mb2FkLGZhbHNlKX0pKGZ1bmN0aW9uKGEpe3YuY3Vy
-cmVudFNjcmlwdD1hCmlmKHR5cGVvZiBkYXJ0TWFpblJ1bm5lcj09PSJmdW5jdGlvbiIpZGFydE1haW5S
-dW5uZXIoTC5JcSxbXSkKZWxzZSBMLklxKFtdKX0pfSkoKQovLyMgc291cmNlTWFwcGluZ1VSTD1taWdy
-YXRpb24uanMubWFwCg==
+cmlwdGlvbiIsdGhpcy5hLCJlbnRyaWVzIixxXSx1LlgsdS5fKX19ClUud2IucHJvdG90eXBlPXsKTHQ6
+ZnVuY3Rpb24oKXt2YXIgdCxzLHIscT10aGlzLHA9UC5GbCh1LlgsdS5fKQpwLlkoMCwiZGVzY3JpcHRp
+b24iLHEuYSkKdD1xLmIKaWYodCE9bnVsbClwLlkoMCwiZnVuY3Rpb24iLHQpCnQ9cS5jCmlmKHQhPW51
+bGwpcC5ZKDAsImxpbmsiLHQuTHQoKSkKdD1xLmQKaWYodC5sZW5ndGghPT0wKXtzPUgudDYodCkKcj1z
+LkMoImxKPDEsWjA8cVUqLE1oKj4qPiIpCnAuWSgwLCJoaW50QWN0aW9ucyIsUC5DSChuZXcgSC5sSih0
+LHMuQygiWjA8cVUqLE1oKj4qKDEpIikuYShuZXcgVS5iMCgpKSxyKSwhMCxyLkMoImFMLkUiKSkpfXJl
+dHVybiBwfX0KVS5hTi5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gVS5ueih1LnQuYShh
+KSl9LAokUzozOH0KVS5iMC5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gdS5hWC5hKGEp
+Lkx0KCl9LAokUzozOX0KQi5qOC5wcm90b3R5cGU9ewpMdDpmdW5jdGlvbigpe3JldHVybiBQLkVGKFsi
+bGluZSIsdGhpcy5hLCJleHBsYW5hdGlvbiIsdGhpcy5iLCJvZmZzZXQiLHRoaXMuY10sdS5YLHUuXyl9
+fQpCLnFwLnByb3RvdHlwZT17Ckx0OmZ1bmN0aW9uKCl7dmFyIHQscyxyLHEscCxvLG4sbT10aGlzLGw9
+dS5YLGs9UC5GbChsLHUuZHApCmZvcih0PW0uZCx0PXQuZ1B1KHQpLHQ9dC5na3oodCkscz11Ll8scj11
+Lkc7dC5GKCk7KXtxPXQuZ2woKQpwPXEuYQpvPUguVk0oW10scikKZm9yKHE9Si5JVChxLmIpO3EuRigp
+Oyl7bj1xLmdsKCkKQy5ObS5pKG8sUC5FRihbImxpbmUiLG4uYSwiZXhwbGFuYXRpb24iLG4uYiwib2Zm
+c2V0IixuLmNdLGwscykpfWsuWSgwLHAsbyl9cmV0dXJuIFAuRUYoWyJyZWdpb25zIixtLmEsIm5hdmln
+YXRpb25Db250ZW50IixtLmIsInNvdXJjZUNvZGUiLG0uYywiZWRpdHMiLGtdLGwscyl9fQpULm1RLnBy
+b3RvdHlwZT17fQpMLmUucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscCxvLG4K
+dS5hTC5hKGEpCnQ9d2luZG93LmxvY2F0aW9uLnBhdGhuYW1lCnM9TC5HNih3aW5kb3cubG9jYXRpb24u
+aHJlZikKcj1MLmFLKHdpbmRvdy5sb2NhdGlvbi5ocmVmKQpMLkdlKCkKaWYodCE9PSIvIiYmdCE9PUou
+VDAoZG9jdW1lbnQucXVlcnlTZWxlY3RvcigiLnJvb3QiKS50ZXh0Q29udGVudCkpTC5HNyh0LHMsciwh
+MCxuZXcgTC5WVyh0LHMscikpCnE9ZG9jdW1lbnQKcD1KLnFGKHEucXVlcnlTZWxlY3RvcigiLmFwcGx5
+LW1pZ3JhdGlvbiIpKQpvPXAuJHRpCm49by5DKCJ+KDEpPyIpLmEobmV3IEwub1ooKSkKdS5aLmEobnVs
+bCkKVy5KRShwLmEscC5iLG4sITEsby5jKQpvPUoucUYocS5xdWVyeVNlbGVjdG9yKCIucmVydW4tbWln
+cmF0aW9uIikpCm49by4kdGkKVy5KRShvLmEsby5iLG4uQygifigxKT8iKS5hKG5ldyBMLkhpKCkpLCEx
+LG4uYykKbj1KLnFGKHEucXVlcnlTZWxlY3RvcigiLnJlcG9ydC1wcm9ibGVtIikpCm89bi4kdGkKVy5K
+RShuLmEsbi5iLG8uQygifigxKT8iKS5hKG5ldyBMLkJUKCkpLCExLG8uYykKcT1KLnFGKHEucXVlcnlT
+ZWxlY3RvcigiLnBvcHVwLXBhbmUgLmNsb3NlIikpCm89cS4kdGkKVy5KRShxLmEscS5iLG8uQygifigx
+KT8iKS5hKG5ldyBMLlBZKCkpLCExLG8uYyl9LAokUzoxN30KTC5WVy5wcm90b3R5cGU9ewokMDpmdW5j
+dGlvbigpe0wuRnIodGhpcy5hLHRoaXMuYix0aGlzLmMpfSwKJFM6MH0KTC5vWi5wcm90b3R5cGU9ewok
+MTpmdW5jdGlvbihhKXt2YXIgdCxzLHIscQp1Lk8uYShhKQppZihILm9UKEMub2wudXMod2luZG93LCJU
+aGlzIHdpbGwgYXBwbHkgdGhlIGNoYW5nZXMgeW91J3ZlIHByZXZpZXdlZCB0byB5b3VyIHdvcmtpbmcg
+ZGlyZWN0b3J5LiBJdCBpcyByZWNvbW1lbmRlZCB5b3UgY29tbWl0IGFueSBjaGFuZ2VzIHlvdSBtYWRl
+IGJlZm9yZSBkb2luZyB0aGlzLiIpKSl7dD1MLnR5KCIvYXBwbHktbWlncmF0aW9uIixudWxsKS5XNyhu
+ZXcgTC5qcigpLHUuUCkKcz1uZXcgTC5xbCgpCnUuYjcuYShudWxsKQpyPXQuJHRpCnE9JC5YMwppZihx
+IT09Qy5OVSlzPVAuVkgocyxxKQp0LnhmKG5ldyBQLkZlKG5ldyBQLnZzKHEsciksMixudWxsLHMsci5D
+KCJAPDE+IikuS3Eoci5jKS5DKCJGZTwxLDI+IikpKX19LAokUzoyfQpMLmpyLnByb3RvdHlwZT17CiQx
+OmZ1bmN0aW9uKGEpe3ZhciB0CnUudC5hKGEpCnQ9ZG9jdW1lbnQuYm9keQp0LmNsYXNzTGlzdC5yZW1v
+dmUoInByb3Bvc2VkIikKdC5jbGFzc0xpc3QuYWRkKCJhcHBsaWVkIil9LAokUzo0Mn0KTC5xbC5wcm90
+b3R5cGU9ewokMjpmdW5jdGlvbihhLGIpe0wuQzIoIkNvdWxkIG5vdCBhcHBseSBtaWdyYXRpb24iLGEs
+Yil9LAokQzoiJDIiLAokUjoyLAokUzo2fQpMLkhpLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3Jl
+dHVybiB0aGlzLnhuKHUuTy5hKGEpKX0sCnhuOmZ1bmN0aW9uKGEpe3ZhciB0PTAscz1QLkZYKHUuUCks
+cj0xLHEscD1bXSxvLG4sbSxsCnZhciAkYXN5bmMkJDE9UC5seihmdW5jdGlvbihiLGMpe2lmKGI9PT0x
+KXtxPWMKdD1yfXdoaWxlKHRydWUpc3dpdGNoKHQpe2Nhc2UgMDpyPTMKZG9jdW1lbnQuYm9keS5jbGFz
+c0xpc3QuYWRkKCJyZXJ1bm5pbmciKQp0PTYKcmV0dXJuIFAualEoTC50eSgiL3JlcnVuLW1pZ3JhdGlv
+biIsbnVsbCksJGFzeW5jJCQxKQpjYXNlIDY6d2luZG93LmxvY2F0aW9uLnJlbG9hZCgpCnAucHVzaCg1
+KQp0PTQKYnJlYWsKY2FzZSAzOnI9MgpsPXEKbz1ILlJ1KGwpCm49SC50cyhsKQpMLkMyKCJGYWlsZWQg
+dG8gcmVydW4gbWlncmF0aW9uIixvLG4pCnAucHVzaCg1KQp0PTQKYnJlYWsKY2FzZSAyOnA9WzFdCmNh
+c2UgNDpyPTEKZG9jdW1lbnQuYm9keS5jbGFzc0xpc3QucmVtb3ZlKCJyZXJ1bm5pbmciKQp0PXAucG9w
+KCkKYnJlYWsKY2FzZSA1OnJldHVybiBQLnlDKG51bGwscykKY2FzZSAxOnJldHVybiBQLmYzKHEscyl9
+fSkKcmV0dXJuIFAuREkoJGFzeW5jJCQxLHMpfSwKJFM6MTh9CkwuQlQucHJvdG90eXBlPXsKJDE6ZnVu
+Y3Rpb24oYSl7dmFyIHQKdS5PLmEoYSkKdD11LlgKQy5vbC5Qbyh3aW5kb3csUC5YZCgiaHR0cHMiLCJn
+aXRodWIuY29tIiwiZGFydC1sYW5nL3Nkay9pc3N1ZXMvbmV3IixQLkVGKFsidGl0bGUiLCJDdXN0b21l
+ci1yZXBvcnRlZCBpc3N1ZSB3aXRoIE5OQkQgbWlncmF0aW9uIHRvb2wiLCJsYWJlbHMiLCJhcmVhLWFu
+YWx5emVyLGFuYWx5emVyLW5uYmQtbWlncmF0aW9uLHR5cGUtYnVnIiwiYm9keSIsIiMjIyMgU3RlcHMg
+dG8gcmVwcm9kdWNlXG5cbiMjIyMgV2hhdCBkaWQgeW91IGV4cGVjdCB0byBoYXBwZW4/XG5cbiMjIyMg
+V2hhdCBhY3R1YWxseSBoYXBwZW5lZD9cblxuX1NjcmVlbnNob3RzIGFyZSBhcHByZWNpYXRlZF9cblxu
+KipEYXJ0IFNESyB2ZXJzaW9uKio6ICIrSC5Faihkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgic2RrLXZl
+cnNpb24iKS50ZXh0Q29udGVudCkrIlxuXG5UaGFua3MgZm9yIGZpbGluZyFcbiJdLHQsdCkpLmduRCgp
+LCJyZXBvcnQtcHJvYmxlbSIpfSwKJFM6Mn0KTC5QWS5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2
+YXIgdAp1Lk8uYShhKQp0PWRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoIi5wb3B1cC1wYW5lIikuc3R5bGUK
+dC5kaXNwbGF5PSJub25lIgpyZXR1cm4ibm9uZSJ9LAokUzo0NH0KTC5MLnByb3RvdHlwZT17CiQxOmZ1
+bmN0aW9uKGEpe3ZhciB0LHMscgp1LmFMLmEoYSkKdD13aW5kb3cubG9jYXRpb24ucGF0aG5hbWUKcz1M
+Lkc2KHdpbmRvdy5sb2NhdGlvbi5ocmVmKQpyPUwuYUsod2luZG93LmxvY2F0aW9uLmhyZWYpCmlmKHQu
+bGVuZ3RoPjEpTC5HNyh0LHMsciwhMSxudWxsKQplbHNle0wuQkUodCxuZXcgQi5xcCgiIiwiIiwiIixD
+LkNNKSwhMCkKTC5CWCgiJm5ic3A7IixudWxsKX19LAokUzoxN30KTC5XeC5wcm90b3R5cGU9ewokMTpm
+dW5jdGlvbihhKXt2YXIgdCxzLHIscT0iY29sbGFwc2VkIgp1Lk8uYShhKQp0PXRoaXMuYQpzPUouWUUo
+dCkKcj10aGlzLmIKaWYoIXMuZ1AodCkudGcoMCxxKSl7cy5nUCh0KS5pKDAscSkKSi5kUihyKS5pKDAs
+cSl9ZWxzZXtzLmdQKHQpLlIoMCxxKQpKLmRSKHIpLlIoMCxxKX19LAokUzoyfQpMLkFPLnByb3RvdHlw
+ZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0PUoucUYodS5nLmEoYSkpLHM9dC4kdGkscj1zLkMoIn4oMSk/
+IikuYShuZXcgTC5kTih0aGlzLmEpKQp1LlouYShudWxsKQpXLkpFKHQuYSx0LmIsciwhMSxzLmMpfSwK
+JFM6M30KTC5kTi5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXt2YXIgdAp1Lk8uYShhKQp0PWRvY3Vt
+ZW50LnF1ZXJ5U2VsZWN0b3IoInRhYmxlW2RhdGEtcGF0aF0iKQp0LnRvU3RyaW5nCkwudDIoYSx0aGlz
+LmEsdC5nZXRBdHRyaWJ1dGUoImRhdGEtIituZXcgVy5TeShuZXcgVy5pNyh0KSkuTygicGF0aCIpKSl9
+LAokUzoyfQpMLkhvLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3ZhciB0LHMscgp1LmcuYShhKQp0
+PUoucUYoYSkKcz10LiR0aQpyPXMuQygifigxKT8iKS5hKG5ldyBMLnh6KGEsdGhpcy5hKSkKdS5aLmEo
+bnVsbCkKVy5KRSh0LmEsdC5iLHIsITEscy5jKX0sCiRTOjN9CkwueHoucHJvdG90eXBlPXsKJDE6ZnVu
+Y3Rpb24oYSl7dmFyIHQKdS5PLmEoYSkKdD10aGlzLmEKTC5oWCh0aGlzLmIsUC5RQSh0LmdldEF0dHJp
+YnV0ZSgiZGF0YS0iK25ldyBXLlN5KG5ldyBXLmk3KHQpKS5PKCJvZmZzZXQiKSksbnVsbCksUC5RQSh0
+LmdldEF0dHJpYnV0ZSgiZGF0YS0iK25ldyBXLlN5KG5ldyBXLmk3KHQpKS5PKCJsaW5lIikpLG51bGwp
+KX0sCiRTOjJ9CkwuSUMucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dmFyIHQ9Si5xRih1LmcuYShh
+KSkscz10LiR0aQpzLkMoIn4oMSk/IikuYShMLmlTKCkpCnUuWi5hKG51bGwpClcuSkUodC5hLHQuYixM
+LmlTKCksITEscy5jKX0sCiRTOjN9CkwuZkMucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7dS5lUS5h
+KGEpCnRoaXMuYS5hTSgwLHRoaXMuYil9LAokUzo0Nn0KTC5uVC5wcm90b3R5cGU9ewokMDpmdW5jdGlv
+bigpe0wuRnIodGhpcy5hLmEsdGhpcy5iLHRoaXMuYyl9LAokUzowfQpMLk5ZLnByb3RvdHlwZT17CiQw
+OmZ1bmN0aW9uKCl7TC5Gcih0aGlzLmEuYSxudWxsLG51bGwpfSwKJFM6MH0KTC5lWC5wcm90b3R5cGU9
+ewokMTpmdW5jdGlvbihhKXt1LmcuYShhKQokLnpCKCkudG9TdHJpbmcKdS5kSC5hKCQub3coKS5xKDAs
+ImhsanMiKSkuVjcoImhpZ2hsaWdodEJsb2NrIixbYV0pfSwKJFM6M30KTC5FRS5wcm90b3R5cGU9ewok
+MTpmdW5jdGlvbihhKXt2YXIgdCxzCnUuTy5hKGEpCnQ9dGhpcy5hCnM9dGhpcy5iCkwuYWYod2luZG93
+LmxvY2F0aW9uLnBhdGhuYW1lLHQscywhMCxuZXcgTC5RTCh0LHMpKQpMLmhYKHRoaXMuYyx0LHMpfSwK
+JFM6Mn0KTC5RTC5wcm90b3R5cGU9ewokMDpmdW5jdGlvbigpe0wuRnIod2luZG93LmxvY2F0aW9uLnBh
+dGhuYW1lLHRoaXMuYSx0aGlzLmIpfSwKJFM6MH0KTC5WUy5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihh
+KXt2YXIgdCxzPSJzZWxlY3RlZC1maWxlIgp1LmcuYShhKQphLnRvU3RyaW5nCnQ9Si5ZRShhKQppZihh
+LmdldEF0dHJpYnV0ZSgiZGF0YS0iK25ldyBXLlN5KG5ldyBXLmk3KGEpKS5PKCJuYW1lIikpPT09dGhp
+cy5hLmEpdC5nUChhKS5pKDAscykKZWxzZSB0LmdQKGEpLlIoMCxzKX0sCiRTOjN9CkwuVEQucHJvdG90
+eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIEwudDIodS5PLmEoYSksITAsbnVsbCl9LAokUzoxOX0K
+TC5BUy5wcm90b3R5cGU9ewokMTpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5QTCh1Lk8uYShhKSl9LApQ
+TDpmdW5jdGlvbihhKXt2YXIgdD0wLHM9UC5GWCh1LlApLHI9MSxxLHA9W10sbz10aGlzLG4sbSxsLGss
+agp2YXIgJGFzeW5jJCQxPVAubHooZnVuY3Rpb24oYixjKXtpZihiPT09MSl7cT1jCnQ9cn13aGlsZSh0
+cnVlKXN3aXRjaCh0KXtjYXNlIDA6cj0zCmw9dS5YCnQ9NgpyZXR1cm4gUC5qUShMLnR5KEwuUTQoIi9h
+cHBseS1oaW50IixQLkZsKGwsbCkpLG8uYS5MdCgpKSwkYXN5bmMkJDEpCmNhc2UgNjpsPW8uYgpMLkc3
+KGwuYyxudWxsLGwuYiwhMSxudWxsKQpkb2N1bWVudC5ib2R5LmNsYXNzTGlzdC5hZGQoIm5lZWRzLXJl
+cnVuIikKcj0xCnQ9NQpicmVhawpjYXNlIDM6cj0yCmo9cQpuPUguUnUoaikKbT1ILnRzKGopCkwuQzIo
+IkNvdWxkIG5vdCBhcHBseSBoaW50IixuLG0pCnQ9NQpicmVhawpjYXNlIDI6dD0xCmJyZWFrCmNhc2Ug
+NTpyZXR1cm4gUC55QyhudWxsLHMpCmNhc2UgMTpyZXR1cm4gUC5mMyhxLHMpfX0pCnJldHVybiBQLkRJ
+KCRhc3luYyQkMSxzKX0sCiRTOjE4fQpMLlhBLnByb3RvdHlwZT17CkViOmZ1bmN0aW9uKGEsYixjKXty
+ZXR1cm4hMH0sCmkwOmZ1bmN0aW9uKGEpe3JldHVybiEwfSwKJGlrRjoxfQpMLlpaLnByb3RvdHlwZT17
+Ckx0OmZ1bmN0aW9uKCl7dmFyIHQscz10aGlzLHI9UC5GbCh1LlgsdS5fKQpyLlkoMCwidHlwZSIsTC52
+eShzLmEpKQpyLlkoMCwibmFtZSIscy5iKQp0PXMuYwppZih0IT1udWxsKXIuWSgwLCJzdWJ0cmVlIixM
+LlZEKHQpKQp0PXMuZAppZih0IT1udWxsKXIuWSgwLCJwYXRoIix0KQp0PXMuZQppZih0IT1udWxsKXIu
+WSgwLCJocmVmIix0KQp0PXMuZgppZih0IT1udWxsKXIuWSgwLCJlZGl0Q291bnQiLHQpCnJldHVybiBy
+fX0KTC5POS5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiB0aGlzLmJ9fQpNLmxJLnByb3Rv
+dHlwZT17CldPOmZ1bmN0aW9uKGEsYil7dmFyIHQscz1udWxsCk0uWUYoImFic29sdXRlIixILlZNKFti
+LG51bGwsbnVsbCxudWxsLG51bGwsbnVsbCxudWxsXSx1LmkpKQp0PXRoaXMuYQp0PXQuWXIoYik+MCYm
+IXQuaEsoYikKaWYodClyZXR1cm4gYgp0PUQuUlgoKQpyZXR1cm4gdGhpcy5xNygwLHQsYixzLHMscyxz
+LHMscyl9LAp6ZjpmdW5jdGlvbihhKXt2YXIgdCxzLHI9WC5DTChhLHRoaXMuYSkKci5JVigpCnQ9ci5k
+CnM9dC5sZW5ndGgKaWYocz09PTApe3Q9ci5iCnJldHVybiB0PT1udWxsPyIuIjp0fWlmKHM9PT0xKXt0
+PXIuYgpyZXR1cm4gdD09bnVsbD8iLiI6dH1pZigwPj1zKXJldHVybiBILk9IKHQsLTEpCnQucG9wKCkK
+Qy5ObS5tdihyLmUpCnIuSVYoKQpyZXR1cm4gci53KDApfSwKcTc6ZnVuY3Rpb24oYSxiLGMsZCxlLGYs
+ZyxoLGkpe3ZhciB0PUguVk0oW2IsYyxkLGUsZixnLGgsaV0sdS5pKQpNLllGKCJqb2luIix0KQpyZXR1
+cm4gdGhpcy5JUChuZXcgSC5VNSh0LHUuZ2YuYShuZXcgTS5NaSgpKSx1LmZpKSl9LApJUDpmdW5jdGlv
+bihhKXt2YXIgdCxzLHIscSxwLG8sbixtLGwsawp1LmVTLmEoYSkKZm9yKHQ9YS4kdGkscz10LkMoImEy
+KGNYLkUpIikuYShuZXcgTS5xNygpKSxyPWEuZ2t6KGEpLHQ9bmV3IEguU08ocixzLHQuQygiU088Y1gu
+RT4iKSkscz10aGlzLmEscT0hMSxwPSExLG89IiI7dC5GKCk7KXtuPXIuZ2woKQppZihzLmhLKG4pJiZw
+KXttPVguQ0wobixzKQpsPW8uY2hhckNvZGVBdCgwKT09MD9vOm8Kbz1DLnhCLk5qKGwsMCxzLlNwKGws
+ITApKQptLmI9bwppZihzLmRzKG8pKUMuTm0uWShtLmUsMCxzLmdtSSgpKQpvPW0udygwKX1lbHNlIGlm
+KHMuWXIobik+MCl7cD0hcy5oSyhuKQpvPUguRWoobil9ZWxzZXtrPW4ubGVuZ3RoCmlmKGshPT0wKXtp
+ZigwPj1rKXJldHVybiBILk9IKG4sMCkKaz1zLlVkKG5bMF0pfWVsc2Ugaz0hMQppZighaylpZihxKW8r
+PXMuZ21JKCkKbys9bn1xPXMuZHMobil9cmV0dXJuIG8uY2hhckNvZGVBdCgwKT09MD9vOm99LApvNTpm
+dW5jdGlvbihhKXt2YXIgdAppZighdGhpcy55MyhhKSlyZXR1cm4gYQp0PVguQ0woYSx0aGlzLmEpCnQu
+clIoKQpyZXR1cm4gdC53KDApfSwKeTM6ZnVuY3Rpb24oYSl7dmFyIHQscyxyLHEscCxvLG4sbSxsLGsK
+YS50b1N0cmluZwp0PXRoaXMuYQpzPXQuWXIoYSkKaWYocyE9PTApe2lmKHQ9PT0kLktrKCkpZm9yKHI9
+MDtyPHM7KytyKWlmKEMueEIuVyhhLHIpPT09NDcpcmV0dXJuITAKcT1zCnA9NDd9ZWxzZXtxPTAKcD1u
+dWxsfWZvcihvPW5ldyBILnFqKGEpLmEsbj1vLmxlbmd0aCxyPXEsbT1udWxsO3I8bjsrK3IsbT1wLHA9
+bCl7bD1DLnhCLm0obyxyKQppZih0LnI0KGwpKXtpZih0PT09JC5LaygpJiZsPT09NDcpcmV0dXJuITAK
+aWYocCE9bnVsbCYmdC5yNChwKSlyZXR1cm4hMAppZihwPT09NDYpaz1tPT1udWxsfHxtPT09NDZ8fHQu
+cjQobSkKZWxzZSBrPSExCmlmKGspcmV0dXJuITB9fWlmKHA9PW51bGwpcmV0dXJuITAKaWYodC5yNChw
+KSlyZXR1cm4hMAppZihwPT09NDYpdD1tPT1udWxsfHx0LnI0KG0pfHxtPT09NDYKZWxzZSB0PSExCmlm
+KHQpcmV0dXJuITAKcmV0dXJuITF9LApIUDpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHAsbyxuLG09
+dGhpcyxsPSdVbmFibGUgdG8gZmluZCBhIHBhdGggdG8gIicKYj1tLldPKDAsYikKdD1tLmEKaWYodC5Z
+cihiKTw9MCYmdC5ZcihhKT4wKXJldHVybiBtLm81KGEpCmlmKHQuWXIoYSk8PTB8fHQuaEsoYSkpYT1t
+LldPKDAsYSkKaWYodC5ZcihhKTw9MCYmdC5ZcihiKT4wKXRocm93IEguYihYLkk3KGwrSC5FaihhKSsn
+IiBmcm9tICInK0guRWooYikrJyIuJykpCnM9WC5DTChiLHQpCnMuclIoKQpyPVguQ0woYSx0KQpyLnJS
+KCkKcT1zLmQKcD1xLmxlbmd0aAppZihwIT09MCl7aWYoMD49cClyZXR1cm4gSC5PSChxLDApCnE9Si5S
+TShxWzBdLCIuIil9ZWxzZSBxPSExCmlmKHEpcmV0dXJuIHIudygwKQpxPXMuYgpwPXIuYgppZihxIT1w
+KXE9cT09bnVsbHx8cD09bnVsbHx8IXQuTmMocSxwKQplbHNlIHE9ITEKaWYocSlyZXR1cm4gci53KDAp
+CndoaWxlKCEwKXtxPXMuZApwPXEubGVuZ3RoCmlmKHAhPT0wKXtvPXIuZApuPW8ubGVuZ3RoCmlmKG4h
+PT0wKXtpZigwPj1wKXJldHVybiBILk9IKHEsMCkKcT1xWzBdCmlmKDA+PW4pcmV0dXJuIEguT0gobyww
+KQpvPXQuTmMocSxvWzBdKQpxPW99ZWxzZSBxPSExfWVsc2UgcT0hMQppZighcSlicmVhawpDLk5tLlc0
+KHMuZCwwKQpDLk5tLlc0KHMuZSwxKQpDLk5tLlc0KHIuZCwwKQpDLk5tLlc0KHIuZSwxKX1xPXMuZApw
+PXEubGVuZ3RoCmlmKHAhPT0wKXtpZigwPj1wKXJldHVybiBILk9IKHEsMCkKcT1KLlJNKHFbMF0sIi4u
+Iil9ZWxzZSBxPSExCmlmKHEpdGhyb3cgSC5iKFguSTcobCtILkVqKGEpKyciIGZyb20gIicrSC5Faihi
+KSsnIi4nKSkKcT11LlgKQy5ObS5VRyhyLmQsMCxQLk84KHMuZC5sZW5ndGgsIi4uIiwhMSxxKSkKQy5O
+bS5ZKHIuZSwwLCIiKQpDLk5tLlVHKHIuZSwxLFAuTzgocy5kLmxlbmd0aCx0LmdtSSgpLCExLHEpKQp0
+PXIuZApxPXQubGVuZ3RoCmlmKHE9PT0wKXJldHVybiIuIgppZihxPjEmJkouUk0oQy5ObS5ncloodCks
+Ii4iKSl7dD1yLmQKaWYoMD49dC5sZW5ndGgpcmV0dXJuIEguT0godCwtMSkKdC5wb3AoKQp0PXIuZQpD
+Lk5tLm12KHQpCkMuTm0ubXYodCkKQy5ObS5pKHQsIiIpfXIuYj0iIgpyLklWKCkKcmV0dXJuIHIudygw
+KX19Ck0uTWkucHJvdG90eXBlPXsKJDE6ZnVuY3Rpb24oYSl7cmV0dXJuIEguaChhKSE9bnVsbH0sCiRT
+OjIwfQpNLnE3LnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe3JldHVybiBILmgoYSkhPT0iIn0sCiRT
+OjIwfQpNLk5vLnByb3RvdHlwZT17CiQxOmZ1bmN0aW9uKGEpe0guaChhKQpyZXR1cm4gYT09bnVsbD8i
+bnVsbCI6JyInK2ErJyInfSwKJFM6NDl9CkIuZnYucHJvdG90eXBlPXsKeFo6ZnVuY3Rpb24oYSl7dmFy
+IHQscz10aGlzLllyKGEpCmlmKHM+MClyZXR1cm4gSi5sZChhLDAscykKaWYodGhpcy5oSyhhKSl7aWYo
+MD49YS5sZW5ndGgpcmV0dXJuIEguT0goYSwwKQp0PWFbMF19ZWxzZSB0PW51bGwKcmV0dXJuIHR9LApO
+YzpmdW5jdGlvbihhLGIpe3JldHVybiBhPT1ifX0KWC5XRC5wcm90b3R5cGU9ewpJVjpmdW5jdGlvbigp
+e3ZhciB0LHMscj10aGlzCndoaWxlKCEwKXt0PXIuZAppZighKHQubGVuZ3RoIT09MCYmSi5STShDLk5t
+LmdyWih0KSwiIikpKWJyZWFrCnQ9ci5kCmlmKDA+PXQubGVuZ3RoKXJldHVybiBILk9IKHQsLTEpCnQu
+cG9wKCkKQy5ObS5tdihyLmUpfXQ9ci5lCnM9dC5sZW5ndGgKaWYocyE9PTApQy5ObS5ZKHQscy0xLCIi
+KX0sCnJSOmZ1bmN0aW9uKCl7dmFyIHQscyxyLHEscCxvLG49dGhpcyxtPUguVk0oW10sdS5pKQpmb3Io
+dD1uLmQscz10Lmxlbmd0aCxyPTAscT0wO3E8dC5sZW5ndGg7dC5sZW5ndGg9PT1zfHwoMCxILmxrKSh0
+KSwrK3Epe3A9dFtxXQpvPUouaWEocCkKaWYoIShvLkROKHAsIi4iKXx8by5ETihwLCIiKSkpaWYoby5E
+TihwLCIuLiIpKXtvPW0ubGVuZ3RoCmlmKG8hPT0wKXtpZigwPj1vKXJldHVybiBILk9IKG0sLTEpCm0u
+cG9wKCl9ZWxzZSArK3J9ZWxzZSBDLk5tLmkobSxwKX1pZihuLmI9PW51bGwpQy5ObS5VRyhtLDAsUC5P
+OChyLCIuLiIsITEsdS5YKSkKaWYobS5sZW5ndGg9PT0wJiZuLmI9PW51bGwpQy5ObS5pKG0sIi4iKQpu
+LnNuSihtKQp0PW4uYQpuLnNQaChQLk84KG0ubGVuZ3RoKzEsdC5nbUkoKSwhMCx1LlgpKQpzPW4uYgpp
+ZihzPT1udWxsfHxtLmxlbmd0aD09PTB8fCF0LmRzKHMpKUMuTm0uWShuLmUsMCwiIikKcz1uLmIKaWYo
+cyE9bnVsbCYmdD09PSQuS2soKSl7cy50b1N0cmluZwpuLmI9SC55cyhzLCIvIiwiXFwiKX1uLklWKCl9
+LAp3OmZ1bmN0aW9uKGEpe3ZhciB0LHMscj10aGlzLHE9ci5iCnE9cSE9bnVsbD9xOiIiCmZvcih0PTA7
+dDxyLmQubGVuZ3RoOysrdCl7cz1yLmUKaWYodD49cy5sZW5ndGgpcmV0dXJuIEguT0gocyx0KQpzPXEr
+SC5FaihzW3RdKQpxPXIuZAppZih0Pj1xLmxlbmd0aClyZXR1cm4gSC5PSChxLHQpCnE9cytILkVqKHFb
+dF0pfXErPUguRWooQy5ObS5nclooci5lKSkKcmV0dXJuIHEuY2hhckNvZGVBdCgwKT09MD9xOnF9LApz
+bko6ZnVuY3Rpb24oYSl7dGhpcy5kPXUuZUcuYShhKX0sCnNQaDpmdW5jdGlvbihhKXt0aGlzLmU9dS5l
+Ry5hKGEpfX0KWC5kdi5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiJQYXRoRXhjZXB0aW9u
+OiAiK3RoaXMuYX0sCiRpUno6MX0KTy56TC5wcm90b3R5cGU9ewp3OmZ1bmN0aW9uKGEpe3JldHVybiB0
+aGlzLmdvYyh0aGlzKX19CkUuT0YucHJvdG90eXBlPXsKVWQ6ZnVuY3Rpb24oYSl7cmV0dXJuIEMueEIu
+dGcoYSwiLyIpfSwKcjQ6ZnVuY3Rpb24oYSl7cmV0dXJuIGE9PT00N30sCmRzOmZ1bmN0aW9uKGEpe3Zh
+ciB0PWEubGVuZ3RoCnJldHVybiB0IT09MCYmQy54Qi5tKGEsdC0xKSE9PTQ3fSwKU3A6ZnVuY3Rpb24o
+YSxiKXtpZihhLmxlbmd0aCE9PTAmJkMueEIuVyhhLDApPT09NDcpcmV0dXJuIDEKcmV0dXJuIDB9LApZ
+cjpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5TcChhLCExKX0sCmhLOmZ1bmN0aW9uKGEpe3JldHVybiEx
+fSwKZ29jOmZ1bmN0aW9uKCl7cmV0dXJuInBvc2l4In0sCmdtSTpmdW5jdGlvbigpe3JldHVybiIvIn19
+CkYucnUucHJvdG90eXBlPXsKVWQ6ZnVuY3Rpb24oYSl7cmV0dXJuIEMueEIudGcoYSwiLyIpfSwKcjQ6
+ZnVuY3Rpb24oYSl7cmV0dXJuIGE9PT00N30sCmRzOmZ1bmN0aW9uKGEpe3ZhciB0PWEubGVuZ3RoCmlm
+KHQ9PT0wKXJldHVybiExCmlmKEMueEIubShhLHQtMSkhPT00NylyZXR1cm4hMApyZXR1cm4gQy54Qi5U
+YyhhLCI6Ly8iKSYmdGhpcy5ZcihhKT09PXR9LApTcDpmdW5jdGlvbihhLGIpe3ZhciB0LHMscixxLHA9
+YS5sZW5ndGgKaWYocD09PTApcmV0dXJuIDAKaWYoQy54Qi5XKGEsMCk9PT00NylyZXR1cm4gMQpmb3Io
+dD0wO3Q8cDsrK3Qpe3M9Qy54Qi5XKGEsdCkKaWYocz09PTQ3KXJldHVybiAwCmlmKHM9PT01OCl7aWYo
+dD09PTApcmV0dXJuIDAKcj1DLnhCLlhVKGEsIi8iLEMueEIuUWkoYSwiLy8iLHQrMSk/dCszOnQpCmlm
+KHI8PTApcmV0dXJuIHAKaWYoIWJ8fHA8ciszKXJldHVybiByCmlmKCFDLnhCLm4oYSwiZmlsZTovLyIp
+KXJldHVybiByCmlmKCFCLll1KGEscisxKSlyZXR1cm4gcgpxPXIrMwpyZXR1cm4gcD09PXE/cTpyKzR9
+fXJldHVybiAwfSwKWXI6ZnVuY3Rpb24oYSl7cmV0dXJuIHRoaXMuU3AoYSwhMSl9LApoSzpmdW5jdGlv
+bihhKXtyZXR1cm4gYS5sZW5ndGghPT0wJiZDLnhCLlcoYSwwKT09PTQ3fSwKZ29jOmZ1bmN0aW9uKCl7
+cmV0dXJuInVybCJ9LApnbUk6ZnVuY3Rpb24oKXtyZXR1cm4iLyJ9fQpMLklWLnByb3RvdHlwZT17ClVk
+OmZ1bmN0aW9uKGEpe3JldHVybiBDLnhCLnRnKGEsIi8iKX0sCnI0OmZ1bmN0aW9uKGEpe3JldHVybiBh
+PT09NDd8fGE9PT05Mn0sCmRzOmZ1bmN0aW9uKGEpe3ZhciB0PWEubGVuZ3RoCmlmKHQ9PT0wKXJldHVy
+biExCnQ9Qy54Qi5tKGEsdC0xKQpyZXR1cm4hKHQ9PT00N3x8dD09PTkyKX0sClNwOmZ1bmN0aW9uKGEs
+Yil7dmFyIHQscyxyPWEubGVuZ3RoCmlmKHI9PT0wKXJldHVybiAwCnQ9Qy54Qi5XKGEsMCkKaWYodD09
+PTQ3KXJldHVybiAxCmlmKHQ9PT05Mil7aWYocjwyfHxDLnhCLlcoYSwxKSE9PTkyKXJldHVybiAxCnM9
+Qy54Qi5YVShhLCJcXCIsMikKaWYocz4wKXtzPUMueEIuWFUoYSwiXFwiLHMrMSkKaWYocz4wKXJldHVy
+biBzfXJldHVybiByfWlmKHI8MylyZXR1cm4gMAppZighQi5PUyh0KSlyZXR1cm4gMAppZihDLnhCLlco
+YSwxKSE9PTU4KXJldHVybiAwCnI9Qy54Qi5XKGEsMikKaWYoIShyPT09NDd8fHI9PT05MikpcmV0dXJu
+IDAKcmV0dXJuIDN9LApZcjpmdW5jdGlvbihhKXtyZXR1cm4gdGhpcy5TcChhLCExKX0sCmhLOmZ1bmN0
+aW9uKGEpe3JldHVybiB0aGlzLllyKGEpPT09MX0sCk90OmZ1bmN0aW9uKGEsYil7dmFyIHQKaWYoYT09
+PWIpcmV0dXJuITAKaWYoYT09PTQ3KXJldHVybiBiPT09OTIKaWYoYT09PTkyKXJldHVybiBiPT09NDcK
+aWYoKGFeYikhPT0zMilyZXR1cm4hMQp0PWF8MzIKcmV0dXJuIHQ+PTk3JiZ0PD0xMjJ9LApOYzpmdW5j
+dGlvbihhLGIpe3ZhciB0LHMscgppZihhPT1iKXJldHVybiEwCnQ9YS5sZW5ndGgKaWYodCE9PWIubGVu
+Z3RoKXJldHVybiExCmZvcihzPUouclkoYikscj0wO3I8dDsrK3IpaWYoIXRoaXMuT3QoQy54Qi5XKGEs
+cikscy5XKGIscikpKXJldHVybiExCnJldHVybiEwfSwKZ29jOmZ1bmN0aW9uKCl7cmV0dXJuIndpbmRv
+d3MifSwKZ21JOmZ1bmN0aW9uKCl7cmV0dXJuIlxcIn19OyhmdW5jdGlvbiBhbGlhc2VzKCl7dmFyIHQ9
+Si52Qi5wcm90b3R5cGUKdC5VPXQudwp0LlNqPXQuZTcKdD1KLk1GLnByb3RvdHlwZQp0LnQ9dC53CnQ9
+UC5jWC5wcm90b3R5cGUKdC5HRz10LmV2CnQ9UC5NaC5wcm90b3R5cGUKdC54Yj10LncKdD1XLmN2LnBy
+b3RvdHlwZQp0LkRXPXQucjYKdD1XLm02LnByb3RvdHlwZQp0LmpGPXQuRWIKdD1QLkU0LnByb3RvdHlw
+ZQp0LlVyPXQucQp0LmU0PXQuWX0pKCk7KGZ1bmN0aW9uIGluc3RhbGxUZWFyT2Zmcygpe3ZhciB0PWh1
+bmtIZWxwZXJzLl9zdGF0aWNfMSxzPWh1bmtIZWxwZXJzLl9zdGF0aWNfMCxyPWh1bmtIZWxwZXJzLmlu
+c3RhbGxJbnN0YW5jZVRlYXJPZmYscT1odW5rSGVscGVycy5pbnN0YWxsU3RhdGljVGVhck9mZixwPWh1
+bmtIZWxwZXJzLl9pbnN0YW5jZV8xdQp0KFAsIkVYIiwiWlYiLDcpCnQoUCwieXQiLCJvQSIsNykKdChQ
+LCJxVyIsIkJ6Iiw3KQpzKFAsIlY5IiwiZU4iLDEpCnIoUC5QZi5wcm90b3R5cGUsImdZSiIsMCwxLG51
+bGwsWyIkMiIsIiQxIl0sWyJ3MCIsInBtIl0sMjksMCkKdChQLCJDeSIsIk5DIiw0KQp0KFAsIlBIIiwi
+TXQiLDUpCnEoVywicFMiLDQsbnVsbCxbIiQ0Il0sWyJxRCJdLDgsMCkKcShXLCJWNCIsNCxudWxsLFsi
+JDQiXSxbIlFXIl0sOCwwKQpwKFAuQXMucHJvdG90eXBlLCJndU0iLCJUIiw1KQp0KFAsImlHIiwid1ki
+LDUyKQp0KFAsIncwIiwiZFUiLDM1KQp0KEwsImlTIiwiaTYiLDE5KX0pKCk7KGZ1bmN0aW9uIGluaGVy
+aXRhbmNlKCl7dmFyIHQ9aHVua0hlbHBlcnMubWl4aW4scz1odW5rSGVscGVycy5pbmhlcml0LHI9aHVu
+a0hlbHBlcnMuaW5oZXJpdE1hbnkKcyhQLk1oLG51bGwpCnIoUC5NaCxbSC5GSyxKLnZCLEoubTEsUC5Y
+UyxQLm5ZLFAuY1gsSC5hNyxQLkFuLEguU1UsSC5SZSxILnd2LFAuUG4sSC5XVSxILkxJLEgudixILmY5
+LEgudGUsSC5icSxILlhPLEgua3IsUC5ZayxILmRiLEguTjYsSC5WUixILkVLLEguUGIsSC50USxILlNk
+LEguSmMsSC5HLFAuVzMsUC5paCxQLkZ5LFAuR1YsUC5iOCxQLlBmLFAuRmUsUC52cyxQLk9NLFAucWgs
+UC5NTyxQLmtULFAueEksUC5DdyxQLm0wLFAuWHYsUC5ibixQLmxtLFAubEQsUC5LUCxQLk1hLFAuV1ks
+UC5VayxQLlNoLFAuUncsUC5ieixQLmEyLFAuaVAsUC5sZixQLms1LFAuS1ksUC5DRCxQLmFFLFAuRUgs
+UC56TSxQLlowLFAuTjMsUC5jOCxQLk9kLFAuaWIsUC5HeixQLlpkLFAucVUsUC5SbixQLkdELFAuRG4s
+UC5QRSxQLlVmLFcuaWQsVy5GayxXLkpRLFcuR20sVy52RCxXLm02LFcuT3csVy5XOSxXLmRXLFcuRmIs
+Vy5rRixXLm1rLFcuS28sUC5pSixQLkU0LFAubjYsTS5INyxVLkxMLFUuZDIsVS5TZSxVLk1sLFUueUQs
+VS53YixCLmo4LEIucXAsVC5tUSxMLlhBLEwuWlosTC5POSxNLmxJLE8uekwsWC5XRCxYLmR2XSkKcihK
+LnZCLFtKLnlFLEoud2UsSi5NRixKLmpkLEoucUksSi5EcixILkVULFcuRDAsVy5BeixXLkxlLFcuTmgs
+Vy5hZSxXLklCLFcubjcsVy5lYSxXLmJyLFcuU2csVy51OCxXLks3LFcuWFcsUC5oRl0pCnIoSi5NRixb
+Si5pQyxKLmtkLEouYzVdKQpzKEouUG8sSi5qZCkKcihKLnFJLFtKLmJVLEouVkFdKQpyKFAuWFMsW0gu
+bmQsSC5XMCxILmF6LEgudlYsSC5FcSxQLkM2LEgudTksUC5VZCxQLm4sUC51LFAubXAsUC51YixQLmRz
+LFAubGosUC5VVixQLmNdKQpzKFAudXksUC5uWSkKcihQLnV5LFtILncyLFcud3osVy5lN10pCnMoSC5x
+aixILncyKQpyKFAuY1gsW0guYlEsSC5pMSxILlU1LEguWFIsUC5tVyxILnVuXSkKcihILmJRLFtILmFM
+LEguaTUsUC54dV0pCnIoSC5hTCxbSC5uSCxILmxKLFAuaThdKQpzKEgueHksSC5pMSkKcihQLkFuLFtI
+Lk1ILEguU09dKQpzKFAuUlUsUC5QbikKcyhQLkdqLFAuUlUpCnMoSC5QRCxQLkdqKQpzKEguTFAsSC5X
+VSkKcihILnYsW0guQ2osSC5sYyxILmRDLEgud04sSC5WWCxQLnRoLFAuaGEsUC5WcyxQLkZ0LFAueUgs
+UC5XTSxQLlNYLFAuR3MsUC5kYSxQLm9RLFAucFYsUC5VNyxQLnZyLFAucnQsUC5LRixQLlpMLFAuUlQs
+UC5qWixQLnJxLFAuUlcsUC5CNSxQLnVPLFAucEssUC5oaixQLlZwLFAuT1IsUC5yYSxQLnlRLFAucGcs
+UC5jMixQLnRpLFAuV0YsUC5uMSxQLmNTLFAuVkMsUC5KVCxQLlJaLFAuTUUsUC55NSxQLnEzLFAueUks
+UC5jNixQLnFkLFcuQ3YsVy5LUyxXLkEzLFcudk4sVy5VdixXLkVnLFcuRW8sVy5XayxXLklBLFcuZm0s
+UC5qZyxQLlRhLFAuR0UsUC5ONyxQLnVRLFAuUEMsUC5tdCxQLk56LFAuUVMsUC5ucCxVLk1ELFUuYU4s
+VS5iMCxMLmUsTC5WVyxMLm9aLEwuanIsTC5xbCxMLkhpLEwuQlQsTC5QWSxMLkwsTC5XeCxMLkFPLEwu
+ZE4sTC5IbyxMLnh6LEwuSUMsTC5mQyxMLm5ULEwuTlksTC5lWCxMLkVFLEwuUUwsTC5WUyxMLlRELEwu
+QVMsTS5NaSxNLnE3LE0uTm9dKQpyKEgubGMsW0guengsSC5yVF0pCnMoSC5rWSxQLkM2KQpzKFAuaWws
+UC5ZaykKcihQLmlsLFtILk41LFAudXcsVy5jZixXLlN5XSkKcihQLm1XLFtILktXLFAucTRdKQpzKEgu
+TFosSC5FVCkKcihILkxaLFtILlJHLEguV0JdKQpzKEguVlAsSC5SRykKcyhILkRnLEguVlApCnMoSC5a
+RyxILldCKQpzKEguUGcsSC5aRykKcihILlBnLFtILnhqLEguZEUsSC5aQSxILmRULEguUHEsSC5lRSxI
+LlY2XSkKcyhILmlNLEgudTkpCnMoUC5aZixQLlBmKQpzKFAuSmksUC5tMCkKcyhQLmI2LFAuWHYpCnMo
+UC5WaixQLldZKQpyKFAuVWssW1AuQ1YsUC5aaSxQLmJ5XSkKcyhQLndJLFAua1QpCnIoUC53SSxbUC5V
+OCxQLm9qLFAuTXgsUC5FMyxQLkdZXSkKcyhQLks4LFAuVWQpCnMoUC50dSxQLlNoKQpzKFAudTUsUC5a
+aSkKcihQLmxmLFtQLkNQLFAuSWZdKQpyKFAudSxbUC5iSixQLmVZXSkKcyhQLnFlLFAuRG4pCnIoVy5E
+MCxbVy51SCxXLndhLFcuSzUsVy5DbV0pCnIoVy51SCxbVy5jdixXLm54LFcuUUYsVy5DUV0pCnIoVy5j
+dixbVy5xRSxQLmQ1XSkKcihXLnFFLFtXLkdoLFcuZlksVy5uQixXLlFQLFcuaDQsVy5TTixXLmxwLFcu
+VGIsVy5JdixXLldQLFcueVldKQpzKFcub0osVy5MZSkKcyhXLmhILFcuQXopCnMoVy5WYixXLlFGKQpz
+KFcuZkosVy53YSkKcihXLmVhLFtXLnc2LFcuZXddKQpzKFcuQWosVy53NikKcyhXLnJCLFcuSzcpCnMo
+Vy5CSCxXLnJCKQpzKFcudzQsVy5JQikKcyhXLm9hLFcuWFcpCnMoVy5yaCxXLm9hKQpzKFcuaTcsVy5j
+ZikKcyhQLkFzLFAuVmopCnIoUC5BcyxbVy5JNCxQLktlXSkKcyhXLlJPLFAucWgpCnMoVy5ldSxXLlJP
+KQpzKFcueEMsUC5NTykKcyhXLmN0LFcubTYpCnMoUC5CZixQLmlKKQpyKFAuRTQsW1AucjcsUC5jb10p
+CnMoUC5UeixQLmNvKQpzKFAuYkIsUC5kNSkKcyhCLmZ2LE8uekwpCnIoQi5mdixbRS5PRixGLnJ1LEwu
+SVZdKQp0KEgudzIsSC5SZSkKdChILlJHLFAubEQpCnQoSC5WUCxILlNVKQp0KEguV0IsUC5sRCkKdChI
+LlpHLEguU1UpCnQoUC5uWSxQLmxEKQp0KFAuV1ksUC5NYSkKdChQLlJVLFAuS1ApCnQoVy5MZSxXLmlk
+KQp0KFcuSzcsUC5sRCkKdChXLnJCLFcuR20pCnQoVy5YVyxQLmxEKQp0KFcub2EsVy5HbSkKdChQLmNv
+LFAubEQpfSkoKQp2YXIgdj17dHlwZVVuaXZlcnNlOntlQzpuZXcgTWFwKCksdFI6e30sZVQ6e30sdFBW
+Ont9LHNFQTpbXX0sbWFuZ2xlZEdsb2JhbE5hbWVzOntJZjoiaW50IixDUDoiZG91YmxlIixsZjoibnVt
+IixxVToiU3RyaW5nIixhMjoiYm9vbCIsYzg6Ik51bGwiLHpNOiJMaXN0In0sbWFuZ2xlZE5hbWVzOnt9
+LGdldFR5cGVGcm9tTmFtZTpnZXRHbG9iYWxGcm9tTmFtZSxtZXRhZGF0YTpbXSx0eXBlczpbImM4KCki
+LCJ+KCkiLCJjOChBaiopIiwiYzgoY3YqKSIsIkAoQCkiLCJxVShxVSkiLCJjOChALEApIiwifih+KCkp
+IiwiYTIoY3YscVUscVUsSlEpIiwiYzgoQCkiLCJjOChxVSxxVSkiLCJjOChNaD8sTWg/KSIsIkAoKSIs
+ImM4KHFVLEApIiwiYTIoa0YpIiwiYTIocVUpIiwifih4dTxxVT4pIiwiYzgoZWEqKSIsImI4PGM4Pioo
+QWoqKSIsIn4oQWoqKSIsImEyKihxVSopIiwiWjA8cVUscVU+KFowPHFVLHFVPixxVSkiLCJ+KHFVLHFV
+PykiLCJuNihJZikiLCJuNihALEApIiwiYTIodUgpIiwiYzgoQCxHeikiLCJAKGVhKSIsImM4KElmLEAp
+IiwifihNaFtHej9dKSIsIn4odUgsdUg/KSIsImM4KE1oLEd6KSIsImEyKHh1PHFVPikiLCJ2czxAPihA
+KSIsInI3KEApIiwiTWg/KEApIiwiRTQoQCkiLCJhMiooSDcqKSIsIkxMKihAKSIsIlowPHFVKixNaCo+
+KihMTCopIiwiQChxVSkiLCJAKEAscVUpIiwiYzgoWjA8cVUqLE1oKj4qKSIsImM4KEdELEApIiwicVUq
+KEFqKikiLCJ+KEApIiwiYzgoZXcqKSIsIn4ocVUsSWYpIiwifihxVVtAXSkiLCJxVSoocVUqKSIsIklm
+KElmLElmKSIsImM4KH4oKSkiLCJNaD8oTWg/KSIsIlR6PEA+KEApIl0saW50ZXJjZXB0b3JzQnlUYWc6
+bnVsbCxsZWFmVGFnczpudWxsLGFycmF5UnRpOnR5cGVvZiBTeW1ib2w9PSJmdW5jdGlvbiImJnR5cGVv
+ZiBTeW1ib2woKT09InN5bWJvbCI/U3ltYm9sKCIkdGkiKToiJHRpIn0KSC54Yih2LnR5cGVVbml2ZXJz
+ZSxKU09OLnBhcnNlKCd7ImM1IjoiTUYiLCJpQyI6Ik1GIiwia2QiOiJNRiIsInJ4IjoiZWEiLCJlNSI6
+ImVhIiwiWTAiOiJkNSIsInRwIjoiZDUiLCJHOCI6ImV3IiwiTXIiOiJxRSIsImVMIjoicUUiLCJJMCI6
+InVIIiwiaHMiOiJ1SCIsIlhnIjoiUUYiLCJuciI6IkFqIiwieTQiOiJ3NiIsImFQIjoiQ20iLCJ4YyI6
+Im54Iiwia0oiOiJueCIsInpVIjoiRGciLCJkZiI6IkVUIiwieUUiOnsiYTIiOltdfSwid2UiOnsiYzgi
+OltdfSwiTUYiOnsidm0iOltdLCJFSCI6W119LCJqZCI6eyJ6TSI6WyIxIl0sImJRIjpbIjEiXSwiY1gi
+OlsiMSJdfSwiUG8iOnsiamQiOlsiMSJdLCJ6TSI6WyIxIl0sImJRIjpbIjEiXSwiY1giOlsiMSJdfSwi
+bTEiOnsiQW4iOlsiMSJdfSwicUkiOnsiQ1AiOltdLCJsZiI6W119LCJiVSI6eyJDUCI6W10sIklmIjpb
+XSwibGYiOltdfSwiVkEiOnsiQ1AiOltdLCJsZiI6W119LCJEciI6eyJxVSI6W10sInZYIjpbXX0sIm5k
+Ijp7IlhTIjpbXX0sInFqIjp7ImxEIjpbIklmIl0sIlJlIjpbIklmIl0sInpNIjpbIklmIl0sImJRIjpb
+IklmIl0sImNYIjpbIklmIl0sImxELkUiOiJJZiIsIlJlLkUiOiJJZiJ9LCJiUSI6eyJjWCI6WyIxIl19
+LCJhTCI6eyJiUSI6WyIxIl0sImNYIjpbIjEiXX0sIm5IIjp7ImFMIjpbIjEiXSwiYlEiOlsiMSJdLCJj
+WCI6WyIxIl0sImFMLkUiOiIxIiwiY1guRSI6IjEifSwiYTciOnsiQW4iOlsiMSJdfSwiaTEiOnsiY1gi
+OlsiMiJdLCJjWC5FIjoiMiJ9LCJ4eSI6eyJpMSI6WyIxIiwiMiJdLCJiUSI6WyIyIl0sImNYIjpbIjIi
+XSwiY1guRSI6IjIifSwiTUgiOnsiQW4iOlsiMiJdfSwibEoiOnsiYUwiOlsiMiJdLCJiUSI6WyIyIl0s
+ImNYIjpbIjIiXSwiYUwuRSI6IjIiLCJjWC5FIjoiMiJ9LCJVNSI6eyJjWCI6WyIxIl0sImNYLkUiOiIx
+In0sIlNPIjp7IkFuIjpbIjEiXX0sIncyIjp7ImxEIjpbIjEiXSwiUmUiOlsiMSJdLCJ6TSI6WyIxIl0s
+ImJRIjpbIjEiXSwiY1giOlsiMSJdfSwid3YiOnsiR0QiOltdfSwiUEQiOnsiR2oiOlsiMSIsIjIiXSwi
+UlUiOlsiMSIsIjIiXSwiUG4iOlsiMSIsIjIiXSwiS1AiOlsiMSIsIjIiXSwiWjAiOlsiMSIsIjIiXX0s
+IldVIjp7IlowIjpbIjEiLCIyIl19LCJMUCI6eyJXVSI6WyIxIiwiMiJdLCJaMCI6WyIxIiwiMiJdfSwi
+WFIiOnsiY1giOlsiMSJdLCJjWC5FIjoiMSJ9LCJMSSI6eyJ2USI6W119LCJXMCI6eyJYUyI6W119LCJh
+eiI6eyJYUyI6W119LCJ2ViI6eyJYUyI6W119LCJ0ZSI6eyJSeiI6W119LCJYTyI6eyJHeiI6W119LCJ2
+Ijp7IkVIIjpbXX0sImxjIjp7IkVIIjpbXX0sInp4Ijp7IkVIIjpbXX0sInJUIjp7IkVIIjpbXX0sIkVx
+Ijp7IlhTIjpbXX0sImtZIjp7IlhTIjpbXX0sIk41Ijp7IllrIjpbIjEiLCIyIl0sIkZvIjpbIjEiLCIy
+Il0sIlowIjpbIjEiLCIyIl0sIllrLksiOiIxIiwiWWsuViI6IjIifSwiaTUiOnsiYlEiOlsiMSJdLCJj
+WCI6WyIxIl0sImNYLkUiOiIxIn0sIk42Ijp7IkFuIjpbIjEiXX0sIlZSIjp7IndMIjpbXSwidlgiOltd
+fSwiRUsiOnsiaWIiOltdLCJPZCI6W119LCJLVyI6eyJjWCI6WyJpYiJdLCJjWC5FIjoiaWIifSwiUGIi
+OnsiQW4iOlsiaWIiXX0sInRRIjp7Ik9kIjpbXX0sInVuIjp7ImNYIjpbIk9kIl0sImNYLkUiOiJPZCJ9
+LCJTZCI6eyJBbiI6WyJPZCJdfSwiRVQiOnsiZXEiOltdfSwiTFoiOnsiWGoiOlsiMSJdLCJFVCI6W10s
+ImVxIjpbXX0sIkRnIjp7ImxEIjpbIkNQIl0sIlhqIjpbIkNQIl0sInpNIjpbIkNQIl0sIkVUIjpbXSwi
+YlEiOlsiQ1AiXSwiZXEiOltdLCJjWCI6WyJDUCJdLCJTVSI6WyJDUCJdLCJsRC5FIjoiQ1AifSwiUGci
+OnsibEQiOlsiSWYiXSwiWGoiOlsiSWYiXSwiek0iOlsiSWYiXSwiRVQiOltdLCJiUSI6WyJJZiJdLCJl
+cSI6W10sImNYIjpbIklmIl0sIlNVIjpbIklmIl19LCJ4aiI6eyJsRCI6WyJJZiJdLCJYaiI6WyJJZiJd
+LCJ6TSI6WyJJZiJdLCJFVCI6W10sImJRIjpbIklmIl0sImVxIjpbXSwiY1giOlsiSWYiXSwiU1UiOlsi
+SWYiXSwibEQuRSI6IklmIn0sImRFIjp7ImxEIjpbIklmIl0sIlhqIjpbIklmIl0sInpNIjpbIklmIl0s
+IkVUIjpbXSwiYlEiOlsiSWYiXSwiZXEiOltdLCJjWCI6WyJJZiJdLCJTVSI6WyJJZiJdLCJsRC5FIjoi
+SWYifSwiWkEiOnsibEQiOlsiSWYiXSwiWGoiOlsiSWYiXSwiek0iOlsiSWYiXSwiRVQiOltdLCJiUSI6
+WyJJZiJdLCJlcSI6W10sImNYIjpbIklmIl0sIlNVIjpbIklmIl0sImxELkUiOiJJZiJ9LCJkVCI6eyJs
+RCI6WyJJZiJdLCJYaiI6WyJJZiJdLCJ6TSI6WyJJZiJdLCJFVCI6W10sImJRIjpbIklmIl0sImVxIjpb
+XSwiY1giOlsiSWYiXSwiU1UiOlsiSWYiXSwibEQuRSI6IklmIn0sIlBxIjp7ImxEIjpbIklmIl0sIlhq
+IjpbIklmIl0sInpNIjpbIklmIl0sIkVUIjpbXSwiYlEiOlsiSWYiXSwiZXEiOltdLCJjWCI6WyJJZiJd
+LCJTVSI6WyJJZiJdLCJsRC5FIjoiSWYifSwiZUUiOnsibEQiOlsiSWYiXSwiWGoiOlsiSWYiXSwiek0i
+OlsiSWYiXSwiRVQiOltdLCJiUSI6WyJJZiJdLCJlcSI6W10sImNYIjpbIklmIl0sIlNVIjpbIklmIl0s
+ImxELkUiOiJJZiJ9LCJWNiI6eyJsRCI6WyJJZiJdLCJuNiI6W10sIlhqIjpbIklmIl0sInpNIjpbIklm
+Il0sIkVUIjpbXSwiYlEiOlsiSWYiXSwiZXEiOltdLCJjWCI6WyJJZiJdLCJTVSI6WyJJZiJdLCJsRC5F
+IjoiSWYifSwidTkiOnsiWFMiOltdfSwiaU0iOnsiWFMiOltdfSwiR1YiOnsiQW4iOlsiMSJdfSwicTQi
+OnsiY1giOlsiMSJdLCJjWC5FIjoiMSJ9LCJaZiI6eyJQZiI6WyIxIl19LCJ2cyI6eyJiOCI6WyIxIl19
+LCJDdyI6eyJYUyI6W119LCJtMCI6eyJKQiI6W119LCJKaSI6eyJtMCI6W10sIkpCIjpbXX0sImI2Ijp7
+Ilh2IjpbIjEiXSwieHUiOlsiMSJdLCJiUSI6WyIxIl0sImNYIjpbIjEiXX0sImxtIjp7IkFuIjpbIjEi
+XX0sIm1XIjp7ImNYIjpbIjEiXX0sInV5Ijp7ImxEIjpbIjEiXSwiek0iOlsiMSJdLCJiUSI6WyIxIl0s
+ImNYIjpbIjEiXX0sImlsIjp7IllrIjpbIjEiLCIyIl0sIlowIjpbIjEiLCIyIl19LCJZayI6eyJaMCI6
+WyIxIiwiMiJdfSwiUG4iOnsiWjAiOlsiMSIsIjIiXX0sIkdqIjp7IlJVIjpbIjEiLCIyIl0sIlBuIjpb
+IjEiLCIyIl0sIktQIjpbIjEiLCIyIl0sIlowIjpbIjEiLCIyIl19LCJWaiI6eyJNYSI6WyIxIl0sInh1
+IjpbIjEiXSwiYlEiOlsiMSJdLCJjWCI6WyIxIl19LCJYdiI6eyJ4dSI6WyIxIl0sImJRIjpbIjEiXSwi
+Y1giOlsiMSJdfSwidXciOnsiWWsiOlsicVUiLCJAIl0sIlowIjpbInFVIiwiQCJdLCJZay5LIjoicVUi
+LCJZay5WIjoiQCJ9LCJpOCI6eyJhTCI6WyJxVSJdLCJiUSI6WyJxVSJdLCJjWCI6WyJxVSJdLCJhTC5F
+IjoicVUiLCJjWC5FIjoicVUifSwiQ1YiOnsiVWsiOlsiek08SWY+IiwicVUiXSwiVWsuUyI6InpNPElm
+PiJ9LCJVOCI6eyJ3SSI6WyJ6TTxJZj4iLCJxVSJdfSwiWmkiOnsiVWsiOlsicVUiLCJ6TTxJZj4iXX0s
+IlVkIjp7IlhTIjpbXX0sIks4Ijp7IlhTIjpbXX0sImJ5Ijp7IlVrIjpbIk1oPyIsInFVIl0sIlVrLlMi
+OiJNaD8ifSwib2oiOnsid0kiOlsiTWg/IiwicVUiXX0sIk14Ijp7IndJIjpbInFVIiwiTWg/Il19LCJ1
+NSI6eyJVayI6WyJxVSIsInpNPElmPiJdLCJVay5TIjoicVUifSwiRTMiOnsid0kiOlsicVUiLCJ6TTxJ
+Zj4iXX0sIkdZIjp7IndJIjpbInpNPElmPiIsInFVIl19LCJDUCI6eyJsZiI6W119LCJDNiI6eyJYUyI6
+W119LCJuIjp7IlhTIjpbXX0sInUiOnsiWFMiOltdfSwiYkoiOnsiWFMiOltdfSwiZVkiOnsiWFMiOltd
+fSwibXAiOnsiWFMiOltdfSwidWIiOnsiWFMiOltdfSwiZHMiOnsiWFMiOltdfSwibGoiOnsiWFMiOltd
+fSwiVVYiOnsiWFMiOltdfSwiazUiOnsiWFMiOltdfSwiS1kiOnsiWFMiOltdfSwiYyI6eyJYUyI6W119
+LCJDRCI6eyJSeiI6W119LCJhRSI6eyJSeiI6W119LCJJZiI6eyJsZiI6W119LCJ6TSI6eyJiUSI6WyIx
+Il0sImNYIjpbIjEiXX0sImliIjp7Ik9kIjpbXX0sInh1Ijp7ImJRIjpbIjEiXSwiY1giOlsiMSJdfSwi
+WmQiOnsiR3oiOltdfSwicVUiOnsidlgiOltdfSwiUm4iOnsiQkwiOltdfSwiRG4iOnsiaUQiOltdfSwi
+VWYiOnsiaUQiOltdfSwicWUiOnsiaUQiOltdfSwicUUiOnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0s
+IkdoIjp7ImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJmWSI6eyJjdiI6W10sInVIIjpbXSwiRDAiOltd
+fSwibkIiOnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sIlFQIjp7ImN2IjpbXSwidUgiOltdLCJEMCI6
+W119LCJueCI6eyJ1SCI6W10sIkQwIjpbXX0sIlFGIjp7InVIIjpbXSwiRDAiOltdfSwiSUIiOnsidG4i
+OlsibGYiXX0sInd6Ijp7ImxEIjpbIjEiXSwiek0iOlsiMSJdLCJiUSI6WyIxIl0sImNYIjpbIjEiXSwi
+bEQuRSI6IjEifSwiY3YiOnsidUgiOltdLCJEMCI6W119LCJoSCI6eyJBeiI6W119LCJoNCI6eyJjdiI6
+W10sInVIIjpbXSwiRDAiOltdfSwiVmIiOnsidUgiOltdLCJEMCI6W119LCJmSiI6eyJEMCI6W119LCJ3
+YSI6eyJEMCI6W119LCJBaiI6eyJlYSI6W119LCJlNyI6eyJsRCI6WyJ1SCJdLCJ6TSI6WyJ1SCJdLCJi
+USI6WyJ1SCJdLCJjWCI6WyJ1SCJdLCJsRC5FIjoidUgifSwidUgiOnsiRDAiOltdfSwiQkgiOnsibEQi
+OlsidUgiXSwiR20iOlsidUgiXSwiek0iOlsidUgiXSwiWGoiOlsidUgiXSwiYlEiOlsidUgiXSwiY1gi
+OlsidUgiXSwibEQuRSI6InVIIiwiR20uRSI6InVIIn0sIlNOIjp7ImN2IjpbXSwidUgiOltdLCJEMCI6
+W119LCJldyI6eyJlYSI6W119LCJscCI6eyJjdiI6W10sInVIIjpbXSwiRDAiOltdfSwiVGIiOnsiY3Yi
+OltdLCJ1SCI6W10sIkQwIjpbXX0sIkl2Ijp7ImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJXUCI6eyJj
+diI6W10sInVIIjpbXSwiRDAiOltdfSwieVkiOnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sInc2Ijp7
+ImVhIjpbXX0sIks1Ijp7InY2IjpbXSwiRDAiOltdfSwiQ20iOnsiRDAiOltdfSwiQ1EiOnsidUgiOltd
+LCJEMCI6W119LCJ3NCI6eyJ0biI6WyJsZiJdfSwicmgiOnsibEQiOlsidUgiXSwiR20iOlsidUgiXSwi
+ek0iOlsidUgiXSwiWGoiOlsidUgiXSwiYlEiOlsidUgiXSwiY1giOlsidUgiXSwibEQuRSI6InVIIiwi
+R20uRSI6InVIIn0sImNmIjp7IllrIjpbInFVIiwicVUiXSwiWjAiOlsicVUiLCJxVSJdfSwiaTciOnsi
+WWsiOlsicVUiLCJxVSJdLCJaMCI6WyJxVSIsInFVIl0sIllrLksiOiJxVSIsIllrLlYiOiJxVSJ9LCJT
+eSI6eyJZayI6WyJxVSIsInFVIl0sIlowIjpbInFVIiwicVUiXSwiWWsuSyI6InFVIiwiWWsuViI6InFV
+In0sIkk0Ijp7Ik1hIjpbInFVIl0sInh1IjpbInFVIl0sImJRIjpbInFVIl0sImNYIjpbInFVIl19LCJS
+TyI6eyJxaCI6WyIxIl19LCJldSI6eyJSTyI6WyIxIl0sInFoIjpbIjEiXX0sInhDIjp7Ik1PIjpbIjEi
+XX0sIkpRIjp7ImtGIjpbXX0sInZEIjp7ImtGIjpbXX0sIm02Ijp7ImtGIjpbXX0sImN0Ijp7ImtGIjpb
+XX0sIk93Ijp7ImtGIjpbXX0sIlc5Ijp7IkFuIjpbIjEiXX0sImRXIjp7InY2IjpbXSwiRDAiOltdfSwi
+bWsiOnsieTAiOltdfSwiS28iOnsib24iOltdfSwiQXMiOnsiTWEiOlsicVUiXSwieHUiOlsicVUiXSwi
+YlEiOlsicVUiXSwiY1giOlsicVUiXX0sInI3Ijp7IkU0IjpbXX0sIlR6Ijp7ImxEIjpbIjEiXSwiek0i
+OlsiMSJdLCJiUSI6WyIxIl0sIkU0IjpbXSwiY1giOlsiMSJdLCJsRC5FIjoiMSJ9LCJiQiI6eyJkNSI6
+W10sImN2IjpbXSwidUgiOltdLCJEMCI6W119LCJLZSI6eyJNYSI6WyJxVSJdLCJ4dSI6WyJxVSJdLCJi
+USI6WyJxVSJdLCJjWCI6WyJxVSJdfSwiZDUiOnsiY3YiOltdLCJ1SCI6W10sIkQwIjpbXX0sIm42Ijp7
+InpNIjpbIklmIl0sImJRIjpbIklmIl0sImNYIjpbIklmIl0sImVxIjpbXX0sIlhBIjp7ImtGIjpbXX0s
+ImR2Ijp7IlJ6IjpbXX0sIk9GIjp7ImZ2IjpbXX0sInJ1Ijp7ImZ2IjpbXX0sIklWIjp7ImZ2IjpbXX19
+JykpCkguRkYodi50eXBlVW5pdmVyc2UsSlNPTi5wYXJzZSgneyJiUSI6MSwidzIiOjEsIkxaIjoxLCJr
+VCI6MiwibVciOjEsInV5IjoxLCJpbCI6MiwiVmoiOjEsIm5ZIjoxLCJXWSI6MSwiY28iOjF9JykpCnZh
+ciB1PShmdW5jdGlvbiBydGlpKCl7dmFyIHQ9SC5OMApyZXR1cm57bjp0KCJDdyIpLGNSOnQoIm5CIiks
+dzp0KCJBeiIpLGs6dCgiUVAiKSxnRjp0KCJQRDxHRCxAPiIpLGd3OnQoImJRPEA+IiksaDp0KCJjdiIp
+LG06dCgiWFMiKSxCOnQoImVhIiksYVM6dCgiRDAiKSxjODp0KCJoSCIpLFk6dCgiRUgiKSxkOnQoImI4
+PEA+IiksSTp0KCJTZyIpLG86dCgidlEiKSxlaDp0KCJjWDx1SD4iKSxROnQoImNYPHFVPiIpLHA6dCgi
+Y1g8QD4iKSxyOnQoImpkPGtGPiIpLHM6dCgiamQ8cVU+IiksdTp0KCJqZDxAPiIpLGE6dCgiamQ8SWY+
+IiksZDc6dCgiamQ8U2UqPiIpLGg0OnQoImpkPGo4Kj4iKSxHOnQoImpkPFowPHFVKixNaCo+Kj4iKSxj
+UTp0KCJqZDxaWio+IiksaTp0KCJqZDxxVSo+IiksYUE6dCgiamQ8eUQqPiIpLGFKOnQoImpkPHdiKj4i
+KSxWOnQoImpkPElmKj4iKSxUOnQoIndlIiksZUg6dCgidm0iKSx2OnQoImM1IiksYVU6dCgiWGo8QD4i
+KSxhbTp0KCJUejxAPiIpLGVvOnQoIk41PEdELEA+IiksZHo6dCgiaEYiKSxiOnQoInpNPEA+IiksTDp0
+KCJ6TTxJZj4iKSxKOnQoIlowPHFVLHFVPiIpLGY6dCgiWjA8QCxAPiIpLGRvOnQoImxKPHFVLEA+Iiks
+Zmo6dCgibEo8cVUqLHFVPiIpLGRFOnQoIkVUIiksYm06dCgiVjYiKSxBOnQoInVIIiksRDp0KCJrRiIp
+LFA6dCgiYzgiKSxLOnQoIk1oIikscTp0KCJ0bjxsZj4iKSxmdjp0KCJ3TCIpLGV3OnQoImJCIiksQzp0
+KCJ4dTxxVT4iKSxsOnQoIkd6IiksTjp0KCJxVSIpLGQwOnQoInFVKHFVKikiKSxnNzp0KCJkNSIpLGZv
+OnQoIkdEIiksYVc6dCgieVkiKSx4OnQoImVxIiksZ2M6dCgibjYiKSxhazp0KCJrZCIpLEU6dCgiR2o8
+cVUscVU+IiksZEQ6dCgiaUQiKSxmaTp0KCJVNTxxVSo+IiksZzQ6dCgiSzUiKSxjaTp0KCJ2NiIpLGcy
+OnQoIkNtIiksYkM6dCgiWmY8ZkoqPiIpLGg5OnQoIkNRIiksYWM6dCgiZTciKSxqOnQoImV1PEFqKj4i
+KSxSOnQoInd6PGN2Kj4iKSxjOnQoInZzPEA+IiksZko6dCgidnM8SWY+IiksZ1Y6dCgidnM8ZkoqPiIp
+LGNyOnQoIkpRIikseTp0KCJhMiIpLGFsOnQoImEyKE1oKSIpLGdmOnQoImEyKHFVKikiKSxnUjp0KCJD
+UCIpLHo6dCgiQCIpLGZPOnQoIkAoKSIpLGJJOnQoIkAoTWgpIiksYWc6dCgiQChNaCxHeikiKSxiVTp0
+KCJAKHh1PHFVPikiKSxkTzp0KCJAKHFVKSIpLGI4OnQoIkAoQCxAKSIpLFM6dCgiSWYiKSxkZDp0KCJH
+aCoiKSxnOnQoImN2KiIpLGFMOnQoImVhKiIpLGVqOnQoIlJ6KiIpLGFYOnQoIkxMKiIpLGZFOnQoIkg3
+KiIpLFU6dCgiY1g8QD4qIiksZVM6dCgiY1g8cVUqPioiKSxkSDp0KCJFNCoiKSxmSzp0KCJ6TTxAPioi
+KSxkXzp0KCJ6TTxqOCo+KiIpLGRwOnQoInpNPFowPHFVKixNaCo+Kj4qIiksZUU6dCgiek08TWgqPioi
+KSxlRzp0KCJ6TTxxVSo+KiIpLGJaOnQoInU4KiIpLHQ6dCgiWjA8cVUqLE1oKj4qIiksTzp0KCJBaioi
+KSxhdzp0KCIwJioiKSxfOnQoIk1oKiIpLGVROnQoImV3KiIpLFg6dCgicVUqIiksY2g6dCgiRDA/Iiks
+Ykc6dCgiYjg8Yzg+PyIpLGJrOnQoInpNPHFVPj8iKSxiTTp0KCJ6TTxAPj8iKSxjWjp0KCJaMDxxVSxx
+VT4/IiksYzk6dCgiWjA8cVUsQD4/IiksVzp0KCJNaD8iKSxGOnQoIkZlPEAsQD4/IiksZTp0KCJibj8i
+KSxiNzp0KCJhMihNaCk/IiksYnc6dCgiQChlYSk/IiksZlY6dCgiTWg/KE1oPyxNaD8pPyIpLGRBOnQo
+Ik1oPyhAKT8iKSxaOnQoIn4oKT8iKSxlYjp0KCJ+KGV3Kik/IiksZGk6dCgibGYiKSxIOnQoIn4iKSxN
+OnQoIn4oKSIpLGVBOnQoIn4ocVUscVUpIiksY0E6dCgifihxVSxAKSIpfX0pKCk7KGZ1bmN0aW9uIGNv
+bnN0YW50cygpe3ZhciB0PWh1bmtIZWxwZXJzLm1ha2VDb25zdExpc3QKQy5SWT1XLlFQLnByb3RvdHlw
+ZQpDLm1IPVcuYWUucHJvdG90eXBlCkMuQlo9Vy5WYi5wcm90b3R5cGUKQy5EdD1XLmZKLnByb3RvdHlw
+ZQpDLk9rPUoudkIucHJvdG90eXBlCkMuTm09Si5qZC5wcm90b3R5cGUKQy5qbj1KLmJVLnByb3RvdHlw
+ZQpDLmpOPUoud2UucHJvdG90eXBlCkMuQ0Q9Si5xSS5wcm90b3R5cGUKQy54Qj1KLkRyLnByb3RvdHlw
+ZQpDLkRHPUouYzUucHJvdG90eXBlCkMuRXg9Vy51OC5wcm90b3R5cGUKQy50NT1XLkJILnByb3RvdHlw
+ZQpDLkx0PVcuU04ucHJvdG90eXBlCkMuWlE9Si5pQy5wcm90b3R5cGUKQy5JZT1XLlRiLnByb3RvdHlw
+ZQpDLnZCPUoua2QucHJvdG90eXBlCkMub2w9Vy5LNS5wcm90b3R5cGUKQy55OD1uZXcgUC5VOCgpCkMu
+aDk9bmV3IFAuQ1YoKQpDLk80PWZ1bmN0aW9uIGdldFRhZ0ZhbGxiYWNrKG8pIHsKICB2YXIgcyA9IE9i
+amVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChvKTsKICByZXR1cm4gcy5zdWJzdHJpbmcoOCwgcy5s
+ZW5ndGggLSAxKTsKfQpDLllxPWZ1bmN0aW9uKCkgewogIHZhciB0b1N0cmluZ0Z1bmN0aW9uID0gT2Jq
+ZWN0LnByb3RvdHlwZS50b1N0cmluZzsKICBmdW5jdGlvbiBnZXRUYWcobykgewogICAgdmFyIHMgPSB0
+b1N0cmluZ0Z1bmN0aW9uLmNhbGwobyk7CiAgICByZXR1cm4gcy5zdWJzdHJpbmcoOCwgcy5sZW5ndGgg
+LSAxKTsKICB9CiAgZnVuY3Rpb24gZ2V0VW5rbm93blRhZyhvYmplY3QsIHRhZykgewogICAgaWYgKC9e
+SFRNTFtBLVpdLipFbGVtZW50JC8udGVzdCh0YWcpKSB7CiAgICAgIHZhciBuYW1lID0gdG9TdHJpbmdG
+dW5jdGlvbi5jYWxsKG9iamVjdCk7CiAgICAgIGlmIChuYW1lID09ICJbb2JqZWN0IE9iamVjdF0iKSBy
+ZXR1cm4gbnVsbDsKICAgICAgcmV0dXJuICJIVE1MRWxlbWVudCI7CiAgICB9CiAgfQogIGZ1bmN0aW9u
+IGdldFVua25vd25UYWdHZW5lcmljQnJvd3NlcihvYmplY3QsIHRhZykgewogICAgaWYgKHNlbGYuSFRN
+TEVsZW1lbnQgJiYgb2JqZWN0IGluc3RhbmNlb2YgSFRNTEVsZW1lbnQpIHJldHVybiAiSFRNTEVsZW1l
+bnQiOwogICAgcmV0dXJuIGdldFVua25vd25UYWcob2JqZWN0LCB0YWcpOwogIH0KICBmdW5jdGlvbiBw
+cm90b3R5cGVGb3JUYWcodGFnKSB7CiAgICBpZiAodHlwZW9mIHdpbmRvdyA9PSAidW5kZWZpbmVkIikg
+cmV0dXJuIG51bGw7CiAgICBpZiAodHlwZW9mIHdpbmRvd1t0YWddID09ICJ1bmRlZmluZWQiKSByZXR1
+cm4gbnVsbDsKICAgIHZhciBjb25zdHJ1Y3RvciA9IHdpbmRvd1t0YWddOwogICAgaWYgKHR5cGVvZiBj
+b25zdHJ1Y3RvciAhPSAiZnVuY3Rpb24iKSByZXR1cm4gbnVsbDsKICAgIHJldHVybiBjb25zdHJ1Y3Rv
+ci5wcm90b3R5cGU7CiAgfQogIGZ1bmN0aW9uIGRpc2NyaW1pbmF0b3IodGFnKSB7IHJldHVybiBudWxs
+OyB9CiAgdmFyIGlzQnJvd3NlciA9IHR5cGVvZiBuYXZpZ2F0b3IgPT0gIm9iamVjdCI7CiAgcmV0dXJu
+IHsKICAgIGdldFRhZzogZ2V0VGFnLAogICAgZ2V0VW5rbm93blRhZzogaXNCcm93c2VyID8gZ2V0VW5r
+bm93blRhZ0dlbmVyaWNCcm93c2VyIDogZ2V0VW5rbm93blRhZywKICAgIHByb3RvdHlwZUZvclRhZzog
+cHJvdG90eXBlRm9yVGFnLAogICAgZGlzY3JpbWluYXRvcjogZGlzY3JpbWluYXRvciB9Owp9CkMud2I9
+ZnVuY3Rpb24oZ2V0VGFnRmFsbGJhY2spIHsKICByZXR1cm4gZnVuY3Rpb24oaG9va3MpIHsKICAgIGlm
+ICh0eXBlb2YgbmF2aWdhdG9yICE9ICJvYmplY3QiKSByZXR1cm4gaG9va3M7CiAgICB2YXIgdWEgPSBu
+YXZpZ2F0b3IudXNlckFnZW50OwogICAgaWYgKHVhLmluZGV4T2YoIkR1bXBSZW5kZXJUcmVlIikgPj0g
+MCkgcmV0dXJuIGhvb2tzOwogICAgaWYgKHVhLmluZGV4T2YoIkNocm9tZSIpID49IDApIHsKICAgICAg
+ZnVuY3Rpb24gY29uZmlybShwKSB7CiAgICAgICAgcmV0dXJuIHR5cGVvZiB3aW5kb3cgPT0gIm9iamVj
+dCIgJiYgd2luZG93W3BdICYmIHdpbmRvd1twXS5uYW1lID09IHA7CiAgICAgIH0KICAgICAgaWYgKGNv
+bmZpcm0oIldpbmRvdyIpICYmIGNvbmZpcm0oIkhUTUxFbGVtZW50IikpIHJldHVybiBob29rczsKICAg
+IH0KICAgIGhvb2tzLmdldFRhZyA9IGdldFRhZ0ZhbGxiYWNrOwogIH07Cn0KQy5LVT1mdW5jdGlvbiho
+b29rcykgewogIGlmICh0eXBlb2YgZGFydEV4cGVyaW1lbnRhbEZpeHVwR2V0VGFnICE9ICJmdW5jdGlv
+biIpIHJldHVybiBob29rczsKICBob29rcy5nZXRUYWcgPSBkYXJ0RXhwZXJpbWVudGFsRml4dXBHZXRU
+YWcoaG9va3MuZ2V0VGFnKTsKfQpDLmZRPWZ1bmN0aW9uKGhvb2tzKSB7CiAgdmFyIGdldFRhZyA9IGhv
+b2tzLmdldFRhZzsKICB2YXIgcHJvdG90eXBlRm9yVGFnID0gaG9va3MucHJvdG90eXBlRm9yVGFnOwog
+IGZ1bmN0aW9uIGdldFRhZ0ZpeGVkKG8pIHsKICAgIHZhciB0YWcgPSBnZXRUYWcobyk7CiAgICBpZiAo
+dGFnID09ICJEb2N1bWVudCIpIHsKICAgICAgaWYgKCEhby54bWxWZXJzaW9uKSByZXR1cm4gIiFEb2N1
+bWVudCI7CiAgICAgIHJldHVybiAiIUhUTUxEb2N1bWVudCI7CiAgICB9CiAgICByZXR1cm4gdGFnOwog
+IH0KICBmdW5jdGlvbiBwcm90b3R5cGVGb3JUYWdGaXhlZCh0YWcpIHsKICAgIGlmICh0YWcgPT0gIkRv
+Y3VtZW50IikgcmV0dXJuIG51bGw7CiAgICByZXR1cm4gcHJvdG90eXBlRm9yVGFnKHRhZyk7CiAgfQog
+IGhvb2tzLmdldFRhZyA9IGdldFRhZ0ZpeGVkOwogIGhvb2tzLnByb3RvdHlwZUZvclRhZyA9IHByb3Rv
+dHlwZUZvclRhZ0ZpeGVkOwp9CkMuZGs9ZnVuY3Rpb24oaG9va3MpIHsKICB2YXIgdXNlckFnZW50ID0g
+dHlwZW9mIG5hdmlnYXRvciA9PSAib2JqZWN0IiA/IG5hdmlnYXRvci51c2VyQWdlbnQgOiAiIjsKICBp
+ZiAodXNlckFnZW50LmluZGV4T2YoIkZpcmVmb3giKSA9PSAtMSkgcmV0dXJuIGhvb2tzOwogIHZhciBn
+ZXRUYWcgPSBob29rcy5nZXRUYWc7CiAgdmFyIHF1aWNrTWFwID0gewogICAgIkJlZm9yZVVubG9hZEV2
+ZW50IjogIkV2ZW50IiwKICAgICJEYXRhVHJhbnNmZXIiOiAiQ2xpcGJvYXJkIiwKICAgICJHZW9HZW9s
+b2NhdGlvbiI6ICJHZW9sb2NhdGlvbiIsCiAgICAiTG9jYXRpb24iOiAiIUxvY2F0aW9uIiwKICAgICJX
+b3JrZXJNZXNzYWdlRXZlbnQiOiAiTWVzc2FnZUV2ZW50IiwKICAgICJYTUxEb2N1bWVudCI6ICIhRG9j
+dW1lbnQifTsKICBmdW5jdGlvbiBnZXRUYWdGaXJlZm94KG8pIHsKICAgIHZhciB0YWcgPSBnZXRUYWco
+byk7CiAgICByZXR1cm4gcXVpY2tNYXBbdGFnXSB8fCB0YWc7CiAgfQogIGhvb2tzLmdldFRhZyA9IGdl
+dFRhZ0ZpcmVmb3g7Cn0KQy54aT1mdW5jdGlvbihob29rcykgewogIHZhciB1c2VyQWdlbnQgPSB0eXBl
+b2YgbmF2aWdhdG9yID09ICJvYmplY3QiID8gbmF2aWdhdG9yLnVzZXJBZ2VudCA6ICIiOwogIGlmICh1
+c2VyQWdlbnQuaW5kZXhPZigiVHJpZGVudC8iKSA9PSAtMSkgcmV0dXJuIGhvb2tzOwogIHZhciBnZXRU
+YWcgPSBob29rcy5nZXRUYWc7CiAgdmFyIHF1aWNrTWFwID0gewogICAgIkJlZm9yZVVubG9hZEV2ZW50
+IjogIkV2ZW50IiwKICAgICJEYXRhVHJhbnNmZXIiOiAiQ2xpcGJvYXJkIiwKICAgICJIVE1MRERFbGVt
+ZW50IjogIkhUTUxFbGVtZW50IiwKICAgICJIVE1MRFRFbGVtZW50IjogIkhUTUxFbGVtZW50IiwKICAg
+ICJIVE1MUGhyYXNlRWxlbWVudCI6ICJIVE1MRWxlbWVudCIsCiAgICAiUG9zaXRpb24iOiAiR2VvcG9z
+aXRpb24iCiAgfTsKICBmdW5jdGlvbiBnZXRUYWdJRShvKSB7CiAgICB2YXIgdGFnID0gZ2V0VGFnKG8p
+OwogICAgdmFyIG5ld1RhZyA9IHF1aWNrTWFwW3RhZ107CiAgICBpZiAobmV3VGFnKSByZXR1cm4gbmV3
+VGFnOwogICAgaWYgKHRhZyA9PSAiT2JqZWN0IikgewogICAgICBpZiAod2luZG93LkRhdGFWaWV3ICYm
+IChvIGluc3RhbmNlb2Ygd2luZG93LkRhdGFWaWV3KSkgcmV0dXJuICJEYXRhVmlldyI7CiAgICB9CiAg
+ICByZXR1cm4gdGFnOwogIH0KICBmdW5jdGlvbiBwcm90b3R5cGVGb3JUYWdJRSh0YWcpIHsKICAgIHZh
+ciBjb25zdHJ1Y3RvciA9IHdpbmRvd1t0YWddOwogICAgaWYgKGNvbnN0cnVjdG9yID09IG51bGwpIHJl
+dHVybiBudWxsOwogICAgcmV0dXJuIGNvbnN0cnVjdG9yLnByb3RvdHlwZTsKICB9CiAgaG9va3MuZ2V0
+VGFnID0gZ2V0VGFnSUU7CiAgaG9va3MucHJvdG90eXBlRm9yVGFnID0gcHJvdG90eXBlRm9yVGFnSUU7
+Cn0KQy5pNz1mdW5jdGlvbihob29rcykgeyByZXR1cm4gaG9va3M7IH0KCkMuQ3Q9bmV3IFAuYnkoKQpD
+LkVxPW5ldyBQLms1KCkKQy54TT1uZXcgUC51NSgpCkMuUWs9bmV3IFAuRTMoKQpDLk52PW5ldyBILmty
+KCkKQy5OVT1uZXcgUC5KaSgpCkMucGQ9bmV3IFAuWmQoKQpDLkFkPW5ldyBNLkg3KDAsIkhpbnRBY3Rp
+b25LaW5kLmFkZE51bGxhYmxlSGludCIpCkMubmU9bmV3IE0uSDcoMSwiSGludEFjdGlvbktpbmQuYWRk
+Tm9uTnVsbGFibGVIaW50IikKQy5teT1uZXcgTS5INygyLCJIaW50QWN0aW9uS2luZC5jaGFuZ2VUb051
+bGxhYmxlSGludCIpCkMucng9bmV3IE0uSDcoMywiSGludEFjdGlvbktpbmQuY2hhbmdlVG9Ob25OdWxs
+YWJsZUhpbnQiKQpDLndWPW5ldyBNLkg3KDQsIkhpbnRBY3Rpb25LaW5kLnJlbW92ZU51bGxhYmxlSGlu
+dCIpCkMuZlI9bmV3IE0uSDcoNSwiSGludEFjdGlvbktpbmQucmVtb3ZlTm9uTnVsbGFibGVIaW50IikK
+Qy5BMz1uZXcgUC5NeChudWxsKQpDLm5YPW5ldyBQLm9qKG51bGwpCkMuYWs9SC5WTSh0KFswLDAsMzI3
+NzYsMzM3OTIsMSwxMDI0MCwwLDBdKSx1LlYpCkMuY209SC5WTSh0KFsiKjo6Y2xhc3MiLCIqOjpkaXIi
+LCIqOjpkcmFnZ2FibGUiLCIqOjpoaWRkZW4iLCIqOjppZCIsIio6OmluZXJ0IiwiKjo6aXRlbXByb3Ai
+LCIqOjppdGVtcmVmIiwiKjo6aXRlbXNjb3BlIiwiKjo6bGFuZyIsIio6OnNwZWxsY2hlY2siLCIqOjp0
+aXRsZSIsIio6OnRyYW5zbGF0ZSIsIkE6OmFjY2Vzc2tleSIsIkE6OmNvb3JkcyIsIkE6OmhyZWZsYW5n
+IiwiQTo6bmFtZSIsIkE6OnNoYXBlIiwiQTo6dGFiaW5kZXgiLCJBOjp0YXJnZXQiLCJBOjp0eXBlIiwi
+QVJFQTo6YWNjZXNza2V5IiwiQVJFQTo6YWx0IiwiQVJFQTo6Y29vcmRzIiwiQVJFQTo6bm9ocmVmIiwi
+QVJFQTo6c2hhcGUiLCJBUkVBOjp0YWJpbmRleCIsIkFSRUE6OnRhcmdldCIsIkFVRElPOjpjb250cm9s
+cyIsIkFVRElPOjpsb29wIiwiQVVESU86Om1lZGlhZ3JvdXAiLCJBVURJTzo6bXV0ZWQiLCJBVURJTzo6
+cHJlbG9hZCIsIkJETzo6ZGlyIiwiQk9EWTo6YWxpbmsiLCJCT0RZOjpiZ2NvbG9yIiwiQk9EWTo6bGlu
+ayIsIkJPRFk6OnRleHQiLCJCT0RZOjp2bGluayIsIkJSOjpjbGVhciIsIkJVVFRPTjo6YWNjZXNza2V5
+IiwiQlVUVE9OOjpkaXNhYmxlZCIsIkJVVFRPTjo6bmFtZSIsIkJVVFRPTjo6dGFiaW5kZXgiLCJCVVRU
+T046OnR5cGUiLCJCVVRUT046OnZhbHVlIiwiQ0FOVkFTOjpoZWlnaHQiLCJDQU5WQVM6OndpZHRoIiwi
+Q0FQVElPTjo6YWxpZ24iLCJDT0w6OmFsaWduIiwiQ09MOjpjaGFyIiwiQ09MOjpjaGFyb2ZmIiwiQ09M
+OjpzcGFuIiwiQ09MOjp2YWxpZ24iLCJDT0w6OndpZHRoIiwiQ09MR1JPVVA6OmFsaWduIiwiQ09MR1JP
+VVA6OmNoYXIiLCJDT0xHUk9VUDo6Y2hhcm9mZiIsIkNPTEdST1VQOjpzcGFuIiwiQ09MR1JPVVA6OnZh
+bGlnbiIsIkNPTEdST1VQOjp3aWR0aCIsIkNPTU1BTkQ6OmNoZWNrZWQiLCJDT01NQU5EOjpjb21tYW5k
+IiwiQ09NTUFORDo6ZGlzYWJsZWQiLCJDT01NQU5EOjpsYWJlbCIsIkNPTU1BTkQ6OnJhZGlvZ3JvdXAi
+LCJDT01NQU5EOjp0eXBlIiwiREFUQTo6dmFsdWUiLCJERUw6OmRhdGV0aW1lIiwiREVUQUlMUzo6b3Bl
+biIsIkRJUjo6Y29tcGFjdCIsIkRJVjo6YWxpZ24iLCJETDo6Y29tcGFjdCIsIkZJRUxEU0VUOjpkaXNh
+YmxlZCIsIkZPTlQ6OmNvbG9yIiwiRk9OVDo6ZmFjZSIsIkZPTlQ6OnNpemUiLCJGT1JNOjphY2NlcHQi
+LCJGT1JNOjphdXRvY29tcGxldGUiLCJGT1JNOjplbmN0eXBlIiwiRk9STTo6bWV0aG9kIiwiRk9STTo6
+bmFtZSIsIkZPUk06Om5vdmFsaWRhdGUiLCJGT1JNOjp0YXJnZXQiLCJGUkFNRTo6bmFtZSIsIkgxOjph
+bGlnbiIsIkgyOjphbGlnbiIsIkgzOjphbGlnbiIsIkg0OjphbGlnbiIsIkg1OjphbGlnbiIsIkg2Ojph
+bGlnbiIsIkhSOjphbGlnbiIsIkhSOjpub3NoYWRlIiwiSFI6OnNpemUiLCJIUjo6d2lkdGgiLCJIVE1M
+Ojp2ZXJzaW9uIiwiSUZSQU1FOjphbGlnbiIsIklGUkFNRTo6ZnJhbWVib3JkZXIiLCJJRlJBTUU6Omhl
+aWdodCIsIklGUkFNRTo6bWFyZ2luaGVpZ2h0IiwiSUZSQU1FOjptYXJnaW53aWR0aCIsIklGUkFNRTo6
+d2lkdGgiLCJJTUc6OmFsaWduIiwiSU1HOjphbHQiLCJJTUc6OmJvcmRlciIsIklNRzo6aGVpZ2h0Iiwi
+SU1HOjpoc3BhY2UiLCJJTUc6OmlzbWFwIiwiSU1HOjpuYW1lIiwiSU1HOjp1c2VtYXAiLCJJTUc6OnZz
+cGFjZSIsIklNRzo6d2lkdGgiLCJJTlBVVDo6YWNjZXB0IiwiSU5QVVQ6OmFjY2Vzc2tleSIsIklOUFVU
+OjphbGlnbiIsIklOUFVUOjphbHQiLCJJTlBVVDo6YXV0b2NvbXBsZXRlIiwiSU5QVVQ6OmF1dG9mb2N1
+cyIsIklOUFVUOjpjaGVja2VkIiwiSU5QVVQ6OmRpc2FibGVkIiwiSU5QVVQ6OmlucHV0bW9kZSIsIklO
+UFVUOjppc21hcCIsIklOUFVUOjpsaXN0IiwiSU5QVVQ6Om1heCIsIklOUFVUOjptYXhsZW5ndGgiLCJJ
+TlBVVDo6bWluIiwiSU5QVVQ6Om11bHRpcGxlIiwiSU5QVVQ6Om5hbWUiLCJJTlBVVDo6cGxhY2Vob2xk
+ZXIiLCJJTlBVVDo6cmVhZG9ubHkiLCJJTlBVVDo6cmVxdWlyZWQiLCJJTlBVVDo6c2l6ZSIsIklOUFVU
+OjpzdGVwIiwiSU5QVVQ6OnRhYmluZGV4IiwiSU5QVVQ6OnR5cGUiLCJJTlBVVDo6dXNlbWFwIiwiSU5Q
+VVQ6OnZhbHVlIiwiSU5TOjpkYXRldGltZSIsIktFWUdFTjo6ZGlzYWJsZWQiLCJLRVlHRU46OmtleXR5
+cGUiLCJLRVlHRU46Om5hbWUiLCJMQUJFTDo6YWNjZXNza2V5IiwiTEFCRUw6OmZvciIsIkxFR0VORDo6
+YWNjZXNza2V5IiwiTEVHRU5EOjphbGlnbiIsIkxJOjp0eXBlIiwiTEk6OnZhbHVlIiwiTElOSzo6c2l6
+ZXMiLCJNQVA6Om5hbWUiLCJNRU5VOjpjb21wYWN0IiwiTUVOVTo6bGFiZWwiLCJNRU5VOjp0eXBlIiwi
+TUVURVI6OmhpZ2giLCJNRVRFUjo6bG93IiwiTUVURVI6Om1heCIsIk1FVEVSOjptaW4iLCJNRVRFUjo6
+dmFsdWUiLCJPQkpFQ1Q6OnR5cGVtdXN0bWF0Y2giLCJPTDo6Y29tcGFjdCIsIk9MOjpyZXZlcnNlZCIs
+Ik9MOjpzdGFydCIsIk9MOjp0eXBlIiwiT1BUR1JPVVA6OmRpc2FibGVkIiwiT1BUR1JPVVA6OmxhYmVs
+IiwiT1BUSU9OOjpkaXNhYmxlZCIsIk9QVElPTjo6bGFiZWwiLCJPUFRJT046OnNlbGVjdGVkIiwiT1BU
+SU9OOjp2YWx1ZSIsIk9VVFBVVDo6Zm9yIiwiT1VUUFVUOjpuYW1lIiwiUDo6YWxpZ24iLCJQUkU6Ondp
+ZHRoIiwiUFJPR1JFU1M6Om1heCIsIlBST0dSRVNTOjptaW4iLCJQUk9HUkVTUzo6dmFsdWUiLCJTRUxF
+Q1Q6OmF1dG9jb21wbGV0ZSIsIlNFTEVDVDo6ZGlzYWJsZWQiLCJTRUxFQ1Q6Om11bHRpcGxlIiwiU0VM
+RUNUOjpuYW1lIiwiU0VMRUNUOjpyZXF1aXJlZCIsIlNFTEVDVDo6c2l6ZSIsIlNFTEVDVDo6dGFiaW5k
+ZXgiLCJTT1VSQ0U6OnR5cGUiLCJUQUJMRTo6YWxpZ24iLCJUQUJMRTo6Ymdjb2xvciIsIlRBQkxFOjpi
+b3JkZXIiLCJUQUJMRTo6Y2VsbHBhZGRpbmciLCJUQUJMRTo6Y2VsbHNwYWNpbmciLCJUQUJMRTo6ZnJh
+bWUiLCJUQUJMRTo6cnVsZXMiLCJUQUJMRTo6c3VtbWFyeSIsIlRBQkxFOjp3aWR0aCIsIlRCT0RZOjph
+bGlnbiIsIlRCT0RZOjpjaGFyIiwiVEJPRFk6OmNoYXJvZmYiLCJUQk9EWTo6dmFsaWduIiwiVEQ6OmFi
+YnIiLCJURDo6YWxpZ24iLCJURDo6YXhpcyIsIlREOjpiZ2NvbG9yIiwiVEQ6OmNoYXIiLCJURDo6Y2hh
+cm9mZiIsIlREOjpjb2xzcGFuIiwiVEQ6OmhlYWRlcnMiLCJURDo6aGVpZ2h0IiwiVEQ6Om5vd3JhcCIs
+IlREOjpyb3dzcGFuIiwiVEQ6OnNjb3BlIiwiVEQ6OnZhbGlnbiIsIlREOjp3aWR0aCIsIlRFWFRBUkVB
+OjphY2Nlc3NrZXkiLCJURVhUQVJFQTo6YXV0b2NvbXBsZXRlIiwiVEVYVEFSRUE6OmNvbHMiLCJURVhU
+QVJFQTo6ZGlzYWJsZWQiLCJURVhUQVJFQTo6aW5wdXRtb2RlIiwiVEVYVEFSRUE6Om5hbWUiLCJURVhU
+QVJFQTo6cGxhY2Vob2xkZXIiLCJURVhUQVJFQTo6cmVhZG9ubHkiLCJURVhUQVJFQTo6cmVxdWlyZWQi
+LCJURVhUQVJFQTo6cm93cyIsIlRFWFRBUkVBOjp0YWJpbmRleCIsIlRFWFRBUkVBOjp3cmFwIiwiVEZP
+T1Q6OmFsaWduIiwiVEZPT1Q6OmNoYXIiLCJURk9PVDo6Y2hhcm9mZiIsIlRGT09UOjp2YWxpZ24iLCJU
+SDo6YWJiciIsIlRIOjphbGlnbiIsIlRIOjpheGlzIiwiVEg6OmJnY29sb3IiLCJUSDo6Y2hhciIsIlRI
+OjpjaGFyb2ZmIiwiVEg6OmNvbHNwYW4iLCJUSDo6aGVhZGVycyIsIlRIOjpoZWlnaHQiLCJUSDo6bm93
+cmFwIiwiVEg6OnJvd3NwYW4iLCJUSDo6c2NvcGUiLCJUSDo6dmFsaWduIiwiVEg6OndpZHRoIiwiVEhF
+QUQ6OmFsaWduIiwiVEhFQUQ6OmNoYXIiLCJUSEVBRDo6Y2hhcm9mZiIsIlRIRUFEOjp2YWxpZ24iLCJU
+Ujo6YWxpZ24iLCJUUjo6Ymdjb2xvciIsIlRSOjpjaGFyIiwiVFI6OmNoYXJvZmYiLCJUUjo6dmFsaWdu
+IiwiVFJBQ0s6OmRlZmF1bHQiLCJUUkFDSzo6a2luZCIsIlRSQUNLOjpsYWJlbCIsIlRSQUNLOjpzcmNs
+YW5nIiwiVUw6OmNvbXBhY3QiLCJVTDo6dHlwZSIsIlZJREVPOjpjb250cm9scyIsIlZJREVPOjpoZWln
+aHQiLCJWSURFTzo6bG9vcCIsIlZJREVPOjptZWRpYWdyb3VwIiwiVklERU86Om11dGVkIiwiVklERU86
+OnByZWxvYWQiLCJWSURFTzo6d2lkdGgiXSksdS5pKQpDLlZDPUguVk0odChbMCwwLDY1NDkwLDQ1MDU1
+LDY1NTM1LDM0ODE1LDY1NTM0LDE4NDMxXSksdS5WKQpDLm1LPUguVk0odChbMCwwLDI2NjI0LDEwMjMs
+NjU1MzQsMjA0Nyw2NTUzNCwyMDQ3XSksdS5WKQpDLlNxPUguVk0odChbIkhFQUQiLCJBUkVBIiwiQkFT
+RSIsIkJBU0VGT05UIiwiQlIiLCJDT0wiLCJDT0xHUk9VUCIsIkVNQkVEIiwiRlJBTUUiLCJGUkFNRVNF
+VCIsIkhSIiwiSU1BR0UiLCJJTUciLCJJTlBVVCIsIklTSU5ERVgiLCJMSU5LIiwiTUVUQSIsIlBBUkFN
+IiwiU09VUkNFIiwiU1RZTEUiLCJUSVRMRSIsIldCUiJdKSx1LmkpCkMuaFU9SC5WTSh0KFtdKSx1LnUp
+CkMuZG49SC5WTSh0KFtdKSxILk4wKCJqZDxMTCo+IikpCkMueEQ9SC5WTSh0KFtdKSx1LmkpCkMudG89
+SC5WTSh0KFswLDAsMzI3MjIsMTIyODcsNjU1MzQsMzQ4MTUsNjU1MzQsMTg0MzFdKSx1LlYpCkMucms9
+SC5WTSh0KFtDLkFkLEMubmUsQy5teSxDLnJ4LEMud1YsQy5mUl0pLEguTjAoImpkPEg3Kj4iKSkKQy5G
+Mz1ILlZNKHQoWzAsMCwyNDU3NiwxMDIzLDY1NTM0LDM0ODE1LDY1NTM0LDE4NDMxXSksdS5WKQpDLmVh
+PUguVk0odChbMCwwLDMyNzU0LDExMjYzLDY1NTM0LDM0ODE1LDY1NTM0LDE4NDMxXSksdS5WKQpDLlpK
+PUguVk0odChbMCwwLDMyNzIyLDEyMjg3LDY1NTM1LDM0ODE1LDY1NTM0LDE4NDMxXSksdS5WKQpDLldk
+PUguVk0odChbMCwwLDY1NDkwLDEyMjg3LDY1NTM1LDM0ODE1LDY1NTM0LDE4NDMxXSksdS5WKQpDLlF4
+PUguVk0odChbImJpbmQiLCJpZiIsInJlZiIsInJlcGVhdCIsInN5bnRheCJdKSx1LmkpCkMuQkk9SC5W
+TSh0KFsiQTo6aHJlZiIsIkFSRUE6OmhyZWYiLCJCTE9DS1FVT1RFOjpjaXRlIiwiQk9EWTo6YmFja2dy
+b3VuZCIsIkNPTU1BTkQ6Omljb24iLCJERUw6OmNpdGUiLCJGT1JNOjphY3Rpb24iLCJJTUc6OnNyYyIs
+IklOUFVUOjpzcmMiLCJJTlM6OmNpdGUiLCJROjpjaXRlIiwiVklERU86OnBvc3RlciJdKSx1LmkpCkMu
+Q009bmV3IEguTFAoMCx7fSxDLnhELEguTjAoIkxQPHFVKix6TTxqOCo+Kj4iKSkKQy5XTz1uZXcgSC5M
+UCgwLHt9LEMueEQsSC5OMCgiTFA8cVUqLHFVKj4iKSkKQy5pSD1ILlZNKHQoW10pLEguTjAoImpkPEdE
+Kj4iKSkKQy5EeD1uZXcgSC5MUCgwLHt9LEMuaUgsSC5OMCgiTFA8R0QqLEA+IikpCkMuWTI9bmV3IEwu
+TzkoIk5hdmlnYXRpb25UcmVlTm9kZVR5cGUuZGlyZWN0b3J5IikKQy5yZj1uZXcgTC5POSgiTmF2aWdh
+dGlvblRyZWVOb2RlVHlwZS5maWxlIikKQy5UZT1uZXcgSC53digiY2FsbCIpCkMub0U9bmV3IFAuR1ko
+ITEpCkMud1E9bmV3IFAuRnkobnVsbCwyKX0pKCk7KGZ1bmN0aW9uIHN0YXRpY0ZpZWxkcygpeyQuem09
+bnVsbAokLnlqPTAKJC5tSj1udWxsCiQuUDQ9bnVsbAokLk5GPW51bGwKJC5UWD1udWxsCiQueDc9bnVs
+bAokLm53PW51bGwKJC52dj1udWxsCiQuQnY9bnVsbAokLlM2PW51bGwKJC5rOD1udWxsCiQubWc9bnVs
+bAokLlVEPSExCiQuWDM9Qy5OVQokLnhnPUguVk0oW10sSC5OMCgiamQ8TWg+IikpCiQueG89bnVsbAok
+LkJPPW51bGwKJC5sdD1udWxsCiQuRVU9bnVsbAokLm9yPVAuRmwodS5OLHUuWSkKJC5JNj1udWxsCiQu
+RmY9bnVsbH0pKCk7KGZ1bmN0aW9uIGxhenlJbml0aWFsaXplcnMoKXt2YXIgdD1odW5rSGVscGVycy5s
+YXp5CnQoJCwiZmEiLCJ3IixmdW5jdGlvbigpe3JldHVybiBILllnKCJfJGRhcnRfZGFydENsb3N1cmUi
+KX0pCnQoJCwiVTIiLCJTbiIsZnVuY3Rpb24oKXtyZXR1cm4gSC5jTShILlM3KHsKdG9TdHJpbmc6ZnVu
+Y3Rpb24oKXtyZXR1cm4iJHJlY2VpdmVyJCJ9fSkpfSkKdCgkLCJ4cSIsImxxIixmdW5jdGlvbigpe3Jl
+dHVybiBILmNNKEguUzcoeyRtZXRob2QkOm51bGwsCnRvU3RyaW5nOmZ1bmN0aW9uKCl7cmV0dXJuIiRy
+ZWNlaXZlciQifX0pKX0pCnQoJCwiUjEiLCJOOSIsZnVuY3Rpb24oKXtyZXR1cm4gSC5jTShILlM3KG51
+bGwpKX0pCnQoJCwiZk4iLCJpSSIsZnVuY3Rpb24oKXtyZXR1cm4gSC5jTShmdW5jdGlvbigpe3ZhciAk
+YXJndW1lbnRzRXhwciQ9JyRhcmd1bWVudHMkJwp0cnl7bnVsbC4kbWV0aG9kJCgkYXJndW1lbnRzRXhw
+ciQpfWNhdGNoKHMpe3JldHVybiBzLm1lc3NhZ2V9fSgpKX0pCnQoJCwicWkiLCJVTiIsZnVuY3Rpb24o
+KXtyZXR1cm4gSC5jTShILlM3KHZvaWQgMCkpfSkKdCgkLCJyWiIsIlpoIixmdW5jdGlvbigpe3JldHVy
+biBILmNNKGZ1bmN0aW9uKCl7dmFyICRhcmd1bWVudHNFeHByJD0nJGFyZ3VtZW50cyQnCnRyeXsodm9p
+ZCAwKS4kbWV0aG9kJCgkYXJndW1lbnRzRXhwciQpfWNhdGNoKHMpe3JldHVybiBzLm1lc3NhZ2V9fSgp
+KX0pCnQoJCwia3EiLCJyTiIsZnVuY3Rpb24oKXtyZXR1cm4gSC5jTShILk1qKG51bGwpKX0pCnQoJCwi
+dHQiLCJjMyIsZnVuY3Rpb24oKXtyZXR1cm4gSC5jTShmdW5jdGlvbigpe3RyeXtudWxsLiRtZXRob2Qk
+fWNhdGNoKHMpe3JldHVybiBzLm1lc3NhZ2V9fSgpKX0pCnQoJCwiZHQiLCJISyIsZnVuY3Rpb24oKXty
+ZXR1cm4gSC5jTShILk1qKHZvaWQgMCkpfSkKdCgkLCJBNyIsInIxIixmdW5jdGlvbigpe3JldHVybiBI
+LmNNKGZ1bmN0aW9uKCl7dHJ5eyh2b2lkIDApLiRtZXRob2QkfWNhdGNoKHMpe3JldHVybiBzLm1lc3Nh
+Z2V9fSgpKX0pCnQoJCwiV2MiLCJ1dCIsZnVuY3Rpb24oKXtyZXR1cm4gUC5PaigpfSkKdCgkLCJraCIs
+InJmIixmdW5jdGlvbigpe3JldHVybiBuZXcgUC5wZygpLiQwKCl9KQp0KCQsImFYIiwiSEciLGZ1bmN0
+aW9uKCl7cmV0dXJuIG5ldyBQLmMyKCkuJDAoKX0pCnQoJCwiYnQiLCJWNyIsZnVuY3Rpb24oKXtyZXR1
+cm4gbmV3IEludDhBcnJheShILlhGKEguVk0oWy0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0y
+LC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0yLC0y
+LC0yLC0yLC0yLC0yLC0yLC0yLC0xLC0yLC0yLC0yLC0yLC0yLDYyLC0yLDYyLC0yLDYzLDUyLDUzLDU0
+LDU1LDU2LDU3LDU4LDU5LDYwLDYxLC0yLC0yLC0yLC0xLC0yLC0yLC0yLDAsMSwyLDMsNCw1LDYsNyw4
+LDksMTAsMTEsMTIsMTMsMTQsMTUsMTYsMTcsMTgsMTksMjAsMjEsMjIsMjMsMjQsMjUsLTIsLTIsLTIs
+LTIsNjMsLTIsMjYsMjcsMjgsMjksMzAsMzEsMzIsMzMsMzQsMzUsMzYsMzcsMzgsMzksNDAsNDEsNDIs
+NDMsNDQsNDUsNDYsNDcsNDgsNDksNTAsNTEsLTIsLTIsLTIsLTIsLTJdLHUuYSkpKX0pCnQoJCwiTTUi
+LCJ3USIsZnVuY3Rpb24oKXtyZXR1cm4gdHlwZW9mIHByb2Nlc3MhPSJ1bmRlZmluZWQiJiZPYmplY3Qu
+cHJvdG90eXBlLnRvU3RyaW5nLmNhbGwocHJvY2Vzcyk9PSJbb2JqZWN0IHByb2Nlc3NdIiYmcHJvY2Vz
+cy5wbGF0Zm9ybT09IndpbjMyIn0pCnQoJCwibWYiLCJ6NCIsZnVuY3Rpb24oKXtyZXR1cm4gUC5udSgi
+XltcXC1cXC4wLTlBLVpfYS16fl0qJCIpfSkKdCgkLCJPUSIsInZaIixmdW5jdGlvbigpe3JldHVybiBQ
+LktOKCl9KQp0KCQsIlNDIiwiQU4iLGZ1bmN0aW9uKCl7cmV0dXJuIFAudE0oWyJBIiwiQUJCUiIsIkFD
+Uk9OWU0iLCJBRERSRVNTIiwiQVJFQSIsIkFSVElDTEUiLCJBU0lERSIsIkFVRElPIiwiQiIsIkJESSIs
+IkJETyIsIkJJRyIsIkJMT0NLUVVPVEUiLCJCUiIsIkJVVFRPTiIsIkNBTlZBUyIsIkNBUFRJT04iLCJD
+RU5URVIiLCJDSVRFIiwiQ09ERSIsIkNPTCIsIkNPTEdST1VQIiwiQ09NTUFORCIsIkRBVEEiLCJEQVRB
+TElTVCIsIkREIiwiREVMIiwiREVUQUlMUyIsIkRGTiIsIkRJUiIsIkRJViIsIkRMIiwiRFQiLCJFTSIs
+IkZJRUxEU0VUIiwiRklHQ0FQVElPTiIsIkZJR1VSRSIsIkZPTlQiLCJGT09URVIiLCJGT1JNIiwiSDEi
+LCJIMiIsIkgzIiwiSDQiLCJINSIsIkg2IiwiSEVBREVSIiwiSEdST1VQIiwiSFIiLCJJIiwiSUZSQU1F
+IiwiSU1HIiwiSU5QVVQiLCJJTlMiLCJLQkQiLCJMQUJFTCIsIkxFR0VORCIsIkxJIiwiTUFQIiwiTUFS
+SyIsIk1FTlUiLCJNRVRFUiIsIk5BViIsIk5PQlIiLCJPTCIsIk9QVEdST1VQIiwiT1BUSU9OIiwiT1VU
+UFVUIiwiUCIsIlBSRSIsIlBST0dSRVNTIiwiUSIsIlMiLCJTQU1QIiwiU0VDVElPTiIsIlNFTEVDVCIs
+IlNNQUxMIiwiU09VUkNFIiwiU1BBTiIsIlNUUklLRSIsIlNUUk9ORyIsIlNVQiIsIlNVTU1BUlkiLCJT
+VVAiLCJUQUJMRSIsIlRCT0RZIiwiVEQiLCJURVhUQVJFQSIsIlRGT09UIiwiVEgiLCJUSEVBRCIsIlRJ
+TUUiLCJUUiIsIlRSQUNLIiwiVFQiLCJVIiwiVUwiLCJWQVIiLCJWSURFTyIsIldCUiJdLHUuTil9KQp0
+KCQsIlg0IiwiaEciLGZ1bmN0aW9uKCl7cmV0dXJuIFAubnUoIl5cXFMrJCIpfSkKdCgkLCJ3TyIsIm93
+IixmdW5jdGlvbigpe3JldHVybiBQLk5EKHNlbGYpfSkKdCgkLCJrdCIsIlI4IixmdW5jdGlvbigpe3Jl
+dHVybiBILllnKCJfJGRhcnRfZGFydE9iamVjdCIpfSkKdCgkLCJmSyIsImtJIixmdW5jdGlvbigpe3Jl
+dHVybiBmdW5jdGlvbiBEYXJ0T2JqZWN0KGEpe3RoaXMubz1hfX0pCnQoJCwicXQiLCJ6QiIsZnVuY3Rp
+b24oKXtyZXR1cm4gbmV3IFQubVEoKX0pCnQoJCwiT2wiLCJVRSIsZnVuY3Rpb24oKXtyZXR1cm4gUC5o
+SyhDLm9sLmdtVyhXLngzKCkpLmhyZWYpLmdoWSgpLnEoMCwiYXV0aFRva2VuIil9KQp0KCQsImhUIiwi
+eVAiLGZ1bmN0aW9uKCl7cmV0dXJuIFcuWnIoKS5xdWVyeVNlbGVjdG9yKCIuZWRpdC1saXN0IC5wYW5l
+bC1jb250ZW50Iil9KQp0KCQsIlc2IiwiaEwiLGZ1bmN0aW9uKCl7cmV0dXJuIFcuWnIoKS5xdWVyeVNl
+bGVjdG9yKCIuZWRpdC1wYW5lbCAucGFuZWwtY29udGVudCIpfSkKdCgkLCJUUiIsIkRXIixmdW5jdGlv
+bigpe3JldHVybiBXLlpyKCkucXVlcnlTZWxlY3RvcigiZm9vdGVyIil9KQp0KCQsIkVZIiwiZmkiLGZ1
+bmN0aW9uKCl7cmV0dXJuIFcuWnIoKS5xdWVyeVNlbGVjdG9yKCJoZWFkZXIiKX0pCnQoJCwiYXYiLCJE
+OSIsZnVuY3Rpb24oKXtyZXR1cm4gVy5acigpLnF1ZXJ5U2VsZWN0b3IoIiN1bml0LW5hbWUiKX0pCnQo
+JCwiZmUiLCJLRyIsZnVuY3Rpb24oKXtyZXR1cm4gbmV3IEwuWEEoKX0pCnQoJCwiZW8iLCJuVSIsZnVu
+Y3Rpb24oKXtyZXR1cm4gbmV3IE0ubEkoJC5IaygpKX0pCnQoJCwieXIiLCJiRCIsZnVuY3Rpb24oKXty
+ZXR1cm4gbmV3IEUuT0YoUC5udSgiLyIpLFAubnUoIlteL10kIiksUC5udSgiXi8iKSl9KQp0KCQsIk1r
+IiwiS2siLGZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBMLklWKFAubnUoIlsvXFxcXF0iKSxQLm51KCJbXi9c
+XFxcXSQiKSxQLm51KCJeKFxcXFxcXFxcW15cXFxcXStcXFxcW15cXFxcL10rfFthLXpBLVpdOlsvXFxc
+XF0pIiksUC5udSgiXlsvXFxcXF0oPyFbL1xcXFxdKSIpKX0pCnQoJCwiYWsiLCJFYiIsZnVuY3Rpb24o
+KXtyZXR1cm4gbmV3IEYucnUoUC5udSgiLyIpLFAubnUoIiheW2EtekEtWl1bLSsuYS16QS1aXFxkXSo6
+Ly98W14vXSkkIiksUC5udSgiW2EtekEtWl1bLSsuYS16QS1aXFxkXSo6Ly9bXi9dKiIpLFAubnUoIl4v
+IikpfSkKdCgkLCJscyIsIkhrIixmdW5jdGlvbigpe3JldHVybiBPLlJoKCl9KX0pKCk7KGZ1bmN0aW9u
+IG5hdGl2ZVN1cHBvcnQoKXshZnVuY3Rpb24oKXt2YXIgdD1mdW5jdGlvbihhKXt2YXIgbj17fQpuW2Fd
+PTEKcmV0dXJuIE9iamVjdC5rZXlzKGh1bmtIZWxwZXJzLmNvbnZlcnRUb0Zhc3RPYmplY3QobikpWzBd
+fQp2LmdldElzb2xhdGVUYWc9ZnVuY3Rpb24oYSl7cmV0dXJuIHQoIl9fX2RhcnRfIithK3YuaXNvbGF0
+ZVRhZyl9CnZhciBzPSJfX19kYXJ0X2lzb2xhdGVfdGFnc18iCnZhciByPU9iamVjdFtzXXx8KE9iamVj
+dFtzXT1PYmplY3QuY3JlYXRlKG51bGwpKQp2YXIgcT0iX1p4WXhYIgpmb3IodmFyIHA9MDs7cCsrKXt2
+YXIgbz10KHErIl8iK3ArIl8iKQppZighKG8gaW4gcikpe3Jbb109MQp2Lmlzb2xhdGVUYWc9bwpicmVh
+a319di5kaXNwYXRjaFByb3BlcnR5TmFtZT12LmdldElzb2xhdGVUYWcoImRpc3BhdGNoX3JlY29yZCIp
+fSgpCmh1bmtIZWxwZXJzLnNldE9yVXBkYXRlSW50ZXJjZXB0b3JzQnlUYWcoe0RPTUVycm9yOkoudkIs
+TWVkaWFFcnJvcjpKLnZCLE5hdmlnYXRvcjpKLnZCLE5hdmlnYXRvckNvbmN1cnJlbnRIYXJkd2FyZTpK
+LnZCLE5hdmlnYXRvclVzZXJNZWRpYUVycm9yOkoudkIsT3ZlcmNvbnN0cmFpbmVkRXJyb3I6Si52QixQ
+b3NpdGlvbkVycm9yOkoudkIsUmFuZ2U6Si52QixTUUxFcnJvcjpKLnZCLERhdGFWaWV3OkguRVQsQXJy
+YXlCdWZmZXJWaWV3OkguRVQsRmxvYXQzMkFycmF5OkguRGcsRmxvYXQ2NEFycmF5OkguRGcsSW50MTZB
+cnJheTpILnhqLEludDMyQXJyYXk6SC5kRSxJbnQ4QXJyYXk6SC5aQSxVaW50MTZBcnJheTpILmRULFVp
+bnQzMkFycmF5OkguUHEsVWludDhDbGFtcGVkQXJyYXk6SC5lRSxDYW52YXNQaXhlbEFycmF5OkguZUUs
+VWludDhBcnJheTpILlY2LEhUTUxBdWRpb0VsZW1lbnQ6Vy5xRSxIVE1MQlJFbGVtZW50OlcucUUsSFRN
+TEJ1dHRvbkVsZW1lbnQ6Vy5xRSxIVE1MQ2FudmFzRWxlbWVudDpXLnFFLEhUTUxDb250ZW50RWxlbWVu
+dDpXLnFFLEhUTUxETGlzdEVsZW1lbnQ6Vy5xRSxIVE1MRGF0YUVsZW1lbnQ6Vy5xRSxIVE1MRGF0YUxp
+c3RFbGVtZW50OlcucUUsSFRNTERldGFpbHNFbGVtZW50OlcucUUsSFRNTERpYWxvZ0VsZW1lbnQ6Vy5x
+RSxIVE1MRGl2RWxlbWVudDpXLnFFLEhUTUxFbWJlZEVsZW1lbnQ6Vy5xRSxIVE1MRmllbGRTZXRFbGVt
+ZW50OlcucUUsSFRNTEhSRWxlbWVudDpXLnFFLEhUTUxIZWFkRWxlbWVudDpXLnFFLEhUTUxIZWFkaW5n
+RWxlbWVudDpXLnFFLEhUTUxIdG1sRWxlbWVudDpXLnFFLEhUTUxJRnJhbWVFbGVtZW50OlcucUUsSFRN
+TEltYWdlRWxlbWVudDpXLnFFLEhUTUxJbnB1dEVsZW1lbnQ6Vy5xRSxIVE1MTElFbGVtZW50OlcucUUs
+SFRNTExhYmVsRWxlbWVudDpXLnFFLEhUTUxMZWdlbmRFbGVtZW50OlcucUUsSFRNTExpbmtFbGVtZW50
+OlcucUUsSFRNTE1hcEVsZW1lbnQ6Vy5xRSxIVE1MTWVkaWFFbGVtZW50OlcucUUsSFRNTE1lbnVFbGVt
+ZW50OlcucUUsSFRNTE1ldGFFbGVtZW50OlcucUUsSFRNTE1ldGVyRWxlbWVudDpXLnFFLEhUTUxNb2RF
+bGVtZW50OlcucUUsSFRNTE9MaXN0RWxlbWVudDpXLnFFLEhUTUxPYmplY3RFbGVtZW50OlcucUUsSFRN
+TE9wdEdyb3VwRWxlbWVudDpXLnFFLEhUTUxPcHRpb25FbGVtZW50OlcucUUsSFRNTE91dHB1dEVsZW1l
+bnQ6Vy5xRSxIVE1MUGFyYW1FbGVtZW50OlcucUUsSFRNTFBpY3R1cmVFbGVtZW50OlcucUUsSFRNTFBy
+ZUVsZW1lbnQ6Vy5xRSxIVE1MUHJvZ3Jlc3NFbGVtZW50OlcucUUsSFRNTFF1b3RlRWxlbWVudDpXLnFF
+LEhUTUxTY3JpcHRFbGVtZW50OlcucUUsSFRNTFNoYWRvd0VsZW1lbnQ6Vy5xRSxIVE1MU2xvdEVsZW1l
+bnQ6Vy5xRSxIVE1MU291cmNlRWxlbWVudDpXLnFFLEhUTUxTcGFuRWxlbWVudDpXLnFFLEhUTUxTdHls
+ZUVsZW1lbnQ6Vy5xRSxIVE1MVGFibGVDYXB0aW9uRWxlbWVudDpXLnFFLEhUTUxUYWJsZUNlbGxFbGVt
+ZW50OlcucUUsSFRNTFRhYmxlRGF0YUNlbGxFbGVtZW50OlcucUUsSFRNTFRhYmxlSGVhZGVyQ2VsbEVs
+ZW1lbnQ6Vy5xRSxIVE1MVGFibGVDb2xFbGVtZW50OlcucUUsSFRNTFRleHRBcmVhRWxlbWVudDpXLnFF
+LEhUTUxUaW1lRWxlbWVudDpXLnFFLEhUTUxUaXRsZUVsZW1lbnQ6Vy5xRSxIVE1MVHJhY2tFbGVtZW50
+OlcucUUsSFRNTFVMaXN0RWxlbWVudDpXLnFFLEhUTUxVbmtub3duRWxlbWVudDpXLnFFLEhUTUxWaWRl
+b0VsZW1lbnQ6Vy5xRSxIVE1MRGlyZWN0b3J5RWxlbWVudDpXLnFFLEhUTUxGb250RWxlbWVudDpXLnFF
+LEhUTUxGcmFtZUVsZW1lbnQ6Vy5xRSxIVE1MRnJhbWVTZXRFbGVtZW50OlcucUUsSFRNTE1hcnF1ZWVF
+bGVtZW50OlcucUUsSFRNTEVsZW1lbnQ6Vy5xRSxIVE1MQW5jaG9yRWxlbWVudDpXLkdoLEhUTUxBcmVh
+RWxlbWVudDpXLmZZLEhUTUxCYXNlRWxlbWVudDpXLm5CLEJsb2I6Vy5BeixIVE1MQm9keUVsZW1lbnQ6
+Vy5RUCxDREFUQVNlY3Rpb246Vy5ueCxDaGFyYWN0ZXJEYXRhOlcubngsQ29tbWVudDpXLm54LFByb2Nl
+c3NpbmdJbnN0cnVjdGlvbjpXLm54LFRleHQ6Vy5ueCxDU1NTdHlsZURlY2xhcmF0aW9uOlcub0osTVNT
+dHlsZUNTU1Byb3BlcnRpZXM6Vy5vSixDU1MyUHJvcGVydGllczpXLm9KLFhNTERvY3VtZW50OlcuUUYs
+RG9jdW1lbnQ6Vy5RRixET01FeGNlcHRpb246Vy5OaCxET01JbXBsZW1lbnRhdGlvbjpXLmFlLERPTVJl
+Y3RSZWFkT25seTpXLklCLERPTVRva2VuTGlzdDpXLm43LEVsZW1lbnQ6Vy5jdixBYm9ydFBheW1lbnRF
+dmVudDpXLmVhLEFuaW1hdGlvbkV2ZW50OlcuZWEsQW5pbWF0aW9uUGxheWJhY2tFdmVudDpXLmVhLEFw
+cGxpY2F0aW9uQ2FjaGVFcnJvckV2ZW50OlcuZWEsQmFja2dyb3VuZEZldGNoQ2xpY2tFdmVudDpXLmVh
+LEJhY2tncm91bmRGZXRjaEV2ZW50OlcuZWEsQmFja2dyb3VuZEZldGNoRmFpbEV2ZW50OlcuZWEsQmFj
+a2dyb3VuZEZldGNoZWRFdmVudDpXLmVhLEJlZm9yZUluc3RhbGxQcm9tcHRFdmVudDpXLmVhLEJlZm9y
+ZVVubG9hZEV2ZW50OlcuZWEsQmxvYkV2ZW50OlcuZWEsQ2FuTWFrZVBheW1lbnRFdmVudDpXLmVhLENs
+aXBib2FyZEV2ZW50OlcuZWEsQ2xvc2VFdmVudDpXLmVhLEN1c3RvbUV2ZW50OlcuZWEsRGV2aWNlTW90
+aW9uRXZlbnQ6Vy5lYSxEZXZpY2VPcmllbnRhdGlvbkV2ZW50OlcuZWEsRXJyb3JFdmVudDpXLmVhLEV4
+dGVuZGFibGVFdmVudDpXLmVhLEV4dGVuZGFibGVNZXNzYWdlRXZlbnQ6Vy5lYSxGZXRjaEV2ZW50Olcu
+ZWEsRm9udEZhY2VTZXRMb2FkRXZlbnQ6Vy5lYSxGb3JlaWduRmV0Y2hFdmVudDpXLmVhLEdhbWVwYWRF
+dmVudDpXLmVhLEhhc2hDaGFuZ2VFdmVudDpXLmVhLEluc3RhbGxFdmVudDpXLmVhLE1lZGlhRW5jcnlw
+dGVkRXZlbnQ6Vy5lYSxNZWRpYUtleU1lc3NhZ2VFdmVudDpXLmVhLE1lZGlhUXVlcnlMaXN0RXZlbnQ6
+Vy5lYSxNZWRpYVN0cmVhbUV2ZW50OlcuZWEsTWVkaWFTdHJlYW1UcmFja0V2ZW50OlcuZWEsTWVzc2Fn
+ZUV2ZW50OlcuZWEsTUlESUNvbm5lY3Rpb25FdmVudDpXLmVhLE1JRElNZXNzYWdlRXZlbnQ6Vy5lYSxN
+dXRhdGlvbkV2ZW50OlcuZWEsTm90aWZpY2F0aW9uRXZlbnQ6Vy5lYSxQYWdlVHJhbnNpdGlvbkV2ZW50
+OlcuZWEsUGF5bWVudFJlcXVlc3RFdmVudDpXLmVhLFBheW1lbnRSZXF1ZXN0VXBkYXRlRXZlbnQ6Vy5l
+YSxQb3BTdGF0ZUV2ZW50OlcuZWEsUHJlc2VudGF0aW9uQ29ubmVjdGlvbkF2YWlsYWJsZUV2ZW50Olcu
+ZWEsUHJlc2VudGF0aW9uQ29ubmVjdGlvbkNsb3NlRXZlbnQ6Vy5lYSxQcm9taXNlUmVqZWN0aW9uRXZl
+bnQ6Vy5lYSxQdXNoRXZlbnQ6Vy5lYSxSVENEYXRhQ2hhbm5lbEV2ZW50OlcuZWEsUlRDRFRNRlRvbmVD
+aGFuZ2VFdmVudDpXLmVhLFJUQ1BlZXJDb25uZWN0aW9uSWNlRXZlbnQ6Vy5lYSxSVENUcmFja0V2ZW50
+OlcuZWEsU2VjdXJpdHlQb2xpY3lWaW9sYXRpb25FdmVudDpXLmVhLFNlbnNvckVycm9yRXZlbnQ6Vy5l
+YSxTcGVlY2hSZWNvZ25pdGlvbkVycm9yOlcuZWEsU3BlZWNoUmVjb2duaXRpb25FdmVudDpXLmVhLFNw
+ZWVjaFN5bnRoZXNpc0V2ZW50OlcuZWEsU3RvcmFnZUV2ZW50OlcuZWEsU3luY0V2ZW50OlcuZWEsVHJh
+Y2tFdmVudDpXLmVhLFRyYW5zaXRpb25FdmVudDpXLmVhLFdlYktpdFRyYW5zaXRpb25FdmVudDpXLmVh
+LFZSRGV2aWNlRXZlbnQ6Vy5lYSxWUkRpc3BsYXlFdmVudDpXLmVhLFZSU2Vzc2lvbkV2ZW50OlcuZWEs
+TW9qb0ludGVyZmFjZVJlcXVlc3RFdmVudDpXLmVhLFVTQkNvbm5lY3Rpb25FdmVudDpXLmVhLElEQlZl
+cnNpb25DaGFuZ2VFdmVudDpXLmVhLEF1ZGlvUHJvY2Vzc2luZ0V2ZW50OlcuZWEsT2ZmbGluZUF1ZGlv
+Q29tcGxldGlvbkV2ZW50OlcuZWEsV2ViR0xDb250ZXh0RXZlbnQ6Vy5lYSxFdmVudDpXLmVhLElucHV0
+RXZlbnQ6Vy5lYSxTdWJtaXRFdmVudDpXLmVhLEV2ZW50VGFyZ2V0OlcuRDAsRmlsZTpXLmhILEhUTUxG
+b3JtRWxlbWVudDpXLmg0LEhpc3Rvcnk6Vy5icixIVE1MRG9jdW1lbnQ6Vy5WYixYTUxIdHRwUmVxdWVz
+dDpXLmZKLFhNTEh0dHBSZXF1ZXN0RXZlbnRUYXJnZXQ6Vy53YSxJbWFnZURhdGE6Vy5TZyxMb2NhdGlv
+bjpXLnU4LE1vdXNlRXZlbnQ6Vy5BaixEcmFnRXZlbnQ6Vy5BaixQb2ludGVyRXZlbnQ6Vy5BaixXaGVl
+bEV2ZW50OlcuQWosRG9jdW1lbnRGcmFnbWVudDpXLnVILFNoYWRvd1Jvb3Q6Vy51SCxEb2N1bWVudFR5
+cGU6Vy51SCxOb2RlOlcudUgsTm9kZUxpc3Q6Vy5CSCxSYWRpb05vZGVMaXN0OlcuQkgsSFRNTFBhcmFn
+cmFwaEVsZW1lbnQ6Vy5TTixQcm9ncmVzc0V2ZW50OlcuZXcsUmVzb3VyY2VQcm9ncmVzc0V2ZW50Olcu
+ZXcsSFRNTFNlbGVjdEVsZW1lbnQ6Vy5scCxIVE1MVGFibGVFbGVtZW50OlcuVGIsSFRNTFRhYmxlUm93
+RWxlbWVudDpXLkl2LEhUTUxUYWJsZVNlY3Rpb25FbGVtZW50OlcuV1AsSFRNTFRlbXBsYXRlRWxlbWVu
+dDpXLnlZLENvbXBvc2l0aW9uRXZlbnQ6Vy53NixGb2N1c0V2ZW50OlcudzYsS2V5Ym9hcmRFdmVudDpX
+Lnc2LFRleHRFdmVudDpXLnc2LFRvdWNoRXZlbnQ6Vy53NixVSUV2ZW50OlcudzYsV2luZG93OlcuSzUs
+RE9NV2luZG93OlcuSzUsRGVkaWNhdGVkV29ya2VyR2xvYmFsU2NvcGU6Vy5DbSxTZXJ2aWNlV29ya2Vy
+R2xvYmFsU2NvcGU6Vy5DbSxTaGFyZWRXb3JrZXJHbG9iYWxTY29wZTpXLkNtLFdvcmtlckdsb2JhbFNj
+b3BlOlcuQ20sQXR0cjpXLkNRLENsaWVudFJlY3Q6Vy53NCxET01SZWN0OlcudzQsTmFtZWROb2RlTWFw
+OlcucmgsTW96TmFtZWRBdHRyTWFwOlcucmgsSURCS2V5UmFuZ2U6UC5oRixTVkdTY3JpcHRFbGVtZW50
+OlAuYkIsU1ZHQUVsZW1lbnQ6UC5kNSxTVkdBbmltYXRlRWxlbWVudDpQLmQ1LFNWR0FuaW1hdGVNb3Rp
+b25FbGVtZW50OlAuZDUsU1ZHQW5pbWF0ZVRyYW5zZm9ybUVsZW1lbnQ6UC5kNSxTVkdBbmltYXRpb25F
+bGVtZW50OlAuZDUsU1ZHQ2lyY2xlRWxlbWVudDpQLmQ1LFNWR0NsaXBQYXRoRWxlbWVudDpQLmQ1LFNW
+R0RlZnNFbGVtZW50OlAuZDUsU1ZHRGVzY0VsZW1lbnQ6UC5kNSxTVkdEaXNjYXJkRWxlbWVudDpQLmQ1
+LFNWR0VsbGlwc2VFbGVtZW50OlAuZDUsU1ZHRkVCbGVuZEVsZW1lbnQ6UC5kNSxTVkdGRUNvbG9yTWF0
+cml4RWxlbWVudDpQLmQ1LFNWR0ZFQ29tcG9uZW50VHJhbnNmZXJFbGVtZW50OlAuZDUsU1ZHRkVDb21w
+b3NpdGVFbGVtZW50OlAuZDUsU1ZHRkVDb252b2x2ZU1hdHJpeEVsZW1lbnQ6UC5kNSxTVkdGRURpZmZ1
+c2VMaWdodGluZ0VsZW1lbnQ6UC5kNSxTVkdGRURpc3BsYWNlbWVudE1hcEVsZW1lbnQ6UC5kNSxTVkdG
+RURpc3RhbnRMaWdodEVsZW1lbnQ6UC5kNSxTVkdGRUZsb29kRWxlbWVudDpQLmQ1LFNWR0ZFRnVuY0FF
+bGVtZW50OlAuZDUsU1ZHRkVGdW5jQkVsZW1lbnQ6UC5kNSxTVkdGRUZ1bmNHRWxlbWVudDpQLmQ1LFNW
+R0ZFRnVuY1JFbGVtZW50OlAuZDUsU1ZHRkVHYXVzc2lhbkJsdXJFbGVtZW50OlAuZDUsU1ZHRkVJbWFn
+ZUVsZW1lbnQ6UC5kNSxTVkdGRU1lcmdlRWxlbWVudDpQLmQ1LFNWR0ZFTWVyZ2VOb2RlRWxlbWVudDpQ
+LmQ1LFNWR0ZFTW9ycGhvbG9neUVsZW1lbnQ6UC5kNSxTVkdGRU9mZnNldEVsZW1lbnQ6UC5kNSxTVkdG
+RVBvaW50TGlnaHRFbGVtZW50OlAuZDUsU1ZHRkVTcGVjdWxhckxpZ2h0aW5nRWxlbWVudDpQLmQ1LFNW
+R0ZFU3BvdExpZ2h0RWxlbWVudDpQLmQ1LFNWR0ZFVGlsZUVsZW1lbnQ6UC5kNSxTVkdGRVR1cmJ1bGVu
+Y2VFbGVtZW50OlAuZDUsU1ZHRmlsdGVyRWxlbWVudDpQLmQ1LFNWR0ZvcmVpZ25PYmplY3RFbGVtZW50
+OlAuZDUsU1ZHR0VsZW1lbnQ6UC5kNSxTVkdHZW9tZXRyeUVsZW1lbnQ6UC5kNSxTVkdHcmFwaGljc0Vs
+ZW1lbnQ6UC5kNSxTVkdJbWFnZUVsZW1lbnQ6UC5kNSxTVkdMaW5lRWxlbWVudDpQLmQ1LFNWR0xpbmVh
+ckdyYWRpZW50RWxlbWVudDpQLmQ1LFNWR01hcmtlckVsZW1lbnQ6UC5kNSxTVkdNYXNrRWxlbWVudDpQ
+LmQ1LFNWR01ldGFkYXRhRWxlbWVudDpQLmQ1LFNWR1BhdGhFbGVtZW50OlAuZDUsU1ZHUGF0dGVybkVs
+ZW1lbnQ6UC5kNSxTVkdQb2x5Z29uRWxlbWVudDpQLmQ1LFNWR1BvbHlsaW5lRWxlbWVudDpQLmQ1LFNW
+R1JhZGlhbEdyYWRpZW50RWxlbWVudDpQLmQ1LFNWR1JlY3RFbGVtZW50OlAuZDUsU1ZHU2V0RWxlbWVu
+dDpQLmQ1LFNWR1N0b3BFbGVtZW50OlAuZDUsU1ZHU3R5bGVFbGVtZW50OlAuZDUsU1ZHU1ZHRWxlbWVu
+dDpQLmQ1LFNWR1N3aXRjaEVsZW1lbnQ6UC5kNSxTVkdTeW1ib2xFbGVtZW50OlAuZDUsU1ZHVFNwYW5F
+bGVtZW50OlAuZDUsU1ZHVGV4dENvbnRlbnRFbGVtZW50OlAuZDUsU1ZHVGV4dEVsZW1lbnQ6UC5kNSxT
+VkdUZXh0UGF0aEVsZW1lbnQ6UC5kNSxTVkdUZXh0UG9zaXRpb25pbmdFbGVtZW50OlAuZDUsU1ZHVGl0
+bGVFbGVtZW50OlAuZDUsU1ZHVXNlRWxlbWVudDpQLmQ1LFNWR1ZpZXdFbGVtZW50OlAuZDUsU1ZHR3Jh
+ZGllbnRFbGVtZW50OlAuZDUsU1ZHQ29tcG9uZW50VHJhbnNmZXJGdW5jdGlvbkVsZW1lbnQ6UC5kNSxT
+VkdGRURyb3BTaGFkb3dFbGVtZW50OlAuZDUsU1ZHTVBhdGhFbGVtZW50OlAuZDUsU1ZHRWxlbWVudDpQ
+LmQ1fSkKaHVua0hlbHBlcnMuc2V0T3JVcGRhdGVMZWFmVGFncyh7RE9NRXJyb3I6dHJ1ZSxNZWRpYUVy
+cm9yOnRydWUsTmF2aWdhdG9yOnRydWUsTmF2aWdhdG9yQ29uY3VycmVudEhhcmR3YXJlOnRydWUsTmF2
+aWdhdG9yVXNlck1lZGlhRXJyb3I6dHJ1ZSxPdmVyY29uc3RyYWluZWRFcnJvcjp0cnVlLFBvc2l0aW9u
+RXJyb3I6dHJ1ZSxSYW5nZTp0cnVlLFNRTEVycm9yOnRydWUsRGF0YVZpZXc6dHJ1ZSxBcnJheUJ1ZmZl
+clZpZXc6ZmFsc2UsRmxvYXQzMkFycmF5OnRydWUsRmxvYXQ2NEFycmF5OnRydWUsSW50MTZBcnJheTp0
+cnVlLEludDMyQXJyYXk6dHJ1ZSxJbnQ4QXJyYXk6dHJ1ZSxVaW50MTZBcnJheTp0cnVlLFVpbnQzMkFy
+cmF5OnRydWUsVWludDhDbGFtcGVkQXJyYXk6dHJ1ZSxDYW52YXNQaXhlbEFycmF5OnRydWUsVWludDhB
+cnJheTpmYWxzZSxIVE1MQXVkaW9FbGVtZW50OnRydWUsSFRNTEJSRWxlbWVudDp0cnVlLEhUTUxCdXR0
+b25FbGVtZW50OnRydWUsSFRNTENhbnZhc0VsZW1lbnQ6dHJ1ZSxIVE1MQ29udGVudEVsZW1lbnQ6dHJ1
+ZSxIVE1MRExpc3RFbGVtZW50OnRydWUsSFRNTERhdGFFbGVtZW50OnRydWUsSFRNTERhdGFMaXN0RWxl
+bWVudDp0cnVlLEhUTUxEZXRhaWxzRWxlbWVudDp0cnVlLEhUTUxEaWFsb2dFbGVtZW50OnRydWUsSFRN
+TERpdkVsZW1lbnQ6dHJ1ZSxIVE1MRW1iZWRFbGVtZW50OnRydWUsSFRNTEZpZWxkU2V0RWxlbWVudDp0
+cnVlLEhUTUxIUkVsZW1lbnQ6dHJ1ZSxIVE1MSGVhZEVsZW1lbnQ6dHJ1ZSxIVE1MSGVhZGluZ0VsZW1l
+bnQ6dHJ1ZSxIVE1MSHRtbEVsZW1lbnQ6dHJ1ZSxIVE1MSUZyYW1lRWxlbWVudDp0cnVlLEhUTUxJbWFn
+ZUVsZW1lbnQ6dHJ1ZSxIVE1MSW5wdXRFbGVtZW50OnRydWUsSFRNTExJRWxlbWVudDp0cnVlLEhUTUxM
+YWJlbEVsZW1lbnQ6dHJ1ZSxIVE1MTGVnZW5kRWxlbWVudDp0cnVlLEhUTUxMaW5rRWxlbWVudDp0cnVl
+LEhUTUxNYXBFbGVtZW50OnRydWUsSFRNTE1lZGlhRWxlbWVudDp0cnVlLEhUTUxNZW51RWxlbWVudDp0
+cnVlLEhUTUxNZXRhRWxlbWVudDp0cnVlLEhUTUxNZXRlckVsZW1lbnQ6dHJ1ZSxIVE1MTW9kRWxlbWVu
+dDp0cnVlLEhUTUxPTGlzdEVsZW1lbnQ6dHJ1ZSxIVE1MT2JqZWN0RWxlbWVudDp0cnVlLEhUTUxPcHRH
+cm91cEVsZW1lbnQ6dHJ1ZSxIVE1MT3B0aW9uRWxlbWVudDp0cnVlLEhUTUxPdXRwdXRFbGVtZW50OnRy
+dWUsSFRNTFBhcmFtRWxlbWVudDp0cnVlLEhUTUxQaWN0dXJlRWxlbWVudDp0cnVlLEhUTUxQcmVFbGVt
+ZW50OnRydWUsSFRNTFByb2dyZXNzRWxlbWVudDp0cnVlLEhUTUxRdW90ZUVsZW1lbnQ6dHJ1ZSxIVE1M
+U2NyaXB0RWxlbWVudDp0cnVlLEhUTUxTaGFkb3dFbGVtZW50OnRydWUsSFRNTFNsb3RFbGVtZW50OnRy
+dWUsSFRNTFNvdXJjZUVsZW1lbnQ6dHJ1ZSxIVE1MU3BhbkVsZW1lbnQ6dHJ1ZSxIVE1MU3R5bGVFbGVt
+ZW50OnRydWUsSFRNTFRhYmxlQ2FwdGlvbkVsZW1lbnQ6dHJ1ZSxIVE1MVGFibGVDZWxsRWxlbWVudDp0
+cnVlLEhUTUxUYWJsZURhdGFDZWxsRWxlbWVudDp0cnVlLEhUTUxUYWJsZUhlYWRlckNlbGxFbGVtZW50
+OnRydWUsSFRNTFRhYmxlQ29sRWxlbWVudDp0cnVlLEhUTUxUZXh0QXJlYUVsZW1lbnQ6dHJ1ZSxIVE1M
+VGltZUVsZW1lbnQ6dHJ1ZSxIVE1MVGl0bGVFbGVtZW50OnRydWUsSFRNTFRyYWNrRWxlbWVudDp0cnVl
+LEhUTUxVTGlzdEVsZW1lbnQ6dHJ1ZSxIVE1MVW5rbm93bkVsZW1lbnQ6dHJ1ZSxIVE1MVmlkZW9FbGVt
+ZW50OnRydWUsSFRNTERpcmVjdG9yeUVsZW1lbnQ6dHJ1ZSxIVE1MRm9udEVsZW1lbnQ6dHJ1ZSxIVE1M
+RnJhbWVFbGVtZW50OnRydWUsSFRNTEZyYW1lU2V0RWxlbWVudDp0cnVlLEhUTUxNYXJxdWVlRWxlbWVu
+dDp0cnVlLEhUTUxFbGVtZW50OmZhbHNlLEhUTUxBbmNob3JFbGVtZW50OnRydWUsSFRNTEFyZWFFbGVt
+ZW50OnRydWUsSFRNTEJhc2VFbGVtZW50OnRydWUsQmxvYjpmYWxzZSxIVE1MQm9keUVsZW1lbnQ6dHJ1
+ZSxDREFUQVNlY3Rpb246dHJ1ZSxDaGFyYWN0ZXJEYXRhOnRydWUsQ29tbWVudDp0cnVlLFByb2Nlc3Np
+bmdJbnN0cnVjdGlvbjp0cnVlLFRleHQ6dHJ1ZSxDU1NTdHlsZURlY2xhcmF0aW9uOnRydWUsTVNTdHls
+ZUNTU1Byb3BlcnRpZXM6dHJ1ZSxDU1MyUHJvcGVydGllczp0cnVlLFhNTERvY3VtZW50OnRydWUsRG9j
+dW1lbnQ6ZmFsc2UsRE9NRXhjZXB0aW9uOnRydWUsRE9NSW1wbGVtZW50YXRpb246dHJ1ZSxET01SZWN0
+UmVhZE9ubHk6ZmFsc2UsRE9NVG9rZW5MaXN0OnRydWUsRWxlbWVudDpmYWxzZSxBYm9ydFBheW1lbnRF
+dmVudDp0cnVlLEFuaW1hdGlvbkV2ZW50OnRydWUsQW5pbWF0aW9uUGxheWJhY2tFdmVudDp0cnVlLEFw
+cGxpY2F0aW9uQ2FjaGVFcnJvckV2ZW50OnRydWUsQmFja2dyb3VuZEZldGNoQ2xpY2tFdmVudDp0cnVl
+LEJhY2tncm91bmRGZXRjaEV2ZW50OnRydWUsQmFja2dyb3VuZEZldGNoRmFpbEV2ZW50OnRydWUsQmFj
+a2dyb3VuZEZldGNoZWRFdmVudDp0cnVlLEJlZm9yZUluc3RhbGxQcm9tcHRFdmVudDp0cnVlLEJlZm9y
+ZVVubG9hZEV2ZW50OnRydWUsQmxvYkV2ZW50OnRydWUsQ2FuTWFrZVBheW1lbnRFdmVudDp0cnVlLENs
+aXBib2FyZEV2ZW50OnRydWUsQ2xvc2VFdmVudDp0cnVlLEN1c3RvbUV2ZW50OnRydWUsRGV2aWNlTW90
+aW9uRXZlbnQ6dHJ1ZSxEZXZpY2VPcmllbnRhdGlvbkV2ZW50OnRydWUsRXJyb3JFdmVudDp0cnVlLEV4
+dGVuZGFibGVFdmVudDp0cnVlLEV4dGVuZGFibGVNZXNzYWdlRXZlbnQ6dHJ1ZSxGZXRjaEV2ZW50OnRy
+dWUsRm9udEZhY2VTZXRMb2FkRXZlbnQ6dHJ1ZSxGb3JlaWduRmV0Y2hFdmVudDp0cnVlLEdhbWVwYWRF
+dmVudDp0cnVlLEhhc2hDaGFuZ2VFdmVudDp0cnVlLEluc3RhbGxFdmVudDp0cnVlLE1lZGlhRW5jcnlw
+dGVkRXZlbnQ6dHJ1ZSxNZWRpYUtleU1lc3NhZ2VFdmVudDp0cnVlLE1lZGlhUXVlcnlMaXN0RXZlbnQ6
+dHJ1ZSxNZWRpYVN0cmVhbUV2ZW50OnRydWUsTWVkaWFTdHJlYW1UcmFja0V2ZW50OnRydWUsTWVzc2Fn
+ZUV2ZW50OnRydWUsTUlESUNvbm5lY3Rpb25FdmVudDp0cnVlLE1JRElNZXNzYWdlRXZlbnQ6dHJ1ZSxN
+dXRhdGlvbkV2ZW50OnRydWUsTm90aWZpY2F0aW9uRXZlbnQ6dHJ1ZSxQYWdlVHJhbnNpdGlvbkV2ZW50
+OnRydWUsUGF5bWVudFJlcXVlc3RFdmVudDp0cnVlLFBheW1lbnRSZXF1ZXN0VXBkYXRlRXZlbnQ6dHJ1
+ZSxQb3BTdGF0ZUV2ZW50OnRydWUsUHJlc2VudGF0aW9uQ29ubmVjdGlvbkF2YWlsYWJsZUV2ZW50OnRy
+dWUsUHJlc2VudGF0aW9uQ29ubmVjdGlvbkNsb3NlRXZlbnQ6dHJ1ZSxQcm9taXNlUmVqZWN0aW9uRXZl
+bnQ6dHJ1ZSxQdXNoRXZlbnQ6dHJ1ZSxSVENEYXRhQ2hhbm5lbEV2ZW50OnRydWUsUlRDRFRNRlRvbmVD
+aGFuZ2VFdmVudDp0cnVlLFJUQ1BlZXJDb25uZWN0aW9uSWNlRXZlbnQ6dHJ1ZSxSVENUcmFja0V2ZW50
+OnRydWUsU2VjdXJpdHlQb2xpY3lWaW9sYXRpb25FdmVudDp0cnVlLFNlbnNvckVycm9yRXZlbnQ6dHJ1
+ZSxTcGVlY2hSZWNvZ25pdGlvbkVycm9yOnRydWUsU3BlZWNoUmVjb2duaXRpb25FdmVudDp0cnVlLFNw
+ZWVjaFN5bnRoZXNpc0V2ZW50OnRydWUsU3RvcmFnZUV2ZW50OnRydWUsU3luY0V2ZW50OnRydWUsVHJh
+Y2tFdmVudDp0cnVlLFRyYW5zaXRpb25FdmVudDp0cnVlLFdlYktpdFRyYW5zaXRpb25FdmVudDp0cnVl
+LFZSRGV2aWNlRXZlbnQ6dHJ1ZSxWUkRpc3BsYXlFdmVudDp0cnVlLFZSU2Vzc2lvbkV2ZW50OnRydWUs
+TW9qb0ludGVyZmFjZVJlcXVlc3RFdmVudDp0cnVlLFVTQkNvbm5lY3Rpb25FdmVudDp0cnVlLElEQlZl
+cnNpb25DaGFuZ2VFdmVudDp0cnVlLEF1ZGlvUHJvY2Vzc2luZ0V2ZW50OnRydWUsT2ZmbGluZUF1ZGlv
+Q29tcGxldGlvbkV2ZW50OnRydWUsV2ViR0xDb250ZXh0RXZlbnQ6dHJ1ZSxFdmVudDpmYWxzZSxJbnB1
+dEV2ZW50OmZhbHNlLFN1Ym1pdEV2ZW50OmZhbHNlLEV2ZW50VGFyZ2V0OmZhbHNlLEZpbGU6dHJ1ZSxI
+VE1MRm9ybUVsZW1lbnQ6dHJ1ZSxIaXN0b3J5OnRydWUsSFRNTERvY3VtZW50OnRydWUsWE1MSHR0cFJl
+cXVlc3Q6dHJ1ZSxYTUxIdHRwUmVxdWVzdEV2ZW50VGFyZ2V0OmZhbHNlLEltYWdlRGF0YTp0cnVlLExv
+Y2F0aW9uOnRydWUsTW91c2VFdmVudDp0cnVlLERyYWdFdmVudDp0cnVlLFBvaW50ZXJFdmVudDp0cnVl
+LFdoZWVsRXZlbnQ6dHJ1ZSxEb2N1bWVudEZyYWdtZW50OnRydWUsU2hhZG93Um9vdDp0cnVlLERvY3Vt
+ZW50VHlwZTp0cnVlLE5vZGU6ZmFsc2UsTm9kZUxpc3Q6dHJ1ZSxSYWRpb05vZGVMaXN0OnRydWUsSFRN
+TFBhcmFncmFwaEVsZW1lbnQ6dHJ1ZSxQcm9ncmVzc0V2ZW50OnRydWUsUmVzb3VyY2VQcm9ncmVzc0V2
+ZW50OnRydWUsSFRNTFNlbGVjdEVsZW1lbnQ6dHJ1ZSxIVE1MVGFibGVFbGVtZW50OnRydWUsSFRNTFRh
+YmxlUm93RWxlbWVudDp0cnVlLEhUTUxUYWJsZVNlY3Rpb25FbGVtZW50OnRydWUsSFRNTFRlbXBsYXRl
+RWxlbWVudDp0cnVlLENvbXBvc2l0aW9uRXZlbnQ6dHJ1ZSxGb2N1c0V2ZW50OnRydWUsS2V5Ym9hcmRF
+dmVudDp0cnVlLFRleHRFdmVudDp0cnVlLFRvdWNoRXZlbnQ6dHJ1ZSxVSUV2ZW50OmZhbHNlLFdpbmRv
+dzp0cnVlLERPTVdpbmRvdzp0cnVlLERlZGljYXRlZFdvcmtlckdsb2JhbFNjb3BlOnRydWUsU2Vydmlj
+ZVdvcmtlckdsb2JhbFNjb3BlOnRydWUsU2hhcmVkV29ya2VyR2xvYmFsU2NvcGU6dHJ1ZSxXb3JrZXJH
+bG9iYWxTY29wZTp0cnVlLEF0dHI6dHJ1ZSxDbGllbnRSZWN0OnRydWUsRE9NUmVjdDp0cnVlLE5hbWVk
+Tm9kZU1hcDp0cnVlLE1vek5hbWVkQXR0ck1hcDp0cnVlLElEQktleVJhbmdlOnRydWUsU1ZHU2NyaXB0
+RWxlbWVudDp0cnVlLFNWR0FFbGVtZW50OnRydWUsU1ZHQW5pbWF0ZUVsZW1lbnQ6dHJ1ZSxTVkdBbmlt
+YXRlTW90aW9uRWxlbWVudDp0cnVlLFNWR0FuaW1hdGVUcmFuc2Zvcm1FbGVtZW50OnRydWUsU1ZHQW5p
+bWF0aW9uRWxlbWVudDp0cnVlLFNWR0NpcmNsZUVsZW1lbnQ6dHJ1ZSxTVkdDbGlwUGF0aEVsZW1lbnQ6
+dHJ1ZSxTVkdEZWZzRWxlbWVudDp0cnVlLFNWR0Rlc2NFbGVtZW50OnRydWUsU1ZHRGlzY2FyZEVsZW1l
+bnQ6dHJ1ZSxTVkdFbGxpcHNlRWxlbWVudDp0cnVlLFNWR0ZFQmxlbmRFbGVtZW50OnRydWUsU1ZHRkVD
+b2xvck1hdHJpeEVsZW1lbnQ6dHJ1ZSxTVkdGRUNvbXBvbmVudFRyYW5zZmVyRWxlbWVudDp0cnVlLFNW
+R0ZFQ29tcG9zaXRlRWxlbWVudDp0cnVlLFNWR0ZFQ29udm9sdmVNYXRyaXhFbGVtZW50OnRydWUsU1ZH
+RkVEaWZmdXNlTGlnaHRpbmdFbGVtZW50OnRydWUsU1ZHRkVEaXNwbGFjZW1lbnRNYXBFbGVtZW50OnRy
+dWUsU1ZHRkVEaXN0YW50TGlnaHRFbGVtZW50OnRydWUsU1ZHRkVGbG9vZEVsZW1lbnQ6dHJ1ZSxTVkdG
+RUZ1bmNBRWxlbWVudDp0cnVlLFNWR0ZFRnVuY0JFbGVtZW50OnRydWUsU1ZHRkVGdW5jR0VsZW1lbnQ6
+dHJ1ZSxTVkdGRUZ1bmNSRWxlbWVudDp0cnVlLFNWR0ZFR2F1c3NpYW5CbHVyRWxlbWVudDp0cnVlLFNW
+R0ZFSW1hZ2VFbGVtZW50OnRydWUsU1ZHRkVNZXJnZUVsZW1lbnQ6dHJ1ZSxTVkdGRU1lcmdlTm9kZUVs
+ZW1lbnQ6dHJ1ZSxTVkdGRU1vcnBob2xvZ3lFbGVtZW50OnRydWUsU1ZHRkVPZmZzZXRFbGVtZW50OnRy
+dWUsU1ZHRkVQb2ludExpZ2h0RWxlbWVudDp0cnVlLFNWR0ZFU3BlY3VsYXJMaWdodGluZ0VsZW1lbnQ6
+dHJ1ZSxTVkdGRVNwb3RMaWdodEVsZW1lbnQ6dHJ1ZSxTVkdGRVRpbGVFbGVtZW50OnRydWUsU1ZHRkVU
+dXJidWxlbmNlRWxlbWVudDp0cnVlLFNWR0ZpbHRlckVsZW1lbnQ6dHJ1ZSxTVkdGb3JlaWduT2JqZWN0
+RWxlbWVudDp0cnVlLFNWR0dFbGVtZW50OnRydWUsU1ZHR2VvbWV0cnlFbGVtZW50OnRydWUsU1ZHR3Jh
+cGhpY3NFbGVtZW50OnRydWUsU1ZHSW1hZ2VFbGVtZW50OnRydWUsU1ZHTGluZUVsZW1lbnQ6dHJ1ZSxT
+VkdMaW5lYXJHcmFkaWVudEVsZW1lbnQ6dHJ1ZSxTVkdNYXJrZXJFbGVtZW50OnRydWUsU1ZHTWFza0Vs
+ZW1lbnQ6dHJ1ZSxTVkdNZXRhZGF0YUVsZW1lbnQ6dHJ1ZSxTVkdQYXRoRWxlbWVudDp0cnVlLFNWR1Bh
+dHRlcm5FbGVtZW50OnRydWUsU1ZHUG9seWdvbkVsZW1lbnQ6dHJ1ZSxTVkdQb2x5bGluZUVsZW1lbnQ6
+dHJ1ZSxTVkdSYWRpYWxHcmFkaWVudEVsZW1lbnQ6dHJ1ZSxTVkdSZWN0RWxlbWVudDp0cnVlLFNWR1Nl
+dEVsZW1lbnQ6dHJ1ZSxTVkdTdG9wRWxlbWVudDp0cnVlLFNWR1N0eWxlRWxlbWVudDp0cnVlLFNWR1NW
+R0VsZW1lbnQ6dHJ1ZSxTVkdTd2l0Y2hFbGVtZW50OnRydWUsU1ZHU3ltYm9sRWxlbWVudDp0cnVlLFNW
+R1RTcGFuRWxlbWVudDp0cnVlLFNWR1RleHRDb250ZW50RWxlbWVudDp0cnVlLFNWR1RleHRFbGVtZW50
+OnRydWUsU1ZHVGV4dFBhdGhFbGVtZW50OnRydWUsU1ZHVGV4dFBvc2l0aW9uaW5nRWxlbWVudDp0cnVl
+LFNWR1RpdGxlRWxlbWVudDp0cnVlLFNWR1VzZUVsZW1lbnQ6dHJ1ZSxTVkdWaWV3RWxlbWVudDp0cnVl
+LFNWR0dyYWRpZW50RWxlbWVudDp0cnVlLFNWR0NvbXBvbmVudFRyYW5zZmVyRnVuY3Rpb25FbGVtZW50
+OnRydWUsU1ZHRkVEcm9wU2hhZG93RWxlbWVudDp0cnVlLFNWR01QYXRoRWxlbWVudDp0cnVlLFNWR0Vs
+ZW1lbnQ6ZmFsc2V9KQpILkxaLiRuYXRpdmVTdXBlcmNsYXNzVGFnPSJBcnJheUJ1ZmZlclZpZXciCkgu
+UkcuJG5hdGl2ZVN1cGVyY2xhc3NUYWc9IkFycmF5QnVmZmVyVmlldyIKSC5WUC4kbmF0aXZlU3VwZXJj
+bGFzc1RhZz0iQXJyYXlCdWZmZXJWaWV3IgpILkRnLiRuYXRpdmVTdXBlcmNsYXNzVGFnPSJBcnJheUJ1
+ZmZlclZpZXciCkguV0IuJG5hdGl2ZVN1cGVyY2xhc3NUYWc9IkFycmF5QnVmZmVyVmlldyIKSC5aRy4k
+bmF0aXZlU3VwZXJjbGFzc1RhZz0iQXJyYXlCdWZmZXJWaWV3IgpILlBnLiRuYXRpdmVTdXBlcmNsYXNz
+VGFnPSJBcnJheUJ1ZmZlclZpZXcifSkoKQpjb252ZXJ0QWxsVG9GYXN0T2JqZWN0KHcpCmNvbnZlcnRU
+b0Zhc3RPYmplY3QoJCk7KGZ1bmN0aW9uKGEpe2lmKHR5cGVvZiBkb2N1bWVudD09PSJ1bmRlZmluZWQi
+KXthKG51bGwpCnJldHVybn1pZih0eXBlb2YgZG9jdW1lbnQuY3VycmVudFNjcmlwdCE9J3VuZGVmaW5l
+ZCcpe2EoZG9jdW1lbnQuY3VycmVudFNjcmlwdCkKcmV0dXJufXZhciB0PWRvY3VtZW50LnNjcmlwdHMK
+ZnVuY3Rpb24gb25Mb2FkKGIpe2Zvcih2YXIgcj0wO3I8dC5sZW5ndGg7KytyKXRbcl0ucmVtb3ZlRXZl
+bnRMaXN0ZW5lcigibG9hZCIsb25Mb2FkLGZhbHNlKQphKGIudGFyZ2V0KX1mb3IodmFyIHM9MDtzPHQu
+bGVuZ3RoOysrcyl0W3NdLmFkZEV2ZW50TGlzdGVuZXIoImxvYWQiLG9uTG9hZCxmYWxzZSl9KShmdW5j
+dGlvbihhKXt2LmN1cnJlbnRTY3JpcHQ9YQppZih0eXBlb2YgZGFydE1haW5SdW5uZXI9PT0iZnVuY3Rp
+b24iKWRhcnRNYWluUnVubmVyKEwuSXEsW10pCmVsc2UgTC5JcShbXSl9KX0pKCkKLy8jIHNvdXJjZU1h
+cHBpbmdVUkw9bWlncmF0aW9uLmpzLm1hcAo=
 ''';
diff --git a/pkg/nnbd_migration/lib/src/front_end/web/migration.dart b/pkg/nnbd_migration/lib/src/front_end/web/migration.dart
index 776dab7..6649147 100644
--- a/pkg/nnbd_migration/lib/src/front_end/web/migration.dart
+++ b/pkg/nnbd_migration/lib/src/front_end/web/migration.dart
@@ -678,12 +678,12 @@
       arrow.innerHtml = '&#x25BC;';
       Element icon = document.createElement('span');
       li.append(icon);
-      icon.innerHtml = '&#x1F4C1;';
+      icon.innerHtml = '<span class="material-icons">folder_open</span>';
       li.append(Text(entity.name));
       writeNavigationSubtree(li, entity.subtree);
       addArrowClickHandler(arrow);
     } else {
-      li.innerHtml = '&#x1F4C4;';
+      li.innerHtml = '<span class="material-icons">insert_drive_file</span>';
       Element a = document.createElement('a');
       li.append(a);
       a.classes.add('nav-link');
diff --git a/pkg/nnbd_migration/lib/src/preview/dart_logo_page.dart b/pkg/nnbd_migration/lib/src/preview/dart_logo_page.dart
index b4f8b70..061ace1 100644
--- a/pkg/nnbd_migration/lib/src/preview/dart_logo_page.dart
+++ b/pkg/nnbd_migration/lib/src/preview/dart_logo_page.dart
@@ -1,4 +1,4 @@
-// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
diff --git a/pkg/nnbd_migration/lib/src/preview/http_preview_server.dart b/pkg/nnbd_migration/lib/src/preview/http_preview_server.dart
index 2f90a02..3afdadb 100644
--- a/pkg/nnbd_migration/lib/src/preview/http_preview_server.dart
+++ b/pkg/nnbd_migration/lib/src/preview/http_preview_server.dart
@@ -35,13 +35,15 @@
   // A function which allows the migration to be rerun, taking changed paths.
   final Future<MigrationState> Function() rerunFunction;
 
+  final String hostname;
+
   /// Integer for a port to run the preview server on.  If null or zero, allow
   /// [HttpServer.bind] to pick one.
   final int preferredPort;
 
   /// Initialize a newly created HTTP server.
-  HttpPreviewServer(
-      this.migrationState, this.rerunFunction, this.preferredPort);
+  HttpPreviewServer(this.migrationState, this.rerunFunction, this.hostname,
+      this.preferredPort);
 
   Future<String> get authToken async {
     await _serverFuture;
@@ -50,6 +52,11 @@
   }
 
   /// Return the port this server is bound to.
+  Future<String> get boundHostname async {
+    return (await _serverFuture)?.address?.host;
+  }
+
+  /// Return the port this server is bound to.
   Future<int> get boundPort async {
     return (await _serverFuture)?.port;
   }
@@ -67,8 +74,15 @@
     }
 
     try {
-      _serverFuture =
-          HttpServer.bind(InternetAddress.loopbackIPv4, preferredPort ?? 0);
+      if (hostname == 'localhost') {
+        _serverFuture =
+            HttpServer.bind(InternetAddress.loopbackIPv4, preferredPort ?? 0);
+      } else if (hostname == 'any') {
+        _serverFuture =
+            HttpServer.bind(InternetAddress.anyIPv6, preferredPort ?? 0);
+      } else {
+        _serverFuture = HttpServer.bind(hostname, preferredPort ?? 0);
+      }
 
       var server = await _serverFuture;
       _handleServer(server);
diff --git a/pkg/nnbd_migration/lib/src/preview/material_icons_page.dart b/pkg/nnbd_migration/lib/src/preview/material_icons_page.dart
new file mode 100644
index 0000000..0364582
--- /dev/null
+++ b/pkg/nnbd_migration/lib/src/preview/material_icons_page.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:nnbd_migration/src/front_end/resources/resources.g.dart'
+    as resources;
+import 'package:nnbd_migration/src/preview/preview_page.dart';
+import 'package:nnbd_migration/src/preview/preview_site.dart';
+
+/// The page that contains the CSS used to style the semantic highlighting
+/// within a Dart file.
+class MaterialIconsPage extends PreviewPage {
+  /// Initialize a newly created CSS page within the given [site].
+  MaterialIconsPage(PreviewSite site)
+      : super(site, PreviewSite.materialIconsPath.substring(1));
+
+  @override
+  bool get requiresAuth => false;
+
+  @override
+  void generateBody(Map<String, String> params) {
+    throw UnimplementedError();
+  }
+
+  @override
+  Future<void> generatePage(Map<String, String> params) async {
+    buf.write(resources.MaterialIconsRegular_ttf);
+  }
+}
diff --git a/pkg/nnbd_migration/lib/src/preview/preview_site.dart b/pkg/nnbd_migration/lib/src/preview/preview_site.dart
index 6e67a2d..9e02a7b 100644
--- a/pkg/nnbd_migration/lib/src/preview/preview_site.dart
+++ b/pkg/nnbd_migration/lib/src/preview/preview_site.dart
@@ -20,11 +20,14 @@
 import 'package:nnbd_migration/src/preview/highlight_js_page.dart';
 import 'package:nnbd_migration/src/preview/http_preview_server.dart';
 import 'package:nnbd_migration/src/preview/index_file_page.dart';
+import 'package:nnbd_migration/src/preview/material_icons_page.dart';
 import 'package:nnbd_migration/src/preview/navigation_tree_page.dart';
 import 'package:nnbd_migration/src/preview/not_found_page.dart';
 import 'package:nnbd_migration/src/preview/pages.dart';
 import 'package:nnbd_migration/src/preview/preview_page.dart';
 import 'package:nnbd_migration/src/preview/region_page.dart';
+import 'package:nnbd_migration/src/preview/roboto_mono_page.dart';
+import 'package:nnbd_migration/src/preview/roboto_page.dart';
 import 'package:nnbd_migration/src/preview/unauthorized_page.dart';
 
 // The randomly generated auth token used to access the preview site.
@@ -51,6 +54,15 @@
   /// The path of the Dart logo displayed in the toolbar.
   static const dartLogoPath = '/dart_192.png';
 
+  /// The path of the Material icons font.
+  static const materialIconsPath = '/MaterialIconsRegular.ttf';
+
+  /// The path of the Roboto font.
+  static const robotoFontPath = '/RobotoRegular.ttf';
+
+  /// The path of the Roboto Mono font.
+  static const robotoMonoFontPath = '/RobotoMonoRegular.ttf';
+
   static const navigationTreePath = '/_preview/navigationTree.json';
 
   static const applyHintPath = '/apply-hint';
@@ -141,6 +153,18 @@
         // Note: `return await` needed due to
         // https://github.com/dart-lang/sdk/issues/39204
         return await respond(request, DartLogoPage(this));
+      } else if (path == materialIconsPath) {
+        // Note: `return await` needed due to
+        // https://github.com/dart-lang/sdk/issues/39204
+        return await respond(request, MaterialIconsPage(this));
+      } else if (path == robotoFontPath) {
+        // Note: `return await` needed due to
+        // https://github.com/dart-lang/sdk/issues/39204
+        return await respond(request, RobotoPage(this));
+      } else if (path == robotoMonoFontPath) {
+        // Note: `return await` needed due to
+        // https://github.com/dart-lang/sdk/issues/39204
+        return await respond(request, RobotoMonoPage(this));
       } else if (path == '/' ||
           decodedPath == migrationInfo.includedRoot ||
           decodedPath ==
@@ -369,6 +393,10 @@
           ContentType('application', 'javascript', charset: 'utf-8');
     } else if (page is DartLogoPage) {
       response.headers.contentType = ContentType('image', 'png');
+    } else if (page is MaterialIconsPage ||
+        page is RobotoPage ||
+        page is RobotoMonoPage) {
+      response.headers.contentType = ContentType('font', 'ttf');
     } else {
       response.headers.contentType = ContentType.html;
     }
diff --git a/pkg/nnbd_migration/lib/src/preview/roboto_mono_page.dart b/pkg/nnbd_migration/lib/src/preview/roboto_mono_page.dart
new file mode 100644
index 0000000..913ba72
--- /dev/null
+++ b/pkg/nnbd_migration/lib/src/preview/roboto_mono_page.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:nnbd_migration/src/front_end/resources/resources.g.dart'
+    as resources;
+import 'package:nnbd_migration/src/preview/preview_page.dart';
+import 'package:nnbd_migration/src/preview/preview_site.dart';
+
+/// The page that contains the CSS used to style the semantic highlighting
+/// within a Dart file.
+class RobotoMonoPage extends PreviewPage {
+  /// Initialize a newly created CSS page within the given [site].
+  RobotoMonoPage(PreviewSite site)
+      : super(site, PreviewSite.robotoMonoFontPath.substring(1));
+
+  @override
+  bool get requiresAuth => false;
+
+  @override
+  void generateBody(Map<String, String> params) {
+    throw UnimplementedError();
+  }
+
+  @override
+  Future<void> generatePage(Map<String, String> params) async {
+    buf.write(resources.RobotoMonoRegular_ttf);
+  }
+}
diff --git a/pkg/nnbd_migration/lib/src/preview/roboto_page.dart b/pkg/nnbd_migration/lib/src/preview/roboto_page.dart
new file mode 100644
index 0000000..db4c92a
--- /dev/null
+++ b/pkg/nnbd_migration/lib/src/preview/roboto_page.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:nnbd_migration/src/front_end/resources/resources.g.dart'
+    as resources;
+import 'package:nnbd_migration/src/preview/preview_page.dart';
+import 'package:nnbd_migration/src/preview/preview_site.dart';
+
+/// The page that contains the CSS used to style the semantic highlighting
+/// within a Dart file.
+class RobotoPage extends PreviewPage {
+  /// Initialize a newly created CSS page within the given [site].
+  RobotoPage(PreviewSite site)
+      : super(site, PreviewSite.robotoFontPath.substring(1));
+
+  @override
+  bool get requiresAuth => false;
+
+  @override
+  void generateBody(Map<String, String> params) {
+    throw UnimplementedError();
+  }
+
+  @override
+  Future<void> generatePage(Map<String, String> params) async {
+    buf.write(resources.RobotoRegular_ttf);
+  }
+}
diff --git a/pkg/nnbd_migration/test/api_test.dart b/pkg/nnbd_migration/test/api_test.dart
index a6f7f61..e14309d 100644
--- a/pkg/nnbd_migration/test/api_test.dart
+++ b/pkg/nnbd_migration/test/api_test.dart
@@ -5237,6 +5237,34 @@
     await _checkSingleFileChanges(content, expected);
   }
 
+  Future<void> test_regression_42374() async {
+    var content = '''
+class C<R> {
+  R m(dynamic x) {
+    assert(x is R);
+    return x as R;
+  }
+}
+
+void main() {
+  C<int/*!*/>().m(null!);
+}
+''';
+    var expected = '''
+class C<R> {
+  R m(dynamic x) {
+    assert(x is R);
+    return x as R;
+  }
+}
+
+void main() {
+  C<int>().m(null!);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
   Future<void> test_remove_question_from_question_dot() async {
     var content = '_f(int/*!*/ i) => i?.isEven;';
     var expected = '_f(int i) => i.isEven;';
@@ -6065,6 +6093,33 @@
   }
 
   Future<void>
+      test_unconditional_assert_is_statement_implies_non_null_intent() async {
+    var content = '''
+void f(Object i) {
+  assert(i is int);
+}
+void g(bool b, int i) {
+  if (b) f(i);
+}
+main() {
+  g(false, null);
+}
+''';
+    var expected = '''
+void f(Object i) {
+  assert(i is int);
+}
+void g(bool b, int? i) {
+  if (b) f(i!);
+}
+main() {
+  g(false, null);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  Future<void>
       test_unconditional_assert_statement_implies_non_null_intent() async {
     var content = '''
 void f(int i) {
diff --git a/pkg/nnbd_migration/test/edge_builder_test.dart b/pkg/nnbd_migration/test/edge_builder_test.dart
index 7df67db..bf2f75b 100644
--- a/pkg/nnbd_migration/test/edge_builder_test.dart
+++ b/pkg/nnbd_migration/test/edge_builder_test.dart
@@ -728,6 +728,18 @@
     assertEdge(decoratedTypeAnnotation('int i').node, never, hard: true);
   }
 
+  Future<void> test_assert_is_demonstrates_non_null_intent() async {
+    // Note, this could also be handled via improved flow analysis rather than a
+    // hard edge.
+    await analyze('''
+void f(dynamic i) {
+  assert(i is int);
+}
+''');
+
+    assertEdge(decoratedTypeAnnotation('dynamic i').node, never, hard: true);
+  }
+
   Future<void> test_assign_bound_to_type_parameter() async {
     await analyze('''
 class C<T extends List<int>> {
@@ -6222,8 +6234,8 @@
   Future<void> test_prefixedIdentifier_bangHint() async {
     await analyze('''
 import 'dart:math' as m;
-double f1() => m.PI;
-double f2() => m.PI/*!*/;
+double f1() => m.pi;
+double f2() => m.pi/*!*/;
 ''');
     expect(
         assertEdge(anyNode, decoratedTypeAnnotation('double f1').node,
@@ -6235,7 +6247,7 @@
                 hard: false)
             .sourceNode,
         never);
-    expect(hasNullCheckHint(findNode.prefixed('m.PI/*!*/')), isTrue);
+    expect(hasNullCheckHint(findNode.prefixed('m.pi/*!*/')), isTrue);
   }
 
   Future<void> test_prefixedIdentifier_field_type() async {
diff --git a/pkg/nnbd_migration/test/migration_cli_test.dart b/pkg/nnbd_migration/test/migration_cli_test.dart
index daf4b38..1c43754 100644
--- a/pkg/nnbd_migration/test/migration_cli_test.dart
+++ b/pkg/nnbd_migration/test/migration_cli_test.dart
@@ -61,10 +61,12 @@
   _ExceptionGeneratingNonNullableFix(DartFixListener listener,
       ResourceProvider resourceProvider, LineInfo Function(String) getLineInfo,
       {List<String> included = const <String>[],
+      String hostname,
       int preferredPort,
       String summaryPath})
       : super(listener, resourceProvider, getLineInfo,
             included: included,
+            hostname: hostname,
             preferredPort: preferredPort,
             summaryPath: summaryPath);
 
@@ -121,17 +123,20 @@
   NonNullableFix createNonNullableFix(DartFixListener listener,
       ResourceProvider resourceProvider, LineInfo getLineInfo(String path),
       {List<String> included = const <String>[],
+      String hostname,
       int preferredPort,
       String summaryPath}) {
     if (cli._test.injectArtificialException) {
       return _ExceptionGeneratingNonNullableFix(
           listener, resourceProvider, getLineInfo,
           included: included,
+          hostname: hostname,
           preferredPort: preferredPort,
           summaryPath: summaryPath);
     } else {
       return super.createNonNullableFix(listener, resourceProvider, getLineInfo,
           included: included,
+          hostname: hostname,
           preferredPort: preferredPort,
           summaryPath: summaryPath);
     }
@@ -759,6 +764,7 @@
     await runWithPreviewServer(cli, [projectDir], (url) async {
       expect(
           logger.stdoutBuffer.toString(), contains('No analysis issues found'));
+      expect(url, startsWith('http://127.0.0.1:'));
       await assertPreviewServerResponsive(url);
     });
     // No changes should have been made.
@@ -872,6 +878,19 @@
     });
   }
 
+  test_lifecycle_preview_on_host_any() async {
+    var projectContents = simpleProject();
+    var projectDir = await createProjectDir(projectContents);
+    var cli = _createCli()
+      ..decodeCommandLineArgs(_parseArgs(['--preview-hostname=any']));
+    await runWithPreviewServer(cli, [projectDir], (url) async {
+      expect(url, isNot(contains('localhost')));
+      await assertPreviewServerResponsive(url);
+    });
+    // No changes should have been made.
+    assertProjectContents(projectDir, projectContents);
+  }
+
   test_lifecycle_preview_region_link() async {
     var projectContents = simpleProject(sourceText: 'int x;');
     var projectDir = await createProjectDir(projectContents);
@@ -1294,6 +1313,16 @@
     expect(stderrText, contains('No more than one path may be specified'));
   }
 
+  test_option_preview_hostname() {
+    expect(
+        assertParseArgsSuccess(['--preview-hostname', 'any']).previewHostname,
+        'any');
+  }
+
+  test_option_preview_hostname_default() {
+    expect(assertParseArgsSuccess([]).previewHostname, 'localhost');
+  }
+
   test_option_preview_port() {
     expect(
         assertParseArgsSuccess(['--preview-port', '4040']).previewPort, 4040);
diff --git a/pkg/nnbd_migration/tool/codegen/generate_resources.dart b/pkg/nnbd_migration/tool/codegen/generate_resources.dart
index 8a342a1..18695ef 100644
--- a/pkg/nnbd_migration/tool/codegen/generate_resources.dart
+++ b/pkg/nnbd_migration/tool/codegen/generate_resources.dart
@@ -69,6 +69,7 @@
   '.html',
   '.js',
   '.png',
+  '.ttf',
 ];
 
 String base64Encode(List<int> bytes) {
@@ -173,7 +174,8 @@
     var name = path.basename(resource.path).replaceAll('.', '_');
 
     String source;
-    if (path.extension(resource.path) == '.png') {
+    var extension = path.extension(resource.path);
+    if (extension == '.png' || extension == '.ttf') {
       source = resource.readAsStringSync(encoding: latin1);
     } else {
       source = resource.readAsStringSync();
@@ -240,7 +242,9 @@
       continue;
     }
 
-    if (name == 'migration.js' || name == 'dart_192.png') {
+    if (name == 'migration.js' ||
+        name == 'dart_192.png' ||
+        path.extension(name) == '.ttf') {
       // skip the compiled js and logo
       continue;
     }
diff --git a/pkg/nnbd_migration/tool/src/package.dart b/pkg/nnbd_migration/tool/src/package.dart
index 6b67e50..612d9cd 100644
--- a/pkg/nnbd_migration/tool/src/package.dart
+++ b/pkg/nnbd_migration/tool/src/package.dart
@@ -4,7 +4,6 @@
 
 /// Abstractions for the different sources of truth for different packages.
 
-import 'dart:convert';
 import 'dart:io';
 
 import 'package:nnbd_migration/src/utilities/subprocess_launcher.dart';
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 94033c1..4cc5873 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -173,6 +173,7 @@
 frontend_server/test/*: SkipByDesign # Only meant to run on vm
 vm/test/*: SkipByDesign # Only meant to run on vm
 vm_service/test/*: SkipByDesign # Uses dart:io
+vm_snapshot_analysis/test/*: SkipByDesign # Only meant to run on vm
 
 [ $system == windows ]
 analysis_server/test/integration/analysis/get_errors_nonStandard_sdk_test: Skip
diff --git a/pkg/smith/pubspec.yaml b/pkg/smith/pubspec.yaml
index abd81b3..f88a2d3 100644
--- a/pkg/smith/pubspec.yaml
+++ b/pkg/smith/pubspec.yaml
@@ -1,8 +1,6 @@
 name: smith
-author: Dart Team <misc@dartlang.org>
 description: Shared code for working with the Dart SDK's tests and test runner.
-homepage: http://www.dartlang.org
-# This package is not intended to be published.
+# This package is not intended for consumption on pub.dev. DO NOT publish.
 publish_to: none
 environment:
   sdk: "^2.3.0"
diff --git a/pkg/sourcemap_testing/pubspec.yaml b/pkg/sourcemap_testing/pubspec.yaml
index 070ea67..f1d11f0 100644
--- a/pkg/sourcemap_testing/pubspec.yaml
+++ b/pkg/sourcemap_testing/pubspec.yaml
@@ -1,5 +1,6 @@
 # Helper package for testing sourcemaps. Used by ddc and dart2js.
 name: sourcemap_testing
+# This package is not intended for consumption on pub.dev. DO NOT publish.
 publish_to: none
 
 environment:
diff --git a/pkg/status_file/pubspec.yaml b/pkg/status_file/pubspec.yaml
index 4eb3bcc..ae78d40 100644
--- a/pkg/status_file/pubspec.yaml
+++ b/pkg/status_file/pubspec.yaml
@@ -1,5 +1,5 @@
 name: status_file
-# This package is not intended to be published.
+# This package is not intended for consumption on pub.dev. DO NOT publish.
 publish_to: none
 environment:
   sdk: "^2.3.0"
diff --git a/pkg/telemetry/lib/telemetry.dart b/pkg/telemetry/lib/telemetry.dart
index 2da8ecc..0c28c7d 100644
--- a/pkg/telemetry/lib/telemetry.dart
+++ b/pkg/telemetry/lib/telemetry.dart
@@ -179,8 +179,9 @@
     return false;
   }
 
-  return env['BOT'] == 'true'
-      // https://docs.travis-ci.com/user/environment-variables/#Default-Environment-Variables
+  return env.containsKey('BOT')
+      // https://docs.travis-ci.com/user/environment-variables/
+      // Example .travis.yml file: https://github.com/flutter/devtools/blob/master/.travis.yml
       ||
       env['TRAVIS'] == 'true' ||
       env['CONTINUOUS_INTEGRATION'] == 'true' ||
diff --git a/pkg/telemetry/pubspec.yaml b/pkg/telemetry/pubspec.yaml
index 8084a84..c3ba85f 100644
--- a/pkg/telemetry/pubspec.yaml
+++ b/pkg/telemetry/pubspec.yaml
@@ -1,5 +1,6 @@
 name: telemetry
 description: A library to facilitate reporting analytics and crash reports.
+# This package is not intended for consumption on pub.dev. DO NOT publish.
 publish_to: none
 author: Dart Team <misc@dartlang.org>
 
diff --git a/pkg/test_runner/pubspec.yaml b/pkg/test_runner/pubspec.yaml
index b927d5b..a840b28 100644
--- a/pkg/test_runner/pubspec.yaml
+++ b/pkg/test_runner/pubspec.yaml
@@ -3,6 +3,7 @@
 # BSD-style license that can be found in the LICENSE file.
 
 name: test_runner
+# This package is not intended for consumption on pub.dev. DO NOT publish.
 publish_to: none
 environment:
   sdk: "^2.3.0"
diff --git a/pkg/testing/pubspec.yaml b/pkg/testing/pubspec.yaml
index 9811fa7..f012946 100644
--- a/pkg/testing/pubspec.yaml
+++ b/pkg/testing/pubspec.yaml
@@ -1,6 +1,7 @@
 # This pubspec is currently mainly used to make it easier to develop by making 
 # it a package.
 name: testing
+# This package is not intended for consumption on pub.dev. DO NOT publish.
 publish_to: none
 environment:
   sdk: '>=2.0.0 <3.0.0'
diff --git a/pkg/vm/bin/dump_kernel.dart b/pkg/vm/bin/dump_kernel.dart
index 6419750..852c073 100644
--- a/pkg/vm/bin/dump_kernel.dart
+++ b/pkg/vm/bin/dump_kernel.dart
@@ -22,6 +22,8 @@
     show UnreachableNodeMetadataRepository;
 import 'package:vm/metadata/call_site_attributes.dart'
     show CallSiteAttributesMetadataRepository;
+import 'package:vm/metadata/loading_units.dart'
+    show LoadingUnitsMetadataRepository;
 
 final String _usage = '''
 Usage: dump_kernel input.dill output.txt
@@ -48,6 +50,7 @@
   component.addMetadataRepository(new UnreachableNodeMetadataRepository());
   component.addMetadataRepository(new BytecodeMetadataRepository());
   component.addMetadataRepository(new CallSiteAttributesMetadataRepository());
+  component.addMetadataRepository(new LoadingUnitsMetadataRepository());
 
   final List<int> bytes = new File(input).readAsBytesSync();
   new BinaryBuilderWithMetadata(bytes).readComponent(component);
diff --git a/pkg/vm/bin/protobuf_aware_treeshaker.dart b/pkg/vm/bin/protobuf_aware_treeshaker.dart
index 0f9bf55..143a4c6 100644
--- a/pkg/vm/bin/protobuf_aware_treeshaker.dart
+++ b/pkg/vm/bin/protobuf_aware_treeshaker.dart
@@ -123,6 +123,7 @@
     const bool useGlobalTypeFlowAnalysis = true;
     const bool enableAsserts = false;
     const bool useProtobufAwareTreeShaker = true;
+    const bool useProtobufAwareTreeShakerV2 = false;
     final nopErrorDetector = ErrorDetector();
     runGlobalTransformations(
       target,
@@ -130,6 +131,7 @@
       useGlobalTypeFlowAnalysis,
       enableAsserts,
       useProtobufAwareTreeShaker,
+      useProtobufAwareTreeShakerV2,
       nopErrorDetector,
     );
   } else {
diff --git a/pkg/vm/lib/dominators.dart b/pkg/vm/lib/dominators.dart
new file mode 100644
index 0000000..19c5d84
--- /dev/null
+++ b/pkg/vm/lib/dominators.dart
@@ -0,0 +1,126 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library vm.dominators;
+
+class Vertex<T extends Vertex<T>> {
+  // Input: vertices directly reachable from this vertex.
+  final List<T> successors = <T>[];
+
+  // Output: the nearest vertex that all paths from the root must go through to
+  // reach this vertex.
+  T dominator;
+
+  bool isDominatedBy(T other) {
+    var d = this;
+    while (d != null) {
+      if (d == other) {
+        return true;
+      }
+      d = d.dominator;
+    }
+    return false;
+  }
+
+  // Temporaries. See Lengauer and Tarjan.
+  final List<T> _predecessors = <T>[];
+  int _semi = 0;
+  T _label;
+  T _ancestor;
+  T _parent;
+  List<T> _bucket;
+}
+
+// T. Lengauer and R. E. Tarjan. "A Fast Algorithm for Finding Dominators
+// in a Flowgraph."
+computeDominators<T extends Vertex<T>>(T root) {
+  // Lengauer and Tarjan Step 1.
+  final vertex = <T>[];
+  vertex.add(null);
+
+  var n = 0;
+  dfs(T v) {
+    n++;
+
+    vertex.add(v);
+    v._semi = n;
+    v._label = v;
+    v._ancestor = null;
+
+    for (final w in v.successors) {
+      if (w._semi == 0) {
+        w._parent = v;
+        dfs(w);
+      }
+      w._predecessors.add(v);
+    }
+  }
+
+  dfs(root);
+
+  forestCompress(T v) {
+    if (v._ancestor._ancestor != null) {
+      forestCompress(v._ancestor);
+      if (v._ancestor._label._semi < v._label._semi) {
+        v._label = v._ancestor._label;
+      }
+      v._ancestor = v._ancestor._ancestor;
+    }
+  }
+
+  forestEval(T v) {
+    if (v._ancestor == null) {
+      return v;
+    } else {
+      forestCompress(v);
+      return v._label;
+    }
+  }
+
+  forestLink(T v, T w) {
+    w._ancestor = v;
+  }
+
+  for (var i = vertex.length - 1; i > 1; i--) {
+    Vertex<T> w = vertex[i];
+
+    // Lengauer and Tarjan Step 2.
+    for (Vertex<T> v in w._predecessors) {
+      if (v._semi == 0) continue; // Unreachable
+
+      final u = forestEval(v);
+      if (u._semi < w._semi) {
+        w._semi = u._semi;
+      }
+    }
+
+    Vertex<T> z = vertex[w._semi];
+    var b = z._bucket;
+    if (b == null) {
+      z._bucket = b = <T>[];
+    }
+    b.add(w);
+    forestLink(w._parent, w);
+
+    // Lengauer and Tarjan Step 3.
+    z = w._parent;
+    assert(z != null);
+    b = z._bucket;
+    z._bucket = null;
+    if (b != null) {
+      for (final v in b) {
+        final u = forestEval(v);
+        v.dominator = u._semi < v._semi ? u : w._parent;
+      }
+    }
+  }
+
+  // Lengauer and Tarjan Step 4.
+  for (var i = 2; i < vertex.length; i++) {
+    final w = vertex[i];
+    if (w.dominator != vertex[w._semi]) {
+      w.dominator = w.dominator.dominator;
+    }
+  }
+}
diff --git a/pkg/vm/lib/kernel_front_end.dart b/pkg/vm/lib/kernel_front_end.dart
index 24760e7..06cc08b 100644
--- a/pkg/vm/lib/kernel_front_end.dart
+++ b/pkg/vm/lib/kernel_front_end.dart
@@ -68,6 +68,7 @@
 import 'transformations/call_site_annotator.dart' as call_site_annotator;
 import 'transformations/unreachable_code_elimination.dart'
     as unreachable_code_elimination;
+import 'transformations/deferred_loading.dart' as deferred_loading;
 
 /// Declare options consumed by [runCompiler].
 void declareCompilerOptions(ArgParser args) {
@@ -110,6 +111,8 @@
   args.addFlag('protobuf-tree-shaker',
       help: 'Enable protobuf tree shaker transformation in AOT mode.',
       defaultsTo: false);
+  args.addFlag('protobuf-tree-shaker-v2',
+      help: 'Enable protobuf tree shaker v2 in AOT mode.', defaultsTo: false);
   args.addMultiOption('define',
       abbr: 'D',
       help: 'The values for the environment constants (e.g. -Dkey=value).');
@@ -140,6 +143,9 @@
       help: 'Comma separated list of experimental features to enable.');
   args.addFlag('help',
       abbr: 'h', negatable: false, help: 'Print this help message.');
+  args.addFlag('track-widget-creation',
+      help: 'Run a kernel transformer to track creation locations for widgets.',
+      defaultsTo: false);
 }
 
 /// Create ArgParser and populate it with options consumed by [runCompiler].
@@ -185,6 +191,7 @@
   final bool enableAsserts = options['enable-asserts'];
   final bool nullSafety = options['null-safety'];
   final bool useProtobufTreeShaker = options['protobuf-tree-shaker'];
+  final bool useProtobufTreeShakerV2 = options['protobuf-tree-shaker-v2'];
   final bool splitOutputByPackages = options['split-output-by-packages'];
   final String manifestFilename = options['manifest'];
   final String dataDir = options['component-name'] ?? options['data-dir'];
@@ -255,8 +262,11 @@
     await autoDetectNullSafetyMode(mainUri, compilerOptions);
   }
 
-  compilerOptions.target = createFrontEndTarget(targetName,
-      nullSafety: compilerOptions.nnbdMode == NnbdMode.Strong);
+  compilerOptions.target = createFrontEndTarget(
+    targetName,
+    trackWidgetCreation: options['track-widget-creation'],
+    nullSafety: compilerOptions.nnbdMode == NnbdMode.Strong,
+  );
   if (compilerOptions.target == null) {
     print('Failed to create front-end target $targetName.');
     return badUsageExitCode;
@@ -272,6 +282,7 @@
       bytecodeOptions: bytecodeOptions,
       dropAST: dropAST && !splitOutputByPackages,
       useProtobufTreeShaker: useProtobufTreeShaker,
+      useProtobufTreeShakerV2: useProtobufTreeShakerV2,
       minimalKernel: minimalKernel,
       treeShakeWriteOnlyFields: treeShakeWriteOnlyFields,
       fromDillFile: fromDillFile);
@@ -352,6 +363,7 @@
     BytecodeOptions bytecodeOptions,
     bool dropAST: false,
     bool useProtobufTreeShaker: false,
+    bool useProtobufTreeShakerV2: false,
     bool minimalKernel: false,
     bool treeShakeWriteOnlyFields: false,
     String fromDillFile: null}) async {
@@ -385,6 +397,7 @@
         useGlobalTypeFlowAnalysis,
         enableAsserts,
         useProtobufTreeShaker,
+        useProtobufTreeShakerV2,
         errorDetector,
         minimalKernel: minimalKernel,
         treeShakeWriteOnlyFields: treeShakeWriteOnlyFields);
@@ -462,6 +475,7 @@
     bool useGlobalTypeFlowAnalysis,
     bool enableAsserts,
     bool useProtobufTreeShaker,
+    bool useProtobufTreeShakerV2,
     ErrorDetector errorDetector,
     {bool minimalKernel: false,
     bool treeShakeWriteOnlyFields: false}) async {
@@ -481,10 +495,15 @@
   // before type flow analysis so TFA won't take unreachable code into account.
   unreachable_code_elimination.transformComponent(component, enableAsserts);
 
+  if (useProtobufTreeShaker && useProtobufTreeShakerV2) {
+    throw 'Cannot use both versions of protobuf tree shaker';
+  }
+
   if (useGlobalTypeFlowAnalysis) {
     globalTypeFlow.transformComponent(target, coreTypes, component,
         treeShakeSignatures: !minimalKernel,
-        treeShakeWriteOnlyFields: treeShakeWriteOnlyFields);
+        treeShakeWriteOnlyFields: treeShakeWriteOnlyFields,
+        treeShakeProtobufs: useProtobufTreeShakerV2);
   } else {
     devirtualization.transformComponent(coreTypes, component);
     no_dynamic_invocations_annotator.transformComponent(component);
@@ -513,6 +532,8 @@
   // We don't know yet whether gen_snapshot will want to do obfuscation, but if
   // it does it will need the obfuscation prohibitions.
   obfuscationProhibitions.transformComponent(component, coreTypes);
+
+  deferred_loading.transformComponent(component);
 }
 
 /// Runs given [action] with [CompilerContext]. This is needed to
diff --git a/pkg/vm/lib/metadata/loading_units.dart b/pkg/vm/lib/metadata/loading_units.dart
new file mode 100644
index 0000000..410e0d5
--- /dev/null
+++ b/pkg/vm/lib/metadata/loading_units.dart
@@ -0,0 +1,85 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library vm.metadata.loading_units;
+
+import 'package:kernel/ast.dart';
+
+class LoadingUnit {
+  final int id;
+  final int parentId;
+  final List<String> libraryUris;
+
+  LoadingUnit(this.id, this.parentId, this.libraryUris);
+
+  String toString() {
+    var sb = new StringBuffer();
+    sb.writeln("LoadingUnit(id=$id, parent=${parentId},");
+    for (var uri in libraryUris) {
+      sb.writeln("  $uri");
+    }
+    sb.write(")");
+    return sb.toString();
+  }
+}
+
+class LoadingUnitsMetadata {
+  final List<LoadingUnit> loadingUnits;
+
+  LoadingUnitsMetadata(this.loadingUnits);
+
+  String toString() {
+    var sb = new StringBuffer();
+    sb.writeln("LoadingUnitsMetadata(");
+    for (var unit in loadingUnits) {
+      sb.writeln(unit.toString());
+    }
+    sb.write(")");
+    return sb.toString();
+  }
+}
+
+/// Repository for [LoadingUnitsMetadata].
+class LoadingUnitsMetadataRepository
+    extends MetadataRepository<LoadingUnitsMetadata> {
+  static final repositoryTag = 'vm.loading-units.metadata';
+
+  @override
+  final String tag = repositoryTag;
+
+  @override
+  final Map<TreeNode, LoadingUnitsMetadata> mapping =
+      <TreeNode, LoadingUnitsMetadata>{};
+
+  @override
+  void writeToBinary(
+      LoadingUnitsMetadata metadata, Node node, BinarySink sink) {
+    sink.writeUInt30(metadata.loadingUnits.length);
+    for (LoadingUnit unit in metadata.loadingUnits) {
+      sink.writeUInt30(unit.id);
+      sink.writeUInt30(unit.parentId);
+      sink.writeUInt30(unit.libraryUris.length);
+      for (String uri in unit.libraryUris) {
+        sink.writeStringReference(uri);
+      }
+    }
+  }
+
+  @override
+  LoadingUnitsMetadata readFromBinary(Node node, BinarySource source) {
+    int length = source.readUInt();
+    var units = <LoadingUnit>[];
+    for (int i = 0; i < length; i++) {
+      int id = source.readUInt();
+      int parentId = source.readUInt();
+      var libraryUris = <String>[];
+      int length = source.readUInt();
+      for (int i = 0; i < length; i++) {
+        libraryUris.add(source.readStringReference());
+      }
+      units.add(new LoadingUnit(id, parentId, libraryUris));
+    }
+    return new LoadingUnitsMetadata(units);
+  }
+}
diff --git a/pkg/vm/lib/snapshot/commands/compare.dart b/pkg/vm/lib/snapshot/commands/compare.dart
deleted file mode 100644
index 9e1598d..0000000
--- a/pkg/vm/lib/snapshot/commands/compare.dart
+++ /dev/null
@@ -1,139 +0,0 @@
-// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/// This tool compares two JSON size reports produced by
-/// --print-instructions-sizes-to and reports which symbols increased in size
-/// and which symbols decreased in size.
-library vm.snapshot.compare;
-
-import 'dart:io';
-
-import 'package:args/command_runner.dart';
-import 'package:vm/snapshot/ascii_table.dart';
-
-import 'package:vm/snapshot/program_info.dart';
-import 'package:vm/snapshot/utils.dart';
-
-class CompareCommand extends Command<void> {
-  @override
-  final String name = 'compare';
-
-  @override
-  final String description = '''
-Compare two instruction size outputs and report which symbols changed in size.
-
-This tool compares two JSON size reports produced by
---print-instructions-sizes-to and reports which symbols
-changed in size.
-
-Use --narrow flag to limit column widths.''';
-
-  @override
-  String get invocation =>
-      super.invocation.replaceAll('[arguments]', '<old.json> <new.json>');
-
-  CompareCommand() {
-    argParser
-      ..addOption('column-width',
-          help: 'Truncate column content to the given width'
-              ' (${AsciiTable.unlimitedWidth} means do not truncate).',
-          defaultsTo: AsciiTable.unlimitedWidth.toString())
-      ..addOption('granularity',
-          help: 'Choose the granularity of the output.',
-          allowed: ['method', 'class', 'library', 'package'],
-          defaultsTo: 'method')
-      ..addFlag('collapse-anonymous-closures', help: '''
-Collapse all anonymous closures from the same scope into a single entry.
-When comparing size of AOT snapshots for two different versions of a
-program there is no reliable way to precisely establish which two anonymous
-closures are the same and should be compared in size - so
-comparison might produce a noisy output. This option reduces confusion
-by collapsing different anonymous closures within the same scope into a
-single entry. Note that when comparing the same application compiled
-with two different versions of an AOT compiler closures can be distinguished
-precisely based on their source position (which is included in their name).
-''');
-  }
-
-  @override
-  Future<void> run() async {
-    if (argResults.rest.length != 2) {
-      usageException('Need to provide path to old.json and new.json reports.');
-    }
-
-    final columnWidth = argResults['column-width'];
-    final maxWidth = int.tryParse(columnWidth);
-    if (maxWidth == null) {
-      usageException(
-          'Specified column width (${columnWidth}) is not an integer');
-    }
-
-    final oldJsonPath = _checkExists(argResults.rest[0]);
-    final newJsonPath = _checkExists(argResults.rest[1]);
-    printComparison(oldJsonPath, newJsonPath,
-        maxWidth: maxWidth,
-        granularity: _parseHistogramType(argResults['granularity']),
-        collapseAnonymousClosures: argResults['collapse-anonymous-closures']);
-  }
-
-  HistogramType _parseHistogramType(String value) {
-    switch (value) {
-      case 'method':
-        return HistogramType.bySymbol;
-      case 'class':
-        return HistogramType.byClass;
-      case 'library':
-        return HistogramType.byLibrary;
-      case 'package':
-        return HistogramType.byPackage;
-    }
-  }
-
-  File _checkExists(String path) {
-    final file = File(path);
-    if (!file.existsSync()) {
-      usageException('File $path does not exist!');
-    }
-    return file;
-  }
-}
-
-void printComparison(File oldJson, File newJson,
-    {int maxWidth: 0,
-    bool collapseAnonymousClosures = false,
-    HistogramType granularity = HistogramType.bySymbol}) async {
-  final oldSizes = await loadProgramInfo(oldJson,
-      collapseAnonymousClosures: collapseAnonymousClosures);
-  final newSizes = await loadProgramInfo(newJson,
-      collapseAnonymousClosures: collapseAnonymousClosures);
-  final diff = computeDiff(oldSizes, newSizes);
-
-  // Compute total sizes.
-  final totalOld = oldSizes.totalSize;
-  final totalNew = newSizes.totalSize;
-  final totalDiff = diff.totalSize;
-
-  // Compute histogram.
-  final histogram = SizesHistogram.from(diff, granularity);
-
-  // Now produce the report table.
-  const numLargerSymbolsToReport = 30;
-  const numSmallerSymbolsToReport = 10;
-  printHistogram(histogram,
-      sizeHeader: 'Diff (Bytes)',
-      prefix: histogram.bySize
-          .where((k) => histogram.buckets[k] > 0)
-          .take(numLargerSymbolsToReport),
-      suffix: histogram.bySize.reversed
-          .where((k) => histogram.buckets[k] < 0)
-          .take(numSmallerSymbolsToReport)
-          .toList()
-          .reversed,
-      maxWidth: maxWidth);
-
-  print('Comparing ${oldJson.path} (old) to ${newJson.path} (new)');
-  print('Old   : ${totalOld} bytes.');
-  print('New   : ${totalNew} bytes.');
-  print('Change: ${totalDiff > 0 ? '+' : ''}${totalDiff} bytes.');
-}
diff --git a/pkg/vm/lib/snapshot/utils.dart b/pkg/vm/lib/snapshot/utils.dart
deleted file mode 100644
index e57a188..0000000
--- a/pkg/vm/lib/snapshot/utils.dart
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-library vm.snapshot.utils;
-
-import 'dart:io';
-import 'dart:convert';
-
-import 'package:vm/snapshot/ascii_table.dart';
-import 'package:vm/snapshot/program_info.dart';
-import 'package:vm/snapshot/instruction_sizes.dart' as instruction_sizes;
-
-Future<Object> loadJson(File input) async {
-  return await input
-      .openRead()
-      .transform(utf8.decoder)
-      .transform(json.decoder)
-      .first;
-}
-
-Future<ProgramInfo> loadProgramInfo(File input,
-    {bool collapseAnonymousClosures = false}) async {
-  final json = await loadJson(input);
-  return instruction_sizes.loadProgramInfo(json,
-      collapseAnonymousClosures: collapseAnonymousClosures);
-}
-
-void printHistogram(SizesHistogram histogram,
-    {Iterable<String> prefix = const [],
-    Iterable<String> suffix = const [],
-    String sizeHeader = 'Size (Bytes)',
-    int maxWidth = 0}) {
-  final table = AsciiTable(header: [
-    for (var col in histogram.bucketing.nameComponents) Text.left(col),
-    Text.right(sizeHeader),
-    Text.right('Percent'),
-  ], maxWidth: maxWidth);
-
-  String formatPercent(int value, int total) {
-    final p = value / total * 100.0;
-    return p.toStringAsFixed(2) + "%";
-  }
-
-  if (prefix.isNotEmpty) {
-    for (var key in prefix) {
-      table.addRow([
-        ...histogram.bucketing.namesFromBucket(key),
-        histogram.buckets[key].toString(),
-        formatPercent(histogram.buckets[key], histogram.totalSize),
-      ]);
-    }
-    table.addSeparator(
-        prefix.length < histogram.length ? Separator.Wave : Separator.Line);
-  }
-
-  final numRestRows = histogram.length - (suffix.length + prefix.length);
-  if (numRestRows > 0) {
-    final totalRestBytes = histogram.totalSize -
-        [prefix, suffix]
-            .expand((l) => l)
-            .fold(0, (sum, key) => sum + histogram.buckets[key]);
-    table.addTextSeparator(
-        '$numRestRows more rows accounting for ${totalRestBytes}'
-        ' (${formatPercent(totalRestBytes, histogram.totalSize)}) bytes');
-    final avg = (totalRestBytes / numRestRows).round();
-    table.addTextSeparator(
-        'on average that is ${avg} (${formatPercent(avg, histogram.totalSize)})'
-        ' bytes per row');
-    table.addSeparator(suffix.isNotEmpty ? Separator.Wave : Separator.Line);
-  }
-
-  if (suffix.isNotEmpty) {
-    for (var key in suffix) {
-      table.addRow([
-        ...histogram.bucketing.namesFromBucket(key),
-        histogram.buckets[key].toString(),
-        formatPercent(histogram.buckets[key], histogram.totalSize),
-      ]);
-    }
-    table.addSeparator(Separator.Line);
-  }
-
-  table.render();
-  print('Total: ${histogram.totalSize} bytes');
-}
diff --git a/pkg/vm/lib/transformations/deferred_loading.dart b/pkg/vm/lib/transformations/deferred_loading.dart
new file mode 100644
index 0000000..f2b0318
--- /dev/null
+++ b/pkg/vm/lib/transformations/deferred_loading.dart
@@ -0,0 +1,118 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library vm.transformations.deferred_loading;
+
+import 'package:kernel/ast.dart';
+import '../dominators.dart';
+import '../metadata/loading_units.dart';
+
+class _LoadingUnitBuilder {
+  final int id;
+  final _LibraryVertex root;
+  final List<Library> members = <Library>[];
+
+  _LoadingUnitBuilder(this.id, this.root);
+
+  int get parentId =>
+      root.dominator == null ? 0 : root.dominator.loadingUnit.id;
+
+  LoadingUnit asLoadingUnit() {
+    return new LoadingUnit(
+        id, parentId, members.map((l) => l.importUri.toString()).toList());
+  }
+
+  String toString() =>
+      "_LoadingUnitBuilder(id=$id, parent=${parentId}, size=${members.length})";
+}
+
+class _LibraryVertex extends Vertex<_LibraryVertex> {
+  final Library library;
+  bool isLoadingRoot = true;
+  _LoadingUnitBuilder loadingUnit;
+  _LibraryVertex(this.library);
+
+  String toString() => "_LibraryVertex(${library.importUri})";
+}
+
+List<LoadingUnit> computeLoadingUnits(Component component) {
+  // 1. Build the dominator tree for the library import graph.
+  final map = <Library, _LibraryVertex>{};
+  for (final lib in component.libraries) {
+    map[lib] = new _LibraryVertex(lib);
+  }
+  for (final vertex in map.values) {
+    for (final dep in vertex.library.dependencies) {
+      final target = map[dep.targetLibrary];
+      vertex.successors.add(target);
+    }
+  }
+  final root = map[component.mainMethod.parent as Library];
+
+  // Fake imports from root library to every core library so they end up in
+  // the same loading unit attributed to the user's root library.
+  for (final vertex in map.values) {
+    if (vertex.library.importUri.scheme == "dart") {
+      root.successors.add(vertex);
+      vertex.isLoadingRoot = false;
+    }
+  }
+
+  computeDominators(root);
+
+  // 2. Find loading unit roots.
+  for (var importer in map.values) {
+    if ((importer != root) && (importer.dominator == null)) {
+      continue; // Unreachable library.
+    }
+    for (var dep in importer.library.dependencies) {
+      if (dep.isDeferred) {
+        continue;
+      }
+      var importee = map[dep.targetLibrary];
+      if (importer.isDominatedBy(importee)) {
+        continue;
+      }
+      importee.isLoadingRoot = false;
+    }
+  }
+  assert(root.isLoadingRoot);
+
+  var loadingUnits = <_LoadingUnitBuilder>[];
+  for (var vertex in map.values) {
+    if (vertex.isLoadingRoot) {
+      var unit = new _LoadingUnitBuilder(loadingUnits.length + 1, vertex);
+      vertex.loadingUnit = unit;
+      unit.members.add(vertex.library);
+      loadingUnits.add(unit);
+    }
+  }
+
+  // 3. Attribute every library to the dominating loading unit.
+  for (var vertex in map.values) {
+    if (vertex.isLoadingRoot) {
+      continue; // Already processed.
+    }
+    var dom = vertex.dominator;
+    if (dom == null) {
+      continue; // Unreachable library.
+    }
+    while (dom.loadingUnit == null) {
+      dom = dom.dominator;
+    }
+    vertex.loadingUnit = dom.loadingUnit;
+    vertex.loadingUnit.members.add(vertex.library);
+  }
+
+  return loadingUnits.map((u) => u.asLoadingUnit()).toList();
+}
+
+Component transformComponent(Component component) {
+  final metadata = new LoadingUnitsMetadata(computeLoadingUnits(component));
+  final repo = new LoadingUnitsMetadataRepository();
+  component.addMetadataRepository(repo);
+  repo.mapping[component] = metadata;
+
+  return component;
+}
diff --git a/pkg/vm/lib/transformations/type_flow/analysis.dart b/pkg/vm/lib/transformations/type_flow/analysis.dart
index 974b04c..218f4cc 100644
--- a/pkg/vm/lib/transformations/type_flow/analysis.dart
+++ b/pkg/vm/lib/transformations/type_flow/analysis.dart
@@ -18,6 +18,7 @@
 
 import 'calls.dart';
 import 'native_code.dart';
+import 'protobuf_handler.dart' show ProtobufHandler;
 import 'summary.dart';
 import 'summary_collector.dart';
 import 'types.dart';
@@ -1222,8 +1223,34 @@
     enqueueInvocation(invocation);
   }
 
+  bool invalidateProtobufFields() {
+    if (_typeFlowAnalysis.protobufHandler == null) {
+      return false;
+    }
+    final fields = _typeFlowAnalysis.protobufHandler.getInvalidatedFields();
+    if (fields.isEmpty) {
+      return false;
+    }
+    // Protobuf handler replaced contents of static field initializers.
+    for (var field in fields) {
+      assertx(field.isStatic);
+      // Reset summary in order to rebuild it.
+      _typeFlowAnalysis._summaries[field] = null;
+      // Invalidate (and enqueue) field initializer invocation.
+      final initializerInvocation = _typeFlowAnalysis._invocationsCache
+          .getInvocation(
+              DirectSelector(field, callKind: CallKind.FieldInitializer),
+              Args<Type>(const <Type>[]));
+      invalidateInvocation(initializerInvocation);
+    }
+    return true;
+  }
+
   void process() {
-    while (pending.isNotEmpty) {
+    for (;;) {
+      if (pending.isEmpty && !invalidateProtobufFields()) {
+        break;
+      }
       assertx(callStack.isEmpty && processing.isEmpty);
       Statistics.iterationsOverInvocationsWorkList++;
       processInvocation(pending.first);
@@ -1320,6 +1347,7 @@
   final TypeEnvironment environment;
   final LibraryIndex libraryIndex;
   final PragmaAnnotationParser annotationMatcher;
+  final ProtobufHandler protobufHandler;
   NativeCodeOracle nativeCodeOracle;
   _ClassHierarchyCache hierarchyCache;
   SummaryCollector summaryCollector;
@@ -1343,14 +1371,22 @@
       this._genericInterfacesInfo,
       this.environment,
       this.libraryIndex,
-      {PragmaAnnotationParser matcher})
+      this.protobufHandler,
+      PragmaAnnotationParser matcher)
       : annotationMatcher =
             matcher ?? new ConstantPragmaAnnotationParser(coreTypes) {
     nativeCodeOracle = new NativeCodeOracle(libraryIndex, annotationMatcher);
     hierarchyCache = new _ClassHierarchyCache(this, hierarchy,
         _genericInterfacesInfo, environment, target.flags.enableNullSafety);
-    summaryCollector = new SummaryCollector(target, environment, hierarchy,
-        this, hierarchyCache, nativeCodeOracle, hierarchyCache);
+    summaryCollector = new SummaryCollector(
+        target,
+        environment,
+        hierarchy,
+        this,
+        hierarchyCache,
+        nativeCodeOracle,
+        hierarchyCache,
+        protobufHandler);
     _invocationsCache = new _InvocationsCache(this);
     workList = new _WorkList(this);
 
diff --git a/pkg/vm/lib/transformations/type_flow/protobuf_handler.dart b/pkg/vm/lib/transformations/type_flow/protobuf_handler.dart
new file mode 100644
index 0000000..1e98f46
--- /dev/null
+++ b/pkg/vm/lib/transformations/type_flow/protobuf_handler.dart
@@ -0,0 +1,200 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:kernel/ast.dart';
+import 'package:kernel/clone.dart' show CloneVisitorNotMembers;
+import 'package:kernel/core_types.dart' show CoreTypes;
+import 'package:kernel/library_index.dart' show LibraryIndex;
+
+import 'utils.dart';
+
+/// Tracks used getters and setters of generated protobuf message
+/// classes and prunes metadata declarations.
+class ProtobufHandler {
+  static const String protobufLibraryUri = 'package:protobuf/protobuf.dart';
+  static const String metadataFieldName = '_i';
+
+  // All of those methods have the dart field name as second positional
+  // parameter.
+  // Method names are defined in:
+  // https://github.com/dart-lang/protobuf/blob/master/protobuf/lib/src/protobuf/builder_info.dart
+  // The code is generated by:
+  // https://github.com/dart-lang/protobuf/blob/master/protoc_plugin/lib/protobuf_field.dart.
+  static const Set<String> fieldAddingMethods = const <String>{
+    'a',
+    'aOM',
+    'aOS',
+    'aQM',
+    'pPS',
+    'aQS',
+    'aInt64',
+    'aOB',
+    'e',
+    'p',
+    'pc',
+    'm',
+  };
+
+  final CoreTypes coreTypes;
+  final Class _generatedMessageClass;
+  final Class _tagNumberClass;
+  final Field _tagNumberField;
+  final Class _builderInfoClass;
+  final Procedure _builderInfoAddMethod;
+  final _messageClasses = <Class, _MessageClass>{};
+  final _invalidatedClasses = <_MessageClass>{};
+
+  /// Creates [ProtobufHandler] instance for [component].
+  /// Returns null if protobuf library is not used.
+  static ProtobufHandler forComponent(
+      Component component, CoreTypes coreTypes) {
+    final libraryIndex = LibraryIndex(component, [protobufLibraryUri]);
+    if (!libraryIndex.containsLibrary(protobufLibraryUri)) {
+      return null;
+    }
+    return ProtobufHandler._internal(libraryIndex, coreTypes);
+  }
+
+  ProtobufHandler._internal(LibraryIndex libraryIndex, this.coreTypes)
+      : _generatedMessageClass =
+            libraryIndex.getClass(protobufLibraryUri, 'GeneratedMessage'),
+        _tagNumberClass =
+            libraryIndex.getClass(protobufLibraryUri, 'TagNumber'),
+        _tagNumberField = libraryIndex.getMember(
+            protobufLibraryUri, 'TagNumber', 'tagNumber'),
+        _builderInfoClass =
+            libraryIndex.getClass(protobufLibraryUri, 'BuilderInfo'),
+        _builderInfoAddMethod =
+            libraryIndex.getMember(protobufLibraryUri, 'BuilderInfo', 'add');
+
+  /// This method is called from summary collector when analysis discovered
+  /// that [member] is called and needs to construct a summary for its body.
+  ///
+  /// At this point protobuf handler can
+  ///  - modify static field initializer of metadata field;
+  ///  - track used members of the generated message classes.
+  void beforeSummaryCreation(Member member) {
+    // Only interested in members of subclasses of GeneratedMessage class.
+    final cls = member.enclosingClass;
+    if (cls == null || cls.superclass != _generatedMessageClass) {
+      return;
+    }
+    final messageClass = (_messageClasses[cls] ??= _MessageClass());
+    if (member is Field && member.name.name == metadataFieldName) {
+      // Update contents of static field initializer of metadata field (_i).
+      // according to the used tag numbers.
+      assertx(member.isStatic);
+      if (messageClass._metadataField == null) {
+        messageClass._metadataField = member;
+        ++Statistics.protobufMessagesUsed;
+      } else {
+        assertx(messageClass._metadataField == member);
+      }
+      _updateMetadataField(messageClass);
+      return;
+    }
+    if (member is Procedure && !member.isStatic) {
+      // Track usage of accessors of protobuf fields: extract tag number
+      // from annotations and add tag number to the set of used tags.
+      // This may also add message class to the set of invalidated classes,
+      // so their metadata field initializers will be revisited.
+      for (var annotation in member.annotations) {
+        final constant = (annotation as ConstantExpression).constant;
+        if (constant is InstanceConstant &&
+            constant.classReference == _tagNumberClass.reference) {
+          if (messageClass._usedTags.add(
+              (constant.fieldValues[_tagNumberField.reference] as IntConstant)
+                  .value)) {
+            _invalidatedClasses.add(messageClass);
+          }
+        }
+      }
+    }
+  }
+
+  List<Field> getInvalidatedFields() {
+    final fields = <Field>[];
+    for (var cls in _invalidatedClasses) {
+      if (cls._metadataField != null) {
+        fields.add(cls._metadataField);
+      }
+    }
+    _invalidatedClasses.clear();
+    return fields;
+  }
+
+  /// Updates initializer of metadata field of [cls] message class.
+  void _updateMetadataField(_MessageClass cls) {
+    ++Statistics.protobufMetadataInitializersUpdated;
+    Statistics.protobufMetadataFieldsPruned -= cls.numberOfFieldsPruned;
+
+    final field = cls._metadataField;
+    if (cls._originalInitializer == null) {
+      cls._originalInitializer = field.initializer;
+    }
+    final cloner = CloneVisitorNotMembers();
+    field.initializer = cloner.clone(cls._originalInitializer)..parent = field;
+    final transformer = _MetadataTransformer(this, cls);
+    field.initializer.accept(transformer);
+    _invalidatedClasses.remove(cls);
+
+    cls.numberOfFieldsPruned = transformer.numberOfFieldsPruned;
+    Statistics.protobufMetadataFieldsPruned += cls.numberOfFieldsPruned;
+  }
+
+  bool _isUnusedMetadata(_MessageClass cls, MethodInvocation node) {
+    if (node.interfaceTarget != null &&
+        node.interfaceTarget.enclosingClass == _builderInfoClass &&
+        fieldAddingMethods.contains(node.name.name)) {
+      final tagNumber = (node.arguments.positional[0] as IntLiteral).value;
+      return !cls._usedTags.contains(tagNumber);
+    }
+    return false;
+  }
+}
+
+class _MessageClass {
+  Field _metadataField;
+  Expression _originalInitializer;
+  final _usedTags = <int>{};
+  int numberOfFieldsPruned = 0;
+}
+
+class _MetadataTransformer extends Transformer {
+  final ProtobufHandler ph;
+  final _MessageClass cls;
+  int numberOfFieldsPruned = 0;
+
+  _MetadataTransformer(this.ph, this.cls);
+
+  @override
+  TreeNode visitMethodInvocation(MethodInvocation node) {
+    if (!ph._isUnusedMetadata(cls, node)) {
+      super.visitMethodInvocation(node);
+      return node;
+    }
+    // Replace the field metadata method with a dummy call to
+    // `BuilderInfo.add`. This is to preserve the index calculations when
+    // removing a field.
+    // Change the tag-number to 0. Otherwise the decoder will get confused.
+    ++numberOfFieldsPruned;
+    return MethodInvocation(
+        node.receiver,
+        ph._builderInfoAddMethod.name,
+        Arguments(
+          <Expression>[
+            IntLiteral(0), // tagNumber
+            NullLiteral(), // name
+            NullLiteral(), // fieldType
+            NullLiteral(), // defaultOrMaker
+            NullLiteral(), // subBuilder
+            NullLiteral(), // valueOf
+            NullLiteral(), // enumValues
+          ],
+          types: <DartType>[ph.coreTypes.nullType],
+        ),
+        ph._builderInfoAddMethod)
+      ..fileOffset = node.fileOffset;
+  }
+}
diff --git a/pkg/vm/lib/transformations/type_flow/summary_collector.dart b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
index 8b6f850..43c9e3e 100644
--- a/pkg/vm/lib/transformations/type_flow/summary_collector.dart
+++ b/pkg/vm/lib/transformations/type_flow/summary_collector.dart
@@ -18,6 +18,7 @@
 
 import 'calls.dart';
 import 'native_code.dart';
+import 'protobuf_handler.dart' show ProtobufHandler;
 import 'summary.dart';
 import 'types.dart';
 import 'utils.dart';
@@ -521,6 +522,7 @@
   final TypesBuilder _typesBuilder;
   final NativeCodeOracle _nativeCodeOracle;
   final GenericInterfacesInfo _genericInterfacesInfo;
+  final ProtobufHandler _protobufHandler;
 
   final Map<TreeNode, Call> callSites = <TreeNode, Call>{};
   final Map<AsExpression, TypeCheck> explicitCasts =
@@ -580,7 +582,8 @@
       this._entryPointsListener,
       this._typesBuilder,
       this._nativeCodeOracle,
-      this._genericInterfacesInfo) {
+      this._genericInterfacesInfo,
+      this._protobufHandler) {
     assertx(_genericInterfacesInfo != null);
     constantAllocationCollector = new ConstantAllocationCollector(this);
     _nullMethodsAndGetters.addAll(getSelectors(
@@ -598,6 +601,8 @@
     assertx(!member.isAbstract);
     assertx(!(member is Procedure && member.isRedirectingFactoryConstructor));
 
+    _protobufHandler?.beforeSummaryCreation(member);
+
     _staticTypeContext = new StaticTypeContext(member, _environment);
     _variablesInfo = new _VariablesInfoCollector(member);
     _variableValues = new List<TypeExpr>(_variablesInfo.numVariables);
diff --git a/pkg/vm/lib/transformations/type_flow/transformer.dart b/pkg/vm/lib/transformations/type_flow/transformer.dart
index f592d17..ce7f06e 100644
--- a/pkg/vm/lib/transformations/type_flow/transformer.dart
+++ b/pkg/vm/lib/transformations/type_flow/transformer.dart
@@ -17,6 +17,7 @@
 
 import 'analysis.dart';
 import 'calls.dart';
+import 'protobuf_handler.dart' show ProtobufHandler;
 import 'summary.dart';
 import 'table_selector.dart';
 import 'types.dart';
@@ -40,20 +41,31 @@
     Target target, CoreTypes coreTypes, Component component,
     {PragmaAnnotationParser matcher,
     bool treeShakeSignatures: true,
-    bool treeShakeWriteOnlyFields: true}) {
+    bool treeShakeWriteOnlyFields: true,
+    bool treeShakeProtobufs: false}) {
   void ignoreAmbiguousSupertypes(Class cls, Supertype a, Supertype b) {}
   final hierarchy = new ClassHierarchy(component, coreTypes,
       onAmbiguousSupertypes: ignoreAmbiguousSupertypes);
   final types = new TypeEnvironment(coreTypes, hierarchy);
   final libraryIndex = new LibraryIndex.all(component);
   final genericInterfacesInfo = new GenericInterfacesInfoImpl(hierarchy);
+  final protobufHandler = treeShakeProtobufs
+      ? ProtobufHandler.forComponent(component, coreTypes)
+      : null;
 
   Statistics.reset();
   final analysisStopWatch = new Stopwatch()..start();
 
-  final typeFlowAnalysis = new TypeFlowAnalysis(target, component, coreTypes,
-      hierarchy, genericInterfacesInfo, types, libraryIndex,
-      matcher: matcher);
+  final typeFlowAnalysis = new TypeFlowAnalysis(
+      target,
+      component,
+      coreTypes,
+      hierarchy,
+      genericInterfacesInfo,
+      types,
+      libraryIndex,
+      protobufHandler,
+      matcher);
 
   Procedure main = component.mainMethod;
 
diff --git a/pkg/vm/lib/transformations/type_flow/utils.dart b/pkg/vm/lib/transformations/type_flow/utils.dart
index 30ff278..0d68b35 100644
--- a/pkg/vm/lib/transformations/type_flow/utils.dart
+++ b/pkg/vm/lib/transformations/type_flow/utils.dart
@@ -155,6 +155,9 @@
   static int constructorBodiesDropped = 0;
   static int callsDropped = 0;
   static int throwExpressionsPruned = 0;
+  static int protobufMessagesUsed = 0;
+  static int protobufMetadataInitializersUpdated = 0;
+  static int protobufMetadataFieldsPruned = 0;
 
   /// Resets statistic counters.
   static void reset() {
@@ -181,6 +184,9 @@
     constructorBodiesDropped = 0;
     callsDropped = 0;
     throwExpressionsPruned = 0;
+    protobufMessagesUsed = 0;
+    protobufMetadataInitializersUpdated = 0;
+    protobufMetadataFieldsPruned = 0;
   }
 
   static void print(String caption) {
@@ -208,6 +214,9 @@
     ${constructorBodiesDropped} constructor bodies dropped
     ${callsDropped} calls dropped
     ${throwExpressionsPruned} throw expressions pruned
+    ${protobufMessagesUsed} protobuf messages used
+    ${protobufMetadataInitializersUpdated} protobuf metadata initializers updated
+    ${protobufMetadataFieldsPruned} protobuf metadata fields pruned
     """);
   }
 }
diff --git a/pkg/vm/lib/v8_snapshot_profile.dart b/pkg/vm/lib/v8_snapshot_profile.dart
deleted file mode 100644
index 847836d..0000000
--- a/pkg/vm/lib/v8_snapshot_profile.dart
+++ /dev/null
@@ -1,299 +0,0 @@
-// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import "package:expect/expect.dart";
-import "package:dart2js_info/src/graph.dart";
-
-class _NodeInfo {
-  int type;
-  int name;
-  int id;
-  int selfSize;
-  int edgeCount;
-  _NodeInfo(
-    this.type,
-    this.name,
-    this.id,
-    this.selfSize,
-    this.edgeCount,
-  );
-}
-
-const List<String> _kRequiredNodeFields = [
-  "type",
-  "name",
-  "id",
-  "self_size",
-  "edge_count",
-];
-
-class _EdgeInfo {
-  int type;
-  int nameOrIndex;
-  int nodeOffset;
-  _EdgeInfo(
-    this.type,
-    this.nameOrIndex,
-    this.nodeOffset,
-  );
-}
-
-const List<String> _kRequiredEdgeFields = [
-  "type",
-  "name_or_index",
-  "to_node",
-];
-
-class NodeInfo {
-  final String type;
-  final String name;
-  final int id;
-  final int selfSize;
-  NodeInfo(
-    this.type,
-    this.name,
-    this.id,
-    this.selfSize,
-  );
-}
-
-class EdgeInfo {
-  final int target;
-  final String type;
-
-  // Either a string for property names or an int for array/context elements.
-  final dynamic nameOrIndex;
-
-  EdgeInfo(this.target, this.type, this.nameOrIndex);
-}
-
-class V8SnapshotProfile extends Graph<int> {
-  // Indexed by node offset.
-  final Map<int, _NodeInfo> _nodes = {};
-
-  // Indexed by start node offset.
-  final Map<int, List<_EdgeInfo>> _toEdges = {};
-  final Map<int, List<_EdgeInfo>> _fromEdges = {};
-
-  List<String> _nodeFields = [];
-  List<String> _edgeFields = [];
-
-  List<String> _nodeTypes = [];
-  List<String> _edgeTypes = [];
-
-  List<String> _strings = [];
-
-  // Only used to ensure IDs are unique.
-  Set<int> _ids = Set<int>();
-
-  V8SnapshotProfile.fromJson(Map top) {
-    final Map snapshot = top["snapshot"];
-    _parseMetadata(snapshot["meta"]);
-
-    _parseStrings(top["strings"]);
-    Expect.equals(snapshot["node_count"], _parseNodes(top["nodes"]));
-    Expect.equals(snapshot["edge_count"], _parseEdges(top["edges"]));
-
-    _verifyRoot();
-
-    _calculateFromEdges();
-  }
-
-  void _verifyRoot() {
-    // HeapSnapshotWorker.HeapSnapshot.calculateDistances (from HeapSnapshot.js)
-    // assumes that the root does not have more than one edge to any other node
-    // (most likely an oversight).
-    final Set<int> roots = <int>{};
-    for (final edge in _toEdges[root]) {
-      final int to = edge.nodeOffset;
-      Expect.isTrue(!roots.contains(to), "multiple root edges to node ${to}");
-      roots.add(to);
-    }
-
-    // Check that all nodes are reachable from the root (offset 0).
-    final Set<int> enqueued = {root};
-    final dfs = <int>[root];
-    while (!dfs.isEmpty) {
-      final next = dfs.removeLast();
-      for (final edge in _toEdges[next]) {
-        if (!enqueued.contains(edge.nodeOffset)) {
-          enqueued.add(edge.nodeOffset);
-          dfs.add(edge.nodeOffset);
-        }
-      }
-    }
-    Expect.equals(enqueued.length, nodeCount);
-  }
-
-  void _parseMetadata(Map meta) {
-    final List nodeFields = meta["node_fields"];
-    nodeFields.forEach(_nodeFields.add);
-    for (final field in _kRequiredNodeFields) {
-      Expect.isTrue(nodeFields.contains(field), "missing node field ${field}");
-    }
-
-    final List edgeFields = meta["edge_fields"];
-    edgeFields.forEach(_edgeFields.add);
-    for (final field in _kRequiredEdgeFields) {
-      Expect.isTrue(edgeFields.contains(field), "missing edge field ${field}");
-    }
-
-    // First entry of "node_types" is an array with the actual node types. IDK
-    // what the other entries are for.
-    List nodeTypes = meta["node_types"];
-    nodeTypes = nodeTypes[0];
-    nodeTypes.forEach(_nodeTypes.add);
-
-    // Same for edges.
-    List edgeTypes = meta["edge_types"];
-    edgeTypes = edgeTypes[0];
-    edgeTypes.forEach(_edgeTypes.add);
-  }
-
-  int _parseNodes(List nodes) {
-    final int typeIndex = _nodeFields.indexOf("type");
-    final int nameIndex = _nodeFields.indexOf("name");
-    final int idIndex = _nodeFields.indexOf("id");
-    final int selfSizeIndex = _nodeFields.indexOf("self_size");
-    final int edgeCountIndex = _nodeFields.indexOf("edge_count");
-
-    int offset = 0;
-    for (; offset < nodes.length; offset += _nodeFields.length) {
-      final int type = nodes[offset + typeIndex];
-      Expect.isTrue(0 <= type && type < _nodeTypes.length,
-          "node type ${type} outside range [0, ${_nodeTypes.length})");
-
-      final int name = nodes[offset + nameIndex];
-      Expect.isTrue(0 <= name && name < _strings.length,
-          "node name ${name} outside range [0, ${_strings.length})");
-
-      final int id = nodes[offset + idIndex];
-      Expect.isTrue(id >= 0, "negative node ID ${id}");
-      Expect.isFalse(_ids.contains(id), "node ID ${id} already added");
-      _ids.add(id);
-
-      final int selfSize = nodes[offset + selfSizeIndex];
-      Expect.isTrue(selfSize >= 0, "negative node selfSize ${selfSize}");
-
-      final int edgeCount = nodes[offset + edgeCountIndex];
-      Expect.isTrue(edgeCount >= 0, "negative node edgeCount ${edgeCount}");
-
-      _nodes[offset] = _NodeInfo(type, name, id, selfSize, edgeCount);
-    }
-
-    Expect.equals(offset, nodes.length);
-    return offset ~/ _nodeFields.length;
-  }
-
-  int _parseEdges(List edges) {
-    final int typeIndex = _edgeFields.indexOf("type");
-    final int nameOrIndexIndex = _edgeFields.indexOf("name_or_index");
-    final int toNodeIndex = _edgeFields.indexOf("to_node");
-
-    int edgeOffset = 0;
-    for (int nodeOffset = 0;
-        nodeOffset < _nodes.length * _nodeFields.length;
-        nodeOffset += _nodeFields.length) {
-      final int edgeCount = _nodes[nodeOffset].edgeCount;
-      final List<_EdgeInfo> nodeEdges = List<_EdgeInfo>(edgeCount);
-      for (int i = 0; i < edgeCount; ++i, edgeOffset += _edgeFields.length) {
-        final int type = edges[edgeOffset + typeIndex];
-        Expect.isTrue(0 <= type && type < _edgeTypes.length,
-            "edge type ${type} outside range [0, ${_edgeTypes.length}");
-
-        final int nameOrIndex = edges[edgeOffset + nameOrIndexIndex];
-        if (_edgeTypes[type] == "property") {
-          Expect.isTrue(0 <= nameOrIndex && nameOrIndex < _strings.length,
-              "edge name ${nameOrIndex} outside range [0, ${_strings.length}");
-        } else if (_edgeTypes[type] == "element" ||
-            _edgeTypes[type] == "context") {
-          Expect.isTrue(nameOrIndex >= 0, "negative edge index ${nameOrIndex}");
-        }
-
-        final int toNode = edges[edgeOffset + toNodeIndex];
-        checkNode(toNode);
-        nodeEdges[i] = _EdgeInfo(type, nameOrIndex, toNode);
-      }
-      _toEdges[nodeOffset] = nodeEdges;
-    }
-
-    Expect.equals(edgeOffset, edges.length);
-    return edgeOffset ~/ _edgeFields.length;
-  }
-
-  void checkNode(int offset) {
-    Expect.isTrue(offset >= 0, "negative offset ${offset}");
-    Expect.isTrue(offset % _nodeFields.length == 0,
-        "offset ${offset} not a multiple of ${_nodeFields.length}");
-    Expect.isTrue(
-        offset ~/ _nodeFields.length < _nodes.length,
-        "offset ${offset} divided by ${_nodeFields.length} is greater than or "
-        "equal to node count ${_nodes.length}");
-  }
-
-  void _calculateFromEdges() {
-    for (final MapEntry<int, List<_EdgeInfo>> entry in _toEdges.entries) {
-      final int fromNode = entry.key;
-      for (final _EdgeInfo edge in entry.value) {
-        final List<_EdgeInfo> backEdges =
-            _fromEdges.putIfAbsent(edge.nodeOffset, () => <_EdgeInfo>[]);
-        backEdges.add(_EdgeInfo(edge.type, edge.nameOrIndex, fromNode));
-      }
-    }
-  }
-
-  void _parseStrings(List strings) => strings.forEach(_strings.add);
-
-  int get accountedBytes {
-    int sum = 0;
-    for (final _NodeInfo info in _nodes.values) {
-      sum += info.selfSize;
-    }
-    return sum;
-  }
-
-  int get unknownCount {
-    final int unknownType = _nodeTypes.indexOf("Unknown");
-    Expect.isTrue(
-        unknownType >= 0, 'negative type index for "Unknown": ${unknownType}');
-
-    int count = 0;
-    for (final MapEntry<int, _NodeInfo> entry in _nodes.entries) {
-      if (entry.value.type == unknownType) {
-        ++count;
-      }
-    }
-    return count;
-  }
-
-  bool get isEmpty => _nodes.isEmpty;
-  int get nodeCount => _nodes.length;
-
-  Iterable<int> get nodes => _nodes.keys;
-
-  Iterable<int> targetsOf(int source) {
-    return _toEdges[source].map((_EdgeInfo i) => i.nodeOffset);
-  }
-
-  Iterable<int> sourcesOf(int source) {
-    return _fromEdges[source].map((_EdgeInfo i) => i.nodeOffset);
-  }
-
-  int get root => 0;
-
-  NodeInfo operator [](int node) {
-    _NodeInfo info = _nodes[node];
-    final type = info.type != null ? _nodeTypes[info.type] : null;
-    final name = info.name != null ? _strings[info.name] : null;
-    return NodeInfo(type, name, info.id, info.selfSize);
-  }
-
-  Iterable<EdgeInfo> targets(int node) sync* {
-    for (final _EdgeInfo info in _toEdges[node]) {
-      final String type = _edgeTypes[info.type];
-      yield EdgeInfo(info.nodeOffset, type,
-          type == "property" ? _strings[info.nameOrIndex] : info.nameOrIndex);
-    }
-  }
-}
diff --git a/pkg/vm/pubspec.yaml b/pkg/vm/pubspec.yaml
index 27d6379..ba7b719 100644
--- a/pkg/vm/pubspec.yaml
+++ b/pkg/vm/pubspec.yaml
@@ -1,7 +1,7 @@
-# This package is not intended to be published.
 name: vm
-# version: do-not-upload
 description: VM specific Dart code and helper scripts
+# This package is not intended for consumption on pub.dev. DO NOT publish.
+publish_to: none
 
 environment:
   sdk: "^2.7.0"
diff --git a/pkg/vm/test/dominators_test.dart b/pkg/vm/test/dominators_test.dart
new file mode 100644
index 0000000..f9e6ee6
--- /dev/null
+++ b/pkg/vm/test/dominators_test.dart
@@ -0,0 +1,75 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:expect/expect.dart';
+import 'package:vm/dominators.dart';
+
+class StringVertex extends Vertex<StringVertex> {
+  final String name;
+  StringVertex(this.name);
+  String toString() => name;
+}
+
+main() {
+  // small example from [Lenguaer & Tarjan 1979]
+  var R = new StringVertex("R");
+  var A = new StringVertex("A");
+  var B = new StringVertex("B");
+  var C = new StringVertex("C");
+  var D = new StringVertex("D");
+  var E = new StringVertex("E");
+  var F = new StringVertex("F");
+  var G = new StringVertex("G");
+  var H = new StringVertex("H");
+  var I = new StringVertex("I");
+  var J = new StringVertex("J");
+  var K = new StringVertex("K");
+  var L = new StringVertex("L");
+
+  R.successors.add(A);
+  R.successors.add(B);
+  R.successors.add(C);
+  A.successors.add(D);
+  B.successors.add(A);
+  B.successors.add(D);
+  B.successors.add(E);
+  C.successors.add(F);
+  C.successors.add(G);
+  D.successors.add(L);
+  E.successors.add(H);
+  F.successors.add(I);
+  G.successors.add(I);
+  G.successors.add(J);
+  H.successors.add(E);
+  H.successors.add(K);
+  I.successors.add(K);
+  J.successors.add(I);
+  K.successors.add(I);
+  K.successors.add(R);
+  L.successors.add(H);
+
+  computeDominators(R);
+
+  for (var x in [R, A, B, C, D, E, F, G, H, I, J, K, L]) {
+    print("dom($x) = ${x.dominator}");
+  }
+
+  Expect.equals(null, R.dominator);
+
+  Expect.equals(R, I.dominator);
+  Expect.equals(R, K.dominator);
+  Expect.equals(R, C.dominator);
+  Expect.equals(R, H.dominator);
+  Expect.equals(R, E.dominator);
+  Expect.equals(R, A.dominator);
+  Expect.equals(R, D.dominator);
+  Expect.equals(R, B.dominator);
+
+  Expect.equals(C, F.dominator);
+  Expect.equals(C, G.dominator);
+
+  Expect.equals(G, J.dominator);
+
+  Expect.equals(D, L.dominator);
+}
diff --git a/pkg/vm/test/modular_kernel_plus_aot_test.dart b/pkg/vm/test/modular_kernel_plus_aot_test.dart
index 594e11e..6d0dc45 100644
--- a/pkg/vm/test/modular_kernel_plus_aot_test.dart
+++ b/pkg/vm/test/modular_kernel_plus_aot_test.dart
@@ -57,12 +57,14 @@
     const useGlobalTypeFlowAnalysis = true;
     const enableAsserts = false;
     const useProtobufTreeShaker = false;
+    const useProtobufTreeShakerV2 = false;
     await runGlobalTransformations(
         vmTarget,
         component,
         useGlobalTypeFlowAnalysis,
         enableAsserts,
         useProtobufTreeShaker,
+        useProtobufTreeShakerV2,
         ErrorDetector());
 
     // Verify after running global transformations.
diff --git a/pkg/vm/test/snapshot/instruction_sizes_test.dart b/pkg/vm/test/snapshot/instruction_sizes_test.dart
deleted file mode 100644
index a6ce2eb..0000000
--- a/pkg/vm/test/snapshot/instruction_sizes_test.dart
+++ /dev/null
@@ -1,493 +0,0 @@
-// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:io';
-
-import 'package:path/path.dart' as path;
-import 'package:test/test.dart';
-
-import 'package:vm/snapshot/instruction_sizes.dart' as instruction_sizes;
-import 'package:vm/snapshot/program_info.dart';
-import 'package:vm/snapshot/utils.dart';
-
-final dart2native = () {
-  final sdkBin = path.dirname(Platform.executable);
-  final dart2native =
-      path.join(sdkBin, Platform.isWindows ? 'dart2native.bat' : 'dart2native');
-
-  if (!File(dart2native).existsSync()) {
-    throw 'Failed to locate dart2native in the SDK';
-  }
-
-  return path.canonicalize(dart2native);
-}();
-
-void main() async {
-  if (!Platform.executable.contains('dart-sdk')) {
-    // If we are not running from the prebuilt SDK then this test does nothing.
-    return;
-  }
-
-  group('instruction-sizes', () {
-    final testSource = {
-      'input.dart': """
-@pragma('vm:never-inline')
-dynamic makeSomeClosures() {
-  return [
-    () => true,
-    () => false,
-    () => 11,
-  ];
-}
-
-class A {
-  @pragma('vm:never-inline')
-  dynamic tornOff() {
-    return true;
-  }
-}
-
-class B {
-  @pragma('vm:never-inline')
-  dynamic tornOff() {
-    return false;
-  }
-}
-
-class C {
-  static dynamic tornOff() async {
-    return true;
-  }
-}
-
-@pragma('vm:never-inline')
-Function tearOff(dynamic o) {
-  return o.tornOff;
-}
-
-void main(List<String> args) {
-  for (var cl in makeSomeClosures()) {
-    print(cl());
-  }
-  print(tearOff(args.isEmpty ? A() : B()));
-  print(C.tornOff);
-}
-"""
-    };
-
-    // Almost exactly the same source as above, but with few modifications
-    // marked with a 'modified' comment.
-    final testSourceModified = {
-      'input.dart': """
-@pragma('vm:never-inline')
-dynamic makeSomeClosures() {
-  return [
-    () => true,
-    () => false,
-    () => 11,
-    () => {},  // modified
-  ];
-}
-
-class A {
-  @pragma('vm:never-inline')
-  dynamic tornOff() {
-    for (var cl in makeSomeClosures()) {  // modified
-      print(cl());                        // modified
-    }                                     // modified
-    return true;
-  }
-}
-
-class B {
-  @pragma('vm:never-inline')
-  dynamic tornOff() {
-    return false;
-  }
-}
-
-class C {
-  static dynamic tornOff() async {
-    return true;
-  }
-}
-
-@pragma('vm:never-inline')
-Function tearOff(dynamic o) {
-  return o.tornOff;
-}
-
-void main(List<String> args) {
-  // modified
-  print(tearOff(args.isEmpty ? A() : B()));
-  print(C.tornOff);
-}
-"""
-    };
-
-    final testSourceModified2 = {
-      'input.dart': """
-@pragma('vm:never-inline')
-dynamic makeSomeClosures() {
-  return [
-    () => 0,
-  ];
-}
-
-class A {
-  @pragma('vm:never-inline')
-  dynamic tornOff() {
-    return true;
-  }
-}
-
-class B {
-  @pragma('vm:never-inline')
-  dynamic tornOff() {
-    return false;
-  }
-}
-
-class C {
-  static dynamic tornOff() async {
-    return true;
-  }
-}
-
-@pragma('vm:never-inline')
-Function tearOff(dynamic o) {
-  return o.tornOff;
-}
-
-void main(List<String> args) {
-  for (var cl in makeSomeClosures()) {
-    print(cl());
-  }
-  print(tearOff(args.isEmpty ? A() : B()));
-  print(C.tornOff);
-}
-"""
-    };
-
-    test('basic-parsing', () async {
-      await withSymbolSizes('basic-parsing', testSource, (sizesJson) async {
-        final symbols =
-            instruction_sizes.fromJson(await loadJson(File(sizesJson)));
-        expect(symbols, isNotNull,
-            reason: 'Sizes file was successfully parsed');
-        expect(symbols.length, greaterThan(0),
-            reason: 'Sizes file is non-empty');
-
-        // Check for duplicated symbols (using both raw and scrubbed names).
-        // Maps below contain mappings library-uri -> class-name -> names.
-        final symbolRawNames = <String, Map<String, Set<String>>>{};
-        final symbolScrubbedNames = <String, Map<String, Set<String>>>{};
-
-        Set<String> getSetOfNames(Map<String, Map<String, Set<String>>> map,
-            String libraryUri, String className) {
-          return map
-              .putIfAbsent(libraryUri ?? '', () => {})
-              .putIfAbsent(className ?? '', () => {});
-        }
-
-        for (var sym in symbols) {
-          expect(
-              getSetOfNames(symbolRawNames, sym.libraryUri, sym.className)
-                  .add(sym.name.raw),
-              isTrue,
-              reason:
-                  'All symbols should have unique names (within libraries): ${sym.name.raw}');
-          expect(
-              getSetOfNames(symbolScrubbedNames, sym.libraryUri, sym.className)
-                  .add(sym.name.scrubbed),
-              isTrue,
-              reason: 'Scrubbing the name should not make it non-unique');
-        }
-
-        // Check for expected names which should appear in the output.
-        final inputDartSymbolNames =
-            symbolScrubbedNames['package:input/input.dart'];
-        expect(inputDartSymbolNames, isNotNull,
-            reason: 'Symbols from input.dart are included into sizes output');
-
-        expect(inputDartSymbolNames[''], isNotNull,
-            reason: 'Should include top-level members from input.dart');
-        expect(inputDartSymbolNames[''], contains('makeSomeClosures'));
-        final closures = inputDartSymbolNames[''].where(
-            (name) => name.startsWith('makeSomeClosures.<anonymous closure'));
-        expect(closures.length, 3,
-            reason: 'There are three closures inside makeSomeClosure');
-
-        expect(inputDartSymbolNames['A'], isNotNull,
-            reason: 'Should include class A members from input.dart');
-        expect(inputDartSymbolNames['A'], contains('tornOff'));
-        expect(inputDartSymbolNames['A'], contains('[tear-off] tornOff'));
-        expect(inputDartSymbolNames['A'],
-            contains('[tear-off-extractor] get:tornOff'));
-
-        expect(inputDartSymbolNames['B'], isNotNull,
-            reason: 'Should include class B members from input.dart');
-        expect(inputDartSymbolNames['B'], contains('tornOff'));
-        expect(inputDartSymbolNames['B'], contains('[tear-off] tornOff'));
-        expect(inputDartSymbolNames['B'],
-            contains('[tear-off-extractor] get:tornOff'));
-
-        // Presence of async modifier should not cause tear-off name to end
-        // with {body}.
-        expect(inputDartSymbolNames['C'], contains('[tear-off] tornOff'));
-
-        // Check that output does not contain '[unknown stub]'
-        expect(symbolRawNames[''][''], isNot(contains('[unknown stub]')),
-            reason: 'All stubs must be named');
-      });
-    });
-
-    test('program-info', () async {
-      await withSymbolSizes('program-info', testSource, (sizesJson) async {
-        final info = await loadProgramInfo(File(sizesJson));
-        expect(info.root.children, contains('dart:core'));
-        expect(info.root.children, contains('dart:typed_data'));
-        expect(info.root.children, contains('package:input'));
-
-        final inputLib = info.root.children['package:input']
-            .children['package:input/input.dart'];
-        expect(inputLib, isNotNull);
-        expect(inputLib.children, contains('')); // Top-level class.
-        expect(inputLib.children, contains('A'));
-        expect(inputLib.children, contains('B'));
-        expect(inputLib.children, contains('C'));
-
-        final topLevel = inputLib.children[''];
-        expect(topLevel.children, contains('makeSomeClosures'));
-        expect(
-            topLevel.children['makeSomeClosures'].children.length, equals(3));
-
-        for (var name in [
-          '[tear-off] tornOff',
-          'tornOff',
-          'Allocate A',
-          '[tear-off-extractor] get:tornOff'
-        ]) {
-          expect(inputLib.children['A'].children, contains(name));
-          expect(inputLib.children['A'].children[name].children, isEmpty);
-        }
-
-        for (var name in [
-          '[tear-off] tornOff',
-          'tornOff',
-          'Allocate B',
-          '[tear-off-extractor] get:tornOff'
-        ]) {
-          expect(inputLib.children['B'].children, contains(name));
-          expect(inputLib.children['B'].children[name].children, isEmpty);
-        }
-
-        for (var name in ['tornOff{body}', 'tornOff', '[tear-off] tornOff']) {
-          expect(inputLib.children['C'].children, contains(name));
-          expect(inputLib.children['C'].children[name].children, isEmpty);
-        }
-      });
-    });
-
-    test('histograms', () async {
-      await withSymbolSizes('histograms', testSource, (sizesJson) async {
-        final info = await loadProgramInfo(File(sizesJson));
-        final bySymbol = SizesHistogram.from(info, HistogramType.bySymbol);
-        expect(
-            bySymbol.buckets,
-            contains(bySymbol.bucketing.bucketFor(
-                'package:input', 'package:input/input.dart', 'A', 'tornOff')));
-        expect(
-            bySymbol.buckets,
-            contains(bySymbol.bucketing.bucketFor(
-                'package:input', 'package:input/input.dart', 'B', 'tornOff')));
-        expect(
-            bySymbol.buckets,
-            contains(bySymbol.bucketing.bucketFor(
-                'package:input', 'package:input/input.dart', 'C', 'tornOff')));
-
-        final byClass = SizesHistogram.from(info, HistogramType.byClass);
-        expect(
-            byClass.buckets,
-            contains(byClass.bucketing.bucketFor('package:input',
-                'package:input/input.dart', 'A', 'does-not-matter')));
-        expect(
-            byClass.buckets,
-            contains(byClass.bucketing.bucketFor('package:input',
-                'package:input/input.dart', 'B', 'does-not-matter')));
-        expect(
-            byClass.buckets,
-            contains(byClass.bucketing.bucketFor('package:input',
-                'package:input/input.dart', 'C', 'does-not-matter')));
-
-        final byLibrary = SizesHistogram.from(info, HistogramType.byLibrary);
-        expect(
-            byLibrary.buckets,
-            contains(byLibrary.bucketing.bucketFor(
-                'package:input',
-                'package:input/input.dart',
-                'does-not-matter',
-                'does-not-matter')));
-
-        final byPackage = SizesHistogram.from(info, HistogramType.byPackage);
-        expect(
-            byPackage.buckets,
-            contains(byPackage.bucketing.bucketFor(
-                'package:input',
-                'package:input/does-not-matter.dart',
-                'does-not-matter',
-                'does-not-matter')));
-      });
-    });
-
-    // On Windows there is some issue with interpreting entry point URI as a package URI
-    // it instead gets interpreted as a file URI - which breaks comparison. So we
-    // simply ignore entry point library (main.dart).
-    Map<String, dynamic> diffToJson(ProgramInfo diff) {
-      final diffJson = diff.toJson();
-      diffJson.removeWhere((key, _) => key.startsWith('file:'));
-      return diffJson;
-    }
-
-    test('diff', () async {
-      await withSymbolSizes('diff-1', testSource, (sizesJson) async {
-        await withSymbolSizes('diff-2', testSourceModified,
-            (modifiedSizesJson) async {
-          final info = await loadProgramInfo(File(sizesJson));
-          final modifiedInfo = await loadProgramInfo(File(modifiedSizesJson));
-          final diff = computeDiff(info, modifiedInfo);
-
-          expect(
-              diffToJson(diff),
-              equals({
-                '#type': 'library',
-                '@stubs': {'#type': 'library'},
-                '@unknown': {'#type': 'library'},
-                'package:input': {
-                  '#type': 'package',
-                  'package:input/input.dart': {
-                    '#type': 'library',
-                    '': {
-                      '#type': 'class',
-                      'makeSomeClosures': {
-                        '#type': 'function',
-                        '#size': greaterThan(0), // We added code here.
-                        '<anonymous closure @118>': {
-                          '#type': 'function',
-                          '#size': greaterThan(0),
-                        },
-                      },
-                      'main': {
-                        '#type': 'function',
-                        '#size': lessThan(0), // We removed code from main.
-                      },
-                    },
-                    'A': {
-                      '#type': 'class',
-                      'tornOff': {
-                        '#type': 'function',
-                        '#size': greaterThan(0),
-                      },
-                    }
-                  }
-                }
-              }));
-        });
-      });
-    });
-
-    test('diff-collapsed', () async {
-      await withSymbolSizes('diff-collapsed-1', testSource, (sizesJson) async {
-        await withSymbolSizes('diff-collapsed-2', testSourceModified2,
-            (modifiedSizesJson) async {
-          final info = await loadProgramInfo(File(sizesJson),
-              collapseAnonymousClosures: true);
-          final modifiedInfo = await loadProgramInfo(File(modifiedSizesJson),
-              collapseAnonymousClosures: true);
-          final diff = computeDiff(info, modifiedInfo);
-
-          expect(
-              diffToJson(diff),
-              equals({
-                '#type': 'library',
-                '@stubs': {'#type': 'library'},
-                '@unknown': {'#type': 'library'},
-                'package:input': {
-                  '#type': 'package',
-                  'package:input/input.dart': {
-                    '#type': 'library',
-                    '': {
-                      '#type': 'class',
-                      'makeSomeClosures': {
-                        '#size': lessThan(0),
-                        '#type': 'function',
-                        '<anonymous closure>': {
-                          '#size': lessThan(0),
-                          '#type': 'function'
-                        }
-                      }
-                    }
-                  }
-                }
-              }));
-        });
-      });
-    });
-  });
-}
-
-Future withSymbolSizes(String prefix, Map<String, String> source,
-    Future Function(String sizesJson) f) {
-  return withTempDir(prefix, (dir) async {
-    final outputBinary = path.join(dir, 'output.exe');
-    final sizesJson = path.join(dir, 'sizes.json');
-    final packages = path.join(dir, '.packages');
-    final mainDart = path.join(dir, 'main.dart');
-
-    // Create test input.
-    for (var file in source.entries) {
-      await File(path.join(dir, file.key)).writeAsString(file.value);
-    }
-    await File(packages).writeAsString('''
-input:./
-''');
-    await File(mainDart).writeAsString('''
-import 'package:input/input.dart' as input;
-
-void main(List<String> args) => input.main(args);
-''');
-
-    // Compile input.dart to native and output instruction sizes.
-    final result = await Process.run(dart2native, [
-      '-o',
-      outputBinary,
-      '--packages=$packages',
-      '--extra-gen-snapshot-options=--print_instructions_sizes_to=$sizesJson',
-      mainDart,
-    ]);
-
-    expect(result.exitCode, equals(0), reason: '''
-Compilation completed successfully.
-
-stdout: ${result.stdout}
-stderr: ${result.stderr}
-''');
-    expect(File(outputBinary).existsSync(), isTrue,
-        reason: 'Output binary exists');
-    expect(File(sizesJson).existsSync(), isTrue,
-        reason: 'Instruction sizes output exists');
-
-    await f(sizesJson);
-  });
-}
-
-Future withTempDir(String prefix, Future Function(String dir) f) async {
-  final tempDir =
-      Directory.systemTemp.createTempSync('instruction-sizes-test-${prefix}');
-  try {
-    await f(tempDir.path);
-  } finally {
-    tempDir.deleteSync(recursive: true);
-  }
-}
diff --git a/pkg/vm/test/transformations/deferred_loading_test.dart b/pkg/vm/test/transformations/deferred_loading_test.dart
new file mode 100644
index 0000000..4b5f961
--- /dev/null
+++ b/pkg/vm/test/transformations/deferred_loading_test.dart
@@ -0,0 +1,50 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:kernel/target/targets.dart';
+import 'package:kernel/ast.dart';
+import 'package:kernel/kernel.dart';
+import 'package:test/test.dart';
+import 'package:vm/transformations/deferred_loading.dart'
+    show transformComponent;
+
+import '../common_test_utils.dart';
+
+final String pkgVmDir = Platform.script.resolve('../..').toFilePath();
+
+runTestCase(Uri source) async {
+  final target = new TestingVmTarget(new TargetFlags());
+  Component component =
+      await compileTestCaseToKernelProgram(source, target: target);
+
+  component = transformComponent(component);
+
+  // Remove core libraries so the expected output isn't enormous and broken by
+  // core libraries changes.
+  component.libraries.removeWhere((lib) => lib.importUri.scheme == "dart");
+
+  String actual = kernelComponentToString(component);
+
+  // Remove absolute library URIs.
+  actual = actual.replaceAll(new Uri.file(pkgVmDir).toString(), '#pkg/vm');
+
+  compareResultWithExpectationsFile(source, actual);
+}
+
+main() {
+  group('deferred-loading', () {
+    final testCasesDir =
+        new Directory(pkgVmDir + '/testcases/transformations/deferred_loading');
+
+    for (var entry in testCasesDir
+        .listSync(recursive: true, followLinks: false)
+        .reversed) {
+      if (entry.path.endsWith("main.dart")) {
+        test(entry.path, () => runTestCase(entry.uri));
+      }
+    }
+  });
+}
diff --git a/pkg/vm/test/transformations/type_flow/summary_collector_test.dart b/pkg/vm/test/transformations/type_flow/summary_collector_test.dart
index 26c85a6..969556a 100644
--- a/pkg/vm/test/transformations/type_flow/summary_collector_test.dart
+++ b/pkg/vm/test/transformations/type_flow/summary_collector_test.dart
@@ -73,7 +73,8 @@
         typesBuilder,
         new NativeCodeOracle(
             null, new ConstantPragmaAnnotationParser(coreTypes)),
-        new GenericInterfacesInfoImpl(hierarchy));
+        new GenericInterfacesInfoImpl(hierarchy),
+        /*_protobufHandler=*/ null);
   }
 
   String print(TreeNode node) {
diff --git a/pkg/vm/test/transformations/type_flow/transformer_test.dart b/pkg/vm/test/transformations/type_flow/transformer_test.dart
index 123bc44..810b646 100644
--- a/pkg/vm/test/transformations/type_flow/transformer_test.dart
+++ b/pkg/vm/test/transformations/type_flow/transformer_test.dart
@@ -28,9 +28,25 @@
   final coreTypes = new CoreTypes(component);
 
   component = transformComponent(target, coreTypes, component,
-      matcher: new ConstantPragmaAnnotationParser(coreTypes));
+      matcher: new ConstantPragmaAnnotationParser(coreTypes),
+      treeShakeProtobufs: true);
 
-  final actual = kernelLibraryToString(component.mainMethod.enclosingLibrary);
+  String actual = kernelLibraryToString(component.mainMethod.enclosingLibrary);
+
+  // Tests in /protobuf_handler consist of multiple libraries.
+  // Include libraries with protobuf generated messages into the result.
+  if (source.toString().contains('/protobuf_handler/')) {
+    for (var lib in component.libraries) {
+      if (lib.importUri
+          .toString()
+          .contains('/protobuf_handler/lib/generated/')) {
+        lib.name ??= lib.importUri.pathSegments.last;
+        actual += kernelLibraryToString(lib);
+      }
+    }
+    // Remove library paths.
+    actual = actual.replaceAll(Uri.file(pkgVmDir).toString(), 'file:pkg/vm');
+  }
 
   compareResultWithExpectationsFile(source, actual);
 
@@ -42,19 +58,18 @@
     final testCasesDir = new Directory(
         pkgVmDir + '/testcases/transformations/type_flow/transformer');
 
-    for (var entry in testCasesDir
-        .listSync(recursive: true, followLinks: false)
-        .reversed) {
-      if (entry.path.endsWith('.dart')) {
-        final bool enableNullSafety = entry.path.endsWith('_nnbd_strong.dart');
-        final bool enableNNBD =
-            enableNullSafety || entry.path.endsWith('_nnbd.dart');
+    for (var entry
+        in testCasesDir.listSync(recursive: true, followLinks: false)) {
+      final path = entry.path;
+      if (path.endsWith('.dart') && !path.endsWith('.pb.dart')) {
+        final bool enableNullSafety = path.endsWith('_nnbd_strong.dart');
+        final bool enableNNBD = enableNullSafety || path.endsWith('_nnbd.dart');
         final List<String> experimentalFlags = [
           if (enableNNBD) 'non-nullable',
         ];
-        test(entry.path,
+        test(path,
             () => runTestCase(entry.uri, experimentalFlags, enableNullSafety));
       }
     }
-  });
+  }, timeout: Timeout.none);
 }
diff --git a/pkg/vm/testcases/transformations/deferred_loading/a.dart b/pkg/vm/testcases/transformations/deferred_loading/a.dart
new file mode 100644
index 0000000..4fa8635
--- /dev/null
+++ b/pkg/vm/testcases/transformations/deferred_loading/a.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library a;
+
+import 'd.dart' deferred as d;
+
+a() async {
+  print("A");
+  await d.loadLibrary();
+  return d.d();
+}
diff --git a/pkg/vm/testcases/transformations/deferred_loading/b.dart b/pkg/vm/testcases/transformations/deferred_loading/b.dart
new file mode 100644
index 0000000..c6cb3e2
--- /dev/null
+++ b/pkg/vm/testcases/transformations/deferred_loading/b.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library b;
+
+import 'c.dart' as c;
+
+b() async {
+  print("B");
+  return c.c();
+}
diff --git a/pkg/vm/testcases/transformations/deferred_loading/c.dart b/pkg/vm/testcases/transformations/deferred_loading/c.dart
new file mode 100644
index 0000000..12892dc
--- /dev/null
+++ b/pkg/vm/testcases/transformations/deferred_loading/c.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library c;
+
+import 'b.dart' as b;
+import 'f.dart' deferred as f;
+
+c() async {
+  print("C");
+  await f.loadLibrary();
+  return f.f();
+}
diff --git a/pkg/vm/testcases/transformations/deferred_loading/d.dart b/pkg/vm/testcases/transformations/deferred_loading/d.dart
new file mode 100644
index 0000000..410714e
--- /dev/null
+++ b/pkg/vm/testcases/transformations/deferred_loading/d.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library d;
+
+import 'e.dart' as e;
+
+d() async {
+  print("D");
+  return e.e();
+}
diff --git a/pkg/vm/testcases/transformations/deferred_loading/e.dart b/pkg/vm/testcases/transformations/deferred_loading/e.dart
new file mode 100644
index 0000000..e512b6e
--- /dev/null
+++ b/pkg/vm/testcases/transformations/deferred_loading/e.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library e;
+
+import 'g.dart' deferred as g;
+
+e() async {
+  print("E");
+  await g.loadLibrary();
+  return g.g();
+}
diff --git a/pkg/vm/testcases/transformations/deferred_loading/f.dart b/pkg/vm/testcases/transformations/deferred_loading/f.dart
new file mode 100644
index 0000000..5ba9511
--- /dev/null
+++ b/pkg/vm/testcases/transformations/deferred_loading/f.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library f;
+
+import 'g.dart' deferred as g;
+import 'i.dart' deferred as i;
+
+f() async {
+  print("F");
+  await g.loadLibrary();
+  return g.g();
+  await i.loadLibrary();
+  return i.i();
+}
diff --git a/pkg/vm/testcases/transformations/deferred_loading/g.dart b/pkg/vm/testcases/transformations/deferred_loading/g.dart
new file mode 100644
index 0000000..b7c4bc5
--- /dev/null
+++ b/pkg/vm/testcases/transformations/deferred_loading/g.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library g;
+
+import 'h.dart' as h;
+
+g() async {
+  print("G");
+}
diff --git a/pkg/vm/testcases/transformations/deferred_loading/h.dart b/pkg/vm/testcases/transformations/deferred_loading/h.dart
new file mode 100644
index 0000000..8870dd9
--- /dev/null
+++ b/pkg/vm/testcases/transformations/deferred_loading/h.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library h;
+
+import 'g.dart' as g;
+
+h() async {
+  print("H");
+}
diff --git a/pkg/vm/testcases/transformations/deferred_loading/i.dart b/pkg/vm/testcases/transformations/deferred_loading/i.dart
new file mode 100644
index 0000000..2bbeb73
--- /dev/null
+++ b/pkg/vm/testcases/transformations/deferred_loading/i.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library i;
+
+import 'j.dart' deferred as j;
+import 'b.dart' as b;
+
+i() async {
+  print("I");
+  await j.loadLibrary();
+  return j.j();
+}
diff --git a/pkg/vm/testcases/transformations/deferred_loading/j.dart b/pkg/vm/testcases/transformations/deferred_loading/j.dart
new file mode 100644
index 0000000..9392e67
--- /dev/null
+++ b/pkg/vm/testcases/transformations/deferred_loading/j.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library j;
+
+import 'a.dart' as a;
+
+j() async {
+  print("J");
+}
diff --git a/pkg/vm/testcases/transformations/deferred_loading/main.dart b/pkg/vm/testcases/transformations/deferred_loading/main.dart
new file mode 100644
index 0000000..72703c4
--- /dev/null
+++ b/pkg/vm/testcases/transformations/deferred_loading/main.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library main;
+
+import 'a.dart';
+import 'b.dart';
+
+main() async {
+  await a();
+  await b();
+}
diff --git a/pkg/vm/testcases/transformations/deferred_loading/main.dart.expect b/pkg/vm/testcases/transformations/deferred_loading/main.dart.expect
new file mode 100644
index 0000000..3dbc78e
--- /dev/null
+++ b/pkg/vm/testcases/transformations/deferred_loading/main.dart.expect
@@ -0,0 +1,426 @@
+main = #lib::main;
+ [@vm.loading-units.metadata=LoadingUnitsMetadata(
+LoadingUnit(id=1, parent=0,
+  #lib
+  #pkg/vm/testcases/transformations/deferred_loading/a.dart
+  #pkg/vm/testcases/transformations/deferred_loading/b.dart
+  #pkg/vm/testcases/transformations/deferred_loading/c.dart
+  dart:async
+  dart:collection
+  dart:convert
+  dart:developer
+  dart:ffi
+  dart:_internal
+  dart:isolate
+  dart:math
+  dart:mirrors
+  dart:typed_data
+  dart:vmservice_io
+  dart:_vmservice
+  dart:_builtin
+  dart:nativewrappers
+  dart:io
+  dart:cli
+  dart:wasm
+  dart:core
+  dart:_http
+)
+LoadingUnit(id=2, parent=1,
+  #pkg/vm/testcases/transformations/deferred_loading/d.dart
+  #pkg/vm/testcases/transformations/deferred_loading/e.dart
+)
+LoadingUnit(id=3, parent=1,
+  #pkg/vm/testcases/transformations/deferred_loading/f.dart
+)
+LoadingUnit(id=4, parent=1,
+  #pkg/vm/testcases/transformations/deferred_loading/g.dart
+  #pkg/vm/testcases/transformations/deferred_loading/h.dart
+)
+LoadingUnit(id=5, parent=3,
+  #pkg/vm/testcases/transformations/deferred_loading/i.dart
+)
+LoadingUnit(id=6, parent=5,
+  #pkg/vm/testcases/transformations/deferred_loading/j.dart
+)
+)]library #lib from "#lib" as #lib {
+
+  import "#pkg/vm/testcases/transformations/deferred_loading/a.dart";
+  import "#pkg/vm/testcases/transformations/deferred_loading/b.dart";
+
+  static method main() → dynamic /* originally async */ {
+    final dart.async::_AsyncAwaitCompleter<dynamic>* :async_completer = new dart.async::_AsyncAwaitCompleter::•<dynamic>();
+    FutureOr<dynamic>* :return_value;
+    dynamic :async_stack_trace;
+    (dynamic) →* dynamic :async_op_then;
+    (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
+    dart.core::int* :await_jump_var = 0;
+    dynamic :await_ctx_var;
+    dynamic :saved_try_context_var0;
+    function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+      try {
+        #L1:
+        {
+          [yield] let dynamic #t1 = dart.async::_awaitHelper(a::a(), :async_op_then, :async_op_error, :async_op) in null;
+          :result;
+          [yield] let dynamic #t2 = dart.async::_awaitHelper(b::b(), :async_op_then, :async_op_error, :async_op) in null;
+          :result;
+        }
+        dart.async::_completeOnAsyncReturn(:async_completer, :return_value);
+        return;
+      }
+      on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
+        :async_completer.{dart.async::Completer::completeError}(exception, stack_trace);
+      }
+    :async_stack_trace = dart.async::_asyncStackTraceHelper(:async_op);
+    :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
+    :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
+    :async_completer.{dart.async::_AsyncAwaitCompleter::start}(:async_op);
+    return :async_completer.{dart.async::Completer::future};
+  }
+}
+library a from "#pkg/vm/testcases/transformations/deferred_loading/a.dart" as a {
+
+  import "#pkg/vm/testcases/transformations/deferred_loading/d.dart" deferred as d;
+
+  static method a() → dynamic /* originally async */ {
+    final dart.async::_AsyncAwaitCompleter<dynamic>* :async_completer = new dart.async::_AsyncAwaitCompleter::•<dynamic>();
+    FutureOr<dynamic>* :return_value;
+    dynamic :async_stack_trace;
+    (dynamic) →* dynamic :async_op_then;
+    (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
+    dart.core::int* :await_jump_var = 0;
+    dynamic :await_ctx_var;
+    dynamic :saved_try_context_var0;
+    function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+      try {
+        #L2:
+        {
+          dart.core::print("A");
+          [yield] let dynamic #t3 = dart.async::_awaitHelper(LoadLibrary(d), :async_op_then, :async_op_error, :async_op) in null;
+          :result;
+          :return_value = let final dynamic #t4 = CheckLibraryIsLoaded(d) in d::d();
+          break #L2;
+        }
+        dart.async::_completeOnAsyncReturn(:async_completer, :return_value);
+        return;
+      }
+      on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
+        :async_completer.{dart.async::Completer::completeError}(exception, stack_trace);
+      }
+    :async_stack_trace = dart.async::_asyncStackTraceHelper(:async_op);
+    :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
+    :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
+    :async_completer.{dart.async::_AsyncAwaitCompleter::start}(:async_op);
+    return :async_completer.{dart.async::Completer::future};
+  }
+}
+library b from "#pkg/vm/testcases/transformations/deferred_loading/b.dart" as b {
+
+  import "#pkg/vm/testcases/transformations/deferred_loading/c.dart" as c;
+
+  static method b() → dynamic /* originally async */ {
+    final dart.async::_AsyncAwaitCompleter<dynamic>* :async_completer = new dart.async::_AsyncAwaitCompleter::•<dynamic>();
+    FutureOr<dynamic>* :return_value;
+    dynamic :async_stack_trace;
+    (dynamic) →* dynamic :async_op_then;
+    (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
+    dart.core::int* :await_jump_var = 0;
+    dynamic :await_ctx_var;
+    function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+      try {
+        #L3:
+        {
+          dart.core::print("B");
+          :return_value = c::c();
+          break #L3;
+        }
+        dart.async::_completeOnAsyncReturn(:async_completer, :return_value);
+        return;
+      }
+      on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
+        :async_completer.{dart.async::Completer::completeError}(exception, stack_trace);
+      }
+    :async_stack_trace = dart.async::_asyncStackTraceHelper(:async_op);
+    :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
+    :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
+    :async_completer.{dart.async::_AsyncAwaitCompleter::start}(:async_op);
+    return :async_completer.{dart.async::Completer::future};
+  }
+}
+library d from "#pkg/vm/testcases/transformations/deferred_loading/d.dart" as d {
+
+  import "#pkg/vm/testcases/transformations/deferred_loading/e.dart" as e;
+
+  static method d() → dynamic /* originally async */ {
+    final dart.async::_AsyncAwaitCompleter<dynamic>* :async_completer = new dart.async::_AsyncAwaitCompleter::•<dynamic>();
+    FutureOr<dynamic>* :return_value;
+    dynamic :async_stack_trace;
+    (dynamic) →* dynamic :async_op_then;
+    (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
+    dart.core::int* :await_jump_var = 0;
+    dynamic :await_ctx_var;
+    function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+      try {
+        #L4:
+        {
+          dart.core::print("D");
+          :return_value = e::e();
+          break #L4;
+        }
+        dart.async::_completeOnAsyncReturn(:async_completer, :return_value);
+        return;
+      }
+      on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
+        :async_completer.{dart.async::Completer::completeError}(exception, stack_trace);
+      }
+    :async_stack_trace = dart.async::_asyncStackTraceHelper(:async_op);
+    :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
+    :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
+    :async_completer.{dart.async::_AsyncAwaitCompleter::start}(:async_op);
+    return :async_completer.{dart.async::Completer::future};
+  }
+}
+library c from "#pkg/vm/testcases/transformations/deferred_loading/c.dart" as c {
+
+  import "#pkg/vm/testcases/transformations/deferred_loading/b.dart" as b;
+  import "#pkg/vm/testcases/transformations/deferred_loading/f.dart" deferred as f;
+
+  static method c() → dynamic /* originally async */ {
+    final dart.async::_AsyncAwaitCompleter<dynamic>* :async_completer = new dart.async::_AsyncAwaitCompleter::•<dynamic>();
+    FutureOr<dynamic>* :return_value;
+    dynamic :async_stack_trace;
+    (dynamic) →* dynamic :async_op_then;
+    (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
+    dart.core::int* :await_jump_var = 0;
+    dynamic :await_ctx_var;
+    dynamic :saved_try_context_var0;
+    function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+      try {
+        #L5:
+        {
+          dart.core::print("C");
+          [yield] let dynamic #t5 = dart.async::_awaitHelper(LoadLibrary(f), :async_op_then, :async_op_error, :async_op) in null;
+          :result;
+          :return_value = let final dynamic #t6 = CheckLibraryIsLoaded(f) in f::f();
+          break #L5;
+        }
+        dart.async::_completeOnAsyncReturn(:async_completer, :return_value);
+        return;
+      }
+      on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
+        :async_completer.{dart.async::Completer::completeError}(exception, stack_trace);
+      }
+    :async_stack_trace = dart.async::_asyncStackTraceHelper(:async_op);
+    :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
+    :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
+    :async_completer.{dart.async::_AsyncAwaitCompleter::start}(:async_op);
+    return :async_completer.{dart.async::Completer::future};
+  }
+}
+library e from "#pkg/vm/testcases/transformations/deferred_loading/e.dart" as e {
+
+  import "#pkg/vm/testcases/transformations/deferred_loading/g.dart" deferred as g;
+
+  static method e() → dynamic /* originally async */ {
+    final dart.async::_AsyncAwaitCompleter<dynamic>* :async_completer = new dart.async::_AsyncAwaitCompleter::•<dynamic>();
+    FutureOr<dynamic>* :return_value;
+    dynamic :async_stack_trace;
+    (dynamic) →* dynamic :async_op_then;
+    (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
+    dart.core::int* :await_jump_var = 0;
+    dynamic :await_ctx_var;
+    dynamic :saved_try_context_var0;
+    function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+      try {
+        #L6:
+        {
+          dart.core::print("E");
+          [yield] let dynamic #t7 = dart.async::_awaitHelper(LoadLibrary(g), :async_op_then, :async_op_error, :async_op) in null;
+          :result;
+          :return_value = let final dynamic #t8 = CheckLibraryIsLoaded(g) in g::g();
+          break #L6;
+        }
+        dart.async::_completeOnAsyncReturn(:async_completer, :return_value);
+        return;
+      }
+      on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
+        :async_completer.{dart.async::Completer::completeError}(exception, stack_trace);
+      }
+    :async_stack_trace = dart.async::_asyncStackTraceHelper(:async_op);
+    :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
+    :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
+    :async_completer.{dart.async::_AsyncAwaitCompleter::start}(:async_op);
+    return :async_completer.{dart.async::Completer::future};
+  }
+}
+library f from "#pkg/vm/testcases/transformations/deferred_loading/f.dart" as f {
+
+  import "#pkg/vm/testcases/transformations/deferred_loading/g.dart" deferred as g;
+  import "#pkg/vm/testcases/transformations/deferred_loading/i.dart" deferred as i;
+
+  static method f() → dynamic /* originally async */ {
+    final dart.async::_AsyncAwaitCompleter<dynamic>* :async_completer = new dart.async::_AsyncAwaitCompleter::•<dynamic>();
+    FutureOr<dynamic>* :return_value;
+    dynamic :async_stack_trace;
+    (dynamic) →* dynamic :async_op_then;
+    (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
+    dart.core::int* :await_jump_var = 0;
+    dynamic :await_ctx_var;
+    dynamic :saved_try_context_var0;
+    function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+      try {
+        #L7:
+        {
+          dart.core::print("F");
+          [yield] let dynamic #t9 = dart.async::_awaitHelper(LoadLibrary(g), :async_op_then, :async_op_error, :async_op) in null;
+          :result;
+          :return_value = let final dynamic #t10 = CheckLibraryIsLoaded(g) in g::g();
+          break #L7;
+          [yield] let dynamic #t11 = dart.async::_awaitHelper(LoadLibrary(i), :async_op_then, :async_op_error, :async_op) in null;
+          :result;
+          :return_value = let final dynamic #t12 = CheckLibraryIsLoaded(i) in i::i();
+          break #L7;
+        }
+        dart.async::_completeOnAsyncReturn(:async_completer, :return_value);
+        return;
+      }
+      on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
+        :async_completer.{dart.async::Completer::completeError}(exception, stack_trace);
+      }
+    :async_stack_trace = dart.async::_asyncStackTraceHelper(:async_op);
+    :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
+    :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
+    :async_completer.{dart.async::_AsyncAwaitCompleter::start}(:async_op);
+    return :async_completer.{dart.async::Completer::future};
+  }
+}
+library g from "#pkg/vm/testcases/transformations/deferred_loading/g.dart" as g {
+
+  import "#pkg/vm/testcases/transformations/deferred_loading/h.dart" as h;
+
+  static method g() → dynamic /* originally async */ {
+    final dart.async::_AsyncAwaitCompleter<dynamic>* :async_completer = new dart.async::_AsyncAwaitCompleter::•<dynamic>();
+    FutureOr<dynamic>* :return_value;
+    dynamic :async_stack_trace;
+    (dynamic) →* dynamic :async_op_then;
+    (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
+    dart.core::int* :await_jump_var = 0;
+    dynamic :await_ctx_var;
+    function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+      try {
+        #L8:
+        {
+          dart.core::print("G");
+        }
+        dart.async::_completeOnAsyncReturn(:async_completer, :return_value);
+        return;
+      }
+      on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
+        :async_completer.{dart.async::Completer::completeError}(exception, stack_trace);
+      }
+    :async_stack_trace = dart.async::_asyncStackTraceHelper(:async_op);
+    :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
+    :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
+    :async_completer.{dart.async::_AsyncAwaitCompleter::start}(:async_op);
+    return :async_completer.{dart.async::Completer::future};
+  }
+}
+library i from "#pkg/vm/testcases/transformations/deferred_loading/i.dart" as i {
+
+  import "#pkg/vm/testcases/transformations/deferred_loading/j.dart" deferred as j;
+  import "#pkg/vm/testcases/transformations/deferred_loading/b.dart" as b;
+
+  static method i() → dynamic /* originally async */ {
+    final dart.async::_AsyncAwaitCompleter<dynamic>* :async_completer = new dart.async::_AsyncAwaitCompleter::•<dynamic>();
+    FutureOr<dynamic>* :return_value;
+    dynamic :async_stack_trace;
+    (dynamic) →* dynamic :async_op_then;
+    (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
+    dart.core::int* :await_jump_var = 0;
+    dynamic :await_ctx_var;
+    dynamic :saved_try_context_var0;
+    function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+      try {
+        #L9:
+        {
+          dart.core::print("I");
+          [yield] let dynamic #t13 = dart.async::_awaitHelper(LoadLibrary(j), :async_op_then, :async_op_error, :async_op) in null;
+          :result;
+          :return_value = let final dynamic #t14 = CheckLibraryIsLoaded(j) in j::j();
+          break #L9;
+        }
+        dart.async::_completeOnAsyncReturn(:async_completer, :return_value);
+        return;
+      }
+      on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
+        :async_completer.{dart.async::Completer::completeError}(exception, stack_trace);
+      }
+    :async_stack_trace = dart.async::_asyncStackTraceHelper(:async_op);
+    :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
+    :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
+    :async_completer.{dart.async::_AsyncAwaitCompleter::start}(:async_op);
+    return :async_completer.{dart.async::Completer::future};
+  }
+}
+library h from "#pkg/vm/testcases/transformations/deferred_loading/h.dart" as h {
+
+  import "#pkg/vm/testcases/transformations/deferred_loading/g.dart" as g;
+
+  static method h() → dynamic /* originally async */ {
+    final dart.async::_AsyncAwaitCompleter<dynamic>* :async_completer = new dart.async::_AsyncAwaitCompleter::•<dynamic>();
+    FutureOr<dynamic>* :return_value;
+    dynamic :async_stack_trace;
+    (dynamic) →* dynamic :async_op_then;
+    (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
+    dart.core::int* :await_jump_var = 0;
+    dynamic :await_ctx_var;
+    function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+      try {
+        #L10:
+        {
+          dart.core::print("H");
+        }
+        dart.async::_completeOnAsyncReturn(:async_completer, :return_value);
+        return;
+      }
+      on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
+        :async_completer.{dart.async::Completer::completeError}(exception, stack_trace);
+      }
+    :async_stack_trace = dart.async::_asyncStackTraceHelper(:async_op);
+    :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
+    :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
+    :async_completer.{dart.async::_AsyncAwaitCompleter::start}(:async_op);
+    return :async_completer.{dart.async::Completer::future};
+  }
+}
+library j from "#pkg/vm/testcases/transformations/deferred_loading/j.dart" as j {
+
+  import "#pkg/vm/testcases/transformations/deferred_loading/a.dart" as a;
+
+  static method j() → dynamic /* originally async */ {
+    final dart.async::_AsyncAwaitCompleter<dynamic>* :async_completer = new dart.async::_AsyncAwaitCompleter::•<dynamic>();
+    FutureOr<dynamic>* :return_value;
+    dynamic :async_stack_trace;
+    (dynamic) →* dynamic :async_op_then;
+    (dart.core::Object*, dart.core::StackTrace*) →* dynamic :async_op_error;
+    dart.core::int* :await_jump_var = 0;
+    dynamic :await_ctx_var;
+    function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+      try {
+        #L11:
+        {
+          dart.core::print("J");
+        }
+        dart.async::_completeOnAsyncReturn(:async_completer, :return_value);
+        return;
+      }
+      on dynamic catch(dynamic exception, dart.core::StackTrace* stack_trace) {
+        :async_completer.{dart.async::Completer::completeError}(exception, stack_trace);
+      }
+    :async_stack_trace = dart.async::_asyncStackTraceHelper(:async_op);
+    :async_op_then = dart.async::_asyncThenWrapperHelper(:async_op);
+    :async_op_error = dart.async::_asyncErrorWrapperHelper(:async_op);
+    :async_completer.{dart.async::_AsyncAwaitCompleter::start}(:async_op);
+    return :async_completer.{dart.async::Completer::future};
+  }
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/compile_protos.sh b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/compile_protos.sh
new file mode 100755
index 0000000..8031891
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/compile_protos.sh
@@ -0,0 +1,19 @@
+#!/usr/bin/env bash
+# Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+# Running this script requires having protoc_plugin installed in your path.
+
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
+
+rm -rf $DIR/lib/generated
+mkdir $DIR/lib/generated
+
+# Directory of the script
+GENERATED_DIR=$DIR/lib/generated
+
+protoc --dart_out=$GENERATED_DIR -I$DIR/protos $DIR/protos/*.proto
+rm $GENERATED_DIR/*.pbenum.dart $GENERATED_DIR/*.pbjson.dart $GENERATED_DIR/*.pbserver.dart
+
+dartfmt -w $DIR/lib/generated
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/create_test.dart b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/create_test.dart
new file mode 100644
index 0000000..1912459
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/create_test.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:test/test.dart';
+
+import 'generated/foo.pb.dart';
+
+main() {
+  FooKeep foo = FooKeep()
+    ..barKeep = (BarKeep()..aKeep = 5)
+    ..mapKeep['foo'] = (BarKeep()..aKeep = 2)
+    ..aKeep = 43;
+  test('retrieving values', () {
+    expect(foo.barKeep.aKeep, 5);
+    expect(foo.mapKeep['foo'].aKeep, 2);
+    expect(foo.hasHasKeep(), false);
+    expect(foo.aKeep, 43);
+    foo.clearClearKeep();
+  });
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/create_test.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/create_test.dart.expect
new file mode 100644
index 0000000..f23f5f6
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/create_test.dart.expect
@@ -0,0 +1,133 @@
+library #lib;
+import self as self;
+import "generated/foo.pb.dart" as pb;
+import "dart:core" as core;
+import "package:test_core/test_core.dart" as tes;
+import "package:test_api/src/frontend/expect.dart" as exp;
+
+import "package:test/test.dart";
+import "file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart";
+
+static method main() → dynamic {
+  pb::FooKeep* foo = let final pb::FooKeep* #t1 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep] pb::FooKeep::•() in block {
+    [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.barKeep] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pb::FooKeep::barKeep} = let final pb::BarKeep* #t2 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep] pb::BarKeep::•() in block {
+      [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pb::BarKeep::aKeep} = 5;
+    } =>#t2;
+    [@vm.call-site-attributes.metadata=receiverType:dart.core::Map<dart.core::String*, library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep*>*] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.mapKeep] [@vm.inferred-type.metadata=!] #t1.{pb::FooKeep::mapKeep}.{core::Map::[]=}("foo", let final pb::BarKeep* #t3 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep] pb::BarKeep::•() in block {
+      [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep] [@vm.inferred-type.metadata=!? (skip check)] #t3.{pb::BarKeep::aKeep} = 2;
+    } =>#t3);
+    [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.aKeep] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pb::FooKeep::aKeep} = 43;
+  } =>#t1;
+  tes::test("retrieving values", () → core::Null? {
+    exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep??] [@vm.inferred-type.metadata=int] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.barKeep] [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep?] foo.{pb::FooKeep::barKeep}.{pb::BarKeep::aKeep}, 5);
+    exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep??] [@vm.inferred-type.metadata=int] [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep?] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.mapKeep] [@vm.inferred-type.metadata=!] foo.{pb::FooKeep::mapKeep}.{core::Map::[]}("foo").{pb::BarKeep::aKeep}, 2);
+    exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.hasHasKeep] [@vm.inferred-type.metadata=dart.core::bool (skip check)] foo.{pb::FooKeep::hasHasKeep}(), false);
+    exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.aKeep] [@vm.inferred-type.metadata=int] foo.{pb::FooKeep::aKeep}, 43);
+    [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.clearClearKeep] [@vm.inferred-type.metadata=!? (skip check)] foo.{pb::FooKeep::clearClearKeep}();
+  });
+}
+library foo.pb.dart;
+import self as self;
+import "package:protobuf/protobuf.dart" as pro;
+import "dart:core" as core;
+
+import "dart:core" as $core;
+import "package:protobuf/protobuf.dart" as $pb;
+
+class FooKeep extends pro::GeneratedMessage {
+[@vm.inferred-type.metadata=protobuf::BuilderInfo?]  static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t1 = new pro::BuilderInfo::•("FooKeep", createEmptyInstance: #C1) in block {
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::BarKeep*>(1, "barKeep", protoName: "barKeep", subBuilder: #C2);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::add}<core::Null?>(0, null, null, null, null, null, null);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.m] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::m}<core::String*, self::BarKeep*>(3, "mapKeep", protoName: "mapKeep", entryClassName: "FooKeep.MapKeepEntry", keyFieldType: #C3, valueFieldType: #C4, valueCreator: #C2);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::add}<core::Null?>(0, null, null, null, null, null, null);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::a}<core::int*>(5, "aKeep", #C5, protoName: "aKeep");
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::HasKeep*>(6, "hasKeep", protoName: "hasKeep", subBuilder: #C6);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::ClearKeep*>(7, "clearKeep", protoName: "clearKeep", subBuilder: #C7);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::hasRequiredFields} = false;
+  } =>#t1;
+  constructor _() → self::FooKeep*
+    : super pro::GeneratedMessage::•()
+    ;
+  static factory •() → self::FooKeep*
+    return [@vm.inferred-type.metadata=foo.pb.dart::FooKeep] self::FooKeep::create();
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3]  get info_() → pro::BuilderInfo*
+    return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::FooKeep::_i;
+  @#C10
+  static method create() → self::FooKeep*
+    return new self::FooKeep::_();
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:4]  @#C12
+  get barKeep() → self::BarKeep*
+    return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getN] [@vm.inferred-type.metadata=foo.pb.dart::BarKeep? (skip check)] this.{pro::GeneratedMessage::$_getN}<self::BarKeep*>(0);
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5]  @#C12
+  set barKeep([@vm.inferred-type.metadata=foo.pb.dart::BarKeep] self::BarKeep* v) → void {
+    [@vm.direct-call.metadata=protobuf::GeneratedMessage.setField] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::setField}(1, v);
+  }
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:6]  @#C14
+  get mapKeep() → core::Map<core::String*, self::BarKeep*>*
+    return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getMap] [@vm.inferred-type.metadata=! (skip check)] this.{pro::GeneratedMessage::$_getMap}<core::String*, self::BarKeep*>(2);
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:7]  @#C16
+  get aKeep() → core::int*
+    return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getIZ] [@vm.inferred-type.metadata=int (skip check)] this.{pro::GeneratedMessage::$_getIZ}(4);
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:8]  @#C16
+  set aKeep([@vm.inferred-type.metadata=dart.core::_Smi (value: 43)] core::int* v) → void {
+    [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_setSignedInt32] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::$_setSignedInt32}(4, v);
+  }
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10]  @#C18
+  method hasHasKeep() → core::bool*
+    return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_has] [@vm.inferred-type.metadata=dart.core::bool (skip check)] this.{pro::GeneratedMessage::$_has}(5);
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12]  @#C20
+  method clearClearKeep() → void
+    return [@vm.direct-call.metadata=protobuf::GeneratedMessage.clearField] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] this.{pro::GeneratedMessage::clearField}(7);
+}
+class BarKeep extends pro::GeneratedMessage {
+[@vm.inferred-type.metadata=protobuf::BuilderInfo?]  static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t2 = new pro::BuilderInfo::•("BarKeep", createEmptyInstance: #C2) in block {
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::BuilderInfo::a}<core::int*>(1, "aKeep", #C5, protoName: "aKeep");
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::BuilderInfo::add}<core::Null?>(0, null, null, null, null, null, null);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::BuilderInfo::hasRequiredFields} = false;
+  } =>#t2;
+  constructor _() → self::BarKeep*
+    : super pro::GeneratedMessage::•()
+    ;
+  static factory •() → self::BarKeep*
+    return [@vm.inferred-type.metadata=foo.pb.dart::BarKeep] self::BarKeep::create();
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3]  get info_() → pro::BuilderInfo*
+    return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::BarKeep::_i;
+  @#C10
+  static method create() → self::BarKeep*
+    return new self::BarKeep::_();
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:7]  @#C12
+  get aKeep() → core::int*
+    return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getIZ] [@vm.inferred-type.metadata=int (skip check)] this.{pro::GeneratedMessage::$_getIZ}(0);
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:8]  @#C12
+  set aKeep([@vm.inferred-type.metadata=dart.core::_Smi] core::int* v) → void {
+    [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_setSignedInt32] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::$_setSignedInt32}(0, v);
+  }
+}
+class HasKeep extends pro::GeneratedMessage {
+[@vm.inferred-type.metadata=protobuf::BuilderInfo?]  static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t3 = new pro::BuilderInfo::•("HasKeep", createEmptyInstance: #C6) in block {
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t3.{pro::BuilderInfo::add}<core::Null?>(0, null, null, null, null, null, null);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t3.{pro::BuilderInfo::hasRequiredFields} = false;
+  } =>#t3;
+  constructor _() → self::HasKeep*
+    : super pro::GeneratedMessage::•()
+    ;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3]  get info_() → pro::BuilderInfo*
+    return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::HasKeep::_i;
+  @#C10
+  static method create() → self::HasKeep*
+    return new self::HasKeep::_();
+}
+class ClearKeep extends pro::GeneratedMessage {
+[@vm.inferred-type.metadata=protobuf::BuilderInfo?]  static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t4 = new pro::BuilderInfo::•("ClearKeep", createEmptyInstance: #C7) in block {
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t4.{pro::BuilderInfo::add}<core::Null?>(0, null, null, null, null, null, null);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t4.{pro::BuilderInfo::hasRequiredFields} = false;
+  } =>#t4;
+  constructor _() → self::ClearKeep*
+    : super pro::GeneratedMessage::•()
+    ;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3]  get info_() → pro::BuilderInfo*
+    return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::ClearKeep::_i;
+  @#C10
+  static method create() → self::ClearKeep*
+    return new self::ClearKeep::_();
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/decode_test.dart b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/decode_test.dart
new file mode 100644
index 0000000..d33289f
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/decode_test.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:test/test.dart';
+
+import 'generated/foo.pb.dart';
+
+List<int> buffer = <int>[
+  10, 4, 8, 5, 16, //
+  4, 26, 9, 10, 3,
+  102, 111, 111, 18, 2,
+  8, 42, 34, 9, 10,
+  3, 122, 111, 112, 18,
+  2, 8, 3, 40, 43,
+  50, 0, 58, 0,
+];
+
+main() {
+  FooKeep foo = FooKeep.fromBuffer(buffer);
+  test('Kept values are restored correctly', () {
+    expect(foo.mapKeep['foo'].aKeep, 42);
+    expect(foo.barKeep.aKeep, 5);
+    expect(foo.aKeep, 43);
+    expect(foo.hasHasKeep(), true);
+    foo.clearClearKeep();
+  });
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/decode_test.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/decode_test.dart.expect
new file mode 100644
index 0000000..6ffe522
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/decode_test.dart.expect
@@ -0,0 +1,138 @@
+library #lib;
+import self as self;
+import "generated/foo.pb.dart" as pb;
+import "package:test_core/test_core.dart" as tes;
+import "dart:core" as core;
+import "package:test_api/src/frontend/expect.dart" as exp;
+
+import "package:test/test.dart";
+import "file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart";
+
+[@vm.inferred-type.metadata=dart.core::_GrowableList?<dart.core::int*>]static field core::List<core::int*>* buffer = <core::int*>[10, 4, 8, 5, 16, 4, 26, 9, 10, 3, 102, 111, 111, 18, 2, 8, 42, 34, 9, 10, 3, 122, 111, 112, 18, 2, 8, 3, 40, 43, 50, 0, 58, 0];
+static method main() → dynamic {
+  pb::FooKeep* foo = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep] pb::FooKeep::fromBuffer([@vm.inferred-type.metadata=dart.core::_GrowableList?<dart.core::int*>] self::buffer);
+  tes::test("Kept values are restored correctly", () → core::Null? {
+    exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep??] [@vm.inferred-type.metadata=int] [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep?] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.mapKeep] [@vm.inferred-type.metadata=!] foo.{pb::FooKeep::mapKeep}.{core::Map::[]}("foo").{pb::BarKeep::aKeep}, 42);
+    exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep??] [@vm.inferred-type.metadata=int] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.barKeep] [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep?] foo.{pb::FooKeep::barKeep}.{pb::BarKeep::aKeep}, 5);
+    exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.aKeep] [@vm.inferred-type.metadata=int] foo.{pb::FooKeep::aKeep}, 43);
+    exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.hasHasKeep] [@vm.inferred-type.metadata=dart.core::bool (skip check)] foo.{pb::FooKeep::hasHasKeep}(), true);
+    [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.clearClearKeep] [@vm.inferred-type.metadata=!? (skip check)] foo.{pb::FooKeep::clearClearKeep}();
+  });
+}
+library foo.pb.dart;
+import self as self;
+import "package:protobuf/protobuf.dart" as pro;
+import "dart:core" as core;
+
+import "dart:core" as $core;
+import "package:protobuf/protobuf.dart" as $pb;
+
+class FooKeep extends pro::GeneratedMessage {
+[@vm.inferred-type.metadata=protobuf::BuilderInfo?]  static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t1 = new pro::BuilderInfo::•("FooKeep", createEmptyInstance: #C1) in block {
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::BarKeep*>(1, "barKeep", protoName: "barKeep", subBuilder: #C2);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::add}<core::Null?>(0, null, null, null, null, null, null);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.m] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::m}<core::String*, self::BarKeep*>(3, "mapKeep", protoName: "mapKeep", entryClassName: "FooKeep.MapKeepEntry", keyFieldType: #C3, valueFieldType: #C4, valueCreator: #C2);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::add}<core::Null?>(0, null, null, null, null, null, null);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::a}<core::int*>(5, "aKeep", #C5, protoName: "aKeep");
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::HasKeep*>(6, "hasKeep", protoName: "hasKeep", subBuilder: #C6);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::ClearKeep*>(7, "clearKeep", protoName: "clearKeep", subBuilder: #C7);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::hasRequiredFields} = false;
+  } =>#t1;
+  constructor _() → self::FooKeep*
+    : super pro::GeneratedMessage::•()
+    ;
+  static factory •() → self::FooKeep*
+    return [@vm.inferred-type.metadata=foo.pb.dart::FooKeep] self::FooKeep::create();
+  static factory fromBuffer([@vm.inferred-type.metadata=dart.core::_GrowableList?<dart.core::int*>] core::List<core::int*>* i, [[@vm.inferred-type.metadata=protobuf::_EmptyExtensionRegistry (value: const protobuf::_EmptyExtensionRegistry{})] pro::ExtensionRegistry* r = #C8]) → self::FooKeep*
+    return let final self::FooKeep* #t2 = [@vm.inferred-type.metadata=foo.pb.dart::FooKeep] self::FooKeep::create() in block {
+      [@vm.direct-call.metadata=protobuf::GeneratedMessage.mergeFromBuffer] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::GeneratedMessage::mergeFromBuffer}(i, r);
+    } =>#t2;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3]  method clone() → self::FooKeep*
+    return let final self::FooKeep* #t3 = [@vm.inferred-type.metadata=foo.pb.dart::FooKeep] self::FooKeep::•() in block {
+      [@vm.direct-call.metadata=protobuf::GeneratedMessage.mergeFromMessage] [@vm.inferred-type.metadata=!? (skip check)] #t3.{pro::GeneratedMessage::mergeFromMessage}(this);
+    } =>#t3;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:4]  get info_() → pro::BuilderInfo*
+    return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::FooKeep::_i;
+  @#C11
+  static method create() → self::FooKeep*
+    return new self::FooKeep::_();
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:5]  @#C13
+  get barKeep() → self::BarKeep*
+    return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getN] [@vm.inferred-type.metadata=foo.pb.dart::BarKeep? (skip check)] this.{pro::GeneratedMessage::$_getN}<self::BarKeep*>(0);
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:6]  @#C15
+  get mapKeep() → core::Map<core::String*, self::BarKeep*>*
+    return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getMap] [@vm.inferred-type.metadata=! (skip check)] this.{pro::GeneratedMessage::$_getMap}<core::String*, self::BarKeep*>(2);
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:7]  @#C17
+  get aKeep() → core::int*
+    return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getIZ] [@vm.inferred-type.metadata=int (skip check)] this.{pro::GeneratedMessage::$_getIZ}(4);
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:8,getterSelectorId:9]  @#C19
+  method hasHasKeep() → core::bool*
+    return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_has] [@vm.inferred-type.metadata=dart.core::bool (skip check)] this.{pro::GeneratedMessage::$_has}(5);
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:10,getterSelectorId:11]  @#C21
+  method clearClearKeep() → void
+    return [@vm.direct-call.metadata=protobuf::GeneratedMessage.clearField] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] this.{pro::GeneratedMessage::clearField}(7);
+}
+class BarKeep extends pro::GeneratedMessage {
+[@vm.inferred-type.metadata=protobuf::BuilderInfo?]  static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t4 = new pro::BuilderInfo::•("BarKeep", createEmptyInstance: #C2) in block {
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t4.{pro::BuilderInfo::a}<core::int*>(1, "aKeep", #C5, protoName: "aKeep");
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t4.{pro::BuilderInfo::add}<core::Null?>(0, null, null, null, null, null, null);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t4.{pro::BuilderInfo::hasRequiredFields} = false;
+  } =>#t4;
+  constructor _() → self::BarKeep*
+    : super pro::GeneratedMessage::•()
+    ;
+  static factory •() → self::BarKeep*
+    return [@vm.inferred-type.metadata=foo.pb.dart::BarKeep] self::BarKeep::create();
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3]  method clone() → self::BarKeep*
+    return let final self::BarKeep* #t5 = [@vm.inferred-type.metadata=foo.pb.dart::BarKeep] self::BarKeep::•() in block {
+      [@vm.direct-call.metadata=protobuf::GeneratedMessage.mergeFromMessage] [@vm.inferred-type.metadata=!? (skip check)] #t5.{pro::GeneratedMessage::mergeFromMessage}(this);
+    } =>#t5;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:4]  get info_() → pro::BuilderInfo*
+    return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::BarKeep::_i;
+  @#C11
+  static method create() → self::BarKeep*
+    return new self::BarKeep::_();
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:7]  @#C13
+  get aKeep() → core::int*
+    return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getIZ] [@vm.inferred-type.metadata=int (skip check)] this.{pro::GeneratedMessage::$_getIZ}(0);
+}
+class HasKeep extends pro::GeneratedMessage {
+[@vm.inferred-type.metadata=protobuf::BuilderInfo?]  static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t6 = new pro::BuilderInfo::•("HasKeep", createEmptyInstance: #C6) in block {
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t6.{pro::BuilderInfo::add}<core::Null?>(0, null, null, null, null, null, null);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t6.{pro::BuilderInfo::hasRequiredFields} = false;
+  } =>#t6;
+  constructor _() → self::HasKeep*
+    : super pro::GeneratedMessage::•()
+    ;
+  static factory •() → self::HasKeep*
+    return [@vm.inferred-type.metadata=foo.pb.dart::HasKeep] self::HasKeep::create();
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3]  method clone() → self::HasKeep*
+    return let final self::HasKeep* #t7 = [@vm.inferred-type.metadata=foo.pb.dart::HasKeep] self::HasKeep::•() in block {
+      [@vm.direct-call.metadata=protobuf::GeneratedMessage.mergeFromMessage] [@vm.inferred-type.metadata=!? (skip check)] #t7.{pro::GeneratedMessage::mergeFromMessage}(this);
+    } =>#t7;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:4]  get info_() → pro::BuilderInfo*
+    return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::HasKeep::_i;
+  @#C11
+  static method create() → self::HasKeep*
+    return new self::HasKeep::_();
+}
+class ClearKeep extends pro::GeneratedMessage {
+[@vm.inferred-type.metadata=protobuf::BuilderInfo?]  static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t8 = new pro::BuilderInfo::•("ClearKeep", createEmptyInstance: #C7) in block {
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t8.{pro::BuilderInfo::add}<core::Null?>(0, null, null, null, null, null, null);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t8.{pro::BuilderInfo::hasRequiredFields} = false;
+  } =>#t8;
+  constructor _() → self::ClearKeep*
+    : super pro::GeneratedMessage::•()
+    ;
+  static factory •() → self::ClearKeep*
+    return [@vm.inferred-type.metadata=foo.pb.dart::ClearKeep] self::ClearKeep::create();
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:2,getterSelectorId:3]  method clone() → self::ClearKeep*
+    return let final self::ClearKeep* #t9 = [@vm.inferred-type.metadata=foo.pb.dart::ClearKeep] self::ClearKeep::•() in block {
+      [@vm.direct-call.metadata=protobuf::GeneratedMessage.mergeFromMessage] [@vm.inferred-type.metadata=!? (skip check)] #t9.{pro::GeneratedMessage::mergeFromMessage}(this);
+    } =>#t9;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:4]  get info_() → pro::BuilderInfo*
+    return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::ClearKeep::_i;
+  @#C11
+  static method create() → self::ClearKeep*
+    return new self::ClearKeep::_();
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/encode_all_fields.dart b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/encode_all_fields.dart
new file mode 100644
index 0000000..de756cc
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/encode_all_fields.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:math';
+
+import 'generated/foo.pb.dart';
+
+main() {
+  FooKeep foo = FooKeep()
+    ..barKeep = (BarKeep()
+      ..aKeep = 5
+      ..bDrop = 4)
+    ..mapKeep['foo'] = (BarKeep()..aKeep = 42)
+    ..mapDrop['zop'] = (ZopDrop()..aDrop = 3)
+    ..aKeep = 43
+    ..hasKeep = HasKeep()
+    ..clearKeep = ClearKeep();
+  final buffer = foo.writeToBuffer();
+  print('List<int> buffer = <int>[');
+  for (int i = 0; i < buffer.length; i += 5) {
+    final numbers = buffer.sublist(i, min(buffer.length, i + 5)).join(', ');
+    print('  $numbers,${i == 0 ? ' //' : ''}');
+  }
+  print('];');
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/encode_all_fields.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/encode_all_fields.dart.expect
new file mode 100644
index 0000000..5ac9e51
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/encode_all_fields.dart.expect
@@ -0,0 +1,164 @@
+library #lib;
+import self as self;
+import "generated/foo.pb.dart" as pb;
+import "dart:core" as core;
+import "dart:typed_data" as typ;
+import "package:protobuf/protobuf.dart" as pro;
+import "dart:math" as math;
+
+import "dart:math";
+import "file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart";
+
+static method main() → dynamic {
+  pb::FooKeep* foo = let final pb::FooKeep* #t1 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep] pb::FooKeep::•() in block {
+    [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.barKeep] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pb::FooKeep::barKeep} = let final pb::BarKeep* #t2 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep] pb::BarKeep::•() in block {
+      [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pb::BarKeep::aKeep} = 5;
+      [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.bDrop] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pb::BarKeep::bDrop} = 4;
+    } =>#t2;
+    [@vm.call-site-attributes.metadata=receiverType:dart.core::Map<dart.core::String*, library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep*>*] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.mapKeep] [@vm.inferred-type.metadata=!] #t1.{pb::FooKeep::mapKeep}.{core::Map::[]=}("foo", let final pb::BarKeep* #t3 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep] pb::BarKeep::•() in block {
+      [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep] [@vm.inferred-type.metadata=!? (skip check)] #t3.{pb::BarKeep::aKeep} = 42;
+    } =>#t3);
+    [@vm.call-site-attributes.metadata=receiverType:dart.core::Map<dart.core::String*, library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::ZopDrop*>*] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.mapDrop] [@vm.inferred-type.metadata=!] #t1.{pb::FooKeep::mapDrop}.{core::Map::[]=}("zop", let final pb::ZopDrop* #t4 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::ZopDrop] pb::ZopDrop::•() in block {
+      [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::ZopDrop.aDrop] [@vm.inferred-type.metadata=!? (skip check)] #t4.{pb::ZopDrop::aDrop} = 3;
+    } =>#t4);
+    [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.aKeep] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pb::FooKeep::aKeep} = 43;
+    [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.hasKeep] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pb::FooKeep::hasKeep} = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::HasKeep] pb::HasKeep::•();
+    [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.clearKeep] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pb::FooKeep::clearKeep} = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::ClearKeep] pb::ClearKeep::•();
+  } =>#t1;
+  final typ::Uint8List* buffer = [@vm.direct-call.metadata=protobuf::GeneratedMessage.writeToBuffer] [@vm.inferred-type.metadata=dart.typed_data::_Uint8List (skip check)] foo.{pro::GeneratedMessage::writeToBuffer}();
+  core::print("List<int> buffer = <int>[");
+  for (core::int* i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation.<] [@vm.inferred-type.metadata=dart.core::bool (skip check)] i.{core::num::<}([@vm.direct-call.metadata=dart.typed_data::_TypedList.length] [@vm.inferred-type.metadata=dart.core::_Smi] buffer.{core::List::length}); i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(5)) {
+    final core::String* numbers = [@vm.direct-call.metadata=dart.typed_data::_TypedListBase.join] [@vm.inferred-type.metadata=!? (skip check)] [@vm.direct-call.metadata=dart.typed_data::__Uint8List&_TypedList&_IntListMixin&_TypedIntListMixin.sublist] [@vm.inferred-type.metadata=dart.typed_data::_Uint8List (skip check)] buffer.{typ::Uint8List::sublist}(i, [@vm.inferred-type.metadata=int] math::min<core::int*>([@vm.direct-call.metadata=dart.typed_data::_TypedList.length] [@vm.inferred-type.metadata=dart.core::_Smi] buffer.{core::List::length}, [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(5))).{core::Iterable::join}(", ");
+    core::print("  ${numbers},${[@vm.direct-call.metadata=dart.core::_IntegerImplementation.==] [@vm.inferred-type.metadata=dart.core::bool (skip check)] i.{core::num::==}(0) ?{core::String*} " //" : ""}");
+  }
+  core::print("];");
+}
+library foo.pb.dart;
+import self as self;
+import "package:protobuf/protobuf.dart" as pro;
+import "dart:core" as core;
+
+import "dart:core" as $core;
+import "package:protobuf/protobuf.dart" as $pb;
+
+class FooKeep extends pro::GeneratedMessage {
+[@vm.inferred-type.metadata=protobuf::BuilderInfo?]  static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t1 = new pro::BuilderInfo::•("FooKeep", createEmptyInstance: #C1) in block {
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::BarKeep*>(1, "barKeep", protoName: "barKeep", subBuilder: #C2);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::add}<core::Null?>(0, null, null, null, null, null, null);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.m] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::m}<core::String*, self::BarKeep*>(3, "mapKeep", protoName: "mapKeep", entryClassName: "FooKeep.MapKeepEntry", keyFieldType: #C3, valueFieldType: #C4, valueCreator: #C2);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.m] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::m}<core::String*, self::ZopDrop*>(4, "mapDrop", protoName: "mapDrop", entryClassName: "FooKeep.MapDropEntry", keyFieldType: #C3, valueFieldType: #C4, valueCreator: #C5);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::a}<core::int*>(5, "aKeep", #C6, protoName: "aKeep");
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::HasKeep*>(6, "hasKeep", protoName: "hasKeep", subBuilder: #C7);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::ClearKeep*>(7, "clearKeep", protoName: "clearKeep", subBuilder: #C8);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::hasRequiredFields} = false;
+  } =>#t1;
+  constructor _() → self::FooKeep*
+    : super pro::GeneratedMessage::•()
+    ;
+  static factory •() → self::FooKeep*
+    return [@vm.inferred-type.metadata=foo.pb.dart::FooKeep] self::FooKeep::create();
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2]  get info_() → pro::BuilderInfo*
+    return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::FooKeep::_i;
+  @#C11
+  static method create() → self::FooKeep*
+    return new self::FooKeep::_();
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3]  @#C13
+  set barKeep([@vm.inferred-type.metadata=foo.pb.dart::BarKeep] self::BarKeep* v) → void {
+    [@vm.direct-call.metadata=protobuf::GeneratedMessage.setField] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::setField}(1, v);
+  }
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:4]  @#C15
+  get mapKeep() → core::Map<core::String*, self::BarKeep*>*
+    return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getMap] [@vm.inferred-type.metadata=! (skip check)] this.{pro::GeneratedMessage::$_getMap}<core::String*, self::BarKeep*>(2);
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:5]  @#C17
+  get mapDrop() → core::Map<core::String*, self::ZopDrop*>*
+    return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getMap] [@vm.inferred-type.metadata=! (skip check)] this.{pro::GeneratedMessage::$_getMap}<core::String*, self::ZopDrop*>(3);
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6]  @#C19
+  set aKeep([@vm.inferred-type.metadata=dart.core::_Smi (value: 43)] core::int* v) → void {
+    [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_setSignedInt32] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::$_setSignedInt32}(4, v);
+  }
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7]  @#C21
+  set hasKeep([@vm.inferred-type.metadata=foo.pb.dart::HasKeep] self::HasKeep* v) → void {
+    [@vm.direct-call.metadata=protobuf::GeneratedMessage.setField] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::setField}(6, v);
+  }
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:8]  @#C23
+  set clearKeep([@vm.inferred-type.metadata=foo.pb.dart::ClearKeep] self::ClearKeep* v) → void {
+    [@vm.direct-call.metadata=protobuf::GeneratedMessage.setField] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::setField}(7, v);
+  }
+}
+class BarKeep extends pro::GeneratedMessage {
+[@vm.inferred-type.metadata=protobuf::BuilderInfo?]  static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t2 = new pro::BuilderInfo::•("BarKeep", createEmptyInstance: #C2) in block {
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::BuilderInfo::a}<core::int*>(1, "aKeep", #C6, protoName: "aKeep");
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::BuilderInfo::a}<core::int*>(2, "bDrop", #C6, protoName: "bDrop");
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::BuilderInfo::hasRequiredFields} = false;
+  } =>#t2;
+  constructor _() → self::BarKeep*
+    : super pro::GeneratedMessage::•()
+    ;
+  static factory •() → self::BarKeep*
+    return [@vm.inferred-type.metadata=foo.pb.dart::BarKeep] self::BarKeep::create();
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2]  get info_() → pro::BuilderInfo*
+    return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::BarKeep::_i;
+  @#C11
+  static method create() → self::BarKeep*
+    return new self::BarKeep::_();
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6]  @#C13
+  set aKeep([@vm.inferred-type.metadata=dart.core::_Smi] core::int* v) → void {
+    [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_setSignedInt32] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::$_setSignedInt32}(0, v);
+  }
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9]  @#C25
+  set bDrop([@vm.inferred-type.metadata=dart.core::_Smi (value: 4)] core::int* v) → void {
+    [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_setSignedInt32] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::$_setSignedInt32}(1, v);
+  }
+}
+class HasKeep extends pro::GeneratedMessage {
+[@vm.inferred-type.metadata=protobuf::BuilderInfo?]  static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t3 = new pro::BuilderInfo::•("HasKeep", createEmptyInstance: #C7) in block {
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t3.{pro::BuilderInfo::add}<core::Null?>(0, null, null, null, null, null, null);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t3.{pro::BuilderInfo::hasRequiredFields} = false;
+  } =>#t3;
+  constructor _() → self::HasKeep*
+    : super pro::GeneratedMessage::•()
+    ;
+  static factory •() → self::HasKeep*
+    return [@vm.inferred-type.metadata=foo.pb.dart::HasKeep] self::HasKeep::create();
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2]  get info_() → pro::BuilderInfo*
+    return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::HasKeep::_i;
+  @#C11
+  static method create() → self::HasKeep*
+    return new self::HasKeep::_();
+}
+class ClearKeep extends pro::GeneratedMessage {
+[@vm.inferred-type.metadata=protobuf::BuilderInfo?]  static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t4 = new pro::BuilderInfo::•("ClearKeep", createEmptyInstance: #C8) in block {
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t4.{pro::BuilderInfo::add}<core::Null?>(0, null, null, null, null, null, null);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t4.{pro::BuilderInfo::hasRequiredFields} = false;
+  } =>#t4;
+  constructor _() → self::ClearKeep*
+    : super pro::GeneratedMessage::•()
+    ;
+  static factory •() → self::ClearKeep*
+    return [@vm.inferred-type.metadata=foo.pb.dart::ClearKeep] self::ClearKeep::create();
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2]  get info_() → pro::BuilderInfo*
+    return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::ClearKeep::_i;
+  @#C11
+  static method create() → self::ClearKeep*
+    return new self::ClearKeep::_();
+}
+class ZopDrop extends pro::GeneratedMessage {
+[@vm.inferred-type.metadata=protobuf::BuilderInfo?]  static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t5 = new pro::BuilderInfo::•("ZopDrop", createEmptyInstance: #C5) in block {
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t5.{pro::BuilderInfo::a}<core::int*>(1, "aDrop", #C6, protoName: "aDrop");
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t5.{pro::BuilderInfo::hasRequiredFields} = false;
+  } =>#t5;
+  constructor _() → self::ZopDrop*
+    : super pro::GeneratedMessage::•()
+    ;
+  static factory •() → self::ZopDrop*
+    return [@vm.inferred-type.metadata=foo.pb.dart::ZopDrop] self::ZopDrop::create();
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:2]  get info_() → pro::BuilderInfo*
+    return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::ZopDrop::_i;
+  @#C11
+  static method create() → self::ZopDrop*
+    return new self::ZopDrop::_();
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:10]  @#C13
+  set aDrop([@vm.inferred-type.metadata=dart.core::_Smi (value: 3)] core::int* v) → void {
+    [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_setSignedInt32] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::$_setSignedInt32}(0, v);
+  }
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/freeze_test.dart b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/freeze_test.dart
new file mode 100644
index 0000000..0529e4a
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/freeze_test.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:test/test.dart';
+
+import 'generated/foo.pb.dart';
+
+main() {
+  FooKeep foo = FooKeep()
+    ..barKeep = (BarKeep()..aKeep = 5)
+    ..mapKeep['foo'] = (BarKeep()..aKeep = 2)
+    ..aKeep = 43;
+  test('Freezing a message works', () {
+    foo.freeze();
+    expect(foo.barKeep.aKeep, 5);
+    expect(foo.mapKeep['foo'].aKeep, 2);
+    expect(foo.hasHasKeep(), false);
+    expect(foo.aKeep, 43);
+    expect(() => foo.clearClearKeep(),
+        throwsA(const TypeMatcher<UnsupportedError>()));
+  });
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/freeze_test.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/freeze_test.dart.expect
new file mode 100644
index 0000000..ed24036
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/freeze_test.dart.expect
@@ -0,0 +1,137 @@
+library #lib;
+import self as self;
+import "generated/foo.pb.dart" as pb;
+import "dart:core" as core;
+import "package:test_core/test_core.dart" as tes;
+import "package:protobuf/protobuf.dart" as pro;
+import "package:test_api/src/frontend/expect.dart" as exp;
+import "package:test_api/src/frontend/throws_matcher.dart" as thr;
+import "package:matcher/src/type_matcher.dart" as typ;
+
+import "package:test/test.dart";
+import "file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart";
+
+static method main() → dynamic {
+  pb::FooKeep* foo = let final pb::FooKeep* #t1 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep] pb::FooKeep::•() in block {
+    [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.barKeep] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pb::FooKeep::barKeep} = let final pb::BarKeep* #t2 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep] pb::BarKeep::•() in block {
+      [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pb::BarKeep::aKeep} = 5;
+    } =>#t2;
+    [@vm.call-site-attributes.metadata=receiverType:dart.core::Map<dart.core::String*, library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep*>*] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.mapKeep] [@vm.inferred-type.metadata=!] #t1.{pb::FooKeep::mapKeep}.{core::Map::[]=}("foo", let final pb::BarKeep* #t3 = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep] pb::BarKeep::•() in block {
+      [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep] [@vm.inferred-type.metadata=!? (skip check)] #t3.{pb::BarKeep::aKeep} = 2;
+    } =>#t3);
+    [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.aKeep] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pb::FooKeep::aKeep} = 43;
+  } =>#t1;
+  tes::test("Freezing a message works", () → core::Null? {
+    [@vm.direct-call.metadata=protobuf::GeneratedMessage.freeze] [@vm.inferred-type.metadata=!? (skip check)] foo.{pro::GeneratedMessage::freeze}();
+    exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep??] [@vm.inferred-type.metadata=int] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.barKeep] [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep?] foo.{pb::FooKeep::barKeep}.{pb::BarKeep::aKeep}, 5);
+    exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep.aKeep??] [@vm.inferred-type.metadata=int] [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::BarKeep?] [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.mapKeep] [@vm.inferred-type.metadata=!] foo.{pb::FooKeep::mapKeep}.{core::Map::[]}("foo").{pb::BarKeep::aKeep}, 2);
+    exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.hasHasKeep] [@vm.inferred-type.metadata=dart.core::bool (skip check)] foo.{pb::FooKeep::hasHasKeep}(), false);
+    exp::expect([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.aKeep] [@vm.inferred-type.metadata=int] foo.{pb::FooKeep::aKeep}, 43);
+    exp::expect(() → void => [@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart::FooKeep.clearClearKeep] [@vm.inferred-type.metadata=!? (skip check)] foo.{pb::FooKeep::clearClearKeep}(), [@vm.inferred-type.metadata=library package:test_api/src/frontend/throws_matcher.dart::Throws] thr::throwsA(#C2));
+  });
+}
+library foo.pb.dart;
+import self as self;
+import "package:protobuf/protobuf.dart" as pro;
+import "dart:core" as core;
+
+import "dart:core" as $core;
+import "package:protobuf/protobuf.dart" as $pb;
+
+class FooKeep extends pro::GeneratedMessage {
+[@vm.inferred-type.metadata=protobuf::BuilderInfo?]  static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t1 = new pro::BuilderInfo::•("FooKeep", createEmptyInstance: #C1) in block {
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::BarKeep*>(1, "barKeep", protoName: "barKeep", subBuilder: #C2);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::add}<core::Null?>(0, null, null, null, null, null, null);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.m] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::m}<core::String*, self::BarKeep*>(3, "mapKeep", protoName: "mapKeep", entryClassName: "FooKeep.MapKeepEntry", keyFieldType: #C3, valueFieldType: #C4, valueCreator: #C2);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::add}<core::Null?>(0, null, null, null, null, null, null);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::a}<core::int*>(5, "aKeep", #C5, protoName: "aKeep");
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::HasKeep*>(6, "hasKeep", protoName: "hasKeep", subBuilder: #C6);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::aOM}<self::ClearKeep*>(7, "clearKeep", protoName: "clearKeep", subBuilder: #C7);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::hasRequiredFields} = false;
+  } =>#t1;
+  constructor _() → self::FooKeep*
+    : super pro::GeneratedMessage::•()
+    ;
+  static factory •() → self::FooKeep*
+    return [@vm.inferred-type.metadata=foo.pb.dart::FooKeep] self::FooKeep::create();
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3]  get info_() → pro::BuilderInfo*
+    return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::FooKeep::_i;
+  @#C10
+  static method create() → self::FooKeep*
+    return new self::FooKeep::_();
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:4]  @#C12
+  get barKeep() → self::BarKeep*
+    return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getN] [@vm.inferred-type.metadata=foo.pb.dart::BarKeep? (skip check)] this.{pro::GeneratedMessage::$_getN}<self::BarKeep*>(0);
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5]  @#C12
+  set barKeep([@vm.inferred-type.metadata=foo.pb.dart::BarKeep] self::BarKeep* v) → void {
+    [@vm.direct-call.metadata=protobuf::GeneratedMessage.setField] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::setField}(1, v);
+  }
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:6]  @#C14
+  get mapKeep() → core::Map<core::String*, self::BarKeep*>*
+    return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getMap] [@vm.inferred-type.metadata=! (skip check)] this.{pro::GeneratedMessage::$_getMap}<core::String*, self::BarKeep*>(2);
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:7]  @#C16
+  get aKeep() → core::int*
+    return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getIZ] [@vm.inferred-type.metadata=int (skip check)] this.{pro::GeneratedMessage::$_getIZ}(4);
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:8]  @#C16
+  set aKeep([@vm.inferred-type.metadata=dart.core::_Smi (value: 43)] core::int* v) → void {
+    [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_setSignedInt32] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::$_setSignedInt32}(4, v);
+  }
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10]  @#C18
+  method hasHasKeep() → core::bool*
+    return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_has] [@vm.inferred-type.metadata=dart.core::bool (skip check)] this.{pro::GeneratedMessage::$_has}(5);
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12]  @#C20
+  method clearClearKeep() → void
+    return [@vm.direct-call.metadata=protobuf::GeneratedMessage.clearField] [@vm.inferred-type.metadata=dart.core::Null? (skip check) (value: null)] this.{pro::GeneratedMessage::clearField}(7);
+}
+class BarKeep extends pro::GeneratedMessage {
+[@vm.inferred-type.metadata=protobuf::BuilderInfo?]  static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t2 = new pro::BuilderInfo::•("BarKeep", createEmptyInstance: #C2) in block {
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.a] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::BuilderInfo::a}<core::int*>(1, "aKeep", #C5, protoName: "aKeep");
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::BuilderInfo::add}<core::Null?>(0, null, null, null, null, null, null);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t2.{pro::BuilderInfo::hasRequiredFields} = false;
+  } =>#t2;
+  constructor _() → self::BarKeep*
+    : super pro::GeneratedMessage::•()
+    ;
+  static factory •() → self::BarKeep*
+    return [@vm.inferred-type.metadata=foo.pb.dart::BarKeep] self::BarKeep::create();
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3]  get info_() → pro::BuilderInfo*
+    return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::BarKeep::_i;
+  @#C10
+  static method create() → self::BarKeep*
+    return new self::BarKeep::_();
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:7]  @#C12
+  get aKeep() → core::int*
+    return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getIZ] [@vm.inferred-type.metadata=int (skip check)] this.{pro::GeneratedMessage::$_getIZ}(0);
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:8]  @#C12
+  set aKeep([@vm.inferred-type.metadata=dart.core::_Smi] core::int* v) → void {
+    [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_setSignedInt32] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::$_setSignedInt32}(0, v);
+  }
+}
+class HasKeep extends pro::GeneratedMessage {
+[@vm.inferred-type.metadata=protobuf::BuilderInfo?]  static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t3 = new pro::BuilderInfo::•("HasKeep", createEmptyInstance: #C6) in block {
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t3.{pro::BuilderInfo::add}<core::Null?>(0, null, null, null, null, null, null);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t3.{pro::BuilderInfo::hasRequiredFields} = false;
+  } =>#t3;
+  constructor _() → self::HasKeep*
+    : super pro::GeneratedMessage::•()
+    ;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3]  get info_() → pro::BuilderInfo*
+    return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::HasKeep::_i;
+  @#C10
+  static method create() → self::HasKeep*
+    return new self::HasKeep::_();
+}
+class ClearKeep extends pro::GeneratedMessage {
+[@vm.inferred-type.metadata=protobuf::BuilderInfo?]  static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t4 = new pro::BuilderInfo::•("ClearKeep", createEmptyInstance: #C7) in block {
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.add] [@vm.inferred-type.metadata=!? (skip check)] #t4.{pro::BuilderInfo::add}<core::Null?>(0, null, null, null, null, null, null);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t4.{pro::BuilderInfo::hasRequiredFields} = false;
+  } =>#t4;
+  constructor _() → self::ClearKeep*
+    : super pro::GeneratedMessage::•()
+    ;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3]  get info_() → pro::BuilderInfo*
+    return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::ClearKeep::_i;
+  @#C10
+  static method create() → self::ClearKeep*
+    return new self::ClearKeep::_();
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart
new file mode 100644
index 0000000..cab7883
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/foo.pb.dart
@@ -0,0 +1,345 @@
+///
+//  Generated code. Do not modify.
+//  source: foo.proto
+//
+// @dart = 2.3
+// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type
+
+import 'dart:core' as $core;
+
+import 'package:protobuf/protobuf.dart' as $pb;
+
+class FooKeep extends $pb.GeneratedMessage {
+  static final $pb.BuilderInfo _i =
+      $pb.BuilderInfo('FooKeep', createEmptyInstance: create)
+        ..aOM<BarKeep>(1, 'barKeep',
+            protoName: 'barKeep', subBuilder: BarKeep.create)
+        ..aOM<BarKeep>(2, 'barDrop',
+            protoName: 'barDrop', subBuilder: BarKeep.create)
+        ..m<$core.String, BarKeep>(3, 'mapKeep',
+            protoName: 'mapKeep',
+            entryClassName: 'FooKeep.MapKeepEntry',
+            keyFieldType: $pb.PbFieldType.OS,
+            valueFieldType: $pb.PbFieldType.OM,
+            valueCreator: BarKeep.create)
+        ..m<$core.String, ZopDrop>(4, 'mapDrop',
+            protoName: 'mapDrop',
+            entryClassName: 'FooKeep.MapDropEntry',
+            keyFieldType: $pb.PbFieldType.OS,
+            valueFieldType: $pb.PbFieldType.OM,
+            valueCreator: ZopDrop.create)
+        ..a<$core.int>(5, 'aKeep', $pb.PbFieldType.O3, protoName: 'aKeep')
+        ..aOM<HasKeep>(6, 'hasKeep',
+            protoName: 'hasKeep', subBuilder: HasKeep.create)
+        ..aOM<ClearKeep>(7, 'clearKeep',
+            protoName: 'clearKeep', subBuilder: ClearKeep.create)
+        ..hasRequiredFields = false;
+
+  FooKeep._() : super();
+  factory FooKeep() => create();
+  factory FooKeep.fromBuffer($core.List<$core.int> i,
+          [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
+      create()..mergeFromBuffer(i, r);
+  factory FooKeep.fromJson($core.String i,
+          [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
+      create()..mergeFromJson(i, r);
+  FooKeep clone() => FooKeep()..mergeFromMessage(this);
+  FooKeep copyWith(void Function(FooKeep) updates) =>
+      super.copyWith((message) => updates(message as FooKeep));
+  $pb.BuilderInfo get info_ => _i;
+  @$core.pragma('dart2js:noInline')
+  static FooKeep create() => FooKeep._();
+  FooKeep createEmptyInstance() => create();
+  static $pb.PbList<FooKeep> createRepeated() => $pb.PbList<FooKeep>();
+  @$core.pragma('dart2js:noInline')
+  static FooKeep getDefault() =>
+      _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<FooKeep>(create);
+  static FooKeep _defaultInstance;
+
+  @$pb.TagNumber(1)
+  BarKeep get barKeep => $_getN(0);
+  @$pb.TagNumber(1)
+  set barKeep(BarKeep v) {
+    setField(1, v);
+  }
+
+  @$pb.TagNumber(1)
+  $core.bool hasBarKeep() => $_has(0);
+  @$pb.TagNumber(1)
+  void clearBarKeep() => clearField(1);
+  @$pb.TagNumber(1)
+  BarKeep ensureBarKeep() => $_ensure(0);
+
+  @$pb.TagNumber(2)
+  BarKeep get barDrop => $_getN(1);
+  @$pb.TagNumber(2)
+  set barDrop(BarKeep v) {
+    setField(2, v);
+  }
+
+  @$pb.TagNumber(2)
+  $core.bool hasBarDrop() => $_has(1);
+  @$pb.TagNumber(2)
+  void clearBarDrop() => clearField(2);
+  @$pb.TagNumber(2)
+  BarKeep ensureBarDrop() => $_ensure(1);
+
+  @$pb.TagNumber(3)
+  $core.Map<$core.String, BarKeep> get mapKeep => $_getMap(2);
+
+  @$pb.TagNumber(4)
+  $core.Map<$core.String, ZopDrop> get mapDrop => $_getMap(3);
+
+  @$pb.TagNumber(5)
+  $core.int get aKeep => $_getIZ(4);
+  @$pb.TagNumber(5)
+  set aKeep($core.int v) {
+    $_setSignedInt32(4, v);
+  }
+
+  @$pb.TagNumber(5)
+  $core.bool hasAKeep() => $_has(4);
+  @$pb.TagNumber(5)
+  void clearAKeep() => clearField(5);
+
+  @$pb.TagNumber(6)
+  HasKeep get hasKeep => $_getN(5);
+  @$pb.TagNumber(6)
+  set hasKeep(HasKeep v) {
+    setField(6, v);
+  }
+
+  @$pb.TagNumber(6)
+  $core.bool hasHasKeep() => $_has(5);
+  @$pb.TagNumber(6)
+  void clearHasKeep() => clearField(6);
+  @$pb.TagNumber(6)
+  HasKeep ensureHasKeep() => $_ensure(5);
+
+  @$pb.TagNumber(7)
+  ClearKeep get clearKeep => $_getN(6);
+  @$pb.TagNumber(7)
+  set clearKeep(ClearKeep v) {
+    setField(7, v);
+  }
+
+  @$pb.TagNumber(7)
+  $core.bool hasClearKeep() => $_has(6);
+  @$pb.TagNumber(7)
+  void clearClearKeep() => clearField(7);
+  @$pb.TagNumber(7)
+  ClearKeep ensureClearKeep() => $_ensure(6);
+}
+
+class BarKeep extends $pb.GeneratedMessage {
+  static final $pb.BuilderInfo _i =
+      $pb.BuilderInfo('BarKeep', createEmptyInstance: create)
+        ..a<$core.int>(1, 'aKeep', $pb.PbFieldType.O3, protoName: 'aKeep')
+        ..a<$core.int>(2, 'bDrop', $pb.PbFieldType.O3, protoName: 'bDrop')
+        ..hasRequiredFields = false;
+
+  BarKeep._() : super();
+  factory BarKeep() => create();
+  factory BarKeep.fromBuffer($core.List<$core.int> i,
+          [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
+      create()..mergeFromBuffer(i, r);
+  factory BarKeep.fromJson($core.String i,
+          [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
+      create()..mergeFromJson(i, r);
+  BarKeep clone() => BarKeep()..mergeFromMessage(this);
+  BarKeep copyWith(void Function(BarKeep) updates) =>
+      super.copyWith((message) => updates(message as BarKeep));
+  $pb.BuilderInfo get info_ => _i;
+  @$core.pragma('dart2js:noInline')
+  static BarKeep create() => BarKeep._();
+  BarKeep createEmptyInstance() => create();
+  static $pb.PbList<BarKeep> createRepeated() => $pb.PbList<BarKeep>();
+  @$core.pragma('dart2js:noInline')
+  static BarKeep getDefault() =>
+      _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<BarKeep>(create);
+  static BarKeep _defaultInstance;
+
+  @$pb.TagNumber(1)
+  $core.int get aKeep => $_getIZ(0);
+  @$pb.TagNumber(1)
+  set aKeep($core.int v) {
+    $_setSignedInt32(0, v);
+  }
+
+  @$pb.TagNumber(1)
+  $core.bool hasAKeep() => $_has(0);
+  @$pb.TagNumber(1)
+  void clearAKeep() => clearField(1);
+
+  @$pb.TagNumber(2)
+  $core.int get bDrop => $_getIZ(1);
+  @$pb.TagNumber(2)
+  set bDrop($core.int v) {
+    $_setSignedInt32(1, v);
+  }
+
+  @$pb.TagNumber(2)
+  $core.bool hasBDrop() => $_has(1);
+  @$pb.TagNumber(2)
+  void clearBDrop() => clearField(2);
+}
+
+class HasKeep extends $pb.GeneratedMessage {
+  static final $pb.BuilderInfo _i =
+      $pb.BuilderInfo('HasKeep', createEmptyInstance: create)
+        ..a<$core.int>(1, 'aDrop', $pb.PbFieldType.O3, protoName: 'aDrop')
+        ..hasRequiredFields = false;
+
+  HasKeep._() : super();
+  factory HasKeep() => create();
+  factory HasKeep.fromBuffer($core.List<$core.int> i,
+          [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
+      create()..mergeFromBuffer(i, r);
+  factory HasKeep.fromJson($core.String i,
+          [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
+      create()..mergeFromJson(i, r);
+  HasKeep clone() => HasKeep()..mergeFromMessage(this);
+  HasKeep copyWith(void Function(HasKeep) updates) =>
+      super.copyWith((message) => updates(message as HasKeep));
+  $pb.BuilderInfo get info_ => _i;
+  @$core.pragma('dart2js:noInline')
+  static HasKeep create() => HasKeep._();
+  HasKeep createEmptyInstance() => create();
+  static $pb.PbList<HasKeep> createRepeated() => $pb.PbList<HasKeep>();
+  @$core.pragma('dart2js:noInline')
+  static HasKeep getDefault() =>
+      _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<HasKeep>(create);
+  static HasKeep _defaultInstance;
+
+  @$pb.TagNumber(1)
+  $core.int get aDrop => $_getIZ(0);
+  @$pb.TagNumber(1)
+  set aDrop($core.int v) {
+    $_setSignedInt32(0, v);
+  }
+
+  @$pb.TagNumber(1)
+  $core.bool hasADrop() => $_has(0);
+  @$pb.TagNumber(1)
+  void clearADrop() => clearField(1);
+}
+
+class ClearKeep extends $pb.GeneratedMessage {
+  static final $pb.BuilderInfo _i =
+      $pb.BuilderInfo('ClearKeep', createEmptyInstance: create)
+        ..a<$core.int>(1, 'aDrop', $pb.PbFieldType.O3, protoName: 'aDrop')
+        ..hasRequiredFields = false;
+
+  ClearKeep._() : super();
+  factory ClearKeep() => create();
+  factory ClearKeep.fromBuffer($core.List<$core.int> i,
+          [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
+      create()..mergeFromBuffer(i, r);
+  factory ClearKeep.fromJson($core.String i,
+          [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
+      create()..mergeFromJson(i, r);
+  ClearKeep clone() => ClearKeep()..mergeFromMessage(this);
+  ClearKeep copyWith(void Function(ClearKeep) updates) =>
+      super.copyWith((message) => updates(message as ClearKeep));
+  $pb.BuilderInfo get info_ => _i;
+  @$core.pragma('dart2js:noInline')
+  static ClearKeep create() => ClearKeep._();
+  ClearKeep createEmptyInstance() => create();
+  static $pb.PbList<ClearKeep> createRepeated() => $pb.PbList<ClearKeep>();
+  @$core.pragma('dart2js:noInline')
+  static ClearKeep getDefault() =>
+      _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<ClearKeep>(create);
+  static ClearKeep _defaultInstance;
+
+  @$pb.TagNumber(1)
+  $core.int get aDrop => $_getIZ(0);
+  @$pb.TagNumber(1)
+  set aDrop($core.int v) {
+    $_setSignedInt32(0, v);
+  }
+
+  @$pb.TagNumber(1)
+  $core.bool hasADrop() => $_has(0);
+  @$pb.TagNumber(1)
+  void clearADrop() => clearField(1);
+}
+
+class ZopDrop extends $pb.GeneratedMessage {
+  static final $pb.BuilderInfo _i =
+      $pb.BuilderInfo('ZopDrop', createEmptyInstance: create)
+        ..a<$core.int>(1, 'aDrop', $pb.PbFieldType.O3, protoName: 'aDrop')
+        ..hasRequiredFields = false;
+
+  ZopDrop._() : super();
+  factory ZopDrop() => create();
+  factory ZopDrop.fromBuffer($core.List<$core.int> i,
+          [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
+      create()..mergeFromBuffer(i, r);
+  factory ZopDrop.fromJson($core.String i,
+          [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
+      create()..mergeFromJson(i, r);
+  ZopDrop clone() => ZopDrop()..mergeFromMessage(this);
+  ZopDrop copyWith(void Function(ZopDrop) updates) =>
+      super.copyWith((message) => updates(message as ZopDrop));
+  $pb.BuilderInfo get info_ => _i;
+  @$core.pragma('dart2js:noInline')
+  static ZopDrop create() => ZopDrop._();
+  ZopDrop createEmptyInstance() => create();
+  static $pb.PbList<ZopDrop> createRepeated() => $pb.PbList<ZopDrop>();
+  @$core.pragma('dart2js:noInline')
+  static ZopDrop getDefault() =>
+      _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<ZopDrop>(create);
+  static ZopDrop _defaultInstance;
+
+  @$pb.TagNumber(1)
+  $core.int get aDrop => $_getIZ(0);
+  @$pb.TagNumber(1)
+  set aDrop($core.int v) {
+    $_setSignedInt32(0, v);
+  }
+
+  @$pb.TagNumber(1)
+  $core.bool hasADrop() => $_has(0);
+  @$pb.TagNumber(1)
+  void clearADrop() => clearField(1);
+}
+
+class MobDrop extends $pb.GeneratedMessage {
+  static final $pb.BuilderInfo _i =
+      $pb.BuilderInfo('MobDrop', createEmptyInstance: create)
+        ..a<$core.int>(1, 'aDrop', $pb.PbFieldType.O3, protoName: 'aDrop')
+        ..hasRequiredFields = false;
+
+  MobDrop._() : super();
+  factory MobDrop() => create();
+  factory MobDrop.fromBuffer($core.List<$core.int> i,
+          [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
+      create()..mergeFromBuffer(i, r);
+  factory MobDrop.fromJson($core.String i,
+          [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
+      create()..mergeFromJson(i, r);
+  MobDrop clone() => MobDrop()..mergeFromMessage(this);
+  MobDrop copyWith(void Function(MobDrop) updates) =>
+      super.copyWith((message) => updates(message as MobDrop));
+  $pb.BuilderInfo get info_ => _i;
+  @$core.pragma('dart2js:noInline')
+  static MobDrop create() => MobDrop._();
+  MobDrop createEmptyInstance() => create();
+  static $pb.PbList<MobDrop> createRepeated() => $pb.PbList<MobDrop>();
+  @$core.pragma('dart2js:noInline')
+  static MobDrop getDefault() =>
+      _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<MobDrop>(create);
+  static MobDrop _defaultInstance;
+
+  @$pb.TagNumber(1)
+  $core.int get aDrop => $_getIZ(0);
+  @$pb.TagNumber(1)
+  set aDrop($core.int v) {
+    $_setSignedInt32(0, v);
+  }
+
+  @$pb.TagNumber(1)
+  $core.bool hasADrop() => $_has(0);
+  @$pb.TagNumber(1)
+  void clearADrop() => clearField(1);
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/name_mangling.pb.dart b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/name_mangling.pb.dart
new file mode 100644
index 0000000..bc76b27
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/name_mangling.pb.dart
@@ -0,0 +1,80 @@
+///
+//  Generated code. Do not modify.
+//  source: name_mangling.proto
+//
+// @dart = 2.3
+// ignore_for_file: camel_case_types,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type
+
+import 'dart:core' as $core;
+
+import 'package:protobuf/protobuf.dart' as $pb;
+
+class AKeep extends $pb.GeneratedMessage {
+  static final $pb.BuilderInfo _i =
+      $pb.BuilderInfo('AKeep', createEmptyInstance: create)
+        ..hasRequiredFields = false;
+
+  AKeep._() : super();
+  factory AKeep() => create();
+  factory AKeep.fromBuffer($core.List<$core.int> i,
+          [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
+      create()..mergeFromBuffer(i, r);
+  factory AKeep.fromJson($core.String i,
+          [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
+      create()..mergeFromJson(i, r);
+  AKeep clone() => AKeep()..mergeFromMessage(this);
+  AKeep copyWith(void Function(AKeep) updates) =>
+      super.copyWith((message) => updates(message as AKeep));
+  $pb.BuilderInfo get info_ => _i;
+  @$core.pragma('dart2js:noInline')
+  static AKeep create() => AKeep._();
+  AKeep createEmptyInstance() => create();
+  static $pb.PbList<AKeep> createRepeated() => $pb.PbList<AKeep>();
+  @$core.pragma('dart2js:noInline')
+  static AKeep getDefault() =>
+      _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<AKeep>(create);
+  static AKeep _defaultInstance;
+}
+
+class NameManglingKeep extends $pb.GeneratedMessage {
+  static final $pb.BuilderInfo _i =
+      $pb.BuilderInfo('NameManglingKeep', createEmptyInstance: create)
+        ..aOM<AKeep>(10, 'clone', subBuilder: AKeep.create)
+        ..hasRequiredFields = false;
+
+  NameManglingKeep._() : super();
+  factory NameManglingKeep() => create();
+  factory NameManglingKeep.fromBuffer($core.List<$core.int> i,
+          [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
+      create()..mergeFromBuffer(i, r);
+  factory NameManglingKeep.fromJson($core.String i,
+          [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
+      create()..mergeFromJson(i, r);
+  NameManglingKeep clone() => NameManglingKeep()..mergeFromMessage(this);
+  NameManglingKeep copyWith(void Function(NameManglingKeep) updates) =>
+      super.copyWith((message) => updates(message as NameManglingKeep));
+  $pb.BuilderInfo get info_ => _i;
+  @$core.pragma('dart2js:noInline')
+  static NameManglingKeep create() => NameManglingKeep._();
+  NameManglingKeep createEmptyInstance() => create();
+  static $pb.PbList<NameManglingKeep> createRepeated() =>
+      $pb.PbList<NameManglingKeep>();
+  @$core.pragma('dart2js:noInline')
+  static NameManglingKeep getDefault() => _defaultInstance ??=
+      $pb.GeneratedMessage.$_defaultFor<NameManglingKeep>(create);
+  static NameManglingKeep _defaultInstance;
+
+  @$pb.TagNumber(10)
+  AKeep get clone_10 => $_getN(0);
+  @$pb.TagNumber(10)
+  set clone_10(AKeep v) {
+    setField(10, v);
+  }
+
+  @$pb.TagNumber(10)
+  $core.bool hasClone_10() => $_has(0);
+  @$pb.TagNumber(10)
+  void clearClone_10() => clearField(10);
+  @$pb.TagNumber(10)
+  AKeep ensureClone_10() => $_ensure(0);
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/name_mangling_test.dart b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/name_mangling_test.dart
new file mode 100644
index 0000000..b52c5dc
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/name_mangling_test.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:test/test.dart';
+
+import 'generated/name_mangling.pb.dart';
+
+main() {
+  NameManglingKeep n = NameManglingKeep.fromBuffer([]);
+  if (n.hasClone_10()) {
+    print("Has clone field");
+  }
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/name_mangling_test.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/name_mangling_test.dart.expect
new file mode 100644
index 0000000..c392e78
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/name_mangling_test.dart.expect
@@ -0,0 +1,68 @@
+library #lib;
+import self as self;
+import "generated/name_mangling.pb.dart" as pb;
+import "dart:core" as core;
+
+import "package:test/test.dart";
+import "file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/name_mangling.pb.dart";
+
+static method main() → dynamic {
+  pb::NameManglingKeep* n = [@vm.inferred-type.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/name_mangling.pb.dart::NameManglingKeep] pb::NameManglingKeep::fromBuffer(<core::int*>[]);
+  if([@vm.direct-call.metadata=library file:pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/generated/name_mangling.pb.dart::NameManglingKeep.hasClone_10] [@vm.inferred-type.metadata=dart.core::bool (skip check)] n.{pb::NameManglingKeep::hasClone_10}()) {
+    core::print("Has clone field");
+  }
+}
+library name_mangling.pb.dart;
+import self as self;
+import "package:protobuf/protobuf.dart" as pro;
+import "dart:core" as core;
+
+import "dart:core" as $core;
+import "package:protobuf/protobuf.dart" as $pb;
+
+class AKeep extends pro::GeneratedMessage {
+[@vm.inferred-type.metadata=protobuf::BuilderInfo?]  static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t1 = let core::String* #t2 = "AKeep" in let () →* self::AKeep* #t3 = #C1 in new pro::BuilderInfo::•(#t2, #t3) in block {
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t1.{pro::BuilderInfo::hasRequiredFields} = false;
+  } =>#t1;
+  constructor _() → self::AKeep*
+    : super pro::GeneratedMessage::•()
+    ;
+  static factory •() → self::AKeep*
+    return [@vm.inferred-type.metadata=name_mangling.pb.dart::AKeep] self::AKeep::create();
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method clone() → self::AKeep*
+    return let final self::AKeep* #t4 = [@vm.inferred-type.metadata=name_mangling.pb.dart::AKeep] self::AKeep::•() in block {
+      [@vm.direct-call.metadata=protobuf::GeneratedMessage.mergeFromMessage] [@vm.inferred-type.metadata=!? (skip check)] #t4.{pro::GeneratedMessage::mergeFromMessage}(this);
+    } =>#t4;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3]  get info_() → pro::BuilderInfo*
+    return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::AKeep::_i;
+  @#C4
+  static method create() → self::AKeep*
+    return new self::AKeep::_();
+}
+class NameManglingKeep extends pro::GeneratedMessage {
+[@vm.inferred-type.metadata=protobuf::BuilderInfo?]  static final field pro::BuilderInfo* _i = let final pro::BuilderInfo* #t5 = let core::String* #t6 = "NameManglingKeep" in let () →* self::NameManglingKeep* #t7 = #C5 in new pro::BuilderInfo::•(#t6, #t7) in block {
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.aOM] [@vm.inferred-type.metadata=!? (skip check)] #t5.{pro::BuilderInfo::aOM}<self::AKeep*>(10, "clone", subBuilder: #C1);
+    [@vm.direct-call.metadata=protobuf::BuilderInfo.hasRequiredFields] [@vm.inferred-type.metadata=!? (skip check)] #t5.{pro::BuilderInfo::hasRequiredFields} = false;
+  } =>#t5;
+  constructor _() → self::NameManglingKeep*
+    : super pro::GeneratedMessage::•()
+    ;
+  static factory •() → self::NameManglingKeep*
+    return [@vm.inferred-type.metadata=name_mangling.pb.dart::NameManglingKeep] self::NameManglingKeep::create();
+  static factory fromBuffer([@vm.inferred-type.metadata=dart.core::_GrowableList<dart.core::int*>] core::List<core::int*>* i, [[@vm.inferred-type.metadata=protobuf::_EmptyExtensionRegistry (value: const protobuf::_EmptyExtensionRegistry{})] pro::ExtensionRegistry* r = #C6]) → self::NameManglingKeep*
+    return let final self::NameManglingKeep* #t8 = [@vm.inferred-type.metadata=name_mangling.pb.dart::NameManglingKeep] self::NameManglingKeep::create() in block {
+      [@vm.direct-call.metadata=protobuf::GeneratedMessage.mergeFromBuffer] [@vm.inferred-type.metadata=!? (skip check)] #t8.{pro::GeneratedMessage::mergeFromBuffer}(i, r);
+    } =>#t8;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  method clone() → self::NameManglingKeep*
+    return let final self::NameManglingKeep* #t9 = [@vm.inferred-type.metadata=name_mangling.pb.dart::NameManglingKeep] self::NameManglingKeep::•() in block {
+      [@vm.direct-call.metadata=protobuf::GeneratedMessage.mergeFromMessage] [@vm.inferred-type.metadata=!? (skip check)] #t9.{pro::GeneratedMessage::mergeFromMessage}(this);
+    } =>#t9;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:3]  get info_() → pro::BuilderInfo*
+    return [@vm.inferred-type.metadata=protobuf::BuilderInfo?] self::NameManglingKeep::_i;
+  @#C4
+  static method create() → self::NameManglingKeep*
+    return new self::NameManglingKeep::_();
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5]  @#C8
+  method hasClone_10() → core::bool*
+    return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_has] [@vm.inferred-type.metadata=dart.core::bool (skip check)] this.{pro::GeneratedMessage::$_has}(0);
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/nop_test.dart b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/nop_test.dart
new file mode 100644
index 0000000..60997dc
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/nop_test.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+main() {
+  // Ensures the protobuf-aware tree shaker can also transform non-protobuf
+  // using code.
+  print("hello world");
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/nop_test.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/nop_test.dart.expect
new file mode 100644
index 0000000..7512991
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/lib/nop_test.dart.expect
@@ -0,0 +1,7 @@
+library #lib;
+import self as self;
+import "dart:core" as core;
+
+static method main() → dynamic {
+  core::print("hello world");
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/protos/foo.proto b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/protos/foo.proto
new file mode 100644
index 0000000..1f10872
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/protos/foo.proto
@@ -0,0 +1,36 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+syntax = "proto3";
+
+message FooKeep {
+  BarKeep barKeep = 1;
+  BarKeep barDrop = 2;
+  map<string, BarKeep> mapKeep = 3;
+  map<string, ZopDrop> mapDrop = 4;
+  int32 aKeep = 5;
+  HasKeep hasKeep = 6;
+  ClearKeep clearKeep = 7;
+}
+
+message BarKeep {
+  int32 aKeep = 1;
+  int32 bDrop = 2;
+}
+
+message HasKeep {
+  int32 aDrop = 1;
+}
+
+message ClearKeep {
+  int32 aDrop = 1;
+}
+
+message ZopDrop {
+  int32 aDrop = 1;
+}
+
+message MobDrop {
+  int32 aDrop = 1;
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/protos/name_mangling.proto b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/protos/name_mangling.proto
new file mode 100644
index 0000000..f25b2f4
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/protobuf_handler/protos/name_mangling.proto
@@ -0,0 +1,10 @@
+syntax = "proto3";
+
+message AKeep {}
+
+message NameManglingKeep {
+  // the name `clone` is mangled by the protoc_plugin to not conflict with
+  // `GeneratedMessage.clone`.
+  // Still we should be able to detect usages of this field.
+  AKeep clone = 10;
+}
\ No newline at end of file
diff --git a/pkg/vm/tool/precompiler2 b/pkg/vm/tool/precompiler2
index b76c8bb..dd5b9be 100755
--- a/pkg/vm/tool/precompiler2
+++ b/pkg/vm/tool/precompiler2
@@ -34,6 +34,8 @@
     ;;
     --tfa | \
     --no-tfa | \
+    --protobuf-tree-shaker | \
+    --protobuf-tree-shaker-v2 | \
     --gen-bytecode | \
     --no-gen-bytecode | \
     --bytecode-options=* | \
diff --git a/pkg/vm_snapshot_analysis/.gitignore b/pkg/vm_snapshot_analysis/.gitignore
new file mode 100644
index 0000000..49ce72d
--- /dev/null
+++ b/pkg/vm_snapshot_analysis/.gitignore
@@ -0,0 +1,3 @@
+.dart_tool/
+.packages
+pubspec.lock
diff --git a/pkg/vm_snapshot_analysis/AUTHORS b/pkg/vm_snapshot_analysis/AUTHORS
new file mode 100644
index 0000000..846e4a1
--- /dev/null
+++ b/pkg/vm_snapshot_analysis/AUTHORS
@@ -0,0 +1,6 @@
+# Below is a list of people and organizations that have contributed
+# to the Dart project. Names should be added to the list like so:
+#
+#   Name/Organization <email address>
+
+Google LLC
diff --git a/pkg/vm_snapshot_analysis/CHANGELOG.md b/pkg/vm_snapshot_analysis/CHANGELOG.md
new file mode 100644
index 0000000..3742d31
--- /dev/null
+++ b/pkg/vm_snapshot_analysis/CHANGELOG.md
@@ -0,0 +1,5 @@
+# Changelog
+
+## 0.1.0
+
+- Initial release
diff --git a/pkg/vm_snapshot_analysis/LICENSE b/pkg/vm_snapshot_analysis/LICENSE
new file mode 100644
index 0000000..18daf2b
--- /dev/null
+++ b/pkg/vm_snapshot_analysis/LICENSE
@@ -0,0 +1,26 @@
+Copyright 2020, the Dart project authors. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of Google Inc. nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/pkg/vm_snapshot_analysis/README.md b/pkg/vm_snapshot_analysis/README.md
new file mode 100644
index 0000000..92cf613
--- /dev/null
+++ b/pkg/vm_snapshot_analysis/README.md
@@ -0,0 +1,137 @@
+# vm_snapshot_analysis
+
+This package provides libraries and a utility for analysing the size and
+contents of Dart VM AOT snapshots based on the output of
+`--print-instructions-sizes-to` and `--write-v8-snapshot-profile-to` VM flags.
+
+## AOT Snapshot Basics
+
+Dart VM AOT snapshot is simply a serialized representation of the Dart VM
+heap graph. It consists of two parts: data (e.g. strings, `const` instances,
+objects representing classes, libraries, functions and runtime metadata) and
+executable code (machine code generated from Dart sources). Some nodes in this
+graph have clean and direct relationship to  the original program (e.g. objects
+representing libraries, classes, functions), while other nodes don't. Bitwise
+equivalent objects can be deduplicated and shared (e.g. two functions with the
+same body will end up using the same machine code object). This makes
+impossible to attribute of every single byte from the snapshot to a particular
+place in the program with a 100% accuracy.
+
+* `--print-instructions-sizes-to` attributes _executable code_ from the snapshot
+to a particular Dart function (or internal stub) from which this code
+originated (ignoring deduplication). Executable code usually constitutes around
+half of the snapshot, those this varies depending on the application.
+* `--write-v8-snapshot-profile-to` is a graph representation of the snapshot,
+it attributes bytes written into a snapshot to a node in the heap graph. This
+format covers both data and code sections of the snapshot.
+
+## CLI
+
+The command line interface to the tools in this package is provided by a single
+entry point `bin/analyse.dart`. It consumes output of
+`--print-instructions-sizes-to` and `--write-v8-snapshot-profile-to` flags and
+presents it in different human readable ways.
+
+This script can be intalled globally as `snapshot_analysis` using
+
+```console
+$ pub global activate vm_snapshot_analysis
+```
+
+`snapshot_analysis` supports the following subcommands:
+
+### `summary`
+
+```console
+$ snapshot_analysis summary [-b granularity] [-w filter] <input.json>
+```
+
+This command shows breakdown of snapshot bytes at the given `granularity` (e.g.
+`method`, `class`, `library` or `package`), filtered by the given substring
+`filter`.
+
+For example, here is a output showing how many bytes from a snapshot
+can be attributed to classes in the `dart:core` library:
+
+```console
+$ pkg/vm/bin/snapshot_analysis.dart summary -b class -w dart:core profile.json
++-----------+------------------------+--------------+---------+----------+
+| Library   | Class                  | Size (Bytes) | Percent | Of total |
++-----------+------------------------+--------------+---------+----------+
+| dart:core | _Uri                   |        43563 |  15.53% |    5.70% |
+| dart:core | _StringBase            |        28831 |  10.28% |    3.77% |
+| dart:core | ::                     |        27559 |   9.83% |    3.60% |
+| @other    |                        |        25467 |   9.08% |    3.33% |
+| dart:core | Uri                    |        14936 |   5.33% |    1.95% |
+| dart:core | int                    |        12276 |   4.38% |    1.61% |
+| dart:core | NoSuchMethodError      |        12222 |   4.36% |    1.60% |
+...
+```
+
+Here objects which can be attributed to `_Uri` take `5.7%` of the snapshot,
+at the same time objects which can be attributed to `dart:core` library
+but not to any specific class within this library take `3.33%` of the snapshot.
+
+
+### `compare`
+
+```console
+$ snapshot_analysis compare [-b granularity] <old.json> <new.json>
+```
+
+This command shows comparison between two size profiles, allowing to understand
+changes to which part of the program contributed most to the change in the
+overall snapshot size.
+
+```console
+$ pkg/vm/bin/snapshot_analysis.dart compare -b class old.json new.json
++------------------------+--------------------------+--------------+---------+
+| Library                | Class                    | Diff (Bytes) | Percent |
++------------------------+--------------------------+--------------+---------+
+| dart:core              | _SimpleUri               |        11519 |  22.34% |
+| dart:core              | _Uri                     |         6563 |  12.73% |
+| dart:io                | _RandomAccessFile        |         5337 |  10.35% |
+| @other                 |                          |         4009 |   7.78% |
+...
+```
+
+In this example `11519` more bytes can be attributed to `_SimpleUri` class in
+`new.json` compared to `old.json`.
+
+### `treemap`
+
+```console
+$ snapshot_analysis treemap <input.json> <output-dir>
+$ google-chrome <output-dir>/index.html
+```
+
+This command generates treemap representation of the information from the
+profile `input.json` and stores it in `output-dir` directory. Treemap can
+later be viewed by opening `<output-dir>/index.html` in the browser of your
+choice.
+
+## API
+
+This package can also be used as a building block for other packages which
+want to analyse VM AOT snapshots.
+
+* `package:vm_snapshot_analysis/instruction_sizes.dart` provides helpers to
+read output of `--print-instructions-sizes-to=...`
+* `package:vm_snapshot_analysis/v8_profile.dart` provides helpers to read
+output of `--write-v8-snapshot-profile-to=...`
+
+Both formats can be converted into a `ProgramInfo` structure which attempts
+to breakdown snapshot size into hierarchical representation of the program
+structure which can be understood by a Dart developer, attributing bytes
+to packages, libraries, classes and functions.
+
+* `package:vm_snapshot_analysis/utils.dart` contains helper method
+`loadProgramInfo` which automatically detects format of the input JSON file
+and creates `ProgramInfo` in an appropriate way, allowing to write code
+which works in the same way with both formats.
+
+## Features and bugs
+
+Please file feature requests and bugs at the [issue tracker][tracker].
+
+[tracker]: https://github.com/dart-lang/sdk/issues
diff --git a/pkg/vm_snapshot_analysis/analysis_options.yaml b/pkg/vm_snapshot_analysis/analysis_options.yaml
new file mode 100644
index 0000000..8981941
--- /dev/null
+++ b/pkg/vm_snapshot_analysis/analysis_options.yaml
@@ -0,0 +1,4 @@
+include: package:pedantic/analysis_options.1.8.0.yaml
+analyzer:
+  exclude:
+    - lib/src/assets/**
diff --git a/pkg/vm/bin/snapshot_analysis.dart b/pkg/vm_snapshot_analysis/bin/analyse.dart
similarity index 67%
rename from pkg/vm/bin/snapshot_analysis.dart
rename to pkg/vm_snapshot_analysis/bin/analyse.dart
index f3a037f..5123fd6 100755
--- a/pkg/vm/bin/snapshot_analysis.dart
+++ b/pkg/vm_snapshot_analysis/bin/analyse.dart
@@ -1,15 +1,17 @@
 #!/usr/bin/env dart
+
 // Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
+import 'dart:io';
 
 import 'package:args/command_runner.dart';
 
-import 'package:vm/snapshot/commands/compare.dart';
-import 'package:vm/snapshot/commands/summary.dart';
-import 'package:vm/snapshot/commands/treemap.dart';
+import 'package:vm_snapshot_analysis/src/commands/compare.dart';
+import 'package:vm_snapshot_analysis/src/commands/summary.dart';
+import 'package:vm_snapshot_analysis/src/commands/treemap.dart';
 
-final runner = CommandRunner('snapshot_analysis.dart',
+final runner = CommandRunner(Platform.script.pathSegments.last,
     'Tools for binary size analysis of Dart VM AOT snapshots.')
   ..addCommand(TreemapCommand())
   ..addCommand(CompareCommand())
diff --git a/pkg/vm/lib/snapshot/ascii_table.dart b/pkg/vm_snapshot_analysis/lib/ascii_table.dart
similarity index 97%
rename from pkg/vm/lib/snapshot/ascii_table.dart
rename to pkg/vm_snapshot_analysis/lib/ascii_table.dart
index a1b1df1..a0e5404 100644
--- a/pkg/vm/lib/snapshot/ascii_table.dart
+++ b/pkg/vm_snapshot_analysis/lib/ascii_table.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-library vm.snapshot.ascii_table;
+library vm_snapshot_analysis.ascii_table;
 
 import 'dart:math' as math;
 
@@ -126,7 +126,7 @@
 
   final List<Row> rows = <Row>[];
 
-  AsciiTable({List<dynamic> header, this.maxWidth: unlimitedWidth}) {
+  AsciiTable({List<dynamic> header, this.maxWidth = unlimitedWidth}) {
     if (header != null) {
       addSeparator();
       addRow(header);
diff --git a/pkg/vm/lib/snapshot/instruction_sizes.dart b/pkg/vm_snapshot_analysis/lib/instruction_sizes.dart
similarity index 96%
rename from pkg/vm/lib/snapshot/instruction_sizes.dart
rename to pkg/vm_snapshot_analysis/lib/instruction_sizes.dart
index c05bad8..635f8dd 100644
--- a/pkg/vm/lib/snapshot/instruction_sizes.dart
+++ b/pkg/vm_snapshot_analysis/lib/instruction_sizes.dart
@@ -3,10 +3,10 @@
 // BSD-style license that can be found in the LICENSE file.
 
 /// Helper functions for parsing output of `--print-instructions-sizes-to` flag.
-library vm.snapshot.instruction_sizes;
+library vm_snapshot_analysis.instruction_sizes;
 
-import 'package:vm/snapshot/name.dart';
-import 'package:vm/snapshot/program_info.dart';
+import 'package:vm_snapshot_analysis/name.dart';
+import 'package:vm_snapshot_analysis/program_info.dart';
 
 /// Parse the output of `--print-instructions-sizes-to` saved in the given
 /// file [input].
diff --git a/pkg/vm/lib/snapshot/name.dart b/pkg/vm_snapshot_analysis/lib/name.dart
similarity index 98%
rename from pkg/vm/lib/snapshot/name.dart
rename to pkg/vm_snapshot_analysis/lib/name.dart
index e636b34..09b7893 100644
--- a/pkg/vm/lib/snapshot/name.dart
+++ b/pkg/vm_snapshot_analysis/lib/name.dart
@@ -3,7 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 /// Helpers for parsing Code object name produced by Code::QualifiedName
-library vm.snapshot.name;
+library vm_snapshot_analysis.name;
 
 // Wrapper around the name of a Code object produced by Code::QualifiedName.
 //
diff --git a/pkg/vm/lib/snapshot/program_info.dart b/pkg/vm_snapshot_analysis/lib/program_info.dart
similarity index 69%
rename from pkg/vm/lib/snapshot/program_info.dart
rename to pkg/vm_snapshot_analysis/lib/program_info.dart
index 09f233c..56be4ac 100644
--- a/pkg/vm/lib/snapshot/program_info.dart
+++ b/pkg/vm_snapshot_analysis/lib/program_info.dart
@@ -3,10 +3,12 @@
 // BSD-style license that can be found in the LICENSE file.
 
 /// Classes for representing information about the program structure.
-library vm.snapshot.program_info;
+library vm_snapshot_analysis.program_info;
 
 import 'package:meta/meta.dart';
 
+import 'package:vm_snapshot_analysis/v8_profile.dart';
+
 /// Represents information about compiled program.
 class ProgramInfo {
   static const int rootId = 0;
@@ -18,6 +20,10 @@
   final ProgramInfoNode unknown;
   int _nextId = 3;
 
+  /// V8 snapshot profile if this [ProgramInfo] object was created from an
+  /// output of `--write-v8-snapshot-profile-to=...` flag.
+  SnapshotInfo snapshotInfo;
+
   ProgramInfo._(this.root, this.stubs, this.unknown);
 
   factory ProgramInfo() {
@@ -53,7 +59,8 @@
   /// Recursively visit all function nodes, which have [FunctionInfo.info]
   /// populated.
   void visit(
-      void Function(String pkg, String lib, String cls, String fun, int size)
+      void Function(
+              String pkg, String lib, String cls, String fun, ProgramInfoNode n)
           callback) {
     final context = List<String>(NodeType.values.length);
 
@@ -65,13 +72,11 @@
         context[node._type] = node.name;
       }
 
-      if (node.size != null) {
-        final String pkg = context[NodeType.packageNode.index];
-        final String lib = context[NodeType.libraryNode.index];
-        final String cls = context[NodeType.classNode.index];
-        final String mem = context[NodeType.functionNode.index];
-        callback(pkg, lib, cls, mem, node.size);
-      }
+      final String pkg = context[NodeType.packageNode.index];
+      final String lib = context[NodeType.libraryNode.index];
+      final String cls = context[NodeType.classNode.index];
+      final String mem = context[NodeType.functionNode.index];
+      callback(pkg, lib, cls, mem, node);
 
       for (var child in node.children.values) {
         recurse(child);
@@ -85,8 +90,8 @@
 
   int get totalSize {
     var result = 0;
-    visit((pkg, lib, cls, fun, size) {
-      result += size;
+    visit((pkg, lib, cls, fun, node) {
+      result += node.size ?? 0;
     });
     return result;
   }
@@ -175,13 +180,11 @@
   return <T>{...?a?.keys, ...?b?.keys};
 }
 
-/// Histogram of sizes based on a [ProgramInfo] bucketed using one of the
-/// [HistogramType] rules.
-class SizesHistogram {
+class Histogram {
   /// Rule used to produce this histogram. Specifies how bucket names
   /// are constructed given (library-uri,class-name,function-name) tuples and
   /// how these bucket names can be deconstructed back into human readable form.
-  final Bucketing bucketing;
+  final BucketInfo bucketInfo;
 
   /// Histogram buckets.
   final Map<String, int> buckets;
@@ -194,24 +197,77 @@
 
   int get length => bySize.length;
 
-  SizesHistogram._(this.bucketing, this.buckets, this.bySize, this.totalSize);
+  Histogram._(this.bucketInfo, this.buckets)
+      : bySize = buckets.keys.toList(growable: false)
+          ..sort((a, b) => buckets[b] - buckets[a]),
+        totalSize = buckets.values.fold(0, (sum, size) => sum + size);
 
-  /// Construct the histogram of specific [type] given a [ProgramInfo].
-  static SizesHistogram from(ProgramInfo info, HistogramType type) {
+  static Histogram fromIterable<T>(
+    Iterable<T> entries, {
+    @required int Function(T) sizeOf,
+    @required String Function(T) bucketFor,
+    @required BucketInfo bucketInfo,
+  }) {
+    final buckets = <String, int>{};
+
+    for (var e in entries) {
+      final bucket = bucketFor(e);
+      final size = sizeOf(e);
+      buckets[bucket] = (buckets[bucket] ?? 0) + size;
+    }
+
+    return Histogram._(bucketInfo, buckets);
+  }
+}
+
+/// Construct the histogram of specific [type] given a [ProgramInfo].
+Histogram computeHistogram(ProgramInfo info, HistogramType type,
+    {String filter}) {
+  bool Function(String, String, String) matchesFilter;
+
+  if (filter != null) {
+    final re = RegExp(filter.replaceAll('*', '.*'), caseSensitive: false);
+    matchesFilter = (lib, cls, fun) => re.hasMatch("${lib}::${cls}.${fun}");
+  } else {
+    matchesFilter = (_, __, ___) => true;
+  }
+
+  if (type == HistogramType.byNodeType) {
+    final Set<int> filteredNodes = {};
+    if (filter != null) {
+      info.visit((pkg, lib, cls, fun, node) {
+        if (matchesFilter(lib, cls, fun)) {
+          filteredNodes.add(node.id);
+        }
+      });
+    }
+
+    return Histogram.fromIterable<Node>(
+        info.snapshotInfo.snapshot.nodes.where((n) =>
+            filter == null ||
+            filteredNodes.contains(info.snapshotInfo.ownerOf(n).id)),
+        sizeOf: (n) {
+          return n.selfSize;
+        },
+        bucketFor: (n) => n.type,
+        bucketInfo: const BucketInfo(nameComponents: ['Type']));
+  } else {
     final buckets = <String, int>{};
     final bucketing = Bucketing._forType[type];
 
-    var totalSize = 0;
-    info.visit((pkg, lib, cls, fun, size) {
+    info.visit((pkg, lib, cls, fun, node) {
+      if (node.size == null || node.size == 0) {
+        return;
+      }
+
       final bucket = bucketing.bucketFor(pkg, lib, cls, fun);
-      buckets[bucket] = (buckets[bucket] ?? 0) + size;
-      totalSize += size;
+      if (!matchesFilter(lib, cls, fun)) {
+        return;
+      }
+      buckets[bucket] = (buckets[bucket] ?? 0) + node.size;
     });
 
-    final bySize = buckets.keys.toList(growable: false);
-    bySize.sort((a, b) => buckets[b] - buckets[a]);
-
-    return SizesHistogram._(bucketing, buckets, bySize, totalSize);
+    return Histogram._(bucketing, buckets);
   }
 }
 
@@ -220,22 +276,28 @@
   byClass,
   byLibrary,
   byPackage,
+  byNodeType,
 }
 
-abstract class Bucketing {
+class BucketInfo {
   /// Specifies which human readable name components can be extracted from
   /// the bucket name.
-  List<String> get nameComponents;
+  final List<String> nameComponents;
 
+  /// Deconstructs bucket name into human readable components (the order matches
+  /// one returned by [nameComponents]).
+  List<String> namesFromBucket(String bucket) => [bucket];
+
+  const BucketInfo({@required this.nameComponents});
+}
+
+abstract class Bucketing extends BucketInfo {
   /// Constructs the bucket name from the given library name [lib], class name
   /// [cls] and function name [fun].
   String bucketFor(String pkg, String lib, String cls, String fun);
 
-  /// Deconstructs bucket name into human readable components (the order matches
-  /// one returned by [nameComponents]).
-  List<String> namesFromBucket(String bucket);
-
-  const Bucketing();
+  const Bucketing({@required List<String> nameComponents})
+      : super(nameComponents: nameComponents);
 
   static const _forType = {
     HistogramType.bySymbol: _BucketBySymbol(),
@@ -250,9 +312,6 @@
 
 class _BucketBySymbol extends Bucketing {
   @override
-  List<String> get nameComponents => const ['Library', 'Symbol'];
-
-  @override
   String bucketFor(String pkg, String lib, String cls, String fun) {
     if (fun == null) {
       return '@other${_nameSeparator}';
@@ -263,14 +322,11 @@
   @override
   List<String> namesFromBucket(String bucket) => bucket.split(_nameSeparator);
 
-  const _BucketBySymbol();
+  const _BucketBySymbol() : super(nameComponents: const ['Library', 'Symbol']);
 }
 
 class _BucketByClass extends Bucketing {
   @override
-  List<String> get nameComponents => ['Library', 'Class'];
-
-  @override
   String bucketFor(String pkg, String lib, String cls, String fun) {
     if (cls == null) {
       return '@other${_nameSeparator}';
@@ -281,34 +337,22 @@
   @override
   List<String> namesFromBucket(String bucket) => bucket.split(_nameSeparator);
 
-  const _BucketByClass();
+  const _BucketByClass() : super(nameComponents: const ['Library', 'Class']);
 }
 
 class _BucketByLibrary extends Bucketing {
   @override
-  List<String> get nameComponents => ['Library'];
-
-  @override
   String bucketFor(String pkg, String lib, String cls, String fun) => '$lib';
 
-  @override
-  List<String> namesFromBucket(String bucket) => [bucket];
-
-  const _BucketByLibrary();
+  const _BucketByLibrary() : super(nameComponents: const ['Library']);
 }
 
 class _BucketByPackage extends Bucketing {
   @override
-  List<String> get nameComponents => ['Package'];
-
-  @override
   String bucketFor(String pkg, String lib, String cls, String fun) =>
       pkg ?? lib;
 
-  @override
-  List<String> namesFromBucket(String bucket) => [bucket];
-
-  const _BucketByPackage();
+  const _BucketByPackage() : super(nameComponents: const ['Package']);
 }
 
 String packageOf(String lib) {
diff --git a/pkg/vm_snapshot_analysis/lib/src/assets/D3SymbolTreeMap.js b/pkg/vm_snapshot_analysis/lib/src/assets/D3SymbolTreeMap.js
new file mode 100644
index 0000000..88dd692
--- /dev/null
+++ b/pkg/vm_snapshot_analysis/lib/src/assets/D3SymbolTreeMap.js
@@ -0,0 +1,938 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// TODO:
+// 1. Visibility functions: base on boxPadding.t, not 15
+// 2. Track a maxDisplayDepth that is user-settable:
+//    maxDepth == currentRoot.depth + maxDisplayDepth
+function D3SymbolTreeMap(mapWidth, mapHeight, levelsToShow) {
+  this._mapContainer = undefined;
+  this._mapWidth = mapWidth;
+  this._mapHeight = mapHeight;
+  this.boxPadding = {'l': 5, 'r': 5, 't': 20, 'b': 5};
+  this.infobox = undefined;
+  this._maskContainer = undefined;
+  this._highlightContainer = undefined;
+  // Transition in this order:
+  // 1. Exiting items go away.
+  // 2. Updated items move.
+  // 3. New items enter.
+  this._exitDuration=500;
+  this._updateDuration=500;
+  this._enterDuration=500;
+  this._firstTransition=true;
+  this._layout = undefined;
+  this._currentRoot = undefined;
+  this._currentNodes = undefined;
+  this._treeData = undefined;
+  this._maxLevelsToShow = levelsToShow;
+  this._currentMaxDepth = this._maxLevelsToShow;
+}
+
+/**
+ * Make a number pretty, with comma separators.
+ */
+D3SymbolTreeMap._pretty = function(num) {
+  var asString = String(num);
+  var result = '';
+  var counter = 0;
+  for (var x = asString.length - 1; x >= 0; x--) {
+    counter++;
+    if (counter === 4) {
+      result = ',' + result;
+      counter = 1;
+    }
+    result = asString.charAt(x) + result;
+  }
+  return result;
+}
+
+/**
+ * Express a number in terms of KiB, MiB, GiB, etc.
+ * Note that these are powers of 2, not of 10.
+ */
+D3SymbolTreeMap._byteify = function(num) {
+  var suffix;
+  if (num >= 1024) {
+    if (num >= 1024 * 1024 * 1024) {
+      suffix = 'GiB';
+      num = num / (1024 * 1024 * 1024);
+    } else if (num >= 1024 * 1024) {
+      suffix = 'MiB';
+      num = num / (1024 * 1024);
+    } else if (num >= 1024) {
+      suffix = 'KiB'
+      num = num / 1024;
+    }
+    return num.toFixed(2) + ' ' + suffix;
+  }
+  return num + ' B';
+}
+
+D3SymbolTreeMap._NM_SYMBOL_TYPE_DESCRIPTIONS = {
+  // Definitions concisely derived from the nm 'man' page
+  'A': 'Global absolute (A)',
+  'B': 'Global uninitialized data (B)',
+  'b': 'Local uninitialized data (b)',
+  'C': 'Global uninitialized common (C)',
+  'D': 'Global initialized data (D)',
+  'd': 'Local initialized data (d)',
+  'G': 'Global small initialized data (G)',
+  'g': 'Local small initialized data (g)',
+  'i': 'Indirect function (i)',
+  'N': 'Debugging (N)',
+  'p': 'Stack unwind (p)',
+  'R': 'Global read-only data (R)',
+  'r': 'Local read-only data (r)',
+  'S': 'Global small uninitialized data (S)',
+  's': 'Local small uninitialized data (s)',
+  'T': 'Global code (T)',
+  't': 'Local code (t)',
+  'U': 'Undefined (U)',
+  'u': 'Unique (u)',
+  'V': 'Global weak object (V)',
+  'v': 'Local weak object (v)',
+  'W': 'Global weak symbol (W)',
+  'w': 'Local weak symbol (w)',
+  '@': 'Vtable entry (@)', // non-standard, hack.
+  '-': 'STABS debugging (-)',
+  '?': 'Unrecognized (?)',
+};
+D3SymbolTreeMap._NM_SYMBOL_TYPES = '';
+for (var symbol_type in D3SymbolTreeMap._NM_SYMBOL_TYPE_DESCRIPTIONS) {
+  D3SymbolTreeMap._NM_SYMBOL_TYPES += symbol_type;
+}
+
+/**
+ * Given a symbol type code, look up and return a human-readable description
+ * of that symbol type. If the symbol type does not match one of the known
+ * types, the unrecognized description (corresponding to symbol type '?') is
+ * returned instead of null or undefined.
+ */
+D3SymbolTreeMap._getSymbolDescription = function(type) {
+  var result = D3SymbolTreeMap._NM_SYMBOL_TYPE_DESCRIPTIONS[type];
+  if (result === undefined) {
+    result = D3SymbolTreeMap._NM_SYMBOL_TYPE_DESCRIPTIONS['?'];
+  }
+  return result;
+}
+
+// Qualitative 12-value pastel Brewer palette.
+D3SymbolTreeMap._colorArray = [
+  'rgb(141,211,199)',
+  'rgb(255,255,179)',
+  'rgb(190,186,218)',
+  'rgb(251,128,114)',
+  'rgb(128,177,211)',
+  'rgb(253,180,98)',
+  'rgb(179,222,105)',
+  'rgb(252,205,229)',
+  'rgb(217,217,217)',
+  'rgb(188,128,189)',
+  'rgb(204,235,197)',
+  'rgb(255,237,111)'];
+
+D3SymbolTreeMap._initColorMap = function() {
+  var map = {};
+  var numColors = D3SymbolTreeMap._colorArray.length;
+  var count = 0;
+  for (var key in D3SymbolTreeMap._NM_SYMBOL_TYPE_DESCRIPTIONS) {
+    var index = count++ % numColors;
+    map[key] = d3.rgb(D3SymbolTreeMap._colorArray[index]);
+  }
+  D3SymbolTreeMap._colorMap = map;
+}
+D3SymbolTreeMap._initColorMap();
+
+D3SymbolTreeMap.getColorForType = function(type) {
+  var result = D3SymbolTreeMap._colorMap[type];
+  if (result === undefined) return d3.rgb('rgb(255,255,255)');
+  return result;
+}
+
+D3SymbolTreeMap.prototype.init = function() {
+  this.infobox = this._createInfoBox();
+  this._mapContainer = d3.select('body').append('div')
+      .style('position', 'relative')
+      .style('width', this._mapWidth)
+      .style('height', this._mapHeight)
+      .style('padding', 0)
+      .style('margin', 0)
+      .style('box-shadow', '5px 5px 5px #888');
+  this._layout = this._createTreeMapLayout();
+  this._setData(tree_data); // TODO: Don't use global 'tree_data'
+}
+
+/**
+ * Sets the data displayed by the treemap and layint out the map.
+ */
+D3SymbolTreeMap.prototype._setData = function(data) {
+  this._treeData = data;
+  console.time('_crunchStats');
+  this._crunchStats(data);
+  console.timeEnd('_crunchStats');
+  this._currentRoot = this._treeData;
+  this._currentNodes = this._layout.nodes(this._currentRoot);
+  this._currentMaxDepth = this._maxLevelsToShow;
+  this._doLayout();
+}
+
+/**
+ * Recursively traverses the entire tree starting from the specified node,
+ * computing statistics and recording metadata as it goes. Call this method
+ * only once per imported tree.
+ */
+D3SymbolTreeMap.prototype._crunchStats = function(node) {
+  var stack = [];
+  stack.idCounter = 0;
+  this._crunchStatsHelper(stack, node);
+}
+
+/**
+ * Invoke the specified visitor function on all data elements currently shown
+ * in the treemap including any and all of their children, starting at the
+ * currently-displayed root and descending recursively. The function will be
+ * passed the datum element representing each node. No traversal guarantees
+ * are made.
+ */
+D3SymbolTreeMap.prototype.visitFromDisplayedRoot = function(visitor) {
+  this._visit(this._currentRoot, visitor);
+}
+
+/**
+ * Helper function for visit functions.
+ */
+D3SymbolTreeMap.prototype._visit = function(datum, visitor) {
+  visitor.call(this, datum);
+  if (datum.children) for (var i = 0; i < datum.children.length; i++) {
+    this._visit(datum.children[i], visitor);
+  }
+}
+
+D3SymbolTreeMap.prototype._crunchStatsHelper = function(stack, node) {
+  // Only overwrite the node ID if it isn't already set.
+  // This allows stats to be crunched multiple times on subsets of data
+  // without breaking the data-to-ID bindings. New nodes get new IDs.
+  if (node.id === undefined) node.id = stack.idCounter++;
+  if (node.children === undefined) {
+    // Leaf node (symbol); accumulate stats.
+    for (var i = 0; i < stack.length; i++) {
+      var ancestor = stack[i];
+      if (!ancestor.symbol_stats) ancestor.symbol_stats = {};
+      if (ancestor.symbol_stats[node.t] === undefined) {
+        // New symbol type we haven't seen before, just record.
+        ancestor.symbol_stats[node.t] = {'count': 1,
+                                         'size': node.value};
+      } else {
+        // Existing symbol type, increment.
+        ancestor.symbol_stats[node.t].count++;
+        ancestor.symbol_stats[node.t].size += node.value;
+      }
+    }
+  } else for (var i = 0; i < node.children.length; i++) {
+    stack.push(node);
+    this._crunchStatsHelper(stack, node.children[i]);
+    stack.pop();
+  }
+}
+
+D3SymbolTreeMap.prototype._createTreeMapLayout = function() {
+  var result = d3.layout.treemap()
+      .padding([this.boxPadding.t, this.boxPadding.r,
+                this.boxPadding.b, this.boxPadding.l])
+      .size([this._mapWidth, this._mapHeight]);
+  return result;
+}
+
+D3SymbolTreeMap.prototype.resize = function(width, height) {
+  this._mapWidth = width;
+  this._mapHeight = height;
+  this._mapContainer.style('width', width).style('height', height);
+  this._layout.size([this._mapWidth, this._mapHeight]);
+  this._currentNodes = this._layout.nodes(this._currentRoot);
+  this._doLayout();
+}
+
+D3SymbolTreeMap.prototype._zoomDatum = function(datum) {
+  if (this._currentRoot === datum) return; // already here
+  this._hideHighlight(datum);
+  this._hideInfoBox(datum);
+  this._currentRoot = datum;
+  this._currentNodes = this._layout.nodes(this._currentRoot);
+  this._currentMaxDepth = this._currentRoot.depth + this._maxLevelsToShow;
+  console.log('zooming into datum ' + this._currentRoot.n);
+  this._doLayout();
+}
+
+D3SymbolTreeMap.prototype.setMaxLevels = function(levelsToShow) {
+  this._maxLevelsToShow = levelsToShow;
+  this._currentNodes = this._layout.nodes(this._currentRoot);
+  this._currentMaxDepth = this._currentRoot.depth + this._maxLevelsToShow;
+  console.log('setting max levels to show: ' + this._maxLevelsToShow);
+  this._doLayout();
+}
+
+/**
+ * Clone the specified tree, returning an independent copy of the data.
+ * Only the original attributes expected to exist prior to invoking
+ * _crunchStatsHelper are retained, with the exception of the 'id' attribute
+ * (which must be retained for proper transitions).
+ * If the optional filter parameter is provided, it will be called with 'this'
+ * set to this treemap instance and passed the 'datum' object as an argument.
+ * When specified, the copy will retain only the data for which the filter
+ * function returns true.
+ */
+D3SymbolTreeMap.prototype._clone = function(datum, filter) {
+  var trackingStats = false;
+  if (this.__cloneState === undefined) {
+    console.time('_clone');
+    trackingStats = true;
+    this.__cloneState = {'accepted': 0, 'rejected': 0,
+                         'forced': 0, 'pruned': 0};
+  }
+
+  // Must go depth-first. All parents of children that are accepted by the
+  // filter must be preserved!
+  var copy = {'n': datum.n, 'k': datum.k};
+  var childAccepted = false;
+  if (datum.children !== undefined) {
+    for (var i = 0; i < datum.children.length; i++) {
+      var copiedChild = this._clone(datum.children[i], filter);
+      if (copiedChild !== undefined) {
+        childAccepted = true; // parent must also be accepted.
+        if (copy.children === undefined) copy.children = [];
+        copy.children.push(copiedChild);
+      }
+    }
+  }
+
+  // Ignore nodes that don't match the filter, when present.
+  var accept = false;
+  if (childAccepted) {
+    // Parent of an accepted child must also be accepted.
+    this.__cloneState.forced++;
+    accept = true;
+  } else if (filter !== undefined && filter.call(this, datum) !== true) {
+    this.__cloneState.rejected++;
+  } else if (datum.children === undefined) {
+    // Accept leaf nodes that passed the filter
+    this.__cloneState.accepted++;
+    accept = true;
+  } else {
+    // Non-leaf node. If no children are accepted, prune it.
+    this.__cloneState.pruned++;
+  }
+
+  if (accept) {
+    if (datum.id !== undefined) copy.id = datum.id;
+    if (datum.lastPathElement !== undefined) {
+      copy.lastPathElement = datum.lastPathElement;
+    }
+    if (datum.t !== undefined) copy.t = datum.t;
+    if (datum.value !== undefined && datum.children === undefined) {
+      copy.value = datum.value;
+    }
+  } else {
+    // Discard the copy we were going to return
+    copy = undefined;
+  }
+
+  if (trackingStats === true) {
+    // We are the fist call in the recursive chain.
+    console.timeEnd('_clone');
+    var totalAccepted = this.__cloneState.accepted +
+                        this.__cloneState.forced;
+    console.log(
+        totalAccepted + ' nodes retained (' +
+        this.__cloneState.forced + ' forced by accepted children, ' +
+        this.__cloneState.accepted + ' accepted on their own merits), ' +
+        this.__cloneState.rejected + ' nodes (and their children) ' +
+                                     'filtered out,' +
+        this.__cloneState.pruned + ' nodes pruned because because no ' +
+                                   'children remained.');
+    delete this.__cloneState;
+  }
+  return copy;
+}
+
+D3SymbolTreeMap.prototype.filter = function(filter) {
+  // Ensure we have a copy of the original root.
+  if (this._backupTree === undefined) this._backupTree = this._treeData;
+  this._mapContainer.selectAll('div').remove();
+  this._setData(this._clone(this._backupTree, filter));
+}
+
+D3SymbolTreeMap.prototype._doLayout = function() {
+  console.time('_doLayout');
+  this._handleInodes();
+  this._handleLeaves();
+  this._firstTransition = false;
+  console.timeEnd('_doLayout');
+}
+
+D3SymbolTreeMap.prototype._highlightElement = function(datum, selection) {
+  this._showHighlight(datum, selection);
+}
+
+D3SymbolTreeMap.prototype._unhighlightElement = function(datum, selection) {
+  this._hideHighlight(datum, selection);
+}
+
+D3SymbolTreeMap.prototype._handleInodes = function() {
+  console.time('_handleInodes');
+  var thisTreeMap = this;
+  var inodes = this._currentNodes.filter(function(datum){
+    return (datum.depth <= thisTreeMap._currentMaxDepth) &&
+            datum.children !== undefined;
+  });
+  var cellsEnter = this._mapContainer.selectAll('div.inode')
+      .data(inodes, function(datum) { return datum.id; })
+      .enter()
+      .append('div').attr('class', 'inode').attr('id', function(datum){
+          return 'node-' + datum.id;});
+
+
+  // Define enter/update/exit for inodes
+  cellsEnter
+      .append('div')
+      .attr('class', 'rect inode_rect_entering')
+      .style('z-index', function(datum) { return datum.id * 2; })
+      .style('position', 'absolute')
+      .style('left', function(datum) { return datum.x; })
+      .style('top', function(datum){ return datum.y; })
+      .style('width', function(datum){ return datum.dx; })
+      .style('height', function(datum){ return datum.dy; })
+      .style('opacity', '0')
+      .style('border', '1px solid black')
+      .style('background-image', function(datum) {
+        return thisTreeMap._makeSymbolBucketBackgroundImage.call(
+               thisTreeMap, datum);
+      })
+      .style('background-color', function(datum) {
+        if (datum.t === undefined) return 'rgb(220,220,220)';
+        return D3SymbolTreeMap.getColorForType(datum.t).toString();
+      })
+      .on('mouseover', function(datum){
+        thisTreeMap._highlightElement.call(
+            thisTreeMap, datum, d3.select(this));
+        thisTreeMap._showInfoBox.call(thisTreeMap, datum);
+      })
+      .on('mouseout', function(datum){
+        thisTreeMap._unhighlightElement.call(
+            thisTreeMap, datum, d3.select(this));
+        thisTreeMap._hideInfoBox.call(thisTreeMap, datum);
+      })
+      .on('mousemove', function(){
+          thisTreeMap._moveInfoBox.call(thisTreeMap, event);
+      })
+      .on('dblclick', function(datum){
+        if (datum !== thisTreeMap._currentRoot) {
+          // Zoom into the selection
+          thisTreeMap._zoomDatum(datum);
+        } else if (datum.parent) {
+          console.log('event.shiftKey=' + event.shiftKey);
+          if (event.shiftKey === true) {
+            // Back to root
+            thisTreeMap._zoomDatum(thisTreeMap._treeData);
+          } else {
+            // Zoom out of the selection
+            thisTreeMap._zoomDatum(datum.parent);
+          }
+        }
+      });
+  cellsEnter
+      .append('div')
+      .attr('class', 'label inode_label_entering')
+      .style('z-index', function(datum) { return (datum.id * 2) + 1; })
+      .style('position', 'absolute')
+      .style('left', function(datum){ return datum.x; })
+      .style('top', function(datum){ return datum.y; })
+      .style('width', function(datum) { return datum.dx; })
+      .style('height', function(datum) { return thisTreeMap.boxPadding.t; })
+      .style('opacity', '0')
+      .style('pointer-events', 'none')
+      .style('-webkit-user-select', 'none')
+      .style('overflow', 'hidden') // required for ellipsis
+      .style('white-space', 'nowrap') // required for ellipsis
+      .style('text-overflow', 'ellipsis')
+      .style('text-align', 'center')
+      .style('vertical-align', 'top')
+      .style('visibility', function(datum) {
+        return (datum.dx < 15 || datum.dy < 15) ? 'hidden' : 'visible';
+      })
+      .text(function(datum) {
+        var sizeish = ' [' + D3SymbolTreeMap._byteify(datum.value) + ']'
+        var text;
+        if (datum.k === 'b') { // bucket
+          if (datum === thisTreeMap._currentRoot) {
+            text = thisTreeMap.pathFor(datum) + ': '
+                + D3SymbolTreeMap._getSymbolDescription(datum.t)
+          } else {
+            text = D3SymbolTreeMap._getSymbolDescription(datum.t);
+          }
+        } else if (datum === thisTreeMap._currentRoot) {
+          // The top-most level should always show the complete path
+          text = thisTreeMap.pathFor(datum);
+        } else {
+          // Anything that isn't a bucket or a leaf (symbol) or the
+          // current root should just show its name.
+          text = datum.n;
+        }
+        return text + sizeish;
+      }
+  );
+
+  // Complicated transition logic:
+  // For nodes that are entering, we want to fade them in in-place AFTER
+  // any adjusting nodes have resized and moved around. That way, new nodes
+  // seamlessly appear in the right spot after their containers have resized
+  // and moved around.
+  // To do this we do some trickery:
+  // 1. Define a '_entering' class on the entering elements
+  // 2. Use this to select only the entering elements and apply the opacity
+  //    transition.
+  // 3. Use the same transition to drop the '_entering' suffix, so that they
+  //    will correctly update in later zoom/resize/whatever operations.
+  // 4. The update transition is achieved by selecting the elements without
+  //    the '_entering_' suffix and applying movement and resizing transition
+  //    effects.
+  this._mapContainer.selectAll('div.inode_rect_entering').transition()
+      .duration(thisTreeMap._enterDuration).delay(
+          this._firstTransition ? 0 : thisTreeMap._exitDuration +
+              thisTreeMap._updateDuration)
+      .attr('class', 'rect inode_rect')
+      .style('opacity', '1')
+  this._mapContainer.selectAll('div.inode_label_entering').transition()
+      .duration(thisTreeMap._enterDuration).delay(
+          this._firstTransition ? 0 : thisTreeMap._exitDuration +
+              thisTreeMap._updateDuration)
+      .attr('class', 'label inode_label')
+      .style('opacity', '1')
+  this._mapContainer.selectAll('div.inode_rect').transition()
+      .duration(thisTreeMap._updateDuration).delay(thisTreeMap._exitDuration)
+      .style('opacity', '1')
+      .style('background-image', function(datum) {
+        return thisTreeMap._makeSymbolBucketBackgroundImage.call(
+            thisTreeMap, datum);
+      })
+      .style('left', function(datum) { return datum.x; })
+      .style('top', function(datum){ return datum.y; })
+      .style('width', function(datum){ return datum.dx; })
+      .style('height', function(datum){ return datum.dy; });
+  this._mapContainer.selectAll('div.inode_label').transition()
+      .duration(thisTreeMap._updateDuration).delay(thisTreeMap._exitDuration)
+      .style('opacity', '1')
+      .style('visibility', function(datum) {
+        return (datum.dx < 15 || datum.dy < 15) ? 'hidden' : 'visible';
+      })
+      .style('left', function(datum){ return datum.x; })
+      .style('top', function(datum){ return datum.y; })
+      .style('width', function(datum) { return datum.dx; })
+      .style('height', function(datum) { return thisTreeMap.boxPadding.t; })
+      .text(function(datum) {
+        var sizeish = ' [' + D3SymbolTreeMap._byteify(datum.value) + ']'
+        var text;
+        if (datum.k === 'b') {
+          if (datum === thisTreeMap._currentRoot) {
+            text = thisTreeMap.pathFor(datum) + ': ' +
+                D3SymbolTreeMap._getSymbolDescription(datum.t)
+          } else {
+            text = D3SymbolTreeMap._getSymbolDescription(datum.t);
+          }
+        } else if (datum === thisTreeMap._currentRoot) {
+          // The top-most level should always show the complete path
+          text = thisTreeMap.pathFor(datum);
+        } else {
+          // Anything that isn't a bucket or a leaf (symbol) or the
+          // current root should just show its name.
+          text = datum.n;
+        }
+        return text + sizeish;
+      });
+  var exit = this._mapContainer.selectAll('div.inode')
+      .data(inodes, function(datum) { return 'inode-' + datum.id; })
+      .exit();
+  exit.selectAll('div.inode_rect').transition().duration(
+      thisTreeMap._exitDuration).style('opacity', 0);
+  exit.selectAll('div.inode_label').transition().duration(
+      thisTreeMap._exitDuration).style('opacity', 0);
+  exit.transition().delay(thisTreeMap._exitDuration + 1).remove();
+
+  console.log(inodes.length + ' inodes layed out.');
+  console.timeEnd('_handleInodes');
+}
+
+D3SymbolTreeMap.prototype._handleLeaves = function() {
+  console.time('_handleLeaves');
+  var color_fn = d3.scale.category10();
+  var thisTreeMap = this;
+  var leaves = this._currentNodes.filter(function(datum){
+    return (datum.depth <= thisTreeMap._currentMaxDepth) &&
+        datum.children === undefined; });
+  var cellsEnter = this._mapContainer.selectAll('div.leaf')
+      .data(leaves, function(datum) { return datum.id; })
+      .enter()
+      .append('div').attr('class', 'leaf').attr('id', function(datum){
+        return 'node-' + datum.id;
+      });
+
+  // Define enter/update/exit for leaves
+  cellsEnter
+      .append('div')
+      .attr('class', 'rect leaf_rect_entering')
+      .style('z-index', function(datum) { return datum.id * 2; })
+      .style('position', 'absolute')
+      .style('left', function(datum){ return datum.x; })
+      .style('top', function(datum){ return datum.y; })
+      .style('width', function(datum){ return datum.dx; })
+      .style('height', function(datum){ return datum.dy; })
+      .style('opacity', '0')
+      .style('background-color', function(datum) {
+        if (datum.t === undefined) return 'rgb(220,220,220)';
+        return D3SymbolTreeMap.getColorForType(datum.t)
+            .darker(0.3).toString();
+      })
+      .style('border', '1px solid black')
+      .on('mouseover', function(datum){
+        thisTreeMap._highlightElement.call(
+            thisTreeMap, datum, d3.select(this));
+        thisTreeMap._showInfoBox.call(thisTreeMap, datum);
+      })
+      .on('mouseout', function(datum){
+        thisTreeMap._unhighlightElement.call(
+            thisTreeMap, datum, d3.select(this));
+        thisTreeMap._hideInfoBox.call(thisTreeMap, datum);
+      })
+      .on('mousemove', function(){ thisTreeMap._moveInfoBox.call(
+        thisTreeMap, event);
+      });
+  cellsEnter
+      .append('div')
+      .attr('class', 'label leaf_label_entering')
+      .style('z-index', function(datum) { return (datum.id * 2) + 1; })
+      .style('position', 'absolute')
+      .style('left', function(datum){ return datum.x; })
+      .style('top', function(datum){ return datum.y; })
+      .style('width', function(datum) { return datum.dx; })
+      .style('height', function(datum) { return datum.dy; })
+      .style('opacity', '0')
+      .style('pointer-events', 'none')
+      .style('-webkit-user-select', 'none')
+      .style('overflow', 'hidden') // required for ellipsis
+      .style('white-space', 'nowrap') // required for ellipsis
+      .style('text-overflow', 'ellipsis')
+      .style('text-align', 'center')
+      .style('vertical-align', 'middle')
+      .style('visibility', function(datum) {
+        return (datum.dx < 15 || datum.dy < 15) ? 'hidden' : 'visible';
+      })
+      .text(function(datum) { return datum.n; });
+
+  // Complicated transition logic: See note in _handleInodes()
+  this._mapContainer.selectAll('div.leaf_rect_entering').transition()
+      .duration(thisTreeMap._enterDuration).delay(
+          this._firstTransition ? 0 : thisTreeMap._exitDuration +
+              thisTreeMap._updateDuration)
+      .attr('class', 'rect leaf_rect')
+      .style('opacity', '1')
+  this._mapContainer.selectAll('div.leaf_label_entering').transition()
+      .duration(thisTreeMap._enterDuration).delay(
+          this._firstTransition ? 0 : thisTreeMap._exitDuration +
+              thisTreeMap._updateDuration)
+      .attr('class', 'label leaf_label')
+      .style('opacity', '1')
+  this._mapContainer.selectAll('div.leaf_rect').transition()
+      .duration(thisTreeMap._updateDuration).delay(thisTreeMap._exitDuration)
+      .style('opacity', '1')
+      .style('left', function(datum){ return datum.x; })
+      .style('top', function(datum){ return datum.y; })
+      .style('width', function(datum){ return datum.dx; })
+      .style('height', function(datum){ return datum.dy; });
+  this._mapContainer.selectAll('div.leaf_label').transition()
+      .duration(thisTreeMap._updateDuration).delay(thisTreeMap._exitDuration)
+      .style('opacity', '1')
+      .style('visibility', function(datum) {
+          return (datum.dx < 15 || datum.dy < 15) ? 'hidden' : 'visible';
+      })
+      .style('left', function(datum){ return datum.x; })
+      .style('top', function(datum){ return datum.y; })
+      .style('width', function(datum) { return datum.dx; })
+      .style('height', function(datum) { return datum.dy; });
+  var exit = this._mapContainer.selectAll('div.leaf')
+      .data(leaves, function(datum) { return 'leaf-' + datum.id; })
+      .exit();
+  exit.selectAll('div.leaf_rect').transition()
+      .duration(thisTreeMap._exitDuration)
+      .style('opacity', 0);
+  exit.selectAll('div.leaf_label').transition()
+      .duration(thisTreeMap._exitDuration)
+      .style('opacity', 0);
+  exit.transition().delay(thisTreeMap._exitDuration + 1).remove();
+
+  console.log(leaves.length + ' leaves layed out.');
+  console.timeEnd('_handleLeaves');
+}
+
+D3SymbolTreeMap.prototype._makeSymbolBucketBackgroundImage = function(datum) {
+  if (!(datum.t === undefined && datum.depth == this._currentMaxDepth)) {
+    return 'none';
+  }
+  var text = '';
+  var lastStop = 0;
+  for (var x = 0; x < D3SymbolTreeMap._NM_SYMBOL_TYPES.length; x++) {
+    symbol_type = D3SymbolTreeMap._NM_SYMBOL_TYPES.charAt(x);
+    var stats = datum.symbol_stats[symbol_type];
+    if (stats !== undefined) {
+      if (text.length !== 0) {
+        text += ', ';
+      }
+      var percent = 100 * (stats.size / datum.value);
+      var nowStop = lastStop + percent;
+      var tempcolor = D3SymbolTreeMap.getColorForType(symbol_type);
+      var color = d3.rgb(tempcolor).toString();
+      text += color + ' ' + lastStop + '%, ' + color + ' ' +
+          nowStop + '%';
+      lastStop = nowStop;
+    }
+  }
+  return 'linear-gradient(' + (datum.dx > datum.dy ? 'to right' :
+                               'to bottom') + ', ' + text + ')';
+}
+
+D3SymbolTreeMap.prototype.pathFor = function(datum) {
+  if (datum.__path) return datum.__path;
+  parts=[];
+  node = datum;
+  while (node) {
+    if (node.k === 'p') { // path node
+      if(node.n !== '/') parts.unshift(node.n);
+    }
+    node = node.parent;
+  }
+  datum.__path = '/' + parts.join('/');
+  return datum.__path;
+}
+
+D3SymbolTreeMap.prototype._createHighlight = function(datum, selection) {
+  var x = parseInt(selection.style('left'));
+  var y = parseInt(selection.style('top'));
+  var w = parseInt(selection.style('width'));
+  var h = parseInt(selection.style('height'));
+  datum.highlight = this._mapContainer.append('div')
+      .attr('id', 'h-' + datum.id)
+      .attr('class', 'highlight')
+      .style('pointer-events', 'none')
+      .style('-webkit-user-select', 'none')
+      .style('z-index', '999999')
+      .style('position', 'absolute')
+      .style('top', y-2)
+      .style('left', x-2)
+      .style('width', w+4)
+      .style('height', h+4)
+      .style('margin', 0)
+      .style('padding', 0)
+      .style('border', '4px outset rgba(250,40,200,0.9)')
+      .style('box-sizing', 'border-box')
+      .style('opacity', 0.0);
+}
+
+D3SymbolTreeMap.prototype._showHighlight = function(datum, selection) {
+  if (datum === this._currentRoot) return;
+  if (datum.highlight === undefined) {
+    this._createHighlight(datum, selection);
+  }
+  datum.highlight.transition().duration(200).style('opacity', 1.0);
+}
+
+D3SymbolTreeMap.prototype._hideHighlight = function(datum, selection) {
+  if (datum.highlight === undefined) return;
+  datum.highlight.transition().duration(750)
+      .style('opacity', 0)
+      .each('end', function(){
+        if (datum.highlight) datum.highlight.remove();
+        delete datum.highlight;
+      });
+}
+
+D3SymbolTreeMap.prototype._createInfoBox = function() {
+  return d3.select('body')
+      .append('div')
+      .attr('id', 'infobox')
+      .style('z-index', '2147483647') // (2^31) - 1: Hopefully safe :)
+      .style('position', 'absolute')
+      .style('visibility', 'hidden')
+      .style('background-color', 'rgba(255,255,255, 0.9)')
+      .style('border', '1px solid black')
+      .style('padding', '10px')
+      .style('-webkit-user-select', 'none')
+      .style('box-shadow', '3px 3px rgba(70,70,70,0.5)')
+      .style('border-radius', '10px')
+      .style('white-space', 'nowrap');
+}
+
+D3SymbolTreeMap.prototype._showInfoBox = function(datum) {
+  this.infobox.text('');
+  var numSymbols = 0;
+  var sizeish = D3SymbolTreeMap._pretty(datum.value) + ' bytes (' +
+      D3SymbolTreeMap._byteify(datum.value) + ')';
+  if (datum.k === 'p' || datum.k === 'b') { // path or bucket
+    if (datum.symbol_stats) { // can be empty if filters are applied
+      for (var x = 0; x < D3SymbolTreeMap._NM_SYMBOL_TYPES.length; x++) {
+        symbol_type = D3SymbolTreeMap._NM_SYMBOL_TYPES.charAt(x);
+        var stats = datum.symbol_stats[symbol_type];
+        if (stats !== undefined) numSymbols += stats.count;
+      }
+    }
+  } else if (datum.k === 's') { // symbol
+    numSymbols = 1;
+  }
+
+  if (datum.k === 'p' && !datum.lastPathElement) {
+    this.infobox.append('div').text('Directory: ' + this.pathFor(datum))
+    this.infobox.append('div').text('Size: ' + sizeish);
+  } else {
+    if (datum.k === 'p') { // path
+      this.infobox.append('div').text('File: ' + this.pathFor(datum))
+      this.infobox.append('div').text('Size: ' + sizeish);
+    } else if (datum.k === 'b') { // bucket
+      this.infobox.append('div').text('Symbol Bucket: ' +
+          D3SymbolTreeMap._getSymbolDescription(datum.t));
+      this.infobox.append('div').text('Count: ' + numSymbols);
+      this.infobox.append('div').text('Size: ' + sizeish);
+      this.infobox.append('div').text('Location: ' + this.pathFor(datum))
+    } else if (datum.k === 's') { // symbol
+      this.infobox.append('div').text('Symbol: ' + datum.n);
+      this.infobox.append('div').text('Type: ' +
+          D3SymbolTreeMap._getSymbolDescription(datum.t));
+      this.infobox.append('div').text('Size: ' + sizeish);
+      this.infobox.append('div').text('Location: ' + this.pathFor(datum))
+    }
+  }
+  if (datum.k === 'p') {
+    this.infobox.append('div')
+        .text('Number of symbols: ' + D3SymbolTreeMap._pretty(numSymbols));
+    if (datum.symbol_stats) { // can be empty if filters are applied
+      var table = this.infobox.append('table')
+          .attr('border', 1).append('tbody');
+      var header = table.append('tr');
+      header.append('th').text('Type');
+      header.append('th').text('Count');
+      header.append('th')
+          .style('white-space', 'nowrap')
+          .text('Total Size (Bytes)');
+      for (var x = 0; x < D3SymbolTreeMap._NM_SYMBOL_TYPES.length; x++) {
+        symbol_type = D3SymbolTreeMap._NM_SYMBOL_TYPES.charAt(x);
+        var stats = datum.symbol_stats[symbol_type];
+        if (stats !== undefined) {
+          var tr = table.append('tr');
+          tr.append('td')
+              .style('white-space', 'nowrap')
+              .text(D3SymbolTreeMap._getSymbolDescription(
+                  symbol_type));
+          tr.append('td').text(D3SymbolTreeMap._pretty(stats.count));
+          tr.append('td').text(D3SymbolTreeMap._pretty(stats.size));
+        }
+      }
+    }
+  }
+  this.infobox.style('visibility', 'visible');
+}
+
+D3SymbolTreeMap.prototype._hideInfoBox = function(datum) {
+  this.infobox.style('visibility', 'hidden');
+}
+
+D3SymbolTreeMap.prototype._moveInfoBox = function(event) {
+  var element = document.getElementById('infobox');
+  var w = element.offsetWidth;
+  var h = element.offsetHeight;
+  var offsetLeft = 10;
+  var offsetTop = 10;
+
+  var rightLimit = window.innerWidth;
+  var rightEdge = event.pageX + offsetLeft + w;
+  if (rightEdge > rightLimit) {
+    // Too close to screen edge, reflect around the cursor
+    offsetLeft = -1 * (w + offsetLeft);
+  }
+
+  var bottomLimit = window.innerHeight;
+  var bottomEdge = event.pageY + offsetTop + h;
+  if (bottomEdge > bottomLimit) {
+    // Too close ot screen edge, reflect around the cursor
+    offsetTop = -1 * (h + offsetTop);
+  }
+
+  this.infobox.style('top', (event.pageY + offsetTop) + 'px')
+      .style('left', (event.pageX + offsetLeft) + 'px');
+}
+
+D3SymbolTreeMap.prototype.biggestSymbols = function(maxRecords) {
+  var result = undefined;
+  var smallest = undefined;
+  var sortFunction = function(a,b) {
+    var result = b.value - a.value;
+    if (result !== 0) return result; // sort by size
+    var pathA = treemap.pathFor(a); // sort by path
+    var pathB = treemap.pathFor(b);
+    if (pathA > pathB) return 1;
+    if (pathB > pathA) return -1;
+    return a.n - b.n; // sort by symbol name
+  };
+  this.visitFromDisplayedRoot(function(datum) {
+    if (datum.children) return; // ignore non-leaves
+    if (!result) { // first element
+      result = [datum];
+      smallest = datum.value;
+      return;
+    }
+    if (result.length < maxRecords) { // filling the array
+      result.push(datum);
+      return;
+    }
+    if (datum.value > smallest) { // array is already full
+      result.push(datum);
+      result.sort(sortFunction);
+      result.pop(); // get rid of smallest element
+      smallest = result[maxRecords - 1].value; // new threshold for entry
+    }
+  });
+  result.sort(sortFunction);
+  return result;
+}
+
+D3SymbolTreeMap.prototype.biggestPaths = function(maxRecords) {
+  var result = undefined;
+  var smallest = undefined;
+  var sortFunction = function(a,b) {
+    var result = b.value - a.value;
+    if (result !== 0) return result; // sort by size
+    var pathA = treemap.pathFor(a); // sort by path
+    var pathB = treemap.pathFor(b);
+    if (pathA > pathB) return 1;
+    if (pathB > pathA) return -1;
+    console.log('warning, multiple entries for the same path: ' + pathA);
+    return 0; // should be impossible
+  };
+  this.visitFromDisplayedRoot(function(datum) {
+    if (!datum.lastPathElement) return; // ignore non-files
+    if (!result) { // first element
+      result = [datum];
+      smallest = datum.value;
+      return;
+    }
+    if (result.length < maxRecords) { // filling the array
+      result.push(datum);
+      return;
+    }
+    if (datum.value > smallest) { // array is already full
+      result.push(datum);
+      result.sort(sortFunction);
+      result.pop(); // get rid of smallest element
+      smallest = result[maxRecords - 1].value; // new threshold for entry
+    }
+  });
+  result.sort(sortFunction);
+  return result;
+}
diff --git a/pkg/vm_snapshot_analysis/lib/src/assets/d3/README.chromium b/pkg/vm_snapshot_analysis/lib/src/assets/d3/README.chromium
new file mode 100644
index 0000000..7697762
--- /dev/null
+++ b/pkg/vm_snapshot_analysis/lib/src/assets/d3/README.chromium
@@ -0,0 +1,31 @@
+Name: d3
+Short Name: d3
+URL: https://github.com/mbostock/d3
+Version: 3.4.4
+Date: Mon Mar 24 20:45:44 2014 -0700
+Revision: fa55eead411a3c1b01703cb1ddfd59ccc0b23124
+License: BSD 3-Clause
+License File: src/LICENSE
+Security Critical: No
+License Android Compatible: Yes
+
+Description:
+A JavaScript library for manipulating documents based on data.
+
+Subject to the security patch(es) described below, you MAY include d3 in web-facing content, such
+as in pages generated by bots or tools.
+
+
+Local Modifications:
+1. Deleted everything except for:
+* d3.js         the standalone non-minified library
+* LICENSE       the BSD-style 3-Clause license
+* README.md     the readme file from github, for basic information
+
+2. Applied the following patches at the request of security:
+patches/001_no_html.patch        Disables the html() convenience functions, which could be used to
+                                 inject arbitrary content into the page. Instead of using html(),
+                                 programmatically create the individual nodes and/or text that you
+                                 require.
+                                 The html() methods have been modified to throw exceptions that
+                                 make it obvious that this feature is disabled for security.
diff --git a/pkg/vm_snapshot_analysis/lib/src/assets/d3/README.dart b/pkg/vm_snapshot_analysis/lib/src/assets/d3/README.dart
new file mode 100644
index 0000000..6abfe09
--- /dev/null
+++ b/pkg/vm_snapshot_analysis/lib/src/assets/d3/README.dart
@@ -0,0 +1 @@
+A local copy of third_party/d3 from Chromium project.
\ No newline at end of file
diff --git a/pkg/vm_snapshot_analysis/lib/src/assets/d3/patches/001_no_html.patch b/pkg/vm_snapshot_analysis/lib/src/assets/d3/patches/001_no_html.patch
new file mode 100644
index 0000000..3c976b0
--- /dev/null
+++ b/pkg/vm_snapshot_analysis/lib/src/assets/d3/patches/001_no_html.patch
@@ -0,0 +1,24 @@
+diff --git a/third_party/d3/src/d3.js b/third_party/d3/src/d3.js
+index a3e4b95..8a98c4d 100644
+--- a/third_party/d3/src/d3.js
++++ b/third_party/d3/src/d3.js
+@@ -713,6 +713,7 @@
+     }) : this.node().textContent;
+   };
+   d3_selectionPrototype.html = function(value) {
++    throw "disallowed by chromium security";
+     return arguments.length ? this.each(typeof value === "function" ? function() {
+       var v = value.apply(this, arguments);
+       this.innerHTML = v == null ? "" : v;
+@@ -9274,9 +9275,11 @@
+     return JSON.parse(request.responseText);
+   }
+   d3.html = function(url, callback) {
++    throw "disallowed by chromium security";
+     return d3_xhr(url, "text/html", d3_html, callback);
+   };
+   function d3_html(request) {
++    throw "disallowed by chromium security";
+     var range = d3_document.createRange();
+     range.selectNode(d3_document.body);
+     return range.createContextualFragment(request.responseText);
diff --git a/pkg/vm_snapshot_analysis/lib/src/assets/d3/src/LICENSE b/pkg/vm_snapshot_analysis/lib/src/assets/d3/src/LICENSE
new file mode 100644
index 0000000..8301346
--- /dev/null
+++ b/pkg/vm_snapshot_analysis/lib/src/assets/d3/src/LICENSE
@@ -0,0 +1,26 @@
+Copyright (c) 2010-2014, Michael Bostock
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+  list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+
+* The name Michael Bostock may not be used to endorse or promote products
+  derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/pkg/vm_snapshot_analysis/lib/src/assets/d3/src/README.md b/pkg/vm_snapshot_analysis/lib/src/assets/d3/src/README.md
new file mode 100644
index 0000000..eb334e2
--- /dev/null
+++ b/pkg/vm_snapshot_analysis/lib/src/assets/d3/src/README.md
@@ -0,0 +1,9 @@
+# Data-Driven Documents
+
+<a href="http://d3js.org"><img src="http://d3js.org/logo.svg" align="left" hspace="10" vspace="6"></a>
+
+**D3.js** is a JavaScript library for manipulating documents based on data. **D3** helps you bring data to life using HTML, SVG and CSS. D3’s emphasis on web standards gives you the full capabilities of modern browsers without tying yourself to a proprietary framework, combining powerful visualization components and a data-driven approach to DOM manipulation.
+
+Want to learn more? [See the wiki.](https://github.com/mbostock/d3/wiki)
+
+For examples, [see the gallery](https://github.com/mbostock/d3/wiki/Gallery) and [mbostock’s bl.ocks](http://bl.ocks.org/mbostock).
diff --git a/pkg/vm_snapshot_analysis/lib/src/assets/d3/src/d3.js b/pkg/vm_snapshot_analysis/lib/src/assets/d3/src/d3.js
new file mode 100644
index 0000000..6dcabdf
--- /dev/null
+++ b/pkg/vm_snapshot_analysis/lib/src/assets/d3/src/d3.js
@@ -0,0 +1,9297 @@
+!function() {
+  var d3 = {
+    version: "3.4.4"
+  };
+  if (!Date.now) Date.now = function() {
+    return +new Date();
+  };
+  var d3_arraySlice = [].slice, d3_array = function(list) {
+    return d3_arraySlice.call(list);
+  };
+  var d3_document = document, d3_documentElement = d3_document.documentElement, d3_window = window;
+  try {
+    d3_array(d3_documentElement.childNodes)[0].nodeType;
+  } catch (e) {
+    d3_array = function(list) {
+      var i = list.length, array = new Array(i);
+      while (i--) array[i] = list[i];
+      return array;
+    };
+  }
+  try {
+    d3_document.createElement("div").style.setProperty("opacity", 0, "");
+  } catch (error) {
+    var d3_element_prototype = d3_window.Element.prototype, d3_element_setAttribute = d3_element_prototype.setAttribute, d3_element_setAttributeNS = d3_element_prototype.setAttributeNS, d3_style_prototype = d3_window.CSSStyleDeclaration.prototype, d3_style_setProperty = d3_style_prototype.setProperty;
+    d3_element_prototype.setAttribute = function(name, value) {
+      d3_element_setAttribute.call(this, name, value + "");
+    };
+    d3_element_prototype.setAttributeNS = function(space, local, value) {
+      d3_element_setAttributeNS.call(this, space, local, value + "");
+    };
+    d3_style_prototype.setProperty = function(name, value, priority) {
+      d3_style_setProperty.call(this, name, value + "", priority);
+    };
+  }
+  d3.ascending = d3_ascending;
+  function d3_ascending(a, b) {
+    return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
+  }
+  d3.descending = function(a, b) {
+    return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
+  };
+  d3.min = function(array, f) {
+    var i = -1, n = array.length, a, b;
+    if (arguments.length === 1) {
+      while (++i < n && !((a = array[i]) != null && a <= a)) a = undefined;
+      while (++i < n) if ((b = array[i]) != null && a > b) a = b;
+    } else {
+      while (++i < n && !((a = f.call(array, array[i], i)) != null && a <= a)) a = undefined;
+      while (++i < n) if ((b = f.call(array, array[i], i)) != null && a > b) a = b;
+    }
+    return a;
+  };
+  d3.max = function(array, f) {
+    var i = -1, n = array.length, a, b;
+    if (arguments.length === 1) {
+      while (++i < n && !((a = array[i]) != null && a <= a)) a = undefined;
+      while (++i < n) if ((b = array[i]) != null && b > a) a = b;
+    } else {
+      while (++i < n && !((a = f.call(array, array[i], i)) != null && a <= a)) a = undefined;
+      while (++i < n) if ((b = f.call(array, array[i], i)) != null && b > a) a = b;
+    }
+    return a;
+  };
+  d3.extent = function(array, f) {
+    var i = -1, n = array.length, a, b, c;
+    if (arguments.length === 1) {
+      while (++i < n && !((a = c = array[i]) != null && a <= a)) a = c = undefined;
+      while (++i < n) if ((b = array[i]) != null) {
+        if (a > b) a = b;
+        if (c < b) c = b;
+      }
+    } else {
+      while (++i < n && !((a = c = f.call(array, array[i], i)) != null && a <= a)) a = undefined;
+      while (++i < n) if ((b = f.call(array, array[i], i)) != null) {
+        if (a > b) a = b;
+        if (c < b) c = b;
+      }
+    }
+    return [ a, c ];
+  };
+  d3.sum = function(array, f) {
+    var s = 0, n = array.length, a, i = -1;
+    if (arguments.length === 1) {
+      while (++i < n) if (!isNaN(a = +array[i])) s += a;
+    } else {
+      while (++i < n) if (!isNaN(a = +f.call(array, array[i], i))) s += a;
+    }
+    return s;
+  };
+  function d3_number(x) {
+    return x != null && !isNaN(x);
+  }
+  d3.mean = function(array, f) {
+    var n = array.length, a, m = 0, i = -1, j = 0;
+    if (arguments.length === 1) {
+      while (++i < n) if (d3_number(a = array[i])) m += (a - m) / ++j;
+    } else {
+      while (++i < n) if (d3_number(a = f.call(array, array[i], i))) m += (a - m) / ++j;
+    }
+    return j ? m : undefined;
+  };
+  d3.quantile = function(values, p) {
+    var H = (values.length - 1) * p + 1, h = Math.floor(H), v = +values[h - 1], e = H - h;
+    return e ? v + e * (values[h] - v) : v;
+  };
+  d3.median = function(array, f) {
+    if (arguments.length > 1) array = array.map(f);
+    array = array.filter(d3_number);
+    return array.length ? d3.quantile(array.sort(d3_ascending), .5) : undefined;
+  };
+  function d3_bisector(compare) {
+    return {
+      left: function(a, x, lo, hi) {
+        if (arguments.length < 3) lo = 0;
+        if (arguments.length < 4) hi = a.length;
+        while (lo < hi) {
+          var mid = lo + hi >>> 1;
+          if (compare(a[mid], x) < 0) lo = mid + 1; else hi = mid;
+        }
+        return lo;
+      },
+      right: function(a, x, lo, hi) {
+        if (arguments.length < 3) lo = 0;
+        if (arguments.length < 4) hi = a.length;
+        while (lo < hi) {
+          var mid = lo + hi >>> 1;
+          if (compare(a[mid], x) > 0) hi = mid; else lo = mid + 1;
+        }
+        return lo;
+      }
+    };
+  }
+  var d3_bisect = d3_bisector(d3_ascending);
+  d3.bisectLeft = d3_bisect.left;
+  d3.bisect = d3.bisectRight = d3_bisect.right;
+  d3.bisector = function(f) {
+    return d3_bisector(f.length === 1 ? function(d, x) {
+      return d3_ascending(f(d), x);
+    } : f);
+  };
+  d3.shuffle = function(array) {
+    var m = array.length, t, i;
+    while (m) {
+      i = Math.random() * m-- | 0;
+      t = array[m], array[m] = array[i], array[i] = t;
+    }
+    return array;
+  };
+  d3.permute = function(array, indexes) {
+    var i = indexes.length, permutes = new Array(i);
+    while (i--) permutes[i] = array[indexes[i]];
+    return permutes;
+  };
+  d3.pairs = function(array) {
+    var i = 0, n = array.length - 1, p0, p1 = array[0], pairs = new Array(n < 0 ? 0 : n);
+    while (i < n) pairs[i] = [ p0 = p1, p1 = array[++i] ];
+    return pairs;
+  };
+  d3.zip = function() {
+    if (!(n = arguments.length)) return [];
+    for (var i = -1, m = d3.min(arguments, d3_zipLength), zips = new Array(m); ++i < m; ) {
+      for (var j = -1, n, zip = zips[i] = new Array(n); ++j < n; ) {
+        zip[j] = arguments[j][i];
+      }
+    }
+    return zips;
+  };
+  function d3_zipLength(d) {
+    return d.length;
+  }
+  d3.transpose = function(matrix) {
+    return d3.zip.apply(d3, matrix);
+  };
+  d3.keys = function(map) {
+    var keys = [];
+    for (var key in map) keys.push(key);
+    return keys;
+  };
+  d3.values = function(map) {
+    var values = [];
+    for (var key in map) values.push(map[key]);
+    return values;
+  };
+  d3.entries = function(map) {
+    var entries = [];
+    for (var key in map) entries.push({
+      key: key,
+      value: map[key]
+    });
+    return entries;
+  };
+  d3.merge = function(arrays) {
+    var n = arrays.length, m, i = -1, j = 0, merged, array;
+    while (++i < n) j += arrays[i].length;
+    merged = new Array(j);
+    while (--n >= 0) {
+      array = arrays[n];
+      m = array.length;
+      while (--m >= 0) {
+        merged[--j] = array[m];
+      }
+    }
+    return merged;
+  };
+  var abs = Math.abs;
+  d3.range = function(start, stop, step) {
+    if (arguments.length < 3) {
+      step = 1;
+      if (arguments.length < 2) {
+        stop = start;
+        start = 0;
+      }
+    }
+    if ((stop - start) / step === Infinity) throw new Error("infinite range");
+    var range = [], k = d3_range_integerScale(abs(step)), i = -1, j;
+    start *= k, stop *= k, step *= k;
+    if (step < 0) while ((j = start + step * ++i) > stop) range.push(j / k); else while ((j = start + step * ++i) < stop) range.push(j / k);
+    return range;
+  };
+  function d3_range_integerScale(x) {
+    var k = 1;
+    while (x * k % 1) k *= 10;
+    return k;
+  }
+  function d3_class(ctor, properties) {
+    try {
+      for (var key in properties) {
+        Object.defineProperty(ctor.prototype, key, {
+          value: properties[key],
+          enumerable: false
+        });
+      }
+    } catch (e) {
+      ctor.prototype = properties;
+    }
+  }
+  d3.map = function(object) {
+    var map = new d3_Map();
+    if (object instanceof d3_Map) object.forEach(function(key, value) {
+      map.set(key, value);
+    }); else for (var key in object) map.set(key, object[key]);
+    return map;
+  };
+  function d3_Map() {}
+  d3_class(d3_Map, {
+    has: d3_map_has,
+    get: function(key) {
+      return this[d3_map_prefix + key];
+    },
+    set: function(key, value) {
+      return this[d3_map_prefix + key] = value;
+    },
+    remove: d3_map_remove,
+    keys: d3_map_keys,
+    values: function() {
+      var values = [];
+      this.forEach(function(key, value) {
+        values.push(value);
+      });
+      return values;
+    },
+    entries: function() {
+      var entries = [];
+      this.forEach(function(key, value) {
+        entries.push({
+          key: key,
+          value: value
+        });
+      });
+      return entries;
+    },
+    size: d3_map_size,
+    empty: d3_map_empty,
+    forEach: function(f) {
+      for (var key in this) if (key.charCodeAt(0) === d3_map_prefixCode) f.call(this, key.substring(1), this[key]);
+    }
+  });
+  var d3_map_prefix = "\x00", d3_map_prefixCode = d3_map_prefix.charCodeAt(0);
+  function d3_map_has(key) {
+    return d3_map_prefix + key in this;
+  }
+  function d3_map_remove(key) {
+    key = d3_map_prefix + key;
+    return key in this && delete this[key];
+  }
+  function d3_map_keys() {
+    var keys = [];
+    this.forEach(function(key) {
+      keys.push(key);
+    });
+    return keys;
+  }
+  function d3_map_size() {
+    var size = 0;
+    for (var key in this) if (key.charCodeAt(0) === d3_map_prefixCode) ++size;
+    return size;
+  }
+  function d3_map_empty() {
+    for (var key in this) if (key.charCodeAt(0) === d3_map_prefixCode) return false;
+    return true;
+  }
+  d3.nest = function() {
+    var nest = {}, keys = [], sortKeys = [], sortValues, rollup;
+    function map(mapType, array, depth) {
+      if (depth >= keys.length) return rollup ? rollup.call(nest, array) : sortValues ? array.sort(sortValues) : array;
+      var i = -1, n = array.length, key = keys[depth++], keyValue, object, setter, valuesByKey = new d3_Map(), values;
+      while (++i < n) {
+        if (values = valuesByKey.get(keyValue = key(object = array[i]))) {
+          values.push(object);
+        } else {
+          valuesByKey.set(keyValue, [ object ]);
+        }
+      }
+      if (mapType) {
+        object = mapType();
+        setter = function(keyValue, values) {
+          object.set(keyValue, map(mapType, values, depth));
+        };
+      } else {
+        object = {};
+        setter = function(keyValue, values) {
+          object[keyValue] = map(mapType, values, depth);
+        };
+      }
+      valuesByKey.forEach(setter);
+      return object;
+    }
+    function entries(map, depth) {
+      if (depth >= keys.length) return map;
+      var array = [], sortKey = sortKeys[depth++];
+      map.forEach(function(key, keyMap) {
+        array.push({
+          key: key,
+          values: entries(keyMap, depth)
+        });
+      });
+      return sortKey ? array.sort(function(a, b) {
+        return sortKey(a.key, b.key);
+      }) : array;
+    }
+    nest.map = function(array, mapType) {
+      return map(mapType, array, 0);
+    };
+    nest.entries = function(array) {
+      return entries(map(d3.map, array, 0), 0);
+    };
+    nest.key = function(d) {
+      keys.push(d);
+      return nest;
+    };
+    nest.sortKeys = function(order) {
+      sortKeys[keys.length - 1] = order;
+      return nest;
+    };
+    nest.sortValues = function(order) {
+      sortValues = order;
+      return nest;
+    };
+    nest.rollup = function(f) {
+      rollup = f;
+      return nest;
+    };
+    return nest;
+  };
+  d3.set = function(array) {
+    var set = new d3_Set();
+    if (array) for (var i = 0, n = array.length; i < n; ++i) set.add(array[i]);
+    return set;
+  };
+  function d3_Set() {}
+  d3_class(d3_Set, {
+    has: d3_map_has,
+    add: function(value) {
+      this[d3_map_prefix + value] = true;
+      return value;
+    },
+    remove: function(value) {
+      value = d3_map_prefix + value;
+      return value in this && delete this[value];
+    },
+    values: d3_map_keys,
+    size: d3_map_size,
+    empty: d3_map_empty,
+    forEach: function(f) {
+      for (var value in this) if (value.charCodeAt(0) === d3_map_prefixCode) f.call(this, value.substring(1));
+    }
+  });
+  d3.behavior = {};
+  d3.rebind = function(target, source) {
+    var i = 1, n = arguments.length, method;
+    while (++i < n) target[method = arguments[i]] = d3_rebind(target, source, source[method]);
+    return target;
+  };
+  function d3_rebind(target, source, method) {
+    return function() {
+      var value = method.apply(source, arguments);
+      return value === source ? target : value;
+    };
+  }
+  function d3_vendorSymbol(object, name) {
+    if (name in object) return name;
+    name = name.charAt(0).toUpperCase() + name.substring(1);
+    for (var i = 0, n = d3_vendorPrefixes.length; i < n; ++i) {
+      var prefixName = d3_vendorPrefixes[i] + name;
+      if (prefixName in object) return prefixName;
+    }
+  }
+  var d3_vendorPrefixes = [ "webkit", "ms", "moz", "Moz", "o", "O" ];
+  function d3_noop() {}
+  d3.dispatch = function() {
+    var dispatch = new d3_dispatch(), i = -1, n = arguments.length;
+    while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch);
+    return dispatch;
+  };
+  function d3_dispatch() {}
+  d3_dispatch.prototype.on = function(type, listener) {
+    var i = type.indexOf("."), name = "";
+    if (i >= 0) {
+      name = type.substring(i + 1);
+      type = type.substring(0, i);
+    }
+    if (type) return arguments.length < 2 ? this[type].on(name) : this[type].on(name, listener);
+    if (arguments.length === 2) {
+      if (listener == null) for (type in this) {
+        if (this.hasOwnProperty(type)) this[type].on(name, null);
+      }
+      return this;
+    }
+  };
+  function d3_dispatch_event(dispatch) {
+    var listeners = [], listenerByName = new d3_Map();
+    function event() {
+      var z = listeners, i = -1, n = z.length, l;
+      while (++i < n) if (l = z[i].on) l.apply(this, arguments);
+      return dispatch;
+    }
+    event.on = function(name, listener) {
+      var l = listenerByName.get(name), i;
+      if (arguments.length < 2) return l && l.on;
+      if (l) {
+        l.on = null;
+        listeners = listeners.slice(0, i = listeners.indexOf(l)).concat(listeners.slice(i + 1));
+        listenerByName.remove(name);
+      }
+      if (listener) listeners.push(listenerByName.set(name, {
+        on: listener
+      }));
+      return dispatch;
+    };
+    return event;
+  }
+  d3.event = null;
+  function d3_eventPreventDefault() {
+    d3.event.preventDefault();
+  }
+  function d3_eventSource() {
+    var e = d3.event, s;
+    while (s = e.sourceEvent) e = s;
+    return e;
+  }
+  function d3_eventDispatch(target) {
+    var dispatch = new d3_dispatch(), i = 0, n = arguments.length;
+    while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch);
+    dispatch.of = function(thiz, argumentz) {
+      return function(e1) {
+        try {
+          var e0 = e1.sourceEvent = d3.event;
+          e1.target = target;
+          d3.event = e1;
+          dispatch[e1.type].apply(thiz, argumentz);
+        } finally {
+          d3.event = e0;
+        }
+      };
+    };
+    return dispatch;
+  }
+  d3.requote = function(s) {
+    return s.replace(d3_requote_re, "\\$&");
+  };
+  var d3_requote_re = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;
+  var d3_subclass = {}.__proto__ ? function(object, prototype) {
+    object.__proto__ = prototype;
+  } : function(object, prototype) {
+    for (var property in prototype) object[property] = prototype[property];
+  };
+  function d3_selection(groups) {
+    d3_subclass(groups, d3_selectionPrototype);
+    return groups;
+  }
+  var d3_select = function(s, n) {
+    return n.querySelector(s);
+  }, d3_selectAll = function(s, n) {
+    return n.querySelectorAll(s);
+  }, d3_selectMatcher = d3_documentElement[d3_vendorSymbol(d3_documentElement, "matchesSelector")], d3_selectMatches = function(n, s) {
+    return d3_selectMatcher.call(n, s);
+  };
+  if (typeof Sizzle === "function") {
+    d3_select = function(s, n) {
+      return Sizzle(s, n)[0] || null;
+    };
+    d3_selectAll = Sizzle;
+    d3_selectMatches = Sizzle.matchesSelector;
+  }
+  d3.selection = function() {
+    return d3_selectionRoot;
+  };
+  var d3_selectionPrototype = d3.selection.prototype = [];
+  d3_selectionPrototype.select = function(selector) {
+    var subgroups = [], subgroup, subnode, group, node;
+    selector = d3_selection_selector(selector);
+    for (var j = -1, m = this.length; ++j < m; ) {
+      subgroups.push(subgroup = []);
+      subgroup.parentNode = (group = this[j]).parentNode;
+      for (var i = -1, n = group.length; ++i < n; ) {
+        if (node = group[i]) {
+          subgroup.push(subnode = selector.call(node, node.__data__, i, j));
+          if (subnode && "__data__" in node) subnode.__data__ = node.__data__;
+        } else {
+          subgroup.push(null);
+        }
+      }
+    }
+    return d3_selection(subgroups);
+  };
+  function d3_selection_selector(selector) {
+    return typeof selector === "function" ? selector : function() {
+      return d3_select(selector, this);
+    };
+  }
+  d3_selectionPrototype.selectAll = function(selector) {
+    var subgroups = [], subgroup, node;
+    selector = d3_selection_selectorAll(selector);
+    for (var j = -1, m = this.length; ++j < m; ) {
+      for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
+        if (node = group[i]) {
+          subgroups.push(subgroup = d3_array(selector.call(node, node.__data__, i, j)));
+          subgroup.parentNode = node;
+        }
+      }
+    }
+    return d3_selection(subgroups);
+  };
+  function d3_selection_selectorAll(selector) {
+    return typeof selector === "function" ? selector : function() {
+      return d3_selectAll(selector, this);
+    };
+  }
+  var d3_nsPrefix = {
+    svg: "http://www.w3.org/2000/svg",
+    xhtml: "http://www.w3.org/1999/xhtml",
+    xlink: "http://www.w3.org/1999/xlink",
+    xml: "http://www.w3.org/XML/1998/namespace",
+    xmlns: "http://www.w3.org/2000/xmlns/"
+  };
+  d3.ns = {
+    prefix: d3_nsPrefix,
+    qualify: function(name) {
+      var i = name.indexOf(":"), prefix = name;
+      if (i >= 0) {
+        prefix = name.substring(0, i);
+        name = name.substring(i + 1);
+      }
+      return d3_nsPrefix.hasOwnProperty(prefix) ? {
+        space: d3_nsPrefix[prefix],
+        local: name
+      } : name;
+    }
+  };
+  d3_selectionPrototype.attr = function(name, value) {
+    if (arguments.length < 2) {
+      if (typeof name === "string") {
+        var node = this.node();
+        name = d3.ns.qualify(name);
+        return name.local ? node.getAttributeNS(name.space, name.local) : node.getAttribute(name);
+      }
+      for (value in name) this.each(d3_selection_attr(value, name[value]));
+      return this;
+    }
+    return this.each(d3_selection_attr(name, value));
+  };
+  function d3_selection_attr(name, value) {
+    name = d3.ns.qualify(name);
+    function attrNull() {
+      this.removeAttribute(name);
+    }
+    function attrNullNS() {
+      this.removeAttributeNS(name.space, name.local);
+    }
+    function attrConstant() {
+      this.setAttribute(name, value);
+    }
+    function attrConstantNS() {
+      this.setAttributeNS(name.space, name.local, value);
+    }
+    function attrFunction() {
+      var x = value.apply(this, arguments);
+      if (x == null) this.removeAttribute(name); else this.setAttribute(name, x);
+    }
+    function attrFunctionNS() {
+      var x = value.apply(this, arguments);
+      if (x == null) this.removeAttributeNS(name.space, name.local); else this.setAttributeNS(name.space, name.local, x);
+    }
+    return value == null ? name.local ? attrNullNS : attrNull : typeof value === "function" ? name.local ? attrFunctionNS : attrFunction : name.local ? attrConstantNS : attrConstant;
+  }
+  function d3_collapse(s) {
+    return s.trim().replace(/\s+/g, " ");
+  }
+  d3_selectionPrototype.classed = function(name, value) {
+    if (arguments.length < 2) {
+      if (typeof name === "string") {
+        var node = this.node(), n = (name = d3_selection_classes(name)).length, i = -1;
+        if (value = node.classList) {
+          while (++i < n) if (!value.contains(name[i])) return false;
+        } else {
+          value = node.getAttribute("class");
+          while (++i < n) if (!d3_selection_classedRe(name[i]).test(value)) return false;
+        }
+        return true;
+      }
+      for (value in name) this.each(d3_selection_classed(value, name[value]));
+      return this;
+    }
+    return this.each(d3_selection_classed(name, value));
+  };
+  function d3_selection_classedRe(name) {
+    return new RegExp("(?:^|\\s+)" + d3.requote(name) + "(?:\\s+|$)", "g");
+  }
+  function d3_selection_classes(name) {
+    return name.trim().split(/^|\s+/);
+  }
+  function d3_selection_classed(name, value) {
+    name = d3_selection_classes(name).map(d3_selection_classedName);
+    var n = name.length;
+    function classedConstant() {
+      var i = -1;
+      while (++i < n) name[i](this, value);
+    }
+    function classedFunction() {
+      var i = -1, x = value.apply(this, arguments);
+      while (++i < n) name[i](this, x);
+    }
+    return typeof value === "function" ? classedFunction : classedConstant;
+  }
+  function d3_selection_classedName(name) {
+    var re = d3_selection_classedRe(name);
+    return function(node, value) {
+      if (c = node.classList) return value ? c.add(name) : c.remove(name);
+      var c = node.getAttribute("class") || "";
+      if (value) {
+        re.lastIndex = 0;
+        if (!re.test(c)) node.setAttribute("class", d3_collapse(c + " " + name));
+      } else {
+        node.setAttribute("class", d3_collapse(c.replace(re, " ")));
+      }
+    };
+  }
+  d3_selectionPrototype.style = function(name, value, priority) {
+    var n = arguments.length;
+    if (n < 3) {
+      if (typeof name !== "string") {
+        if (n < 2) value = "";
+        for (priority in name) this.each(d3_selection_style(priority, name[priority], value));
+        return this;
+      }
+      if (n < 2) return d3_window.getComputedStyle(this.node(), null).getPropertyValue(name);
+      priority = "";
+    }
+    return this.each(d3_selection_style(name, value, priority));
+  };
+  function d3_selection_style(name, value, priority) {
+    function styleNull() {
+      this.style.removeProperty(name);
+    }
+    function styleConstant() {
+      this.style.setProperty(name, value, priority);
+    }
+    function styleFunction() {
+      var x = value.apply(this, arguments);
+      if (x == null) this.style.removeProperty(name); else this.style.setProperty(name, x, priority);
+    }
+    return value == null ? styleNull : typeof value === "function" ? styleFunction : styleConstant;
+  }
+  d3_selectionPrototype.property = function(name, value) {
+    if (arguments.length < 2) {
+      if (typeof name === "string") return this.node()[name];
+      for (value in name) this.each(d3_selection_property(value, name[value]));
+      return this;
+    }
+    return this.each(d3_selection_property(name, value));
+  };
+  function d3_selection_property(name, value) {
+    function propertyNull() {
+      delete this[name];
+    }
+    function propertyConstant() {
+      this[name] = value;
+    }
+    function propertyFunction() {
+      var x = value.apply(this, arguments);
+      if (x == null) delete this[name]; else this[name] = x;
+    }
+    return value == null ? propertyNull : typeof value === "function" ? propertyFunction : propertyConstant;
+  }
+  d3_selectionPrototype.text = function(value) {
+    return arguments.length ? this.each(typeof value === "function" ? function() {
+      var v = value.apply(this, arguments);
+      this.textContent = v == null ? "" : v;
+    } : value == null ? function() {
+      this.textContent = "";
+    } : function() {
+      this.textContent = value;
+    }) : this.node().textContent;
+  };
+  d3_selectionPrototype.html = function(value) {
+    throw "disallowed by chromium security";
+    return arguments.length ? this.each(typeof value === "function" ? function() {
+      var v = value.apply(this, arguments);
+      this.innerHTML = v == null ? "" : v;
+    } : value == null ? function() {
+      this.innerHTML = "";
+    } : function() {
+      this.innerHTML = value;
+    }) : this.node().innerHTML;
+  };
+  d3_selectionPrototype.append = function(name) {
+    name = d3_selection_creator(name);
+    return this.select(function() {
+      return this.appendChild(name.apply(this, arguments));
+    });
+  };
+  function d3_selection_creator(name) {
+    return typeof name === "function" ? name : (name = d3.ns.qualify(name)).local ? function() {
+      return this.ownerDocument.createElementNS(name.space, name.local);
+    } : function() {
+      return this.ownerDocument.createElementNS(this.namespaceURI, name);
+    };
+  }
+  d3_selectionPrototype.insert = function(name, before) {
+    name = d3_selection_creator(name);
+    before = d3_selection_selector(before);
+    return this.select(function() {
+      return this.insertBefore(name.apply(this, arguments), before.apply(this, arguments) || null);
+    });
+  };
+  d3_selectionPrototype.remove = function() {
+    return this.each(function() {
+      var parent = this.parentNode;
+      if (parent) parent.removeChild(this);
+    });
+  };
+  d3_selectionPrototype.data = function(value, key) {
+    var i = -1, n = this.length, group, node;
+    if (!arguments.length) {
+      value = new Array(n = (group = this[0]).length);
+      while (++i < n) {
+        if (node = group[i]) {
+          value[i] = node.__data__;
+        }
+      }
+      return value;
+    }
+    function bind(group, groupData) {
+      var i, n = group.length, m = groupData.length, n0 = Math.min(n, m), updateNodes = new Array(m), enterNodes = new Array(m), exitNodes = new Array(n), node, nodeData;
+      if (key) {
+        var nodeByKeyValue = new d3_Map(), dataByKeyValue = new d3_Map(), keyValues = [], keyValue;
+        for (i = -1; ++i < n; ) {
+          keyValue = key.call(node = group[i], node.__data__, i);
+          if (nodeByKeyValue.has(keyValue)) {
+            exitNodes[i] = node;
+          } else {
+            nodeByKeyValue.set(keyValue, node);
+          }
+          keyValues.push(keyValue);
+        }
+        for (i = -1; ++i < m; ) {
+          keyValue = key.call(groupData, nodeData = groupData[i], i);
+          if (node = nodeByKeyValue.get(keyValue)) {
+            updateNodes[i] = node;
+            node.__data__ = nodeData;
+          } else if (!dataByKeyValue.has(keyValue)) {
+            enterNodes[i] = d3_selection_dataNode(nodeData);
+          }
+          dataByKeyValue.set(keyValue, nodeData);
+          nodeByKeyValue.remove(keyValue);
+        }
+        for (i = -1; ++i < n; ) {
+          if (nodeByKeyValue.has(keyValues[i])) {
+            exitNodes[i] = group[i];
+          }
+        }
+      } else {
+        for (i = -1; ++i < n0; ) {
+          node = group[i];
+          nodeData = groupData[i];
+          if (node) {
+            node.__data__ = nodeData;
+            updateNodes[i] = node;
+          } else {
+            enterNodes[i] = d3_selection_dataNode(nodeData);
+          }
+        }
+        for (;i < m; ++i) {
+          enterNodes[i] = d3_selection_dataNode(groupData[i]);
+        }
+        for (;i < n; ++i) {
+          exitNodes[i] = group[i];
+        }
+      }
+      enterNodes.update = updateNodes;
+      enterNodes.parentNode = updateNodes.parentNode = exitNodes.parentNode = group.parentNode;
+      enter.push(enterNodes);
+      update.push(updateNodes);
+      exit.push(exitNodes);
+    }
+    var enter = d3_selection_enter([]), update = d3_selection([]), exit = d3_selection([]);
+    if (typeof value === "function") {
+      while (++i < n) {
+        bind(group = this[i], value.call(group, group.parentNode.__data__, i));
+      }
+    } else {
+      while (++i < n) {
+        bind(group = this[i], value);
+      }
+    }
+    update.enter = function() {
+      return enter;
+    };
+    update.exit = function() {
+      return exit;
+    };
+    return update;
+  };
+  function d3_selection_dataNode(data) {
+    return {
+      __data__: data
+    };
+  }
+  d3_selectionPrototype.datum = function(value) {
+    return arguments.length ? this.property("__data__", value) : this.property("__data__");
+  };
+  d3_selectionPrototype.filter = function(filter) {
+    var subgroups = [], subgroup, group, node;
+    if (typeof filter !== "function") filter = d3_selection_filter(filter);
+    for (var j = 0, m = this.length; j < m; j++) {
+      subgroups.push(subgroup = []);
+      subgroup.parentNode = (group = this[j]).parentNode;
+      for (var i = 0, n = group.length; i < n; i++) {
+        if ((node = group[i]) && filter.call(node, node.__data__, i, j)) {
+          subgroup.push(node);
+        }
+      }
+    }
+    return d3_selection(subgroups);
+  };
+  function d3_selection_filter(selector) {
+    return function() {
+      return d3_selectMatches(this, selector);
+    };
+  }
+  d3_selectionPrototype.order = function() {
+    for (var j = -1, m = this.length; ++j < m; ) {
+      for (var group = this[j], i = group.length - 1, next = group[i], node; --i >= 0; ) {
+        if (node = group[i]) {
+          if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next);
+          next = node;
+        }
+      }
+    }
+    return this;
+  };
+  d3_selectionPrototype.sort = function(comparator) {
+    comparator = d3_selection_sortComparator.apply(this, arguments);
+    for (var j = -1, m = this.length; ++j < m; ) this[j].sort(comparator);
+    return this.order();
+  };
+  function d3_selection_sortComparator(comparator) {
+    if (!arguments.length) comparator = d3_ascending;
+    return function(a, b) {
+      return a && b ? comparator(a.__data__, b.__data__) : !a - !b;
+    };
+  }
+  d3_selectionPrototype.each = function(callback) {
+    return d3_selection_each(this, function(node, i, j) {
+      callback.call(node, node.__data__, i, j);
+    });
+  };
+  function d3_selection_each(groups, callback) {
+    for (var j = 0, m = groups.length; j < m; j++) {
+      for (var group = groups[j], i = 0, n = group.length, node; i < n; i++) {
+        if (node = group[i]) callback(node, i, j);
+      }
+    }
+    return groups;
+  }
+  d3_selectionPrototype.call = function(callback) {
+    var args = d3_array(arguments);
+    callback.apply(args[0] = this, args);
+    return this;
+  };
+  d3_selectionPrototype.empty = function() {
+    return !this.node();
+  };
+  d3_selectionPrototype.node = function() {
+    for (var j = 0, m = this.length; j < m; j++) {
+      for (var group = this[j], i = 0, n = group.length; i < n; i++) {
+        var node = group[i];
+        if (node) return node;
+      }
+    }
+    return null;
+  };
+  d3_selectionPrototype.size = function() {
+    var n = 0;
+    this.each(function() {
+      ++n;
+    });
+    return n;
+  };
+  function d3_selection_enter(selection) {
+    d3_subclass(selection, d3_selection_enterPrototype);
+    return selection;
+  }
+  var d3_selection_enterPrototype = [];
+  d3.selection.enter = d3_selection_enter;
+  d3.selection.enter.prototype = d3_selection_enterPrototype;
+  d3_selection_enterPrototype.append = d3_selectionPrototype.append;
+  d3_selection_enterPrototype.empty = d3_selectionPrototype.empty;
+  d3_selection_enterPrototype.node = d3_selectionPrototype.node;
+  d3_selection_enterPrototype.call = d3_selectionPrototype.call;
+  d3_selection_enterPrototype.size = d3_selectionPrototype.size;
+  d3_selection_enterPrototype.select = function(selector) {
+    var subgroups = [], subgroup, subnode, upgroup, group, node;
+    for (var j = -1, m = this.length; ++j < m; ) {
+      upgroup = (group = this[j]).update;
+      subgroups.push(subgroup = []);
+      subgroup.parentNode = group.parentNode;
+      for (var i = -1, n = group.length; ++i < n; ) {
+        if (node = group[i]) {
+          subgroup.push(upgroup[i] = subnode = selector.call(group.parentNode, node.__data__, i, j));
+          subnode.__data__ = node.__data__;
+        } else {
+          subgroup.push(null);
+        }
+      }
+    }
+    return d3_selection(subgroups);
+  };
+  d3_selection_enterPrototype.insert = function(name, before) {
+    if (arguments.length < 2) before = d3_selection_enterInsertBefore(this);
+    return d3_selectionPrototype.insert.call(this, name, before);
+  };
+  function d3_selection_enterInsertBefore(enter) {
+    var i0, j0;
+    return function(d, i, j) {
+      var group = enter[j].update, n = group.length, node;
+      if (j != j0) j0 = j, i0 = 0;
+      if (i >= i0) i0 = i + 1;
+      while (!(node = group[i0]) && ++i0 < n) ;
+      return node;
+    };
+  }
+  d3_selectionPrototype.transition = function() {
+    var id = d3_transitionInheritId || ++d3_transitionId, subgroups = [], subgroup, node, transition = d3_transitionInherit || {
+      time: Date.now(),
+      ease: d3_ease_cubicInOut,
+      delay: 0,
+      duration: 250
+    };
+    for (var j = -1, m = this.length; ++j < m; ) {
+      subgroups.push(subgroup = []);
+      for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
+        if (node = group[i]) d3_transitionNode(node, i, id, transition);
+        subgroup.push(node);
+      }
+    }
+    return d3_transition(subgroups, id);
+  };
+  d3_selectionPrototype.interrupt = function() {
+    return this.each(d3_selection_interrupt);
+  };
+  function d3_selection_interrupt() {
+    var lock = this.__transition__;
+    if (lock) ++lock.active;
+  }
+  d3.select = function(node) {
+    var group = [ typeof node === "string" ? d3_select(node, d3_document) : node ];
+    group.parentNode = d3_documentElement;
+    return d3_selection([ group ]);
+  };
+  d3.selectAll = function(nodes) {
+    var group = d3_array(typeof nodes === "string" ? d3_selectAll(nodes, d3_document) : nodes);
+    group.parentNode = d3_documentElement;
+    return d3_selection([ group ]);
+  };
+  var d3_selectionRoot = d3.select(d3_documentElement);
+  d3_selectionPrototype.on = function(type, listener, capture) {
+    var n = arguments.length;
+    if (n < 3) {
+      if (typeof type !== "string") {
+        if (n < 2) listener = false;
+        for (capture in type) this.each(d3_selection_on(capture, type[capture], listener));
+        return this;
+      }
+      if (n < 2) return (n = this.node()["__on" + type]) && n._;
+      capture = false;
+    }
+    return this.each(d3_selection_on(type, listener, capture));
+  };
+  function d3_selection_on(type, listener, capture) {
+    var name = "__on" + type, i = type.indexOf("."), wrap = d3_selection_onListener;
+    if (i > 0) type = type.substring(0, i);
+    var filter = d3_selection_onFilters.get(type);
+    if (filter) type = filter, wrap = d3_selection_onFilter;
+    function onRemove() {
+      var l = this[name];
+      if (l) {
+        this.removeEventListener(type, l, l.$);
+        delete this[name];
+      }
+    }
+    function onAdd() {
+      var l = wrap(listener, d3_array(arguments));
+      onRemove.call(this);
+      this.addEventListener(type, this[name] = l, l.$ = capture);
+      l._ = listener;
+    }
+    function removeAll() {
+      var re = new RegExp("^__on([^.]+)" + d3.requote(type) + "$"), match;
+      for (var name in this) {
+        if (match = name.match(re)) {
+          var l = this[name];
+          this.removeEventListener(match[1], l, l.$);
+          delete this[name];
+        }
+      }
+    }
+    return i ? listener ? onAdd : onRemove : listener ? d3_noop : removeAll;
+  }
+  var d3_selection_onFilters = d3.map({
+    mouseenter: "mouseover",
+    mouseleave: "mouseout"
+  });
+  d3_selection_onFilters.forEach(function(k) {
+    if ("on" + k in d3_document) d3_selection_onFilters.remove(k);
+  });
+  function d3_selection_onListener(listener, argumentz) {
+    return function(e) {
+      var o = d3.event;
+      d3.event = e;
+      argumentz[0] = this.__data__;
+      try {
+        listener.apply(this, argumentz);
+      } finally {
+        d3.event = o;
+      }
+    };
+  }
+  function d3_selection_onFilter(listener, argumentz) {
+    var l = d3_selection_onListener(listener, argumentz);
+    return function(e) {
+      var target = this, related = e.relatedTarget;
+      if (!related || related !== target && !(related.compareDocumentPosition(target) & 8)) {
+        l.call(target, e);
+      }
+    };
+  }
+  var d3_event_dragSelect = "onselectstart" in d3_document ? null : d3_vendorSymbol(d3_documentElement.style, "userSelect"), d3_event_dragId = 0;
+  function d3_event_dragSuppress() {
+    var name = ".dragsuppress-" + ++d3_event_dragId, click = "click" + name, w = d3.select(d3_window).on("touchmove" + name, d3_eventPreventDefault).on("dragstart" + name, d3_eventPreventDefault).on("selectstart" + name, d3_eventPreventDefault);
+    if (d3_event_dragSelect) {
+      var style = d3_documentElement.style, select = style[d3_event_dragSelect];
+      style[d3_event_dragSelect] = "none";
+    }
+    return function(suppressClick) {
+      w.on(name, null);
+      if (d3_event_dragSelect) style[d3_event_dragSelect] = select;
+      if (suppressClick) {
+        function off() {
+          w.on(click, null);
+        }
+        w.on(click, function() {
+          d3_eventPreventDefault();
+          off();
+        }, true);
+        setTimeout(off, 0);
+      }
+    };
+  }
+  d3.mouse = function(container) {
+    return d3_mousePoint(container, d3_eventSource());
+  };
+  function d3_mousePoint(container, e) {
+    if (e.changedTouches) e = e.changedTouches[0];
+    var svg = container.ownerSVGElement || container;
+    if (svg.createSVGPoint) {
+      var point = svg.createSVGPoint();
+      point.x = e.clientX, point.y = e.clientY;
+      point = point.matrixTransform(container.getScreenCTM().inverse());
+      return [ point.x, point.y ];
+    }
+    var rect = container.getBoundingClientRect();
+    return [ e.clientX - rect.left - container.clientLeft, e.clientY - rect.top - container.clientTop ];
+  }
+  d3.touches = function(container, touches) {
+    if (arguments.length < 2) touches = d3_eventSource().touches;
+    return touches ? d3_array(touches).map(function(touch) {
+      var point = d3_mousePoint(container, touch);
+      point.identifier = touch.identifier;
+      return point;
+    }) : [];
+  };
+  d3.behavior.drag = function() {
+    var event = d3_eventDispatch(drag, "drag", "dragstart", "dragend"), origin = null, mousedown = dragstart(d3_noop, d3.mouse, d3_behavior_dragMouseSubject, "mousemove", "mouseup"), touchstart = dragstart(d3_behavior_dragTouchId, d3.touch, d3_behavior_dragTouchSubject, "touchmove", "touchend");
+    function drag() {
+      this.on("mousedown.drag", mousedown).on("touchstart.drag", touchstart);
+    }
+    function dragstart(id, position, subject, move, end) {
+      return function() {
+        var that = this, target = d3.event.target, parent = that.parentNode, dispatch = event.of(that, arguments), dragged = 0, dragId = id(), dragName = ".drag" + (dragId == null ? "" : "-" + dragId), dragOffset, dragSubject = d3.select(subject()).on(move + dragName, moved).on(end + dragName, ended), dragRestore = d3_event_dragSuppress(), position0 = position(parent, dragId);
+        if (origin) {
+          dragOffset = origin.apply(that, arguments);
+          dragOffset = [ dragOffset.x - position0[0], dragOffset.y - position0[1] ];
+        } else {
+          dragOffset = [ 0, 0 ];
+        }
+        dispatch({
+          type: "dragstart"
+        });
+        function moved() {
+          var position1 = position(parent, dragId), dx, dy;
+          if (!position1) return;
+          dx = position1[0] - position0[0];
+          dy = position1[1] - position0[1];
+          dragged |= dx | dy;
+          position0 = position1;
+          dispatch({
+            type: "drag",
+            x: position1[0] + dragOffset[0],
+            y: position1[1] + dragOffset[1],
+            dx: dx,
+            dy: dy
+          });
+        }
+        function ended() {
+          if (!position(parent, dragId)) return;
+          dragSubject.on(move + dragName, null).on(end + dragName, null);
+          dragRestore(dragged && d3.event.target === target);
+          dispatch({
+            type: "dragend"
+          });
+        }
+      };
+    }
+    drag.origin = function(x) {
+      if (!arguments.length) return origin;
+      origin = x;
+      return drag;
+    };
+    return d3.rebind(drag, event, "on");
+  };
+  function d3_behavior_dragTouchId() {
+    return d3.event.changedTouches[0].identifier;
+  }
+  function d3_behavior_dragTouchSubject() {
+    return d3.event.target;
+  }
+  function d3_behavior_dragMouseSubject() {
+    return d3_window;
+  }
+  var π = Math.PI, τ = 2 * π, halfπ = π / 2, ε = 1e-6, ε2 = ε * ε, d3_radians = π / 180, d3_degrees = 180 / π;
+  function d3_sgn(x) {
+    return x > 0 ? 1 : x < 0 ? -1 : 0;
+  }
+  function d3_cross2d(a, b, c) {
+    return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]);
+  }
+  function d3_acos(x) {
+    return x > 1 ? 0 : x < -1 ? π : Math.acos(x);
+  }
+  function d3_asin(x) {
+    return x > 1 ? halfπ : x < -1 ? -halfπ : Math.asin(x);
+  }
+  function d3_sinh(x) {
+    return ((x = Math.exp(x)) - 1 / x) / 2;
+  }
+  function d3_cosh(x) {
+    return ((x = Math.exp(x)) + 1 / x) / 2;
+  }
+  function d3_tanh(x) {
+    return ((x = Math.exp(2 * x)) - 1) / (x + 1);
+  }
+  function d3_haversin(x) {
+    return (x = Math.sin(x / 2)) * x;
+  }
+  var ρ = Math.SQRT2, ρ2 = 2, ρ4 = 4;
+  d3.interpolateZoom = function(p0, p1) {
+    var ux0 = p0[0], uy0 = p0[1], w0 = p0[2], ux1 = p1[0], uy1 = p1[1], w1 = p1[2];
+    var dx = ux1 - ux0, dy = uy1 - uy0, d2 = dx * dx + dy * dy, d1 = Math.sqrt(d2), b0 = (w1 * w1 - w0 * w0 + ρ4 * d2) / (2 * w0 * ρ2 * d1), b1 = (w1 * w1 - w0 * w0 - ρ4 * d2) / (2 * w1 * ρ2 * d1), r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0), r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1), dr = r1 - r0, S = (dr || Math.log(w1 / w0)) / ρ;
+    function interpolate(t) {
+      var s = t * S;
+      if (dr) {
+        var coshr0 = d3_cosh(r0), u = w0 / (ρ2 * d1) * (coshr0 * d3_tanh(ρ * s + r0) - d3_sinh(r0));
+        return [ ux0 + u * dx, uy0 + u * dy, w0 * coshr0 / d3_cosh(ρ * s + r0) ];
+      }
+      return [ ux0 + t * dx, uy0 + t * dy, w0 * Math.exp(ρ * s) ];
+    }
+    interpolate.duration = S * 1e3;
+    return interpolate;
+  };
+  d3.behavior.zoom = function() {
+    var view = {
+      x: 0,
+      y: 0,
+      k: 1
+    }, translate0, center, size = [ 960, 500 ], scaleExtent = d3_behavior_zoomInfinity, mousedown = "mousedown.zoom", mousemove = "mousemove.zoom", mouseup = "mouseup.zoom", mousewheelTimer, touchstart = "touchstart.zoom", touchtime, event = d3_eventDispatch(zoom, "zoomstart", "zoom", "zoomend"), x0, x1, y0, y1;
+    function zoom(g) {
+      g.on(mousedown, mousedowned).on(d3_behavior_zoomWheel + ".zoom", mousewheeled).on(mousemove, mousewheelreset).on("dblclick.zoom", dblclicked).on(touchstart, touchstarted);
+    }
+    zoom.event = function(g) {
+      g.each(function() {
+        var dispatch = event.of(this, arguments), view1 = view;
+        if (d3_transitionInheritId) {
+          d3.select(this).transition().each("start.zoom", function() {
+            view = this.__chart__ || {
+              x: 0,
+              y: 0,
+              k: 1
+            };
+            zoomstarted(dispatch);
+          }).tween("zoom:zoom", function() {
+            var dx = size[0], dy = size[1], cx = dx / 2, cy = dy / 2, i = d3.interpolateZoom([ (cx - view.x) / view.k, (cy - view.y) / view.k, dx / view.k ], [ (cx - view1.x) / view1.k, (cy - view1.y) / view1.k, dx / view1.k ]);
+            return function(t) {
+              var l = i(t), k = dx / l[2];
+              this.__chart__ = view = {
+                x: cx - l[0] * k,
+                y: cy - l[1] * k,
+                k: k
+              };
+              zoomed(dispatch);
+            };
+          }).each("end.zoom", function() {
+            zoomended(dispatch);
+          });
+        } else {
+          this.__chart__ = view;
+          zoomstarted(dispatch);
+          zoomed(dispatch);
+          zoomended(dispatch);
+        }
+      });
+    };
+    zoom.translate = function(_) {
+      if (!arguments.length) return [ view.x, view.y ];
+      view = {
+        x: +_[0],
+        y: +_[1],
+        k: view.k
+      };
+      rescale();
+      return zoom;
+    };
+    zoom.scale = function(_) {
+      if (!arguments.length) return view.k;
+      view = {
+        x: view.x,
+        y: view.y,
+        k: +_
+      };
+      rescale();
+      return zoom;
+    };
+    zoom.scaleExtent = function(_) {
+      if (!arguments.length) return scaleExtent;
+      scaleExtent = _ == null ? d3_behavior_zoomInfinity : [ +_[0], +_[1] ];
+      return zoom;
+    };
+    zoom.center = function(_) {
+      if (!arguments.length) return center;
+      center = _ && [ +_[0], +_[1] ];
+      return zoom;
+    };
+    zoom.size = function(_) {
+      if (!arguments.length) return size;
+      size = _ && [ +_[0], +_[1] ];
+      return zoom;
+    };
+    zoom.x = function(z) {
+      if (!arguments.length) return x1;
+      x1 = z;
+      x0 = z.copy();
+      view = {
+        x: 0,
+        y: 0,
+        k: 1
+      };
+      return zoom;
+    };
+    zoom.y = function(z) {
+      if (!arguments.length) return y1;
+      y1 = z;
+      y0 = z.copy();
+      view = {
+        x: 0,
+        y: 0,
+        k: 1
+      };
+      return zoom;
+    };
+    function location(p) {
+      return [ (p[0] - view.x) / view.k, (p[1] - view.y) / view.k ];
+    }
+    function point(l) {
+      return [ l[0] * view.k + view.x, l[1] * view.k + view.y ];
+    }
+    function scaleTo(s) {
+      view.k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], s));
+    }
+    function translateTo(p, l) {
+      l = point(l);
+      view.x += p[0] - l[0];
+      view.y += p[1] - l[1];
+    }
+    function rescale() {
+      if (x1) x1.domain(x0.range().map(function(x) {
+        return (x - view.x) / view.k;
+      }).map(x0.invert));
+      if (y1) y1.domain(y0.range().map(function(y) {
+        return (y - view.y) / view.k;
+      }).map(y0.invert));
+    }
+    function zoomstarted(dispatch) {
+      dispatch({
+        type: "zoomstart"
+      });
+    }
+    function zoomed(dispatch) {
+      rescale();
+      dispatch({
+        type: "zoom",
+        scale: view.k,
+        translate: [ view.x, view.y ]
+      });
+    }
+    function zoomended(dispatch) {
+      dispatch({
+        type: "zoomend"
+      });
+    }
+    function mousedowned() {
+      var that = this, target = d3.event.target, dispatch = event.of(that, arguments), dragged = 0, subject = d3.select(d3_window).on(mousemove, moved).on(mouseup, ended), location0 = location(d3.mouse(that)), dragRestore = d3_event_dragSuppress();
+      d3_selection_interrupt.call(that);
+      zoomstarted(dispatch);
+      function moved() {
+        dragged = 1;
+        translateTo(d3.mouse(that), location0);
+        zoomed(dispatch);
+      }
+      function ended() {
+        subject.on(mousemove, d3_window === that ? mousewheelreset : null).on(mouseup, null);
+        dragRestore(dragged && d3.event.target === target);
+        zoomended(dispatch);
+      }
+    }
+    function touchstarted() {
+      var that = this, dispatch = event.of(that, arguments), locations0 = {}, distance0 = 0, scale0, zoomName = ".zoom-" + d3.event.changedTouches[0].identifier, touchmove = "touchmove" + zoomName, touchend = "touchend" + zoomName, target = d3.select(d3.event.target).on(touchmove, moved).on(touchend, ended), subject = d3.select(that).on(mousedown, null).on(touchstart, started), dragRestore = d3_event_dragSuppress();
+      d3_selection_interrupt.call(that);
+      started();
+      zoomstarted(dispatch);
+      function relocate() {
+        var touches = d3.touches(that);
+        scale0 = view.k;
+        touches.forEach(function(t) {
+          if (t.identifier in locations0) locations0[t.identifier] = location(t);
+        });
+        return touches;
+      }
+      function started() {
+        var changed = d3.event.changedTouches;
+        for (var i = 0, n = changed.length; i < n; ++i) {
+          locations0[changed[i].identifier] = null;
+        }
+        var touches = relocate(), now = Date.now();
+        if (touches.length === 1) {
+          if (now - touchtime < 500) {
+            var p = touches[0], l = locations0[p.identifier];
+            scaleTo(view.k * 2);
+            translateTo(p, l);
+            d3_eventPreventDefault();
+            zoomed(dispatch);
+          }
+          touchtime = now;
+        } else if (touches.length > 1) {
+          var p = touches[0], q = touches[1], dx = p[0] - q[0], dy = p[1] - q[1];
+          distance0 = dx * dx + dy * dy;
+        }
+      }
+      function moved() {
+        var touches = d3.touches(that), p0, l0, p1, l1;
+        for (var i = 0, n = touches.length; i < n; ++i, l1 = null) {
+          p1 = touches[i];
+          if (l1 = locations0[p1.identifier]) {
+            if (l0) break;
+            p0 = p1, l0 = l1;
+          }
+        }
+        if (l1) {
+          var distance1 = (distance1 = p1[0] - p0[0]) * distance1 + (distance1 = p1[1] - p0[1]) * distance1, scale1 = distance0 && Math.sqrt(distance1 / distance0);
+          p0 = [ (p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2 ];
+          l0 = [ (l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2 ];
+          scaleTo(scale1 * scale0);
+        }
+        touchtime = null;
+        translateTo(p0, l0);
+        zoomed(dispatch);
+      }
+      function ended() {
+        if (d3.event.touches.length) {
+          var changed = d3.event.changedTouches;
+          for (var i = 0, n = changed.length; i < n; ++i) {
+            delete locations0[changed[i].identifier];
+          }
+          for (var identifier in locations0) {
+            return void relocate();
+          }
+        }
+        target.on(zoomName, null);
+        subject.on(mousedown, mousedowned).on(touchstart, touchstarted);
+        dragRestore();
+        zoomended(dispatch);
+      }
+    }
+    function mousewheeled() {
+      var dispatch = event.of(this, arguments);
+      if (mousewheelTimer) clearTimeout(mousewheelTimer); else d3_selection_interrupt.call(this), 
+      zoomstarted(dispatch);
+      mousewheelTimer = setTimeout(function() {
+        mousewheelTimer = null;
+        zoomended(dispatch);
+      }, 50);
+      d3_eventPreventDefault();
+      var point = center || d3.mouse(this);
+      if (!translate0) translate0 = location(point);
+      scaleTo(Math.pow(2, d3_behavior_zoomDelta() * .002) * view.k);
+      translateTo(point, translate0);
+      zoomed(dispatch);
+    }
+    function mousewheelreset() {
+      translate0 = null;
+    }
+    function dblclicked() {
+      var dispatch = event.of(this, arguments), p = d3.mouse(this), l = location(p), k = Math.log(view.k) / Math.LN2;
+      zoomstarted(dispatch);
+      scaleTo(Math.pow(2, d3.event.shiftKey ? Math.ceil(k) - 1 : Math.floor(k) + 1));
+      translateTo(p, l);
+      zoomed(dispatch);
+      zoomended(dispatch);
+    }
+    return d3.rebind(zoom, event, "on");
+  };
+  var d3_behavior_zoomInfinity = [ 0, Infinity ];
+  var d3_behavior_zoomDelta, d3_behavior_zoomWheel = "onwheel" in d3_document ? (d3_behavior_zoomDelta = function() {
+    return -d3.event.deltaY * (d3.event.deltaMode ? 120 : 1);
+  }, "wheel") : "onmousewheel" in d3_document ? (d3_behavior_zoomDelta = function() {
+    return d3.event.wheelDelta;
+  }, "mousewheel") : (d3_behavior_zoomDelta = function() {
+    return -d3.event.detail;
+  }, "MozMousePixelScroll");
+  function d3_Color() {}
+  d3_Color.prototype.toString = function() {
+    return this.rgb() + "";
+  };
+  d3.hsl = function(h, s, l) {
+    return arguments.length === 1 ? h instanceof d3_Hsl ? d3_hsl(h.h, h.s, h.l) : d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl) : d3_hsl(+h, +s, +l);
+  };
+  function d3_hsl(h, s, l) {
+    return new d3_Hsl(h, s, l);
+  }
+  function d3_Hsl(h, s, l) {
+    this.h = h;
+    this.s = s;
+    this.l = l;
+  }
+  var d3_hslPrototype = d3_Hsl.prototype = new d3_Color();
+  d3_hslPrototype.brighter = function(k) {
+    k = Math.pow(.7, arguments.length ? k : 1);
+    return d3_hsl(this.h, this.s, this.l / k);
+  };
+  d3_hslPrototype.darker = function(k) {
+    k = Math.pow(.7, arguments.length ? k : 1);
+    return d3_hsl(this.h, this.s, k * this.l);
+  };
+  d3_hslPrototype.rgb = function() {
+    return d3_hsl_rgb(this.h, this.s, this.l);
+  };
+  function d3_hsl_rgb(h, s, l) {
+    var m1, m2;
+    h = isNaN(h) ? 0 : (h %= 360) < 0 ? h + 360 : h;
+    s = isNaN(s) ? 0 : s < 0 ? 0 : s > 1 ? 1 : s;
+    l = l < 0 ? 0 : l > 1 ? 1 : l;
+    m2 = l <= .5 ? l * (1 + s) : l + s - l * s;
+    m1 = 2 * l - m2;
+    function v(h) {
+      if (h > 360) h -= 360; else if (h < 0) h += 360;
+      if (h < 60) return m1 + (m2 - m1) * h / 60;
+      if (h < 180) return m2;
+      if (h < 240) return m1 + (m2 - m1) * (240 - h) / 60;
+      return m1;
+    }
+    function vv(h) {
+      return Math.round(v(h) * 255);
+    }
+    return d3_rgb(vv(h + 120), vv(h), vv(h - 120));
+  }
+  d3.hcl = function(h, c, l) {
+    return arguments.length === 1 ? h instanceof d3_Hcl ? d3_hcl(h.h, h.c, h.l) : h instanceof d3_Lab ? d3_lab_hcl(h.l, h.a, h.b) : d3_lab_hcl((h = d3_rgb_lab((h = d3.rgb(h)).r, h.g, h.b)).l, h.a, h.b) : d3_hcl(+h, +c, +l);
+  };
+  function d3_hcl(h, c, l) {
+    return new d3_Hcl(h, c, l);
+  }
+  function d3_Hcl(h, c, l) {
+    this.h = h;
+    this.c = c;
+    this.l = l;
+  }
+  var d3_hclPrototype = d3_Hcl.prototype = new d3_Color();
+  d3_hclPrototype.brighter = function(k) {
+    return d3_hcl(this.h, this.c, Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)));
+  };
+  d3_hclPrototype.darker = function(k) {
+    return d3_hcl(this.h, this.c, Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)));
+  };
+  d3_hclPrototype.rgb = function() {
+    return d3_hcl_lab(this.h, this.c, this.l).rgb();
+  };
+  function d3_hcl_lab(h, c, l) {
+    if (isNaN(h)) h = 0;
+    if (isNaN(c)) c = 0;
+    return d3_lab(l, Math.cos(h *= d3_radians) * c, Math.sin(h) * c);
+  }
+  d3.lab = function(l, a, b) {
+    return arguments.length === 1 ? l instanceof d3_Lab ? d3_lab(l.l, l.a, l.b) : l instanceof d3_Hcl ? d3_hcl_lab(l.l, l.c, l.h) : d3_rgb_lab((l = d3.rgb(l)).r, l.g, l.b) : d3_lab(+l, +a, +b);
+  };
+  function d3_lab(l, a, b) {
+    return new d3_Lab(l, a, b);
+  }
+  function d3_Lab(l, a, b) {
+    this.l = l;
+    this.a = a;
+    this.b = b;
+  }
+  var d3_lab_K = 18;
+  var d3_lab_X = .95047, d3_lab_Y = 1, d3_lab_Z = 1.08883;
+  var d3_labPrototype = d3_Lab.prototype = new d3_Color();
+  d3_labPrototype.brighter = function(k) {
+    return d3_lab(Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);
+  };
+  d3_labPrototype.darker = function(k) {
+    return d3_lab(Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);
+  };
+  d3_labPrototype.rgb = function() {
+    return d3_lab_rgb(this.l, this.a, this.b);
+  };
+  function d3_lab_rgb(l, a, b) {
+    var y = (l + 16) / 116, x = y + a / 500, z = y - b / 200;
+    x = d3_lab_xyz(x) * d3_lab_X;
+    y = d3_lab_xyz(y) * d3_lab_Y;
+    z = d3_lab_xyz(z) * d3_lab_Z;
+    return d3_rgb(d3_xyz_rgb(3.2404542 * x - 1.5371385 * y - .4985314 * z), d3_xyz_rgb(-.969266 * x + 1.8760108 * y + .041556 * z), d3_xyz_rgb(.0556434 * x - .2040259 * y + 1.0572252 * z));
+  }
+  function d3_lab_hcl(l, a, b) {
+    return l > 0 ? d3_hcl(Math.atan2(b, a) * d3_degrees, Math.sqrt(a * a + b * b), l) : d3_hcl(NaN, NaN, l);
+  }
+  function d3_lab_xyz(x) {
+    return x > .206893034 ? x * x * x : (x - 4 / 29) / 7.787037;
+  }
+  function d3_xyz_lab(x) {
+    return x > .008856 ? Math.pow(x, 1 / 3) : 7.787037 * x + 4 / 29;
+  }
+  function d3_xyz_rgb(r) {
+    return Math.round(255 * (r <= .00304 ? 12.92 * r : 1.055 * Math.pow(r, 1 / 2.4) - .055));
+  }
+  d3.rgb = function(r, g, b) {
+    return arguments.length === 1 ? r instanceof d3_Rgb ? d3_rgb(r.r, r.g, r.b) : d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb) : d3_rgb(~~r, ~~g, ~~b);
+  };
+  function d3_rgbNumber(value) {
+    return d3_rgb(value >> 16, value >> 8 & 255, value & 255);
+  }
+  function d3_rgbString(value) {
+    return d3_rgbNumber(value) + "";
+  }
+  function d3_rgb(r, g, b) {
+    return new d3_Rgb(r, g, b);
+  }
+  function d3_Rgb(r, g, b) {
+    this.r = r;
+    this.g = g;
+    this.b = b;
+  }
+  var d3_rgbPrototype = d3_Rgb.prototype = new d3_Color();
+  d3_rgbPrototype.brighter = function(k) {
+    k = Math.pow(.7, arguments.length ? k : 1);
+    var r = this.r, g = this.g, b = this.b, i = 30;
+    if (!r && !g && !b) return d3_rgb(i, i, i);
+    if (r && r < i) r = i;
+    if (g && g < i) g = i;
+    if (b && b < i) b = i;
+    return d3_rgb(Math.min(255, ~~(r / k)), Math.min(255, ~~(g / k)), Math.min(255, ~~(b / k)));
+  };
+  d3_rgbPrototype.darker = function(k) {
+    k = Math.pow(.7, arguments.length ? k : 1);
+    return d3_rgb(~~(k * this.r), ~~(k * this.g), ~~(k * this.b));
+  };
+  d3_rgbPrototype.hsl = function() {
+    return d3_rgb_hsl(this.r, this.g, this.b);
+  };
+  d3_rgbPrototype.toString = function() {
+    return "#" + d3_rgb_hex(this.r) + d3_rgb_hex(this.g) + d3_rgb_hex(this.b);
+  };
+  function d3_rgb_hex(v) {
+    return v < 16 ? "0" + Math.max(0, v).toString(16) : Math.min(255, v).toString(16);
+  }
+  function d3_rgb_parse(format, rgb, hsl) {
+    var r = 0, g = 0, b = 0, m1, m2, color;
+    m1 = /([a-z]+)\((.*)\)/i.exec(format);
+    if (m1) {
+      m2 = m1[2].split(",");
+      switch (m1[1]) {
+       case "hsl":
+        {
+          return hsl(parseFloat(m2[0]), parseFloat(m2[1]) / 100, parseFloat(m2[2]) / 100);
+        }
+
+       case "rgb":
+        {
+          return rgb(d3_rgb_parseNumber(m2[0]), d3_rgb_parseNumber(m2[1]), d3_rgb_parseNumber(m2[2]));
+        }
+      }
+    }
+    if (color = d3_rgb_names.get(format)) return rgb(color.r, color.g, color.b);
+    if (format != null && format.charAt(0) === "#" && !isNaN(color = parseInt(format.substring(1), 16))) {
+      if (format.length === 4) {
+        r = (color & 3840) >> 4;
+        r = r >> 4 | r;
+        g = color & 240;
+        g = g >> 4 | g;
+        b = color & 15;
+        b = b << 4 | b;
+      } else if (format.length === 7) {
+        r = (color & 16711680) >> 16;
+        g = (color & 65280) >> 8;
+        b = color & 255;
+      }
+    }
+    return rgb(r, g, b);
+  }
+  function d3_rgb_hsl(r, g, b) {
+    var min = Math.min(r /= 255, g /= 255, b /= 255), max = Math.max(r, g, b), d = max - min, h, s, l = (max + min) / 2;
+    if (d) {
+      s = l < .5 ? d / (max + min) : d / (2 - max - min);
+      if (r == max) h = (g - b) / d + (g < b ? 6 : 0); else if (g == max) h = (b - r) / d + 2; else h = (r - g) / d + 4;
+      h *= 60;
+    } else {
+      h = NaN;
+      s = l > 0 && l < 1 ? 0 : h;
+    }
+    return d3_hsl(h, s, l);
+  }
+  function d3_rgb_lab(r, g, b) {
+    r = d3_rgb_xyz(r);
+    g = d3_rgb_xyz(g);
+    b = d3_rgb_xyz(b);
+    var x = d3_xyz_lab((.4124564 * r + .3575761 * g + .1804375 * b) / d3_lab_X), y = d3_xyz_lab((.2126729 * r + .7151522 * g + .072175 * b) / d3_lab_Y), z = d3_xyz_lab((.0193339 * r + .119192 * g + .9503041 * b) / d3_lab_Z);
+    return d3_lab(116 * y - 16, 500 * (x - y), 200 * (y - z));
+  }
+  function d3_rgb_xyz(r) {
+    return (r /= 255) <= .04045 ? r / 12.92 : Math.pow((r + .055) / 1.055, 2.4);
+  }
+  function d3_rgb_parseNumber(c) {
+    var f = parseFloat(c);
+    return c.charAt(c.length - 1) === "%" ? Math.round(f * 2.55) : f;
+  }
+  var d3_rgb_names = d3.map({
+    aliceblue: 15792383,
+    antiquewhite: 16444375,
+    aqua: 65535,
+    aquamarine: 8388564,
+    azure: 15794175,
+    beige: 16119260,
+    bisque: 16770244,
+    black: 0,
+    blanchedalmond: 16772045,
+    blue: 255,
+    blueviolet: 9055202,
+    brown: 10824234,
+    burlywood: 14596231,
+    cadetblue: 6266528,
+    chartreuse: 8388352,
+    chocolate: 13789470,
+    coral: 16744272,
+    cornflowerblue: 6591981,
+    cornsilk: 16775388,
+    crimson: 14423100,
+    cyan: 65535,
+    darkblue: 139,
+    darkcyan: 35723,
+    darkgoldenrod: 12092939,
+    darkgray: 11119017,
+    darkgreen: 25600,
+    darkgrey: 11119017,
+    darkkhaki: 12433259,
+    darkmagenta: 9109643,
+    darkolivegreen: 5597999,
+    darkorange: 16747520,
+    darkorchid: 10040012,
+    darkred: 9109504,
+    darksalmon: 15308410,
+    darkseagreen: 9419919,
+    darkslateblue: 4734347,
+    darkslategray: 3100495,
+    darkslategrey: 3100495,
+    darkturquoise: 52945,
+    darkviolet: 9699539,
+    deeppink: 16716947,
+    deepskyblue: 49151,
+    dimgray: 6908265,
+    dimgrey: 6908265,
+    dodgerblue: 2003199,
+    firebrick: 11674146,
+    floralwhite: 16775920,
+    forestgreen: 2263842,
+    fuchsia: 16711935,
+    gainsboro: 14474460,
+    ghostwhite: 16316671,
+    gold: 16766720,
+    goldenrod: 14329120,
+    gray: 8421504,
+    green: 32768,
+    greenyellow: 11403055,
+    grey: 8421504,
+    honeydew: 15794160,
+    hotpink: 16738740,
+    indianred: 13458524,
+    indigo: 4915330,
+    ivory: 16777200,
+    khaki: 15787660,
+    lavender: 15132410,
+    lavenderblush: 16773365,
+    lawngreen: 8190976,
+    lemonchiffon: 16775885,
+    lightblue: 11393254,
+    lightcoral: 15761536,
+    lightcyan: 14745599,
+    lightgoldenrodyellow: 16448210,
+    lightgray: 13882323,
+    lightgreen: 9498256,
+    lightgrey: 13882323,
+    lightpink: 16758465,
+    lightsalmon: 16752762,
+    lightseagreen: 2142890,
+    lightskyblue: 8900346,
+    lightslategray: 7833753,
+    lightslategrey: 7833753,
+    lightsteelblue: 11584734,
+    lightyellow: 16777184,
+    lime: 65280,
+    limegreen: 3329330,
+    linen: 16445670,
+    magenta: 16711935,
+    maroon: 8388608,
+    mediumaquamarine: 6737322,
+    mediumblue: 205,
+    mediumorchid: 12211667,
+    mediumpurple: 9662683,
+    mediumseagreen: 3978097,
+    mediumslateblue: 8087790,
+    mediumspringgreen: 64154,
+    mediumturquoise: 4772300,
+    mediumvioletred: 13047173,
+    midnightblue: 1644912,
+    mintcream: 16121850,
+    mistyrose: 16770273,
+    moccasin: 16770229,
+    navajowhite: 16768685,
+    navy: 128,
+    oldlace: 16643558,
+    olive: 8421376,
+    olivedrab: 7048739,
+    orange: 16753920,
+    orangered: 16729344,
+    orchid: 14315734,
+    palegoldenrod: 15657130,
+    palegreen: 10025880,
+    paleturquoise: 11529966,
+    palevioletred: 14381203,
+    papayawhip: 16773077,
+    peachpuff: 16767673,
+    peru: 13468991,
+    pink: 16761035,
+    plum: 14524637,
+    powderblue: 11591910,
+    purple: 8388736,
+    red: 16711680,
+    rosybrown: 12357519,
+    royalblue: 4286945,
+    saddlebrown: 9127187,
+    salmon: 16416882,
+    sandybrown: 16032864,
+    seagreen: 3050327,
+    seashell: 16774638,
+    sienna: 10506797,
+    silver: 12632256,
+    skyblue: 8900331,
+    slateblue: 6970061,
+    slategray: 7372944,
+    slategrey: 7372944,
+    snow: 16775930,
+    springgreen: 65407,
+    steelblue: 4620980,
+    tan: 13808780,
+    teal: 32896,
+    thistle: 14204888,
+    tomato: 16737095,
+    turquoise: 4251856,
+    violet: 15631086,
+    wheat: 16113331,
+    white: 16777215,
+    whitesmoke: 16119285,
+    yellow: 16776960,
+    yellowgreen: 10145074
+  });
+  d3_rgb_names.forEach(function(key, value) {
+    d3_rgb_names.set(key, d3_rgbNumber(value));
+  });
+  function d3_functor(v) {
+    return typeof v === "function" ? v : function() {
+      return v;
+    };
+  }
+  d3.functor = d3_functor;
+  function d3_identity(d) {
+    return d;
+  }
+  d3.xhr = d3_xhrType(d3_identity);
+  function d3_xhrType(response) {
+    return function(url, mimeType, callback) {
+      if (arguments.length === 2 && typeof mimeType === "function") callback = mimeType, 
+      mimeType = null;
+      return d3_xhr(url, mimeType, response, callback);
+    };
+  }
+  function d3_xhr(url, mimeType, response, callback) {
+    var xhr = {}, dispatch = d3.dispatch("beforesend", "progress", "load", "error"), headers = {}, request = new XMLHttpRequest(), responseType = null;
+    if (d3_window.XDomainRequest && !("withCredentials" in request) && /^(http(s)?:)?\/\//.test(url)) request = new XDomainRequest();
+    "onload" in request ? request.onload = request.onerror = respond : request.onreadystatechange = function() {
+      request.readyState > 3 && respond();
+    };
+    function respond() {
+      var status = request.status, result;
+      if (!status && request.responseText || status >= 200 && status < 300 || status === 304) {
+        try {
+          result = response.call(xhr, request);
+        } catch (e) {
+          dispatch.error.call(xhr, e);
+          return;
+        }
+        dispatch.load.call(xhr, result);
+      } else {
+        dispatch.error.call(xhr, request);
+      }
+    }
+    request.onprogress = function(event) {
+      var o = d3.event;
+      d3.event = event;
+      try {
+        dispatch.progress.call(xhr, request);
+      } finally {
+        d3.event = o;
+      }
+    };
+    xhr.header = function(name, value) {
+      name = (name + "").toLowerCase();
+      if (arguments.length < 2) return headers[name];
+      if (value == null) delete headers[name]; else headers[name] = value + "";
+      return xhr;
+    };
+    xhr.mimeType = function(value) {
+      if (!arguments.length) return mimeType;
+      mimeType = value == null ? null : value + "";
+      return xhr;
+    };
+    xhr.responseType = function(value) {
+      if (!arguments.length) return responseType;
+      responseType = value;
+      return xhr;
+    };
+    xhr.response = function(value) {
+      response = value;
+      return xhr;
+    };
+    [ "get", "post" ].forEach(function(method) {
+      xhr[method] = function() {
+        return xhr.send.apply(xhr, [ method ].concat(d3_array(arguments)));
+      };
+    });
+    xhr.send = function(method, data, callback) {
+      if (arguments.length === 2 && typeof data === "function") callback = data, data = null;
+      request.open(method, url, true);
+      if (mimeType != null && !("accept" in headers)) headers["accept"] = mimeType + ",*/*";
+      if (request.setRequestHeader) for (var name in headers) request.setRequestHeader(name, headers[name]);
+      if (mimeType != null && request.overrideMimeType) request.overrideMimeType(mimeType);
+      if (responseType != null) request.responseType = responseType;
+      if (callback != null) xhr.on("error", callback).on("load", function(request) {
+        callback(null, request);
+      });
+      dispatch.beforesend.call(xhr, request);
+      request.send(data == null ? null : data);
+      return xhr;
+    };
+    xhr.abort = function() {
+      request.abort();
+      return xhr;
+    };
+    d3.rebind(xhr, dispatch, "on");
+    return callback == null ? xhr : xhr.get(d3_xhr_fixCallback(callback));
+  }
+  function d3_xhr_fixCallback(callback) {
+    return callback.length === 1 ? function(error, request) {
+      callback(error == null ? request : null);
+    } : callback;
+  }
+  d3.dsv = function(delimiter, mimeType) {
+    var reFormat = new RegExp('["' + delimiter + "\n]"), delimiterCode = delimiter.charCodeAt(0);
+    function dsv(url, row, callback) {
+      if (arguments.length < 3) callback = row, row = null;
+      var xhr = d3_xhr(url, mimeType, row == null ? response : typedResponse(row), callback);
+      xhr.row = function(_) {
+        return arguments.length ? xhr.response((row = _) == null ? response : typedResponse(_)) : row;
+      };
+      return xhr;
+    }
+    function response(request) {
+      return dsv.parse(request.responseText);
+    }
+    function typedResponse(f) {
+      return function(request) {
+        return dsv.parse(request.responseText, f);
+      };
+    }
+    dsv.parse = function(text, f) {
+      var o;
+      return dsv.parseRows(text, function(row, i) {
+        if (o) return o(row, i - 1);
+        var a = new Function("d", "return {" + row.map(function(name, i) {
+          return JSON.stringify(name) + ": d[" + i + "]";
+        }).join(",") + "}");
+        o = f ? function(row, i) {
+          return f(a(row), i);
+        } : a;
+      });
+    };
+    dsv.parseRows = function(text, f) {
+      var EOL = {}, EOF = {}, rows = [], N = text.length, I = 0, n = 0, t, eol;
+      function token() {
+        if (I >= N) return EOF;
+        if (eol) return eol = false, EOL;
+        var j = I;
+        if (text.charCodeAt(j) === 34) {
+          var i = j;
+          while (i++ < N) {
+            if (text.charCodeAt(i) === 34) {
+              if (text.charCodeAt(i + 1) !== 34) break;
+              ++i;
+            }
+          }
+          I = i + 2;
+          var c = text.charCodeAt(i + 1);
+          if (c === 13) {
+            eol = true;
+            if (text.charCodeAt(i + 2) === 10) ++I;
+          } else if (c === 10) {
+            eol = true;
+          }
+          return text.substring(j + 1, i).replace(/""/g, '"');
+        }
+        while (I < N) {
+          var c = text.charCodeAt(I++), k = 1;
+          if (c === 10) eol = true; else if (c === 13) {
+            eol = true;
+            if (text.charCodeAt(I) === 10) ++I, ++k;
+          } else if (c !== delimiterCode) continue;
+          return text.substring(j, I - k);
+        }
+        return text.substring(j);
+      }
+      while ((t = token()) !== EOF) {
+        var a = [];
+        while (t !== EOL && t !== EOF) {
+          a.push(t);
+          t = token();
+        }
+        if (f && !(a = f(a, n++))) continue;
+        rows.push(a);
+      }
+      return rows;
+    };
+    dsv.format = function(rows) {
+      if (Array.isArray(rows[0])) return dsv.formatRows(rows);
+      var fieldSet = new d3_Set(), fields = [];
+      rows.forEach(function(row) {
+        for (var field in row) {
+          if (!fieldSet.has(field)) {
+            fields.push(fieldSet.add(field));
+          }
+        }
+      });
+      return [ fields.map(formatValue).join(delimiter) ].concat(rows.map(function(row) {
+        return fields.map(function(field) {
+          return formatValue(row[field]);
+        }).join(delimiter);
+      })).join("\n");
+    };
+    dsv.formatRows = function(rows) {
+      return rows.map(formatRow).join("\n");
+    };
+    function formatRow(row) {
+      return row.map(formatValue).join(delimiter);
+    }
+    function formatValue(text) {
+      return reFormat.test(text) ? '"' + text.replace(/\"/g, '""') + '"' : text;
+    }
+    return dsv;
+  };
+  d3.csv = d3.dsv(",", "text/csv");
+  d3.tsv = d3.dsv("	", "text/tab-separated-values");
+  d3.touch = function(container, touches, identifier) {
+    if (arguments.length < 3) identifier = touches, touches = d3_eventSource().changedTouches;
+    if (touches) for (var i = 0, n = touches.length, touch; i < n; ++i) {
+      if ((touch = touches[i]).identifier === identifier) {
+        return d3_mousePoint(container, touch);
+      }
+    }
+  };
+  var d3_timer_queueHead, d3_timer_queueTail, d3_timer_interval, d3_timer_timeout, d3_timer_active, d3_timer_frame = d3_window[d3_vendorSymbol(d3_window, "requestAnimationFrame")] || function(callback) {
+    setTimeout(callback, 17);
+  };
+  d3.timer = function(callback, delay, then) {
+    var n = arguments.length;
+    if (n < 2) delay = 0;
+    if (n < 3) then = Date.now();
+    var time = then + delay, timer = {
+      c: callback,
+      t: time,
+      f: false,
+      n: null
+    };
+    if (d3_timer_queueTail) d3_timer_queueTail.n = timer; else d3_timer_queueHead = timer;
+    d3_timer_queueTail = timer;
+    if (!d3_timer_interval) {
+      d3_timer_timeout = clearTimeout(d3_timer_timeout);
+      d3_timer_interval = 1;
+      d3_timer_frame(d3_timer_step);
+    }
+  };
+  function d3_timer_step() {
+    var now = d3_timer_mark(), delay = d3_timer_sweep() - now;
+    if (delay > 24) {
+      if (isFinite(delay)) {
+        clearTimeout(d3_timer_timeout);
+        d3_timer_timeout = setTimeout(d3_timer_step, delay);
+      }
+      d3_timer_interval = 0;
+    } else {
+      d3_timer_interval = 1;
+      d3_timer_frame(d3_timer_step);
+    }
+  }
+  d3.timer.flush = function() {
+    d3_timer_mark();
+    d3_timer_sweep();
+  };
+  function d3_timer_mark() {
+    var now = Date.now();
+    d3_timer_active = d3_timer_queueHead;
+    while (d3_timer_active) {
+      if (now >= d3_timer_active.t) d3_timer_active.f = d3_timer_active.c(now - d3_timer_active.t);
+      d3_timer_active = d3_timer_active.n;
+    }
+    return now;
+  }
+  function d3_timer_sweep() {
+    var t0, t1 = d3_timer_queueHead, time = Infinity;
+    while (t1) {
+      if (t1.f) {
+        t1 = t0 ? t0.n = t1.n : d3_timer_queueHead = t1.n;
+      } else {
+        if (t1.t < time) time = t1.t;
+        t1 = (t0 = t1).n;
+      }
+    }
+    d3_timer_queueTail = t0;
+    return time;
+  }
+  function d3_format_precision(x, p) {
+    return p - (x ? Math.ceil(Math.log(x) / Math.LN10) : 1);
+  }
+  d3.round = function(x, n) {
+    return n ? Math.round(x * (n = Math.pow(10, n))) / n : Math.round(x);
+  };
+  var d3_formatPrefixes = [ "y", "z", "a", "f", "p", "n", "µ", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y" ].map(d3_formatPrefix);
+  d3.formatPrefix = function(value, precision) {
+    var i = 0;
+    if (value) {
+      if (value < 0) value *= -1;
+      if (precision) value = d3.round(value, d3_format_precision(value, precision));
+      i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10);
+      i = Math.max(-24, Math.min(24, Math.floor((i - 1) / 3) * 3));
+    }
+    return d3_formatPrefixes[8 + i / 3];
+  };
+  function d3_formatPrefix(d, i) {
+    var k = Math.pow(10, abs(8 - i) * 3);
+    return {
+      scale: i > 8 ? function(d) {
+        return d / k;
+      } : function(d) {
+        return d * k;
+      },
+      symbol: d
+    };
+  }
+  function d3_locale_numberFormat(locale) {
+    var locale_decimal = locale.decimal, locale_thousands = locale.thousands, locale_grouping = locale.grouping, locale_currency = locale.currency, formatGroup = locale_grouping ? function(value) {
+      var i = value.length, t = [], j = 0, g = locale_grouping[0];
+      while (i > 0 && g > 0) {
+        t.push(value.substring(i -= g, i + g));
+        g = locale_grouping[j = (j + 1) % locale_grouping.length];
+      }
+      return t.reverse().join(locale_thousands);
+    } : d3_identity;
+    return function(specifier) {
+      var match = d3_format_re.exec(specifier), fill = match[1] || " ", align = match[2] || ">", sign = match[3] || "", symbol = match[4] || "", zfill = match[5], width = +match[6], comma = match[7], precision = match[8], type = match[9], scale = 1, prefix = "", suffix = "", integer = false;
+      if (precision) precision = +precision.substring(1);
+      if (zfill || fill === "0" && align === "=") {
+        zfill = fill = "0";
+        align = "=";
+        if (comma) width -= Math.floor((width - 1) / 4);
+      }
+      switch (type) {
+       case "n":
+        comma = true;
+        type = "g";
+        break;
+
+       case "%":
+        scale = 100;
+        suffix = "%";
+        type = "f";
+        break;
+
+       case "p":
+        scale = 100;
+        suffix = "%";
+        type = "r";
+        break;
+
+       case "b":
+       case "o":
+       case "x":
+       case "X":
+        if (symbol === "#") prefix = "0" + type.toLowerCase();
+
+       case "c":
+       case "d":
+        integer = true;
+        precision = 0;
+        break;
+
+       case "s":
+        scale = -1;
+        type = "r";
+        break;
+      }
+      if (symbol === "$") prefix = locale_currency[0], suffix = locale_currency[1];
+      if (type == "r" && !precision) type = "g";
+      if (precision != null) {
+        if (type == "g") precision = Math.max(1, Math.min(21, precision)); else if (type == "e" || type == "f") precision = Math.max(0, Math.min(20, precision));
+      }
+      type = d3_format_types.get(type) || d3_format_typeDefault;
+      var zcomma = zfill && comma;
+      return function(value) {
+        var fullSuffix = suffix;
+        if (integer && value % 1) return "";
+        var negative = value < 0 || value === 0 && 1 / value < 0 ? (value = -value, "-") : sign;
+        if (scale < 0) {
+          var unit = d3.formatPrefix(value, precision);
+          value = unit.scale(value);
+          fullSuffix = unit.symbol + suffix;
+        } else {
+          value *= scale;
+        }
+        value = type(value, precision);
+        var i = value.lastIndexOf("."), before = i < 0 ? value : value.substring(0, i), after = i < 0 ? "" : locale_decimal + value.substring(i + 1);
+        if (!zfill && comma) before = formatGroup(before);
+        var length = prefix.length + before.length + after.length + (zcomma ? 0 : negative.length), padding = length < width ? new Array(length = width - length + 1).join(fill) : "";
+        if (zcomma) before = formatGroup(padding + before);
+        negative += prefix;
+        value = before + after;
+        return (align === "<" ? negative + value + padding : align === ">" ? padding + negative + value : align === "^" ? padding.substring(0, length >>= 1) + negative + value + padding.substring(length) : negative + (zcomma ? value : padding + value)) + fullSuffix;
+      };
+    };
+  }
+  var d3_format_re = /(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i;
+  var d3_format_types = d3.map({
+    b: function(x) {
+      return x.toString(2);
+    },
+    c: function(x) {
+      return String.fromCharCode(x);
+    },
+    o: function(x) {
+      return x.toString(8);
+    },
+    x: function(x) {
+      return x.toString(16);
+    },
+    X: function(x) {
+      return x.toString(16).toUpperCase();
+    },
+    g: function(x, p) {
+      return x.toPrecision(p);
+    },
+    e: function(x, p) {
+      return x.toExponential(p);
+    },
+    f: function(x, p) {
+      return x.toFixed(p);
+    },
+    r: function(x, p) {
+      return (x = d3.round(x, d3_format_precision(x, p))).toFixed(Math.max(0, Math.min(20, d3_format_precision(x * (1 + 1e-15), p))));
+    }
+  });
+  function d3_format_typeDefault(x) {
+    return x + "";
+  }
+  var d3_time = d3.time = {}, d3_date = Date;
+  function d3_date_utc() {
+    this._ = new Date(arguments.length > 1 ? Date.UTC.apply(this, arguments) : arguments[0]);
+  }
+  d3_date_utc.prototype = {
+    getDate: function() {
+      return this._.getUTCDate();
+    },
+    getDay: function() {
+      return this._.getUTCDay();
+    },
+    getFullYear: function() {
+      return this._.getUTCFullYear();
+    },
+    getHours: function() {
+      return this._.getUTCHours();
+    },
+    getMilliseconds: function() {
+      return this._.getUTCMilliseconds();
+    },
+    getMinutes: function() {
+      return this._.getUTCMinutes();
+    },
+    getMonth: function() {
+      return this._.getUTCMonth();
+    },
+    getSeconds: function() {
+      return this._.getUTCSeconds();
+    },
+    getTime: function() {
+      return this._.getTime();
+    },
+    getTimezoneOffset: function() {
+      return 0;
+    },
+    valueOf: function() {
+      return this._.valueOf();
+    },
+    setDate: function() {
+      d3_time_prototype.setUTCDate.apply(this._, arguments);
+    },
+    setDay: function() {
+      d3_time_prototype.setUTCDay.apply(this._, arguments);
+    },
+    setFullYear: function() {
+      d3_time_prototype.setUTCFullYear.apply(this._, arguments);
+    },
+    setHours: function() {
+      d3_time_prototype.setUTCHours.apply(this._, arguments);
+    },
+    setMilliseconds: function() {
+      d3_time_prototype.setUTCMilliseconds.apply(this._, arguments);
+    },
+    setMinutes: function() {
+      d3_time_prototype.setUTCMinutes.apply(this._, arguments);
+    },
+    setMonth: function() {
+      d3_time_prototype.setUTCMonth.apply(this._, arguments);
+    },
+    setSeconds: function() {
+      d3_time_prototype.setUTCSeconds.apply(this._, arguments);
+    },
+    setTime: function() {
+      d3_time_prototype.setTime.apply(this._, arguments);
+    }
+  };
+  var d3_time_prototype = Date.prototype;
+  function d3_time_interval(local, step, number) {
+    function round(date) {
+      var d0 = local(date), d1 = offset(d0, 1);
+      return date - d0 < d1 - date ? d0 : d1;
+    }
+    function ceil(date) {
+      step(date = local(new d3_date(date - 1)), 1);
+      return date;
+    }
+    function offset(date, k) {
+      step(date = new d3_date(+date), k);
+      return date;
+    }
+    function range(t0, t1, dt) {
+      var time = ceil(t0), times = [];
+      if (dt > 1) {
+        while (time < t1) {
+          if (!(number(time) % dt)) times.push(new Date(+time));
+          step(time, 1);
+        }
+      } else {
+        while (time < t1) times.push(new Date(+time)), step(time, 1);
+      }
+      return times;
+    }
+    function range_utc(t0, t1, dt) {
+      try {
+        d3_date = d3_date_utc;
+        var utc = new d3_date_utc();
+        utc._ = t0;
+        return range(utc, t1, dt);
+      } finally {
+        d3_date = Date;
+      }
+    }
+    local.floor = local;
+    local.round = round;
+    local.ceil = ceil;
+    local.offset = offset;
+    local.range = range;
+    var utc = local.utc = d3_time_interval_utc(local);
+    utc.floor = utc;
+    utc.round = d3_time_interval_utc(round);
+    utc.ceil = d3_time_interval_utc(ceil);
+    utc.offset = d3_time_interval_utc(offset);
+    utc.range = range_utc;
+    return local;
+  }
+  function d3_time_interval_utc(method) {
+    return function(date, k) {
+      try {
+        d3_date = d3_date_utc;
+        var utc = new d3_date_utc();
+        utc._ = date;
+        return method(utc, k)._;
+      } finally {
+        d3_date = Date;
+      }
+    };
+  }
+  d3_time.year = d3_time_interval(function(date) {
+    date = d3_time.day(date);
+    date.setMonth(0, 1);
+    return date;
+  }, function(date, offset) {
+    date.setFullYear(date.getFullYear() + offset);
+  }, function(date) {
+    return date.getFullYear();
+  });
+  d3_time.years = d3_time.year.range;
+  d3_time.years.utc = d3_time.year.utc.range;
+  d3_time.day = d3_time_interval(function(date) {
+    var day = new d3_date(2e3, 0);
+    day.setFullYear(date.getFullYear(), date.getMonth(), date.getDate());
+    return day;
+  }, function(date, offset) {
+    date.setDate(date.getDate() + offset);
+  }, function(date) {
+    return date.getDate() - 1;
+  });
+  d3_time.days = d3_time.day.range;
+  d3_time.days.utc = d3_time.day.utc.range;
+  d3_time.dayOfYear = function(date) {
+    var year = d3_time.year(date);
+    return Math.floor((date - year - (date.getTimezoneOffset() - year.getTimezoneOffset()) * 6e4) / 864e5);
+  };
+  [ "sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday" ].forEach(function(day, i) {
+    i = 7 - i;
+    var interval = d3_time[day] = d3_time_interval(function(date) {
+      (date = d3_time.day(date)).setDate(date.getDate() - (date.getDay() + i) % 7);
+      return date;
+    }, function(date, offset) {
+      date.setDate(date.getDate() + Math.floor(offset) * 7);
+    }, function(date) {
+      var day = d3_time.year(date).getDay();
+      return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7) - (day !== i);
+    });
+    d3_time[day + "s"] = interval.range;
+    d3_time[day + "s"].utc = interval.utc.range;
+    d3_time[day + "OfYear"] = function(date) {
+      var day = d3_time.year(date).getDay();
+      return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7);
+    };
+  });
+  d3_time.week = d3_time.sunday;
+  d3_time.weeks = d3_time.sunday.range;
+  d3_time.weeks.utc = d3_time.sunday.utc.range;
+  d3_time.weekOfYear = d3_time.sundayOfYear;
+  function d3_locale_timeFormat(locale) {
+    var locale_dateTime = locale.dateTime, locale_date = locale.date, locale_time = locale.time, locale_periods = locale.periods, locale_days = locale.days, locale_shortDays = locale.shortDays, locale_months = locale.months, locale_shortMonths = locale.shortMonths;
+    function d3_time_format(template) {
+      var n = template.length;
+      function format(date) {
+        var string = [], i = -1, j = 0, c, p, f;
+        while (++i < n) {
+          if (template.charCodeAt(i) === 37) {
+            string.push(template.substring(j, i));
+            if ((p = d3_time_formatPads[c = template.charAt(++i)]) != null) c = template.charAt(++i);
+            if (f = d3_time_formats[c]) c = f(date, p == null ? c === "e" ? " " : "0" : p);
+            string.push(c);
+            j = i + 1;
+          }
+        }
+        string.push(template.substring(j, i));
+        return string.join("");
+      }
+      format.parse = function(string) {
+        var d = {
+          y: 1900,
+          m: 0,
+          d: 1,
+          H: 0,
+          M: 0,
+          S: 0,
+          L: 0,
+          Z: null
+        }, i = d3_time_parse(d, template, string, 0);
+        if (i != string.length) return null;
+        if ("p" in d) d.H = d.H % 12 + d.p * 12;
+        var localZ = d.Z != null && d3_date !== d3_date_utc, date = new (localZ ? d3_date_utc : d3_date)();
+        if ("j" in d) date.setFullYear(d.y, 0, d.j); else if ("w" in d && ("W" in d || "U" in d)) {
+          date.setFullYear(d.y, 0, 1);
+          date.setFullYear(d.y, 0, "W" in d ? (d.w + 6) % 7 + d.W * 7 - (date.getDay() + 5) % 7 : d.w + d.U * 7 - (date.getDay() + 6) % 7);
+        } else date.setFullYear(d.y, d.m, d.d);
+        date.setHours(d.H + Math.floor(d.Z / 100), d.M + d.Z % 100, d.S, d.L);
+        return localZ ? date._ : date;
+      };
+      format.toString = function() {
+        return template;
+      };
+      return format;
+    }
+    function d3_time_parse(date, template, string, j) {
+      var c, p, t, i = 0, n = template.length, m = string.length;
+      while (i < n) {
+        if (j >= m) return -1;
+        c = template.charCodeAt(i++);
+        if (c === 37) {
+          t = template.charAt(i++);
+          p = d3_time_parsers[t in d3_time_formatPads ? template.charAt(i++) : t];
+          if (!p || (j = p(date, string, j)) < 0) return -1;
+        } else if (c != string.charCodeAt(j++)) {
+          return -1;
+        }
+      }
+      return j;
+    }
+    d3_time_format.utc = function(template) {
+      var local = d3_time_format(template);
+      function format(date) {
+        try {
+          d3_date = d3_date_utc;
+          var utc = new d3_date();
+          utc._ = date;
+          return local(utc);
+        } finally {
+          d3_date = Date;
+        }
+      }
+      format.parse = function(string) {
+        try {
+          d3_date = d3_date_utc;
+          var date = local.parse(string);
+          return date && date._;
+        } finally {
+          d3_date = Date;
+        }
+      };
+      format.toString = local.toString;
+      return format;
+    };
+    d3_time_format.multi = d3_time_format.utc.multi = d3_time_formatMulti;
+    var d3_time_periodLookup = d3.map(), d3_time_dayRe = d3_time_formatRe(locale_days), d3_time_dayLookup = d3_time_formatLookup(locale_days), d3_time_dayAbbrevRe = d3_time_formatRe(locale_shortDays), d3_time_dayAbbrevLookup = d3_time_formatLookup(locale_shortDays), d3_time_monthRe = d3_time_formatRe(locale_months), d3_time_monthLookup = d3_time_formatLookup(locale_months), d3_time_monthAbbrevRe = d3_time_formatRe(locale_shortMonths), d3_time_monthAbbrevLookup = d3_time_formatLookup(locale_shortMonths);
+    locale_periods.forEach(function(p, i) {
+      d3_time_periodLookup.set(p.toLowerCase(), i);
+    });
+    var d3_time_formats = {
+      a: function(d) {
+        return locale_shortDays[d.getDay()];
+      },
+      A: function(d) {
+        return locale_days[d.getDay()];
+      },
+      b: function(d) {
+        return locale_shortMonths[d.getMonth()];
+      },
+      B: function(d) {
+        return locale_months[d.getMonth()];
+      },
+      c: d3_time_format(locale_dateTime),
+      d: function(d, p) {
+        return d3_time_formatPad(d.getDate(), p, 2);
+      },
+      e: function(d, p) {
+        return d3_time_formatPad(d.getDate(), p, 2);
+      },
+      H: function(d, p) {
+        return d3_time_formatPad(d.getHours(), p, 2);
+      },
+      I: function(d, p) {
+        return d3_time_formatPad(d.getHours() % 12 || 12, p, 2);
+      },
+      j: function(d, p) {
+        return d3_time_formatPad(1 + d3_time.dayOfYear(d), p, 3);
+      },
+      L: function(d, p) {
+        return d3_time_formatPad(d.getMilliseconds(), p, 3);
+      },
+      m: function(d, p) {
+        return d3_time_formatPad(d.getMonth() + 1, p, 2);
+      },
+      M: function(d, p) {
+        return d3_time_formatPad(d.getMinutes(), p, 2);
+      },
+      p: function(d) {
+        return locale_periods[+(d.getHours() >= 12)];
+      },
+      S: function(d, p) {
+        return d3_time_formatPad(d.getSeconds(), p, 2);
+      },
+      U: function(d, p) {
+        return d3_time_formatPad(d3_time.sundayOfYear(d), p, 2);
+      },
+      w: function(d) {
+        return d.getDay();
+      },
+      W: function(d, p) {
+        return d3_time_formatPad(d3_time.mondayOfYear(d), p, 2);
+      },
+      x: d3_time_format(locale_date),
+      X: d3_time_format(locale_time),
+      y: function(d, p) {
+        return d3_time_formatPad(d.getFullYear() % 100, p, 2);
+      },
+      Y: function(d, p) {
+        return d3_time_formatPad(d.getFullYear() % 1e4, p, 4);
+      },
+      Z: d3_time_zone,
+      "%": function() {
+        return "%";
+      }
+    };
+    var d3_time_parsers = {
+      a: d3_time_parseWeekdayAbbrev,
+      A: d3_time_parseWeekday,
+      b: d3_time_parseMonthAbbrev,
+      B: d3_time_parseMonth,
+      c: d3_time_parseLocaleFull,
+      d: d3_time_parseDay,
+      e: d3_time_parseDay,
+      H: d3_time_parseHour24,
+      I: d3_time_parseHour24,
+      j: d3_time_parseDayOfYear,
+      L: d3_time_parseMilliseconds,
+      m: d3_time_parseMonthNumber,
+      M: d3_time_parseMinutes,
+      p: d3_time_parseAmPm,
+      S: d3_time_parseSeconds,
+      U: d3_time_parseWeekNumberSunday,
+      w: d3_time_parseWeekdayNumber,
+      W: d3_time_parseWeekNumberMonday,
+      x: d3_time_parseLocaleDate,
+      X: d3_time_parseLocaleTime,
+      y: d3_time_parseYear,
+      Y: d3_time_parseFullYear,
+      Z: d3_time_parseZone,
+      "%": d3_time_parseLiteralPercent
+    };
+    function d3_time_parseWeekdayAbbrev(date, string, i) {
+      d3_time_dayAbbrevRe.lastIndex = 0;
+      var n = d3_time_dayAbbrevRe.exec(string.substring(i));
+      return n ? (date.w = d3_time_dayAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
+    }
+    function d3_time_parseWeekday(date, string, i) {
+      d3_time_dayRe.lastIndex = 0;
+      var n = d3_time_dayRe.exec(string.substring(i));
+      return n ? (date.w = d3_time_dayLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
+    }
+    function d3_time_parseMonthAbbrev(date, string, i) {
+      d3_time_monthAbbrevRe.lastIndex = 0;
+      var n = d3_time_monthAbbrevRe.exec(string.substring(i));
+      return n ? (date.m = d3_time_monthAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
+    }
+    function d3_time_parseMonth(date, string, i) {
+      d3_time_monthRe.lastIndex = 0;
+      var n = d3_time_monthRe.exec(string.substring(i));
+      return n ? (date.m = d3_time_monthLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
+    }
+    function d3_time_parseLocaleFull(date, string, i) {
+      return d3_time_parse(date, d3_time_formats.c.toString(), string, i);
+    }
+    function d3_time_parseLocaleDate(date, string, i) {
+      return d3_time_parse(date, d3_time_formats.x.toString(), string, i);
+    }
+    function d3_time_parseLocaleTime(date, string, i) {
+      return d3_time_parse(date, d3_time_formats.X.toString(), string, i);
+    }
+    function d3_time_parseAmPm(date, string, i) {
+      var n = d3_time_periodLookup.get(string.substring(i, i += 2).toLowerCase());
+      return n == null ? -1 : (date.p = n, i);
+    }
+    return d3_time_format;
+  }
+  var d3_time_formatPads = {
+    "-": "",
+    _: " ",
+    "0": "0"
+  }, d3_time_numberRe = /^\s*\d+/, d3_time_percentRe = /^%/;
+  function d3_time_formatPad(value, fill, width) {
+    var sign = value < 0 ? "-" : "", string = (sign ? -value : value) + "", length = string.length;
+    return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string);
+  }
+  function d3_time_formatRe(names) {
+    return new RegExp("^(?:" + names.map(d3.requote).join("|") + ")", "i");
+  }
+  function d3_time_formatLookup(names) {
+    var map = new d3_Map(), i = -1, n = names.length;
+    while (++i < n) map.set(names[i].toLowerCase(), i);
+    return map;
+  }
+  function d3_time_parseWeekdayNumber(date, string, i) {
+    d3_time_numberRe.lastIndex = 0;
+    var n = d3_time_numberRe.exec(string.substring(i, i + 1));
+    return n ? (date.w = +n[0], i + n[0].length) : -1;
+  }
+  function d3_time_parseWeekNumberSunday(date, string, i) {
+    d3_time_numberRe.lastIndex = 0;
+    var n = d3_time_numberRe.exec(string.substring(i));
+    return n ? (date.U = +n[0], i + n[0].length) : -1;
+  }
+  function d3_time_parseWeekNumberMonday(date, string, i) {
+    d3_time_numberRe.lastIndex = 0;
+    var n = d3_time_numberRe.exec(string.substring(i));
+    return n ? (date.W = +n[0], i + n[0].length) : -1;
+  }
+  function d3_time_parseFullYear(date, string, i) {
+    d3_time_numberRe.lastIndex = 0;
+    var n = d3_time_numberRe.exec(string.substring(i, i + 4));
+    return n ? (date.y = +n[0], i + n[0].length) : -1;
+  }
+  function d3_time_parseYear(date, string, i) {
+    d3_time_numberRe.lastIndex = 0;
+    var n = d3_time_numberRe.exec(string.substring(i, i + 2));
+    return n ? (date.y = d3_time_expandYear(+n[0]), i + n[0].length) : -1;
+  }
+  function d3_time_parseZone(date, string, i) {
+    return /^[+-]\d{4}$/.test(string = string.substring(i, i + 5)) ? (date.Z = +string, 
+    i + 5) : -1;
+  }
+  function d3_time_expandYear(d) {
+    return d + (d > 68 ? 1900 : 2e3);
+  }
+  function d3_time_parseMonthNumber(date, string, i) {
+    d3_time_numberRe.lastIndex = 0;
+    var n = d3_time_numberRe.exec(string.substring(i, i + 2));
+    return n ? (date.m = n[0] - 1, i + n[0].length) : -1;
+  }
+  function d3_time_parseDay(date, string, i) {
+    d3_time_numberRe.lastIndex = 0;
+    var n = d3_time_numberRe.exec(string.substring(i, i + 2));
+    return n ? (date.d = +n[0], i + n[0].length) : -1;
+  }
+  function d3_time_parseDayOfYear(date, string, i) {
+    d3_time_numberRe.lastIndex = 0;
+    var n = d3_time_numberRe.exec(string.substring(i, i + 3));
+    return n ? (date.j = +n[0], i + n[0].length) : -1;
+  }
+  function d3_time_parseHour24(date, string, i) {
+    d3_time_numberRe.lastIndex = 0;
+    var n = d3_time_numberRe.exec(string.substring(i, i + 2));
+    return n ? (date.H = +n[0], i + n[0].length) : -1;
+  }
+  function d3_time_parseMinutes(date, string, i) {
+    d3_time_numberRe.lastIndex = 0;
+    var n = d3_time_numberRe.exec(string.substring(i, i + 2));
+    return n ? (date.M = +n[0], i + n[0].length) : -1;
+  }
+  function d3_time_parseSeconds(date, string, i) {
+    d3_time_numberRe.lastIndex = 0;
+    var n = d3_time_numberRe.exec(string.substring(i, i + 2));
+    return n ? (date.S = +n[0], i + n[0].length) : -1;
+  }
+  function d3_time_parseMilliseconds(date, string, i) {
+    d3_time_numberRe.lastIndex = 0;
+    var n = d3_time_numberRe.exec(string.substring(i, i + 3));
+    return n ? (date.L = +n[0], i + n[0].length) : -1;
+  }
+  function d3_time_zone(d) {
+    var z = d.getTimezoneOffset(), zs = z > 0 ? "-" : "+", zh = ~~(abs(z) / 60), zm = abs(z) % 60;
+    return zs + d3_time_formatPad(zh, "0", 2) + d3_time_formatPad(zm, "0", 2);
+  }
+  function d3_time_parseLiteralPercent(date, string, i) {
+    d3_time_percentRe.lastIndex = 0;
+    var n = d3_time_percentRe.exec(string.substring(i, i + 1));
+    return n ? i + n[0].length : -1;
+  }
+  function d3_time_formatMulti(formats) {
+    var n = formats.length, i = -1;
+    while (++i < n) formats[i][0] = this(formats[i][0]);
+    return function(date) {
+      var i = 0, f = formats[i];
+      while (!f[1](date)) f = formats[++i];
+      return f[0](date);
+    };
+  }
+  d3.locale = function(locale) {
+    return {
+      numberFormat: d3_locale_numberFormat(locale),
+      timeFormat: d3_locale_timeFormat(locale)
+    };
+  };
+  var d3_locale_enUS = d3.locale({
+    decimal: ".",
+    thousands: ",",
+    grouping: [ 3 ],
+    currency: [ "$", "" ],
+    dateTime: "%a %b %e %X %Y",
+    date: "%m/%d/%Y",
+    time: "%H:%M:%S",
+    periods: [ "AM", "PM" ],
+    days: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ],
+    shortDays: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ],
+    months: [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ],
+    shortMonths: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ]
+  });
+  d3.format = d3_locale_enUS.numberFormat;
+  d3.geo = {};
+  function d3_adder() {}
+  d3_adder.prototype = {
+    s: 0,
+    t: 0,
+    add: function(y) {
+      d3_adderSum(y, this.t, d3_adderTemp);
+      d3_adderSum(d3_adderTemp.s, this.s, this);
+      if (this.s) this.t += d3_adderTemp.t; else this.s = d3_adderTemp.t;
+    },
+    reset: function() {
+      this.s = this.t = 0;
+    },
+    valueOf: function() {
+      return this.s;
+    }
+  };
+  var d3_adderTemp = new d3_adder();
+  function d3_adderSum(a, b, o) {
+    var x = o.s = a + b, bv = x - a, av = x - bv;
+    o.t = a - av + (b - bv);
+  }
+  d3.geo.stream = function(object, listener) {
+    if (object && d3_geo_streamObjectType.hasOwnProperty(object.type)) {
+      d3_geo_streamObjectType[object.type](object, listener);
+    } else {
+      d3_geo_streamGeometry(object, listener);
+    }
+  };
+  function d3_geo_streamGeometry(geometry, listener) {
+    if (geometry && d3_geo_streamGeometryType.hasOwnProperty(geometry.type)) {
+      d3_geo_streamGeometryType[geometry.type](geometry, listener);
+    }
+  }
+  var d3_geo_streamObjectType = {
+    Feature: function(feature, listener) {
+      d3_geo_streamGeometry(feature.geometry, listener);
+    },
+    FeatureCollection: function(object, listener) {
+      var features = object.features, i = -1, n = features.length;
+      while (++i < n) d3_geo_streamGeometry(features[i].geometry, listener);
+    }
+  };
+  var d3_geo_streamGeometryType = {
+    Sphere: function(object, listener) {
+      listener.sphere();
+    },
+    Point: function(object, listener) {
+      object = object.coordinates;
+      listener.point(object[0], object[1], object[2]);
+    },
+    MultiPoint: function(object, listener) {
+      var coordinates = object.coordinates, i = -1, n = coordinates.length;
+      while (++i < n) object = coordinates[i], listener.point(object[0], object[1], object[2]);
+    },
+    LineString: function(object, listener) {
+      d3_geo_streamLine(object.coordinates, listener, 0);
+    },
+    MultiLineString: function(object, listener) {
+      var coordinates = object.coordinates, i = -1, n = coordinates.length;
+      while (++i < n) d3_geo_streamLine(coordinates[i], listener, 0);
+    },
+    Polygon: function(object, listener) {
+      d3_geo_streamPolygon(object.coordinates, listener);
+    },
+    MultiPolygon: function(object, listener) {
+      var coordinates = object.coordinates, i = -1, n = coordinates.length;
+      while (++i < n) d3_geo_streamPolygon(coordinates[i], listener);
+    },
+    GeometryCollection: function(object, listener) {
+      var geometries = object.geometries, i = -1, n = geometries.length;
+      while (++i < n) d3_geo_streamGeometry(geometries[i], listener);
+    }
+  };
+  function d3_geo_streamLine(coordinates, listener, closed) {
+    var i = -1, n = coordinates.length - closed, coordinate;
+    listener.lineStart();
+    while (++i < n) coordinate = coordinates[i], listener.point(coordinate[0], coordinate[1], coordinate[2]);
+    listener.lineEnd();
+  }
+  function d3_geo_streamPolygon(coordinates, listener) {
+    var i = -1, n = coordinates.length;
+    listener.polygonStart();
+    while (++i < n) d3_geo_streamLine(coordinates[i], listener, 1);
+    listener.polygonEnd();
+  }
+  d3.geo.area = function(object) {
+    d3_geo_areaSum = 0;
+    d3.geo.stream(object, d3_geo_area);
+    return d3_geo_areaSum;
+  };
+  var d3_geo_areaSum, d3_geo_areaRingSum = new d3_adder();
+  var d3_geo_area = {
+    sphere: function() {
+      d3_geo_areaSum += 4 * π;
+    },
+    point: d3_noop,
+    lineStart: d3_noop,
+    lineEnd: d3_noop,
+    polygonStart: function() {
+      d3_geo_areaRingSum.reset();
+      d3_geo_area.lineStart = d3_geo_areaRingStart;
+    },
+    polygonEnd: function() {
+      var area = 2 * d3_geo_areaRingSum;
+      d3_geo_areaSum += area < 0 ? 4 * π + area : area;
+      d3_geo_area.lineStart = d3_geo_area.lineEnd = d3_geo_area.point = d3_noop;
+    }
+  };
+  function d3_geo_areaRingStart() {
+    var λ00, φ00, λ0, cosφ0, sinφ0;
+    d3_geo_area.point = function(λ, φ) {
+      d3_geo_area.point = nextPoint;
+      λ0 = (λ00 = λ) * d3_radians, cosφ0 = Math.cos(φ = (φ00 = φ) * d3_radians / 2 + π / 4), 
+      sinφ0 = Math.sin(φ);
+    };
+    function nextPoint(λ, φ) {
+      λ *= d3_radians;
+      φ = φ * d3_radians / 2 + π / 4;
+      var dλ = λ - λ0, sdλ = dλ >= 0 ? 1 : -1, adλ = sdλ * dλ, cosφ = Math.cos(φ), sinφ = Math.sin(φ), k = sinφ0 * sinφ, u = cosφ0 * cosφ + k * Math.cos(adλ), v = k * sdλ * Math.sin(adλ);
+      d3_geo_areaRingSum.add(Math.atan2(v, u));
+      λ0 = λ, cosφ0 = cosφ, sinφ0 = sinφ;
+    }
+    d3_geo_area.lineEnd = function() {
+      nextPoint(λ00, φ00);
+    };
+  }
+  function d3_geo_cartesian(spherical) {
+    var λ = spherical[0], φ = spherical[1], cosφ = Math.cos(φ);
+    return [ cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ) ];
+  }
+  function d3_geo_cartesianDot(a, b) {
+    return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
+  }
+  function d3_geo_cartesianCross(a, b) {
+    return [ a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0] ];
+  }
+  function d3_geo_cartesianAdd(a, b) {
+    a[0] += b[0];
+    a[1] += b[1];
+    a[2] += b[2];
+  }
+  function d3_geo_cartesianScale(vector, k) {
+    return [ vector[0] * k, vector[1] * k, vector[2] * k ];
+  }
+  function d3_geo_cartesianNormalize(d) {
+    var l = Math.sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);
+    d[0] /= l;
+    d[1] /= l;
+    d[2] /= l;
+  }
+  function d3_geo_spherical(cartesian) {
+    return [ Math.atan2(cartesian[1], cartesian[0]), d3_asin(cartesian[2]) ];
+  }
+  function d3_geo_sphericalEqual(a, b) {
+    return abs(a[0] - b[0]) < ε && abs(a[1] - b[1]) < ε;
+  }
+  d3.geo.bounds = function() {
+    var λ0, φ0, λ1, φ1, λ_, λ__, φ__, p0, dλSum, ranges, range;
+    var bound = {
+      point: point,
+      lineStart: lineStart,
+      lineEnd: lineEnd,
+      polygonStart: function() {
+        bound.point = ringPoint;
+        bound.lineStart = ringStart;
+        bound.lineEnd = ringEnd;
+        dλSum = 0;
+        d3_geo_area.polygonStart();
+      },
+      polygonEnd: function() {
+        d3_geo_area.polygonEnd();
+        bound.point = point;
+        bound.lineStart = lineStart;
+        bound.lineEnd = lineEnd;
+        if (d3_geo_areaRingSum < 0) λ0 = -(λ1 = 180), φ0 = -(φ1 = 90); else if (dλSum > ε) φ1 = 90; else if (dλSum < -ε) φ0 = -90;
+        range[0] = λ0, range[1] = λ1;
+      }
+    };
+    function point(λ, φ) {
+      ranges.push(range = [ λ0 = λ, λ1 = λ ]);
+      if (φ < φ0) φ0 = φ;
+      if (φ > φ1) φ1 = φ;
+    }
+    function linePoint(λ, φ) {
+      var p = d3_geo_cartesian([ λ * d3_radians, φ * d3_radians ]);
+      if (p0) {
+        var normal = d3_geo_cartesianCross(p0, p), equatorial = [ normal[1], -normal[0], 0 ], inflection = d3_geo_cartesianCross(equatorial, normal);
+        d3_geo_cartesianNormalize(inflection);
+        inflection = d3_geo_spherical(inflection);
+        var dλ = λ - λ_, s = dλ > 0 ? 1 : -1, λi = inflection[0] * d3_degrees * s, antimeridian = abs(dλ) > 180;
+        if (antimeridian ^ (s * λ_ < λi && λi < s * λ)) {
+          var φi = inflection[1] * d3_degrees;
+          if (φi > φ1) φ1 = φi;
+        } else if (λi = (λi + 360) % 360 - 180, antimeridian ^ (s * λ_ < λi && λi < s * λ)) {
+          var φi = -inflection[1] * d3_degrees;
+          if (φi < φ0) φ0 = φi;
+        } else {
+          if (φ < φ0) φ0 = φ;
+          if (φ > φ1) φ1 = φ;
+        }
+        if (antimeridian) {
+          if (λ < λ_) {
+            if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ;
+          } else {
+            if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ;
+          }
+        } else {
+          if (λ1 >= λ0) {
+            if (λ < λ0) λ0 = λ;
+            if (λ > λ1) λ1 = λ;
+          } else {
+            if (λ > λ_) {
+              if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ;
+            } else {
+              if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ;
+            }
+          }
+        }
+      } else {
+        point(λ, φ);
+      }
+      p0 = p, λ_ = λ;
+    }
+    function lineStart() {
+      bound.point = linePoint;
+    }
+    function lineEnd() {
+      range[0] = λ0, range[1] = λ1;
+      bound.point = point;
+      p0 = null;
+    }
+    function ringPoint(λ, φ) {
+      if (p0) {
+        var dλ = λ - λ_;
+        dλSum += abs(dλ) > 180 ? dλ + (dλ > 0 ? 360 : -360) : dλ;
+      } else λ__ = λ, φ__ = φ;
+      d3_geo_area.point(λ, φ);
+      linePoint(λ, φ);
+    }
+    function ringStart() {
+      d3_geo_area.lineStart();
+    }
+    function ringEnd() {
+      ringPoint(λ__, φ__);
+      d3_geo_area.lineEnd();
+      if (abs(dλSum) > ε) λ0 = -(λ1 = 180);
+      range[0] = λ0, range[1] = λ1;
+      p0 = null;
+    }
+    function angle(λ0, λ1) {
+      return (λ1 -= λ0) < 0 ? λ1 + 360 : λ1;
+    }
+    function compareRanges(a, b) {
+      return a[0] - b[0];
+    }
+    function withinRange(x, range) {
+      return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x;
+    }
+    return function(feature) {
+      φ1 = λ1 = -(λ0 = φ0 = Infinity);
+      ranges = [];
+      d3.geo.stream(feature, bound);
+      var n = ranges.length;
+      if (n) {
+        ranges.sort(compareRanges);
+        for (var i = 1, a = ranges[0], b, merged = [ a ]; i < n; ++i) {
+          b = ranges[i];
+          if (withinRange(b[0], a) || withinRange(b[1], a)) {
+            if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1];
+            if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0];
+          } else {
+            merged.push(a = b);
+          }
+        }
+        var best = -Infinity, dλ;
+        for (var n = merged.length - 1, i = 0, a = merged[n], b; i <= n; a = b, ++i) {
+          b = merged[i];
+          if ((dλ = angle(a[1], b[0])) > best) best = dλ, λ0 = b[0], λ1 = a[1];
+        }
+      }
+      ranges = range = null;
+      return λ0 === Infinity || φ0 === Infinity ? [ [ NaN, NaN ], [ NaN, NaN ] ] : [ [ λ0, φ0 ], [ λ1, φ1 ] ];
+    };
+  }();
+  d3.geo.centroid = function(object) {
+    d3_geo_centroidW0 = d3_geo_centroidW1 = d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0;
+    d3.geo.stream(object, d3_geo_centroid);
+    var x = d3_geo_centroidX2, y = d3_geo_centroidY2, z = d3_geo_centroidZ2, m = x * x + y * y + z * z;
+    if (m < ε2) {
+      x = d3_geo_centroidX1, y = d3_geo_centroidY1, z = d3_geo_centroidZ1;
+      if (d3_geo_centroidW1 < ε) x = d3_geo_centroidX0, y = d3_geo_centroidY0, z = d3_geo_centroidZ0;
+      m = x * x + y * y + z * z;
+      if (m < ε2) return [ NaN, NaN ];
+    }
+    return [ Math.atan2(y, x) * d3_degrees, d3_asin(z / Math.sqrt(m)) * d3_degrees ];
+  };
+  var d3_geo_centroidW0, d3_geo_centroidW1, d3_geo_centroidX0, d3_geo_centroidY0, d3_geo_centroidZ0, d3_geo_centroidX1, d3_geo_centroidY1, d3_geo_centroidZ1, d3_geo_centroidX2, d3_geo_centroidY2, d3_geo_centroidZ2;
+  var d3_geo_centroid = {
+    sphere: d3_noop,
+    point: d3_geo_centroidPoint,
+    lineStart: d3_geo_centroidLineStart,
+    lineEnd: d3_geo_centroidLineEnd,
+    polygonStart: function() {
+      d3_geo_centroid.lineStart = d3_geo_centroidRingStart;
+    },
+    polygonEnd: function() {
+      d3_geo_centroid.lineStart = d3_geo_centroidLineStart;
+    }
+  };
+  function d3_geo_centroidPoint(λ, φ) {
+    λ *= d3_radians;
+    var cosφ = Math.cos(φ *= d3_radians);
+    d3_geo_centroidPointXYZ(cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ));
+  }
+  function d3_geo_centroidPointXYZ(x, y, z) {
+    ++d3_geo_centroidW0;
+    d3_geo_centroidX0 += (x - d3_geo_centroidX0) / d3_geo_centroidW0;
+    d3_geo_centroidY0 += (y - d3_geo_centroidY0) / d3_geo_centroidW0;
+    d3_geo_centroidZ0 += (z - d3_geo_centroidZ0) / d3_geo_centroidW0;
+  }
+  function d3_geo_centroidLineStart() {
+    var x0, y0, z0;
+    d3_geo_centroid.point = function(λ, φ) {
+      λ *= d3_radians;
+      var cosφ = Math.cos(φ *= d3_radians);
+      x0 = cosφ * Math.cos(λ);
+      y0 = cosφ * Math.sin(λ);
+      z0 = Math.sin(φ);
+      d3_geo_centroid.point = nextPoint;
+      d3_geo_centroidPointXYZ(x0, y0, z0);
+    };
+    function nextPoint(λ, φ) {
+      λ *= d3_radians;
+      var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), w = Math.atan2(Math.sqrt((w = y0 * z - z0 * y) * w + (w = z0 * x - x0 * z) * w + (w = x0 * y - y0 * x) * w), x0 * x + y0 * y + z0 * z);
+      d3_geo_centroidW1 += w;
+      d3_geo_centroidX1 += w * (x0 + (x0 = x));
+      d3_geo_centroidY1 += w * (y0 + (y0 = y));
+      d3_geo_centroidZ1 += w * (z0 + (z0 = z));
+      d3_geo_centroidPointXYZ(x0, y0, z0);
+    }
+  }
+  function d3_geo_centroidLineEnd() {
+    d3_geo_centroid.point = d3_geo_centroidPoint;
+  }
+  function d3_geo_centroidRingStart() {
+    var λ00, φ00, x0, y0, z0;
+    d3_geo_centroid.point = function(λ, φ) {
+      λ00 = λ, φ00 = φ;
+      d3_geo_centroid.point = nextPoint;
+      λ *= d3_radians;
+      var cosφ = Math.cos(φ *= d3_radians);
+      x0 = cosφ * Math.cos(λ);
+      y0 = cosφ * Math.sin(λ);
+      z0 = Math.sin(φ);
+      d3_geo_centroidPointXYZ(x0, y0, z0);
+    };
+    d3_geo_centroid.lineEnd = function() {
+      nextPoint(λ00, φ00);
+      d3_geo_centroid.lineEnd = d3_geo_centroidLineEnd;
+      d3_geo_centroid.point = d3_geo_centroidPoint;
+    };
+    function nextPoint(λ, φ) {
+      λ *= d3_radians;
+      var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), cx = y0 * z - z0 * y, cy = z0 * x - x0 * z, cz = x0 * y - y0 * x, m = Math.sqrt(cx * cx + cy * cy + cz * cz), u = x0 * x + y0 * y + z0 * z, v = m && -d3_acos(u) / m, w = Math.atan2(m, u);
+      d3_geo_centroidX2 += v * cx;
+      d3_geo_centroidY2 += v * cy;
+      d3_geo_centroidZ2 += v * cz;
+      d3_geo_centroidW1 += w;
+      d3_geo_centroidX1 += w * (x0 + (x0 = x));
+      d3_geo_centroidY1 += w * (y0 + (y0 = y));
+      d3_geo_centroidZ1 += w * (z0 + (z0 = z));
+      d3_geo_centroidPointXYZ(x0, y0, z0);
+    }
+  }
+  function d3_true() {
+    return true;
+  }
+  function d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener) {
+    var subject = [], clip = [];
+    segments.forEach(function(segment) {
+      if ((n = segment.length - 1) <= 0) return;
+      var n, p0 = segment[0], p1 = segment[n];
+      if (d3_geo_sphericalEqual(p0, p1)) {
+        listener.lineStart();
+        for (var i = 0; i < n; ++i) listener.point((p0 = segment[i])[0], p0[1]);
+        listener.lineEnd();
+        return;
+      }
+      var a = new d3_geo_clipPolygonIntersection(p0, segment, null, true), b = new d3_geo_clipPolygonIntersection(p0, null, a, false);
+      a.o = b;
+      subject.push(a);
+      clip.push(b);
+      a = new d3_geo_clipPolygonIntersection(p1, segment, null, false);
+      b = new d3_geo_clipPolygonIntersection(p1, null, a, true);
+      a.o = b;
+      subject.push(a);
+      clip.push(b);
+    });
+    clip.sort(compare);
+    d3_geo_clipPolygonLinkCircular(subject);
+    d3_geo_clipPolygonLinkCircular(clip);
+    if (!subject.length) return;
+    for (var i = 0, entry = clipStartInside, n = clip.length; i < n; ++i) {
+      clip[i].e = entry = !entry;
+    }
+    var start = subject[0], points, point;
+    while (1) {
+      var current = start, isSubject = true;
+      while (current.v) if ((current = current.n) === start) return;
+      points = current.z;
+      listener.lineStart();
+      do {
+        current.v = current.o.v = true;
+        if (current.e) {
+          if (isSubject) {
+            for (var i = 0, n = points.length; i < n; ++i) listener.point((point = points[i])[0], point[1]);
+          } else {
+            interpolate(current.x, current.n.x, 1, listener);
+          }
+          current = current.n;
+        } else {
+          if (isSubject) {
+            points = current.p.z;
+            for (var i = points.length - 1; i >= 0; --i) listener.point((point = points[i])[0], point[1]);
+          } else {
+            interpolate(current.x, current.p.x, -1, listener);
+          }
+          current = current.p;
+        }
+        current = current.o;
+        points = current.z;
+        isSubject = !isSubject;
+      } while (!current.v);
+      listener.lineEnd();
+    }
+  }
+  function d3_geo_clipPolygonLinkCircular(array) {
+    if (!(n = array.length)) return;
+    var n, i = 0, a = array[0], b;
+    while (++i < n) {
+      a.n = b = array[i];
+      b.p = a;
+      a = b;
+    }
+    a.n = b = array[0];
+    b.p = a;
+  }
+  function d3_geo_clipPolygonIntersection(point, points, other, entry) {
+    this.x = point;
+    this.z = points;
+    this.o = other;
+    this.e = entry;
+    this.v = false;
+    this.n = this.p = null;
+  }
+  function d3_geo_clip(pointVisible, clipLine, interpolate, clipStart) {
+    return function(rotate, listener) {
+      var line = clipLine(listener), rotatedClipStart = rotate.invert(clipStart[0], clipStart[1]);
+      var clip = {
+        point: point,
+        lineStart: lineStart,
+        lineEnd: lineEnd,
+        polygonStart: function() {
+          clip.point = pointRing;
+          clip.lineStart = ringStart;
+          clip.lineEnd = ringEnd;
+          segments = [];
+          polygon = [];
+          listener.polygonStart();
+        },
+        polygonEnd: function() {
+          clip.point = point;
+          clip.lineStart = lineStart;
+          clip.lineEnd = lineEnd;
+          segments = d3.merge(segments);
+          var clipStartInside = d3_geo_pointInPolygon(rotatedClipStart, polygon);
+          if (segments.length) {
+            d3_geo_clipPolygon(segments, d3_geo_clipSort, clipStartInside, interpolate, listener);
+          } else if (clipStartInside) {
+            listener.lineStart();
+            interpolate(null, null, 1, listener);
+            listener.lineEnd();
+          }
+          listener.polygonEnd();
+          segments = polygon = null;
+        },
+        sphere: function() {
+          listener.polygonStart();
+          listener.lineStart();
+          interpolate(null, null, 1, listener);
+          listener.lineEnd();
+          listener.polygonEnd();
+        }
+      };
+      function point(λ, φ) {
+        var point = rotate(λ, φ);
+        if (pointVisible(λ = point[0], φ = point[1])) listener.point(λ, φ);
+      }
+      function pointLine(λ, φ) {
+        var point = rotate(λ, φ);
+        line.point(point[0], point[1]);
+      }
+      function lineStart() {
+        clip.point = pointLine;
+        line.lineStart();
+      }
+      function lineEnd() {
+        clip.point = point;
+        line.lineEnd();
+      }
+      var segments;
+      var buffer = d3_geo_clipBufferListener(), ringListener = clipLine(buffer), polygon, ring;
+      function pointRing(λ, φ) {
+        ring.push([ λ, φ ]);
+        var point = rotate(λ, φ);
+        ringListener.point(point[0], point[1]);
+      }
+      function ringStart() {
+        ringListener.lineStart();
+        ring = [];
+      }
+      function ringEnd() {
+        pointRing(ring[0][0], ring[0][1]);
+        ringListener.lineEnd();
+        var clean = ringListener.clean(), ringSegments = buffer.buffer(), segment, n = ringSegments.length;
+        ring.pop();
+        polygon.push(ring);
+        ring = null;
+        if (!n) return;
+        if (clean & 1) {
+          segment = ringSegments[0];
+          var n = segment.length - 1, i = -1, point;
+          listener.lineStart();
+          while (++i < n) listener.point((point = segment[i])[0], point[1]);
+          listener.lineEnd();
+          return;
+        }
+        if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift()));
+        segments.push(ringSegments.filter(d3_geo_clipSegmentLength1));
+      }
+      return clip;
+    };
+  }
+  function d3_geo_clipSegmentLength1(segment) {
+    return segment.length > 1;
+  }
+  function d3_geo_clipBufferListener() {
+    var lines = [], line;
+    return {
+      lineStart: function() {
+        lines.push(line = []);
+      },
+      point: function(λ, φ) {
+        line.push([ λ, φ ]);
+      },
+      lineEnd: d3_noop,
+      buffer: function() {
+        var buffer = lines;
+        lines = [];
+        line = null;
+        return buffer;
+      },
+      rejoin: function() {
+        if (lines.length > 1) lines.push(lines.pop().concat(lines.shift()));
+      }
+    };
+  }
+  function d3_geo_clipSort(a, b) {
+    return ((a = a.x)[0] < 0 ? a[1] - halfπ - ε : halfπ - a[1]) - ((b = b.x)[0] < 0 ? b[1] - halfπ - ε : halfπ - b[1]);
+  }
+  function d3_geo_pointInPolygon(point, polygon) {
+    var meridian = point[0], parallel = point[1], meridianNormal = [ Math.sin(meridian), -Math.cos(meridian), 0 ], polarAngle = 0, winding = 0;
+    d3_geo_areaRingSum.reset();
+    for (var i = 0, n = polygon.length; i < n; ++i) {
+      var ring = polygon[i], m = ring.length;
+      if (!m) continue;
+      var point0 = ring[0], λ0 = point0[0], φ0 = point0[1] / 2 + π / 4, sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), j = 1;
+      while (true) {
+        if (j === m) j = 0;
+        point = ring[j];
+        var λ = point[0], φ = point[1] / 2 + π / 4, sinφ = Math.sin(φ), cosφ = Math.cos(φ), dλ = λ - λ0, sdλ = dλ >= 0 ? 1 : -1, adλ = sdλ * dλ, antimeridian = adλ > π, k = sinφ0 * sinφ;
+        d3_geo_areaRingSum.add(Math.atan2(k * sdλ * Math.sin(adλ), cosφ0 * cosφ + k * Math.cos(adλ)));
+        polarAngle += antimeridian ? dλ + sdλ * τ : dλ;
+        if (antimeridian ^ λ0 >= meridian ^ λ >= meridian) {
+          var arc = d3_geo_cartesianCross(d3_geo_cartesian(point0), d3_geo_cartesian(point));
+          d3_geo_cartesianNormalize(arc);
+          var intersection = d3_geo_cartesianCross(meridianNormal, arc);
+          d3_geo_cartesianNormalize(intersection);
+          var φarc = (antimeridian ^ dλ >= 0 ? -1 : 1) * d3_asin(intersection[2]);
+          if (parallel > φarc || parallel === φarc && (arc[0] || arc[1])) {
+            winding += antimeridian ^ dλ >= 0 ? 1 : -1;
+          }
+        }
+        if (!j++) break;
+        λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ, point0 = point;
+      }
+    }
+    return (polarAngle < -ε || polarAngle < ε && d3_geo_areaRingSum < 0) ^ winding & 1;
+  }
+  var d3_geo_clipAntimeridian = d3_geo_clip(d3_true, d3_geo_clipAntimeridianLine, d3_geo_clipAntimeridianInterpolate, [ -π, -π / 2 ]);
+  function d3_geo_clipAntimeridianLine(listener) {
+    var λ0 = NaN, φ0 = NaN, sλ0 = NaN, clean;
+    return {
+      lineStart: function() {
+        listener.lineStart();
+        clean = 1;
+      },
+      point: function(λ1, φ1) {
+        var sλ1 = λ1 > 0 ? π : -π, dλ = abs(λ1 - λ0);
+        if (abs(dλ - π) < ε) {
+          listener.point(λ0, φ0 = (φ0 + φ1) / 2 > 0 ? halfπ : -halfπ);
+          listener.point(sλ0, φ0);
+          listener.lineEnd();
+          listener.lineStart();
+          listener.point(sλ1, φ0);
+          listener.point(λ1, φ0);
+          clean = 0;
+        } else if (sλ0 !== sλ1 && dλ >= π) {
+          if (abs(λ0 - sλ0) < ε) λ0 -= sλ0 * ε;
+          if (abs(λ1 - sλ1) < ε) λ1 -= sλ1 * ε;
+          φ0 = d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1);
+          listener.point(sλ0, φ0);
+          listener.lineEnd();
+          listener.lineStart();
+          listener.point(sλ1, φ0);
+          clean = 0;
+        }
+        listener.point(λ0 = λ1, φ0 = φ1);
+        sλ0 = sλ1;
+      },
+      lineEnd: function() {
+        listener.lineEnd();
+        λ0 = φ0 = NaN;
+      },
+      clean: function() {
+        return 2 - clean;
+      }
+    };
+  }
+  function d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1) {
+    var cosφ0, cosφ1, sinλ0_λ1 = Math.sin(λ0 - λ1);
+    return abs(sinλ0_λ1) > ε ? Math.atan((Math.sin(φ0) * (cosφ1 = Math.cos(φ1)) * Math.sin(λ1) - Math.sin(φ1) * (cosφ0 = Math.cos(φ0)) * Math.sin(λ0)) / (cosφ0 * cosφ1 * sinλ0_λ1)) : (φ0 + φ1) / 2;
+  }
+  function d3_geo_clipAntimeridianInterpolate(from, to, direction, listener) {
+    var φ;
+    if (from == null) {
+      φ = direction * halfπ;
+      listener.point(-π, φ);
+      listener.point(0, φ);
+      listener.point(π, φ);
+      listener.point(π, 0);
+      listener.point(π, -φ);
+      listener.point(0, -φ);
+      listener.point(-π, -φ);
+      listener.point(-π, 0);
+      listener.point(-π, φ);
+    } else if (abs(from[0] - to[0]) > ε) {
+      var s = from[0] < to[0] ? π : -π;
+      φ = direction * s / 2;
+      listener.point(-s, φ);
+      listener.point(0, φ);
+      listener.point(s, φ);
+    } else {
+      listener.point(to[0], to[1]);
+    }
+  }
+  function d3_geo_clipCircle(radius) {
+    var cr = Math.cos(radius), smallRadius = cr > 0, notHemisphere = abs(cr) > ε, interpolate = d3_geo_circleInterpolate(radius, 6 * d3_radians);
+    return d3_geo_clip(visible, clipLine, interpolate, smallRadius ? [ 0, -radius ] : [ -π, radius - π ]);
+    function visible(λ, φ) {
+      return Math.cos(λ) * Math.cos(φ) > cr;
+    }
+    function clipLine(listener) {
+      var point0, c0, v0, v00, clean;
+      return {
+        lineStart: function() {
+          v00 = v0 = false;
+          clean = 1;
+        },
+        point: function(λ, φ) {
+          var point1 = [ λ, φ ], point2, v = visible(λ, φ), c = smallRadius ? v ? 0 : code(λ, φ) : v ? code(λ + (λ < 0 ? π : -π), φ) : 0;
+          if (!point0 && (v00 = v0 = v)) listener.lineStart();
+          if (v !== v0) {
+            point2 = intersect(point0, point1);
+            if (d3_geo_sphericalEqual(point0, point2) || d3_geo_sphericalEqual(point1, point2)) {
+              point1[0] += ε;
+              point1[1] += ε;
+              v = visible(point1[0], point1[1]);
+            }
+          }
+          if (v !== v0) {
+            clean = 0;
+            if (v) {
+              listener.lineStart();
+              point2 = intersect(point1, point0);
+              listener.point(point2[0], point2[1]);
+            } else {
+              point2 = intersect(point0, point1);
+              listener.point(point2[0], point2[1]);
+              listener.lineEnd();
+            }
+            point0 = point2;
+          } else if (notHemisphere && point0 && smallRadius ^ v) {
+            var t;
+            if (!(c & c0) && (t = intersect(point1, point0, true))) {
+              clean = 0;
+              if (smallRadius) {
+                listener.lineStart();
+                listener.point(t[0][0], t[0][1]);
+                listener.point(t[1][0], t[1][1]);
+                listener.lineEnd();
+              } else {
+                listener.point(t[1][0], t[1][1]);
+                listener.lineEnd();
+                listener.lineStart();
+                listener.point(t[0][0], t[0][1]);
+              }
+            }
+          }
+          if (v && (!point0 || !d3_geo_sphericalEqual(point0, point1))) {
+            listener.point(point1[0], point1[1]);
+          }
+          point0 = point1, v0 = v, c0 = c;
+        },
+        lineEnd: function() {
+          if (v0) listener.lineEnd();
+          point0 = null;
+        },
+        clean: function() {
+          return clean | (v00 && v0) << 1;
+        }
+      };
+    }
+    function intersect(a, b, two) {
+      var pa = d3_geo_cartesian(a), pb = d3_geo_cartesian(b);
+      var n1 = [ 1, 0, 0 ], n2 = d3_geo_cartesianCross(pa, pb), n2n2 = d3_geo_cartesianDot(n2, n2), n1n2 = n2[0], determinant = n2n2 - n1n2 * n1n2;
+      if (!determinant) return !two && a;
+      var c1 = cr * n2n2 / determinant, c2 = -cr * n1n2 / determinant, n1xn2 = d3_geo_cartesianCross(n1, n2), A = d3_geo_cartesianScale(n1, c1), B = d3_geo_cartesianScale(n2, c2);
+      d3_geo_cartesianAdd(A, B);
+      var u = n1xn2, w = d3_geo_cartesianDot(A, u), uu = d3_geo_cartesianDot(u, u), t2 = w * w - uu * (d3_geo_cartesianDot(A, A) - 1);
+      if (t2 < 0) return;
+      var t = Math.sqrt(t2), q = d3_geo_cartesianScale(u, (-w - t) / uu);
+      d3_geo_cartesianAdd(q, A);
+      q = d3_geo_spherical(q);
+      if (!two) return q;
+      var λ0 = a[0], λ1 = b[0], φ0 = a[1], φ1 = b[1], z;
+      if (λ1 < λ0) z = λ0, λ0 = λ1, λ1 = z;
+      var δλ = λ1 - λ0, polar = abs(δλ - π) < ε, meridian = polar || δλ < ε;
+      if (!polar && φ1 < φ0) z = φ0, φ0 = φ1, φ1 = z;
+      if (meridian ? polar ? φ0 + φ1 > 0 ^ q[1] < (abs(q[0] - λ0) < ε ? φ0 : φ1) : φ0 <= q[1] && q[1] <= φ1 : δλ > π ^ (λ0 <= q[0] && q[0] <= λ1)) {
+        var q1 = d3_geo_cartesianScale(u, (-w + t) / uu);
+        d3_geo_cartesianAdd(q1, A);
+        return [ q, d3_geo_spherical(q1) ];
+      }
+    }
+    function code(λ, φ) {
+      var r = smallRadius ? radius : π - radius, code = 0;
+      if (λ < -r) code |= 1; else if (λ > r) code |= 2;
+      if (φ < -r) code |= 4; else if (φ > r) code |= 8;
+      return code;
+    }
+  }
+  function d3_geom_clipLine(x0, y0, x1, y1) {
+    return function(line) {
+      var a = line.a, b = line.b, ax = a.x, ay = a.y, bx = b.x, by = b.y, t0 = 0, t1 = 1, dx = bx - ax, dy = by - ay, r;
+      r = x0 - ax;
+      if (!dx && r > 0) return;
+      r /= dx;
+      if (dx < 0) {
+        if (r < t0) return;
+        if (r < t1) t1 = r;
+      } else if (dx > 0) {
+        if (r > t1) return;
+        if (r > t0) t0 = r;
+      }
+      r = x1 - ax;
+      if (!dx && r < 0) return;
+      r /= dx;
+      if (dx < 0) {
+        if (r > t1) return;
+        if (r > t0) t0 = r;
+      } else if (dx > 0) {
+        if (r < t0) return;
+        if (r < t1) t1 = r;
+      }
+      r = y0 - ay;
+      if (!dy && r > 0) return;
+      r /= dy;
+      if (dy < 0) {
+        if (r < t0) return;
+        if (r < t1) t1 = r;
+      } else if (dy > 0) {
+        if (r > t1) return;
+        if (r > t0) t0 = r;
+      }
+      r = y1 - ay;
+      if (!dy && r < 0) return;
+      r /= dy;
+      if (dy < 0) {
+        if (r > t1) return;
+        if (r > t0) t0 = r;
+      } else if (dy > 0) {
+        if (r < t0) return;
+        if (r < t1) t1 = r;
+      }
+      if (t0 > 0) line.a = {
+        x: ax + t0 * dx,
+        y: ay + t0 * dy
+      };
+      if (t1 < 1) line.b = {
+        x: ax + t1 * dx,
+        y: ay + t1 * dy
+      };
+      return line;
+    };
+  }
+  var d3_geo_clipExtentMAX = 1e9;
+  d3.geo.clipExtent = function() {
+    var x0, y0, x1, y1, stream, clip, clipExtent = {
+      stream: function(output) {
+        if (stream) stream.valid = false;
+        stream = clip(output);
+        stream.valid = true;
+        return stream;
+      },
+      extent: function(_) {
+        if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ];
+        clip = d3_geo_clipExtent(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]);
+        if (stream) stream.valid = false, stream = null;
+        return clipExtent;
+      }
+    };
+    return clipExtent.extent([ [ 0, 0 ], [ 960, 500 ] ]);
+  };
+  function d3_geo_clipExtent(x0, y0, x1, y1) {
+    return function(listener) {
+      var listener_ = listener, bufferListener = d3_geo_clipBufferListener(), clipLine = d3_geom_clipLine(x0, y0, x1, y1), segments, polygon, ring;
+      var clip = {
+        point: point,
+        lineStart: lineStart,
+        lineEnd: lineEnd,
+        polygonStart: function() {
+          listener = bufferListener;
+          segments = [];
+          polygon = [];
+          clean = true;
+        },
+        polygonEnd: function() {
+          listener = listener_;
+          segments = d3.merge(segments);
+          var clipStartInside = insidePolygon([ x0, y1 ]), inside = clean && clipStartInside, visible = segments.length;
+          if (inside || visible) {
+            listener.polygonStart();
+            if (inside) {
+              listener.lineStart();
+              interpolate(null, null, 1, listener);
+              listener.lineEnd();
+            }
+            if (visible) {
+              d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener);
+            }
+            listener.polygonEnd();
+          }
+          segments = polygon = ring = null;
+        }
+      };
+      function insidePolygon(p) {
+        var wn = 0, n = polygon.length, y = p[1];
+        for (var i = 0; i < n; ++i) {
+          for (var j = 1, v = polygon[i], m = v.length, a = v[0], b; j < m; ++j) {
+            b = v[j];
+            if (a[1] <= y) {
+              if (b[1] > y && d3_cross2d(a, b, p) > 0) ++wn;
+            } else {
+              if (b[1] <= y && d3_cross2d(a, b, p) < 0) --wn;
+            }
+            a = b;
+          }
+        }
+        return wn !== 0;
+      }
+      function interpolate(from, to, direction, listener) {
+        var a = 0, a1 = 0;
+        if (from == null || (a = corner(from, direction)) !== (a1 = corner(to, direction)) || comparePoints(from, to) < 0 ^ direction > 0) {
+          do {
+            listener.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0);
+          } while ((a = (a + direction + 4) % 4) !== a1);
+        } else {
+          listener.point(to[0], to[1]);
+        }
+      }
+      function pointVisible(x, y) {
+        return x0 <= x && x <= x1 && y0 <= y && y <= y1;
+      }
+      function point(x, y) {
+        if (pointVisible(x, y)) listener.point(x, y);
+      }
+      var x__, y__, v__, x_, y_, v_, first, clean;
+      function lineStart() {
+        clip.point = linePoint;
+        if (polygon) polygon.push(ring = []);
+        first = true;
+        v_ = false;
+        x_ = y_ = NaN;
+      }
+      function lineEnd() {
+        if (segments) {
+          linePoint(x__, y__);
+          if (v__ && v_) bufferListener.rejoin();
+          segments.push(bufferListener.buffer());
+        }
+        clip.point = point;
+        if (v_) listener.lineEnd();
+      }
+      function linePoint(x, y) {
+        x = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, x));
+        y = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, y));
+        var v = pointVisible(x, y);
+        if (polygon) ring.push([ x, y ]);
+        if (first) {
+          x__ = x, y__ = y, v__ = v;
+          first = false;
+          if (v) {
+            listener.lineStart();
+            listener.point(x, y);
+          }
+        } else {
+          if (v && v_) listener.point(x, y); else {
+            var l = {
+              a: {
+                x: x_,
+                y: y_
+              },
+              b: {
+                x: x,
+                y: y
+              }
+            };
+            if (clipLine(l)) {
+              if (!v_) {
+                listener.lineStart();
+                listener.point(l.a.x, l.a.y);
+              }
+              listener.point(l.b.x, l.b.y);
+              if (!v) listener.lineEnd();
+              clean = false;
+            } else if (v) {
+              listener.lineStart();
+              listener.point(x, y);
+              clean = false;
+            }
+          }
+        }
+        x_ = x, y_ = y, v_ = v;
+      }
+      return clip;
+    };
+    function corner(p, direction) {
+      return abs(p[0] - x0) < ε ? direction > 0 ? 0 : 3 : abs(p[0] - x1) < ε ? direction > 0 ? 2 : 1 : abs(p[1] - y0) < ε ? direction > 0 ? 1 : 0 : direction > 0 ? 3 : 2;
+    }
+    function compare(a, b) {
+      return comparePoints(a.x, b.x);
+    }
+    function comparePoints(a, b) {
+      var ca = corner(a, 1), cb = corner(b, 1);
+      return ca !== cb ? ca - cb : ca === 0 ? b[1] - a[1] : ca === 1 ? a[0] - b[0] : ca === 2 ? a[1] - b[1] : b[0] - a[0];
+    }
+  }
+  function d3_geo_compose(a, b) {
+    function compose(x, y) {
+      return x = a(x, y), b(x[0], x[1]);
+    }
+    if (a.invert && b.invert) compose.invert = function(x, y) {
+      return x = b.invert(x, y), x && a.invert(x[0], x[1]);
+    };
+    return compose;
+  }
+  function d3_geo_conic(projectAt) {
+    var φ0 = 0, φ1 = π / 3, m = d3_geo_projectionMutator(projectAt), p = m(φ0, φ1);
+    p.parallels = function(_) {
+      if (!arguments.length) return [ φ0 / π * 180, φ1 / π * 180 ];
+      return m(φ0 = _[0] * π / 180, φ1 = _[1] * π / 180);
+    };
+    return p;
+  }
+  function d3_geo_conicEqualArea(φ0, φ1) {
+    var sinφ0 = Math.sin(φ0), n = (sinφ0 + Math.sin(φ1)) / 2, C = 1 + sinφ0 * (2 * n - sinφ0), ρ0 = Math.sqrt(C) / n;
+    function forward(λ, φ) {
+      var ρ = Math.sqrt(C - 2 * n * Math.sin(φ)) / n;
+      return [ ρ * Math.sin(λ *= n), ρ0 - ρ * Math.cos(λ) ];
+    }
+    forward.invert = function(x, y) {
+      var ρ0_y = ρ0 - y;
+      return [ Math.atan2(x, ρ0_y) / n, d3_asin((C - (x * x + ρ0_y * ρ0_y) * n * n) / (2 * n)) ];
+    };
+    return forward;
+  }
+  (d3.geo.conicEqualArea = function() {
+    return d3_geo_conic(d3_geo_conicEqualArea);
+  }).raw = d3_geo_conicEqualArea;
+  d3.geo.albers = function() {
+    return d3.geo.conicEqualArea().rotate([ 96, 0 ]).center([ -.6, 38.7 ]).parallels([ 29.5, 45.5 ]).scale(1070);
+  };
+  d3.geo.albersUsa = function() {
+    var lower48 = d3.geo.albers();
+    var alaska = d3.geo.conicEqualArea().rotate([ 154, 0 ]).center([ -2, 58.5 ]).parallels([ 55, 65 ]);
+    var hawaii = d3.geo.conicEqualArea().rotate([ 157, 0 ]).center([ -3, 19.9 ]).parallels([ 8, 18 ]);
+    var point, pointStream = {
+      point: function(x, y) {
+        point = [ x, y ];
+      }
+    }, lower48Point, alaskaPoint, hawaiiPoint;
+    function albersUsa(coordinates) {
+      var x = coordinates[0], y = coordinates[1];
+      point = null;
+      (lower48Point(x, y), point) || (alaskaPoint(x, y), point) || hawaiiPoint(x, y);
+      return point;
+    }
+    albersUsa.invert = function(coordinates) {
+      var k = lower48.scale(), t = lower48.translate(), x = (coordinates[0] - t[0]) / k, y = (coordinates[1] - t[1]) / k;
+      return (y >= .12 && y < .234 && x >= -.425 && x < -.214 ? alaska : y >= .166 && y < .234 && x >= -.214 && x < -.115 ? hawaii : lower48).invert(coordinates);
+    };
+    albersUsa.stream = function(stream) {
+      var lower48Stream = lower48.stream(stream), alaskaStream = alaska.stream(stream), hawaiiStream = hawaii.stream(stream);
+      return {
+        point: function(x, y) {
+          lower48Stream.point(x, y);
+          alaskaStream.point(x, y);
+          hawaiiStream.point(x, y);
+        },
+        sphere: function() {
+          lower48Stream.sphere();
+          alaskaStream.sphere();
+          hawaiiStream.sphere();
+        },
+        lineStart: function() {
+          lower48Stream.lineStart();
+          alaskaStream.lineStart();
+          hawaiiStream.lineStart();
+        },
+        lineEnd: function() {
+          lower48Stream.lineEnd();
+          alaskaStream.lineEnd();
+          hawaiiStream.lineEnd();
+        },
+        polygonStart: function() {
+          lower48Stream.polygonStart();
+          alaskaStream.polygonStart();
+          hawaiiStream.polygonStart();
+        },
+        polygonEnd: function() {
+          lower48Stream.polygonEnd();
+          alaskaStream.polygonEnd();
+          hawaiiStream.polygonEnd();
+        }
+      };
+    };
+    albersUsa.precision = function(_) {
+      if (!arguments.length) return lower48.precision();
+      lower48.precision(_);
+      alaska.precision(_);
+      hawaii.precision(_);
+      return albersUsa;
+    };
+    albersUsa.scale = function(_) {
+      if (!arguments.length) return lower48.scale();
+      lower48.scale(_);
+      alaska.scale(_ * .35);
+      hawaii.scale(_);
+      return albersUsa.translate(lower48.translate());
+    };
+    albersUsa.translate = function(_) {
+      if (!arguments.length) return lower48.translate();
+      var k = lower48.scale(), x = +_[0], y = +_[1];
+      lower48Point = lower48.translate(_).clipExtent([ [ x - .455 * k, y - .238 * k ], [ x + .455 * k, y + .238 * k ] ]).stream(pointStream).point;
+      alaskaPoint = alaska.translate([ x - .307 * k, y + .201 * k ]).clipExtent([ [ x - .425 * k + ε, y + .12 * k + ε ], [ x - .214 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point;
+      hawaiiPoint = hawaii.translate([ x - .205 * k, y + .212 * k ]).clipExtent([ [ x - .214 * k + ε, y + .166 * k + ε ], [ x - .115 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point;
+      return albersUsa;
+    };
+    return albersUsa.scale(1070);
+  };
+  var d3_geo_pathAreaSum, d3_geo_pathAreaPolygon, d3_geo_pathArea = {
+    point: d3_noop,
+    lineStart: d3_noop,
+    lineEnd: d3_noop,
+    polygonStart: function() {
+      d3_geo_pathAreaPolygon = 0;
+      d3_geo_pathArea.lineStart = d3_geo_pathAreaRingStart;
+    },
+    polygonEnd: function() {
+      d3_geo_pathArea.lineStart = d3_geo_pathArea.lineEnd = d3_geo_pathArea.point = d3_noop;
+      d3_geo_pathAreaSum += abs(d3_geo_pathAreaPolygon / 2);
+    }
+  };
+  function d3_geo_pathAreaRingStart() {
+    var x00, y00, x0, y0;
+    d3_geo_pathArea.point = function(x, y) {
+      d3_geo_pathArea.point = nextPoint;
+      x00 = x0 = x, y00 = y0 = y;
+    };
+    function nextPoint(x, y) {
+      d3_geo_pathAreaPolygon += y0 * x - x0 * y;
+      x0 = x, y0 = y;
+    }
+    d3_geo_pathArea.lineEnd = function() {
+      nextPoint(x00, y00);
+    };
+  }
+  var d3_geo_pathBoundsX0, d3_geo_pathBoundsY0, d3_geo_pathBoundsX1, d3_geo_pathBoundsY1;
+  var d3_geo_pathBounds = {
+    point: d3_geo_pathBoundsPoint,
+    lineStart: d3_noop,
+    lineEnd: d3_noop,
+    polygonStart: d3_noop,
+    polygonEnd: d3_noop
+  };
+  function d3_geo_pathBoundsPoint(x, y) {
+    if (x < d3_geo_pathBoundsX0) d3_geo_pathBoundsX0 = x;
+    if (x > d3_geo_pathBoundsX1) d3_geo_pathBoundsX1 = x;
+    if (y < d3_geo_pathBoundsY0) d3_geo_pathBoundsY0 = y;
+    if (y > d3_geo_pathBoundsY1) d3_geo_pathBoundsY1 = y;
+  }
+  function d3_geo_pathBuffer() {
+    var pointCircle = d3_geo_pathBufferCircle(4.5), buffer = [];
+    var stream = {
+      point: point,
+      lineStart: function() {
+        stream.point = pointLineStart;
+      },
+      lineEnd: lineEnd,
+      polygonStart: function() {
+        stream.lineEnd = lineEndPolygon;
+      },
+      polygonEnd: function() {
+        stream.lineEnd = lineEnd;
+        stream.point = point;
+      },
+      pointRadius: function(_) {
+        pointCircle = d3_geo_pathBufferCircle(_);
+        return stream;
+      },
+      result: function() {
+        if (buffer.length) {
+          var result = buffer.join("");
+          buffer = [];
+          return result;
+        }
+      }
+    };
+    function point(x, y) {
+      buffer.push("M", x, ",", y, pointCircle);
+    }
+    function pointLineStart(x, y) {
+      buffer.push("M", x, ",", y);
+      stream.point = pointLine;
+    }
+    function pointLine(x, y) {
+      buffer.push("L", x, ",", y);
+    }
+    function lineEnd() {
+      stream.point = point;
+    }
+    function lineEndPolygon() {
+      buffer.push("Z");
+    }
+    return stream;
+  }
+  function d3_geo_pathBufferCircle(radius) {
+    return "m0," + radius + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius + "z";
+  }
+  var d3_geo_pathCentroid = {
+    point: d3_geo_pathCentroidPoint,
+    lineStart: d3_geo_pathCentroidLineStart,
+    lineEnd: d3_geo_pathCentroidLineEnd,
+    polygonStart: function() {
+      d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidRingStart;
+    },
+    polygonEnd: function() {
+      d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint;
+      d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidLineStart;
+      d3_geo_pathCentroid.lineEnd = d3_geo_pathCentroidLineEnd;
+    }
+  };
+  function d3_geo_pathCentroidPoint(x, y) {
+    d3_geo_centroidX0 += x;
+    d3_geo_centroidY0 += y;
+    ++d3_geo_centroidZ0;
+  }
+  function d3_geo_pathCentroidLineStart() {
+    var x0, y0;
+    d3_geo_pathCentroid.point = function(x, y) {
+      d3_geo_pathCentroid.point = nextPoint;
+      d3_geo_pathCentroidPoint(x0 = x, y0 = y);
+    };
+    function nextPoint(x, y) {
+      var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy);
+      d3_geo_centroidX1 += z * (x0 + x) / 2;
+      d3_geo_centroidY1 += z * (y0 + y) / 2;
+      d3_geo_centroidZ1 += z;
+      d3_geo_pathCentroidPoint(x0 = x, y0 = y);
+    }
+  }
+  function d3_geo_pathCentroidLineEnd() {
+    d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint;
+  }
+  function d3_geo_pathCentroidRingStart() {
+    var x00, y00, x0, y0;
+    d3_geo_pathCentroid.point = function(x, y) {
+      d3_geo_pathCentroid.point = nextPoint;
+      d3_geo_pathCentroidPoint(x00 = x0 = x, y00 = y0 = y);
+    };
+    function nextPoint(x, y) {
+      var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy);
+      d3_geo_centroidX1 += z * (x0 + x) / 2;
+      d3_geo_centroidY1 += z * (y0 + y) / 2;
+      d3_geo_centroidZ1 += z;
+      z = y0 * x - x0 * y;
+      d3_geo_centroidX2 += z * (x0 + x);
+      d3_geo_centroidY2 += z * (y0 + y);
+      d3_geo_centroidZ2 += z * 3;
+      d3_geo_pathCentroidPoint(x0 = x, y0 = y);
+    }
+    d3_geo_pathCentroid.lineEnd = function() {
+      nextPoint(x00, y00);
+    };
+  }
+  function d3_geo_pathContext(context) {
+    var pointRadius = 4.5;
+    var stream = {
+      point: point,
+      lineStart: function() {
+        stream.point = pointLineStart;
+      },
+      lineEnd: lineEnd,
+      polygonStart: function() {
+        stream.lineEnd = lineEndPolygon;
+      },
+      polygonEnd: function() {
+        stream.lineEnd = lineEnd;
+        stream.point = point;
+      },
+      pointRadius: function(_) {
+        pointRadius = _;
+        return stream;
+      },
+      result: d3_noop
+    };
+    function point(x, y) {
+      context.moveTo(x, y);
+      context.arc(x, y, pointRadius, 0, τ);
+    }
+    function pointLineStart(x, y) {
+      context.moveTo(x, y);
+      stream.point = pointLine;
+    }
+    function pointLine(x, y) {
+      context.lineTo(x, y);
+    }
+    function lineEnd() {
+      stream.point = point;
+    }
+    function lineEndPolygon() {
+      context.closePath();
+    }
+    return stream;
+  }
+  function d3_geo_resample(project) {
+    var δ2 = .5, cosMinDistance = Math.cos(30 * d3_radians), maxDepth = 16;
+    function resample(stream) {
+      return (maxDepth ? resampleRecursive : resampleNone)(stream);
+    }
+    function resampleNone(stream) {
+      return d3_geo_transformPoint(stream, function(x, y) {
+        x = project(x, y);
+        stream.point(x[0], x[1]);
+      });
+    }
+    function resampleRecursive(stream) {
+      var λ00, φ00, x00, y00, a00, b00, c00, λ0, x0, y0, a0, b0, c0;
+      var resample = {
+        point: point,
+        lineStart: lineStart,
+        lineEnd: lineEnd,
+        polygonStart: function() {
+          stream.polygonStart();
+          resample.lineStart = ringStart;
+        },
+        polygonEnd: function() {
+          stream.polygonEnd();
+          resample.lineStart = lineStart;
+        }
+      };
+      function point(x, y) {
+        x = project(x, y);
+        stream.point(x[0], x[1]);
+      }
+      function lineStart() {
+        x0 = NaN;
+        resample.point = linePoint;
+        stream.lineStart();
+      }
+      function linePoint(λ, φ) {
+        var c = d3_geo_cartesian([ λ, φ ]), p = project(λ, φ);
+        resampleLineTo(x0, y0, λ0, a0, b0, c0, x0 = p[0], y0 = p[1], λ0 = λ, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream);
+        stream.point(x0, y0);
+      }
+      function lineEnd() {
+        resample.point = point;
+        stream.lineEnd();
+      }
+      function ringStart() {
+        lineStart();
+        resample.point = ringPoint;
+        resample.lineEnd = ringEnd;
+      }
+      function ringPoint(λ, φ) {
+        linePoint(λ00 = λ, φ00 = φ), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0;
+        resample.point = linePoint;
+      }
+      function ringEnd() {
+        resampleLineTo(x0, y0, λ0, a0, b0, c0, x00, y00, λ00, a00, b00, c00, maxDepth, stream);
+        resample.lineEnd = lineEnd;
+        lineEnd();
+      }
+      return resample;
+    }
+    function resampleLineTo(x0, y0, λ0, a0, b0, c0, x1, y1, λ1, a1, b1, c1, depth, stream) {
+      var dx = x1 - x0, dy = y1 - y0, d2 = dx * dx + dy * dy;
+      if (d2 > 4 * δ2 && depth--) {
+        var a = a0 + a1, b = b0 + b1, c = c0 + c1, m = Math.sqrt(a * a + b * b + c * c), φ2 = Math.asin(c /= m), λ2 = abs(abs(c) - 1) < ε || abs(λ0 - λ1) < ε ? (λ0 + λ1) / 2 : Math.atan2(b, a), p = project(λ2, φ2), x2 = p[0], y2 = p[1], dx2 = x2 - x0, dy2 = y2 - y0, dz = dy * dx2 - dx * dy2;
+        if (dz * dz / d2 > δ2 || abs((dx * dx2 + dy * dy2) / d2 - .5) > .3 || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) {
+          resampleLineTo(x0, y0, λ0, a0, b0, c0, x2, y2, λ2, a /= m, b /= m, c, depth, stream);
+          stream.point(x2, y2);
+          resampleLineTo(x2, y2, λ2, a, b, c, x1, y1, λ1, a1, b1, c1, depth, stream);
+        }
+      }
+    }
+    resample.precision = function(_) {
+      if (!arguments.length) return Math.sqrt(δ2);
+      maxDepth = (δ2 = _ * _) > 0 && 16;
+      return resample;
+    };
+    return resample;
+  }
+  d3.geo.path = function() {
+    var pointRadius = 4.5, projection, context, projectStream, contextStream, cacheStream;
+    function path(object) {
+      if (object) {
+        if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments));
+        if (!cacheStream || !cacheStream.valid) cacheStream = projectStream(contextStream);
+        d3.geo.stream(object, cacheStream);
+      }
+      return contextStream.result();
+    }
+    path.area = function(object) {
+      d3_geo_pathAreaSum = 0;
+      d3.geo.stream(object, projectStream(d3_geo_pathArea));
+      return d3_geo_pathAreaSum;
+    };
+    path.centroid = function(object) {
+      d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0;
+      d3.geo.stream(object, projectStream(d3_geo_pathCentroid));
+      return d3_geo_centroidZ2 ? [ d3_geo_centroidX2 / d3_geo_centroidZ2, d3_geo_centroidY2 / d3_geo_centroidZ2 ] : d3_geo_centroidZ1 ? [ d3_geo_centroidX1 / d3_geo_centroidZ1, d3_geo_centroidY1 / d3_geo_centroidZ1 ] : d3_geo_centroidZ0 ? [ d3_geo_centroidX0 / d3_geo_centroidZ0, d3_geo_centroidY0 / d3_geo_centroidZ0 ] : [ NaN, NaN ];
+    };
+    path.bounds = function(object) {
+      d3_geo_pathBoundsX1 = d3_geo_pathBoundsY1 = -(d3_geo_pathBoundsX0 = d3_geo_pathBoundsY0 = Infinity);
+      d3.geo.stream(object, projectStream(d3_geo_pathBounds));
+      return [ [ d3_geo_pathBoundsX0, d3_geo_pathBoundsY0 ], [ d3_geo_pathBoundsX1, d3_geo_pathBoundsY1 ] ];
+    };
+    path.projection = function(_) {
+      if (!arguments.length) return projection;
+      projectStream = (projection = _) ? _.stream || d3_geo_pathProjectStream(_) : d3_identity;
+      return reset();
+    };
+    path.context = function(_) {
+      if (!arguments.length) return context;
+      contextStream = (context = _) == null ? new d3_geo_pathBuffer() : new d3_geo_pathContext(_);
+      if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius);
+      return reset();
+    };
+    path.pointRadius = function(_) {
+      if (!arguments.length) return pointRadius;
+      pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_);
+      return path;
+    };
+    function reset() {
+      cacheStream = null;
+      return path;
+    }
+    return path.projection(d3.geo.albersUsa()).context(null);
+  };
+  function d3_geo_pathProjectStream(project) {
+    var resample = d3_geo_resample(function(x, y) {
+      return project([ x * d3_degrees, y * d3_degrees ]);
+    });
+    return function(stream) {
+      return d3_geo_projectionRadians(resample(stream));
+    };
+  }
+  d3.geo.transform = function(methods) {
+    return {
+      stream: function(stream) {
+        var transform = new d3_geo_transform(stream);
+        for (var k in methods) transform[k] = methods[k];
+        return transform;
+      }
+    };
+  };
+  function d3_geo_transform(stream) {
+    this.stream = stream;
+  }
+  d3_geo_transform.prototype = {
+    point: function(x, y) {
+      this.stream.point(x, y);
+    },
+    sphere: function() {
+      this.stream.sphere();
+    },
+    lineStart: function() {
+      this.stream.lineStart();
+    },
+    lineEnd: function() {
+      this.stream.lineEnd();
+    },
+    polygonStart: function() {
+      this.stream.polygonStart();
+    },
+    polygonEnd: function() {
+      this.stream.polygonEnd();
+    }
+  };
+  function d3_geo_transformPoint(stream, point) {
+    return {
+      point: point,
+      sphere: function() {
+        stream.sphere();
+      },
+      lineStart: function() {
+        stream.lineStart();
+      },
+      lineEnd: function() {
+        stream.lineEnd();
+      },
+      polygonStart: function() {
+        stream.polygonStart();
+      },
+      polygonEnd: function() {
+        stream.polygonEnd();
+      }
+    };
+  }
+  d3.geo.projection = d3_geo_projection;
+  d3.geo.projectionMutator = d3_geo_projectionMutator;
+  function d3_geo_projection(project) {
+    return d3_geo_projectionMutator(function() {
+      return project;
+    })();
+  }
+  function d3_geo_projectionMutator(projectAt) {
+    var project, rotate, projectRotate, projectResample = d3_geo_resample(function(x, y) {
+      x = project(x, y);
+      return [ x[0] * k + δx, δy - x[1] * k ];
+    }), k = 150, x = 480, y = 250, λ = 0, φ = 0, δλ = 0, δφ = 0, δγ = 0, δx, δy, preclip = d3_geo_clipAntimeridian, postclip = d3_identity, clipAngle = null, clipExtent = null, stream;
+    function projection(point) {
+      point = projectRotate(point[0] * d3_radians, point[1] * d3_radians);
+      return [ point[0] * k + δx, δy - point[1] * k ];
+    }
+    function invert(point) {
+      point = projectRotate.invert((point[0] - δx) / k, (δy - point[1]) / k);
+      return point && [ point[0] * d3_degrees, point[1] * d3_degrees ];
+    }
+    projection.stream = function(output) {
+      if (stream) stream.valid = false;
+      stream = d3_geo_projectionRadians(preclip(rotate, projectResample(postclip(output))));
+      stream.valid = true;
+      return stream;
+    };
+    projection.clipAngle = function(_) {
+      if (!arguments.length) return clipAngle;
+      preclip = _ == null ? (clipAngle = _, d3_geo_clipAntimeridian) : d3_geo_clipCircle((clipAngle = +_) * d3_radians);
+      return invalidate();
+    };
+    projection.clipExtent = function(_) {
+      if (!arguments.length) return clipExtent;
+      clipExtent = _;
+      postclip = _ ? d3_geo_clipExtent(_[0][0], _[0][1], _[1][0], _[1][1]) : d3_identity;
+      return invalidate();
+    };
+    projection.scale = function(_) {
+      if (!arguments.length) return k;
+      k = +_;
+      return reset();
+    };
+    projection.translate = function(_) {
+      if (!arguments.length) return [ x, y ];
+      x = +_[0];
+      y = +_[1];
+      return reset();
+    };
+    projection.center = function(_) {
+      if (!arguments.length) return [ λ * d3_degrees, φ * d3_degrees ];
+      λ = _[0] % 360 * d3_radians;
+      φ = _[1] % 360 * d3_radians;
+      return reset();
+    };
+    projection.rotate = function(_) {
+      if (!arguments.length) return [ δλ * d3_degrees, δφ * d3_degrees, δγ * d3_degrees ];
+      δλ = _[0] % 360 * d3_radians;
+      δφ = _[1] % 360 * d3_radians;
+      δγ = _.length > 2 ? _[2] % 360 * d3_radians : 0;
+      return reset();
+    };
+    d3.rebind(projection, projectResample, "precision");
+    function reset() {
+      projectRotate = d3_geo_compose(rotate = d3_geo_rotation(δλ, δφ, δγ), project);
+      var center = project(λ, φ);
+      δx = x - center[0] * k;
+      δy = y + center[1] * k;
+      return invalidate();
+    }
+    function invalidate() {
+      if (stream) stream.valid = false, stream = null;
+      return projection;
+    }
+    return function() {
+      project = projectAt.apply(this, arguments);
+      projection.invert = project.invert && invert;
+      return reset();
+    };
+  }
+  function d3_geo_projectionRadians(stream) {
+    return d3_geo_transformPoint(stream, function(x, y) {
+      stream.point(x * d3_radians, y * d3_radians);
+    });
+  }
+  function d3_geo_equirectangular(λ, φ) {
+    return [ λ, φ ];
+  }
+  (d3.geo.equirectangular = function() {
+    return d3_geo_projection(d3_geo_equirectangular);
+  }).raw = d3_geo_equirectangular.invert = d3_geo_equirectangular;
+  d3.geo.rotation = function(rotate) {
+    rotate = d3_geo_rotation(rotate[0] % 360 * d3_radians, rotate[1] * d3_radians, rotate.length > 2 ? rotate[2] * d3_radians : 0);
+    function forward(coordinates) {
+      coordinates = rotate(coordinates[0] * d3_radians, coordinates[1] * d3_radians);
+      return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates;
+    }
+    forward.invert = function(coordinates) {
+      coordinates = rotate.invert(coordinates[0] * d3_radians, coordinates[1] * d3_radians);
+      return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates;
+    };
+    return forward;
+  };
+  function d3_geo_identityRotation(λ, φ) {
+    return [ λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ ];
+  }
+  d3_geo_identityRotation.invert = d3_geo_equirectangular;
+  function d3_geo_rotation(δλ, δφ, δγ) {
+    return δλ ? δφ || δγ ? d3_geo_compose(d3_geo_rotationλ(δλ), d3_geo_rotationφγ(δφ, δγ)) : d3_geo_rotationλ(δλ) : δφ || δγ ? d3_geo_rotationφγ(δφ, δγ) : d3_geo_identityRotation;
+  }
+  function d3_geo_forwardRotationλ(δλ) {
+    return function(λ, φ) {
+      return λ += δλ, [ λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ ];
+    };
+  }
+  function d3_geo_rotationλ(δλ) {
+    var rotation = d3_geo_forwardRotationλ(δλ);
+    rotation.invert = d3_geo_forwardRotationλ(-δλ);
+    return rotation;
+  }
+  function d3_geo_rotationφγ(δφ, δγ) {
+    var cosδφ = Math.cos(δφ), sinδφ = Math.sin(δφ), cosδγ = Math.cos(δγ), sinδγ = Math.sin(δγ);
+    function rotation(λ, φ) {
+      var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδφ + x * sinδφ;
+      return [ Math.atan2(y * cosδγ - k * sinδγ, x * cosδφ - z * sinδφ), d3_asin(k * cosδγ + y * sinδγ) ];
+    }
+    rotation.invert = function(λ, φ) {
+      var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδγ - y * sinδγ;
+      return [ Math.atan2(y * cosδγ + z * sinδγ, x * cosδφ + k * sinδφ), d3_asin(k * cosδφ - x * sinδφ) ];
+    };
+    return rotation;
+  }
+  d3.geo.circle = function() {
+    var origin = [ 0, 0 ], angle, precision = 6, interpolate;
+    function circle() {
+      var center = typeof origin === "function" ? origin.apply(this, arguments) : origin, rotate = d3_geo_rotation(-center[0] * d3_radians, -center[1] * d3_radians, 0).invert, ring = [];
+      interpolate(null, null, 1, {
+        point: function(x, y) {
+          ring.push(x = rotate(x, y));
+          x[0] *= d3_degrees, x[1] *= d3_degrees;
+        }
+      });
+      return {
+        type: "Polygon",
+        coordinates: [ ring ]
+      };
+    }
+    circle.origin = function(x) {
+      if (!arguments.length) return origin;
+      origin = x;
+      return circle;
+    };
+    circle.angle = function(x) {
+      if (!arguments.length) return angle;
+      interpolate = d3_geo_circleInterpolate((angle = +x) * d3_radians, precision * d3_radians);
+      return circle;
+    };
+    circle.precision = function(_) {
+      if (!arguments.length) return precision;
+      interpolate = d3_geo_circleInterpolate(angle * d3_radians, (precision = +_) * d3_radians);
+      return circle;
+    };
+    return circle.angle(90);
+  };
+  function d3_geo_circleInterpolate(radius, precision) {
+    var cr = Math.cos(radius), sr = Math.sin(radius);
+    return function(from, to, direction, listener) {
+      var step = direction * precision;
+      if (from != null) {
+        from = d3_geo_circleAngle(cr, from);
+        to = d3_geo_circleAngle(cr, to);
+        if (direction > 0 ? from < to : from > to) from += direction * τ;
+      } else {
+        from = radius + direction * τ;
+        to = radius - .5 * step;
+      }
+      for (var point, t = from; direction > 0 ? t > to : t < to; t -= step) {
+        listener.point((point = d3_geo_spherical([ cr, -sr * Math.cos(t), -sr * Math.sin(t) ]))[0], point[1]);
+      }
+    };
+  }
+  function d3_geo_circleAngle(cr, point) {
+    var a = d3_geo_cartesian(point);
+    a[0] -= cr;
+    d3_geo_cartesianNormalize(a);
+    var angle = d3_acos(-a[1]);
+    return ((-a[2] < 0 ? -angle : angle) + 2 * Math.PI - ε) % (2 * Math.PI);
+  }
+  d3.geo.distance = function(a, b) {
+    var Δλ = (b[0] - a[0]) * d3_radians, φ0 = a[1] * d3_radians, φ1 = b[1] * d3_radians, sinΔλ = Math.sin(Δλ), cosΔλ = Math.cos(Δλ), sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), sinφ1 = Math.sin(φ1), cosφ1 = Math.cos(φ1), t;
+    return Math.atan2(Math.sqrt((t = cosφ1 * sinΔλ) * t + (t = cosφ0 * sinφ1 - sinφ0 * cosφ1 * cosΔλ) * t), sinφ0 * sinφ1 + cosφ0 * cosφ1 * cosΔλ);
+  };
+  d3.geo.graticule = function() {
+    var x1, x0, X1, X0, y1, y0, Y1, Y0, dx = 10, dy = dx, DX = 90, DY = 360, x, y, X, Y, precision = 2.5;
+    function graticule() {
+      return {
+        type: "MultiLineString",
+        coordinates: lines()
+      };
+    }
+    function lines() {
+      return d3.range(Math.ceil(X0 / DX) * DX, X1, DX).map(X).concat(d3.range(Math.ceil(Y0 / DY) * DY, Y1, DY).map(Y)).concat(d3.range(Math.ceil(x0 / dx) * dx, x1, dx).filter(function(x) {
+        return abs(x % DX) > ε;
+      }).map(x)).concat(d3.range(Math.ceil(y0 / dy) * dy, y1, dy).filter(function(y) {
+        return abs(y % DY) > ε;
+      }).map(y));
+    }
+    graticule.lines = function() {
+      return lines().map(function(coordinates) {
+        return {
+          type: "LineString",
+          coordinates: coordinates
+        };
+      });
+    };
+    graticule.outline = function() {
+      return {
+        type: "Polygon",
+        coordinates: [ X(X0).concat(Y(Y1).slice(1), X(X1).reverse().slice(1), Y(Y0).reverse().slice(1)) ]
+      };
+    };
+    graticule.extent = function(_) {
+      if (!arguments.length) return graticule.minorExtent();
+      return graticule.majorExtent(_).minorExtent(_);
+    };
+    graticule.majorExtent = function(_) {
+      if (!arguments.length) return [ [ X0, Y0 ], [ X1, Y1 ] ];
+      X0 = +_[0][0], X1 = +_[1][0];
+      Y0 = +_[0][1], Y1 = +_[1][1];
+      if (X0 > X1) _ = X0, X0 = X1, X1 = _;
+      if (Y0 > Y1) _ = Y0, Y0 = Y1, Y1 = _;
+      return graticule.precision(precision);
+    };
+    graticule.minorExtent = function(_) {
+      if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ];
+      x0 = +_[0][0], x1 = +_[1][0];
+      y0 = +_[0][1], y1 = +_[1][1];
+      if (x0 > x1) _ = x0, x0 = x1, x1 = _;
+      if (y0 > y1) _ = y0, y0 = y1, y1 = _;
+      return graticule.precision(precision);
+    };
+    graticule.step = function(_) {
+      if (!arguments.length) return graticule.minorStep();
+      return graticule.majorStep(_).minorStep(_);
+    };
+    graticule.majorStep = function(_) {
+      if (!arguments.length) return [ DX, DY ];
+      DX = +_[0], DY = +_[1];
+      return graticule;
+    };
+    graticule.minorStep = function(_) {
+      if (!arguments.length) return [ dx, dy ];
+      dx = +_[0], dy = +_[1];
+      return graticule;
+    };
+    graticule.precision = function(_) {
+      if (!arguments.length) return precision;
+      precision = +_;
+      x = d3_geo_graticuleX(y0, y1, 90);
+      y = d3_geo_graticuleY(x0, x1, precision);
+      X = d3_geo_graticuleX(Y0, Y1, 90);
+      Y = d3_geo_graticuleY(X0, X1, precision);
+      return graticule;
+    };
+    return graticule.majorExtent([ [ -180, -90 + ε ], [ 180, 90 - ε ] ]).minorExtent([ [ -180, -80 - ε ], [ 180, 80 + ε ] ]);
+  };
+  function d3_geo_graticuleX(y0, y1, dy) {
+    var y = d3.range(y0, y1 - ε, dy).concat(y1);
+    return function(x) {
+      return y.map(function(y) {
+        return [ x, y ];
+      });
+    };
+  }
+  function d3_geo_graticuleY(x0, x1, dx) {
+    var x = d3.range(x0, x1 - ε, dx).concat(x1);
+    return function(y) {
+      return x.map(function(x) {
+        return [ x, y ];
+      });
+    };
+  }
+  function d3_source(d) {
+    return d.source;
+  }
+  function d3_target(d) {
+    return d.target;
+  }
+  d3.geo.greatArc = function() {
+    var source = d3_source, source_, target = d3_target, target_;
+    function greatArc() {
+      return {
+        type: "LineString",
+        coordinates: [ source_ || source.apply(this, arguments), target_ || target.apply(this, arguments) ]
+      };
+    }
+    greatArc.distance = function() {
+      return d3.geo.distance(source_ || source.apply(this, arguments), target_ || target.apply(this, arguments));
+    };
+    greatArc.source = function(_) {
+      if (!arguments.length) return source;
+      source = _, source_ = typeof _ === "function" ? null : _;
+      return greatArc;
+    };
+    greatArc.target = function(_) {
+      if (!arguments.length) return target;
+      target = _, target_ = typeof _ === "function" ? null : _;
+      return greatArc;
+    };
+    greatArc.precision = function() {
+      return arguments.length ? greatArc : 0;
+    };
+    return greatArc;
+  };
+  d3.geo.interpolate = function(source, target) {
+    return d3_geo_interpolate(source[0] * d3_radians, source[1] * d3_radians, target[0] * d3_radians, target[1] * d3_radians);
+  };
+  function d3_geo_interpolate(x0, y0, x1, y1) {
+    var cy0 = Math.cos(y0), sy0 = Math.sin(y0), cy1 = Math.cos(y1), sy1 = Math.sin(y1), kx0 = cy0 * Math.cos(x0), ky0 = cy0 * Math.sin(x0), kx1 = cy1 * Math.cos(x1), ky1 = cy1 * Math.sin(x1), d = 2 * Math.asin(Math.sqrt(d3_haversin(y1 - y0) + cy0 * cy1 * d3_haversin(x1 - x0))), k = 1 / Math.sin(d);
+    var interpolate = d ? function(t) {
+      var B = Math.sin(t *= d) * k, A = Math.sin(d - t) * k, x = A * kx0 + B * kx1, y = A * ky0 + B * ky1, z = A * sy0 + B * sy1;
+      return [ Math.atan2(y, x) * d3_degrees, Math.atan2(z, Math.sqrt(x * x + y * y)) * d3_degrees ];
+    } : function() {
+      return [ x0 * d3_degrees, y0 * d3_degrees ];
+    };
+    interpolate.distance = d;
+    return interpolate;
+  }
+  d3.geo.length = function(object) {
+    d3_geo_lengthSum = 0;
+    d3.geo.stream(object, d3_geo_length);
+    return d3_geo_lengthSum;
+  };
+  var d3_geo_lengthSum;
+  var d3_geo_length = {
+    sphere: d3_noop,
+    point: d3_noop,
+    lineStart: d3_geo_lengthLineStart,
+    lineEnd: d3_noop,
+    polygonStart: d3_noop,
+    polygonEnd: d3_noop
+  };
+  function d3_geo_lengthLineStart() {
+    var λ0, sinφ0, cosφ0;
+    d3_geo_length.point = function(λ, φ) {
+      λ0 = λ * d3_radians, sinφ0 = Math.sin(φ *= d3_radians), cosφ0 = Math.cos(φ);
+      d3_geo_length.point = nextPoint;
+    };
+    d3_geo_length.lineEnd = function() {
+      d3_geo_length.point = d3_geo_length.lineEnd = d3_noop;
+    };
+    function nextPoint(λ, φ) {
+      var sinφ = Math.sin(φ *= d3_radians), cosφ = Math.cos(φ), t = abs((λ *= d3_radians) - λ0), cosΔλ = Math.cos(t);
+      d3_geo_lengthSum += Math.atan2(Math.sqrt((t = cosφ * Math.sin(t)) * t + (t = cosφ0 * sinφ - sinφ0 * cosφ * cosΔλ) * t), sinφ0 * sinφ + cosφ0 * cosφ * cosΔλ);
+      λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ;
+    }
+  }
+  function d3_geo_azimuthal(scale, angle) {
+    function azimuthal(λ, φ) {
+      var cosλ = Math.cos(λ), cosφ = Math.cos(φ), k = scale(cosλ * cosφ);
+      return [ k * cosφ * Math.sin(λ), k * Math.sin(φ) ];
+    }
+    azimuthal.invert = function(x, y) {
+      var ρ = Math.sqrt(x * x + y * y), c = angle(ρ), sinc = Math.sin(c), cosc = Math.cos(c);
+      return [ Math.atan2(x * sinc, ρ * cosc), Math.asin(ρ && y * sinc / ρ) ];
+    };
+    return azimuthal;
+  }
+  var d3_geo_azimuthalEqualArea = d3_geo_azimuthal(function(cosλcosφ) {
+    return Math.sqrt(2 / (1 + cosλcosφ));
+  }, function(ρ) {
+    return 2 * Math.asin(ρ / 2);
+  });
+  (d3.geo.azimuthalEqualArea = function() {
+    return d3_geo_projection(d3_geo_azimuthalEqualArea);
+  }).raw = d3_geo_azimuthalEqualArea;
+  var d3_geo_azimuthalEquidistant = d3_geo_azimuthal(function(cosλcosφ) {
+    var c = Math.acos(cosλcosφ);
+    return c && c / Math.sin(c);
+  }, d3_identity);
+  (d3.geo.azimuthalEquidistant = function() {
+    return d3_geo_projection(d3_geo_azimuthalEquidistant);
+  }).raw = d3_geo_azimuthalEquidistant;
+  function d3_geo_conicConformal(φ0, φ1) {
+    var cosφ0 = Math.cos(φ0), t = function(φ) {
+      return Math.tan(π / 4 + φ / 2);
+    }, n = φ0 === φ1 ? Math.sin(φ0) : Math.log(cosφ0 / Math.cos(φ1)) / Math.log(t(φ1) / t(φ0)), F = cosφ0 * Math.pow(t(φ0), n) / n;
+    if (!n) return d3_geo_mercator;
+    function forward(λ, φ) {
+      if (F > 0) {
+        if (φ < -halfπ + ε) φ = -halfπ + ε;
+      } else {
+        if (φ > halfπ - ε) φ = halfπ - ε;
+      }
+      var ρ = F / Math.pow(t(φ), n);
+      return [ ρ * Math.sin(n * λ), F - ρ * Math.cos(n * λ) ];
+    }
+    forward.invert = function(x, y) {
+      var ρ0_y = F - y, ρ = d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y);
+      return [ Math.atan2(x, ρ0_y) / n, 2 * Math.atan(Math.pow(F / ρ, 1 / n)) - halfπ ];
+    };
+    return forward;
+  }
+  (d3.geo.conicConformal = function() {
+    return d3_geo_conic(d3_geo_conicConformal);
+  }).raw = d3_geo_conicConformal;
+  function d3_geo_conicEquidistant(φ0, φ1) {
+    var cosφ0 = Math.cos(φ0), n = φ0 === φ1 ? Math.sin(φ0) : (cosφ0 - Math.cos(φ1)) / (φ1 - φ0), G = cosφ0 / n + φ0;
+    if (abs(n) < ε) return d3_geo_equirectangular;
+    function forward(λ, φ) {
+      var ρ = G - φ;
+      return [ ρ * Math.sin(n * λ), G - ρ * Math.cos(n * λ) ];
+    }
+    forward.invert = function(x, y) {
+      var ρ0_y = G - y;
+      return [ Math.atan2(x, ρ0_y) / n, G - d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y) ];
+    };
+    return forward;
+  }
+  (d3.geo.conicEquidistant = function() {
+    return d3_geo_conic(d3_geo_conicEquidistant);
+  }).raw = d3_geo_conicEquidistant;
+  var d3_geo_gnomonic = d3_geo_azimuthal(function(cosλcosφ) {
+    return 1 / cosλcosφ;
+  }, Math.atan);
+  (d3.geo.gnomonic = function() {
+    return d3_geo_projection(d3_geo_gnomonic);
+  }).raw = d3_geo_gnomonic;
+  function d3_geo_mercator(λ, φ) {
+    return [ λ, Math.log(Math.tan(π / 4 + φ / 2)) ];
+  }
+  d3_geo_mercator.invert = function(x, y) {
+    return [ x, 2 * Math.atan(Math.exp(y)) - halfπ ];
+  };
+  function d3_geo_mercatorProjection(project) {
+    var m = d3_geo_projection(project), scale = m.scale, translate = m.translate, clipExtent = m.clipExtent, clipAuto;
+    m.scale = function() {
+      var v = scale.apply(m, arguments);
+      return v === m ? clipAuto ? m.clipExtent(null) : m : v;
+    };
+    m.translate = function() {
+      var v = translate.apply(m, arguments);
+      return v === m ? clipAuto ? m.clipExtent(null) : m : v;
+    };
+    m.clipExtent = function(_) {
+      var v = clipExtent.apply(m, arguments);
+      if (v === m) {
+        if (clipAuto = _ == null) {
+          var k = π * scale(), t = translate();
+          clipExtent([ [ t[0] - k, t[1] - k ], [ t[0] + k, t[1] + k ] ]);
+        }
+      } else if (clipAuto) {
+        v = null;
+      }
+      return v;
+    };
+    return m.clipExtent(null);
+  }
+  (d3.geo.mercator = function() {
+    return d3_geo_mercatorProjection(d3_geo_mercator);
+  }).raw = d3_geo_mercator;
+  var d3_geo_orthographic = d3_geo_azimuthal(function() {
+    return 1;
+  }, Math.asin);
+  (d3.geo.orthographic = function() {
+    return d3_geo_projection(d3_geo_orthographic);
+  }).raw = d3_geo_orthographic;
+  var d3_geo_stereographic = d3_geo_azimuthal(function(cosλcosφ) {
+    return 1 / (1 + cosλcosφ);
+  }, function(ρ) {
+    return 2 * Math.atan(ρ);
+  });
+  (d3.geo.stereographic = function() {
+    return d3_geo_projection(d3_geo_stereographic);
+  }).raw = d3_geo_stereographic;
+  function d3_geo_transverseMercator(λ, φ) {
+    return [ Math.log(Math.tan(π / 4 + φ / 2)), -λ ];
+  }
+  d3_geo_transverseMercator.invert = function(x, y) {
+    return [ -y, 2 * Math.atan(Math.exp(x)) - halfπ ];
+  };
+  (d3.geo.transverseMercator = function() {
+    var projection = d3_geo_mercatorProjection(d3_geo_transverseMercator), center = projection.center, rotate = projection.rotate;
+    projection.center = function(_) {
+      return _ ? center([ -_[1], _[0] ]) : (_ = center(), [ -_[1], _[0] ]);
+    };
+    projection.rotate = function(_) {
+      return _ ? rotate([ _[0], _[1], _.length > 2 ? _[2] + 90 : 90 ]) : (_ = rotate(), 
+      [ _[0], _[1], _[2] - 90 ]);
+    };
+    return projection.rotate([ 0, 0 ]);
+  }).raw = d3_geo_transverseMercator;
+  d3.geom = {};
+  function d3_geom_pointX(d) {
+    return d[0];
+  }
+  function d3_geom_pointY(d) {
+    return d[1];
+  }
+  d3.geom.hull = function(vertices) {
+    var x = d3_geom_pointX, y = d3_geom_pointY;
+    if (arguments.length) return hull(vertices);
+    function hull(data) {
+      if (data.length < 3) return [];
+      var fx = d3_functor(x), fy = d3_functor(y), i, n = data.length, points = [], flippedPoints = [];
+      for (i = 0; i < n; i++) {
+        points.push([ +fx.call(this, data[i], i), +fy.call(this, data[i], i), i ]);
+      }
+      points.sort(d3_geom_hullOrder);
+      for (i = 0; i < n; i++) flippedPoints.push([ points[i][0], -points[i][1] ]);
+      var upper = d3_geom_hullUpper(points), lower = d3_geom_hullUpper(flippedPoints);
+      var skipLeft = lower[0] === upper[0], skipRight = lower[lower.length - 1] === upper[upper.length - 1], polygon = [];
+      for (i = upper.length - 1; i >= 0; --i) polygon.push(data[points[upper[i]][2]]);
+      for (i = +skipLeft; i < lower.length - skipRight; ++i) polygon.push(data[points[lower[i]][2]]);
+      return polygon;
+    }
+    hull.x = function(_) {
+      return arguments.length ? (x = _, hull) : x;
+    };
+    hull.y = function(_) {
+      return arguments.length ? (y = _, hull) : y;
+    };
+    return hull;
+  };
+  function d3_geom_hullUpper(points) {
+    var n = points.length, hull = [ 0, 1 ], hs = 2;
+    for (var i = 2; i < n; i++) {
+      while (hs > 1 && d3_cross2d(points[hull[hs - 2]], points[hull[hs - 1]], points[i]) <= 0) --hs;
+      hull[hs++] = i;
+    }
+    return hull.slice(0, hs);
+  }
+  function d3_geom_hullOrder(a, b) {
+    return a[0] - b[0] || a[1] - b[1];
+  }
+  d3.geom.polygon = function(coordinates) {
+    d3_subclass(coordinates, d3_geom_polygonPrototype);
+    return coordinates;
+  };
+  var d3_geom_polygonPrototype = d3.geom.polygon.prototype = [];
+  d3_geom_polygonPrototype.area = function() {
+    var i = -1, n = this.length, a, b = this[n - 1], area = 0;
+    while (++i < n) {
+      a = b;
+      b = this[i];
+      area += a[1] * b[0] - a[0] * b[1];
+    }
+    return area * .5;
+  };
+  d3_geom_polygonPrototype.centroid = function(k) {
+    var i = -1, n = this.length, x = 0, y = 0, a, b = this[n - 1], c;
+    if (!arguments.length) k = -1 / (6 * this.area());
+    while (++i < n) {
+      a = b;
+      b = this[i];
+      c = a[0] * b[1] - b[0] * a[1];
+      x += (a[0] + b[0]) * c;
+      y += (a[1] + b[1]) * c;
+    }
+    return [ x * k, y * k ];
+  };
+  d3_geom_polygonPrototype.clip = function(subject) {
+    var input, closed = d3_geom_polygonClosed(subject), i = -1, n = this.length - d3_geom_polygonClosed(this), j, m, a = this[n - 1], b, c, d;
+    while (++i < n) {
+      input = subject.slice();
+      subject.length = 0;
+      b = this[i];
+      c = input[(m = input.length - closed) - 1];
+      j = -1;
+      while (++j < m) {
+        d = input[j];
+        if (d3_geom_polygonInside(d, a, b)) {
+          if (!d3_geom_polygonInside(c, a, b)) {
+            subject.push(d3_geom_polygonIntersect(c, d, a, b));
+          }
+          subject.push(d);
+        } else if (d3_geom_polygonInside(c, a, b)) {
+          subject.push(d3_geom_polygonIntersect(c, d, a, b));
+        }
+        c = d;
+      }
+      if (closed) subject.push(subject[0]);
+      a = b;
+    }
+    return subject;
+  };
+  function d3_geom_polygonInside(p, a, b) {
+    return (b[0] - a[0]) * (p[1] - a[1]) < (b[1] - a[1]) * (p[0] - a[0]);
+  }
+  function d3_geom_polygonIntersect(c, d, a, b) {
+    var x1 = c[0], x3 = a[0], x21 = d[0] - x1, x43 = b[0] - x3, y1 = c[1], y3 = a[1], y21 = d[1] - y1, y43 = b[1] - y3, ua = (x43 * (y1 - y3) - y43 * (x1 - x3)) / (y43 * x21 - x43 * y21);
+    return [ x1 + ua * x21, y1 + ua * y21 ];
+  }
+  function d3_geom_polygonClosed(coordinates) {
+    var a = coordinates[0], b = coordinates[coordinates.length - 1];
+    return !(a[0] - b[0] || a[1] - b[1]);
+  }
+  var d3_geom_voronoiEdges, d3_geom_voronoiCells, d3_geom_voronoiBeaches, d3_geom_voronoiBeachPool = [], d3_geom_voronoiFirstCircle, d3_geom_voronoiCircles, d3_geom_voronoiCirclePool = [];
+  function d3_geom_voronoiBeach() {
+    d3_geom_voronoiRedBlackNode(this);
+    this.edge = this.site = this.circle = null;
+  }
+  function d3_geom_voronoiCreateBeach(site) {
+    var beach = d3_geom_voronoiBeachPool.pop() || new d3_geom_voronoiBeach();
+    beach.site = site;
+    return beach;
+  }
+  function d3_geom_voronoiDetachBeach(beach) {
+    d3_geom_voronoiDetachCircle(beach);
+    d3_geom_voronoiBeaches.remove(beach);
+    d3_geom_voronoiBeachPool.push(beach);
+    d3_geom_voronoiRedBlackNode(beach);
+  }
+  function d3_geom_voronoiRemoveBeach(beach) {
+    var circle = beach.circle, x = circle.x, y = circle.cy, vertex = {
+      x: x,
+      y: y
+    }, previous = beach.P, next = beach.N, disappearing = [ beach ];
+    d3_geom_voronoiDetachBeach(beach);
+    var lArc = previous;
+    while (lArc.circle && abs(x - lArc.circle.x) < ε && abs(y - lArc.circle.cy) < ε) {
+      previous = lArc.P;
+      disappearing.unshift(lArc);
+      d3_geom_voronoiDetachBeach(lArc);
+      lArc = previous;
+    }
+    disappearing.unshift(lArc);
+    d3_geom_voronoiDetachCircle(lArc);
+    var rArc = next;
+    while (rArc.circle && abs(x - rArc.circle.x) < ε && abs(y - rArc.circle.cy) < ε) {
+      next = rArc.N;
+      disappearing.push(rArc);
+      d3_geom_voronoiDetachBeach(rArc);
+      rArc = next;
+    }
+    disappearing.push(rArc);
+    d3_geom_voronoiDetachCircle(rArc);
+    var nArcs = disappearing.length, iArc;
+    for (iArc = 1; iArc < nArcs; ++iArc) {
+      rArc = disappearing[iArc];
+      lArc = disappearing[iArc - 1];
+      d3_geom_voronoiSetEdgeEnd(rArc.edge, lArc.site, rArc.site, vertex);
+    }
+    lArc = disappearing[0];
+    rArc = disappearing[nArcs - 1];
+    rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, rArc.site, null, vertex);
+    d3_geom_voronoiAttachCircle(lArc);
+    d3_geom_voronoiAttachCircle(rArc);
+  }
+  function d3_geom_voronoiAddBeach(site) {
+    var x = site.x, directrix = site.y, lArc, rArc, dxl, dxr, node = d3_geom_voronoiBeaches._;
+    while (node) {
+      dxl = d3_geom_voronoiLeftBreakPoint(node, directrix) - x;
+      if (dxl > ε) node = node.L; else {
+        dxr = x - d3_geom_voronoiRightBreakPoint(node, directrix);
+        if (dxr > ε) {
+          if (!node.R) {
+            lArc = node;
+            break;
+          }
+          node = node.R;
+        } else {
+          if (dxl > -ε) {
+            lArc = node.P;
+            rArc = node;
+          } else if (dxr > -ε) {
+            lArc = node;
+            rArc = node.N;
+          } else {
+            lArc = rArc = node;
+          }
+          break;
+        }
+      }
+    }
+    var newArc = d3_geom_voronoiCreateBeach(site);
+    d3_geom_voronoiBeaches.insert(lArc, newArc);
+    if (!lArc && !rArc) return;
+    if (lArc === rArc) {
+      d3_geom_voronoiDetachCircle(lArc);
+      rArc = d3_geom_voronoiCreateBeach(lArc.site);
+      d3_geom_voronoiBeaches.insert(newArc, rArc);
+      newArc.edge = rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site);
+      d3_geom_voronoiAttachCircle(lArc);
+      d3_geom_voronoiAttachCircle(rArc);
+      return;
+    }
+    if (!rArc) {
+      newArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site);
+      return;
+    }
+    d3_geom_voronoiDetachCircle(lArc);
+    d3_geom_voronoiDetachCircle(rArc);
+    var lSite = lArc.site, ax = lSite.x, ay = lSite.y, bx = site.x - ax, by = site.y - ay, rSite = rArc.site, cx = rSite.x - ax, cy = rSite.y - ay, d = 2 * (bx * cy - by * cx), hb = bx * bx + by * by, hc = cx * cx + cy * cy, vertex = {
+      x: (cy * hb - by * hc) / d + ax,
+      y: (bx * hc - cx * hb) / d + ay
+    };
+    d3_geom_voronoiSetEdgeEnd(rArc.edge, lSite, rSite, vertex);
+    newArc.edge = d3_geom_voronoiCreateEdge(lSite, site, null, vertex);
+    rArc.edge = d3_geom_voronoiCreateEdge(site, rSite, null, vertex);
+    d3_geom_voronoiAttachCircle(lArc);
+    d3_geom_voronoiAttachCircle(rArc);
+  }
+  function d3_geom_voronoiLeftBreakPoint(arc, directrix) {
+    var site = arc.site, rfocx = site.x, rfocy = site.y, pby2 = rfocy - directrix;
+    if (!pby2) return rfocx;
+    var lArc = arc.P;
+    if (!lArc) return -Infinity;
+    site = lArc.site;
+    var lfocx = site.x, lfocy = site.y, plby2 = lfocy - directrix;
+    if (!plby2) return lfocx;
+    var hl = lfocx - rfocx, aby2 = 1 / pby2 - 1 / plby2, b = hl / plby2;
+    if (aby2) return (-b + Math.sqrt(b * b - 2 * aby2 * (hl * hl / (-2 * plby2) - lfocy + plby2 / 2 + rfocy - pby2 / 2))) / aby2 + rfocx;
+    return (rfocx + lfocx) / 2;
+  }
+  function d3_geom_voronoiRightBreakPoint(arc, directrix) {
+    var rArc = arc.N;
+    if (rArc) return d3_geom_voronoiLeftBreakPoint(rArc, directrix);
+    var site = arc.site;
+    return site.y === directrix ? site.x : Infinity;
+  }
+  function d3_geom_voronoiCell(site) {
+    this.site = site;
+    this.edges = [];
+  }
+  d3_geom_voronoiCell.prototype.prepare = function() {
+    var halfEdges = this.edges, iHalfEdge = halfEdges.length, edge;
+    while (iHalfEdge--) {
+      edge = halfEdges[iHalfEdge].edge;
+      if (!edge.b || !edge.a) halfEdges.splice(iHalfEdge, 1);
+    }
+    halfEdges.sort(d3_geom_voronoiHalfEdgeOrder);
+    return halfEdges.length;
+  };
+  function d3_geom_voronoiCloseCells(extent) {
+    var x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], x2, y2, x3, y3, cells = d3_geom_voronoiCells, iCell = cells.length, cell, iHalfEdge, halfEdges, nHalfEdges, start, end;
+    while (iCell--) {
+      cell = cells[iCell];
+      if (!cell || !cell.prepare()) continue;
+      halfEdges = cell.edges;
+      nHalfEdges = halfEdges.length;
+      iHalfEdge = 0;
+      while (iHalfEdge < nHalfEdges) {
+        end = halfEdges[iHalfEdge].end(), x3 = end.x, y3 = end.y;
+        start = halfEdges[++iHalfEdge % nHalfEdges].start(), x2 = start.x, y2 = start.y;
+        if (abs(x3 - x2) > ε || abs(y3 - y2) > ε) {
+          halfEdges.splice(iHalfEdge, 0, new d3_geom_voronoiHalfEdge(d3_geom_voronoiCreateBorderEdge(cell.site, end, abs(x3 - x0) < ε && y1 - y3 > ε ? {
+            x: x0,
+            y: abs(x2 - x0) < ε ? y2 : y1
+          } : abs(y3 - y1) < ε && x1 - x3 > ε ? {
+            x: abs(y2 - y1) < ε ? x2 : x1,
+            y: y1
+          } : abs(x3 - x1) < ε && y3 - y0 > ε ? {
+            x: x1,
+            y: abs(x2 - x1) < ε ? y2 : y0
+          } : abs(y3 - y0) < ε && x3 - x0 > ε ? {
+            x: abs(y2 - y0) < ε ? x2 : x0,
+            y: y0
+          } : null), cell.site, null));
+          ++nHalfEdges;
+        }
+      }
+    }
+  }
+  function d3_geom_voronoiHalfEdgeOrder(a, b) {
+    return b.angle - a.angle;
+  }
+  function d3_geom_voronoiCircle() {
+    d3_geom_voronoiRedBlackNode(this);
+    this.x = this.y = this.arc = this.site = this.cy = null;
+  }
+  function d3_geom_voronoiAttachCircle(arc) {
+    var lArc = arc.P, rArc = arc.N;
+    if (!lArc || !rArc) return;
+    var lSite = lArc.site, cSite = arc.site, rSite = rArc.site;
+    if (lSite === rSite) return;
+    var bx = cSite.x, by = cSite.y, ax = lSite.x - bx, ay = lSite.y - by, cx = rSite.x - bx, cy = rSite.y - by;
+    var d = 2 * (ax * cy - ay * cx);
+    if (d >= -ε2) return;
+    var ha = ax * ax + ay * ay, hc = cx * cx + cy * cy, x = (cy * ha - ay * hc) / d, y = (ax * hc - cx * ha) / d, cy = y + by;
+    var circle = d3_geom_voronoiCirclePool.pop() || new d3_geom_voronoiCircle();
+    circle.arc = arc;
+    circle.site = cSite;
+    circle.x = x + bx;
+    circle.y = cy + Math.sqrt(x * x + y * y);
+    circle.cy = cy;
+    arc.circle = circle;
+    var before = null, node = d3_geom_voronoiCircles._;
+    while (node) {
+      if (circle.y < node.y || circle.y === node.y && circle.x <= node.x) {
+        if (node.L) node = node.L; else {
+          before = node.P;
+          break;
+        }
+      } else {
+        if (node.R) node = node.R; else {
+          before = node;
+          break;
+        }
+      }
+    }
+    d3_geom_voronoiCircles.insert(before, circle);
+    if (!before) d3_geom_voronoiFirstCircle = circle;
+  }
+  function d3_geom_voronoiDetachCircle(arc) {
+    var circle = arc.circle;
+    if (circle) {
+      if (!circle.P) d3_geom_voronoiFirstCircle = circle.N;
+      d3_geom_voronoiCircles.remove(circle);
+      d3_geom_voronoiCirclePool.push(circle);
+      d3_geom_voronoiRedBlackNode(circle);
+      arc.circle = null;
+    }
+  }
+  function d3_geom_voronoiClipEdges(extent) {
+    var edges = d3_geom_voronoiEdges, clip = d3_geom_clipLine(extent[0][0], extent[0][1], extent[1][0], extent[1][1]), i = edges.length, e;
+    while (i--) {
+      e = edges[i];
+      if (!d3_geom_voronoiConnectEdge(e, extent) || !clip(e) || abs(e.a.x - e.b.x) < ε && abs(e.a.y - e.b.y) < ε) {
+        e.a = e.b = null;
+        edges.splice(i, 1);
+      }
+    }
+  }
+  function d3_geom_voronoiConnectEdge(edge, extent) {
+    var vb = edge.b;
+    if (vb) return true;
+    var va = edge.a, x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], lSite = edge.l, rSite = edge.r, lx = lSite.x, ly = lSite.y, rx = rSite.x, ry = rSite.y, fx = (lx + rx) / 2, fy = (ly + ry) / 2, fm, fb;
+    if (ry === ly) {
+      if (fx < x0 || fx >= x1) return;
+      if (lx > rx) {
+        if (!va) va = {
+          x: fx,
+          y: y0
+        }; else if (va.y >= y1) return;
+        vb = {
+          x: fx,
+          y: y1
+        };
+      } else {
+        if (!va) va = {
+          x: fx,
+          y: y1
+        }; else if (va.y < y0) return;
+        vb = {
+          x: fx,
+          y: y0
+        };
+      }
+    } else {
+      fm = (lx - rx) / (ry - ly);
+      fb = fy - fm * fx;
+      if (fm < -1 || fm > 1) {
+        if (lx > rx) {
+          if (!va) va = {
+            x: (y0 - fb) / fm,
+            y: y0
+          }; else if (va.y >= y1) return;
+          vb = {
+            x: (y1 - fb) / fm,
+            y: y1
+          };
+        } else {
+          if (!va) va = {
+            x: (y1 - fb) / fm,
+            y: y1
+          }; else if (va.y < y0) return;
+          vb = {
+            x: (y0 - fb) / fm,
+            y: y0
+          };
+        }
+      } else {
+        if (ly < ry) {
+          if (!va) va = {
+            x: x0,
+            y: fm * x0 + fb
+          }; else if (va.x >= x1) return;
+          vb = {
+            x: x1,
+            y: fm * x1 + fb
+          };
+        } else {
+          if (!va) va = {
+            x: x1,
+            y: fm * x1 + fb
+          }; else if (va.x < x0) return;
+          vb = {
+            x: x0,
+            y: fm * x0 + fb
+          };
+        }
+      }
+    }
+    edge.a = va;
+    edge.b = vb;
+    return true;
+  }
+  function d3_geom_voronoiEdge(lSite, rSite) {
+    this.l = lSite;
+    this.r = rSite;
+    this.a = this.b = null;
+  }
+  function d3_geom_voronoiCreateEdge(lSite, rSite, va, vb) {
+    var edge = new d3_geom_voronoiEdge(lSite, rSite);
+    d3_geom_voronoiEdges.push(edge);
+    if (va) d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, va);
+    if (vb) d3_geom_voronoiSetEdgeEnd(edge, rSite, lSite, vb);
+    d3_geom_voronoiCells[lSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, lSite, rSite));
+    d3_geom_voronoiCells[rSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, rSite, lSite));
+    return edge;
+  }
+  function d3_geom_voronoiCreateBorderEdge(lSite, va, vb) {
+    var edge = new d3_geom_voronoiEdge(lSite, null);
+    edge.a = va;
+    edge.b = vb;
+    d3_geom_voronoiEdges.push(edge);
+    return edge;
+  }
+  function d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, vertex) {
+    if (!edge.a && !edge.b) {
+      edge.a = vertex;
+      edge.l = lSite;
+      edge.r = rSite;
+    } else if (edge.l === rSite) {
+      edge.b = vertex;
+    } else {
+      edge.a = vertex;
+    }
+  }
+  function d3_geom_voronoiHalfEdge(edge, lSite, rSite) {
+    var va = edge.a, vb = edge.b;
+    this.edge = edge;
+    this.site = lSite;
+    this.angle = rSite ? Math.atan2(rSite.y - lSite.y, rSite.x - lSite.x) : edge.l === lSite ? Math.atan2(vb.x - va.x, va.y - vb.y) : Math.atan2(va.x - vb.x, vb.y - va.y);
+  }
+  d3_geom_voronoiHalfEdge.prototype = {
+    start: function() {
+      return this.edge.l === this.site ? this.edge.a : this.edge.b;
+    },
+    end: function() {
+      return this.edge.l === this.site ? this.edge.b : this.edge.a;
+    }
+  };
+  function d3_geom_voronoiRedBlackTree() {
+    this._ = null;
+  }
+  function d3_geom_voronoiRedBlackNode(node) {
+    node.U = node.C = node.L = node.R = node.P = node.N = null;
+  }
+  d3_geom_voronoiRedBlackTree.prototype = {
+    insert: function(after, node) {
+      var parent, grandpa, uncle;
+      if (after) {
+        node.P = after;
+        node.N = after.N;
+        if (after.N) after.N.P = node;
+        after.N = node;
+        if (after.R) {
+          after = after.R;
+          while (after.L) after = after.L;
+          after.L = node;
+        } else {
+          after.R = node;
+        }
+        parent = after;
+      } else if (this._) {
+        after = d3_geom_voronoiRedBlackFirst(this._);
+        node.P = null;
+        node.N = after;
+        after.P = after.L = node;
+        parent = after;
+      } else {
+        node.P = node.N = null;
+        this._ = node;
+        parent = null;
+      }
+      node.L = node.R = null;
+      node.U = parent;
+      node.C = true;
+      after = node;
+      while (parent && parent.C) {
+        grandpa = parent.U;
+        if (parent === grandpa.L) {
+          uncle = grandpa.R;
+          if (uncle && uncle.C) {
+            parent.C = uncle.C = false;
+            grandpa.C = true;
+            after = grandpa;
+          } else {
+            if (after === parent.R) {
+              d3_geom_voronoiRedBlackRotateLeft(this, parent);
+              after = parent;
+              parent = after.U;
+            }
+            parent.C = false;
+            grandpa.C = true;
+            d3_geom_voronoiRedBlackRotateRight(this, grandpa);
+          }
+        } else {
+          uncle = grandpa.L;
+          if (uncle && uncle.C) {
+            parent.C = uncle.C = false;
+            grandpa.C = true;
+            after = grandpa;
+          } else {
+            if (after === parent.L) {
+              d3_geom_voronoiRedBlackRotateRight(this, parent);
+              after = parent;
+              parent = after.U;
+            }
+            parent.C = false;
+            grandpa.C = true;
+            d3_geom_voronoiRedBlackRotateLeft(this, grandpa);
+          }
+        }
+        parent = after.U;
+      }
+      this._.C = false;
+    },
+    remove: function(node) {
+      if (node.N) node.N.P = node.P;
+      if (node.P) node.P.N = node.N;
+      node.N = node.P = null;
+      var parent = node.U, sibling, left = node.L, right = node.R, next, red;
+      if (!left) next = right; else if (!right) next = left; else next = d3_geom_voronoiRedBlackFirst(right);
+      if (parent) {
+        if (parent.L === node) parent.L = next; else parent.R = next;
+      } else {
+        this._ = next;
+      }
+      if (left && right) {
+        red = next.C;
+        next.C = node.C;
+        next.L = left;
+        left.U = next;
+        if (next !== right) {
+          parent = next.U;
+          next.U = node.U;
+          node = next.R;
+          parent.L = node;
+          next.R = right;
+          right.U = next;
+        } else {
+          next.U = parent;
+          parent = next;
+          node = next.R;
+        }
+      } else {
+        red = node.C;
+        node = next;
+      }
+      if (node) node.U = parent;
+      if (red) return;
+      if (node && node.C) {
+        node.C = false;
+        return;
+      }
+      do {
+        if (node === this._) break;
+        if (node === parent.L) {
+          sibling = parent.R;
+          if (sibling.C) {
+            sibling.C = false;
+            parent.C = true;
+            d3_geom_voronoiRedBlackRotateLeft(this, parent);
+            sibling = parent.R;
+          }
+          if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) {
+            if (!sibling.R || !sibling.R.C) {
+              sibling.L.C = false;
+              sibling.C = true;
+              d3_geom_voronoiRedBlackRotateRight(this, sibling);
+              sibling = parent.R;
+            }
+            sibling.C = parent.C;
+            parent.C = sibling.R.C = false;
+            d3_geom_voronoiRedBlackRotateLeft(this, parent);
+            node = this._;
+            break;
+          }
+        } else {
+          sibling = parent.L;
+          if (sibling.C) {
+            sibling.C = false;
+            parent.C = true;
+            d3_geom_voronoiRedBlackRotateRight(this, parent);
+            sibling = parent.L;
+          }
+          if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) {
+            if (!sibling.L || !sibling.L.C) {
+              sibling.R.C = false;
+              sibling.C = true;
+              d3_geom_voronoiRedBlackRotateLeft(this, sibling);
+              sibling = parent.L;
+            }
+            sibling.C = parent.C;
+            parent.C = sibling.L.C = false;
+            d3_geom_voronoiRedBlackRotateRight(this, parent);
+            node = this._;
+            break;
+          }
+        }
+        sibling.C = true;
+        node = parent;
+        parent = parent.U;
+      } while (!node.C);
+      if (node) node.C = false;
+    }
+  };
+  function d3_geom_voronoiRedBlackRotateLeft(tree, node) {
+    var p = node, q = node.R, parent = p.U;
+    if (parent) {
+      if (parent.L === p) parent.L = q; else parent.R = q;
+    } else {
+      tree._ = q;
+    }
+    q.U = parent;
+    p.U = q;
+    p.R = q.L;
+    if (p.R) p.R.U = p;
+    q.L = p;
+  }
+  function d3_geom_voronoiRedBlackRotateRight(tree, node) {
+    var p = node, q = node.L, parent = p.U;
+    if (parent) {
+      if (parent.L === p) parent.L = q; else parent.R = q;
+    } else {
+      tree._ = q;
+    }
+    q.U = parent;
+    p.U = q;
+    p.L = q.R;
+    if (p.L) p.L.U = p;
+    q.R = p;
+  }
+  function d3_geom_voronoiRedBlackFirst(node) {
+    while (node.L) node = node.L;
+    return node;
+  }
+  function d3_geom_voronoi(sites, bbox) {
+    var site = sites.sort(d3_geom_voronoiVertexOrder).pop(), x0, y0, circle;
+    d3_geom_voronoiEdges = [];
+    d3_geom_voronoiCells = new Array(sites.length);
+    d3_geom_voronoiBeaches = new d3_geom_voronoiRedBlackTree();
+    d3_geom_voronoiCircles = new d3_geom_voronoiRedBlackTree();
+    while (true) {
+      circle = d3_geom_voronoiFirstCircle;
+      if (site && (!circle || site.y < circle.y || site.y === circle.y && site.x < circle.x)) {
+        if (site.x !== x0 || site.y !== y0) {
+          d3_geom_voronoiCells[site.i] = new d3_geom_voronoiCell(site);
+          d3_geom_voronoiAddBeach(site);
+          x0 = site.x, y0 = site.y;
+        }
+        site = sites.pop();
+      } else if (circle) {
+        d3_geom_voronoiRemoveBeach(circle.arc);
+      } else {
+        break;
+      }
+    }
+    if (bbox) d3_geom_voronoiClipEdges(bbox), d3_geom_voronoiCloseCells(bbox);
+    var diagram = {
+      cells: d3_geom_voronoiCells,
+      edges: d3_geom_voronoiEdges
+    };
+    d3_geom_voronoiBeaches = d3_geom_voronoiCircles = d3_geom_voronoiEdges = d3_geom_voronoiCells = null;
+    return diagram;
+  }
+  function d3_geom_voronoiVertexOrder(a, b) {
+    return b.y - a.y || b.x - a.x;
+  }
+  d3.geom.voronoi = function(points) {
+    var x = d3_geom_pointX, y = d3_geom_pointY, fx = x, fy = y, clipExtent = d3_geom_voronoiClipExtent;
+    if (points) return voronoi(points);
+    function voronoi(data) {
+      var polygons = new Array(data.length), x0 = clipExtent[0][0], y0 = clipExtent[0][1], x1 = clipExtent[1][0], y1 = clipExtent[1][1];
+      d3_geom_voronoi(sites(data), clipExtent).cells.forEach(function(cell, i) {
+        var edges = cell.edges, site = cell.site, polygon = polygons[i] = edges.length ? edges.map(function(e) {
+          var s = e.start();
+          return [ s.x, s.y ];
+        }) : site.x >= x0 && site.x <= x1 && site.y >= y0 && site.y <= y1 ? [ [ x0, y1 ], [ x1, y1 ], [ x1, y0 ], [ x0, y0 ] ] : [];
+        polygon.point = data[i];
+      });
+      return polygons;
+    }
+    function sites(data) {
+      return data.map(function(d, i) {
+        return {
+          x: Math.round(fx(d, i) / ε) * ε,
+          y: Math.round(fy(d, i) / ε) * ε,
+          i: i
+        };
+      });
+    }
+    voronoi.links = function(data) {
+      return d3_geom_voronoi(sites(data)).edges.filter(function(edge) {
+        return edge.l && edge.r;
+      }).map(function(edge) {
+        return {
+          source: data[edge.l.i],
+          target: data[edge.r.i]
+        };
+      });
+    };
+    voronoi.triangles = function(data) {
+      var triangles = [];
+      d3_geom_voronoi(sites(data)).cells.forEach(function(cell, i) {
+        var site = cell.site, edges = cell.edges.sort(d3_geom_voronoiHalfEdgeOrder), j = -1, m = edges.length, e0, s0, e1 = edges[m - 1].edge, s1 = e1.l === site ? e1.r : e1.l;
+        while (++j < m) {
+          e0 = e1;
+          s0 = s1;
+          e1 = edges[j].edge;
+          s1 = e1.l === site ? e1.r : e1.l;
+          if (i < s0.i && i < s1.i && d3_geom_voronoiTriangleArea(site, s0, s1) < 0) {
+            triangles.push([ data[i], data[s0.i], data[s1.i] ]);
+          }
+        }
+      });
+      return triangles;
+    };
+    voronoi.x = function(_) {
+      return arguments.length ? (fx = d3_functor(x = _), voronoi) : x;
+    };
+    voronoi.y = function(_) {
+      return arguments.length ? (fy = d3_functor(y = _), voronoi) : y;
+    };
+    voronoi.clipExtent = function(_) {
+      if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent;
+      clipExtent = _ == null ? d3_geom_voronoiClipExtent : _;
+      return voronoi;
+    };
+    voronoi.size = function(_) {
+      if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent && clipExtent[1];
+      return voronoi.clipExtent(_ && [ [ 0, 0 ], _ ]);
+    };
+    return voronoi;
+  };
+  var d3_geom_voronoiClipExtent = [ [ -1e6, -1e6 ], [ 1e6, 1e6 ] ];
+  function d3_geom_voronoiTriangleArea(a, b, c) {
+    return (a.x - c.x) * (b.y - a.y) - (a.x - b.x) * (c.y - a.y);
+  }
+  d3.geom.delaunay = function(vertices) {
+    return d3.geom.voronoi().triangles(vertices);
+  };
+  d3.geom.quadtree = function(points, x1, y1, x2, y2) {
+    var x = d3_geom_pointX, y = d3_geom_pointY, compat;
+    if (compat = arguments.length) {
+      x = d3_geom_quadtreeCompatX;
+      y = d3_geom_quadtreeCompatY;
+      if (compat === 3) {
+        y2 = y1;
+        x2 = x1;
+        y1 = x1 = 0;
+      }
+      return quadtree(points);
+    }
+    function quadtree(data) {
+      var d, fx = d3_functor(x), fy = d3_functor(y), xs, ys, i, n, x1_, y1_, x2_, y2_;
+      if (x1 != null) {
+        x1_ = x1, y1_ = y1, x2_ = x2, y2_ = y2;
+      } else {
+        x2_ = y2_ = -(x1_ = y1_ = Infinity);
+        xs = [], ys = [];
+        n = data.length;
+        if (compat) for (i = 0; i < n; ++i) {
+          d = data[i];
+          if (d.x < x1_) x1_ = d.x;
+          if (d.y < y1_) y1_ = d.y;
+          if (d.x > x2_) x2_ = d.x;
+          if (d.y > y2_) y2_ = d.y;
+          xs.push(d.x);
+          ys.push(d.y);
+        } else for (i = 0; i < n; ++i) {
+          var x_ = +fx(d = data[i], i), y_ = +fy(d, i);
+          if (x_ < x1_) x1_ = x_;
+          if (y_ < y1_) y1_ = y_;
+          if (x_ > x2_) x2_ = x_;
+          if (y_ > y2_) y2_ = y_;
+          xs.push(x_);
+          ys.push(y_);
+        }
+      }
+      var dx = x2_ - x1_, dy = y2_ - y1_;
+      if (dx > dy) y2_ = y1_ + dx; else x2_ = x1_ + dy;
+      function insert(n, d, x, y, x1, y1, x2, y2) {
+        if (isNaN(x) || isNaN(y)) return;
+        if (n.leaf) {
+          var nx = n.x, ny = n.y;
+          if (nx != null) {
+            if (abs(nx - x) + abs(ny - y) < .01) {
+              insertChild(n, d, x, y, x1, y1, x2, y2);
+            } else {
+              var nPoint = n.point;
+              n.x = n.y = n.point = null;
+              insertChild(n, nPoint, nx, ny, x1, y1, x2, y2);
+              insertChild(n, d, x, y, x1, y1, x2, y2);
+            }
+          } else {
+            n.x = x, n.y = y, n.point = d;
+          }
+        } else {
+          insertChild(n, d, x, y, x1, y1, x2, y2);
+        }
+      }
+      function insertChild(n, d, x, y, x1, y1, x2, y2) {
+        var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, right = x >= sx, bottom = y >= sy, i = (bottom << 1) + right;
+        n.leaf = false;
+        n = n.nodes[i] || (n.nodes[i] = d3_geom_quadtreeNode());
+        if (right) x1 = sx; else x2 = sx;
+        if (bottom) y1 = sy; else y2 = sy;
+        insert(n, d, x, y, x1, y1, x2, y2);
+      }
+      var root = d3_geom_quadtreeNode();
+      root.add = function(d) {
+        insert(root, d, +fx(d, ++i), +fy(d, i), x1_, y1_, x2_, y2_);
+      };
+      root.visit = function(f) {
+        d3_geom_quadtreeVisit(f, root, x1_, y1_, x2_, y2_);
+      };
+      i = -1;
+      if (x1 == null) {
+        while (++i < n) {
+          insert(root, data[i], xs[i], ys[i], x1_, y1_, x2_, y2_);
+        }
+        --i;
+      } else data.forEach(root.add);
+      xs = ys = data = d = null;
+      return root;
+    }
+    quadtree.x = function(_) {
+      return arguments.length ? (x = _, quadtree) : x;
+    };
+    quadtree.y = function(_) {
+      return arguments.length ? (y = _, quadtree) : y;
+    };
+    quadtree.extent = function(_) {
+      if (!arguments.length) return x1 == null ? null : [ [ x1, y1 ], [ x2, y2 ] ];
+      if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = +_[0][0], y1 = +_[0][1], x2 = +_[1][0], 
+      y2 = +_[1][1];
+      return quadtree;
+    };
+    quadtree.size = function(_) {
+      if (!arguments.length) return x1 == null ? null : [ x2 - x1, y2 - y1 ];
+      if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = y1 = 0, x2 = +_[0], y2 = +_[1];
+      return quadtree;
+    };
+    return quadtree;
+  };
+  function d3_geom_quadtreeCompatX(d) {
+    return d.x;
+  }
+  function d3_geom_quadtreeCompatY(d) {
+    return d.y;
+  }
+  function d3_geom_quadtreeNode() {
+    return {
+      leaf: true,
+      nodes: [],
+      point: null,
+      x: null,
+      y: null
+    };
+  }
+  function d3_geom_quadtreeVisit(f, node, x1, y1, x2, y2) {
+    if (!f(node, x1, y1, x2, y2)) {
+      var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, children = node.nodes;
+      if (children[0]) d3_geom_quadtreeVisit(f, children[0], x1, y1, sx, sy);
+      if (children[1]) d3_geom_quadtreeVisit(f, children[1], sx, y1, x2, sy);
+      if (children[2]) d3_geom_quadtreeVisit(f, children[2], x1, sy, sx, y2);
+      if (children[3]) d3_geom_quadtreeVisit(f, children[3], sx, sy, x2, y2);
+    }
+  }
+  d3.interpolateRgb = d3_interpolateRgb;
+  function d3_interpolateRgb(a, b) {
+    a = d3.rgb(a);
+    b = d3.rgb(b);
+    var ar = a.r, ag = a.g, ab = a.b, br = b.r - ar, bg = b.g - ag, bb = b.b - ab;
+    return function(t) {
+      return "#" + d3_rgb_hex(Math.round(ar + br * t)) + d3_rgb_hex(Math.round(ag + bg * t)) + d3_rgb_hex(Math.round(ab + bb * t));
+    };
+  }
+  d3.interpolateObject = d3_interpolateObject;
+  function d3_interpolateObject(a, b) {
+    var i = {}, c = {}, k;
+    for (k in a) {
+      if (k in b) {
+        i[k] = d3_interpolate(a[k], b[k]);
+      } else {
+        c[k] = a[k];
+      }
+    }
+    for (k in b) {
+      if (!(k in a)) {
+        c[k] = b[k];
+      }
+    }
+    return function(t) {
+      for (k in i) c[k] = i[k](t);
+      return c;
+    };
+  }
+  d3.interpolateNumber = d3_interpolateNumber;
+  function d3_interpolateNumber(a, b) {
+    b -= a = +a;
+    return function(t) {
+      return a + b * t;
+    };
+  }
+  d3.interpolateString = d3_interpolateString;
+  function d3_interpolateString(a, b) {
+    var m, i, j, s0 = 0, s1 = 0, s = [], q = [], n, o;
+    a = a + "", b = b + "";
+    d3_interpolate_number.lastIndex = 0;
+    for (i = 0; m = d3_interpolate_number.exec(b); ++i) {
+      if (m.index) s.push(b.substring(s0, s1 = m.index));
+      q.push({
+        i: s.length,
+        x: m[0]
+      });
+      s.push(null);
+      s0 = d3_interpolate_number.lastIndex;
+    }
+    if (s0 < b.length) s.push(b.substring(s0));
+    for (i = 0, n = q.length; (m = d3_interpolate_number.exec(a)) && i < n; ++i) {
+      o = q[i];
+      if (o.x == m[0]) {
+        if (o.i) {
+          if (s[o.i + 1] == null) {
+            s[o.i - 1] += o.x;
+            s.splice(o.i, 1);
+            for (j = i + 1; j < n; ++j) q[j].i--;
+          } else {
+            s[o.i - 1] += o.x + s[o.i + 1];
+            s.splice(o.i, 2);
+            for (j = i + 1; j < n; ++j) q[j].i -= 2;
+          }
+        } else {
+          if (s[o.i + 1] == null) {
+            s[o.i] = o.x;
+          } else {
+            s[o.i] = o.x + s[o.i + 1];
+            s.splice(o.i + 1, 1);
+            for (j = i + 1; j < n; ++j) q[j].i--;
+          }
+        }
+        q.splice(i, 1);
+        n--;
+        i--;
+      } else {
+        o.x = d3_interpolateNumber(parseFloat(m[0]), parseFloat(o.x));
+      }
+    }
+    while (i < n) {
+      o = q.pop();
+      if (s[o.i + 1] == null) {
+        s[o.i] = o.x;
+      } else {
+        s[o.i] = o.x + s[o.i + 1];
+        s.splice(o.i + 1, 1);
+      }
+      n--;
+    }
+    if (s.length === 1) {
+      return s[0] == null ? (o = q[0].x, function(t) {
+        return o(t) + "";
+      }) : function() {
+        return b;
+      };
+    }
+    return function(t) {
+      for (i = 0; i < n; ++i) s[(o = q[i]).i] = o.x(t);
+      return s.join("");
+    };
+  }
+  var d3_interpolate_number = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g;
+  d3.interpolate = d3_interpolate;
+  function d3_interpolate(a, b) {
+    var i = d3.interpolators.length, f;
+    while (--i >= 0 && !(f = d3.interpolators[i](a, b))) ;
+    return f;
+  }
+  d3.interpolators = [ function(a, b) {
+    var t = typeof b;
+    return (t === "string" ? d3_rgb_names.has(b) || /^(#|rgb\(|hsl\()/.test(b) ? d3_interpolateRgb : d3_interpolateString : b instanceof d3_Color ? d3_interpolateRgb : Array.isArray(b) ? d3_interpolateArray : t === "object" && isNaN(b) ? d3_interpolateObject : d3_interpolateNumber)(a, b);
+  } ];
+  d3.interpolateArray = d3_interpolateArray;
+  function d3_interpolateArray(a, b) {
+    var x = [], c = [], na = a.length, nb = b.length, n0 = Math.min(a.length, b.length), i;
+    for (i = 0; i < n0; ++i) x.push(d3_interpolate(a[i], b[i]));
+    for (;i < na; ++i) c[i] = a[i];
+    for (;i < nb; ++i) c[i] = b[i];
+    return function(t) {
+      for (i = 0; i < n0; ++i) c[i] = x[i](t);
+      return c;
+    };
+  }
+  var d3_ease_default = function() {
+    return d3_identity;
+  };
+  var d3_ease = d3.map({
+    linear: d3_ease_default,
+    poly: d3_ease_poly,
+    quad: function() {
+      return d3_ease_quad;
+    },
+    cubic: function() {
+      return d3_ease_cubic;
+    },
+    sin: function() {
+      return d3_ease_sin;
+    },
+    exp: function() {
+      return d3_ease_exp;
+    },
+    circle: function() {
+      return d3_ease_circle;
+    },
+    elastic: d3_ease_elastic,
+    back: d3_ease_back,
+    bounce: function() {
+      return d3_ease_bounce;
+    }
+  });
+  var d3_ease_mode = d3.map({
+    "in": d3_identity,
+    out: d3_ease_reverse,
+    "in-out": d3_ease_reflect,
+    "out-in": function(f) {
+      return d3_ease_reflect(d3_ease_reverse(f));
+    }
+  });
+  d3.ease = function(name) {
+    var i = name.indexOf("-"), t = i >= 0 ? name.substring(0, i) : name, m = i >= 0 ? name.substring(i + 1) : "in";
+    t = d3_ease.get(t) || d3_ease_default;
+    m = d3_ease_mode.get(m) || d3_identity;
+    return d3_ease_clamp(m(t.apply(null, d3_arraySlice.call(arguments, 1))));
+  };
+  function d3_ease_clamp(f) {
+    return function(t) {
+      return t <= 0 ? 0 : t >= 1 ? 1 : f(t);
+    };
+  }
+  function d3_ease_reverse(f) {
+    return function(t) {
+      return 1 - f(1 - t);
+    };
+  }
+  function d3_ease_reflect(f) {
+    return function(t) {
+      return .5 * (t < .5 ? f(2 * t) : 2 - f(2 - 2 * t));
+    };
+  }
+  function d3_ease_quad(t) {
+    return t * t;
+  }
+  function d3_ease_cubic(t) {
+    return t * t * t;
+  }
+  function d3_ease_cubicInOut(t) {
+    if (t <= 0) return 0;
+    if (t >= 1) return 1;
+    var t2 = t * t, t3 = t2 * t;
+    return 4 * (t < .5 ? t3 : 3 * (t - t2) + t3 - .75);
+  }
+  function d3_ease_poly(e) {
+    return function(t) {
+      return Math.pow(t, e);
+    };
+  }
+  function d3_ease_sin(t) {
+    return 1 - Math.cos(t * halfπ);
+  }
+  function d3_ease_exp(t) {
+    return Math.pow(2, 10 * (t - 1));
+  }
+  function d3_ease_circle(t) {
+    return 1 - Math.sqrt(1 - t * t);
+  }
+  function d3_ease_elastic(a, p) {
+    var s;
+    if (arguments.length < 2) p = .45;
+    if (arguments.length) s = p / τ * Math.asin(1 / a); else a = 1, s = p / 4;
+    return function(t) {
+      return 1 + a * Math.pow(2, -10 * t) * Math.sin((t - s) * τ / p);
+    };
+  }
+  function d3_ease_back(s) {
+    if (!s) s = 1.70158;
+    return function(t) {
+      return t * t * ((s + 1) * t - s);
+    };
+  }
+  function d3_ease_bounce(t) {
+    return t < 1 / 2.75 ? 7.5625 * t * t : t < 2 / 2.75 ? 7.5625 * (t -= 1.5 / 2.75) * t + .75 : t < 2.5 / 2.75 ? 7.5625 * (t -= 2.25 / 2.75) * t + .9375 : 7.5625 * (t -= 2.625 / 2.75) * t + .984375;
+  }
+  d3.interpolateHcl = d3_interpolateHcl;
+  function d3_interpolateHcl(a, b) {
+    a = d3.hcl(a);
+    b = d3.hcl(b);
+    var ah = a.h, ac = a.c, al = a.l, bh = b.h - ah, bc = b.c - ac, bl = b.l - al;
+    if (isNaN(bc)) bc = 0, ac = isNaN(ac) ? b.c : ac;
+    if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360;
+    return function(t) {
+      return d3_hcl_lab(ah + bh * t, ac + bc * t, al + bl * t) + "";
+    };
+  }
+  d3.interpolateHsl = d3_interpolateHsl;
+  function d3_interpolateHsl(a, b) {
+    a = d3.hsl(a);
+    b = d3.hsl(b);
+    var ah = a.h, as = a.s, al = a.l, bh = b.h - ah, bs = b.s - as, bl = b.l - al;
+    if (isNaN(bs)) bs = 0, as = isNaN(as) ? b.s : as;
+    if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360;
+    return function(t) {
+      return d3_hsl_rgb(ah + bh * t, as + bs * t, al + bl * t) + "";
+    };
+  }
+  d3.interpolateLab = d3_interpolateLab;
+  function d3_interpolateLab(a, b) {
+    a = d3.lab(a);
+    b = d3.lab(b);
+    var al = a.l, aa = a.a, ab = a.b, bl = b.l - al, ba = b.a - aa, bb = b.b - ab;
+    return function(t) {
+      return d3_lab_rgb(al + bl * t, aa + ba * t, ab + bb * t) + "";
+    };
+  }
+  d3.interpolateRound = d3_interpolateRound;
+  function d3_interpolateRound(a, b) {
+    b -= a;
+    return function(t) {
+      return Math.round(a + b * t);
+    };
+  }
+  d3.transform = function(string) {
+    var g = d3_document.createElementNS(d3.ns.prefix.svg, "g");
+    return (d3.transform = function(string) {
+      if (string != null) {
+        g.setAttribute("transform", string);
+        var t = g.transform.baseVal.consolidate();
+      }
+      return new d3_transform(t ? t.matrix : d3_transformIdentity);
+    })(string);
+  };
+  function d3_transform(m) {
+    var r0 = [ m.a, m.b ], r1 = [ m.c, m.d ], kx = d3_transformNormalize(r0), kz = d3_transformDot(r0, r1), ky = d3_transformNormalize(d3_transformCombine(r1, r0, -kz)) || 0;
+    if (r0[0] * r1[1] < r1[0] * r0[1]) {
+      r0[0] *= -1;
+      r0[1] *= -1;
+      kx *= -1;
+      kz *= -1;
+    }
+    this.rotate = (kx ? Math.atan2(r0[1], r0[0]) : Math.atan2(-r1[0], r1[1])) * d3_degrees;
+    this.translate = [ m.e, m.f ];
+    this.scale = [ kx, ky ];
+    this.skew = ky ? Math.atan2(kz, ky) * d3_degrees : 0;
+  }
+  d3_transform.prototype.toString = function() {
+    return "translate(" + this.translate + ")rotate(" + this.rotate + ")skewX(" + this.skew + ")scale(" + this.scale + ")";
+  };
+  function d3_transformDot(a, b) {
+    return a[0] * b[0] + a[1] * b[1];
+  }
+  function d3_transformNormalize(a) {
+    var k = Math.sqrt(d3_transformDot(a, a));
+    if (k) {
+      a[0] /= k;
+      a[1] /= k;
+    }
+    return k;
+  }
+  function d3_transformCombine(a, b, k) {
+    a[0] += k * b[0];
+    a[1] += k * b[1];
+    return a;
+  }
+  var d3_transformIdentity = {
+    a: 1,
+    b: 0,
+    c: 0,
+    d: 1,
+    e: 0,
+    f: 0
+  };
+  d3.interpolateTransform = d3_interpolateTransform;
+  function d3_interpolateTransform(a, b) {
+    var s = [], q = [], n, A = d3.transform(a), B = d3.transform(b), ta = A.translate, tb = B.translate, ra = A.rotate, rb = B.rotate, wa = A.skew, wb = B.skew, ka = A.scale, kb = B.scale;
+    if (ta[0] != tb[0] || ta[1] != tb[1]) {
+      s.push("translate(", null, ",", null, ")");
+      q.push({
+        i: 1,
+        x: d3_interpolateNumber(ta[0], tb[0])
+      }, {
+        i: 3,
+        x: d3_interpolateNumber(ta[1], tb[1])
+      });
+    } else if (tb[0] || tb[1]) {
+      s.push("translate(" + tb + ")");
+    } else {
+      s.push("");
+    }
+    if (ra != rb) {
+      if (ra - rb > 180) rb += 360; else if (rb - ra > 180) ra += 360;
+      q.push({
+        i: s.push(s.pop() + "rotate(", null, ")") - 2,
+        x: d3_interpolateNumber(ra, rb)
+      });
+    } else if (rb) {
+      s.push(s.pop() + "rotate(" + rb + ")");
+    }
+    if (wa != wb) {
+      q.push({
+        i: s.push(s.pop() + "skewX(", null, ")") - 2,
+        x: d3_interpolateNumber(wa, wb)
+      });
+    } else if (wb) {
+      s.push(s.pop() + "skewX(" + wb + ")");
+    }
+    if (ka[0] != kb[0] || ka[1] != kb[1]) {
+      n = s.push(s.pop() + "scale(", null, ",", null, ")");
+      q.push({
+        i: n - 4,
+        x: d3_interpolateNumber(ka[0], kb[0])
+      }, {
+        i: n - 2,
+        x: d3_interpolateNumber(ka[1], kb[1])
+      });
+    } else if (kb[0] != 1 || kb[1] != 1) {
+      s.push(s.pop() + "scale(" + kb + ")");
+    }
+    n = q.length;
+    return function(t) {
+      var i = -1, o;
+      while (++i < n) s[(o = q[i]).i] = o.x(t);
+      return s.join("");
+    };
+  }
+  function d3_uninterpolateNumber(a, b) {
+    b = b - (a = +a) ? 1 / (b - a) : 0;
+    return function(x) {
+      return (x - a) * b;
+    };
+  }
+  function d3_uninterpolateClamp(a, b) {
+    b = b - (a = +a) ? 1 / (b - a) : 0;
+    return function(x) {
+      return Math.max(0, Math.min(1, (x - a) * b));
+    };
+  }
+  d3.layout = {};
+  d3.layout.bundle = function() {
+    return function(links) {
+      var paths = [], i = -1, n = links.length;
+      while (++i < n) paths.push(d3_layout_bundlePath(links[i]));
+      return paths;
+    };
+  };
+  function d3_layout_bundlePath(link) {
+    var start = link.source, end = link.target, lca = d3_layout_bundleLeastCommonAncestor(start, end), points = [ start ];
+    while (start !== lca) {
+      start = start.parent;
+      points.push(start);
+    }
+    var k = points.length;
+    while (end !== lca) {
+      points.splice(k, 0, end);
+      end = end.parent;
+    }
+    return points;
+  }
+  function d3_layout_bundleAncestors(node) {
+    var ancestors = [], parent = node.parent;
+    while (parent != null) {
+      ancestors.push(node);
+      node = parent;
+      parent = parent.parent;
+    }
+    ancestors.push(node);
+    return ancestors;
+  }
+  function d3_layout_bundleLeastCommonAncestor(a, b) {
+    if (a === b) return a;
+    var aNodes = d3_layout_bundleAncestors(a), bNodes = d3_layout_bundleAncestors(b), aNode = aNodes.pop(), bNode = bNodes.pop(), sharedNode = null;
+    while (aNode === bNode) {
+      sharedNode = aNode;
+      aNode = aNodes.pop();
+      bNode = bNodes.pop();
+    }
+    return sharedNode;
+  }
+  d3.layout.chord = function() {
+    var chord = {}, chords, groups, matrix, n, padding = 0, sortGroups, sortSubgroups, sortChords;
+    function relayout() {
+      var subgroups = {}, groupSums = [], groupIndex = d3.range(n), subgroupIndex = [], k, x, x0, i, j;
+      chords = [];
+      groups = [];
+      k = 0, i = -1;
+      while (++i < n) {
+        x = 0, j = -1;
+        while (++j < n) {
+          x += matrix[i][j];
+        }
+        groupSums.push(x);
+        subgroupIndex.push(d3.range(n));
+        k += x;
+      }
+      if (sortGroups) {
+        groupIndex.sort(function(a, b) {
+          return sortGroups(groupSums[a], groupSums[b]);
+        });
+      }
+      if (sortSubgroups) {
+        subgroupIndex.forEach(function(d, i) {
+          d.sort(function(a, b) {
+            return sortSubgroups(matrix[i][a], matrix[i][b]);
+          });
+        });
+      }
+      k = (τ - padding * n) / k;
+      x = 0, i = -1;
+      while (++i < n) {
+        x0 = x, j = -1;
+        while (++j < n) {
+          var di = groupIndex[i], dj = subgroupIndex[di][j], v = matrix[di][dj], a0 = x, a1 = x += v * k;
+          subgroups[di + "-" + dj] = {
+            index: di,
+            subindex: dj,
+            startAngle: a0,
+            endAngle: a1,
+            value: v
+          };
+        }
+        groups[di] = {
+          index: di,
+          startAngle: x0,
+          endAngle: x,
+          value: (x - x0) / k
+        };
+        x += padding;
+      }
+      i = -1;
+      while (++i < n) {
+        j = i - 1;
+        while (++j < n) {
+          var source = subgroups[i + "-" + j], target = subgroups[j + "-" + i];
+          if (source.value || target.value) {
+            chords.push(source.value < target.value ? {
+              source: target,
+              target: source
+            } : {
+              source: source,
+              target: target
+            });
+          }
+        }
+      }
+      if (sortChords) resort();
+    }
+    function resort() {
+      chords.sort(function(a, b) {
+        return sortChords((a.source.value + a.target.value) / 2, (b.source.value + b.target.value) / 2);
+      });
+    }
+    chord.matrix = function(x) {
+      if (!arguments.length) return matrix;
+      n = (matrix = x) && matrix.length;
+      chords = groups = null;
+      return chord;
+    };
+    chord.padding = function(x) {
+      if (!arguments.length) return padding;
+      padding = x;
+      chords = groups = null;
+      return chord;
+    };
+    chord.sortGroups = function(x) {
+      if (!arguments.length) return sortGroups;
+      sortGroups = x;
+      chords = groups = null;
+      return chord;
+    };
+    chord.sortSubgroups = function(x) {
+      if (!arguments.length) return sortSubgroups;
+      sortSubgroups = x;
+      chords = null;
+      return chord;
+    };
+    chord.sortChords = function(x) {
+      if (!arguments.length) return sortChords;
+      sortChords = x;
+      if (chords) resort();
+      return chord;
+    };
+    chord.chords = function() {
+      if (!chords) relayout();
+      return chords;
+    };
+    chord.groups = function() {
+      if (!groups) relayout();
+      return groups;
+    };
+    return chord;
+  };
+  d3.layout.force = function() {
+    var force = {}, event = d3.dispatch("start", "tick", "end"), size = [ 1, 1 ], drag, alpha, friction = .9, linkDistance = d3_layout_forceLinkDistance, linkStrength = d3_layout_forceLinkStrength, charge = -30, chargeDistance2 = d3_layout_forceChargeDistance2, gravity = .1, theta2 = .64, nodes = [], links = [], distances, strengths, charges;
+    function repulse(node) {
+      return function(quad, x1, _, x2) {
+        if (quad.point !== node) {
+          var dx = quad.cx - node.x, dy = quad.cy - node.y, dw = x2 - x1, dn = dx * dx + dy * dy;
+          if (dw * dw / theta2 < dn) {
+            if (dn < chargeDistance2) {
+              var k = quad.charge / dn;
+              node.px -= dx * k;
+              node.py -= dy * k;
+            }
+            return true;
+          }
+          if (quad.point && dn && dn < chargeDistance2) {
+            var k = quad.pointCharge / dn;
+            node.px -= dx * k;
+            node.py -= dy * k;
+          }
+        }
+        return !quad.charge;
+      };
+    }
+    force.tick = function() {
+      if ((alpha *= .99) < .005) {
+        event.end({
+          type: "end",
+          alpha: alpha = 0
+        });
+        return true;
+      }
+      var n = nodes.length, m = links.length, q, i, o, s, t, l, k, x, y;
+      for (i = 0; i < m; ++i) {
+        o = links[i];
+        s = o.source;
+        t = o.target;
+        x = t.x - s.x;
+        y = t.y - s.y;
+        if (l = x * x + y * y) {
+          l = alpha * strengths[i] * ((l = Math.sqrt(l)) - distances[i]) / l;
+          x *= l;
+          y *= l;
+          t.x -= x * (k = s.weight / (t.weight + s.weight));
+          t.y -= y * k;
+          s.x += x * (k = 1 - k);
+          s.y += y * k;
+        }
+      }
+      if (k = alpha * gravity) {
+        x = size[0] / 2;
+        y = size[1] / 2;
+        i = -1;
+        if (k) while (++i < n) {
+          o = nodes[i];
+          o.x += (x - o.x) * k;
+          o.y += (y - o.y) * k;
+        }
+      }
+      if (charge) {
+        d3_layout_forceAccumulate(q = d3.geom.quadtree(nodes), alpha, charges);
+        i = -1;
+        while (++i < n) {
+          if (!(o = nodes[i]).fixed) {
+            q.visit(repulse(o));
+          }
+        }
+      }
+      i = -1;
+      while (++i < n) {
+        o = nodes[i];
+        if (o.fixed) {
+          o.x = o.px;
+          o.y = o.py;
+        } else {
+          o.x -= (o.px - (o.px = o.x)) * friction;
+          o.y -= (o.py - (o.py = o.y)) * friction;
+        }
+      }
+      event.tick({
+        type: "tick",
+        alpha: alpha
+      });
+    };
+    force.nodes = function(x) {
+      if (!arguments.length) return nodes;
+      nodes = x;
+      return force;
+    };
+    force.links = function(x) {
+      if (!arguments.length) return links;
+      links = x;
+      return force;
+    };
+    force.size = function(x) {
+      if (!arguments.length) return size;
+      size = x;
+      return force;
+    };
+    force.linkDistance = function(x) {
+      if (!arguments.length) return linkDistance;
+      linkDistance = typeof x === "function" ? x : +x;
+      return force;
+    };
+    force.distance = force.linkDistance;
+    force.linkStrength = function(x) {
+      if (!arguments.length) return linkStrength;
+      linkStrength = typeof x === "function" ? x : +x;
+      return force;
+    };
+    force.friction = function(x) {
+      if (!arguments.length) return friction;
+      friction = +x;
+      return force;
+    };
+    force.charge = function(x) {
+      if (!arguments.length) return charge;
+      charge = typeof x === "function" ? x : +x;
+      return force;
+    };
+    force.chargeDistance = function(x) {
+      if (!arguments.length) return Math.sqrt(chargeDistance2);
+      chargeDistance2 = x * x;
+      return force;
+    };
+    force.gravity = function(x) {
+      if (!arguments.length) return gravity;
+      gravity = +x;
+      return force;
+    };
+    force.theta = function(x) {
+      if (!arguments.length) return Math.sqrt(theta2);
+      theta2 = x * x;
+      return force;
+    };
+    force.alpha = function(x) {
+      if (!arguments.length) return alpha;
+      x = +x;
+      if (alpha) {
+        if (x > 0) alpha = x; else alpha = 0;
+      } else if (x > 0) {
+        event.start({
+          type: "start",
+          alpha: alpha = x
+        });
+        d3.timer(force.tick);
+      }
+      return force;
+    };
+    force.start = function() {
+      var i, n = nodes.length, m = links.length, w = size[0], h = size[1], neighbors, o;
+      for (i = 0; i < n; ++i) {
+        (o = nodes[i]).index = i;
+        o.weight = 0;
+      }
+      for (i = 0; i < m; ++i) {
+        o = links[i];
+        if (typeof o.source == "number") o.source = nodes[o.source];
+        if (typeof o.target == "number") o.target = nodes[o.target];
+        ++o.source.weight;
+        ++o.target.weight;
+      }
+      for (i = 0; i < n; ++i) {
+        o = nodes[i];
+        if (isNaN(o.x)) o.x = position("x", w);
+        if (isNaN(o.y)) o.y = position("y", h);
+        if (isNaN(o.px)) o.px = o.x;
+        if (isNaN(o.py)) o.py = o.y;
+      }
+      distances = [];
+      if (typeof linkDistance === "function") for (i = 0; i < m; ++i) distances[i] = +linkDistance.call(this, links[i], i); else for (i = 0; i < m; ++i) distances[i] = linkDistance;
+      strengths = [];
+      if (typeof linkStrength === "function") for (i = 0; i < m; ++i) strengths[i] = +linkStrength.call(this, links[i], i); else for (i = 0; i < m; ++i) strengths[i] = linkStrength;
+      charges = [];
+      if (typeof charge === "function") for (i = 0; i < n; ++i) charges[i] = +charge.call(this, nodes[i], i); else for (i = 0; i < n; ++i) charges[i] = charge;
+      function position(dimension, size) {
+        if (!neighbors) {
+          neighbors = new Array(n);
+          for (j = 0; j < n; ++j) {
+            neighbors[j] = [];
+          }
+          for (j = 0; j < m; ++j) {
+            var o = links[j];
+            neighbors[o.source.index].push(o.target);
+            neighbors[o.target.index].push(o.source);
+          }
+        }
+        var candidates = neighbors[i], j = -1, m = candidates.length, x;
+        while (++j < m) if (!isNaN(x = candidates[j][dimension])) return x;
+        return Math.random() * size;
+      }
+      return force.resume();
+    };
+    force.resume = function() {
+      return force.alpha(.1);
+    };
+    force.stop = function() {
+      return force.alpha(0);
+    };
+    force.drag = function() {
+      if (!drag) drag = d3.behavior.drag().origin(d3_identity).on("dragstart.force", d3_layout_forceDragstart).on("drag.force", dragmove).on("dragend.force", d3_layout_forceDragend);
+      if (!arguments.length) return drag;
+      this.on("mouseover.force", d3_layout_forceMouseover).on("mouseout.force", d3_layout_forceMouseout).call(drag);
+    };
+    function dragmove(d) {
+      d.px = d3.event.x, d.py = d3.event.y;
+      force.resume();
+    }
+    return d3.rebind(force, event, "on");
+  };
+  function d3_layout_forceDragstart(d) {
+    d.fixed |= 2;
+  }
+  function d3_layout_forceDragend(d) {
+    d.fixed &= ~6;
+  }
+  function d3_layout_forceMouseover(d) {
+    d.fixed |= 4;
+    d.px = d.x, d.py = d.y;
+  }
+  function d3_layout_forceMouseout(d) {
+    d.fixed &= ~4;
+  }
+  function d3_layout_forceAccumulate(quad, alpha, charges) {
+    var cx = 0, cy = 0;
+    quad.charge = 0;
+    if (!quad.leaf) {
+      var nodes = quad.nodes, n = nodes.length, i = -1, c;
+      while (++i < n) {
+        c = nodes[i];
+        if (c == null) continue;
+        d3_layout_forceAccumulate(c, alpha, charges);
+        quad.charge += c.charge;
+        cx += c.charge * c.cx;
+        cy += c.charge * c.cy;
+      }
+    }
+    if (quad.point) {
+      if (!quad.leaf) {
+        quad.point.x += Math.random() - .5;
+        quad.point.y += Math.random() - .5;
+      }
+      var k = alpha * charges[quad.point.index];
+      quad.charge += quad.pointCharge = k;
+      cx += k * quad.point.x;
+      cy += k * quad.point.y;
+    }
+    quad.cx = cx / quad.charge;
+    quad.cy = cy / quad.charge;
+  }
+  var d3_layout_forceLinkDistance = 20, d3_layout_forceLinkStrength = 1, d3_layout_forceChargeDistance2 = Infinity;
+  d3.layout.hierarchy = function() {
+    var sort = d3_layout_hierarchySort, children = d3_layout_hierarchyChildren, value = d3_layout_hierarchyValue;
+    function recurse(node, depth, nodes) {
+      var childs = children.call(hierarchy, node, depth);
+      node.depth = depth;
+      nodes.push(node);
+      if (childs && (n = childs.length)) {
+        var i = -1, n, c = node.children = new Array(n), v = 0, j = depth + 1, d;
+        while (++i < n) {
+          d = c[i] = recurse(childs[i], j, nodes);
+          d.parent = node;
+          v += d.value;
+        }
+        if (sort) c.sort(sort);
+        if (value) node.value = v;
+      } else {
+        delete node.children;
+        if (value) {
+          node.value = +value.call(hierarchy, node, depth) || 0;
+        }
+      }
+      return node;
+    }
+    function revalue(node, depth) {
+      var children = node.children, v = 0;
+      if (children && (n = children.length)) {
+        var i = -1, n, j = depth + 1;
+        while (++i < n) v += revalue(children[i], j);
+      } else if (value) {
+        v = +value.call(hierarchy, node, depth) || 0;
+      }
+      if (value) node.value = v;
+      return v;
+    }
+    function hierarchy(d) {
+      var nodes = [];
+      recurse(d, 0, nodes);
+      return nodes;
+    }
+    hierarchy.sort = function(x) {
+      if (!arguments.length) return sort;
+      sort = x;
+      return hierarchy;
+    };
+    hierarchy.children = function(x) {
+      if (!arguments.length) return children;
+      children = x;
+      return hierarchy;
+    };
+    hierarchy.value = function(x) {
+      if (!arguments.length) return value;
+      value = x;
+      return hierarchy;
+    };
+    hierarchy.revalue = function(root) {
+      revalue(root, 0);
+      return root;
+    };
+    return hierarchy;
+  };
+  function d3_layout_hierarchyRebind(object, hierarchy) {
+    d3.rebind(object, hierarchy, "sort", "children", "value");
+    object.nodes = object;
+    object.links = d3_layout_hierarchyLinks;
+    return object;
+  }
+  function d3_layout_hierarchyChildren(d) {
+    return d.children;
+  }
+  function d3_layout_hierarchyValue(d) {
+    return d.value;
+  }
+  function d3_layout_hierarchySort(a, b) {
+    return b.value - a.value;
+  }
+  function d3_layout_hierarchyLinks(nodes) {
+    return d3.merge(nodes.map(function(parent) {
+      return (parent.children || []).map(function(child) {
+        return {
+          source: parent,
+          target: child
+        };
+      });
+    }));
+  }
+  d3.layout.partition = function() {
+    var hierarchy = d3.layout.hierarchy(), size = [ 1, 1 ];
+    function position(node, x, dx, dy) {
+      var children = node.children;
+      node.x = x;
+      node.y = node.depth * dy;
+      node.dx = dx;
+      node.dy = dy;
+      if (children && (n = children.length)) {
+        var i = -1, n, c, d;
+        dx = node.value ? dx / node.value : 0;
+        while (++i < n) {
+          position(c = children[i], x, d = c.value * dx, dy);
+          x += d;
+        }
+      }
+    }
+    function depth(node) {
+      var children = node.children, d = 0;
+      if (children && (n = children.length)) {
+        var i = -1, n;
+        while (++i < n) d = Math.max(d, depth(children[i]));
+      }
+      return 1 + d;
+    }
+    function partition(d, i) {
+      var nodes = hierarchy.call(this, d, i);
+      position(nodes[0], 0, size[0], size[1] / depth(nodes[0]));
+      return nodes;
+    }
+    partition.size = function(x) {
+      if (!arguments.length) return size;
+      size = x;
+      return partition;
+    };
+    return d3_layout_hierarchyRebind(partition, hierarchy);
+  };
+  d3.layout.pie = function() {
+    var value = Number, sort = d3_layout_pieSortByValue, startAngle = 0, endAngle = τ;
+    function pie(data) {
+      var values = data.map(function(d, i) {
+        return +value.call(pie, d, i);
+      });
+      var a = +(typeof startAngle === "function" ? startAngle.apply(this, arguments) : startAngle);
+      var k = ((typeof endAngle === "function" ? endAngle.apply(this, arguments) : endAngle) - a) / d3.sum(values);
+      var index = d3.range(data.length);
+      if (sort != null) index.sort(sort === d3_layout_pieSortByValue ? function(i, j) {
+        return values[j] - values[i];
+      } : function(i, j) {
+        return sort(data[i], data[j]);
+      });
+      var arcs = [];
+      index.forEach(function(i) {
+        var d;
+        arcs[i] = {
+          data: data[i],
+          value: d = values[i],
+          startAngle: a,
+          endAngle: a += d * k
+        };
+      });
+      return arcs;
+    }
+    pie.value = function(x) {
+      if (!arguments.length) return value;
+      value = x;
+      return pie;
+    };
+    pie.sort = function(x) {
+      if (!arguments.length) return sort;
+      sort = x;
+      return pie;
+    };
+    pie.startAngle = function(x) {
+      if (!arguments.length) return startAngle;
+      startAngle = x;
+      return pie;
+    };
+    pie.endAngle = function(x) {
+      if (!arguments.length) return endAngle;
+      endAngle = x;
+      return pie;
+    };
+    return pie;
+  };
+  var d3_layout_pieSortByValue = {};
+  d3.layout.stack = function() {
+    var values = d3_identity, order = d3_layout_stackOrderDefault, offset = d3_layout_stackOffsetZero, out = d3_layout_stackOut, x = d3_layout_stackX, y = d3_layout_stackY;
+    function stack(data, index) {
+      var series = data.map(function(d, i) {
+        return values.call(stack, d, i);
+      });
+      var points = series.map(function(d) {
+        return d.map(function(v, i) {
+          return [ x.call(stack, v, i), y.call(stack, v, i) ];
+        });
+      });
+      var orders = order.call(stack, points, index);
+      series = d3.permute(series, orders);
+      points = d3.permute(points, orders);
+      var offsets = offset.call(stack, points, index);
+      var n = series.length, m = series[0].length, i, j, o;
+      for (j = 0; j < m; ++j) {
+        out.call(stack, series[0][j], o = offsets[j], points[0][j][1]);
+        for (i = 1; i < n; ++i) {
+          out.call(stack, series[i][j], o += points[i - 1][j][1], points[i][j][1]);
+        }
+      }
+      return data;
+    }
+    stack.values = function(x) {
+      if (!arguments.length) return values;
+      values = x;
+      return stack;
+    };
+    stack.order = function(x) {
+      if (!arguments.length) return order;
+      order = typeof x === "function" ? x : d3_layout_stackOrders.get(x) || d3_layout_stackOrderDefault;
+      return stack;
+    };
+    stack.offset = function(x) {
+      if (!arguments.length) return offset;
+      offset = typeof x === "function" ? x : d3_layout_stackOffsets.get(x) || d3_layout_stackOffsetZero;
+      return stack;
+    };
+    stack.x = function(z) {
+      if (!arguments.length) return x;
+      x = z;
+      return stack;
+    };
+    stack.y = function(z) {
+      if (!arguments.length) return y;
+      y = z;
+      return stack;
+    };
+    stack.out = function(z) {
+      if (!arguments.length) return out;
+      out = z;
+      return stack;
+    };
+    return stack;
+  };
+  function d3_layout_stackX(d) {
+    return d.x;
+  }
+  function d3_layout_stackY(d) {
+    return d.y;
+  }
+  function d3_layout_stackOut(d, y0, y) {
+    d.y0 = y0;
+    d.y = y;
+  }
+  var d3_layout_stackOrders = d3.map({
+    "inside-out": function(data) {
+      var n = data.length, i, j, max = data.map(d3_layout_stackMaxIndex), sums = data.map(d3_layout_stackReduceSum), index = d3.range(n).sort(function(a, b) {
+        return max[a] - max[b];
+      }), top = 0, bottom = 0, tops = [], bottoms = [];
+      for (i = 0; i < n; ++i) {
+        j = index[i];
+        if (top < bottom) {
+          top += sums[j];
+          tops.push(j);
+        } else {
+          bottom += sums[j];
+          bottoms.push(j);
+        }
+      }
+      return bottoms.reverse().concat(tops);
+    },
+    reverse: function(data) {
+      return d3.range(data.length).reverse();
+    },
+    "default": d3_layout_stackOrderDefault
+  });
+  var d3_layout_stackOffsets = d3.map({
+    silhouette: function(data) {
+      var n = data.length, m = data[0].length, sums = [], max = 0, i, j, o, y0 = [];
+      for (j = 0; j < m; ++j) {
+        for (i = 0, o = 0; i < n; i++) o += data[i][j][1];
+        if (o > max) max = o;
+        sums.push(o);
+      }
+      for (j = 0; j < m; ++j) {
+        y0[j] = (max - sums[j]) / 2;
+      }
+      return y0;
+    },
+    wiggle: function(data) {
+      var n = data.length, x = data[0], m = x.length, i, j, k, s1, s2, s3, dx, o, o0, y0 = [];
+      y0[0] = o = o0 = 0;
+      for (j = 1; j < m; ++j) {
+        for (i = 0, s1 = 0; i < n; ++i) s1 += data[i][j][1];
+        for (i = 0, s2 = 0, dx = x[j][0] - x[j - 1][0]; i < n; ++i) {
+          for (k = 0, s3 = (data[i][j][1] - data[i][j - 1][1]) / (2 * dx); k < i; ++k) {
+            s3 += (data[k][j][1] - data[k][j - 1][1]) / dx;
+          }
+          s2 += s3 * data[i][j][1];
+        }
+        y0[j] = o -= s1 ? s2 / s1 * dx : 0;
+        if (o < o0) o0 = o;
+      }
+      for (j = 0; j < m; ++j) y0[j] -= o0;
+      return y0;
+    },
+    expand: function(data) {
+      var n = data.length, m = data[0].length, k = 1 / n, i, j, o, y0 = [];
+      for (j = 0; j < m; ++j) {
+        for (i = 0, o = 0; i < n; i++) o += data[i][j][1];
+        if (o) for (i = 0; i < n; i++) data[i][j][1] /= o; else for (i = 0; i < n; i++) data[i][j][1] = k;
+      }
+      for (j = 0; j < m; ++j) y0[j] = 0;
+      return y0;
+    },
+    zero: d3_layout_stackOffsetZero
+  });
+  function d3_layout_stackOrderDefault(data) {
+    return d3.range(data.length);
+  }
+  function d3_layout_stackOffsetZero(data) {
+    var j = -1, m = data[0].length, y0 = [];
+    while (++j < m) y0[j] = 0;
+    return y0;
+  }
+  function d3_layout_stackMaxIndex(array) {
+    var i = 1, j = 0, v = array[0][1], k, n = array.length;
+    for (;i < n; ++i) {
+      if ((k = array[i][1]) > v) {
+        j = i;
+        v = k;
+      }
+    }
+    return j;
+  }
+  function d3_layout_stackReduceSum(d) {
+    return d.reduce(d3_layout_stackSum, 0);
+  }
+  function d3_layout_stackSum(p, d) {
+    return p + d[1];
+  }
+  d3.layout.histogram = function() {
+    var frequency = true, valuer = Number, ranger = d3_layout_histogramRange, binner = d3_layout_histogramBinSturges;
+    function histogram(data, i) {
+      var bins = [], values = data.map(valuer, this), range = ranger.call(this, values, i), thresholds = binner.call(this, range, values, i), bin, i = -1, n = values.length, m = thresholds.length - 1, k = frequency ? 1 : 1 / n, x;
+      while (++i < m) {
+        bin = bins[i] = [];
+        bin.dx = thresholds[i + 1] - (bin.x = thresholds[i]);
+        bin.y = 0;
+      }
+      if (m > 0) {
+        i = -1;
+        while (++i < n) {
+          x = values[i];
+          if (x >= range[0] && x <= range[1]) {
+            bin = bins[d3.bisect(thresholds, x, 1, m) - 1];
+            bin.y += k;
+            bin.push(data[i]);
+          }
+        }
+      }
+      return bins;
+    }
+    histogram.value = function(x) {
+      if (!arguments.length) return valuer;
+      valuer = x;
+      return histogram;
+    };
+    histogram.range = function(x) {
+      if (!arguments.length) return ranger;
+      ranger = d3_functor(x);
+      return histogram;
+    };
+    histogram.bins = function(x) {
+      if (!arguments.length) return binner;
+      binner = typeof x === "number" ? function(range) {
+        return d3_layout_histogramBinFixed(range, x);
+      } : d3_functor(x);
+      return histogram;
+    };
+    histogram.frequency = function(x) {
+      if (!arguments.length) return frequency;
+      frequency = !!x;
+      return histogram;
+    };
+    return histogram;
+  };
+  function d3_layout_histogramBinSturges(range, values) {
+    return d3_layout_histogramBinFixed(range, Math.ceil(Math.log(values.length) / Math.LN2 + 1));
+  }
+  function d3_layout_histogramBinFixed(range, n) {
+    var x = -1, b = +range[0], m = (range[1] - b) / n, f = [];
+    while (++x <= n) f[x] = m * x + b;
+    return f;
+  }
+  function d3_layout_histogramRange(values) {
+    return [ d3.min(values), d3.max(values) ];
+  }
+  d3.layout.tree = function() {
+    var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = false;
+    function tree(d, i) {
+      var nodes = hierarchy.call(this, d, i), root = nodes[0];
+      function firstWalk(node, previousSibling) {
+        var children = node.children, layout = node._tree;
+        if (children && (n = children.length)) {
+          var n, firstChild = children[0], previousChild, ancestor = firstChild, child, i = -1;
+          while (++i < n) {
+            child = children[i];
+            firstWalk(child, previousChild);
+            ancestor = apportion(child, previousChild, ancestor);
+            previousChild = child;
+          }
+          d3_layout_treeShift(node);
+          var midpoint = .5 * (firstChild._tree.prelim + child._tree.prelim);
+          if (previousSibling) {
+            layout.prelim = previousSibling._tree.prelim + separation(node, previousSibling);
+            layout.mod = layout.prelim - midpoint;
+          } else {
+            layout.prelim = midpoint;
+          }
+        } else {
+          if (previousSibling) {
+            layout.prelim = previousSibling._tree.prelim + separation(node, previousSibling);
+          }
+        }
+      }
+      function secondWalk(node, x) {
+        node.x = node._tree.prelim + x;
+        var children = node.children;
+        if (children && (n = children.length)) {
+          var i = -1, n;
+          x += node._tree.mod;
+          while (++i < n) {
+            secondWalk(children[i], x);
+          }
+        }
+      }
+      function apportion(node, previousSibling, ancestor) {
+        if (previousSibling) {
+          var vip = node, vop = node, vim = previousSibling, vom = node.parent.children[0], sip = vip._tree.mod, sop = vop._tree.mod, sim = vim._tree.mod, som = vom._tree.mod, shift;
+          while (vim = d3_layout_treeRight(vim), vip = d3_layout_treeLeft(vip), vim && vip) {
+            vom = d3_layout_treeLeft(vom);
+            vop = d3_layout_treeRight(vop);
+            vop._tree.ancestor = node;
+            shift = vim._tree.prelim + sim - vip._tree.prelim - sip + separation(vim, vip);
+            if (shift > 0) {
+              d3_layout_treeMove(d3_layout_treeAncestor(vim, node, ancestor), node, shift);
+              sip += shift;
+              sop += shift;
+            }
+            sim += vim._tree.mod;
+            sip += vip._tree.mod;
+            som += vom._tree.mod;
+            sop += vop._tree.mod;
+          }
+          if (vim && !d3_layout_treeRight(vop)) {
+            vop._tree.thread = vim;
+            vop._tree.mod += sim - sop;
+          }
+          if (vip && !d3_layout_treeLeft(vom)) {
+            vom._tree.thread = vip;
+            vom._tree.mod += sip - som;
+            ancestor = node;
+          }
+        }
+        return ancestor;
+      }
+      d3_layout_treeVisitAfter(root, function(node, previousSibling) {
+        node._tree = {
+          ancestor: node,
+          prelim: 0,
+          mod: 0,
+          change: 0,
+          shift: 0,
+          number: previousSibling ? previousSibling._tree.number + 1 : 0
+        };
+      });
+      firstWalk(root);
+      secondWalk(root, -root._tree.prelim);
+      var left = d3_layout_treeSearch(root, d3_layout_treeLeftmost), right = d3_layout_treeSearch(root, d3_layout_treeRightmost), deep = d3_layout_treeSearch(root, d3_layout_treeDeepest), x0 = left.x - separation(left, right) / 2, x1 = right.x + separation(right, left) / 2, y1 = deep.depth || 1;
+      d3_layout_treeVisitAfter(root, nodeSize ? function(node) {
+        node.x *= size[0];
+        node.y = node.depth * size[1];
+        delete node._tree;
+      } : function(node) {
+        node.x = (node.x - x0) / (x1 - x0) * size[0];
+        node.y = node.depth / y1 * size[1];
+        delete node._tree;
+      });
+      return nodes;
+    }
+    tree.separation = function(x) {
+      if (!arguments.length) return separation;
+      separation = x;
+      return tree;
+    };
+    tree.size = function(x) {
+      if (!arguments.length) return nodeSize ? null : size;
+      nodeSize = (size = x) == null;
+      return tree;
+    };
+    tree.nodeSize = function(x) {
+      if (!arguments.length) return nodeSize ? size : null;
+      nodeSize = (size = x) != null;
+      return tree;
+    };
+    return d3_layout_hierarchyRebind(tree, hierarchy);
+  };
+  function d3_layout_treeSeparation(a, b) {
+    return a.parent == b.parent ? 1 : 2;
+  }
+  function d3_layout_treeLeft(node) {
+    var children = node.children;
+    return children && children.length ? children[0] : node._tree.thread;
+  }
+  function d3_layout_treeRight(node) {
+    var children = node.children, n;
+    return children && (n = children.length) ? children[n - 1] : node._tree.thread;
+  }
+  function d3_layout_treeSearch(node, compare) {
+    var children = node.children;
+    if (children && (n = children.length)) {
+      var child, n, i = -1;
+      while (++i < n) {
+        if (compare(child = d3_layout_treeSearch(children[i], compare), node) > 0) {
+          node = child;
+        }
+      }
+    }
+    return node;
+  }
+  function d3_layout_treeRightmost(a, b) {
+    return a.x - b.x;
+  }
+  function d3_layout_treeLeftmost(a, b) {
+    return b.x - a.x;
+  }
+  function d3_layout_treeDeepest(a, b) {
+    return a.depth - b.depth;
+  }
+  function d3_layout_treeVisitAfter(node, callback) {
+    function visit(node, previousSibling) {
+      var children = node.children;
+      if (children && (n = children.length)) {
+        var child, previousChild = null, i = -1, n;
+        while (++i < n) {
+          child = children[i];
+          visit(child, previousChild);
+          previousChild = child;
+        }
+      }
+      callback(node, previousSibling);
+    }
+    visit(node, null);
+  }
+  function d3_layout_treeShift(node) {
+    var shift = 0, change = 0, children = node.children, i = children.length, child;
+    while (--i >= 0) {
+      child = children[i]._tree;
+      child.prelim += shift;
+      child.mod += shift;
+      shift += child.shift + (change += child.change);
+    }
+  }
+  function d3_layout_treeMove(ancestor, node, shift) {
+    ancestor = ancestor._tree;
+    node = node._tree;
+    var change = shift / (node.number - ancestor.number);
+    ancestor.change += change;
+    node.change -= change;
+    node.shift += shift;
+    node.prelim += shift;
+    node.mod += shift;
+  }
+  function d3_layout_treeAncestor(vim, node, ancestor) {
+    return vim._tree.ancestor.parent == node.parent ? vim._tree.ancestor : ancestor;
+  }
+  d3.layout.pack = function() {
+    var hierarchy = d3.layout.hierarchy().sort(d3_layout_packSort), padding = 0, size = [ 1, 1 ], radius;
+    function pack(d, i) {
+      var nodes = hierarchy.call(this, d, i), root = nodes[0], w = size[0], h = size[1], r = radius == null ? Math.sqrt : typeof radius === "function" ? radius : function() {
+        return radius;
+      };
+      root.x = root.y = 0;
+      d3_layout_treeVisitAfter(root, function(d) {
+        d.r = +r(d.value);
+      });
+      d3_layout_treeVisitAfter(root, d3_layout_packSiblings);
+      if (padding) {
+        var dr = padding * (radius ? 1 : Math.max(2 * root.r / w, 2 * root.r / h)) / 2;
+        d3_layout_treeVisitAfter(root, function(d) {
+          d.r += dr;
+        });
+        d3_layout_treeVisitAfter(root, d3_layout_packSiblings);
+        d3_layout_treeVisitAfter(root, function(d) {
+          d.r -= dr;
+        });
+      }
+      d3_layout_packTransform(root, w / 2, h / 2, radius ? 1 : 1 / Math.max(2 * root.r / w, 2 * root.r / h));
+      return nodes;
+    }
+    pack.size = function(_) {
+      if (!arguments.length) return size;
+      size = _;
+      return pack;
+    };
+    pack.radius = function(_) {
+      if (!arguments.length) return radius;
+      radius = _ == null || typeof _ === "function" ? _ : +_;
+      return pack;
+    };
+    pack.padding = function(_) {
+      if (!arguments.length) return padding;
+      padding = +_;
+      return pack;
+    };
+    return d3_layout_hierarchyRebind(pack, hierarchy);
+  };
+  function d3_layout_packSort(a, b) {
+    return a.value - b.value;
+  }
+  function d3_layout_packInsert(a, b) {
+    var c = a._pack_next;
+    a._pack_next = b;
+    b._pack_prev = a;
+    b._pack_next = c;
+    c._pack_prev = b;
+  }
+  function d3_layout_packSplice(a, b) {
+    a._pack_next = b;
+    b._pack_prev = a;
+  }
+  function d3_layout_packIntersects(a, b) {
+    var dx = b.x - a.x, dy = b.y - a.y, dr = a.r + b.r;
+    return .999 * dr * dr > dx * dx + dy * dy;
+  }
+  function d3_layout_packSiblings(node) {
+    if (!(nodes = node.children) || !(n = nodes.length)) return;
+    var nodes, xMin = Infinity, xMax = -Infinity, yMin = Infinity, yMax = -Infinity, a, b, c, i, j, k, n;
+    function bound(node) {
+      xMin = Math.min(node.x - node.r, xMin);
+      xMax = Math.max(node.x + node.r, xMax);
+      yMin = Math.min(node.y - node.r, yMin);
+      yMax = Math.max(node.y + node.r, yMax);
+    }
+    nodes.forEach(d3_layout_packLink);
+    a = nodes[0];
+    a.x = -a.r;
+    a.y = 0;
+    bound(a);
+    if (n > 1) {
+      b = nodes[1];
+      b.x = b.r;
+      b.y = 0;
+      bound(b);
+      if (n > 2) {
+        c = nodes[2];
+        d3_layout_packPlace(a, b, c);
+        bound(c);
+        d3_layout_packInsert(a, c);
+        a._pack_prev = c;
+        d3_layout_packInsert(c, b);
+        b = a._pack_next;
+        for (i = 3; i < n; i++) {
+          d3_layout_packPlace(a, b, c = nodes[i]);
+          var isect = 0, s1 = 1, s2 = 1;
+          for (j = b._pack_next; j !== b; j = j._pack_next, s1++) {
+            if (d3_layout_packIntersects(j, c)) {
+              isect = 1;
+              break;
+            }
+          }
+          if (isect == 1) {
+            for (k = a._pack_prev; k !== j._pack_prev; k = k._pack_prev, s2++) {
+              if (d3_layout_packIntersects(k, c)) {
+                break;
+              }
+            }
+          }
+          if (isect) {
+            if (s1 < s2 || s1 == s2 && b.r < a.r) d3_layout_packSplice(a, b = j); else d3_layout_packSplice(a = k, b);
+            i--;
+          } else {
+            d3_layout_packInsert(a, c);
+            b = c;
+            bound(c);
+          }
+        }
+      }
+    }
+    var cx = (xMin + xMax) / 2, cy = (yMin + yMax) / 2, cr = 0;
+    for (i = 0; i < n; i++) {
+      c = nodes[i];
+      c.x -= cx;
+      c.y -= cy;
+      cr = Math.max(cr, c.r + Math.sqrt(c.x * c.x + c.y * c.y));
+    }
+    node.r = cr;
+    nodes.forEach(d3_layout_packUnlink);
+  }
+  function d3_layout_packLink(node) {
+    node._pack_next = node._pack_prev = node;
+  }
+  function d3_layout_packUnlink(node) {
+    delete node._pack_next;
+    delete node._pack_prev;
+  }
+  function d3_layout_packTransform(node, x, y, k) {
+    var children = node.children;
+    node.x = x += k * node.x;
+    node.y = y += k * node.y;
+    node.r *= k;
+    if (children) {
+      var i = -1, n = children.length;
+      while (++i < n) d3_layout_packTransform(children[i], x, y, k);
+    }
+  }
+  function d3_layout_packPlace(a, b, c) {
+    var db = a.r + c.r, dx = b.x - a.x, dy = b.y - a.y;
+    if (db && (dx || dy)) {
+      var da = b.r + c.r, dc = dx * dx + dy * dy;
+      da *= da;
+      db *= db;
+      var x = .5 + (db - da) / (2 * dc), y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc);
+      c.x = a.x + x * dx + y * dy;
+      c.y = a.y + x * dy - y * dx;
+    } else {
+      c.x = a.x + db;
+      c.y = a.y;
+    }
+  }
+  d3.layout.cluster = function() {
+    var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = false;
+    function cluster(d, i) {
+      var nodes = hierarchy.call(this, d, i), root = nodes[0], previousNode, x = 0;
+      d3_layout_treeVisitAfter(root, function(node) {
+        var children = node.children;
+        if (children && children.length) {
+          node.x = d3_layout_clusterX(children);
+          node.y = d3_layout_clusterY(children);
+        } else {
+          node.x = previousNode ? x += separation(node, previousNode) : 0;
+          node.y = 0;
+          previousNode = node;
+        }
+      });
+      var left = d3_layout_clusterLeft(root), right = d3_layout_clusterRight(root), x0 = left.x - separation(left, right) / 2, x1 = right.x + separation(right, left) / 2;
+      d3_layout_treeVisitAfter(root, nodeSize ? function(node) {
+        node.x = (node.x - root.x) * size[0];
+        node.y = (root.y - node.y) * size[1];
+      } : function(node) {
+        node.x = (node.x - x0) / (x1 - x0) * size[0];
+        node.y = (1 - (root.y ? node.y / root.y : 1)) * size[1];
+      });
+      return nodes;
+    }
+    cluster.separation = function(x) {
+      if (!arguments.length) return separation;
+      separation = x;
+      return cluster;
+    };
+    cluster.size = function(x) {
+      if (!arguments.length) return nodeSize ? null : size;
+      nodeSize = (size = x) == null;
+      return cluster;
+    };
+    cluster.nodeSize = function(x) {
+      if (!arguments.length) return nodeSize ? size : null;
+      nodeSize = (size = x) != null;
+      return cluster;
+    };
+    return d3_layout_hierarchyRebind(cluster, hierarchy);
+  };
+  function d3_layout_clusterY(children) {
+    return 1 + d3.max(children, function(child) {
+      return child.y;
+    });
+  }
+  function d3_layout_clusterX(children) {
+    return children.reduce(function(x, child) {
+      return x + child.x;
+    }, 0) / children.length;
+  }
+  function d3_layout_clusterLeft(node) {
+    var children = node.children;
+    return children && children.length ? d3_layout_clusterLeft(children[0]) : node;
+  }
+  function d3_layout_clusterRight(node) {
+    var children = node.children, n;
+    return children && (n = children.length) ? d3_layout_clusterRight(children[n - 1]) : node;
+  }
+  d3.layout.treemap = function() {
+    var hierarchy = d3.layout.hierarchy(), round = Math.round, size = [ 1, 1 ], padding = null, pad = d3_layout_treemapPadNull, sticky = false, stickies, mode = "squarify", ratio = .5 * (1 + Math.sqrt(5));
+    function scale(children, k) {
+      var i = -1, n = children.length, child, area;
+      while (++i < n) {
+        area = (child = children[i]).value * (k < 0 ? 0 : k);
+        child.area = isNaN(area) || area <= 0 ? 0 : area;
+      }
+    }
+    function squarify(node) {
+      var children = node.children;
+      if (children && children.length) {
+        var rect = pad(node), row = [], remaining = children.slice(), child, best = Infinity, score, u = mode === "slice" ? rect.dx : mode === "dice" ? rect.dy : mode === "slice-dice" ? node.depth & 1 ? rect.dy : rect.dx : Math.min(rect.dx, rect.dy), n;
+        scale(remaining, rect.dx * rect.dy / node.value);
+        row.area = 0;
+        while ((n = remaining.length) > 0) {
+          row.push(child = remaining[n - 1]);
+          row.area += child.area;
+          if (mode !== "squarify" || (score = worst(row, u)) <= best) {
+            remaining.pop();
+            best = score;
+          } else {
+            row.area -= row.pop().area;
+            position(row, u, rect, false);
+            u = Math.min(rect.dx, rect.dy);
+            row.length = row.area = 0;
+            best = Infinity;
+          }
+        }
+        if (row.length) {
+          position(row, u, rect, true);
+          row.length = row.area = 0;
+        }
+        children.forEach(squarify);
+      }
+    }
+    function stickify(node) {
+      var children = node.children;
+      if (children && children.length) {
+        var rect = pad(node), remaining = children.slice(), child, row = [];
+        scale(remaining, rect.dx * rect.dy / node.value);
+        row.area = 0;
+        while (child = remaining.pop()) {
+          row.push(child);
+          row.area += child.area;
+          if (child.z != null) {
+            position(row, child.z ? rect.dx : rect.dy, rect, !remaining.length);
+            row.length = row.area = 0;
+          }
+        }
+        children.forEach(stickify);
+      }
+    }
+    function worst(row, u) {
+      var s = row.area, r, rmax = 0, rmin = Infinity, i = -1, n = row.length;
+      while (++i < n) {
+        if (!(r = row[i].area)) continue;
+        if (r < rmin) rmin = r;
+        if (r > rmax) rmax = r;
+      }
+      s *= s;
+      u *= u;
+      return s ? Math.max(u * rmax * ratio / s, s / (u * rmin * ratio)) : Infinity;
+    }
+    function position(row, u, rect, flush) {
+      var i = -1, n = row.length, x = rect.x, y = rect.y, v = u ? round(row.area / u) : 0, o;
+      if (u == rect.dx) {
+        if (flush || v > rect.dy) v = rect.dy;
+        while (++i < n) {
+          o = row[i];
+          o.x = x;
+          o.y = y;
+          o.dy = v;
+          x += o.dx = Math.min(rect.x + rect.dx - x, v ? round(o.area / v) : 0);
+        }
+        o.z = true;
+        o.dx += rect.x + rect.dx - x;
+        rect.y += v;
+        rect.dy -= v;
+      } else {
+        if (flush || v > rect.dx) v = rect.dx;
+        while (++i < n) {
+          o = row[i];
+          o.x = x;
+          o.y = y;
+          o.dx = v;
+          y += o.dy = Math.min(rect.y + rect.dy - y, v ? round(o.area / v) : 0);
+        }
+        o.z = false;
+        o.dy += rect.y + rect.dy - y;
+        rect.x += v;
+        rect.dx -= v;
+      }
+    }
+    function treemap(d) {
+      var nodes = stickies || hierarchy(d), root = nodes[0];
+      root.x = 0;
+      root.y = 0;
+      root.dx = size[0];
+      root.dy = size[1];
+      if (stickies) hierarchy.revalue(root);
+      scale([ root ], root.dx * root.dy / root.value);
+      (stickies ? stickify : squarify)(root);
+      if (sticky) stickies = nodes;
+      return nodes;
+    }
+    treemap.size = function(x) {
+      if (!arguments.length) return size;
+      size = x;
+      return treemap;
+    };
+    treemap.padding = function(x) {
+      if (!arguments.length) return padding;
+      function padFunction(node) {
+        var p = x.call(treemap, node, node.depth);
+        return p == null ? d3_layout_treemapPadNull(node) : d3_layout_treemapPad(node, typeof p === "number" ? [ p, p, p, p ] : p);
+      }
+      function padConstant(node) {
+        return d3_layout_treemapPad(node, x);
+      }
+      var type;
+      pad = (padding = x) == null ? d3_layout_treemapPadNull : (type = typeof x) === "function" ? padFunction : type === "number" ? (x = [ x, x, x, x ], 
+      padConstant) : padConstant;
+      return treemap;
+    };
+    treemap.round = function(x) {
+      if (!arguments.length) return round != Number;
+      round = x ? Math.round : Number;
+      return treemap;
+    };
+    treemap.sticky = function(x) {
+      if (!arguments.length) return sticky;
+      sticky = x;
+      stickies = null;
+      return treemap;
+    };
+    treemap.ratio = function(x) {
+      if (!arguments.length) return ratio;
+      ratio = x;
+      return treemap;
+    };
+    treemap.mode = function(x) {
+      if (!arguments.length) return mode;
+      mode = x + "";
+      return treemap;
+    };
+    return d3_layout_hierarchyRebind(treemap, hierarchy);
+  };
+  function d3_layout_treemapPadNull(node) {
+    return {
+      x: node.x,
+      y: node.y,
+      dx: node.dx,
+      dy: node.dy
+    };
+  }
+  function d3_layout_treemapPad(node, padding) {
+    var x = node.x + padding[3], y = node.y + padding[0], dx = node.dx - padding[1] - padding[3], dy = node.dy - padding[0] - padding[2];
+    if (dx < 0) {
+      x += dx / 2;
+      dx = 0;
+    }
+    if (dy < 0) {
+      y += dy / 2;
+      dy = 0;
+    }
+    return {
+      x: x,
+      y: y,
+      dx: dx,
+      dy: dy
+    };
+  }
+  d3.random = {
+    normal: function(µ, σ) {
+      var n = arguments.length;
+      if (n < 2) σ = 1;
+      if (n < 1) µ = 0;
+      return function() {
+        var x, y, r;
+        do {
+          x = Math.random() * 2 - 1;
+          y = Math.random() * 2 - 1;
+          r = x * x + y * y;
+        } while (!r || r > 1);
+        return µ + σ * x * Math.sqrt(-2 * Math.log(r) / r);
+      };
+    },
+    logNormal: function() {
+      var random = d3.random.normal.apply(d3, arguments);
+      return function() {
+        return Math.exp(random());
+      };
+    },
+    bates: function(m) {
+      var random = d3.random.irwinHall(m);
+      return function() {
+        return random() / m;
+      };
+    },
+    irwinHall: function(m) {
+      return function() {
+        for (var s = 0, j = 0; j < m; j++) s += Math.random();
+        return s;
+      };
+    }
+  };
+  d3.scale = {};
+  function d3_scaleExtent(domain) {
+    var start = domain[0], stop = domain[domain.length - 1];
+    return start < stop ? [ start, stop ] : [ stop, start ];
+  }
+  function d3_scaleRange(scale) {
+    return scale.rangeExtent ? scale.rangeExtent() : d3_scaleExtent(scale.range());
+  }
+  function d3_scale_bilinear(domain, range, uninterpolate, interpolate) {
+    var u = uninterpolate(domain[0], domain[1]), i = interpolate(range[0], range[1]);
+    return function(x) {
+      return i(u(x));
+    };
+  }
+  function d3_scale_nice(domain, nice) {
+    var i0 = 0, i1 = domain.length - 1, x0 = domain[i0], x1 = domain[i1], dx;
+    if (x1 < x0) {
+      dx = i0, i0 = i1, i1 = dx;
+      dx = x0, x0 = x1, x1 = dx;
+    }
+    domain[i0] = nice.floor(x0);
+    domain[i1] = nice.ceil(x1);
+    return domain;
+  }
+  function d3_scale_niceStep(step) {
+    return step ? {
+      floor: function(x) {
+        return Math.floor(x / step) * step;
+      },
+      ceil: function(x) {
+        return Math.ceil(x / step) * step;
+      }
+    } : d3_scale_niceIdentity;
+  }
+  var d3_scale_niceIdentity = {
+    floor: d3_identity,
+    ceil: d3_identity
+  };
+  function d3_scale_polylinear(domain, range, uninterpolate, interpolate) {
+    var u = [], i = [], j = 0, k = Math.min(domain.length, range.length) - 1;
+    if (domain[k] < domain[0]) {
+      domain = domain.slice().reverse();
+      range = range.slice().reverse();
+    }
+    while (++j <= k) {
+      u.push(uninterpolate(domain[j - 1], domain[j]));
+      i.push(interpolate(range[j - 1], range[j]));
+    }
+    return function(x) {
+      var j = d3.bisect(domain, x, 1, k) - 1;
+      return i[j](u[j](x));
+    };
+  }
+  d3.scale.linear = function() {
+    return d3_scale_linear([ 0, 1 ], [ 0, 1 ], d3_interpolate, false);
+  };
+  function d3_scale_linear(domain, range, interpolate, clamp) {
+    var output, input;
+    function rescale() {
+      var linear = Math.min(domain.length, range.length) > 2 ? d3_scale_polylinear : d3_scale_bilinear, uninterpolate = clamp ? d3_uninterpolateClamp : d3_uninterpolateNumber;
+      output = linear(domain, range, uninterpolate, interpolate);
+      input = linear(range, domain, uninterpolate, d3_interpolate);
+      return scale;
+    }
+    function scale(x) {
+      return output(x);
+    }
+    scale.invert = function(y) {
+      return input(y);
+    };
+    scale.domain = function(x) {
+      if (!arguments.length) return domain;
+      domain = x.map(Number);
+      return rescale();
+    };
+    scale.range = function(x) {
+      if (!arguments.length) return range;
+      range = x;
+      return rescale();
+    };
+    scale.rangeRound = function(x) {
+      return scale.range(x).interpolate(d3_interpolateRound);
+    };
+    scale.clamp = function(x) {
+      if (!arguments.length) return clamp;
+      clamp = x;
+      return rescale();
+    };
+    scale.interpolate = function(x) {
+      if (!arguments.length) return interpolate;
+      interpolate = x;
+      return rescale();
+    };
+    scale.ticks = function(m) {
+      return d3_scale_linearTicks(domain, m);
+    };
+    scale.tickFormat = function(m, format) {
+      return d3_scale_linearTickFormat(domain, m, format);
+    };
+    scale.nice = function(m) {
+      d3_scale_linearNice(domain, m);
+      return rescale();
+    };
+    scale.copy = function() {
+      return d3_scale_linear(domain, range, interpolate, clamp);
+    };
+    return rescale();
+  }
+  function d3_scale_linearRebind(scale, linear) {
+    return d3.rebind(scale, linear, "range", "rangeRound", "interpolate", "clamp");
+  }
+  function d3_scale_linearNice(domain, m) {
+    return d3_scale_nice(domain, d3_scale_niceStep(d3_scale_linearTickRange(domain, m)[2]));
+  }
+  function d3_scale_linearTickRange(domain, m) {
+    if (m == null) m = 10;
+    var extent = d3_scaleExtent(domain), span = extent[1] - extent[0], step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10)), err = m / span * step;
+    if (err <= .15) step *= 10; else if (err <= .35) step *= 5; else if (err <= .75) step *= 2;
+    extent[0] = Math.ceil(extent[0] / step) * step;
+    extent[1] = Math.floor(extent[1] / step) * step + step * .5;
+    extent[2] = step;
+    return extent;
+  }
+  function d3_scale_linearTicks(domain, m) {
+    return d3.range.apply(d3, d3_scale_linearTickRange(domain, m));
+  }
+  function d3_scale_linearTickFormat(domain, m, format) {
+    var range = d3_scale_linearTickRange(domain, m);
+    if (format) {
+      var match = d3_format_re.exec(format);
+      match.shift();
+      if (match[8] === "s") {
+        var prefix = d3.formatPrefix(Math.max(abs(range[0]), abs(range[1])));
+        if (!match[7]) match[7] = "." + d3_scale_linearPrecision(prefix.scale(range[2]));
+        match[8] = "f";
+        format = d3.format(match.join(""));
+        return function(d) {
+          return format(prefix.scale(d)) + prefix.symbol;
+        };
+      }
+      if (!match[7]) match[7] = "." + d3_scale_linearFormatPrecision(match[8], range);
+      format = match.join("");
+    } else {
+      format = ",." + d3_scale_linearPrecision(range[2]) + "f";
+    }
+    return d3.format(format);
+  }
+  var d3_scale_linearFormatSignificant = {
+    s: 1,
+    g: 1,
+    p: 1,
+    r: 1,
+    e: 1
+  };
+  function d3_scale_linearPrecision(value) {
+    return -Math.floor(Math.log(value) / Math.LN10 + .01);
+  }
+  function d3_scale_linearFormatPrecision(type, range) {
+    var p = d3_scale_linearPrecision(range[2]);
+    return type in d3_scale_linearFormatSignificant ? Math.abs(p - d3_scale_linearPrecision(Math.max(abs(range[0]), abs(range[1])))) + +(type !== "e") : p - (type === "%") * 2;
+  }
+  d3.scale.log = function() {
+    return d3_scale_log(d3.scale.linear().domain([ 0, 1 ]), 10, true, [ 1, 10 ]);
+  };
+  function d3_scale_log(linear, base, positive, domain) {
+    function log(x) {
+      return (positive ? Math.log(x < 0 ? 0 : x) : -Math.log(x > 0 ? 0 : -x)) / Math.log(base);
+    }
+    function pow(x) {
+      return positive ? Math.pow(base, x) : -Math.pow(base, -x);
+    }
+    function scale(x) {
+      return linear(log(x));
+    }
+    scale.invert = function(x) {
+      return pow(linear.invert(x));
+    };
+    scale.domain = function(x) {
+      if (!arguments.length) return domain;
+      positive = x[0] >= 0;
+      linear.domain((domain = x.map(Number)).map(log));
+      return scale;
+    };
+    scale.base = function(_) {
+      if (!arguments.length) return base;
+      base = +_;
+      linear.domain(domain.map(log));
+      return scale;
+    };
+    scale.nice = function() {
+      var niced = d3_scale_nice(domain.map(log), positive ? Math : d3_scale_logNiceNegative);
+      linear.domain(niced);
+      domain = niced.map(pow);
+      return scale;
+    };
+    scale.ticks = function() {
+      var extent = d3_scaleExtent(domain), ticks = [], u = extent[0], v = extent[1], i = Math.floor(log(u)), j = Math.ceil(log(v)), n = base % 1 ? 2 : base;
+      if (isFinite(j - i)) {
+        if (positive) {
+          for (;i < j; i++) for (var k = 1; k < n; k++) ticks.push(pow(i) * k);
+          ticks.push(pow(i));
+        } else {
+          ticks.push(pow(i));
+          for (;i++ < j; ) for (var k = n - 1; k > 0; k--) ticks.push(pow(i) * k);
+        }
+        for (i = 0; ticks[i] < u; i++) {}
+        for (j = ticks.length; ticks[j - 1] > v; j--) {}
+        ticks = ticks.slice(i, j);
+      }
+      return ticks;
+    };
+    scale.tickFormat = function(n, format) {
+      if (!arguments.length) return d3_scale_logFormat;
+      if (arguments.length < 2) format = d3_scale_logFormat; else if (typeof format !== "function") format = d3.format(format);
+      var k = Math.max(.1, n / scale.ticks().length), f = positive ? (e = 1e-12, Math.ceil) : (e = -1e-12, 
+      Math.floor), e;
+      return function(d) {
+        return d / pow(f(log(d) + e)) <= k ? format(d) : "";
+      };
+    };
+    scale.copy = function() {
+      return d3_scale_log(linear.copy(), base, positive, domain);
+    };
+    return d3_scale_linearRebind(scale, linear);
+  }
+  var d3_scale_logFormat = d3.format(".0e"), d3_scale_logNiceNegative = {
+    floor: function(x) {
+      return -Math.ceil(-x);
+    },
+    ceil: function(x) {
+      return -Math.floor(-x);
+    }
+  };
+  d3.scale.pow = function() {
+    return d3_scale_pow(d3.scale.linear(), 1, [ 0, 1 ]);
+  };
+  function d3_scale_pow(linear, exponent, domain) {
+    var powp = d3_scale_powPow(exponent), powb = d3_scale_powPow(1 / exponent);
+    function scale(x) {
+      return linear(powp(x));
+    }
+    scale.invert = function(x) {
+      return powb(linear.invert(x));
+    };
+    scale.domain = function(x) {
+      if (!arguments.length) return domain;
+      linear.domain((domain = x.map(Number)).map(powp));
+      return scale;
+    };
+    scale.ticks = function(m) {
+      return d3_scale_linearTicks(domain, m);
+    };
+    scale.tickFormat = function(m, format) {
+      return d3_scale_linearTickFormat(domain, m, format);
+    };
+    scale.nice = function(m) {
+      return scale.domain(d3_scale_linearNice(domain, m));
+    };
+    scale.exponent = function(x) {
+      if (!arguments.length) return exponent;
+      powp = d3_scale_powPow(exponent = x);
+      powb = d3_scale_powPow(1 / exponent);
+      linear.domain(domain.map(powp));
+      return scale;
+    };
+    scale.copy = function() {
+      return d3_scale_pow(linear.copy(), exponent, domain);
+    };
+    return d3_scale_linearRebind(scale, linear);
+  }
+  function d3_scale_powPow(e) {
+    return function(x) {
+      return x < 0 ? -Math.pow(-x, e) : Math.pow(x, e);
+    };
+  }
+  d3.scale.sqrt = function() {
+    return d3.scale.pow().exponent(.5);
+  };
+  d3.scale.ordinal = function() {
+    return d3_scale_ordinal([], {
+      t: "range",
+      a: [ [] ]
+    });
+  };
+  function d3_scale_ordinal(domain, ranger) {
+    var index, range, rangeBand;
+    function scale(x) {
+      return range[((index.get(x) || (ranger.t === "range" ? index.set(x, domain.push(x)) : NaN)) - 1) % range.length];
+    }
+    function steps(start, step) {
+      return d3.range(domain.length).map(function(i) {
+        return start + step * i;
+      });
+    }
+    scale.domain = function(x) {
+      if (!arguments.length) return domain;
+      domain = [];
+      index = new d3_Map();
+      var i = -1, n = x.length, xi;
+      while (++i < n) if (!index.has(xi = x[i])) index.set(xi, domain.push(xi));
+      return scale[ranger.t].apply(scale, ranger.a);
+    };
+    scale.range = function(x) {
+      if (!arguments.length) return range;
+      range = x;
+      rangeBand = 0;
+      ranger = {
+        t: "range",
+        a: arguments
+      };
+      return scale;
+    };
+    scale.rangePoints = function(x, padding) {
+      if (arguments.length < 2) padding = 0;
+      var start = x[0], stop = x[1], step = (stop - start) / (Math.max(1, domain.length - 1) + padding);
+      range = steps(domain.length < 2 ? (start + stop) / 2 : start + step * padding / 2, step);
+      rangeBand = 0;
+      ranger = {
+        t: "rangePoints",
+        a: arguments
+      };
+      return scale;
+    };
+    scale.rangeBands = function(x, padding, outerPadding) {
+      if (arguments.length < 2) padding = 0;
+      if (arguments.length < 3) outerPadding = padding;
+      var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = (stop - start) / (domain.length - padding + 2 * outerPadding);
+      range = steps(start + step * outerPadding, step);
+      if (reverse) range.reverse();
+      rangeBand = step * (1 - padding);
+      ranger = {
+        t: "rangeBands",
+        a: arguments
+      };
+      return scale;
+    };
+    scale.rangeRoundBands = function(x, padding, outerPadding) {
+      if (arguments.length < 2) padding = 0;
+      if (arguments.length < 3) outerPadding = padding;
+      var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = Math.floor((stop - start) / (domain.length - padding + 2 * outerPadding)), error = stop - start - (domain.length - padding) * step;
+      range = steps(start + Math.round(error / 2), step);
+      if (reverse) range.reverse();
+      rangeBand = Math.round(step * (1 - padding));
+      ranger = {
+        t: "rangeRoundBands",
+        a: arguments
+      };
+      return scale;
+    };
+    scale.rangeBand = function() {
+      return rangeBand;
+    };
+    scale.rangeExtent = function() {
+      return d3_scaleExtent(ranger.a[0]);
+    };
+    scale.copy = function() {
+      return d3_scale_ordinal(domain, ranger);
+    };
+    return scale.domain(domain);
+  }
+  d3.scale.category10 = function() {
+    return d3.scale.ordinal().range(d3_category10);
+  };
+  d3.scale.category20 = function() {
+    return d3.scale.ordinal().range(d3_category20);
+  };
+  d3.scale.category20b = function() {
+    return d3.scale.ordinal().range(d3_category20b);
+  };
+  d3.scale.category20c = function() {
+    return d3.scale.ordinal().range(d3_category20c);
+  };
+  var d3_category10 = [ 2062260, 16744206, 2924588, 14034728, 9725885, 9197131, 14907330, 8355711, 12369186, 1556175 ].map(d3_rgbString);
+  var d3_category20 = [ 2062260, 11454440, 16744206, 16759672, 2924588, 10018698, 14034728, 16750742, 9725885, 12955861, 9197131, 12885140, 14907330, 16234194, 8355711, 13092807, 12369186, 14408589, 1556175, 10410725 ].map(d3_rgbString);
+  var d3_category20b = [ 3750777, 5395619, 7040719, 10264286, 6519097, 9216594, 11915115, 13556636, 9202993, 12426809, 15186514, 15190932, 8666169, 11356490, 14049643, 15177372, 8077683, 10834324, 13528509, 14589654 ].map(d3_rgbString);
+  var d3_category20c = [ 3244733, 7057110, 10406625, 13032431, 15095053, 16616764, 16625259, 16634018, 3253076, 7652470, 10607003, 13101504, 7695281, 10394312, 12369372, 14342891, 6513507, 9868950, 12434877, 14277081 ].map(d3_rgbString);
+  d3.scale.quantile = function() {
+    return d3_scale_quantile([], []);
+  };
+  function d3_scale_quantile(domain, range) {
+    var thresholds;
+    function rescale() {
+      var k = 0, q = range.length;
+      thresholds = [];
+      while (++k < q) thresholds[k - 1] = d3.quantile(domain, k / q);
+      return scale;
+    }
+    function scale(x) {
+      if (!isNaN(x = +x)) return range[d3.bisect(thresholds, x)];
+    }
+    scale.domain = function(x) {
+      if (!arguments.length) return domain;
+      domain = x.filter(function(d) {
+        return !isNaN(d);
+      }).sort(d3_ascending);
+      return rescale();
+    };
+    scale.range = function(x) {
+      if (!arguments.length) return range;
+      range = x;
+      return rescale();
+    };
+    scale.quantiles = function() {
+      return thresholds;
+    };
+    scale.invertExtent = function(y) {
+      y = range.indexOf(y);
+      return y < 0 ? [ NaN, NaN ] : [ y > 0 ? thresholds[y - 1] : domain[0], y < thresholds.length ? thresholds[y] : domain[domain.length - 1] ];
+    };
+    scale.copy = function() {
+      return d3_scale_quantile(domain, range);
+    };
+    return rescale();
+  }
+  d3.scale.quantize = function() {
+    return d3_scale_quantize(0, 1, [ 0, 1 ]);
+  };
+  function d3_scale_quantize(x0, x1, range) {
+    var kx, i;
+    function scale(x) {
+      return range[Math.max(0, Math.min(i, Math.floor(kx * (x - x0))))];
+    }
+    function rescale() {
+      kx = range.length / (x1 - x0);
+      i = range.length - 1;
+      return scale;
+    }
+    scale.domain = function(x) {
+      if (!arguments.length) return [ x0, x1 ];
+      x0 = +x[0];
+      x1 = +x[x.length - 1];
+      return rescale();
+    };
+    scale.range = function(x) {
+      if (!arguments.length) return range;
+      range = x;
+      return rescale();
+    };
+    scale.invertExtent = function(y) {
+      y = range.indexOf(y);
+      y = y < 0 ? NaN : y / kx + x0;
+      return [ y, y + 1 / kx ];
+    };
+    scale.copy = function() {
+      return d3_scale_quantize(x0, x1, range);
+    };
+    return rescale();
+  }
+  d3.scale.threshold = function() {
+    return d3_scale_threshold([ .5 ], [ 0, 1 ]);
+  };
+  function d3_scale_threshold(domain, range) {
+    function scale(x) {
+      if (x <= x) return range[d3.bisect(domain, x)];
+    }
+    scale.domain = function(_) {
+      if (!arguments.length) return domain;
+      domain = _;
+      return scale;
+    };
+    scale.range = function(_) {
+      if (!arguments.length) return range;
+      range = _;
+      return scale;
+    };
+    scale.invertExtent = function(y) {
+      y = range.indexOf(y);
+      return [ domain[y - 1], domain[y] ];
+    };
+    scale.copy = function() {
+      return d3_scale_threshold(domain, range);
+    };
+    return scale;
+  }
+  d3.scale.identity = function() {
+    return d3_scale_identity([ 0, 1 ]);
+  };
+  function d3_scale_identity(domain) {
+    function identity(x) {
+      return +x;
+    }
+    identity.invert = identity;
+    identity.domain = identity.range = function(x) {
+      if (!arguments.length) return domain;
+      domain = x.map(identity);
+      return identity;
+    };
+    identity.ticks = function(m) {
+      return d3_scale_linearTicks(domain, m);
+    };
+    identity.tickFormat = function(m, format) {
+      return d3_scale_linearTickFormat(domain, m, format);
+    };
+    identity.copy = function() {
+      return d3_scale_identity(domain);
+    };
+    return identity;
+  }
+  d3.svg = {};
+  d3.svg.arc = function() {
+    var innerRadius = d3_svg_arcInnerRadius, outerRadius = d3_svg_arcOuterRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle;
+    function arc() {
+      var r0 = innerRadius.apply(this, arguments), r1 = outerRadius.apply(this, arguments), a0 = startAngle.apply(this, arguments) + d3_svg_arcOffset, a1 = endAngle.apply(this, arguments) + d3_svg_arcOffset, da = (a1 < a0 && (da = a0, 
+      a0 = a1, a1 = da), a1 - a0), df = da < π ? "0" : "1", c0 = Math.cos(a0), s0 = Math.sin(a0), c1 = Math.cos(a1), s1 = Math.sin(a1);
+      return da >= d3_svg_arcMax ? r0 ? "M0," + r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + -r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + r1 + "M0," + r0 + "A" + r0 + "," + r0 + " 0 1,0 0," + -r0 + "A" + r0 + "," + r0 + " 0 1,0 0," + r0 + "Z" : "M0," + r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + -r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + r1 + "Z" : r0 ? "M" + r1 * c0 + "," + r1 * s0 + "A" + r1 + "," + r1 + " 0 " + df + ",1 " + r1 * c1 + "," + r1 * s1 + "L" + r0 * c1 + "," + r0 * s1 + "A" + r0 + "," + r0 + " 0 " + df + ",0 " + r0 * c0 + "," + r0 * s0 + "Z" : "M" + r1 * c0 + "," + r1 * s0 + "A" + r1 + "," + r1 + " 0 " + df + ",1 " + r1 * c1 + "," + r1 * s1 + "L0,0" + "Z";
+    }
+    arc.innerRadius = function(v) {
+      if (!arguments.length) return innerRadius;
+      innerRadius = d3_functor(v);
+      return arc;
+    };
+    arc.outerRadius = function(v) {
+      if (!arguments.length) return outerRadius;
+      outerRadius = d3_functor(v);
+      return arc;
+    };
+    arc.startAngle = function(v) {
+      if (!arguments.length) return startAngle;
+      startAngle = d3_functor(v);
+      return arc;
+    };
+    arc.endAngle = function(v) {
+      if (!arguments.length) return endAngle;
+      endAngle = d3_functor(v);
+      return arc;
+    };
+    arc.centroid = function() {
+      var r = (innerRadius.apply(this, arguments) + outerRadius.apply(this, arguments)) / 2, a = (startAngle.apply(this, arguments) + endAngle.apply(this, arguments)) / 2 + d3_svg_arcOffset;
+      return [ Math.cos(a) * r, Math.sin(a) * r ];
+    };
+    return arc;
+  };
+  var d3_svg_arcOffset = -halfπ, d3_svg_arcMax = τ - ε;
+  function d3_svg_arcInnerRadius(d) {
+    return d.innerRadius;
+  }
+  function d3_svg_arcOuterRadius(d) {
+    return d.outerRadius;
+  }
+  function d3_svg_arcStartAngle(d) {
+    return d.startAngle;
+  }
+  function d3_svg_arcEndAngle(d) {
+    return d.endAngle;
+  }
+  function d3_svg_line(projection) {
+    var x = d3_geom_pointX, y = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, tension = .7;
+    function line(data) {
+      var segments = [], points = [], i = -1, n = data.length, d, fx = d3_functor(x), fy = d3_functor(y);
+      function segment() {
+        segments.push("M", interpolate(projection(points), tension));
+      }
+      while (++i < n) {
+        if (defined.call(this, d = data[i], i)) {
+          points.push([ +fx.call(this, d, i), +fy.call(this, d, i) ]);
+        } else if (points.length) {
+          segment();
+          points = [];
+        }
+      }
+      if (points.length) segment();
+      return segments.length ? segments.join("") : null;
+    }
+    line.x = function(_) {
+      if (!arguments.length) return x;
+      x = _;
+      return line;
+    };
+    line.y = function(_) {
+      if (!arguments.length) return y;
+      y = _;
+      return line;
+    };
+    line.defined = function(_) {
+      if (!arguments.length) return defined;
+      defined = _;
+      return line;
+    };
+    line.interpolate = function(_) {
+      if (!arguments.length) return interpolateKey;
+      if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key;
+      return line;
+    };
+    line.tension = function(_) {
+      if (!arguments.length) return tension;
+      tension = _;
+      return line;
+    };
+    return line;
+  }
+  d3.svg.line = function() {
+    return d3_svg_line(d3_identity);
+  };
+  var d3_svg_lineInterpolators = d3.map({
+    linear: d3_svg_lineLinear,
+    "linear-closed": d3_svg_lineLinearClosed,
+    step: d3_svg_lineStep,
+    "step-before": d3_svg_lineStepBefore,
+    "step-after": d3_svg_lineStepAfter,
+    basis: d3_svg_lineBasis,
+    "basis-open": d3_svg_lineBasisOpen,
+    "basis-closed": d3_svg_lineBasisClosed,
+    bundle: d3_svg_lineBundle,
+    cardinal: d3_svg_lineCardinal,
+    "cardinal-open": d3_svg_lineCardinalOpen,
+    "cardinal-closed": d3_svg_lineCardinalClosed,
+    monotone: d3_svg_lineMonotone
+  });
+  d3_svg_lineInterpolators.forEach(function(key, value) {
+    value.key = key;
+    value.closed = /-closed$/.test(key);
+  });
+  function d3_svg_lineLinear(points) {
+    return points.join("L");
+  }
+  function d3_svg_lineLinearClosed(points) {
+    return d3_svg_lineLinear(points) + "Z";
+  }
+  function d3_svg_lineStep(points) {
+    var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ];
+    while (++i < n) path.push("H", (p[0] + (p = points[i])[0]) / 2, "V", p[1]);
+    if (n > 1) path.push("H", p[0]);
+    return path.join("");
+  }
+  function d3_svg_lineStepBefore(points) {
+    var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ];
+    while (++i < n) path.push("V", (p = points[i])[1], "H", p[0]);
+    return path.join("");
+  }
+  function d3_svg_lineStepAfter(points) {
+    var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ];
+    while (++i < n) path.push("H", (p = points[i])[0], "V", p[1]);
+    return path.join("");
+  }
+  function d3_svg_lineCardinalOpen(points, tension) {
+    return points.length < 4 ? d3_svg_lineLinear(points) : points[1] + d3_svg_lineHermite(points.slice(1, points.length - 1), d3_svg_lineCardinalTangents(points, tension));
+  }
+  function d3_svg_lineCardinalClosed(points, tension) {
+    return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite((points.push(points[0]), 
+    points), d3_svg_lineCardinalTangents([ points[points.length - 2] ].concat(points, [ points[1] ]), tension));
+  }
+  function d3_svg_lineCardinal(points, tension) {
+    return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineCardinalTangents(points, tension));
+  }
+  function d3_svg_lineHermite(points, tangents) {
+    if (tangents.length < 1 || points.length != tangents.length && points.length != tangents.length + 2) {
+      return d3_svg_lineLinear(points);
+    }
+    var quad = points.length != tangents.length, path = "", p0 = points[0], p = points[1], t0 = tangents[0], t = t0, pi = 1;
+    if (quad) {
+      path += "Q" + (p[0] - t0[0] * 2 / 3) + "," + (p[1] - t0[1] * 2 / 3) + "," + p[0] + "," + p[1];
+      p0 = points[1];
+      pi = 2;
+    }
+    if (tangents.length > 1) {
+      t = tangents[1];
+      p = points[pi];
+      pi++;
+      path += "C" + (p0[0] + t0[0]) + "," + (p0[1] + t0[1]) + "," + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1];
+      for (var i = 2; i < tangents.length; i++, pi++) {
+        p = points[pi];
+        t = tangents[i];
+        path += "S" + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1];
+      }
+    }
+    if (quad) {
+      var lp = points[pi];
+      path += "Q" + (p[0] + t[0] * 2 / 3) + "," + (p[1] + t[1] * 2 / 3) + "," + lp[0] + "," + lp[1];
+    }
+    return path;
+  }
+  function d3_svg_lineCardinalTangents(points, tension) {
+    var tangents = [], a = (1 - tension) / 2, p0, p1 = points[0], p2 = points[1], i = 1, n = points.length;
+    while (++i < n) {
+      p0 = p1;
+      p1 = p2;
+      p2 = points[i];
+      tangents.push([ a * (p2[0] - p0[0]), a * (p2[1] - p0[1]) ]);
+    }
+    return tangents;
+  }
+  function d3_svg_lineBasis(points) {
+    if (points.length < 3) return d3_svg_lineLinear(points);
+    var i = 1, n = points.length, pi = points[0], x0 = pi[0], y0 = pi[1], px = [ x0, x0, x0, (pi = points[1])[0] ], py = [ y0, y0, y0, pi[1] ], path = [ x0, ",", y0, "L", d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ];
+    points.push(points[n - 1]);
+    while (++i <= n) {
+      pi = points[i];
+      px.shift();
+      px.push(pi[0]);
+      py.shift();
+      py.push(pi[1]);
+      d3_svg_lineBasisBezier(path, px, py);
+    }
+    points.pop();
+    path.push("L", pi);
+    return path.join("");
+  }
+  function d3_svg_lineBasisOpen(points) {
+    if (points.length < 4) return d3_svg_lineLinear(points);
+    var path = [], i = -1, n = points.length, pi, px = [ 0 ], py = [ 0 ];
+    while (++i < 3) {
+      pi = points[i];
+      px.push(pi[0]);
+      py.push(pi[1]);
+    }
+    path.push(d3_svg_lineDot4(d3_svg_lineBasisBezier3, px) + "," + d3_svg_lineDot4(d3_svg_lineBasisBezier3, py));
+    --i;
+    while (++i < n) {
+      pi = points[i];
+      px.shift();
+      px.push(pi[0]);
+      py.shift();
+      py.push(pi[1]);
+      d3_svg_lineBasisBezier(path, px, py);
+    }
+    return path.join("");
+  }
+  function d3_svg_lineBasisClosed(points) {
+    var path, i = -1, n = points.length, m = n + 4, pi, px = [], py = [];
+    while (++i < 4) {
+      pi = points[i % n];
+      px.push(pi[0]);
+      py.push(pi[1]);
+    }
+    path = [ d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ];
+    --i;
+    while (++i < m) {
+      pi = points[i % n];
+      px.shift();
+      px.push(pi[0]);
+      py.shift();
+      py.push(pi[1]);
+      d3_svg_lineBasisBezier(path, px, py);
+    }
+    return path.join("");
+  }
+  function d3_svg_lineBundle(points, tension) {
+    var n = points.length - 1;
+    if (n) {
+      var x0 = points[0][0], y0 = points[0][1], dx = points[n][0] - x0, dy = points[n][1] - y0, i = -1, p, t;
+      while (++i <= n) {
+        p = points[i];
+        t = i / n;
+        p[0] = tension * p[0] + (1 - tension) * (x0 + t * dx);
+        p[1] = tension * p[1] + (1 - tension) * (y0 + t * dy);
+      }
+    }
+    return d3_svg_lineBasis(points);
+  }
+  function d3_svg_lineDot4(a, b) {
+    return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
+  }
+  var d3_svg_lineBasisBezier1 = [ 0, 2 / 3, 1 / 3, 0 ], d3_svg_lineBasisBezier2 = [ 0, 1 / 3, 2 / 3, 0 ], d3_svg_lineBasisBezier3 = [ 0, 1 / 6, 2 / 3, 1 / 6 ];
+  function d3_svg_lineBasisBezier(path, x, y) {
+    path.push("C", d3_svg_lineDot4(d3_svg_lineBasisBezier1, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier1, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, y));
+  }
+  function d3_svg_lineSlope(p0, p1) {
+    return (p1[1] - p0[1]) / (p1[0] - p0[0]);
+  }
+  function d3_svg_lineFiniteDifferences(points) {
+    var i = 0, j = points.length - 1, m = [], p0 = points[0], p1 = points[1], d = m[0] = d3_svg_lineSlope(p0, p1);
+    while (++i < j) {
+      m[i] = (d + (d = d3_svg_lineSlope(p0 = p1, p1 = points[i + 1]))) / 2;
+    }
+    m[i] = d;
+    return m;
+  }
+  function d3_svg_lineMonotoneTangents(points) {
+    var tangents = [], d, a, b, s, m = d3_svg_lineFiniteDifferences(points), i = -1, j = points.length - 1;
+    while (++i < j) {
+      d = d3_svg_lineSlope(points[i], points[i + 1]);
+      if (abs(d) < ε) {
+        m[i] = m[i + 1] = 0;
+      } else {
+        a = m[i] / d;
+        b = m[i + 1] / d;
+        s = a * a + b * b;
+        if (s > 9) {
+          s = d * 3 / Math.sqrt(s);
+          m[i] = s * a;
+          m[i + 1] = s * b;
+        }
+      }
+    }
+    i = -1;
+    while (++i <= j) {
+      s = (points[Math.min(j, i + 1)][0] - points[Math.max(0, i - 1)][0]) / (6 * (1 + m[i] * m[i]));
+      tangents.push([ s || 0, m[i] * s || 0 ]);
+    }
+    return tangents;
+  }
+  function d3_svg_lineMonotone(points) {
+    return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineMonotoneTangents(points));
+  }
+  d3.svg.line.radial = function() {
+    var line = d3_svg_line(d3_svg_lineRadial);
+    line.radius = line.x, delete line.x;
+    line.angle = line.y, delete line.y;
+    return line;
+  };
+  function d3_svg_lineRadial(points) {
+    var point, i = -1, n = points.length, r, a;
+    while (++i < n) {
+      point = points[i];
+      r = point[0];
+      a = point[1] + d3_svg_arcOffset;
+      point[0] = r * Math.cos(a);
+      point[1] = r * Math.sin(a);
+    }
+    return points;
+  }
+  function d3_svg_area(projection) {
+    var x0 = d3_geom_pointX, x1 = d3_geom_pointX, y0 = 0, y1 = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, interpolateReverse = interpolate, L = "L", tension = .7;
+    function area(data) {
+      var segments = [], points0 = [], points1 = [], i = -1, n = data.length, d, fx0 = d3_functor(x0), fy0 = d3_functor(y0), fx1 = x0 === x1 ? function() {
+        return x;
+      } : d3_functor(x1), fy1 = y0 === y1 ? function() {
+        return y;
+      } : d3_functor(y1), x, y;
+      function segment() {
+        segments.push("M", interpolate(projection(points1), tension), L, interpolateReverse(projection(points0.reverse()), tension), "Z");
+      }
+      while (++i < n) {
+        if (defined.call(this, d = data[i], i)) {
+          points0.push([ x = +fx0.call(this, d, i), y = +fy0.call(this, d, i) ]);
+          points1.push([ +fx1.call(this, d, i), +fy1.call(this, d, i) ]);
+        } else if (points0.length) {
+          segment();
+          points0 = [];
+          points1 = [];
+        }
+      }
+      if (points0.length) segment();
+      return segments.length ? segments.join("") : null;
+    }
+    area.x = function(_) {
+      if (!arguments.length) return x1;
+      x0 = x1 = _;
+      return area;
+    };
+    area.x0 = function(_) {
+      if (!arguments.length) return x0;
+      x0 = _;
+      return area;
+    };
+    area.x1 = function(_) {
+      if (!arguments.length) return x1;
+      x1 = _;
+      return area;
+    };
+    area.y = function(_) {
+      if (!arguments.length) return y1;
+      y0 = y1 = _;
+      return area;
+    };
+    area.y0 = function(_) {
+      if (!arguments.length) return y0;
+      y0 = _;
+      return area;
+    };
+    area.y1 = function(_) {
+      if (!arguments.length) return y1;
+      y1 = _;
+      return area;
+    };
+    area.defined = function(_) {
+      if (!arguments.length) return defined;
+      defined = _;
+      return area;
+    };
+    area.interpolate = function(_) {
+      if (!arguments.length) return interpolateKey;
+      if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key;
+      interpolateReverse = interpolate.reverse || interpolate;
+      L = interpolate.closed ? "M" : "L";
+      return area;
+    };
+    area.tension = function(_) {
+      if (!arguments.length) return tension;
+      tension = _;
+      return area;
+    };
+    return area;
+  }
+  d3_svg_lineStepBefore.reverse = d3_svg_lineStepAfter;
+  d3_svg_lineStepAfter.reverse = d3_svg_lineStepBefore;
+  d3.svg.area = function() {
+    return d3_svg_area(d3_identity);
+  };
+  d3.svg.area.radial = function() {
+    var area = d3_svg_area(d3_svg_lineRadial);
+    area.radius = area.x, delete area.x;
+    area.innerRadius = area.x0, delete area.x0;
+    area.outerRadius = area.x1, delete area.x1;
+    area.angle = area.y, delete area.y;
+    area.startAngle = area.y0, delete area.y0;
+    area.endAngle = area.y1, delete area.y1;
+    return area;
+  };
+  d3.svg.chord = function() {
+    var source = d3_source, target = d3_target, radius = d3_svg_chordRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle;
+    function chord(d, i) {
+      var s = subgroup(this, source, d, i), t = subgroup(this, target, d, i);
+      return "M" + s.p0 + arc(s.r, s.p1, s.a1 - s.a0) + (equals(s, t) ? curve(s.r, s.p1, s.r, s.p0) : curve(s.r, s.p1, t.r, t.p0) + arc(t.r, t.p1, t.a1 - t.a0) + curve(t.r, t.p1, s.r, s.p0)) + "Z";
+    }
+    function subgroup(self, f, d, i) {
+      var subgroup = f.call(self, d, i), r = radius.call(self, subgroup, i), a0 = startAngle.call(self, subgroup, i) + d3_svg_arcOffset, a1 = endAngle.call(self, subgroup, i) + d3_svg_arcOffset;
+      return {
+        r: r,
+        a0: a0,
+        a1: a1,
+        p0: [ r * Math.cos(a0), r * Math.sin(a0) ],
+        p1: [ r * Math.cos(a1), r * Math.sin(a1) ]
+      };
+    }
+    function equals(a, b) {
+      return a.a0 == b.a0 && a.a1 == b.a1;
+    }
+    function arc(r, p, a) {
+      return "A" + r + "," + r + " 0 " + +(a > π) + ",1 " + p;
+    }
+    function curve(r0, p0, r1, p1) {
+      return "Q 0,0 " + p1;
+    }
+    chord.radius = function(v) {
+      if (!arguments.length) return radius;
+      radius = d3_functor(v);
+      return chord;
+    };
+    chord.source = function(v) {
+      if (!arguments.length) return source;
+      source = d3_functor(v);
+      return chord;
+    };
+    chord.target = function(v) {
+      if (!arguments.length) return target;
+      target = d3_functor(v);
+      return chord;
+    };
+    chord.startAngle = function(v) {
+      if (!arguments.length) return startAngle;
+      startAngle = d3_functor(v);
+      return chord;
+    };
+    chord.endAngle = function(v) {
+      if (!arguments.length) return endAngle;
+      endAngle = d3_functor(v);
+      return chord;
+    };
+    return chord;
+  };
+  function d3_svg_chordRadius(d) {
+    return d.radius;
+  }
+  d3.svg.diagonal = function() {
+    var source = d3_source, target = d3_target, projection = d3_svg_diagonalProjection;
+    function diagonal(d, i) {
+      var p0 = source.call(this, d, i), p3 = target.call(this, d, i), m = (p0.y + p3.y) / 2, p = [ p0, {
+        x: p0.x,
+        y: m
+      }, {
+        x: p3.x,
+        y: m
+      }, p3 ];
+      p = p.map(projection);
+      return "M" + p[0] + "C" + p[1] + " " + p[2] + " " + p[3];
+    }
+    diagonal.source = function(x) {
+      if (!arguments.length) return source;
+      source = d3_functor(x);
+      return diagonal;
+    };
+    diagonal.target = function(x) {
+      if (!arguments.length) return target;
+      target = d3_functor(x);
+      return diagonal;
+    };
+    diagonal.projection = function(x) {
+      if (!arguments.length) return projection;
+      projection = x;
+      return diagonal;
+    };
+    return diagonal;
+  };
+  function d3_svg_diagonalProjection(d) {
+    return [ d.x, d.y ];
+  }
+  d3.svg.diagonal.radial = function() {
+    var diagonal = d3.svg.diagonal(), projection = d3_svg_diagonalProjection, projection_ = diagonal.projection;
+    diagonal.projection = function(x) {
+      return arguments.length ? projection_(d3_svg_diagonalRadialProjection(projection = x)) : projection;
+    };
+    return diagonal;
+  };
+  function d3_svg_diagonalRadialProjection(projection) {
+    return function() {
+      var d = projection.apply(this, arguments), r = d[0], a = d[1] + d3_svg_arcOffset;
+      return [ r * Math.cos(a), r * Math.sin(a) ];
+    };
+  }
+  d3.svg.symbol = function() {
+    var type = d3_svg_symbolType, size = d3_svg_symbolSize;
+    function symbol(d, i) {
+      return (d3_svg_symbols.get(type.call(this, d, i)) || d3_svg_symbolCircle)(size.call(this, d, i));
+    }
+    symbol.type = function(x) {
+      if (!arguments.length) return type;
+      type = d3_functor(x);
+      return symbol;
+    };
+    symbol.size = function(x) {
+      if (!arguments.length) return size;
+      size = d3_functor(x);
+      return symbol;
+    };
+    return symbol;
+  };
+  function d3_svg_symbolSize() {
+    return 64;
+  }
+  function d3_svg_symbolType() {
+    return "circle";
+  }
+  function d3_svg_symbolCircle(size) {
+    var r = Math.sqrt(size / π);
+    return "M0," + r + "A" + r + "," + r + " 0 1,1 0," + -r + "A" + r + "," + r + " 0 1,1 0," + r + "Z";
+  }
+  var d3_svg_symbols = d3.map({
+    circle: d3_svg_symbolCircle,
+    cross: function(size) {
+      var r = Math.sqrt(size / 5) / 2;
+      return "M" + -3 * r + "," + -r + "H" + -r + "V" + -3 * r + "H" + r + "V" + -r + "H" + 3 * r + "V" + r + "H" + r + "V" + 3 * r + "H" + -r + "V" + r + "H" + -3 * r + "Z";
+    },
+    diamond: function(size) {
+      var ry = Math.sqrt(size / (2 * d3_svg_symbolTan30)), rx = ry * d3_svg_symbolTan30;
+      return "M0," + -ry + "L" + rx + ",0" + " 0," + ry + " " + -rx + ",0" + "Z";
+    },
+    square: function(size) {
+      var r = Math.sqrt(size) / 2;
+      return "M" + -r + "," + -r + "L" + r + "," + -r + " " + r + "," + r + " " + -r + "," + r + "Z";
+    },
+    "triangle-down": function(size) {
+      var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2;
+      return "M0," + ry + "L" + rx + "," + -ry + " " + -rx + "," + -ry + "Z";
+    },
+    "triangle-up": function(size) {
+      var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2;
+      return "M0," + -ry + "L" + rx + "," + ry + " " + -rx + "," + ry + "Z";
+    }
+  });
+  d3.svg.symbolTypes = d3_svg_symbols.keys();
+  var d3_svg_symbolSqrt3 = Math.sqrt(3), d3_svg_symbolTan30 = Math.tan(30 * d3_radians);
+  function d3_transition(groups, id) {
+    d3_subclass(groups, d3_transitionPrototype);
+    groups.id = id;
+    return groups;
+  }
+  var d3_transitionPrototype = [], d3_transitionId = 0, d3_transitionInheritId, d3_transitionInherit;
+  d3_transitionPrototype.call = d3_selectionPrototype.call;
+  d3_transitionPrototype.empty = d3_selectionPrototype.empty;
+  d3_transitionPrototype.node = d3_selectionPrototype.node;
+  d3_transitionPrototype.size = d3_selectionPrototype.size;
+  d3.transition = function(selection) {
+    return arguments.length ? d3_transitionInheritId ? selection.transition() : selection : d3_selectionRoot.transition();
+  };
+  d3.transition.prototype = d3_transitionPrototype;
+  d3_transitionPrototype.select = function(selector) {
+    var id = this.id, subgroups = [], subgroup, subnode, node;
+    selector = d3_selection_selector(selector);
+    for (var j = -1, m = this.length; ++j < m; ) {
+      subgroups.push(subgroup = []);
+      for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
+        if ((node = group[i]) && (subnode = selector.call(node, node.__data__, i, j))) {
+          if ("__data__" in node) subnode.__data__ = node.__data__;
+          d3_transitionNode(subnode, i, id, node.__transition__[id]);
+          subgroup.push(subnode);
+        } else {
+          subgroup.push(null);
+        }
+      }
+    }
+    return d3_transition(subgroups, id);
+  };
+  d3_transitionPrototype.selectAll = function(selector) {
+    var id = this.id, subgroups = [], subgroup, subnodes, node, subnode, transition;
+    selector = d3_selection_selectorAll(selector);
+    for (var j = -1, m = this.length; ++j < m; ) {
+      for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
+        if (node = group[i]) {
+          transition = node.__transition__[id];
+          subnodes = selector.call(node, node.__data__, i, j);
+          subgroups.push(subgroup = []);
+          for (var k = -1, o = subnodes.length; ++k < o; ) {
+            if (subnode = subnodes[k]) d3_transitionNode(subnode, k, id, transition);
+            subgroup.push(subnode);
+          }
+        }
+      }
+    }
+    return d3_transition(subgroups, id);
+  };
+  d3_transitionPrototype.filter = function(filter) {
+    var subgroups = [], subgroup, group, node;
+    if (typeof filter !== "function") filter = d3_selection_filter(filter);
+    for (var j = 0, m = this.length; j < m; j++) {
+      subgroups.push(subgroup = []);
+      for (var group = this[j], i = 0, n = group.length; i < n; i++) {
+        if ((node = group[i]) && filter.call(node, node.__data__, i, j)) {
+          subgroup.push(node);
+        }
+      }
+    }
+    return d3_transition(subgroups, this.id);
+  };
+  d3_transitionPrototype.tween = function(name, tween) {
+    var id = this.id;
+    if (arguments.length < 2) return this.node().__transition__[id].tween.get(name);
+    return d3_selection_each(this, tween == null ? function(node) {
+      node.__transition__[id].tween.remove(name);
+    } : function(node) {
+      node.__transition__[id].tween.set(name, tween);
+    });
+  };
+  function d3_transition_tween(groups, name, value, tween) {
+    var id = groups.id;
+    return d3_selection_each(groups, typeof value === "function" ? function(node, i, j) {
+      node.__transition__[id].tween.set(name, tween(value.call(node, node.__data__, i, j)));
+    } : (value = tween(value), function(node) {
+      node.__transition__[id].tween.set(name, value);
+    }));
+  }
+  d3_transitionPrototype.attr = function(nameNS, value) {
+    if (arguments.length < 2) {
+      for (value in nameNS) this.attr(value, nameNS[value]);
+      return this;
+    }
+    var interpolate = nameNS == "transform" ? d3_interpolateTransform : d3_interpolate, name = d3.ns.qualify(nameNS);
+    function attrNull() {
+      this.removeAttribute(name);
+    }
+    function attrNullNS() {
+      this.removeAttributeNS(name.space, name.local);
+    }
+    function attrTween(b) {
+      return b == null ? attrNull : (b += "", function() {
+        var a = this.getAttribute(name), i;
+        return a !== b && (i = interpolate(a, b), function(t) {
+          this.setAttribute(name, i(t));
+        });
+      });
+    }
+    function attrTweenNS(b) {
+      return b == null ? attrNullNS : (b += "", function() {
+        var a = this.getAttributeNS(name.space, name.local), i;
+        return a !== b && (i = interpolate(a, b), function(t) {
+          this.setAttributeNS(name.space, name.local, i(t));
+        });
+      });
+    }
+    return d3_transition_tween(this, "attr." + nameNS, value, name.local ? attrTweenNS : attrTween);
+  };
+  d3_transitionPrototype.attrTween = function(nameNS, tween) {
+    var name = d3.ns.qualify(nameNS);
+    function attrTween(d, i) {
+      var f = tween.call(this, d, i, this.getAttribute(name));
+      return f && function(t) {
+        this.setAttribute(name, f(t));
+      };
+    }
+    function attrTweenNS(d, i) {
+      var f = tween.call(this, d, i, this.getAttributeNS(name.space, name.local));
+      return f && function(t) {
+        this.setAttributeNS(name.space, name.local, f(t));
+      };
+    }
+    return this.tween("attr." + nameNS, name.local ? attrTweenNS : attrTween);
+  };
+  d3_transitionPrototype.style = function(name, value, priority) {
+    var n = arguments.length;
+    if (n < 3) {
+      if (typeof name !== "string") {
+        if (n < 2) value = "";
+        for (priority in name) this.style(priority, name[priority], value);
+        return this;
+      }
+      priority = "";
+    }
+    function styleNull() {
+      this.style.removeProperty(name);
+    }
+    function styleString(b) {
+      return b == null ? styleNull : (b += "", function() {
+        var a = d3_window.getComputedStyle(this, null).getPropertyValue(name), i;
+        return a !== b && (i = d3_interpolate(a, b), function(t) {
+          this.style.setProperty(name, i(t), priority);
+        });
+      });
+    }
+    return d3_transition_tween(this, "style." + name, value, styleString);
+  };
+  d3_transitionPrototype.styleTween = function(name, tween, priority) {
+    if (arguments.length < 3) priority = "";
+    function styleTween(d, i) {
+      var f = tween.call(this, d, i, d3_window.getComputedStyle(this, null).getPropertyValue(name));
+      return f && function(t) {
+        this.style.setProperty(name, f(t), priority);
+      };
+    }
+    return this.tween("style." + name, styleTween);
+  };
+  d3_transitionPrototype.text = function(value) {
+    return d3_transition_tween(this, "text", value, d3_transition_text);
+  };
+  function d3_transition_text(b) {
+    if (b == null) b = "";
+    return function() {
+      this.textContent = b;
+    };
+  }
+  d3_transitionPrototype.remove = function() {
+    return this.each("end.transition", function() {
+      var p;
+      if (this.__transition__.count < 2 && (p = this.parentNode)) p.removeChild(this);
+    });
+  };
+  d3_transitionPrototype.ease = function(value) {
+    var id = this.id;
+    if (arguments.length < 1) return this.node().__transition__[id].ease;
+    if (typeof value !== "function") value = d3.ease.apply(d3, arguments);
+    return d3_selection_each(this, function(node) {
+      node.__transition__[id].ease = value;
+    });
+  };
+  d3_transitionPrototype.delay = function(value) {
+    var id = this.id;
+    if (arguments.length < 1) return this.node().__transition__[id].delay;
+    return d3_selection_each(this, typeof value === "function" ? function(node, i, j) {
+      node.__transition__[id].delay = +value.call(node, node.__data__, i, j);
+    } : (value = +value, function(node) {
+      node.__transition__[id].delay = value;
+    }));
+  };
+  d3_transitionPrototype.duration = function(value) {
+    var id = this.id;
+    if (arguments.length < 1) return this.node().__transition__[id].duration;
+    return d3_selection_each(this, typeof value === "function" ? function(node, i, j) {
+      node.__transition__[id].duration = Math.max(1, value.call(node, node.__data__, i, j));
+    } : (value = Math.max(1, value), function(node) {
+      node.__transition__[id].duration = value;
+    }));
+  };
+  d3_transitionPrototype.each = function(type, listener) {
+    var id = this.id;
+    if (arguments.length < 2) {
+      var inherit = d3_transitionInherit, inheritId = d3_transitionInheritId;
+      d3_transitionInheritId = id;
+      d3_selection_each(this, function(node, i, j) {
+        d3_transitionInherit = node.__transition__[id];
+        type.call(node, node.__data__, i, j);
+      });
+      d3_transitionInherit = inherit;
+      d3_transitionInheritId = inheritId;
+    } else {
+      d3_selection_each(this, function(node) {
+        var transition = node.__transition__[id];
+        (transition.event || (transition.event = d3.dispatch("start", "end"))).on(type, listener);
+      });
+    }
+    return this;
+  };
+  d3_transitionPrototype.transition = function() {
+    var id0 = this.id, id1 = ++d3_transitionId, subgroups = [], subgroup, group, node, transition;
+    for (var j = 0, m = this.length; j < m; j++) {
+      subgroups.push(subgroup = []);
+      for (var group = this[j], i = 0, n = group.length; i < n; i++) {
+        if (node = group[i]) {
+          transition = Object.create(node.__transition__[id0]);
+          transition.delay += transition.duration;
+          d3_transitionNode(node, i, id1, transition);
+        }
+        subgroup.push(node);
+      }
+    }
+    return d3_transition(subgroups, id1);
+  };
+  function d3_transitionNode(node, i, id, inherit) {
+    var lock = node.__transition__ || (node.__transition__ = {
+      active: 0,
+      count: 0
+    }), transition = lock[id];
+    if (!transition) {
+      var time = inherit.time;
+      transition = lock[id] = {
+        tween: new d3_Map(),
+        time: time,
+        ease: inherit.ease,
+        delay: inherit.delay,
+        duration: inherit.duration
+      };
+      ++lock.count;
+      d3.timer(function(elapsed) {
+        var d = node.__data__, ease = transition.ease, delay = transition.delay, duration = transition.duration, timer = d3_timer_active, tweened = [];
+        timer.t = delay + time;
+        if (delay <= elapsed) return start(elapsed - delay);
+        timer.c = start;
+        function start(elapsed) {
+          if (lock.active > id) return stop();
+          lock.active = id;
+          transition.event && transition.event.start.call(node, d, i);
+          transition.tween.forEach(function(key, value) {
+            if (value = value.call(node, d, i)) {
+              tweened.push(value);
+            }
+          });
+          d3.timer(function() {
+            timer.c = tick(elapsed || 1) ? d3_true : tick;
+            return 1;
+          }, 0, time);
+        }
+        function tick(elapsed) {
+          if (lock.active !== id) return stop();
+          var t = elapsed / duration, e = ease(t), n = tweened.length;
+          while (n > 0) {
+            tweened[--n].call(node, e);
+          }
+          if (t >= 1) {
+            transition.event && transition.event.end.call(node, d, i);
+            return stop();
+          }
+        }
+        function stop() {
+          if (--lock.count) delete lock[id]; else delete node.__transition__;
+          return 1;
+        }
+      }, 0, time);
+    }
+  }
+  d3.svg.axis = function() {
+    var scale = d3.scale.linear(), orient = d3_svg_axisDefaultOrient, innerTickSize = 6, outerTickSize = 6, tickPadding = 3, tickArguments_ = [ 10 ], tickValues = null, tickFormat_;
+    function axis(g) {
+      g.each(function() {
+        var g = d3.select(this);
+        var scale0 = this.__chart__ || scale, scale1 = this.__chart__ = scale.copy();
+        var ticks = tickValues == null ? scale1.ticks ? scale1.ticks.apply(scale1, tickArguments_) : scale1.domain() : tickValues, tickFormat = tickFormat_ == null ? scale1.tickFormat ? scale1.tickFormat.apply(scale1, tickArguments_) : d3_identity : tickFormat_, tick = g.selectAll(".tick").data(ticks, scale1), tickEnter = tick.enter().insert("g", ".domain").attr("class", "tick").style("opacity", ε), tickExit = d3.transition(tick.exit()).style("opacity", ε).remove(), tickUpdate = d3.transition(tick.order()).style("opacity", 1), tickTransform;
+        var range = d3_scaleRange(scale1), path = g.selectAll(".domain").data([ 0 ]), pathUpdate = (path.enter().append("path").attr("class", "domain"), 
+        d3.transition(path));
+        tickEnter.append("line");
+        tickEnter.append("text");
+        var lineEnter = tickEnter.select("line"), lineUpdate = tickUpdate.select("line"), text = tick.select("text").text(tickFormat), textEnter = tickEnter.select("text"), textUpdate = tickUpdate.select("text");
+        switch (orient) {
+         case "bottom":
+          {
+            tickTransform = d3_svg_axisX;
+            lineEnter.attr("y2", innerTickSize);
+            textEnter.attr("y", Math.max(innerTickSize, 0) + tickPadding);
+            lineUpdate.attr("x2", 0).attr("y2", innerTickSize);
+            textUpdate.attr("x", 0).attr("y", Math.max(innerTickSize, 0) + tickPadding);
+            text.attr("dy", ".71em").style("text-anchor", "middle");
+            pathUpdate.attr("d", "M" + range[0] + "," + outerTickSize + "V0H" + range[1] + "V" + outerTickSize);
+            break;
+          }
+
+         case "top":
+          {
+            tickTransform = d3_svg_axisX;
+            lineEnter.attr("y2", -innerTickSize);
+            textEnter.attr("y", -(Math.max(innerTickSize, 0) + tickPadding));
+            lineUpdate.attr("x2", 0).attr("y2", -innerTickSize);
+            textUpdate.attr("x", 0).attr("y", -(Math.max(innerTickSize, 0) + tickPadding));
+            text.attr("dy", "0em").style("text-anchor", "middle");
+            pathUpdate.attr("d", "M" + range[0] + "," + -outerTickSize + "V0H" + range[1] + "V" + -outerTickSize);
+            break;
+          }
+
+         case "left":
+          {
+            tickTransform = d3_svg_axisY;
+            lineEnter.attr("x2", -innerTickSize);
+            textEnter.attr("x", -(Math.max(innerTickSize, 0) + tickPadding));
+            lineUpdate.attr("x2", -innerTickSize).attr("y2", 0);
+            textUpdate.attr("x", -(Math.max(innerTickSize, 0) + tickPadding)).attr("y", 0);
+            text.attr("dy", ".32em").style("text-anchor", "end");
+            pathUpdate.attr("d", "M" + -outerTickSize + "," + range[0] + "H0V" + range[1] + "H" + -outerTickSize);
+            break;
+          }
+
+         case "right":
+          {
+            tickTransform = d3_svg_axisY;
+            lineEnter.attr("x2", innerTickSize);
+            textEnter.attr("x", Math.max(innerTickSize, 0) + tickPadding);
+            lineUpdate.attr("x2", innerTickSize).attr("y2", 0);
+            textUpdate.attr("x", Math.max(innerTickSize, 0) + tickPadding).attr("y", 0);
+            text.attr("dy", ".32em").style("text-anchor", "start");
+            pathUpdate.attr("d", "M" + outerTickSize + "," + range[0] + "H0V" + range[1] + "H" + outerTickSize);
+            break;
+          }
+        }
+        if (scale1.rangeBand) {
+          var x = scale1, dx = x.rangeBand() / 2;
+          scale0 = scale1 = function(d) {
+            return x(d) + dx;
+          };
+        } else if (scale0.rangeBand) {
+          scale0 = scale1;
+        } else {
+          tickExit.call(tickTransform, scale1);
+        }
+        tickEnter.call(tickTransform, scale0);
+        tickUpdate.call(tickTransform, scale1);
+      });
+    }
+    axis.scale = function(x) {
+      if (!arguments.length) return scale;
+      scale = x;
+      return axis;
+    };
+    axis.orient = function(x) {
+      if (!arguments.length) return orient;
+      orient = x in d3_svg_axisOrients ? x + "" : d3_svg_axisDefaultOrient;
+      return axis;
+    };
+    axis.ticks = function() {
+      if (!arguments.length) return tickArguments_;
+      tickArguments_ = arguments;
+      return axis;
+    };
+    axis.tickValues = function(x) {
+      if (!arguments.length) return tickValues;
+      tickValues = x;
+      return axis;
+    };
+    axis.tickFormat = function(x) {
+      if (!arguments.length) return tickFormat_;
+      tickFormat_ = x;
+      return axis;
+    };
+    axis.tickSize = function(x) {
+      var n = arguments.length;
+      if (!n) return innerTickSize;
+      innerTickSize = +x;
+      outerTickSize = +arguments[n - 1];
+      return axis;
+    };
+    axis.innerTickSize = function(x) {
+      if (!arguments.length) return innerTickSize;
+      innerTickSize = +x;
+      return axis;
+    };
+    axis.outerTickSize = function(x) {
+      if (!arguments.length) return outerTickSize;
+      outerTickSize = +x;
+      return axis;
+    };
+    axis.tickPadding = function(x) {
+      if (!arguments.length) return tickPadding;
+      tickPadding = +x;
+      return axis;
+    };
+    axis.tickSubdivide = function() {
+      return arguments.length && axis;
+    };
+    return axis;
+  };
+  var d3_svg_axisDefaultOrient = "bottom", d3_svg_axisOrients = {
+    top: 1,
+    right: 1,
+    bottom: 1,
+    left: 1
+  };
+  function d3_svg_axisX(selection, x) {
+    selection.attr("transform", function(d) {
+      return "translate(" + x(d) + ",0)";
+    });
+  }
+  function d3_svg_axisY(selection, y) {
+    selection.attr("transform", function(d) {
+      return "translate(0," + y(d) + ")";
+    });
+  }
+  d3.svg.brush = function() {
+    var event = d3_eventDispatch(brush, "brushstart", "brush", "brushend"), x = null, y = null, xExtent = [ 0, 0 ], yExtent = [ 0, 0 ], xExtentDomain, yExtentDomain, xClamp = true, yClamp = true, resizes = d3_svg_brushResizes[0];
+    function brush(g) {
+      g.each(function() {
+        var g = d3.select(this).style("pointer-events", "all").style("-webkit-tap-highlight-color", "rgba(0,0,0,0)").on("mousedown.brush", brushstart).on("touchstart.brush", brushstart);
+        var background = g.selectAll(".background").data([ 0 ]);
+        background.enter().append("rect").attr("class", "background").style("visibility", "hidden").style("cursor", "crosshair");
+        g.selectAll(".extent").data([ 0 ]).enter().append("rect").attr("class", "extent").style("cursor", "move");
+        var resize = g.selectAll(".resize").data(resizes, d3_identity);
+        resize.exit().remove();
+        resize.enter().append("g").attr("class", function(d) {
+          return "resize " + d;
+        }).style("cursor", function(d) {
+          return d3_svg_brushCursor[d];
+        }).append("rect").attr("x", function(d) {
+          return /[ew]$/.test(d) ? -3 : null;
+        }).attr("y", function(d) {
+          return /^[ns]/.test(d) ? -3 : null;
+        }).attr("width", 6).attr("height", 6).style("visibility", "hidden");
+        resize.style("display", brush.empty() ? "none" : null);
+        var gUpdate = d3.transition(g), backgroundUpdate = d3.transition(background), range;
+        if (x) {
+          range = d3_scaleRange(x);
+          backgroundUpdate.attr("x", range[0]).attr("width", range[1] - range[0]);
+          redrawX(gUpdate);
+        }
+        if (y) {
+          range = d3_scaleRange(y);
+          backgroundUpdate.attr("y", range[0]).attr("height", range[1] - range[0]);
+          redrawY(gUpdate);
+        }
+        redraw(gUpdate);
+      });
+    }
+    brush.event = function(g) {
+      g.each(function() {
+        var event_ = event.of(this, arguments), extent1 = {
+          x: xExtent,
+          y: yExtent,
+          i: xExtentDomain,
+          j: yExtentDomain
+        }, extent0 = this.__chart__ || extent1;
+        this.__chart__ = extent1;
+        if (d3_transitionInheritId) {
+          d3.select(this).transition().each("start.brush", function() {
+            xExtentDomain = extent0.i;
+            yExtentDomain = extent0.j;
+            xExtent = extent0.x;
+            yExtent = extent0.y;
+            event_({
+              type: "brushstart"
+            });
+          }).tween("brush:brush", function() {
+            var xi = d3_interpolateArray(xExtent, extent1.x), yi = d3_interpolateArray(yExtent, extent1.y);
+            xExtentDomain = yExtentDomain = null;
+            return function(t) {
+              xExtent = extent1.x = xi(t);
+              yExtent = extent1.y = yi(t);
+              event_({
+                type: "brush",
+                mode: "resize"
+              });
+            };
+          }).each("end.brush", function() {
+            xExtentDomain = extent1.i;
+            yExtentDomain = extent1.j;
+            event_({
+              type: "brush",
+              mode: "resize"
+            });
+            event_({
+              type: "brushend"
+            });
+          });
+        } else {
+          event_({
+            type: "brushstart"
+          });
+          event_({
+            type: "brush",
+            mode: "resize"
+          });
+          event_({
+            type: "brushend"
+          });
+        }
+      });
+    };
+    function redraw(g) {
+      g.selectAll(".resize").attr("transform", function(d) {
+        return "translate(" + xExtent[+/e$/.test(d)] + "," + yExtent[+/^s/.test(d)] + ")";
+      });
+    }
+    function redrawX(g) {
+      g.select(".extent").attr("x", xExtent[0]);
+      g.selectAll(".extent,.n>rect,.s>rect").attr("width", xExtent[1] - xExtent[0]);
+    }
+    function redrawY(g) {
+      g.select(".extent").attr("y", yExtent[0]);
+      g.selectAll(".extent,.e>rect,.w>rect").attr("height", yExtent[1] - yExtent[0]);
+    }
+    function brushstart() {
+      var target = this, eventTarget = d3.select(d3.event.target), event_ = event.of(target, arguments), g = d3.select(target), resizing = eventTarget.datum(), resizingX = !/^(n|s)$/.test(resizing) && x, resizingY = !/^(e|w)$/.test(resizing) && y, dragging = eventTarget.classed("extent"), dragRestore = d3_event_dragSuppress(), center, origin = d3.mouse(target), offset;
+      var w = d3.select(d3_window).on("keydown.brush", keydown).on("keyup.brush", keyup);
+      if (d3.event.changedTouches) {
+        w.on("touchmove.brush", brushmove).on("touchend.brush", brushend);
+      } else {
+        w.on("mousemove.brush", brushmove).on("mouseup.brush", brushend);
+      }
+      g.interrupt().selectAll("*").interrupt();
+      if (dragging) {
+        origin[0] = xExtent[0] - origin[0];
+        origin[1] = yExtent[0] - origin[1];
+      } else if (resizing) {
+        var ex = +/w$/.test(resizing), ey = +/^n/.test(resizing);
+        offset = [ xExtent[1 - ex] - origin[0], yExtent[1 - ey] - origin[1] ];
+        origin[0] = xExtent[ex];
+        origin[1] = yExtent[ey];
+      } else if (d3.event.altKey) center = origin.slice();
+      g.style("pointer-events", "none").selectAll(".resize").style("display", null);
+      d3.select("body").style("cursor", eventTarget.style("cursor"));
+      event_({
+        type: "brushstart"
+      });
+      brushmove();
+      function keydown() {
+        if (d3.event.keyCode == 32) {
+          if (!dragging) {
+            center = null;
+            origin[0] -= xExtent[1];
+            origin[1] -= yExtent[1];
+            dragging = 2;
+          }
+          d3_eventPreventDefault();
+        }
+      }
+      function keyup() {
+        if (d3.event.keyCode == 32 && dragging == 2) {
+          origin[0] += xExtent[1];
+          origin[1] += yExtent[1];
+          dragging = 0;
+          d3_eventPreventDefault();
+        }
+      }
+      function brushmove() {
+        var point = d3.mouse(target), moved = false;
+        if (offset) {
+          point[0] += offset[0];
+          point[1] += offset[1];
+        }
+        if (!dragging) {
+          if (d3.event.altKey) {
+            if (!center) center = [ (xExtent[0] + xExtent[1]) / 2, (yExtent[0] + yExtent[1]) / 2 ];
+            origin[0] = xExtent[+(point[0] < center[0])];
+            origin[1] = yExtent[+(point[1] < center[1])];
+          } else center = null;
+        }
+        if (resizingX && move1(point, x, 0)) {
+          redrawX(g);
+          moved = true;
+        }
+        if (resizingY && move1(point, y, 1)) {
+          redrawY(g);
+          moved = true;
+        }
+        if (moved) {
+          redraw(g);
+          event_({
+            type: "brush",
+            mode: dragging ? "move" : "resize"
+          });
+        }
+      }
+      function move1(point, scale, i) {
+        var range = d3_scaleRange(scale), r0 = range[0], r1 = range[1], position = origin[i], extent = i ? yExtent : xExtent, size = extent[1] - extent[0], min, max;
+        if (dragging) {
+          r0 -= position;
+          r1 -= size + position;
+        }
+        min = (i ? yClamp : xClamp) ? Math.max(r0, Math.min(r1, point[i])) : point[i];
+        if (dragging) {
+          max = (min += position) + size;
+        } else {
+          if (center) position = Math.max(r0, Math.min(r1, 2 * center[i] - min));
+          if (position < min) {
+            max = min;
+            min = position;
+          } else {
+            max = position;
+          }
+        }
+        if (extent[0] != min || extent[1] != max) {
+          if (i) yExtentDomain = null; else xExtentDomain = null;
+          extent[0] = min;
+          extent[1] = max;
+          return true;
+        }
+      }
+      function brushend() {
+        brushmove();
+        g.style("pointer-events", "all").selectAll(".resize").style("display", brush.empty() ? "none" : null);
+        d3.select("body").style("cursor", null);
+        w.on("mousemove.brush", null).on("mouseup.brush", null).on("touchmove.brush", null).on("touchend.brush", null).on("keydown.brush", null).on("keyup.brush", null);
+        dragRestore();
+        event_({
+          type: "brushend"
+        });
+      }
+    }
+    brush.x = function(z) {
+      if (!arguments.length) return x;
+      x = z;
+      resizes = d3_svg_brushResizes[!x << 1 | !y];
+      return brush;
+    };
+    brush.y = function(z) {
+      if (!arguments.length) return y;
+      y = z;
+      resizes = d3_svg_brushResizes[!x << 1 | !y];
+      return brush;
+    };
+    brush.clamp = function(z) {
+      if (!arguments.length) return x && y ? [ xClamp, yClamp ] : x ? xClamp : y ? yClamp : null;
+      if (x && y) xClamp = !!z[0], yClamp = !!z[1]; else if (x) xClamp = !!z; else if (y) yClamp = !!z;
+      return brush;
+    };
+    brush.extent = function(z) {
+      var x0, x1, y0, y1, t;
+      if (!arguments.length) {
+        if (x) {
+          if (xExtentDomain) {
+            x0 = xExtentDomain[0], x1 = xExtentDomain[1];
+          } else {
+            x0 = xExtent[0], x1 = xExtent[1];
+            if (x.invert) x0 = x.invert(x0), x1 = x.invert(x1);
+            if (x1 < x0) t = x0, x0 = x1, x1 = t;
+          }
+        }
+        if (y) {
+          if (yExtentDomain) {
+            y0 = yExtentDomain[0], y1 = yExtentDomain[1];
+          } else {
+            y0 = yExtent[0], y1 = yExtent[1];
+            if (y.invert) y0 = y.invert(y0), y1 = y.invert(y1);
+            if (y1 < y0) t = y0, y0 = y1, y1 = t;
+          }
+        }
+        return x && y ? [ [ x0, y0 ], [ x1, y1 ] ] : x ? [ x0, x1 ] : y && [ y0, y1 ];
+      }
+      if (x) {
+        x0 = z[0], x1 = z[1];
+        if (y) x0 = x0[0], x1 = x1[0];
+        xExtentDomain = [ x0, x1 ];
+        if (x.invert) x0 = x(x0), x1 = x(x1);
+        if (x1 < x0) t = x0, x0 = x1, x1 = t;
+        if (x0 != xExtent[0] || x1 != xExtent[1]) xExtent = [ x0, x1 ];
+      }
+      if (y) {
+        y0 = z[0], y1 = z[1];
+        if (x) y0 = y0[1], y1 = y1[1];
+        yExtentDomain = [ y0, y1 ];
+        if (y.invert) y0 = y(y0), y1 = y(y1);
+        if (y1 < y0) t = y0, y0 = y1, y1 = t;
+        if (y0 != yExtent[0] || y1 != yExtent[1]) yExtent = [ y0, y1 ];
+      }
+      return brush;
+    };
+    brush.clear = function() {
+      if (!brush.empty()) {
+        xExtent = [ 0, 0 ], yExtent = [ 0, 0 ];
+        xExtentDomain = yExtentDomain = null;
+      }
+      return brush;
+    };
+    brush.empty = function() {
+      return !!x && xExtent[0] == xExtent[1] || !!y && yExtent[0] == yExtent[1];
+    };
+    return d3.rebind(brush, event, "on");
+  };
+  var d3_svg_brushCursor = {
+    n: "ns-resize",
+    e: "ew-resize",
+    s: "ns-resize",
+    w: "ew-resize",
+    nw: "nwse-resize",
+    ne: "nesw-resize",
+    se: "nwse-resize",
+    sw: "nesw-resize"
+  };
+  var d3_svg_brushResizes = [ [ "n", "e", "s", "w", "nw", "ne", "se", "sw" ], [ "e", "w" ], [ "n", "s" ], [] ];
+  var d3_time_format = d3_time.format = d3_locale_enUS.timeFormat;
+  var d3_time_formatUtc = d3_time_format.utc;
+  var d3_time_formatIso = d3_time_formatUtc("%Y-%m-%dT%H:%M:%S.%LZ");
+  d3_time_format.iso = Date.prototype.toISOString && +new Date("2000-01-01T00:00:00.000Z") ? d3_time_formatIsoNative : d3_time_formatIso;
+  function d3_time_formatIsoNative(date) {
+    return date.toISOString();
+  }
+  d3_time_formatIsoNative.parse = function(string) {
+    var date = new Date(string);
+    return isNaN(date) ? null : date;
+  };
+  d3_time_formatIsoNative.toString = d3_time_formatIso.toString;
+  d3_time.second = d3_time_interval(function(date) {
+    return new d3_date(Math.floor(date / 1e3) * 1e3);
+  }, function(date, offset) {
+    date.setTime(date.getTime() + Math.floor(offset) * 1e3);
+  }, function(date) {
+    return date.getSeconds();
+  });
+  d3_time.seconds = d3_time.second.range;
+  d3_time.seconds.utc = d3_time.second.utc.range;
+  d3_time.minute = d3_time_interval(function(date) {
+    return new d3_date(Math.floor(date / 6e4) * 6e4);
+  }, function(date, offset) {
+    date.setTime(date.getTime() + Math.floor(offset) * 6e4);
+  }, function(date) {
+    return date.getMinutes();
+  });
+  d3_time.minutes = d3_time.minute.range;
+  d3_time.minutes.utc = d3_time.minute.utc.range;
+  d3_time.hour = d3_time_interval(function(date) {
+    var timezone = date.getTimezoneOffset() / 60;
+    return new d3_date((Math.floor(date / 36e5 - timezone) + timezone) * 36e5);
+  }, function(date, offset) {
+    date.setTime(date.getTime() + Math.floor(offset) * 36e5);
+  }, function(date) {
+    return date.getHours();
+  });
+  d3_time.hours = d3_time.hour.range;
+  d3_time.hours.utc = d3_time.hour.utc.range;
+  d3_time.month = d3_time_interval(function(date) {
+    date = d3_time.day(date);
+    date.setDate(1);
+    return date;
+  }, function(date, offset) {
+    date.setMonth(date.getMonth() + offset);
+  }, function(date) {
+    return date.getMonth();
+  });
+  d3_time.months = d3_time.month.range;
+  d3_time.months.utc = d3_time.month.utc.range;
+  function d3_time_scale(linear, methods, format) {
+    function scale(x) {
+      return linear(x);
+    }
+    scale.invert = function(x) {
+      return d3_time_scaleDate(linear.invert(x));
+    };
+    scale.domain = function(x) {
+      if (!arguments.length) return linear.domain().map(d3_time_scaleDate);
+      linear.domain(x);
+      return scale;
+    };
+    function tickMethod(extent, count) {
+      var span = extent[1] - extent[0], target = span / count, i = d3.bisect(d3_time_scaleSteps, target);
+      return i == d3_time_scaleSteps.length ? [ methods.year, d3_scale_linearTickRange(extent.map(function(d) {
+        return d / 31536e6;
+      }), count)[2] ] : !i ? [ d3_time_scaleMilliseconds, d3_scale_linearTickRange(extent, count)[2] ] : methods[target / d3_time_scaleSteps[i - 1] < d3_time_scaleSteps[i] / target ? i - 1 : i];
+    }
+    scale.nice = function(interval, skip) {
+      var domain = scale.domain(), extent = d3_scaleExtent(domain), method = interval == null ? tickMethod(extent, 10) : typeof interval === "number" && tickMethod(extent, interval);
+      if (method) interval = method[0], skip = method[1];
+      function skipped(date) {
+        return !isNaN(date) && !interval.range(date, d3_time_scaleDate(+date + 1), skip).length;
+      }
+      return scale.domain(d3_scale_nice(domain, skip > 1 ? {
+        floor: function(date) {
+          while (skipped(date = interval.floor(date))) date = d3_time_scaleDate(date - 1);
+          return date;
+        },
+        ceil: function(date) {
+          while (skipped(date = interval.ceil(date))) date = d3_time_scaleDate(+date + 1);
+          return date;
+        }
+      } : interval));
+    };
+    scale.ticks = function(interval, skip) {
+      var extent = d3_scaleExtent(scale.domain()), method = interval == null ? tickMethod(extent, 10) : typeof interval === "number" ? tickMethod(extent, interval) : !interval.range && [ {
+        range: interval
+      }, skip ];
+      if (method) interval = method[0], skip = method[1];
+      return interval.range(extent[0], d3_time_scaleDate(+extent[1] + 1), skip < 1 ? 1 : skip);
+    };
+    scale.tickFormat = function() {
+      return format;
+    };
+    scale.copy = function() {
+      return d3_time_scale(linear.copy(), methods, format);
+    };
+    return d3_scale_linearRebind(scale, linear);
+  }
+  function d3_time_scaleDate(t) {
+    return new Date(t);
+  }
+  var d3_time_scaleSteps = [ 1e3, 5e3, 15e3, 3e4, 6e4, 3e5, 9e5, 18e5, 36e5, 108e5, 216e5, 432e5, 864e5, 1728e5, 6048e5, 2592e6, 7776e6, 31536e6 ];
+  var d3_time_scaleLocalMethods = [ [ d3_time.second, 1 ], [ d3_time.second, 5 ], [ d3_time.second, 15 ], [ d3_time.second, 30 ], [ d3_time.minute, 1 ], [ d3_time.minute, 5 ], [ d3_time.minute, 15 ], [ d3_time.minute, 30 ], [ d3_time.hour, 1 ], [ d3_time.hour, 3 ], [ d3_time.hour, 6 ], [ d3_time.hour, 12 ], [ d3_time.day, 1 ], [ d3_time.day, 2 ], [ d3_time.week, 1 ], [ d3_time.month, 1 ], [ d3_time.month, 3 ], [ d3_time.year, 1 ] ];
+  var d3_time_scaleLocalFormat = d3_time_format.multi([ [ ".%L", function(d) {
+    return d.getMilliseconds();
+  } ], [ ":%S", function(d) {
+    return d.getSeconds();
+  } ], [ "%I:%M", function(d) {
+    return d.getMinutes();
+  } ], [ "%I %p", function(d) {
+    return d.getHours();
+  } ], [ "%a %d", function(d) {
+    return d.getDay() && d.getDate() != 1;
+  } ], [ "%b %d", function(d) {
+    return d.getDate() != 1;
+  } ], [ "%B", function(d) {
+    return d.getMonth();
+  } ], [ "%Y", d3_true ] ]);
+  var d3_time_scaleMilliseconds = {
+    range: function(start, stop, step) {
+      return d3.range(Math.ceil(start / step) * step, +stop, step).map(d3_time_scaleDate);
+    },
+    floor: d3_identity,
+    ceil: d3_identity
+  };
+  d3_time_scaleLocalMethods.year = d3_time.year;
+  d3_time.scale = function() {
+    return d3_time_scale(d3.scale.linear(), d3_time_scaleLocalMethods, d3_time_scaleLocalFormat);
+  };
+  var d3_time_scaleUtcMethods = d3_time_scaleLocalMethods.map(function(m) {
+    return [ m[0].utc, m[1] ];
+  });
+  var d3_time_scaleUtcFormat = d3_time_formatUtc.multi([ [ ".%L", function(d) {
+    return d.getUTCMilliseconds();
+  } ], [ ":%S", function(d) {
+    return d.getUTCSeconds();
+  } ], [ "%I:%M", function(d) {
+    return d.getUTCMinutes();
+  } ], [ "%I %p", function(d) {
+    return d.getUTCHours();
+  } ], [ "%a %d", function(d) {
+    return d.getUTCDay() && d.getUTCDate() != 1;
+  } ], [ "%b %d", function(d) {
+    return d.getUTCDate() != 1;
+  } ], [ "%B", function(d) {
+    return d.getUTCMonth();
+  } ], [ "%Y", d3_true ] ]);
+  d3_time_scaleUtcMethods.year = d3_time.year.utc;
+  d3_time.scale.utc = function() {
+    return d3_time_scale(d3.scale.linear(), d3_time_scaleUtcMethods, d3_time_scaleUtcFormat);
+  };
+  d3.text = d3_xhrType(function(request) {
+    return request.responseText;
+  });
+  d3.json = function(url, callback) {
+    return d3_xhr(url, "application/json", d3_json, callback);
+  };
+  function d3_json(request) {
+    return JSON.parse(request.responseText);
+  }
+  d3.html = function(url, callback) {
+    throw "disallowed by chromium security";
+    return d3_xhr(url, "text/html", d3_html, callback);
+  };
+  function d3_html(request) {
+    throw "disallowed by chromium security";
+    var range = d3_document.createRange();
+    range.selectNode(d3_document.body);
+    return range.createContextualFragment(request.responseText);
+  }
+  d3.xml = d3_xhrType(function(request) {
+    return request.responseXML;
+  });
+  if (typeof define === "function" && define.amd) {
+    define(d3);
+  } else if (typeof module === "object" && module.exports) {
+    module.exports = d3;
+  } else {
+    this.d3 = d3;
+  }
+}();
\ No newline at end of file
diff --git a/pkg/vm_snapshot_analysis/lib/src/assets/index.html b/pkg/vm_snapshot_analysis/lib/src/assets/index.html
new file mode 100644
index 0000000..7e1a1fc
--- /dev/null
+++ b/pkg/vm_snapshot_analysis/lib/src/assets/index.html
@@ -0,0 +1,525 @@
+<!--
+  Copyright 2014 The Chromium Authors. All rights reserved.
+  Use of this source code is governed by a BSD-style license that can be
+  found in the LICENSE file.
+-->
+<html>
+<head>
+<title>Binary Size Analysis</title>
+<script src="d3/d3.js" charset="utf-8"></script>
+<script src="D3SymbolTreeMap.js" charset="utf-8"></script>
+<script src="data.js" charset="utf-8"></script>
+<style>
+body {
+    margin: 0px;
+    padding: 5px;
+}
+.swatch {
+    border: 1px solid rgb(100,100,100);
+    -webkit-user-select: none;
+    cursor: default;
+}
+</style>
+<script>
+var treemap;
+var filterChanging = false;
+var savedSettings = {};
+
+function init() {
+    if (window.metadata !== undefined && window.metadata.subtitle) {
+        document.getElementById('subtitle').innerHTML = ': ' + escape(metadata.subtitle);
+    }
+    initFilterOptions();
+    treemap = new D3SymbolTreeMap(
+        savedSettings.width,
+        savedSettings.height,
+        savedSettings.maxLevels);
+    treemap.init();
+}
+
+function getIdealSizes() {
+    var width = window.innerWidth - 20;
+    var height = window.innerHeight - 70;
+    return {'width': width, 'height': height};
+}
+
+function showReport(title, data, headers, dataFunction, styleFunction) {
+    var div =  d3.select('body').append('div')
+        .style('margin', '0')
+        .style('padding', '5px')
+        .style('position', 'absolute')
+        .style('top', '10%')
+        .style('left', '10%')
+        .style('background-color', 'rgba(255,255,255,0.9)')
+        .style('width', '80%')
+        .style('height', '80%')
+        .style('z-index', '2147483647')
+        .style('border', '3px ridge grey')
+        .style('box-shadow', '10px 10px 5px rgba(80,80,80,0.7)')
+        .style('text-align', 'center')
+        .style('border-radius', '10px');
+    var titlebar = div.append('div')
+        .style('margin', '0')
+        .style('padding', '5px')
+        .style('position', 'absolute')
+        .style('top', '0%')
+        .style('left', '0%')
+        .style('width', '100%')
+        .style('height', '10%')
+        .style('font-size', 'x-large');
+    titlebar.text(title);
+    var controls = div.append('div')
+        .style('margin', '0')
+        .style('padding', '5px')
+        .style('position', 'absolute')
+        .style('top', '90%')
+        .style('left', '0%')
+        .style('width', '100%')
+        .style('height', '10%');
+    controls.append('input').attr('type', 'button')
+        .attr('value', 'Dismiss')
+        .on('click', function(){div.remove();});
+
+    var tableDiv = div.append('div')
+        .style('overflow', 'auto')
+        .style('position', 'absolute')
+        .style('top', '10%')
+        .style('left', '0%')
+        .style('width', '100%')
+        .style('height', '80%')
+        .style('border-top', '1px solid rgb(230,230,230)')
+        .style('border-bottom', '1px solid rgb(230,230,230)');
+    var table = tableDiv.append('table')
+        .attr('border', '1')
+        .attr('cellspacing', '0')
+        .attr('cellpadding', '2')
+        .style('margin-left', 'auto')
+        .style('margin-right', 'auto');
+    var header = table.append('tr');
+    for (var i = 0; i < headers.length; i++) {
+        header.append('th').text(headers[i]);
+    }
+
+    for (var i = 0; i < data.length; i++) {
+        var row = table.append('tr');
+        for (j = 0; j < headers.length; j++) {
+            var td = row.append('td');
+            if (styleFunction) {
+                styleFunction.call(this, td, j);
+            }
+            dataFunction.call(this, data[i], j, td);
+        }
+    }
+}
+
+function bigSymbolsReport() {
+    var list = treemap.biggestSymbols(100);
+    var headers = ['Rank', 'Size (Bytes)', 'Type', 'Location'];
+    var styleFunction = function(selection, index) {
+        if (index === 3) {
+            selection.style('font-family', 'monospace');
+        }
+    };
+    var recordIndex = 1;
+    var dataFunction = function(record, index, cell) {
+        if (index === 0) {
+            cell.text(recordIndex++);
+        } else if (index === 1) {
+            cell.text(D3SymbolTreeMap._pretty(record.value));
+        } else if (index === 2) {
+            cell.text(record.t);
+        } else {
+            if (treemap.pathFor(record).indexOf('/out') == 0) {
+                cell.append('span').text(treemap.pathFor(record));
+                cell.append('br');
+                cell.append('span').text('Symbol: ');
+                cell.append('span').text(record.n);
+            } else {
+                var href = 'https://code.google.com/p/chromium/codesearch#chromium/src'
+                    + treemap.pathFor(record)
+                    + '&q='
+                    + record.n;
+                cell.append('a')
+                    .attr('href', href)
+                    .attr('target', '_blank')
+                    .text(treemap.pathFor(record));
+                cell.append('br');
+                cell.append('span').text('Symbol: ');
+                cell.append('span').text(record.n);
+            }
+        }
+    };
+    showReport('100 Largest Symbols', list, headers, dataFunction, styleFunction);
+}
+
+function bigPathsReport() {
+    var list = treemap.biggestPaths(100);
+    var headers = ['Rank', 'Size (Bytes)', 'Location'];
+    var styleFunction = function(selection, index) {
+        if (index === 2) {
+            selection.style('font-family', 'monospace');
+        }
+    };
+    var recordIndex = 1;
+    var dataFunction = function(record, index, cell) {
+        if (index === 0) {
+            cell.text(recordIndex++);
+        } else if (index === 1) {
+            cell.text(D3SymbolTreeMap._pretty(record.value));
+        } else if (index === 2) {
+            if (treemap.pathFor(record).indexOf('/out') == 0) {
+                cell.text(treemap.pathFor(record));
+            } else {
+                var href = 'https://code.google.com/p/chromium/codesearch#chromium/src' + treemap.pathFor(record);
+                cell.append('a')
+                    .attr('href', href)
+                    .attr('target', '_blank')
+                    .text(treemap.pathFor(record));
+            }
+
+        }
+    };
+    showReport('100 Largest Paths', list, headers, dataFunction, styleFunction);
+}
+
+function symbolFilterTextChanged() {
+    if (filterChanging) return true;
+    filterChanging = true;
+    var enabled = document.getElementById('symbol_types_filter').value;
+    for (var x=0; x<=25; x++) {
+        var checkBox = document.getElementById('check_' + x);
+        checkBox.checked = (enabled.indexOf(checkBox.value) != -1);
+    }
+    filterChanging = false;
+}
+
+function updateFilterText() {
+    if (filterChanging) return true;
+    filterChanging = true;
+    var text = '';
+    for (var x=0; x<=25; x++) {
+        var checkBox = document.getElementById('check_' + x);
+        if (checkBox.checked) {
+            text += checkBox.value;
+        }
+    }
+    document.getElementById('symbol_types_filter').value=text;
+    filterChanging = false;
+}
+
+function initFilterOptions() {
+    updateFilterText();
+    for (var x=0; x<=25; x++) {
+        var checkBox = document.getElementById('check_' + x);
+        checkBox.onchange=updateFilterText;
+        var swatch = document.getElementById('swatch_' + x);
+        swatch.style.backgroundColor = D3SymbolTreeMap.getColorForType(checkBox.value).toString();
+    }
+    var gteCheckbox = document.getElementById('check_gte');
+    gteCheckbox.onchange = function() {
+        document.getElementById('symbol_filter_gte').disabled = !gteCheckbox.checked;
+    }
+    var regexCheckbox = document.getElementById('check_regex');
+    regexCheckbox.onchange = function() {
+        document.getElementById('symbol_filter_regex').disabled = !regexCheckbox.checked;
+    }
+    var excludeRegexCheckbox = document.getElementById('check_exclude_regex');
+    excludeRegexCheckbox.onchange = function() {
+        document.getElementById('symbol_filter_exclude_regex').disabled = !excludeRegexCheckbox.checked;
+    }
+    var idealSizes = getIdealSizes();
+    document.getElementById('width').value = idealSizes.width;
+    document.getElementById('height').value = idealSizes.height;
+    saveFilterSettings();
+}
+
+function filterSetAll(enabled) {
+    for (var x=0; x<=25; x++) {
+        var checkBox = document.getElementById('check_' + x);
+        checkBox.checked = enabled;
+    }
+    updateFilterText();
+}
+
+function showOptions() {
+    loadFilterSettings();
+    var container = document.getElementById('options_container');
+    var w = container.offsetWidth;
+    var h = container.offsetHeight;
+    container.style.margin = '-' + (h/2) + 'px 0 0 -' + (w/2) + 'px';
+    container.style.visibility = 'visible';
+}
+
+function hideOptions() {
+    var container = document.getElementById('options_container');
+    container.style.visibility = 'hidden';
+}
+
+function applySettings() {
+    hideOptions();
+    var oldWidth = savedSettings.width;
+    var oldHeight = savedSettings.height;
+    var oldSymbols = savedSettings.symbolTypes;
+    var oldRegex = savedSettings.regex;
+    var oldExcludeRegex = savedSettings.excludeRegex;
+    var oldGte = savedSettings.gte;
+    var oldMaxLevels = savedSettings.maxLevels;
+    saveFilterSettings();
+    var resizeNeeded = oldWidth !== savedSettings.width || oldHeight !== savedSettings.height;
+    var regexChanged = oldRegex !== savedSettings.regex;
+    var excludeRegexChanged = oldExcludeRegex !== savedSettings.excludeRegex;
+    var symbolsChanged = oldSymbols !== savedSettings.symbolTypes;
+    var gteChanged = oldGte !== savedSettings.gte;
+    var filterChanged = regexChanged || excludeRegexChanged || symbolsChanged || gteChanged;
+    var maxLevelsChanged = oldMaxLevels !== savedSettings.maxLevels;
+
+    if (filterChanged) {
+        // Type filters
+        typeFilter = function(datum) {
+            if (datum.depth === 0) return true; // root node
+            if (datum.t === undefined) return true;
+            return savedSettings.symbolTypes !== undefined &&
+                savedSettings.symbolTypes.indexOf(datum.t) !== -1;
+        }
+
+        // Regex filter
+        var regexFilter = undefined;
+        if (savedSettings.regex !== undefined && savedSettings.regex.length > 0) {
+            console.log('filter: regex is "' + savedSettings.regex + '"');
+            var regex = new RegExp(savedSettings.regex);
+            regexFilter = function(datum) {
+                if (datum.depth === 0) return true; // root node
+                var fullName = this.pathFor(datum);
+                if (datum.children === undefined) { // it is a leaf node (symbol)
+                    fullName += ':' + datum.n;
+                }
+                return regex.test(fullName);
+            }
+        }
+
+        // Exclude regex filter
+        var excludeRegexFilter = undefined;
+        if (savedSettings.excludeRegex !== undefined && savedSettings.excludeRegex.length > 0) {
+            console.log('filter: exclude-regex is "' + savedSettings.excludeRegex + '"');
+            var excludeRegex = new RegExp(savedSettings.excludeRegex);
+            excludeRegexFilter = function(datum) {
+                if (datum.depth === 0) return true; // root node
+                var fullName = this.pathFor(datum);
+                if (datum.children === undefined) { // it is a leaf node (symbol)
+                    fullName += ':' + datum.n;
+                }
+                return !excludeRegex.test(fullName);
+            }
+        }
+
+        // Size filter
+        var sizeFilter = undefined;
+        if (savedSettings.gte !== undefined) {
+            console.log('filter: minimum size is ' + savedSettings.gte + ' bytes');
+            sizeFilter = function(datum) {
+                if (datum.children !== undefined) return true; // non-leaf
+                if (datum.value === undefined) console.log('whoops');
+                return datum.value >= savedSettings.gte;
+            }
+        }
+
+        // Make a filter to apply to the tree
+        var filter = function(datum) {
+            if (typeFilter && !typeFilter.call(this, datum)) return false;
+            if (regexFilter && !regexFilter.call(this, datum)) return false;
+            if (excludeRegexFilter && !excludeRegexFilter.call(this, datum)) return false;
+            if (sizeFilter && !sizeFilter.call(this, datum)) return false;
+            return true;
+        };
+        treemap.filter(filter);
+    }
+
+    // Adjust levels if needed.
+    if (maxLevelsChanged) {
+        treemap.setMaxLevels(savedSettings.maxLevels);
+    }
+
+    // Resize map if necessary.
+    if (resizeNeeded) {
+        console.log('desired treemap dimensions have changed, requesting resize');
+        treemap.resize(savedSettings.width, savedSettings.height);
+    }
+}
+
+function cancelSettings() {
+    hideOptions();
+    loadFilterSettings();
+}
+
+function saveFilterSettings() {
+    savedSettings.symbolTypes = document.getElementById('symbol_types_filter').value;
+    if (document.getElementById('check_regex').checked) {
+        savedSettings.regex = document.getElementById('symbol_filter_regex').value;
+    } else {
+        savedSettings.regex = undefined;
+    }
+    if (document.getElementById('check_exclude_regex').checked) {
+        savedSettings.excludeRegex = document.getElementById('symbol_filter_exclude_regex').value;
+    } else {
+        savedSettings.excludeRegex = undefined;
+    }
+    if (document.getElementById('check_gte').checked) {
+        savedSettings.gte = parseInt(document.getElementById('symbol_filter_gte').value);
+    } else {
+        savedSettings.gte = undefined;
+    }
+    savedSettings.width = parseInt(document.getElementById('width').value);
+    savedSettings.height = parseInt(document.getElementById('height').value);
+    savedSettings.maxLevels = parseInt(document.getElementById('max_levels').value);
+}
+
+function loadFilterSettings() {
+    document.getElementById('symbol_types_filter').value = savedSettings.symbolTypes;
+    symbolFilterTextChanged();
+    if (savedSettings.regex !== undefined) {
+        document.getElementById('check_regex').checked = true;
+        document.getElementById('symbol_filter_regex').value = savedSettings.regex;
+    } else {
+        document.getElementById('check_regex').checked = false;
+    }
+    if (savedSettings.excludeRegex !== undefined) {
+        document.getElementById('check_exclude_regex').checked = true;
+        document.getElementById('symbol_filter_exclude_regex').value = savedSettings.excludeRegex;
+    } else {
+        document.getElementById('check_exclude_regex').checked = false;
+    }
+    if (savedSettings.gte !== undefined) {
+        document.getElementById('check_gte').checked = true;
+        document.getElementById('symbol_filter_gte').value = savedSettings.gte;
+    } else {
+        document.getElementById('check_gte').checked = false;
+    }
+    document.getElementById('width').value = savedSettings.width;
+    document.getElementById('height').value = savedSettings.height;
+    document.getElementById('max_levels').value = savedSettings.maxLevels;
+}
+
+function escape(str) {
+    return str.replace(/&/g, '&amp;')
+              .replace(/"/g, '&quot;')
+              .replace(/</g, '&lt;')
+              .replace(/>/g, '&gt;');
+}
+</script>
+</head>
+<body onload='init()'>
+<div style='position: absolute; top: 5px; left: 5px;'>
+  <input type='button' onclick='showOptions()' value='Options &amp; Legend...'>
+  <span style='-webkit-user-select: none; cursor: help;' title='Click to view the symbol legend or to configure filters and options for the treemap'>[?]</span>
+</div>
+<div style='position: absolute; right: 5px; top: 5px; white-space: nowrap;'>
+    Reports:
+    <input type='button' onclick='bigSymbolsReport()' value='Large Symbols' title='Click to view a report of the largest 100 symbols that are with the bounds of the treemap that is currently displayed.'>
+    <input type='button' onclick='bigPathsReport()' value='Large Files' title='Click to view a report of the largest 100 source files that are with the bounds of the treemap that is currently displayed.'>
+</div>
+<div style='text-align: center; margin-bottom: 5px;'>
+    <span style='font-size: x-large; font-weight: bold; font-variant: small-caps'>Binary Size Analysis<span id='subtitle'></span></span>
+    <br><span style='font-size: small; font-style: italic;'>Double-click a box to zoom in, double-click outermost title to zoom out.</span>
+</div>
+<table id='options_container' style='visibility: hidden; border: 3px ridge grey; padding: 0px; top: 50%; left: 50%; position: fixed; z-index: 2147483646; overflow: auto; background-color: rgba(255,255,255,0.9); border-radius: 10px; box-shadow: 10px 10px 5px rgba(80,80,80,0.7);'><tr><td style='vertical-align: top'>
+    <table cellspacing=0 cellborder=0 style='width:100%'>
+        <tr><th colspan=3 style='padding-bottom: .25em; text-decoration: underline;'>Symbol Types To Show</th></tr>
+        <tr>
+            <td style='width: 33%; white-space: nowrap; vertical-align: top;'>
+                    <span class='swatch' id='swatch_0'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_0' value='A'>Global absolute (A)
+                <br><span class='swatch' id='swatch_1'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_1' value='B'>Global uninitialized data (B)
+                <br><span class='swatch' id='swatch_2'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_2' value='b'>Local uninitialized data (b)
+                <br><span class='swatch' id='swatch_3'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_3' value='C'>Global uninitialized common (C)
+                <br><span class='swatch' id='swatch_4'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_4' value='D'>Global initialized data (D)
+                <br><span class='swatch' id='swatch_5'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_5' value='d'>Local initialized data (d)
+                <br><span class='swatch' id='swatch_6'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_6' value='G'>Global small initialized data (G)
+                <br><span class='swatch' id='swatch_7'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_7' value='g'>Local small initialized data (g)
+                <br><span class='swatch' id='swatch_8'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_8' value='i'>Indirect function (i)
+            </td>
+            <td style='width: 33%; white-space: nowrap; vertical-align: top;'>
+                    <span class='swatch' id='swatch_9'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_9' value='N'>Debugging (N)
+                <br><span class='swatch' id='swatch_10'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_10' value='p'>Stack unwind (p)
+                <br><span class='swatch' id='swatch_11'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_11' value='R'>Global read-only data (R)
+                <br><span class='swatch' id='swatch_12'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_12' value='r'>Local read-only data (r)
+                <br><span class='swatch' id='swatch_13'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_13' value='S'>Global small uninitialized data (S)
+                <br><span class='swatch' id='swatch_14'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_14' value='s'>Local small uninitialized data (s)
+                <br><span class='swatch' id='swatch_15'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_15' value='T'>Global code (T)
+                <br><span class='swatch' id='swatch_16'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_16' value='t'>Local code (t)
+                <br><span class='swatch' id='swatch_17'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_17' value='U'>Undefined (U)
+            </td>
+            <td style='width: 33%; white-space: nowrap; vertical-align: top;'>
+                    <span class='swatch' id='swatch_18'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_18' value='u'>Unique (u)
+                <br><span class='swatch' id='swatch_19'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_19' value='V'>Global weak object (V)
+                <br><span class='swatch' id='swatch_20'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_20' value='v'>Local weak object (v)
+                <br><span class='swatch' id='swatch_21'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_21' value='W'>Global weak symbol (W)
+                <br><span class='swatch' id='swatch_22'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_22' value='w'>Local weak symbol (w)
+                <br><span class='swatch' id='swatch_23'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_23' value='@'>Vtable entry (@)
+                <br><span class='swatch' id='swatch_24'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_24' value='-'>STABS debugging (-)
+                <br><span class='swatch' id='swatch_25'>&nbsp;&nbsp;&nbsp;</span><input checked type='checkbox' id='check_25' value='?'>Unrecognized (?)
+            </td>
+        </tr>
+        <tr><td colspan=3 style='text-align: center; white-space: nowrap; padding-top: 1em;'>
+            Select <input type='button' onclick='filterSetAll(true)' value='All'>,
+            <input type='button' onclick='filterSetAll(false)' value='None'>,
+            or type a string: <input id='symbol_types_filter' size=30 value='' onkeyup='symbolFilterTextChanged()' onblur='updateFilterText()'>
+            <span style='-webkit-user-select: none; cursor: help;' title='Enter codes from the list above for the symbols you want to see. The checkboxes will update automatically to match the string that you enter.'>[?]</span>
+        </td></tr>
+   </table>
+</td></tr><tr><td style='vertical-align: top; padding-top: 10px; border-top: 1px solid grey;'>
+    <table cellspacing=0 cellborder=0 style='width: 100%'>
+        <tr><th colspan=2 style='padding-bottom: .25em; text-decoration: underline;'>Advanced Options</th></tr>
+        <tr>
+            <td style='white-space: nowrap; vertical-align: top;'>
+                <input type='checkbox' id='check_regex'>
+                Only include symbols matching this regex:
+            </td>
+            <td style='text-align: right; vertical-align: top;'>
+                <input disabled id='symbol_filter_regex' size=30 value='' style='text-align: right;'>
+                <span style='-webkit-user-select: none; cursor: help;' title='Enter a javascript regex. Only symbols that match this regex will be shown. This filter applies before any exclusion regex specified below. The format of each symbol is [path]:[symbol_name]'>[?]</span>
+            </td>
+        </tr>
+        <tr>
+            <td style='white-space: nowrap; vertical-align: top;'>
+                <input type='checkbox' id='check_exclude_regex'>
+                Exclude all symbols matching this regex:
+            </td>
+            <td style='text-align: right; vertical-align: top;'>
+                <input disabled id='symbol_filter_exclude_regex' size=30 value='' style='text-align: right;'>
+                <span style='-webkit-user-select: none; cursor: help;' title='Enter a javascript regex. Symbols that match this tegex will not be shown. This filter applies after any inclusion filter specified above. The format of each symbol is [path]:[symbol_name]'>[?]</span>
+            </td>
+        </tr>
+        <tr>
+            <td style='white-space: nowrap; vertical-align: top;'>
+                <input type='checkbox' id='check_gte'>
+                Only include symbols that are at least <span style='font-style: italic;'>n</span> bytes:
+            </td>
+            <td style='text-align: right; vertical-align: top;'>
+                <input disabled id='symbol_filter_gte' size=8 value='' style='text-align: right;'>
+                <span style='-webkit-user-select: none; cursor: help;' title='Symbols whose size is less than this value will be hidden.'>[?]</span>
+            </td>
+        </tr>
+        <tr>
+            <td style='white-space: nowrap vertical-align: top;;'>
+                Show at most <span style='font-style: italic;'>n</span> levels of detail at a time:
+            </td>
+            <td style='text-align: right; vertical-align: top;'>
+                <input id='max_levels' size=4 value='2' style='text-align: right;'><span style='-webkit-user-select: none; cursor: help;' title='Increasing this value shows more detail without the need to zoom, but uses more computing power.'>[?]</span>
+            </td>
+        </tr>
+        <tr>
+            <td style='white-space: nowrap vertical-align: top;;'>
+                Set the size of the treemap to <span style='font-style: italic;'>W x H</span> pixels:
+            </td>
+            <td style='text-align: right; vertical-align: top;'>
+                <input id='width' size=4 value='' style='text-align: right;'>
+                &nbsp;x&nbsp;<input id='height' size=4 value='' style='text-align: right;'>
+            </td>
+        </tr>
+    </table>
+</td></tr>
+<tr><td style='padding-top: 10px; text-align: right; border-top: 1px solid grey'>
+    <input type='button' value='Apply' onclick='applySettings()'>
+    <input type='button' value='Cancel' onclick='cancelSettings()'>
+</td></tr></table>
+</body>
+</html>
diff --git a/pkg/vm_snapshot_analysis/lib/src/commands/compare.dart b/pkg/vm_snapshot_analysis/lib/src/commands/compare.dart
new file mode 100644
index 0000000..52f8b43
--- /dev/null
+++ b/pkg/vm_snapshot_analysis/lib/src/commands/compare.dart
@@ -0,0 +1,153 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// This tool compares two JSON size reports produced by
+/// --print-instructions-sizes-to and reports which symbols increased in size
+/// and which symbols decreased in size.
+library vm_snapshot_analysis.compare;
+
+import 'dart:io';
+
+import 'package:args/command_runner.dart';
+
+import 'package:vm_snapshot_analysis/ascii_table.dart';
+import 'package:vm_snapshot_analysis/program_info.dart';
+import 'package:vm_snapshot_analysis/utils.dart';
+import 'package:vm_snapshot_analysis/v8_profile.dart';
+
+class CompareCommand extends Command<void> {
+  @override
+  final String name = 'compare';
+
+  @override
+  final String description = '''
+Compare two instruction size outputs and report which symbols changed in size.
+
+This tool compares two JSON size reports produced by
+--print-instructions-sizes-to or --write-v8-snapshot-profile-to
+and reports which symbols changed in size.
+
+Both reports should be produced by the same flag!
+
+Use --narrow flag to limit column widths.''';
+
+  @override
+  String get invocation =>
+      super.invocation.replaceAll('[arguments]', '<old.json> <new.json>');
+
+  CompareCommand() {
+    argParser
+      ..addOption('column-width',
+          help: 'Truncate column content to the given width'
+              ' (${AsciiTable.unlimitedWidth} means do not truncate).',
+          defaultsTo: AsciiTable.unlimitedWidth.toString())
+      ..addOption('by',
+          abbr: 'b',
+          help: 'Choose the breakdown rule for the output.',
+          allowed: ['method', 'class', 'library', 'package'],
+          defaultsTo: 'method')
+      ..addFlag('collapse-anonymous-closures', help: '''
+Collapse all anonymous closures from the same scope into a single entry.
+When comparing size of AOT snapshots for two different versions of a
+program there is no reliable way to precisely establish which two anonymous
+closures are the same and should be compared in size - so
+comparison might produce a noisy output. This option reduces confusion
+by collapsing different anonymous closures within the same scope into a
+single entry. Note that when comparing the same application compiled
+with two different versions of an AOT compiler closures can be distinguished
+precisely based on their source position (which is included in their name).
+''');
+  }
+
+  @override
+  Future<void> run() async {
+    if (argResults.rest.length != 2) {
+      usageException('Need to provide path to old.json and new.json reports.');
+    }
+
+    final columnWidth = argResults['column-width'];
+    final maxWidth = int.tryParse(columnWidth);
+    if (maxWidth == null) {
+      usageException(
+          'Specified column width (${columnWidth}) is not an integer');
+    }
+
+    final oldJsonPath = _checkExists(argResults.rest[0]);
+    final newJsonPath = _checkExists(argResults.rest[1]);
+    printComparison(oldJsonPath, newJsonPath,
+        maxWidth: maxWidth,
+        granularity: _parseHistogramType(argResults['by']),
+        collapseAnonymousClosures: argResults['collapse-anonymous-closures']);
+  }
+
+  HistogramType _parseHistogramType(String value) {
+    switch (value) {
+      case 'method':
+        return HistogramType.bySymbol;
+      case 'class':
+        return HistogramType.byClass;
+      case 'library':
+        return HistogramType.byLibrary;
+      case 'package':
+        return HistogramType.byPackage;
+    }
+    return null;
+  }
+
+  File _checkExists(String path) {
+    final file = File(path);
+    if (!file.existsSync()) {
+      usageException('File $path does not exist!');
+    }
+    return file;
+  }
+
+  void printComparison(File oldJson, File newJson,
+      {int maxWidth = 0,
+      bool collapseAnonymousClosures = false,
+      HistogramType granularity = HistogramType.bySymbol}) async {
+    final oldSizes = await loadProgramInfo(oldJson,
+        collapseAnonymousClosures: collapseAnonymousClosures);
+    final newSizes = await loadProgramInfo(newJson,
+        collapseAnonymousClosures: collapseAnonymousClosures);
+
+    if ((oldSizes.snapshotInfo == null) != (newSizes.snapshotInfo == null)) {
+      usageException('Input files must be produced by the same flag.');
+    }
+
+    final diff = computeDiff(oldSizes, newSizes);
+
+    // Compute total sizes.
+    final totalOld = oldSizes.totalSize;
+    final totalNew = newSizes.totalSize;
+    final totalDiff = diff.totalSize;
+
+    // Compute histogram.
+    final histogram = computeHistogram(diff, granularity);
+
+    // Now produce the report table.
+    const numLargerSymbolsToReport = 30;
+    const numSmallerSymbolsToReport = 10;
+    printHistogram(diff, histogram,
+        sizeHeader: 'Diff (Bytes)',
+        prefix: histogram.bySize
+            .where((k) => histogram.buckets[k] > 0)
+            .take(numLargerSymbolsToReport),
+        suffix: histogram.bySize.reversed
+            .where((k) => histogram.buckets[k] < 0)
+            .take(numSmallerSymbolsToReport)
+            .toList()
+            .reversed,
+        maxWidth: maxWidth);
+
+    print('Comparing ${oldJson.path} (old) to ${newJson.path} (new)');
+    print('Old   : ${totalOld} bytes.');
+    print('New   : ${totalNew} bytes.');
+    print('Change: ${totalDiff > 0 ? '+' : ''}${totalDiff} bytes.');
+
+    if (oldSizes.snapshotInfo != null) {
+      print(bucketLegend);
+    }
+  }
+}
diff --git a/pkg/vm/lib/snapshot/commands/summary.dart b/pkg/vm_snapshot_analysis/lib/src/commands/summary.dart
similarity index 75%
rename from pkg/vm/lib/snapshot/commands/summary.dart
rename to pkg/vm_snapshot_analysis/lib/src/commands/summary.dart
index f3860a7..af159f1 100644
--- a/pkg/vm/lib/snapshot/commands/summary.dart
+++ b/pkg/vm_snapshot_analysis/lib/src/commands/summary.dart
@@ -5,16 +5,17 @@
 /// This tool generates a summary report from a binary size reports produced by
 /// the AOT compiler's --print-instructions-sizes-to and
 /// --write-v8-snapshot-profile-to flags.
-library vm.snapshot.summary;
+library vm_snapshot_analysis.summary;
 
 import 'dart:async';
 import 'dart:io';
 
 import 'package:args/command_runner.dart';
 
-import 'package:vm/snapshot/ascii_table.dart';
-import 'package:vm/snapshot/program_info.dart';
-import 'package:vm/snapshot/utils.dart';
+import 'package:vm_snapshot_analysis/ascii_table.dart';
+import 'package:vm_snapshot_analysis/program_info.dart';
+import 'package:vm_snapshot_analysis/utils.dart';
+import 'package:vm_snapshot_analysis/v8_profile.dart';
 
 class SummaryCommand extends Command<void> {
   @override
@@ -35,10 +36,16 @@
           help: 'Truncate column content to the given width'
               ' (${AsciiTable.unlimitedWidth} means do not truncate).',
           defaultsTo: AsciiTable.unlimitedWidth.toString())
-      ..addOption('granularity',
-          help: 'Choose the granularity of the output.',
+      ..addOption('by',
+          abbr: 'b',
+          help: 'Choose breakdown rule of the output.',
           allowed: ['method', 'class', 'library', 'package'],
           defaultsTo: 'method')
+      ..addOption(
+        'where',
+        abbr: 'w',
+        help: 'Filter output using the given glob.',
+      )
       ..addFlag('collapse-anonymous-closures', help: '''
 Collapse all anonymous closures from the same scope into a single entry.
 When comparing size of AOT snapshots for two different versions of a
@@ -76,8 +83,9 @@
 
     await outputSummary(input,
         maxWidth: maxWidth,
-        granularity: _parseHistogramType(argResults['granularity']),
-        collapseAnonymousClosures: argResults['collapse-anonymous-closures']);
+        granularity: _parseHistogramType(argResults['by']),
+        collapseAnonymousClosures: argResults['collapse-anonymous-closures'],
+        filter: argResults['where']);
   }
 
   static HistogramType _parseHistogramType(String value) {
@@ -98,14 +106,25 @@
 void outputSummary(File input,
     {int maxWidth = 0,
     bool collapseAnonymousClosures = false,
-    HistogramType granularity = HistogramType.bySymbol}) async {
+    HistogramType granularity = HistogramType.bySymbol,
+    String filter}) async {
   final info = await loadProgramInfo(input);
 
   // Compute histogram.
-  final histogram = SizesHistogram.from(info, granularity);
+  final histogram = computeHistogram(info, granularity, filter: filter);
 
   // Now produce the report table.
   const topToReport = 30;
-  printHistogram(histogram,
+  printHistogram(info, histogram,
       prefix: histogram.bySize.take(topToReport), maxWidth: maxWidth);
+
+  if (info.snapshotInfo != null) {
+    print('\nBreakdown by object type:');
+    final typeHistogram =
+        computeHistogram(info, HistogramType.byNodeType, filter: filter);
+    printHistogram(info, typeHistogram,
+        prefix: typeHistogram.bySize, maxWidth: maxWidth);
+
+    print(bucketLegend);
+  }
 }
diff --git a/pkg/vm/lib/snapshot/commands/treemap.dart b/pkg/vm_snapshot_analysis/lib/src/commands/treemap.dart
similarity index 64%
rename from pkg/vm/lib/snapshot/commands/treemap.dart
rename to pkg/vm_snapshot_analysis/lib/src/commands/treemap.dart
index 1aa05d3..c5b1b55 100644
--- a/pkg/vm/lib/snapshot/commands/treemap.dart
+++ b/pkg/vm_snapshot_analysis/lib/src/commands/treemap.dart
@@ -8,18 +8,22 @@
 ///
 /// It used the same visualization framework as Chromium's binary_size tool
 /// located in runtime/third_party/binary_size.
-library vm.snapshot.commands.treemap;
+library vm_snapshot_analysis.commands.treemap;
 
 import 'dart:async';
 import 'dart:convert';
 import 'dart:io';
+import 'dart:isolate';
 import 'dart:math' show max;
 
 import 'package:path/path.dart' as p;
 import 'package:args/command_runner.dart';
 
-import 'package:vm/snapshot/instruction_sizes.dart' as instruction_sizes;
-import 'package:vm/snapshot/utils.dart';
+import 'package:vm_snapshot_analysis/instruction_sizes.dart'
+    as instruction_sizes;
+import 'package:vm_snapshot_analysis/program_info.dart';
+import 'package:vm_snapshot_analysis/v8_profile.dart' as v8_profile;
+import 'package:vm_snapshot_analysis/utils.dart';
 
 class TreemapCommand extends Command<void> {
   @override
@@ -30,7 +34,7 @@
 Create interactive treemap from snapshot profiling information.
 
 This tool is used to process snapshot size reports produced by
---print-instructions-sizes-to=symbol-sizes.json.
+--print-instructions-sizes-to and --write-v8-snapshot-profile-to flags.
 
 It will create an interactive web-page in the output-directory which can be
 viewed in a browser:
@@ -55,8 +59,8 @@
       usageException('Need to specify input JSON and output directory.');
     }
 
-    final input = new File(argResults.rest[0]);
-    final outputDir = new Directory(argResults.rest[1]);
+    final input = File(argResults.rest[0]);
+    final outputDir = Directory(argResults.rest[1]);
 
     if (!input.existsSync()) {
       usageException('Input file ${input.path} does not exist!');
@@ -74,38 +78,43 @@
 Future<void> generateTreeMap(File input, Directory outputDir) async {
   // Load symbols data produced by the AOT compiler and convert it to
   // a tree.
-  final symbols = instruction_sizes.fromJson(await loadJson(input));
+  final inputJson = await loadJson(input);
 
   final root = {'n': '', 'children': {}, 'k': kindPath, 'maxDepth': 0};
-  for (var symbol in symbols) {
-    addSymbol(root, treePath(symbol), symbol.name.scrubbed, symbol.size);
+
+  if (v8_profile.Snapshot.isV8HeapSnapshot(inputJson)) {
+    treemapFromSnapshot(root, v8_profile.Snapshot.fromJson(inputJson));
+  } else {
+    final symbols = instruction_sizes.fromJson(inputJson);
+    for (var symbol in symbols) {
+      addSymbol(root, treePath(symbol), symbol.name.scrubbed, symbol.size);
+    }
   }
   final tree = flatten(root);
 
   // Create output directory and copy all auxiliary files from binary_size tool.
   await outputDir.create(recursive: true);
 
-  final scriptLocation = p.dirname(Platform.script.toFilePath());
-  final sdkRoot = p.join(scriptLocation, '..', '..', '..');
-  final d3SrcDir = p.join(sdkRoot, 'runtime', 'third_party', 'd3', 'src');
-  final templateDir = p.join(
-      sdkRoot, 'runtime', 'third_party', 'binary_size', 'src', 'template');
+  final assetsUri = await Isolate.resolvePackageUri(
+      Uri.parse('package:vm_snapshot_analysis/src/assets'));
+  final assetsDir = assetsUri.toFilePath();
+  final d3SrcDir = p.join(assetsDir, 'd3', 'src');
 
   final d3OutDir = p.join(outputDir.path, 'd3');
-  await new Directory(d3OutDir).create(recursive: true);
+  await Directory(d3OutDir).create(recursive: true);
 
   for (var file in ['LICENSE', 'd3.js']) {
     await copyFile(d3SrcDir, file, d3OutDir);
   }
   for (var file in ['index.html', 'D3SymbolTreeMap.js']) {
-    await copyFile(templateDir, file, outputDir.path);
+    await copyFile(assetsDir, file, outputDir.path);
   }
 
   // Serialize symbol size tree as JSON.
   final dataJsPath = p.join(outputDir.path, 'data.js');
-  final sink = new File(dataJsPath).openWrite();
+  final sink = File(dataJsPath).openWrite();
   sink.write('var tree_data=');
-  await sink.addStream(new Stream<Object>.fromIterable([tree])
+  await sink.addStream(Stream<Object>.fromIterable([tree])
       .transform(json.encoder.fuse(utf8.encoder)));
   await sink.close();
 
@@ -113,6 +122,42 @@
   print('Generated ${p.toUri(p.absolute(outputDir.path, 'index.html'))}');
 }
 
+void treemapFromSnapshot(Map<String, dynamic> root, v8_profile.Snapshot snap) {
+  final info = v8_profile.toProgramInfo(snap);
+
+  final ownerPathCache = List<String>(info.snapshotInfo.infoNodes.length);
+  ownerPathCache[info.root.id] = info.root.name;
+
+  String nameOf(v8_profile.Node node) {
+    switch (node.type) {
+      case 'Library':
+      case 'Class':
+      case 'Function':
+        return node.name;
+
+      default:
+        return '${node.type}';
+    }
+  }
+
+  String ownerPath(ProgramInfoNode n) {
+    return ownerPathCache[n.id] ??=
+        ((n.parent != info.root) ? '${ownerPath(n.parent)}/${n.name}' : n.name);
+  }
+
+  for (var node in snap.nodes) {
+    if (node.selfSize > 0) {
+      final owner = info.snapshotInfo.ownerOf(node);
+      final path = ownerPath(owner);
+      final name = nameOf(node);
+      addSymbol(root, path, name, node.selfSize,
+          symbolType: node.type == '(RO) Instructions'
+              ? symbolTypeGlobalText
+              : symbolTypeGlobalInitializedData);
+    }
+  }
+}
+
 /// Returns a /-separated path to the given symbol within the treemap.
 String treePath(instruction_sizes.SymbolInfo symbol) {
   if (symbol.name.isStub) {
@@ -130,14 +175,12 @@
 const kindPath = 'p';
 const kindBucket = 'b';
 const symbolTypeGlobalText = 'T';
+const symbolTypeGlobalInitializedData = 'D';
 
 /// Create a child with the given name within the given node or return
 /// an existing child.
 Map<String, dynamic> addChild(
     Map<String, dynamic> node, String kind, String name) {
-  if (kind == kindSymbol && node['children'].containsKey(name)) {
-    print('Duplicate symbol ${name}');
-  }
   return node['children'].putIfAbsent(name, () {
     final n = <String, dynamic>{'n': name, 'k': kind};
     if (kind != kindSymbol) {
@@ -148,7 +191,8 @@
 }
 
 /// Add the given symbol to the tree.
-void addSymbol(Map<String, dynamic> root, String path, String name, int size) {
+void addSymbol(Map<String, dynamic> root, String path, String name, int size,
+    {String symbolType = symbolTypeGlobalText}) {
   var node = root;
   var depth = 0;
   for (var part in path.split('/')) {
@@ -156,11 +200,11 @@
     depth++;
   }
   node['lastPathElement'] = true;
-  node = addChild(node, kindBucket, symbolTypeGlobalText);
-  node['t'] = symbolTypeGlobalText;
+  node = addChild(node, kindBucket, symbolType);
+  node['t'] = symbolType;
   node = addChild(node, kindSymbol, name);
-  node['t'] = symbolTypeGlobalText;
-  node['value'] = size;
+  node['t'] = symbolType;
+  node['value'] = (node['value'] ?? 0) + size;
   depth += 2;
   root['maxDepth'] = max<int>(root['maxDepth'], depth);
 }
@@ -182,5 +226,5 @@
 
 /// Copy file with the given name from [fromDir] to [toDir].
 Future<void> copyFile(String fromDir, String name, String toDir) async {
-  await new File(p.join(fromDir, name)).copy(p.join(toDir, name));
+  await File(p.join(fromDir, name)).copy(p.join(toDir, name));
 }
diff --git a/pkg/vm_snapshot_analysis/lib/utils.dart b/pkg/vm_snapshot_analysis/lib/utils.dart
new file mode 100644
index 0000000..2f6746a
--- /dev/null
+++ b/pkg/vm_snapshot_analysis/lib/utils.dart
@@ -0,0 +1,102 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+library vm_snapshot_analysis.utils;
+
+import 'dart:io';
+import 'dart:convert';
+
+import 'package:vm_snapshot_analysis/ascii_table.dart';
+import 'package:vm_snapshot_analysis/program_info.dart';
+import 'package:vm_snapshot_analysis/instruction_sizes.dart'
+    as instruction_sizes;
+import 'package:vm_snapshot_analysis/v8_profile.dart' as v8_profile;
+
+Future<Object> loadJson(File input) async {
+  return await input
+      .openRead()
+      .transform(utf8.decoder)
+      .transform(json.decoder)
+      .first;
+}
+
+Future<ProgramInfo> loadProgramInfo(File input,
+    {bool collapseAnonymousClosures = false}) async {
+  final json = await loadJson(input);
+  if (v8_profile.Snapshot.isV8HeapSnapshot(json)) {
+    return v8_profile.toProgramInfo(v8_profile.Snapshot.fromJson(json),
+        collapseAnonymousClosures: collapseAnonymousClosures);
+  } else {
+    return instruction_sizes.loadProgramInfo(json,
+        collapseAnonymousClosures: collapseAnonymousClosures);
+  }
+}
+
+void printHistogram(ProgramInfo info, Histogram histogram,
+    {Iterable<String> prefix = const [],
+    Iterable<String> suffix = const [],
+    String sizeHeader = 'Size (Bytes)',
+    int maxWidth = 0}) {
+  final totalSize = info.totalSize;
+  final wasFiltered = totalSize != histogram.totalSize;
+  final table = AsciiTable(header: [
+    for (var col in histogram.bucketInfo.nameComponents) Text.left(col),
+    Text.right(sizeHeader),
+    Text.right('Percent'),
+    if (wasFiltered) Text.right('Of total'),
+  ], maxWidth: maxWidth);
+
+  String formatPercent(int value, int total) {
+    final p = value / total * 100.0;
+    return p.toStringAsFixed(2) + "%";
+  }
+
+  if (prefix.isNotEmpty) {
+    for (var key in prefix) {
+      final size = histogram.buckets[key];
+      table.addRow([
+        ...histogram.bucketInfo.namesFromBucket(key),
+        size.toString(),
+        formatPercent(size, histogram.totalSize),
+        if (wasFiltered) formatPercent(size, totalSize),
+      ]);
+    }
+    table.addSeparator(
+        prefix.length < histogram.length ? Separator.Wave : Separator.Line);
+  }
+
+  final visibleSize = [prefix, suffix]
+      .expand((l) => l)
+      .fold(0, (sum, key) => sum + histogram.buckets[key]);
+  final numRestRows = histogram.length - (suffix.length + prefix.length);
+  if (numRestRows > 0) {
+    final totalRestBytes = histogram.totalSize - visibleSize;
+    table.addTextSeparator(
+        '$numRestRows more rows accounting for ${totalRestBytes}'
+        ' (${formatPercent(totalRestBytes, totalSize)} of total) bytes');
+    final avg = (totalRestBytes / numRestRows).round();
+    table.addTextSeparator(
+        'on average that is ${avg} (${formatPercent(avg, histogram.totalSize)})'
+        ' bytes per row');
+    table.addSeparator(suffix.isNotEmpty ? Separator.Wave : Separator.Line);
+  }
+
+  if (suffix.isNotEmpty) {
+    for (var key in suffix) {
+      table.addRow([
+        ...histogram.bucketInfo.namesFromBucket(key),
+        histogram.buckets[key].toString(),
+        formatPercent(histogram.buckets[key], histogram.totalSize),
+      ]);
+    }
+    table.addSeparator(Separator.Line);
+  }
+
+  table.render();
+
+  if (wasFiltered || visibleSize != histogram.totalSize) {
+    print('In visible rows: ${visibleSize}'
+        ' (${formatPercent(visibleSize, totalSize)} of total)');
+  }
+  print('Total: ${totalSize} bytes');
+}
diff --git a/pkg/vm_snapshot_analysis/lib/v8_profile.dart b/pkg/vm_snapshot_analysis/lib/v8_profile.dart
new file mode 100644
index 0000000..c002c6f
--- /dev/null
+++ b/pkg/vm_snapshot_analysis/lib/v8_profile.dart
@@ -0,0 +1,564 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// This library contains utilities for reading and analyzing snapshot profiles
+/// produced by `--write-v8-snapshot-profile-to` VM flag.
+library vm_snapshot_analysis.v8_profile;
+
+import 'package:meta/meta.dart';
+import 'package:vm_snapshot_analysis/name.dart';
+
+import 'package:vm_snapshot_analysis/program_info.dart';
+
+/// This class represents snapshot graph.
+///
+/// Note that we do not eagerly deserialize the graph, instead we provide helper
+/// methods and wrapper objects to work with serialized representation.
+class Snapshot {
+  final Meta meta;
+  final int nodeCount;
+  final int edgeCount;
+
+  /// Serialized flat representation of nodes in the graph. Each node occupies
+  /// [meta.nodeFieldCount] consecutive elements of the list.
+  final List _nodes;
+
+  /// Serialized flat representation of edges between nodes. Each edge occupies
+  /// [meta.edgeFieldCount] consecutive elements of the list. All outgoing edges
+  /// for a node are serialized consecutively, number of outgoing edges is given
+  /// by the value at index [meta.nodeEdgeCountIndex] inside the node.
+  final List _edges;
+
+  /// Auxiliary array which gives starting index of edges (in the [_edges] list)
+  /// for the given node index.
+  final List<int> _edgesStartIndexForNode;
+
+  final List strings;
+
+  Snapshot._(this.meta, this.nodeCount, this.edgeCount, this._nodes,
+      this._edges, this.strings, this._edgesStartIndexForNode);
+
+  /// Return node with the given index.
+  Node nodeAt(int index) {
+    assert(index >= 0, 'Node index should be positive: $index');
+    return Node._(snapshot: this, index: index);
+  }
+
+  /// Return all nodes in the snapshot.
+  Iterable<Node> get nodes => Iterable.generate(nodeCount, nodeAt);
+
+  /// Returns true if the given JSON object is likely to be a serialized
+  /// snapshot using V8 heap snapshot format.
+  static bool isV8HeapSnapshot(Object m) =>
+      m is Map<String, dynamic> && m.containsKey('snapshot');
+
+  /// Construct [Snapshot] object from the given JSON object.
+  factory Snapshot.fromJson(Map<String, dynamic> m) {
+    // Extract meta information first.
+    final meta = Meta._fromJson(m['snapshot']['meta']);
+
+    final nodes = m['nodes'];
+
+    // Build an array of starting indexes of edges for each node.
+    final edgesStartIndexForNode = <int>[0];
+    int nextStartIndex = 0;
+    for (var i = meta.nodeEdgeCountIndex;
+        i < nodes.length;
+        i += meta.nodeFieldCount) {
+      nextStartIndex += nodes[i];
+      edgesStartIndexForNode.add(nextStartIndex);
+    }
+
+    return Snapshot._(
+        meta,
+        m['snapshot']['node_count'],
+        m['snapshot']['edge_count'],
+        m['nodes'],
+        m['edges'],
+        m['strings'],
+        edgesStartIndexForNode);
+  }
+}
+
+/// Meta-information about the serialized snapshot.
+///
+/// Describes the structure of serialized nodes and edges by giving indexes of
+/// the various fields.
+class Meta {
+  final int nodeTypeIndex;
+  final int nodeNameIndex;
+  final int nodeIdIndex;
+  final int nodeSelfSizeIndex;
+  final int nodeEdgeCountIndex;
+  final int nodeFieldCount;
+
+  final int edgeTypeIndex;
+  final int edgeNameOrIndexIndex;
+  final int edgeToNodeIndex;
+  final int edgeFieldCount;
+
+  final List<String> nodeTypes;
+  final List<String> edgeTypes;
+
+  Meta._(
+      {this.nodeTypeIndex,
+      this.nodeNameIndex,
+      this.nodeIdIndex,
+      this.nodeSelfSizeIndex,
+      this.nodeEdgeCountIndex,
+      this.nodeFieldCount,
+      this.edgeTypeIndex,
+      this.edgeNameOrIndexIndex,
+      this.edgeToNodeIndex,
+      this.edgeFieldCount,
+      this.nodeTypes,
+      this.edgeTypes});
+
+  factory Meta._fromJson(Map<String, dynamic> m) {
+    final nodeFields = m['node_fields'];
+    final nodeTypes = m['node_types'].first.cast<String>();
+    final edgeFields = m['edge_fields'];
+    final edgeTypes = m['edge_types'].first.cast<String>();
+    return Meta._(
+        nodeTypeIndex: nodeFields.indexOf('type'),
+        nodeNameIndex: nodeFields.indexOf('name'),
+        nodeIdIndex: nodeFields.indexOf('id'),
+        nodeSelfSizeIndex: nodeFields.indexOf('self_size'),
+        nodeEdgeCountIndex: nodeFields.indexOf('edge_count'),
+        nodeFieldCount: nodeFields.length,
+        edgeTypeIndex: edgeFields.indexOf('type'),
+        edgeNameOrIndexIndex: edgeFields.indexOf('name_or_index'),
+        edgeToNodeIndex: edgeFields.indexOf('to_node'),
+        edgeFieldCount: edgeFields.length,
+        nodeTypes: nodeTypes,
+        edgeTypes: edgeTypes);
+  }
+}
+
+/// Edge from [Node] to [Node] in the [Snapshot] graph.
+class Edge {
+  final Snapshot snapshot;
+
+  /// Index of this [Edge] within the [snapshot].
+  final int index;
+
+  Edge._({this.snapshot, this.index});
+
+  String get type => snapshot
+      .meta.edgeTypes[snapshot._edges[_offset + snapshot.meta.edgeTypeIndex]];
+
+  Node get target {
+    return Node._(
+        snapshot: snapshot,
+        index: snapshot._edges[_offset + snapshot.meta.edgeToNodeIndex] ~/
+            snapshot.meta.nodeFieldCount);
+  }
+
+  String get name {
+    final nameOrIndex =
+        snapshot._edges[_offset + snapshot.meta.edgeNameOrIndexIndex];
+    return type == 'property' ? snapshot.strings[nameOrIndex] : '@$nameOrIndex';
+  }
+
+  @override
+  String toString() {
+    final nameOrIndex =
+        snapshot._edges[_offset + snapshot.meta.edgeNameOrIndexIndex];
+    return {
+      'type': type,
+      'nameOrIndex':
+          type == 'property' ? snapshot.strings[nameOrIndex] : nameOrIndex,
+      'toNode': target.index,
+    }.toString();
+  }
+
+  /// Offset into [Snapshot._edges] list at which this edge begins.
+  int get _offset => index * snapshot.meta.edgeFieldCount;
+}
+
+/// Node in the [Snapshot] graph.
+class Node {
+  final Snapshot snapshot;
+
+  /// Index of this [Node] within the [snapshot].
+  final int index;
+
+  Node._({this.snapshot, this.index});
+
+  int get edgeCount =>
+      snapshot._nodes[_offset + snapshot.meta.nodeEdgeCountIndex];
+
+  String get type => snapshot
+      .meta.nodeTypes[snapshot._nodes[_offset + snapshot.meta.nodeTypeIndex]];
+
+  String get name =>
+      snapshot.strings[snapshot._nodes[_offset + snapshot.meta.nodeNameIndex]];
+
+  int get selfSize =>
+      snapshot._nodes[_offset + snapshot.meta.nodeSelfSizeIndex];
+
+  int get id => snapshot._nodes[_offset + snapshot.meta.nodeIdIndex];
+
+  /// Returns all outgoing edges for this node.
+  Iterable<Edge> get edges sync* {
+    var firstEdgeIndex = snapshot._edgesStartIndexForNode[index];
+    for (var i = 0, n = edgeCount; i < n; i++) {
+      yield Edge._(snapshot: snapshot, index: firstEdgeIndex + i);
+    }
+  }
+
+  @override
+  String toString() {
+    return {
+      'type': type,
+      'name': name,
+      'id': id,
+      'selfSize': selfSize,
+      'edges': edges.toList(),
+    }.toString();
+  }
+
+  /// Returns the target of an outgoing edge with the given name (if any).
+  Node operator [](String edgeName) => this
+      .edges
+      .firstWhere((e) => e.name == edgeName, orElse: () => null)
+      ?.target;
+
+  @override
+  bool operator ==(Object other) {
+    return other is Node && other.index == index;
+  }
+
+  @override
+  int get hashCode => this.index.hashCode;
+
+  /// Offset into [Snapshot._nodes] list at which this node begins.
+  int get _offset => index * snapshot.meta.nodeFieldCount;
+}
+
+/// Class representing information about V8 snapshot profile in relation
+/// to a [ProgramInfo] structure that was derived from it.
+class SnapshotInfo {
+  final Snapshot snapshot;
+
+  final List<ProgramInfoNode> infoNodes;
+  final Map<int, int> _ownerOf;
+
+  SnapshotInfo._(this.snapshot, this.infoNodes, this._ownerOf);
+
+  ProgramInfoNode ownerOf(Node node) =>
+      infoNodes[_ownerOf[node.index] ?? ProgramInfo.unknownId];
+}
+
+ProgramInfo toProgramInfo(Snapshot snap,
+    {bool collapseAnonymousClosures = false}) {
+  return _ProgramInfoBuilder(
+          collapseAnonymousClosures: collapseAnonymousClosures)
+      .build(snap);
+}
+
+class _ProgramInfoBuilder {
+  final bool collapseAnonymousClosures;
+
+  final program = ProgramInfo();
+
+  final List<ProgramInfoNode> infoNodes = [];
+
+  /// Mapping between snapshot [Node] index and id of [ProgramInfoNode] which
+  /// own this node.
+  final Map<int, int> ownerOf = {};
+
+  /// Mapping between snapshot [Node] indices and corresponding
+  /// [ProgramInfoNode] objects. Note that multiple snapshot nodes might be
+  /// mapped to a single [ProgramInfoNode] (e.g. when anonymous closures are
+  /// collapsed).
+  final Map<int, ProgramInfoNode> infoNodeByIndex = {};
+
+  // Mapping between package names and corresponding [ProgramInfoNode] objects
+  // representing those packages.
+  final Map<String, ProgramInfoNode> infoNodeForPackage = {};
+
+  /// Owners of some [Node] are determined by the program structure and not
+  /// by their reachability through the graph. For example, an owner of a
+  /// function is a class that contains it, even though the function can
+  /// also be reachable from another function through object pool.
+  final Set<int> nodesWithFrozenOwner = {};
+
+  /// Cache used to optimize common ancestor operation on [ProgramInfoNode] ids.
+  /// See [findCommonAncestor] method.
+  final Map<int, int> commonAncestorCache = {};
+
+  _ProgramInfoBuilder({this.collapseAnonymousClosures});
+
+  /// Recover [ProgramInfo] structure from the snapshot profile.
+  ///
+  /// This is done via a simple graph traversal: first all nodes representing
+  /// objects with clear ownership (like libraries, classes, functions) are
+  /// discovered and corresponding [ProgramInfoNode] objects are created for
+  /// them. Then the rest of the snapshot is attributed to one of these nodes
+  /// based on reachability (ignoring reachability from normal snapshot roots):
+  /// let `R(n)` be a set of [ProgramInfoNode] objects from which a given
+  /// snapshot node `n` is reachable. Then we define an owner of `n` to be
+  /// a lowest common ancestor of all nodes in `R(n)`.
+  ///
+  /// Nodes which are not reachable from any normal [ProgramInfoNode] are
+  /// attributed to special `@unknown` [ProgramInfoNode].
+  ProgramInfo build(Snapshot snap) {
+    infoNodes.add(program.root);
+    infoNodes.add(program.stubs);
+    infoNodes.add(program.unknown);
+
+    // Create ProgramInfoNode for every snapshot node representing an element
+    // of the program structure (e.g. a library, a class, a function).
+    snap.nodes.forEach(getInfoNodeFor);
+
+    // Propagate the ownership information across the edges.
+    final worklist = ownerOf.keys.toList();
+    while (worklist.isNotEmpty) {
+      final node = snap.nodeAt(worklist.removeLast());
+      final sourceOwner = ownerOf[node.index];
+      for (var e in node.edges) {
+        final target = e.target;
+        if (!nodesWithFrozenOwner.contains(target.index)) {
+          final targetOwner = ownerOf[target.index];
+          final updatedOwner = findCommonAncestor(sourceOwner, targetOwner);
+          if (updatedOwner != targetOwner) {
+            ownerOf[target.index] = updatedOwner;
+            worklist.add(target.index);
+          }
+        }
+      }
+    }
+
+    // Now attribute sizes from the snapshot to nodes that own them.
+    for (var node in snap.nodes) {
+      if (node.selfSize > 0) {
+        final owner = infoNodes[ownerOf[node.index] ?? ProgramInfo.unknownId];
+        owner.size = (owner.size ?? 0) + node.selfSize;
+      }
+    }
+
+    program.snapshotInfo = SnapshotInfo._(snap, infoNodes, ownerOf);
+
+    return program;
+  }
+
+  ProgramInfoNode getInfoNodeFor(Node node) {
+    var info = infoNodeByIndex[node.index];
+    if (info == null) {
+      info = createInfoNodeFor(node);
+      if (info != null) {
+        // Snapshot nodes which represent the program structure can't change
+        // their owner during iteration - their owner is frozen and is given
+        // by the program structure.
+        nodesWithFrozenOwner.add(node.index);
+        ownerOf[node.index] = info.parent?.id ?? info.id;
+
+        // Handle some nodes specially.
+        switch (node.type) {
+          case 'Code':
+            // Freeze ownership of the Instructions object.
+            final instructions = node['<instructions>'];
+            nodesWithFrozenOwner.add(instructions.index);
+            ownerOf[instructions.index] =
+                findCommonAncestor(ownerOf[instructions.index], info.id);
+            break;
+          case 'Library':
+            // Freeze ownership of the Script objects owned by this library.
+            final scripts = node['owned_scripts_'];
+            if (scripts != null) {
+              for (var e in scripts.edges) {
+                if (e.target.type == 'Script') {
+                  nodesWithFrozenOwner.add(e.target.index);
+                  ownerOf[e.target.index] =
+                      findCommonAncestor(ownerOf[e.target.index], info.id);
+                }
+              }
+            }
+            break;
+        }
+      }
+    }
+    return info;
+  }
+
+  ProgramInfoNode createInfoNodeFor(Node node) {
+    switch (node.type) {
+      case 'Code':
+        var owner = node['owner_'];
+        if (owner.type != 'Type') {
+          if (owner.type == 'WeakSerializationReference') {
+            owner = node[':owner_'];
+          }
+          final ownerNode =
+              owner.type == 'Null' ? program.stubs : getInfoNodeFor(owner);
+          return makeInfoNode(node.index,
+              name: node.name, parent: ownerNode, type: NodeType.other);
+        }
+        break;
+
+      case 'Function':
+        if (node.name != '<anonymous signature>') {
+          var owner = node['owner_'];
+          if (node['data_'].type == 'ClosureData') {
+            owner = node['data_']['parent_function_'];
+          }
+          return makeInfoNode(node.index,
+              name: node.name,
+              parent: getInfoNodeFor(owner),
+              type: NodeType.functionNode);
+        }
+        break;
+
+      case 'PatchClass':
+        return getInfoNodeFor(node['patched_class_']);
+
+      case 'Class':
+        if (node['library_'] != null) {
+          return makeInfoNode(node.index,
+              name: node.name,
+              parent: getInfoNodeFor(node['library_']) ?? program.root,
+              type: NodeType.classNode);
+        }
+        break;
+
+      case 'Library':
+        // Create fake owner node for the package which contains this library.
+        final packageName = packageOf(node.name);
+        return makeInfoNode(node.index,
+            name: node.name,
+            parent: packageName != node.name
+                ? packageOwner(packageName)
+                : program.root,
+            type: NodeType.libraryNode);
+
+      case 'Field':
+        return makeInfoNode(node.index,
+            name: node.name,
+            parent: getInfoNodeFor(node['owner_']),
+            type: NodeType.other);
+    }
+    return null;
+  }
+
+  ProgramInfoNode makeInfoNode(int index,
+      {@required ProgramInfoNode parent,
+      @required String name,
+      @required NodeType type}) {
+    assert(parent != null,
+        'Trying to create node of type ${type} with ${name} and no parent.');
+    assert(name != null);
+
+    name = Name(name).scrubbed;
+    if (collapseAnonymousClosures) {
+      name = Name.collapse(name);
+    }
+
+    final node = program.makeNode(name: name, parent: parent, type: type);
+    if (node.id == infoNodes.length) {
+      infoNodes.add(node);
+    }
+    if (index != null) {
+      assert(!infoNodeByIndex.containsKey(index));
+      infoNodeByIndex[index] = node;
+    }
+    return node;
+  }
+
+  ProgramInfoNode packageOwner(String packageName) =>
+      infoNodeForPackage.putIfAbsent(
+          packageName,
+          () => makeInfoNode(null,
+              name: packageName,
+              type: NodeType.packageNode,
+              parent: program.root));
+
+  /// Create a single key from two node ids.
+  /// Note that this operation is commutative, because common ancestor of A and
+  /// B is the same as common ancestor of B and A.
+  static int ancestorCacheKey(int a, int b) {
+    if (a > b) {
+      return b << 32 | a;
+    } else {
+      return a << 32 | b;
+    }
+  }
+
+  /// Returns id of a common ancestor between [ProgramInfoNode] with [idA] and
+  /// [idB].
+  int findCommonAncestor(int idA, int idB) {
+    if (idA == null) {
+      return idB;
+    }
+    if (idB == null) {
+      return idA;
+    }
+    if (idA == idB) {
+      return idA;
+    }
+
+    // If either are shared - then result is shared.
+    if (idA == ProgramInfo.rootId || idB == ProgramInfo.rootId) {
+      return ProgramInfo.rootId;
+    }
+
+    final infoA = infoNodes[idA];
+    final infoB = infoNodes[idB];
+
+    final key = ancestorCacheKey(idA, idB);
+    var ancestor = commonAncestorCache[key];
+    if (ancestor == null) {
+      commonAncestorCache[key] =
+          ancestor = findCommonAncestorImpl(infoA, infoB).id;
+    }
+    return ancestor;
+  }
+
+  static List<ProgramInfoNode> pathToRoot(ProgramInfoNode node) {
+    final path = <ProgramInfoNode>[];
+    while (node != null) {
+      path.add(node);
+      node = node.parent;
+    }
+    return path;
+  }
+
+  static ProgramInfoNode findCommonAncestorImpl(
+      ProgramInfoNode a, ProgramInfoNode b) {
+    final pathA = pathToRoot(a);
+    final pathB = pathToRoot(b);
+    var i = pathA.length - 1, j = pathB.length - 1;
+    while (i > 0 && j > 0 && (pathA[i - 1] == pathB[j - 1])) {
+      i--;
+      j--;
+    }
+    assert(pathA[i] == pathB[j]);
+    return pathA[i];
+  }
+}
+
+final bucketLegend = '''
+
+--------------------------------------------------------------------------------
+IMPORTANT: Dart AOT snapshot is a serialized representation of Dart VM heap.
+Outside of few specific cases (e.g. an object representing a library clearly
+originates from the library it represents) there is no well defined relationship
+between snapshot bytes and a specific method/class/library to which these
+bytes can be attributed with certainty. This snapshot analysis tool tries
+to attribute bytes to specific program structure elements based on their
+reachability from objects with well defined origin - meaning that this analysis
+has some margin of error and imprecision.
+
+- @other bucket denotes bytes attributed to entities outside of the current
+granularity. For example, when breaking down the size by method name there
+might be bytes which exist outside of any specific symbol - in which case
+they will be attributed to @other.
+- @stubs bucket accumulates bytes attributed to stubs (pieces of machine code
+produced by the VM for internal purposes).
+- @shared bucket accumulates bytes shared between otherwise unrelated program
+entities
+- @unknown bucket accumulates bytes which are not reachable from any program
+structure nodes (usually VM internal objects).
+--------------------------------------------------------------------------------
+''';
diff --git a/pkg/vm_snapshot_analysis/pubspec.yaml b/pkg/vm_snapshot_analysis/pubspec.yaml
new file mode 100644
index 0000000..ab0a015
--- /dev/null
+++ b/pkg/vm_snapshot_analysis/pubspec.yaml
@@ -0,0 +1,20 @@
+name: vm_snapshot_analysis
+description: Utilities for working with non-symbolic stack traces.
+version: 0.1.0
+
+homepage: https://github.com/dart-lang/sdk/tree/master/pkg/vm_snapshot_analysis
+
+environment:
+  sdk: '>=2.8.0 <3.0.0'
+
+executables:
+  snapshot_analysis: analyse
+
+dependencies:
+  args: ^1.6.0
+  path: ^1.7.0
+  meta: ^1.1.8
+
+dev_dependencies:
+  pedantic: ^1.9.0
+  test: ^1.15.1
diff --git a/pkg/vm_snapshot_analysis/test/instruction_sizes_test.dart b/pkg/vm_snapshot_analysis/test/instruction_sizes_test.dart
new file mode 100644
index 0000000..55c71f0
--- /dev/null
+++ b/pkg/vm_snapshot_analysis/test/instruction_sizes_test.dart
@@ -0,0 +1,720 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:path/path.dart' as path;
+import 'package:test/test.dart';
+
+import 'package:vm_snapshot_analysis/instruction_sizes.dart'
+    as instruction_sizes;
+import 'package:vm_snapshot_analysis/program_info.dart';
+import 'package:vm_snapshot_analysis/utils.dart';
+
+final dart2native = () {
+  final sdkBin = path.dirname(Platform.executable);
+  final dart2native =
+      path.join(sdkBin, Platform.isWindows ? 'dart2native.bat' : 'dart2native');
+
+  if (!File(dart2native).existsSync()) {
+    throw 'Failed to locate dart2native in the SDK';
+  }
+
+  return path.canonicalize(dart2native);
+}();
+
+final testSource = {
+  'input.dart': """
+class K {
+  final value;
+  const K(this.value);
+}
+
+@pragma('vm:never-inline')
+dynamic makeSomeClosures() {
+  return [
+    () => const K(0),
+    () => const K(1),
+    () => 11,
+  ];
+}
+
+class A {
+  @pragma('vm:never-inline')
+  dynamic tornOff() {
+    return const K(2);
+  }
+}
+
+class B {
+  @pragma('vm:never-inline')
+  dynamic tornOff() {
+    return const K(3);
+  }
+}
+
+class C {
+  static dynamic tornOff() async {
+    return const K(4);
+  }
+}
+
+@pragma('vm:never-inline')
+Function tearOff(dynamic o) {
+  return o.tornOff;
+}
+
+void main(List<String> args) {
+  for (var cl in makeSomeClosures()) {
+    print(cl());
+  }
+  print(tearOff(args.isEmpty ? A() : B()));
+  print(C.tornOff);
+}
+"""
+};
+
+// Almost exactly the same source as above, but with few modifications
+// marked with a 'modified' comment.
+final testSourceModified = {
+  'input.dart': """
+class K {
+  final value;
+  const K(this.value);
+}
+
+@pragma('vm:never-inline')
+dynamic makeSomeClosures() {
+  return [
+    () => const K(0),
+    () => const K(1),
+    () => 11,
+    () => {},  // modified
+  ];
+}
+
+class A {
+  @pragma('vm:never-inline')
+  dynamic tornOff() {
+    for (var cl in makeSomeClosures()) {  // modified
+      print(cl());                        // modified
+    }                                     // modified
+    return const K(2);
+  }
+}
+
+class B {
+  @pragma('vm:never-inline')
+  dynamic tornOff() {
+    return const K(3);
+  }
+}
+
+class C {
+  static dynamic tornOff() async {
+    return const K(4);
+  }
+}
+
+@pragma('vm:never-inline')
+Function tearOff(dynamic o) {
+  return o.tornOff;
+}
+
+void main(List<String> args) {
+  // modified
+  print(tearOff(args.isEmpty ? A() : B()));
+  print(C.tornOff);
+}
+"""
+};
+
+final testSourceModified2 = {
+  'input.dart': """
+class K {
+  final value;
+  const K(this.value);
+}
+
+@pragma('vm:never-inline')
+dynamic makeSomeClosures() {
+  return [
+    () => const K(0),
+  ];
+}
+
+class A {
+  @pragma('vm:never-inline')
+  dynamic tornOff() {
+    return const K(2);
+  }
+}
+
+class B {
+  @pragma('vm:never-inline')
+  dynamic tornOff() {
+    return const K(3);
+  }
+}
+
+class C {
+  static dynamic tornOff() async {
+    return const K(4);
+  }
+}
+
+@pragma('vm:never-inline')
+Function tearOff(dynamic o) {
+  return o.tornOff;
+}
+
+void main(List<String> args) {
+  for (var cl in makeSomeClosures()) {
+    print(cl());
+  }
+  print(tearOff(args.isEmpty ? A() : B()));
+  print(C.tornOff);
+}
+"""
+};
+
+extension on Histogram {
+  String bucketFor(String pkg, String lib, String cls, String fun) =>
+      (this.bucketInfo as Bucketing).bucketFor(pkg, lib, cls, fun);
+}
+
+void main() async {
+  if (!Platform.executable.contains('dart-sdk')) {
+    // If we are not running from the prebuilt SDK then this test does nothing.
+    return;
+  }
+
+  group('instruction-sizes', () {
+    test('basic-parsing', () async {
+      await withSymbolSizes('basic-parsing', testSource, (sizesJson) async {
+        final symbols =
+            instruction_sizes.fromJson(await loadJson(File(sizesJson)));
+        expect(symbols, isNotNull,
+            reason: 'Sizes file was successfully parsed');
+        expect(symbols.length, greaterThan(0),
+            reason: 'Sizes file is non-empty');
+
+        // Check for duplicated symbols (using both raw and scrubbed names).
+        // Maps below contain mappings library-uri -> class-name -> names.
+        final symbolRawNames = <String, Map<String, Set<String>>>{};
+        final symbolScrubbedNames = <String, Map<String, Set<String>>>{};
+
+        Set<String> getSetOfNames(Map<String, Map<String, Set<String>>> map,
+            String libraryUri, String className) {
+          return map
+              .putIfAbsent(libraryUri ?? '', () => {})
+              .putIfAbsent(className ?? '', () => {});
+        }
+
+        for (var sym in symbols) {
+          expect(
+              getSetOfNames(symbolRawNames, sym.libraryUri, sym.className)
+                  .add(sym.name.raw),
+              isTrue,
+              reason:
+                  'All symbols should have unique names (within libraries): ${sym.name.raw}');
+          expect(
+              getSetOfNames(symbolScrubbedNames, sym.libraryUri, sym.className)
+                  .add(sym.name.scrubbed),
+              isTrue,
+              reason: 'Scrubbing the name should not make it non-unique');
+        }
+
+        // Check for expected names which should appear in the output.
+        final inputDartSymbolNames =
+            symbolScrubbedNames['package:input/input.dart'];
+        expect(inputDartSymbolNames, isNotNull,
+            reason: 'Symbols from input.dart are included into sizes output');
+
+        expect(inputDartSymbolNames[''], isNotNull,
+            reason: 'Should include top-level members from input.dart');
+        expect(inputDartSymbolNames[''], contains('makeSomeClosures'));
+        final closures = inputDartSymbolNames[''].where(
+            (name) => name.startsWith('makeSomeClosures.<anonymous closure'));
+        expect(closures.length, 3,
+            reason: 'There are three closures inside makeSomeClosure');
+
+        expect(inputDartSymbolNames['A'], isNotNull,
+            reason: 'Should include class A members from input.dart');
+        expect(inputDartSymbolNames['A'], contains('tornOff'));
+        expect(inputDartSymbolNames['A'], contains('[tear-off] tornOff'));
+        expect(inputDartSymbolNames['A'],
+            contains('[tear-off-extractor] get:tornOff'));
+
+        expect(inputDartSymbolNames['B'], isNotNull,
+            reason: 'Should include class B members from input.dart');
+        expect(inputDartSymbolNames['B'], contains('tornOff'));
+        expect(inputDartSymbolNames['B'], contains('[tear-off] tornOff'));
+        expect(inputDartSymbolNames['B'],
+            contains('[tear-off-extractor] get:tornOff'));
+
+        // Presence of async modifier should not cause tear-off name to end
+        // with {body}.
+        expect(inputDartSymbolNames['C'], contains('[tear-off] tornOff'));
+
+        // Check that output does not contain '[unknown stub]'
+        expect(symbolRawNames[''][''], isNot(contains('[unknown stub]')),
+            reason: 'All stubs must be named');
+      });
+    });
+
+    test('program-info-from-sizes', () async {
+      await withSymbolSizes('program-info-from-sizes', testSource,
+          (sizesJson) async {
+        final info = await loadProgramInfo(File(sizesJson));
+        expect(info.root.children, contains('dart:core'));
+        expect(info.root.children, contains('dart:typed_data'));
+        expect(info.root.children, contains('package:input'));
+
+        final inputLib = info.root.children['package:input']
+            .children['package:input/input.dart'];
+        expect(inputLib, isNotNull);
+        expect(inputLib.children, contains('')); // Top-level class.
+        expect(inputLib.children, contains('A'));
+        expect(inputLib.children, contains('B'));
+        expect(inputLib.children, contains('C'));
+
+        final topLevel = inputLib.children[''];
+        expect(topLevel.children, contains('makeSomeClosures'));
+        expect(
+            topLevel.children['makeSomeClosures'].children.length, equals(3));
+
+        for (var name in [
+          '[tear-off] tornOff',
+          'tornOff',
+          'Allocate A',
+          '[tear-off-extractor] get:tornOff'
+        ]) {
+          expect(inputLib.children['A'].children, contains(name));
+          expect(inputLib.children['A'].children[name].children, isEmpty);
+        }
+
+        for (var name in [
+          '[tear-off] tornOff',
+          'tornOff',
+          'Allocate B',
+          '[tear-off-extractor] get:tornOff'
+        ]) {
+          expect(inputLib.children['B'].children, contains(name));
+          expect(inputLib.children['B'].children[name].children, isEmpty);
+        }
+
+        for (var name in ['tornOff{body}', 'tornOff', '[tear-off] tornOff']) {
+          expect(inputLib.children['C'].children, contains(name));
+          expect(inputLib.children['C'].children[name].children, isEmpty);
+        }
+      });
+    });
+
+    test('histograms', () async {
+      await withSymbolSizes('histograms', testSource, (sizesJson) async {
+        final info = await loadProgramInfo(File(sizesJson));
+        final bySymbol = computeHistogram(info, HistogramType.bySymbol);
+        expect(
+            bySymbol.buckets,
+            contains(bySymbol.bucketFor(
+                'package:input', 'package:input/input.dart', 'A', 'tornOff')));
+        expect(
+            bySymbol.buckets,
+            contains(bySymbol.bucketFor(
+                'package:input', 'package:input/input.dart', 'B', 'tornOff')));
+        expect(
+            bySymbol.buckets,
+            contains(bySymbol.bucketFor(
+                'package:input', 'package:input/input.dart', 'C', 'tornOff')));
+
+        final byClass = computeHistogram(info, HistogramType.byClass);
+        expect(
+            byClass.buckets,
+            contains(byClass.bucketFor('package:input',
+                'package:input/input.dart', 'A', 'does-not-matter')));
+        expect(
+            byClass.buckets,
+            contains(byClass.bucketFor('package:input',
+                'package:input/input.dart', 'B', 'does-not-matter')));
+        expect(
+            byClass.buckets,
+            contains(byClass.bucketFor('package:input',
+                'package:input/input.dart', 'C', 'does-not-matter')));
+
+        final byLibrary = computeHistogram(info, HistogramType.byLibrary);
+        expect(
+            byLibrary.buckets,
+            contains(byLibrary.bucketFor(
+                'package:input',
+                'package:input/input.dart',
+                'does-not-matter',
+                'does-not-matter')));
+
+        final byPackage = computeHistogram(info, HistogramType.byPackage);
+        expect(
+            byPackage.buckets,
+            contains(byPackage.bucketFor(
+                'package:input',
+                'package:input/does-not-matter.dart',
+                'does-not-matter',
+                'does-not-matter')));
+      });
+    });
+
+    test('diff', () async {
+      await withSymbolSizes('diff-1', testSource, (sizesJson) async {
+        await withSymbolSizes('diff-2', testSourceModified,
+            (modifiedSizesJson) async {
+          final info = await loadProgramInfo(File(sizesJson));
+          final modifiedInfo = await loadProgramInfo(File(modifiedSizesJson));
+          final diff = computeDiff(info, modifiedInfo);
+
+          expect(
+              diffToJson(diff),
+              equals({
+                '#type': 'library',
+                '@stubs': {'#type': 'library'},
+                '@unknown': {'#type': 'library'},
+                'package:input': {
+                  '#type': 'package',
+                  'package:input/input.dart': {
+                    '#type': 'library',
+                    '': {
+                      '#type': 'class',
+                      'makeSomeClosures': {
+                        '#type': 'function',
+                        '#size': greaterThan(0), // We added code here.
+                        '<anonymous closure @180>': {
+                          '#type': 'function',
+                          '#size': greaterThan(0),
+                        },
+                      },
+                      'main': {
+                        '#type': 'function',
+                        '#size': lessThan(0), // We removed code from main.
+                      },
+                    },
+                    'A': {
+                      '#type': 'class',
+                      'tornOff': {
+                        '#type': 'function',
+                        '#size': greaterThan(0),
+                      },
+                    }
+                  }
+                }
+              }));
+        });
+      });
+    });
+
+    test('diff-collapsed', () async {
+      await withSymbolSizes('diff-collapsed-1', testSource, (sizesJson) async {
+        await withSymbolSizes('diff-collapsed-2', testSourceModified2,
+            (modifiedSizesJson) async {
+          final info = await loadProgramInfo(File(sizesJson),
+              collapseAnonymousClosures: true);
+          final modifiedInfo = await loadProgramInfo(File(modifiedSizesJson),
+              collapseAnonymousClosures: true);
+          final diff = computeDiff(info, modifiedInfo);
+
+          expect(
+              diffToJson(diff),
+              equals({
+                '#type': 'library',
+                '@stubs': {'#type': 'library'},
+                '@unknown': {'#type': 'library'},
+                'package:input': {
+                  '#type': 'package',
+                  'package:input/input.dart': {
+                    '#type': 'library',
+                    '': {
+                      '#type': 'class',
+                      'makeSomeClosures': {
+                        '#size': lessThan(0),
+                        '#type': 'function',
+                        '<anonymous closure>': {
+                          '#size': lessThan(0),
+                          '#type': 'function'
+                        }
+                      }
+                    }
+                  }
+                }
+              }));
+        });
+      });
+    });
+  });
+
+  group('v8-profile', () {
+    test('program-info-from-profile', () async {
+      await withV8Profile('program-info-from-profile', testSource,
+          (profileJson) async {
+        final info = await loadProgramInfo(File(profileJson));
+        expect(info.root.children, contains('dart:core'));
+        expect(info.root.children, contains('dart:typed_data'));
+        expect(info.root.children, contains('package:input'));
+
+        final inputLib = info.root.children['package:input']
+            .children['package:input/input.dart'];
+        expect(inputLib, isNotNull);
+        expect(inputLib.children, contains('::')); // Top-level class.
+        expect(inputLib.children, contains('A'));
+        expect(inputLib.children, contains('B'));
+        expect(inputLib.children, contains('C'));
+
+        final topLevel = inputLib.children['::'];
+        expect(topLevel.children, contains('makeSomeClosures'));
+        expect(
+            topLevel.children['makeSomeClosures'].children.values
+                .where((child) => child.type == NodeType.functionNode)
+                .length,
+            equals(3));
+
+        for (var name in [
+          'tornOff',
+          'Allocate A',
+          '[tear-off-extractor] get:tornOff'
+        ]) {
+          expect(inputLib.children['A'].children, contains(name));
+        }
+        expect(inputLib.children['A'].children['tornOff'].children,
+            contains('[tear-off] tornOff'));
+
+        for (var name in [
+          'tornOff',
+          'Allocate B',
+          '[tear-off-extractor] get:tornOff'
+        ]) {
+          expect(inputLib.children['B'].children, contains(name));
+        }
+        expect(inputLib.children['B'].children['tornOff'].children,
+            contains('[tear-off] tornOff'));
+
+        expect(inputLib.children['C'].children, contains('tornOff'));
+        for (var name in ['tornOff{body}', '[tear-off] tornOff']) {
+          expect(inputLib.children['C'].children['tornOff'].children,
+              contains(name));
+        }
+      });
+    });
+
+    test('histograms', () async {
+      await withV8Profile('histograms', testSource, (sizesJson) async {
+        final info = await loadProgramInfo(File(sizesJson));
+        final bySymbol = computeHistogram(info, HistogramType.bySymbol);
+        expect(
+            bySymbol.buckets,
+            contains(bySymbol.bucketFor(
+                'package:input', 'package:input/input.dart', 'A', 'tornOff')));
+        expect(
+            bySymbol.buckets,
+            contains(bySymbol.bucketFor(
+                'package:input', 'package:input/input.dart', 'B', 'tornOff')));
+        expect(
+            bySymbol.buckets,
+            contains(bySymbol.bucketFor(
+                'package:input', 'package:input/input.dart', 'C', 'tornOff')));
+
+        final byClass = computeHistogram(info, HistogramType.byClass);
+        expect(
+            byClass.buckets,
+            contains(byClass.bucketFor('package:input',
+                'package:input/input.dart', 'A', 'does-not-matter')));
+        expect(
+            byClass.buckets,
+            contains(byClass.bucketFor('package:input',
+                'package:input/input.dart', 'B', 'does-not-matter')));
+        expect(
+            byClass.buckets,
+            contains(byClass.bucketFor('package:input',
+                'package:input/input.dart', 'C', 'does-not-matter')));
+
+        final byLibrary = computeHistogram(info, HistogramType.byLibrary);
+        expect(
+            byLibrary.buckets,
+            contains(byLibrary.bucketFor(
+                'package:input',
+                'package:input/input.dart',
+                'does-not-matter',
+                'does-not-matter')));
+
+        final byPackage = computeHistogram(info, HistogramType.byPackage);
+        expect(
+            byPackage.buckets,
+            contains(byPackage.bucketFor(
+                'package:input',
+                'package:input/does-not-matter.dart',
+                'does-not-matter',
+                'does-not-matter')));
+      });
+    });
+
+    test('diff', () async {
+      await withV8Profile('diff-1', testSource, (profileJson) async {
+        await withV8Profile('diff-2', testSourceModified,
+            (modifiedProfileJson) async {
+          final info = await loadProgramInfo(File(profileJson));
+          final modifiedInfo = await loadProgramInfo(File(modifiedProfileJson));
+          final diff = computeDiff(info, modifiedInfo);
+
+          expect(
+              diffToJson(diff, keepOnlyInputPackage: true),
+              equals({
+                'package:input': {
+                  '#type': 'package',
+                  'package:input/input.dart': {
+                    '#type': 'library',
+                    '::': {
+                      '#type': 'class',
+                      'makeSomeClosures': {
+                        '#type': 'function',
+                        '#size': greaterThan(0), // We added code here.
+                        '<anonymous closure @180>': {
+                          '#type': 'function',
+                          '#size': greaterThan(0),
+                          'makeSomeClosures.<anonymous closure @180>': {
+                            '#size': greaterThan(0)
+                          },
+                        },
+                        'makeSomeClosures': {'#size': greaterThan(0)},
+                      },
+                      'main': {
+                        '#type': 'function',
+                        '#size': lessThan(0), // We removed code from main.
+                        'main': {'#size': lessThan(0)},
+                      },
+                    },
+                    'A': {
+                      '#type': 'class',
+                      'tornOff': {
+                        '#type': 'function',
+                        '#size': greaterThan(0),
+                        'tornOff': {'#size': greaterThan(0)},
+                      },
+                    }
+                  }
+                }
+              }));
+        });
+      });
+    });
+
+    test('diff-collapsed', () async {
+      await withV8Profile('diff-collapsed-1', testSource, (profileJson) async {
+        await withV8Profile('diff-collapsed-2', testSourceModified2,
+            (modifiedProfileJson) async {
+          final info = await loadProgramInfo(File(profileJson),
+              collapseAnonymousClosures: true);
+          final modifiedInfo = await loadProgramInfo(File(modifiedProfileJson),
+              collapseAnonymousClosures: true);
+          final diff = computeDiff(info, modifiedInfo);
+
+          expect(
+              diffToJson(diff, keepOnlyInputPackage: true),
+              equals({
+                'package:input': {
+                  '#type': 'package',
+                  'package:input/input.dart': {
+                    '#type': 'library',
+                    '#size': lessThan(0),
+                    '::': {
+                      '#type': 'class',
+                      'makeSomeClosures': {
+                        '#type': 'function',
+                        '#size': lessThan(0),
+                        '<anonymous closure>': {
+                          '#type': 'function',
+                          '#size': lessThan(0),
+                          'makeSomeClosures.<anonymous closure>': {
+                            '#size': lessThan(0)
+                          },
+                        },
+                        'makeSomeClosures': {'#size': lessThan(0)},
+                      },
+                    },
+                  }
+                }
+              }));
+        });
+      });
+    });
+  });
+}
+
+Future withSymbolSizes(String prefix, Map<String, String> source,
+        Future Function(String sizesJson) f) =>
+    withFlag(prefix, source, '--print_instructions_sizes_to', f);
+
+Future withV8Profile(String prefix, Map<String, String> source,
+        Future Function(String sizesJson) f) =>
+    withFlag(prefix, source, '--write_v8_snapshot_profile_to', f);
+
+Future withFlag(String prefix, Map<String, String> source, String flag,
+    Future Function(String sizesJson) f) {
+  return withTempDir(prefix, (dir) async {
+    final outputBinary = path.join(dir, 'output.exe');
+    final sizesJson = path.join(dir, 'sizes.json');
+    final packages = path.join(dir, '.packages');
+    final mainDart = path.join(dir, 'main.dart');
+
+    // Create test input.
+    for (var file in source.entries) {
+      await File(path.join(dir, file.key)).writeAsString(file.value);
+    }
+    await File(packages).writeAsString('''
+input:./
+''');
+    await File(mainDart).writeAsString('''
+import 'package:input/input.dart' as input;
+
+void main(List<String> args) => input.main(args);
+''');
+
+    // Compile input.dart to native and output instruction sizes.
+    final result = await Process.run(dart2native, [
+      '-o',
+      outputBinary,
+      '--packages=$packages',
+      '--extra-gen-snapshot-options=$flag=$sizesJson',
+      mainDart,
+    ]);
+
+    expect(result.exitCode, equals(0), reason: '''
+Compilation completed successfully.
+
+stdout: ${result.stdout}
+stderr: ${result.stderr}
+''');
+    expect(File(outputBinary).existsSync(), isTrue,
+        reason: 'Output binary exists');
+    expect(File(sizesJson).existsSync(), isTrue,
+        reason: 'Instruction sizes output exists');
+
+    await f(sizesJson);
+  });
+}
+
+Future withTempDir(String prefix, Future Function(String dir) f) async {
+  final tempDir =
+      Directory.systemTemp.createTempSync('instruction-sizes-test-${prefix}');
+  try {
+    await f(tempDir.path);
+  } finally {
+    tempDir.deleteSync(recursive: true);
+  }
+}
+
+// On Windows there is some issue with interpreting entry point URI as a package URI
+// it instead gets interpreted as a file URI - which breaks comparison. So we
+// simply ignore entry point library (main.dart).
+Map<String, dynamic> diffToJson(ProgramInfo diff,
+    {bool keepOnlyInputPackage = false}) {
+  final diffJson = diff.toJson();
+  diffJson.removeWhere((key, _) =>
+      keepOnlyInputPackage ? key != 'package:input' : key.startsWith('file:'));
+  return diffJson;
+}
diff --git a/pkg/vm/test/snapshot/name_test.dart b/pkg/vm_snapshot_analysis/test/name_test.dart
similarity index 95%
rename from pkg/vm/test/snapshot/name_test.dart
rename to pkg/vm_snapshot_analysis/test/name_test.dart
index 9bd1216..762f7f4 100644
--- a/pkg/vm/test/snapshot/name_test.dart
+++ b/pkg/vm_snapshot_analysis/test/name_test.dart
@@ -4,7 +4,7 @@
 
 import 'package:test/test.dart';
 
-import 'package:vm/snapshot/name.dart';
+import 'package:vm_snapshot_analysis/name.dart';
 
 void main() async {
   group('name', () {
diff --git a/runtime/bin/crypto_macos.cc b/runtime/bin/crypto_macos.cc
index e5bf130..b3afc6f 100644
--- a/runtime/bin/crypto_macos.cc
+++ b/runtime/bin/crypto_macos.cc
@@ -16,16 +16,14 @@
 namespace bin {
 
 bool Crypto::GetRandomBytes(intptr_t count, uint8_t* buffer) {
-  ThreadSignalBlocker signal_blocker(SIGPROF);
-  intptr_t fd = TEMP_FAILURE_RETRY_NO_SIGNAL_BLOCKER(
-      open("/dev/urandom", O_RDONLY | O_CLOEXEC));
+  intptr_t fd = TEMP_FAILURE_RETRY(open("/dev/urandom", O_RDONLY | O_CLOEXEC));
   if (fd < 0) {
     return false;
   }
   intptr_t bytes_read = 0;
   do {
-    int res = TEMP_FAILURE_RETRY_NO_SIGNAL_BLOCKER(
-        read(fd, buffer + bytes_read, count - bytes_read));
+    int res =
+        TEMP_FAILURE_RETRY(read(fd, buffer + bytes_read, count - bytes_read));
     if (res < 0) {
       int err = errno;
       close(fd);
diff --git a/runtime/bin/main_options.cc b/runtime/bin/main_options.cc
index aceeeca..c8ab364 100644
--- a/runtime/bin/main_options.cc
+++ b/runtime/bin/main_options.cc
@@ -13,6 +13,7 @@
 #include "bin/error_exit.h"
 #include "bin/options.h"
 #include "bin/platform.h"
+#include "bin/utils.h"
 #include "platform/syslog.h"
 #if !defined(DART_IO_SECURE_SOCKET_DISABLED)
 #include "bin/security_context.h"
@@ -34,8 +35,13 @@
     NULL,
 };
 
+static const char* kEnableExperiment1 = "--enable-experiment";
+static const char* kEnableExperiment2 = "--enable_experiment";
+
 SnapshotKind Options::gen_snapshot_kind_ = kNone;
 bool Options::enable_vm_service_ = false;
+MallocGrowableArray<const char*> Options::enabled_experiments_ =
+    MallocGrowableArray<const char*>(4);
 
 #define OPTION_FIELD(variable) Options::variable##_
 
@@ -379,6 +385,27 @@
   return true;
 }
 
+bool Options::ProcessEnableExperimentOption(const char* arg,
+                                            CommandLineOptions* vm_options) {
+  const char* value =
+      OptionProcessor::ProcessOption(arg, "--enable_experiment=");
+  if (value == nullptr) {
+    value = OptionProcessor::ProcessOption(arg, "--enable-experiment=");
+  }
+  if (value == nullptr) {
+    return false;
+  }
+  vm_options->AddArgument(arg);
+  Utils::CStringUniquePtr tmp = Utils::CreateCStringUniquePtr(strdup(value));
+  char* save_ptr;  // Needed for strtok_r.
+  char* token = strtok_r(const_cast<char*>(tmp.get()), ",", &save_ptr);
+  while (token != NULL) {
+    enabled_experiments_.Add(token);
+    token = strtok_r(NULL, ",", &save_ptr);
+  }
+  return true;
+}
+
 static void ResolveDartDevSnapshotPath(const char* script,
                                        char** snapshot_path) {
   if (!DartDevUtils::TryResolveDartDevSnapshotPath(snapshot_path)) {
@@ -557,19 +584,61 @@
   } else if (i > 1) {
     // If we're running with DartDev, we're going to ignore the VM options for
     // this VM instance and print a warning.
-    Syslog::PrintErr(
-        "Warning: The following flags were passed as VM options and are being "
-        "ignored: ");
-    for (int j = 1; j < script_or_cmd_index; ++j) {
-      Syslog::PrintErr("%s", argv[j]);
-      if (j + 1 < script_or_cmd_index) {
-        Syslog::PrintErr(", ");
+
+    int num_experiment_flags = 0;
+    if (!enabled_experiments_.is_empty()) {
+      for (intptr_t j = 1; j < script_or_cmd_index; ++j) {
+        if ((strstr(argv[j], kEnableExperiment1) != nullptr) ||
+            (strstr(argv[j], kEnableExperiment2) != nullptr)) {
+          ++num_experiment_flags;
+        }
       }
     }
-    Syslog::PrintErr(
-        "\nThese flags should be passed after the dart command (e.g., 'dart "
-        "run --enable-asserts foo.dart' instead of 'dart --enable-asserts run "
-        "foo.dart').\n");
+    if (num_experiment_flags + 1 != script_or_cmd_index) {
+      Syslog::PrintErr(
+          "Warning: The following flags were passed as VM options and are "
+          "being "
+          "ignored:\n\n");
+      for (int j = 1; j < script_or_cmd_index; ++j) {
+        if ((strstr(argv[j], kEnableExperiment1) == nullptr) &&
+            (strstr(argv[j], kEnableExperiment2) == nullptr)) {
+          Syslog::PrintErr("  %s\n", argv[j]);
+        }
+      }
+      Syslog::PrintErr(
+          "\nThese flags should be passed after the dart command (e.g., 'dart "
+          "run --enable-asserts foo.dart' instead of 'dart --enable-asserts "
+          "run "
+          "foo.dart').\n\n");
+    }
+  }
+
+  if (!enabled_experiments_.is_empty() &&
+      !(Options::disable_dart_dev() || run_script)) {
+    intptr_t num_experiments = enabled_experiments_.length();
+    int option_size = strlen(kEnableExperiment1) + 1;
+    for (intptr_t i = 0; i < num_experiments; ++i) {
+      const char* flag = enabled_experiments_.At(i);
+      option_size += strlen(flag);
+      if (i + 1 != num_experiments) {
+        // Account for comma if there's more experiments to add.
+        ++option_size;
+      }
+    }
+    // Make room for null terminator
+    ++option_size;
+
+    char* enabled_experiments_arg = new char[option_size];
+    int offset = snprintf(enabled_experiments_arg, option_size,
+                          "%s=", kEnableExperiment1);
+    for (intptr_t i = 0; i < num_experiments; ++i) {
+      const char* flag = enabled_experiments_.At(i);
+      const char* kFormat = (i + 1 != num_experiments) ? "%s," : "%s";
+      offset += snprintf(enabled_experiments_arg + offset, option_size - offset,
+                         kFormat, flag);
+      ASSERT(offset < option_size);
+    }
+    dart_options->AddArgument(enabled_experiments_arg);
   }
 
   // Parse out options to be passed to dart main.
diff --git a/runtime/bin/main_options.h b/runtime/bin/main_options.h
index 9247863..4fe673c 100644
--- a/runtime/bin/main_options.h
+++ b/runtime/bin/main_options.h
@@ -8,6 +8,7 @@
 #include "bin/dartutils.h"
 #include "bin/dfe.h"
 #include "platform/globals.h"
+#include "platform/growable_array.h"
 #include "platform/hashmap.h"
 
 namespace dart {
@@ -69,7 +70,8 @@
   V(ProcessEnvironmentOption)                                                  \
   V(ProcessEnableVmServiceOption)                                              \
   V(ProcessObserveOption)                                                      \
-  V(ProcessAbiVersionOption)
+  V(ProcessAbiVersionOption)                                                   \
+  V(ProcessEnableExperimentOption)
 
 // This enum must match the strings in kSnapshotKindNames in main_options.cc.
 enum SnapshotKind {
@@ -177,6 +179,7 @@
                                     const char* default_ip);
 
   static int target_abi_version_;
+  static MallocGrowableArray<const char*> enabled_experiments_;
 
 #define OPTION_FRIEND(flag, variable) friend class OptionProcessor_##flag;
   STRING_OPTIONS_LIST(OPTION_FRIEND)
diff --git a/runtime/observatory/web/main.dart b/runtime/observatory/web/main.dart
index b09362d..dec58d7 100644
--- a/runtime/observatory/web/main.dart
+++ b/runtime/observatory/web/main.dart
@@ -7,6 +7,7 @@
 import 'package:observatory/elements.dart';
 import 'package:stack_trace/stack_trace.dart';
 
+
 main() async {
   Chain.capture(() async {
     Logger.root.level = Level.INFO;
diff --git a/runtime/tests/vm/dart/generic_check_bound_slow_path_test.dart b/runtime/tests/vm/dart/generic_check_bound_slow_path_test.dart
new file mode 100644
index 0000000..7290b2f
--- /dev/null
+++ b/runtime/tests/vm/dart/generic_check_bound_slow_path_test.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// VMOptions=--shared_slow_path_triggers_gc
+
+import 'dart:typed_data';
+
+import 'package:expect/expect.dart';
+
+Uint8List l = int.parse('1') == 1 ? Uint8List(10) : Uint8List(0);
+final int outOfRangeSmi = int.parse('-1');
+final int outOfRangeSmi2 = int.parse('10');
+final int outOfRangeMint = int.parse('${0x7fffffffffffffff}');
+final int outOfRangeMint2 = int.parse('${0x8000000000000000}');
+
+buildErrorMatcher(int outOfRangeValue) {
+  return (error) {
+    return error is RangeError &&
+        error.start == 0 &&
+        error.end == 9 &&
+        error.invalidValue == outOfRangeValue;
+  };
+}
+
+main() {
+  for (int i = 0; i < 10; ++i) l[i] = i;
+
+  Expect.throws(() => l[outOfRangeSmi], buildErrorMatcher(outOfRangeSmi));
+  Expect.throws(() => l[outOfRangeSmi2], buildErrorMatcher(outOfRangeSmi2));
+  Expect.throws(() => l[outOfRangeMint], buildErrorMatcher(outOfRangeMint));
+  Expect.throws(() => l[outOfRangeMint2], buildErrorMatcher(outOfRangeMint2));
+
+  if (int.parse('1') == 0) l = Uint8List(0);
+  for (int i = 0; i < 10; ++i) {
+    Expect.equals(i, l[i]);
+  }
+}
diff --git a/runtime/tests/vm/dart/type_casts_with_null_safety_autodetection_strong_script.dart b/runtime/tests/vm/dart/type_casts_with_null_safety_autodetection_strong_script.dart
new file mode 100644
index 0000000..0821461
--- /dev/null
+++ b/runtime/tests/vm/dart/type_casts_with_null_safety_autodetection_strong_script.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test script for type_casts_with_null_safety_autodetection_test.dart which
+// is supposed to run in strong mode because it is opted-in.
+
+import 'package:expect/expect.dart';
+
+dynamic nullObj;
+
+@pragma('vm:never-inline')
+typeCast<T>(x) => x as T;
+
+doTests() {
+  typeCast<dynamic>(nullObj);
+  typeCast<void>(nullObj);
+  Expect.throwsTypeError(() => typeCast<Object>(nullObj));
+  Expect.throwsTypeError(() => typeCast<int>(nullObj));
+  typeCast<List<int>>(<int>[]);
+  Expect.throwsTypeError(() => typeCast<List<int>>(<Null>[]));
+}
+
+main() {
+  for (int i = 0; i < 20; ++i) {
+    doTests();
+  }
+  print('OK(strong)');
+}
diff --git a/runtime/tests/vm/dart/type_casts_with_null_safety_autodetection_test.dart b/runtime/tests/vm/dart/type_casts_with_null_safety_autodetection_test.dart
new file mode 100644
index 0000000..701f409
--- /dev/null
+++ b/runtime/tests/vm/dart/type_casts_with_null_safety_autodetection_test.dart
@@ -0,0 +1,43 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// OtherResources=type_casts_with_null_safety_autodetection_strong_script.dart
+// OtherResources=type_casts_with_null_safety_autodetection_weak_script.dart
+
+// This test verifies that casts with type testing stubs work as expected
+// if null safety mode (weak/strong) is auto-detected.
+
+import 'dart:io' show File, Platform;
+
+import 'package:path/path.dart' as path;
+import 'snapshot_test_helper.dart';
+
+runTest(String script, String output, String temp) async {
+  // Need to copy test scripts out of Dart SDK to avoid hardcoded
+  // opted-in/opted-out status for Dart SDK tests.
+  final scriptInTemp = path.join(temp, script);
+  File.fromUri(Platform.script.resolve(script)).copySync(scriptInTemp);
+
+  // Do not add Platform.executableArguments into arguments to avoid passing
+  // --null-safety / --no-null-safety arguments.
+  final result = await runBinary("RUN $script", Platform.executable, [
+    '--enable-experiment=non-nullable',
+    '--deterministic',
+    '--optimization-counter-threshold=10',
+    '--packages=${Platform.packageConfig}',
+    scriptInTemp,
+  ]);
+  expectOutput(output, result);
+}
+
+main() async {
+  await withTempDir((String temp) async {
+    await runTest(
+        'type_casts_with_null_safety_autodetection_strong_script.dart',
+        'OK(strong)',
+        temp);
+    await runTest('type_casts_with_null_safety_autodetection_weak_script.dart',
+        'OK(weak)', temp);
+  });
+}
diff --git a/runtime/tests/vm/dart/type_casts_with_null_safety_autodetection_weak_script.dart b/runtime/tests/vm/dart/type_casts_with_null_safety_autodetection_weak_script.dart
new file mode 100644
index 0000000..a12eacd
--- /dev/null
+++ b/runtime/tests/vm/dart/type_casts_with_null_safety_autodetection_weak_script.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test script for type_casts_with_null_safety_autodetection_test.dart which
+// is supposed to run in weak mode because it is opted-out.
+
+// @dart=2.6
+
+import 'package:expect/expect.dart';
+
+dynamic nullObj;
+
+@pragma('vm:never-inline')
+typeCast<T>(x) => x as T;
+
+void doTests() {
+  typeCast<dynamic>(nullObj);
+  typeCast<void>(nullObj);
+  typeCast<Object>(nullObj);
+  typeCast<int>(nullObj);
+  typeCast<List<int>>(<int>[]);
+  typeCast<List<int>>(<Null>[]);
+}
+
+main() {
+  for (int i = 0; i < 20; ++i) {
+    doTests();
+  }
+  print('OK(weak)');
+}
diff --git a/runtime/tests/vm/dart/use_dwarf_stack_traces_flag_test.dart b/runtime/tests/vm/dart/use_dwarf_stack_traces_flag_test.dart
index 7a2ed6c..07a40c0 100644
--- a/runtime/tests/vm/dart/use_dwarf_stack_traces_flag_test.dart
+++ b/runtime/tests/vm/dart/use_dwarf_stack_traces_flag_test.dart
@@ -132,7 +132,16 @@
     Expect.isTrue(translatedStackFrames.length > 0);
     Expect.isTrue(originalStackFrames.length > 0);
 
-    Expect.deepEquals(translatedStackFrames, originalStackFrames);
+    // In symbolic mode, we don't store column information to avoid an increase
+    // in size of CodeStackMaps. Thus, we need to strip any columns from the
+    // translated non-symbolic stack to compare them via equality.
+    final columnStrippedTranslated = removeColumns(translatedStackFrames);
+
+    print('Stack frames from translated non-symbolic stack trace, no columns:');
+    columnStrippedTranslated.forEach(print);
+    print('');
+
+    Expect.deepEquals(columnStrippedTranslated, originalStackFrames);
 
     // Since we compiled directly to ELF, there should be a DSO base address
     // in the stack trace header and 'virt' markers in the stack frames.
@@ -175,6 +184,19 @@
   return lines.where((line) => _symbolicFrameRE.hasMatch(line));
 }
 
+final _columnsRE = RegExp(r'[(](.*:\d+):\d+[)]');
+
+Iterable<String> removeColumns(Iterable<String> lines) sync* {
+  for (final line in lines) {
+    final match = _columnsRE.firstMatch(line);
+    if (match != null) {
+      yield line.replaceRange(match.start, match.end, '(${match.group(1)!})');
+    } else {
+      yield line;
+    }
+  }
+}
+
 Iterable<int> parseUsingAddressRegExp(RegExp re, Iterable<String> lines) sync* {
   for (final line in lines) {
     final match = re.firstMatch(line);
diff --git a/runtime/tests/vm/dart/v8_snapshot_profile_writer_test.dart b/runtime/tests/vm/dart/v8_snapshot_profile_writer_test.dart
index ea385af..7ef3be5 100644
--- a/runtime/tests/vm/dart/v8_snapshot_profile_writer_test.dart
+++ b/runtime/tests/vm/dart/v8_snapshot_profile_writer_test.dart
@@ -2,12 +2,12 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import "dart:convert";
-import "dart:io";
+import 'dart:convert';
+import 'dart:io';
 
-import "package:expect/expect.dart";
+import 'package:expect/expect.dart';
 import 'package:path/path.dart' as path;
-import "package:vm/v8_snapshot_profile.dart";
+import 'package:vm_snapshot_analysis/v8_profile.dart';
 
 import 'use_flag_test_helper.dart';
 
@@ -77,32 +77,52 @@
       strippedPath = snapshotPath;
     }
 
-    final V8SnapshotProfile profile = V8SnapshotProfile.fromJson(
-        JsonDecoder().convert(File(profilePath).readAsStringSync()));
+    final profile =
+        Snapshot.fromJson(jsonDecode(File(profilePath).readAsStringSync()));
 
     // Verify that there are no "unknown" nodes. These are emitted when we see a
     // reference to an some object but no other metadata about the object was
     // recorded. We should at least record the type for every object in the
     // graph (in some cases the shallow size can legitimately be 0, e.g. for
     // "base objects").
-    for (final int node in profile.nodes) {
-      Expect.notEquals("Unknown", profile[node].type,
-          "unknown node at ID ${profile[node].id}");
+    for (final node in profile.nodes) {
+      Expect.notEquals("Unknown", node.type, "unknown node at ID ${node.id}");
     }
 
-    // Verify that all nodes are reachable from the declared roots.
-    int unreachableNodes = 0;
-    Set<int> nodesReachableFromRoots = profile.preOrder(profile.root).toSet();
-    for (final int node in profile.nodes) {
-      Expect.isTrue(nodesReachableFromRoots.contains(node),
-          "unreachable node at ID ${profile[node].id}");
+    // HeapSnapshotWorker.HeapSnapshot.calculateDistances (from HeapSnapshot.js)
+    // assumes that the root does not have more than one edge to any other node
+    // (most likely an oversight).
+    final Set<int> roots = <int>{};
+    for (final edge in profile.nodeAt(0).edges) {
+      Expect.isTrue(roots.add(edge.target.index));
+    }
+
+    // Check that all nodes are reachable from the root (index 0).
+    final Set<int> reachable = {0};
+    final dfs = <int>[0];
+    while (!dfs.isEmpty) {
+      final next = dfs.removeLast();
+      for (final edge in profile.nodeAt(next).edges) {
+        final target = edge.target;
+        if (!reachable.contains(target.index)) {
+          reachable.add(target.index);
+          dfs.add(target.index);
+        }
+      }
+    }
+
+    if (reachable.length != profile.nodeCount) {
+      for (final node in profile.nodes) {
+        Expect.isTrue(reachable.contains(node.index),
+            "unreachable node at ID ${node.id}");
+      }
     }
 
     // Verify that the actual size of the snapshot is close to the sum of the
     // shallow sizes of all objects in the profile. They will not be exactly
     // equal because of global headers and padding.
     final actual = await File(strippedPath).length();
-    final expected = profile.accountedBytes;
+    final expected = profile.nodes.fold<int>(0, (size, n) => size + n.selfSize);
 
     final bareUsed = useBare ? "bare" : "non-bare";
     final fileType = useAsm ? "assembly" : "ELF";
diff --git a/runtime/tests/vm/dart_2/generic_check_bound_slow_path_test.dart b/runtime/tests/vm/dart_2/generic_check_bound_slow_path_test.dart
new file mode 100644
index 0000000..7290b2f
--- /dev/null
+++ b/runtime/tests/vm/dart_2/generic_check_bound_slow_path_test.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// VMOptions=--shared_slow_path_triggers_gc
+
+import 'dart:typed_data';
+
+import 'package:expect/expect.dart';
+
+Uint8List l = int.parse('1') == 1 ? Uint8List(10) : Uint8List(0);
+final int outOfRangeSmi = int.parse('-1');
+final int outOfRangeSmi2 = int.parse('10');
+final int outOfRangeMint = int.parse('${0x7fffffffffffffff}');
+final int outOfRangeMint2 = int.parse('${0x8000000000000000}');
+
+buildErrorMatcher(int outOfRangeValue) {
+  return (error) {
+    return error is RangeError &&
+        error.start == 0 &&
+        error.end == 9 &&
+        error.invalidValue == outOfRangeValue;
+  };
+}
+
+main() {
+  for (int i = 0; i < 10; ++i) l[i] = i;
+
+  Expect.throws(() => l[outOfRangeSmi], buildErrorMatcher(outOfRangeSmi));
+  Expect.throws(() => l[outOfRangeSmi2], buildErrorMatcher(outOfRangeSmi2));
+  Expect.throws(() => l[outOfRangeMint], buildErrorMatcher(outOfRangeMint));
+  Expect.throws(() => l[outOfRangeMint2], buildErrorMatcher(outOfRangeMint2));
+
+  if (int.parse('1') == 0) l = Uint8List(0);
+  for (int i = 0; i < 10; ++i) {
+    Expect.equals(i, l[i]);
+  }
+}
diff --git a/runtime/tests/vm/dart_2/use_dwarf_stack_traces_flag_test.dart b/runtime/tests/vm/dart_2/use_dwarf_stack_traces_flag_test.dart
index c67b5ef..40aa94a 100644
--- a/runtime/tests/vm/dart_2/use_dwarf_stack_traces_flag_test.dart
+++ b/runtime/tests/vm/dart_2/use_dwarf_stack_traces_flag_test.dart
@@ -132,7 +132,16 @@
     Expect.isTrue(translatedStackFrames.length > 0);
     Expect.isTrue(originalStackFrames.length > 0);
 
-    Expect.deepEquals(translatedStackFrames, originalStackFrames);
+    // In symbolic mode, we don't store column information to avoid an increase
+    // in size of CodeStackMaps. Thus, we need to strip any columns from the
+    // translated non-symbolic stack to compare them via equality.
+    final columnStrippedTranslated = removeColumns(translatedStackFrames);
+
+    print('Stack frames from translated non-symbolic stack trace, no columns:');
+    columnStrippedTranslated.forEach(print);
+    print('');
+
+    Expect.deepEquals(columnStrippedTranslated, originalStackFrames);
 
     // Since we compiled directly to ELF, there should be a DSO base address
     // in the stack trace header and 'virt' markers in the stack frames.
@@ -175,6 +184,19 @@
   return lines.where((line) => _symbolicFrameRE.hasMatch(line));
 }
 
+final _columnsRE = RegExp(r'[(](.*:\d+):\d+[)]');
+
+Iterable<String> removeColumns(Iterable<String> lines) sync* {
+  for (final line in lines) {
+    final match = _columnsRE.firstMatch(line);
+    if (match != null) {
+      yield line.replaceRange(match.start, match.end, '(${match.group(1)})');
+    } else {
+      yield line;
+    }
+  }
+}
+
 Iterable<int> parseUsingAddressRegExp(RegExp re, Iterable<String> lines) sync* {
   for (final line in lines) {
     final match = re.firstMatch(line);
diff --git a/runtime/tests/vm/dart_2/v8_snapshot_profile_writer_test.dart b/runtime/tests/vm/dart_2/v8_snapshot_profile_writer_test.dart
index de5facf..8778573 100644
--- a/runtime/tests/vm/dart_2/v8_snapshot_profile_writer_test.dart
+++ b/runtime/tests/vm/dart_2/v8_snapshot_profile_writer_test.dart
@@ -2,12 +2,12 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import "dart:convert";
-import "dart:io";
+import 'dart:convert';
+import 'dart:io';
 
-import "package:expect/expect.dart";
+import 'package:expect/expect.dart';
 import 'package:path/path.dart' as path;
-import "package:vm/v8_snapshot_profile.dart";
+import 'package:vm_snapshot_analysis/v8_profile.dart';
 
 import 'use_flag_test_helper.dart';
 
@@ -77,32 +77,52 @@
       strippedPath = snapshotPath;
     }
 
-    final V8SnapshotProfile profile = V8SnapshotProfile.fromJson(
-        JsonDecoder().convert(File(profilePath).readAsStringSync()));
+    final profile =
+        Snapshot.fromJson(jsonDecode(File(profilePath).readAsStringSync()));
 
     // Verify that there are no "unknown" nodes. These are emitted when we see a
     // reference to an some object but no other metadata about the object was
     // recorded. We should at least record the type for every object in the
     // graph (in some cases the shallow size can legitimately be 0, e.g. for
     // "base objects").
-    for (final int node in profile.nodes) {
-      Expect.notEquals("Unknown", profile[node].type,
-          "unknown node at ID ${profile[node].id}");
+    for (final node in profile.nodes) {
+      Expect.notEquals("Unknown", node.type, "unknown node at ID ${node.id}");
     }
 
-    // Verify that all nodes are reachable from the declared roots.
-    int unreachableNodes = 0;
-    Set<int> nodesReachableFromRoots = profile.preOrder(profile.root).toSet();
-    for (final int node in profile.nodes) {
-      Expect.isTrue(nodesReachableFromRoots.contains(node),
-          "unreachable node at ID ${profile[node].id}");
+    // HeapSnapshotWorker.HeapSnapshot.calculateDistances (from HeapSnapshot.js)
+    // assumes that the root does not have more than one edge to any other node
+    // (most likely an oversight).
+    final Set<int> roots = <int>{};
+    for (final edge in profile.nodeAt(0).edges) {
+      Expect.isTrue(roots.add(edge.target.index));
+    }
+
+    // Check that all nodes are reachable from the root (index 0).
+    final Set<int> reachable = {0};
+    final dfs = <int>[0];
+    while (!dfs.isEmpty) {
+      final next = dfs.removeLast();
+      for (final edge in profile.nodeAt(next).edges) {
+        final target = edge.target;
+        if (!reachable.contains(target.index)) {
+          reachable.add(target.index);
+          dfs.add(target.index);
+        }
+      }
+    }
+
+    if (reachable.length != profile.nodeCount) {
+      for (final node in profile.nodes) {
+        Expect.isTrue(reachable.contains(node.index),
+            "unreachable node at ID ${node.id}");
+      }
     }
 
     // Verify that the actual size of the snapshot is close to the sum of the
     // shallow sizes of all objects in the profile. They will not be exactly
     // equal because of global headers and padding.
     final actual = await File(strippedPath).length();
-    final expected = profile.accountedBytes;
+    final expected = profile.nodes.fold<int>(0, (size, n) => size + n.selfSize);
 
     final bareUsed = useBare ? "bare" : "non-bare";
     final fileType = useAsm ? "assembly" : "ELF";
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index c8912f5..72ce9c8 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -248,6 +248,7 @@
 dart/minimal_kernel_test: SkipByDesign # Test needs to run from source
 dart/null_safety_autodetection_in_kernel_compiler_test: SkipByDesign # Test needs to run from source
 dart/snapshot_depfile_test: SkipByDesign # Test needs to run from source
+dart/type_casts_with_null_safety_autodetection_test: SkipByDesign # Test needs to run from source
 dart_2/appjit*: SkipByDesign # Test needs to run from source
 dart_2/bytecode_and_ast_mix_test: SkipByDesign # Test needs to run from source
 dart_2/kernel_determinism_test: SkipByDesign # Test needs to run from source
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index f3ca74d..4bd04c8 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -6713,6 +6713,21 @@
 #undef CHECK_FLAG
 #undef SET_FLAG
 
+#if defined(DART_PRECOMPILED_RUNTIME)
+    if (FLAG_null_safety == kNullSafetyOptionUnspecified) {
+      if (strncmp(cursor, "null-safety", end - cursor) == 0) {
+        FLAG_null_safety = kNullSafetyOptionStrong;
+        cursor = end;
+        continue;
+      }
+      if (strncmp(cursor, "no-null-safety", end - cursor) == 0) {
+        FLAG_null_safety = kNullSafetyOptionWeak;
+        cursor = end;
+        continue;
+      }
+    }
+#endif  // defined(DART_PRECOMPILED_RUNTIME)
+
     cursor = end;
   }
 
diff --git a/runtime/vm/code_descriptors.cc b/runtime/vm/code_descriptors.cc
index 1a5a5f2..aaaa159 100644
--- a/runtime/vm/code_descriptors.cc
+++ b/runtime/vm/code_descriptors.cc
@@ -573,18 +573,32 @@
 
 void CodeSourceMapBuilder::WriteChangePosition(TokenPosition pos) {
   stream_.Write<uint8_t>(kChangePosition);
+  intptr_t position_or_line = pos.value();
+#if defined(DART_PRECOMPILER)
+  intptr_t column = TokenPosition::kNoSourcePos;
   if (FLAG_precompiled_mode) {
-    intptr_t line = -1;
+    // Don't use the raw position value directly in precompiled mode. Instead,
+    // use the value of kNoSource as a fallback when no line or column
+    // information is found.
+    position_or_line = TokenPosition::kNoSourcePos;
     intptr_t inline_id = buffered_inline_id_stack_.Last();
     if (inline_id < inline_id_to_function_.length()) {
       const Function* function = inline_id_to_function_[inline_id];
       Script& script = Script::Handle(function->script());
-      line = script.GetTokenLineUsingLineStarts(pos.SourcePosition());
+      script.GetTokenLocationUsingLineStarts(pos.SourcePosition(),
+                                             &position_or_line, &column);
     }
-    stream_.Write<int32_t>(static_cast<int32_t>(line));
-  } else {
-    stream_.Write<int32_t>(static_cast<int32_t>(pos.value()));
   }
+#endif
+  stream_.Write<int32_t>(position_or_line);
+#if defined(DART_PRECOMPILER)
+  // For non-symbolic stack traces, the CodeSourceMaps are not serialized,
+  // so we need not worry about increasing snapshot size by including more
+  // information here.
+  if (FLAG_dwarf_stack_traces_mode) {
+    stream_.Write<int32_t>(column);
+  }
+#endif
   written_token_pos_stack_.Last() = pos;
 }
 
@@ -606,9 +620,8 @@
     uint8_t opcode = stream.Read<uint8_t>();
     switch (opcode) {
       case CodeSourceMapBuilder::kChangePosition: {
-        int32_t position = stream.Read<int32_t>();
         (*token_positions)[token_positions->length() - 1] =
-            TokenPosition(position);
+            ReadPosition(&stream);
         break;
       }
       case CodeSourceMapBuilder::kAdvancePC: {
@@ -668,7 +681,7 @@
     uint8_t opcode = stream.Read<uint8_t>();
     switch (opcode) {
       case CodeSourceMapBuilder::kChangePosition: {
-        stream.Read<int32_t>();
+        ReadPosition(&stream);
         break;
       }
       case CodeSourceMapBuilder::kAdvancePC: {
@@ -721,7 +734,7 @@
     uint8_t opcode = stream.Read<uint8_t>();
     switch (opcode) {
       case CodeSourceMapBuilder::kChangePosition: {
-        stream.Read<int32_t>();
+        ReadPosition(&stream);
         break;
       }
       case CodeSourceMapBuilder::kAdvancePC: {
@@ -775,8 +788,7 @@
     uint8_t opcode = stream.Read<uint8_t>();
     switch (opcode) {
       case CodeSourceMapBuilder::kChangePosition: {
-        int32_t position = stream.Read<int32_t>();
-        token_positions[token_positions.length() - 1] = TokenPosition(position);
+        token_positions[token_positions.length() - 1] = ReadPosition(&stream);
         break;
       }
       case CodeSourceMapBuilder::kAdvancePC: {
@@ -830,7 +842,7 @@
     uint8_t opcode = stream.Read<uint8_t>();
     switch (opcode) {
       case CodeSourceMapBuilder::kChangePosition: {
-        stream.Read<int32_t>();
+        ReadPosition(&stream);
         break;
       }
       case CodeSourceMapBuilder::kAdvancePC: {
@@ -862,4 +874,17 @@
   return -1;
 }
 
+TokenPosition CodeSourceMapReader::ReadPosition(ReadStream* stream) {
+  const intptr_t line = stream->Read<int32_t>();
+#if defined(DART_PRECOMPILER)
+  // The special handling for non-symbolic stack trace mode only needs to
+  // happen in the precompiler, because those CSMs are not serialized in
+  // precompiled snapshots.
+  if (FLAG_dwarf_stack_traces_mode) {
+    stream->Read<int32_t>();  // Discard the column information.
+  }
+#endif
+  return TokenPosition(line);
+}
+
 }  // namespace dart
diff --git a/runtime/vm/code_descriptors.h b/runtime/vm/code_descriptors.h
index 4ad6723..8b74bde 100644
--- a/runtime/vm/code_descriptors.h
+++ b/runtime/vm/code_descriptors.h
@@ -359,6 +359,10 @@
   intptr_t GetNullCheckNameIndexAt(int32_t pc_offset);
 
  private:
+  // Reads a TokenPosition value from a CSM, handling the different encoding for
+  // when non-symbolic stack traces are enabled.
+  static TokenPosition ReadPosition(ReadStream* stream);
+
   const CodeSourceMap& map_;
   const Array& functions_;
   const Function& root_;
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index dc254d4..a7565cd 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -861,15 +861,16 @@
 
 intptr_t CheckClassInstr::ComputeCidMask() const {
   ASSERT(IsBitTest());
+  const uintptr_t one = 1;
   intptr_t min = cids_.ComputeLowestCid();
   intptr_t mask = 0;
   for (intptr_t i = 0; i < cids_.length(); ++i) {
-    intptr_t run;
-    uintptr_t range = 1ul + cids_[i].Extent();
+    uintptr_t run;
+    uintptr_t range = one + cids_[i].Extent();
     if (range >= static_cast<uintptr_t>(compiler::target::kBitsPerWord)) {
       run = -1;
     } else {
-      run = (1 << range) - 1;
+      run = (one << range) - 1;
     }
     mask |= run << (cids_[i].cid_start - min);
   }
@@ -1522,7 +1523,9 @@
 bool Instruction::HasUnmatchedInputRepresentations() const {
   for (intptr_t i = 0; i < InputCount(); i++) {
     Definition* input = InputAt(i)->definition();
-    if (RequiredInputRepresentation(i) != input->representation()) {
+    const Representation input_representation = RequiredInputRepresentation(i);
+    if (input_representation != kNoRepresentation &&
+        input_representation != input->representation()) {
       return true;
     }
   }
@@ -5150,6 +5153,9 @@
 }
 
 void GenericCheckBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(representation() == RequiredInputRepresentation(kIndexPos));
+  ASSERT(representation() == RequiredInputRepresentation(kLengthPos));
+
   RangeErrorSlowPath* slow_path =
       new RangeErrorSlowPath(this, compiler->CurrentTryIndex());
   compiler->AddSlowPathCode(slow_path);
@@ -5158,8 +5164,15 @@
   Register length = length_loc.reg();
   Register index = index_loc.reg();
   const intptr_t index_cid = this->index()->Type()->ToCid();
-  if (index_cid != kSmiCid) {
-    __ BranchIfNotSmi(index, slow_path->entry_label());
+
+  // The length comes from one of our variable-sized heap objects (e.g. typed
+  // data array) and is therefore guaranteed to be in the positive Smi range.
+  if (representation() == kTagged) {
+    if (index_cid != kSmiCid) {
+      __ BranchIfNotSmi(index, slow_path->entry_label());
+    }
+  } else {
+    ASSERT(representation() == kUnboxedInt64);
   }
   __ CompareRegisters(index, length);
   __ BranchIf(UNSIGNED_GREATER_EQUAL, slow_path->entry_label());
@@ -5714,6 +5727,22 @@
   SetInputAt(1, index);
 }
 
+Definition* LoadIndexedInstr::Canonicalize(FlowGraph* flow_graph) {
+  auto Z = flow_graph->zone();
+  if (auto box = index()->definition()->AsBoxInt64()) {
+    // TODO(dartbug.com/39432): Make LoadIndexed fully suport unboxed indices.
+    if (!box->ComputeCanDeoptimize() && compiler::target::kWordSize == 8) {
+      auto load = new (Z) LoadIndexedInstr(
+          array()->CopyWithType(Z), box->value()->CopyWithType(Z),
+          /*index_unboxed=*/true, index_scale(), class_id(), alignment_,
+          GetDeoptId(), token_pos(), result_type_);
+      flow_graph->InsertBefore(this, load, env(), FlowGraph::kValue);
+      return load;
+    }
+  }
+  return this;
+}
+
 StoreIndexedInstr::StoreIndexedInstr(Value* array,
                                      Value* index,
                                      Value* value,
@@ -5738,6 +5767,23 @@
   SetInputAt(kValuePos, value);
 }
 
+Instruction* StoreIndexedInstr::Canonicalize(FlowGraph* flow_graph) {
+  auto Z = flow_graph->zone();
+  if (auto box = index()->definition()->AsBoxInt64()) {
+    // TODO(dartbug.com/39432): Make StoreIndexed fully suport unboxed indices.
+    if (!box->ComputeCanDeoptimize() && compiler::target::kWordSize == 8) {
+      auto store = new (Z) StoreIndexedInstr(
+          array()->CopyWithType(Z), box->value()->CopyWithType(Z),
+          value()->CopyWithType(Z), emit_store_barrier_,
+          /*index_unboxed=*/true, index_scale(), class_id(), alignment_,
+          GetDeoptId(), token_pos(), speculative_mode_);
+      flow_graph->InsertBefore(this, store, env(), FlowGraph::kEffect);
+      return nullptr;
+    }
+  }
+  return this;
+}
+
 bool Utf8ScanInstr::IsScanFlagsUnboxed() const {
   return FlowGraphCompiler::IsUnboxedField(scan_flags_field_.field());
 }
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index 833b344..1d28f31 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -5564,6 +5564,8 @@
 
   virtual bool HasUnknownSideEffects() const { return false; }
 
+  virtual Definition* Canonicalize(FlowGraph* flow_graph);
+
   ADD_EXTRA_INFO_TO_S_EXPRESSION_SUPPORT
 
  private:
@@ -5864,6 +5866,8 @@
 
   void PrintOperandsTo(BufferFormatter* f) const;
 
+  virtual Instruction* Canonicalize(FlowGraph* flow_graph);
+
   ADD_EXTRA_INFO_TO_S_EXPRESSION_SUPPORT
 
  private:
@@ -8697,6 +8701,12 @@
 // or otherwise throws an out-of-bounds exception (viz. non-speculative).
 class GenericCheckBoundInstr : public CheckBoundBase {
  public:
+  // We prefer to have unboxed inputs on 64-bit where values can fit into a
+  // register.
+  static bool UseUnboxedRepresentation() {
+    return compiler::target::kWordSize == 8;
+  }
+
   GenericCheckBoundInstr(Value* length, Value* index, intptr_t deopt_id)
       : CheckBoundBase(length, index, deopt_id) {}
 
@@ -8707,6 +8717,21 @@
   virtual CompileType ComputeType() const;
   virtual bool RecomputeType();
 
+  virtual intptr_t DeoptimizationTarget() const { return DeoptId::kNone; }
+
+  virtual SpeculativeMode SpeculativeModeOfInput(intptr_t index) const {
+    return kNotSpeculative;
+  }
+
+  virtual Representation representation() const {
+    return UseUnboxedRepresentation() ? kUnboxedInt64 : kTagged;
+  }
+
+  virtual Representation RequiredInputRepresentation(intptr_t idx) const {
+    ASSERT(idx == kIndexPos || idx == kLengthPos);
+    return UseUnboxedRepresentation() ? kUnboxedInt64 : kTagged;
+  }
+
   // GenericCheckBound can implicitly call Dart code (RangeError or
   // ArgumentError constructor), so it can lazily deopt.
   virtual bool ComputeCanDeoptimize() const {
diff --git a/runtime/vm/compiler/backend/il_test_helper.cc b/runtime/vm/compiler/backend/il_test_helper.cc
index 316025e..9c5788a 100644
--- a/runtime/vm/compiler/backend/il_test_helper.cc
+++ b/runtime/vm/compiler/backend/il_test_helper.cc
@@ -234,6 +234,11 @@
   Instruction* cursor = cursor_;
   for (size_t i = 0; i < qcodes.size(); ++i) {
     Instruction** capture = qcodes[i].capture_;
+    if (parallel_moves_handling_ == ParallelMovesHandling::kSkip) {
+      while (cursor->IsParallelMove()) {
+        cursor = cursor->next();
+      }
+    }
     if (trace_) {
       OS::PrintErr("  matching %30s @ %s\n",
                    MatchOpCodeToCString(qcodes[i].opcode()),
@@ -274,6 +279,9 @@
     if (branch == nullptr) return nullptr;
     return branch->false_successor();
   }
+  if (opcode == kNop) {
+    return cursor;
+  }
   if (opcode == kMoveAny) {
     return cursor->next();
   }
@@ -342,6 +350,9 @@
   if (opcode == kMatchAndMoveBranchFalse) {
     return "kMatchAndMoveBranchFalse";
   }
+  if (opcode == kNop) {
+    return "kNop";
+  }
   if (opcode == kMoveAny) {
     return "kMoveAny";
   }
diff --git a/runtime/vm/compiler/backend/il_test_helper.h b/runtime/vm/compiler/backend/il_test_helper.h
index 903b94a..ec00bb7 100644
--- a/runtime/vm/compiler/backend/il_test_helper.h
+++ b/runtime/vm/compiler/backend/il_test_helper.h
@@ -110,6 +110,9 @@
   // Matches a branch and moves right.
   kMatchAndMoveBranchFalse,
 
+  // Is ignored.
+  kNop,
+
   // Moves forward across any instruction.
   kMoveAny,
 
@@ -150,6 +153,16 @@
   Instruction** capture_;
 };
 
+enum class ParallelMovesHandling {
+  // Matcher doesn't do anything special with ParallelMove instructions.
+  kDefault,
+  // All ParallelMove instructions are skipped.
+  // This mode is useful when matching a flow graph after the whole
+  // compiler pipeline, as it may have ParallelMove instructions
+  // at arbitrary architecture-dependent places.
+  kSkip,
+};
+
 // Used for matching a sequence of IL instructions including capturing support.
 //
 // Example:
@@ -170,9 +183,14 @@
 // value for the cursor.
 class ILMatcher : public ValueObject {
  public:
-  ILMatcher(FlowGraph* flow_graph, Instruction* cursor, bool trace = true)
+  ILMatcher(FlowGraph* flow_graph,
+            Instruction* cursor,
+            bool trace = true,
+            ParallelMovesHandling parallel_moves_handling =
+                ParallelMovesHandling::kDefault)
       : flow_graph_(flow_graph),
         cursor_(cursor),
+        parallel_moves_handling_(parallel_moves_handling),
   // clang-format off
 #if !defined(PRODUCT)
         trace_(trace) {}
@@ -202,6 +220,7 @@
 
   FlowGraph* flow_graph_;
   Instruction* cursor_;
+  ParallelMovesHandling parallel_moves_handling_;
   bool trace_;
 };
 
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index 449cfbd..88915ae 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -1617,19 +1617,17 @@
   LocationSummary* locs = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
   locs->set_in(0, Location::RequiresRegister());
-  // The smi index is either untagged (element size == 1), or it is left smi
-  // tagged (for all element sizes > 1).
-  if (index_scale() == 1) {
-    locs->set_in(1,
-                 CanBeImmediateIndex(index(), class_id())
-                     ? Location::Constant(index()->definition()->AsConstant())
-                     : Location::WritableRegister());
-  } else {
-    locs->set_in(1,
-                 CanBeImmediateIndex(index(), class_id())
-                     ? Location::Constant(index()->definition()->AsConstant())
-                     : Location::RequiresRegister());
-  }
+  // For tagged index with index_scale=1 as well as untagged index with
+  // index_scale=16 we need a writable register due to assdressing mode
+  // restrictions on X64.
+  const bool need_writable_index_register =
+      (index_scale() == 1 && !index_unboxed_) ||
+      (index_scale() == 16 && index_unboxed_);
+  locs->set_in(
+      1, CanBeImmediateIndex(index(), class_id())
+             ? Location::Constant(index()->definition()->AsConstant())
+             : (need_writable_index_register ? Location::WritableRegister()
+                                             : Location::RequiresRegister()));
   if ((representation() == kUnboxedDouble) ||
       (representation() == kUnboxedFloat32x4) ||
       (representation() == kUnboxedInt32x4) ||
@@ -1646,22 +1644,27 @@
   const Register array = locs()->in(0).reg();
   const Location index = locs()->in(1);
 
+  intptr_t index_scale = index_scale_;
+  if (index.IsRegister()) {
+    if (index_scale == 1 && !index_unboxed_) {
+      __ SmiUntag(index.reg());
+    } else if (index_scale == 16 && index_unboxed_) {
+      // X64 does not support addressing mode using TIMES_16.
+      __ SmiTag(index.reg());
+      index_scale >>= 1;
+    }
+  } else {
+    ASSERT(index.IsConstant());
+  }
+
   compiler::Address element_address =
       index.IsRegister() ? compiler::Assembler::ElementAddressForRegIndex(
-                               IsExternal(), class_id(), index_scale(),
+                               IsExternal(), class_id(), index_scale,
                                index_unboxed_, array, index.reg())
                          : compiler::Assembler::ElementAddressForIntIndex(
-                               IsExternal(), class_id(), index_scale(), array,
+                               IsExternal(), class_id(), index_scale, array,
                                Smi::Cast(index.constant()).Value());
 
-  if (index_scale() == 1 && !index_unboxed_) {
-    if (index.IsRegister()) {
-      __ SmiUntag(index.reg());
-    } else {
-      ASSERT(index.IsConstant());
-    }
-  }
-
   if (representation() == kUnboxedDouble ||
       representation() == kUnboxedFloat32x4 ||
       representation() == kUnboxedInt32x4 ||
@@ -1848,19 +1851,17 @@
   LocationSummary* locs = new (zone)
       LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
   locs->set_in(0, Location::RequiresRegister());
-  // The smi index is either untagged (element size == 1), or it is left smi
-  // tagged (for all element sizes > 1).
-  if (index_scale() == 1) {
-    locs->set_in(1,
-                 CanBeImmediateIndex(index(), class_id())
-                     ? Location::Constant(index()->definition()->AsConstant())
-                     : Location::WritableRegister());
-  } else {
-    locs->set_in(1,
-                 CanBeImmediateIndex(index(), class_id())
-                     ? Location::Constant(index()->definition()->AsConstant())
-                     : Location::RequiresRegister());
-  }
+  // For tagged index with index_scale=1 as well as untagged index with
+  // index_scale=16 we need a writable register due to assdressing mode
+  // restrictions on X64.
+  const bool need_writable_index_register =
+      (index_scale() == 1 && !index_unboxed_) ||
+      (index_scale() == 16 && index_unboxed_);
+  locs->set_in(
+      1, CanBeImmediateIndex(index(), class_id())
+             ? Location::Constant(index()->definition()->AsConstant())
+             : (need_writable_index_register ? Location::WritableRegister()
+                                             : Location::RequiresRegister()));
   switch (class_id()) {
     case kArrayCid:
       locs->set_in(2, ShouldEmitStoreBarrier()
@@ -1915,17 +1916,27 @@
   const Register array = locs()->in(0).reg();
   const Location index = locs()->in(1);
 
+  intptr_t index_scale = index_scale_;
+  if (index.IsRegister()) {
+    if (index_scale == 1 && !index_unboxed_) {
+      __ SmiUntag(index.reg());
+    } else if (index_scale == 16 && index_unboxed_) {
+      // X64 does not support addressing mode using TIMES_16.
+      __ SmiTag(index.reg());
+      index_scale >>= 1;
+    }
+  } else {
+    ASSERT(index.IsConstant());
+  }
+
   compiler::Address element_address =
       index.IsRegister() ? compiler::Assembler::ElementAddressForRegIndex(
-                               IsExternal(), class_id(), index_scale(),
+                               IsExternal(), class_id(), index_scale,
                                index_unboxed_, array, index.reg())
                          : compiler::Assembler::ElementAddressForIntIndex(
-                               IsExternal(), class_id(), index_scale(), array,
+                               IsExternal(), class_id(), index_scale, array,
                                Smi::Cast(index.constant()).Value());
 
-  if ((index_scale() == 1) && index.IsRegister() && !index_unboxed_) {
-    __ SmiUntag(index.reg());
-  }
   switch (class_id()) {
     case kArrayCid:
       if (ShouldEmitStoreBarrier()) {
diff --git a/runtime/vm/compiler/backend/inliner.cc b/runtime/vm/compiler/backend/inliner.cc
index 25c3e44..4b47da7 100644
--- a/runtime/vm/compiler/backend/inliner.cc
+++ b/runtime/vm/compiler/backend/inliner.cc
@@ -2436,6 +2436,8 @@
 }
 
 static bool InlineGetIndexed(FlowGraph* flow_graph,
+                             bool can_speculate,
+                             bool is_dynamic_call,
                              MethodRecognizer::Kind kind,
                              Definition* call,
                              Definition* receiver,
@@ -2447,6 +2449,11 @@
 
   Definition* array = receiver;
   Definition* index = call->ArgumentAt(1);
+
+  if (!can_speculate && is_dynamic_call && !index->Type()->IsInt()) {
+    return false;
+  }
+
   *entry =
       new (Z) FunctionEntryInstr(graph_entry, flow_graph->allocate_block_id(),
                                  call->GetBlock()->try_index(), DeoptId::kNone);
@@ -3401,6 +3408,7 @@
 }
 
 static bool InlineSimdOp(FlowGraph* flow_graph,
+                         bool is_dynamic_call,
                          Instruction* call,
                          Definition* receiver,
                          MethodRecognizer::Kind kind,
@@ -3411,13 +3419,6 @@
   if (!ShouldInlineSimd()) {
     return false;
   }
-  bool is_dynamic_call = false;
-  if (auto instance_call = call->AsInstanceCallBase()) {
-    is_dynamic_call = Function::IsDynamicInvocationForwarderName(
-        instance_call->function_name());
-  } else if (auto static_call = call->AsStaticCall()) {
-    is_dynamic_call = static_call->function().IsDynamicInvocationForwarder();
-  }
   if (is_dynamic_call && call->ArgumentCount() > 1) {
     // Issue(dartbug.com/37737): Dynamic invocation forwarders have the
     // same recognized kind as the method they are forwarding to.
@@ -3666,6 +3667,8 @@
   }
 
   const bool can_speculate = policy->IsAllowedForInlining(call->deopt_id());
+  const bool is_dynamic_call = Function::IsDynamicInvocationForwarderName(
+      String::Handle(flow_graph->zone(), target.name()));
 
   const MethodRecognizer::Kind kind = target.recognized_kind();
   switch (kind) {
@@ -3680,36 +3683,36 @@
     case MethodRecognizer::kExternalUint8ClampedArrayGetIndexed:
     case MethodRecognizer::kInt16ArrayGetIndexed:
     case MethodRecognizer::kUint16ArrayGetIndexed:
-      return InlineGetIndexed(flow_graph, kind, call, receiver, graph_entry,
-                              entry, last, result);
+      return InlineGetIndexed(flow_graph, can_speculate, is_dynamic_call, kind,
+                              call, receiver, graph_entry, entry, last, result);
     case MethodRecognizer::kFloat32ArrayGetIndexed:
     case MethodRecognizer::kFloat64ArrayGetIndexed:
       if (!CanUnboxDouble()) {
         return false;
       }
-      return InlineGetIndexed(flow_graph, kind, call, receiver, graph_entry,
-                              entry, last, result);
+      return InlineGetIndexed(flow_graph, can_speculate, is_dynamic_call, kind,
+                              call, receiver, graph_entry, entry, last, result);
     case MethodRecognizer::kFloat32x4ArrayGetIndexed:
     case MethodRecognizer::kFloat64x2ArrayGetIndexed:
       if (!ShouldInlineSimd()) {
         return false;
       }
-      return InlineGetIndexed(flow_graph, kind, call, receiver, graph_entry,
-                              entry, last, result);
+      return InlineGetIndexed(flow_graph, can_speculate, is_dynamic_call, kind,
+                              call, receiver, graph_entry, entry, last, result);
     case MethodRecognizer::kInt32ArrayGetIndexed:
     case MethodRecognizer::kUint32ArrayGetIndexed:
       if (!CanUnboxInt32()) {
         return false;
       }
-      return InlineGetIndexed(flow_graph, kind, call, receiver, graph_entry,
-                              entry, last, result);
+      return InlineGetIndexed(flow_graph, can_speculate, is_dynamic_call, kind,
+                              call, receiver, graph_entry, entry, last, result);
     case MethodRecognizer::kInt64ArrayGetIndexed:
     case MethodRecognizer::kUint64ArrayGetIndexed:
       if (!ShouldInlineInt64ArrayOps()) {
         return false;
       }
-      return InlineGetIndexed(flow_graph, kind, call, receiver, graph_entry,
-                              entry, last, result);
+      return InlineGetIndexed(flow_graph, can_speculate, is_dynamic_call, kind,
+                              call, receiver, graph_entry, entry, last, result);
     case MethodRecognizer::kClassIDgetID:
       return InlineLoadClassId(flow_graph, call, graph_entry, entry, last,
                                result);
@@ -4040,8 +4043,8 @@
     case MethodRecognizer::kFloat64x2Div:
     case MethodRecognizer::kFloat64x2Add:
     case MethodRecognizer::kFloat64x2Sub:
-      return InlineSimdOp(flow_graph, call, receiver, kind, graph_entry, entry,
-                          last, result);
+      return InlineSimdOp(flow_graph, is_dynamic_call, call, receiver, kind,
+                          graph_entry, entry, last, result);
 
     case MethodRecognizer::kMathSqrt:
     case MethodRecognizer::kMathDoublePow:
diff --git a/runtime/vm/compiler/backend/inliner_test.cc b/runtime/vm/compiler/backend/inliner_test.cc
index 87e8029..2db1229 100644
--- a/runtime/vm/compiler/backend/inliner_test.cc
+++ b/runtime/vm/compiler/backend/inliner_test.cc
@@ -213,44 +213,80 @@
   FlowGraph* flow_graph = pipeline.RunPasses({});
 
   auto entry = flow_graph->graph_entry()->normal_entry();
-  ILMatcher cursor(flow_graph, entry);
+  ILMatcher cursor(flow_graph, entry, /*trace=*/true,
+                   ParallelMovesHandling::kSkip);
 
-  RELEASE_ASSERT(cursor.TryMatch({
-      kMoveGlob,
-      kMatchAndMoveCreateArray,
-      kMoveParallelMoves,
-      kMatchAndMoveUnboxInt64,
-      kMatchAndMoveUnboxedConstant,
-      kMatchAndMoveUnboxedConstant,
-      kMoveParallelMoves,
-      kMatchAndMoveGoto,
+  if (function.is_declared_in_bytecode()) {
+    RELEASE_ASSERT(cursor.TryMatch({
+        kMoveGlob,
+        kMatchAndMoveCreateArray,
+        kWordSize == 8 ? kMatchAndMoveUnboxInt64 : kNop,
+        kMatchAndMoveGoto,
 
-      // Loop header
-      kMatchAndMoveJoinEntry,
-      kMatchAndMoveCheckStackOverflow,
-      kMatchAndMoveBranchTrue,
+        // Loop header
+        kMatchAndMoveJoinEntry,
+        kMatchAndMoveCheckStackOverflow,
+        kMatchAndMoveUnboxInt64,
+        kMatchAndMoveUnboxInt64,
+        kMatchAndMoveBranchTrue,
 
-      // Loop body
-      kMatchAndMoveTargetEntry,
-      kMatchAndMoveBoxInt64,
-      kMatchAndMoveBoxInt64,
-      kMoveParallelMoves,
-      kMatchAndMoveStoreIndexed,
-      kMoveParallelMoves,
-      kMatchAndMoveBinaryInt64Op,
-      kMoveParallelMoves,
-      kMatchAndMoveGoto,
+        // Loop body
+        kMatchAndMoveTargetEntry,
+        kWordSize == 8 ? kMatchAndMoveUnboxInt64 : kNop,
+        kMatchAndMoveGenericCheckBound,
+        kMatchAndMoveStoreIndexed,
+        kMatchAndMoveCheckedSmiOp,
+        kMatchAndMoveGoto,
 
-      // Loop header once again
-      kMatchAndMoveJoinEntry,
-      kMatchAndMoveCheckStackOverflow,
-      kMatchAndMoveBranchFalse,
+        // Loop header once again
+        kMatchAndMoveJoinEntry,
+        kMatchAndMoveCheckStackOverflow,
+        kMatchAndMoveUnboxInt64,
+        kMatchAndMoveUnboxInt64,
+        kMatchAndMoveBranchFalse,
 
-      // After loop
-      kMatchAndMoveTargetEntry,
-      kMoveParallelMoves,
-      kMatchReturn,
-  }));
+        // After loop
+        kMatchAndMoveTargetEntry,
+        kMatchReturn,
+    }));
+  } else {
+    Instruction* unbox1 = nullptr;
+    Instruction* unbox2 = nullptr;
+
+    RELEASE_ASSERT(cursor.TryMatch({
+        kMoveGlob,
+        kMatchAndMoveCreateArray,
+        kMatchAndMoveUnboxInt64,
+        {kMoveAny, &unbox1},
+        {kMoveAny, &unbox2},
+        kMatchAndMoveGoto,
+
+        // Loop header
+        kMatchAndMoveJoinEntry,
+        kMatchAndMoveCheckStackOverflow,
+        kMatchAndMoveBranchTrue,
+
+        // Loop body
+        kMatchAndMoveTargetEntry,
+        kWordSize == 4 ? kMatchAndMoveBoxInt64 : kNop,
+        kMatchAndMoveBoxInt64,
+        kMatchAndMoveStoreIndexed,
+        kMatchAndMoveBinaryInt64Op,
+        kMatchAndMoveGoto,
+
+        // Loop header once again
+        kMatchAndMoveJoinEntry,
+        kMatchAndMoveCheckStackOverflow,
+        kMatchAndMoveBranchFalse,
+
+        // After loop
+        kMatchAndMoveTargetEntry,
+        kMatchReturn,
+    }));
+
+    EXPECT(unbox1->IsUnboxedConstant() || unbox1->IsUnboxInt64());
+    EXPECT(unbox2->IsUnboxedConstant() || unbox2->IsUnboxInt64());
+  }
 }
 
 #endif  // defined(DART_PRECOMPILER)
diff --git a/runtime/vm/compiler/backend/typed_data_aot_test.cc b/runtime/vm/compiler/backend/typed_data_aot_test.cc
index b1dd7c0..d978e86 100644
--- a/runtime/vm/compiler/backend/typed_data_aot_test.cc
+++ b/runtime/vm/compiler/backend/typed_data_aot_test.cc
@@ -77,7 +77,9 @@
   }
 
   EXPECT(load_field->InputAt(0)->definition()->IsParameter());
-  EXPECT(bounds_check->InputAt(0)->definition() == load_field);
+  EXPECT(bounds_check->length()
+             ->definition()
+             ->OriginalDefinitionIgnoreBoxingAndConstraints() == load_field);
   EXPECT(load_untagged->InputAt(0)->definition()->IsParameter());
   EXPECT(load_indexed->InputAt(0)->definition() == load_untagged);
 }
diff --git a/runtime/vm/compiler/stub_code_compiler.cc b/runtime/vm/compiler/stub_code_compiler.cc
index c02a246..87f0a60 100644
--- a/runtime/vm/compiler/stub_code_compiler.cc
+++ b/runtime/vm/compiler/stub_code_compiler.cc
@@ -20,6 +20,22 @@
 
 namespace compiler {
 
+intptr_t StubCodeCompiler::WordOffsetFromFpToCpuRegister(
+    Register cpu_register) {
+  ASSERT(RegisterSet::Contains(kDartAvailableCpuRegs, cpu_register));
+
+  // Skip FP + saved PC.
+  intptr_t slots_from_fp = 2;
+  for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) {
+    Register reg = static_cast<Register>(i);
+    if (reg == cpu_register) break;
+    if (RegisterSet::Contains(kDartAvailableCpuRegs, reg)) {
+      slots_from_fp++;
+    }
+  }
+  return slots_from_fp;
+}
+
 void StubCodeCompiler::GenerateInitStaticFieldStub(Assembler* assembler) {
   __ EnterStubFrame();
   __ PushObject(NullObject());  // Make room for result.
diff --git a/runtime/vm/compiler/stub_code_compiler.h b/runtime/vm/compiler/stub_code_compiler.h
index cf4e58d..875ea17 100644
--- a/runtime/vm/compiler/stub_code_compiler.h
+++ b/runtime/vm/compiler/stub_code_compiler.h
@@ -125,6 +125,18 @@
   static void GenerateJITCallbackTrampolines(Assembler* assembler,
                                              intptr_t next_callback_id);
 
+  // Calculates the offset (in words) from FP to the provided [cpu_register].
+  //
+  // Assumes
+  //   * all [kDartAvailableCpuRegs] followed by saved-PC, saved-FP were
+  //     pushed on the stack
+  //   * [cpu_register] is in [kDartAvailableCpuRegs]
+  //
+  // The intended use of this function is to find registers on the stack which
+  // were spilled in the
+  // `StubCode::*<stub-name>Shared{With,Without}FpuRegsStub()`
+  static intptr_t WordOffsetFromFpToCpuRegister(Register cpu_register);
+
  private:
   // Common function for generating InitLateInstanceField and
   // InitLateFinalInstanceField stubs.
diff --git a/runtime/vm/compiler/stub_code_compiler_arm.cc b/runtime/vm/compiler/stub_code_compiler_arm.cc
index 24a50e7..5d9365d 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm.cc
@@ -6,6 +6,7 @@
 #include "vm/globals.h"
 
 // For `AllocateObjectInstr::WillAllocateNewOrRemembered`
+// For `GenericCheckBoundInstr::UseUnboxedRepresentation`
 #include "vm/compiler/backend/il.h"
 
 #define SHOULD_NOT_INCLUDE_RUNTIME
@@ -164,14 +165,11 @@
   __ Ret();
 }
 
-void GenerateSharedStub(
-    Assembler* assembler,
-    bool save_fpu_registers,
-    const RuntimeEntry* target,
-    intptr_t self_code_stub_offset_from_thread,
-    bool allow_return,
-    bool store_runtime_result_in_r0 = false,
-    std::initializer_list<Register> runtime_call_arguments = {}) {
+void GenerateSharedStubGeneric(Assembler* assembler,
+                               bool save_fpu_registers,
+                               intptr_t self_code_stub_offset_from_thread,
+                               bool allow_return,
+                               std::function<void()> perform_runtime_call) {
   // If the target CPU does not support VFP the caller should always use the
   // non-FPU stub.
   if (save_fpu_registers && !TargetCPUFeatures::vfp_supported()) {
@@ -187,44 +185,45 @@
   // To make the stack map calculation architecture independent we do the same
   // as on intel.
   __ Push(LR);
-
   __ PushRegisters(all_registers);
   __ ldr(CODE_REG, Address(THR, self_code_stub_offset_from_thread));
   __ EnterStubFrame();
-
-  if (store_runtime_result_in_r0) {
-    ASSERT(all_registers.ContainsRegister(R0));
-    ASSERT(allow_return);
-
-    // Push an even value so it will not be seen as a pointer
-    __ Push(LR);
-  }
-
-  for (Register argument_reg : runtime_call_arguments) {
-    __ PushRegister(argument_reg);
-  }
-  __ CallRuntime(*target, /*argument_count=*/runtime_call_arguments.size());
+  perform_runtime_call();
   if (!allow_return) {
     __ Breakpoint();
     return;
   }
-
-  __ Drop(runtime_call_arguments.size());
-  if (store_runtime_result_in_r0) {
-    __ Pop(R0);
-  }
   __ LeaveStubFrame();
-  if (store_runtime_result_in_r0) {
-    // Stores the runtime result in stack where R0 was pushed ( R0 is the very
-    // last register to be pushed by __ PushRegisters(all_registers) )
-    __ str(R0, Address(SP));
-  }
-
   __ PopRegisters(all_registers);
   __ Pop(LR);
   __ bx(LR);
 }
 
+static void GenerateSharedStub(Assembler* assembler,
+                               bool save_fpu_registers,
+                               const RuntimeEntry* target,
+                               intptr_t self_code_stub_offset_from_thread,
+                               bool allow_return,
+                               bool store_runtime_result_in_r0 = false) {
+  ASSERT(!store_runtime_result_in_r0 || allow_return);
+  auto perform_runtime_call = [&]() {
+    if (store_runtime_result_in_r0) {
+      __ PushRegister(LR);  // Push an even register.
+    }
+    __ CallRuntime(*target, /*argument_count=*/0);
+    if (store_runtime_result_in_r0) {
+      __ PopRegister(R0);
+      __ str(
+          R0,
+          Address(FP, target::kWordSize *
+                          StubCodeCompiler::WordOffsetFromFpToCpuRegister(R0)));
+    }
+  };
+  GenerateSharedStubGeneric(assembler, save_fpu_registers,
+                            self_code_stub_offset_from_thread, allow_return,
+                            perform_runtime_call);
+}
+
 // R1: The extracted method.
 // R4: The type_arguments_field_offset (or 0)
 // SP+0: The object from which we are tearing a method off.
@@ -497,7 +496,7 @@
   GenerateSharedStub(
       assembler, /*save_fpu_registers=*/false, &kNullErrorRuntimeEntry,
       target::Thread::null_error_shared_without_fpu_regs_stub_offset(),
-      /*allow_return=*/false, {});
+      /*allow_return=*/false);
 }
 
 void StubCodeCompiler::GenerateNullErrorSharedWithFPURegsStub(
@@ -505,7 +504,7 @@
   GenerateSharedStub(
       assembler, /*save_fpu_registers=*/true, &kNullErrorRuntimeEntry,
       target::Thread::null_error_shared_with_fpu_regs_stub_offset(),
-      /*allow_return=*/false, {});
+      /*allow_return=*/false);
 }
 
 void StubCodeCompiler::GenerateNullArgErrorSharedWithoutFPURegsStub(
@@ -513,7 +512,7 @@
   GenerateSharedStub(
       assembler, /*save_fpu_registers=*/false, &kArgumentNullErrorRuntimeEntry,
       target::Thread::null_arg_error_shared_without_fpu_regs_stub_offset(),
-      /*allow_return=*/false, {});
+      /*allow_return=*/false);
 }
 
 void StubCodeCompiler::GenerateNullArgErrorSharedWithFPURegsStub(
@@ -521,27 +520,34 @@
   GenerateSharedStub(
       assembler, /*save_fpu_registers=*/true, &kArgumentNullErrorRuntimeEntry,
       target::Thread::null_arg_error_shared_with_fpu_regs_stub_offset(),
-      /*allow_return=*/false, {});
+      /*allow_return=*/false);
+}
+
+static void GenerateRangeError(Assembler* assembler, bool with_fpu_regs) {
+  auto perform_runtime_call = [&]() {
+    ASSERT(!GenericCheckBoundInstr::UseUnboxedRepresentation());
+    __ PushRegister(RangeErrorABI::kLengthReg);
+    __ PushRegister(RangeErrorABI::kIndexReg);
+    __ CallRuntime(kRangeErrorRuntimeEntry, /*argument_count=*/2);
+    __ Breakpoint();
+  };
+
+  GenerateSharedStubGeneric(
+      assembler, /*save_fpu_registers=*/with_fpu_regs,
+      with_fpu_regs
+          ? target::Thread::range_error_shared_with_fpu_regs_stub_offset()
+          : target::Thread::range_error_shared_without_fpu_regs_stub_offset(),
+      /*allow_return=*/false, perform_runtime_call);
 }
 
 void StubCodeCompiler::GenerateRangeErrorSharedWithoutFPURegsStub(
     Assembler* assembler) {
-  GenerateSharedStub(
-      assembler, /*save_fpu_registers=*/false, &kRangeErrorRuntimeEntry,
-      target::Thread::range_error_shared_without_fpu_regs_stub_offset(),
-      /*allow_return=*/false,
-      /*store_runtime_result_in_r0=*/false,
-      {RangeErrorABI::kLengthReg, RangeErrorABI::kIndexReg});
+  GenerateRangeError(assembler, /*with_fpu_regs=*/false);
 }
 
 void StubCodeCompiler::GenerateRangeErrorSharedWithFPURegsStub(
     Assembler* assembler) {
-  GenerateSharedStub(
-      assembler, /*save_fpu_registers=*/true, &kRangeErrorRuntimeEntry,
-      target::Thread::range_error_shared_with_fpu_regs_stub_offset(),
-      /*allow_return=*/false,
-      /*store_runtime_result_in_r0=*/false,
-      {RangeErrorABI::kLengthReg, RangeErrorABI::kIndexReg});
+  GenerateRangeError(assembler, /*with_fpu_regs=*/true);
 }
 
 void StubCodeCompiler::GenerateStackOverflowSharedWithoutFPURegsStub(
@@ -549,7 +555,7 @@
   GenerateSharedStub(
       assembler, /*save_fpu_registers=*/false, &kStackOverflowRuntimeEntry,
       target::Thread::stack_overflow_shared_without_fpu_regs_stub_offset(),
-      /*allow_return=*/true, {});
+      /*allow_return=*/true);
 }
 
 void StubCodeCompiler::GenerateStackOverflowSharedWithFPURegsStub(
@@ -557,7 +563,7 @@
   GenerateSharedStub(
       assembler, /*save_fpu_registers=*/true, &kStackOverflowRuntimeEntry,
       target::Thread::stack_overflow_shared_with_fpu_regs_stub_offset(),
-      /*allow_return=*/true, {});
+      /*allow_return=*/true);
 }
 
 // Input parameters:
@@ -1204,7 +1210,7 @@
                      &kAllocateMintRuntimeEntry,
                      target::Thread::allocate_mint_with_fpu_regs_stub_offset(),
                      /*allow_return=*/true,
-                     /*store_runtime_result_in_r0=*/true, {});
+                     /*store_runtime_result_in_r0=*/true);
 }
 
 // Called for allocation of Mint.
@@ -1223,7 +1229,7 @@
       assembler, /*save_fpu_registers=*/false, &kAllocateMintRuntimeEntry,
       target::Thread::allocate_mint_without_fpu_regs_stub_offset(),
       /*allow_return=*/true,
-      /*store_runtime_result_in_r0=*/true, {});
+      /*store_runtime_result_in_r0=*/true);
 }
 
 // Called when invoking Dart code from C++ (VM code).
diff --git a/runtime/vm/compiler/stub_code_compiler_arm64.cc b/runtime/vm/compiler/stub_code_compiler_arm64.cc
index f8c009c..08d5931 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm64.cc
@@ -5,6 +5,7 @@
 #include "vm/globals.h"
 
 // For `AllocateObjectInstr::WillAllocateNewOrRemembered`
+// For `GenericCheckBoundInstr::UseUnboxedRepresentation`
 #include "vm/compiler/backend/il.h"
 
 #define SHOULD_NOT_INCLUDE_RUNTIME
@@ -184,14 +185,12 @@
   __ ret();
 }
 
-void GenerateSharedStub(
+static void GenerateSharedStubGeneric(
     Assembler* assembler,
     bool save_fpu_registers,
-    const RuntimeEntry* target,
     intptr_t self_code_stub_offset_from_thread,
     bool allow_return,
-    bool store_runtime_result_in_r0 = false,
-    std::initializer_list<Register> runtime_call_arguments = {}) {
+    std::function<void()> perform_runtime_call) {
   // We want the saved registers to appear like part of the caller's frame, so
   // we push them before calling EnterStubFrame.
   RegisterSet all_registers;
@@ -203,37 +202,42 @@
   __ PushRegisters(all_registers);
   __ ldr(CODE_REG, Address(THR, self_code_stub_offset_from_thread));
   __ EnterStubFrame();
-  if (store_runtime_result_in_r0) {
-    ASSERT(all_registers.ContainsRegister(R0));
-    ASSERT(allow_return);
-
-    // Push an even value so it will not be seen as a pointer
-    __ Push(LR);
-  }
-  for (Register argument_reg : runtime_call_arguments) {
-    __ PushRegister(argument_reg);
-  }
-  __ CallRuntime(*target, /*argument_count=*/runtime_call_arguments.size());
+  perform_runtime_call();
   if (!allow_return) {
     __ Breakpoint();
     return;
   }
-
-  __ Drop(runtime_call_arguments.size());
-  if (store_runtime_result_in_r0) {
-    __ Pop(R0);
-  }
   __ LeaveStubFrame();
-  if (store_runtime_result_in_r0) {
-    // Stores the runtime result in stack where R0 was pushed ( R0 is the very
-    // last register to be pushed by __ PushRegisters(all_registers) )
-    __ str(R0, Address(SP));
-  }
   __ PopRegisters(all_registers);
   __ Pop(LR);
   __ ret(LR);
 }
 
+static void GenerateSharedStub(Assembler* assembler,
+                               bool save_fpu_registers,
+                               const RuntimeEntry* target,
+                               intptr_t self_code_stub_offset_from_thread,
+                               bool allow_return,
+                               bool store_runtime_result_in_r0 = false) {
+  ASSERT(!store_runtime_result_in_r0 || allow_return);
+  auto perform_runtime_call = [&]() {
+    if (store_runtime_result_in_r0) {
+      __ PushRegister(NULL_REG);
+    }
+    __ CallRuntime(*target, /*argument_count=*/0);
+    if (store_runtime_result_in_r0) {
+      __ PopRegister(R0);
+      __ str(
+          R0,
+          Address(FP, target::kWordSize *
+                          StubCodeCompiler::WordOffsetFromFpToCpuRegister(R0)));
+    }
+  };
+  GenerateSharedStubGeneric(assembler, save_fpu_registers,
+                            self_code_stub_offset_from_thread, allow_return,
+                            perform_runtime_call);
+}
+
 void StubCodeCompiler::GenerateEnterSafepointStub(Assembler* assembler) {
   RegisterSet all_registers;
   all_registers.AddAllGeneralRegisters();
@@ -549,7 +553,7 @@
   GenerateSharedStub(
       assembler, /*save_fpu_registers=*/false, &kNullErrorRuntimeEntry,
       target::Thread::null_error_shared_without_fpu_regs_stub_offset(),
-      /*allow_return=*/false, {});
+      /*allow_return=*/false);
 }
 
 void StubCodeCompiler::GenerateNullErrorSharedWithFPURegsStub(
@@ -557,7 +561,7 @@
   GenerateSharedStub(
       assembler, /*save_fpu_registers=*/true, &kNullErrorRuntimeEntry,
       target::Thread::null_error_shared_with_fpu_regs_stub_offset(),
-      /*allow_return=*/false, {});
+      /*allow_return=*/false);
 }
 
 void StubCodeCompiler::GenerateNullArgErrorSharedWithoutFPURegsStub(
@@ -565,7 +569,7 @@
   GenerateSharedStub(
       assembler, /*save_fpu_registers=*/false, &kArgumentNullErrorRuntimeEntry,
       target::Thread::null_arg_error_shared_without_fpu_regs_stub_offset(),
-      /*allow_return=*/false, {});
+      /*allow_return=*/false);
 }
 
 void StubCodeCompiler::GenerateNullArgErrorSharedWithFPURegsStub(
@@ -573,27 +577,64 @@
   GenerateSharedStub(
       assembler, /*save_fpu_registers=*/true, &kArgumentNullErrorRuntimeEntry,
       target::Thread::null_arg_error_shared_with_fpu_regs_stub_offset(),
-      /*allow_return=*/false, {});
+      /*allow_return=*/false);
+}
+
+static void GenerateRangeError(Assembler* assembler, bool with_fpu_regs) {
+  auto perform_runtime_call = [&]() {
+    // If the generated code has unboxed index/length we need to box them before
+    // calling the runtime entry.
+    if (GenericCheckBoundInstr::UseUnboxedRepresentation()) {
+      Label length, smi_case;
+
+      // The user-controlled index might not fit into a Smi.
+      __ adds(RangeErrorABI::kIndexReg, RangeErrorABI::kIndexReg,
+              compiler::Operand(RangeErrorABI::kIndexReg));
+      __ BranchIf(NO_OVERFLOW, &length);
+      {
+        // Allocate a mint, reload the two registers and popualte the mint.
+        __ PushRegister(NULL_REG);
+        __ CallRuntime(kAllocateMintRuntimeEntry, /*argument_count=*/0);
+        __ PopRegister(RangeErrorABI::kIndexReg);
+        __ ldr(TMP,
+               Address(FP, target::kWordSize *
+                               StubCodeCompiler::WordOffsetFromFpToCpuRegister(
+                                   RangeErrorABI::kIndexReg)));
+        __ str(TMP, FieldAddress(RangeErrorABI::kIndexReg,
+                                 target::Mint::value_offset()));
+        __ ldr(RangeErrorABI::kLengthReg,
+               Address(FP, target::kWordSize *
+                               StubCodeCompiler::WordOffsetFromFpToCpuRegister(
+                                   RangeErrorABI::kLengthReg)));
+      }
+
+      // Length is guaranteed to be in positive Smi range (it comes from a load
+      // of a vm recognized array).
+      __ Bind(&length);
+      __ SmiTag(RangeErrorABI::kLengthReg);
+    }
+    __ PushRegister(RangeErrorABI::kLengthReg);
+    __ PushRegister(RangeErrorABI::kIndexReg);
+    __ CallRuntime(kRangeErrorRuntimeEntry, /*argument_count=*/2);
+    __ Breakpoint();
+  };
+
+  GenerateSharedStubGeneric(
+      assembler, /*save_fpu_registers=*/with_fpu_regs,
+      with_fpu_regs
+          ? target::Thread::range_error_shared_with_fpu_regs_stub_offset()
+          : target::Thread::range_error_shared_without_fpu_regs_stub_offset(),
+      /*allow_return=*/false, perform_runtime_call);
 }
 
 void StubCodeCompiler::GenerateRangeErrorSharedWithoutFPURegsStub(
     Assembler* assembler) {
-  GenerateSharedStub(
-      assembler, /*save_fpu_registers=*/false, &kRangeErrorRuntimeEntry,
-      target::Thread::range_error_shared_without_fpu_regs_stub_offset(),
-      /*allow_return=*/false,
-      /*store_runtime_result_in_r0=*/false,
-      {RangeErrorABI::kLengthReg, RangeErrorABI::kIndexReg});
+  GenerateRangeError(assembler, /*with_fpu_regs=*/false);
 }
 
 void StubCodeCompiler::GenerateRangeErrorSharedWithFPURegsStub(
     Assembler* assembler) {
-  GenerateSharedStub(
-      assembler, /*save_fpu_registers=*/true, &kRangeErrorRuntimeEntry,
-      target::Thread::range_error_shared_with_fpu_regs_stub_offset(),
-      /*allow_return=*/false,
-      /*store_runtime_result_in_r0=*/false,
-      {RangeErrorABI::kLengthReg, RangeErrorABI::kIndexReg});
+  GenerateRangeError(assembler, /*with_fpu_regs=*/true);
 }
 
 void StubCodeCompiler::GenerateStackOverflowSharedWithoutFPURegsStub(
@@ -601,7 +642,7 @@
   GenerateSharedStub(
       assembler, /*save_fpu_registers=*/false, &kStackOverflowRuntimeEntry,
       target::Thread::stack_overflow_shared_without_fpu_regs_stub_offset(),
-      /*allow_return=*/true, {});
+      /*allow_return=*/true);
 }
 
 void StubCodeCompiler::GenerateStackOverflowSharedWithFPURegsStub(
@@ -609,7 +650,7 @@
   GenerateSharedStub(
       assembler, /*save_fpu_registers=*/true, &kStackOverflowRuntimeEntry,
       target::Thread::stack_overflow_shared_with_fpu_regs_stub_offset(),
-      /*allow_return=*/true, {});
+      /*allow_return=*/true);
 }
 
 void StubCodeCompiler::GeneratePrintStopMessageStub(Assembler* assembler) {
@@ -1288,7 +1329,7 @@
                      &kAllocateMintRuntimeEntry,
                      target::Thread::allocate_mint_with_fpu_regs_stub_offset(),
                      /*allow_return=*/true,
-                     /*store_runtime_result_in_r0=*/true, {});
+                     /*store_runtime_result_in_r0=*/true);
 }
 
 void StubCodeCompiler::GenerateAllocateMintSharedWithoutFPURegsStub(
@@ -1306,7 +1347,7 @@
       assembler, /*save_fpu_registers=*/false, &kAllocateMintRuntimeEntry,
       target::Thread::allocate_mint_without_fpu_regs_stub_offset(),
       /*allow_return=*/true,
-      /*store_runtime_result_in_r0=*/true, {});
+      /*store_runtime_result_in_r0=*/true);
 }
 
 // Called when invoking Dart code from C++ (VM code).
diff --git a/runtime/vm/compiler/stub_code_compiler_x64.cc b/runtime/vm/compiler/stub_code_compiler_x64.cc
index 67261a1..4d4637a 100644
--- a/runtime/vm/compiler/stub_code_compiler_x64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_x64.cc
@@ -6,6 +6,7 @@
 #include "vm/globals.h"
 
 // For `AllocateObjectInstr::WillAllocateNewOrRemembered`
+// For `GenericCheckBoundInstr::UseUnboxedRepresentation`
 #include "vm/compiler/backend/il.h"
 
 #define SHOULD_NOT_INCLUDE_RUNTIME
@@ -163,13 +164,12 @@
   __ ret();
 }
 
-void GenerateSharedStub(
+static void GenerateSharedStubGeneric(
     Assembler* assembler,
     bool save_fpu_registers,
-    const RuntimeEntry* target,
     intptr_t self_code_stub_offset_from_thread,
     bool allow_return,
-    std::initializer_list<Register> runtime_call_arguments) {
+    std::function<void()> perform_runtime_call) {
   // We want the saved registers to appear like part of the caller's frame, so
   // we push them before calling EnterStubFrame.
   __ PushRegisters(kDartAvailableCpuRegs,
@@ -177,30 +177,22 @@
 
   const intptr_t kSavedCpuRegisterSlots =
       Utils::CountOneBitsWord(kDartAvailableCpuRegs);
-
   const intptr_t kSavedFpuRegisterSlots =
       save_fpu_registers
           ? kNumberOfFpuRegisters * kFpuRegisterSize / target::kWordSize
           : 0;
-
   const intptr_t kAllSavedRegistersSlots =
       kSavedCpuRegisterSlots + kSavedFpuRegisterSlots;
 
   // Copy down the return address so the stack layout is correct.
   __ pushq(Address(RSP, kAllSavedRegistersSlots * target::kWordSize));
-
   __ movq(CODE_REG, Address(THR, self_code_stub_offset_from_thread));
-
   __ EnterStubFrame();
-  for (Register argument_reg : runtime_call_arguments) {
-    __ PushRegister(argument_reg);
-  }
-  __ CallRuntime(*target, /*argument_count=*/runtime_call_arguments.size());
+  perform_runtime_call();
   if (!allow_return) {
     __ Breakpoint();
     return;
   }
-  __ Drop(runtime_call_arguments.size());
   __ LeaveStubFrame();
 
   // Drop "official" return address -- we can just use the one stored above the
@@ -213,6 +205,19 @@
   __ ret();
 }
 
+static void GenerateSharedStub(Assembler* assembler,
+                               bool save_fpu_registers,
+                               const RuntimeEntry* target,
+                               intptr_t self_code_stub_offset_from_thread,
+                               bool allow_return) {
+  auto perform_runtime_call = [&]() {
+    __ CallRuntime(*target, /*argument_count=*/0);
+  };
+  GenerateSharedStubGeneric(assembler, save_fpu_registers,
+                            self_code_stub_offset_from_thread, allow_return,
+                            perform_runtime_call);
+}
+
 void StubCodeCompiler::GenerateEnterSafepointStub(Assembler* assembler) {
   RegisterSet all_registers;
   all_registers.AddAllGeneralRegisters();
@@ -484,7 +489,7 @@
   GenerateSharedStub(
       assembler, /*save_fpu_registers=*/false, &kNullErrorRuntimeEntry,
       target::Thread::null_error_shared_without_fpu_regs_stub_offset(),
-      /*allow_return=*/false, {});
+      /*allow_return=*/false);
 }
 
 void StubCodeCompiler::GenerateNullErrorSharedWithFPURegsStub(
@@ -492,7 +497,7 @@
   GenerateSharedStub(
       assembler, /*save_fpu_registers=*/true, &kNullErrorRuntimeEntry,
       target::Thread::null_error_shared_with_fpu_regs_stub_offset(),
-      /*allow_return=*/false, {});
+      /*allow_return=*/false);
 }
 
 void StubCodeCompiler::GenerateNullArgErrorSharedWithoutFPURegsStub(
@@ -500,7 +505,7 @@
   GenerateSharedStub(
       assembler, /*save_fpu_registers=*/false, &kArgumentNullErrorRuntimeEntry,
       target::Thread::null_arg_error_shared_without_fpu_regs_stub_offset(),
-      /*allow_return=*/false, {});
+      /*allow_return=*/false);
 }
 
 void StubCodeCompiler::GenerateNullArgErrorSharedWithFPURegsStub(
@@ -508,25 +513,66 @@
   GenerateSharedStub(
       assembler, /*save_fpu_registers=*/true, &kArgumentNullErrorRuntimeEntry,
       target::Thread::null_arg_error_shared_with_fpu_regs_stub_offset(),
-      /*allow_return=*/false, {});
+      /*allow_return=*/false);
+}
+
+static void GenerateRangeError(Assembler* assembler, bool with_fpu_regs) {
+  auto perform_runtime_call = [&]() {
+    // If the generated code has unboxed index/length we need to box them before
+    // calling the runtime entry.
+    if (GenericCheckBoundInstr::UseUnboxedRepresentation()) {
+      Label length, smi_case;
+
+      // The user-controlled index might not fit into a Smi.
+      __ addq(RangeErrorABI::kIndexReg, RangeErrorABI::kIndexReg);
+      __ BranchIf(NO_OVERFLOW, &length);
+      {
+        // Allocate a mint, reload the two registers and popualte the mint.
+        __ PushImmediate(Immediate(0));
+        __ CallRuntime(kAllocateMintRuntimeEntry, /*argument_count=*/0);
+        __ PopRegister(RangeErrorABI::kIndexReg);
+        __ movq(
+            TMP,
+            Address(RBP, target::kWordSize *
+                             StubCodeCompiler::WordOffsetFromFpToCpuRegister(
+                                 RangeErrorABI::kIndexReg)));
+        __ movq(FieldAddress(RangeErrorABI::kIndexReg,
+                             target::Mint::value_offset()),
+                TMP);
+        __ movq(
+            RangeErrorABI::kLengthReg,
+            Address(RBP, target::kWordSize *
+                             StubCodeCompiler::WordOffsetFromFpToCpuRegister(
+                                 RangeErrorABI::kLengthReg)));
+      }
+
+      // Length is guaranteed to be in positive Smi range (it comes from a load
+      // of a vm recognized array).
+      __ Bind(&length);
+      __ SmiTag(RangeErrorABI::kLengthReg);
+    }
+    __ PushRegister(RangeErrorABI::kLengthReg);
+    __ PushRegister(RangeErrorABI::kIndexReg);
+    __ CallRuntime(kRangeErrorRuntimeEntry, /*argument_count=*/2);
+    __ Breakpoint();
+  };
+
+  GenerateSharedStubGeneric(
+      assembler, /*save_fpu_registers=*/with_fpu_regs,
+      with_fpu_regs
+          ? target::Thread::range_error_shared_with_fpu_regs_stub_offset()
+          : target::Thread::range_error_shared_without_fpu_regs_stub_offset(),
+      /*allow_return=*/false, perform_runtime_call);
 }
 
 void StubCodeCompiler::GenerateRangeErrorSharedWithoutFPURegsStub(
     Assembler* assembler) {
-  GenerateSharedStub(
-      assembler, /*save_fpu_registers=*/false, &kRangeErrorRuntimeEntry,
-      target::Thread::range_error_shared_without_fpu_regs_stub_offset(),
-      /*allow_return=*/false,
-      {RangeErrorABI::kLengthReg, RangeErrorABI::kIndexReg});
+  GenerateRangeError(assembler, /*with_fpu_regs=*/false);
 }
 
 void StubCodeCompiler::GenerateRangeErrorSharedWithFPURegsStub(
     Assembler* assembler) {
-  GenerateSharedStub(
-      assembler, /*save_fpu_registers=*/true, &kRangeErrorRuntimeEntry,
-      target::Thread::range_error_shared_with_fpu_regs_stub_offset(),
-      /*allow_return=*/false,
-      {RangeErrorABI::kLengthReg, RangeErrorABI::kIndexReg});
+  GenerateRangeError(assembler, /*with_fpu_regs=*/true);
 }
 
 void StubCodeCompiler::GenerateStackOverflowSharedWithoutFPURegsStub(
@@ -534,7 +580,7 @@
   GenerateSharedStub(
       assembler, /*save_fpu_registers=*/false, &kStackOverflowRuntimeEntry,
       target::Thread::stack_overflow_shared_without_fpu_regs_stub_offset(),
-      /*allow_return=*/true, {});
+      /*allow_return=*/true);
 }
 
 void StubCodeCompiler::GenerateStackOverflowSharedWithFPURegsStub(
@@ -542,7 +588,7 @@
   GenerateSharedStub(
       assembler, /*save_fpu_registers=*/true, &kStackOverflowRuntimeEntry,
       target::Thread::stack_overflow_shared_with_fpu_regs_stub_offset(),
-      /*allow_return=*/true, {});
+      /*allow_return=*/true);
 }
 
 // Input parameters:
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index 3ec567d..31f2973 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -753,12 +753,13 @@
                             intptr_t kernel_buffer_size,
                             const char* package_config,
                             const char* original_working_directory) {
+#if !defined(DART_PRECOMPILED_RUNTIME)
   // Before creating the isolate we first determine the null safety mode
   // in which the isolate needs to run based on one of these factors :
   // - if loading from source, based on opt-in status of the source
   // - if loading from a kernel file, based on the mode used when
   //   generating the kernel file
-  // - if loading from an appJIT or AOT snapshot, based on the mode used
+  // - if loading from an appJIT, based on the mode used
   //   when generating the snapshot.
   ASSERT(FLAG_null_safety == kNullSafetyOptionUnspecified);
 
@@ -772,7 +773,6 @@
     }
   }
 
-#if !defined(DART_PRECOMPILED_RUNTIME)
   // If kernel_buffer is specified, it could be a self contained
   // kernel file or the kernel file of the application,
   // figure out the null safety mode by sniffing the kernel file.
@@ -791,8 +791,10 @@
     return KernelIsolate::DetectNullSafety(script_uri, package_config,
                                            original_working_directory);
   }
-#endif  // !defined(DART_PRECOMPILED_RUNTIME)
   return false;
+#else
+  UNREACHABLE();
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
 }
 
 #if defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index b3800b5..7893030 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -6032,6 +6032,10 @@
                                        const uint8_t* snapshot_instructions,
                                        const uint8_t* kernel_buffer,
                                        intptr_t kernel_buffer_size) {
+#if defined(DART_PRECOMPILED_RUNTIME)
+  ASSERT(FLAG_null_safety != kNullSafetyOptionUnspecified);
+  return (FLAG_null_safety == kNullSafetyOptionStrong);
+#else
   bool null_safety;
   if (FLAG_null_safety == kNullSafetyOptionUnspecified) {
     null_safety = Dart::DetectNullSafety(
@@ -6041,6 +6045,7 @@
     null_safety = (FLAG_null_safety == kNullSafetyOptionStrong);
   }
   return null_safety;
+#endif  // defined(DART_PRECOMPILED_RUNTIME)
 }
 
 // --- Service support ---
diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc
index 6c306ac..8a1350e 100644
--- a/runtime/vm/dart_entry.cc
+++ b/runtime/vm/dart_entry.cc
@@ -188,6 +188,7 @@
                                 Thread* thread) {
   ASSERT(!code.IsNull());
   ASSERT(thread->no_callback_scope_depth() == 0);
+  ASSERT(!Isolate::Current()->null_safety_not_set());
 
   invokestub entrypoint =
       reinterpret_cast<invokestub>(StubCode::InvokeDartCode().EntryPoint());
diff --git a/runtime/vm/dwarf.cc b/runtime/vm/dwarf.cc
index cdee3d3..db73b08 100644
--- a/runtime/vm/dwarf.cc
+++ b/runtime/vm/dwarf.cc
@@ -11,15 +11,36 @@
 
 namespace dart {
 
-#ifdef DART_PRECOMPILER
+#if defined(DART_PRECOMPILER)
+
+class DwarfPosition {
+ public:
+  // The DWARF standard uses 0 to denote missing line or column information.
+  DwarfPosition(intptr_t line, intptr_t column)
+      : line_(line > 0 ? line : 0), column_(column > 0 ? column : 0) {
+    // Should only have no line information if also no column information.
+    ASSERT(line_ > 0 || column_ == 0);
+  }
+  explicit DwarfPosition(intptr_t line) : DwarfPosition(line, 0) {}
+  constexpr DwarfPosition() : line_(0), column_(0) {}
+
+  intptr_t line() const { return line_; }
+  intptr_t column() const { return column_; }
+
+ private:
+  intptr_t line_;
+  intptr_t column_;
+};
+
+static constexpr auto kNoDwarfPositionInfo = DwarfPosition();
 
 class InliningNode : public ZoneAllocated {
  public:
   InliningNode(const Function& function,
-               TokenPosition call_pos,
+               const DwarfPosition& position,
                int32_t start_pc_offset)
       : function(function),
-        call_pos(call_pos),
+        position(position),
         start_pc_offset(start_pc_offset),
         end_pc_offset(-1),
         children_head(NULL),
@@ -39,7 +60,7 @@
   }
 
   const Function& function;
-  TokenPosition call_pos;
+  DwarfPosition position;
   int32_t start_pc_offset;
   int32_t end_pc_offset;
   InliningNode* children_head;
@@ -170,14 +191,6 @@
   return index;
 }
 
-intptr_t Dwarf::TokenPositionToLine(const TokenPosition& token_pos) {
-  // By the point we're creating the DWARF information, the values of
-  // non-special token positions have been converted to line numbers, so
-  // we just need to handle special (negative) token positions.
-  ASSERT(token_pos.value() > TokenPosition::kLast.value());
-  return token_pos.value() < 0 ? kNoLineInformation : token_pos.value();
-}
-
 intptr_t Dwarf::AddFunction(const Function& function) {
   RELEASE_ASSERT(!function.IsNull());
   FunctionIndexPair* pair = function_to_index_.Lookup(&function);
@@ -257,8 +270,6 @@
   stream->uleb128(DW_FORM_string);
   stream->uleb128(DW_AT_decl_file);
   stream->uleb128(DW_FORM_udata);
-  stream->uleb128(DW_AT_decl_line);
-  stream->uleb128(DW_FORM_udata);
   stream->uleb128(DW_AT_inline);
   stream->uleb128(DW_FORM_udata);
   stream->uleb128(0);
@@ -289,6 +300,8 @@
   stream->uleb128(DW_FORM_udata);
   stream->uleb128(DW_AT_call_line);
   stream->uleb128(DW_FORM_udata);
+  stream->uleb128(DW_AT_call_column);
+  stream->uleb128(DW_FORM_udata);
   stream->uleb128(0);
   stream->uleb128(0);  // End of attributes.
 
@@ -354,8 +367,8 @@
   String& name = String::Handle(zone_);
   stream->InitializeAbstractOrigins(functions_.length());
   // By the point we're creating DWARF information, scripts have already lost
-  // their token stream, so we can't look up their line number information.
-  auto const line = kNoLineInformation;
+  // their token stream and we can't look up their line number or column
+  // information, hence the lack of DW_AT_decl_line and DW_AT_decl_column.
   for (intptr_t i = 0; i < functions_.length(); i++) {
     const Function& function = *(functions_[i]);
     name = function.QualifiedUserVisibleName();
@@ -367,7 +380,6 @@
     stream->uleb128(kAbstractFunction);
     stream->string(name_cstr);        // DW_AT_name
     stream->uleb128(file);            // DW_AT_decl_file
-    stream->uleb128(line);            // DW_AT_decl_line
     stream->uleb128(DW_INL_inlined);  // DW_AT_inline
     stream->uleb128(0);               // End of children.
   }
@@ -411,6 +423,15 @@
   }
 }
 
+static DwarfPosition ReadPosition(ReadStream* stream) {
+  const intptr_t line = stream->Read<int32_t>();
+  if (!FLAG_dwarf_stack_traces_mode) {
+    return DwarfPosition(line);
+  }
+  const intptr_t column = stream->Read<int32_t>();
+  return DwarfPosition(line, column);
+}
+
 // Our state machine encodes position metadata such that we don't know the
 // end pc for an inlined function until it is popped, but DWARF DIEs encode
 // it where the function is pushed. We expand the state transitions into
@@ -428,24 +449,23 @@
   }
 
   GrowableArray<InliningNode*> node_stack(zone_, 4);
-  GrowableArray<TokenPosition> token_positions(zone_, 4);
+  GrowableArray<DwarfPosition> token_positions(zone_, 4);
 
   NoSafepointScope no_safepoint;
   ReadStream stream(map.Data(), map.Length());
 
   int32_t current_pc_offset = 0;
+  token_positions.Add(kNoDwarfPositionInfo);
   InliningNode* root_node =
-      new (zone_) InliningNode(root_function, TokenPosition(), 0);
+      new (zone_) InliningNode(root_function, token_positions.Last(), 0);
   root_node->end_pc_offset = code.Size();
   node_stack.Add(root_node);
-  token_positions.Add(CodeSourceMapBuilder::kInitialPosition);
 
   while (stream.PendingBytes() > 0) {
     uint8_t opcode = stream.Read<uint8_t>();
     switch (opcode) {
       case CodeSourceMapBuilder::kChangePosition: {
-        int32_t position = stream.Read<int32_t>();
-        token_positions[token_positions.length() - 1] = TokenPosition(position);
+        token_positions[token_positions.length() - 1] = ReadPosition(&stream);
         break;
       }
       case CodeSourceMapBuilder::kAdvancePC: {
@@ -457,12 +477,11 @@
         int32_t func = stream.Read<int32_t>();
         const Function& child_func =
             Function::ZoneHandle(zone_, Function::RawCast(functions.At(func)));
-        TokenPosition call_pos = token_positions.Last();
-        InliningNode* child_node =
-            new (zone_) InliningNode(child_func, call_pos, current_pc_offset);
+        InliningNode* child_node = new (zone_)
+            InliningNode(child_func, token_positions.Last(), current_pc_offset);
         node_stack.Last()->AppendChild(child_node);
         node_stack.Add(child_node);
-        token_positions.Add(CodeSourceMapBuilder::kInitialPosition);
+        token_positions.Add(kNoDwarfPositionInfo);
         break;
       }
       case CodeSourceMapBuilder::kPopFunction: {
@@ -498,7 +517,6 @@
                               const Script& parent_script,
                               SnapshotTextObjectNamer* namer) {
   intptr_t file = LookupScript(parent_script);
-  const auto& token_pos = node->call_pos;
   intptr_t function_index = LookupFunction(node->function);
   const Script& script = Script::Handle(zone_, node->function.script());
 
@@ -514,7 +532,9 @@
   // DW_AT_call_file
   stream->uleb128(file);
   // DW_AT_call_line
-  stream->uleb128(TokenPositionToLine(token_pos));
+  stream->uleb128(node->position.line());
+  // DW_at_call_column
+  stream->uleb128(node->position.column());
 
   for (InliningNode* child = node->children_head; child != NULL;
        child = child->children_next) {
@@ -582,17 +602,21 @@
 
   // 6.2.5 The Line Number Program
 
+  // The initial values for the line number program state machine registers
+  // according to the DWARF standard.
+  intptr_t previous_pc_offset = 0;
   intptr_t previous_file = 1;
   intptr_t previous_line = 1;
+  intptr_t previous_column = 0;
+  // Other info not stored in the state machine registers.
   const char* previous_asm_name = nullptr;
-  intptr_t previous_pc_offset = 0;
 
   Function& root_function = Function::Handle(zone_);
   Script& script = Script::Handle(zone_);
   CodeSourceMap& map = CodeSourceMap::Handle(zone_);
   Array& functions = Array::Handle(zone_);
   GrowableArray<const Function*> function_stack(zone_, 8);
-  GrowableArray<TokenPosition> token_positions(zone_, 8);
+  GrowableArray<DwarfPosition> token_positions(zone_, 8);
   SnapshotTextObjectNamer namer(zone_);
 
   for (intptr_t i = 0; i < codes_.length(); i++) {
@@ -614,15 +638,14 @@
 
     int32_t current_pc_offset = 0;
     function_stack.Add(&root_function);
-    token_positions.Add(CodeSourceMapBuilder::kInitialPosition);
+    token_positions.Add(kNoDwarfPositionInfo);
 
     while (code_map_stream.PendingBytes() > 0) {
       uint8_t opcode = code_map_stream.Read<uint8_t>();
       switch (opcode) {
         case CodeSourceMapBuilder::kChangePosition: {
-          int32_t position = code_map_stream.Read<int32_t>();
           token_positions[token_positions.length() - 1] =
-              TokenPosition(position);
+              ReadPosition(&code_map_stream);
           break;
         }
         case CodeSourceMapBuilder::kAdvancePC: {
@@ -641,12 +664,18 @@
           }
 
           // 2. Update LNP line.
-          const auto line = TokenPositionToLine(token_positions.Last());
+          const intptr_t line = token_positions.Last().line();
+          const intptr_t column = token_positions.Last().column();
           if (line != previous_line) {
             stream->u1(DW_LNS_advance_line);
             stream->sleb128(line - previous_line);
             previous_line = line;
           }
+          if (column != previous_column) {
+            stream->u1(DW_LNS_set_column);
+            stream->uleb128(column);
+            previous_column = column;
+          }
 
           // 3. Emit LNP row if the address register has been updated to a
           // non-zero value (dartbug.com/41756).
@@ -676,7 +705,7 @@
           const Function& child_func = Function::Handle(
               zone_, Function::RawCast(functions.At(func_index)));
           function_stack.Add(&child_func);
-          token_positions.Add(CodeSourceMapBuilder::kInitialPosition);
+          token_positions.Add(kNoDwarfPositionInfo);
           break;
         }
         case CodeSourceMapBuilder::kPopFunction: {
diff --git a/runtime/vm/dwarf.h b/runtime/vm/dwarf.h
index dc1692c..65d612c 100644
--- a/runtime/vm/dwarf.h
+++ b/runtime/vm/dwarf.h
@@ -313,6 +313,7 @@
   static const intptr_t DW_LNS_advance_pc = 0x2;
   static const intptr_t DW_LNS_advance_line = 0x3;
   static const intptr_t DW_LNS_set_file = 0x4;
+  static const intptr_t DW_LNS_set_column = 0x5;
 
   static const intptr_t DW_LNE_end_sequence = 0x01;
   static const intptr_t DW_LNE_set_address = 0x02;
@@ -324,12 +325,6 @@
     kInlinedFunction,
   };
 
-  static constexpr intptr_t kNoLineInformation = 0;
-
-  // Returns the line number or kNoLineInformation if there is no line
-  // information available for the given token position.
-  static intptr_t TokenPositionToLine(const TokenPosition& token_pos);
-
   void WriteAbstractFunctions(DwarfWriteStream* stream);
   void WriteConcreteFunctions(DwarfWriteStream* stream);
   InliningNode* ExpandInliningTree(const Code& code);
diff --git a/runtime/vm/kernel.cc b/runtime/vm/kernel.cc
index d6663e3..84f456c 100644
--- a/runtime/vm/kernel.cc
+++ b/runtime/vm/kernel.cc
@@ -36,26 +36,6 @@
   }
 }
 
-intptr_t KernelLineStartsReader::LineNumberForPosition(
-    intptr_t position) const {
-  intptr_t line_count = line_starts_data_.Length();
-  intptr_t current_start = 0;
-  for (intptr_t i = 0; i < line_count; ++i) {
-    current_start += helper_->At(line_starts_data_, i);
-    if (current_start > position) {
-      // If current_start is greater than the desired position, it means that
-      // it is for the line after |position|. However, since line numbers
-      // start at 1, we just return |i|.
-      return i;
-    }
-
-    if (current_start == position) {
-      return i + 1;
-    }
-  }
-  return line_count;
-}
-
 void KernelLineStartsReader::LocationForPosition(intptr_t position,
                                                  intptr_t* line,
                                                  intptr_t* col) const {
diff --git a/runtime/vm/kernel.h b/runtime/vm/kernel.h
index f612540..2ac42a1 100644
--- a/runtime/vm/kernel.h
+++ b/runtime/vm/kernel.h
@@ -140,8 +140,6 @@
     return helper_->At(line_starts_data_, index);
   }
 
-  intptr_t LineNumberForPosition(intptr_t position) const;
-
   void LocationForPosition(intptr_t position,
                            intptr_t* line,
                            intptr_t* col) const;
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 8e58e0f..29e4c97 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -10757,24 +10757,28 @@
 
 // Specialized for AOT compilation, which does this lookup for every token
 // position that could be part of a stack trace.
-intptr_t Script::GetTokenLineUsingLineStarts(
-    TokenPosition target_token_pos) const {
-  if (target_token_pos.IsNoSource()) {
-    return 0;
-  }
+bool Script::GetTokenLocationUsingLineStarts(TokenPosition target_token_pos,
+                                             intptr_t* line,
+                                             intptr_t* column) const {
+#if defined(DART_PRECOMPILED_RUNTIME)
+  return false;
+#else
+  // Negative positions denote positions that do not correspond to Dart code.
+  if (target_token_pos.value() < 0) return false;
+
   Zone* zone = Thread::Current()->zone();
   TypedData& line_starts_data = TypedData::Handle(zone, line_starts());
   // Scripts loaded from bytecode may have null line_starts().
-  if (line_starts_data.IsNull()) {
-    return 0;
-  }
+  if (line_starts_data.IsNull()) return false;
 
-#if !defined(DART_PRECOMPILED_RUNTIME)
   kernel::KernelLineStartsReader line_starts_reader(line_starts_data, zone);
-  return line_starts_reader.LineNumberForPosition(target_token_pos.value());
-#else
-  return 0;
-#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+  line_starts_reader.LocationForPosition(target_token_pos.value(), line,
+                                         column);
+  // The line and column numbers returned are ordinals, so we shouldn't get 0.
+  ASSERT(*line > 0);
+  ASSERT(*column > 0);
+  return true;
+#endif
 }
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index d87f411..0193fcd 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -4495,7 +4495,9 @@
 
   void SetLocationOffset(intptr_t line_offset, intptr_t col_offset) const;
 
-  intptr_t GetTokenLineUsingLineStarts(TokenPosition token_pos) const;
+  bool GetTokenLocationUsingLineStarts(TokenPosition token_pos,
+                                       intptr_t* line,
+                                       intptr_t* column) const;
   void GetTokenLocation(TokenPosition token_pos,
                         intptr_t* line,
                         intptr_t* column,
diff --git a/sdk/lib/_http/http_headers.dart b/sdk/lib/_http/http_headers.dart
index ae8b482..a2edfbd 100644
--- a/sdk/lib/_http/http_headers.dart
+++ b/sdk/lib/_http/http_headers.dart
@@ -80,6 +80,9 @@
     String lowercaseName = _validateField(name);
     _headers.remove(lowercaseName);
     _originalHeaderNames?.remove(lowercaseName);
+    if (lowercaseName == HttpHeaders.contentLengthHeader) {
+      _contentLength = -1;
+    }
     if (lowercaseName == HttpHeaders.transferEncodingHeader) {
       _chunkedTransferEncoding = false;
     }
diff --git a/sdk/lib/_http/http_impl.dart b/sdk/lib/_http/http_impl.dart
index 766b567..162461c 100644
--- a/sdk/lib/_http/http_impl.dart
+++ b/sdk/lib/_http/http_impl.dart
@@ -1808,7 +1808,11 @@
             startTimer();
             return;
           }
-          if (closed) return;
+          // Keep the connection open if the CONNECT request was successful.
+          if (closed ||
+              (method == 'CONNECT' && incoming.statusCode == HttpStatus.ok)) {
+            return;
+          }
           if (!closing &&
               !_dispose &&
               incoming.headers.persistentConnection &&
@@ -1895,10 +1899,8 @@
     timeline?.instant('Establishing proxy tunnel', arguments: {
       'proxyInfo': {
         if (proxy.host != null) 'host': proxy.host,
-        if (proxy.port != null)
-          'port': proxy.port,
-        if (proxy.username != null)
-          'username': proxy.username,
+        if (proxy.port != null) 'port': proxy.port,
+        if (proxy.username != null) 'username': proxy.username,
         // TODO(bkonyi): is this something we would want to surface? Initial
         // thought is no.
         // if (proxy.password != null)
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/runtime.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/runtime.dart
index 4867462..68c6691 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/runtime.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/runtime.dart
@@ -202,7 +202,10 @@
   for (var m in _cacheMaps) JS('', '#.clear()', m);
   _cacheMaps.clear();
   JS('', '#.clear()', _nullComparisonSet);
+  JS('', '#.clear()', constants);
+  JS('', '#.clear()', constantLists);
   JS('', '#.clear()', constantMaps);
+  JS('', '#.clear()', constantSets);
 }
 
 /// Marks enqueuing an async operation.
diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
index f5f25a0..ad77d63 100644
--- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
+++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart
@@ -530,7 +530,24 @@
     var formals = _getCanonicalTypeFormals(type.typeFormals.length);
     var normBounds =
         type.instantiateTypeBounds(formals).map(normalizeHelper).toList();
-    var normFunc = normalizeHelper(type.instantiate(formals)) as FunctionType;
+
+    // Normalize type arguments that are bounded by Never to Never at their
+    // use site in the function type signature.
+    var substitutedTypes = [];
+    for (var i = 0; i < formals.length; i++) {
+      var substitutedType = normBounds[i];
+      while (formals.contains(substitutedType)) {
+        substitutedType = normBounds[formals.indexOf(substitutedType)];
+      }
+      if (substitutedType == _never) {
+        substitutedTypes.add(_never);
+        continue;
+      }
+      substitutedTypes.add(formals[i]);
+    }
+
+    var normFunc =
+        normalizeHelper(type.instantiate(substitutedTypes)) as FunctionType;
     // Create a comparison key for structural identity.
     var typeObjectIdKey = JS('', '[]');
     JS('', '#.push(...#)', typeObjectIdKey, normBounds);
diff --git a/sdk/lib/_internal/js_runtime/lib/js_helper.dart b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
index bf335946..7e3b6f1 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
@@ -82,22 +82,6 @@
 /// them.
 abstract class InternalMap {}
 
-/// Extracts the JavaScript-constructor name from the given isCheckProperty.
-// TODO(floitsch): move this to foreign_helper.dart or similar.
-@pragma('dart2js:tryInline')
-String isCheckPropertyToJsConstructorName(String isCheckProperty) {
-  return JS_BUILTIN('returns:String;depends:none;effects:none',
-      JsBuiltin.isCheckPropertyToJsConstructorName, isCheckProperty);
-}
-
-/// Retrieves the class name from type information stored on the constructor of
-/// [type].
-// TODO(floitsch): move this to foreign_helper.dart or similar.
-@pragma('dart2js:tryInline')
-String rawRtiToJsConstructorName(Object rti) {
-  return JS_BUILTIN('String', JsBuiltin.rawRtiToJsConstructorName, rti);
-}
-
 /// Given a raw constructor name, return the unminified name, if available,
 /// otherwise tag the name with `minified:`.
 String unminifyOrTag(String rawClassName) {
@@ -107,25 +91,6 @@
   return rawClassName;
 }
 
-/// Returns the rti from the given [constructorName].
-// TODO(floitsch): make this a builtin.
-jsConstructorNameToRti(String constructorName) {
-  var getTypeFromName = JS_EMBEDDED_GLOBAL('', GET_TYPE_FROM_NAME);
-  return JS('', '#(#)', getTypeFromName, constructorName);
-}
-
-/// Returns the raw runtime type of the given object [o].
-///
-/// The argument [o] must be the interceptor for primitive types. If
-/// necessary run it through [getInterceptor] first.
-// TODO(floitsch): move this to foreign_helper.dart or similar.
-// TODO(floitsch): we should call getInterceptor ourselves, but currently
-//    getInterceptor is not GVNed.
-@pragma('dart2js:tryInline')
-Object getRawRuntimeType(Object o) {
-  return JS_BUILTIN('', JsBuiltin.rawRuntimeType, o);
-}
-
 /// Returns the metadata of the given [index].
 // TODO(floitsch): move this to foreign_helper.dart or similar.
 @pragma('dart2js:tryInline')
@@ -416,72 +381,6 @@
     return _objectTypeNameNewRti(object);
   }
 
-  static String _objectClassName(Object object) {
-    var interceptor = getInterceptor(object);
-    // The interceptor is either an object (self-intercepting plain Dart class),
-    // the prototype of the constructor for an Interceptor class (like
-    // `JSString.prototype`, `JSNull.prototype`), or an Interceptor object
-    // instance (`const JSString()`, should use `JSString.prototype`).
-    //
-    // These all should have a `constructor` property with a `name` property.
-    String? name;
-    var interceptorConstructor = JS('', '#.constructor', interceptor);
-    if (JS('bool', 'typeof # == "function"', interceptorConstructor)) {
-      var interceptorConstructorName = JS('', '#.name', interceptorConstructor);
-      if (interceptorConstructorName is String) {
-        name = interceptorConstructorName;
-      }
-    }
-
-    if (name == null ||
-        identical(interceptor, JS_INTERCEPTOR_CONSTANT(Interceptor)) ||
-        object is UnknownJavaScriptObject) {
-      // Try to do better.  If we do not find something better, leave the name
-      // as 'UnknownJavaScriptObject' or 'Interceptor' (or the minified name).
-      //
-      // When we get here via the UnknownJavaScriptObject test (for JavaScript
-      // objects from outside the program), the object's constructor has a
-      // better name that 'UnknownJavaScriptObject'.
-      //
-      // When we get here the Interceptor test (for Native classes that are
-      // declared in the Dart program but have been 'folded' into Interceptor),
-      // the native class's constructor name is better than the generic
-      // 'Interceptor' (an abstract class).
-
-      // Try the [constructorNameFallback]. This gets the constructor name for
-      // any browser (used by [getNativeInterceptor]).
-      String dispatchName = constructorNameFallback(object);
-      name ??= dispatchName;
-      if (dispatchName == 'Object') {
-        // Try to decompile the constructor by turning it into a string and get
-        // the name out of that. If the decompiled name is a string containing
-        // an identifier, we use that instead of the very generic 'Object'.
-        var objectConstructor = JS('', '#.constructor', object);
-        if (JS('bool', 'typeof # == "function"', objectConstructor)) {
-          var match = JS('var', r'#.match(/^\s*function\s*([\w$]*)\s*\(/)',
-              JS('var', r'String(#)', objectConstructor));
-          var decompiledName = match == null ? null : JS('var', r'#[1]', match);
-          if (decompiledName is String &&
-              JS('bool', r'/^\w+$/.test(#)', decompiledName)) {
-            name = decompiledName;
-          }
-        }
-      }
-      return JS('String', '#', name);
-    }
-
-    // Type inference does not understand that [name] is now always a non-null
-    // String. (There is some imprecision in the negation of the disjunction.)
-    name = JS<String>('String', '#', name);
-
-    // TODO(kasperl): If the namer gave us a fresh global name, we may
-    // want to remove the numeric suffix that makes it unique too.
-    if (name.length > 1 && identical(name.codeUnitAt(0), DOLLAR_CHAR_VALUE)) {
-      name = name.substring(1);
-    }
-    return unminifyOrTag(name);
-  }
-
   /// Returns the type of [object] as a string (including type arguments).
   /// Tries to return a sensible name for non-Dart objects.
   ///
@@ -1261,18 +1160,10 @@
   JS('void', 'throw #', wrapException(ex));
 }
 
-throwRuntimeError(message) {
-  throw new RuntimeError(message);
-}
-
 throwUnsupportedError(message) {
   throw new UnsupportedError(message);
 }
 
-throwAbstractClassInstantiationError(className) {
-  throw new AbstractClassInstantiationError(className);
-}
-
 // This is used in open coded for-in loops on arrays.
 //
 //     checkConcurrentModificationError(a.length == startLength, a)
@@ -2138,45 +2029,6 @@
     return constructor;
   }
 
-  static _computeSignatureFunctionLegacy(
-      Object functionType, bool isStatic, bool isIntercepted) {
-    if (JS('bool', 'typeof # == "number"', functionType)) {
-      // We cannot call [getType] here, since the types-metadata might not be
-      // set yet. This is, because fromTearOff might be called for constants
-      // when the program isn't completely set up yet.
-      //
-      // Note that we cannot just textually inline the call
-      // `getType(functionType)` since we cannot guarantee that the (then)
-      // captured variable `functionType` isn't reused.
-      return JS(
-          '',
-          '''(function(getType, t) {
-                    return function(){ return getType(t); };
-                })(#, #)''',
-          RAW_DART_FUNCTION_REF(getType),
-          functionType);
-    }
-    if (JS('bool', 'typeof # == "function"', functionType)) {
-      if (isStatic) {
-        return functionType;
-      } else {
-        var getReceiver = isIntercepted
-            ? RAW_DART_FUNCTION_REF(BoundClosure.receiverOf)
-            : RAW_DART_FUNCTION_REF(BoundClosure.selfOf);
-        return JS(
-            '',
-            'function(f,r){'
-                'return function(){'
-                'return f.apply({\$receiver:r(this)},arguments)'
-                '}'
-                '}(#,#)',
-            functionType,
-            getReceiver);
-      }
-    }
-    throw 'Error in functionType of tearoff';
-  }
-
   static _computeSignatureFunctionNewRti(
       Object functionType, bool isStatic, bool isIntercepted) {
     if (JS('bool', 'typeof # == "number"', functionType)) {
diff --git a/sdk/lib/_internal/js_runtime/lib/shared/embedded_names.dart b/sdk/lib/_internal/js_runtime/lib/shared/embedded_names.dart
index c50d99c..e80fb6a 100644
--- a/sdk/lib/_internal/js_runtime/lib/shared/embedded_names.dart
+++ b/sdk/lib/_internal/js_runtime/lib/shared/embedded_names.dart
@@ -11,29 +11,6 @@
 /// This library is shared between the compiler and the runtime system.
 library dart2js._embedded_names;
 
-/// The name of the property that is used to mark a type as typedef.
-///
-/// Without reflection typedefs are removed (expanded to their function type)
-/// but with reflection an object is needed to have the typedef's name. The
-/// object is marked with this property.
-///
-/// This property name only lives on internal type-objects and is only used
-/// when reflection is enabled.
-const TYPEDEF_PREDICATE_PROPERTY_NAME = r"$$isTypedef";
-
-/// The name of the property that is used to find the function type of a
-/// typedef.
-///
-/// Without reflection typedefs are removed (expanded to their function type)
-/// but with reflection an object is needed to have the typedef's name.
-///
-/// The typedef's object contains a pointer to its function type (as an index
-/// into the embedded global [TYPES]) in this property.
-///
-/// This property name only lives on internal type-objects and is only used
-/// when reflection is enabled.
-const TYPEDEF_TYPE_PROPERTY_NAME = r"$typedefType";
-
 /// The name of the property that is used to find the native superclass of
 /// an extended class.
 ///
@@ -206,51 +183,6 @@
 /// This embedded global is used for --experiment-new-rti.
 const RTI_UNIVERSE = 'typeUniverse';
 
-/// Returns a function that creates all precompiled functions (in particular
-/// constructors).
-///
-/// That is, the function returns the array that the full emitter would
-/// otherwise build dynamically when it finishes all classes.
-///
-/// This constant is only used in CSP mode.
-///
-/// This global is an emitter-internal embedded global, and not used by the
-/// runtime. The constant remains in this file to make sure that other embedded
-/// globals don't clash with it.
-const PRECOMPILED = 'precompiled';
-
-/// An emitter-internal embedded global. This global is not used by the runtime.
-const FINISHED_CLASSES = 'finishedClasses';
-
-/// A JavaScript object literal that maps the (minified) JavaScript constructor
-/// name (as given by [JsBuiltin.rawRtiToJsConstructorName] to the
-/// JavaScript constructor.
-///
-/// This embedded global is only used by reflection.
-const ALL_CLASSES = 'allClasses';
-
-/// A map from element to type information.
-///
-/// This embedded global is only used by reflection.
-const TYPE_INFORMATION = 'typeInformation';
-
-/// A map from statics to their descriptors.
-///
-/// This embedded global is only used by reflection.
-const STATICS = 'statics';
-
-/// An array of library descriptors.
-///
-/// The descriptor contains information such as name, uri, classes, ...
-///
-/// This embedded global is only used by reflection.
-const LIBRARIES = 'libraries';
-
-/// A map from lazy statics to their initializers.
-///
-/// This embedded global is only used by reflection.
-const LAZIES = 'lazies';
-
 /// Names that are supported by [JS_GET_NAME].
 // TODO(herhut): Make entries lower case (as in fields) and find a better name.
 enum JsGetName {
@@ -264,8 +196,6 @@
   CALL_PREFIX4,
   CALL_PREFIX5,
   CALL_CATCH_ALL,
-  REFLECTABLE,
-  CLASS_DESCRIPTOR_PROPERTY,
   REQUIRED_PARAMETER_PROPERTY,
   DEFAULT_VALUES_PROPERTY,
   CALL_NAME_PROPERTY,
@@ -297,12 +227,6 @@
   /// String representation of the type of the object class.
   OBJECT_CLASS_TYPE_NAME,
 
-  /// String representation of the type of the function class.
-  FUNCTION_CLASS_TYPE_NAME,
-
-  /// String representation of the type of the JavaScriptFunction class.
-  JS_FUNCTION_CLASS_TYPE_NAME,
-
   /// Property name for Rti._as field.
   RTI_FIELD_AS,
 
@@ -328,34 +252,12 @@
   ///       ...
   dartClosureConstructor,
 
-  /// Returns the JavaScript-constructor name given an [isCheckProperty].
-  ///
-  /// This relies on a deterministic encoding of is-check properties (for
-  /// example `$isFoo` for a class `Foo`). In minified code the returned
-  /// classname is the minified name of the class.
-  ///
-  ///     JS_BUILTIN('returns:String;depends:none;effects:none',
-  ///                JsBuiltin.isCheckPropertyToJsConstructorName,
-  ///                isCheckProperty);
-  isCheckPropertyToJsConstructorName,
-
   /// Returns true if the given type is a type argument of a js-interop class
   /// or a supertype of a js-interop class.
   ///
   ///     JS_BUILTIN('bool', JsBuiltin.isJsInteropTypeArgument, o)
   isJsInteropTypeArgument,
 
-  /// Returns the JavaScript-constructor name given an rti encoding.
-  ///
-  ///     JS_BUILTIN('String', JsBuiltin.rawRtiToJsConstructorName, rti)
-  rawRtiToJsConstructorName,
-
-  /// Returns the raw runtime type of the given object. The given argument
-  /// [o] should be the interceptor (for non-Dart objects).
-  ///
-  ///     JS_BUILTIN('', JsBuiltin.rawRuntimeType, o)
-  rawRuntimeType,
-
   /// Returns the metadata of the given [index].
   ///
   ///     JS_BUILTIN('returns:var;effects:none;depends:none',
diff --git a/sdk/lib/_internal/vm/lib/ffi_patch.dart b/sdk/lib/_internal/vm/lib/ffi_patch.dart
index 735c7e2..a04c737 100644
--- a/sdk/lib/_internal/vm/lib/ffi_patch.dart
+++ b/sdk/lib/_internal/vm/lib/ffi_patch.dart
@@ -68,7 +68,7 @@
 // Function objects returned by this native method are not Dart instances,
 // so we need to use top type as a return type to avoid type check.
 dynamic _nativeCallbackFunction<NS extends Function>(Function target,
-    Object exceptionalReturn) native "Ffi_nativeCallbackFunction";
+    Object? exceptionalReturn) native "Ffi_nativeCallbackFunction";
 
 Pointer<NS> _pointerFromFunction<NS extends NativeFunction>(dynamic function)
     native "Ffi_pointerFromFunction";
diff --git a/sdk/lib/_internal/vm/lib/mirrors_impl.dart b/sdk/lib/_internal/vm/lib/mirrors_impl.dart
index a7f1f13..712d2c8 100644
--- a/sdk/lib/_internal/vm/lib/mirrors_impl.dart
+++ b/sdk/lib/_internal/vm/lib/mirrors_impl.dart
@@ -1160,7 +1160,7 @@
 }
 
 class _MethodMirror extends _DeclarationMirror implements MethodMirror {
-  final Type _instantiator;
+  final Type? _instantiator;
   final bool isStatic;
   final int _kindFlags;
 
@@ -1353,7 +1353,7 @@
             false // Not extension member.
             );
 
-  Object _defaultValueReflectee;
+  Object? _defaultValueReflectee;
   InstanceMirror? _defaultValue;
   InstanceMirror? get defaultValue {
     if (!isOptional) {
diff --git a/sdk/lib/_internal/vm/lib/string_patch.dart b/sdk/lib/_internal/vm/lib/string_patch.dart
index 55fc053..5d6612d 100644
--- a/sdk/lib/_internal/vm/lib/string_patch.dart
+++ b/sdk/lib/_internal/vm/lib/string_patch.dart
@@ -824,7 +824,7 @@
 
   // Convert single object to string.
   @pragma("vm:entry-point", "call")
-  static String _interpolateSingle(Object o) {
+  static String _interpolateSingle(Object? o) {
     if (o is String) return o;
     final s = o.toString();
     if (s is! String) {
diff --git a/tests/dart2js/internal/mock_libraries.dart b/tests/dart2js/internal/mock_libraries.dart
index 28f6f01..f747443 100644
--- a/tests/dart2js/internal/mock_libraries.dart
+++ b/tests/dart2js/internal/mock_libraries.dart
@@ -275,8 +275,6 @@
   'stringTypeCheck': 'stringTypeCheck(x) {}',
   'subtypeCast': 'subtypeCast(object, isField, checks, asField) {}',
   'subtypeOfRuntimeTypeCast': 'subtypeOfRuntimeTypeCast(object, type) {}',
-  'throwAbstractClassInstantiationError':
-      'throwAbstractClassInstantiationError(className) {}',
   'checkConcurrentModificationError':
       'checkConcurrentModificationError(collection) {}',
   'throwConcurrentModificationError':
@@ -285,7 +283,6 @@
   'throwExpression': 'throwExpression(e) {}',
   'throwNoSuchMethod':
       'throwNoSuchMethod(obj, name, arguments, expectedArgumentNames) {}',
-  'throwRuntimeError': 'throwRuntimeError(message) {}',
   'throwUnsupportedError': 'throwUnsupportedError(message) {}',
   'throwTypeError': 'throwTypeError(message) {}',
   'unwrapException': 'unwrapException(e) {}',
diff --git a/tests/dart2js_2/internal/mock_libraries.dart b/tests/dart2js_2/internal/mock_libraries.dart
index edd762b..adec88a 100644
--- a/tests/dart2js_2/internal/mock_libraries.dart
+++ b/tests/dart2js_2/internal/mock_libraries.dart
@@ -234,8 +234,6 @@
   'S': 'S() {}',
   'setRuntimeTypeInfo': 'setRuntimeTypeInfo(a, b) {}',
   'subtypeOfRuntimeTypeCast': 'subtypeOfRuntimeTypeCast(object, type) {}',
-  'throwAbstractClassInstantiationError':
-      'throwAbstractClassInstantiationError(className) {}',
   'checkConcurrentModificationError':
       'checkConcurrentModificationError(collection) {}',
   'throwConcurrentModificationError':
@@ -244,7 +242,6 @@
   'throwExpression': 'throwExpression(e) {}',
   'throwNoSuchMethod':
       'throwNoSuchMethod(obj, name, arguments, expectedArgumentNames) {}',
-  'throwRuntimeError': 'throwRuntimeError(message) {}',
   'throwUnsupportedError': 'throwUnsupportedError(message) {}',
   'unwrapException': 'unwrapException(e) {}',
   'voidTypeCheck': 'voidTypeCheck(value) {}',
diff --git a/tests/language/covariant/subtyping_test.dart b/tests/language/covariant/subtyping_test.dart
index 51aa58f..43d665e 100644
--- a/tests/language/covariant/subtyping_test.dart
+++ b/tests/language/covariant/subtyping_test.dart
@@ -217,20 +217,25 @@
   method7(T Function() Function() returnsReturnsT) => null; // needs check
 }
 
+typedef F1 = dynamic Function(Object?);
+typedef F2 = dynamic Function(dynamic Function(int));
+typedef F3 = dynamic Function(dynamic Function(int Function()));
+typedef F4 = dynamic Function(dynamic Function(int) Function());
+
 testTearOffRuntimeType() {
-  expectRTTI(tearoff, type) => Expect.equals('${tearoff.runtimeType}', type,
+  expectRTTI(tearoff, type) => Expect.equals(tearoff.runtimeType, type,
       'covariant params should reify with Object? as their type');
 
   TearOff<num> t = new TearOff<int>();
-  expectRTTI(t.method1, '(Object?) => dynamic');
+  expectRTTI(t.method1, F1);
 
-  expectRTTI(t.method2, '((int) => dynamic) => dynamic');
-  expectRTTI(t.method3, '(Object?) => dynamic');
+  expectRTTI(t.method2, F2);
+  expectRTTI(t.method3, F1);
 
-  expectRTTI(t.method4, '(Object?) => dynamic');
-  expectRTTI(t.method5, '((() => int) => dynamic) => dynamic');
-  expectRTTI(t.method6, '(() => (int) => dynamic) => dynamic');
-  expectRTTI(t.method7, '(Object?) => dynamic');
+  expectRTTI(t.method4, F1);
+  expectRTTI(t.method5, F3);
+  expectRTTI(t.method6, F4);
+  expectRTTI(t.method7, F1);
 }
 
 main() {
diff --git a/tests/language/interface/implements_futureor_test.dart b/tests/language/interface/implements_futureor_test.dart
index 1ec6779..abe2e64 100644
--- a/tests/language/interface/implements_futureor_test.dart
+++ b/tests/language/interface/implements_futureor_test.dart
@@ -6,7 +6,7 @@
 
 class A<T> implements FutureOr<T> {}
 //                    ^^^^^^^^^^^
-// [analyzer] COMPILE_TIME_ERROR.IMPLEMENTS_DISALLOWED_CLASS
+// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_DISALLOWED_TYPE
 //    ^
 // [cfe] The type 'FutureOr' can't be used in an 'implements' clause.
 
diff --git a/tests/language/null_aware/access_runtime_1_test.dart b/tests/language/null_aware/access_runtime_1_test.dart
new file mode 100644
index 0000000..ba92ba5
--- /dev/null
+++ b/tests/language/null_aware/access_runtime_1_test.dart
@@ -0,0 +1,58 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it does not appear on the LHS of an
+// assignment.
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+class B {}
+
+class C extends B {
+  int? v;
+  C(this.v);
+  static int? staticInt;
+}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if property access using "?." is not
+  // implemented.  This makes status files easier to maintain.
+  nullC()?.v;
+
+  // e1?.id is equivalent to ((x) => x == null ? null : x.id)(e1).
+  Expect.equals(null, nullC()?.v);
+
+
+  // C?.id is equivalent to C.id.
+
+
+
+  // The static type of e1?.d is the static type of e1.id.
+
+
+
+
+
+
+
+  // Let T be the static type of e1 and let y be a fresh variable of type T.
+  // Exactly the same static warnings that would be caused by y.id are also
+  // generated in the case of e1?.id.
+
+
+
+  // '?.' cannot be used to access toplevel properties in libraries imported via
+  // prefix.
+
+
+  // Nor can it be used to access the hashCode getter on the class Type.
+
+
+}
diff --git a/tests/language/null_aware/access_runtime_2_test.dart b/tests/language/null_aware/access_runtime_2_test.dart
new file mode 100644
index 0000000..b67de99
--- /dev/null
+++ b/tests/language/null_aware/access_runtime_2_test.dart
@@ -0,0 +1,59 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it does not appear on the LHS of an
+// assignment.
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+class B {}
+
+class C extends B {
+  int? v;
+  C(this.v);
+  static int? staticInt;
+}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if property access using "?." is not
+  // implemented.  This makes status files easier to maintain.
+  nullC()?.v;
+
+  // e1?.id is equivalent to ((x) => x == null ? null : x.id)(e1).
+
+  C? c = new C(1);
+  Expect.equals(1, c?.v);
+
+  // C?.id is equivalent to C.id.
+
+
+
+  // The static type of e1?.d is the static type of e1.id.
+
+
+
+
+
+
+
+  // Let T be the static type of e1 and let y be a fresh variable of type T.
+  // Exactly the same static warnings that would be caused by y.id are also
+  // generated in the case of e1?.id.
+
+
+
+  // '?.' cannot be used to access toplevel properties in libraries imported via
+  // prefix.
+
+
+  // Nor can it be used to access the hashCode getter on the class Type.
+
+
+}
diff --git a/tests/language/null_aware/access_runtime_3_test.dart b/tests/language/null_aware/access_runtime_3_test.dart
new file mode 100644
index 0000000..633aa36
--- /dev/null
+++ b/tests/language/null_aware/access_runtime_3_test.dart
@@ -0,0 +1,58 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it does not appear on the LHS of an
+// assignment.
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+class B {}
+
+class C extends B {
+  int? v;
+  C(this.v);
+  static int? staticInt;
+}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if property access using "?." is not
+  // implemented.  This makes status files easier to maintain.
+  nullC()?.v;
+
+  // e1?.id is equivalent to ((x) => x == null ? null : x.id)(e1).
+
+
+
+  // C?.id is equivalent to C.id.
+  { C.staticInt = 1; Expect.equals(1, C?.staticInt); }
+
+
+  // The static type of e1?.d is the static type of e1.id.
+
+
+
+
+
+
+
+  // Let T be the static type of e1 and let y be a fresh variable of type T.
+  // Exactly the same static warnings that would be caused by y.id are also
+  // generated in the case of e1?.id.
+
+
+
+  // '?.' cannot be used to access toplevel properties in libraries imported via
+  // prefix.
+
+
+  // Nor can it be used to access the hashCode getter on the class Type.
+
+
+}
diff --git a/tests/language/null_aware/access_runtime_4_test.dart b/tests/language/null_aware/access_runtime_4_test.dart
new file mode 100644
index 0000000..96462c6
--- /dev/null
+++ b/tests/language/null_aware/access_runtime_4_test.dart
@@ -0,0 +1,58 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it does not appear on the LHS of an
+// assignment.
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+class B {}
+
+class C extends B {
+  int? v;
+  C(this.v);
+  static int? staticInt;
+}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if property access using "?." is not
+  // implemented.  This makes status files easier to maintain.
+  nullC()?.v;
+
+  // e1?.id is equivalent to ((x) => x == null ? null : x.id)(e1).
+
+
+
+  // C?.id is equivalent to C.id.
+
+  { h.C.staticInt = 1; Expect.equals(1, h.C?.staticInt); }
+
+  // The static type of e1?.d is the static type of e1.id.
+
+
+
+
+
+
+
+  // Let T be the static type of e1 and let y be a fresh variable of type T.
+  // Exactly the same static warnings that would be caused by y.id are also
+  // generated in the case of e1?.id.
+
+
+
+  // '?.' cannot be used to access toplevel properties in libraries imported via
+  // prefix.
+
+
+  // Nor can it be used to access the hashCode getter on the class Type.
+
+
+}
diff --git a/tests/language/null_aware/access_runtime_5_test.dart b/tests/language/null_aware/access_runtime_5_test.dart
new file mode 100644
index 0000000..5984802
--- /dev/null
+++ b/tests/language/null_aware/access_runtime_5_test.dart
@@ -0,0 +1,59 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it does not appear on the LHS of an
+// assignment.
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+class B {}
+
+class C extends B {
+  int? v;
+  C(this.v);
+  static int? staticInt;
+}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if property access using "?." is not
+  // implemented.  This makes status files easier to maintain.
+  nullC()?.v;
+
+  // e1?.id is equivalent to ((x) => x == null ? null : x.id)(e1).
+
+
+
+  // C?.id is equivalent to C.id.
+
+
+
+  // The static type of e1?.d is the static type of e1.id.
+  C? c = new C(1);
+  { int? i = c?.v; Expect.equals(1, i); }
+
+
+
+
+
+
+  // Let T be the static type of e1 and let y be a fresh variable of type T.
+  // Exactly the same static warnings that would be caused by y.id are also
+  // generated in the case of e1?.id.
+
+
+
+  // '?.' cannot be used to access toplevel properties in libraries imported via
+  // prefix.
+
+
+  // Nor can it be used to access the hashCode getter on the class Type.
+
+
+}
diff --git a/tests/language/null_aware/access_runtime_6_test.dart b/tests/language/null_aware/access_runtime_6_test.dart
new file mode 100644
index 0000000..5b4a999
--- /dev/null
+++ b/tests/language/null_aware/access_runtime_6_test.dart
@@ -0,0 +1,58 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it does not appear on the LHS of an
+// assignment.
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+class B {}
+
+class C extends B {
+  int? v;
+  C(this.v);
+  static int? staticInt;
+}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if property access using "?." is not
+  // implemented.  This makes status files easier to maintain.
+  nullC()?.v;
+
+  // e1?.id is equivalent to ((x) => x == null ? null : x.id)(e1).
+
+
+
+  // C?.id is equivalent to C.id.
+
+
+
+  // The static type of e1?.d is the static type of e1.id.
+
+
+  { C.staticInt = 1; int? i = C?.staticInt; Expect.equals(1, i); }
+
+
+
+
+  // Let T be the static type of e1 and let y be a fresh variable of type T.
+  // Exactly the same static warnings that would be caused by y.id are also
+  // generated in the case of e1?.id.
+
+
+
+  // '?.' cannot be used to access toplevel properties in libraries imported via
+  // prefix.
+
+
+  // Nor can it be used to access the hashCode getter on the class Type.
+
+
+}
diff --git a/tests/language/null_aware/access_runtime_7_test.dart b/tests/language/null_aware/access_runtime_7_test.dart
new file mode 100644
index 0000000..7f53dc1
--- /dev/null
+++ b/tests/language/null_aware/access_runtime_7_test.dart
@@ -0,0 +1,58 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it does not appear on the LHS of an
+// assignment.
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+class B {}
+
+class C extends B {
+  int? v;
+  C(this.v);
+  static int? staticInt;
+}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if property access using "?." is not
+  // implemented.  This makes status files easier to maintain.
+  nullC()?.v;
+
+  // e1?.id is equivalent to ((x) => x == null ? null : x.id)(e1).
+
+
+
+  // C?.id is equivalent to C.id.
+
+
+
+  // The static type of e1?.d is the static type of e1.id.
+
+
+
+  { h.C.staticInt = 1; int? i = h.C?.staticInt; Expect.equals(1, i); }
+
+
+
+  // Let T be the static type of e1 and let y be a fresh variable of type T.
+  // Exactly the same static warnings that would be caused by y.id are also
+  // generated in the case of e1?.id.
+
+
+
+  // '?.' cannot be used to access toplevel properties in libraries imported via
+  // prefix.
+
+
+  // Nor can it be used to access the hashCode getter on the class Type.
+
+
+}
diff --git a/tests/language/null_aware/access_runtime_test.dart b/tests/language/null_aware/access_runtime_test.dart
new file mode 100644
index 0000000..5d8a2c8
--- /dev/null
+++ b/tests/language/null_aware/access_runtime_test.dart
@@ -0,0 +1,58 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it does not appear on the LHS of an
+// assignment.
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+class B {}
+
+class C extends B {
+  int? v;
+  C(this.v);
+  static int? staticInt;
+}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if property access using "?." is not
+  // implemented.  This makes status files easier to maintain.
+  nullC()?.v;
+
+  // e1?.id is equivalent to ((x) => x == null ? null : x.id)(e1).
+
+
+
+  // C?.id is equivalent to C.id.
+
+
+
+  // The static type of e1?.d is the static type of e1.id.
+
+
+
+
+
+
+
+  // Let T be the static type of e1 and let y be a fresh variable of type T.
+  // Exactly the same static warnings that would be caused by y.id are also
+  // generated in the case of e1?.id.
+
+
+
+  // '?.' cannot be used to access toplevel properties in libraries imported via
+  // prefix.
+
+
+  // Nor can it be used to access the hashCode getter on the class Type.
+
+
+}
diff --git a/tests/language/null_aware/access_test.dart b/tests/language/null_aware/access_test.dart
new file mode 100644
index 0000000..deaa991
--- /dev/null
+++ b/tests/language/null_aware/access_test.dart
@@ -0,0 +1,88 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it does not appear on the LHS of an
+// assignment.
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+class B {}
+
+class C extends B {
+  int? v;
+  C(this.v);
+  static int? staticInt;
+}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if property access using "?." is not
+  // implemented.  This makes status files easier to maintain.
+  nullC()?.v;
+
+  // e1?.id is equivalent to ((x) => x == null ? null : x.id)(e1).
+  Expect.equals(null, nullC()?.v);
+  Expect.equals(1, new C(1)?.v);
+  //                       ^^
+  // [analyzer] STATIC_WARNING.INVALID_NULL_AWARE_OPERATOR
+
+  // C?.id is equivalent to C.id.
+  { C.staticInt = 1; Expect.equals(1, C?.staticInt); }
+  { h.C.staticInt = 1; Expect.equals(1, h.C?.staticInt); }
+
+  // The static type of e1?.d is the static type of e1.id.
+  { int? i = new C(1)?.v; Expect.equals(1, i); }
+  //                 ^^
+  // [analyzer] STATIC_WARNING.INVALID_NULL_AWARE_OPERATOR
+  { String? s = new C(null)?.v; Expect.equals(null, s); }
+  //            ^^^^^^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+  //                ^
+  // [cfe] A value of type 'int?' can't be assigned to a variable of type 'String?'.
+  //                       ^^
+  // [analyzer] STATIC_WARNING.INVALID_NULL_AWARE_OPERATOR
+  { C.staticInt = 1; int? i = C?.staticInt; Expect.equals(1, i); }
+  { h.C.staticInt = 1; int? i = h.C?.staticInt; Expect.equals(1, i); }
+  { C.staticInt = null; String? s = C?.staticInt; Expect.equals(null, s); }
+  //                                ^^^^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+  //                                   ^
+  // [cfe] A value of type 'int?' can't be assigned to a variable of type 'String?'.
+  { h.C.staticNullable = null; String? s = h.C?.staticNullable; Expect.equals(null, s); }
+  //                                       ^^^^^^^^^^^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+  //                                            ^
+  // [cfe] A value of type 'int?' can't be assigned to a variable of type 'String?'.
+
+  // Let T be the static type of e1 and let y be a fresh variable of type T.
+  // Exactly the same static warnings that would be caused by y.id are also
+  // generated in the case of e1?.id.
+  Expect.equals(null, nullC()?.bad);
+  //                           ^^^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] The getter 'bad' isn't defined for the class 'C'.
+  { B? b = new C(1); Expect.equals(1, b?.v); }
+  //                                     ^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] The getter 'v' isn't defined for the class 'B'.
+
+  // '?.' cannot be used to access toplevel properties in libraries imported via
+  // prefix.
+  var x = h?.topLevelVar;
+  //      ^
+  // [analyzer] COMPILE_TIME_ERROR.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT
+  // [cfe] A prefix can't be used with null-aware operators.
+
+  // Nor can it be used to access the hashCode getter on the class Type.
+  Expect.throwsNoSuchMethodError(() => C?.hashCode);
+  //                                      ^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] Getter not found: 'hashCode'.
+  Expect.throwsNoSuchMethodError(() => h.C?.hashCode);
+  //                                        ^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] Getter not found: 'hashCode'.
+}
diff --git a/tests/language/null_aware/assignment_runtime_10_test.dart b/tests/language/null_aware/assignment_runtime_10_test.dart
new file mode 100644
index 0000000..91abae7
--- /dev/null
+++ b/tests/language/null_aware/assignment_runtime_10_test.dart
@@ -0,0 +1,101 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears on the LHS of an
+// assignment.
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+bad() {
+  Expect.fail('Should not be executed');
+}
+
+class B {}
+
+class C extends B {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v = e2 is equivalent to ((x) => x == null ? null : x.v = e2)(e1).
+
+
+
+  // C?.v = e2 is equivalent to C.v = e2.
+
+
+
+  // The static type of e1?.v = e2 is the static type of e2.
+
+
+
+
+
+
+
+  // Exactly the same errors that would be caused by e1.v = e2 are
+  // also generated in the case of e1?.v = e2.
+
+
+
+  // e1?.v op= e2 is equivalent to ((x) => x?.v = x.v op e2)(e1).
+
+
+
+  // C?.v op= e2 is equivalent to C.v op= e2.
+  { C.staticInt = 1; Expect.equals(3, C?.staticInt += 2); Expect.equals(3, C?.staticInt); }
+
+  // The static type of e1?.v op= e2 is the static type of e1.v op e2.
+
+
+
+
+  // Let T be the static type of e1 and let y be a fresh variable of type T.
+  // Exactly the same errors that would be caused by y.v op e2 are
+  // also generated in the case of e1?.v op= e2.
+
+
+
+
+
+
+
+
+
+  // '?.' cannot be used to assign to toplevel properties in libraries imported
+  // via prefix.
+
+
+
+}
diff --git a/tests/language/null_aware/assignment_runtime_11_test.dart b/tests/language/null_aware/assignment_runtime_11_test.dart
new file mode 100644
index 0000000..05b84a6
--- /dev/null
+++ b/tests/language/null_aware/assignment_runtime_11_test.dart
@@ -0,0 +1,101 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears on the LHS of an
+// assignment.
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+bad() {
+  Expect.fail('Should not be executed');
+}
+
+class B {}
+
+class C extends B {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v = e2 is equivalent to ((x) => x == null ? null : x.v = e2)(e1).
+
+
+
+  // C?.v = e2 is equivalent to C.v = e2.
+
+
+
+  // The static type of e1?.v = e2 is the static type of e2.
+
+
+
+
+
+
+
+  // Exactly the same errors that would be caused by e1.v = e2 are
+  // also generated in the case of e1?.v = e2.
+
+
+
+  // e1?.v op= e2 is equivalent to ((x) => x?.v = x.v op e2)(e1).
+
+
+
+  // C?.v op= e2 is equivalent to C.v op= e2.
+
+
+  // The static type of e1?.v op= e2 is the static type of e1.v op e2.
+  { D? d = new D(new E()); F? f = (d?.v += 1); Expect.identical(d!.v, f); }
+
+
+
+  // Let T be the static type of e1 and let y be a fresh variable of type T.
+  // Exactly the same errors that would be caused by y.v op e2 are
+  // also generated in the case of e1?.v op= e2.
+
+
+
+
+
+
+
+
+
+  // '?.' cannot be used to assign to toplevel properties in libraries imported
+  // via prefix.
+
+
+
+}
diff --git a/tests/language/null_aware/assignment_runtime_12_test.dart b/tests/language/null_aware/assignment_runtime_12_test.dart
new file mode 100644
index 0000000..c17f848
--- /dev/null
+++ b/tests/language/null_aware/assignment_runtime_12_test.dart
@@ -0,0 +1,101 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears on the LHS of an
+// assignment.
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+bad() {
+  Expect.fail('Should not be executed');
+}
+
+class B {}
+
+class C extends B {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v = e2 is equivalent to ((x) => x == null ? null : x.v = e2)(e1).
+
+
+
+  // C?.v = e2 is equivalent to C.v = e2.
+
+
+
+  // The static type of e1?.v = e2 is the static type of e2.
+
+
+
+
+
+
+
+  // Exactly the same errors that would be caused by e1.v = e2 are
+  // also generated in the case of e1?.v = e2.
+
+
+
+  // e1?.v op= e2 is equivalent to ((x) => x?.v = x.v op e2)(e1).
+
+
+
+  // C?.v op= e2 is equivalent to C.v op= e2.
+
+
+  // The static type of e1?.v op= e2 is the static type of e1.v op e2.
+
+  { D.staticE = new E(); F? f = (D?.staticE += 1); Expect.identical(D.staticE, f); }
+
+
+  // Let T be the static type of e1 and let y be a fresh variable of type T.
+  // Exactly the same errors that would be caused by y.v op e2 are
+  // also generated in the case of e1?.v op= e2.
+
+
+
+
+
+
+
+
+
+  // '?.' cannot be used to assign to toplevel properties in libraries imported
+  // via prefix.
+
+
+
+}
diff --git a/tests/language/null_aware/assignment_runtime_13_test.dart b/tests/language/null_aware/assignment_runtime_13_test.dart
new file mode 100644
index 0000000..961aff3
--- /dev/null
+++ b/tests/language/null_aware/assignment_runtime_13_test.dart
@@ -0,0 +1,101 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears on the LHS of an
+// assignment.
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+bad() {
+  Expect.fail('Should not be executed');
+}
+
+class B {}
+
+class C extends B {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v = e2 is equivalent to ((x) => x == null ? null : x.v = e2)(e1).
+
+
+
+  // C?.v = e2 is equivalent to C.v = e2.
+
+
+
+  // The static type of e1?.v = e2 is the static type of e2.
+
+
+
+
+
+
+
+  // Exactly the same errors that would be caused by e1.v = e2 are
+  // also generated in the case of e1?.v = e2.
+
+
+
+  // e1?.v op= e2 is equivalent to ((x) => x?.v = x.v op e2)(e1).
+
+
+
+  // C?.v op= e2 is equivalent to C.v op= e2.
+
+
+  // The static type of e1?.v op= e2 is the static type of e1.v op e2.
+
+
+  { h.D.staticE = new h.E(); h.F? f = (h.D?.staticE += 1); Expect.identical(h.D.staticE, f); }
+
+  // Let T be the static type of e1 and let y be a fresh variable of type T.
+  // Exactly the same errors that would be caused by y.v op e2 are
+  // also generated in the case of e1?.v op= e2.
+
+
+
+
+
+
+
+
+
+  // '?.' cannot be used to assign to toplevel properties in libraries imported
+  // via prefix.
+
+
+
+}
diff --git a/tests/language/null_aware/assignment_runtime_1_test.dart b/tests/language/null_aware/assignment_runtime_1_test.dart
new file mode 100644
index 0000000..121302d
--- /dev/null
+++ b/tests/language/null_aware/assignment_runtime_1_test.dart
@@ -0,0 +1,101 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears on the LHS of an
+// assignment.
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+bad() {
+  Expect.fail('Should not be executed');
+}
+
+class B {}
+
+class C extends B {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v = e2 is equivalent to ((x) => x == null ? null : x.v = e2)(e1).
+  Expect.equals(null, nullC()?.v = bad());
+
+
+  // C?.v = e2 is equivalent to C.v = e2.
+
+
+
+  // The static type of e1?.v = e2 is the static type of e2.
+
+
+
+
+
+
+
+  // Exactly the same errors that would be caused by e1.v = e2 are
+  // also generated in the case of e1?.v = e2.
+
+
+
+  // e1?.v op= e2 is equivalent to ((x) => x?.v = x.v op e2)(e1).
+
+
+
+  // C?.v op= e2 is equivalent to C.v op= e2.
+
+
+  // The static type of e1?.v op= e2 is the static type of e1.v op e2.
+
+
+
+
+  // Let T be the static type of e1 and let y be a fresh variable of type T.
+  // Exactly the same errors that would be caused by y.v op e2 are
+  // also generated in the case of e1?.v op= e2.
+
+
+
+
+
+
+
+
+
+  // '?.' cannot be used to assign to toplevel properties in libraries imported
+  // via prefix.
+
+
+
+}
diff --git a/tests/language/null_aware/assignment_runtime_2_test.dart b/tests/language/null_aware/assignment_runtime_2_test.dart
new file mode 100644
index 0000000..825bfc6
--- /dev/null
+++ b/tests/language/null_aware/assignment_runtime_2_test.dart
@@ -0,0 +1,101 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears on the LHS of an
+// assignment.
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+bad() {
+  Expect.fail('Should not be executed');
+}
+
+class B {}
+
+class C extends B {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v = e2 is equivalent to ((x) => x == null ? null : x.v = e2)(e1).
+
+  { C? c = new C(1); Expect.equals(2, c?.v = 2); Expect.equals(2, c!.v); }
+
+  // C?.v = e2 is equivalent to C.v = e2.
+
+
+
+  // The static type of e1?.v = e2 is the static type of e2.
+
+
+
+
+
+
+
+  // Exactly the same errors that would be caused by e1.v = e2 are
+  // also generated in the case of e1?.v = e2.
+
+
+
+  // e1?.v op= e2 is equivalent to ((x) => x?.v = x.v op e2)(e1).
+
+
+
+  // C?.v op= e2 is equivalent to C.v op= e2.
+
+
+  // The static type of e1?.v op= e2 is the static type of e1.v op e2.
+
+
+
+
+  // Let T be the static type of e1 and let y be a fresh variable of type T.
+  // Exactly the same errors that would be caused by y.v op e2 are
+  // also generated in the case of e1?.v op= e2.
+
+
+
+
+
+
+
+
+
+  // '?.' cannot be used to assign to toplevel properties in libraries imported
+  // via prefix.
+
+
+
+}
diff --git a/tests/language/null_aware/assignment_runtime_3_test.dart b/tests/language/null_aware/assignment_runtime_3_test.dart
new file mode 100644
index 0000000..bc50d98
--- /dev/null
+++ b/tests/language/null_aware/assignment_runtime_3_test.dart
@@ -0,0 +1,101 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears on the LHS of an
+// assignment.
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+bad() {
+  Expect.fail('Should not be executed');
+}
+
+class B {}
+
+class C extends B {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v = e2 is equivalent to ((x) => x == null ? null : x.v = e2)(e1).
+
+
+
+  // C?.v = e2 is equivalent to C.v = e2.
+  { C.staticInt = 1; Expect.equals(2, C?.staticInt = 2); Expect.equals(2, C.staticInt); }
+
+
+  // The static type of e1?.v = e2 is the static type of e2.
+
+
+
+
+
+
+
+  // Exactly the same errors that would be caused by e1.v = e2 are
+  // also generated in the case of e1?.v = e2.
+
+
+
+  // e1?.v op= e2 is equivalent to ((x) => x?.v = x.v op e2)(e1).
+
+
+
+  // C?.v op= e2 is equivalent to C.v op= e2.
+
+
+  // The static type of e1?.v op= e2 is the static type of e1.v op e2.
+
+
+
+
+  // Let T be the static type of e1 and let y be a fresh variable of type T.
+  // Exactly the same errors that would be caused by y.v op e2 are
+  // also generated in the case of e1?.v op= e2.
+
+
+
+
+
+
+
+
+
+  // '?.' cannot be used to assign to toplevel properties in libraries imported
+  // via prefix.
+
+
+
+}
diff --git a/tests/language/null_aware/assignment_runtime_4_test.dart b/tests/language/null_aware/assignment_runtime_4_test.dart
new file mode 100644
index 0000000..dcf3ab0
--- /dev/null
+++ b/tests/language/null_aware/assignment_runtime_4_test.dart
@@ -0,0 +1,101 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears on the LHS of an
+// assignment.
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+bad() {
+  Expect.fail('Should not be executed');
+}
+
+class B {}
+
+class C extends B {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v = e2 is equivalent to ((x) => x == null ? null : x.v = e2)(e1).
+
+
+
+  // C?.v = e2 is equivalent to C.v = e2.
+
+  { h.C.staticInt = 1; Expect.equals(2, h.C?.staticInt = 2); Expect.equals(2, h.C.staticInt); }
+
+  // The static type of e1?.v = e2 is the static type of e2.
+
+
+
+
+
+
+
+  // Exactly the same errors that would be caused by e1.v = e2 are
+  // also generated in the case of e1?.v = e2.
+
+
+
+  // e1?.v op= e2 is equivalent to ((x) => x?.v = x.v op e2)(e1).
+
+
+
+  // C?.v op= e2 is equivalent to C.v op= e2.
+
+
+  // The static type of e1?.v op= e2 is the static type of e1.v op e2.
+
+
+
+
+  // Let T be the static type of e1 and let y be a fresh variable of type T.
+  // Exactly the same errors that would be caused by y.v op e2 are
+  // also generated in the case of e1?.v op= e2.
+
+
+
+
+
+
+
+
+
+  // '?.' cannot be used to assign to toplevel properties in libraries imported
+  // via prefix.
+
+
+
+}
diff --git a/tests/language/null_aware/assignment_runtime_5_test.dart b/tests/language/null_aware/assignment_runtime_5_test.dart
new file mode 100644
index 0000000..abcf60a
--- /dev/null
+++ b/tests/language/null_aware/assignment_runtime_5_test.dart
@@ -0,0 +1,101 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears on the LHS of an
+// assignment.
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+bad() {
+  Expect.fail('Should not be executed');
+}
+
+class B {}
+
+class C extends B {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v = e2 is equivalent to ((x) => x == null ? null : x.v = e2)(e1).
+
+
+
+  // C?.v = e2 is equivalent to C.v = e2.
+
+
+
+  // The static type of e1?.v = e2 is the static type of e2.
+  { D? d = new D(new E()); G g = new G(); F? f = (d?.v = g); Expect.identical(f, g); }
+
+
+
+
+
+
+  // Exactly the same errors that would be caused by e1.v = e2 are
+  // also generated in the case of e1?.v = e2.
+
+
+
+  // e1?.v op= e2 is equivalent to ((x) => x?.v = x.v op e2)(e1).
+
+
+
+  // C?.v op= e2 is equivalent to C.v op= e2.
+
+
+  // The static type of e1?.v op= e2 is the static type of e1.v op e2.
+
+
+
+
+  // Let T be the static type of e1 and let y be a fresh variable of type T.
+  // Exactly the same errors that would be caused by y.v op e2 are
+  // also generated in the case of e1?.v op= e2.
+
+
+
+
+
+
+
+
+
+  // '?.' cannot be used to assign to toplevel properties in libraries imported
+  // via prefix.
+
+
+
+}
diff --git a/tests/language/null_aware/assignment_runtime_6_test.dart b/tests/language/null_aware/assignment_runtime_6_test.dart
new file mode 100644
index 0000000..e1a732b
--- /dev/null
+++ b/tests/language/null_aware/assignment_runtime_6_test.dart
@@ -0,0 +1,101 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears on the LHS of an
+// assignment.
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+bad() {
+  Expect.fail('Should not be executed');
+}
+
+class B {}
+
+class C extends B {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v = e2 is equivalent to ((x) => x == null ? null : x.v = e2)(e1).
+
+
+
+  // C?.v = e2 is equivalent to C.v = e2.
+
+
+
+  // The static type of e1?.v = e2 is the static type of e2.
+
+
+  { D.staticE = new E(); G g = new G(); F? f = (D?.staticE = g); Expect.identical(f, g); }
+
+
+
+
+  // Exactly the same errors that would be caused by e1.v = e2 are
+  // also generated in the case of e1?.v = e2.
+
+
+
+  // e1?.v op= e2 is equivalent to ((x) => x?.v = x.v op e2)(e1).
+
+
+
+  // C?.v op= e2 is equivalent to C.v op= e2.
+
+
+  // The static type of e1?.v op= e2 is the static type of e1.v op e2.
+
+
+
+
+  // Let T be the static type of e1 and let y be a fresh variable of type T.
+  // Exactly the same errors that would be caused by y.v op e2 are
+  // also generated in the case of e1?.v op= e2.
+
+
+
+
+
+
+
+
+
+  // '?.' cannot be used to assign to toplevel properties in libraries imported
+  // via prefix.
+
+
+
+}
diff --git a/tests/language/null_aware/assignment_runtime_7_test.dart b/tests/language/null_aware/assignment_runtime_7_test.dart
new file mode 100644
index 0000000..8a5ba98
--- /dev/null
+++ b/tests/language/null_aware/assignment_runtime_7_test.dart
@@ -0,0 +1,101 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears on the LHS of an
+// assignment.
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+bad() {
+  Expect.fail('Should not be executed');
+}
+
+class B {}
+
+class C extends B {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v = e2 is equivalent to ((x) => x == null ? null : x.v = e2)(e1).
+
+
+
+  // C?.v = e2 is equivalent to C.v = e2.
+
+
+
+  // The static type of e1?.v = e2 is the static type of e2.
+
+
+
+  { h.D.staticE = new h.E(); h.G g = new h.G(); h.F? f = (h.D?.staticE = g); Expect.identical(f, g); }
+
+
+
+  // Exactly the same errors that would be caused by e1.v = e2 are
+  // also generated in the case of e1?.v = e2.
+
+
+
+  // e1?.v op= e2 is equivalent to ((x) => x?.v = x.v op e2)(e1).
+
+
+
+  // C?.v op= e2 is equivalent to C.v op= e2.
+
+
+  // The static type of e1?.v op= e2 is the static type of e1.v op e2.
+
+
+
+
+  // Let T be the static type of e1 and let y be a fresh variable of type T.
+  // Exactly the same errors that would be caused by y.v op e2 are
+  // also generated in the case of e1?.v op= e2.
+
+
+
+
+
+
+
+
+
+  // '?.' cannot be used to assign to toplevel properties in libraries imported
+  // via prefix.
+
+
+
+}
diff --git a/tests/language/null_aware/assignment_runtime_8_test.dart b/tests/language/null_aware/assignment_runtime_8_test.dart
new file mode 100644
index 0000000..34f7359
--- /dev/null
+++ b/tests/language/null_aware/assignment_runtime_8_test.dart
@@ -0,0 +1,102 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears on the LHS of an
+// assignment.
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+int bad() {
+  Expect.fail('Should not be executed');
+  return -1;
+}
+
+class B {}
+
+class C extends B {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v = e2 is equivalent to ((x) => x == null ? null : x.v = e2)(e1).
+
+
+
+  // C?.v = e2 is equivalent to C.v = e2.
+
+
+
+  // The static type of e1?.v = e2 is the static type of e2.
+
+
+
+
+
+
+
+  // Exactly the same errors that would be caused by e1.v = e2 are
+  // also generated in the case of e1?.v = e2.
+
+
+
+  // e1?.v op= e2 is equivalent to ((x) => x?.v = x.v op e2)(e1).
+  Expect.equals(null, nullC()?.v += bad());
+
+
+  // C?.v op= e2 is equivalent to C.v op= e2.
+
+
+  // The static type of e1?.v op= e2 is the static type of e1.v op e2.
+
+
+
+
+  // Let T be the static type of e1 and let y be a fresh variable of type T.
+  // Exactly the same errors that would be caused by y.v op e2 are
+  // also generated in the case of e1?.v op= e2.
+
+
+
+
+
+
+
+
+
+  // '?.' cannot be used to assign to toplevel properties in libraries imported
+  // via prefix.
+
+
+
+}
diff --git a/tests/language/null_aware/assignment_runtime_9_test.dart b/tests/language/null_aware/assignment_runtime_9_test.dart
new file mode 100644
index 0000000..3c2d6c0
--- /dev/null
+++ b/tests/language/null_aware/assignment_runtime_9_test.dart
@@ -0,0 +1,101 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears on the LHS of an
+// assignment.
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+bad() {
+  Expect.fail('Should not be executed');
+}
+
+class B {}
+
+class C extends B {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v = e2 is equivalent to ((x) => x == null ? null : x.v = e2)(e1).
+
+
+
+  // C?.v = e2 is equivalent to C.v = e2.
+
+
+
+  // The static type of e1?.v = e2 is the static type of e2.
+
+
+
+
+
+
+
+  // Exactly the same errors that would be caused by e1.v = e2 are
+  // also generated in the case of e1?.v = e2.
+
+
+
+  // e1?.v op= e2 is equivalent to ((x) => x?.v = x.v op e2)(e1).
+
+  { C? c = new C(1); Expect.equals(3, c?.v += 2); Expect.equals(3, c!.v); }
+
+  // C?.v op= e2 is equivalent to C.v op= e2.
+
+
+  // The static type of e1?.v op= e2 is the static type of e1.v op e2.
+
+
+
+
+  // Let T be the static type of e1 and let y be a fresh variable of type T.
+  // Exactly the same errors that would be caused by y.v op e2 are
+  // also generated in the case of e1?.v op= e2.
+
+
+
+
+
+
+
+
+
+  // '?.' cannot be used to assign to toplevel properties in libraries imported
+  // via prefix.
+
+
+
+}
diff --git a/tests/language/null_aware/assignment_runtime_test.dart b/tests/language/null_aware/assignment_runtime_test.dart
new file mode 100644
index 0000000..af673ef
--- /dev/null
+++ b/tests/language/null_aware/assignment_runtime_test.dart
@@ -0,0 +1,101 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears on the LHS of an
+// assignment.
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+bad() {
+  Expect.fail('Should not be executed');
+}
+
+class B {}
+
+class C extends B {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v = e2 is equivalent to ((x) => x == null ? null : x.v = e2)(e1).
+
+
+
+  // C?.v = e2 is equivalent to C.v = e2.
+
+
+
+  // The static type of e1?.v = e2 is the static type of e2.
+
+
+
+
+
+
+
+  // Exactly the same errors that would be caused by e1.v = e2 are
+  // also generated in the case of e1?.v = e2.
+
+
+
+  // e1?.v op= e2 is equivalent to ((x) => x?.v = x.v op e2)(e1).
+
+
+
+  // C?.v op= e2 is equivalent to C.v op= e2.
+
+
+  // The static type of e1?.v op= e2 is the static type of e1.v op e2.
+
+
+
+
+  // Let T be the static type of e1 and let y be a fresh variable of type T.
+  // Exactly the same errors that would be caused by y.v op e2 are
+  // also generated in the case of e1?.v op= e2.
+
+
+
+
+
+
+
+
+
+  // '?.' cannot be used to assign to toplevel properties in libraries imported
+  // via prefix.
+
+
+
+}
diff --git a/tests/language/null_aware/assignment_test.dart b/tests/language/null_aware/assignment_test.dart
new file mode 100644
index 0000000..4b5f5de
--- /dev/null
+++ b/tests/language/null_aware/assignment_test.dart
@@ -0,0 +1,176 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears on the LHS of an
+// assignment.
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+int bad() {
+  Expect.fail('Should not be executed');
+  return -1;
+}
+
+class B {}
+
+class C extends B {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v = e2 is equivalent to ((x) => x == null ? null : x.v = e2)(e1).
+  Expect.equals(null, nullC()?.v = bad());
+  { C c = new C(1); Expect.equals(2, c?.v = 2); Expect.equals(2, c.v); }
+  //                                  ^^
+  // [analyzer] STATIC_WARNING.INVALID_NULL_AWARE_OPERATOR
+
+  // C?.v = e2 is equivalent to C.v = e2.
+  { C.staticInt = 1; Expect.equals(2, C?.staticInt = 2); Expect.equals(2, C.staticInt); }
+  { h.C.staticInt = 1; Expect.equals(2, h.C?.staticInt = 2); Expect.equals(2, h.C.staticInt); }
+
+  // The static type of e1?.v = e2 is the static type of e2.
+  { D? d = new D(new E()); G g = new G(); F? f = (d?.v = g); Expect.identical(f, g); }
+  { D? d = new D(new E()); E e = new G(); F? f = (d?.v = e); }
+  //                                             ^^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+  //                                              ^
+  // [cfe] A value of type 'E?' can't be assigned to a variable of type 'F?'.
+  { D.staticE = new E(); G g = new G(); F? f = (D?.staticE = g); Expect.identical(f, g); }
+  { h.D.staticE = new h.E(); h.G g = new h.G(); h.F? f = (h.D?.staticE = g); Expect.identical(f, g); }
+  { D.staticE = new E(); E e = new G(); F? f = (D?.staticE = e); }
+  //                                           ^^^^^^^^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+  //                                               ^
+  // [cfe] A value of type 'E' can't be assigned to a variable of type 'F?'.
+  { h.D.staticE = new h.E(); h.E e = new h.G(); h.F f = (h.D?.staticE = e); }
+  //                                                    ^^^^^^^^^^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+  //                                                          ^
+  // [cfe] A value of type 'E' can't be assigned to a variable of type 'F'.
+
+  // Exactly the same errors that would be caused by e1.v = e2 are
+  // also generated in the case of e1?.v = e2.
+  Expect.equals(null, nullC()?.bad = bad());
+  //                           ^^^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_SETTER
+  // [cfe] The setter 'bad' isn't defined for the class 'C'.
+  { B b = new C(1); Expect.equals(2, b?.v = 2); }
+  //                                  ^^
+  // [analyzer] STATIC_WARNING.INVALID_NULL_AWARE_OPERATOR
+  //                                    ^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_SETTER
+  // [cfe] The setter 'v' isn't defined for the class 'B'.
+
+  // e1?.v op= e2 is equivalent to ((x) => x?.v = x.v op e2)(e1).
+  Expect.equals(null, nullC()?.v += bad());
+  { C c = new C(1); Expect.equals(3, c?.v += 2); Expect.equals(3, c.v); }
+  //                                  ^^
+  // [analyzer] STATIC_WARNING.INVALID_NULL_AWARE_OPERATOR
+
+  // C?.v op= e2 is equivalent to C.v op= e2.
+  { C.staticInt = 1; Expect.equals(3, C?.staticInt += 2); Expect.equals(3, C?.staticInt); }
+
+  // The static type of e1?.v op= e2 is the static type of e1.v op e2.
+  { D d = new D(new E()); F? f = (d?.v += 1); Expect.identical(d.v, f); }
+  //                               ^^
+  // [analyzer] STATIC_WARNING.INVALID_NULL_AWARE_OPERATOR
+  { D.staticE = new E(); F? f = (D?.staticE += 1); Expect.identical(D.staticE, f); }
+  { h.D.staticE = new h.E(); h.F? f = (h.D?.staticE += 1); Expect.identical(h.D.staticE, f); }
+
+  // Let T be the static type of e1 and let y be a fresh variable of type T.
+  // Exactly the same errors that would be caused by y.v op e2 are
+  // also generated in the case of e1?.v op= e2.
+  nullC()?.bad = bad();
+  //       ^^^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_SETTER
+  // [cfe] The setter 'bad' isn't defined for the class 'C'.
+  { B b = new C(1); b?.v += 2; }
+  //                 ^^
+  // [analyzer] STATIC_WARNING.INVALID_NULL_AWARE_OPERATOR
+  //                   ^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] The getter 'v' isn't defined for the class 'B'.
+  //                   ^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_SETTER
+  // [cfe] The setter 'v' isn't defined for the class 'B'.
+  { D d = new D(new E()); F? f = (d?.v += nullC()); }
+  //                               ^^
+  // [analyzer] STATIC_WARNING.INVALID_NULL_AWARE_OPERATOR
+  //                                      ^^^^^^^
+  // [analyzer] STATIC_WARNING.ARGUMENT_TYPE_NOT_ASSIGNABLE
+  // [cfe] A value of type 'C?' can't be assigned to a variable of type 'int'.
+  { D d = new D(new E()); H? h = (d?.v += 1); }
+  //                             ^^^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+  //                              ^
+  // [cfe] A value of type 'G?' can't be assigned to a variable of type 'H?'.
+  //                               ^^
+  // [analyzer] STATIC_WARNING.INVALID_NULL_AWARE_OPERATOR
+  { D.staticE = new E(); F? f = (D?.staticE += nullC()); }
+  //                                           ^^^^^^^
+  // [analyzer] STATIC_WARNING.ARGUMENT_TYPE_NOT_ASSIGNABLE
+  // [cfe] A value of type 'C?' can't be assigned to a variable of type 'int'.
+  { h.D.staticE = new h.E(); h.F? f = (h.D?.staticE += h.nullC()); }
+  //                                                   ^^^^^^^^^
+  // [analyzer] STATIC_WARNING.ARGUMENT_TYPE_NOT_ASSIGNABLE
+  // [cfe] A value of type 'C?' can't be assigned to a variable of type 'int'.
+  { D.staticE = new E(); H? h = (D?.staticE += 1); }
+  //                            ^^^^^^^^^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+  //                                ^
+  // [cfe] A value of type 'G' can't be assigned to a variable of type 'H?'.
+  { h.D.staticE = new h.E(); h.H? hh = (h.D?.staticE += 1); }
+  //                                   ^^^^^^^^^^^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+  //                                         ^
+  // [cfe] A value of type 'G' can't be assigned to a variable of type 'H?'.
+
+  // '?.' cannot be used to assign to toplevel properties in libraries imported
+  // via prefix.
+  h?.topLevelVar = null;
+//^
+// [analyzer] COMPILE_TIME_ERROR.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT
+// [cfe] A prefix can't be used with null-aware operators.
+//               ^
+// [cfe] Can't assign to this.
+  h?.topLevelVar += null;
+//^
+// [analyzer] COMPILE_TIME_ERROR.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT
+// [cfe] A prefix can't be used with null-aware operators.
+//               ^
+// [cfe] Can't assign to this.
+  h?.topLevelVar ??= null;
+//^
+// [analyzer] COMPILE_TIME_ERROR.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT
+// [cfe] A prefix can't be used with null-aware operators.
+//               ^
+// [cfe] Can't assign to this.
+}
diff --git a/tests/language/null_aware/conditional_access_helper.dart b/tests/language/null_aware/conditional_access_helper.dart
new file mode 100644
index 0000000..3227005
--- /dev/null
+++ b/tests/language/null_aware/conditional_access_helper.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Library used by conditional_property_assignment_test.dart,
+// conditional_property_access_test.dart, and
+// conditional_method_invocation_test.dart, all of which import it using the
+// prefix "h.".
+
+library lib;
+
+var topLevelVar;
+
+void topLevelFunction() {}
+
+class C {
+  static late int staticInt;
+  static int? staticNullable;
+  static staticF(callback()) => callback();
+  static int? staticG(int? callback()) => callback();
+}
+
+C? nullC() => null;
+
+class D {
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+  G operator -(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
diff --git a/tests/language/null_aware/dynamic_test.dart b/tests/language/null_aware/dynamic_test.dart
new file mode 100644
index 0000000..36dfc10
--- /dev/null
+++ b/tests/language/null_aware/dynamic_test.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:expect/expect.dart';
+
+void main() {
+  dynamic l;
+  var val = l?.first?.abs();
+  Expect.equals(null, val);
+  l = [null, -2, -3];
+  val = l?.first?.abs();
+  Expect.equals(null, val);
+  l = [-1, -2, -3];
+  val = l?.first?.abs();
+  Expect.equals(1, val);
+}
diff --git a/tests/language/null_aware/increment_decrement_runtime_10_test.dart b/tests/language/null_aware/increment_decrement_runtime_10_test.dart
new file mode 100644
index 0000000..1ee42a7
--- /dev/null
+++ b/tests/language/null_aware/increment_decrement_runtime_10_test.dart
@@ -0,0 +1,109 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears in a postincrement or
+// preincrement expression (or a postdecrement or predecrement expression).
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+class C {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+  G operator -(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v++ is equivalent to ((x) => x == null ? null : x.v++)(e1).
+
+
+
+  // C?.v++ is equivalent to C.v++.
+
+
+
+  // The static type of e1?.v++ is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // e1?.v-- is equivalent to ((x) => x == null ? null : x.v--)(e1).
+
+
+
+  // C?.v-- is equivalent to C.v--.
+  { C.staticInt = 1; Expect.equals(1, C?.staticInt--); Expect.equals(0, C.staticInt); }
+
+
+  // The static type of e1?.v-- is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // ++e1?.v is equivalent to e1?.v += 1.
+
+
+
+  // ++C?.v is equivalent to C?.v += 1.
+
+
+
+  // The static type of ++e1?.v is the same as the static type of e1.v + 1.
+
+
+
+
+
+
+
+  // --e1?.v is equivalent to e1?.v -= 1.
+
+
+
+  // --C?.v is equivalent to C?.v -= 1.
+
+
+
+  // The static type of --e1?.v is the same as the static type of e1.v - 1.
+
+
+
+
+
+
+}
diff --git a/tests/language/null_aware/increment_decrement_runtime_11_test.dart b/tests/language/null_aware/increment_decrement_runtime_11_test.dart
new file mode 100644
index 0000000..2a96102
--- /dev/null
+++ b/tests/language/null_aware/increment_decrement_runtime_11_test.dart
@@ -0,0 +1,109 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears in a postincrement or
+// preincrement expression (or a postdecrement or predecrement expression).
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+class C {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+  G operator -(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v++ is equivalent to ((x) => x == null ? null : x.v++)(e1).
+
+
+
+  // C?.v++ is equivalent to C.v++.
+
+
+
+  // The static type of e1?.v++ is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // e1?.v-- is equivalent to ((x) => x == null ? null : x.v--)(e1).
+
+
+
+  // C?.v-- is equivalent to C.v--.
+
+  { h.C.staticInt = 1; Expect.equals(1, h.C?.staticInt--); Expect.equals(0, h.C.staticInt); }
+
+  // The static type of e1?.v-- is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // ++e1?.v is equivalent to e1?.v += 1.
+
+
+
+  // ++C?.v is equivalent to C?.v += 1.
+
+
+
+  // The static type of ++e1?.v is the same as the static type of e1.v + 1.
+
+
+
+
+
+
+
+  // --e1?.v is equivalent to e1?.v -= 1.
+
+
+
+  // --C?.v is equivalent to C?.v -= 1.
+
+
+
+  // The static type of --e1?.v is the same as the static type of e1.v - 1.
+
+
+
+
+
+
+}
diff --git a/tests/language/null_aware/increment_decrement_runtime_12_test.dart b/tests/language/null_aware/increment_decrement_runtime_12_test.dart
new file mode 100644
index 0000000..03986fb
--- /dev/null
+++ b/tests/language/null_aware/increment_decrement_runtime_12_test.dart
@@ -0,0 +1,109 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears in a postincrement or
+// preincrement expression (or a postdecrement or predecrement expression).
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+class C {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+  G operator -(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v++ is equivalent to ((x) => x == null ? null : x.v++)(e1).
+
+
+
+  // C?.v++ is equivalent to C.v++.
+
+
+
+  // The static type of e1?.v++ is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // e1?.v-- is equivalent to ((x) => x == null ? null : x.v--)(e1).
+
+
+
+  // C?.v-- is equivalent to C.v--.
+
+
+
+  // The static type of e1?.v-- is the same as the static type of e1.v.
+  { E e1 = new E(); D? d = new D(e1); E? e2 = d?.v--; Expect.identical(e1, e2); }
+
+
+
+
+
+
+  // ++e1?.v is equivalent to e1?.v += 1.
+
+
+
+  // ++C?.v is equivalent to C?.v += 1.
+
+
+
+  // The static type of ++e1?.v is the same as the static type of e1.v + 1.
+
+
+
+
+
+
+
+  // --e1?.v is equivalent to e1?.v -= 1.
+
+
+
+  // --C?.v is equivalent to C?.v -= 1.
+
+
+
+  // The static type of --e1?.v is the same as the static type of e1.v - 1.
+
+
+
+
+
+
+}
diff --git a/tests/language/null_aware/increment_decrement_runtime_13_test.dart b/tests/language/null_aware/increment_decrement_runtime_13_test.dart
new file mode 100644
index 0000000..54a60b5
--- /dev/null
+++ b/tests/language/null_aware/increment_decrement_runtime_13_test.dart
@@ -0,0 +1,109 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears in a postincrement or
+// preincrement expression (or a postdecrement or predecrement expression).
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+class C {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+  G operator -(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v++ is equivalent to ((x) => x == null ? null : x.v++)(e1).
+
+
+
+  // C?.v++ is equivalent to C.v++.
+
+
+
+  // The static type of e1?.v++ is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // e1?.v-- is equivalent to ((x) => x == null ? null : x.v--)(e1).
+
+
+
+  // C?.v-- is equivalent to C.v--.
+
+
+
+  // The static type of e1?.v-- is the same as the static type of e1.v.
+
+
+  { E e1 = new E(); D.staticE = e1; E? e2 = D?.staticE--; Expect.identical(e1, e2); }
+
+
+
+
+  // ++e1?.v is equivalent to e1?.v += 1.
+
+
+
+  // ++C?.v is equivalent to C?.v += 1.
+
+
+
+  // The static type of ++e1?.v is the same as the static type of e1.v + 1.
+
+
+
+
+
+
+
+  // --e1?.v is equivalent to e1?.v -= 1.
+
+
+
+  // --C?.v is equivalent to C?.v -= 1.
+
+
+
+  // The static type of --e1?.v is the same as the static type of e1.v - 1.
+
+
+
+
+
+
+}
diff --git a/tests/language/null_aware/increment_decrement_runtime_14_test.dart b/tests/language/null_aware/increment_decrement_runtime_14_test.dart
new file mode 100644
index 0000000..aedf157
--- /dev/null
+++ b/tests/language/null_aware/increment_decrement_runtime_14_test.dart
@@ -0,0 +1,109 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears in a postincrement or
+// preincrement expression (or a postdecrement or predecrement expression).
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+class C {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+  G operator -(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v++ is equivalent to ((x) => x == null ? null : x.v++)(e1).
+
+
+
+  // C?.v++ is equivalent to C.v++.
+
+
+
+  // The static type of e1?.v++ is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // e1?.v-- is equivalent to ((x) => x == null ? null : x.v--)(e1).
+
+
+
+  // C?.v-- is equivalent to C.v--.
+
+
+
+  // The static type of e1?.v-- is the same as the static type of e1.v.
+
+
+
+  { h.E e1 = new h.E(); h.D.staticE = e1; h.E? e2 = h.D?.staticE--; Expect.identical(e1, e2); }
+
+
+
+  // ++e1?.v is equivalent to e1?.v += 1.
+
+
+
+  // ++C?.v is equivalent to C?.v += 1.
+
+
+
+  // The static type of ++e1?.v is the same as the static type of e1.v + 1.
+
+
+
+
+
+
+
+  // --e1?.v is equivalent to e1?.v -= 1.
+
+
+
+  // --C?.v is equivalent to C?.v -= 1.
+
+
+
+  // The static type of --e1?.v is the same as the static type of e1.v - 1.
+
+
+
+
+
+
+}
diff --git a/tests/language/null_aware/increment_decrement_runtime_15_test.dart b/tests/language/null_aware/increment_decrement_runtime_15_test.dart
new file mode 100644
index 0000000..674833c
--- /dev/null
+++ b/tests/language/null_aware/increment_decrement_runtime_15_test.dart
@@ -0,0 +1,109 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears in a postincrement or
+// preincrement expression (or a postdecrement or predecrement expression).
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+class C {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+  G operator -(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v++ is equivalent to ((x) => x == null ? null : x.v++)(e1).
+
+
+
+  // C?.v++ is equivalent to C.v++.
+
+
+
+  // The static type of e1?.v++ is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // e1?.v-- is equivalent to ((x) => x == null ? null : x.v--)(e1).
+
+
+
+  // C?.v-- is equivalent to C.v--.
+
+
+
+  // The static type of e1?.v-- is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // ++e1?.v is equivalent to e1?.v += 1.
+  Expect.equals(null, ++nullC()?.v);
+
+
+  // ++C?.v is equivalent to C?.v += 1.
+
+
+
+  // The static type of ++e1?.v is the same as the static type of e1.v + 1.
+
+
+
+
+
+
+
+  // --e1?.v is equivalent to e1?.v -= 1.
+
+
+
+  // --C?.v is equivalent to C?.v -= 1.
+
+
+
+  // The static type of --e1?.v is the same as the static type of e1.v - 1.
+
+
+
+
+
+
+}
diff --git a/tests/language/null_aware/increment_decrement_runtime_16_test.dart b/tests/language/null_aware/increment_decrement_runtime_16_test.dart
new file mode 100644
index 0000000..1016d22
--- /dev/null
+++ b/tests/language/null_aware/increment_decrement_runtime_16_test.dart
@@ -0,0 +1,109 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears in a postincrement or
+// preincrement expression (or a postdecrement or predecrement expression).
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+class C {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+  G operator -(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v++ is equivalent to ((x) => x == null ? null : x.v++)(e1).
+
+
+
+  // C?.v++ is equivalent to C.v++.
+
+
+
+  // The static type of e1?.v++ is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // e1?.v-- is equivalent to ((x) => x == null ? null : x.v--)(e1).
+
+
+
+  // C?.v-- is equivalent to C.v--.
+
+
+
+  // The static type of e1?.v-- is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // ++e1?.v is equivalent to e1?.v += 1.
+
+  { C? c = new C(1); Expect.equals(2, ++c?.v); Expect.equals(2, c!.v); }
+
+  // ++C?.v is equivalent to C?.v += 1.
+
+
+
+  // The static type of ++e1?.v is the same as the static type of e1.v + 1.
+
+
+
+
+
+
+
+  // --e1?.v is equivalent to e1?.v -= 1.
+
+
+
+  // --C?.v is equivalent to C?.v -= 1.
+
+
+
+  // The static type of --e1?.v is the same as the static type of e1.v - 1.
+
+
+
+
+
+
+}
diff --git a/tests/language/null_aware/increment_decrement_runtime_17_test.dart b/tests/language/null_aware/increment_decrement_runtime_17_test.dart
new file mode 100644
index 0000000..4997a21
--- /dev/null
+++ b/tests/language/null_aware/increment_decrement_runtime_17_test.dart
@@ -0,0 +1,109 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears in a postincrement or
+// preincrement expression (or a postdecrement or predecrement expression).
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+class C {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+  G operator -(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v++ is equivalent to ((x) => x == null ? null : x.v++)(e1).
+
+
+
+  // C?.v++ is equivalent to C.v++.
+
+
+
+  // The static type of e1?.v++ is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // e1?.v-- is equivalent to ((x) => x == null ? null : x.v--)(e1).
+
+
+
+  // C?.v-- is equivalent to C.v--.
+
+
+
+  // The static type of e1?.v-- is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // ++e1?.v is equivalent to e1?.v += 1.
+
+
+
+  // ++C?.v is equivalent to C?.v += 1.
+  { C.staticInt = 1; Expect.equals(2, ++C?.staticInt); Expect.equals(2, C.staticInt); }
+
+
+  // The static type of ++e1?.v is the same as the static type of e1.v + 1.
+
+
+
+
+
+
+
+  // --e1?.v is equivalent to e1?.v -= 1.
+
+
+
+  // --C?.v is equivalent to C?.v -= 1.
+
+
+
+  // The static type of --e1?.v is the same as the static type of e1.v - 1.
+
+
+
+
+
+
+}
diff --git a/tests/language/null_aware/increment_decrement_runtime_18_test.dart b/tests/language/null_aware/increment_decrement_runtime_18_test.dart
new file mode 100644
index 0000000..c42e93a
--- /dev/null
+++ b/tests/language/null_aware/increment_decrement_runtime_18_test.dart
@@ -0,0 +1,109 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears in a postincrement or
+// preincrement expression (or a postdecrement or predecrement expression).
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+class C {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+  G operator -(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v++ is equivalent to ((x) => x == null ? null : x.v++)(e1).
+
+
+
+  // C?.v++ is equivalent to C.v++.
+
+
+
+  // The static type of e1?.v++ is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // e1?.v-- is equivalent to ((x) => x == null ? null : x.v--)(e1).
+
+
+
+  // C?.v-- is equivalent to C.v--.
+
+
+
+  // The static type of e1?.v-- is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // ++e1?.v is equivalent to e1?.v += 1.
+
+
+
+  // ++C?.v is equivalent to C?.v += 1.
+
+  { h.C.staticInt = 1; Expect.equals(2, ++h.C?.staticInt); Expect.equals(2, h.C.staticInt); }
+
+  // The static type of ++e1?.v is the same as the static type of e1.v + 1.
+
+
+
+
+
+
+
+  // --e1?.v is equivalent to e1?.v -= 1.
+
+
+
+  // --C?.v is equivalent to C?.v -= 1.
+
+
+
+  // The static type of --e1?.v is the same as the static type of e1.v - 1.
+
+
+
+
+
+
+}
diff --git a/tests/language/null_aware/increment_decrement_runtime_19_test.dart b/tests/language/null_aware/increment_decrement_runtime_19_test.dart
new file mode 100644
index 0000000..bb8c565
--- /dev/null
+++ b/tests/language/null_aware/increment_decrement_runtime_19_test.dart
@@ -0,0 +1,109 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears in a postincrement or
+// preincrement expression (or a postdecrement or predecrement expression).
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+class C {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+  G operator -(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v++ is equivalent to ((x) => x == null ? null : x.v++)(e1).
+
+
+
+  // C?.v++ is equivalent to C.v++.
+
+
+
+  // The static type of e1?.v++ is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // e1?.v-- is equivalent to ((x) => x == null ? null : x.v--)(e1).
+
+
+
+  // C?.v-- is equivalent to C.v--.
+
+
+
+  // The static type of e1?.v-- is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // ++e1?.v is equivalent to e1?.v += 1.
+
+
+
+  // ++C?.v is equivalent to C?.v += 1.
+
+
+
+  // The static type of ++e1?.v is the same as the static type of e1.v + 1.
+  { D? d = new D(new E()); F? f = ++d?.v; Expect.identical(d!.v, f); }
+
+
+
+
+
+
+  // --e1?.v is equivalent to e1?.v -= 1.
+
+
+
+  // --C?.v is equivalent to C?.v -= 1.
+
+
+
+  // The static type of --e1?.v is the same as the static type of e1.v - 1.
+
+
+
+
+
+
+}
diff --git a/tests/language/null_aware/increment_decrement_runtime_1_test.dart b/tests/language/null_aware/increment_decrement_runtime_1_test.dart
new file mode 100644
index 0000000..d23da62
--- /dev/null
+++ b/tests/language/null_aware/increment_decrement_runtime_1_test.dart
@@ -0,0 +1,109 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears in a postincrement or
+// preincrement expression (or a postdecrement or predecrement expression).
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+class C {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+  G operator -(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v++ is equivalent to ((x) => x == null ? null : x.v++)(e1).
+  Expect.equals(null, nullC()?.v++);
+
+
+  // C?.v++ is equivalent to C.v++.
+
+
+
+  // The static type of e1?.v++ is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // e1?.v-- is equivalent to ((x) => x == null ? null : x.v--)(e1).
+
+
+
+  // C?.v-- is equivalent to C.v--.
+
+
+
+  // The static type of e1?.v-- is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // ++e1?.v is equivalent to e1?.v += 1.
+
+
+
+  // ++C?.v is equivalent to C?.v += 1.
+
+
+
+  // The static type of ++e1?.v is the same as the static type of e1.v + 1.
+
+
+
+
+
+
+
+  // --e1?.v is equivalent to e1?.v -= 1.
+
+
+
+  // --C?.v is equivalent to C?.v -= 1.
+
+
+
+  // The static type of --e1?.v is the same as the static type of e1.v - 1.
+
+
+
+
+
+
+}
diff --git a/tests/language/null_aware/increment_decrement_runtime_20_test.dart b/tests/language/null_aware/increment_decrement_runtime_20_test.dart
new file mode 100644
index 0000000..d3dc17e
--- /dev/null
+++ b/tests/language/null_aware/increment_decrement_runtime_20_test.dart
@@ -0,0 +1,109 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears in a postincrement or
+// preincrement expression (or a postdecrement or predecrement expression).
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+class C {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+  G operator -(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v++ is equivalent to ((x) => x == null ? null : x.v++)(e1).
+
+
+
+  // C?.v++ is equivalent to C.v++.
+
+
+
+  // The static type of e1?.v++ is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // e1?.v-- is equivalent to ((x) => x == null ? null : x.v--)(e1).
+
+
+
+  // C?.v-- is equivalent to C.v--.
+
+
+
+  // The static type of e1?.v-- is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // ++e1?.v is equivalent to e1?.v += 1.
+
+
+
+  // ++C?.v is equivalent to C?.v += 1.
+
+
+
+  // The static type of ++e1?.v is the same as the static type of e1.v + 1.
+
+
+  { D.staticE = new E(); F? f = ++D?.staticE; Expect.identical(D.staticE, f); }
+
+
+
+
+  // --e1?.v is equivalent to e1?.v -= 1.
+
+
+
+  // --C?.v is equivalent to C?.v -= 1.
+
+
+
+  // The static type of --e1?.v is the same as the static type of e1.v - 1.
+
+
+
+
+
+
+}
diff --git a/tests/language/null_aware/increment_decrement_runtime_21_test.dart b/tests/language/null_aware/increment_decrement_runtime_21_test.dart
new file mode 100644
index 0000000..b12232c
--- /dev/null
+++ b/tests/language/null_aware/increment_decrement_runtime_21_test.dart
@@ -0,0 +1,109 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears in a postincrement or
+// preincrement expression (or a postdecrement or predecrement expression).
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+class C {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+  G operator -(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v++ is equivalent to ((x) => x == null ? null : x.v++)(e1).
+
+
+
+  // C?.v++ is equivalent to C.v++.
+
+
+
+  // The static type of e1?.v++ is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // e1?.v-- is equivalent to ((x) => x == null ? null : x.v--)(e1).
+
+
+
+  // C?.v-- is equivalent to C.v--.
+
+
+
+  // The static type of e1?.v-- is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // ++e1?.v is equivalent to e1?.v += 1.
+
+
+
+  // ++C?.v is equivalent to C?.v += 1.
+
+
+
+  // The static type of ++e1?.v is the same as the static type of e1.v + 1.
+
+
+
+  { h.D.staticE = new h.E(); h.F? f = ++h.D?.staticE; Expect.identical(h.D.staticE, f); }
+
+
+
+  // --e1?.v is equivalent to e1?.v -= 1.
+
+
+
+  // --C?.v is equivalent to C?.v -= 1.
+
+
+
+  // The static type of --e1?.v is the same as the static type of e1.v - 1.
+
+
+
+
+
+
+}
diff --git a/tests/language/null_aware/increment_decrement_runtime_22_test.dart b/tests/language/null_aware/increment_decrement_runtime_22_test.dart
new file mode 100644
index 0000000..59b625c
--- /dev/null
+++ b/tests/language/null_aware/increment_decrement_runtime_22_test.dart
@@ -0,0 +1,109 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears in a postincrement or
+// preincrement expression (or a postdecrement or predecrement expression).
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+class C {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+  G operator -(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v++ is equivalent to ((x) => x == null ? null : x.v++)(e1).
+
+
+
+  // C?.v++ is equivalent to C.v++.
+
+
+
+  // The static type of e1?.v++ is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // e1?.v-- is equivalent to ((x) => x == null ? null : x.v--)(e1).
+
+
+
+  // C?.v-- is equivalent to C.v--.
+
+
+
+  // The static type of e1?.v-- is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // ++e1?.v is equivalent to e1?.v += 1.
+
+
+
+  // ++C?.v is equivalent to C?.v += 1.
+
+
+
+  // The static type of ++e1?.v is the same as the static type of e1.v + 1.
+
+
+
+
+
+
+
+  // --e1?.v is equivalent to e1?.v -= 1.
+  Expect.equals(null, --nullC()?.v);
+
+
+  // --C?.v is equivalent to C?.v -= 1.
+
+
+
+  // The static type of --e1?.v is the same as the static type of e1.v - 1.
+
+
+
+
+
+
+}
diff --git a/tests/language/null_aware/increment_decrement_runtime_23_test.dart b/tests/language/null_aware/increment_decrement_runtime_23_test.dart
new file mode 100644
index 0000000..b2dc6b5
--- /dev/null
+++ b/tests/language/null_aware/increment_decrement_runtime_23_test.dart
@@ -0,0 +1,109 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears in a postincrement or
+// preincrement expression (or a postdecrement or predecrement expression).
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+class C {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+  G operator -(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v++ is equivalent to ((x) => x == null ? null : x.v++)(e1).
+
+
+
+  // C?.v++ is equivalent to C.v++.
+
+
+
+  // The static type of e1?.v++ is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // e1?.v-- is equivalent to ((x) => x == null ? null : x.v--)(e1).
+
+
+
+  // C?.v-- is equivalent to C.v--.
+
+
+
+  // The static type of e1?.v-- is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // ++e1?.v is equivalent to e1?.v += 1.
+
+
+
+  // ++C?.v is equivalent to C?.v += 1.
+
+
+
+  // The static type of ++e1?.v is the same as the static type of e1.v + 1.
+
+
+
+
+
+
+
+  // --e1?.v is equivalent to e1?.v -= 1.
+
+  { C? c = new C(1); Expect.equals(0, --c?.v); Expect.equals(0, c!.v); }
+
+  // --C?.v is equivalent to C?.v -= 1.
+
+
+
+  // The static type of --e1?.v is the same as the static type of e1.v - 1.
+
+
+
+
+
+
+}
diff --git a/tests/language/null_aware/increment_decrement_runtime_24_test.dart b/tests/language/null_aware/increment_decrement_runtime_24_test.dart
new file mode 100644
index 0000000..f80ef6e
--- /dev/null
+++ b/tests/language/null_aware/increment_decrement_runtime_24_test.dart
@@ -0,0 +1,109 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears in a postincrement or
+// preincrement expression (or a postdecrement or predecrement expression).
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+class C {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+  G operator -(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v++ is equivalent to ((x) => x == null ? null : x.v++)(e1).
+
+
+
+  // C?.v++ is equivalent to C.v++.
+
+
+
+  // The static type of e1?.v++ is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // e1?.v-- is equivalent to ((x) => x == null ? null : x.v--)(e1).
+
+
+
+  // C?.v-- is equivalent to C.v--.
+
+
+
+  // The static type of e1?.v-- is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // ++e1?.v is equivalent to e1?.v += 1.
+
+
+
+  // ++C?.v is equivalent to C?.v += 1.
+
+
+
+  // The static type of ++e1?.v is the same as the static type of e1.v + 1.
+
+
+
+
+
+
+
+  // --e1?.v is equivalent to e1?.v -= 1.
+
+
+
+  // --C?.v is equivalent to C?.v -= 1.
+  { C.staticInt = 1; Expect.equals(0, --C?.staticInt); Expect.equals(0, C.staticInt); }
+
+
+  // The static type of --e1?.v is the same as the static type of e1.v - 1.
+
+
+
+
+
+
+}
diff --git a/tests/language/null_aware/increment_decrement_runtime_25_test.dart b/tests/language/null_aware/increment_decrement_runtime_25_test.dart
new file mode 100644
index 0000000..83ef846
--- /dev/null
+++ b/tests/language/null_aware/increment_decrement_runtime_25_test.dart
@@ -0,0 +1,109 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears in a postincrement or
+// preincrement expression (or a postdecrement or predecrement expression).
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+class C {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+  G operator -(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v++ is equivalent to ((x) => x == null ? null : x.v++)(e1).
+
+
+
+  // C?.v++ is equivalent to C.v++.
+
+
+
+  // The static type of e1?.v++ is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // e1?.v-- is equivalent to ((x) => x == null ? null : x.v--)(e1).
+
+
+
+  // C?.v-- is equivalent to C.v--.
+
+
+
+  // The static type of e1?.v-- is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // ++e1?.v is equivalent to e1?.v += 1.
+
+
+
+  // ++C?.v is equivalent to C?.v += 1.
+
+
+
+  // The static type of ++e1?.v is the same as the static type of e1.v + 1.
+
+
+
+
+
+
+
+  // --e1?.v is equivalent to e1?.v -= 1.
+
+
+
+  // --C?.v is equivalent to C?.v -= 1.
+
+  { h.C.staticInt = 1; Expect.equals(0, --h.C?.staticInt); Expect.equals(0, h.C.staticInt); }
+
+  // The static type of --e1?.v is the same as the static type of e1.v - 1.
+
+
+
+
+
+
+}
diff --git a/tests/language/null_aware/increment_decrement_runtime_26_test.dart b/tests/language/null_aware/increment_decrement_runtime_26_test.dart
new file mode 100644
index 0000000..4201d15
--- /dev/null
+++ b/tests/language/null_aware/increment_decrement_runtime_26_test.dart
@@ -0,0 +1,109 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears in a postincrement or
+// preincrement expression (or a postdecrement or predecrement expression).
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+class C {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+  G operator -(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v++ is equivalent to ((x) => x == null ? null : x.v++)(e1).
+
+
+
+  // C?.v++ is equivalent to C.v++.
+
+
+
+  // The static type of e1?.v++ is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // e1?.v-- is equivalent to ((x) => x == null ? null : x.v--)(e1).
+
+
+
+  // C?.v-- is equivalent to C.v--.
+
+
+
+  // The static type of e1?.v-- is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // ++e1?.v is equivalent to e1?.v += 1.
+
+
+
+  // ++C?.v is equivalent to C?.v += 1.
+
+
+
+  // The static type of ++e1?.v is the same as the static type of e1.v + 1.
+
+
+
+
+
+
+
+  // --e1?.v is equivalent to e1?.v -= 1.
+
+
+
+  // --C?.v is equivalent to C?.v -= 1.
+
+
+
+  // The static type of --e1?.v is the same as the static type of e1.v - 1.
+  { D? d = new D(new E()); F? f = --d?.v; Expect.identical(d!.v, f); }
+
+
+
+
+
+}
diff --git a/tests/language/null_aware/increment_decrement_runtime_27_test.dart b/tests/language/null_aware/increment_decrement_runtime_27_test.dart
new file mode 100644
index 0000000..c753b8a
--- /dev/null
+++ b/tests/language/null_aware/increment_decrement_runtime_27_test.dart
@@ -0,0 +1,109 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears in a postincrement or
+// preincrement expression (or a postdecrement or predecrement expression).
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+class C {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+  G operator -(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v++ is equivalent to ((x) => x == null ? null : x.v++)(e1).
+
+
+
+  // C?.v++ is equivalent to C.v++.
+
+
+
+  // The static type of e1?.v++ is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // e1?.v-- is equivalent to ((x) => x == null ? null : x.v--)(e1).
+
+
+
+  // C?.v-- is equivalent to C.v--.
+
+
+
+  // The static type of e1?.v-- is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // ++e1?.v is equivalent to e1?.v += 1.
+
+
+
+  // ++C?.v is equivalent to C?.v += 1.
+
+
+
+  // The static type of ++e1?.v is the same as the static type of e1.v + 1.
+
+
+
+
+
+
+
+  // --e1?.v is equivalent to e1?.v -= 1.
+
+
+
+  // --C?.v is equivalent to C?.v -= 1.
+
+
+
+  // The static type of --e1?.v is the same as the static type of e1.v - 1.
+
+
+  { D.staticE = new E(); F? f = --D?.staticE; Expect.identical(D.staticE, f); }
+
+
+
+}
diff --git a/tests/language/null_aware/increment_decrement_runtime_28_test.dart b/tests/language/null_aware/increment_decrement_runtime_28_test.dart
new file mode 100644
index 0000000..fbec38a
--- /dev/null
+++ b/tests/language/null_aware/increment_decrement_runtime_28_test.dart
@@ -0,0 +1,109 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears in a postincrement or
+// preincrement expression (or a postdecrement or predecrement expression).
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+class C {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+  G operator -(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v++ is equivalent to ((x) => x == null ? null : x.v++)(e1).
+
+
+
+  // C?.v++ is equivalent to C.v++.
+
+
+
+  // The static type of e1?.v++ is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // e1?.v-- is equivalent to ((x) => x == null ? null : x.v--)(e1).
+
+
+
+  // C?.v-- is equivalent to C.v--.
+
+
+
+  // The static type of e1?.v-- is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // ++e1?.v is equivalent to e1?.v += 1.
+
+
+
+  // ++C?.v is equivalent to C?.v += 1.
+
+
+
+  // The static type of ++e1?.v is the same as the static type of e1.v + 1.
+
+
+
+
+
+
+
+  // --e1?.v is equivalent to e1?.v -= 1.
+
+
+
+  // --C?.v is equivalent to C?.v -= 1.
+
+
+
+  // The static type of --e1?.v is the same as the static type of e1.v - 1.
+
+
+
+  { h.D.staticE = new h.E(); h.F? f = --h.D?.staticE; Expect.identical(h.D.staticE, f); }
+
+
+}
diff --git a/tests/language/null_aware/increment_decrement_runtime_2_test.dart b/tests/language/null_aware/increment_decrement_runtime_2_test.dart
new file mode 100644
index 0000000..67bca4a
--- /dev/null
+++ b/tests/language/null_aware/increment_decrement_runtime_2_test.dart
@@ -0,0 +1,109 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears in a postincrement or
+// preincrement expression (or a postdecrement or predecrement expression).
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+class C {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+  G operator -(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v++ is equivalent to ((x) => x == null ? null : x.v++)(e1).
+
+  { C? c = new C(1); Expect.equals(1, c?.v++); Expect.equals(2, c!.v); }
+
+  // C?.v++ is equivalent to C.v++.
+
+
+
+  // The static type of e1?.v++ is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // e1?.v-- is equivalent to ((x) => x == null ? null : x.v--)(e1).
+
+
+
+  // C?.v-- is equivalent to C.v--.
+
+
+
+  // The static type of e1?.v-- is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // ++e1?.v is equivalent to e1?.v += 1.
+
+
+
+  // ++C?.v is equivalent to C?.v += 1.
+
+
+
+  // The static type of ++e1?.v is the same as the static type of e1.v + 1.
+
+
+
+
+
+
+
+  // --e1?.v is equivalent to e1?.v -= 1.
+
+
+
+  // --C?.v is equivalent to C?.v -= 1.
+
+
+
+  // The static type of --e1?.v is the same as the static type of e1.v - 1.
+
+
+
+
+
+
+}
diff --git a/tests/language/null_aware/increment_decrement_runtime_3_test.dart b/tests/language/null_aware/increment_decrement_runtime_3_test.dart
new file mode 100644
index 0000000..d28f21e
--- /dev/null
+++ b/tests/language/null_aware/increment_decrement_runtime_3_test.dart
@@ -0,0 +1,109 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears in a postincrement or
+// preincrement expression (or a postdecrement or predecrement expression).
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+class C {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+  G operator -(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v++ is equivalent to ((x) => x == null ? null : x.v++)(e1).
+
+
+
+  // C?.v++ is equivalent to C.v++.
+  { C.staticInt = 1; Expect.equals(1, C?.staticInt++); Expect.equals(2, C.staticInt); }
+
+
+  // The static type of e1?.v++ is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // e1?.v-- is equivalent to ((x) => x == null ? null : x.v--)(e1).
+
+
+
+  // C?.v-- is equivalent to C.v--.
+
+
+
+  // The static type of e1?.v-- is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // ++e1?.v is equivalent to e1?.v += 1.
+
+
+
+  // ++C?.v is equivalent to C?.v += 1.
+
+
+
+  // The static type of ++e1?.v is the same as the static type of e1.v + 1.
+
+
+
+
+
+
+
+  // --e1?.v is equivalent to e1?.v -= 1.
+
+
+
+  // --C?.v is equivalent to C?.v -= 1.
+
+
+
+  // The static type of --e1?.v is the same as the static type of e1.v - 1.
+
+
+
+
+
+
+}
diff --git a/tests/language/null_aware/increment_decrement_runtime_4_test.dart b/tests/language/null_aware/increment_decrement_runtime_4_test.dart
new file mode 100644
index 0000000..d5a21b7
--- /dev/null
+++ b/tests/language/null_aware/increment_decrement_runtime_4_test.dart
@@ -0,0 +1,109 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears in a postincrement or
+// preincrement expression (or a postdecrement or predecrement expression).
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+class C {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+  G operator -(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v++ is equivalent to ((x) => x == null ? null : x.v++)(e1).
+
+
+
+  // C?.v++ is equivalent to C.v++.
+
+  { h.C.staticInt = 1; Expect.equals(1, h.C?.staticInt++); Expect.equals(2, h.C.staticInt); }
+
+  // The static type of e1?.v++ is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // e1?.v-- is equivalent to ((x) => x == null ? null : x.v--)(e1).
+
+
+
+  // C?.v-- is equivalent to C.v--.
+
+
+
+  // The static type of e1?.v-- is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // ++e1?.v is equivalent to e1?.v += 1.
+
+
+
+  // ++C?.v is equivalent to C?.v += 1.
+
+
+
+  // The static type of ++e1?.v is the same as the static type of e1.v + 1.
+
+
+
+
+
+
+
+  // --e1?.v is equivalent to e1?.v -= 1.
+
+
+
+  // --C?.v is equivalent to C?.v -= 1.
+
+
+
+  // The static type of --e1?.v is the same as the static type of e1.v - 1.
+
+
+
+
+
+
+}
diff --git a/tests/language/null_aware/increment_decrement_runtime_5_test.dart b/tests/language/null_aware/increment_decrement_runtime_5_test.dart
new file mode 100644
index 0000000..8ca6c72
--- /dev/null
+++ b/tests/language/null_aware/increment_decrement_runtime_5_test.dart
@@ -0,0 +1,109 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears in a postincrement or
+// preincrement expression (or a postdecrement or predecrement expression).
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+class C {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+  G operator -(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v++ is equivalent to ((x) => x == null ? null : x.v++)(e1).
+
+
+
+  // C?.v++ is equivalent to C.v++.
+
+
+
+  // The static type of e1?.v++ is the same as the static type of e1.v.
+  { E e1 = new E(); D? d = new D(e1); E? e2 = d?.v++; Expect.identical(e1, e2); }
+
+
+
+
+
+
+  // e1?.v-- is equivalent to ((x) => x == null ? null : x.v--)(e1).
+
+
+
+  // C?.v-- is equivalent to C.v--.
+
+
+
+  // The static type of e1?.v-- is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // ++e1?.v is equivalent to e1?.v += 1.
+
+
+
+  // ++C?.v is equivalent to C?.v += 1.
+
+
+
+  // The static type of ++e1?.v is the same as the static type of e1.v + 1.
+
+
+
+
+
+
+
+  // --e1?.v is equivalent to e1?.v -= 1.
+
+
+
+  // --C?.v is equivalent to C?.v -= 1.
+
+
+
+  // The static type of --e1?.v is the same as the static type of e1.v - 1.
+
+
+
+
+
+
+}
diff --git a/tests/language/null_aware/increment_decrement_runtime_6_test.dart b/tests/language/null_aware/increment_decrement_runtime_6_test.dart
new file mode 100644
index 0000000..3d4f812
--- /dev/null
+++ b/tests/language/null_aware/increment_decrement_runtime_6_test.dart
@@ -0,0 +1,109 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears in a postincrement or
+// preincrement expression (or a postdecrement or predecrement expression).
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+class C {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+  G operator -(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v++ is equivalent to ((x) => x == null ? null : x.v++)(e1).
+
+
+
+  // C?.v++ is equivalent to C.v++.
+
+
+
+  // The static type of e1?.v++ is the same as the static type of e1.v.
+
+
+  { E e1 = new E(); D.staticE = e1; E? e2 = D?.staticE++; Expect.identical(e1, e2); }
+
+
+
+
+  // e1?.v-- is equivalent to ((x) => x == null ? null : x.v--)(e1).
+
+
+
+  // C?.v-- is equivalent to C.v--.
+
+
+
+  // The static type of e1?.v-- is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // ++e1?.v is equivalent to e1?.v += 1.
+
+
+
+  // ++C?.v is equivalent to C?.v += 1.
+
+
+
+  // The static type of ++e1?.v is the same as the static type of e1.v + 1.
+
+
+
+
+
+
+
+  // --e1?.v is equivalent to e1?.v -= 1.
+
+
+
+  // --C?.v is equivalent to C?.v -= 1.
+
+
+
+  // The static type of --e1?.v is the same as the static type of e1.v - 1.
+
+
+
+
+
+
+}
diff --git a/tests/language/null_aware/increment_decrement_runtime_7_test.dart b/tests/language/null_aware/increment_decrement_runtime_7_test.dart
new file mode 100644
index 0000000..b9ae91d
--- /dev/null
+++ b/tests/language/null_aware/increment_decrement_runtime_7_test.dart
@@ -0,0 +1,109 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears in a postincrement or
+// preincrement expression (or a postdecrement or predecrement expression).
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+class C {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+  G operator -(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v++ is equivalent to ((x) => x == null ? null : x.v++)(e1).
+
+
+
+  // C?.v++ is equivalent to C.v++.
+
+
+
+  // The static type of e1?.v++ is the same as the static type of e1.v.
+
+
+
+  { h.E e1 = new h.E(); h.D.staticE = e1; h.E? e2 = h.D?.staticE++; Expect.identical(e1, e2); }
+
+
+
+  // e1?.v-- is equivalent to ((x) => x == null ? null : x.v--)(e1).
+
+
+
+  // C?.v-- is equivalent to C.v--.
+
+
+
+  // The static type of e1?.v-- is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // ++e1?.v is equivalent to e1?.v += 1.
+
+
+
+  // ++C?.v is equivalent to C?.v += 1.
+
+
+
+  // The static type of ++e1?.v is the same as the static type of e1.v + 1.
+
+
+
+
+
+
+
+  // --e1?.v is equivalent to e1?.v -= 1.
+
+
+
+  // --C?.v is equivalent to C?.v -= 1.
+
+
+
+  // The static type of --e1?.v is the same as the static type of e1.v - 1.
+
+
+
+
+
+
+}
diff --git a/tests/language/null_aware/increment_decrement_runtime_8_test.dart b/tests/language/null_aware/increment_decrement_runtime_8_test.dart
new file mode 100644
index 0000000..669b7ed
--- /dev/null
+++ b/tests/language/null_aware/increment_decrement_runtime_8_test.dart
@@ -0,0 +1,109 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears in a postincrement or
+// preincrement expression (or a postdecrement or predecrement expression).
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+class C {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+  G operator -(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v++ is equivalent to ((x) => x == null ? null : x.v++)(e1).
+
+
+
+  // C?.v++ is equivalent to C.v++.
+
+
+
+  // The static type of e1?.v++ is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // e1?.v-- is equivalent to ((x) => x == null ? null : x.v--)(e1).
+  Expect.equals(null, nullC()?.v--);
+
+
+  // C?.v-- is equivalent to C.v--.
+
+
+
+  // The static type of e1?.v-- is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // ++e1?.v is equivalent to e1?.v += 1.
+
+
+
+  // ++C?.v is equivalent to C?.v += 1.
+
+
+
+  // The static type of ++e1?.v is the same as the static type of e1.v + 1.
+
+
+
+
+
+
+
+  // --e1?.v is equivalent to e1?.v -= 1.
+
+
+
+  // --C?.v is equivalent to C?.v -= 1.
+
+
+
+  // The static type of --e1?.v is the same as the static type of e1.v - 1.
+
+
+
+
+
+
+}
diff --git a/tests/language/null_aware/increment_decrement_runtime_9_test.dart b/tests/language/null_aware/increment_decrement_runtime_9_test.dart
new file mode 100644
index 0000000..cd3bd72
--- /dev/null
+++ b/tests/language/null_aware/increment_decrement_runtime_9_test.dart
@@ -0,0 +1,109 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears in a postincrement or
+// preincrement expression (or a postdecrement or predecrement expression).
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+class C {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+  G operator -(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v++ is equivalent to ((x) => x == null ? null : x.v++)(e1).
+
+
+
+  // C?.v++ is equivalent to C.v++.
+
+
+
+  // The static type of e1?.v++ is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // e1?.v-- is equivalent to ((x) => x == null ? null : x.v--)(e1).
+
+  { C? c = new C(1); Expect.equals(1, c?.v--); Expect.equals(0, c!.v); }
+
+  // C?.v-- is equivalent to C.v--.
+
+
+
+  // The static type of e1?.v-- is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // ++e1?.v is equivalent to e1?.v += 1.
+
+
+
+  // ++C?.v is equivalent to C?.v += 1.
+
+
+
+  // The static type of ++e1?.v is the same as the static type of e1.v + 1.
+
+
+
+
+
+
+
+  // --e1?.v is equivalent to e1?.v -= 1.
+
+
+
+  // --C?.v is equivalent to C?.v -= 1.
+
+
+
+  // The static type of --e1?.v is the same as the static type of e1.v - 1.
+
+
+
+
+
+
+}
diff --git a/tests/language/null_aware/increment_decrement_runtime_test.dart b/tests/language/null_aware/increment_decrement_runtime_test.dart
new file mode 100644
index 0000000..0ccc804
--- /dev/null
+++ b/tests/language/null_aware/increment_decrement_runtime_test.dart
@@ -0,0 +1,109 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears in a postincrement or
+// preincrement expression (or a postdecrement or predecrement expression).
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+class C {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+  G operator -(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v++ is equivalent to ((x) => x == null ? null : x.v++)(e1).
+
+
+
+  // C?.v++ is equivalent to C.v++.
+
+
+
+  // The static type of e1?.v++ is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // e1?.v-- is equivalent to ((x) => x == null ? null : x.v--)(e1).
+
+
+
+  // C?.v-- is equivalent to C.v--.
+
+
+
+  // The static type of e1?.v-- is the same as the static type of e1.v.
+
+
+
+
+
+
+
+  // ++e1?.v is equivalent to e1?.v += 1.
+
+
+
+  // ++C?.v is equivalent to C?.v += 1.
+
+
+
+  // The static type of ++e1?.v is the same as the static type of e1.v + 1.
+
+
+
+
+
+
+
+  // --e1?.v is equivalent to e1?.v -= 1.
+
+
+
+  // --C?.v is equivalent to C?.v -= 1.
+
+
+
+  // The static type of --e1?.v is the same as the static type of e1.v - 1.
+
+
+
+
+
+
+}
diff --git a/tests/language/null_aware/increment_decrement_test.dart b/tests/language/null_aware/increment_decrement_test.dart
new file mode 100644
index 0000000..1a5ea4e
--- /dev/null
+++ b/tests/language/null_aware/increment_decrement_test.dart
@@ -0,0 +1,152 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it appears in a postincrement or
+// preincrement expression (or a postdecrement or predecrement expression).
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+class C {
+  int v;
+  C(this.v);
+  static late int staticInt;
+}
+
+class D {
+  E v;
+  D(this.v);
+  static late E staticE;
+}
+
+class E {
+  G operator +(int i) => new I();
+  G operator -(int i) => new I();
+}
+
+class F {}
+
+class G extends E implements F {}
+
+class H {}
+
+class I extends G implements H {}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if assignment to "?." is not implemented.
+  // This makes status files easier to maintain.
+  nullC()?.v = 1;
+
+  // e1?.v++ is equivalent to ((x) => x == null ? null : x.v++)(e1).
+  Expect.equals(null, nullC()?.v++);
+  { C? c = new C(1); Expect.equals(1, c?.v++); Expect.equals(2, c!.v); }
+
+  // C?.v++ is equivalent to C.v++.
+  { C.staticInt = 1; Expect.equals(1, C?.staticInt++); Expect.equals(2, C.staticInt); }
+  { h.C.staticInt = 1; Expect.equals(1, h.C?.staticInt++); Expect.equals(2, h.C.staticInt); }
+
+  // The static type of e1?.v++ is the same as the static type of e1.v.
+  { E e1 = new E(); D? d = new D(e1); E? e2 = d?.v++; Expect.identical(e1, e2); }
+  { G g = new G(); D? d = new D(g); F? f = d?.v++; Expect.identical(f, g); }
+  //                                       ^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+  // [cfe] A value of type 'E?' can't be assigned to a variable of type 'F?'.
+  { E e1 = new E(); D.staticE = e1; E? e2 = D?.staticE++; Expect.identical(e1, e2); }
+  { h.E e1 = new h.E(); h.D.staticE = e1; h.E? e2 = h.D?.staticE++; Expect.identical(e1, e2); }
+  { G g = new G(); D.staticE = g; F? f = D?.staticE++; Expect.identical(f, g); }
+  //                                     ^^^^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+  //                                               ^
+  // [cfe] A value of type 'E' can't be assigned to a variable of type 'F?'.
+  { h.G g = new h.G(); h.D.staticE = g; h.F? f = h.D?.staticE++; Expect.identical(f, g); }
+  //                                             ^^^^^^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+  //                                                         ^
+  // [cfe] A value of type 'E' can't be assigned to a variable of type 'F?'.
+
+  // e1?.v-- is equivalent to ((x) => x == null ? null : x.v--)(e1).
+  Expect.equals(null, nullC()?.v--);
+  { C? c = new C(1); Expect.equals(1, c?.v--); Expect.equals(0, c!.v); }
+
+  // C?.v-- is equivalent to C.v--.
+  { C.staticInt = 1; Expect.equals(1, C?.staticInt--); Expect.equals(0, C.staticInt); }
+  { h.C.staticInt = 1; Expect.equals(1, h.C?.staticInt--); Expect.equals(0, h.C.staticInt); }
+
+  // The static type of e1?.v-- is the same as the static type of e1.v.
+  { E e1 = new E(); D? d = new D(e1); E? e2 = d?.v--; Expect.identical(e1, e2); }
+  { G g = new G(); D? d = new D(g); F? f = d?.v--; Expect.identical(f, g); }
+  //                                       ^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+  // [cfe] A value of type 'E?' can't be assigned to a variable of type 'F?'.
+  { E e1 = new E(); D.staticE = e1; E? e2 = D?.staticE--; Expect.identical(e1, e2); }
+  { h.E e1 = new h.E(); h.D.staticE = e1; h.E? e2 = h.D?.staticE--; Expect.identical(e1, e2); }
+  { G g = new G(); D.staticE = g; F? f = D?.staticE--; Expect.identical(f, g); }
+  //                                     ^^^^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+  //                                               ^
+  // [cfe] A value of type 'E' can't be assigned to a variable of type 'F?'.
+  { h.G g = new h.G(); h.D.staticE = g; h.F? f = h.D?.staticE--; Expect.identical(f, g); }
+  //                                             ^^^^^^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+  //                                                         ^
+  // [cfe] A value of type 'E' can't be assigned to a variable of type 'F?'.
+
+  // ++e1?.v is equivalent to e1?.v += 1.
+  Expect.equals(null, ++nullC()?.v);
+  { C? c = new C(1); Expect.equals(2, ++c?.v); Expect.equals(2, c!.v); }
+
+  // ++C?.v is equivalent to C?.v += 1.
+  { C.staticInt = 1; Expect.equals(2, ++C?.staticInt); Expect.equals(2, C.staticInt); }
+  { h.C.staticInt = 1; Expect.equals(2, ++h.C?.staticInt); Expect.equals(2, h.C.staticInt); }
+
+  // The static type of ++e1?.v is the same as the static type of e1.v + 1.
+  { D? d = new D(new E()); F? f = ++d?.v; Expect.identical(d!.v, f); }
+  { D? d = new D(new E()); H? h = ++d?.v; Expect.identical(d!.v, h); }
+  //                              ^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+  //                                ^
+  // [cfe] A value of type 'G?' can't be assigned to a variable of type 'H?'.
+  { D.staticE = new E(); F? f = ++D?.staticE; Expect.identical(D.staticE, f); }
+  { h.D.staticE = new h.E(); h.F? f = ++h.D?.staticE; Expect.identical(h.D.staticE, f); }
+  { D.staticE = new E(); H? h = ++D?.staticE; Expect.identical(D.staticE, h); }
+  //                            ^^^^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+  //                                 ^
+  // [cfe] A value of type 'G' can't be assigned to a variable of type 'H?'.
+  { h.D.staticE = new h.E(); h.H? hh = ++h.D?.staticE; Expect.identical(h.D.staticE, hh); }
+  //                                   ^^^^^^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+  //                                          ^
+  // [cfe] A value of type 'G' can't be assigned to a variable of type 'H?'.
+
+  // --e1?.v is equivalent to e1?.v -= 1.
+  Expect.equals(null, --nullC()?.v);
+  { C? c = new C(1); Expect.equals(0, --c?.v); Expect.equals(0, c!.v); }
+
+  // --C?.v is equivalent to C?.v -= 1.
+  { C.staticInt = 1; Expect.equals(0, --C?.staticInt); Expect.equals(0, C.staticInt); }
+  { h.C.staticInt = 1; Expect.equals(0, --h.C?.staticInt); Expect.equals(0, h.C.staticInt); }
+
+  // The static type of --e1?.v is the same as the static type of e1.v - 1.
+  { D? d = new D(new E()); F? f = --d?.v; Expect.identical(d!.v, f); }
+  { D? d = new D(new E()); H? h = --d?.v; Expect.identical(d!.v, h); }
+  //                              ^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+  //                                ^
+  // [cfe] A value of type 'G?' can't be assigned to a variable of type 'H?'.
+  { D.staticE = new E(); F? f = --D?.staticE; Expect.identical(D.staticE, f); }
+  { h.D.staticE = new h.E(); h.F? f = --h.D?.staticE; Expect.identical(h.D.staticE, f); }
+  { D.staticE = new E(); H? h = --D?.staticE; Expect.identical(D.staticE, h); }
+  //                            ^^^^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+  //                                 ^
+  // [cfe] A value of type 'G' can't be assigned to a variable of type 'H?'.
+  { h.D.staticE = new h.E(); h.H? hh = --h.D?.staticE; Expect.identical(h.D.staticE, hh); }
+  //                                   ^^^^^^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+  //                                          ^
+  // [cfe] A value of type 'G' can't be assigned to a variable of type 'H?'.
+}
diff --git a/tests/language/null_aware/invocation_runtime_1_test.dart b/tests/language/null_aware/invocation_runtime_1_test.dart
new file mode 100644
index 0000000..e5e1ed7
--- /dev/null
+++ b/tests/language/null_aware/invocation_runtime_1_test.dart
@@ -0,0 +1,65 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it is used to invoke a method.
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+bad() {
+  Expect.fail('Should not be executed');
+}
+
+class B {}
+
+class C extends B {
+  f(callback()?) => callback!();
+  int g(int callback()) => callback();
+  static staticF(callback()) => callback();
+  static int staticG(int callback()) => callback();
+}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if method invocation using "?." is not
+  // implemented.  This makes status files easier to maintain.
+  nullC()?.f(null);
+
+  // o?.m(...) is equivalent to ((x) => x == null ? null : x.m(...))(o).
+  Expect.equals(null, nullC()?.f(bad()));
+
+
+  // C?.m(...) is equivalent to C.m(...).
+
+
+
+  // The static type of o?.m(...) is the same as the static type of
+  // o.m(...).
+
+
+
+
+
+
+
+
+
+  // Let T be the static type of o and let y be a fresh variable of type T.
+  // Exactly the same static warnings that would be caused by y.m(...) are also
+  // generated in the case of o?.m(...).
+
+
+
+  // '?.' can't be used to access toplevel functions in libraries imported via
+  // prefix.
+
+
+  // Nor can it be used to access the toString method on the class Type.
+
+
+}
diff --git a/tests/language/null_aware/invocation_runtime_2_test.dart b/tests/language/null_aware/invocation_runtime_2_test.dart
new file mode 100644
index 0000000..70a36d1
--- /dev/null
+++ b/tests/language/null_aware/invocation_runtime_2_test.dart
@@ -0,0 +1,66 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it is used to invoke a method.
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+bad() {
+  Expect.fail('Should not be executed');
+}
+
+class B {}
+
+class C extends B {
+  f(callback()?) => callback!();
+  int g(int callback()) => callback();
+  static staticF(callback()) => callback();
+  static int staticG(int callback()) => callback();
+}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if method invocation using "?." is not
+  // implemented.  This makes status files easier to maintain.
+  nullC()?.f(null);
+
+  // o?.m(...) is equivalent to ((x) => x == null ? null : x.m(...))(o).
+
+  C? c = C();
+  Expect.equals(1, c?.f(() => 1));
+
+  // C?.m(...) is equivalent to C.m(...).
+
+
+
+  // The static type of o?.m(...) is the same as the static type of
+  // o.m(...).
+
+
+
+
+
+
+
+
+
+  // Let T be the static type of o and let y be a fresh variable of type T.
+  // Exactly the same static warnings that would be caused by y.m(...) are also
+  // generated in the case of o?.m(...).
+
+
+
+  // '?.' can't be used to access toplevel functions in libraries imported via
+  // prefix.
+
+
+  // Nor can it be used to access the toString method on the class Type.
+
+
+}
diff --git a/tests/language/null_aware/invocation_runtime_3_test.dart b/tests/language/null_aware/invocation_runtime_3_test.dart
new file mode 100644
index 0000000..13f50a1
--- /dev/null
+++ b/tests/language/null_aware/invocation_runtime_3_test.dart
@@ -0,0 +1,65 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it is used to invoke a method.
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+bad() {
+  Expect.fail('Should not be executed');
+}
+
+class B {}
+
+class C extends B {
+  f(callback()?) => callback!();
+  int g(int callback()) => callback();
+  static staticF(callback()) => callback();
+  static int staticG(int callback()) => callback();
+}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if method invocation using "?." is not
+  // implemented.  This makes status files easier to maintain.
+  nullC()?.f(null);
+
+  // o?.m(...) is equivalent to ((x) => x == null ? null : x.m(...))(o).
+
+
+
+  // C?.m(...) is equivalent to C.m(...).
+  Expect.equals(1, C?.staticF(() => 1));
+
+
+  // The static type of o?.m(...) is the same as the static type of
+  // o.m(...).
+
+
+
+
+
+
+
+
+
+  // Let T be the static type of o and let y be a fresh variable of type T.
+  // Exactly the same static warnings that would be caused by y.m(...) are also
+  // generated in the case of o?.m(...).
+
+
+
+  // '?.' can't be used to access toplevel functions in libraries imported via
+  // prefix.
+
+
+  // Nor can it be used to access the toString method on the class Type.
+
+
+}
diff --git a/tests/language/null_aware/invocation_runtime_4_test.dart b/tests/language/null_aware/invocation_runtime_4_test.dart
new file mode 100644
index 0000000..ea6b6b1
--- /dev/null
+++ b/tests/language/null_aware/invocation_runtime_4_test.dart
@@ -0,0 +1,65 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it is used to invoke a method.
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+bad() {
+  Expect.fail('Should not be executed');
+}
+
+class B {}
+
+class C extends B {
+  f(callback()?) => callback!();
+  int g(int callback()) => callback();
+  static staticF(callback()) => callback();
+  static int staticG(int callback()) => callback();
+}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if method invocation using "?." is not
+  // implemented.  This makes status files easier to maintain.
+  nullC()?.f(null);
+
+  // o?.m(...) is equivalent to ((x) => x == null ? null : x.m(...))(o).
+
+
+
+  // C?.m(...) is equivalent to C.m(...).
+
+  Expect.equals(1, h.C?.staticF(() => 1));
+
+  // The static type of o?.m(...) is the same as the static type of
+  // o.m(...).
+
+
+
+
+
+
+
+
+
+  // Let T be the static type of o and let y be a fresh variable of type T.
+  // Exactly the same static warnings that would be caused by y.m(...) are also
+  // generated in the case of o?.m(...).
+
+
+
+  // '?.' can't be used to access toplevel functions in libraries imported via
+  // prefix.
+
+
+  // Nor can it be used to access the toString method on the class Type.
+
+
+}
diff --git a/tests/language/null_aware/invocation_runtime_5_test.dart b/tests/language/null_aware/invocation_runtime_5_test.dart
new file mode 100644
index 0000000..b95b1e5
--- /dev/null
+++ b/tests/language/null_aware/invocation_runtime_5_test.dart
@@ -0,0 +1,65 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it is used to invoke a method.
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+bad() {
+  Expect.fail('Should not be executed');
+}
+
+class B {}
+
+class C extends B {
+  f(callback()?) => callback!();
+  int g(int callback()) => callback();
+  static staticF(callback()) => callback();
+  static int staticG(int callback()) => callback();
+}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if method invocation using "?." is not
+  // implemented.  This makes status files easier to maintain.
+  nullC()?.f(null);
+
+  // o?.m(...) is equivalent to ((x) => x == null ? null : x.m(...))(o).
+
+
+
+  // C?.m(...) is equivalent to C.m(...).
+
+
+
+  // The static type of o?.m(...) is the same as the static type of
+  // o.m(...).
+  { int? i = nullC()?.g(bad()); Expect.equals(null, i); }
+
+
+
+
+
+
+
+
+  // Let T be the static type of o and let y be a fresh variable of type T.
+  // Exactly the same static warnings that would be caused by y.m(...) are also
+  // generated in the case of o?.m(...).
+
+
+
+  // '?.' can't be used to access toplevel functions in libraries imported via
+  // prefix.
+
+
+  // Nor can it be used to access the toString method on the class Type.
+
+
+}
diff --git a/tests/language/null_aware/invocation_runtime_6_test.dart b/tests/language/null_aware/invocation_runtime_6_test.dart
new file mode 100644
index 0000000..23559d8
--- /dev/null
+++ b/tests/language/null_aware/invocation_runtime_6_test.dart
@@ -0,0 +1,66 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it is used to invoke a method.
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+bad() {
+  Expect.fail('Should not be executed');
+}
+
+class B {}
+
+class C extends B {
+  f(callback()?) => callback!();
+  int g(int callback()) => callback();
+  static staticF(callback()) => callback();
+  static int staticG(int callback()) => callback();
+}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if method invocation using "?." is not
+  // implemented.  This makes status files easier to maintain.
+  nullC()?.f(null);
+
+  // o?.m(...) is equivalent to ((x) => x == null ? null : x.m(...))(o).
+
+
+
+  // C?.m(...) is equivalent to C.m(...).
+
+
+
+  // The static type of o?.m(...) is the same as the static type of
+  // o.m(...).
+
+  C? c = new C();
+  { int? i = c?.g(() => 1); Expect.equals(1, i); }
+
+
+
+
+
+
+
+  // Let T be the static type of o and let y be a fresh variable of type T.
+  // Exactly the same static warnings that would be caused by y.m(...) are also
+  // generated in the case of o?.m(...).
+
+
+
+  // '?.' can't be used to access toplevel functions in libraries imported via
+  // prefix.
+
+
+  // Nor can it be used to access the toString method on the class Type.
+
+
+}
diff --git a/tests/language/null_aware/invocation_runtime_7_test.dart b/tests/language/null_aware/invocation_runtime_7_test.dart
new file mode 100644
index 0000000..8bed5f0
--- /dev/null
+++ b/tests/language/null_aware/invocation_runtime_7_test.dart
@@ -0,0 +1,65 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it is used to invoke a method.
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+bad() {
+  Expect.fail('Should not be executed');
+}
+
+class B {}
+
+class C extends B {
+  f(callback()?) => callback!();
+  int g(int callback()) => callback();
+  static staticF(callback()) => callback();
+  static int staticG(int callback()) => callback();
+}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if method invocation using "?." is not
+  // implemented.  This makes status files easier to maintain.
+  nullC()?.f(null);
+
+  // o?.m(...) is equivalent to ((x) => x == null ? null : x.m(...))(o).
+
+
+
+  // C?.m(...) is equivalent to C.m(...).
+
+
+
+  // The static type of o?.m(...) is the same as the static type of
+  // o.m(...).
+
+
+
+
+  { int? i = C?.staticG(() => 1); Expect.equals(1, i); }
+
+
+
+
+  // Let T be the static type of o and let y be a fresh variable of type T.
+  // Exactly the same static warnings that would be caused by y.m(...) are also
+  // generated in the case of o?.m(...).
+
+
+
+  // '?.' can't be used to access toplevel functions in libraries imported via
+  // prefix.
+
+
+  // Nor can it be used to access the toString method on the class Type.
+
+
+}
diff --git a/tests/language/null_aware/invocation_runtime_8_test.dart b/tests/language/null_aware/invocation_runtime_8_test.dart
new file mode 100644
index 0000000..62f8c4a
--- /dev/null
+++ b/tests/language/null_aware/invocation_runtime_8_test.dart
@@ -0,0 +1,65 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it is used to invoke a method.
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+bad() {
+  Expect.fail('Should not be executed');
+}
+
+class B {}
+
+class C extends B {
+  f(callback()?) => callback!();
+  int g(int callback()) => callback();
+  static staticF(callback()) => callback();
+  static int staticG(int callback()) => callback();
+}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if method invocation using "?." is not
+  // implemented.  This makes status files easier to maintain.
+  nullC()?.f(null);
+
+  // o?.m(...) is equivalent to ((x) => x == null ? null : x.m(...))(o).
+
+
+
+  // C?.m(...) is equivalent to C.m(...).
+
+
+
+  // The static type of o?.m(...) is the same as the static type of
+  // o.m(...).
+
+
+
+
+
+  { int? i = h.C?.staticG(() => 1); Expect.equals(1, i); }
+
+
+
+  // Let T be the static type of o and let y be a fresh variable of type T.
+  // Exactly the same static warnings that would be caused by y.m(...) are also
+  // generated in the case of o?.m(...).
+
+
+
+  // '?.' can't be used to access toplevel functions in libraries imported via
+  // prefix.
+
+
+  // Nor can it be used to access the toString method on the class Type.
+
+
+}
diff --git a/tests/language/null_aware/invocation_runtime_test.dart b/tests/language/null_aware/invocation_runtime_test.dart
new file mode 100644
index 0000000..8956053
--- /dev/null
+++ b/tests/language/null_aware/invocation_runtime_test.dart
@@ -0,0 +1,65 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it is used to invoke a method.
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+bad() {
+  Expect.fail('Should not be executed');
+}
+
+class B {}
+
+class C extends B {
+  f(callback()?) => callback!();
+  int g(int callback()) => callback();
+  static staticF(callback()) => callback();
+  static int staticG(int callback()) => callback();
+}
+
+C? nullC() => null;
+
+main() {
+  // Make sure the "none" test fails if method invocation using "?." is not
+  // implemented.  This makes status files easier to maintain.
+  nullC()?.f(null);
+
+  // o?.m(...) is equivalent to ((x) => x == null ? null : x.m(...))(o).
+
+
+
+  // C?.m(...) is equivalent to C.m(...).
+
+
+
+  // The static type of o?.m(...) is the same as the static type of
+  // o.m(...).
+
+
+
+
+
+
+
+
+
+  // Let T be the static type of o and let y be a fresh variable of type T.
+  // Exactly the same static warnings that would be caused by y.m(...) are also
+  // generated in the case of o?.m(...).
+
+
+
+  // '?.' can't be used to access toplevel functions in libraries imported via
+  // prefix.
+
+
+  // Nor can it be used to access the toString method on the class Type.
+
+
+}
diff --git a/tests/language/null_aware/invocation_test.dart b/tests/language/null_aware/invocation_test.dart
new file mode 100644
index 0000000..4131cdf
--- /dev/null
+++ b/tests/language/null_aware/invocation_test.dart
@@ -0,0 +1,94 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Verify semantics of the ?. operator when it is used to invoke a method.
+
+import "package:expect/expect.dart";
+import "conditional_access_helper.dart" as h;
+
+bad() {
+  Expect.fail('Should not be executed');
+}
+
+class B {}
+
+class C extends B {
+  f(callback()?) => callback!();
+  int? g(int? callback()) => callback();
+  static staticF(callback()) => callback();
+  static int? staticG(int? callback()) => callback();
+}
+
+C? nullC() => null;
+
+main() {
+  C? c = C();
+
+  // Make sure the "none" test fails if method invocation using "?." is not
+  // implemented.  This makes status files easier to maintain.
+  nullC()?.f(null);
+
+  // o?.m(...) is equivalent to ((x) => x == null ? null : x.m(...))(o).
+  Expect.equals(null, nullC()?.f(bad()));
+  Expect.equals(1, c?.f(() => 1));
+
+  // C?.m(...) is equivalent to C.m(...).
+  Expect.equals(1, C?.staticF(() => 1));
+  Expect.equals(1, h.C?.staticF(() => 1));
+
+  // The static type of o?.m(...) is the same as the static type of
+  // o.m(...).
+  { int? i = nullC()?.g(bad()); Expect.equals(null, i); }
+  { int? i = c?.g(() => 1); Expect.equals(1, i); }
+  { String? s = nullC()?.g(bad()); Expect.equals(null, s); }
+  //            ^^^^^^^^^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+  // [cfe] A value of type 'int?' can't be assigned to a variable of type 'String?'.
+  { String? s = c?.g(() => null); Expect.equals(null, s); }
+  //            ^^^^^^^^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+  //            ^
+  // [cfe] A value of type 'int?' can't be assigned to a variable of type 'String?'.
+  { int? i = C?.staticG(() => 1); Expect.equals(1, i); }
+  { int? i = h.C?.staticG(() => 1); Expect.equals(1, i); }
+  { String? s = C?.staticG(() => null); Expect.equals(null, s); }
+  //            ^^^^^^^^^^^^^^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+  //               ^
+  // [cfe] A value of type 'int?' can't be assigned to a variable of type 'String?'.
+  { String? s = h.C?.staticG(() => null); Expect.equals(null, s); }
+  //            ^^^^^^^^^^^^^^^^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+  //                 ^
+  // [cfe] A value of type 'int?' can't be assigned to a variable of type 'String?'.
+
+  // Let T be the static type of o and let y be a fresh variable of type T.
+  // Exactly the same static warnings that would be caused by y.m(...) are also
+  // generated in the case of o?.m(...).
+  { B? b = new C(); Expect.equals(1, b?.f(() => 1)); }
+  //                                    ^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_METHOD
+  // [cfe] The method 'f' isn't defined for the class 'B'.
+  { int? i = 1; Expect.equals(null, nullC()?.f(i)); }
+  //                                           ^
+  // [analyzer] STATIC_WARNING.ARGUMENT_TYPE_NOT_ASSIGNABLE
+  // [cfe] The argument type 'int?' can't be assigned to the parameter type 'dynamic Function()?'.
+
+  // '?.' can't be used to access toplevel functions in libraries imported via
+  // prefix.
+  h?.topLevelFunction();
+//^
+// [analyzer] COMPILE_TIME_ERROR.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT
+// [cfe] A prefix can't be used with null-aware operators.
+
+  // Nor can it be used to access the toString method on the class Type.
+  Expect.throwsNoSuchMethodError(() => C?.toString());
+  //                                      ^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_METHOD
+  // [cfe] Method not found: 'C.toString'.
+  Expect.throwsNoSuchMethodError(() => h.C?.toString());
+  //                                        ^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_METHOD
+  // [cfe] Method not found: 'C.toString'.
+}
diff --git a/tests/language/null_aware/opt_test.dart b/tests/language/null_aware/opt_test.dart
new file mode 100644
index 0000000..c5bb8a7
--- /dev/null
+++ b/tests/language/null_aware/opt_test.dart
@@ -0,0 +1,103 @@
+// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// VMOptions=--optimization_counter_threshold=5
+//
+// Basic null-aware operator test that invokes the optimizing compiler.
+
+import "package:expect/expect.dart";
+
+class C {
+  C(this.f);
+  var f;
+  m(a) => a;
+}
+
+bomb() {
+  Expect.fail('Should not be executed');
+  return 100;
+}
+
+getNull() => null;
+
+test() {
+  var c;
+  C? d = new C(5);
+  Expect.equals(null, c?.m(bomb()));
+  Expect.equals(null, getNull()?.anything(bomb()));
+  Expect.equals(1, d?.m(1));
+
+  C? c2 = new C(1);
+  Expect.equals(1, c2?.f);
+  Expect.equals(null, c?.v);
+  Expect.equals(10, c ?? 10);
+  Expect.equals(d, d ?? bomb());
+  List<List<int>>? list = [[3]];
+  Expect.equals(
+      3,
+      list?.expand((i) => i).toList()[0]);
+  Expect.equals(null, (null as dynamic)?.expand((i) => i)?.toList());
+
+  var e;
+  // The assignment to e is not executed since d != null.
+  d ??= e ??= new C(100);
+  Expect.equals(null, e);
+  e ??= new C(100);
+  Expect.equals(100, e?.f);
+  e?.f ??= 200;
+  Expect.equals(100, e?.f);
+
+  e.f = null;
+  e?.f ??= 200;
+  Expect.equals(200, e?.f);
+
+  c?.f ??= 400;
+  Expect.equals(null, c?.f);
+  Expect.equals(null, c?.f++);
+  e?.f++;
+  Expect.equals(201, e.f);
+
+  int? five = 5;
+  var x = five ?? bomb();
+}
+
+// Check that instructions without result do not crash.
+test2() {
+  var c;
+  c?.v;
+  c?.m(bomb());
+}
+
+class Bar {
+  String? s;
+}
+
+class Foo {
+  Bar? _bar;
+  String? str;
+
+  Foo(this._bar) : str = _bar?.s;
+}
+
+// Check that ?? isn't incorrectly optimized as non-nullable
+// (DDC regression test)
+test3() {
+  List? n = null;
+  var func = n?.add;
+  var result = func ?? 1;
+  Expect.equals(result, 1);
+
+  String? x = null;
+  Expect.equals(x?.split(',') ?? 'hello', 'hello');
+}
+
+main() {
+  for (int i = 0; i < 10; i++) {
+    test();
+    test2();
+    test3();
+  }
+
+  Expect.equals(null, new Foo(new Bar()).str);
+}
diff --git a/tests/language/type_object/constant_type_literal_runtime_test.dart b/tests/language/type_object/constant_type_literal_runtime_test.dart
new file mode 100644
index 0000000..30fdd50
--- /dev/null
+++ b/tests/language/type_object/constant_type_literal_runtime_test.dart
@@ -0,0 +1,20 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test for type literals as compile-time constants.
+
+class C<T> {
+  void m() {
+    const List lst = const [
+
+    ];
+  }
+}
+
+main() {
+  new C().m();
+}
diff --git a/tests/language/type_object/constant_type_literal_test.dart b/tests/language/type_object/constant_type_literal_test.dart
new file mode 100644
index 0000000..91e07f4
--- /dev/null
+++ b/tests/language/type_object/constant_type_literal_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test for type literals as compile-time constants.
+
+class C<T> {
+  void m() {
+    const List lst = const [
+      T
+//    ^
+// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
+// [cfe] Type variables can't be used as constants.
+//    ^
+// [analyzer] COMPILE_TIME_ERROR.NON_CONSTANT_LIST_ELEMENT
+    ];
+  }
+}
+
+main() {
+  new C().m();
+}
diff --git a/tests/language/type_object/first_class_types_constants_test.dart b/tests/language/type_object/first_class_types_constants_test.dart
new file mode 100644
index 0000000..f0447f7
--- /dev/null
+++ b/tests/language/type_object/first_class_types_constants_test.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+class C<T> {
+  final T t;
+  const C(this.t);
+}
+
+typedef int Fun(bool, String);
+
+const c0 = C;
+const c1 = const C<Type>(C);
+const c2 = Fun;
+const c3 = const C<Type>(Fun);
+
+main() {
+  Expect.identical(C, C);
+  Expect.identical(C, c0);
+  Expect.identical(c1, c1);
+  Expect.notEquals(c0, c1);
+  Expect.notEquals(c1, c2);
+  Expect.identical(c1.t, c0);
+  Expect.notEquals(C, Fun);
+  Expect.identical(Fun, Fun);
+  Expect.identical(Fun, c2);
+  Expect.identical(c3.t, c2);
+}
diff --git a/tests/language/type_object/first_class_types_lib1.dart b/tests/language/type_object/first_class_types_lib1.dart
new file mode 100644
index 0000000..baadc66
--- /dev/null
+++ b/tests/language/type_object/first_class_types_lib1.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library lib1;
+
+class A {}
diff --git a/tests/language/type_object/first_class_types_lib2.dart b/tests/language/type_object/first_class_types_lib2.dart
new file mode 100644
index 0000000..de943b7
--- /dev/null
+++ b/tests/language/type_object/first_class_types_lib2.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library lib2;
+
+class A {}
diff --git a/tests/language/type_object/first_class_types_libraries_test.dart b/tests/language/type_object/first_class_types_libraries_test.dart
new file mode 100644
index 0000000..ad5f552
--- /dev/null
+++ b/tests/language/type_object/first_class_types_libraries_test.dart
@@ -0,0 +1,25 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library firstClassLibrariestest;
+
+import "package:expect/expect.dart";
+import 'first_class_types_lib1.dart' as lib1;
+import 'first_class_types_lib2.dart' as lib2;
+
+class C<X> {}
+
+sameType(a, b) {
+  Expect.equals(a.runtimeType, b.runtimeType);
+}
+
+differentType(a, b) {
+  Expect.notEquals(a.runtimeType, b.runtimeType);
+}
+
+main() {
+  sameType(new lib1.A(), new lib1.A());
+  differentType(new lib1.A(), new lib2.A());
+  differentType(new C<lib1.A>(), new C<lib2.A>());
+}
diff --git a/tests/language/type_object/first_class_types_literals_runtime_1_test.dart b/tests/language/type_object/first_class_types_literals_runtime_1_test.dart
new file mode 100644
index 0000000..b415e99
--- /dev/null
+++ b/tests/language/type_object/first_class_types_literals_runtime_1_test.dart
@@ -0,0 +1,67 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+class C<T, U, V> {}
+
+class D {}
+
+typedef int Foo(bool b);
+
+sameType(a, b) {
+  Expect.equals(a.runtimeType, b.runtimeType);
+}
+
+main() {
+  void foo(a) {}
+
+  // Test that literals can be used in different contexts.
+  [int];
+  ([int]);
+  foo([int]);
+  [int].length;
+  ({1: int});
+  foo({1: int});
+  ({1: int}).keys;
+
+  // Test type literals.
+  Expect.equals(int, int);
+  Expect.notEquals(int, num);
+  Expect.equals(Foo, Foo);
+  Expect.equals(dynamic, dynamic);
+
+  // Test that class literals return instances of Type.
+  Expect.isTrue((D).runtimeType is Type);
+  Expect.isTrue((dynamic).runtimeType is Type);
+
+  // Test that types from runtimeType and literals agree.
+  Expect.equals(int, 1.runtimeType);
+  Expect.equals(String, 'hest'.runtimeType);
+  Expect.equals(double, (0.5).runtimeType);
+  Expect.equals(bool, true.runtimeType);
+  Expect.equals(Object, Object().runtimeType);
+  Expect.equals(C, new C().runtimeType);
+
+
+  // runtimeType on type is idempotent.
+  Expect.equals((D).runtimeType, (D).runtimeType.runtimeType);
+
+  // Test that operator calls on class literals go to Type.
+
+
+
+
+
+
+
+
+
+
+
+  Expect.equals((dynamic).toString(), 'dynamic');
+}
diff --git a/tests/language/type_object/first_class_types_literals_runtime_2_test.dart b/tests/language/type_object/first_class_types_literals_runtime_2_test.dart
new file mode 100644
index 0000000..e5c8442
--- /dev/null
+++ b/tests/language/type_object/first_class_types_literals_runtime_2_test.dart
@@ -0,0 +1,67 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+class C<T, U, V> {}
+
+class D {}
+
+typedef int Foo(bool b);
+
+sameType(a, b) {
+  Expect.equals(a.runtimeType, b.runtimeType);
+}
+
+main() {
+  void foo(a) {}
+
+  // Test that literals can be used in different contexts.
+  [int];
+  ([int]);
+  foo([int]);
+  [int].length;
+  ({1: int});
+  foo({1: int});
+  ({1: int}).keys;
+
+  // Test type literals.
+  Expect.equals(int, int);
+  Expect.notEquals(int, num);
+  Expect.equals(Foo, Foo);
+  Expect.equals(dynamic, dynamic);
+
+  // Test that class literals return instances of Type.
+  Expect.isTrue((D).runtimeType is Type);
+  Expect.isTrue((dynamic).runtimeType is Type);
+
+  // Test that types from runtimeType and literals agree.
+  Expect.equals(int, 1.runtimeType);
+  Expect.equals(String, 'hest'.runtimeType);
+  Expect.equals(double, (0.5).runtimeType);
+  Expect.equals(bool, true.runtimeType);
+  Expect.equals(Object, Object().runtimeType);
+
+  Expect.equals(D, new D().runtimeType);
+
+  // runtimeType on type is idempotent.
+  Expect.equals((D).runtimeType, (D).runtimeType.runtimeType);
+
+  // Test that operator calls on class literals go to Type.
+
+
+
+
+
+
+
+
+
+
+
+  Expect.equals((dynamic).toString(), 'dynamic');
+}
diff --git a/tests/language/type_object/first_class_types_literals_runtime_test.dart b/tests/language/type_object/first_class_types_literals_runtime_test.dart
new file mode 100644
index 0000000..3df083a
--- /dev/null
+++ b/tests/language/type_object/first_class_types_literals_runtime_test.dart
@@ -0,0 +1,67 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+class C<T, U, V> {}
+
+class D {}
+
+typedef int Foo(bool b);
+
+sameType(a, b) {
+  Expect.equals(a.runtimeType, b.runtimeType);
+}
+
+main() {
+  void foo(a) {}
+
+  // Test that literals can be used in different contexts.
+  [int];
+  ([int]);
+  foo([int]);
+  [int].length;
+  ({1: int});
+  foo({1: int});
+  ({1: int}).keys;
+
+  // Test type literals.
+  Expect.equals(int, int);
+  Expect.notEquals(int, num);
+  Expect.equals(Foo, Foo);
+  Expect.equals(dynamic, dynamic);
+
+  // Test that class literals return instances of Type.
+  Expect.isTrue((D).runtimeType is Type);
+  Expect.isTrue((dynamic).runtimeType is Type);
+
+  // Test that types from runtimeType and literals agree.
+  Expect.equals(int, 1.runtimeType);
+  Expect.equals(String, 'hest'.runtimeType);
+  Expect.equals(double, (0.5).runtimeType);
+  Expect.equals(bool, true.runtimeType);
+  Expect.equals(Object, Object().runtimeType);
+
+
+
+  // runtimeType on type is idempotent.
+  Expect.equals((D).runtimeType, (D).runtimeType.runtimeType);
+
+  // Test that operator calls on class literals go to Type.
+
+
+
+
+
+
+
+
+
+
+
+  Expect.equals((dynamic).toString(), 'dynamic');
+}
diff --git a/tests/language/type_object/first_class_types_literals_test.dart b/tests/language/type_object/first_class_types_literals_test.dart
new file mode 100644
index 0000000..aa02a4d
--- /dev/null
+++ b/tests/language/type_object/first_class_types_literals_test.dart
@@ -0,0 +1,100 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+class C<T, U, V> {}
+
+class D {}
+
+typedef int Foo(bool b);
+
+sameType(a, b) {
+  Expect.equals(a.runtimeType, b.runtimeType);
+}
+
+main() {
+  void foo(a) {}
+
+  // Test that literals can be used in different contexts.
+  [int];
+  ([int]);
+  foo([int]);
+  [int].length;
+  ({1: int});
+  foo({1: int});
+  ({1: int}).keys;
+
+  // Test type literals.
+  Expect.equals(int, int);
+  Expect.notEquals(int, num);
+  Expect.equals(Foo, Foo);
+  Expect.equals(dynamic, dynamic);
+
+  // Test that class literals return instances of Type.
+  Expect.isTrue((D).runtimeType is Type);
+  Expect.isTrue((dynamic).runtimeType is Type);
+
+  // Test that types from runtimeType and literals agree.
+  Expect.equals(int, 1.runtimeType);
+  Expect.equals(String, 'hest'.runtimeType);
+  Expect.equals(double, (0.5).runtimeType);
+  Expect.equals(bool, true.runtimeType);
+  Expect.equals(Object, Object().runtimeType);
+  Expect.equals(C, new C().runtimeType);
+  Expect.equals(D, new D().runtimeType);
+
+  // runtimeType on type is idempotent.
+  Expect.equals((D).runtimeType, (D).runtimeType.runtimeType);
+
+  // Test that operator calls on class literals go to Type.
+  Expect.throwsNoSuchMethodError(() => C = 1);
+  //                                   ^
+  // [analyzer] STATIC_WARNING.ASSIGNMENT_TO_TYPE
+  // [cfe] Can't assign to a type literal.
+  //                                       ^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+  Expect.throwsNoSuchMethodError(() => C++);
+  //                                   ^
+  // [analyzer] STATIC_WARNING.ASSIGNMENT_TO_TYPE
+  // [cfe] Can't assign to a type literal.
+  //                                    ^^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_OPERATOR
+  Expect.throwsNoSuchMethodError(() => C + 1);
+  //                                     ^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_OPERATOR
+  // [cfe] The operator '+' isn't defined for the class 'Type'.
+  Expect.throwsNoSuchMethodError(() => C[2]);
+  //                                    ^^^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_OPERATOR
+  // [cfe] The operator '[]' isn't defined for the class 'Type'.
+  Expect.throwsNoSuchMethodError(() => C[2] = 'hest');
+  //                                    ^^^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_OPERATOR
+  // [cfe] The operator '[]=' isn't defined for the class 'Type'.
+  Expect.throwsNoSuchMethodError(() => dynamic = 1);
+  //                                   ^
+  // [cfe] Can't assign to a type literal.
+  //                                             ^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+  Expect.throwsNoSuchMethodError(() => dynamic++);
+  //                                   ^
+  // [cfe] Can't assign to a type literal.
+  //                                          ^^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_OPERATOR
+  Expect.throwsNoSuchMethodError(() => dynamic + 1);
+  //                                           ^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_OPERATOR
+  // [cfe] The operator '+' isn't defined for the class 'Type'.
+  Expect.throwsNoSuchMethodError(() => dynamic[2]);
+  //                                          ^^^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_OPERATOR
+  // [cfe] The operator '[]' isn't defined for the class 'Type'.
+  Expect.throwsNoSuchMethodError(() => dynamic[2] = 'hest');
+  //                                          ^^^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_OPERATOR
+  // [cfe] The operator '[]=' isn't defined for the class 'Type'.
+
+  Expect.equals((dynamic).toString(), 'dynamic');
+}
diff --git a/tests/language/type_object/first_class_types_test.dart b/tests/language/type_object/first_class_types_test.dart
new file mode 100644
index 0000000..d2eca28
--- /dev/null
+++ b/tests/language/type_object/first_class_types_test.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+class C<T> {}
+
+sameType(a, b) {
+  Expect.equals(a.runtimeType, b.runtimeType);
+}
+
+differentType(a, b) {
+  Expect.isFalse(a.runtimeType == b.runtimeType);
+}
+
+main() {
+  // Test types obtained by calling runtimeType.
+  var v1 = new C<int>();
+  var v2 = new C<int>();
+  sameType(v1, v2);
+
+  var v3 = new C<num>();
+  differentType(v1, v3);
+
+  var i = 1;
+  var s = 'string';
+  var d = 3.14;
+  var b = true;
+  sameType(2, i);
+  sameType('hest', s);
+  sameType(1.2, d);
+  sameType(false, b);
+
+  List l = [1, 2, 3];
+  Map m = {'a': 1, 'b': 2};
+  sameType([], l);
+  sameType({}, m);
+
+  // Test parameterized lists.
+  sameType(<int>[], <int>[]);
+  differentType(<int>[], <num>[]);
+  differentType(<int>[], []);
+}
diff --git a/tests/language/type_object/literal_canonicalization_test.dart b/tests/language/type_object/literal_canonicalization_test.dart
new file mode 100644
index 0000000..790f1b6
--- /dev/null
+++ b/tests/language/type_object/literal_canonicalization_test.dart
@@ -0,0 +1,26 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+class Foo {}
+
+class Box<T> {
+  Type get typeArg => T;
+}
+
+/// A typedef that defines a non-generic function type.
+typedef int Func1(bool b);
+
+/// Semantically identical to [Func], but using the Dart 2 syntax.
+typedef Func2 = int Function(bool);
+
+main() {
+  // Literals are canonicalized.
+  Expect.identical(Foo, Foo);
+  Expect.identical(Box, Box);
+  Expect.identical(new Box<Foo>().typeArg, new Box<Foo>().typeArg);
+  Expect.identical(Func1, Func1);
+  Expect.identical(Func2, Func2);
+}
diff --git a/tests/language/type_object/literal_prefix_call_test.dart b/tests/language/type_object/literal_prefix_call_test.dart
new file mode 100644
index 0000000..6467fdb
--- /dev/null
+++ b/tests/language/type_object/literal_prefix_call_test.dart
@@ -0,0 +1,10 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+import 'dart:core' as core;
+
+main() {
+  core.Map();
+}
diff --git a/tests/language/type_object/literal_type_literal_test.dart b/tests/language/type_object/literal_type_literal_test.dart
new file mode 100644
index 0000000..92da452
--- /dev/null
+++ b/tests/language/type_object/literal_type_literal_test.dart
@@ -0,0 +1,119 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+import 'literal_type_literal_test.dart' as prefix;
+
+// TODO(rnystrom): This test has a lot of overlap with some other language
+// tests, but those are sort of all over the place so I thought it useful to
+// test all of the relevant bits in one place here.
+
+class Foo {
+  static var property;
+  static method() => "result";
+}
+
+class Box<T> {
+  Type get typeArg => T;
+}
+
+class G<A, B> {}
+
+/// A typedef that defines a non-generic function type.
+typedef int Func(bool b);
+
+/// Semantically identical to [Func], but using the Dart 2 syntax.
+typedef Func2 = int Function(bool);
+
+/// A typedef that defines a generic function type.
+typedef GenericFunc = int Function<T>(T);
+
+/// A typedef with a type paramter that defines a non-generic function type.
+typedef int GenericTypedef<T>(T t);
+
+/// Semantically identical to [GenericTypedef], but using the Dart 2 syntax.
+typedef GenericTypedef2<T> = int Function(T);
+
+/// A typedef with a type paramter that defines a generic function type.
+typedef GenericTypedefAndFunc<S> = S Function<T>(T);
+
+main() {
+  // Primitive types.
+  testType(Object, "Object");
+  testType(Null, "Null");
+  testType(bool, "bool");
+  testType(double, "double");
+  testType(int, "int");
+  testType(num, "num");
+  testType(String, "String");
+
+  // Class types.
+  testType(Foo, "Foo");
+
+  // Generic classes.
+  testType(Box, ["Box", "Box<dynamic>"]);
+  testType(new Box<Foo>().typeArg, "Foo");
+  testType(new Box<dynamic>().typeArg, "dynamic");
+  testType(new Box<Box<Foo>>().typeArg, "Box<Foo>");
+  testType(G, ["G", "G<dynamic, dynamic>"]);
+  testType(new Box<G<int, String>>().typeArg, "G<int, String>");
+
+  // Typedef.
+  testType(Func, ["Func", "(bool) => int"]);
+  testType(Func2, ["Func2", "(bool) => int"]);
+  testType(GenericTypedef,
+      ["GenericTypedef", "GenericTypedef<dynamic>", "(dynamic) => int"]);
+  testType(GenericTypedef2,
+      ["GenericTypedef2", "GenericTypedef2<dynamic>", "(dynamic) => int"]);
+  testType(new Box<GenericTypedef<int>>().typeArg,
+      ["GenericTypedef<int>", "(int) => int"]);
+  testType(GenericFunc, ["GenericFunc", RegExp(r'<(\w+)>\((\1)\) => int')]);
+  testType(GenericTypedefAndFunc, [
+    "GenericTypedefAndFunc",
+    "GenericTypedefAndFunc<dynamic>",
+    RegExp(r'<(\w+)>\((\1)\) => dynamic')
+  ]);
+
+  // Literals are canonicalized.
+  // See type_literal_canonicalization_test.dart
+
+  // Static member uses are not type literals.
+  Foo.property = "value";
+  Expect.equals("value", Foo.property);
+  Expect.equals("result", Foo.method());
+
+  // Prefixed types are type literals.
+  testType(prefix.Foo, "Foo");
+
+  // Prefix member uses are not.
+  prefix.Foo.property = "value2";
+  Expect.equals("value2", prefix.Foo.property);
+  Expect.equals("result", prefix.Foo.method());
+}
+
+void testType(Type type, Object expectedToStringValues) {
+  Expect.isTrue(type is Type);
+  String text = type.toString();
+
+  // dart2js minified names should be tagged. We can still test types that don't
+  // contain minified names.
+  if (text.contains('minified:')) return;
+
+  if (expectedToStringValues is List) {
+    var matched = false;
+    for (var value in expectedToStringValues) {
+      if (value is String) {
+        matched = matched || value == text;
+      } else if (value is RegExp) {
+        matched = matched || value.hasMatch(text);
+      }
+    }
+    Expect.isTrue(matched,
+        'type `$type`.toString() should be one of: $expectedToStringValues.');
+  } else {
+    var string = expectedToStringValues as String;
+    Expect.equals(string, text);
+  }
+}
diff --git a/tests/language/type_object/reify_type_variable_test.dart b/tests/language/type_object/reify_type_variable_test.dart
new file mode 100644
index 0000000..50c5e41
--- /dev/null
+++ b/tests/language/type_object/reify_type_variable_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+class Foo<T> {
+  reify() {
+    return T;
+  }
+}
+
+main() {
+  Expect.equals(int, new Foo<int>().reify());
+  Expect.equals(Foo, new Foo().runtimeType);
+}
diff --git a/tests/language/type_object/runtime_type_function_helper.dart b/tests/language/type_object/runtime_type_function_helper.dart
new file mode 100644
index 0000000..c9f9822
--- /dev/null
+++ b/tests/language/type_object/runtime_type_function_helper.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+typedef String F(String returns, String arguments, [Map<String, String> named]);
+
+/// Formats a type like `(String, [int], {bool name}) => double`.
+String fn(String returns, String positional,
+    [Map<String, String> named = const {}]) {
+  var result = new StringBuffer();
+  result.write("($positional");
+  if (positional != "" && named.isNotEmpty) result.write(", ");
+  if (named.isNotEmpty) {
+    result.write("{");
+    bool first = true;
+    named.forEach((name, type) {
+      if (first) {
+        first = false;
+      } else {
+        result.write(", ");
+      }
+      result.write("$type $name");
+    });
+    result.write("}");
+  }
+  result.write(") => $returns");
+  return result.toString();
+}
+
+void check(String text, var thing) {
+  var type = thing.runtimeType.toString();
+  if (type == text) return;
+  Expect.fail("""
+Type print string does not match expectation
+  Expected: '$text'
+  Actual: '$type'
+""");
+}
diff --git a/tests/language/type_object/runtime_type_function_legacy_lib.dart b/tests/language/type_object/runtime_type_function_legacy_lib.dart
new file mode 100644
index 0000000..26e01de
--- /dev/null
+++ b/tests/language/type_object/runtime_type_function_legacy_lib.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart=2.6
+
+typedef String F(String returns, String arguments, [Map<String, String> named]);
+
+legacyMain() {}
+
+class Xyzzy {
+  static void foo() {}
+  static String opt(String x, [String a, b]) => "";
+  static String nam(String x, {String a, b}) => "";
+  void intAdd(int x) {}
+}
+
+// Using 'MyList' instead of core lib 'List' keeps covariant parameter type of
+// tear-offs 'Object' (legacy lib) instead of 'Object?' (opted-in lib).
+class MyList<E> {
+  void add(E value) {}
+}
+
+class G<U, V> {
+  U foo(V x) => null;
+  U moo(V f(U x)) => null;
+  U higherOrder(int f(U x)) => null;
+}
diff --git a/tests/language/type_object/runtime_type_function_test.dart b/tests/language/type_object/runtime_type_function_test.dart
new file mode 100644
index 0000000..1ca042d
--- /dev/null
+++ b/tests/language/type_object/runtime_type_function_test.dart
@@ -0,0 +1,67 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+import "runtime_type_function_helper.dart";
+
+main() {
+  // Types that do not use class names - these can be checked on dart2js in
+  // minified mode.
+
+  check(fn('dynamic', ''), main); //        Top-level tear-off.
+  check(fn('void', ''), Xyzzy.foo); //      Class static member tear-off.
+  check(fn('void', 'Object?'), new MyList().add); //  Instance tear-off.
+  check(fn('int', ''), () => 1); //       closure.
+
+  var s = new Xyzzy().runtimeType.toString();
+  if (s.length <= 3) return; // dart2js --minify has minified names.
+
+  Expect.equals('Xyzzy', s, 'runtime type of plain class prints as class name');
+
+  check(fn('void', 'String, dynamic'), check);
+
+  // Class static member tear-offs.
+  check(fn('String', 'String, [String?, dynamic]'), Xyzzy.opt);
+  check(fn('String', 'String', {'a': 'String?', 'b': 'dynamic'}), Xyzzy.nam);
+
+  // Instance method tear-offs.
+  check(fn('void', 'Object?'), new MyList<String>().add);
+  check(fn('void', 'Object?'), new MyList<int>().add);
+  check(fn('void', 'int'), new Xyzzy().intAdd);
+
+  check(fn('String', 'Object?'), new G<String, int>().foo);
+
+  // Instance method with function parameter.
+  var string2int = fn('int', 'String');
+  check(fn('String', 'Object?'), new G<String, int>().moo);
+  check(fn('String', '$string2int'), new G<String, int>().higherOrder);
+
+  // Closures.
+  String localFunc(String a, String b, [Map<String, String>? named]) => a + b;
+  void localFunc2(int a) {
+    print(a);
+  }
+
+  Expect.isTrue(localFunc is F);
+  check(fn('String', 'String, String, [Map<String, String>?]'), localFunc);
+  check(fn('void', 'int'), localFunc2);
+}
+
+class Xyzzy {
+  static void foo() {}
+  static String opt(String x, [String? a, b]) => "";
+  static String nam(String x, {String? a, b}) => "";
+  void intAdd(int x) {}
+}
+
+class MyList<E> {
+  void add(E value) {}
+}
+
+class G<U, V> {
+  U foo(V x) => throw "uncalled";
+  U moo(V f(U x)) => throw "uncalled";
+  U higherOrder(int f(U x)) => throw "uncalled";
+}
diff --git a/tests/language/type_object/runtime_type_function_weak_test.dart b/tests/language/type_object/runtime_type_function_weak_test.dart
new file mode 100644
index 0000000..c280da3
--- /dev/null
+++ b/tests/language/type_object/runtime_type_function_weak_test.dart
@@ -0,0 +1,45 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Requirements=nnbd-weak
+
+/// Test string representations of legacy types accessed from a null safe
+/// library.
+import "package:expect/expect.dart";
+
+import "runtime_type_function_helper.dart";
+import "runtime_type_function_legacy_lib.dart";
+
+main() {
+  // Types that do not use class names - these can be checked on dart2js in
+  // minified mode.
+
+  check(fn('dynamic', ''), legacyMain); //        Top-level tear-off.
+  check(fn('void', ''), Xyzzy.foo); //      Class static member tear-off.
+  check(fn('void', 'Object'), new MyList().add); //  Instance tear-off.
+  check(fn('int', ''), () => 1); //       closure.
+
+  var s = new Xyzzy().runtimeType.toString();
+  if (s.length <= 3) return; // dart2js --minify has minified names.
+
+  Expect.equals('Xyzzy', s, 'runtime type of plain class prints as class name');
+
+  check(fn('void', 'String, dynamic'), check);
+
+  // Class static member tear-offs.
+  check(fn('String', 'String, [String, dynamic]'), Xyzzy.opt);
+  check(fn('String', 'String', {'a': 'String', 'b': 'dynamic'}), Xyzzy.nam);
+
+  // Instance method tear-offs.
+  check(fn('void', 'Object'), new MyList<String>().add);
+  check(fn('void', 'Object'), new MyList<int>().add);
+  check(fn('void', 'int'), new Xyzzy().intAdd);
+
+  check(fn('String', 'Object'), new G<String, int>().foo);
+
+  // Instance method with function parameter.
+  var string2int = fn('int', 'String');
+  check(fn('String', 'Object'), new G<String, int>().moo);
+  check(fn('String', '$string2int'), new G<String, int>().higherOrder);
+}
diff --git a/tests/language/type_object/runtime_type_test.dart b/tests/language/type_object/runtime_type_test.dart
new file mode 100644
index 0000000..f0b66db
--- /dev/null
+++ b/tests/language/type_object/runtime_type_test.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+class A {}
+
+class B {}
+
+main() {
+  var a = new A();
+  var b = new B();
+  var f = () => null;
+  var funcType = f.runtimeType;
+  var classA = A;
+  var classB = B;
+
+  Expect.isTrue(a.runtimeType is Type);
+  Expect.equals(A, a.runtimeType);
+  Expect.notEquals(B, a.runtimeType);
+  Expect.notEquals(A, b.runtimeType);
+
+  Expect.isTrue(f.runtimeType is Type);
+  Expect.isFalse(f.runtimeType == a.runtimeType);
+
+  Expect.isTrue(classA.runtimeType is Type);
+  Expect.isTrue(classA.runtimeType == classB.runtimeType);
+  Expect.isFalse(classA.runtimeType == a.runtimeType);
+  Expect.isFalse(classA.runtimeType == f.runtimeType);
+
+  Expect.isTrue(funcType.runtimeType == classA.runtimeType);
+
+  Expect.isTrue(null.runtimeType is Type);
+  Expect.equals(Null, null.runtimeType);
+}
diff --git a/tests/language/type_promotion/assign_runtime_test.dart b/tests/language/type_promotion/assign_runtime_test.dart
new file mode 100644
index 0000000..244ab17
--- /dev/null
+++ b/tests/language/type_promotion/assign_runtime_test.dart
@@ -0,0 +1,54 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test type promotion of assigned locals.
+
+class A {
+  var a = "a";
+}
+
+class B extends A {
+  var b = "b";
+}
+
+class C extends B {
+  var c = "c";
+}
+
+class D extends A {
+  var d = "d";
+}
+
+class E implements C, D {
+  var a = "";
+  var b = "";
+  var c = "";
+  var d = "";
+}
+
+void main() {
+  A a = new E();
+  if (a is B) {
+    print(a.a);
+
+    a = A();
+  }
+  if (a is B) {
+    a = A();
+    print(a.a);
+
+  }
+  if (a is B) {
+    print(a.a);
+
+    {
+      a = A();
+    }
+    print(a.a);
+
+  }
+}
diff --git a/tests/language/type_promotion/assign_test.dart b/tests/language/type_promotion/assign_test.dart
new file mode 100644
index 0000000..737a750
--- /dev/null
+++ b/tests/language/type_promotion/assign_test.dart
@@ -0,0 +1,57 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test type promotion of assigned locals.
+
+class A {
+  var a = "a";
+}
+
+class B extends A {
+  var b = "b";
+}
+
+class C extends B {
+  var c = "c";
+}
+
+class D extends A {
+  var d = "d";
+}
+
+class E implements C, D {
+  var a = "";
+  var b = "";
+  var c = "";
+  var d = "";
+}
+
+void main() {
+  A a = new E();
+  if (a is B) {
+    print(a.a);
+    print(a.b);
+    a = A();
+  }
+  if (a is B) {
+    a = A();
+    print(a.a);
+    print(a.b);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'b' isn't defined for the class 'A'.
+  }
+  if (a is B) {
+    print(a.a);
+    print(a.b);
+    {
+      a = A();
+    }
+    print(a.a);
+    print(a.b);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'b' isn't defined for the class 'A'.
+  }
+}
diff --git a/tests/language/type_promotion/closure_runtime_1_test.dart b/tests/language/type_promotion/closure_runtime_1_test.dart
new file mode 100644
index 0000000..9700e47
--- /dev/null
+++ b/tests/language/type_promotion/closure_runtime_1_test.dart
@@ -0,0 +1,203 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test type promotion of locals potentially mutated in closures.
+
+import "package:meta/meta.dart" show virtual;
+
+class A {
+  var a = "a";
+  A operator +(int i) => this;
+}
+
+class B extends A {
+  var b = "b";
+}
+
+class C extends B {
+  var c = "c";
+}
+
+class D extends A {
+  var d = "d";
+}
+
+class E extends D implements C {
+  var a = "";
+  var b = "";
+  var c = "";
+  var d = "";
+}
+
+func(x) => true;
+
+void main() {
+  test1();
+  test2();
+  test3();
+  test3a();
+  test4();
+  test5();
+  test6();
+  test6a();
+  test7();
+  test8();
+  test9();
+  test10();
+  test11();
+  test12();
+}
+
+void test1() {
+  A a = new E();
+  if (a is B) {
+    print(a.a);
+
+  }
+  void foo() {
+    a = new D();
+  }
+}
+
+void test2() {
+  A a = new E();
+  void foo() {
+    a = new D();
+  }
+
+  if (a is B) {
+    print(a.a);
+
+  }
+}
+
+void test3() {
+  A a = new E();
+  void foo() {
+    a = new D();
+  }
+
+  if (a is B) {
+    print(a.a);
+
+    void foo() {
+      a = new D();
+    }
+
+    print(a.a);
+
+  }
+}
+
+void test3a() {
+  A a = new E();
+  void foo() {
+    a = new D();
+  }
+
+  if ((((a)) is B)) {
+    print(a.a);
+
+    void foo() {
+      a = new D();
+    }
+
+    print(a.a);
+
+  }
+}
+
+void test4() {
+  A a = new E();
+  if (a is B) {
+    func(() => a.b);
+    print(a.a);
+    print(a.b);
+  }
+}
+
+void test5() {
+  A a = new E();
+  if (a is B) {
+
+    print(a.a);
+  }
+  a = A();
+}
+
+void test6() {
+  A a = new E();
+  if (a is B) {
+    func(() => a);
+    print(a.a);
+
+  }
+  a = A();
+}
+
+void test6a() {
+  A a = new E();
+  if (((a) is B)) {
+    func(() => a);
+    print(a.a);
+
+  }
+  a = A();
+}
+
+void test7() {
+  A a = new E();
+  if (a is B && func(() => a)) {
+    print(a.a);
+
+  }
+  a = A();
+}
+
+void test8() {
+  A a = new E();
+  if (a is B
+
+      ) {
+    print(a.a);
+  }
+  a = A();
+}
+
+void test9() {
+  A a = new E();
+
+  a = A();
+}
+
+void test10() {
+  List<A> a = <E>[new E()];
+  if (a is List<B>) {
+    func(() => a[0]);
+
+  }
+  a = [];
+}
+
+void test11() {
+  List<A> a = <E>[new E()];
+  if (a is List<B>) {
+    func(() => a[0] = E());
+
+  }
+  a = [];
+}
+
+void test12() {
+  A a = new E();
+  if (a is B) {
+    func(() => a++);
+    print(a.a);
+
+  }
+  a = A();
+}
diff --git a/tests/language/type_promotion/closure_runtime_2_test.dart b/tests/language/type_promotion/closure_runtime_2_test.dart
new file mode 100644
index 0000000..52dc86f
--- /dev/null
+++ b/tests/language/type_promotion/closure_runtime_2_test.dart
@@ -0,0 +1,203 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test type promotion of locals potentially mutated in closures.
+
+import "package:meta/meta.dart" show virtual;
+
+class A {
+  var a = "a";
+  A operator +(int i) => this;
+}
+
+class B extends A {
+  var b = "b";
+}
+
+class C extends B {
+  var c = "c";
+}
+
+class D extends A {
+  var d = "d";
+}
+
+class E extends D implements C {
+  var a = "";
+  var b = "";
+  var c = "";
+  var d = "";
+}
+
+func(x) => true;
+
+void main() {
+  test1();
+  test2();
+  test3();
+  test3a();
+  test4();
+  test5();
+  test6();
+  test6a();
+  test7();
+  test8();
+  test9();
+  test10();
+  test11();
+  test12();
+}
+
+void test1() {
+  A a = new E();
+  if (a is B) {
+    print(a.a);
+
+  }
+  void foo() {
+    a = new D();
+  }
+}
+
+void test2() {
+  A a = new E();
+  void foo() {
+    a = new D();
+  }
+
+  if (a is B) {
+    print(a.a);
+
+  }
+}
+
+void test3() {
+  A a = new E();
+  void foo() {
+    a = new D();
+  }
+
+  if (a is B) {
+    print(a.a);
+
+    void foo() {
+      a = new D();
+    }
+
+    print(a.a);
+
+  }
+}
+
+void test3a() {
+  A a = new E();
+  void foo() {
+    a = new D();
+  }
+
+  if ((((a)) is B)) {
+    print(a.a);
+
+    void foo() {
+      a = new D();
+    }
+
+    print(a.a);
+
+  }
+}
+
+void test4() {
+  A a = new E();
+  if (a is B) {
+
+    print(a.a);
+    print(a.b);
+  }
+}
+
+void test5() {
+  A a = new E();
+  if (a is B) {
+
+    print(a.a);
+  }
+  a = A();
+}
+
+void test6() {
+  A a = new E();
+  if (a is B) {
+    func(() => a);
+    print(a.a);
+
+  }
+  a = A();
+}
+
+void test6a() {
+  A a = new E();
+  if (((a) is B)) {
+    func(() => a);
+    print(a.a);
+
+  }
+  a = A();
+}
+
+void test7() {
+  A a = new E();
+  if (a is B && func(() => a)) {
+    print(a.a);
+    print(a.b);
+  }
+  a = A();
+}
+
+void test8() {
+  A a = new E();
+  if (a is B
+
+      ) {
+    print(a.a);
+  }
+  a = A();
+}
+
+void test9() {
+  A a = new E();
+
+  a = A();
+}
+
+void test10() {
+  List<A> a = <E>[new E()];
+  if (a is List<B>) {
+    func(() => a[0]);
+
+  }
+  a = [];
+}
+
+void test11() {
+  List<A> a = <E>[new E()];
+  if (a is List<B>) {
+    func(() => a[0] = E());
+
+  }
+  a = [];
+}
+
+void test12() {
+  A a = new E();
+  if (a is B) {
+    func(() => a++);
+    print(a.a);
+
+  }
+  a = A();
+}
diff --git a/tests/language/type_promotion/closure_runtime_test.dart b/tests/language/type_promotion/closure_runtime_test.dart
new file mode 100644
index 0000000..07b6caa
--- /dev/null
+++ b/tests/language/type_promotion/closure_runtime_test.dart
@@ -0,0 +1,203 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test type promotion of locals potentially mutated in closures.
+
+import "package:meta/meta.dart" show virtual;
+
+class A {
+  var a = "a";
+  A operator +(int i) => this;
+}
+
+class B extends A {
+  var b = "b";
+}
+
+class C extends B {
+  var c = "c";
+}
+
+class D extends A {
+  var d = "d";
+}
+
+class E extends D implements C {
+  var a = "";
+  var b = "";
+  var c = "";
+  var d = "";
+}
+
+func(x) => true;
+
+void main() {
+  test1();
+  test2();
+  test3();
+  test3a();
+  test4();
+  test5();
+  test6();
+  test6a();
+  test7();
+  test8();
+  test9();
+  test10();
+  test11();
+  test12();
+}
+
+void test1() {
+  A a = new E();
+  if (a is B) {
+    print(a.a);
+
+  }
+  void foo() {
+    a = new D();
+  }
+}
+
+void test2() {
+  A a = new E();
+  void foo() {
+    a = new D();
+  }
+
+  if (a is B) {
+    print(a.a);
+
+  }
+}
+
+void test3() {
+  A a = new E();
+  void foo() {
+    a = new D();
+  }
+
+  if (a is B) {
+    print(a.a);
+
+    void foo() {
+      a = new D();
+    }
+
+    print(a.a);
+
+  }
+}
+
+void test3a() {
+  A a = new E();
+  void foo() {
+    a = new D();
+  }
+
+  if ((((a)) is B)) {
+    print(a.a);
+
+    void foo() {
+      a = new D();
+    }
+
+    print(a.a);
+
+  }
+}
+
+void test4() {
+  A a = new E();
+  if (a is B) {
+
+    print(a.a);
+    print(a.b);
+  }
+}
+
+void test5() {
+  A a = new E();
+  if (a is B) {
+
+    print(a.a);
+  }
+  a = A();
+}
+
+void test6() {
+  A a = new E();
+  if (a is B) {
+    func(() => a);
+    print(a.a);
+
+  }
+  a = A();
+}
+
+void test6a() {
+  A a = new E();
+  if (((a) is B)) {
+    func(() => a);
+    print(a.a);
+
+  }
+  a = A();
+}
+
+void test7() {
+  A a = new E();
+  if (a is B && func(() => a)) {
+    print(a.a);
+
+  }
+  a = A();
+}
+
+void test8() {
+  A a = new E();
+  if (a is B
+
+      ) {
+    print(a.a);
+  }
+  a = A();
+}
+
+void test9() {
+  A a = new E();
+
+  a = A();
+}
+
+void test10() {
+  List<A> a = <E>[new E()];
+  if (a is List<B>) {
+    func(() => a[0]);
+
+  }
+  a = [];
+}
+
+void test11() {
+  List<A> a = <E>[new E()];
+  if (a is List<B>) {
+    func(() => a[0] = E());
+
+  }
+  a = [];
+}
+
+void test12() {
+  A a = new E();
+  if (a is B) {
+    func(() => a++);
+    print(a.a);
+
+  }
+  a = A();
+}
diff --git a/tests/language/type_promotion/closure_test.dart b/tests/language/type_promotion/closure_test.dart
new file mode 100644
index 0000000..17246dc
--- /dev/null
+++ b/tests/language/type_promotion/closure_test.dart
@@ -0,0 +1,227 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test type promotion of locals potentially mutated in closures.
+
+import "package:meta/meta.dart" show virtual;
+
+class A {
+  var a = "a";
+  A operator +(int i) => this;
+}
+
+class B extends A {
+  var b = "b";
+}
+
+class C extends B {
+  var c = "c";
+}
+
+class D extends A {
+  var d = "d";
+}
+
+class E extends D implements C {
+  var a = "";
+  var b = "";
+  var c = "";
+  var d = "";
+}
+
+func(x) => true;
+
+void main() {
+  test1();
+  test2();
+  test3();
+  test3a();
+  test4();
+  test5();
+  test6();
+  test6a();
+  test7();
+  test8();
+  test9();
+  test10();
+  test11();
+  test12();
+}
+
+void test1() {
+  A a = new E();
+  if (a is B) {
+    print(a.a);
+    print(a.b);
+  }
+  void foo() {
+    a = new D();
+  }
+}
+
+void test2() {
+  A a = new E();
+  void foo() {
+    a = new D();
+  }
+
+  if (a is B) {
+    print(a.a);
+    print(a.b);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'b' isn't defined for the class 'A'.
+  }
+}
+
+void test3() {
+  A a = new E();
+  void foo() {
+    a = new D();
+  }
+
+  if (a is B) {
+    print(a.a);
+    print(a.b);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'b' isn't defined for the class 'A'.
+    void foo() {
+      a = new D();
+    }
+
+    print(a.a);
+    print(a.b);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'b' isn't defined for the class 'A'.
+  }
+}
+
+void test3a() {
+  A a = new E();
+  void foo() {
+    a = new D();
+  }
+
+  if ((((a)) is B)) {
+    print(a.a);
+    print(a.b);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'b' isn't defined for the class 'A'.
+    void foo() {
+      a = new D();
+    }
+
+    print(a.a);
+    print(a.b);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'b' isn't defined for the class 'A'.
+  }
+}
+
+void test4() {
+  A a = new E();
+  if (a is B) {
+    func(() => a.b);
+    print(a.a);
+    print(a.b);
+  }
+}
+
+void test5() {
+  A a = new E();
+  if (a is B) {
+    func(() => a.b);
+    //           ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'b' isn't defined for the class 'A'.
+    print(a.a);
+  }
+  a = A();
+}
+
+void test6() {
+  A a = new E();
+  if (a is B) {
+    func(() => a);
+    print(a.a);
+    print(a.b);
+  }
+  a = A();
+}
+
+void test6a() {
+  A a = new E();
+  if (((a) is B)) {
+    func(() => a);
+    print(a.a);
+    print(a.b);
+  }
+  a = A();
+}
+
+void test7() {
+  A a = new E();
+  if (a is B && func(() => a)) {
+    print(a.a);
+    print(a.b);
+  }
+  a = A();
+}
+
+void test8() {
+  A a = new E();
+  if (a is B
+      && func(() => a.b)
+      //              ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'b' isn't defined for the class 'A'.
+      ) {
+    print(a.a);
+  }
+  a = A();
+}
+
+void test9() {
+  A a = new E();
+  var b = a is B ? func(() => a.b) : false;
+  //                            ^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] The getter 'b' isn't defined for the class 'A'.
+  a = A();
+}
+
+void test10() {
+  List<A> a = <E>[new E()];
+  if (a is List<B>) {
+    func(() => a[0]);
+    print(a[0].b);
+  }
+  a = [];
+}
+
+void test11() {
+  List<A> a = <E>[new E()];
+  if (a is List<B>) {
+    func(() => a[0] = E());
+    print(a[0].b);
+  }
+  a = [];
+}
+
+void test12() {
+  A a = new E();
+  if (a is B) {
+    func(() => a++);
+    print(a.a);
+    print(a.b);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'b' isn't defined for the class 'A'.
+  }
+  a = A();
+}
diff --git a/tests/language/type_promotion/functions_runtime_test.dart b/tests/language/type_promotion/functions_runtime_test.dart
new file mode 100644
index 0000000..5e462be
--- /dev/null
+++ b/tests/language/type_promotion/functions_runtime_test.dart
@@ -0,0 +1,127 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test type promotion of functions.
+
+class A {}
+
+class B extends A {}
+
+class C {}
+
+// Subtype relations:
+//
+//   FuncDynToA    == A       Function(dynamic) <:
+//   FuncDynToDyn  == dynamic Function(dynamic) <:> // "void == dynamic"
+//   FuncDynToVoid == void    Function(dynamic) <:
+//   FuncAtoDyn    == dynamic Function(A).
+//
+// Declarations ordered by "super before sub", as is common for classes:
+
+typedef FuncAtoDyn(A a);
+typedef void FuncDynToVoid(x);
+typedef FuncDynToDyn(x);
+typedef A FuncDynToA(x);
+
+dynamic func(x) => x;
+
+late A a;
+late B b;
+late C c;
+
+main() {
+  testFuncAtoDyn();
+  testFuncDynToDyn();
+  testFuncDynToVoid();
+  testFuncDynToA();
+}
+
+testFuncAtoDyn() {
+  FuncAtoDyn funcAtoDyn = func;
+  a = funcAtoDyn(new A());
+  b = funcAtoDyn(new B());
+
+
+  if (funcAtoDyn is FuncDynToDyn) {
+    // Promotion: FuncDynToDyn <: FuncAtoDyn.
+    a = funcAtoDyn(new A());
+    b = funcAtoDyn(new B());
+    c = funcAtoDyn(new C());
+  }
+}
+
+testFuncDynToDyn() {
+  FuncDynToDyn funcDynToDyn = func;
+  a = funcDynToDyn(new A());
+  b = funcDynToDyn(new B());
+  c = funcDynToDyn(new C());
+
+  if (funcDynToDyn is FuncAtoDyn) {
+    // No promotion: FuncAtoDyn <\: FuncDynToDyn.
+    a = funcDynToDyn(new A());
+    b = funcDynToDyn(new B());
+    c = funcDynToDyn(new C());
+  }
+
+  if (funcDynToDyn is FuncDynToVoid) {
+    // Promotion: FuncDynToVoid <: FuncDynToDyn.
+    funcDynToDyn(new A());
+    funcDynToDyn(new B());
+    funcDynToDyn(new C());
+    // Returned value has type `void`, usage is restricted.
+
+  }
+
+  if (funcDynToDyn is FuncDynToA) {
+    // Promotion: FuncDynToA <: FuncDynToDyn.
+    a = funcDynToDyn(new A());
+    b = funcDynToDyn(new B()) as B;
+
+  }
+}
+
+testFuncDynToVoid() {
+  FuncDynToVoid funcDynToVoid = func;
+
+
+
+
+  if (funcDynToVoid is FuncDynToDyn) {
+    // Promotion: FuncDynToDyn <:> FuncDynToVoid.
+    a = funcDynToVoid(new A());
+    b = funcDynToVoid(new B());
+    c = funcDynToVoid(new C());
+  }
+
+  if (funcDynToVoid is FuncDynToA) {
+    // Promotion: FuncDynToA <: FuncDynToVoid.
+    a = funcDynToVoid(new A());
+    b = funcDynToVoid(new B()) as B;
+
+  }
+}
+
+testFuncDynToA() {
+  FuncDynToA funcDynToA = (x) => x as A;
+  a = funcDynToA(new A());
+  b = funcDynToA(new B()) as B;
+
+
+  if (funcDynToA is FuncDynToDyn) {
+    // No promotion: FuncDynToDyn <\: FuncDynToA.
+    a = funcDynToA(new A());
+    b = funcDynToA(new B()) as B;
+
+  }
+
+  if (funcDynToA is FuncDynToVoid) {
+    // No promotion: FuncDynToVoid <\: FuncDynToA.
+    a = funcDynToA(new A());
+    b = funcDynToA(new B()) as B;
+
+  }
+}
diff --git a/tests/language/type_promotion/functions_test.dart b/tests/language/type_promotion/functions_test.dart
new file mode 100644
index 0000000..1e0b4ae
--- /dev/null
+++ b/tests/language/type_promotion/functions_test.dart
@@ -0,0 +1,164 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test type promotion of functions.
+
+class A {}
+
+class B extends A {}
+
+class C {}
+
+// Subtype relations:
+//
+//   FuncDynToA    == A       Function(dynamic) <:
+//   FuncDynToDyn  == dynamic Function(dynamic) <:> // "void == dynamic"
+//   FuncDynToVoid == void    Function(dynamic) <:
+//   FuncAtoDyn    == dynamic Function(A).
+//
+// Declarations ordered by "super before sub", as is common for classes:
+
+typedef FuncAtoDyn(A a);
+typedef void FuncDynToVoid(x);
+typedef FuncDynToDyn(x);
+typedef A FuncDynToA(x);
+
+dynamic func(x) => x;
+
+late A a;
+late B b;
+late C c;
+
+main() {
+  testFuncAtoDyn();
+  testFuncDynToDyn();
+  testFuncDynToVoid();
+  testFuncDynToA();
+}
+
+testFuncAtoDyn() {
+  FuncAtoDyn funcAtoDyn = func;
+  a = funcAtoDyn(new A());
+  b = funcAtoDyn(new B());
+  c = funcAtoDyn(new C());
+  //             ^^^^^^^
+  // [analyzer] STATIC_WARNING.ARGUMENT_TYPE_NOT_ASSIGNABLE
+  //                 ^
+  // [cfe] The argument type 'C' can't be assigned to the parameter type 'A'.
+
+  if (funcAtoDyn is FuncDynToDyn) {
+    // Promotion: FuncDynToDyn <: FuncAtoDyn.
+    a = funcAtoDyn(new A());
+    b = funcAtoDyn(new B());
+    c = funcAtoDyn(new C());
+  }
+}
+
+testFuncDynToDyn() {
+  FuncDynToDyn funcDynToDyn = func;
+  a = funcDynToDyn(new A());
+  b = funcDynToDyn(new B());
+  c = funcDynToDyn(new C());
+
+  if (funcDynToDyn is FuncAtoDyn) {
+    // No promotion: FuncAtoDyn <\: FuncDynToDyn.
+    a = funcDynToDyn(new A());
+    b = funcDynToDyn(new B());
+    c = funcDynToDyn(new C());
+  }
+
+  if (funcDynToDyn is FuncDynToVoid) {
+    // Promotion: FuncDynToVoid <: FuncDynToDyn.
+    funcDynToDyn(new A());
+    funcDynToDyn(new B());
+    funcDynToDyn(new C());
+    // Returned value has type `void`, usage is restricted.
+    Object o = funcDynToDyn(null);
+    //         ^^^^^^^^^^^^^^^^^^
+    // [analyzer] STATIC_WARNING.USE_OF_VOID_RESULT
+    //                     ^
+    // [cfe] This expression has type 'void' and can't be used.
+  }
+
+  if (funcDynToDyn is FuncDynToA) {
+    // Promotion: FuncDynToA <: FuncDynToDyn.
+    a = funcDynToDyn(new A());
+    b = funcDynToDyn(new B()) as B;
+    c = funcDynToDyn(new C());
+    //  ^^^^^^^^^^^^^^^^^^^^^
+    // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+    //              ^
+    // [cfe] A value of type 'A' can't be assigned to a variable of type 'C'.
+  }
+}
+
+testFuncDynToVoid() {
+  FuncDynToVoid funcDynToVoid = func;
+  a = funcDynToVoid(new A());
+  //  ^^^^^^^^^^^^^^^^^^^^^^
+  // [analyzer] STATIC_WARNING.USE_OF_VOID_RESULT
+  //               ^
+  // [cfe] This expression has type 'void' and can't be used.
+  b = funcDynToVoid(new B());
+  //  ^^^^^^^^^^^^^^^^^^^^^^
+  // [analyzer] STATIC_WARNING.USE_OF_VOID_RESULT
+  //               ^
+  // [cfe] This expression has type 'void' and can't be used.
+  c = funcDynToVoid(new C());
+  //  ^^^^^^^^^^^^^^^^^^^^^^
+  // [analyzer] STATIC_WARNING.USE_OF_VOID_RESULT
+  //               ^
+  // [cfe] This expression has type 'void' and can't be used.
+
+  if (funcDynToVoid is FuncDynToDyn) {
+    // Promotion: FuncDynToDyn <:> FuncDynToVoid.
+    a = funcDynToVoid(new A());
+    b = funcDynToVoid(new B());
+    c = funcDynToVoid(new C());
+  }
+
+  if (funcDynToVoid is FuncDynToA) {
+    // Promotion: FuncDynToA <: FuncDynToVoid.
+    a = funcDynToVoid(new A());
+    b = funcDynToVoid(new B()) as B;
+    c = funcDynToVoid(new C());
+    //  ^^^^^^^^^^^^^^^^^^^^^^
+    // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+    //               ^
+    // [cfe] A value of type 'A' can't be assigned to a variable of type 'C'.
+  }
+}
+
+testFuncDynToA() {
+  FuncDynToA funcDynToA = (x) => x as A;
+  a = funcDynToA(new A());
+  b = funcDynToA(new B()) as B;
+  c = funcDynToA(new C());
+  //  ^^^^^^^^^^^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+  //            ^
+  // [cfe] A value of type 'A' can't be assigned to a variable of type 'C'.
+
+  if (funcDynToA is FuncDynToDyn) {
+    // No promotion: FuncDynToDyn <\: FuncDynToA.
+    a = funcDynToA(new A());
+    b = funcDynToA(new B()) as B;
+    c = funcDynToA(new C());
+    //  ^^^^^^^^^^^^^^^^^^^
+    // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+    //            ^
+    // [cfe] A value of type 'A' can't be assigned to a variable of type 'C'.
+  }
+
+  if (funcDynToA is FuncDynToVoid) {
+    // No promotion: FuncDynToVoid <\: FuncDynToA.
+    a = funcDynToA(new A());
+    b = funcDynToA(new B()) as B;
+    c = funcDynToA(new C());
+    //  ^^^^^^^^^^^^^^^^^^^
+    // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+    //            ^
+    // [cfe] A value of type 'A' can't be assigned to a variable of type 'C'.
+  }
+}
diff --git a/tests/language/type_promotion/local_runtime_test.dart b/tests/language/type_promotion/local_runtime_test.dart
new file mode 100644
index 0000000..b010208
--- /dev/null
+++ b/tests/language/type_promotion/local_runtime_test.dart
@@ -0,0 +1,163 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test type promotion of locals.
+
+class A {
+  var a = "a";
+}
+
+class B extends A {
+  var b = "b";
+}
+
+class C extends B {
+  var c = "c";
+}
+
+class D extends A {
+  var d = "d";
+}
+
+class E implements C, D {
+  var a = "";
+  var b = "";
+  var c = "";
+  var d = "";
+}
+
+void main() {
+  A a = new E();
+  print(a.a);
+
+
+
+
+  if (a is B) {
+    print(a.a);
+    print(a.b);
+
+
+
+    if (a is C) {
+      print(a.a);
+      print(a.b);
+      print(a.c);
+
+    }
+
+    print(a.a);
+    print(a.b);
+
+
+  }
+  if (a is C) {
+    print(a.a);
+    print(a.b);
+    print(a.c);
+
+
+    if (a is B) {
+      print(a.a);
+      print(a.b);
+      print(a.c);
+
+    }
+    if (a is D) {
+      print(a.a);
+      print(a.b);
+      print(a.c);
+
+    }
+
+    print(a.a);
+    print(a.b);
+    print(a.c);
+
+  }
+
+  print(a.a);
+
+
+
+
+  if (a is D) {
+    print(a.a);
+
+
+    print(a.d);
+  }
+
+  print(a.a);
+
+
+
+
+  var o1 = a is B
+          ? '${a.a}'
+              '${a.b}'
+
+
+          : '${a.a}'
+
+
+
+      ;
+
+  var o2 = a is C
+          ? '${a.a}'
+              '${a.b}'
+              '${a.c}'
+
+          : '${a.a}'
+
+
+
+      ;
+
+  var o3 = a is D
+          ? '${a.a}'
+
+
+              '${a.d}'
+          : '${a.a}'
+
+
+
+      ;
+
+  if (a is B && a is B) {
+    print(a.a);
+    print(a.b);
+
+
+  }
+  if (a is B && a is C) {
+    print(a.a);
+    print(a.b);
+    print(a.c);
+
+  }
+  if (a is C && a is B) {
+    print(a.a);
+    print(a.b);
+    print(a.c);
+
+  }
+  if (a is C && a is D) {
+    print(a.a);
+    print(a.b);
+    print(a.c);
+
+  }
+  if (a is D && a is C) {
+    print(a.a);
+
+
+    print(a.d);
+  }
+}
diff --git a/tests/language/type_promotion/local_test.dart b/tests/language/type_promotion/local_test.dart
new file mode 100644
index 0000000..c0fe87d
--- /dev/null
+++ b/tests/language/type_promotion/local_test.dart
@@ -0,0 +1,283 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test type promotion of locals.
+
+class A {
+  var a = "a";
+}
+
+class B extends A {
+  var b = "b";
+}
+
+class C extends B {
+  var c = "c";
+}
+
+class D extends A {
+  var d = "d";
+}
+
+class E implements C, D {
+  var a = "";
+  var b = "";
+  var c = "";
+  var d = "";
+}
+
+void main() {
+  A a = new E();
+  print(a.a);
+  print(a.b);
+  //      ^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] The getter 'b' isn't defined for the class 'A'.
+  print(a.c);
+  //      ^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] The getter 'c' isn't defined for the class 'A'.
+  print(a.d);
+  //      ^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] The getter 'd' isn't defined for the class 'A'.
+
+  if (a is B) {
+    print(a.a);
+    print(a.b);
+    print(a.c);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'c' isn't defined for the class 'B'.
+    print(a.d);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'd' isn't defined for the class 'B'.
+
+    if (a is C) {
+      print(a.a);
+      print(a.b);
+      print(a.c);
+      print(a.d);
+      //      ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'd' isn't defined for the class 'C'.
+    }
+
+    print(a.a);
+    print(a.b);
+    print(a.c);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'c' isn't defined for the class 'B'.
+    print(a.d);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'd' isn't defined for the class 'B'.
+  }
+  if (a is C) {
+    print(a.a);
+    print(a.b);
+    print(a.c);
+    print(a.d);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'd' isn't defined for the class 'C'.
+
+    if (a is B) {
+      print(a.a);
+      print(a.b);
+      print(a.c);
+      print(a.d);
+      //      ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'd' isn't defined for the class 'C'.
+    }
+    if (a is D) {
+      print(a.a);
+      print(a.b);
+      print(a.c);
+      print(a.d);
+      //      ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'd' isn't defined for the class 'C'.
+    }
+
+    print(a.a);
+    print(a.b);
+    print(a.c);
+    print(a.d);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'd' isn't defined for the class 'C'.
+  }
+
+  print(a.a);
+  print(a.b);
+  //      ^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] The getter 'b' isn't defined for the class 'A'.
+  print(a.c);
+  //      ^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] The getter 'c' isn't defined for the class 'A'.
+  print(a.d);
+  //      ^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] The getter 'd' isn't defined for the class 'A'.
+
+  if (a is D) {
+    print(a.a);
+    print(a.b);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'b' isn't defined for the class 'D'.
+    print(a.c);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'c' isn't defined for the class 'D'.
+    print(a.d);
+  }
+
+  print(a.a);
+  print(a.b);
+  //      ^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] The getter 'b' isn't defined for the class 'A'.
+  print(a.c);
+  //      ^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] The getter 'c' isn't defined for the class 'A'.
+  print(a.d);
+  //      ^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] The getter 'd' isn't defined for the class 'A'.
+
+  var o1 = a is B
+          ? '${a.a}'
+              '${a.b}'
+      '${a.c}'
+      //   ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'c' isn't defined for the class 'B'.
+      '${a.d}'
+      //   ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'd' isn't defined for the class 'B'.
+          : '${a.a}'
+      '${a.b}'
+      //   ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'b' isn't defined for the class 'A'.
+      '${a.c}'
+      //   ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'c' isn't defined for the class 'A'.
+      '${a.d}'
+      //   ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'd' isn't defined for the class 'A'.
+      ;
+
+  var o2 = a is C
+          ? '${a.a}'
+              '${a.b}'
+              '${a.c}'
+      '${a.d}'
+      //   ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'd' isn't defined for the class 'C'.
+          : '${a.a}'
+      '${a.b}'
+      //   ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'b' isn't defined for the class 'A'.
+      '${a.c}'
+      //   ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'c' isn't defined for the class 'A'.
+      '${a.d}'
+      //   ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'd' isn't defined for the class 'A'.
+      ;
+
+  var o3 = a is D
+          ? '${a.a}'
+      '${a.b}'
+      //   ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'b' isn't defined for the class 'D'.
+      '${a.c}'
+      //   ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'c' isn't defined for the class 'D'.
+              '${a.d}'
+          : '${a.a}'
+      '${a.b}'
+      //   ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'b' isn't defined for the class 'A'.
+      '${a.c}'
+      //   ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'c' isn't defined for the class 'A'.
+      '${a.d}'
+      //   ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'd' isn't defined for the class 'A'.
+      ;
+
+  if (a is B && a is B) {
+    print(a.a);
+    print(a.b);
+    print(a.c);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'c' isn't defined for the class 'B'.
+    print(a.d);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'd' isn't defined for the class 'B'.
+  }
+  if (a is B && a is C) {
+    print(a.a);
+    print(a.b);
+    print(a.c);
+    print(a.d);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'd' isn't defined for the class 'C'.
+  }
+  if (a is C && a is B) {
+    print(a.a);
+    print(a.b);
+    print(a.c);
+    print(a.d);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'd' isn't defined for the class 'C'.
+  }
+  if (a is C && a is D) {
+    print(a.a);
+    print(a.b);
+    print(a.c);
+    print(a.d);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'd' isn't defined for the class 'C'.
+  }
+  if (a is D && a is C) {
+    print(a.a);
+    print(a.b);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'b' isn't defined for the class 'D'.
+    print(a.c);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'c' isn't defined for the class 'D'.
+    print(a.d);
+  }
+}
diff --git a/tests/language/type_promotion/logical_and_runtime_test.dart b/tests/language/type_promotion/logical_and_runtime_test.dart
new file mode 100644
index 0000000..ce27686
--- /dev/null
+++ b/tests/language/type_promotion/logical_and_runtime_test.dart
@@ -0,0 +1,52 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test type promotion of locals potentially mutated.
+
+class A {
+  var a = true;
+}
+
+class B extends A {
+  var b = true;
+}
+
+class C extends B {
+  var c = true;
+}
+
+class D extends A {
+  var d = true;
+}
+
+class E implements C, D {
+  var a = true;
+  var b = true;
+  var c = true;
+  var d = true;
+}
+
+void main() {
+  A a = new E();
+  var b;
+  if (a is D && ((a = new D()) != null)) {
+
+  }
+  if (a is D && (b = a.d)) {
+
+    a = A();
+  }
+  if ((((a) is D) && (b = (a).d))) {
+
+    a = A();
+  }
+  if (f(a = A()) && a is D) {
+    b = a.d;
+  }
+}
+
+bool f(x) => true;
diff --git a/tests/language/type_promotion/logical_and_test.dart b/tests/language/type_promotion/logical_and_test.dart
new file mode 100644
index 0000000..ec4b756
--- /dev/null
+++ b/tests/language/type_promotion/logical_and_test.dart
@@ -0,0 +1,49 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test type promotion of locals potentially mutated.
+
+class A {
+  var a = true;
+}
+
+class B extends A {
+  var b = true;
+}
+
+class C extends B {
+  var c = true;
+}
+
+class D extends A {
+  var d = true;
+}
+
+class E implements C, D {
+  var a = true;
+  var b = true;
+  var c = true;
+  var d = true;
+}
+
+void main() {
+  A a = new E();
+  var b;
+  if (a is D && ((a = new D()) != null)) {
+    b = a.d;
+  }
+  if (a is D && (b = a.d)) {
+    b = a.d;
+    a = A();
+  }
+  if ((((a) is D) && (b = (a).d))) {
+    b = a.d;
+    a = A();
+  }
+  if (f(a = A()) && a is D) {
+    b = a.d;
+  }
+}
+
+bool f(x) => true;
diff --git a/tests/language/type_promotion/more_specific_runtime_1_test.dart b/tests/language/type_promotion/more_specific_runtime_1_test.dart
new file mode 100644
index 0000000..b6b1f54
--- /dev/null
+++ b/tests/language/type_promotion/more_specific_runtime_1_test.dart
@@ -0,0 +1,93 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test use of more specific in type promotion of interface types.
+
+class A {
+  var a;
+}
+
+class B extends A {
+  var b;
+}
+
+class C {
+  var c;
+}
+
+class D<T> {
+  T? d;
+
+  D(this.d);
+}
+
+class E<T> extends D<T> {
+  T? e;
+
+  E(e)
+      : this.e = e,
+        super(e);
+}
+
+void main() {
+  testInterface();
+  testGeneric();
+}
+
+void testInterface() {
+  var x;
+  var y;
+
+  A a = new B();
+  if (a is B) {
+    // Promotion B << A.
+    x = a.b;
+  }
+  if (a is C) {
+    // No promotion C !<< A.
+
+  }
+  B b = new B();
+  if (b is A) {
+    // No promotion B !<< A.
+
+  }
+  if (x is A) {
+    // Promotion A << dynamic.
+
+  }
+}
+
+testGeneric() {
+  var x;
+  var y;
+
+  D d1 = new E<B>(null);
+  if (d1 is E) {
+    // Promotion: E << D.
+
+  }
+  if (d1 is E<A>) {
+    // Promotion: E<A> << D.
+
+
+
+  }
+
+  D<A> d2 = new E<B>(null);
+  if (d2 is E) {
+    // No promotion: E !<< D<A>
+
+  }
+
+  D<A> d3 = new E<B>(new B());
+  if (d3 is E<B>) {
+    // Promotion: E<B> << D<A>
+
+
+  }
+}
diff --git a/tests/language/type_promotion/more_specific_runtime_2_test.dart b/tests/language/type_promotion/more_specific_runtime_2_test.dart
new file mode 100644
index 0000000..1ffb593
--- /dev/null
+++ b/tests/language/type_promotion/more_specific_runtime_2_test.dart
@@ -0,0 +1,93 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test use of more specific in type promotion of interface types.
+
+class A {
+  var a;
+}
+
+class B extends A {
+  var b;
+}
+
+class C {
+  var c;
+}
+
+class D<T> {
+  T? d;
+
+  D(this.d);
+}
+
+class E<T> extends D<T> {
+  T? e;
+
+  E(e)
+      : this.e = e,
+        super(e);
+}
+
+void main() {
+  testInterface();
+  testGeneric();
+}
+
+void testInterface() {
+  var x;
+  var y;
+
+  A a = new B();
+  if (a is B) {
+    // Promotion B << A.
+
+  }
+  if (a is C) {
+    // No promotion C !<< A.
+
+  }
+  B b = new B();
+  if (b is A) {
+    // No promotion B !<< A.
+    x = b.b;
+  }
+  if (x is A) {
+    // Promotion A << dynamic.
+
+  }
+}
+
+testGeneric() {
+  var x;
+  var y;
+
+  D d1 = new E<B>(null);
+  if (d1 is E) {
+    // Promotion: E << D.
+
+  }
+  if (d1 is E<A>) {
+    // Promotion: E<A> << D.
+
+
+
+  }
+
+  D<A> d2 = new E<B>(null);
+  if (d2 is E) {
+    // No promotion: E !<< D<A>
+
+  }
+
+  D<A> d3 = new E<B>(new B());
+  if (d3 is E<B>) {
+    // Promotion: E<B> << D<A>
+
+
+  }
+}
diff --git a/tests/language/type_promotion/more_specific_runtime_3_test.dart b/tests/language/type_promotion/more_specific_runtime_3_test.dart
new file mode 100644
index 0000000..de25d35
--- /dev/null
+++ b/tests/language/type_promotion/more_specific_runtime_3_test.dart
@@ -0,0 +1,93 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test use of more specific in type promotion of interface types.
+
+class A {
+  var a;
+}
+
+class B extends A {
+  var b;
+}
+
+class C {
+  var c;
+}
+
+class D<T> {
+  T? d;
+
+  D(this.d);
+}
+
+class E<T> extends D<T> {
+  T? e;
+
+  E(e)
+      : this.e = e,
+        super(e);
+}
+
+void main() {
+  testInterface();
+  testGeneric();
+}
+
+void testInterface() {
+  var x;
+  var y;
+
+  A a = new B();
+  if (a is B) {
+    // Promotion B << A.
+
+  }
+  if (a is C) {
+    // No promotion C !<< A.
+
+  }
+  B b = new B();
+  if (b is A) {
+    // No promotion B !<< A.
+
+  }
+  if (x is A) {
+    // Promotion A << dynamic.
+
+  }
+}
+
+testGeneric() {
+  var x;
+  var y;
+
+  D d1 = new E<B>(null);
+  if (d1 is E) {
+    // Promotion: E << D.
+    x = d1.e;
+  }
+  if (d1 is E<A>) {
+    // Promotion: E<A> << D.
+
+
+
+  }
+
+  D<A> d2 = new E<B>(null);
+  if (d2 is E) {
+    // No promotion: E !<< D<A>
+
+  }
+
+  D<A> d3 = new E<B>(new B());
+  if (d3 is E<B>) {
+    // Promotion: E<B> << D<A>
+
+
+  }
+}
diff --git a/tests/language/type_promotion/more_specific_runtime_4_test.dart b/tests/language/type_promotion/more_specific_runtime_4_test.dart
new file mode 100644
index 0000000..355e24c
--- /dev/null
+++ b/tests/language/type_promotion/more_specific_runtime_4_test.dart
@@ -0,0 +1,93 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test use of more specific in type promotion of interface types.
+
+class A {
+  var a;
+}
+
+class B extends A {
+  var b;
+}
+
+class C {
+  var c;
+}
+
+class D<T> {
+  T? d;
+
+  D(this.d);
+}
+
+class E<T> extends D<T> {
+  T? e;
+
+  E(e)
+      : this.e = e,
+        super(e);
+}
+
+void main() {
+  testInterface();
+  testGeneric();
+}
+
+void testInterface() {
+  var x;
+  var y;
+
+  A a = new B();
+  if (a is B) {
+    // Promotion B << A.
+
+  }
+  if (a is C) {
+    // No promotion C !<< A.
+
+  }
+  B b = new B();
+  if (b is A) {
+    // No promotion B !<< A.
+
+  }
+  if (x is A) {
+    // Promotion A << dynamic.
+
+  }
+}
+
+testGeneric() {
+  var x;
+  var y;
+
+  D d1 = new E<B>(null);
+  if (d1 is E) {
+    // Promotion: E << D.
+
+  }
+  if (d1 is E<A>) {
+    // Promotion: E<A> << D.
+
+
+    x = d1.e;
+  }
+
+  D<A> d2 = new E<B>(null);
+  if (d2 is E) {
+    // No promotion: E !<< D<A>
+
+  }
+
+  D<A> d3 = new E<B>(new B());
+  if (d3 is E<B>) {
+    // Promotion: E<B> << D<A>
+
+
+  }
+}
diff --git a/tests/language/type_promotion/more_specific_runtime_5_test.dart b/tests/language/type_promotion/more_specific_runtime_5_test.dart
new file mode 100644
index 0000000..74539dd
--- /dev/null
+++ b/tests/language/type_promotion/more_specific_runtime_5_test.dart
@@ -0,0 +1,93 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test use of more specific in type promotion of interface types.
+
+class A {
+  var a;
+}
+
+class B extends A {
+  var b;
+}
+
+class C {
+  var c;
+}
+
+class D<T> {
+  T? d;
+
+  D(this.d);
+}
+
+class E<T> extends D<T> {
+  T? e;
+
+  E(e)
+      : this.e = e,
+        super(e);
+}
+
+void main() {
+  testInterface();
+  testGeneric();
+}
+
+void testInterface() {
+  var x;
+  var y;
+
+  A a = new B();
+  if (a is B) {
+    // Promotion B << A.
+
+  }
+  if (a is C) {
+    // No promotion C !<< A.
+
+  }
+  B b = new B();
+  if (b is A) {
+    // No promotion B !<< A.
+
+  }
+  if (x is A) {
+    // Promotion A << dynamic.
+
+  }
+}
+
+testGeneric() {
+  var x;
+  var y;
+
+  D d1 = new E<B>(null);
+  if (d1 is E) {
+    // Promotion: E << D.
+
+  }
+  if (d1 is E<A>) {
+    // Promotion: E<A> << D.
+
+
+
+  }
+
+  D<A> d2 = new E<B>(null);
+  if (d2 is E) {
+    // No promotion: E !<< D<A>
+
+  }
+
+  D<A> d3 = new E<B>(new B());
+  if (d3 is E<B>) {
+    // Promotion: E<B> << D<A>
+    x = d3.d!.b;
+
+  }
+}
diff --git a/tests/language/type_promotion/more_specific_runtime_6_test.dart b/tests/language/type_promotion/more_specific_runtime_6_test.dart
new file mode 100644
index 0000000..e9ad755
--- /dev/null
+++ b/tests/language/type_promotion/more_specific_runtime_6_test.dart
@@ -0,0 +1,93 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test use of more specific in type promotion of interface types.
+
+class A {
+  var a;
+}
+
+class B extends A {
+  var b;
+}
+
+class C {
+  var c;
+}
+
+class D<T> {
+  T? d;
+
+  D(this.d);
+}
+
+class E<T> extends D<T> {
+  T? e;
+
+  E(e)
+      : this.e = e,
+        super(e);
+}
+
+void main() {
+  testInterface();
+  testGeneric();
+}
+
+void testInterface() {
+  var x;
+  var y;
+
+  A a = new B();
+  if (a is B) {
+    // Promotion B << A.
+
+  }
+  if (a is C) {
+    // No promotion C !<< A.
+
+  }
+  B b = new B();
+  if (b is A) {
+    // No promotion B !<< A.
+
+  }
+  if (x is A) {
+    // Promotion A << dynamic.
+
+  }
+}
+
+testGeneric() {
+  var x;
+  var y;
+
+  D d1 = new E<B>(null);
+  if (d1 is E) {
+    // Promotion: E << D.
+
+  }
+  if (d1 is E<A>) {
+    // Promotion: E<A> << D.
+
+
+
+  }
+
+  D<A> d2 = new E<B>(null);
+  if (d2 is E) {
+    // No promotion: E !<< D<A>
+
+  }
+
+  D<A> d3 = new E<B>(new B());
+  if (d3 is E<B>) {
+    // Promotion: E<B> << D<A>
+
+    x = d3.e!.b;
+  }
+}
diff --git a/tests/language/type_promotion/more_specific_runtime_test.dart b/tests/language/type_promotion/more_specific_runtime_test.dart
new file mode 100644
index 0000000..3a3e7bf
--- /dev/null
+++ b/tests/language/type_promotion/more_specific_runtime_test.dart
@@ -0,0 +1,93 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test use of more specific in type promotion of interface types.
+
+class A {
+  var a;
+}
+
+class B extends A {
+  var b;
+}
+
+class C {
+  var c;
+}
+
+class D<T> {
+  T? d;
+
+  D(this.d);
+}
+
+class E<T> extends D<T> {
+  T? e;
+
+  E(e)
+      : this.e = e,
+        super(e);
+}
+
+void main() {
+  testInterface();
+  testGeneric();
+}
+
+void testInterface() {
+  var x;
+  var y;
+
+  A a = new B();
+  if (a is B) {
+    // Promotion B << A.
+
+  }
+  if (a is C) {
+    // No promotion C !<< A.
+
+  }
+  B b = new B();
+  if (b is A) {
+    // No promotion B !<< A.
+
+  }
+  if (x is A) {
+    // Promotion A << dynamic.
+
+  }
+}
+
+testGeneric() {
+  var x;
+  var y;
+
+  D d1 = new E<B>(null);
+  if (d1 is E) {
+    // Promotion: E << D.
+
+  }
+  if (d1 is E<A>) {
+    // Promotion: E<A> << D.
+
+
+
+  }
+
+  D<A> d2 = new E<B>(null);
+  if (d2 is E) {
+    // No promotion: E !<< D<A>
+
+  }
+
+  D<A> d3 = new E<B>(new B());
+  if (d3 is E<B>) {
+    // Promotion: E<B> << D<A>
+
+
+  }
+}
diff --git a/tests/language/type_promotion/more_specific_test.dart b/tests/language/type_promotion/more_specific_test.dart
new file mode 100644
index 0000000..21392a3
--- /dev/null
+++ b/tests/language/type_promotion/more_specific_test.dart
@@ -0,0 +1,107 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test use of more specific in type promotion of interface types.
+
+class A {
+  var a;
+}
+
+class B extends A {
+  var b;
+}
+
+class C {
+  var c;
+}
+
+class D<T> {
+  T d;
+
+  D(this.d);
+}
+
+class E<T> extends D<T> {
+  T? e;
+
+  E(e)
+      : this.e = e,
+        super(e);
+}
+
+void main() {
+  testInterface();
+  testGeneric();
+}
+
+void testInterface() {
+  var x;
+  var y;
+
+  A a = new B();
+  if (a is B) {
+    // Promotion B << A.
+    x = a.b;
+  }
+  if (a is C) {
+    // No promotion C !<< A.
+    x = a.c;
+    //    ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'c' isn't defined for the class 'A'.
+  }
+  B b = new B();
+  if (b is A) {
+    // No promotion B !<< A.
+    x = b.b;
+  }
+  if (x is A) {
+    // Promotion A << dynamic.
+    y = x.b;
+    //    ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'b' isn't defined for the class 'A'.
+  }
+}
+
+testGeneric() {
+  var x;
+  var y;
+
+  D d1 = new E<B>(null);
+  if (d1 is E) {
+    // Promotion: E << D.
+    x = d1.e;
+  }
+  if (d1 is E<A>) {
+    // Promotion: E<A> << D.
+    int a = d1.d;
+    //      ^^^^
+    // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+    //         ^
+    // [cfe] A value of type 'A' can't be assigned to a variable of type 'int'.
+    String b = d1.d;
+    //         ^^^^
+    // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+    //            ^
+    // [cfe] A value of type 'A' can't be assigned to a variable of type 'String'.
+    x = d1.e;
+  }
+
+  D<A> d2 = new E<B>(null);
+  if (d2 is E) {
+    // No promotion: E !<< D<A>
+    x = d2.e;
+    //     ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'e' isn't defined for the class 'D<A>'.
+  }
+
+  D<A> d3 = new E<B>(new B());
+  if (d3 is E<B>) {
+    // Promotion: E<B> << D<A>
+    x = d3.d.b;
+    x = d3.e!.b;
+  }
+}
diff --git a/tests/language/type_promotion/multiple_runtime_test.dart b/tests/language/type_promotion/multiple_runtime_test.dart
new file mode 100644
index 0000000..b465d9b
--- /dev/null
+++ b/tests/language/type_promotion/multiple_runtime_test.dart
@@ -0,0 +1,103 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test type promotion of locals.
+
+class A {
+  var a = "a";
+}
+
+class B extends A {
+  var b = "b";
+}
+
+class C extends B {
+  var c = "c";
+}
+
+class D extends A {
+  var d = "d";
+}
+
+class E implements C, D {
+  var a = "";
+  var b = "";
+  var c = "";
+  var d = "";
+}
+
+void main() {
+  test(new E());
+}
+
+void test(A a1) {
+  A a2 = new E();
+  print(a1.a);
+
+
+
+
+  print(a2.a);
+
+
+
+
+  if (a1 is B && a2 is C) {
+    print(a1.a);
+    print(a1.b);
+
+
+
+    print(a2.a);
+    print(a2.b);
+    print(a2.c);
+
+
+    if (a1 is C && a2 is D) {
+      print(a1.a);
+      print(a1.b);
+      print(a1.c);
+
+
+      print(a2.a);
+      print(a2.b);
+      print(a2.c);
+
+    }
+  }
+
+  var o1 = a1 is B && a2 is C
+          ? '${a1.a}'
+              '${a1.b}'
+
+
+              '${a2.a}'
+              '${a2.b}'
+              '${a2.c}'
+
+          : '${a1.a}'
+
+
+
+          '${a2.a}'
+
+
+
+      ;
+
+  if (a2 is C && a1 is B && a1 is C && a2 is B && a2 is D) {
+    print(a1.a);
+    print(a1.b);
+    print(a1.c);
+
+
+    print(a2.a);
+    print(a2.b);
+    print(a2.c);
+
+  }
+}
diff --git a/tests/language/type_promotion/multiple_test.dart b/tests/language/type_promotion/multiple_test.dart
new file mode 100644
index 0000000..8410597
--- /dev/null
+++ b/tests/language/type_promotion/multiple_test.dart
@@ -0,0 +1,166 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test type promotion of locals.
+
+class A {
+  var a = "a";
+}
+
+class B extends A {
+  var b = "b";
+}
+
+class C extends B {
+  var c = "c";
+}
+
+class D extends A {
+  var d = "d";
+}
+
+class E implements C, D {
+  var a = "";
+  var b = "";
+  var c = "";
+  var d = "";
+}
+
+void main() {
+  test(new E());
+}
+
+void test(A a1) {
+  A a2 = new E();
+  print(a1.a);
+  print(a1.b);
+  //       ^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] The getter 'b' isn't defined for the class 'A'.
+  print(a1.c);
+  //       ^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] The getter 'c' isn't defined for the class 'A'.
+  print(a1.d);
+  //       ^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] The getter 'd' isn't defined for the class 'A'.
+
+  print(a2.a);
+  print(a2.b);
+  //       ^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] The getter 'b' isn't defined for the class 'A'.
+  print(a2.c);
+  //       ^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] The getter 'c' isn't defined for the class 'A'.
+  print(a2.d);
+  //       ^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] The getter 'd' isn't defined for the class 'A'.
+
+  if (a1 is B && a2 is C) {
+    print(a1.a);
+    print(a1.b);
+    print(a1.c);
+    //       ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'c' isn't defined for the class 'B'.
+    print(a1.d);
+    //       ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'd' isn't defined for the class 'B'.
+
+    print(a2.a);
+    print(a2.b);
+    print(a2.c);
+    print(a2.d);
+    //       ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'd' isn't defined for the class 'C'.
+
+    if (a1 is C && a2 is D) {
+      print(a1.a);
+      print(a1.b);
+      print(a1.c);
+      print(a1.d);
+      //       ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'd' isn't defined for the class 'C'.
+
+      print(a2.a);
+      print(a2.b);
+      print(a2.c);
+      print(a2.d);
+      //       ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'd' isn't defined for the class 'C'.
+    }
+  }
+
+  var o1 = a1 is B && a2 is C
+          ? '${a1.a}'
+              '${a1.b}'
+      '${a1.c}'
+      //    ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'c' isn't defined for the class 'B'.
+      '${a1.d}'
+      //    ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'd' isn't defined for the class 'B'.
+              '${a2.a}'
+              '${a2.b}'
+              '${a2.c}'
+      '${a2.d}'
+      //    ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'd' isn't defined for the class 'C'.
+          : '${a1.a}'
+      '${a1.b}'
+      //    ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'b' isn't defined for the class 'A'.
+      '${a1.c}'
+      //    ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'c' isn't defined for the class 'A'.
+      '${a1.d}'
+      //    ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'd' isn't defined for the class 'A'.
+          '${a2.a}'
+      '${a2.b}'
+      //    ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'b' isn't defined for the class 'A'.
+      '${a2.c}'
+      //    ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'c' isn't defined for the class 'A'.
+      '${a2.d}'
+      //    ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'd' isn't defined for the class 'A'.
+      ;
+
+  if (a2 is C && a1 is B && a1 is C && a2 is B && a2 is D) {
+    print(a1.a);
+    print(a1.b);
+    print(a1.c);
+    print(a1.d);
+    //       ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'd' isn't defined for the class 'C'.
+
+    print(a2.a);
+    print(a2.b);
+    print(a2.c);
+    print(a2.d);
+    //       ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'd' isn't defined for the class 'C'.
+  }
+}
diff --git a/tests/language/type_promotion/parameter_runtime_test.dart b/tests/language/type_promotion/parameter_runtime_test.dart
new file mode 100644
index 0000000..935dd06
--- /dev/null
+++ b/tests/language/type_promotion/parameter_runtime_test.dart
@@ -0,0 +1,211 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test type promotion of parameters.
+
+class A {
+  var a = "a";
+}
+
+class B extends A {
+  var b = "b";
+}
+
+class C extends B {
+  var c = "c";
+}
+
+class D extends A {
+  var d = "d";
+}
+
+class E implements C, D {
+  var a = "";
+  var b = "";
+  var c = "";
+  var d = "";
+}
+
+void main() {
+  test(new E());
+}
+
+void test(A a) {
+  print(a.a);
+
+
+
+
+  if (a is B) {
+    print(a.a);
+    print(a.b);
+
+
+
+    if (a is C) {
+      print(a.a);
+      print(a.b);
+      print(a.c);
+
+    }
+
+    print(a.a);
+    print(a.b);
+
+
+  }
+  if (a is C) {
+    print(a.a);
+    print(a.b);
+    print(a.c);
+
+
+    if (a is B) {
+      print(a.a);
+      print(a.b);
+      print(a.c);
+
+    }
+    if (a is D) {
+      print(a.a);
+      print(a.b);
+      print(a.c);
+
+    }
+
+    print(a.a);
+    print(a.b);
+    print(a.c);
+
+  }
+
+  print(a.a);
+
+
+
+
+  if (a is D) {
+    print(a.a);
+
+
+    print(a.d);
+  }
+
+  print(a.a);
+
+
+
+
+  var o1 = a is B
+          ? '${a.a}'
+              '${a.b}'
+
+
+          : '${a.a}'
+
+
+
+      ;
+
+  var o2 = a is C
+          ? '${a.a}'
+              '${a.b}'
+              '${a.c}'
+
+          : '${a.a}'
+
+
+
+      ;
+
+  var o3 = a is D
+          ? '${a.a}'
+
+
+              '${a.d}'
+          : '${a.a}'
+
+
+
+      ;
+
+  if (a is B && a is B) {
+    print(a.a);
+    print(a.b);
+
+
+  }
+  if (a is B && a is C) {
+    print(a.a);
+    print(a.b);
+    print(a.c);
+
+  }
+  if (a is C && a is B) {
+    print(a.a);
+    print(a.b);
+    print(a.c);
+
+  }
+  if (a is C && a is D) {
+    print(a.a);
+    print(a.b);
+    print(a.c);
+
+  }
+  if (a is D && a is C) {
+    print(a.a);
+
+
+    print(a.d);
+  }
+  if (a is D &&
+      a.a == ""
+
+
+      &&
+      a.d == "") {
+    print(a.a);
+
+
+    print(a.d);
+  }
+  if (a.a == ""
+
+
+
+          &&
+          a is B &&
+          a.a == "" &&
+          a.b == ""
+
+
+          &&
+          a is C &&
+          a.a == "" &&
+          a.b == "" &&
+          a.c == ""
+
+      ) {
+    print(a.a);
+    print(a.b);
+    print(a.c);
+
+  }
+  if ((a is B)) {
+    print(a.a);
+    print(a.b);
+
+
+  }
+  if ((a is B && (a) is C) && a is B) {
+    print(a.a);
+    print(a.b);
+    print(a.c);
+
+  }
+}
diff --git a/tests/language/type_promotion/parameter_test.dart b/tests/language/type_promotion/parameter_test.dart
new file mode 100644
index 0000000..b93d764
--- /dev/null
+++ b/tests/language/type_promotion/parameter_test.dart
@@ -0,0 +1,373 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test type promotion of parameters.
+
+class A {
+  var a = "a";
+}
+
+class B extends A {
+  var b = "b";
+}
+
+class C extends B {
+  var c = "c";
+}
+
+class D extends A {
+  var d = "d";
+}
+
+class E implements C, D {
+  var a = "";
+  var b = "";
+  var c = "";
+  var d = "";
+}
+
+void main() {
+  test(new E());
+}
+
+void test(A a) {
+  print(a.a);
+  print(a.b);
+  //      ^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] The getter 'b' isn't defined for the class 'A'.
+  print(a.c);
+  //      ^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] The getter 'c' isn't defined for the class 'A'.
+  print(a.d);
+  //      ^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] The getter 'd' isn't defined for the class 'A'.
+
+  if (a is B) {
+    print(a.a);
+    print(a.b);
+    print(a.c);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'c' isn't defined for the class 'B'.
+    print(a.d);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'd' isn't defined for the class 'B'.
+
+    if (a is C) {
+      print(a.a);
+      print(a.b);
+      print(a.c);
+      print(a.d);
+      //      ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'd' isn't defined for the class 'C'.
+    }
+
+    print(a.a);
+    print(a.b);
+    print(a.c);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'c' isn't defined for the class 'B'.
+    print(a.d);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'd' isn't defined for the class 'B'.
+  }
+  if (a is C) {
+    print(a.a);
+    print(a.b);
+    print(a.c);
+    print(a.d);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'd' isn't defined for the class 'C'.
+
+    if (a is B) {
+      print(a.a);
+      print(a.b);
+      print(a.c);
+      print(a.d);
+      //      ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'd' isn't defined for the class 'C'.
+    }
+    if (a is D) {
+      print(a.a);
+      print(a.b);
+      print(a.c);
+      print(a.d);
+      //      ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'd' isn't defined for the class 'C'.
+    }
+
+    print(a.a);
+    print(a.b);
+    print(a.c);
+    print(a.d);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'd' isn't defined for the class 'C'.
+  }
+
+  print(a.a);
+  print(a.b);
+  //      ^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] The getter 'b' isn't defined for the class 'A'.
+  print(a.c);
+  //      ^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] The getter 'c' isn't defined for the class 'A'.
+  print(a.d);
+  //      ^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] The getter 'd' isn't defined for the class 'A'.
+
+  if (a is D) {
+    print(a.a);
+    print(a.b);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'b' isn't defined for the class 'D'.
+    print(a.c);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'c' isn't defined for the class 'D'.
+    print(a.d);
+  }
+
+  print(a.a);
+  print(a.b);
+  //      ^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] The getter 'b' isn't defined for the class 'A'.
+  print(a.c);
+  //      ^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] The getter 'c' isn't defined for the class 'A'.
+  print(a.d);
+  //      ^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] The getter 'd' isn't defined for the class 'A'.
+
+  var o1 = a is B
+          ? '${a.a}'
+              '${a.b}'
+      '${a.c}'
+      //   ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'c' isn't defined for the class 'B'.
+      '${a.d}'
+      //   ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'd' isn't defined for the class 'B'.
+          : '${a.a}'
+      '${a.b}'
+      //   ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'b' isn't defined for the class 'A'.
+      '${a.c}'
+      //   ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'c' isn't defined for the class 'A'.
+      '${a.d}'
+      //   ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'd' isn't defined for the class 'A'.
+      ;
+
+  var o2 = a is C
+          ? '${a.a}'
+              '${a.b}'
+              '${a.c}'
+      '${a.d}'
+      //   ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'd' isn't defined for the class 'C'.
+          : '${a.a}'
+      '${a.b}'
+      //   ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'b' isn't defined for the class 'A'.
+      '${a.c}'
+      //   ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'c' isn't defined for the class 'A'.
+      '${a.d}'
+      //   ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'd' isn't defined for the class 'A'.
+      ;
+
+  var o3 = a is D
+          ? '${a.a}'
+      '${a.b}'
+      //   ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'b' isn't defined for the class 'D'.
+      '${a.c}'
+      //   ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'c' isn't defined for the class 'D'.
+              '${a.d}'
+          : '${a.a}'
+      '${a.b}'
+      //   ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'b' isn't defined for the class 'A'.
+      '${a.c}'
+      //   ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'c' isn't defined for the class 'A'.
+      '${a.d}'
+      //   ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'd' isn't defined for the class 'A'.
+      ;
+
+  if (a is B && a is B) {
+    print(a.a);
+    print(a.b);
+    print(a.c);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'c' isn't defined for the class 'B'.
+    print(a.d);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'd' isn't defined for the class 'B'.
+  }
+  if (a is B && a is C) {
+    print(a.a);
+    print(a.b);
+    print(a.c);
+    print(a.d);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'd' isn't defined for the class 'C'.
+  }
+  if (a is C && a is B) {
+    print(a.a);
+    print(a.b);
+    print(a.c);
+    print(a.d);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'd' isn't defined for the class 'C'.
+  }
+  if (a is C && a is D) {
+    print(a.a);
+    print(a.b);
+    print(a.c);
+    print(a.d);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'd' isn't defined for the class 'C'.
+  }
+  if (a is D && a is C) {
+    print(a.a);
+    print(a.b);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'b' isn't defined for the class 'D'.
+    print(a.c);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'c' isn't defined for the class 'D'.
+    print(a.d);
+  }
+  if (a is D &&
+      a.a == ""
+      && a.b == ""
+      //   ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'b' isn't defined for the class 'D'.
+      && a.c == ""
+      //   ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'c' isn't defined for the class 'D'.
+      &&
+      a.d == "") {
+    print(a.a);
+    print(a.b);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'b' isn't defined for the class 'D'.
+    print(a.c);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'c' isn't defined for the class 'D'.
+    print(a.d);
+  }
+  if (a.a == ""
+      && a.b == ""
+      //   ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'b' isn't defined for the class 'A'.
+      && a.c == ""
+      //   ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'c' isn't defined for the class 'A'.
+      && a.d == ""
+      //   ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'd' isn't defined for the class 'A'.
+          &&
+          a is B &&
+          a.a == "" &&
+          a.b == ""
+      && a.c == ""
+      //   ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'c' isn't defined for the class 'B'.
+      && a.d == ""
+      //   ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'd' isn't defined for the class 'B'.
+          &&
+          a is C &&
+          a.a == "" &&
+          a.b == "" &&
+          a.c == ""
+      && a.d == ""
+      //   ^
+      // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+      // [cfe] The getter 'd' isn't defined for the class 'C'.
+      ) {
+    print(a.a);
+    print(a.b);
+    print(a.c);
+    print(a.d);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'd' isn't defined for the class 'C'.
+  }
+  if ((a is B)) {
+    print(a.a);
+    print(a.b);
+    print(a.c);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'c' isn't defined for the class 'B'.
+    print(a.d);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'd' isn't defined for the class 'B'.
+  }
+  if ((a is B && (a) is C) && a is B) {
+    print(a.a);
+    print(a.b);
+    print(a.c);
+    print(a.d);
+    //      ^
+    // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+    // [cfe] The getter 'd' isn't defined for the class 'C'.
+  }
+}
diff --git a/tests/language/type_variable/bound_access_runtime_test.dart b/tests/language/type_variable/bound_access_runtime_test.dart
new file mode 100644
index 0000000..0c7a123
--- /dev/null
+++ b/tests/language/type_variable/bound_access_runtime_test.dart
@@ -0,0 +1,32 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class DynamicClass<T extends dynamic, S extends T> {
+  T field1;
+  T field2;
+
+  DynamicClass(this.field1, this.field2);
+
+  method() => field1 * field2;
+}
+
+class NumClass<T extends num, S extends T> {
+  T field1;
+  S field2;
+
+  NumClass(this.field1, this.field2);
+
+  num method1() => field1 * field2;
+
+
+}
+
+main() {
+  new DynamicClass<num, int>(0.5, 2).method();
+  new NumClass<num, double>(2, 0.5).method1();
+
+}
diff --git a/tests/language/type_variable/bound_access_test.dart b/tests/language/type_variable/bound_access_test.dart
new file mode 100644
index 0000000..77f8594
--- /dev/null
+++ b/tests/language/type_variable/bound_access_test.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class DynamicClass<T extends dynamic, S extends T> {
+  T field1;
+  T field2;
+
+  DynamicClass(this.field1, this.field2);
+
+  method() => field1 * field2;
+}
+
+class NumClass<T extends num, S extends T> {
+  T field1;
+  S field2;
+
+  NumClass(this.field1, this.field2);
+
+  num method1() => field1 * field2;
+
+  num method2() => field1 + field2.length;
+  //                               ^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] The getter 'length' isn't defined for the class 'num'.
+}
+
+main() {
+  new DynamicClass<num, int>(0.5, 2).method();
+  new NumClass<num, double>(2, 0.5).method1();
+  new NumClass<num, double>(2, 0.5).method2();
+}
diff --git a/tests/language/type_variable/bounds2_test.dart b/tests/language/type_variable/bounds2_test.dart
new file mode 100644
index 0000000..ecb6c9f
--- /dev/null
+++ b/tests/language/type_variable/bounds2_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+// Test of parameterized types with invalid bounds.
+
+abstract class J<T> {}
+
+abstract class I<T extends num> {}
+
+class A</*@compile-error=unspecified*/T> implements I<T>, J<T> {}
+
+main() {
+  // We are only interested in the instance creation, hence
+  // the result is assigned to `dynamic`.
+  dynamic a = /*@compile-error=unspecified*/ new A<String>();
+}
diff --git a/tests/language/type_variable/bounds3_runtime_test.dart b/tests/language/type_variable/bounds3_runtime_test.dart
new file mode 100644
index 0000000..4dd5843
--- /dev/null
+++ b/tests/language/type_variable/bounds3_runtime_test.dart
@@ -0,0 +1,21 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test of parameterized types with invalid bounds.
+
+class A<K extends int> {}
+
+class B<X, Y> {
+  foo(x) {
+
+  }
+}
+
+main() {
+  var b = new B<double, double>();
+  b.foo(new A());
+}
diff --git a/tests/language/type_variable/bounds3_test.dart b/tests/language/type_variable/bounds3_test.dart
new file mode 100644
index 0000000..471112b
--- /dev/null
+++ b/tests/language/type_variable/bounds3_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test of parameterized types with invalid bounds.
+
+class A<K extends int> {}
+
+class B<X, Y> {
+  foo(x) {
+    return x is A<X>;
+    //       ^
+    // [cfe] Type argument 'X' doesn't conform to the bound 'int' of the type variable 'K' on 'A'.
+    //            ^
+    // [analyzer] COMPILE_TIME_ERROR.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS
+  }
+}
+
+main() {
+  var b = new B<double, double>();
+  b.foo(new A());
+}
diff --git a/tests/language/type_variable/bounds4_runtime_test.dart b/tests/language/type_variable/bounds4_runtime_test.dart
new file mode 100644
index 0000000..eef3b1d
--- /dev/null
+++ b/tests/language/type_variable/bounds4_runtime_test.dart
@@ -0,0 +1,58 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test instantiation of object with malbounded types.
+
+class A<
+    T
+
+    > {}
+
+class B<T> implements A<T> {}
+
+class C<
+    T
+
+    > implements B<T> {}
+
+class Class<T> {
+  newA() {
+    new A<T>();
+  }
+  newB() {
+    new B<T>();
+  }
+  newC() {
+    new C<T>();
+  }
+}
+
+void test(f()) {
+  var v = f();
+}
+
+void main() {
+  test(() => new A<int>());
+  // TODO(eernst): Should it be a compile-time error to create an instance
+  // of this class in #01?
+  test(() => new B<int>());
+  test(() => new C<int>());
+
+  test(() => new A<String>());
+  test(() => new B<String>());
+  test(() => new C<String>());
+
+  dynamic c = new Class<int>();
+  test(() => c.newA());
+  test(() => c.newB());
+  test(() => c.newC());
+
+  c = new Class<String>();
+  test(() => c.newA());
+  test(() => c.newB());
+  test(() => c.newC());
+}
diff --git a/tests/language/type_variable/bounds4_test.dart b/tests/language/type_variable/bounds4_test.dart
new file mode 100644
index 0000000..9908b9c
--- /dev/null
+++ b/tests/language/type_variable/bounds4_test.dart
@@ -0,0 +1,75 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test instantiation of object with malbounded types.
+
+class A<
+    T
+          extends num
+    > {}
+
+class B<T> implements A<T> {}
+//    ^
+// [cfe] Type argument 'T' doesn't conform to the bound 'num' of the type variable 'T' on 'A' in the supertype 'A' of class 'B'.
+//                      ^
+// [analyzer] COMPILE_TIME_ERROR.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS
+
+class C<
+    T
+          extends num
+    > implements B<T> {}
+
+class Class<T> {
+  newA() {
+    new A<T>();
+    //  ^
+    // [cfe] Type argument 'T' doesn't conform to the bound 'num' of the type variable 'T' on 'A'.
+    //    ^
+    // [analyzer] COMPILE_TIME_ERROR.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS
+  }
+  newB() {
+    new B<T>();
+  }
+  newC() {
+    new C<T>();
+    //  ^
+    // [cfe] Type argument 'T' doesn't conform to the bound 'num' of the type variable 'T' on 'C'.
+    //    ^
+    // [analyzer] COMPILE_TIME_ERROR.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS
+  }
+}
+
+void test(f()) {
+  var v = f();
+}
+
+void main() {
+  test(() => new A<int>());
+  // TODO(eernst): Should it be a compile-time error to create an instance
+  // of this class in #01?
+  test(() => new B<int>());
+  test(() => new C<int>());
+
+  test(() => new A<String>());
+  //             ^
+  // [cfe] Type argument 'String' doesn't conform to the bound 'num' of the type variable 'T' on 'A'.
+  //               ^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS
+  test(() => new B<String>());
+  test(() => new C<String>());
+  //             ^
+  // [cfe] Type argument 'String' doesn't conform to the bound 'num' of the type variable 'T' on 'C'.
+  //               ^^^^^^
+  // [analyzer] COMPILE_TIME_ERROR.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS
+
+  dynamic c = new Class<int>();
+  test(() => c.newA());
+  test(() => c.newB());
+  test(() => c.newC());
+
+  c = new Class<String>();
+  test(() => c.newA());
+  test(() => c.newB());
+  test(() => c.newC());
+}
diff --git a/tests/language/type_variable/bounds_test.dart b/tests/language/type_variable/bounds_test.dart
new file mode 100644
index 0000000..c23942d
--- /dev/null
+++ b/tests/language/type_variable/bounds_test.dart
@@ -0,0 +1,75 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test of parameterized factory methods.
+
+class Foo<T extends num> {
+  Foo();
+
+  factory Foo.bad() = XFoo; // //# 00: compile-time error
+
+  factory Foo.good() = Foo<T>;
+
+  factory Foo.IFoo() {
+    throw "uncalled";
+  }
+}
+
+abstract class IFoo<T extends num> {
+  factory IFoo() = Foo<T>; //# 11: compile-time error
+}
+
+// String is not a subtype of num.
+class Baz
+    extends Foo<String> //# 01: compile-time error
+{}
+
+class Biz extends Foo<int> {}
+
+late Foo<int> fi;
+
+// String is not a subtype of num.
+late Foo
+    <String> //# 02: compile-time error
+    fs;
+
+class Box<T> {
+  // Box.T is not guaranteed to be a subtype of num.
+  Foo<T> t; //# 03: compile-time error
+
+  makeFoo() {
+    // Box.T is not guaranteed to be a subtype of num.
+    return new Foo<T>(); //# 04: compile-time error
+  }
+}
+
+main() {
+  // String is not a subtype of num.
+  var v1 = new Foo<String>(); //# 05: compile-time error
+
+  // String is not a subtype of num.
+  Foo<String> v2 = null; //# 06: compile-time error
+
+  new Baz();
+  new Biz();
+
+  fi = new Foo();
+  fs = new Foo();
+
+  new Box().makeFoo();
+  new Box<int>().makeFoo();
+  new Box<String>().makeFoo();
+
+  // Fisk does not exist.
+  new Box<Fisk>(); //# 07: compile-time error
+
+  // Too many type arguments.
+  new Box<Object, Object>(); //# 08: compile-time error
+
+  // Fisk does not exist.
+  Box<Fisk> box = null; //# 09: compile-time error
+
+  // Too many type arguments.
+  Box<Object, Object> box = null; //# 10: compile-time error
+}
diff --git a/tests/language/type_variable/closure2_test.dart b/tests/language/type_variable/closure2_test.dart
new file mode 100644
index 0000000..1b55ff9
--- /dev/null
+++ b/tests/language/type_variable/closure2_test.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+class A<T> {}
+
+class C<T> {
+  a() {
+    return () => new A<T>();
+  }
+
+  list() {
+    return () => <T>[];
+  }
+
+  map() {
+    return () => <T, T>{};
+  }
+}
+
+main() {
+  Expect.isTrue(new C<int>().a()() is A<int>);
+  Expect.isFalse(new C<int>().a()() is A<String>);
+  Expect.isTrue(new C<int>().list()() is List<int>);
+  Expect.isFalse(new C<int>().list()() is List<String>);
+  Expect.isTrue(new C<int>().map()() is Map<int, int>);
+  Expect.isFalse(new C<int>().map()() is Map<String, int>);
+  Expect.isFalse(new C<int>().map()() is Map<int, String>);
+}
diff --git a/tests/language/type_variable/closure3_test.dart b/tests/language/type_variable/closure3_test.dart
new file mode 100644
index 0000000..ecb1c39
--- /dev/null
+++ b/tests/language/type_variable/closure3_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+class A<T> {}
+
+class C<T> {
+  a() {
+    return () => new A<T>();
+  }
+}
+
+main() {
+  Expect.isTrue(new C<int>().a()() is A<int>);
+  Expect.isFalse(new C<int>().a()() is A<String>);
+}
diff --git a/tests/language/type_variable/closure4_test.dart b/tests/language/type_variable/closure4_test.dart
new file mode 100644
index 0000000..e75bc08
--- /dev/null
+++ b/tests/language/type_variable/closure4_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+class A<T> {}
+
+class C<T> {
+  map() {
+    return () => <T, T>{};
+  }
+}
+
+main() {
+  Expect.isTrue(new C<int>().map()() is Map<int, int>);
+  Expect.isFalse(new C<int>().map()() is Map<String, int>);
+  Expect.isFalse(new C<int>().map()() is Map<int, String>);
+}
diff --git a/tests/language/type_variable/closure_test.dart b/tests/language/type_variable/closure_test.dart
new file mode 100644
index 0000000..7fd7381
--- /dev/null
+++ b/tests/language/type_variable/closure_test.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+class C<T> {
+  C.foo() {
+    x = (a) => a is T;
+  }
+  C.bar() {
+    x = (a) => a is! T;
+  }
+  C.baz() {
+    x = (a) => a as T;
+  }
+  var x;
+}
+
+main() {
+  Expect.isTrue(new C<int>.foo().x(1));
+  Expect.isFalse(new C<int>.foo().x('1'));
+  Expect.isFalse(new C<int>.bar().x(1));
+  Expect.isTrue(new C<int>.bar().x('1'));
+  Expect.equals(new C<int>.baz().x(1), 1);
+  Expect.throws(() => new C<int>.baz().x('1'));
+}
diff --git a/tests/language/type_variable/conflict2_runtime_test.dart b/tests/language/type_variable/conflict2_runtime_test.dart
new file mode 100644
index 0000000..275f8dc
--- /dev/null
+++ b/tests/language/type_variable/conflict2_runtime_test.dart
@@ -0,0 +1,59 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Regression test for issue 13134. Invocation of a type parameter.
+
+import "package:expect/expect.dart";
+
+class C<T> {
+  noSuchMethod(Invocation im) {
+    throw "noSuchMethod shouldn't be called in this test.";
+  }
+
+  // This is equivalent to (T).call(). See issue 19725
+
+
+  // T is in scope, even in static context. Compile-time error to call this.T().
+
+
+  // X is not in scope. NoSuchMethodError.
+
+
+  // Class 'C' has no static method 'T': NoSuchMethodError.
+
+
+  // Class '_Type' has no instance method 'call': NoSuchMethodError.
+
+
+  // Runtime type T not accessible from static context. Compile-time error.
+
+
+  // Class '_Type' has no [] operator: NoSuchMethodError.
+
+
+  // Runtime type T not accessible from static context. Compile-time error.
+
+
+  // Class '_Type' has no member m: NoSuchMethodError.
+
+
+  // Runtime type T not accessible from static context. Compile-time error.
+
+}
+
+main() {
+
+
+
+
+
+
+
+
+
+
+}
diff --git a/tests/language/type_variable/conflict2_test.dart b/tests/language/type_variable/conflict2_test.dart
new file mode 100644
index 0000000..4a03e01
--- /dev/null
+++ b/tests/language/type_variable/conflict2_test.dart
@@ -0,0 +1,99 @@
+// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Regression test for issue 13134. Invocation of a type parameter.
+
+import "package:expect/expect.dart";
+
+class C<T> {
+  noSuchMethod(Invocation im) {
+    throw "noSuchMethod shouldn't be called in this test.";
+  }
+
+  // This is equivalent to (T).call(). See issue 19725
+  foo() => T();
+  //       ^
+  // [analyzer] STATIC_TYPE_WARNING.INVOCATION_OF_NON_FUNCTION
+  // [cfe] Method not found: 'T'.
+
+  // T is in scope, even in static context. Compile-time error to call this.T().
+  static bar() => T();
+  //              ^
+  // [analyzer] STATIC_TYPE_WARNING.INVOCATION_OF_NON_FUNCTION
+  // [cfe] Method not found: 'T'.
+  //              ^
+  // [analyzer] STATIC_WARNING.TYPE_PARAMETER_REFERENCED_BY_STATIC
+
+  // X is not in scope. NoSuchMethodError.
+  static baz() => X();
+  //              ^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_METHOD
+  // [cfe] Method not found: 'X'.
+
+  // Class 'C' has no static method 'T': NoSuchMethodError.
+  static qux() => C.T();
+  //                ^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_METHOD
+  // [cfe] Method not found: 'C.T'.
+
+  // Class '_Type' has no instance method 'call': NoSuchMethodError.
+  quux() => (T)();
+  //        ^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVOCATION_OF_NON_FUNCTION_EXPRESSION
+  //           ^
+  // [cfe] The method 'call' isn't defined for the class 'Type'.
+
+  // Runtime type T not accessible from static context. Compile-time error.
+  static corge() => (T)();
+  //                ^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVOCATION_OF_NON_FUNCTION_EXPRESSION
+  //                 ^
+  // [analyzer] STATIC_WARNING.TYPE_PARAMETER_REFERENCED_BY_STATIC
+  // [cfe] Type variables can't be used in static members.
+  //                   ^
+  // [cfe] The method 'call' isn't defined for the class 'Type'.
+
+  // Class '_Type' has no [] operator: NoSuchMethodError.
+  grault() => T[0];
+  //           ^^^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_OPERATOR
+  // [cfe] The operator '[]' isn't defined for the class 'Type'.
+
+  // Runtime type T not accessible from static context. Compile-time error.
+  static garply() => T[0];
+  //                 ^
+  // [analyzer] STATIC_WARNING.TYPE_PARAMETER_REFERENCED_BY_STATIC
+  // [cfe] Type variables can't be used in static members.
+  //                  ^^^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_OPERATOR
+  // [cfe] The operator '[]' isn't defined for the class 'Type'.
+
+  // Class '_Type' has no member m: NoSuchMethodError.
+  waldo() => T.m;
+  //           ^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] The getter 'm' isn't defined for the class 'Type'.
+
+  // Runtime type T not accessible from static context. Compile-time error.
+  static fred() => T.m;
+  //               ^
+  // [analyzer] STATIC_WARNING.TYPE_PARAMETER_REFERENCED_BY_STATIC
+  // [cfe] Type variables can't be used in static members.
+  //                 ^
+  // [analyzer] STATIC_TYPE_WARNING.UNDEFINED_GETTER
+  // [cfe] The getter 'm' isn't defined for the class 'Type'.
+}
+
+main() {
+  Expect.throwsNoSuchMethodError(() => new C().foo());
+  C.bar();
+  Expect.throwsNoSuchMethodError(() => C.baz());
+  Expect.throwsNoSuchMethodError(() => C.qux());
+  Expect.throwsNoSuchMethodError(() => new C().quux());
+  C.corge();
+  Expect.throwsNoSuchMethodError(() => new C().grault());
+  C.garply();
+  Expect.throwsNoSuchMethodError(() => new C().waldo());
+  C.fred();
+}
diff --git a/tests/language/type_variable/conflict_runtime_test.dart b/tests/language/type_variable/conflict_runtime_test.dart
new file mode 100644
index 0000000..04623cb
--- /dev/null
+++ b/tests/language/type_variable/conflict_runtime_test.dart
@@ -0,0 +1,54 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test that we report a compile-time error when a type parameter conflicts
+// with an instance or static member with the same name.
+
+import "package:expect/expect.dart";
+
+class G1<T> {
+
+}
+
+class G2<T> {
+
+}
+
+class G3<T> {
+
+}
+
+class G4<T> {
+
+}
+
+class G5<T> {
+
+}
+
+class G6<T> {
+
+}
+
+class G7<T> {
+
+}
+
+class G8<T> {
+
+}
+
+main() {
+  new G1<int>();
+  new G2<int>();
+  new G3<int>();
+  new G4<int>();
+  new G5<int>();
+  new G6<int>();
+  new G7<int>();
+  new G8<int>();
+}
diff --git a/tests/language/type_variable/conflict_test.dart b/tests/language/type_variable/conflict_test.dart
new file mode 100644
index 0000000..cc8e4da
--- /dev/null
+++ b/tests/language/type_variable/conflict_test.dart
@@ -0,0 +1,83 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test that we report a compile-time error when a type parameter conflicts
+// with an instance or static member with the same name.
+
+import "package:expect/expect.dart";
+
+class G1<T> {
+//       ^
+// [analyzer] COMPILE_TIME_ERROR.CONFLICTING_TYPE_VARIABLE_AND_MEMBER
+  var T;
+  //  ^
+  // [cfe] Conflicts with type variable 'T'.
+}
+
+class G2<T> {
+//       ^
+// [analyzer] COMPILE_TIME_ERROR.CONFLICTING_TYPE_VARIABLE_AND_MEMBER
+  get T {}
+  //  ^
+  // [cfe] Conflicts with type variable 'T'.
+}
+
+class G3<T> {
+//       ^
+// [analyzer] COMPILE_TIME_ERROR.CONFLICTING_TYPE_VARIABLE_AND_MEMBER
+  T() {}
+//^
+// [cfe] Conflicts with type variable 'T'.
+}
+
+class G4<T> {
+//       ^
+// [analyzer] COMPILE_TIME_ERROR.CONFLICTING_TYPE_VARIABLE_AND_MEMBER
+  static var T;
+  //         ^
+  // [cfe] Conflicts with type variable 'T'.
+}
+
+class G5<T> {
+//       ^
+// [analyzer] COMPILE_TIME_ERROR.CONFLICTING_TYPE_VARIABLE_AND_MEMBER
+  static get T {}
+  //         ^
+  // [cfe] Conflicts with type variable 'T'.
+}
+
+class G6<T> {
+//       ^
+// [analyzer] COMPILE_TIME_ERROR.CONFLICTING_TYPE_VARIABLE_AND_MEMBER
+  static T() {}
+  //     ^
+  // [cfe] Conflicts with type variable 'T'.
+}
+
+class G7<T> {
+//       ^
+// [analyzer] COMPILE_TIME_ERROR.CONFLICTING_TYPE_VARIABLE_AND_MEMBER
+  set T(_) {}
+  //  ^
+  // [cfe] Conflicts with type variable 'T'.
+}
+
+class G8<T> {
+//       ^
+// [analyzer] COMPILE_TIME_ERROR.CONFLICTING_TYPE_VARIABLE_AND_MEMBER
+  static set T(x) {}
+  //         ^
+  // [cfe] Conflicts with type variable 'T'.
+}
+
+main() {
+  new G1<int>();
+  new G2<int>();
+  new G3<int>();
+  new G4<int>();
+  new G5<int>();
+  new G6<int>();
+  new G7<int>();
+  new G8<int>();
+}
diff --git a/tests/language/type_variable/field_initializer2_test.dart b/tests/language/type_variable/field_initializer2_test.dart
new file mode 100644
index 0000000..5249bf2
--- /dev/null
+++ b/tests/language/type_variable/field_initializer2_test.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Check that an inlined field initializer has access to the enclosing
+// type variables.
+
+import "package:expect/expect.dart";
+
+class A<T> {
+  var c = new X<T>();
+}
+
+class B<T> extends A<T> {}
+
+class X<T> {}
+
+main() {
+  Expect.isTrue(new B<int>().c is X<int>);
+  Expect.isFalse(new B<String>().c is X<int>);
+}
diff --git a/tests/language/type_variable/field_initializer_closure2_test.dart b/tests/language/type_variable/field_initializer_closure2_test.dart
new file mode 100644
index 0000000..f3536ca
--- /dev/null
+++ b/tests/language/type_variable/field_initializer_closure2_test.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Check that an inlined field closure has access to the enclosing
+// type variables.
+
+import "package:expect/expect.dart";
+
+class A<T> {
+  var c = (() => new X<T>())();
+}
+
+class B<T> extends A<T> {}
+
+class X<T> {}
+
+main() {
+  Expect.isTrue(new B<int>().c is X<int>);
+  Expect.isFalse(new B<String>().c is X<int>);
+}
diff --git a/tests/language/type_variable/field_initializer_closure_test.dart b/tests/language/type_variable/field_initializer_closure_test.dart
new file mode 100644
index 0000000..3b27750
--- /dev/null
+++ b/tests/language/type_variable/field_initializer_closure_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Check that an inlined field closure has access to the enclosing
+// type variables.
+
+import "package:expect/expect.dart";
+
+class A<T> {
+  var c = (() => <T>[])();
+}
+
+class B<T> extends A<T> {}
+
+main() {
+  Expect.isTrue(new B<int>().c is List<int>);
+  Expect.isFalse(new B<String>().c is List<int>);
+}
diff --git a/tests/language/type_variable/field_initializer_test.dart b/tests/language/type_variable/field_initializer_test.dart
new file mode 100644
index 0000000..09331c9
--- /dev/null
+++ b/tests/language/type_variable/field_initializer_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Check that an inlined field initializer has access to the enclosing
+// type variables.
+
+import "package:expect/expect.dart";
+
+class A<T> {
+  var c = <T>[];
+}
+
+class B<T> extends A<T> {}
+
+main() {
+  Expect.isTrue(new B<int>().c is List<int>);
+  Expect.isFalse(new B<String>().c is List<int>);
+}
diff --git a/tests/language/type_variable/function_type_test.dart b/tests/language/type_variable/function_type_test.dart
new file mode 100644
index 0000000..f2b3602
--- /dev/null
+++ b/tests/language/type_variable/function_type_test.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:expect/expect.dart';
+
+typedef T Func<T>();
+
+class Foo<S> {
+  m(x) => x is Func<S>;
+}
+
+class Bar<T> {
+  f() {
+    T local() {
+      throw "uncalled";
+    }
+    return local;
+  }
+}
+
+void main() {
+  dynamic x = new Foo<List<String>>();
+  if (new DateTime.now().millisecondsSinceEpoch == 42) x = new Foo<int>();
+  Expect.isFalse(x.m(new Bar<String>().f()));
+  Expect.isTrue(x.m(new Bar<List<String>>().f()));
+}
diff --git a/tests/language/type_variable/identifier_expression_test.dart b/tests/language/type_variable/identifier_expression_test.dart
new file mode 100644
index 0000000..1827c56
--- /dev/null
+++ b/tests/language/type_variable/identifier_expression_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--enable_type_checks
+
+class A {
+  static func() {
+    return "class A";
+  }
+}
+
+class B<T> {
+  doFunc() {
+    T.func(); /*@compile-error=unspecified*/
+  }
+}
+
+main() {
+  new B<A>().doFunc();
+}
diff --git a/tests/language/type_variable/initializer_test.dart b/tests/language/type_variable/initializer_test.dart
new file mode 100644
index 0000000..3d5a85d
--- /dev/null
+++ b/tests/language/type_variable/initializer_test.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+// Regression test for dart2js where the reference to [:this:] in a
+// constructor was not propagated to the super initializers.
+
+class A<T> {
+  var map;
+  // Usage of type variables in the initializer makes the SSA builder
+  // want to access [:this:]. And because the initializers of A are
+  // inlined in the constructor of B, we have to make sure the
+  // [:this:] in the A constructor has a corresponding
+  // SSA instruction.
+  A() : map = new Map<T, T>();
+}
+
+class B<T> extends A<T> {}
+
+main() {
+  Expect.isTrue(new B<int>().map is Map<int, int>);
+}
diff --git a/tests/language/type_variable/nested_test.dart b/tests/language/type_variable/nested_test.dart
new file mode 100644
index 0000000..423ce6d
--- /dev/null
+++ b/tests/language/type_variable/nested_test.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Regression test for
+// http://code.google.com/p/dart/issues/detail?id=9050.
+
+import 'package:expect/expect.dart';
+
+class A<T> {}
+
+class B<T> {
+  var _copy;
+  B() {
+    // We used to not register the dependency between List and B.
+    _copy = <A<T>>[];
+  }
+}
+
+main() {
+  var a = new B();
+  Expect.isFalse(a._copy is List<int>);
+  Expect.isTrue(a._copy is List<A>);
+  Expect.isFalse(a._copy is List<A<int>>); //# 01: ok
+
+  a = new B<String>();
+  Expect.isFalse(a._copy is List<String>);
+  Expect.isTrue(a._copy is List<A>);
+  Expect.isTrue(a._copy is List<A<String>>);
+  Expect.isTrue(a._copy is List<A<Object>>);
+  Expect.isFalse(a._copy is List<A<int>>);
+}
diff --git a/tests/language/type_variable/promotion_issue39752_test.dart b/tests/language/type_variable/promotion_issue39752_test.dart
new file mode 100644
index 0000000..731557d
--- /dev/null
+++ b/tests/language/type_variable/promotion_issue39752_test.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+main() {}
+
+void f<T>(T a) {
+  if (a is num) {
+    if (a is int) {
+      a.isEven;
+    }
+  }
+}
diff --git a/tests/language/type_variable/promotion_test.dart b/tests/language/type_variable/promotion_test.dart
new file mode 100644
index 0000000..c0a507c
--- /dev/null
+++ b/tests/language/type_variable/promotion_test.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:expect/expect.dart';
+
+class A {}
+
+class B extends A {}
+
+class Foo<T extends A> {
+  String foo(T x) {
+    if (x is B) {
+      var list = [x];
+      return list.runtimeType.toString();
+    }
+    return '';
+  }
+
+  List<T> bar(T x) {
+    var tlist = <T>[];
+    if (x is B) {
+      var list = [x];
+      tlist = list;
+    }
+    return tlist;
+  }
+}
+
+main() {
+  var foo = new Foo<B>();
+  var b = new B();
+
+  // List class has many different platform specific implementations
+  // so we can't rely on the fact that all of them have the same
+  // user visible name. Instead we build a name for List<B> from List<A>.
+  final expected = (<A>[]).runtimeType.toString().replaceAll('<$A>', '<$B>');
+  Expect.equals(expected, foo.foo(b));
+  Expect.listEquals([b], foo.bar(b));
+}
diff --git a/tests/language/type_variable/scope2_test.dart b/tests/language/type_variable/scope2_test.dart
new file mode 100644
index 0000000..6893e2d
--- /dev/null
+++ b/tests/language/type_variable/scope2_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+// Test that malformed type arguments are treated as an error.
+
+class Foo<T> {
+  // T is not in scope for a static method.
+  static Foo<T> m() { /*@compile-error=unspecified*/
+    return new Foo();
+  }
+}
+
+main() {}
diff --git a/tests/language/type_variable/scope3_runtime_test.dart b/tests/language/type_variable/scope3_runtime_test.dart
new file mode 100644
index 0000000..e75b4a0
--- /dev/null
+++ b/tests/language/type_variable/scope3_runtime_test.dart
@@ -0,0 +1,20 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test that a type parameter cannot be repeated.
+
+class Foo<
+    T
+
+    > {}
+
+main() {
+  new Foo<
+      String
+
+      >();
+}
diff --git a/tests/language/type_variable/scope3_test.dart b/tests/language/type_variable/scope3_test.dart
new file mode 100644
index 0000000..9a38200
--- /dev/null
+++ b/tests/language/type_variable/scope3_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test that a type parameter cannot be repeated.
+
+class Foo<
+    T
+    , T
+    //^
+    // [analyzer] COMPILE_TIME_ERROR.DUPLICATE_DEFINITION
+    // [cfe] A type variable can't have the same name as another.
+    > {}
+
+main() {
+  new Foo<
+      String
+      , String
+      >();
+}
diff --git a/tests/language/type_variable/scope_runtime_test.dart b/tests/language/type_variable/scope_runtime_test.dart
new file mode 100644
index 0000000..7212278
--- /dev/null
+++ b/tests/language/type_variable/scope_runtime_test.dart
@@ -0,0 +1,52 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test that type variables referenced from within static members are malformed.
+
+class Foo<T> implements I<T> {
+  Foo() {}
+
+  static
+
+      m(
+
+          f) {
+
+    return new Foo<String>();
+  }
+
+  // T is in scope for a factory method.
+  factory Foo.I(Foo<T> f) {
+    Foo<T> x = f;
+    return f;
+  }
+
+  // T is not in scope for a static field.
+
+
+  static
+
+      get f {
+    return new Foo<String>();
+  }
+
+  static void set f(
+
+      value) {}
+}
+
+abstract class I<T> {
+  factory I(Foo<T> f) = Foo<T>.I;
+}
+
+main() {
+  Foo.m(new Foo<String>());
+  new I(new Foo<String>());
+
+  var x = Foo.f;
+  Foo.f = x;
+}
diff --git a/tests/language/type_variable/scope_test.dart b/tests/language/type_variable/scope_test.dart
new file mode 100644
index 0000000..9930d68
--- /dev/null
+++ b/tests/language/type_variable/scope_test.dart
@@ -0,0 +1,85 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test that type variables referenced from within static members are malformed.
+
+class Foo<T> implements I<T> {
+  Foo() {}
+
+  static
+  Foo<T>
+  //  ^
+  // [analyzer] STATIC_WARNING.TYPE_PARAMETER_REFERENCED_BY_STATIC
+      m(
+//    ^
+// [cfe] Can only use type variables in instance methods.
+    Foo<T>
+    //  ^
+    // [analyzer] STATIC_WARNING.TYPE_PARAMETER_REFERENCED_BY_STATIC
+    // [cfe] Type variables can't be used in static members.
+          f) {
+    Foo<T> x = new Foo<String>();
+    //  ^
+    // [analyzer] STATIC_WARNING.TYPE_PARAMETER_REFERENCED_BY_STATIC
+    // [cfe] Type variables can't be used in static members.
+    //         ^^^^^^^^^^^^^^^^^
+    // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+    return new Foo<String>();
+    //     ^^^^^^^^^^^^^^^^^
+    // [analyzer] STATIC_TYPE_WARNING.RETURN_OF_INVALID_TYPE
+  }
+
+  // T is in scope for a factory method.
+  factory Foo.I(Foo<T> f) {
+    Foo<T> x = f;
+    return f;
+  }
+
+  // T is not in scope for a static field.
+  static late Foo<T> f1;
+  //              ^
+  // [analyzer] STATIC_WARNING.TYPE_PARAMETER_REFERENCED_BY_STATIC
+  // [cfe] Type variables can't be used in static members.
+  //                 ^
+  // [cfe] Verification of the generated program failed:
+
+  static
+  Foo<T>
+  //  ^
+  // [analyzer] STATIC_WARNING.TYPE_PARAMETER_REFERENCED_BY_STATIC
+      get f {
+      //  ^
+      // [cfe] Can only use type variables in instance methods.
+    return new Foo<String>();
+    //     ^^^^^^^^^^^^^^^^^
+    // [analyzer] STATIC_TYPE_WARNING.RETURN_OF_INVALID_TYPE
+  }
+
+  static void set f(
+  //              ^
+  // [cfe] Can only use type variables in instance methods.
+                    Foo<T>
+                    //  ^
+                    // [analyzer] STATIC_WARNING.TYPE_PARAMETER_REFERENCED_BY_STATIC
+                    // [cfe] Type variables can't be used in static members.
+      value) {}
+}
+
+abstract class I<T> {
+  factory I(Foo<T> f) = Foo<T>.I;
+}
+
+main() {
+  Foo.m(new Foo<String>());
+  //    ^^^^^^^^^^^^^^^^^
+  // [analyzer] STATIC_WARNING.ARGUMENT_TYPE_NOT_ASSIGNABLE
+  new I(new Foo<String>());
+  Foo.f1 = new Foo<String>();
+  //       ^^^^^^^^^^^^^^^^^
+  // [analyzer] STATIC_TYPE_WARNING.INVALID_ASSIGNMENT
+  //           ^
+  // [cfe] A value of type 'Foo<String>' can't be assigned to a variable of type 'Foo<T>'.
+  var x = Foo.f;
+  Foo.f = x;
+}
diff --git a/tests/language/type_variable/static_context_test.dart b/tests/language/type_variable/static_context_test.dart
new file mode 100644
index 0000000..e0cd2bc
--- /dev/null
+++ b/tests/language/type_variable/static_context_test.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// A type variable can't be referenced in a static class
+
+class A<T> {
+  static int method() {
+    // error, can't reference a type variable in a static context
+    var foo =
+        new T(); /*@compile-error=unspecified*/
+  }
+}
+
+main() {
+  A.method();
+}
diff --git a/tests/language/type_variable/typedef_test.dart b/tests/language/type_variable/typedef_test.dart
new file mode 100644
index 0000000..caa1649
--- /dev/null
+++ b/tests/language/type_variable/typedef_test.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Test that rti dependency registration takes type variables within typedefs
+// into account.
+
+import 'package:expect/expect.dart';
+
+typedef Foo<T>(T t);
+
+class A<T> {
+  m() => new B<Foo<T>>();
+}
+
+class B<T> {
+  m(o) => o is T;
+}
+
+foo(int i) {}
+bar(String s) {}
+
+void main() {
+  Expect.isTrue(new A<int>().m().m(foo));
+  Expect.isFalse(new A<int>().m().m(bar));
+  Expect.isFalse(new A<String>().m().m(foo));
+  Expect.isTrue(new A<String>().m().m(bar));
+  Expect.isFalse(new A<double>().m().m(foo));
+  Expect.isFalse(new A<double>().m().m(bar));
+}
diff --git a/tests/language/typedef/bad_typedef_runtime_test.dart b/tests/language/typedef/bad_typedef_runtime_test.dart
new file mode 100644
index 0000000..274f7e7
--- /dev/null
+++ b/tests/language/typedef/bad_typedef_runtime_test.dart
@@ -0,0 +1,19 @@
+// TODO(multitest): This was automatically migrated from a multitest and may
+// contain strange or dead code.
+
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test for a function type test that cannot be eliminated at compile time.
+
+import "package:expect/expect.dart";
+
+typedef int H(
+    Function
+
+        x);
+
+main() {
+  bool b = true;
+  Expect.isFalse(b is H);
+}
diff --git a/tests/language/typedef/bad_typedef_test.dart b/tests/language/typedef/bad_typedef_test.dart
new file mode 100644
index 0000000..c49eea8
--- /dev/null
+++ b/tests/language/typedef/bad_typedef_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// Dart test for a function type test that cannot be eliminated at compile time.
+
+import "package:expect/expect.dart";
+
+typedef int H(
+    Function
+    Function
+        x);
+//      ^
+// [analyzer] SYNTACTIC_ERROR.EXPECTED_TOKEN
+// [cfe] Expected ')' before this.
+
+main() {
+  bool b = true;
+  Expect.isFalse(b is H);
+}
diff --git a/tests/language/typedef/check_bounds_generic_test.dart b/tests/language/typedef/check_bounds_generic_test.dart
new file mode 100644
index 0000000..a96fd1f
--- /dev/null
+++ b/tests/language/typedef/check_bounds_generic_test.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Check that typedef type parameters are verified to satisfy their bounds.
+
+typedef F<T extends num> = T Function<U>(T x);
+
+void g(/*@compile-error=unspecified*/ F<String>? f) {}
+
+main() {
+  g(null);
+}
diff --git a/tests/language/typedef/check_bounds_test.dart b/tests/language/typedef/check_bounds_test.dart
new file mode 100644
index 0000000..45018ec
--- /dev/null
+++ b/tests/language/typedef/check_bounds_test.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Check that typedef type parameters are verified to satisfy their bounds.
+
+typedef T F<T extends num>(T x);
+
+void g(/*@compile-error=unspecified*/ F<String>? f) {}
+
+main() {
+  g(null);
+}
diff --git a/tests/language/typedef/check_bounds_unused_test.dart b/tests/language/typedef/check_bounds_unused_test.dart
new file mode 100644
index 0000000..8f9bed5
--- /dev/null
+++ b/tests/language/typedef/check_bounds_unused_test.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Check that typedef type parameters are verified to satisfy their bounds, even
+// if the type parameter in question isn't used by the typedef.
+
+typedef void F<T extends num>();
+
+void g(/*@compile-error=unspecified*/ F<String>? f) {}
+
+main() {
+  g(null);
+}
diff --git a/tests/language/typedef/class_in_other_file_helper.dart b/tests/language/typedef/class_in_other_file_helper.dart
new file mode 100644
index 0000000..3b66850
--- /dev/null
+++ b/tests/language/typedef/class_in_other_file_helper.dart
@@ -0,0 +1,5 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class Bar {}
diff --git a/tests/language/typedef/class_in_other_file_test.dart b/tests/language/typedef/class_in_other_file_test.dart
new file mode 100644
index 0000000..c4a5b1a
--- /dev/null
+++ b/tests/language/typedef/class_in_other_file_test.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// This has crashed DDC with Kernel because of a
+// "Concurrent modification during iteration" exception.
+
+import 'class_in_other_file_helper.dart';
+
+typedef bool Foo1(bool baz);
+typedef bool Foo2(Bar baz);
+
+main() {}
diff --git a/tests/language/typedef/cyclic_test.dart b/tests/language/typedef/cyclic_test.dart
new file mode 100644
index 0000000..6da9ad6
--- /dev/null
+++ b/tests/language/typedef/cyclic_test.dart
@@ -0,0 +1,69 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Check that cyclic reference of a typedef is a compile-time error.
+
+// To test various cyclic references the definition of the [:typedef A():] is
+// split over several lines:
+typedef
+
+// Cyclic through return type.
+A //# 01: compile-time error
+
+    A // The name of the typedef
+
+// Cyclic through type variable bound.
+<T extends A> //# 10: compile-time error
+
+// Cyclic through generic type variable bound.
+<T extends List<A>> //# 11: compile-time error
+
+    (// The left parenthesis of the typedef arguments.
+
+// Cyclic through parameter type.
+A a //# 02: compile-time error
+
+// Cyclic through optional parameter type.
+[A a] //# 03: compile-time error
+
+// Cyclic through named parameter type.
+{A a} //# 04: compile-time error
+
+// Cyclic through generic parameter type.
+List<A> a //# 05: compile-time error
+
+// Cyclic through return type of function typed parameter.
+A f() //# 06: compile-time error
+
+// Cyclic through parameter type of function typed parameter.
+f(A a) //# 07: compile-time error
+
+// Cyclic through another typedef.
+B b //# 08: compile-time error
+
+// Cyclic through another more typedefs.
+C c //# 09: compile-time error
+
+// Reference through a class is not a cyclic self-reference.
+Class c //# 12: ok
+
+// Reference through a class type bound is not a cyclic self-reference.
+Class c //# 13: compile-time error
+
+    ); // The right parenthesis of the typedef arguments.
+
+typedef B(A a);
+typedef C(B b);
+
+class Class
+<T extends A> //# 13: continued
+{
+  A? a; //# 12: continued
+}
+
+void testA(A? a) {}
+
+void main() {
+  testA(null);
+}
diff --git a/tests/language/typedef/is_test.dart b/tests/language/typedef/is_test.dart
new file mode 100644
index 0000000..e8c4d3b
--- /dev/null
+++ b/tests/language/typedef/is_test.dart
@@ -0,0 +1,125 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+// Test is-test of typedefs with optional and named parameters.
+
+typedef int Func1(int a);
+typedef int Func2(int a, [int b]);
+typedef int Func3(int a, [int b, int c]);
+typedef int Func4([int a, int b, int c]);
+typedef int Func5(int a, {int b});
+typedef int Func6(int a, {int b, int c});
+typedef int Func7({int a, int b, int c});
+
+void main() {
+  int func1(int i) => -1;
+  Expect.isTrue(func1 is Func1);
+  Expect.isFalse(func1 is Func2);
+  Expect.isFalse(func1 is Func3);
+  Expect.isFalse(func1 is Func4);
+  Expect.isFalse(func1 is Func5);
+  Expect.isFalse(func1 is Func6);
+  Expect.isFalse(func1 is Func7);
+
+  int func2(int i, int j) => -1;
+  Expect.isFalse(func2 is Func1);
+  Expect.isFalse(func2 is Func2);
+  Expect.isFalse(func2 is Func3);
+  Expect.isFalse(func2 is Func4);
+  Expect.isFalse(func2 is Func5);
+  Expect.isFalse(func2 is Func6);
+  Expect.isFalse(func2 is Func7);
+
+  int func3(int i, int j, int k) => -1;
+  Expect.isFalse(func3 is Func1);
+  Expect.isFalse(func3 is Func2);
+  Expect.isFalse(func3 is Func3);
+  Expect.isFalse(func3 is Func4);
+  Expect.isFalse(func3 is Func5);
+  Expect.isFalse(func3 is Func6);
+  Expect.isFalse(func3 is Func7);
+
+  int func4(int i, [int j = -1]) => -1;
+  Expect.isTrue(func4 is Func1);
+  Expect.isTrue(func4 is Func2);
+  Expect.isFalse(func4 is Func3);
+  Expect.isFalse(func4 is Func4);
+  Expect.isFalse(func4 is Func5);
+  Expect.isFalse(func4 is Func6);
+  Expect.isFalse(func4 is Func7);
+
+  int func5(int i, [int j = -1, int k = -1]) => -1;
+  Expect.isTrue(func5 is Func1);
+  Expect.isTrue(func5 is Func2);
+  Expect.isTrue(func5 is Func3);
+  Expect.isFalse(func5 is Func4);
+  Expect.isFalse(func5 is Func5);
+  Expect.isFalse(func5 is Func6);
+  Expect.isFalse(func5 is Func7);
+
+  int func6([int i = -1, int j = -1, int k = -1]) => -1;
+  Expect.isTrue(func6 is Func1);
+  Expect.isTrue(func6 is Func2);
+  Expect.isTrue(func6 is Func3);
+  Expect.isTrue(func6 is Func4);
+  Expect.isFalse(func6 is Func5);
+  Expect.isFalse(func6 is Func6);
+  Expect.isFalse(func6 is Func7);
+
+  int func7(int i, {int j = -1}) => -1;
+  Expect.isTrue(func7 is Func1);
+  Expect.isFalse(func7 is Func2);
+  Expect.isFalse(func7 is Func3);
+  Expect.isFalse(func7 is Func4);
+  Expect.isFalse(func7 is Func5);
+  Expect.isFalse(func7 is Func6);
+  Expect.isFalse(func7 is Func7);
+
+  int func8(int i, {int b = -1}) => -1;
+  Expect.isTrue(func8 is Func1);
+  Expect.isFalse(func8 is Func2);
+  Expect.isFalse(func8 is Func3);
+  Expect.isFalse(func8 is Func4);
+  Expect.isTrue(func8 is Func5);
+  Expect.isFalse(func8 is Func6);
+  Expect.isFalse(func8 is Func7);
+
+  int func9(int i, {int b = -1, int c = -1}) => -1;
+  Expect.isTrue(func9 is Func1);
+  Expect.isFalse(func9 is Func2);
+  Expect.isFalse(func9 is Func3);
+  Expect.isFalse(func9 is Func4);
+  Expect.isTrue(func9 is Func5);
+  Expect.isTrue(func9 is Func6);
+  Expect.isFalse(func9 is Func7);
+
+  int func10(int i, {int c = -1, int b = -1}) => -1;
+  Expect.isTrue(func10 is Func1);
+  Expect.isFalse(func10 is Func2);
+  Expect.isFalse(func10 is Func3);
+  Expect.isFalse(func10 is Func4);
+  Expect.isTrue(func10 is Func5);
+  Expect.isTrue(func10 is Func6);
+  Expect.isFalse(func10 is Func7);
+
+  int func11({int a = -1, int b = -1, int c = -1}) => -1;
+  Expect.isFalse(func11 is Func1);
+  Expect.isFalse(func11 is Func2);
+  Expect.isFalse(func11 is Func3);
+  Expect.isFalse(func11 is Func4);
+  Expect.isFalse(func11 is Func5);
+  Expect.isFalse(func11 is Func6);
+  Expect.isTrue(func11 is Func7);
+
+  int func12({int c = -1, int a = -1, int b = -1}) => -1;
+  Expect.isFalse(func12 is Func1);
+  Expect.isFalse(func12 is Func2);
+  Expect.isFalse(func12 is Func3);
+  Expect.isFalse(func12 is Func4);
+  Expect.isFalse(func12 is Func5);
+  Expect.isFalse(func12 is Func6);
+  Expect.isTrue(func12 is Func7);
+}
diff --git a/tests/language_2/covariant/subtyping_test.dart b/tests/language_2/covariant/subtyping_test.dart
index b083c3d..255c360 100644
--- a/tests/language_2/covariant/subtyping_test.dart
+++ b/tests/language_2/covariant/subtyping_test.dart
@@ -217,20 +217,25 @@
   method7(T Function() Function() returnsReturnsT) => null; // needs check
 }
 
+typedef F1 = dynamic Function(Object);
+typedef F2 = dynamic Function(dynamic Function(int));
+typedef F3 = dynamic Function(dynamic Function(int Function()));
+typedef F4 = dynamic Function(dynamic Function(int) Function());
+
 testTearOffRuntimeType() {
-  expectRTTI(tearoff, type) => Expect.equals('${tearoff.runtimeType}', type,
+  expectRTTI(tearoff, type) => Expect.equals(tearoff.runtimeType, type,
       'covariant params should reify with Object as their type');
 
   TearOff<num> t = new TearOff<int>();
-  expectRTTI(t.method1, '(Object) => dynamic');
+  expectRTTI(t.method1, F1);
 
-  expectRTTI(t.method2, '((int) => dynamic) => dynamic');
-  expectRTTI(t.method3, '(Object) => dynamic');
+  expectRTTI(t.method2, F2);
+  expectRTTI(t.method3, F1);
 
-  expectRTTI(t.method4, '(Object) => dynamic');
-  expectRTTI(t.method5, '((() => int) => dynamic) => dynamic');
-  expectRTTI(t.method6, '(() => (int) => dynamic) => dynamic');
-  expectRTTI(t.method7, '(Object) => dynamic');
+  expectRTTI(t.method4, F1);
+  expectRTTI(t.method5, F3);
+  expectRTTI(t.method6, F4);
+  expectRTTI(t.method7, F1);
 }
 
 main() {
diff --git a/tests/language_2/interface/implements_futureor_test.dart b/tests/language_2/interface/implements_futureor_test.dart
index 1ec6779..abe2e64 100644
--- a/tests/language_2/interface/implements_futureor_test.dart
+++ b/tests/language_2/interface/implements_futureor_test.dart
@@ -6,7 +6,7 @@
 
 class A<T> implements FutureOr<T> {}
 //                    ^^^^^^^^^^^
-// [analyzer] COMPILE_TIME_ERROR.IMPLEMENTS_DISALLOWED_CLASS
+// [analyzer] COMPILE_TIME_ERROR.SUBTYPE_OF_DISALLOWED_TYPE
 //    ^
 // [cfe] The type 'FutureOr' can't be used in an 'implements' clause.
 
diff --git a/tests/language_2/nonfunction_type_aliases/infer_aliased_instance_creation_01_test.dart b/tests/language_2/nonfunction_type_aliases/infer_aliased_instance_creation_01_test.dart
new file mode 100644
index 0000000..99f6365c
--- /dev/null
+++ b/tests/language_2/nonfunction_type_aliases/infer_aliased_instance_creation_01_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// SharedOptions=--enable-experiment=nonfunction-type-aliases
+
+import 'package:expect/expect.dart';
+
+class C<X> {
+  C(Type t) {
+    Expect.equals(t, X);
+  }
+}
+
+typedef T<X> = C<X>;
+
+void main() {
+  T<num> x1 = T(num);
+  C<num> x2 = T(num);
+}
diff --git a/tests/language_2/nonfunction_type_aliases/infer_aliased_instance_creation_02_test.dart b/tests/language_2/nonfunction_type_aliases/infer_aliased_instance_creation_02_test.dart
new file mode 100644
index 0000000..081f4d8
--- /dev/null
+++ b/tests/language_2/nonfunction_type_aliases/infer_aliased_instance_creation_02_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// SharedOptions=--enable-experiment=nonfunction-type-aliases
+
+import 'package:expect/expect.dart';
+
+class C {}
+
+typedef T<X> = C;
+
+void main() {
+  T<num> x1 = T();
+  C x2 = T();
+}
diff --git a/tests/language_2/nonfunction_type_aliases/infer_aliased_instance_creation_03_test.dart b/tests/language_2/nonfunction_type_aliases/infer_aliased_instance_creation_03_test.dart
new file mode 100644
index 0000000..b11314a
--- /dev/null
+++ b/tests/language_2/nonfunction_type_aliases/infer_aliased_instance_creation_03_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// SharedOptions=--enable-experiment=nonfunction-type-aliases
+
+import 'package:expect/expect.dart';
+
+class C<X> {
+  C(Type t) {
+    Expect.equals(t, X);
+  }
+}
+
+typedef T = C<num>;
+
+void main() {
+  T x1 = T(num);
+  C<num> x2 = T(num);
+}
diff --git a/tests/language_2/nonfunction_type_aliases/infer_aliased_instance_creation_04_test.dart b/tests/language_2/nonfunction_type_aliases/infer_aliased_instance_creation_04_test.dart
new file mode 100644
index 0000000..97d6600
--- /dev/null
+++ b/tests/language_2/nonfunction_type_aliases/infer_aliased_instance_creation_04_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// SharedOptions=--enable-experiment=nonfunction-type-aliases
+
+import 'package:expect/expect.dart';
+
+class C<X> {
+  C(Type t) {
+    Expect.equals(t, X);
+  }
+}
+
+typedef T<X> = C<List<X>>;
+
+Type typeOf<X>() => X;
+
+void main() {
+  T<num> x1 = T(typeOf<List<num>>());
+  C<Iterable<num>> x2 = T(typeOf<List<num>>());
+}
diff --git a/tests/language_2/nonfunction_type_aliases/infer_aliased_instance_creation_05_test.dart b/tests/language_2/nonfunction_type_aliases/infer_aliased_instance_creation_05_test.dart
new file mode 100644
index 0000000..7736a0d
--- /dev/null
+++ b/tests/language_2/nonfunction_type_aliases/infer_aliased_instance_creation_05_test.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// SharedOptions=--enable-experiment=nonfunction-type-aliases
+
+import 'package:expect/expect.dart';
+
+class C<X, Y> {
+  C(Type tx, Type ty) {
+    Expect.equals(tx, X);
+    Expect.equals(ty, Y);
+  }
+}
+
+typedef T<Y, X> = C<X, Y>;
+
+void main() {
+  T<int, String> x1 = T(String, int);
+  C<String, int> x2 = T(String, int);
+}
diff --git a/tests/language_2/nonfunction_type_aliases/infer_aliased_instance_creation_06_test.dart b/tests/language_2/nonfunction_type_aliases/infer_aliased_instance_creation_06_test.dart
new file mode 100644
index 0000000..543deb9
--- /dev/null
+++ b/tests/language_2/nonfunction_type_aliases/infer_aliased_instance_creation_06_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// SharedOptions=--enable-experiment=nonfunction-type-aliases
+
+import 'package:expect/expect.dart';
+
+class C<X> {
+  C(X x, Type t) {
+    Expect.equals(t, X);
+  }
+}
+
+typedef T<X> = C<X>;
+
+void main() {
+  T(1, int);
+}
diff --git a/tests/language_2/nonfunction_type_aliases/infer_aliased_instance_creation_07_test.dart b/tests/language_2/nonfunction_type_aliases/infer_aliased_instance_creation_07_test.dart
new file mode 100644
index 0000000..0d61966
--- /dev/null
+++ b/tests/language_2/nonfunction_type_aliases/infer_aliased_instance_creation_07_test.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// SharedOptions=--enable-experiment=nonfunction-type-aliases
+
+import 'package:expect/expect.dart';
+
+class C<X> {
+  C(X x, Type t) {
+    Expect.equals(t, X);
+  }
+}
+
+typedef T<X> = C<List<X>>;
+
+Type typeOf<X>() => X;
+
+void main() {
+  T(<num>[1], typeOf<List<num>>());
+}
diff --git a/tests/language_2/nonfunction_type_aliases/infer_aliased_instance_creation_08_test.dart b/tests/language_2/nonfunction_type_aliases/infer_aliased_instance_creation_08_test.dart
new file mode 100644
index 0000000..fe92b57
--- /dev/null
+++ b/tests/language_2/nonfunction_type_aliases/infer_aliased_instance_creation_08_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// SharedOptions=--enable-experiment=nonfunction-type-aliases
+
+import 'package:expect/expect.dart';
+
+class C<X extends num> {
+  C(Type t) {
+    Expect.equals(t, X);
+  }
+}
+
+typedef T<X extends int> = C<X>;
+
+void main() {
+  T<int> x1 = T(int);
+  C<int> x2 = T(int);
+}
diff --git a/tests/language_2/nonfunction_type_aliases/infer_aliased_instance_creation_09_test.dart b/tests/language_2/nonfunction_type_aliases/infer_aliased_instance_creation_09_test.dart
new file mode 100644
index 0000000..7a07602
--- /dev/null
+++ b/tests/language_2/nonfunction_type_aliases/infer_aliased_instance_creation_09_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// SharedOptions=--enable-experiment=nonfunction-type-aliases
+
+import 'package:expect/expect.dart';
+
+class C {}
+
+typedef T<X extends num> = C;
+
+void main() {
+  T<num> x1 = T();
+  C x2 = T();
+}
diff --git a/tests/language_2/nonfunction_type_aliases/infer_aliased_instance_creation_10_test.dart b/tests/language_2/nonfunction_type_aliases/infer_aliased_instance_creation_10_test.dart
new file mode 100644
index 0000000..8ce475d
--- /dev/null
+++ b/tests/language_2/nonfunction_type_aliases/infer_aliased_instance_creation_10_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// SharedOptions=--enable-experiment=nonfunction-type-aliases
+
+import 'package:expect/expect.dart';
+
+class C<X extends num> {
+  C(Type t) {
+    Expect.equals(t, X);
+  }
+}
+
+typedef T = C<num>;
+
+void main() {
+  T x1 = T(num);
+  C<num> x2 = T(num);
+}
diff --git a/tests/language_2/nonfunction_type_aliases/infer_aliased_instance_creation_11_test.dart b/tests/language_2/nonfunction_type_aliases/infer_aliased_instance_creation_11_test.dart
new file mode 100644
index 0000000..b669f00
--- /dev/null
+++ b/tests/language_2/nonfunction_type_aliases/infer_aliased_instance_creation_11_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// SharedOptions=--enable-experiment=nonfunction-type-aliases
+
+import 'package:expect/expect.dart';
+
+class C<X extends Iterable<num>> {
+  C(Type t) {
+    Expect.equals(t, X);
+  }
+}
+
+typedef T<X extends int> = C<List<X>>;
+
+Type typeOf<X>() => X;
+
+void main() {
+  T<int> x1 = T(typeOf<List<int>>());
+  C<Iterable<num>> x2 = T(typeOf<List<int>>());
+}
diff --git a/tests/language_2/nonfunction_type_aliases/infer_aliased_instance_creation_12_test.dart b/tests/language_2/nonfunction_type_aliases/infer_aliased_instance_creation_12_test.dart
new file mode 100644
index 0000000..4322e2d
--- /dev/null
+++ b/tests/language_2/nonfunction_type_aliases/infer_aliased_instance_creation_12_test.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// SharedOptions=--enable-experiment=nonfunction-type-aliases
+
+import 'package:expect/expect.dart';
+
+class C<X extends String, Y extends num> {
+  C(Type tx, Type ty) {
+    Expect.equals(tx, X);
+    Expect.equals(ty, Y);
+  }
+}
+
+typedef T<Y extends int, X extends String> = C<X, Y>;
+
+void main() {
+  T<int, String> x1 = T(String, int);
+  C<String, int> x2 = T(String, int);
+}
diff --git a/tests/language_2/type_object/runtime_type_function_test.dart b/tests/language_2/type_object/runtime_type_function_test.dart
index b1c30c6..1e56ee1 100644
--- a/tests/language_2/type_object/runtime_type_function_test.dart
+++ b/tests/language_2/type_object/runtime_type_function_test.dart
@@ -5,10 +5,9 @@
 import "package:expect/expect.dart";
 
 typedef String F(String returns, String arguments, [Map<String, String> named]);
-F fn;
 
-/// Formats types the VM way: `(String, [int], {bool name}) => double`.
-String form1(String returns, String positional,
+/// Formats a type like `(String, [int], {bool name}) => double`.
+String fn(String returns, String positional,
     [Map<String, String> named = const {}]) {
   var result = new StringBuffer();
   result.write("($positional");
@@ -30,39 +29,7 @@
   return result.toString();
 }
 
-/// Formats types the dart2js way: `double Function(String, [int], {bool name})`.
-String form2(String returns, String positional,
-    [Map<String, String> named = const {}]) {
-  var result = new StringBuffer();
-  result.write("$returns Function");
-  result.write("($positional");
-  if (positional != "" && named.isNotEmpty) result.write(", ");
-  if (named.isNotEmpty) {
-    result.write("{");
-    bool first = true;
-    named.forEach((name, type) {
-      if (first) {
-        first = false;
-      } else {
-        result.write(", ");
-      }
-      result.write("$type $name");
-    });
-    result.write("}");
-  }
-  result.write(")");
-}
-
-F detectForm() {
-  var s = main.runtimeType.toString();
-  if (s.contains('=>')) return form1;
-  if (s.contains('Function')) return form2;
-  Expect.fail('"$s" contains neither "=>", nor "Function"');
-}
-
 main() {
-  fn = detectForm();
-
   // Types that do not use class names - these can be checked on dart2js in
   // minified mode.
 
diff --git a/tests/standalone/dwarf_stack_trace_obfuscate_test.dart b/tests/standalone/dwarf_stack_trace_obfuscate_test.dart
new file mode 100644
index 0000000..5750ab5
--- /dev/null
+++ b/tests/standalone/dwarf_stack_trace_obfuscate_test.dart
@@ -0,0 +1,76 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// VMOptions=--dwarf-stack-traces --save-debugging-info=dwarf_obfuscate.so --obfuscate
+
+import 'dart:io';
+
+import 'package:native_stack_traces/native_stack_traces.dart';
+import 'package:path/path.dart' as path;
+
+import 'dwarf_stack_trace_test.dart' as base;
+
+@pragma("vm:prefer-inline")
+bar() {
+  // Keep the 'throw' and its argument on separate lines.
+  throw // force linebreak with dartfmt
+      "Hello, Dwarf!";
+}
+
+@pragma("vm:never-inline")
+foo() {
+  bar();
+}
+
+Future<void> main() async {
+  String rawStack = "";
+  try {
+    foo();
+  } catch (e, st) {
+    rawStack = st.toString();
+  }
+
+  if (path.basenameWithoutExtension(Platform.executable) !=
+      "dart_precompiled_runtime") {
+    return; // Not running from an AOT compiled snapshot.
+  }
+
+  if (Platform.isAndroid) {
+    return; // Generated dwarf.so not available on the test device.
+  }
+
+  final dwarf = Dwarf.fromFile("dwarf_obfuscate.so");
+
+  await base.checkStackTrace(rawStack, dwarf, expectedCallsInfo);
+}
+
+final expectedCallsInfo = <List<DartCallInfo>>[
+  // The first frame should correspond to the throw in bar, which was inlined
+  // into foo (so we'll get information for two calls for that PC address).
+  [
+    DartCallInfo(
+        function: "bar",
+        filename: "dwarf_stack_trace_obfuscate_test.dart",
+        line: 17,
+        column: 3,
+        inlined: true),
+    DartCallInfo(
+        function: "foo",
+        filename: "dwarf_stack_trace_obfuscate_test.dart",
+        line: 23,
+        column: 3,
+        inlined: false)
+  ],
+  // The second frame corresponds to call to foo in main.
+  [
+    DartCallInfo(
+        function: "main",
+        filename: "dwarf_stack_trace_obfuscate_test.dart",
+        line: 29,
+        column: 5,
+        inlined: false)
+  ],
+  // Don't assume anything about any of the frames below the call to foo
+  // in main, as this makes the test too brittle.
+];
diff --git a/tests/standalone/dwarf_stack_trace_test.dart b/tests/standalone/dwarf_stack_trace_test.dart
new file mode 100644
index 0000000..9cf2cb0
--- /dev/null
+++ b/tests/standalone/dwarf_stack_trace_test.dart
@@ -0,0 +1,228 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// VMOptions=--dwarf-stack-traces --save-debugging-info=dwarf.so
+
+import 'dart:convert';
+import 'dart:io';
+
+import 'package:native_stack_traces/native_stack_traces.dart';
+import 'package:path/path.dart' as path;
+import 'package:expect/expect.dart';
+
+@pragma("vm:prefer-inline")
+bar() {
+  // Keep the 'throw' and its argument on separate lines.
+  throw // force linebreak with dartfmt
+      "Hello, Dwarf!";
+}
+
+@pragma("vm:never-inline")
+foo() {
+  bar();
+}
+
+Future<void> main() async {
+  String rawStack = "";
+  try {
+    foo();
+  } catch (e, st) {
+    rawStack = st.toString();
+  }
+
+  if (path.basenameWithoutExtension(Platform.executable) !=
+      "dart_precompiled_runtime") {
+    return; // Not running from an AOT compiled snapshot.
+  }
+
+  if (Platform.isAndroid) {
+    return; // Generated dwarf.so not available on the test device.
+  }
+
+  final dwarf = Dwarf.fromFile("dwarf.so");
+
+  await checkStackTrace(rawStack, dwarf, expectedCallsInfo);
+}
+
+Future<void> checkStackTrace(String rawStack, Dwarf dwarf,
+    List<List<DartCallInfo>> expectedCallsInfo) async {
+  print("");
+  print("Raw stack trace:");
+  print(rawStack);
+
+  final rawLines =
+      await Stream.value(rawStack).transform(const LineSplitter()).toList();
+
+  final pcOffsets = collectPCOffsets(rawLines).toList();
+
+  // We should have at least enough PC addresses to cover the frames we'll be
+  // checking.
+  Expect.isTrue(pcOffsets.length >= expectedCallsInfo.length);
+
+  final virtualAddresses =
+      pcOffsets.map((o) => dwarf.virtualAddressOf(o)).toList();
+
+  // Some double-checks using other information in the non-symbolic stack trace.
+  final dsoBase = dsoBaseAddresses(rawLines).single;
+  final absolutes = absoluteAddresses(rawLines);
+  final relocatedAddresses = absolutes.map((a) => a - dsoBase);
+  final explicits = explicitVirtualAddresses(rawLines);
+
+  // Explicits will be empty if not generating ELF snapshots directly, which
+  // means we can't depend on virtual addresses in the snapshot lining up with
+  // those in the separate debugging information.
+  if (explicits.isNotEmpty) {
+    // Direct-to-ELF snapshots should have a build ID.
+    Expect.isNotNull(dwarf.buildId);
+    Expect.deepEquals(relocatedAddresses, virtualAddresses);
+    Expect.deepEquals(explicits, virtualAddresses);
+  }
+
+  final gotCallsInfo = <List<DartCallInfo>>[];
+
+  for (final addr in virtualAddresses) {
+    final externalCallInfo = dwarf.callInfoFor(addr);
+    Expect.isNotNull(externalCallInfo);
+    final allCallInfo = dwarf.callInfoFor(addr, includeInternalFrames: true);
+    Expect.isNotNull(allCallInfo);
+    for (final call in allCallInfo) {
+      Expect.isTrue(call is DartCallInfo, "got non-Dart call info ${call}");
+    }
+    Expect.deepEquals(externalCallInfo, allCallInfo);
+    gotCallsInfo.add(allCallInfo.cast<DartCallInfo>().toList());
+  }
+
+  print("");
+  print("Call information for PC addresses:");
+  for (var i = 0; i < virtualAddresses.length; i++) {
+    print("For PC 0x${virtualAddresses[i].toRadixString(16)}:");
+    print("  Calls corresponding to user or library code:");
+    gotCallsInfo[i].forEach((frame) => print("    ${frame}"));
+  }
+
+  checkFrames(gotCallsInfo, expectedCallsInfo);
+
+  final gotSymbolizedLines = await Stream.fromIterable(rawLines)
+      .transform(DwarfStackTraceDecoder(dwarf, includeInternalFrames: true))
+      .toList();
+
+  final gotSymbolizedCalls =
+      gotSymbolizedLines.where((s) => s.startsWith('#')).toList();
+
+  print("");
+  print("Symbolized stack trace:");
+  gotSymbolizedLines.forEach(print);
+  print("");
+  print("Extracted calls:");
+  gotSymbolizedCalls.forEach(print);
+
+  final expectedStrings = extractCallStrings(expectedCallsInfo);
+  // There are two strings in the list for each line in the output.
+  final expectedCallCount = expectedStrings.length ~/ 2;
+
+  Expect.isTrue(gotSymbolizedCalls.length >= expectedCallCount);
+
+  // Strip off any unexpected lines, so we can also make sure we didn't get
+  // unexpected calls prior to those calls we expect.
+  final gotCallsTrace =
+      gotSymbolizedCalls.sublist(0, expectedCallCount).join('\n');
+
+  Expect.stringContainsInOrder(gotCallsTrace, expectedStrings);
+}
+
+final expectedCallsInfo = <List<DartCallInfo>>[
+  // The first frame should correspond to the throw in bar, which was inlined
+  // into foo (so we'll get information for two calls for that PC address).
+  [
+    DartCallInfo(
+        function: "bar",
+        filename: "dwarf_stack_trace_test.dart",
+        line: 17,
+        column: 3,
+        inlined: true),
+    DartCallInfo(
+        function: "foo",
+        filename: "dwarf_stack_trace_test.dart",
+        line: 23,
+        column: 3,
+        inlined: false)
+  ],
+  // The second frame corresponds to call to foo in main.
+  [
+    DartCallInfo(
+        function: "main",
+        filename: "dwarf_stack_trace_test.dart",
+        line: 29,
+        column: 5,
+        inlined: false)
+  ],
+  // Don't assume anything about any of the frames below the call to foo
+  // in main, as this makes the test too brittle.
+];
+
+void checkFrames(
+    List<List<DartCallInfo>> gotInfo, List<List<DartCallInfo>> expectedInfo) {
+  // There may be frames below those we check.
+  Expect.isTrue(gotInfo.length >= expectedInfo.length);
+
+  // We can't just use deep equality, since we only have the filenames in the
+  // expected version, not the whole path, and we don't really care if
+  // non-positive line numbers match, as long as they're both non-positive.
+  for (var i = 0; i < expectedInfo.length; i++) {
+    for (var j = 0; j < expectedInfo[i].length; j++) {
+      final got = gotInfo[i][j];
+      final expected = expectedInfo[i][j];
+      Expect.equals(expected.function, got.function);
+      Expect.equals(expected.inlined, got.inlined);
+      Expect.equals(expected.filename, path.basename(got.filename));
+      if (expected.isInternal) {
+        Expect.isTrue(got.isInternal);
+      } else {
+        Expect.equals(expected.line, got.line);
+      }
+    }
+  }
+}
+
+List<String> extractCallStrings(List<List<CallInfo>> expectedCalls) {
+  var ret = <String>[];
+  for (final frame in expectedCalls) {
+    for (final call in frame) {
+      if (call is DartCallInfo) {
+        ret.add(call.function);
+        if (call.isInternal) {
+          ret.add("${call.filename}:??");
+        } else {
+          ret.add("${call.filename}:${call.line}");
+        }
+      }
+    }
+  }
+  return ret;
+}
+
+Iterable<int> parseUsingAddressRegExp(RegExp re, Iterable<String> lines) sync* {
+  for (final line in lines) {
+    final match = re.firstMatch(line);
+    if (match == null) continue;
+    final s = match.group(1);
+    if (s == null) continue;
+    yield int.parse(s, radix: 16);
+  }
+}
+
+final _absRE = RegExp(r'abs ([a-f\d]+)');
+
+Iterable<int> absoluteAddresses(Iterable<String> lines) =>
+    parseUsingAddressRegExp(_absRE, lines);
+
+final _virtRE = RegExp(r'virt ([a-f\d]+)');
+
+Iterable<int> explicitVirtualAddresses(Iterable<String> lines) =>
+    parseUsingAddressRegExp(_virtRE, lines);
+
+final _dsoBaseRE = RegExp(r'isolate_dso_base: ([a-f\d]+)');
+
+Iterable<int> dsoBaseAddresses(Iterable<String> lines) =>
+    parseUsingAddressRegExp(_dsoBaseRE, lines);
diff --git a/tests/standalone/io/http_headers_content_length_test.dart b/tests/standalone/io/http_headers_content_length_test.dart
new file mode 100644
index 0000000..9997ffe
--- /dev/null
+++ b/tests/standalone/io/http_headers_content_length_test.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:io";
+
+import "package:expect/expect.dart";
+
+Future<void> main() async {
+  final server = await HttpServer.bind("localhost", 0);
+  final request = await HttpClient().get("localhost", server.port, "/");
+  final headers = request.headers;
+  headers.contentLength = 100;
+  headers.set('Content-Length', 100);
+  Expect.equals('100', headers['Content-Length']?[0]);
+  try {
+    await request.close();
+  } catch (e) {
+    server.close();
+  }
+}
diff --git a/tests/standalone/io/http_proxy_close_test.dart b/tests/standalone/io/http_proxy_close_test.dart
new file mode 100644
index 0000000..2fd39f2
--- /dev/null
+++ b/tests/standalone/io/http_proxy_close_test.dart
@@ -0,0 +1,50 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:io";
+
+import 'package:expect/expect.dart';
+
+// Test that a HTTP "CONNECT" request with 200 status code won't close the
+// underlying socket.
+// issue: https://github.com/dart-lang/sdk/issues/37808
+Future<void> testConnect(int statusCode, int port) async {
+  final url = "https://domain.invalid";
+  var client = HttpClient();
+  try {
+    client.findProxy = (uri) => "PROXY 127.0.0.1:$port";
+    try {
+      final request = await client.getUrl(Uri.parse(url));
+      await request.close();
+      Expect.fail('request should have thrown an exception');
+    } catch (e) {
+      if (statusCode == HttpStatus.ok) {
+        // Underlying sockets won't be closed and then handshake will fail.
+        Expect.type<HandshakeException>(e);
+      } else {
+        Expect.type<HttpException>(e);
+      }
+    }
+  } finally {
+    client.close();
+  }
+}
+
+Future<void> main() async {
+  final server = await HttpServer.bind('127.0.0.1', 0);
+  try {
+    final statusCodes = <int>[200, 299, 199, 300];
+    int index = 0;
+    server.listen((request) {
+      request.response.statusCode = statusCodes[index++];
+      request.response.headers.contentLength = 0;
+      request.response.close();
+    });
+    for (final statusCode in statusCodes) {
+      await testConnect(statusCode, server.port);
+    }
+  } finally {
+    server.close();
+  }
+}
diff --git a/tests/standalone_2/dwarf_stack_trace_obfuscate_test.dart b/tests/standalone_2/dwarf_stack_trace_obfuscate_test.dart
index 37fd305..5750ab5 100644
--- a/tests/standalone_2/dwarf_stack_trace_obfuscate_test.dart
+++ b/tests/standalone_2/dwarf_stack_trace_obfuscate_test.dart
@@ -24,7 +24,7 @@
 }
 
 Future<void> main() async {
-  String rawStack;
+  String rawStack = "";
   try {
     foo();
   } catch (e, st) {
@@ -45,7 +45,7 @@
   await base.checkStackTrace(rawStack, dwarf, expectedCallsInfo);
 }
 
-final expectedCallsInfo = <List<CallInfo>>[
+final expectedCallsInfo = <List<DartCallInfo>>[
   // The first frame should correspond to the throw in bar, which was inlined
   // into foo (so we'll get information for two calls for that PC address).
   [
@@ -53,11 +53,13 @@
         function: "bar",
         filename: "dwarf_stack_trace_obfuscate_test.dart",
         line: 17,
+        column: 3,
         inlined: true),
     DartCallInfo(
         function: "foo",
         filename: "dwarf_stack_trace_obfuscate_test.dart",
         line: 23,
+        column: 3,
         inlined: false)
   ],
   // The second frame corresponds to call to foo in main.
@@ -66,6 +68,7 @@
         function: "main",
         filename: "dwarf_stack_trace_obfuscate_test.dart",
         line: 29,
+        column: 5,
         inlined: false)
   ],
   // Don't assume anything about any of the frames below the call to foo
diff --git a/tests/standalone_2/dwarf_stack_trace_test.dart b/tests/standalone_2/dwarf_stack_trace_test.dart
index dac3e58..9cf2cb0 100644
--- a/tests/standalone_2/dwarf_stack_trace_test.dart
+++ b/tests/standalone_2/dwarf_stack_trace_test.dart
@@ -24,7 +24,7 @@
 }
 
 Future<void> main() async {
-  String rawStack;
+  String rawStack = "";
   try {
     foo();
   } catch (e, st) {
@@ -46,10 +46,7 @@
 }
 
 Future<void> checkStackTrace(String rawStack, Dwarf dwarf,
-    List<List<CallInfo>> expectedCallsInfo) async {
-  final expectedAllCallsInfo = expectedCallsInfo;
-  final expectedExternalCallInfo = removeInternalCalls(expectedCallsInfo);
-
+    List<List<DartCallInfo>> expectedCallsInfo) async {
   print("");
   print("Raw stack trace:");
   print(rawStack);
@@ -61,7 +58,7 @@
 
   // We should have at least enough PC addresses to cover the frames we'll be
   // checking.
-  Expect.isTrue(pcOffsets.length >= expectedAllCallsInfo.length);
+  Expect.isTrue(pcOffsets.length >= expectedCallsInfo.length);
 
   final virtualAddresses =
       pcOffsets.map((o) => dwarf.virtualAddressOf(o)).toList();
@@ -82,13 +79,18 @@
     Expect.deepEquals(explicits, virtualAddresses);
   }
 
-  final externalFramesInfo = <List<CallInfo>>[];
-  final allFramesInfo = <List<CallInfo>>[];
+  final gotCallsInfo = <List<DartCallInfo>>[];
 
   for (final addr in virtualAddresses) {
-    externalFramesInfo.add(dwarf.callInfoFor(addr)?.toList());
-    allFramesInfo
-        .add(dwarf.callInfoFor(addr, includeInternalFrames: true)?.toList());
+    final externalCallInfo = dwarf.callInfoFor(addr);
+    Expect.isNotNull(externalCallInfo);
+    final allCallInfo = dwarf.callInfoFor(addr, includeInternalFrames: true);
+    Expect.isNotNull(allCallInfo);
+    for (final call in allCallInfo) {
+      Expect.isTrue(call is DartCallInfo, "got non-Dart call info ${call}");
+    }
+    Expect.deepEquals(externalCallInfo, allCallInfo);
+    gotCallsInfo.add(allCallInfo.cast<DartCallInfo>().toList());
   }
 
   print("");
@@ -96,66 +98,40 @@
   for (var i = 0; i < virtualAddresses.length; i++) {
     print("For PC 0x${virtualAddresses[i].toRadixString(16)}:");
     print("  Calls corresponding to user or library code:");
-    externalFramesInfo[i]?.forEach((frame) => print("    ${frame}"));
-    print("  All calls:");
-    allFramesInfo[i]?.forEach((frame) => print("    ${frame}"));
+    gotCallsInfo[i].forEach((frame) => print("    ${frame}"));
   }
 
-  // Check that our results are also consistent.
-  checkConsistency(externalFramesInfo, allFramesInfo);
+  checkFrames(gotCallsInfo, expectedCallsInfo);
 
-  checkFrames(externalFramesInfo, expectedExternalCallInfo);
-  checkFrames(allFramesInfo, expectedAllCallsInfo);
-
-  final externalSymbolizedLines = await Stream.fromIterable(rawLines)
-      .transform(DwarfStackTraceDecoder(dwarf))
-      .toList();
-
-  final externalSymbolizedCalls =
-      externalSymbolizedLines.where((s) => s.startsWith('#')).toList();
-
-  print("");
-  print("Symbolized external-only stack trace:");
-  externalSymbolizedLines.forEach(print);
-  print("");
-  print("Extracted calls:");
-  externalSymbolizedCalls.forEach(print);
-
-  final allSymbolizedLines = await Stream.fromIterable(rawLines)
+  final gotSymbolizedLines = await Stream.fromIterable(rawLines)
       .transform(DwarfStackTraceDecoder(dwarf, includeInternalFrames: true))
       .toList();
 
-  final allSymbolizedCalls =
-      allSymbolizedLines.where((s) => s.startsWith('#')).toList();
+  final gotSymbolizedCalls =
+      gotSymbolizedLines.where((s) => s.startsWith('#')).toList();
 
   print("");
-  print("Symbolized full stack trace:");
-  allSymbolizedLines.forEach(print);
+  print("Symbolized stack trace:");
+  gotSymbolizedLines.forEach(print);
   print("");
   print("Extracted calls:");
-  allSymbolizedCalls.forEach(print);
+  gotSymbolizedCalls.forEach(print);
 
-  final expectedExternalStrings = extractCallStrings(expectedExternalCallInfo);
+  final expectedStrings = extractCallStrings(expectedCallsInfo);
   // There are two strings in the list for each line in the output.
-  final expectedExternalCallCount = expectedExternalStrings.length ~/ 2;
-  final expectedStrings = extractCallStrings(expectedAllCallsInfo);
   final expectedCallCount = expectedStrings.length ~/ 2;
 
-  Expect.isTrue(externalSymbolizedCalls.length >= expectedExternalCallCount);
-  Expect.isTrue(allSymbolizedCalls.length >= expectedCallCount);
+  Expect.isTrue(gotSymbolizedCalls.length >= expectedCallCount);
 
   // Strip off any unexpected lines, so we can also make sure we didn't get
   // unexpected calls prior to those calls we expect.
-  final externalCallsTrace =
-      externalSymbolizedCalls.sublist(0, expectedExternalCallCount).join('\n');
-  final allCallsTrace =
-      allSymbolizedCalls.sublist(0, expectedCallCount).join('\n');
+  final gotCallsTrace =
+      gotSymbolizedCalls.sublist(0, expectedCallCount).join('\n');
 
-  Expect.stringContainsInOrder(externalCallsTrace, expectedExternalStrings);
-  Expect.stringContainsInOrder(allCallsTrace, expectedStrings);
+  Expect.stringContainsInOrder(gotCallsTrace, expectedStrings);
 }
 
-final expectedCallsInfo = <List<CallInfo>>[
+final expectedCallsInfo = <List<DartCallInfo>>[
   // The first frame should correspond to the throw in bar, which was inlined
   // into foo (so we'll get information for two calls for that PC address).
   [
@@ -163,11 +139,13 @@
         function: "bar",
         filename: "dwarf_stack_trace_test.dart",
         line: 17,
+        column: 3,
         inlined: true),
     DartCallInfo(
         function: "foo",
         filename: "dwarf_stack_trace_test.dart",
         line: 23,
+        column: 3,
         inlined: false)
   ],
   // The second frame corresponds to call to foo in main.
@@ -176,65 +154,25 @@
         function: "main",
         filename: "dwarf_stack_trace_test.dart",
         line: 29,
+        column: 5,
         inlined: false)
   ],
   // Don't assume anything about any of the frames below the call to foo
   // in main, as this makes the test too brittle.
 ];
 
-List<List<CallInfo>> removeInternalCalls(List<List<CallInfo>> original) =>
-    original
-        .map((frame) => frame.where((call) => !call.isInternal).toList())
-        .toList();
-
-void checkConsistency(
-    List<List<CallInfo>> externalFrames, List<List<CallInfo>> allFrames) {
-  // We should have the same number of frames for both external-only
-  // and combined call information.
-  Expect.equals(allFrames.length, externalFrames.length);
-
-  for (var frame in externalFrames) {
-    // There should be no frames in either version where we failed to look up
-    // call information.
-    Expect.isNotNull(frame);
-
-    // External-only call information should only include call information with
-    // positive line numbers.
-    for (var call in frame) {
-      Expect.isTrue(!call.isInternal);
-    }
-  }
-
-  for (var frame in allFrames) {
-    // There should be no frames in either version where we failed to look up
-    // call information.
-    Expect.isNotNull(frame);
-
-    // All frames in the internal-including version should have at least one
-    // piece of call information.
-    Expect.isTrue(frame.isNotEmpty);
-  }
-
-  // The information in the external-only and combined call information should
-  // be consistent for externally visible calls.
-  final allFramesStripped = removeInternalCalls(allFrames);
-  for (var i = 0; i < allFramesStripped.length; i++) {
-    Expect.listEquals(allFramesStripped[i], externalFrames[i]);
-  }
-}
-
 void checkFrames(
-    List<List<CallInfo>> framesInfo, List<List<CallInfo>> expectedInfo) {
+    List<List<DartCallInfo>> gotInfo, List<List<DartCallInfo>> expectedInfo) {
   // There may be frames below those we check.
-  Expect.isTrue(framesInfo.length >= expectedInfo.length);
+  Expect.isTrue(gotInfo.length >= expectedInfo.length);
 
   // We can't just use deep equality, since we only have the filenames in the
   // expected version, not the whole path, and we don't really care if
   // non-positive line numbers match, as long as they're both non-positive.
   for (var i = 0; i < expectedInfo.length; i++) {
     for (var j = 0; j < expectedInfo[i].length; j++) {
-      final DartCallInfo got = framesInfo[i][j];
-      final DartCallInfo expected = expectedInfo[i][j];
+      final got = gotInfo[i][j];
+      final expected = expectedInfo[i][j];
       Expect.equals(expected.function, got.function);
       Expect.equals(expected.inlined, got.inlined);
       Expect.equals(expected.filename, path.basename(got.filename));
@@ -267,9 +205,10 @@
 Iterable<int> parseUsingAddressRegExp(RegExp re, Iterable<String> lines) sync* {
   for (final line in lines) {
     final match = re.firstMatch(line);
-    if (match != null) {
-      yield int.parse(match.group(1), radix: 16);
-    }
+    if (match == null) continue;
+    final s = match.group(1);
+    if (s == null) continue;
+    yield int.parse(s, radix: 16);
   }
 }
 
diff --git a/tests/standalone_2/io/http_headers_content_length_test.dart b/tests/standalone_2/io/http_headers_content_length_test.dart
new file mode 100644
index 0000000..523ac69
--- /dev/null
+++ b/tests/standalone_2/io/http_headers_content_length_test.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:io";
+
+import "package:expect/expect.dart";
+
+Future<void> main() async {
+  final server = await HttpServer.bind("localhost", 0);
+  final request = await HttpClient().get("localhost", server.port, "/");
+  final headers = request.headers;
+  headers.contentLength = 100;
+  headers.set('Content-Length', 100);
+  Expect.equals('100', headers['Content-Length'][0]);
+  try {
+    await request.close();
+  } catch (e) {
+    server.close();
+  }
+}
diff --git a/tests/standalone_2/io/http_proxy_close_test.dart b/tests/standalone_2/io/http_proxy_close_test.dart
new file mode 100644
index 0000000..2fd39f2
--- /dev/null
+++ b/tests/standalone_2/io/http_proxy_close_test.dart
@@ -0,0 +1,50 @@
+// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:io";
+
+import 'package:expect/expect.dart';
+
+// Test that a HTTP "CONNECT" request with 200 status code won't close the
+// underlying socket.
+// issue: https://github.com/dart-lang/sdk/issues/37808
+Future<void> testConnect(int statusCode, int port) async {
+  final url = "https://domain.invalid";
+  var client = HttpClient();
+  try {
+    client.findProxy = (uri) => "PROXY 127.0.0.1:$port";
+    try {
+      final request = await client.getUrl(Uri.parse(url));
+      await request.close();
+      Expect.fail('request should have thrown an exception');
+    } catch (e) {
+      if (statusCode == HttpStatus.ok) {
+        // Underlying sockets won't be closed and then handshake will fail.
+        Expect.type<HandshakeException>(e);
+      } else {
+        Expect.type<HttpException>(e);
+      }
+    }
+  } finally {
+    client.close();
+  }
+}
+
+Future<void> main() async {
+  final server = await HttpServer.bind('127.0.0.1', 0);
+  try {
+    final statusCodes = <int>[200, 299, 199, 300];
+    int index = 0;
+    server.listen((request) {
+      request.response.statusCode = statusCodes[index++];
+      request.response.headers.contentLength = 0;
+      request.response.close();
+    });
+    for (final statusCode in statusCodes) {
+      await testConnect(statusCode, server.port);
+    }
+  } finally {
+    server.close();
+  }
+}
diff --git a/tools/FAKE_COMMITS b/tools/FAKE_COMMITS
index 5ce0701..286b4b7 100644
--- a/tools/FAKE_COMMITS
+++ b/tools/FAKE_COMMITS
@@ -24,6 +24,7 @@
 Trigger mirroring of github repository
 Force build after DEPS format revert
 Force build while trybots are broken, to check builders for brokenness.
+Force build to test recipe changes
 
 Analyzer branch commits:
 Force build on new analyzer-branch linux build with new workflow
diff --git a/tools/VERSION b/tools/VERSION
index 60fa9bb..fd6266b 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -33,7 +33,7 @@
 MAJOR 2
 MINOR 9
 PATCH 0
-PRERELEASE 18
+PRERELEASE 19
 PRERELEASE_PATCH 0
 ABI_VERSION 37
 OLDEST_SUPPORTED_ABI_VERSION 37
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index 828c326..be160e9 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -2630,7 +2630,6 @@
           "name": "dart2js nnbd unit tests",
           "arguments": [
             "-nunittest-weak-asserts-no-sdk-linux",
-            "dart2js_2",
             "pkg//compiler/"
           ]
         }
diff --git a/tools/dom/nnbd_src/AttributeMap.dart b/tools/dom/nnbd_src/AttributeMap.dart
deleted file mode 100644
index 88f3bd4..0000000
--- a/tools/dom/nnbd_src/AttributeMap.dart
+++ /dev/null
@@ -1,299 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of html;
-
-abstract class _AttributeMap extends MapBase<String, String> {
-  final Element _element;
-
-  _AttributeMap(this._element);
-
-  void addAll(Map<String, String> other) {
-    other.forEach((k, v) {
-      this[k] = v;
-    });
-  }
-
-  Map<K, V> cast<K, V>() => Map.castFrom<String, String, K, V>(this);
-  bool containsValue(Object? value) {
-    for (var v in this.values) {
-      if (value == v) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  String putIfAbsent(String key, String ifAbsent()) {
-    if (!containsKey(key)) {
-      this[key] = ifAbsent();
-    }
-    return this[key] as String;
-  }
-
-  void clear() {
-    for (var key in keys) {
-      remove(key);
-    }
-  }
-
-  void forEach(void f(String key, String value)) {
-    for (var key in keys) {
-      var value = this[key];
-      f(key, value as String);
-    }
-  }
-
-  Iterable<String> get keys {
-    // TODO: generate a lazy collection instead.
-    var attributes = _element._attributes;
-    var keys = <String>[];
-    for (int i = 0, len = attributes.length; i < len; i++) {
-      _Attr attr = attributes[i] as _Attr;
-      if (_matches(attr)) {
-        keys.add(attr.name);
-      }
-    }
-    return keys;
-  }
-
-  Iterable<String> get values {
-    // TODO: generate a lazy collection instead.
-    var attributes = _element._attributes;
-    var values = <String>[];
-    for (int i = 0, len = attributes.length; i < len; i++) {
-      _Attr attr = attributes[i] as _Attr;
-      if (_matches(attr)) {
-        values.add(attr.value);
-      }
-    }
-    return values;
-  }
-
-  /**
-   * Returns true if there is no {key, value} pair in the map.
-   */
-  bool get isEmpty {
-    return length == 0;
-  }
-
-  /**
-   * Returns true if there is at least one {key, value} pair in the map.
-   */
-  bool get isNotEmpty => !isEmpty;
-
-  /**
-   * Checks to see if the node should be included in this map.
-   */
-  bool _matches(_Attr node);
-}
-
-/**
- * Wrapper to expose [Element.attributes] as a typed map.
- */
-class _ElementAttributeMap extends _AttributeMap {
-  _ElementAttributeMap(Element element) : super(element);
-
-  bool containsKey(Object? key) {
-    return key is String && _element._hasAttribute(key);
-  }
-
-  String? operator [](Object? key) {
-    return _element.getAttribute(key as String);
-  }
-
-  void operator []=(String key, String value) {
-    _element.setAttribute(key, value);
-  }
-
-  @pragma('dart2js:tryInline')
-  String? remove(Object? key) => key is String ? _remove(_element, key) : null;
-
-  /**
-   * The number of {key, value} pairs in the map.
-   */
-  int get length {
-    return keys.length;
-  }
-
-  bool _matches(_Attr node) => node._namespaceUri == null;
-
-  // Inline this because almost all call sites of [remove] do not use [value],
-  // and the annotations on the `getAttribute` call allow it to be removed.
-  @pragma('dart2js:tryInline')
-  static String? _remove(Element element, String key) {
-    String? value = JS(
-        // throws:null(1) is not accurate since [key] could be malformed, but
-        // [key] is checked again by `removeAttributeNS`.
-        'returns:String|Null;depends:all;effects:none;throws:null(1)',
-        '#.getAttribute(#)',
-        element,
-        key);
-    JS('', '#.removeAttribute(#)', element, key);
-    return value;
-  }
-}
-
-/**
- * Wrapper to expose namespaced attributes as a typed map.
- */
-class _NamespacedAttributeMap extends _AttributeMap {
-  final String? _namespace;
-
-  _NamespacedAttributeMap(Element element, this._namespace) : super(element);
-
-  bool containsKey(Object? key) {
-    return key is String && _element._hasAttributeNS(_namespace, key);
-  }
-
-  String? operator [](Object? key) {
-    return _element.getAttributeNS(_namespace, key as String);
-  }
-
-  void operator []=(String key, String value) {
-    _element.setAttributeNS(_namespace, key, value);
-  }
-
-  @pragma('dart2js:tryInline')
-  String? remove(Object? key) =>
-      key is String ? _remove(_namespace, _element, key) : null;
-
-  /**
-   * The number of {key, value} pairs in the map.
-   */
-  int get length {
-    return keys.length;
-  }
-
-  bool _matches(_Attr node) => node._namespaceUri == _namespace;
-
-  // Inline this because almost all call sites of [remove] do not use the
-  // returned [value], and the annotations on the `getAttributeNS` call allow it
-  // to be removed.
-  @pragma('dart2js:tryInline')
-  static String? _remove(String? namespace, Element element, String key) {
-    String? value = JS(
-        // throws:null(1) is not accurate since [key] could be malformed, but
-        // [key] is checked again by `removeAttributeNS`.
-        'returns:String|Null;depends:all;effects:none;throws:null(1)',
-        '#.getAttributeNS(#, #)',
-        element,
-        namespace,
-        key);
-    JS('', '#.removeAttributeNS(#, #)', element, namespace, key);
-    return value;
-  }
-}
-
-/**
- * Provides a Map abstraction on top of data-* attributes, similar to the
- * dataSet in the old DOM.
- */
-class _DataAttributeMap extends MapBase<String, String> {
-  final Map<String, String> _attributes;
-
-  _DataAttributeMap(this._attributes);
-
-  // interface Map
-
-  void addAll(Map<String, String> other) {
-    other.forEach((k, v) {
-      this[k] = v;
-    });
-  }
-
-  Map<K, V> cast<K, V>() => Map.castFrom<String, String, K, V>(this);
-  // TODO: Use lazy iterator when it is available on Map.
-  bool containsValue(Object? value) => values.any((v) => v == value);
-
-  bool containsKey(Object? key) =>
-      _attributes.containsKey(_attr(key as String));
-
-  String? operator [](Object? key) => _attributes[_attr(key as String)];
-
-  void operator []=(String key, String value) {
-    _attributes[_attr(key)] = value;
-  }
-
-  String putIfAbsent(String key, String ifAbsent()) =>
-      _attributes.putIfAbsent(_attr(key), ifAbsent);
-
-  String? remove(Object? key) => _attributes.remove(_attr(key as String));
-
-  void clear() {
-    // Needs to operate on a snapshot since we are mutating the collection.
-    for (String key in keys) {
-      remove(key);
-    }
-  }
-
-  void forEach(void f(String key, String value)) {
-    _attributes.forEach((String key, String value) {
-      if (_matches(key)) {
-        f(_strip(key), value);
-      }
-    });
-  }
-
-  Iterable<String> get keys {
-    final keys = <String>[];
-    _attributes.forEach((String key, String value) {
-      if (_matches(key)) {
-        keys.add(_strip(key));
-      }
-    });
-    return keys;
-  }
-
-  Iterable<String> get values {
-    final values = <String>[];
-    _attributes.forEach((String key, String value) {
-      if (_matches(key)) {
-        values.add(value);
-      }
-    });
-    return values;
-  }
-
-  int get length => keys.length;
-
-  // TODO: Use lazy iterator when it is available on Map.
-  bool get isEmpty => length == 0;
-
-  bool get isNotEmpty => !isEmpty;
-
-  // Helpers.
-  String _attr(String key) => 'data-${_toHyphenedName(key)}';
-  bool _matches(String key) => key.startsWith('data-');
-  String _strip(String key) => _toCamelCase(key.substring(5));
-
-  /**
-   * Converts a string name with hyphens into an identifier, by removing hyphens
-   * and capitalizing the following letter. Optionally [startUppercase] to
-   * capitalize the first letter.
-   */
-  String _toCamelCase(String hyphenedName, {bool startUppercase: false}) {
-    var segments = hyphenedName.split('-');
-    int start = startUppercase ? 0 : 1;
-    for (int i = start; i < segments.length; i++) {
-      var segment = segments[i];
-      if (segment.length > 0) {
-        // Character between 'a'..'z' mapped to 'A'..'Z'
-        segments[i] = '${segment[0].toUpperCase()}${segment.substring(1)}';
-      }
-    }
-    return segments.join('');
-  }
-
-  /** Reverse of [toCamelCase]. */
-  String _toHyphenedName(String word) {
-    var sb = new StringBuffer();
-    for (int i = 0; i < word.length; i++) {
-      var lower = word[i].toLowerCase();
-      if (word[i] != lower && i > 0) sb.write('-');
-      sb.write(lower);
-    }
-    return sb.toString();
-  }
-}
diff --git a/tools/dom/nnbd_src/CanvasImageSource.dart b/tools/dom/nnbd_src/CanvasImageSource.dart
deleted file mode 100644
index ffcd34a..0000000
--- a/tools/dom/nnbd_src/CanvasImageSource.dart
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of html;
-
-/**
- * An object that can be drawn to a 2D canvas rendering context.
- *
- * The image drawn to the canvas depends on the type of this object:
- *
- * * If this object is an [ImageElement], then this element's image is
- * drawn to the canvas. If this element is an animated image, then this
- * element's poster frame is drawn. If this element has no poster frame, then
- * the first frame of animation is drawn.
- *
- * * If this object is a [VideoElement], then the frame at this element's current
- * playback position is drawn to the canvas.
- *
- * * If this object is a [CanvasElement], then this element's bitmap is drawn to
- * the canvas.
- *
- * **Note:** Currently all versions of Internet Explorer do not support
- * drawing a video element to a canvas. You may also encounter problems drawing
- * a video to a canvas in Firefox if the source of the video is a data URL.
- *
- * ## See also
- *
- * * [CanvasRenderingContext2D.drawImage]
- * * [CanvasRenderingContext2D.drawImageToRect]
- * * [CanvasRenderingContext2D.drawImageScaled]
- * * [CanvasRenderingContext2D.drawImageScaledFromSource]
- *
- * ## Other resources
- *
- * * [Image sources for 2D rendering
- *   contexts](https://html.spec.whatwg.org/multipage/scripting.html#image-sources-for-2d-rendering-contexts)
- *   from WHATWG.
- * * [Drawing images](https://html.spec.whatwg.org/multipage/scripting.html#dom-context-2d-drawimage)
- *   from WHATWG.
- */
-abstract class CanvasImageSource {}
diff --git a/tools/dom/nnbd_src/CrossFrameTypes.dart b/tools/dom/nnbd_src/CrossFrameTypes.dart
deleted file mode 100644
index 7d210a3..0000000
--- a/tools/dom/nnbd_src/CrossFrameTypes.dart
+++ /dev/null
@@ -1,156 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of html;
-
-/**
- * Top-level container for a browser tab or window.
- *
- * In a web browser, a [WindowBase] object represents any browser window. This
- * object contains the window's state and its relation to other
- * windows, such as which window opened this window.
- *
- * **Note:** This class represents any window, while [Window] is
- * used to access the properties and content of the current window or tab.
- *
- * ## See also
- *
- * * [Window]
- *
- * ## Other resources
- *
- * * [DOM Window](https://developer.mozilla.org/en-US/docs/DOM/window) from MDN.
- * * [Window](http://www.w3.org/TR/Window/) from the W3C.
- */
-abstract class WindowBase implements EventTarget {
-  // Fields.
-
-  /**
-   * The current location of this window.
-   *
-   *     Location currentLocation = window.location;
-   *     print(currentLocation.href); // 'http://www.example.com:80/'
-   */
-  LocationBase get location;
-
-  /**
-   * The current session history for this window.
-   *
-   * ## Other resources
-   *
-   * * [Session history and navigation
-   *   specification](https://html.spec.whatwg.org/multipage/browsers.html#history)
-   *   from WHATWG.
-   */
-  HistoryBase get history;
-
-  /**
-   * Indicates whether this window has been closed.
-   *
-   *     print(window.closed); // 'false'
-   *     window.close();
-   *     print(window.closed); // 'true'
-   */
-  bool get closed;
-
-  /**
-   * A reference to the window that opened this one.
-   *
-   *     Window thisWindow = window;
-   *     WindowBase otherWindow = thisWindow.open('http://www.example.com/', 'foo');
-   *     print(otherWindow.opener == thisWindow); // 'true'
-   */
-  WindowBase? get opener;
-
-  /**
-   * A reference to the parent of this window.
-   *
-   * If this [WindowBase] has no parent, [parent] will return a reference to
-   * the [WindowBase] itself.
-   *
-   *     IFrameElement myIFrame = new IFrameElement();
-   *     window.document.body.elements.add(myIFrame);
-   *     print(myIframe.contentWindow.parent == window) // 'true'
-   *
-   *     print(window.parent == window) // 'true'
-   */
-  WindowBase? get parent;
-
-  /**
-   * A reference to the topmost window in the window hierarchy.
-   *
-   * If this [WindowBase] is the topmost [WindowBase], [top] will return a
-   * reference to the [WindowBase] itself.
-   *
-   *     // Add an IFrame to the current window.
-   *     IFrameElement myIFrame = new IFrameElement();
-   *     window.document.body.elements.add(myIFrame);
-   *
-   *     // Add an IFrame inside of the other IFrame.
-   *     IFrameElement innerIFrame = new IFrameElement();
-   *     myIFrame.elements.add(innerIFrame);
-   *
-   *     print(myIframe.contentWindow.top == window) // 'true'
-   *     print(innerIFrame.contentWindow.top == window) // 'true'
-   *
-   *     print(window.top == window) // 'true'
-   */
-  WindowBase? get top;
-
-  // Methods.
-  /**
-   * Closes the window.
-   *
-   * This method should only succeed if the [WindowBase] object is
-   * **script-closeable** and the window calling [close] is allowed to navigate
-   * the window.
-   *
-   * A window is script-closeable if it is either a window
-   * that was opened by another window, or if it is a window with only one
-   * document in its history.
-   *
-   * A window might not be allowed to navigate, and therefore close, another
-   * window due to browser security features.
-   *
-   *     var other = window.open('http://www.example.com', 'foo');
-   *     // Closes other window, as it is script-closeable.
-   *     other.close();
-   *     print(other.closed); // 'true'
-   *
-   *     var newLocation = window.location
-   *         ..href = 'http://www.mysite.com';
-   *     window.location = newLocation;
-   *     // Does not close this window, as the history has changed.
-   *     window.close();
-   *     print(window.closed); // 'false'
-   *
-   * See also:
-   *
-   * * [Window close discussion](http://www.w3.org/TR/html5/browsers.html#dom-window-close) from the W3C
-   */
-  void close();
-
-  /**
-   * Sends a cross-origin message.
-   *
-   * ## Other resources
-   *
-   * * [window.postMessage](https://developer.mozilla.org/en-US/docs/Web/API/Window.postMessage)
-   *   from MDN.
-   * * [Cross-document messaging](https://html.spec.whatwg.org/multipage/comms.html#web-messaging)
-   *   from WHATWG.
-   */
-  void postMessage(var message, String targetOrigin,
-      [List<MessagePort>? messagePorts]);
-}
-
-abstract class LocationBase {
-  void set href(String val);
-}
-
-abstract class HistoryBase {
-  void back();
-  void forward();
-  void go(int distance);
-}
diff --git a/tools/dom/nnbd_src/CssClassSet.dart b/tools/dom/nnbd_src/CssClassSet.dart
deleted file mode 100644
index 6a76202..0000000
--- a/tools/dom/nnbd_src/CssClassSet.dart
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of html;
-
-/** A Set that stores the CSS class names for an element. */
-abstract class CssClassSet implements Set<String> {
-  /**
-   * Adds the class [value] to the element if it is not on it, removes it if it
-   * is.
-   *
-   * If [shouldAdd] is true, then we always add that [value] to the element. If
-   * [shouldAdd] is false then we always remove [value] from the element.
-   *
-   * If this corresponds to one element, returns `true` if [value] is present
-   * after the operation, and returns `false` if [value] is absent after the
-   * operation.
-   *
-   * If this CssClassSet corresponds to many elements, `false` is always
-   * returned.
-   *
-   * [value] must be a valid 'token' representing a single class, i.e. a
-   * non-empty string containing no whitespace.  To toggle multiple classes, use
-   * [toggleAll].
-   */
-  bool toggle(String value, [bool? shouldAdd]);
-
-  /**
-   * Returns [:true:] if classes cannot be added or removed from this
-   * [:CssClassSet:].
-   */
-  bool get frozen;
-
-  /**
-   * Determine if this element contains the class [value].
-   *
-   * This is the Dart equivalent of jQuery's
-   * [hasClass](http://api.jquery.com/hasClass/).
-   *
-   * [value] must be a valid 'token' representing a single class, i.e. a
-   * non-empty string containing no whitespace.
-   */
-  bool contains(Object? value);
-
-  /**
-   * Add the class [value] to element.
-   *
-   * [add] and [addAll] are the Dart equivalent of jQuery's
-   * [addClass](http://api.jquery.com/addClass/).
-   *
-   * If this CssClassSet corresponds to one element. Returns true if [value] was
-   * added to the set, otherwise false.
-   *
-   * If this CssClassSet corresponds to many elements, `false` is always
-   * returned.
-   *
-   * [value] must be a valid 'token' representing a single class, i.e. a
-   * non-empty string containing no whitespace.  To add multiple classes use
-   * [addAll].
-   */
-  bool add(String value);
-
-  /**
-   * Remove the class [value] from element, and return true on successful
-   * removal.
-   *
-   * [remove] and [removeAll] are the Dart equivalent of jQuery's
-   * [removeClass](http://api.jquery.com/removeClass/).
-   *
-   * [value] must be a valid 'token' representing a single class, i.e. a
-   * non-empty string containing no whitespace.  To remove multiple classes, use
-   * [removeAll].
-   */
-  bool remove(Object? value);
-
-  /**
-   * Add all classes specified in [iterable] to element.
-   *
-   * [add] and [addAll] are the Dart equivalent of jQuery's
-   * [addClass](http://api.jquery.com/addClass/).
-   *
-   * Each element of [iterable] must be a valid 'token' representing a single
-   * class, i.e. a non-empty string containing no whitespace.
-   */
-  void addAll(Iterable<String> iterable);
-
-  /**
-   * Remove all classes specified in [iterable] from element.
-   *
-   * [remove] and [removeAll] are the Dart equivalent of jQuery's
-   * [removeClass](http://api.jquery.com/removeClass/).
-   *
-   * Each element of [iterable] must be a valid 'token' representing a single
-   * class, i.e. a non-empty string containing no whitespace.
-   */
-  void removeAll(Iterable<Object?> iterable);
-
-  /**
-   * Toggles all classes specified in [iterable] on element.
-   *
-   * Iterate through [iterable]'s items, and add it if it is not on it, or
-   * remove it if it is. This is the Dart equivalent of jQuery's
-   * [toggleClass](http://api.jquery.com/toggleClass/).
-   * If [shouldAdd] is true, then we always add all the classes in [iterable]
-   * element. If [shouldAdd] is false then we always remove all the classes in
-   * [iterable] from the element.
-   *
-   * Each element of [iterable] must be a valid 'token' representing a single
-   * class, i.e. a non-empty string containing no whitespace.
-   */
-  void toggleAll(Iterable<String> iterable, [bool? shouldAdd]);
-}
diff --git a/tools/dom/nnbd_src/CssRectangle.dart b/tools/dom/nnbd_src/CssRectangle.dart
deleted file mode 100644
index d26aac7..0000000
--- a/tools/dom/nnbd_src/CssRectangle.dart
+++ /dev/null
@@ -1,372 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of html;
-
-/**
- * A rectangle representing all the content of the element in the
- * [box model](http://www.w3.org/TR/CSS2/box.html).
- */
-class _ContentCssRect extends CssRect {
-  _ContentCssRect(Element element) : super(element);
-
-  num get height =>
-      _element.offsetHeight + _addOrSubtractToBoxModel(_HEIGHT, _CONTENT);
-
-  num get width =>
-      _element.offsetWidth + _addOrSubtractToBoxModel(_WIDTH, _CONTENT);
-
-  /**
-   * Set the height to `newHeight`.
-   *
-   * newHeight can be either a [num] representing the height in pixels or a
-   * [Dimension] object. Values of newHeight that are less than zero are
-   * converted to effectively setting the height to 0. This is equivalent to the
-   * `height` function in jQuery and the calculated `height` CSS value,
-   * converted to a num in pixels.
-   */
-  set height(dynamic newHeight) {
-    if (newHeight is Dimension) {
-      Dimension newHeightAsDimension = newHeight;
-      if (newHeightAsDimension.value < 0) newHeight = new Dimension.px(0);
-      _element.style.height = newHeight.toString();
-    } else if (newHeight is num) {
-      if (newHeight < 0) newHeight = 0;
-      _element.style.height = '${newHeight}px';
-    } else {
-      throw new ArgumentError("newHeight is not a Dimension or num");
-    }
-  }
-
-  /**
-   * Set the current computed width in pixels of this element.
-   *
-   * newWidth can be either a [num] representing the width in pixels or a
-   * [Dimension] object. This is equivalent to the `width` function in jQuery
-   * and the calculated
-   * `width` CSS value, converted to a dimensionless num in pixels.
-   */
-  set width(dynamic newWidth) {
-    if (newWidth is Dimension) {
-      Dimension newWidthAsDimension = newWidth;
-      if (newWidthAsDimension.value < 0) newWidth = new Dimension.px(0);
-      _element.style.width = newWidth.toString();
-    } else if (newWidth is num) {
-      if (newWidth < 0) newWidth = 0;
-      _element.style.width = '${newWidth}px';
-    } else {
-      throw new ArgumentError("newWidth is not a Dimension or num");
-    }
-  }
-
-  num get left =>
-      _element.getBoundingClientRect().left -
-      _addOrSubtractToBoxModel(['left'], _CONTENT);
-  num get top =>
-      _element.getBoundingClientRect().top -
-      _addOrSubtractToBoxModel(['top'], _CONTENT);
-}
-
-/**
- * A list of element content rectangles in the
- * [box model](http://www.w3.org/TR/CSS2/box.html).
- */
-class _ContentCssListRect extends _ContentCssRect {
-  List<Element> _elementList;
-
-  _ContentCssListRect(List<Element> elementList)
-      : _elementList = elementList,
-        super(elementList.first);
-
-  /**
-   * Set the height to `newHeight`.
-   *
-   * Values of newHeight that are less than zero are converted to effectively
-   * setting the height to 0. This is equivalent to the `height`
-   * function in jQuery and the calculated `height` CSS value, converted to a
-   * num in pixels.
-   */
-  set height(newHeight) {
-    _elementList.forEach((e) => e.contentEdge.height = newHeight);
-  }
-
-  /**
-   * Set the current computed width in pixels of this element.
-   *
-   * This is equivalent to the `width` function in jQuery and the calculated
-   * `width` CSS value, converted to a dimensionless num in pixels.
-   */
-  set width(newWidth) {
-    _elementList.forEach((e) => e.contentEdge.width = newWidth);
-  }
-}
-
-/**
- * A rectangle representing the dimensions of the space occupied by the
- * element's content + padding in the
- * [box model](http://www.w3.org/TR/CSS2/box.html).
- */
-class _PaddingCssRect extends CssRect {
-  _PaddingCssRect(element) : super(element);
-  num get height =>
-      _element.offsetHeight + _addOrSubtractToBoxModel(_HEIGHT, _PADDING);
-  num get width =>
-      _element.offsetWidth + _addOrSubtractToBoxModel(_WIDTH, _PADDING);
-
-  num get left =>
-      _element.getBoundingClientRect().left -
-      _addOrSubtractToBoxModel(['left'], _PADDING);
-  num get top =>
-      _element.getBoundingClientRect().top -
-      _addOrSubtractToBoxModel(['top'], _PADDING);
-}
-
-/**
- * A rectangle representing the dimensions of the space occupied by the
- * element's content + padding + border in the
- * [box model](http://www.w3.org/TR/CSS2/box.html).
- */
-class _BorderCssRect extends CssRect {
-  _BorderCssRect(element) : super(element);
-  num get height => _element.offsetHeight;
-  num get width => _element.offsetWidth;
-
-  num get left => _element.getBoundingClientRect().left;
-  num get top => _element.getBoundingClientRect().top;
-}
-
-/**
- * A rectangle representing the dimensions of the space occupied by the
- * element's content + padding + border + margin in the
- * [box model](http://www.w3.org/TR/CSS2/box.html).
- */
-class _MarginCssRect extends CssRect {
-  _MarginCssRect(element) : super(element);
-  num get height =>
-      _element.offsetHeight + _addOrSubtractToBoxModel(_HEIGHT, _MARGIN);
-  num get width =>
-      _element.offsetWidth + _addOrSubtractToBoxModel(_WIDTH, _MARGIN);
-
-  num get left =>
-      _element.getBoundingClientRect().left -
-      _addOrSubtractToBoxModel(['left'], _MARGIN);
-  num get top =>
-      _element.getBoundingClientRect().top -
-      _addOrSubtractToBoxModel(['top'], _MARGIN);
-}
-
-/**
- * A class for representing CSS dimensions.
- *
- * In contrast to the more general purpose [Rectangle] class, this class's
- * values are mutable, so one can change the height of an element
- * programmatically.
- *
- * _Important_ _note_: use of these methods will perform CSS calculations that
- * can trigger a browser reflow. Therefore, use of these properties _during_ an
- * animation frame is discouraged. See also:
- * [Browser Reflow](https://developers.google.com/speed/articles/reflow)
- */
-abstract class CssRect implements Rectangle<num> {
-  Element _element;
-
-  CssRect(this._element);
-
-  num get left;
-
-  num get top;
-
-  /**
-   * The height of this rectangle.
-   *
-   * This is equivalent to the `height` function in jQuery and the calculated
-   * `height` CSS value, converted to a dimensionless num in pixels. Unlike
-   * [getBoundingClientRect], `height` will return the same numerical width if
-   * the element is hidden or not.
-   */
-  num get height;
-
-  /**
-   * The width of this rectangle.
-   *
-   * This is equivalent to the `width` function in jQuery and the calculated
-   * `width` CSS value, converted to a dimensionless num in pixels. Unlike
-   * [getBoundingClientRect], `width` will return the same numerical width if
-   * the element is hidden or not.
-   */
-  num get width;
-
-  /**
-   * Set the height to `newHeight`.
-   *
-   * newHeight can be either a [num] representing the height in pixels or a
-   * [Dimension] object. Values of newHeight that are less than zero are
-   * converted to effectively setting the height to 0. This is equivalent to the
-   * `height` function in jQuery and the calculated `height` CSS value,
-   * converted to a num in pixels.
-   *
-   * Note that only the content height can actually be set via this method.
-   */
-  set height(dynamic newHeight) {
-    throw new UnsupportedError("Can only set height for content rect.");
-  }
-
-  /**
-   * Set the current computed width in pixels of this element.
-   *
-   * newWidth can be either a [num] representing the width in pixels or a
-   * [Dimension] object. This is equivalent to the `width` function in jQuery
-   * and the calculated
-   * `width` CSS value, converted to a dimensionless num in pixels.
-   *
-   * Note that only the content width can be set via this method.
-   */
-  set width(dynamic newWidth) {
-    throw new UnsupportedError("Can only set width for content rect.");
-  }
-
-  /**
-   * Return a value that is used to modify the initial height or width
-   * measurement of an element. Depending on the value (ideally an enum) passed
-   * to augmentingMeasurement, we may need to add or subtract margin, padding,
-   * or border values, depending on the measurement we're trying to obtain.
-   */
-  num _addOrSubtractToBoxModel(
-      List<String> dimensions, String augmentingMeasurement) {
-    // getComputedStyle always returns pixel values (hence, computed), so we're
-    // always dealing with pixels in this method.
-    var styles = _element.getComputedStyle();
-
-    num val = 0;
-
-    for (String measurement in dimensions) {
-      // The border-box and default box model both exclude margin in the regular
-      // height/width calculation, so add it if we want it for this measurement.
-      if (augmentingMeasurement == _MARGIN) {
-        val += new Dimension.css(
-                styles.getPropertyValue('$augmentingMeasurement-$measurement'))
-            .value;
-      }
-
-      // The border-box includes padding and border, so remove it if we want
-      // just the content itself.
-      if (augmentingMeasurement == _CONTENT) {
-        val -= new Dimension.css(
-                styles.getPropertyValue('${_PADDING}-$measurement'))
-            .value;
-      }
-
-      // At this point, we don't wan't to augment with border or margin,
-      // so remove border.
-      if (augmentingMeasurement != _MARGIN) {
-        val -= new Dimension.css(
-                styles.getPropertyValue('border-${measurement}-width'))
-            .value;
-      }
-    }
-    return val;
-  }
-
-  // TODO(jacobr): these methods are duplicated from _RectangleBase in dart:math
-  // Ideally we would provide a RectangleMixin class that provides this
-  // implementation. In an ideal world we would exp
-  /** The x-coordinate of the right edge. */
-  num get right => left + width;
-  /** The y-coordinate of the bottom edge. */
-  num get bottom => top + height;
-
-  String toString() {
-    return 'Rectangle ($left, $top) $width x $height';
-  }
-
-  bool operator ==(other) =>
-      other is Rectangle &&
-      left == other.left &&
-      top == other.top &&
-      right == other.right &&
-      bottom == other.bottom;
-
-  int get hashCode => _JenkinsSmiHash.hash4(
-      left.hashCode, top.hashCode, right.hashCode, bottom.hashCode);
-
-  /**
-   * Computes the intersection of `this` and [other].
-   *
-   * The intersection of two axis-aligned rectangles, if any, is always another
-   * axis-aligned rectangle.
-   *
-   * Returns the intersection of this and `other`, or `null` if they don't
-   * intersect.
-   */
-  Rectangle<num>? intersection(Rectangle<num> other) {
-    var x0 = max(left, other.left);
-    var x1 = min(left + width, other.left + other.width);
-
-    if (x0 <= x1) {
-      var y0 = max(top, other.top);
-      var y1 = min(top + height, other.top + other.height);
-
-      if (y0 <= y1) {
-        return new Rectangle<num>(x0, y0, x1 - x0, y1 - y0);
-      }
-    }
-    return null;
-  }
-
-  /**
-   * Returns true if `this` intersects [other].
-   */
-  bool intersects(Rectangle<num> other) {
-    return (left <= other.left + other.width &&
-        other.left <= left + width &&
-        top <= other.top + other.height &&
-        other.top <= top + height);
-  }
-
-  /**
-   * Returns a new rectangle which completely contains `this` and [other].
-   */
-  Rectangle<num> boundingBox(Rectangle<num> other) {
-    var right = max(this.left + this.width, other.left + other.width);
-    var bottom = max(this.top + this.height, other.top + other.height);
-
-    var left = min(this.left, other.left);
-    var top = min(this.top, other.top);
-
-    return new Rectangle<num>(left, top, right - left, bottom - top);
-  }
-
-  /**
-   * Tests whether `this` entirely contains [another].
-   */
-  bool containsRectangle(Rectangle<num> another) {
-    return left <= another.left &&
-        left + width >= another.left + another.width &&
-        top <= another.top &&
-        top + height >= another.top + another.height;
-  }
-
-  /**
-   * Tests whether [another] is inside or along the edges of `this`.
-   */
-  bool containsPoint(Point<num> another) {
-    return another.x >= left &&
-        another.x <= left + width &&
-        another.y >= top &&
-        another.y <= top + height;
-  }
-
-  Point<num> get topLeft => new Point<num>(this.left, this.top);
-  Point<num> get topRight => new Point<num>(this.left + this.width, this.top);
-  Point<num> get bottomRight =>
-      new Point<num>(this.left + this.width, this.top + this.height);
-  Point<num> get bottomLeft =>
-      new Point<num>(this.left, this.top + this.height);
-}
-
-final _HEIGHT = ['top', 'bottom'];
-final _WIDTH = ['right', 'left'];
-final _CONTENT = 'content';
-final _PADDING = 'padding';
-final _MARGIN = 'margin';
diff --git a/tools/dom/nnbd_src/Dimension.dart b/tools/dom/nnbd_src/Dimension.dart
deleted file mode 100644
index 7ed02192..0000000
--- a/tools/dom/nnbd_src/Dimension.dart
+++ /dev/null
@@ -1,84 +0,0 @@
-part of html;
-
-/**
- * Class representing a
- * [length measurement](https://developer.mozilla.org/en-US/docs/Web/CSS/length)
- * in CSS.
- */
-class Dimension {
-  num _value;
-  String _unit;
-
-  /** Set this CSS Dimension to a percentage `value`. */
-  Dimension.percent(this._value) : _unit = '%';
-
-  /** Set this CSS Dimension to a pixel `value`. */
-  Dimension.px(this._value) : _unit = 'px';
-
-  /** Set this CSS Dimension to a pica `value`. */
-  Dimension.pc(this._value) : _unit = 'pc';
-
-  /** Set this CSS Dimension to a point `value`. */
-  Dimension.pt(this._value) : _unit = 'pt';
-
-  /** Set this CSS Dimension to an inch `value`. */
-  Dimension.inch(this._value) : _unit = 'in';
-
-  /** Set this CSS Dimension to a centimeter `value`. */
-  Dimension.cm(this._value) : _unit = 'cm';
-
-  /** Set this CSS Dimension to a millimeter `value`. */
-  Dimension.mm(this._value) : _unit = 'mm';
-
-  /**
-   * Set this CSS Dimension to the specified number of ems.
-   *
-   * 1em is equal to the current font size. (So 2ems is equal to double the font
-   * size). This is useful for producing website layouts that scale nicely with
-   * the user's desired font size.
-   */
-  Dimension.em(this._value) : _unit = 'em';
-
-  /**
-   * Set this CSS Dimension to the specified number of x-heights.
-   *
-   * One ex is equal to the x-height of a font's baseline to its mean line,
-   * generally the height of the letter "x" in the font, which is usually about
-   * half the font-size.
-   */
-  Dimension.ex(this._value) : _unit = 'ex';
-
-  /**
-   * Construct a Dimension object from the valid, simple CSS string `cssValue`
-   * that represents a distance measurement.
-   *
-   * This constructor is intended as a convenience method for working with
-   * simplistic CSS length measurements. Non-numeric values such as `auto` or
-   * `inherit` or invalid CSS will cause this constructor to throw a
-   * FormatError.
-   */
-  Dimension.css(String cssValue)
-      : _unit = '',
-        _value = 0 {
-    if (cssValue == '') cssValue = '0px';
-    if (cssValue.endsWith('%')) {
-      _unit = '%';
-    } else {
-      _unit = cssValue.substring(cssValue.length - 2);
-    }
-    if (cssValue.contains('.')) {
-      _value =
-          double.parse(cssValue.substring(0, cssValue.length - _unit.length));
-    } else {
-      _value = int.parse(cssValue.substring(0, cssValue.length - _unit.length));
-    }
-  }
-
-  /** Print out the CSS String representation of this value. */
-  String toString() {
-    return '${_value}${_unit}';
-  }
-
-  /** Return a unitless, numerical value of this CSS value. */
-  num get value => this._value;
-}
diff --git a/tools/dom/nnbd_src/EventListener.dart b/tools/dom/nnbd_src/EventListener.dart
deleted file mode 100644
index 60b29f1..0000000
--- a/tools/dom/nnbd_src/EventListener.dart
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of html;
-
-typedef EventListener(Event event);
diff --git a/tools/dom/nnbd_src/EventStreamProvider.dart b/tools/dom/nnbd_src/EventStreamProvider.dart
deleted file mode 100644
index fe01be9..0000000
--- a/tools/dom/nnbd_src/EventStreamProvider.dart
+++ /dev/null
@@ -1,461 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of html;
-
-/**
- * A factory to expose DOM events as Streams.
- */
-class EventStreamProvider<T extends Event> {
-  final String _eventType;
-
-  const EventStreamProvider(this._eventType);
-
-  /**
-   * Gets a [Stream] for this event type, on the specified target.
-   *
-   * This will always return a broadcast stream so multiple listeners can be
-   * used simultaneously.
-   *
-   * This may be used to capture DOM events:
-   *
-   *     Element.keyDownEvent.forTarget(element, useCapture: true).listen(...);
-   *
-   *     // Alternate method:
-   *     Element.keyDownEvent.forTarget(element).capture(...);
-   *
-   * Or for listening to an event which will bubble through the DOM tree:
-   *
-   *     MediaElement.pauseEvent.forTarget(document.body).listen(...);
-   *
-   * See also:
-   *
-   * * [EventTarget.addEventListener](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener)
-   *   from MDN.
-   */
-  Stream<T> forTarget(EventTarget? e, {bool useCapture: false}) =>
-      new _EventStream<T>(e, _eventType, useCapture);
-
-  /**
-   * Gets an [ElementEventStream] for this event type, on the specified element.
-   *
-   * This will always return a broadcast stream so multiple listeners can be
-   * used simultaneously.
-   *
-   * This may be used to capture DOM events:
-   *
-   *     Element.keyDownEvent.forElement(element, useCapture: true).listen(...);
-   *
-   *     // Alternate method:
-   *     Element.keyDownEvent.forElement(element).capture(...);
-   *
-   * Or for listening to an event which will bubble through the DOM tree:
-   *
-   *     MediaElement.pauseEvent.forElement(document.body).listen(...);
-   *
-   * See also:
-   *
-   * * [EventTarget.addEventListener](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener)
-   *   from MDN.
-   */
-  ElementStream<T> forElement(Element e, {bool useCapture: false}) {
-    return new _ElementEventStreamImpl<T>(e, _eventType, useCapture);
-  }
-
-  /**
-   * Gets an [ElementEventStream] for this event type, on the list of elements.
-   *
-   * This will always return a broadcast stream so multiple listeners can be
-   * used simultaneously.
-   *
-   * This may be used to capture DOM events:
-   *
-   *     Element.keyDownEvent._forElementList(element, useCapture: true).listen(...);
-   *
-   * See also:
-   *
-   * * [EventTarget.addEventListener](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener)
-   *   from MDN.
-   */
-  ElementStream<T> _forElementList(ElementList<Element> e,
-      {bool useCapture: false}) {
-    return new _ElementListEventStreamImpl<T>(e, _eventType, useCapture);
-  }
-
-  /**
-   * Gets the type of the event which this would listen for on the specified
-   * event target.
-   *
-   * The target is necessary because some browsers may use different event names
-   * for the same purpose and the target allows differentiating browser support.
-   */
-  String getEventType(EventTarget target) {
-    return _eventType;
-  }
-}
-
-/** A specialized Stream available to [Element]s to enable event delegation. */
-abstract class ElementStream<T extends Event> implements Stream<T> {
-  /**
-   * Return a stream that only fires when the particular event fires for
-   * elements matching the specified CSS selector.
-   *
-   * This is the Dart equivalent to jQuery's
-   * [delegate](http://api.jquery.com/delegate/).
-   */
-  Stream<T> matches(String selector);
-
-  /**
-   * Adds a capturing subscription to this stream.
-   *
-   * If the target of the event is a descendant of the element from which this
-   * stream derives then [onData] is called before the event propagates down to
-   * the target. This is the opposite of bubbling behavior, where the event
-   * is first processed for the event target and then bubbles upward.
-   *
-   * ## Other resources
-   *
-   * * [Event Capture](http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-flow-capture)
-   *   from the W3C DOM Events specification.
-   */
-  StreamSubscription<T> capture(void onData(T event));
-}
-
-/**
- * Adapter for exposing DOM events as Dart streams.
- */
-class _EventStream<T extends Event> extends Stream<T> {
-  final EventTarget? _target;
-  final String _eventType;
-  final bool _useCapture;
-
-  _EventStream(this._target, this._eventType, this._useCapture);
-
-  // DOM events are inherently multi-subscribers.
-  Stream<T> asBroadcastStream(
-          {void onListen(StreamSubscription<T> subscription)?,
-          void onCancel(StreamSubscription<T> subscription)?}) =>
-      this;
-  bool get isBroadcast => true;
-
-  // TODO(9757): Inlining should be smart and inline only when inlining would
-  // enable scalar replacement of an immediately allocated receiver.
-  @pragma('dart2js:tryInline')
-  StreamSubscription<T> listen(void onData(T event)?,
-      {Function? onError, void onDone()?, bool? cancelOnError}) {
-    return new _EventStreamSubscription<T>(
-        this._target, this._eventType, onData, this._useCapture);
-  }
-}
-
-bool _matchesWithAncestors(Event event, String selector) {
-  var target = event.target;
-  return target is Element ? target.matchesWithAncestors(selector) : false;
-}
-
-/**
- * Adapter for exposing DOM Element events as streams, while also allowing
- * event delegation.
- */
-class _ElementEventStreamImpl<T extends Event> extends _EventStream<T>
-    implements ElementStream<T> {
-  _ElementEventStreamImpl(target, eventType, useCapture)
-      : super(target, eventType, useCapture);
-
-  Stream<T> matches(String selector) =>
-      this.where((event) => _matchesWithAncestors(event, selector)).map((e) {
-        e._selector = selector;
-        return e;
-      });
-
-  StreamSubscription<T> capture(void onData(T event)) =>
-      new _EventStreamSubscription<T>(
-          this._target, this._eventType, onData, true);
-}
-
-/**
- * Adapter for exposing events on a collection of DOM Elements as streams,
- * while also allowing event delegation.
- */
-class _ElementListEventStreamImpl<T extends Event> extends Stream<T>
-    implements ElementStream<T> {
-  final Iterable<Element> _targetList;
-  final bool _useCapture;
-  final String _eventType;
-
-  _ElementListEventStreamImpl(
-      this._targetList, this._eventType, this._useCapture);
-
-  Stream<T> matches(String selector) =>
-      this.where((event) => _matchesWithAncestors(event, selector)).map((e) {
-        e._selector = selector;
-        return e;
-      });
-
-  // Delegate all regular Stream behavior to a wrapped Stream.
-  StreamSubscription<T> listen(void onData(T event)?,
-      {Function? onError, void onDone()?, bool? cancelOnError}) {
-    var pool = new _StreamPool<T>.broadcast();
-    for (var target in _targetList) {
-      pool.add(new _EventStream<T>(target, _eventType, _useCapture));
-    }
-    return pool.stream.listen(onData,
-        onError: onError, onDone: onDone, cancelOnError: cancelOnError);
-  }
-
-  StreamSubscription<T> capture(void onData(T event)) {
-    var pool = new _StreamPool<T>.broadcast();
-    for (var target in _targetList) {
-      pool.add(new _EventStream<T>(target, _eventType, true));
-    }
-    return pool.stream.listen(onData);
-  }
-
-  Stream<T> asBroadcastStream(
-          {void onListen(StreamSubscription<T> subscription)?,
-          void onCancel(StreamSubscription<T> subscription)?}) =>
-      this;
-  bool get isBroadcast => true;
-}
-
-// We would like this to just be EventListener<T> but that typdef cannot
-// use generics until dartbug/26276 is fixed.
-typedef _EventListener<T extends Event>(T event);
-
-class _EventStreamSubscription<T extends Event> extends StreamSubscription<T> {
-  int _pauseCount = 0;
-  EventTarget? _target;
-  final String _eventType;
-  EventListener? _onData;
-  final bool _useCapture;
-
-  // TODO(leafp): It would be better to write this as
-  // _onData = onData == null ? null :
-  //   onData is void Function(Event)
-  //     ? _wrapZone<Event>(onData)
-  //     : _wrapZone<Event>((e) => onData(e as T))
-  // In order to support existing tests which pass the wrong type of events but
-  // use a more general listener, without causing as much slowdown for things
-  // which are typed correctly.  But this currently runs afoul of restrictions
-  // on is checks for compatibility with the VM.
-  _EventStreamSubscription(
-      this._target, this._eventType, void onData(T event)?, this._useCapture)
-      : _onData = onData == null
-            ? null
-            : _wrapZone<Event>((e) => (onData as dynamic)(e)) {
-    _tryResume();
-  }
-
-  Future cancel() {
-    // Check for strong mode. This function can no longer return null in strong
-    // mode, so only return null in weak mode to preserve synchronous timing.
-    // See issue 41653 for more details.
-    dynamic emptyFuture =
-        typeAcceptsNull<Event>() ? null : Future<void>.value();
-    if (_canceled) return emptyFuture as Future;
-
-    _unlisten();
-    // Clear out the target to indicate this is complete.
-    _target = null;
-    _onData = null;
-    return emptyFuture as Future;
-  }
-
-  bool get _canceled => _target == null;
-
-  void onData(void handleData(T event)?) {
-    if (_canceled) {
-      throw new StateError("Subscription has been canceled.");
-    }
-    // Remove current event listener.
-    _unlisten();
-    _onData = handleData == null
-        ? null
-        : _wrapZone<Event>((e) => (handleData as dynamic)(e));
-    _tryResume();
-  }
-
-  /// Has no effect.
-  void onError(Function? handleError) {}
-
-  /// Has no effect.
-  void onDone(void handleDone()?) {}
-
-  void pause([Future? resumeSignal]) {
-    if (_canceled) return;
-    ++_pauseCount;
-    _unlisten();
-
-    if (resumeSignal != null) {
-      resumeSignal.whenComplete(resume);
-    }
-  }
-
-  bool get isPaused => _pauseCount > 0;
-
-  void resume() {
-    if (_canceled || !isPaused) return;
-    --_pauseCount;
-    _tryResume();
-  }
-
-  void _tryResume() {
-    if (_onData != null && !isPaused) {
-      _target!.addEventListener(_eventType, _onData, _useCapture);
-    }
-  }
-
-  void _unlisten() {
-    if (_onData != null) {
-      _target!.removeEventListener(_eventType, _onData, _useCapture);
-    }
-  }
-
-  Future<E> asFuture<E>([E? futureValue]) {
-    // We just need a future that will never succeed or fail.
-    var completer = new Completer<E>();
-    return completer.future;
-  }
-}
-
-/**
- * A stream of custom events, which enables the user to "fire" (add) their own
- * custom events to a stream.
- */
-abstract class CustomStream<T extends Event> implements Stream<T> {
-  /**
-   * Add the following custom event to the stream for dispatching to interested
-   * listeners.
-   */
-  void add(T event);
-}
-
-class _CustomEventStreamImpl<T extends Event> extends Stream<T>
-    implements CustomStream<T> {
-  StreamController<T> _streamController;
-  /** The type of event this stream is providing (e.g. "keydown"). */
-  String _type;
-
-  _CustomEventStreamImpl(String type)
-      : _type = type,
-        _streamController = new StreamController.broadcast(sync: true);
-
-  // Delegate all regular Stream behavior to our wrapped Stream.
-  StreamSubscription<T> listen(void onData(T event)?,
-      {Function? onError, void onDone()?, bool? cancelOnError}) {
-    return _streamController.stream.listen(onData,
-        onError: onError, onDone: onDone, cancelOnError: cancelOnError);
-  }
-
-  Stream<T> asBroadcastStream(
-          {void onListen(StreamSubscription<T> subscription)?,
-          void onCancel(StreamSubscription<T> subscription)?}) =>
-      _streamController.stream;
-
-  bool get isBroadcast => true;
-
-  void add(T event) {
-    if (event.type == _type) _streamController.add(event);
-  }
-}
-
-class _CustomKeyEventStreamImpl extends _CustomEventStreamImpl<KeyEvent>
-    implements CustomStream<KeyEvent> {
-  _CustomKeyEventStreamImpl(String type) : super(type);
-
-  void add(KeyEvent event) {
-    if (event.type == _type) {
-      event.currentTarget!.dispatchEvent(event._parent);
-      _streamController.add(event);
-    }
-  }
-}
-
-/**
- * A pool of streams whose events are unified and emitted through a central
- * stream.
- */
-// TODO (efortuna): Remove this when Issue 12218 is addressed.
-class _StreamPool<T> {
-  StreamController<T>? _controller;
-
-  /// Subscriptions to the streams that make up the pool.
-  var _subscriptions = new Map<Stream<T>, StreamSubscription<T>>();
-
-  /**
-   * Creates a new stream pool where [stream] can be listened to more than
-   * once.
-   *
-   * Any events from buffered streams in the pool will be emitted immediately,
-   * regardless of whether [stream] has any subscribers.
-   */
-  _StreamPool.broadcast() {
-    _controller =
-        new StreamController<T>.broadcast(sync: true, onCancel: close);
-  }
-
-  /**
-   * The stream through which all events from streams in the pool are emitted.
-   */
-  Stream<T> get stream => _controller!.stream;
-
-  /**
-   * Adds [stream] as a member of this pool.
-   *
-   * Any events from [stream] will be emitted through [this.stream]. If
-   * [stream] is sync, they'll be emitted synchronously; if [stream] is async,
-   * they'll be emitted asynchronously.
-   */
-  void add(Stream<T> stream) {
-    if (_subscriptions.containsKey(stream)) return;
-    _subscriptions[stream] = stream.listen(_controller!.add,
-        onError: _controller!.addError, onDone: () => remove(stream));
-  }
-
-  /** Removes [stream] as a member of this pool. */
-  void remove(Stream<T> stream) {
-    var subscription = _subscriptions.remove(stream);
-    if (subscription != null) subscription.cancel();
-  }
-
-  /** Removes all streams from this pool and closes [stream]. */
-  void close() {
-    for (var subscription in _subscriptions.values) {
-      subscription.cancel();
-    }
-    _subscriptions.clear();
-    _controller!.close();
-  }
-}
-
-/**
- * A factory to expose DOM events as streams, where the DOM event name has to
- * be determined on the fly (for example, mouse wheel events).
- */
-class _CustomEventStreamProvider<T extends Event>
-    implements EventStreamProvider<T> {
-  final _eventTypeGetter;
-  const _CustomEventStreamProvider(this._eventTypeGetter);
-
-  Stream<T> forTarget(EventTarget? e, {bool useCapture: false}) {
-    return new _EventStream<T>(e, _eventTypeGetter(e), useCapture);
-  }
-
-  ElementStream<T> forElement(Element e, {bool useCapture: false}) {
-    return new _ElementEventStreamImpl<T>(e, _eventTypeGetter(e), useCapture);
-  }
-
-  ElementStream<T> _forElementList(ElementList<Element> e,
-      {bool useCapture: false}) {
-    return new _ElementListEventStreamImpl<T>(
-        e, _eventTypeGetter(e), useCapture);
-  }
-
-  String getEventType(EventTarget target) {
-    return _eventTypeGetter(target);
-  }
-
-  String get _eventType =>
-      throw new UnsupportedError('Access type through getEventType method.');
-}
diff --git a/tools/dom/nnbd_src/Html5NodeValidator.dart b/tools/dom/nnbd_src/Html5NodeValidator.dart
deleted file mode 100644
index e6bdede..0000000
--- a/tools/dom/nnbd_src/Html5NodeValidator.dart
+++ /dev/null
@@ -1,449 +0,0 @@
-// DO NOT EDIT- this file is generated from running tool/generator.sh.
-
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of dart.dom.html;
-
-/**
- * A Dart DOM validator generated from Caja whitelists.
- *
- * This contains a whitelist of known HTML tagNames and attributes and will only
- * accept known good values.
- *
- * See also:
- *
- * * <https://code.google.com/p/google-caja/wiki/CajaWhitelists>
- */
-class _Html5NodeValidator implements NodeValidator {
-  static final Set<String> _allowedElements = new Set.from([
-    'A',
-    'ABBR',
-    'ACRONYM',
-    'ADDRESS',
-    'AREA',
-    'ARTICLE',
-    'ASIDE',
-    'AUDIO',
-    'B',
-    'BDI',
-    'BDO',
-    'BIG',
-    'BLOCKQUOTE',
-    'BR',
-    'BUTTON',
-    'CANVAS',
-    'CAPTION',
-    'CENTER',
-    'CITE',
-    'CODE',
-    'COL',
-    'COLGROUP',
-    'COMMAND',
-    'DATA',
-    'DATALIST',
-    'DD',
-    'DEL',
-    'DETAILS',
-    'DFN',
-    'DIR',
-    'DIV',
-    'DL',
-    'DT',
-    'EM',
-    'FIELDSET',
-    'FIGCAPTION',
-    'FIGURE',
-    'FONT',
-    'FOOTER',
-    'FORM',
-    'H1',
-    'H2',
-    'H3',
-    'H4',
-    'H5',
-    'H6',
-    'HEADER',
-    'HGROUP',
-    'HR',
-    'I',
-    'IFRAME',
-    'IMG',
-    'INPUT',
-    'INS',
-    'KBD',
-    'LABEL',
-    'LEGEND',
-    'LI',
-    'MAP',
-    'MARK',
-    'MENU',
-    'METER',
-    'NAV',
-    'NOBR',
-    'OL',
-    'OPTGROUP',
-    'OPTION',
-    'OUTPUT',
-    'P',
-    'PRE',
-    'PROGRESS',
-    'Q',
-    'S',
-    'SAMP',
-    'SECTION',
-    'SELECT',
-    'SMALL',
-    'SOURCE',
-    'SPAN',
-    'STRIKE',
-    'STRONG',
-    'SUB',
-    'SUMMARY',
-    'SUP',
-    'TABLE',
-    'TBODY',
-    'TD',
-    'TEXTAREA',
-    'TFOOT',
-    'TH',
-    'THEAD',
-    'TIME',
-    'TR',
-    'TRACK',
-    'TT',
-    'U',
-    'UL',
-    'VAR',
-    'VIDEO',
-    'WBR',
-  ]);
-
-  static const _standardAttributes = const <String>[
-    '*::class',
-    '*::dir',
-    '*::draggable',
-    '*::hidden',
-    '*::id',
-    '*::inert',
-    '*::itemprop',
-    '*::itemref',
-    '*::itemscope',
-    '*::lang',
-    '*::spellcheck',
-    '*::title',
-    '*::translate',
-    'A::accesskey',
-    'A::coords',
-    'A::hreflang',
-    'A::name',
-    'A::shape',
-    'A::tabindex',
-    'A::target',
-    'A::type',
-    'AREA::accesskey',
-    'AREA::alt',
-    'AREA::coords',
-    'AREA::nohref',
-    'AREA::shape',
-    'AREA::tabindex',
-    'AREA::target',
-    'AUDIO::controls',
-    'AUDIO::loop',
-    'AUDIO::mediagroup',
-    'AUDIO::muted',
-    'AUDIO::preload',
-    'BDO::dir',
-    'BODY::alink',
-    'BODY::bgcolor',
-    'BODY::link',
-    'BODY::text',
-    'BODY::vlink',
-    'BR::clear',
-    'BUTTON::accesskey',
-    'BUTTON::disabled',
-    'BUTTON::name',
-    'BUTTON::tabindex',
-    'BUTTON::type',
-    'BUTTON::value',
-    'CANVAS::height',
-    'CANVAS::width',
-    'CAPTION::align',
-    'COL::align',
-    'COL::char',
-    'COL::charoff',
-    'COL::span',
-    'COL::valign',
-    'COL::width',
-    'COLGROUP::align',
-    'COLGROUP::char',
-    'COLGROUP::charoff',
-    'COLGROUP::span',
-    'COLGROUP::valign',
-    'COLGROUP::width',
-    'COMMAND::checked',
-    'COMMAND::command',
-    'COMMAND::disabled',
-    'COMMAND::label',
-    'COMMAND::radiogroup',
-    'COMMAND::type',
-    'DATA::value',
-    'DEL::datetime',
-    'DETAILS::open',
-    'DIR::compact',
-    'DIV::align',
-    'DL::compact',
-    'FIELDSET::disabled',
-    'FONT::color',
-    'FONT::face',
-    'FONT::size',
-    'FORM::accept',
-    'FORM::autocomplete',
-    'FORM::enctype',
-    'FORM::method',
-    'FORM::name',
-    'FORM::novalidate',
-    'FORM::target',
-    'FRAME::name',
-    'H1::align',
-    'H2::align',
-    'H3::align',
-    'H4::align',
-    'H5::align',
-    'H6::align',
-    'HR::align',
-    'HR::noshade',
-    'HR::size',
-    'HR::width',
-    'HTML::version',
-    'IFRAME::align',
-    'IFRAME::frameborder',
-    'IFRAME::height',
-    'IFRAME::marginheight',
-    'IFRAME::marginwidth',
-    'IFRAME::width',
-    'IMG::align',
-    'IMG::alt',
-    'IMG::border',
-    'IMG::height',
-    'IMG::hspace',
-    'IMG::ismap',
-    'IMG::name',
-    'IMG::usemap',
-    'IMG::vspace',
-    'IMG::width',
-    'INPUT::accept',
-    'INPUT::accesskey',
-    'INPUT::align',
-    'INPUT::alt',
-    'INPUT::autocomplete',
-    'INPUT::autofocus',
-    'INPUT::checked',
-    'INPUT::disabled',
-    'INPUT::inputmode',
-    'INPUT::ismap',
-    'INPUT::list',
-    'INPUT::max',
-    'INPUT::maxlength',
-    'INPUT::min',
-    'INPUT::multiple',
-    'INPUT::name',
-    'INPUT::placeholder',
-    'INPUT::readonly',
-    'INPUT::required',
-    'INPUT::size',
-    'INPUT::step',
-    'INPUT::tabindex',
-    'INPUT::type',
-    'INPUT::usemap',
-    'INPUT::value',
-    'INS::datetime',
-    'KEYGEN::disabled',
-    'KEYGEN::keytype',
-    'KEYGEN::name',
-    'LABEL::accesskey',
-    'LABEL::for',
-    'LEGEND::accesskey',
-    'LEGEND::align',
-    'LI::type',
-    'LI::value',
-    'LINK::sizes',
-    'MAP::name',
-    'MENU::compact',
-    'MENU::label',
-    'MENU::type',
-    'METER::high',
-    'METER::low',
-    'METER::max',
-    'METER::min',
-    'METER::value',
-    'OBJECT::typemustmatch',
-    'OL::compact',
-    'OL::reversed',
-    'OL::start',
-    'OL::type',
-    'OPTGROUP::disabled',
-    'OPTGROUP::label',
-    'OPTION::disabled',
-    'OPTION::label',
-    'OPTION::selected',
-    'OPTION::value',
-    'OUTPUT::for',
-    'OUTPUT::name',
-    'P::align',
-    'PRE::width',
-    'PROGRESS::max',
-    'PROGRESS::min',
-    'PROGRESS::value',
-    'SELECT::autocomplete',
-    'SELECT::disabled',
-    'SELECT::multiple',
-    'SELECT::name',
-    'SELECT::required',
-    'SELECT::size',
-    'SELECT::tabindex',
-    'SOURCE::type',
-    'TABLE::align',
-    'TABLE::bgcolor',
-    'TABLE::border',
-    'TABLE::cellpadding',
-    'TABLE::cellspacing',
-    'TABLE::frame',
-    'TABLE::rules',
-    'TABLE::summary',
-    'TABLE::width',
-    'TBODY::align',
-    'TBODY::char',
-    'TBODY::charoff',
-    'TBODY::valign',
-    'TD::abbr',
-    'TD::align',
-    'TD::axis',
-    'TD::bgcolor',
-    'TD::char',
-    'TD::charoff',
-    'TD::colspan',
-    'TD::headers',
-    'TD::height',
-    'TD::nowrap',
-    'TD::rowspan',
-    'TD::scope',
-    'TD::valign',
-    'TD::width',
-    'TEXTAREA::accesskey',
-    'TEXTAREA::autocomplete',
-    'TEXTAREA::cols',
-    'TEXTAREA::disabled',
-    'TEXTAREA::inputmode',
-    'TEXTAREA::name',
-    'TEXTAREA::placeholder',
-    'TEXTAREA::readonly',
-    'TEXTAREA::required',
-    'TEXTAREA::rows',
-    'TEXTAREA::tabindex',
-    'TEXTAREA::wrap',
-    'TFOOT::align',
-    'TFOOT::char',
-    'TFOOT::charoff',
-    'TFOOT::valign',
-    'TH::abbr',
-    'TH::align',
-    'TH::axis',
-    'TH::bgcolor',
-    'TH::char',
-    'TH::charoff',
-    'TH::colspan',
-    'TH::headers',
-    'TH::height',
-    'TH::nowrap',
-    'TH::rowspan',
-    'TH::scope',
-    'TH::valign',
-    'TH::width',
-    'THEAD::align',
-    'THEAD::char',
-    'THEAD::charoff',
-    'THEAD::valign',
-    'TR::align',
-    'TR::bgcolor',
-    'TR::char',
-    'TR::charoff',
-    'TR::valign',
-    'TRACK::default',
-    'TRACK::kind',
-    'TRACK::label',
-    'TRACK::srclang',
-    'UL::compact',
-    'UL::type',
-    'VIDEO::controls',
-    'VIDEO::height',
-    'VIDEO::loop',
-    'VIDEO::mediagroup',
-    'VIDEO::muted',
-    'VIDEO::preload',
-    'VIDEO::width',
-  ];
-
-  static const _uriAttributes = const <String>[
-    'A::href',
-    'AREA::href',
-    'BLOCKQUOTE::cite',
-    'BODY::background',
-    'COMMAND::icon',
-    'DEL::cite',
-    'FORM::action',
-    'IMG::src',
-    'INPUT::src',
-    'INS::cite',
-    'Q::cite',
-    'VIDEO::poster',
-  ];
-
-  final UriPolicy uriPolicy;
-
-  static final Map<String, Function> _attributeValidators = {};
-
-  /**
-   * All known URI attributes will be validated against the UriPolicy, if
-   * [uriPolicy] is null then a default UriPolicy will be used.
-   */
-  _Html5NodeValidator({UriPolicy? uriPolicy})
-      : uriPolicy = uriPolicy ?? UriPolicy() {
-    if (_attributeValidators.isEmpty) {
-      for (var attr in _standardAttributes) {
-        _attributeValidators[attr] = _standardAttributeValidator;
-      }
-
-      for (var attr in _uriAttributes) {
-        _attributeValidators[attr] = _uriAttributeValidator;
-      }
-    }
-  }
-
-  bool allowsElement(Element element) {
-    return _allowedElements.contains(Element._safeTagName(element));
-  }
-
-  bool allowsAttribute(Element element, String attributeName, String value) {
-    var tagName = Element._safeTagName(element);
-    var validator = _attributeValidators['$tagName::$attributeName'];
-    if (validator == null) {
-      validator = _attributeValidators['*::$attributeName'];
-    }
-    if (validator == null) {
-      return false;
-    }
-    return validator(element, attributeName, value, this);
-  }
-
-  static bool _standardAttributeValidator(Element element, String attributeName,
-      String value, _Html5NodeValidator context) {
-    return true;
-  }
-
-  static bool _uriAttributeValidator(Element element, String attributeName,
-      String value, _Html5NodeValidator context) {
-    return context.uriPolicy.allowsUri(value);
-  }
-}
diff --git a/tools/dom/nnbd_src/ImmutableListMixin.dart b/tools/dom/nnbd_src/ImmutableListMixin.dart
deleted file mode 100644
index 9910ebe..0000000
--- a/tools/dom/nnbd_src/ImmutableListMixin.dart
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of dart.dom.html;
-
-abstract class ImmutableListMixin<E> implements List<E> {
-  // From Iterable<$E>:
-  Iterator<E> get iterator {
-    // Note: NodeLists are not fixed size. And most probably length shouldn't
-    // be cached in both iterator _and_ forEach method. For now caching it
-    // for consistency.
-    return new FixedSizeListIterator<E>(this);
-  }
-
-  // From List<E>:
-  void add(E value) {
-    throw new UnsupportedError("Cannot add to immutable List.");
-  }
-
-  void addAll(Iterable<E> iterable) {
-    throw new UnsupportedError("Cannot add to immutable List.");
-  }
-
-  void sort([int compare(E a, E b)?]) {
-    throw new UnsupportedError("Cannot sort immutable List.");
-  }
-
-  void shuffle([Random? random]) {
-    throw new UnsupportedError("Cannot shuffle immutable List.");
-  }
-
-  void insert(int index, E element) {
-    throw new UnsupportedError("Cannot add to immutable List.");
-  }
-
-  void insertAll(int index, Iterable<E> iterable) {
-    throw new UnsupportedError("Cannot add to immutable List.");
-  }
-
-  void setAll(int index, Iterable<E> iterable) {
-    throw new UnsupportedError("Cannot modify an immutable List.");
-  }
-
-  E removeAt(int pos) {
-    throw new UnsupportedError("Cannot remove from immutable List.");
-  }
-
-  E removeLast() {
-    throw new UnsupportedError("Cannot remove from immutable List.");
-  }
-
-  bool remove(Object? object) {
-    throw new UnsupportedError("Cannot remove from immutable List.");
-  }
-
-  void removeWhere(bool test(E element)) {
-    throw new UnsupportedError("Cannot remove from immutable List.");
-  }
-
-  void retainWhere(bool test(E element)) {
-    throw new UnsupportedError("Cannot remove from immutable List.");
-  }
-
-  void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {
-    throw new UnsupportedError("Cannot setRange on immutable List.");
-  }
-
-  void removeRange(int start, int end) {
-    throw new UnsupportedError("Cannot removeRange on immutable List.");
-  }
-
-  void replaceRange(int start, int end, Iterable<E> iterable) {
-    throw new UnsupportedError("Cannot modify an immutable List.");
-  }
-
-  void fillRange(int start, int end, [E? fillValue]) {
-    throw new UnsupportedError("Cannot modify an immutable List.");
-  }
-}
diff --git a/tools/dom/nnbd_src/KeyCode.dart b/tools/dom/nnbd_src/KeyCode.dart
deleted file mode 100644
index a51d062..0000000
--- a/tools/dom/nnbd_src/KeyCode.dart
+++ /dev/null
@@ -1,331 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of html;
-
-/**
- * Defines the keycode values for keys that are returned by
- * KeyboardEvent.keyCode.
- *
- * Important note: There is substantial divergence in how different browsers
- * handle keycodes and their variants in different locales/keyboard layouts. We
- * provide these constants to help make code processing keys more readable.
- */
-abstract class KeyCode {
-  // These constant names were borrowed from Closure's Keycode enumeration
-  // class.
-  // https://github.com/google/closure-library/blob/master/closure/goog/events/keycodes.js
-  static const int WIN_KEY_FF_LINUX = 0;
-  static const int MAC_ENTER = 3;
-  static const int BACKSPACE = 8;
-  static const int TAB = 9;
-  /** NUM_CENTER is also NUMLOCK for FF and Safari on Mac. */
-  static const int NUM_CENTER = 12;
-  static const int ENTER = 13;
-  static const int SHIFT = 16;
-  static const int CTRL = 17;
-  static const int ALT = 18;
-  static const int PAUSE = 19;
-  static const int CAPS_LOCK = 20;
-  static const int ESC = 27;
-  static const int SPACE = 32;
-  static const int PAGE_UP = 33;
-  static const int PAGE_DOWN = 34;
-  static const int END = 35;
-  static const int HOME = 36;
-  static const int LEFT = 37;
-  static const int UP = 38;
-  static const int RIGHT = 39;
-  static const int DOWN = 40;
-  static const int NUM_NORTH_EAST = 33;
-  static const int NUM_SOUTH_EAST = 34;
-  static const int NUM_SOUTH_WEST = 35;
-  static const int NUM_NORTH_WEST = 36;
-  static const int NUM_WEST = 37;
-  static const int NUM_NORTH = 38;
-  static const int NUM_EAST = 39;
-  static const int NUM_SOUTH = 40;
-  static const int PRINT_SCREEN = 44;
-  static const int INSERT = 45;
-  static const int NUM_INSERT = 45;
-  static const int DELETE = 46;
-  static const int NUM_DELETE = 46;
-  static const int ZERO = 48;
-  static const int ONE = 49;
-  static const int TWO = 50;
-  static const int THREE = 51;
-  static const int FOUR = 52;
-  static const int FIVE = 53;
-  static const int SIX = 54;
-  static const int SEVEN = 55;
-  static const int EIGHT = 56;
-  static const int NINE = 57;
-  static const int FF_SEMICOLON = 59;
-  static const int FF_EQUALS = 61;
-  /**
-   * CAUTION: The question mark is for US-keyboard layouts. It varies
-   * for other locales and keyboard layouts.
-   */
-  static const int QUESTION_MARK = 63;
-  static const int A = 65;
-  static const int B = 66;
-  static const int C = 67;
-  static const int D = 68;
-  static const int E = 69;
-  static const int F = 70;
-  static const int G = 71;
-  static const int H = 72;
-  static const int I = 73;
-  static const int J = 74;
-  static const int K = 75;
-  static const int L = 76;
-  static const int M = 77;
-  static const int N = 78;
-  static const int O = 79;
-  static const int P = 80;
-  static const int Q = 81;
-  static const int R = 82;
-  static const int S = 83;
-  static const int T = 84;
-  static const int U = 85;
-  static const int V = 86;
-  static const int W = 87;
-  static const int X = 88;
-  static const int Y = 89;
-  static const int Z = 90;
-  static const int META = 91;
-  static const int WIN_KEY_LEFT = 91;
-  static const int WIN_KEY_RIGHT = 92;
-  static const int CONTEXT_MENU = 93;
-  static const int NUM_ZERO = 96;
-  static const int NUM_ONE = 97;
-  static const int NUM_TWO = 98;
-  static const int NUM_THREE = 99;
-  static const int NUM_FOUR = 100;
-  static const int NUM_FIVE = 101;
-  static const int NUM_SIX = 102;
-  static const int NUM_SEVEN = 103;
-  static const int NUM_EIGHT = 104;
-  static const int NUM_NINE = 105;
-  static const int NUM_MULTIPLY = 106;
-  static const int NUM_PLUS = 107;
-  static const int NUM_MINUS = 109;
-  static const int NUM_PERIOD = 110;
-  static const int NUM_DIVISION = 111;
-  static const int F1 = 112;
-  static const int F2 = 113;
-  static const int F3 = 114;
-  static const int F4 = 115;
-  static const int F5 = 116;
-  static const int F6 = 117;
-  static const int F7 = 118;
-  static const int F8 = 119;
-  static const int F9 = 120;
-  static const int F10 = 121;
-  static const int F11 = 122;
-  static const int F12 = 123;
-  static const int NUMLOCK = 144;
-  static const int SCROLL_LOCK = 145;
-
-  // OS-specific media keys like volume controls and browser controls.
-  static const int FIRST_MEDIA_KEY = 166;
-  static const int LAST_MEDIA_KEY = 183;
-
-  /**
-   * CAUTION: This constant requires localization for other locales and keyboard
-   * layouts.
-   */
-  static const int SEMICOLON = 186;
-  /**
-   * CAUTION: This constant requires localization for other locales and keyboard
-   * layouts.
-   */
-  static const int DASH = 189;
-  /**
-   * CAUTION: This constant requires localization for other locales and keyboard
-   * layouts.
-   */
-  static const int EQUALS = 187;
-  /**
-   * CAUTION: This constant requires localization for other locales and keyboard
-   * layouts.
-   */
-  static const int COMMA = 188;
-  /**
-   * CAUTION: This constant requires localization for other locales and keyboard
-   * layouts.
-   */
-  static const int PERIOD = 190;
-  /**
-   * CAUTION: This constant requires localization for other locales and keyboard
-   * layouts.
-   */
-  static const int SLASH = 191;
-  /**
-   * CAUTION: This constant requires localization for other locales and keyboard
-   * layouts.
-   */
-  static const int APOSTROPHE = 192;
-  /**
-   * CAUTION: This constant requires localization for other locales and keyboard
-   * layouts.
-   */
-  static const int TILDE = 192;
-  /**
-   * CAUTION: This constant requires localization for other locales and keyboard
-   * layouts.
-   */
-  static const int SINGLE_QUOTE = 222;
-  /**
-   * CAUTION: This constant requires localization for other locales and keyboard
-   * layouts.
-   */
-  static const int OPEN_SQUARE_BRACKET = 219;
-  /**
-   * CAUTION: This constant requires localization for other locales and keyboard
-   * layouts.
-   */
-  static const int BACKSLASH = 220;
-  /**
-   * CAUTION: This constant requires localization for other locales and keyboard
-   * layouts.
-   */
-  static const int CLOSE_SQUARE_BRACKET = 221;
-  static const int WIN_KEY = 224;
-  static const int MAC_FF_META = 224;
-  static const int WIN_IME = 229;
-
-  /** A sentinel value if the keycode could not be determined. */
-  static const int UNKNOWN = -1;
-
-  /**
-   * Returns true if the keyCode produces a (US keyboard) character.
-   * Note: This does not (yet) cover characters on non-US keyboards (Russian,
-   * Hebrew, etc.).
-   */
-  static bool isCharacterKey(int keyCode) {
-    if ((keyCode >= ZERO && keyCode <= NINE) ||
-        (keyCode >= NUM_ZERO && keyCode <= NUM_MULTIPLY) ||
-        (keyCode >= A && keyCode <= Z)) {
-      return true;
-    }
-
-    // Safari sends zero key code for non-latin characters.
-    if (Device.isWebKit && keyCode == 0) {
-      return true;
-    }
-
-    return (keyCode == SPACE ||
-        keyCode == QUESTION_MARK ||
-        keyCode == NUM_PLUS ||
-        keyCode == NUM_MINUS ||
-        keyCode == NUM_PERIOD ||
-        keyCode == NUM_DIVISION ||
-        keyCode == SEMICOLON ||
-        keyCode == FF_SEMICOLON ||
-        keyCode == DASH ||
-        keyCode == EQUALS ||
-        keyCode == FF_EQUALS ||
-        keyCode == COMMA ||
-        keyCode == PERIOD ||
-        keyCode == SLASH ||
-        keyCode == APOSTROPHE ||
-        keyCode == SINGLE_QUOTE ||
-        keyCode == OPEN_SQUARE_BRACKET ||
-        keyCode == BACKSLASH ||
-        keyCode == CLOSE_SQUARE_BRACKET);
-  }
-
-  /**
-   * Experimental helper function for converting keyCodes to keyNames for the
-   * keyIdentifier attribute still used in browsers not updated with current
-   * spec. This is an imperfect conversion! It will need to be refined, but
-   * hopefully it can just completely go away once all the browsers update to
-   * follow the DOM3 spec.
-   */
-  static String _convertKeyCodeToKeyName(int keyCode) {
-    switch (keyCode) {
-      case KeyCode.ALT:
-        return _KeyName.ALT;
-      case KeyCode.BACKSPACE:
-        return _KeyName.BACKSPACE;
-      case KeyCode.CAPS_LOCK:
-        return _KeyName.CAPS_LOCK;
-      case KeyCode.CTRL:
-        return _KeyName.CONTROL;
-      case KeyCode.DELETE:
-        return _KeyName.DEL;
-      case KeyCode.DOWN:
-        return _KeyName.DOWN;
-      case KeyCode.END:
-        return _KeyName.END;
-      case KeyCode.ENTER:
-        return _KeyName.ENTER;
-      case KeyCode.ESC:
-        return _KeyName.ESC;
-      case KeyCode.F1:
-        return _KeyName.F1;
-      case KeyCode.F2:
-        return _KeyName.F2;
-      case KeyCode.F3:
-        return _KeyName.F3;
-      case KeyCode.F4:
-        return _KeyName.F4;
-      case KeyCode.F5:
-        return _KeyName.F5;
-      case KeyCode.F6:
-        return _KeyName.F6;
-      case KeyCode.F7:
-        return _KeyName.F7;
-      case KeyCode.F8:
-        return _KeyName.F8;
-      case KeyCode.F9:
-        return _KeyName.F9;
-      case KeyCode.F10:
-        return _KeyName.F10;
-      case KeyCode.F11:
-        return _KeyName.F11;
-      case KeyCode.F12:
-        return _KeyName.F12;
-      case KeyCode.HOME:
-        return _KeyName.HOME;
-      case KeyCode.INSERT:
-        return _KeyName.INSERT;
-      case KeyCode.LEFT:
-        return _KeyName.LEFT;
-      case KeyCode.META:
-        return _KeyName.META;
-      case KeyCode.NUMLOCK:
-        return _KeyName.NUM_LOCK;
-      case KeyCode.PAGE_DOWN:
-        return _KeyName.PAGE_DOWN;
-      case KeyCode.PAGE_UP:
-        return _KeyName.PAGE_UP;
-      case KeyCode.PAUSE:
-        return _KeyName.PAUSE;
-      case KeyCode.PRINT_SCREEN:
-        return _KeyName.PRINT_SCREEN;
-      case KeyCode.RIGHT:
-        return _KeyName.RIGHT;
-      case KeyCode.SCROLL_LOCK:
-        return _KeyName.SCROLL;
-      case KeyCode.SHIFT:
-        return _KeyName.SHIFT;
-      case KeyCode.SPACE:
-        return _KeyName.SPACEBAR;
-      case KeyCode.TAB:
-        return _KeyName.TAB;
-      case KeyCode.UP:
-        return _KeyName.UP;
-      case KeyCode.WIN_IME:
-      case KeyCode.WIN_KEY:
-      case KeyCode.WIN_KEY_LEFT:
-      case KeyCode.WIN_KEY_RIGHT:
-        return _KeyName.WIN;
-      default:
-        return _KeyName.UNIDENTIFIED;
-    }
-    return _KeyName.UNIDENTIFIED;
-  }
-}
diff --git a/tools/dom/nnbd_src/KeyLocation.dart b/tools/dom/nnbd_src/KeyLocation.dart
deleted file mode 100644
index db4c423..0000000
--- a/tools/dom/nnbd_src/KeyLocation.dart
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of html;
-
-/**
- * Defines the standard key locations returned by
- * KeyboardEvent.getKeyLocation.
- */
-abstract class KeyLocation {
-  /**
-   * The event key is not distinguished as the left or right version
-   * of the key, and did not originate from the numeric keypad (or did not
-   * originate with a virtual key corresponding to the numeric keypad).
-   */
-  static const int STANDARD = 0;
-
-  /**
-   * The event key is in the left key location.
-   */
-  static const int LEFT = 1;
-
-  /**
-   * The event key is in the right key location.
-   */
-  static const int RIGHT = 2;
-
-  /**
-   * The event key originated on the numeric keypad or with a virtual key
-   * corresponding to the numeric keypad.
-   */
-  static const int NUMPAD = 3;
-
-  /**
-   * The event key originated on a mobile device, either on a physical
-   * keypad or a virtual keyboard.
-   */
-  static const int MOBILE = 4;
-
-  /**
-   * The event key originated on a game controller or a joystick on a mobile
-   * device.
-   */
-  static const int JOYSTICK = 5;
-}
diff --git a/tools/dom/nnbd_src/KeyName.dart b/tools/dom/nnbd_src/KeyName.dart
deleted file mode 100644
index 094d57e..0000000
--- a/tools/dom/nnbd_src/KeyName.dart
+++ /dev/null
@@ -1,494 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of html;
-
-/**
- * Defines the standard keyboard identifier names for keys that are returned
- * by KeyboardEvent.getKeyboardIdentifier when the key does not have a direct
- * unicode mapping.
- */
-abstract class _KeyName {
-  /** The Accept (Commit, OK) key */
-  static const String ACCEPT = "Accept";
-
-  /** The Add key */
-  static const String ADD = "Add";
-
-  /** The Again key */
-  static const String AGAIN = "Again";
-
-  /** The All Candidates key */
-  static const String ALL_CANDIDATES = "AllCandidates";
-
-  /** The Alphanumeric key */
-  static const String ALPHANUMERIC = "Alphanumeric";
-
-  /** The Alt (Menu) key */
-  static const String ALT = "Alt";
-
-  /** The Alt-Graph key */
-  static const String ALT_GRAPH = "AltGraph";
-
-  /** The Application key */
-  static const String APPS = "Apps";
-
-  /** The ATTN key */
-  static const String ATTN = "Attn";
-
-  /** The Browser Back key */
-  static const String BROWSER_BACK = "BrowserBack";
-
-  /** The Browser Favorites key */
-  static const String BROWSER_FAVORTIES = "BrowserFavorites";
-
-  /** The Browser Forward key */
-  static const String BROWSER_FORWARD = "BrowserForward";
-
-  /** The Browser Home key */
-  static const String BROWSER_NAME = "BrowserHome";
-
-  /** The Browser Refresh key */
-  static const String BROWSER_REFRESH = "BrowserRefresh";
-
-  /** The Browser Search key */
-  static const String BROWSER_SEARCH = "BrowserSearch";
-
-  /** The Browser Stop key */
-  static const String BROWSER_STOP = "BrowserStop";
-
-  /** The Camera key */
-  static const String CAMERA = "Camera";
-
-  /** The Caps Lock (Capital) key */
-  static const String CAPS_LOCK = "CapsLock";
-
-  /** The Clear key */
-  static const String CLEAR = "Clear";
-
-  /** The Code Input key */
-  static const String CODE_INPUT = "CodeInput";
-
-  /** The Compose key */
-  static const String COMPOSE = "Compose";
-
-  /** The Control (Ctrl) key */
-  static const String CONTROL = "Control";
-
-  /** The Crsel key */
-  static const String CRSEL = "Crsel";
-
-  /** The Convert key */
-  static const String CONVERT = "Convert";
-
-  /** The Copy key */
-  static const String COPY = "Copy";
-
-  /** The Cut key */
-  static const String CUT = "Cut";
-
-  /** The Decimal key */
-  static const String DECIMAL = "Decimal";
-
-  /** The Divide key */
-  static const String DIVIDE = "Divide";
-
-  /** The Down Arrow key */
-  static const String DOWN = "Down";
-
-  /** The diagonal Down-Left Arrow key */
-  static const String DOWN_LEFT = "DownLeft";
-
-  /** The diagonal Down-Right Arrow key */
-  static const String DOWN_RIGHT = "DownRight";
-
-  /** The Eject key */
-  static const String EJECT = "Eject";
-
-  /** The End key */
-  static const String END = "End";
-
-  /**
-   * The Enter key. Note: This key value must also be used for the Return
-   *  (Macintosh numpad) key
-   */
-  static const String ENTER = "Enter";
-
-  /** The Erase EOF key */
-  static const String ERASE_EOF = "EraseEof";
-
-  /** The Execute key */
-  static const String EXECUTE = "Execute";
-
-  /** The Exsel key */
-  static const String EXSEL = "Exsel";
-
-  /** The Function switch key */
-  static const String FN = "Fn";
-
-  /** The F1 key */
-  static const String F1 = "F1";
-
-  /** The F2 key */
-  static const String F2 = "F2";
-
-  /** The F3 key */
-  static const String F3 = "F3";
-
-  /** The F4 key */
-  static const String F4 = "F4";
-
-  /** The F5 key */
-  static const String F5 = "F5";
-
-  /** The F6 key */
-  static const String F6 = "F6";
-
-  /** The F7 key */
-  static const String F7 = "F7";
-
-  /** The F8 key */
-  static const String F8 = "F8";
-
-  /** The F9 key */
-  static const String F9 = "F9";
-
-  /** The F10 key */
-  static const String F10 = "F10";
-
-  /** The F11 key */
-  static const String F11 = "F11";
-
-  /** The F12 key */
-  static const String F12 = "F12";
-
-  /** The F13 key */
-  static const String F13 = "F13";
-
-  /** The F14 key */
-  static const String F14 = "F14";
-
-  /** The F15 key */
-  static const String F15 = "F15";
-
-  /** The F16 key */
-  static const String F16 = "F16";
-
-  /** The F17 key */
-  static const String F17 = "F17";
-
-  /** The F18 key */
-  static const String F18 = "F18";
-
-  /** The F19 key */
-  static const String F19 = "F19";
-
-  /** The F20 key */
-  static const String F20 = "F20";
-
-  /** The F21 key */
-  static const String F21 = "F21";
-
-  /** The F22 key */
-  static const String F22 = "F22";
-
-  /** The F23 key */
-  static const String F23 = "F23";
-
-  /** The F24 key */
-  static const String F24 = "F24";
-
-  /** The Final Mode (Final) key used on some asian keyboards */
-  static const String FINAL_MODE = "FinalMode";
-
-  /** The Find key */
-  static const String FIND = "Find";
-
-  /** The Full-Width Characters key */
-  static const String FULL_WIDTH = "FullWidth";
-
-  /** The Half-Width Characters key */
-  static const String HALF_WIDTH = "HalfWidth";
-
-  /** The Hangul (Korean characters) Mode key */
-  static const String HANGUL_MODE = "HangulMode";
-
-  /** The Hanja (Korean characters) Mode key */
-  static const String HANJA_MODE = "HanjaMode";
-
-  /** The Help key */
-  static const String HELP = "Help";
-
-  /** The Hiragana (Japanese Kana characters) key */
-  static const String HIRAGANA = "Hiragana";
-
-  /** The Home key */
-  static const String HOME = "Home";
-
-  /** The Insert (Ins) key */
-  static const String INSERT = "Insert";
-
-  /** The Japanese-Hiragana key */
-  static const String JAPANESE_HIRAGANA = "JapaneseHiragana";
-
-  /** The Japanese-Katakana key */
-  static const String JAPANESE_KATAKANA = "JapaneseKatakana";
-
-  /** The Japanese-Romaji key */
-  static const String JAPANESE_ROMAJI = "JapaneseRomaji";
-
-  /** The Junja Mode key */
-  static const String JUNJA_MODE = "JunjaMode";
-
-  /** The Kana Mode (Kana Lock) key */
-  static const String KANA_MODE = "KanaMode";
-
-  /**
-   * The Kanji (Japanese name for ideographic characters of Chinese origin)
-   * Mode key
-   */
-  static const String KANJI_MODE = "KanjiMode";
-
-  /** The Katakana (Japanese Kana characters) key */
-  static const String KATAKANA = "Katakana";
-
-  /** The Start Application One key */
-  static const String LAUNCH_APPLICATION_1 = "LaunchApplication1";
-
-  /** The Start Application Two key */
-  static const String LAUNCH_APPLICATION_2 = "LaunchApplication2";
-
-  /** The Start Mail key */
-  static const String LAUNCH_MAIL = "LaunchMail";
-
-  /** The Left Arrow key */
-  static const String LEFT = "Left";
-
-  /** The Menu key */
-  static const String MENU = "Menu";
-
-  /**
-   * The Meta key. Note: This key value shall be also used for the Apple
-   * Command key
-   */
-  static const String META = "Meta";
-
-  /** The Media Next Track key */
-  static const String MEDIA_NEXT_TRACK = "MediaNextTrack";
-
-  /** The Media Play Pause key */
-  static const String MEDIA_PAUSE_PLAY = "MediaPlayPause";
-
-  /** The Media Previous Track key */
-  static const String MEDIA_PREVIOUS_TRACK = "MediaPreviousTrack";
-
-  /** The Media Stop key */
-  static const String MEDIA_STOP = "MediaStop";
-
-  /** The Mode Change key */
-  static const String MODE_CHANGE = "ModeChange";
-
-  /** The Next Candidate function key */
-  static const String NEXT_CANDIDATE = "NextCandidate";
-
-  /** The Nonconvert (Don't Convert) key */
-  static const String NON_CONVERT = "Nonconvert";
-
-  /** The Number Lock key */
-  static const String NUM_LOCK = "NumLock";
-
-  /** The Page Down (Next) key */
-  static const String PAGE_DOWN = "PageDown";
-
-  /** The Page Up key */
-  static const String PAGE_UP = "PageUp";
-
-  /** The Paste key */
-  static const String PASTE = "Paste";
-
-  /** The Pause key */
-  static const String PAUSE = "Pause";
-
-  /** The Play key */
-  static const String PLAY = "Play";
-
-  /**
-   * The Power key. Note: Some devices may not expose this key to the
-   * operating environment
-   */
-  static const String POWER = "Power";
-
-  /** The Previous Candidate function key */
-  static const String PREVIOUS_CANDIDATE = "PreviousCandidate";
-
-  /** The Print Screen (PrintScrn, SnapShot) key */
-  static const String PRINT_SCREEN = "PrintScreen";
-
-  /** The Process key */
-  static const String PROCESS = "Process";
-
-  /** The Props key */
-  static const String PROPS = "Props";
-
-  /** The Right Arrow key */
-  static const String RIGHT = "Right";
-
-  /** The Roman Characters function key */
-  static const String ROMAN_CHARACTERS = "RomanCharacters";
-
-  /** The Scroll Lock key */
-  static const String SCROLL = "Scroll";
-
-  /** The Select key */
-  static const String SELECT = "Select";
-
-  /** The Select Media key */
-  static const String SELECT_MEDIA = "SelectMedia";
-
-  /** The Separator key */
-  static const String SEPARATOR = "Separator";
-
-  /** The Shift key */
-  static const String SHIFT = "Shift";
-
-  /** The Soft1 key */
-  static const String SOFT_1 = "Soft1";
-
-  /** The Soft2 key */
-  static const String SOFT_2 = "Soft2";
-
-  /** The Soft3 key */
-  static const String SOFT_3 = "Soft3";
-
-  /** The Soft4 key */
-  static const String SOFT_4 = "Soft4";
-
-  /** The Stop key */
-  static const String STOP = "Stop";
-
-  /** The Subtract key */
-  static const String SUBTRACT = "Subtract";
-
-  /** The Symbol Lock key */
-  static const String SYMBOL_LOCK = "SymbolLock";
-
-  /** The Up Arrow key */
-  static const String UP = "Up";
-
-  /** The diagonal Up-Left Arrow key */
-  static const String UP_LEFT = "UpLeft";
-
-  /** The diagonal Up-Right Arrow key */
-  static const String UP_RIGHT = "UpRight";
-
-  /** The Undo key */
-  static const String UNDO = "Undo";
-
-  /** The Volume Down key */
-  static const String VOLUME_DOWN = "VolumeDown";
-
-  /** The Volume Mute key */
-  static const String VOLUMN_MUTE = "VolumeMute";
-
-  /** The Volume Up key */
-  static const String VOLUMN_UP = "VolumeUp";
-
-  /** The Windows Logo key */
-  static const String WIN = "Win";
-
-  /** The Zoom key */
-  static const String ZOOM = "Zoom";
-
-  /**
-   * The Backspace (Back) key. Note: This key value shall be also used for the
-   * key labeled 'delete' MacOS keyboards when not modified by the 'Fn' key
-   */
-  static const String BACKSPACE = "Backspace";
-
-  /** The Horizontal Tabulation (Tab) key */
-  static const String TAB = "Tab";
-
-  /** The Cancel key */
-  static const String CANCEL = "Cancel";
-
-  /** The Escape (Esc) key */
-  static const String ESC = "Esc";
-
-  /** The Space (Spacebar) key:   */
-  static const String SPACEBAR = "Spacebar";
-
-  /**
-   * The Delete (Del) Key. Note: This key value shall be also used for the key
-   * labeled 'delete' MacOS keyboards when modified by the 'Fn' key
-   */
-  static const String DEL = "Del";
-
-  /** The Combining Grave Accent (Greek Varia, Dead Grave) key */
-  static const String DEAD_GRAVE = "DeadGrave";
-
-  /**
-   * The Combining Acute Accent (Stress Mark, Greek Oxia, Tonos, Dead Eacute)
-   * key
-   */
-  static const String DEAD_EACUTE = "DeadEacute";
-
-  /** The Combining Circumflex Accent (Hat, Dead Circumflex) key */
-  static const String DEAD_CIRCUMFLEX = "DeadCircumflex";
-
-  /** The Combining Tilde (Dead Tilde) key */
-  static const String DEAD_TILDE = "DeadTilde";
-
-  /** The Combining Macron (Long, Dead Macron) key */
-  static const String DEAD_MACRON = "DeadMacron";
-
-  /** The Combining Breve (Short, Dead Breve) key */
-  static const String DEAD_BREVE = "DeadBreve";
-
-  /** The Combining Dot Above (Derivative, Dead Above Dot) key */
-  static const String DEAD_ABOVE_DOT = "DeadAboveDot";
-
-  /**
-   * The Combining Diaeresis (Double Dot Abode, Umlaut, Greek Dialytika,
-   * Double Derivative, Dead Diaeresis) key
-   */
-  static const String DEAD_UMLAUT = "DeadUmlaut";
-
-  /** The Combining Ring Above (Dead Above Ring) key */
-  static const String DEAD_ABOVE_RING = "DeadAboveRing";
-
-  /** The Combining Double Acute Accent (Dead Doubleacute) key */
-  static const String DEAD_DOUBLEACUTE = "DeadDoubleacute";
-
-  /** The Combining Caron (Hacek, V Above, Dead Caron) key */
-  static const String DEAD_CARON = "DeadCaron";
-
-  /** The Combining Cedilla (Dead Cedilla) key */
-  static const String DEAD_CEDILLA = "DeadCedilla";
-
-  /** The Combining Ogonek (Nasal Hook, Dead Ogonek) key */
-  static const String DEAD_OGONEK = "DeadOgonek";
-
-  /**
-   * The Combining Greek Ypogegrammeni (Greek Non-Spacing Iota Below, Iota
-   * Subscript, Dead Iota) key
-   */
-  static const String DEAD_IOTA = "DeadIota";
-
-  /**
-   * The Combining Katakana-Hiragana Voiced Sound Mark (Dead Voiced Sound) key
-   */
-  static const String DEAD_VOICED_SOUND = "DeadVoicedSound";
-
-  /**
-   * The Combining Katakana-Hiragana Semi-Voiced Sound Mark (Dead Semivoiced
-   * Sound) key
-   */
-  static const String DEC_SEMIVOICED_SOUND = "DeadSemivoicedSound";
-
-  /**
-   * Key value used when an implementation is unable to identify another key
-   * value, due to either hardware, platform, or software constraints
-   */
-  static const String UNIDENTIFIED = "Unidentified";
-}
diff --git a/tools/dom/nnbd_src/KeyboardEventStream.dart b/tools/dom/nnbd_src/KeyboardEventStream.dart
deleted file mode 100644
index 399c037..0000000
--- a/tools/dom/nnbd_src/KeyboardEventStream.dart
+++ /dev/null
@@ -1,394 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of html;
-
-/**
- * Internal class that does the actual calculations to determine keyCode and
- * charCode for keydown, keypress, and keyup events for all browsers.
- */
-class _KeyboardEventHandler extends EventStreamProvider<KeyEvent> {
-  // This code inspired by Closure's KeyHandling library.
-  // https://github.com/google/closure-library/blob/master/closure/goog/events/keyhandler.js
-
-  /**
-   * The set of keys that have been pressed down without seeing their
-   * corresponding keyup event.
-   */
-  final List<KeyEvent> _keyDownList = <KeyEvent>[];
-
-  /** The type of KeyEvent we are tracking (keyup, keydown, keypress). */
-  final String _type;
-
-  /** The element we are watching for events to happen on. */
-  final EventTarget? _target;
-
-  // The distance to shift from upper case alphabet Roman letters to lower case.
-  static final int _ROMAN_ALPHABET_OFFSET = "a".codeUnits[0] - "A".codeUnits[0];
-
-  /** Custom Stream (Controller) to produce KeyEvents for the stream. */
-  _CustomKeyEventStreamImpl _stream;
-
-  static const _EVENT_TYPE = 'KeyEvent';
-
-  /**
-   * An enumeration of key identifiers currently part of the W3C draft for DOM3
-   * and their mappings to keyCodes.
-   * https://www.w3.org/TR/2003/NOTE-DOM-Level-3-Events-20031107/keyset.html#KeySet-Set
-   */
-  static const Map<String, int> _keyIdentifier = const {
-    'Up': KeyCode.UP,
-    'Down': KeyCode.DOWN,
-    'Left': KeyCode.LEFT,
-    'Right': KeyCode.RIGHT,
-    'Enter': KeyCode.ENTER,
-    'F1': KeyCode.F1,
-    'F2': KeyCode.F2,
-    'F3': KeyCode.F3,
-    'F4': KeyCode.F4,
-    'F5': KeyCode.F5,
-    'F6': KeyCode.F6,
-    'F7': KeyCode.F7,
-    'F8': KeyCode.F8,
-    'F9': KeyCode.F9,
-    'F10': KeyCode.F10,
-    'F11': KeyCode.F11,
-    'F12': KeyCode.F12,
-    'U+007F': KeyCode.DELETE,
-    'Home': KeyCode.HOME,
-    'End': KeyCode.END,
-    'PageUp': KeyCode.PAGE_UP,
-    'PageDown': KeyCode.PAGE_DOWN,
-    'Insert': KeyCode.INSERT
-  };
-
-  /** Return a stream for KeyEvents for the specified target. */
-  // Note: this actually functions like a factory constructor.
-  CustomStream<KeyEvent> forTarget(EventTarget? e, {bool useCapture: false}) {
-    var handler =
-        new _KeyboardEventHandler.initializeAllEventListeners(_type, e);
-    return handler._stream;
-  }
-
-  /**
-   * General constructor, performs basic initialization for our improved
-   * KeyboardEvent controller.
-   */
-  _KeyboardEventHandler(this._type)
-      : _stream = new _CustomKeyEventStreamImpl('event'),
-        _target = null,
-        super(_EVENT_TYPE);
-
-  /**
-   * Hook up all event listeners under the covers so we can estimate keycodes
-   * and charcodes when they are not provided.
-   */
-  _KeyboardEventHandler.initializeAllEventListeners(this._type, this._target)
-      : _stream = new _CustomKeyEventStreamImpl(_type),
-        super(_EVENT_TYPE) {
-    Element.keyDownEvent
-        .forTarget(_target, useCapture: true)
-        .listen(processKeyDown);
-    Element.keyPressEvent
-        .forTarget(_target, useCapture: true)
-        .listen(processKeyPress);
-    Element.keyUpEvent
-        .forTarget(_target, useCapture: true)
-        .listen(processKeyUp);
-  }
-
-  /** Determine if caps lock is one of the currently depressed keys. */
-  bool get _capsLockOn =>
-      _keyDownList.any((var element) => element.keyCode == KeyCode.CAPS_LOCK);
-
-  /**
-   * Given the previously recorded keydown key codes, see if we can determine
-   * the keycode of this keypress [event]. (Generally browsers only provide
-   * charCode information for keypress events, but with a little
-   * reverse-engineering, we can also determine the keyCode.) Returns
-   * KeyCode.UNKNOWN if the keycode could not be determined.
-   */
-  int _determineKeyCodeForKeypress(KeyboardEvent event) {
-    // Note: This function is a work in progress. We'll expand this function
-    // once we get more information about other keyboards.
-    for (var prevEvent in _keyDownList) {
-      if (prevEvent._shadowCharCode == event.charCode) {
-        return prevEvent.keyCode;
-      }
-      if ((event.shiftKey || _capsLockOn) &&
-          event.charCode >= "A".codeUnits[0] &&
-          event.charCode <= "Z".codeUnits[0] &&
-          event.charCode + _ROMAN_ALPHABET_OFFSET ==
-              prevEvent._shadowCharCode) {
-        return prevEvent.keyCode;
-      }
-    }
-    return KeyCode.UNKNOWN;
-  }
-
-  /**
-   * Given the character code returned from a keyDown [event], try to ascertain
-   * and return the corresponding charCode for the character that was pressed.
-   * This information is not shown to the user, but used to help polyfill
-   * keypress events.
-   */
-  int _findCharCodeKeyDown(KeyboardEvent event) {
-    if (event.location == 3) {
-      // Numpad keys.
-      switch (event.keyCode) {
-        case KeyCode.NUM_ZERO:
-          // Even though this function returns _charCodes_, for some cases the
-          // KeyCode == the charCode we want, in which case we use the keycode
-          // constant for readability.
-          return KeyCode.ZERO;
-        case KeyCode.NUM_ONE:
-          return KeyCode.ONE;
-        case KeyCode.NUM_TWO:
-          return KeyCode.TWO;
-        case KeyCode.NUM_THREE:
-          return KeyCode.THREE;
-        case KeyCode.NUM_FOUR:
-          return KeyCode.FOUR;
-        case KeyCode.NUM_FIVE:
-          return KeyCode.FIVE;
-        case KeyCode.NUM_SIX:
-          return KeyCode.SIX;
-        case KeyCode.NUM_SEVEN:
-          return KeyCode.SEVEN;
-        case KeyCode.NUM_EIGHT:
-          return KeyCode.EIGHT;
-        case KeyCode.NUM_NINE:
-          return KeyCode.NINE;
-        case KeyCode.NUM_MULTIPLY:
-          return 42; // Char code for *
-        case KeyCode.NUM_PLUS:
-          return 43; // +
-        case KeyCode.NUM_MINUS:
-          return 45; // -
-        case KeyCode.NUM_PERIOD:
-          return 46; // .
-        case KeyCode.NUM_DIVISION:
-          return 47; // /
-      }
-    } else if (event.keyCode >= 65 && event.keyCode <= 90) {
-      // Set the "char code" for key down as the lower case letter. Again, this
-      // will not show up for the user, but will be helpful in estimating
-      // keyCode locations and other information during the keyPress event.
-      return event.keyCode + _ROMAN_ALPHABET_OFFSET;
-    }
-    switch (event.keyCode) {
-      case KeyCode.SEMICOLON:
-        return KeyCode.FF_SEMICOLON;
-      case KeyCode.EQUALS:
-        return KeyCode.FF_EQUALS;
-      case KeyCode.COMMA:
-        return 44; // Ascii value for ,
-      case KeyCode.DASH:
-        return 45; // -
-      case KeyCode.PERIOD:
-        return 46; // .
-      case KeyCode.SLASH:
-        return 47; // /
-      case KeyCode.APOSTROPHE:
-        return 96; // `
-      case KeyCode.OPEN_SQUARE_BRACKET:
-        return 91; // [
-      case KeyCode.BACKSLASH:
-        return 92; // \
-      case KeyCode.CLOSE_SQUARE_BRACKET:
-        return 93; // ]
-      case KeyCode.SINGLE_QUOTE:
-        return 39; // '
-    }
-    return event.keyCode;
-  }
-
-  /**
-   * Returns true if the key fires a keypress event in the current browser.
-   */
-  bool _firesKeyPressEvent(KeyEvent event) {
-    if (!Device.isIE && !Device.isWebKit) {
-      return true;
-    }
-
-    if (Device.userAgent.contains('Mac') && event.altKey) {
-      return KeyCode.isCharacterKey(event.keyCode);
-    }
-
-    // Alt but not AltGr which is represented as Alt+Ctrl.
-    if (event.altKey && !event.ctrlKey) {
-      return false;
-    }
-
-    // Saves Ctrl or Alt + key for IE and WebKit, which won't fire keypress.
-    if (!event.shiftKey &&
-        (_keyDownList.last.keyCode == KeyCode.CTRL ||
-            _keyDownList.last.keyCode == KeyCode.ALT ||
-            Device.userAgent.contains('Mac') &&
-                _keyDownList.last.keyCode == KeyCode.META)) {
-      return false;
-    }
-
-    // Some keys with Ctrl/Shift do not issue keypress in WebKit.
-    if (Device.isWebKit &&
-        event.ctrlKey &&
-        event.shiftKey &&
-        (event.keyCode == KeyCode.BACKSLASH ||
-            event.keyCode == KeyCode.OPEN_SQUARE_BRACKET ||
-            event.keyCode == KeyCode.CLOSE_SQUARE_BRACKET ||
-            event.keyCode == KeyCode.TILDE ||
-            event.keyCode == KeyCode.SEMICOLON ||
-            event.keyCode == KeyCode.DASH ||
-            event.keyCode == KeyCode.EQUALS ||
-            event.keyCode == KeyCode.COMMA ||
-            event.keyCode == KeyCode.PERIOD ||
-            event.keyCode == KeyCode.SLASH ||
-            event.keyCode == KeyCode.APOSTROPHE ||
-            event.keyCode == KeyCode.SINGLE_QUOTE)) {
-      return false;
-    }
-
-    switch (event.keyCode) {
-      case KeyCode.ENTER:
-        // IE9 does not fire keypress on ENTER.
-        return !Device.isIE;
-      case KeyCode.ESC:
-        return !Device.isWebKit;
-    }
-
-    return KeyCode.isCharacterKey(event.keyCode);
-  }
-
-  /**
-   * Normalize the keycodes to the IE KeyCodes (this is what Chrome, IE, and
-   * Opera all use).
-   */
-  int _normalizeKeyCodes(KeyboardEvent event) {
-    // Note: This may change once we get input about non-US keyboards.
-    if (Device.isFirefox) {
-      switch (event.keyCode) {
-        case KeyCode.FF_EQUALS:
-          return KeyCode.EQUALS;
-        case KeyCode.FF_SEMICOLON:
-          return KeyCode.SEMICOLON;
-        case KeyCode.MAC_FF_META:
-          return KeyCode.META;
-        case KeyCode.WIN_KEY_FF_LINUX:
-          return KeyCode.WIN_KEY;
-      }
-    }
-    return event.keyCode;
-  }
-
-  /** Handle keydown events. */
-  void processKeyDown(KeyboardEvent e) {
-    // Ctrl-Tab and Alt-Tab can cause the focus to be moved to another window
-    // before we've caught a key-up event.  If the last-key was one of these
-    // we reset the state.
-    if (_keyDownList.length > 0 &&
-        (_keyDownList.last.keyCode == KeyCode.CTRL && !e.ctrlKey ||
-            _keyDownList.last.keyCode == KeyCode.ALT && !e.altKey ||
-            Device.userAgent.contains('Mac') &&
-                _keyDownList.last.keyCode == KeyCode.META &&
-                !e.metaKey)) {
-      _keyDownList.clear();
-    }
-
-    var event = new KeyEvent.wrap(e);
-    event._shadowKeyCode = _normalizeKeyCodes(event);
-    // Technically a "keydown" event doesn't have a charCode. This is
-    // calculated nonetheless to provide us with more information in giving
-    // as much information as possible on keypress about keycode and also
-    // charCode.
-    event._shadowCharCode = _findCharCodeKeyDown(event);
-    if (_keyDownList.length > 0 &&
-        event.keyCode != _keyDownList.last.keyCode &&
-        !_firesKeyPressEvent(event)) {
-      // Some browsers have quirks not firing keypress events where all other
-      // browsers do. This makes them more consistent.
-      processKeyPress(e);
-    }
-    _keyDownList.add(event);
-    _stream.add(event);
-  }
-
-  /** Handle keypress events. */
-  void processKeyPress(KeyboardEvent event) {
-    var e = new KeyEvent.wrap(event);
-    // IE reports the character code in the keyCode field for keypress events.
-    // There are two exceptions however, Enter and Escape.
-    if (Device.isIE) {
-      if (e.keyCode == KeyCode.ENTER || e.keyCode == KeyCode.ESC) {
-        e._shadowCharCode = 0;
-      } else {
-        e._shadowCharCode = e.keyCode;
-      }
-    } else if (Device.isOpera) {
-      // Opera reports the character code in the keyCode field.
-      e._shadowCharCode = KeyCode.isCharacterKey(e.keyCode) ? e.keyCode : 0;
-    }
-    // Now we guesstimate about what the keycode is that was actually
-    // pressed, given previous keydown information.
-    e._shadowKeyCode = _determineKeyCodeForKeypress(e);
-
-    // Correct the key value for certain browser-specific quirks.
-    if (e._shadowKeyIdentifier != null &&
-        _keyIdentifier.containsKey(e._shadowKeyIdentifier)) {
-      // This is needed for Safari Windows because it currently doesn't give a
-      // keyCode/which for non printable keys.
-      e._shadowKeyCode = _keyIdentifier[e._shadowKeyIdentifier]!;
-    }
-    e._shadowAltKey = _keyDownList.any((var element) => element.altKey);
-    _stream.add(e);
-  }
-
-  /** Handle keyup events. */
-  void processKeyUp(KeyboardEvent event) {
-    var e = new KeyEvent.wrap(event);
-    KeyboardEvent? toRemove = null;
-    for (var key in _keyDownList) {
-      if (key.keyCode == e.keyCode) {
-        toRemove = key;
-      }
-    }
-    if (toRemove != null) {
-      _keyDownList.removeWhere((element) => element == toRemove);
-    } else if (_keyDownList.length > 0) {
-      // This happens when we've reached some international keyboard case we
-      // haven't accounted for or we haven't correctly eliminated all browser
-      // inconsistencies. Filing bugs on when this is reached is welcome!
-      _keyDownList.removeLast();
-    }
-    _stream.add(e);
-  }
-}
-
-/**
- * Records KeyboardEvents that occur on a particular element, and provides a
- * stream of outgoing KeyEvents with cross-browser consistent keyCode and
- * charCode values despite the fact that a multitude of browsers that have
- * varying keyboard default behavior.
- *
- * Example usage:
- *
- *     KeyboardEventStream.onKeyDown(document.body).listen(
- *         keydownHandlerTest);
- *
- * This class is very much a work in progress, and we'd love to get information
- * on how we can make this class work with as many international keyboards as
- * possible. Bugs welcome!
- */
-class KeyboardEventStream {
-  /** Named constructor to produce a stream for onKeyPress events. */
-  static CustomStream<KeyEvent> onKeyPress(EventTarget target) =>
-      new _KeyboardEventHandler('keypress').forTarget(target);
-
-  /** Named constructor to produce a stream for onKeyUp events. */
-  static CustomStream<KeyEvent> onKeyUp(EventTarget target) =>
-      new _KeyboardEventHandler('keyup').forTarget(target);
-
-  /** Named constructor to produce a stream for onKeyDown events. */
-  static CustomStream<KeyEvent> onKeyDown(EventTarget target) =>
-      new _KeyboardEventHandler('keydown').forTarget(target);
-}
diff --git a/tools/dom/nnbd_src/NodeValidatorBuilder.dart b/tools/dom/nnbd_src/NodeValidatorBuilder.dart
deleted file mode 100644
index 59f2b27..0000000
--- a/tools/dom/nnbd_src/NodeValidatorBuilder.dart
+++ /dev/null
@@ -1,454 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of dart.dom.html;
-
-/**
- * Class which helps construct standard node validation policies.
- *
- * By default this will not accept anything, but the 'allow*' functions can be
- * used to expand what types of elements or attributes are allowed.
- *
- * All allow functions are additive- elements will be accepted if they are
- * accepted by any specific rule.
- *
- * It is important to remember that sanitization is not just intended to prevent
- * cross-site scripting attacks, but also to prevent information from being
- * displayed in unexpected ways. For example something displaying basic
- * formatted text may not expect `<video>` tags to appear. In this case an
- * empty NodeValidatorBuilder with just [allowTextElements] might be
- * appropriate.
- */
-class NodeValidatorBuilder implements NodeValidator {
-  final List<NodeValidator> _validators = <NodeValidator>[];
-
-  NodeValidatorBuilder() {}
-
-  /**
-   * Creates a new NodeValidatorBuilder which accepts common constructs.
-   *
-   * By default this will accept HTML5 elements and attributes with the default
-   * [UriPolicy] and templating elements.
-   *
-   * Notable syntax which is filtered:
-   *
-   * * Only known-good HTML5 elements and attributes are allowed.
-   * * All URLs must be same-origin, use [allowNavigation] and [allowImages] to
-   * specify additional URI policies.
-   * * Inline-styles are not allowed.
-   * * Custom element tags are disallowed, use [allowCustomElement].
-   * * Custom tags extensions are disallowed, use [allowTagExtension].
-   * * SVG Elements are not allowed, use [allowSvg].
-   *
-   * For scenarios where the HTML should only contain formatted text
-   * [allowTextElements] is more appropriate.
-   *
-   * Use [allowSvg] to allow SVG elements.
-   */
-  NodeValidatorBuilder.common() {
-    allowHtml5();
-    allowTemplating();
-  }
-
-  /**
-   * Allows navigation elements- Form and Anchor tags, along with common
-   * attributes.
-   *
-   * The UriPolicy can be used to restrict the locations the navigation elements
-   * are allowed to direct to. By default this will use the default [UriPolicy].
-   */
-  void allowNavigation([UriPolicy? uriPolicy]) {
-    if (uriPolicy == null) {
-      uriPolicy = new UriPolicy();
-    }
-    add(new _SimpleNodeValidator.allowNavigation(uriPolicy));
-  }
-
-  /**
-   * Allows image elements.
-   *
-   * The UriPolicy can be used to restrict the locations the images may be
-   * loaded from. By default this will use the default [UriPolicy].
-   */
-  void allowImages([UriPolicy? uriPolicy]) {
-    if (uriPolicy == null) {
-      uriPolicy = new UriPolicy();
-    }
-    add(new _SimpleNodeValidator.allowImages(uriPolicy));
-  }
-
-  /**
-   * Allow basic text elements.
-   *
-   * This allows a subset of HTML5 elements, specifically just these tags and
-   * no attributes.
-   *
-   * * B
-   * * BLOCKQUOTE
-   * * BR
-   * * EM
-   * * H1
-   * * H2
-   * * H3
-   * * H4
-   * * H5
-   * * H6
-   * * HR
-   * * I
-   * * LI
-   * * OL
-   * * P
-   * * SPAN
-   * * UL
-   */
-  void allowTextElements() {
-    add(new _SimpleNodeValidator.allowTextElements());
-  }
-
-  /**
-   * Allow inline styles on elements.
-   *
-   * If [tagName] is not specified then this allows inline styles on all
-   * elements. Otherwise tagName limits the styles to the specified elements.
-   */
-  void allowInlineStyles({String? tagName}) {
-    if (tagName == null) {
-      tagName = '*';
-    } else {
-      tagName = tagName.toUpperCase();
-    }
-    add(new _SimpleNodeValidator(null, allowedAttributes: ['$tagName::style']));
-  }
-
-  /**
-   * Allow common safe HTML5 elements and attributes.
-   *
-   * This list is based off of the Caja whitelists at:
-   * https://code.google.com/p/google-caja/wiki/CajaWhitelists.
-   *
-   * Common things which are not allowed are script elements, style attributes
-   * and any script handlers.
-   */
-  void allowHtml5({UriPolicy? uriPolicy}) {
-    add(new _Html5NodeValidator(uriPolicy: uriPolicy));
-  }
-
-  /**
-   * Allow SVG elements and attributes except for known bad ones.
-   */
-  void allowSvg() {
-    add(new _SvgNodeValidator());
-  }
-
-  /**
-   * Allow custom elements with the specified tag name and specified attributes.
-   *
-   * This will allow the elements as custom tags (such as <x-foo></x-foo>),
-   * but will not allow tag extensions. Use [allowTagExtension] to allow
-   * tag extensions.
-   */
-  void allowCustomElement(String tagName,
-      {UriPolicy? uriPolicy,
-      Iterable<String>? attributes,
-      Iterable<String>? uriAttributes}) {
-    var tagNameUpper = tagName.toUpperCase();
-    var attrs = attributes
-        ?.map<String>((name) => '$tagNameUpper::${name.toLowerCase()}');
-    var uriAttrs = uriAttributes
-        ?.map<String>((name) => '$tagNameUpper::${name.toLowerCase()}');
-    if (uriPolicy == null) {
-      uriPolicy = new UriPolicy();
-    }
-
-    add(new _CustomElementNodeValidator(
-        uriPolicy, [tagNameUpper], attrs, uriAttrs, false, true));
-  }
-
-  /**
-   * Allow custom tag extensions with the specified type name and specified
-   * attributes.
-   *
-   * This will allow tag extensions (such as <div is="x-foo"></div>),
-   * but will not allow custom tags. Use [allowCustomElement] to allow
-   * custom tags.
-   */
-  void allowTagExtension(String tagName, String baseName,
-      {UriPolicy? uriPolicy,
-      Iterable<String>? attributes,
-      Iterable<String>? uriAttributes}) {
-    var baseNameUpper = baseName.toUpperCase();
-    var tagNameUpper = tagName.toUpperCase();
-    var attrs = attributes
-        ?.map<String>((name) => '$baseNameUpper::${name.toLowerCase()}');
-    var uriAttrs = uriAttributes
-        ?.map<String>((name) => '$baseNameUpper::${name.toLowerCase()}');
-    if (uriPolicy == null) {
-      uriPolicy = new UriPolicy();
-    }
-
-    add(new _CustomElementNodeValidator(uriPolicy,
-        [tagNameUpper, baseNameUpper], attrs, uriAttrs, true, false));
-  }
-
-  void allowElement(String tagName,
-      {UriPolicy? uriPolicy,
-      Iterable<String>? attributes,
-      Iterable<String>? uriAttributes}) {
-    allowCustomElement(tagName,
-        uriPolicy: uriPolicy,
-        attributes: attributes,
-        uriAttributes: uriAttributes);
-  }
-
-  /**
-   * Allow templating elements (such as <template> and template-related
-   * attributes.
-   *
-   * This still requires other validators to allow regular attributes to be
-   * bound (such as [allowHtml5]).
-   */
-  void allowTemplating() {
-    add(new _TemplatingNodeValidator());
-  }
-
-  /**
-   * Add an additional validator to the current list of validators.
-   *
-   * Elements and attributes will be accepted if they are accepted by any
-   * validators.
-   */
-  void add(NodeValidator validator) {
-    _validators.add(validator);
-  }
-
-  bool allowsElement(Element element) {
-    return _validators.any((v) => v.allowsElement(element));
-  }
-
-  bool allowsAttribute(Element element, String attributeName, String value) {
-    return _validators
-        .any((v) => v.allowsAttribute(element, attributeName, value));
-  }
-}
-
-class _SimpleNodeValidator implements NodeValidator {
-  final Set<String> allowedElements = new Set<String>();
-  final Set<String> allowedAttributes = new Set<String>();
-  final Set<String> allowedUriAttributes = new Set<String>();
-  final UriPolicy? uriPolicy;
-
-  factory _SimpleNodeValidator.allowNavigation(UriPolicy uriPolicy) {
-    return new _SimpleNodeValidator(uriPolicy, allowedElements: const [
-      'A',
-      'FORM'
-    ], allowedAttributes: const [
-      'A::accesskey',
-      'A::coords',
-      'A::hreflang',
-      'A::name',
-      'A::shape',
-      'A::tabindex',
-      'A::target',
-      'A::type',
-      'FORM::accept',
-      'FORM::autocomplete',
-      'FORM::enctype',
-      'FORM::method',
-      'FORM::name',
-      'FORM::novalidate',
-      'FORM::target',
-    ], allowedUriAttributes: const [
-      'A::href',
-      'FORM::action',
-    ]);
-  }
-
-  factory _SimpleNodeValidator.allowImages(UriPolicy uriPolicy) {
-    return new _SimpleNodeValidator(uriPolicy, allowedElements: const [
-      'IMG'
-    ], allowedAttributes: const [
-      'IMG::align',
-      'IMG::alt',
-      'IMG::border',
-      'IMG::height',
-      'IMG::hspace',
-      'IMG::ismap',
-      'IMG::name',
-      'IMG::usemap',
-      'IMG::vspace',
-      'IMG::width',
-    ], allowedUriAttributes: const [
-      'IMG::src',
-    ]);
-  }
-
-  factory _SimpleNodeValidator.allowTextElements() {
-    return new _SimpleNodeValidator(null, allowedElements: const [
-      'B',
-      'BLOCKQUOTE',
-      'BR',
-      'EM',
-      'H1',
-      'H2',
-      'H3',
-      'H4',
-      'H5',
-      'H6',
-      'HR',
-      'I',
-      'LI',
-      'OL',
-      'P',
-      'SPAN',
-      'UL',
-    ]);
-  }
-
-  /**
-   * Elements must be uppercased tag names. For example `'IMG'`.
-   * Attributes must be uppercased tag name followed by :: followed by
-   * lowercase attribute name. For example `'IMG:src'`.
-   */
-  _SimpleNodeValidator(this.uriPolicy,
-      {Iterable<String>? allowedElements,
-      Iterable<String>? allowedAttributes,
-      Iterable<String>? allowedUriAttributes}) {
-    this.allowedElements.addAll(allowedElements ?? const []);
-    allowedAttributes = allowedAttributes ?? const [];
-    allowedUriAttributes = allowedUriAttributes ?? const [];
-    var legalAttributes = allowedAttributes
-        .where((x) => !_Html5NodeValidator._uriAttributes.contains(x));
-    var extraUriAttributes = allowedAttributes
-        .where((x) => _Html5NodeValidator._uriAttributes.contains(x));
-    this.allowedAttributes.addAll(legalAttributes);
-    this.allowedUriAttributes.addAll(allowedUriAttributes);
-    this.allowedUriAttributes.addAll(extraUriAttributes);
-  }
-
-  bool allowsElement(Element element) {
-    return allowedElements.contains(Element._safeTagName(element));
-  }
-
-  bool allowsAttribute(Element element, String attributeName, String value) {
-    var tagName = Element._safeTagName(element);
-    if (allowedUriAttributes.contains('$tagName::$attributeName')) {
-      return uriPolicy!.allowsUri(value);
-    } else if (allowedUriAttributes.contains('*::$attributeName')) {
-      return uriPolicy!.allowsUri(value);
-    } else if (allowedAttributes.contains('$tagName::$attributeName')) {
-      return true;
-    } else if (allowedAttributes.contains('*::$attributeName')) {
-      return true;
-    } else if (allowedAttributes.contains('$tagName::*')) {
-      return true;
-    } else if (allowedAttributes.contains('*::*')) {
-      return true;
-    }
-    return false;
-  }
-}
-
-class _CustomElementNodeValidator extends _SimpleNodeValidator {
-  final bool allowTypeExtension;
-  final bool allowCustomTag;
-
-  _CustomElementNodeValidator(
-      UriPolicy uriPolicy,
-      Iterable<String> allowedElements,
-      Iterable<String>? allowedAttributes,
-      Iterable<String>? allowedUriAttributes,
-      bool allowTypeExtension,
-      bool allowCustomTag)
-      : this.allowTypeExtension = allowTypeExtension == true,
-        this.allowCustomTag = allowCustomTag == true,
-        super(uriPolicy,
-            allowedElements: allowedElements,
-            allowedAttributes: allowedAttributes,
-            allowedUriAttributes: allowedUriAttributes);
-
-  bool allowsElement(Element element) {
-    if (allowTypeExtension) {
-      var isAttr = element.attributes['is'];
-      if (isAttr != null) {
-        return allowedElements.contains(isAttr.toUpperCase()) &&
-            allowedElements.contains(Element._safeTagName(element));
-      }
-    }
-    return allowCustomTag &&
-        allowedElements.contains(Element._safeTagName(element));
-  }
-
-  bool allowsAttribute(Element element, String attributeName, String value) {
-    if (allowsElement(element)) {
-      if (allowTypeExtension &&
-          attributeName == 'is' &&
-          allowedElements.contains(value.toUpperCase())) {
-        return true;
-      }
-      return super.allowsAttribute(element, attributeName, value);
-    }
-    return false;
-  }
-}
-
-class _TemplatingNodeValidator extends _SimpleNodeValidator {
-  static const _TEMPLATE_ATTRS = const <String>[
-    'bind',
-    'if',
-    'ref',
-    'repeat',
-    'syntax'
-  ];
-
-  final Set<String> _templateAttrs;
-
-  _TemplatingNodeValidator()
-      : _templateAttrs = new Set<String>.from(_TEMPLATE_ATTRS),
-        super(null,
-            allowedElements: ['TEMPLATE'],
-            allowedAttributes:
-                _TEMPLATE_ATTRS.map((attr) => 'TEMPLATE::$attr')) {}
-
-  bool allowsAttribute(Element element, String attributeName, String value) {
-    if (super.allowsAttribute(element, attributeName, value)) {
-      return true;
-    }
-
-    if (attributeName == 'template' && value == "") {
-      return true;
-    }
-
-    if (element.attributes['template'] == "") {
-      return _templateAttrs.contains(attributeName);
-    }
-    return false;
-  }
-}
-
-class _SvgNodeValidator implements NodeValidator {
-  bool allowsElement(Element element) {
-    if (element is svg.ScriptElement) {
-      return false;
-    }
-    // Firefox 37 has issues with creating foreign elements inside a
-    // foreignobject tag as SvgElement. We don't want foreignobject contents
-    // anyway, so just remove the whole tree outright. And we can't rely
-    // on IE recognizing the SvgForeignObject type, so go by tagName. Bug 23144
-    if (element is svg.SvgElement &&
-        Element._safeTagName(element) == 'foreignObject') {
-      return false;
-    }
-    if (element is svg.SvgElement) {
-      return true;
-    }
-    return false;
-  }
-
-  bool allowsAttribute(Element element, String attributeName, String value) {
-    if (attributeName == 'is' || attributeName.startsWith('on')) {
-      return false;
-    }
-    return allowsElement(element);
-  }
-}
diff --git a/tools/dom/nnbd_src/ReadyState.dart b/tools/dom/nnbd_src/ReadyState.dart
deleted file mode 100644
index 37c3fdb..0000000
--- a/tools/dom/nnbd_src/ReadyState.dart
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of html;
-
-/**
- * Contains the set of standard values returned by HTMLDocument.getReadyState.
- */
-abstract class ReadyState {
-  /**
-   * Indicates the document is still loading and parsing.
-   */
-  static const String LOADING = "loading";
-
-  /**
-   * Indicates the document is finished parsing but is still loading
-   * subresources.
-   */
-  static const String INTERACTIVE = "interactive";
-
-  /**
-   * Indicates the document and all subresources have been loaded.
-   */
-  static const String COMPLETE = "complete";
-}
diff --git a/tools/dom/nnbd_src/Validators.dart b/tools/dom/nnbd_src/Validators.dart
deleted file mode 100644
index a498da9..0000000
--- a/tools/dom/nnbd_src/Validators.dart
+++ /dev/null
@@ -1,321 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of dart.dom.html;
-
-/**
- * Interface used to validate that only accepted elements and attributes are
- * allowed while parsing HTML strings into DOM nodes.
- *
- * In general, customization of validation behavior should be done via the
- * [NodeValidatorBuilder] class to mitigate the chances of incorrectly
- * implementing validation rules.
- */
-abstract class NodeValidator {
-  /**
-   * Construct a default NodeValidator which only accepts whitelisted HTML5
-   * elements and attributes.
-   *
-   * If a uriPolicy is not specified then the default uriPolicy will be used.
-   */
-  factory NodeValidator({UriPolicy? uriPolicy}) =>
-      new _Html5NodeValidator(uriPolicy: uriPolicy);
-
-  factory NodeValidator.throws(NodeValidator base) =>
-      new _ThrowsNodeValidator(base);
-
-  /**
-   * Returns true if the tagName is an accepted type.
-   */
-  bool allowsElement(Element element);
-
-  /**
-   * Returns true if the attribute is allowed.
-   *
-   * The attributeName parameter will always be in lowercase.
-   *
-   * See [allowsElement] for format of tagName.
-   */
-  bool allowsAttribute(Element element, String attributeName, String value);
-}
-
-/**
- * Performs sanitization of a node tree after construction to ensure that it
- * does not contain any disallowed elements or attributes.
- *
- * In general custom implementations of this class should not be necessary and
- * all validation customization should be done in custom NodeValidators, but
- * custom implementations of this class can be created to perform more complex
- * tree sanitization.
- */
-abstract class NodeTreeSanitizer {
-  /**
-   * Constructs a default tree sanitizer which will remove all elements and
-   * attributes which are not allowed by the provided validator.
-   */
-  factory NodeTreeSanitizer(NodeValidator validator) =>
-      new _ValidatingTreeSanitizer(validator);
-
-  /**
-   * Called with the root of the tree which is to be sanitized.
-   *
-   * This method needs to walk the entire tree and either remove elements and
-   * attributes which are not recognized as safe or throw an exception which
-   * will mark the entire tree as unsafe.
-   */
-  void sanitizeTree(Node node);
-
-  /**
-   * A sanitizer for trees that we trust. It does no validation and allows
-   * any elements. It is also more efficient, since it can pass the text
-   * directly through to the underlying APIs without creating a document
-   * fragment to be sanitized.
-   */
-  static const trusted = const _TrustedHtmlTreeSanitizer();
-}
-
-/**
- * A sanitizer for trees that we trust. It does no validation and allows
- * any elements.
- */
-class _TrustedHtmlTreeSanitizer implements NodeTreeSanitizer {
-  const _TrustedHtmlTreeSanitizer();
-
-  sanitizeTree(Node node) {}
-}
-
-/**
- * Defines the policy for what types of uris are allowed for particular
- * attribute values.
- *
- * This can be used to provide custom rules such as allowing all http:// URIs
- * for image attributes but only same-origin URIs for anchor tags.
- */
-abstract class UriPolicy {
-  /**
-   * Constructs the default UriPolicy which is to only allow Uris to the same
-   * origin as the application was launched from.
-   *
-   * This will block all ftp: mailto: URIs. It will also block accessing
-   * https://example.com if the app is running from http://example.com.
-   */
-  factory UriPolicy() => new _SameOriginUriPolicy();
-
-  /**
-   * Checks if the uri is allowed on the specified attribute.
-   *
-   * The uri provided may or may not be a relative path.
-   */
-  bool allowsUri(String uri);
-}
-
-/**
- * Allows URIs to the same origin as the current application was loaded from
- * (such as https://example.com:80).
- */
-class _SameOriginUriPolicy implements UriPolicy {
-  final AnchorElement _hiddenAnchor = new AnchorElement();
-  final Location _loc = window.location;
-
-  bool allowsUri(String uri) {
-    _hiddenAnchor.href = uri;
-    // IE leaves an empty hostname for same-origin URIs.
-    return (_hiddenAnchor.hostname == _loc.hostname &&
-            _hiddenAnchor.port == _loc.port &&
-            _hiddenAnchor.protocol == _loc.protocol) ||
-        (_hiddenAnchor.hostname == '' &&
-            _hiddenAnchor.port == '' &&
-            (_hiddenAnchor.protocol == ':' || _hiddenAnchor.protocol == ''));
-  }
-}
-
-class _ThrowsNodeValidator implements NodeValidator {
-  final NodeValidator validator;
-
-  _ThrowsNodeValidator(this.validator) {}
-
-  bool allowsElement(Element element) {
-    if (!validator.allowsElement(element)) {
-      throw new ArgumentError(Element._safeTagName(element));
-    }
-    return true;
-  }
-
-  bool allowsAttribute(Element element, String attributeName, String value) {
-    if (!validator.allowsAttribute(element, attributeName, value)) {
-      throw new ArgumentError(
-          '${Element._safeTagName(element)}[$attributeName="$value"]');
-    }
-    return true;
-  }
-}
-
-/**
- * Standard tree sanitizer which validates a node tree against the provided
- * validator and removes any nodes or attributes which are not allowed.
- */
-class _ValidatingTreeSanitizer implements NodeTreeSanitizer {
-  NodeValidator validator;
-
-  /// Did we modify the tree by removing anything.
-  bool modifiedTree = false;
-  _ValidatingTreeSanitizer(this.validator) {}
-
-  void sanitizeTree(Node node) {
-    void walk(Node node, Node? parent) {
-      sanitizeNode(node, parent);
-
-      var child = node.lastChild;
-      while (null != child) {
-        Node? nextChild;
-        try {
-          // Child may be removed during the walk, and we may not even be able
-          // to get its previousNode. But it's also possible that previousNode
-          // (i.e. previousSibling) is being spoofed, so double-check it.
-          nextChild = child.previousNode;
-          if (nextChild != null && nextChild.nextNode != child) {
-            throw StateError("Corrupt HTML");
-          }
-        } catch (e) {
-          // Child appears bad, remove it. We want to check the rest of the
-          // children of node and, but we have no way of getting to the next
-          // child, so start again from the last child.
-          _removeNode(child, node);
-          child = null;
-          nextChild = node.lastChild;
-        }
-        if (child != null) walk(child, node);
-        child = nextChild;
-      }
-    }
-
-    modifiedTree = false;
-    walk(node, null);
-    while (modifiedTree) {
-      modifiedTree = false;
-      walk(node, null);
-    }
-  }
-
-  /// Aggressively try to remove node.
-  void _removeNode(Node node, Node? parent) {
-    // If we have the parent, it's presumably already passed more sanitization
-    // or is the fragment, so ask it to remove the child. And if that fails
-    // try to set the outer html.
-    modifiedTree = true;
-    if (parent == null || parent != node.parentNode) {
-      node.remove();
-    } else {
-      parent._removeChild(node);
-    }
-  }
-
-  /// Sanitize the element, assuming we can't trust anything about it.
-  void _sanitizeUntrustedElement(/* Element */ element, Node? parent) {
-    // If the _hasCorruptedAttributes does not successfully return false,
-    // then we consider it corrupted and remove.
-    // TODO(alanknight): This is a workaround because on Firefox
-    // embed/object
-    // tags typeof is "function", not "object". We don't recognize them, and
-    // can't call methods. This does mean that you can't explicitly allow an
-    // embed tag. The only thing that will let it through is a null
-    // sanitizer that doesn't traverse the tree at all. But sanitizing while
-    // allowing embeds seems quite unlikely. This is also the reason that we
-    // can't declare the type of element, as an embed won't pass any type
-    // check in dart2js.
-    var corrupted = true;
-    var attrs;
-    var isAttr;
-    try {
-      // If getting/indexing attributes throws, count that as corrupt.
-      attrs = element.attributes;
-      isAttr = attrs['is'];
-      var corruptedTest1 = Element._hasCorruptedAttributes(element);
-
-      // On IE, erratically, the hasCorruptedAttributes test can return false,
-      // even though it clearly is corrupted. A separate copy of the test
-      // inlining just the basic check seems to help.
-      corrupted = corruptedTest1
-          ? true
-          : Element._hasCorruptedAttributesAdditionalCheck(element);
-    } catch (e) {}
-    var elementText = 'element unprintable';
-    try {
-      elementText = element.toString();
-    } catch (e) {}
-    try {
-      var elementTagName = Element._safeTagName(element);
-      _sanitizeElement(element, parent, corrupted, elementText, elementTagName,
-          attrs, isAttr);
-    } on ArgumentError {
-      // Thrown by _ThrowsNodeValidator
-      rethrow;
-    } catch (e) {
-      // Unexpected exception sanitizing -> remove
-      _removeNode(element, parent);
-      window.console.warn('Removing corrupted element $elementText');
-    }
-  }
-
-  /// Having done basic sanity checking on the element, and computed the
-  /// important attributes we want to check, remove it if it's not valid
-  /// or not allowed, either as a whole or particular attributes.
-  void _sanitizeElement(Element element, Node? parent, bool corrupted,
-      String text, String tag, Map attrs, String? isAttr) {
-    if (false != corrupted) {
-      _removeNode(element, parent);
-      window.console
-          .warn('Removing element due to corrupted attributes on <$text>');
-      return;
-    }
-    if (!validator.allowsElement(element)) {
-      _removeNode(element, parent);
-      window.console.warn('Removing disallowed element <$tag> from $parent');
-      return;
-    }
-
-    if (isAttr != null) {
-      if (!validator.allowsAttribute(element, 'is', isAttr)) {
-        _removeNode(element, parent);
-        window.console.warn('Removing disallowed type extension '
-            '<$tag is="$isAttr">');
-        return;
-      }
-    }
-
-    // TODO(blois): Need to be able to get all attributes, irrespective of
-    // XMLNS.
-    var keys = attrs.keys.toList();
-    for (var i = attrs.length - 1; i >= 0; --i) {
-      var name = keys[i];
-      if (!validator.allowsAttribute(
-          element, name.toLowerCase(), attrs[name])) {
-        window.console.warn('Removing disallowed attribute '
-            '<$tag $name="${attrs[name]}">');
-        attrs.remove(name);
-      }
-    }
-
-    if (element is TemplateElement) {
-      TemplateElement template = element;
-      sanitizeTree(template.content);
-    }
-  }
-
-  /// Sanitize the node and its children recursively.
-  void sanitizeNode(Node node, Node? parent) {
-    switch (node.nodeType) {
-      case Node.ELEMENT_NODE:
-        _sanitizeUntrustedElement(node, parent);
-        break;
-      case Node.COMMENT_NODE:
-      case Node.DOCUMENT_FRAGMENT_NODE:
-      case Node.TEXT_NODE:
-      case Node.CDATA_SECTION_NODE:
-        break;
-      default:
-        _removeNode(node, parent);
-    }
-  }
-}
diff --git a/tools/dom/nnbd_src/WrappedList.dart b/tools/dom/nnbd_src/WrappedList.dart
deleted file mode 100644
index 65d0d94..0000000
--- a/tools/dom/nnbd_src/WrappedList.dart
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of dart.dom.html;
-
-/**
- * A list which just wraps another list, for either intercepting list calls or
- * retyping the list (for example, from List<A> to List<B> where B extends A).
- */
-class _WrappedList<E extends Node> extends ListBase<E>
-    implements NodeListWrapper {
-  final List<Node> _list;
-
-  _WrappedList(this._list);
-
-  // Iterable APIs
-
-  Iterator<E> get iterator => new _WrappedIterator<E>(_list.iterator);
-
-  int get length => _list.length;
-
-  // Collection APIs
-
-  void add(E element) {
-    _list.add(element);
-  }
-
-  bool remove(Object? element) => _list.remove(element);
-
-  void clear() {
-    _list.clear();
-  }
-
-  // List APIs
-
-  E operator [](int index) => _list[index] as E;
-
-  void operator []=(int index, E value) {
-    _list[index] = value;
-  }
-
-  set length(int newLength) {
-    _list.length = newLength;
-  }
-
-  void sort([int compare(E a, E b)?]) {
-    if (compare == null) {
-      _list.sort();
-    } else {
-      _list.sort((Node a, Node b) => compare(a as E, b as E));
-    }
-  }
-
-  int indexOf(Object? element, [int start = 0]) =>
-      _list.indexOf(element as Node, start);
-
-  int lastIndexOf(Object? element, [int? start]) =>
-      _list.lastIndexOf(element as Node, start);
-
-  void insert(int index, E element) => _list.insert(index, element);
-
-  E removeAt(int index) => _list.removeAt(index) as E;
-
-  void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {
-    _list.setRange(start, end, iterable, skipCount);
-  }
-
-  void removeRange(int start, int end) {
-    _list.removeRange(start, end);
-  }
-
-  void replaceRange(int start, int end, Iterable<E> iterable) {
-    _list.replaceRange(start, end, iterable);
-  }
-
-  void fillRange(int start, int end, [E? fillValue]) {
-    _list.fillRange(start, end, fillValue);
-  }
-
-  List<Node> get rawList => _list;
-}
-
-/**
- * Iterator wrapper for _WrappedList.
- */
-class _WrappedIterator<E extends Node> implements Iterator<E> {
-  Iterator<Node> _iterator;
-
-  _WrappedIterator(this._iterator);
-
-  bool moveNext() {
-    return _iterator.moveNext();
-  }
-
-  E get current => _iterator.current as E;
-}
diff --git a/tools/dom/nnbd_src/_HttpRequestUtils.dart b/tools/dom/nnbd_src/_HttpRequestUtils.dart
deleted file mode 100644
index d6e73d7..0000000
--- a/tools/dom/nnbd_src/_HttpRequestUtils.dart
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of html;
-
-class _HttpRequestUtils {
-  // Helper for factory HttpRequest.get
-  static HttpRequest get(
-      String url, onComplete(HttpRequest request), bool withCredentials) {
-    final request = new HttpRequest();
-    request.open('GET', url, async: true);
-
-    request.withCredentials = withCredentials;
-
-    request.onReadyStateChange.listen((e) {
-      if (request.readyState == HttpRequest.DONE) {
-        onComplete(request);
-      }
-    });
-
-    request.send();
-
-    return request;
-  }
-}
diff --git a/tools/dom/nnbd_src/_ListIterators.dart b/tools/dom/nnbd_src/_ListIterators.dart
deleted file mode 100644
index 74aaddc..0000000
--- a/tools/dom/nnbd_src/_ListIterators.dart
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of html;
-
-// Iterator for arrays with fixed size.
-class FixedSizeListIterator<T> implements Iterator<T> {
-  final List<T> _array;
-  final int _length; // Cache array length for faster access.
-  int _position;
-  T? _current;
-
-  FixedSizeListIterator(List<T> array)
-      : _array = array,
-        _position = -1,
-        _length = array.length;
-
-  bool moveNext() {
-    int nextPosition = _position + 1;
-    if (nextPosition < _length) {
-      _current = _array[nextPosition];
-      _position = nextPosition;
-      return true;
-    }
-    _current = null;
-    _position = _length;
-    return false;
-  }
-
-  T get current => _current as T;
-}
-
-// Iterator for arrays with variable size.
-class _VariableSizeListIterator<T> implements Iterator<T> {
-  final List<T> _array;
-  int _position;
-  T? _current;
-
-  _VariableSizeListIterator(List<T> array)
-      : _array = array,
-        _position = -1;
-
-  bool moveNext() {
-    int nextPosition = _position + 1;
-    if (nextPosition < _array.length) {
-      _current = _array[nextPosition];
-      _position = nextPosition;
-      return true;
-    }
-    _current = null;
-    _position = _array.length;
-    return false;
-  }
-
-  T get current => _current as T;
-}
diff --git a/tools/dom/nnbd_src/dart2js_Console.dart b/tools/dom/nnbd_src/dart2js_Console.dart
deleted file mode 100644
index b3297d2..0000000
--- a/tools/dom/nnbd_src/dart2js_Console.dart
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of html;
-
-class Console {
-  const Console._safe();
-  static const Console _safeConsole = const Console._safe();
-
-  bool get _isConsoleDefined => JS('bool', 'typeof console != "undefined"');
-
-  MemoryInfo? get memory =>
-      _isConsoleDefined ? JS('MemoryInfo', 'window.console.memory') : null;
-
-  void assertCondition(bool condition, Object arg) => _isConsoleDefined
-      ? JS('void', 'window.console.assertCondition(#, #)', condition, arg)
-      : null;
-
-  void clear(Object arg) =>
-      _isConsoleDefined ? JS('void', 'window.console.clear(#)', arg) : null;
-
-  void count(Object arg) =>
-      _isConsoleDefined ? JS('void', 'window.console.count(#)', arg) : null;
-
-  void debug(Object arg) =>
-      _isConsoleDefined ? JS('void', 'window.console.debug(#)', arg) : null;
-
-  void dir(Object arg) =>
-      _isConsoleDefined ? JS('void', 'window.console.dir(#)', arg) : null;
-
-  void dirxml(Object arg) =>
-      _isConsoleDefined ? JS('void', 'window.console.dirxml(#)', arg) : null;
-
-  void error(Object arg) =>
-      _isConsoleDefined ? JS('void', 'window.console.error(#)', arg) : null;
-
-  void group(Object arg) =>
-      _isConsoleDefined ? JS('void', 'window.console.group(#)', arg) : null;
-
-  void groupCollapsed(Object arg) => _isConsoleDefined
-      ? JS('void', 'window.console.groupCollapsed(#)', arg)
-      : null;
-
-  void groupEnd() =>
-      _isConsoleDefined ? JS('void', 'window.console.groupEnd()') : null;
-
-  void info(Object arg) =>
-      _isConsoleDefined ? JS('void', 'window.console.info(#)', arg) : null;
-
-  void log(Object arg) =>
-      _isConsoleDefined ? JS('void', 'window.console.log(#)', arg) : null;
-
-  void markTimeline(Object arg) => _isConsoleDefined
-      ? JS('void', 'window.console.markTimeline(#)', arg)
-      : null;
-
-  void profile(String title) =>
-      _isConsoleDefined ? JS('void', 'window.console.profile(#)', title) : null;
-
-  void profileEnd(String title) => _isConsoleDefined
-      ? JS('void', 'window.console.profileEnd(#)', title)
-      : null;
-
-  void table(Object arg) =>
-      _isConsoleDefined ? JS('void', 'window.console.table(#)', arg) : null;
-
-  void time(String title) =>
-      _isConsoleDefined ? JS('void', 'window.console.time(#)', title) : null;
-
-  void timeEnd(String title) =>
-      _isConsoleDefined ? JS('void', 'window.console.timeEnd(#)', title) : null;
-
-  void timeStamp(Object arg) =>
-      _isConsoleDefined ? JS('void', 'window.console.timeStamp(#)', arg) : null;
-
-  void trace(Object arg) =>
-      _isConsoleDefined ? JS('void', 'window.console.trace(#)', arg) : null;
-
-  void warn(Object arg) =>
-      _isConsoleDefined ? JS('void', 'window.console.warn(#)', arg) : null;
-}
diff --git a/tools/dom/nnbd_src/dart2js_Conversions.dart b/tools/dom/nnbd_src/dart2js_Conversions.dart
deleted file mode 100644
index cb943b4..0000000
--- a/tools/dom/nnbd_src/dart2js_Conversions.dart
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-// Conversions for Window.  These check if the window is the local
-// window, and if it's not, wraps or unwraps it with a secure wrapper.
-// We need to test for EventTarget here as well as it's a base type.
-// We omit an unwrapper for Window as no methods take a non-local
-// window as a parameter.
-
-part of html;
-
-WindowBase? _convertNativeToDart_Window(win) {
-  if (win == null) return null;
-  return _DOMWindowCrossFrame._createSafe(win);
-}
-
-EventTarget? _convertNativeToDart_EventTarget(e) {
-  if (e == null) {
-    return null;
-  }
-  // Assume it's a Window if it contains the postMessage property.  It may be
-  // from a different frame - without a patched prototype - so we cannot
-  // rely on Dart type checking.
-  if (JS('bool', r'"postMessage" in #', e)) {
-    var window = _DOMWindowCrossFrame._createSafe(e);
-    // If it's a native window.
-    if (window is EventTarget) {
-      return window;
-    }
-    return null;
-  } else
-    return e;
-}
-
-EventTarget? _convertDartToNative_EventTarget(e) {
-  if (e is _DOMWindowCrossFrame) {
-    return e._window;
-  } else {
-    return e;
-  }
-}
-
-_convertNativeToDart_XHR_Response(o) {
-  if (o is Document) {
-    return o;
-  }
-  return convertNativeToDart_SerializedScriptValue(o);
-}
diff --git a/tools/dom/nnbd_src/dart2js_CssClassSet.dart b/tools/dom/nnbd_src/dart2js_CssClassSet.dart
deleted file mode 100644
index 00d80bc..0000000
--- a/tools/dom/nnbd_src/dart2js_CssClassSet.dart
+++ /dev/null
@@ -1,260 +0,0 @@
-// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of html;
-
-/**
- * A set (union) of the CSS classes that are present in a set of elements.
- * Implemented separately from _ElementCssClassSet for performance.
- */
-class _MultiElementCssClassSet extends CssClassSetImpl {
-  final Iterable<Element> _elementIterable;
-
-  // TODO(sra): Perhaps we should store the DomTokenList instead.
-  final List<CssClassSetImpl> _sets;
-
-  factory _MultiElementCssClassSet(Iterable<Element> elements) {
-    return new _MultiElementCssClassSet._(elements,
-        new List<CssClassSetImpl>.from(elements.map((Element e) => e.classes)));
-  }
-
-  _MultiElementCssClassSet._(this._elementIterable, this._sets);
-
-  Set<String> readClasses() {
-    var s = new LinkedHashSet<String>();
-    _sets.forEach((CssClassSetImpl e) => s.addAll(e.readClasses()));
-    return s;
-  }
-
-  void writeClasses(Set<String> s) {
-    var classes = s.join(' ');
-    for (Element e in _elementIterable) {
-      e.className = classes;
-    }
-  }
-
-  /**
-   * Helper method used to modify the set of css classes on this element.
-   *
-   *   f - callback with:
-   *   s - a Set of all the css class name currently on this element.
-   *
-   *   After f returns, the modified set is written to the
-   *       className property of this element.
-   */
-  modify(f(Set<String> s)) {
-    _sets.forEach((CssClassSetImpl e) => e.modify(f));
-  }
-
-  /**
-   * Adds the class [value] to the element if it is not on it, removes it if it
-   * is.
-   *
-   * TODO(sra): It seems wrong to collect a 'changed' flag like this when the
-   * underlying toggle returns an 'is set' flag.
-   */
-  bool toggle(String value, [bool? shouldAdd]) => _sets.fold(
-      false,
-      (bool changed, CssClassSetImpl e) =>
-          e.toggle(value, shouldAdd) || changed);
-
-  /**
-   * Remove the class [value] from element, and return true on successful
-   * removal.
-   *
-   * This is the Dart equivalent of jQuery's
-   * [removeClass](http://api.jquery.com/removeClass/).
-   */
-  bool remove(Object? value) => _sets.fold(
-      false, (bool changed, CssClassSetImpl e) => e.remove(value) || changed);
-}
-
-class _ElementCssClassSet extends CssClassSetImpl {
-  final Element _element;
-
-  _ElementCssClassSet(this._element);
-
-  Set<String> readClasses() {
-    var s = new LinkedHashSet<String>();
-    var classname = _element.className;
-
-    for (String name in classname.split(' ')) {
-      String trimmed = name.trim();
-      if (!trimmed.isEmpty) {
-        s.add(trimmed);
-      }
-    }
-    return s;
-  }
-
-  void writeClasses(Set<String> s) {
-    _element.className = s.join(' ');
-  }
-
-  int get length => _classListLength(_classListOf(_element));
-  bool get isEmpty => length == 0;
-  bool get isNotEmpty => length != 0;
-
-  void clear() {
-    _element.className = '';
-  }
-
-  bool contains(Object? value) {
-    return _contains(_element, value);
-  }
-
-  bool add(String value) {
-    return _add(_element, value);
-  }
-
-  bool remove(Object? value) {
-    return value is String && _remove(_element, value);
-  }
-
-  bool toggle(String value, [bool? shouldAdd]) {
-    return _toggle(_element, value, shouldAdd);
-  }
-
-  void addAll(Iterable<String> iterable) {
-    _addAll(_element, iterable);
-  }
-
-  void removeAll(Iterable<Object?> iterable) {
-    _removeAll(_element, iterable);
-  }
-
-  void retainAll(Iterable<Object?> iterable) {
-    _removeWhere(_element, iterable.toSet().contains, false);
-  }
-
-  void removeWhere(bool test(String name)) {
-    _removeWhere(_element, test, true);
-  }
-
-  void retainWhere(bool test(String name)) {
-    _removeWhere(_element, test, false);
-  }
-
-  static bool _contains(Element _element, Object? value) {
-    return value is String && _classListContains(_classListOf(_element), value);
-  }
-
-  @pragma('dart2js:tryInline')
-  static bool _add(Element _element, String value) {
-    DomTokenList list = _classListOf(_element);
-    // Compute returned result independently of action upon the set.
-    bool added = !_classListContainsBeforeAddOrRemove(list, value);
-    _classListAdd(list, value);
-    return added;
-  }
-
-  @pragma('dart2js:tryInline')
-  static bool _remove(Element _element, String value) {
-    DomTokenList list = _classListOf(_element);
-    bool removed = _classListContainsBeforeAddOrRemove(list, value);
-    _classListRemove(list, value);
-    return removed;
-  }
-
-  static bool _toggle(Element _element, String value, bool? shouldAdd) {
-    // There is no value that can be passed as the second argument of
-    // DomTokenList.toggle that behaves the same as passing one argument.
-    // `null` is seen as false, meaning 'remove'.
-    return shouldAdd == null
-        ? _toggleDefault(_element, value)
-        : _toggleOnOff(_element, value, shouldAdd);
-  }
-
-  static bool _toggleDefault(Element _element, String value) {
-    DomTokenList list = _classListOf(_element);
-    return _classListToggle1(list, value);
-  }
-
-  static bool _toggleOnOff(Element _element, String value, bool? shouldAdd) {
-    DomTokenList list = _classListOf(_element);
-    // IE's toggle does not take a second parameter. We would prefer:
-    //
-    //    return _classListToggle2(list, value, shouldAdd);
-    //
-    if (shouldAdd ?? false) {
-      _classListAdd(list, value);
-      return true;
-    } else {
-      _classListRemove(list, value);
-      return false;
-    }
-  }
-
-  static void _addAll(Element _element, Iterable<String> iterable) {
-    DomTokenList list = _classListOf(_element);
-    for (String value in iterable) {
-      _classListAdd(list, value);
-    }
-  }
-
-  static void _removeAll(Element _element, Iterable<Object?> iterable) {
-    DomTokenList list = _classListOf(_element);
-    for (Object? value in iterable) {
-      _classListRemove(list, value as String);
-    }
-  }
-
-  static void _removeWhere(
-      Element _element, bool test(String name), bool doRemove) {
-    DomTokenList list = _classListOf(_element);
-    int i = 0;
-    while (i < _classListLength(list)) {
-      String item = list.item(i)!;
-      if (doRemove == test(item)) {
-        _classListRemove(list, item);
-      } else {
-        ++i;
-      }
-    }
-  }
-
-  // A collection of static methods for DomTokenList. These methods are a
-  // work-around for the lack of annotations to express the full behaviour of
-  // the DomTokenList methods.
-
-  static DomTokenList _classListOf(Element e) => JS(
-      'returns:DomTokenList;creates:DomTokenList;effects:none;depends:all;',
-      '#.classList',
-      e);
-
-  static int _classListLength(DomTokenList list) =>
-      JS('returns:JSUInt31;effects:none;depends:all;', '#.length', list);
-
-  static bool _classListContains(DomTokenList list, String value) =>
-      JS('returns:bool;effects:none;depends:all', '#.contains(#)', list, value);
-
-  static bool _classListContainsBeforeAddOrRemove(
-          DomTokenList list, String value) =>
-      // 'throws:never' is a lie, since 'contains' will throw on an illegal
-      // token.  However, we always call this function immediately prior to
-      // add/remove/toggle with the same token.  Often the result of 'contains'
-      // is unused and the lie makes it possible for the 'contains' instruction
-      // to be removed.
-      JS('returns:bool;effects:none;depends:all;throws:null(1)',
-          '#.contains(#)', list, value);
-
-  static void _classListAdd(DomTokenList list, String value) {
-    // list.add(value);
-    JS('', '#.add(#)', list, value);
-  }
-
-  static void _classListRemove(DomTokenList list, String value) {
-    // list.remove(value);
-    JS('', '#.remove(#)', list, value);
-  }
-
-  static bool _classListToggle1(DomTokenList list, String value) {
-    return JS('bool', '#.toggle(#)', list, value);
-  }
-
-  static bool _classListToggle2(
-      DomTokenList list, String value, bool? shouldAdd) {
-    return JS('bool', '#.toggle(#, #)', list, value, shouldAdd);
-  }
-}
diff --git a/tools/dom/nnbd_src/dart2js_CustomElementSupport.dart b/tools/dom/nnbd_src/dart2js_CustomElementSupport.dart
deleted file mode 100644
index bbe6a37..0000000
--- a/tools/dom/nnbd_src/dart2js_CustomElementSupport.dart
+++ /dev/null
@@ -1,214 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of dart.dom.html;
-
-_callConstructor(constructor, interceptor) {
-  return (receiver) {
-    setNativeSubclassDispatchRecord(receiver, interceptor);
-
-    // Mirrors uses the constructor property to cache lookups, so we need it to
-    // be set correctly, including on IE where it is not automatically picked
-    // up from the __proto__.
-    JS('', '#.constructor = #.__proto__.constructor', receiver, receiver);
-    return JS('', '#(#)', constructor, receiver);
-  };
-}
-
-_callAttached(receiver) {
-  return receiver.attached();
-}
-
-_callDetached(receiver) {
-  return receiver.detached();
-}
-
-_callAttributeChanged(receiver, name, oldValue, newValue) {
-  return receiver.attributeChanged(name, oldValue, newValue);
-}
-
-_makeCallbackMethod(callback) {
-  return JS(
-      '',
-      '''((function(invokeCallback) {
-             return function() {
-               return invokeCallback(this);
-             };
-          })(#))''',
-      convertDartClosureToJS(callback, 1));
-}
-
-_makeCallbackMethod3(callback) {
-  return JS(
-      '',
-      '''((function(invokeCallback) {
-             return function(arg1, arg2, arg3) {
-               return invokeCallback(this, arg1, arg2, arg3);
-             };
-          })(#))''',
-      convertDartClosureToJS(callback, 4));
-}
-
-/// Checks whether the given [element] correctly extends from the native class
-/// with the given [baseClassName]. This method will throw if the base class
-/// doesn't match, except when the element extends from `template` and it's base
-/// class is `HTMLUnknownElement`. This exclusion is needed to support extension
-/// of template elements (used heavily in Polymer 1.0) on IE11 when using the
-/// webcomponents-lite.js polyfill.
-void _checkExtendsNativeClassOrTemplate(
-    Element element, String extendsTag, String baseClassName) {
-  if (!JS('bool', '(# instanceof window[#])', element, baseClassName) &&
-      !((extendsTag == 'template' &&
-          JS('bool', '(# instanceof window["HTMLUnknownElement"])',
-              element)))) {
-    throw new UnsupportedError('extendsTag does not match base native class');
-  }
-}
-
-Function _registerCustomElement(context, document, String tag, [Map? options]) {
-  // Function follows the same pattern as the following JavaScript code for
-  // registering a custom element.
-  //
-  //    var proto = Object.create(HTMLElement.prototype, {
-  //        createdCallback: {
-  //          value: function() {
-  //            window.console.log('here');
-  //          }
-  //        }
-  //    });
-  //    document.registerElement('x-foo', { prototype: proto });
-  //    ...
-  //    var e = document.createElement('x-foo');
-
-  var extendsTagName = '';
-  Type? type;
-  if (options != null) {
-    extendsTagName = options['extends'];
-    type = options['prototype'];
-  }
-
-  var interceptorClass = findInterceptorConstructorForType(type);
-  if (interceptorClass == null) {
-    throw new ArgumentError(type);
-  }
-
-  var interceptor = JS('=Object', '#.prototype', interceptorClass);
-
-  var constructor = findConstructorForNativeSubclassType(type, 'created');
-  if (constructor == null) {
-    throw new ArgumentError("$type has no constructor called 'created'");
-  }
-
-  // Workaround for 13190- use an article element to ensure that HTMLElement's
-  // interceptor is resolved correctly.
-  getNativeInterceptor(new Element.tag('article'));
-
-  String baseClassName = findDispatchTagForInterceptorClass(interceptorClass);
-  if (baseClassName == null) {
-    throw new ArgumentError(type);
-  }
-
-  if (extendsTagName == null) {
-    if (baseClassName != 'HTMLElement') {
-      throw new UnsupportedError('Class must provide extendsTag if base '
-          'native class is not HtmlElement');
-    }
-  } else {
-    var element = document.createElement(extendsTagName);
-    _checkExtendsNativeClassOrTemplate(element, extendsTagName, baseClassName);
-  }
-
-  var baseConstructor = JS('=Object', '#[#]', context, baseClassName);
-
-  var properties = JS('=Object', '{}');
-
-  JS(
-      'void',
-      '#.createdCallback = #',
-      properties,
-      JS('=Object', '{value: #}',
-          _makeCallbackMethod(_callConstructor(constructor, interceptor))));
-  JS('void', '#.attachedCallback = #', properties,
-      JS('=Object', '{value: #}', _makeCallbackMethod(_callAttached)));
-  JS('void', '#.detachedCallback = #', properties,
-      JS('=Object', '{value: #}', _makeCallbackMethod(_callDetached)));
-  JS('void', '#.attributeChangedCallback = #', properties,
-      JS('=Object', '{value: #}', _makeCallbackMethod3(_callAttributeChanged)));
-
-  var baseProto = JS('=Object', '#.prototype', baseConstructor);
-  var proto = JS('=Object', 'Object.create(#, #)', baseProto, properties);
-
-  setNativeSubclassDispatchRecord(proto, interceptor);
-
-  var opts = JS('=Object', '{prototype: #}', proto);
-
-  if (extendsTagName != null) {
-    JS('=Object', '#.extends = #', opts, extendsTagName);
-  }
-
-  return JS(
-      'JavaScriptFunction', '#.registerElement(#, #)', document, tag, opts);
-}
-
-//// Called by Element.created to do validation & initialization.
-void _initializeCustomElement(Element e) {
-  // TODO(blois): Add validation that this is only in response to an upgrade.
-}
-
-/// Dart2JS implementation of ElementUpgrader
-class _JSElementUpgrader implements ElementUpgrader {
-  var _interceptor;
-  var _constructor;
-  var _nativeType;
-
-  _JSElementUpgrader(Document document, Type type, String? extendsTag) {
-    var interceptorClass = findInterceptorConstructorForType(type);
-    if (interceptorClass == null) {
-      throw new ArgumentError(type);
-    }
-
-    _constructor = findConstructorForNativeSubclassType(type, 'created');
-    if (_constructor == null) {
-      throw new ArgumentError("$type has no constructor called 'created'");
-    }
-
-    // Workaround for 13190- use an article element to ensure that HTMLElement's
-    // interceptor is resolved correctly.
-    getNativeInterceptor(new Element.tag('article'));
-
-    var baseClassName = findDispatchTagForInterceptorClass(interceptorClass);
-    if (baseClassName == null) {
-      throw new ArgumentError(type);
-    }
-
-    if (extendsTag == null) {
-      if (baseClassName != 'HTMLElement') {
-        throw new UnsupportedError('Class must provide extendsTag if base '
-            'native class is not HtmlElement');
-      }
-      _nativeType = HtmlElement;
-    } else {
-      var element = document.createElement(extendsTag);
-      _checkExtendsNativeClassOrTemplate(element, extendsTag, baseClassName);
-      _nativeType = element.runtimeType;
-    }
-
-    _interceptor = JS('=Object', '#.prototype', interceptorClass);
-  }
-
-  Element upgrade(Element element) {
-    // Only exact type matches are supported- cannot be a subclass.
-    if (element.runtimeType != _nativeType) {
-      // Some browsers may represent non-upgraded elements <x-foo> as
-      // UnknownElement and not a plain HtmlElement.
-      if (_nativeType != HtmlElement || element.runtimeType != UnknownElement) {
-        throw new ArgumentError('element is not subclass of $_nativeType');
-      }
-    }
-
-    setNativeSubclassDispatchRecord(element, _interceptor);
-    JS('', '#(#)', _constructor, element);
-    return element;
-  }
-}
diff --git a/tools/dom/nnbd_src/dart2js_DOMImplementation.dart b/tools/dom/nnbd_src/dart2js_DOMImplementation.dart
deleted file mode 100644
index 8016f6e..0000000
--- a/tools/dom/nnbd_src/dart2js_DOMImplementation.dart
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of html;
-
-// TODO(vsm): Unify with Dartium version.
-class _DOMWindowCrossFrame implements WindowBase {
-  // Private window.  Note, this is a window in another frame, so it
-  // cannot be typed as "Window" as its prototype is not patched
-  // properly.  Its fields and methods can only be accessed via JavaScript.
-  final _window;
-
-  // Fields.
-  HistoryBase get history =>
-      _HistoryCrossFrame._createSafe(JS('HistoryBase', '#.history', _window));
-  LocationBase get location => _LocationCrossFrame._createSafe(
-      JS('LocationBase', '#.location', _window));
-
-  // TODO(vsm): Add frames to navigate subframes.  See 2312.
-
-  bool get closed => JS('bool', '#.closed', _window);
-
-  WindowBase get opener => _createSafe(JS('WindowBase', '#.opener', _window));
-
-  WindowBase get parent => _createSafe(JS('WindowBase', '#.parent', _window));
-
-  WindowBase get top => _createSafe(JS('WindowBase', '#.top', _window));
-
-  // Methods.
-  void close() => JS('void', '#.close()', _window);
-
-  void postMessage(var message, String targetOrigin, [List? messagePorts]) {
-    if (messagePorts == null) {
-      JS('void', '#.postMessage(#,#)', _window,
-          convertDartToNative_SerializedScriptValue(message), targetOrigin);
-    } else {
-      JS(
-          'void',
-          '#.postMessage(#,#,#)',
-          _window,
-          convertDartToNative_SerializedScriptValue(message),
-          targetOrigin,
-          messagePorts);
-    }
-  }
-
-  // Implementation support.
-  _DOMWindowCrossFrame(this._window);
-
-  static WindowBase _createSafe(w) {
-    if (identical(w, window)) {
-      return w;
-    } else {
-      // TODO(vsm): Cache or implement equality.
-      registerGlobalObject(w);
-      return new _DOMWindowCrossFrame(w);
-    }
-  }
-
-  // TODO(efortuna): Remove this method. dartbug.com/16814
-  Events get on => throw new UnsupportedError(
-      'You can only attach EventListeners to your own window.');
-  // TODO(efortuna): Remove this method. dartbug.com/16814
-  void _addEventListener(String? type, EventListener? listener,
-          [bool? useCapture]) =>
-      throw new UnsupportedError(
-          'You can only attach EventListeners to your own window.');
-  // TODO(efortuna): Remove this method. dartbug.com/16814
-  void addEventListener(String type, EventListener? listener,
-          [bool? useCapture]) =>
-      throw new UnsupportedError(
-          'You can only attach EventListeners to your own window.');
-  // TODO(efortuna): Remove this method. dartbug.com/16814
-  bool dispatchEvent(Event event) => throw new UnsupportedError(
-      'You can only attach EventListeners to your own window.');
-  // TODO(efortuna): Remove this method. dartbug.com/16814
-  void _removeEventListener(String? type, EventListener? listener,
-          [bool? useCapture]) =>
-      throw new UnsupportedError(
-          'You can only attach EventListeners to your own window.');
-  // TODO(efortuna): Remove this method. dartbug.com/16814
-  void removeEventListener(String type, EventListener? listener,
-          [bool? useCapture]) =>
-      throw new UnsupportedError(
-          'You can only attach EventListeners to your own window.');
-}
-
-class _LocationCrossFrame implements LocationBase {
-  // Private location.  Note, this is a location object in another frame, so it
-  // cannot be typed as "Location" as its prototype is not patched
-  // properly.  Its fields and methods can only be accessed via JavaScript.
-  var _location;
-
-  set href(String val) => _setHref(_location, val);
-  static void _setHref(location, val) {
-    JS('void', '#.href = #', location, val);
-  }
-
-  // Implementation support.
-  _LocationCrossFrame(this._location);
-
-  static LocationBase _createSafe(location) {
-    if (identical(location, window.location)) {
-      return location;
-    } else {
-      // TODO(vsm): Cache or implement equality.
-      return new _LocationCrossFrame(location);
-    }
-  }
-}
-
-class _HistoryCrossFrame implements HistoryBase {
-  // Private history.  Note, this is a history object in another frame, so it
-  // cannot be typed as "History" as its prototype is not patched
-  // properly.  Its fields and methods can only be accessed via JavaScript.
-  var _history;
-
-  void back() => JS('void', '#.back()', _history);
-
-  void forward() => JS('void', '#.forward()', _history);
-
-  void go(int distance) => JS('void', '#.go(#)', _history, distance);
-
-  // Implementation support.
-  _HistoryCrossFrame(this._history);
-
-  static HistoryBase _createSafe(h) {
-    if (identical(h, window.history)) {
-      return h;
-    } else {
-      // TODO(vsm): Cache or implement equality.
-      return new _HistoryCrossFrame(h);
-    }
-  }
-}
diff --git a/tools/dom/nnbd_src/dart2js_KeyEvent.dart b/tools/dom/nnbd_src/dart2js_KeyEvent.dart
deleted file mode 100644
index 422c7ad..0000000
--- a/tools/dom/nnbd_src/dart2js_KeyEvent.dart
+++ /dev/null
@@ -1,243 +0,0 @@
-/**
- * A custom KeyboardEvent that attempts to eliminate cross-browser
- * inconsistencies, and also provide both keyCode and charCode information
- * for all key events (when such information can be determined).
- *
- * KeyEvent tries to provide a higher level, more polished keyboard event
- * information on top of the "raw" [KeyboardEvent].
- *
- * The mechanics of using KeyEvents is a little different from the underlying
- * [KeyboardEvent]. To use KeyEvents, you need to create a stream and then add
- * KeyEvents to the stream, rather than using the [EventTarget.dispatchEvent].
- * Here's an example usage:
- *
- *     // Initialize a stream for the KeyEvents:
- *     var stream = KeyEvent.keyPressEvent.forTarget(document.body);
- *     // Start listening to the stream of KeyEvents.
- *     stream.listen((keyEvent) =>
- *         window.console.log('KeyPress event detected ${keyEvent.charCode}'));
- *     ...
- *     // Add a new KeyEvent of someone pressing the 'A' key to the stream so
- *     // listeners can know a KeyEvent happened.
- *     stream.add(new KeyEvent('keypress', keyCode: 65, charCode: 97));
- *
- * This class is very much a work in progress, and we'd love to get information
- * on how we can make this class work with as many international keyboards as
- * possible. Bugs welcome!
- */
-class KeyEvent extends _WrappedEvent implements KeyboardEvent {
-  /** The parent KeyboardEvent that this KeyEvent is wrapping and "fixing". */
-  KeyboardEvent _parent;
-
-  /** The "fixed" value of whether the alt key is being pressed. */
-  bool _shadowAltKey;
-
-  /** Calculated value of what the estimated charCode is for this event. */
-  int _shadowCharCode;
-
-  /** Calculated value of what the estimated keyCode is for this event. */
-  int _shadowKeyCode;
-
-  /** Calculated value of what the estimated keyCode is for this event. */
-  int get keyCode => _shadowKeyCode;
-
-  /** Calculated value of what the estimated charCode is for this event. */
-  int get charCode => this.type == 'keypress' ? _shadowCharCode : 0;
-
-  /** Calculated value of whether the alt key is pressed is for this event. */
-  bool get altKey => _shadowAltKey;
-
-  /** Calculated value of what the estimated keyCode is for this event. */
-  int get which => keyCode;
-
-  /** Accessor to the underlying keyCode value is the parent event. */
-  int get _realKeyCode => JS('int', '#.keyCode', _parent);
-
-  /** Accessor to the underlying charCode value is the parent event. */
-  int get _realCharCode => JS('int', '#.charCode', _parent);
-
-  /** Accessor to the underlying altKey value is the parent event. */
-  bool get _realAltKey => JS('bool', '#.altKey', _parent);
-
-  /** Shadows on top of the parent's currentTarget. */
-  EventTarget? _currentTarget;
-
-  InputDeviceCapabilities? get sourceCapabilities =>
-      JS('InputDeviceCapabilities', '#.sourceCapabilities', this);
-
-  /**
-   * The value we want to use for this object's dispatch. Created here so it is
-   * only invoked once.
-   */
-  static final _keyboardEventDispatchRecord = _makeRecord();
-
-  /** Helper to statically create the dispatch record. */
-  static _makeRecord() {
-    var interceptor = JS_INTERCEPTOR_CONSTANT(KeyboardEvent);
-    return makeLeafDispatchRecord(interceptor);
-  }
-
-  /** Construct a KeyEvent with [parent] as the event we're emulating. */
-  KeyEvent.wrap(KeyboardEvent parent)
-      : _parent = parent,
-        _shadowAltKey = false,
-        _shadowCharCode = 0,
-        _shadowKeyCode = 0,
-        super(parent) {
-    _parent = parent;
-    _shadowAltKey = _realAltKey;
-    _shadowCharCode = _realCharCode;
-    _shadowKeyCode = _realKeyCode;
-    _currentTarget = _parent.currentTarget;
-  }
-
-  /** Programmatically create a new KeyEvent (and KeyboardEvent). */
-  factory KeyEvent(String type,
-      {Window? view,
-      bool canBubble: true,
-      bool cancelable: true,
-      int keyCode: 0,
-      int charCode: 0,
-      int location: 1,
-      bool ctrlKey: false,
-      bool altKey: false,
-      bool shiftKey: false,
-      bool metaKey: false,
-      EventTarget? currentTarget}) {
-    if (view == null) {
-      view = window;
-    }
-
-    dynamic eventObj;
-
-    // Currently this works on everything but Safari. Safari throws an
-    // "Attempting to change access mechanism for an unconfigurable property"
-    // TypeError when trying to do the Object.defineProperty hack, so we avoid
-    // this branch if possible.
-    // Also, if we want this branch to work in FF, we also need to modify
-    // _initKeyboardEvent to also take charCode and keyCode values to
-    // initialize initKeyEvent.
-
-    eventObj = new Event.eventType('KeyboardEvent', type,
-        canBubble: canBubble, cancelable: cancelable);
-
-    // Chromium Hack
-    JS(
-        'void',
-        "Object.defineProperty(#, 'keyCode', {"
-            "  get : function() { return this.keyCodeVal; } })",
-        eventObj);
-    JS(
-        'void',
-        "Object.defineProperty(#, 'which', {"
-            "  get : function() { return this.keyCodeVal; } })",
-        eventObj);
-    JS(
-        'void',
-        "Object.defineProperty(#, 'charCode', {"
-            "  get : function() { return this.charCodeVal; } })",
-        eventObj);
-
-    var keyIdentifier = _convertToHexString(charCode, keyCode);
-    eventObj._initKeyboardEvent(type, canBubble, cancelable, view,
-        keyIdentifier, location, ctrlKey, altKey, shiftKey, metaKey);
-    JS('void', '#.keyCodeVal = #', eventObj, keyCode);
-    JS('void', '#.charCodeVal = #', eventObj, charCode);
-
-    // Tell dart2js that it smells like a KeyboardEvent!
-    setDispatchProperty(eventObj, _keyboardEventDispatchRecord);
-
-    var keyEvent = new KeyEvent.wrap(eventObj);
-    if (keyEvent._currentTarget == null) {
-      keyEvent._currentTarget = currentTarget == null ? window : currentTarget;
-    }
-    return keyEvent;
-  }
-
-  // Currently known to work on all browsers but IE.
-  static bool get canUseDispatchEvent => JS(
-      'bool',
-      '(typeof document.body.dispatchEvent == "function")'
-          '&& document.body.dispatchEvent.length > 0');
-
-  /** The currently registered target for this event. */
-  EventTarget? get currentTarget => _currentTarget;
-
-  // This is an experimental method to be sure.
-  static String _convertToHexString(int charCode, int keyCode) {
-    if (charCode != -1) {
-      var hex = charCode.toRadixString(16); // Convert to hexadecimal.
-      StringBuffer sb = new StringBuffer('U+');
-      for (int i = 0; i < 4 - hex.length; i++) sb.write('0');
-      sb.write(hex);
-      return sb.toString();
-    } else {
-      return KeyCode._convertKeyCodeToKeyName(keyCode);
-    }
-  }
-
-  // TODO(efortuna): If KeyEvent is sufficiently successful that we want to make
-  // it the default keyboard event handling, move these methods over to Element.
-  /** Accessor to provide a stream of KeyEvents on the desired target. */
-  static EventStreamProvider<KeyEvent> keyDownEvent =
-      new _KeyboardEventHandler('keydown');
-  /** Accessor to provide a stream of KeyEvents on the desired target. */
-  static EventStreamProvider<KeyEvent> keyUpEvent =
-      new _KeyboardEventHandler('keyup');
-  /** Accessor to provide a stream of KeyEvents on the desired target. */
-  static EventStreamProvider<KeyEvent> keyPressEvent =
-      new _KeyboardEventHandler('keypress');
-
-  String get code => _parent.code;
-  /** True if the ctrl key is pressed during this event. */
-  bool get ctrlKey => _parent.ctrlKey;
-  int get detail => _parent.detail;
-  bool get isComposing => _parent.isComposing;
-  String get key => _parent.key;
-  /**
-   * Accessor to the part of the keyboard that the key was pressed from (one of
-   * KeyLocation.STANDARD, KeyLocation.RIGHT, KeyLocation.LEFT,
-   * KeyLocation.NUMPAD, KeyLocation.MOBILE, KeyLocation.JOYSTICK).
-   */
-  int get location => _parent.location;
-  /** True if the Meta (or Mac command) key is pressed during this event. */
-  bool get metaKey => _parent.metaKey;
-  /** True if the shift key was pressed during this event. */
-  bool get shiftKey => _parent.shiftKey;
-  WindowBase? get view => _parent.view;
-  void _initUIEvent(
-      String type, bool canBubble, bool cancelable, Window? view, int detail) {
-    throw new UnsupportedError("Cannot initialize a UI Event from a KeyEvent.");
-  }
-
-  String get _shadowKeyIdentifier => JS('String', '#.keyIdentifier', _parent);
-
-  int get _charCode => charCode;
-  int get _keyCode => keyCode;
-  int get _which => which;
-
-  String get _keyIdentifier {
-    throw new UnsupportedError("keyIdentifier is unsupported.");
-  }
-
-  void _initKeyboardEvent(
-      String type,
-      bool canBubble,
-      bool cancelable,
-      Window? view,
-      String keyIdentifier,
-      int? location,
-      bool ctrlKey,
-      bool altKey,
-      bool shiftKey,
-      bool metaKey) {
-    throw new UnsupportedError(
-        "Cannot initialize a KeyboardEvent from a KeyEvent.");
-  }
-
-  bool getModifierState(String keyArgument) => throw new UnimplementedError();
-
-  bool get repeat => throw new UnimplementedError();
-  bool get isComposed => throw new UnimplementedError();
-  dynamic get _get_view => throw new UnimplementedError();
-}
diff --git a/tools/dom/nnbd_src/dart2js_Platform.dart b/tools/dom/nnbd_src/dart2js_Platform.dart
deleted file mode 100644
index 995f4f4..0000000
--- a/tools/dom/nnbd_src/dart2js_Platform.dart
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of html;
-
-class Platform {
-  /**
-   * Returns true if dart:typed_data types are supported on this
-   * browser.  If false, using these types will generate a runtime
-   * error.
-   */
-  static final bool supportsTypedData = JS('bool', '!!(window.ArrayBuffer)');
-
-  /**
-   * Returns true if SIMD types in dart:typed_data types are supported
-   * on this browser.  If false, using these types will generate a runtime
-   * error.
-   */
-  static final supportsSimd = false;
-}
diff --git a/tools/dom/nnbd_src/dart2js_TypedArrayFactoryProvider.dart b/tools/dom/nnbd_src/dart2js_TypedArrayFactoryProvider.dart
deleted file mode 100644
index 58112a7..0000000
--- a/tools/dom/nnbd_src/dart2js_TypedArrayFactoryProvider.dart
+++ /dev/null
@@ -1,154 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of html;
-
-class _TypedArrayFactoryProvider {
-  static ByteData createByteData(int length) => _B8(length);
-  static ByteData createByteData_fromBuffer(ByteBuffer buffer,
-      [int byteOffset = 0, int length]) {
-    if (length == null) return _B8_2(buffer, byteOffset);
-    return _B8_3(buffer, byteOffset, length);
-  }
-
-  static Float32List createFloat32List(int length) => _F32(length);
-  static Float32List createFloat32List_fromList(List<num> list) =>
-      _F32(ensureNative(list));
-  static Float32List createFloat32List_fromBuffer(ByteBuffer buffer,
-      [int byteOffset = 0, int length]) {
-    if (length == null) return _F32_2(buffer, byteOffset);
-    return _F32_3(buffer, byteOffset, length);
-  }
-
-  static Float64List createFloat64List(int length) => _F64(length);
-  static Float64List createFloat64List_fromList(List<num> list) =>
-      _F64(ensureNative(list));
-  static Float64List createFloat64List_fromBuffer(ByteBuffer buffer,
-      [int byteOffset = 0, int length]) {
-    if (length == null) return _F64_2(buffer, byteOffset);
-    return _F64_3(buffer, byteOffset, length);
-  }
-
-  static Int8List createInt8List(int length) => _I8(length);
-  static Int8List createInt8List_fromList(List<num> list) =>
-      _I8(ensureNative(list));
-  static Int8List createInt8List_fromBuffer(ByteBuffer buffer,
-      [int byteOffset = 0, int length]) {
-    if (length == null) return _I8_2(buffer, byteOffset);
-    return _I8_3(buffer, byteOffset, length);
-  }
-
-  static Int16List createInt16List(int length) => _I16(length);
-  static Int16List createInt16List_fromList(List<num> list) =>
-      _I16(ensureNative(list));
-  static Int16List createInt16List_fromBuffer(ByteBuffer buffer,
-      [int byteOffset = 0, int length]) {
-    if (length == null) return _I16_2(buffer, byteOffset);
-    return _I16_3(buffer, byteOffset, length);
-  }
-
-  static Int32List createInt32List(int length) => _I32(length);
-  static Int32List createInt32List_fromList(List<num> list) =>
-      _I32(ensureNative(list));
-  static Int32List createInt32List_fromBuffer(ByteBuffer buffer,
-      [int byteOffset = 0, int length]) {
-    if (length == null) return _I32_2(buffer, byteOffset);
-    return _I32_3(buffer, byteOffset, length);
-  }
-
-  static Uint8List createUint8List(int length) => _U8(length);
-  static Uint8List createUint8List_fromList(List<num> list) =>
-      _U8(ensureNative(list));
-  static Uint8List createUint8List_fromBuffer(ByteBuffer buffer,
-      [int byteOffset = 0, int length]) {
-    if (length == null) return _U8_2(buffer, byteOffset);
-    return _U8_3(buffer, byteOffset, length);
-  }
-
-  static Uint16List createUint16List(int length) => _U16(length);
-  static Uint16List createUint16List_fromList(List<num> list) =>
-      _U16(ensureNative(list));
-  static Uint16List createUint16List_fromBuffer(ByteBuffer buffer,
-      [int byteOffset = 0, int length]) {
-    if (length == null) return _U16_2(buffer, byteOffset);
-    return _U16_3(buffer, byteOffset, length);
-  }
-
-  static Uint32List createUint32List(int length) => _U32(length);
-  static Uint32List createUint32List_fromList(List<num> list) =>
-      _U32(ensureNative(list));
-  static Uint32List createUint32List_fromBuffer(ByteBuffer buffer,
-      [int byteOffset = 0, int length]) {
-    if (length == null) return _U32_2(buffer, byteOffset);
-    return _U32_3(buffer, byteOffset, length);
-  }
-
-  static Uint8ClampedList createUint8ClampedList(int length) => _U8C(length);
-  static Uint8ClampedList createUint8ClampedList_fromList(List<num> list) =>
-      _U8C(ensureNative(list));
-  static Uint8ClampedList createUint8ClampedList_fromBuffer(ByteBuffer buffer,
-      [int byteOffset = 0, int length]) {
-    if (length == null) return _U8C_2(buffer, byteOffset);
-    return _U8C_3(buffer, byteOffset, length);
-  }
-
-  static ByteData _B8(arg) =>
-      JS('ByteData', 'new DataView(new ArrayBuffer(#))', arg);
-  static Float32List _F32(arg) => JS('Float32List', 'new Float32Array(#)', arg);
-  static Float64List _F64(arg) => JS('Float64List', 'new Float64Array(#)', arg);
-  static Int8List _I8(arg) => JS('Int8List', 'new Int8Array(#)', arg);
-  static Int16List _I16(arg) => JS('Int16List', 'new Int16Array(#)', arg);
-  static Int32List _I32(arg) => JS('Int32List', 'new Int32Array(#)', arg);
-  static Uint8List _U8(arg) => JS('Uint8List', 'new Uint8Array(#)', arg);
-  static Uint16List _U16(arg) => JS('Uint16List', 'new Uint16Array(#)', arg);
-  static Uint32List _U32(arg) => JS('Uint32List', 'new Uint32Array(#)', arg);
-  static Uint8ClampedList _U8C(arg) =>
-      JS('Uint8ClampedList', 'new Uint8ClampedArray(#)', arg);
-
-  static ByteData _B8_2(arg1, arg2) =>
-      JS('ByteData', 'new DataView(#, #)', arg1, arg2);
-  static Float32List _F32_2(arg1, arg2) =>
-      JS('Float32List', 'new Float32Array(#, #)', arg1, arg2);
-  static Float64List _F64_2(arg1, arg2) =>
-      JS('Float64List', 'new Float64Array(#, #)', arg1, arg2);
-  static Int8List _I8_2(arg1, arg2) =>
-      JS('Int8List', 'new Int8Array(#, #)', arg1, arg2);
-  static Int16List _I16_2(arg1, arg2) =>
-      JS('Int16List', 'new Int16Array(#, #)', arg1, arg2);
-  static Int32List _I32_2(arg1, arg2) =>
-      JS('Int32List', 'new Int32Array(#, #)', arg1, arg2);
-  static Uint8List _U8_2(arg1, arg2) =>
-      JS('Uint8List', 'new Uint8Array(#, #)', arg1, arg2);
-  static Uint16List _U16_2(arg1, arg2) =>
-      JS('Uint16List', 'new Uint16Array(#, #)', arg1, arg2);
-  static Uint32List _U32_2(arg1, arg2) =>
-      JS('Uint32List', 'new Uint32Array(#, #)', arg1, arg2);
-  static Uint8ClampedList _U8C_2(arg1, arg2) =>
-      JS('Uint8ClampedList', 'new Uint8ClampedArray(#, #)', arg1, arg2);
-
-  static ByteData _B8_3(arg1, arg2, arg3) =>
-      JS('ByteData', 'new DataView(#, #, #)', arg1, arg2, arg3);
-  static Float32List _F32_3(arg1, arg2, arg3) =>
-      JS('Float32List', 'new Float32Array(#, #, #)', arg1, arg2, arg3);
-  static Float64List _F64_3(arg1, arg2, arg3) =>
-      JS('Float64List', 'new Float64Array(#, #, #)', arg1, arg2, arg3);
-  static Int8List _I8_3(arg1, arg2, arg3) =>
-      JS('Int8List', 'new Int8Array(#, #, #)', arg1, arg2, arg3);
-  static Int16List _I16_3(arg1, arg2, arg3) =>
-      JS('Int16List', 'new Int16Array(#, #, #)', arg1, arg2, arg3);
-  static Int32List _I32_3(arg1, arg2, arg3) =>
-      JS('Int32List', 'new Int32Array(#, #, #)', arg1, arg2, arg3);
-  static Uint8List _U8_3(arg1, arg2, arg3) =>
-      JS('Uint8List', 'new Uint8Array(#, #, #)', arg1, arg2, arg3);
-  static Uint16List _U16_3(arg1, arg2, arg3) =>
-      JS('Uint16List', 'new Uint16Array(#, #, #)', arg1, arg2, arg3);
-  static Uint32List _U32_3(arg1, arg2, arg3) =>
-      JS('Uint32List', 'new Uint32Array(#, #, #)', arg1, arg2, arg3);
-  static Uint8ClampedList _U8C_3(arg1, arg2, arg3) => JS(
-      'Uint8ClampedList', 'new Uint8ClampedArray(#, #, #)', arg1, arg2, arg3);
-
-  // Ensures that [list] is a JavaScript Array or a typed array.  If necessary,
-  // copies the list.
-  static ensureNative(List list) => list; // TODO: make sure.
-}
diff --git a/tools/dom/nnbd_src/dart2js_WrappedEvent.dart b/tools/dom/nnbd_src/dart2js_WrappedEvent.dart
deleted file mode 100644
index dff9e38..0000000
--- a/tools/dom/nnbd_src/dart2js_WrappedEvent.dart
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of dart.html;
-
-/**
- * Helper class to implement custom events which wrap DOM events.
- */
-class _WrappedEvent implements Event {
-  final Event wrapped;
-
-  /** The CSS selector involved with event delegation. */
-  String? _selector;
-
-  _WrappedEvent(this.wrapped);
-
-  bool get bubbles => wrapped.bubbles;
-
-  bool get cancelable => wrapped.cancelable;
-
-  bool get composed => wrapped.composed;
-
-  EventTarget? get currentTarget => wrapped.currentTarget;
-
-  bool get defaultPrevented => wrapped.defaultPrevented;
-
-  int get eventPhase => wrapped.eventPhase;
-
-  bool get isTrusted => wrapped.isTrusted;
-
-  EventTarget? get target => wrapped.target;
-
-  double get timeStamp => wrapped.timeStamp as double;
-
-  String get type => wrapped.type;
-
-  void _initEvent(String type, [bool? bubbles, bool? cancelable]) {
-    throw new UnsupportedError('Cannot initialize this Event.');
-  }
-
-  void preventDefault() {
-    wrapped.preventDefault();
-  }
-
-  void stopImmediatePropagation() {
-    wrapped.stopImmediatePropagation();
-  }
-
-  void stopPropagation() {
-    wrapped.stopPropagation();
-  }
-
-  List<EventTarget> composedPath() => wrapped.composedPath();
-
-  /**
-   * A pointer to the element whose CSS selector matched within which an event
-   * was fired. If this Event was not associated with any Event delegation,
-   * accessing this value will throw an [UnsupportedError].
-   */
-  Element get matchingTarget {
-    if (_selector == null) {
-      throw new UnsupportedError('Cannot call matchingTarget if this Event did'
-          ' not arise as a result of event delegation.');
-    }
-    Element? currentTarget = this.currentTarget as Element?;
-    Element? target = this.target as Element?;
-    do {
-      if (target!.matches(_selector!)) return target;
-      target = target.parent;
-    } while (target != null && target != currentTarget!.parent);
-    throw new StateError('No selector matched for populating matchedTarget.');
-  }
-
-  /**
-   * This event's path, taking into account shadow DOM.
-   *
-   * ## Other resources
-   *
-   * * [Shadow DOM extensions to
-   *   Event](http://w3c.github.io/webcomponents/spec/shadow/#extensions-to-event)
-   *   from W3C.
-   */
-  // https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#extensions-to-event
-  List<Node> get path => wrapped.path as List<Node>;
-
-  dynamic get _get_currentTarget => wrapped._get_currentTarget;
-
-  dynamic get _get_target => wrapped._get_target;
-}
diff --git a/tools/dom/nnbd_src/native_DOMImplementation.dart b/tools/dom/nnbd_src/native_DOMImplementation.dart
deleted file mode 100644
index 79f5d04..0000000
--- a/tools/dom/nnbd_src/native_DOMImplementation.dart
+++ /dev/null
@@ -1,1399 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of html;
-
-class _Property {
-  _Property(this.name)
-      : _hasValue = false,
-        writable = false,
-        isMethod = false,
-        isOwn = true,
-        wasThrown = false;
-
-  bool get hasValue => _hasValue;
-  get value => _value;
-  set value(v) {
-    _value = v;
-    _hasValue = true;
-  }
-
-  final String name;
-  Function setter;
-  Function getter;
-  var _value;
-  bool _hasValue;
-  bool writable;
-  bool isMethod;
-  bool isOwn;
-  bool wasThrown;
-}
-
-/**
- * Manager for navigating between libraries from the devtools console.
- */
-class _LibraryManager {
-  /**
-   * Current active library
-   */
-  static var _currentLibrary;
-  static var _validCache = false;
-
-  static List<Uri> _libraryUris;
-
-  // List of all maps to check to determine if there is an exact match.
-  static Map<String, List<Uri>> _fastPaths;
-
-  static void _addFastPath(String key, Uri uri) {
-    _fastPaths.putIfAbsent(key, () => <Uri>[]).add(uri);
-  }
-
-  static cache() {
-    if (_validCache) return;
-    _validCache = true;
-    _libraryUris = <Uri>[];
-    _fastPaths = new Map<String, List<Uri>>();
-    var system = currentMirrorSystem();
-    system.libraries.forEach((uri, library) {
-      _libraryUris.add(uri);
-      _addFastPath(uri.toString(), uri);
-      _addFastPath(MirrorSystem.getName(library.simpleName), uri);
-    });
-  }
-
-  static String get currentLibrary {
-    if (_currentLibrary == null) {
-      _currentLibrary =
-          currentMirrorSystem().isolate.rootLibrary.uri.toString();
-    }
-    return _currentLibrary;
-  }
-
-  /**
-   * Find libraries matching a given name.
-   *
-   * Uses heuristics to only return a single match when the user intent is
-   * generally unambiguous.
-   */
-  static List<Uri> findMatches(String name) {
-    cache();
-    var nameAsFile = name.endsWith('.dart') ? name : '${name}.dart';
-    // Perfect match first.
-    var fastPatchMatches = _fastPaths[name];
-    if (fastPatchMatches != null) {
-      return fastPatchMatches.toList();
-    }
-
-    // Exact match for file path.
-    var matches = new LinkedHashSet<Uri>();
-    for (var uri in _libraryUris) {
-      if (uri.path == name || uri.path == nameAsFile) matches.add(uri);
-    }
-    if (matches.isNotEmpty) return matches.toList();
-
-    // Exact match for file name.
-    if (name != nameAsFile) {
-      for (var uri in _libraryUris) {
-        if (uri.pathSegments.isNotEmpty &&
-            (uri.pathSegments.last == nameAsFile)) {
-          matches.add(uri);
-        }
-      }
-      if (matches.isNotEmpty) return matches.toList();
-    }
-
-    for (var uri in _libraryUris) {
-      if (uri.pathSegments.isNotEmpty && (uri.pathSegments.last == name)) {
-        matches.add(uri);
-      }
-    }
-    if (matches.isNotEmpty) return matches.toList();
-
-    // Partial match on path.
-    for (var uri in _libraryUris) {
-      if (uri.path.contains(name)) {
-        matches.add(uri);
-      }
-    }
-    if (matches.isNotEmpty) return matches.toList();
-
-    // Partial match on entire uri.
-    for (var uri in _libraryUris) {
-      if (uri.toString().contains(name)) {
-        matches.add(uri);
-      }
-    }
-
-    if (matches.isNotEmpty) return matches.toList();
-
-    // Partial match on entire uri ignoring case.
-    name = name.toLowerCase();
-    for (var uri in _libraryUris) {
-      if (uri.toString().toLowerCase().contains(name)) {
-        matches.add(uri);
-      }
-    }
-    return matches.toList();
-  }
-
-  static setLibrary([String? name]) {
-    // Bust cache in case library list has changed. Ideally we would listen for
-    // when libraries are loaded and invalidate based on that.
-    _validCache = false;
-    cache();
-    if (name == null) {
-      window.console
-        ..group("Current library: $_currentLibrary")
-        ..groupCollapsed("All libraries:");
-      _listLibraries();
-      window.console..groupEnd()..groupEnd();
-      return;
-    }
-    var matches = findMatches(name);
-    if (matches.length != 1) {
-      if (matches.length > 1) {
-        window.console.warn("Ambiguous library name: $name");
-      }
-      showMatches(name, matches);
-      return;
-    }
-    _currentLibrary = matches.first.toString();
-    window.console.log("Set library to $_currentLibrary");
-  }
-
-  static getLibrary() {
-    return currentLibrary;
-  }
-
-  static List<Uri> _sortUris(Iterable<Uri> uris) {
-    return (uris.toList())
-      ..sort((Uri a, Uri b) {
-        if (a.scheme != b.scheme) {
-          if (a.scheme == 'dart') return -1;
-          if (b.scheme == 'dart') return 1;
-          return a.scheme.compareTo(b.scheme);
-        }
-        return a.toString().compareTo(b.toString());
-      });
-  }
-
-  static void listLibraries() {
-    _validCache = false;
-    cache();
-    _listLibraries();
-  }
-
-  static void _listLibraries() {
-    window.console.log(_sortUris(_libraryUris).join("\n"));
-  }
-
-  // Workaround to allow calling console.log with an arbitrary number of
-  // arguments.
-  static void _log(List<String> args) {
-    js.JsNative.callMethod(window.console, 'log', args);
-  }
-
-  static showMatches(String key, Iterable<Uri> uris) {
-    var boldPairs = [];
-    var sb = new StringBuffer();
-    if (uris.isEmpty) {
-      window.console.group("All libraries:");
-      _listLibraries();
-      window.console
-        ..groupEnd()
-        ..error("No library names or URIs match '$key'");
-      return;
-    }
-    sb.write("${uris.length} matches\n");
-    var lowerCaseKey = key.toLowerCase();
-    for (var uri in uris) {
-      var txt = uri.toString();
-      int index = txt.toLowerCase().indexOf(lowerCaseKey);
-      if (index != -1) {
-        // %c enables styling console log messages with css
-        // specified at the end of the console.
-        sb..write(txt.substring(0, index))..write('%c');
-        var matchEnd = index + key.length;
-        sb
-          ..write(txt.substring(index, matchEnd))
-          ..write('%c')
-          ..write(txt.substring(matchEnd))
-          ..write('\n');
-        boldPairs..add('font-weight: bold')..add('font-weight: normal');
-      }
-    }
-    _log([sb.toString()]..addAll(boldPairs));
-  }
-}
-
-class _ConsoleVariables {
-  Map<String, Object> _data = new Map<String, Object>();
-
-  /**
-   * Forward member accesses to the backing JavaScript object.
-   */
-  noSuchMethod(Invocation invocation) {
-    String member = MirrorSystem.getName(invocation.memberName);
-    if (invocation.isGetter) {
-      return _data[member];
-    } else if (invocation.isSetter) {
-      assert(member.endsWith('='));
-      member = member.substring(0, member.length - 1);
-      _data[member] = invocation.positionalArguments[0];
-    } else {
-      return Function.apply(_data[member], invocation.positionalArguments,
-          invocation.namedArguments);
-    }
-  }
-
-  void clear() => _data.clear();
-
-  /**
-   * List all variables currently defined.
-   */
-  List variables() => _data.keys.toList();
-
-  void setVariable(String name, value) {
-    _data[name] = value;
-  }
-}
-
-/**
- * Base class for invocation trampolines used to closurize methods, getters
- * and setters.
- */
-abstract class _Trampoline implements Function {
-  final ObjectMirror _receiver;
-  final MethodMirror _methodMirror;
-  final Symbol _selector;
-
-  _Trampoline(this._receiver, this._methodMirror, this._selector);
-}
-
-class _MethodTrampoline extends _Trampoline {
-  _MethodTrampoline(
-      ObjectMirror receiver, MethodMirror methodMirror, Symbol selector)
-      : super(receiver, methodMirror, selector);
-
-  noSuchMethod(Invocation msg) {
-    if (msg.memberName != #call) return super.noSuchMethod(msg);
-    return _receiver
-        .invoke(_selector, msg.positionalArguments, msg.namedArguments)
-        .reflectee;
-  }
-}
-
-/**
- * Invocation trampoline class used to closurize getters.
- */
-class _GetterTrampoline extends _Trampoline {
-  _GetterTrampoline(
-      ObjectMirror receiver, MethodMirror methodMirror, Symbol selector)
-      : super(receiver, methodMirror, selector);
-
-  call() => _receiver.getField(_selector).reflectee;
-}
-
-/**
- * Invocation trampoline class used to closurize setters.
- */
-class _SetterTrampoline extends _Trampoline {
-  _SetterTrampoline(
-      ObjectMirror receiver, MethodMirror methodMirror, Symbol selector)
-      : super(receiver, methodMirror, selector);
-
-  call(value) {
-    _receiver.setField(_selector, value);
-  }
-}
-
-class _Utils {
-  static double dateTimeToDouble(DateTime dateTime) =>
-      dateTime.millisecondsSinceEpoch.toDouble();
-  static DateTime doubleToDateTime(double dateTime) {
-    try {
-      return new DateTime.fromMillisecondsSinceEpoch(dateTime.toInt());
-    } catch (_) {
-      // TODO(antonnm): treat exceptions properly in bindings and
-      // find out how to treat NaNs.
-      return null;
-    }
-  }
-
-  static List convertToList(List list) {
-    // FIXME: [possible optimization]: do not copy the array if Dart_IsArray is fine w/ it.
-    final length = list.length;
-    List result = new List(length);
-    result.setRange(0, length, list);
-    return result;
-  }
-
-  static List convertMapToList(Map map) {
-    List result = [];
-    map.forEach((k, v) => result.addAll([k, v]));
-    return result;
-  }
-
-  static int convertCanvasElementGetContextMap(Map map) {
-    int result = 0;
-    if (map['alpha'] == true) result |= 0x01;
-    if (map['depth'] == true) result |= 0x02;
-    if (map['stencil'] == true) result |= 0x4;
-    if (map['antialias'] == true) result |= 0x08;
-    if (map['premultipliedAlpha'] == true) result |= 0x10;
-    if (map['preserveDrawingBuffer'] == true) result |= 0x20;
-
-    return result;
-  }
-
-  static void populateMap(Map result, List list) {
-    for (int i = 0; i < list.length; i += 2) {
-      result[list[i]] = list[i + 1];
-    }
-  }
-
-  static bool isMap(obj) => obj is Map;
-
-  static List toListIfIterable(obj) => obj is Iterable ? obj.toList() : null;
-
-  static Map createMap() => {};
-
-  static parseJson(String jsonSource) =>
-      const JsonDecoder().convert(jsonSource);
-
-  static String getLibraryUrl() => _LibraryManager.currentLibrary;
-
-  static makeUnimplementedError(String fileName, int lineNo) {
-    return new UnsupportedError('[info: $fileName:$lineNo]');
-  }
-
-  static bool isTypeSubclassOf(Type type, Type other) {
-    if (type == other) {
-      return true;
-    }
-    var superclass = reflectClass(type).superclass;
-    if (superclass != null) {
-      return isTypeSubclassOf(superclass.reflectedType, other);
-    }
-    return false;
-  }
-
-  static Element getAndValidateNativeType(Type type, String tagName) {
-    var element = new Element.tag(tagName);
-    if (!isTypeSubclassOf(type, element.runtimeType)) {
-      return null;
-    }
-    return element;
-  }
-
-  static forwardingPrint(String message) =>
-      _blink.Blink_Utils.forwardingPrint(message);
-  static void spawnDomHelper(Function f, int replyTo) =>
-      _blink.Blink_Utils.spawnDomHelper(f, replyTo);
-
-  // TODO(vsm): Make this API compatible with spawnUri.  It should also
-  // return a Future<Isolate>.
-  // TODO(jacobr): IS THIS RIGHT? I worry we have broken conversion from Promise to Future.
-  static spawnDomUri(String uri) => _blink.Blink_Utils.spawnDomUri(uri);
-
-  // The following methods were added for debugger integration to make working
-  // with the Dart C mirrors API simpler.
-  // TODO(jacobr): consider moving them to a separate library.
-  // If Dart supported dynamic code injection, we would only inject this code
-  // when the debugger is invoked.
-
-  /**
-   * Strips the private secret prefix from member names of the form
-   * someName@hash.
-   */
-  static String stripMemberName(String name) {
-    int endIndex = name.indexOf('@');
-    return endIndex > 0 ? name.substring(0, endIndex) : name;
-  }
-
-  /**
-   * Takes a list containing variable names and corresponding values and
-   * returns a map from normalized names to values. Variable names are assumed
-   * to have list offsets 2*n values at offset 2*n+1. This method is required
-   * because Dart_GetLocalVariables returns a list instead of an object that
-   * can be queried to lookup names and values.
-   */
-  static Map<String, dynamic> createLocalVariablesMap(List localVariables) {
-    var map = {};
-    for (int i = 0; i < localVariables.length; i += 2) {
-      map[stripMemberName(localVariables[i])] = localVariables[i + 1];
-    }
-    return map;
-  }
-
-  static _ConsoleVariables _consoleTempVariables = new _ConsoleVariables();
-
-  /**
-   * Takes an [expression] and a list of [local] variable and returns an
-   * expression for a closure with a body matching the original expression
-   * where locals are passed in as arguments. Returns a list containing the
-   * String expression for the closure and the list of arguments that should
-   * be passed to it. The expression should then be evaluated using
-   * Dart_EvaluateExpr which will generate a closure that should be invoked
-   * with the list of arguments passed to this method.
-   *
-   * For example:
-   * <code>
-   * _consoleTempVariables = {'a' : someValue, 'b': someOtherValue}
-   * wrapExpressionAsClosure("foo + bar + a", ["bar", 40, "foo", 2], true)
-   * </code>
-   * will return:
-   * <code>
-   * ["""(final $consoleVariables, final bar, final foo, final a, final b) =>
-   * (foo + bar + a
-   * )""",
-   * [_consoleTempVariables, 40, 2, someValue, someOtherValue]]
-   * </code>
-   */
-  static List wrapExpressionAsClosure(
-      String expression, List locals, bool includeCommandLineAPI) {
-    var args = {};
-    var sb = new StringBuffer("(");
-    addArg(arg, value) {
-      arg = stripMemberName(arg);
-      if (args.containsKey(arg)) return;
-      // We ignore arguments with the name 'this' rather than throwing an
-      // exception because Dart_GetLocalVariables includes 'this' and it
-      // is more convenient to filter it out here than from C++ code.
-      // 'this' needs to be handled by calling Dart_EvaluateExpr with
-      // 'this' as the target rather than by passing it as an argument.
-      if (arg == 'this') return;
-      // Avoid being broken by bogus ':async_op' local passed in when within
-      // an async method.
-      if (arg.startsWith(':')) return;
-      if (args.isNotEmpty) {
-        sb.write(", ");
-      }
-      sb.write("final $arg");
-      args[arg] = value;
-    }
-
-    if (includeCommandLineAPI) {
-      addArg("\$consoleVariables", _consoleTempVariables);
-
-      // FIXME: use a real Dart tokenizer. The following regular expressions
-      // only allow setting variables at the immediate start of the expression
-      // to limit the number of edge cases we have to handle.
-
-      // Match expressions that start with "var x"
-      final _VARIABLE_DECLARATION = new RegExp("^(\\s*)var\\s+(\\w+)");
-      // Match expressions that start with "someExistingConsoleVar ="
-      final _SET_VARIABLE = new RegExp("^(\\s*)(\\w+)(\\s*=)");
-      // Match trailing semicolons.
-      final _ENDING_SEMICOLONS = new RegExp("(;\\s*)*\$");
-      expression = expression.replaceAllMapped(_VARIABLE_DECLARATION, (match) {
-        var variableName = match[2];
-        // Set the console variable if it isn't already set.
-        if (!_consoleTempVariables._data.containsKey(variableName)) {
-          _consoleTempVariables._data[variableName] = null;
-        }
-        return "${match[1]}\$consoleVariables.${variableName}";
-      });
-
-      expression = expression.replaceAllMapped(_SET_VARIABLE, (match) {
-        var variableName = match[2];
-        // Only rewrite if the name matches an existing console variable.
-        if (_consoleTempVariables._data.containsKey(variableName)) {
-          return "${match[1]}\$consoleVariables.${variableName}${match[3]}";
-        } else {
-          return match[0];
-        }
-      });
-
-      // We only allow dart expressions not Dart statements. Silently remove
-      // trailing semicolons the user might have added by accident to reduce the
-      // number of spurious compile errors.
-      expression = expression.replaceFirst(_ENDING_SEMICOLONS, "");
-    }
-
-    if (locals != null) {
-      for (int i = 0; i < locals.length; i += 2) {
-        addArg(locals[i], locals[i + 1]);
-      }
-    }
-    // Inject all the already defined console variables.
-    _consoleTempVariables._data.forEach(addArg);
-
-    // TODO(jacobr): remove the parentheses around the expression once
-    // dartbug.com/13723 is fixed. Currently we wrap expression in parentheses
-    // to ensure only valid Dart expressions are allowed. Otherwise the DartVM
-    // quietly ignores trailing Dart statements resulting in user confusion
-    // when part of an invalid expression they entered is ignored.
-    sb..write(') => (\n$expression\n)');
-    return [sb.toString(), args.values.toList(growable: false)];
-  }
-
-  static String _getShortSymbolName(
-      Symbol symbol, DeclarationMirror declaration) {
-    var name = MirrorSystem.getName(symbol);
-    if (declaration is MethodMirror) {
-      if (declaration.isSetter && name[name.length - 1] == "=") {
-        return name.substring(0, name.length - 1);
-      }
-      if (declaration.isConstructor) {
-        return name.substring(name.indexOf('.') + 1);
-      }
-    }
-    return name;
-  }
-
-  /**
-   * Handle special console commands such as $lib and $libs that should not be
-   * evaluated as Dart expressions and instead should be interpreted directly.
-   * Commands supported:
-   * library <-- shows the current library and lists all libraries.
-   * library "library_uri" <-- select a specific library
-   * library "library_uri_fragment"
-   */
-  static bool maybeHandleSpecialConsoleCommand(String expression) {
-    expression = expression.trim();
-    var setLibraryCommand = r'library ';
-    if (expression == r'library') {
-      _LibraryManager.setLibrary();
-      return true;
-    }
-    if (expression.startsWith(setLibraryCommand)) {
-      expression = expression.substring(setLibraryCommand.length);
-      if (expression.length >= 2) {
-        String start = expression[0];
-        String end = expression[expression.length - 1];
-        // TODO(jacobr): maybe we should require quotes.
-        if ((start == "'" && end == "'") || (start == '"' && end == '"')) {
-          expression = expression.substring(1, expression.length - 1);
-        }
-      }
-
-      _LibraryManager.setLibrary(expression);
-      return true;
-    }
-    return false;
-  }
-
-  /**
-   * Returns a list of completions to use if the receiver is o.
-   */
-  static List<String> getCompletions(o) {
-    MirrorSystem system = currentMirrorSystem();
-    var completions = new Set<String>();
-    addAll(Map<Symbol, dynamic> map, bool isStatic) {
-      map.forEach((symbol, mirror) {
-        if (mirror.isStatic == isStatic && !mirror.isPrivate) {
-          var name = MirrorSystem.getName(symbol);
-          if (mirror is MethodMirror && mirror.isSetter)
-            name = name.substring(0, name.length - 1);
-          completions.add(name);
-        }
-      });
-    }
-
-    addForClass(ClassMirror mirror, bool isStatic) {
-      if (mirror == null) return;
-      addAll(mirror.declarations, isStatic);
-      if (mirror.superclass != null) addForClass(mirror.superclass, isStatic);
-      for (var interface in mirror.superinterfaces) {
-        addForClass(interface, isStatic);
-      }
-    }
-
-    if (o is Type) {
-      addForClass(reflectClass(o), true);
-    } else {
-      addForClass(reflect(o).type, false);
-    }
-    return completions.toList(growable: false);
-  }
-
-  /**
-   * Adds all candidate String completions from [declarations] to [output]
-   * filtering based on [staticContext] and [includePrivate].
-   */
-  static void _getCompletionsHelper(ClassMirror classMirror, bool staticContext,
-      LibraryMirror libraryMirror, Set<String> output) {
-    bool includePrivate = libraryMirror == classMirror.owner;
-    classMirror.declarations.forEach((symbol, declaration) {
-      if (!includePrivate && declaration.isPrivate) return;
-      if (declaration is VariableMirror) {
-        if (staticContext != declaration.isStatic) return;
-      } else if (declaration is MethodMirror) {
-        if (declaration.isOperator) return;
-        if (declaration.isConstructor) {
-          if (!staticContext) return;
-          var name = MirrorSystem.getName(declaration.constructorName);
-          if (name.isNotEmpty) output.add(name);
-          return;
-        }
-        if (staticContext != declaration.isStatic) return;
-      } else if (declaration is TypeMirror) {
-        return;
-      }
-      output.add(_getShortSymbolName(symbol, declaration));
-    });
-
-    if (!staticContext) {
-      for (var interface in classMirror.superinterfaces) {
-        _getCompletionsHelper(interface, staticContext, libraryMirror, output);
-      }
-      if (classMirror.superclass != null) {
-        _getCompletionsHelper(
-            classMirror.superclass, staticContext, libraryMirror, output);
-      }
-    }
-  }
-
-  static void _getLibraryCompletionsHelper(
-      LibraryMirror library, bool includePrivate, Set<String> output) {
-    library.declarations.forEach((symbol, declaration) {
-      if (!includePrivate && declaration.isPrivate) return;
-      output.add(_getShortSymbolName(symbol, declaration));
-    });
-  }
-
-  static LibraryMirror getLibraryMirror(String url) =>
-      currentMirrorSystem().libraries[Uri.parse(url)];
-
-  /**
-   * Get code completions for [o] only showing privates from [libraryUrl].
-   */
-  static List<String> getObjectCompletions(o, String libraryUrl) {
-    var classMirror;
-    bool staticContext;
-    if (o is Type) {
-      classMirror = reflectClass(o);
-      staticContext = true;
-    } else {
-      classMirror = reflect(o).type;
-      staticContext = false;
-    }
-    var names = new Set<String>();
-    getClassCompletions(classMirror, names, staticContext, libraryUrl);
-    return names.toList()..sort();
-  }
-
-  static void getClassCompletions(ClassMirror classMirror, Set<String> names,
-      bool staticContext, String libraryUrl) {
-    LibraryMirror libraryMirror = getLibraryMirror(libraryUrl);
-    _getCompletionsHelper(classMirror, staticContext, libraryMirror, names);
-  }
-
-  static List<String> getLibraryCompletions(String url) {
-    var names = new Set<String>();
-    _getLibraryCompletionsHelper(getLibraryMirror(url), true, names);
-    return names.toList();
-  }
-
-  /**
-   * Get valid code completions from within a library and all libraries
-   * imported by that library.
-   */
-  static List<String> getLibraryCompletionsIncludingImports(String url) {
-    var names = new Set<String>();
-    var libraryMirror = getLibraryMirror(url);
-    _getLibraryCompletionsHelper(libraryMirror, true, names);
-    for (var dependency in libraryMirror.libraryDependencies) {
-      if (dependency.isImport) {
-        if (dependency.prefix == null) {
-          _getLibraryCompletionsHelper(dependency.targetLibrary, false, names);
-        } else {
-          names.add(MirrorSystem.getName(dependency.prefix));
-        }
-      }
-    }
-    return names.toList();
-  }
-
-  static final SIDE_EFFECT_FREE_LIBRARIES = new Set<String>()
-    ..add('dart:html')
-    ..add('dart:indexed_db')
-    ..add('dart:svg')
-    ..add('dart:typed_data')
-    ..add('dart:web_audio')
-    ..add('dart:web_gl')
-    ..add('dart:web_sql');
-
-  static LibraryMirror _getLibrary(MethodMirror methodMirror) {
-    var owner = methodMirror.owner;
-    if (owner is ClassMirror) {
-      return owner;
-    } else if (owner is LibraryMirror) {
-      return owner;
-    }
-    return null;
-  }
-
-  /**
-   * For parity with the JavaScript debugger, we treat some getters as if
-   * they are fields so that users can see their values immediately.
-   * This matches JavaScript's behavior for getters on DOM objects.
-   * In the future we should consider adding an annotation to tag getters
-   * in user libraries as side effect free.
-   */
-  static bool _isSideEffectFreeGetter(
-      MethodMirror methodMirror, LibraryMirror libraryMirror) {
-    // This matches JavaScript behavior. We should consider displaying
-    // getters for all dart platform libraries rather than just the DOM
-    // libraries.
-    return libraryMirror.uri.scheme == 'dart' &&
-        SIDE_EFFECT_FREE_LIBRARIES.contains(libraryMirror.uri.toString());
-  }
-
-  /**
-   * Whether we should treat a property as a field for the purposes of the
-   * debugger.
-   */
-  static bool treatPropertyAsField(
-      MethodMirror methodMirror, LibraryMirror libraryMirror) {
-    return (methodMirror.isGetter || methodMirror.isSetter) &&
-        (methodMirror.isSynthetic ||
-            _isSideEffectFreeGetter(methodMirror, libraryMirror));
-  }
-
-  // TODO(jacobr): generate more concise function descriptions instead of
-  // dumping the entire function source.
-  static String describeFunction(function) {
-    if (function is _Trampoline) return function._methodMirror.source;
-    try {
-      var mirror = reflect(function);
-      return mirror.function.source;
-    } catch (e) {
-      return function.toString();
-    }
-  }
-
-  static List getInvocationTrampolineDetails(_Trampoline method) {
-    var loc = method._methodMirror.location;
-    return [
-      loc.line,
-      loc.column,
-      loc.sourceUri.toString(),
-      MirrorSystem.getName(method._selector)
-    ];
-  }
-
-  static List getLibraryProperties(
-      String libraryUrl, bool ownProperties, bool accessorPropertiesOnly) {
-    var properties = new Map<String, _Property>();
-    var libraryMirror = getLibraryMirror(libraryUrl);
-    _addInstanceMirrors(
-        libraryMirror,
-        libraryMirror,
-        libraryMirror.declarations,
-        ownProperties,
-        accessorPropertiesOnly,
-        false,
-        false,
-        properties);
-    if (!accessorPropertiesOnly) {
-      // We need to add class properties for all classes in the library.
-      libraryMirror.declarations.forEach((symbol, declarationMirror) {
-        if (declarationMirror is ClassMirror) {
-          var name = MirrorSystem.getName(symbol);
-          if (declarationMirror.hasReflectedType &&
-              !properties.containsKey(name)) {
-            properties[name] = new _Property(name)
-              ..value = declarationMirror.reflectedType;
-          }
-        }
-      });
-    }
-    return packageProperties(properties);
-  }
-
-  static List getObjectProperties(
-      o, bool ownProperties, bool accessorPropertiesOnly) {
-    var properties = new Map<String, _Property>();
-    var names = new Set<String>();
-    var objectMirror = reflect(o);
-    var classMirror = objectMirror.type;
-    _addInstanceMirrors(
-        objectMirror,
-        classMirror.owner,
-        classMirror.instanceMembers,
-        ownProperties,
-        accessorPropertiesOnly,
-        false,
-        true,
-        properties);
-    return packageProperties(properties);
-  }
-
-  static List getObjectClassProperties(
-      o, bool ownProperties, bool accessorPropertiesOnly) {
-    var properties = new Map<String, _Property>();
-    var objectMirror = reflect(o);
-    var classMirror = objectMirror.type;
-    _addInstanceMirrors(
-        objectMirror,
-        classMirror.owner,
-        classMirror.instanceMembers,
-        ownProperties,
-        accessorPropertiesOnly,
-        true,
-        false,
-        properties);
-    _addStatics(classMirror, properties, accessorPropertiesOnly);
-    return packageProperties(properties);
-  }
-
-  static List getClassProperties(
-      Type t, bool ownProperties, bool accessorPropertiesOnly) {
-    var properties = new Map<String, _Property>();
-    var classMirror = reflectClass(t);
-    _addStatics(classMirror, properties, accessorPropertiesOnly);
-    return packageProperties(properties);
-  }
-
-  static void _addStatics(ClassMirror classMirror,
-      Map<String, _Property> properties, bool accessorPropertiesOnly) {
-    var libraryMirror = classMirror.owner;
-    classMirror.declarations.forEach((symbol, declaration) {
-      var name = _getShortSymbolName(symbol, declaration);
-      if (name.isEmpty) return;
-      if (declaration is VariableMirror) {
-        if (accessorPropertiesOnly) return;
-        if (!declaration.isStatic) return;
-        properties.putIfAbsent(name, () => new _Property(name))
-          ..value = classMirror.getField(symbol).reflectee
-          ..writable = !declaration.isFinal && !declaration.isConst;
-      } else if (declaration is MethodMirror) {
-        MethodMirror methodMirror = declaration;
-        // FIXMEDART: should we display constructors?
-        if (methodMirror.isConstructor) return;
-        if (!methodMirror.isStatic) return;
-        if (accessorPropertiesOnly) {
-          if (methodMirror.isRegularMethod ||
-              treatPropertyAsField(methodMirror, libraryMirror)) {
-            return;
-          }
-        } else if (!methodMirror.isRegularMethod &&
-            !treatPropertyAsField(methodMirror, libraryMirror)) {
-          return;
-        }
-        var property = properties.putIfAbsent(name, () => new _Property(name));
-        _fillMethodMirrorProperty(libraryMirror, classMirror, methodMirror,
-            symbol, accessorPropertiesOnly, property);
-      }
-    });
-  }
-
-  static void _fillMethodMirrorProperty(
-      LibraryMirror libraryMirror,
-      methodOwner,
-      MethodMirror methodMirror,
-      Symbol symbol,
-      bool accessorPropertiesOnly,
-      _Property property) {
-    if (methodMirror.isRegularMethod) {
-      property
-        ..value = new _MethodTrampoline(methodOwner, methodMirror, symbol)
-        ..isMethod = true;
-    } else if (methodMirror.isGetter) {
-      if (treatPropertyAsField(methodMirror, libraryMirror)) {
-        try {
-          property.value = methodOwner.getField(symbol).reflectee;
-        } catch (e) {
-          property
-            ..wasThrown = true
-            ..value = e;
-        }
-      } else if (accessorPropertiesOnly) {
-        property.getter =
-            new _GetterTrampoline(methodOwner, methodMirror, symbol);
-      }
-    } else if (methodMirror.isSetter) {
-      if (accessorPropertiesOnly &&
-          !treatPropertyAsField(methodMirror, libraryMirror)) {
-        property.setter = new _SetterTrampoline(methodOwner, methodMirror,
-            MirrorSystem.getSymbol(property.name, libraryMirror));
-      }
-      property.writable = true;
-    }
-  }
-
-  /**
-   * Helper method that handles collecting up properties from classes
-   * or libraries using the filters [ownProperties], [accessorPropertiesOnly],
-   * [hideFields], and [hideMethods] to determine which properties are
-   * collected. [accessorPropertiesOnly] specifies whether all properties
-   * should be returned or just accessors. [hideFields] specifies whether
-   * fields should be hidden. hideMethods specifies whether methods should be
-   * shown or hidden. [ownProperties] is not currently used but is part of the
-   * Blink devtools API for enumerating properties.
-   */
-  static void _addInstanceMirrors(
-      ObjectMirror objectMirror,
-      LibraryMirror libraryMirror,
-      Map<Symbol, Mirror> declarations,
-      bool ownProperties,
-      bool accessorPropertiesOnly,
-      bool hideFields,
-      bool hideMethods,
-      Map<String, _Property> properties) {
-    declarations.forEach((symbol, declaration) {
-      if (declaration is TypedefMirror || declaration is ClassMirror) return;
-      var name = _getShortSymbolName(symbol, declaration);
-      if (name.isEmpty) return;
-      bool isField = declaration is VariableMirror ||
-          (declaration is MethodMirror &&
-              treatPropertyAsField(declaration, libraryMirror));
-      if ((isField && hideFields) || (hideMethods && !isField)) return;
-      if (accessorPropertiesOnly) {
-        if (declaration is VariableMirror ||
-            declaration.isRegularMethod ||
-            isField) {
-          return;
-        }
-      } else if (declaration is MethodMirror &&
-          (declaration.isGetter || declaration.isSetter) &&
-          !treatPropertyAsField(declaration, libraryMirror)) {
-        return;
-      }
-      var property = properties.putIfAbsent(name, () => new _Property(name));
-      if (declaration is VariableMirror) {
-        property
-          ..value = objectMirror.getField(symbol).reflectee
-          ..writable = !declaration.isFinal && !declaration.isConst;
-        return;
-      }
-      _fillMethodMirrorProperty(libraryMirror, objectMirror, declaration,
-          symbol, accessorPropertiesOnly, property);
-    });
-  }
-
-  /**
-   * Flatten down the properties data structure into a List that is easy to
-   * access from native code.
-   */
-  static List packageProperties(Map<String, _Property> properties) {
-    var ret = [];
-    for (var property in properties.values) {
-      ret.addAll([
-        property.name,
-        property.setter,
-        property.getter,
-        property.value,
-        property.hasValue,
-        property.writable,
-        property.isMethod,
-        property.isOwn,
-        property.wasThrown
-      ]);
-    }
-    return ret;
-  }
-
-  /**
-   * Get a property, returning null if the property does not exist.
-   * For private property names, we attempt to resolve the property in the
-   * context of each library that the property name could be associated with.
-   */
-  static getObjectPropertySafe(o, String propertyName) {
-    var objectMirror = reflect(o);
-    var classMirror = objectMirror.type;
-    if (propertyName.startsWith("_")) {
-      var attemptedLibraries = new Set<LibraryMirror>();
-      while (classMirror != null) {
-        LibraryMirror library = classMirror.owner;
-        if (!attemptedLibraries.contains(library)) {
-          try {
-            return objectMirror
-                .getField(MirrorSystem.getSymbol(propertyName, library))
-                .reflectee;
-          } catch (e) {}
-          attemptedLibraries.add(library);
-        }
-        classMirror = classMirror.superclass;
-      }
-      return null;
-    }
-    try {
-      return objectMirror
-          .getField(MirrorSystem.getSymbol(propertyName))
-          .reflectee;
-    } catch (e) {
-      return null;
-    }
-  }
-
-  /**
-   * Helper to wrap the inspect method on InjectedScriptHost to provide the
-   * inspect method required for the
-   */
-  static List consoleApi(host) {
-    return [
-      "inspect",
-      (o) {
-        js.JsNative.callMethod(host, "_inspect", [o]);
-        return o;
-      },
-      "dir",
-      window.console.dir,
-      "dirxml",
-      window.console.dirxml
-      // FIXME: add copy method.
-    ];
-  }
-
-  static List getMapKeyList(Map map) => map.keys.toList();
-
-  static bool isNoSuchMethodError(obj) => obj is NoSuchMethodError;
-
-  static void register(
-      Document document, String tag, Type type, String extendsTagName) {
-    var nativeClass = _validateCustomType(type);
-
-    if (extendsTagName == null) {
-      if (nativeClass.reflectedType != HtmlElement) {
-        throw new UnsupportedError('Class must provide extendsTag if base '
-            'native class is not HTMLElement');
-      }
-    }
-
-    _register(document, tag, type, extendsTagName);
-  }
-
-  static void _register(Document document, String tag, Type customType,
-          String extendsTagName) =>
-      _blink.Blink_Utils.register(document, tag, customType, extendsTagName);
-
-  static Element createElement(Document document, String tagName) =>
-      _blink.Blink_Utils.createElement(document, tagName);
-}
-
-class _DOMWindowCrossFrame extends DartHtmlDomObject implements WindowBase {
-  _DOMWindowCrossFrame.internal();
-
-  static _createSafe(win) {
-    if (identical(win, window)) {
-      // The current Window object is the only window object that should not
-      // use _DOMWindowCrossFrame.
-      return window;
-    }
-    return win is _DOMWindowCrossFrame
-        ? win
-        : _blink.Blink_Utils.setInstanceInterceptor(win, _DOMWindowCrossFrame);
-  }
-
-  // Fields.
-  HistoryBase get history {
-    var history = _blink.BlinkWindow.instance.history_Getter_(this);
-    return history is _HistoryCrossFrame
-        ? history
-        : _blink.Blink_Utils.setInstanceInterceptor(
-            history, _HistoryCrossFrame);
-  }
-
-  LocationBase get location {
-    var location = _blink.BlinkWindow.instance.location_Getter_(this);
-    return location is _LocationCrossFrame
-        ? location
-        : _blink.Blink_Utils.setInstanceInterceptor(
-            location, _LocationCrossFrame);
-  }
-
-  bool get closed => _blink.BlinkWindow.instance.closed_Getter_(this);
-  WindowBase get opener => _convertNativeToDart_Window(
-      _blink.BlinkWindow.instance.opener_Getter_(this));
-  WindowBase get parent => _convertNativeToDart_Window(
-      _blink.BlinkWindow.instance.parent_Getter_(this));
-  WindowBase get top => _convertNativeToDart_Window(
-      _blink.BlinkWindow.instance.top_Getter_(this));
-
-  // Methods.
-  void close() => _blink.BlinkWindow.instance.close_Callback_0_(this);
-  void postMessage(Object message, String targetOrigin,
-          [List<MessagePort>? transfer]) =>
-      _blink.BlinkWindow.instance.postMessage_Callback_3_(
-          this,
-          convertDartToNative_SerializedScriptValue(message),
-          targetOrigin,
-          transfer);
-
-  // Implementation support.
-  String get typeName => "Window";
-
-  // TODO(efortuna): Remove this method. dartbug.com/16814
-  Events get on => throw new UnsupportedError(
-      'You can only attach EventListeners to your own window.');
-  // TODO(efortuna): Remove this method. dartbug.com/16814
-  void _addEventListener(
-          [String? type, EventListener? listener, bool? useCapture]) =>
-      throw new UnsupportedError(
-          'You can only attach EventListeners to your own window.');
-  // TODO(efortuna): Remove this method. dartbug.com/16814
-  void addEventListener(String type, EventListener? listener,
-          [bool? useCapture]) =>
-      throw new UnsupportedError(
-          'You can only attach EventListeners to your own window.');
-  // TODO(efortuna): Remove this method. dartbug.com/16814
-  bool dispatchEvent(Event event) => throw new UnsupportedError(
-      'You can only attach EventListeners to your own window.');
-  // TODO(efortuna): Remove this method. dartbug.com/16814
-  void _removeEventListener(
-          [String? type, EventListener? listener, bool? useCapture]) =>
-      throw new UnsupportedError(
-          'You can only attach EventListeners to your own window.');
-  // TODO(efortuna): Remove this method. dartbug.com/16814
-  void removeEventListener(String type, EventListener? listener,
-          [bool? useCapture]) =>
-      throw new UnsupportedError(
-          'You can only attach EventListeners to your own window.');
-}
-
-class _HistoryCrossFrame extends DartHtmlDomObject implements HistoryBase {
-  _HistoryCrossFrame.internal();
-
-  // Methods.
-  void back() => _blink.BlinkHistory.instance.back_Callback_0_(this);
-  void forward() => _blink.BlinkHistory.instance.forward_Callback_0_(this);
-  void go([int? delta]) {
-    if (delta != null) {
-      _blink.BlinkHistory.instance.go_Callback_1_(this, delta);
-      return;
-    }
-    _blink.BlinkHistory.instance.go_Callback_0_(this);
-    return;
-  }
-
-  // Implementation support.
-  String get typeName => "History";
-}
-
-class _LocationCrossFrame extends DartHtmlDomObject implements LocationBase {
-  _LocationCrossFrame.internal();
-
-  // Fields.
-  set href(String value) =>
-      _blink.BlinkLocation.instance.href_Setter_(this, value);
-
-  // Implementation support.
-  String get typeName => "Location";
-}
-
-// TODO(vsm): Remove DOM isolate code once we have Dartium isolates
-// as workers.  This is only used to support
-// printing and timers in background isolates. As workers they should
-// be able to just do those things natively.
-
-_makeSendPortFuture(spawnRequest) {
-  final completer = new Completer<SendPort>.sync();
-  final port = new ReceivePort();
-  port.listen((result) {
-    completer.complete(result);
-    port.close();
-  });
-  // TODO: SendPort.hashCode is ugly way to access port id.
-  spawnRequest(port.sendPort.hashCode);
-  return completer.future;
-}
-
-Future<SendPort> _spawnDomHelper(Function f) => _makeSendPortFuture((portId) {
-      _Utils.spawnDomHelper(f, portId);
-    });
-
-final Future<SendPort> __HELPER_ISOLATE_PORT =
-    _spawnDomHelper(_helperIsolateMain);
-
-// Tricky part.
-// Once __HELPER_ISOLATE_PORT gets resolved, it will still delay in .then
-// and to delay Timer.run is used. However, Timer.run will try to register
-// another Timer and here we got stuck: event cannot be posted as then
-// callback is not executed because it's delayed with timer.
-// Therefore once future is resolved, it's unsafe to call .then on it
-// in Timer code.
-SendPort __SEND_PORT;
-
-_sendToHelperIsolate(msg, SendPort replyTo) {
-  if (__SEND_PORT != null) {
-    __SEND_PORT.send([msg, replyTo]);
-  } else {
-    __HELPER_ISOLATE_PORT.then((port) {
-      __SEND_PORT = port;
-      __SEND_PORT.send([msg, replyTo]);
-    });
-  }
-}
-
-final _TIMER_REGISTRY = new Map<SendPort, Timer>();
-
-const _NEW_TIMER = 'NEW_TIMER';
-const _CANCEL_TIMER = 'CANCEL_TIMER';
-const _TIMER_PING = 'TIMER_PING';
-const _PRINT = 'PRINT';
-
-_helperIsolateMain(originalSendPort) {
-  var port = new ReceivePort();
-  originalSendPort.send(port.sendPort);
-  port.listen((args) {
-    var msg = args.first;
-    var replyTo = args.last;
-    final cmd = msg[0];
-    if (cmd == _NEW_TIMER) {
-      final duration = new Duration(milliseconds: msg[1]);
-      bool periodic = msg[2];
-      ping() {
-        replyTo.send(_TIMER_PING);
-      }
-
-      ;
-      _TIMER_REGISTRY[replyTo] = periodic
-          ? new Timer.periodic(duration, (_) {
-              ping();
-            })
-          : new Timer(duration, ping);
-    } else if (cmd == _CANCEL_TIMER) {
-      _TIMER_REGISTRY.remove(replyTo).cancel();
-    } else if (cmd == _PRINT) {
-      final message = msg[1];
-      // TODO(antonm): we need somehow identify those isolates.
-      print('[From isolate] $message');
-    }
-  });
-}
-
-final _printClosure = (s) => window.console.log(s);
-final _pureIsolatePrintClosure = (s) {
-  _sendToHelperIsolate([_PRINT, s], null);
-};
-
-final _forwardingPrintClosure = _Utils.forwardingPrint;
-
-final _uriBaseClosure = () => Uri.parse(window.location.href);
-
-final _pureIsolateUriBaseClosure = () {
-  throw new UnimplementedError("Uri.base on a background isolate "
-      "is not supported in the browser");
-};
-
-class _Timer implements Timer {
-  static const int _STATE_TIMEOUT = 0;
-  static const int _STATE_INTERVAL = 1;
-  int _state;
-
-  _Timer(int milliSeconds, void callback(Timer timer), bool repeating) {
-    if (repeating) {
-      _state = (window._setInterval(() {
-                callback(this);
-              }, milliSeconds) <<
-              1) |
-          _STATE_INTERVAL;
-    } else {
-      _state = (window._setTimeout(() {
-                _state = null;
-                callback(this);
-              }, milliSeconds) <<
-              1) |
-          _STATE_TIMEOUT;
-    }
-  }
-
-  void cancel() {
-    if (_state == null) return;
-    int id = _state >> 1;
-    if ((_state & 1) == _STATE_TIMEOUT) {
-      window._clearTimeout(id);
-    } else {
-      window._clearInterval(id);
-    }
-    _state = null;
-  }
-
-  bool get isActive => _state != null;
-}
-
-get _timerFactoryClosure =>
-    (int milliSeconds, void callback(Timer timer), bool repeating) {
-      return new _Timer(milliSeconds, callback, repeating);
-    };
-
-class _PureIsolateTimer implements Timer {
-  bool _isActive = true;
-  final ReceivePort _port = new ReceivePort();
-  SendPort _sendPort; // Effectively final.
-
-  //  static SendPort _SEND_PORT;
-
-  _PureIsolateTimer(int milliSeconds, callback, repeating) {
-    _sendPort = _port.sendPort;
-    _port.listen((msg) {
-      assert(msg == _TIMER_PING);
-      _isActive = repeating;
-      callback(this);
-      if (!repeating) _cancel();
-    });
-
-    _send([_NEW_TIMER, milliSeconds, repeating]);
-  }
-
-  void cancel() {
-    _cancel();
-    _send([_CANCEL_TIMER]);
-  }
-
-  void _cancel() {
-    _isActive = false;
-    _port.close();
-  }
-
-  _send(msg) {
-    _sendToHelperIsolate(msg, _sendPort);
-  }
-
-  bool get isActive => _isActive;
-}
-
-get _pureIsolateTimerFactoryClosure =>
-    ((int milliSeconds, void callback(Timer time), bool repeating) =>
-        new _PureIsolateTimer(milliSeconds, callback, repeating));
-
-class _ScheduleImmediateHelper {
-  MutationObserver _observer;
-  final DivElement _div = new DivElement();
-  Function _callback;
-
-  _ScheduleImmediateHelper() {
-    // Run in the root-zone as the DOM callback would otherwise execute in the
-    // current zone.
-    Zone.root.run(() {
-      // Mutation events get fired as soon as the current event stack is unwound
-      // so we just make a dummy event and listen for that.
-      _observer = new MutationObserver(_handleMutation);
-      _observer.observe(_div, attributes: true);
-    });
-  }
-
-  void _schedule(callback) {
-    if (_callback != null) {
-      throw new StateError(
-          'Only one immediate callback can be scheduled at once');
-    }
-    _callback = callback;
-    // Toggle it to trigger the mutation event.
-    _div.hidden = !_div.hidden;
-  }
-
-  _handleMutation(List<MutationRecord> mutations, MutationObserver observer) {
-    var tmp = _callback;
-    _callback = null;
-    tmp();
-  }
-}
-
-final _ScheduleImmediateHelper _scheduleImmediateHelper =
-    new _ScheduleImmediateHelper();
-
-get _scheduleImmediateClosure => (void callback()) {
-      _scheduleImmediateHelper._schedule(callback);
-    };
-
-get _pureIsolateScheduleImmediateClosure => ((void callback()) =>
-    throw new UnimplementedError("scheduleMicrotask in background isolates "
-        "are not supported in the browser"));
-
-// Class for unsupported native browser 'DOM' objects.
-class _UnsupportedBrowserObject extends DartHtmlDomObject {}
diff --git a/tools/dom/nnbd_src/shared_SVGFactoryProviders.dart b/tools/dom/nnbd_src/shared_SVGFactoryProviders.dart
deleted file mode 100644
index 2c729f7..0000000
--- a/tools/dom/nnbd_src/shared_SVGFactoryProviders.dart
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of dart.dom.svg;
-
-class _SvgElementFactoryProvider {
-  static SvgElement createSvgElement_tag(String tag) {
-    final Element temp =
-        document.createElementNS("http://www.w3.org/2000/svg", tag);
-    return temp as SvgElement;
-  }
-}
diff --git a/tools/dom/nnbd_src/shared_html.dart b/tools/dom/nnbd_src/shared_html.dart
deleted file mode 100644
index f86f288..0000000
--- a/tools/dom/nnbd_src/shared_html.dart
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of dart.dom.html;
-
-void Function(T)? _wrapZone<T>(void Function(T)? callback) {
-  // For performance reasons avoid wrapping if we are in the root zone.
-  if (Zone.current == Zone.root) return callback;
-  if (callback == null) return null;
-  return Zone.current.bindUnaryCallbackGuarded(callback);
-}
-
-void Function(T1, T2)? _wrapBinaryZone<T1, T2>(
-    void Function(T1, T2)? callback) {
-  // For performance reasons avoid wrapping if we are in the root zone.
-  if (Zone.current == Zone.root) return callback;
-  if (callback == null) return null;
-  return Zone.current.bindBinaryCallbackGuarded(callback);
-}
-
-/**
- * Finds the first descendant element of this document that matches the
- * specified group of selectors.
- *
- * Unless your webpage contains multiple documents, the top-level
- * [querySelector]
- * method behaves the same as this method, so you should use it instead to
- * save typing a few characters.
- *
- * [selectors] should be a string using CSS selector syntax.
- *
- *     var element1 = document.querySelector('.className');
- *     var element2 = document.querySelector('#id');
- *
- * For details about CSS selector syntax, see the
- * [CSS selector specification](http://www.w3.org/TR/css3-selectors/).
- */
-Element? querySelector(String selectors) => document.querySelector(selectors);
-
-/**
- * Finds all descendant elements of this document that match the specified
- * group of selectors.
- *
- * Unless your webpage contains multiple documents, the top-level
- * [querySelectorAll]
- * method behaves the same as this method, so you should use it instead to
- * save typing a few characters.
- *
- * [selectors] should be a string using CSS selector syntax.
- *
- *     var items = document.querySelectorAll('.itemClassName');
- *
- * For details about CSS selector syntax, see the
- * [CSS selector specification](http://www.w3.org/TR/css3-selectors/).
- */
-ElementList<T> querySelectorAll<T extends Element>(String selectors) =>
-    document.querySelectorAll(selectors);
-
-/// A utility for changing the Dart wrapper type for elements.
-abstract class ElementUpgrader {
-  /// Upgrade the specified element to be of the Dart type this was created for.
-  ///
-  /// After upgrading the element passed in is invalid and the returned value
-  /// should be used instead.
-  Element upgrade(Element element);
-}
diff --git a/tools/dom/scripts/dartdomgenerator.py b/tools/dom/scripts/dartdomgenerator.py
index d4711a7..bf2662d 100755
--- a/tools/dom/scripts/dartdomgenerator.py
+++ b/tools/dom/scripts/dartdomgenerator.py
@@ -73,14 +73,13 @@
 class GeneratorOptions(object):
 
     def __init__(self, templates, database, type_registry, renamer, metadata,
-                 dart_js_interop, nnbd):
+                 dart_js_interop):
         self.templates = templates
         self.database = database
         self.type_registry = type_registry
         self.renamer = renamer
         self.metadata = metadata
         self.dart_js_interop = dart_js_interop
-        self.nnbd = nnbd
 
 
 def LoadDatabase(database_dir, use_database_cache):
@@ -96,18 +95,14 @@
                          dart2js_output_dir,
                          update_dom_metadata=False,
                          logging_level=logging.WARNING,
-                         dart_js_interop=False,
-                         nnbd=False):
+                         dart_js_interop=False):
     print '\n ----- Accessing DOM using %s -----\n' % (
         'dart:js' if dart_js_interop else 'C++')
 
     start_time = time.time()
 
     current_dir = os.path.dirname(__file__)
-    if nnbd:
-        auxiliary_dir = os.path.join(current_dir, '..', 'nnbd_src')
-    else:
-        auxiliary_dir = os.path.join(current_dir, '..', 'src')
+    auxiliary_dir = os.path.join(current_dir, '..', 'src')
     template_dir = os.path.join(current_dir, '..', 'templates')
 
     _logger.setLevel(logging_level)
@@ -142,7 +137,7 @@
                      backend_factory, dart_js_interop):
         options = GeneratorOptions(template_loader, webkit_database,
                                    type_registry, renamer, metadata,
-                                   dart_js_interop, nnbd)
+                                   dart_js_interop)
         dart_library_emitter = DartLibraryEmitter(emitters, dart_output_dir,
                                                   dart_libraries)
         event_generator = HtmlEventGenerator(webkit_database, renamer, metadata,
@@ -167,11 +162,11 @@
             'DARTIUM': False,
             'DART2JS': True,
             'JSINTEROP': False,
-            'NNBD': nnbd
+            'NNBD': True,
         })
         backend_options = GeneratorOptions(template_loader, webkit_database,
                                            type_registry, renamer, metadata,
-                                           dart_js_interop, nnbd)
+                                           dart_js_interop)
         backend_factory = lambda interface:\
             Dart2JSBackend(interface, backend_options, logging_level)
 
@@ -268,12 +263,6 @@
         default=None,
         help='Directory to put the generated files')
     parser.add_option(
-        '--nnbd',
-        dest='nnbd',
-        action='store_true',
-        default=False,
-        help='Generate code with non-nullability annotations')
-    parser.add_option(
         '--use-database-cache',
         dest='use_database_cache',
         action='store_true',
@@ -348,7 +337,7 @@
 
     GenerateFromDatabase(database, dart2js_output_dir,
                          options.update_dom_metadata, logging_level,
-                         options.dart_js_interop, options.nnbd)
+                         options.dart_js_interop)
 
     file_generation_start_time = time.time()
 
diff --git a/tools/dom/scripts/generator.py b/tools/dom/scripts/generator.py
index 44c721e..9f64192 100644
--- a/tools/dom/scripts/generator.py
+++ b/tools/dom/scripts/generator.py
@@ -13,13 +13,6 @@
 from htmlrenamer import custom_html_constructors, html_interface_renames, \
     typed_array_renames
 
-# TODO(srujzs): Pass options flag through to emitter functions.
-class GlobalOptionsHack(object):
-    nnbd = False
-
-global_options_hack = GlobalOptionsHack()
-
-
 _pure_interfaces = monitored.Set('generator._pure_interfaces', [
     'AbstractWorker',
     'CanvasPath',
@@ -688,7 +681,7 @@
   where a type may be omitted.
   The string is empty or has a trailing space.
   """
-    nullability_operator = '?' if global_options_hack.nnbd and nullable else ''
+    nullability_operator = '?' if nullable else ''
     if dart_type == 'dynamic':
         if comment:
             return '/*%s*/ ' % comment  # Just a comment foo(/*T*/ x)
@@ -1274,8 +1267,7 @@
         if self._data.dart_type:
             return self._data.dart_type
         if self.list_item_type() and not self.has_generated_interface():
-            item_nullable = '?' if self._data.item_type_nullable and \
-                global_options_hack.nnbd else ''
+            item_nullable = '?' if self._data.item_type_nullable else ''
             return 'List<%s%s>' % (self._type_registry.TypeInfo(
                 self._data.item_type).dart_type(), item_nullable)
         return self._dart_interface_name
diff --git a/tools/dom/scripts/htmldartgenerator.py b/tools/dom/scripts/htmldartgenerator.py
index ac223d9..f7797fd 100644
--- a/tools/dom/scripts/htmldartgenerator.py
+++ b/tools/dom/scripts/htmldartgenerator.py
@@ -114,7 +114,6 @@
         for id in sorted(operationsByName.keys()):
             operations = operationsByName[id]
             info = AnalyzeOperation(interface, operations)
-            info.nnbd = self._nnbd
             self.AddOperation(info, declare_only, dart_js_interop)
             if ('%s.%s' % (interface.id,
                            info.declared_name) in convert_to_future_members):
@@ -519,8 +518,7 @@
         if self._interface_type_info.list_item_type():
             item_type = self._type_registry.TypeInfo(
                 self._interface_type_info.list_item_type()).dart_type()
-            if self._nnbd and \
-                    self._interface_type_info.list_item_type_nullable():
+            if self._interface_type_info.list_item_type_nullable():
                 item_type += '?'
             implements.append('List<%s>' % item_type)
         return implements
@@ -530,8 +528,7 @@
         if self._interface_type_info.list_item_type():
             item_type = self._type_registry.TypeInfo(
                 self._interface_type_info.list_item_type()).dart_type()
-            if self._nnbd and \
-                    self._interface_type_info.list_item_type_nullable():
+            if self._interface_type_info.list_item_type_nullable():
                 item_type += '?'
             mixins.append('ListMixin<%s>' % item_type)
             mixins.append('ImmutableListMixin<%s>' % item_type)
@@ -907,8 +904,7 @@
             })
         if nullable:
             element_js = element_name + "|Null"
-            if self._nnbd:
-                element_name += '?'
+            element_name += '?'
         else:
             element_js = element_name
         self._members_emitter.Emit(
@@ -938,11 +934,10 @@
         assert (dart_name != 'HistoryBase' and dart_name != 'LocationBase')
         if dart_name == 'Window':
             dart_name = _secure_base_types[dart_name]
-        if self._nnbd:
-            if type_name == 'any':
-                dart_name = 'Object'
-            if nullable and dart_name != 'dynamic':
-                dart_name = dart_name + '?'
+        if type_name == 'any':
+            dart_name = 'Object'
+        if nullable and dart_name != 'dynamic':
+            dart_name = dart_name + '?'
         return dart_name
 
     def SecureBaseName(self, type_name):
@@ -1006,7 +1001,7 @@
                     NAME=temp_name,
                     CONVERT=conversion.function_name,
                     ARG=info.param_infos[position].name,
-                    NULLASSERT='!' if null_assert_needed and self._nnbd else '',
+                    NULLASSERT='!' if null_assert_needed else '',
                     ARITY=callBackInfo)
                 converted_arguments.append(temp_name)
                 param_type = temp_type
diff --git a/tools/dom/scripts/systemhtml.py b/tools/dom/scripts/systemhtml.py
index 70248c6..2cf97d7 100644
--- a/tools/dom/scripts/systemhtml.py
+++ b/tools/dom/scripts/systemhtml.py
@@ -591,11 +591,6 @@
         self._template_loader = options.templates
         self._type_registry = options.type_registry
         self._options = options
-        # TODO(srujzs): This sets the nnbd option globally inside generator.py
-        # since there is no options object there. This should should be cleaned
-        # up and passed as an option instead.
-        global_options_hack.nnbd = options.nnbd
-        self._nnbd = options.nnbd
         self._library_emitter = library_emitter
         self._event_generator = event_generator
         self._interface = interface
@@ -808,9 +803,9 @@
             NATIVESPEC=native_spec,
             KEYTYPE=maplikeKeyType,
             VALUETYPE=maplikeValueType,
-            NULLABLE='?' if self._options.nnbd else '',
-            NULLSAFECAST=True if self._options.nnbd else False,
-            NULLASSERT='!' if self._options.nnbd else '')
+            NULLABLE='?',
+            NULLSAFECAST=True,
+            NULLASSERT='!')
         stream_getter_signatures_emitter = None
         element_stream_getters_emitter = None
         if type(implementation_members_emitter) == tuple:
@@ -1159,7 +1154,6 @@
         self._type_registry = options.type_registry
         self._renamer = options.renamer
         self._metadata = options.metadata
-        self._nnbd = options.nnbd
         self._interface_type_info = self._type_registry.TypeInfo(
             self._interface.id)
         self._current_secondary_parent = None
@@ -1181,8 +1175,7 @@
         ):
             item_type = self._type_registry.TypeInfo(
                 self._interface_type_info.list_item_type()).dart_type()
-            if self._nnbd and \
-                    self._interface_type_info.list_item_type_nullable():
+            if self._interface_type_info.list_item_type_nullable():
                 item_type += '?'
             implements.append('JavaScriptIndexingBehavior<%s>' % item_type)
         return implements
@@ -1241,19 +1234,17 @@
                 "JS$CAST("
                 "'returns:$INTERFACE_NAME;creates:$INTERFACE_NAME;new:true',"
                 " '#.$METHOD(#)', $FACTORY, $ARGUMENTS)",
-                CAST='<' + self._interface_type_info.interface_name() +
-                '>' if self._nnbd else '',
+                CAST='<' + self._interface_type_info.interface_name() + '>',
                 INTERFACE_NAME=self._interface_type_info.interface_name(),
                 FACTORY=factory,
                 METHOD=method,
                 ARGUMENTS=arguments)
-        return emitter.Format(
-            '$FACTORY.$METHOD($ARGUMENTS)$CAST',
-            FACTORY=factory,
-            METHOD=method,
-            ARGUMENTS=arguments,
-            CAST=' as ' + self._interface_type_info.interface_name() \
-            if self._nnbd else '')
+        return emitter.Format('$FACTORY.$METHOD($ARGUMENTS)$CAST',
+                              FACTORY=factory,
+                              METHOD=method,
+                              ARGUMENTS=arguments,
+                              CAST=' as ' +
+                              self._interface_type_info.interface_name())
 
     def _HasUnreliableFactoryConstructor(self):
         return self._interface.doc_js_name in _js_unreliable_element_factories
@@ -1361,8 +1352,8 @@
                                            nullable=nullable),
                 # If the type of the operation is not nullable but the getter
                 # is, we must assert non-null.
-                NULLASSERT='!' if self._nnbd and not nullable and \
-                    indexed_getter_nullable else '')
+                NULLASSERT='!' if not nullable and indexed_getter_nullable \
+                    else '')
 
         if 'CustomIndexedSetter' in self._interface.ext_attrs:
             self._members_emitter.Emit(
@@ -1370,7 +1361,7 @@
                 '  void operator[]=(int index, $TYPE$NULLABLE value) {'
                 ' JS("void", "#[#] = #", this, index, value); }',
                 TYPE=self._NarrowInputType(element_type),
-                NULLABLE='?' if self._nnbd and nullable else '')
+                NULLABLE='?' if nullable else '')
         else:
             theType = self._NarrowInputType(element_type)
             if theType == 'DomRectList':
@@ -1382,7 +1373,7 @@
                 '    throw new UnsupportedError("Cannot assign element of immutable List.");\n'
                 '  }\n',
                 TYPE=theType,
-                NULLABLE='?' if self._nnbd and nullable else '')
+                NULLABLE='?' if nullable else '')
 
         self.EmitListMixin(self._DartType(element_type), nullable)
 
@@ -1460,7 +1451,7 @@
             return
 
         input_type = self._NarrowInputType(attribute.type.id)
-        if self._nnbd and attribute.type.nullable:
+        if attribute.type.nullable:
             input_type += '?'
         if not read_only:
             if attribute.type.id == 'Promise':
@@ -1483,8 +1474,8 @@
                         promiseCall = 'promiseToFutureAsMap'
                         output_conversion = self._OutputConversion("Dictionary",
                                                                    None)
-                        nullability = '?' if self._nnbd and \
-                            output_conversion.nullable_output else ''
+                        nullability = '?' if output_conversion.nullable_output \
+                            else ''
                         promiseType = 'Future<Map<String, dynamic>' + \
                             nullability + '>'
                     else:
@@ -1492,7 +1483,7 @@
                         promiseCall = 'promiseToFuture<%s>' % paramType
                         promiseType = 'Future<%s>' % paramType
 
-                if self._nnbd and attribute.type.nullable:
+                if attribute.type.nullable:
                     promiseType += '?'
 
                 template = '\n  $RENAME$(ANNOTATIONS)$TYPE get $NAME => $PROMISE_CALL(JS("", "#.$NAME", this));\n'
@@ -1592,11 +1583,11 @@
             HTML_NAME=html_name,
             NAME=attr.id,
             RETURN_TYPE=conversion.output_type,
-            NULLABLE_OUT='?' if nullable_out and self._nnbd else '',
+            NULLABLE_OUT='?' if nullable_out else '',
             NATIVE_TYPE=conversion.input_type,
-            NULLABLE_IN='?' if nullable_in and self._nnbd else '',
+            NULLABLE_IN='?' if nullable_in else '',
             NULLASSERT='!' if nullable_in and \
-                not conversion.nullable_input and self._nnbd else '')
+                not conversion.nullable_input else '')
 
     def _AddConvertingSetter(self, attr, html_name, conversion):
         # If the attribute is nullable, the setter should be nullable.
@@ -1617,11 +1608,11 @@
             HTML_NAME=html_name,
             NAME=attr.id,
             INPUT_TYPE=conversion.input_type,
-            NULLABLE_IN='?' if nullable_in and self._nnbd else '',
+            NULLABLE_IN='?' if nullable_in else '',
             NATIVE_TYPE=conversion.output_type,
-            NULLABLE_OUT='?' if nullable_out and self._nnbd else '',
+            NULLABLE_OUT='?' if nullable_out else '',
             NULLASSERT='!' if nullable_in and \
-                not conversion.nullable_input and self._nnbd else '')
+                not conversion.nullable_input else '')
 
     def AmendIndexer(self, element_type):
         pass
@@ -1765,8 +1756,8 @@
                     promiseCall = 'promiseToFutureAsMap'
                     output_conversion = self._OutputConversion("Dictionary",
                                                                None)
-                    nullability = '?' if self._nnbd and \
-                        output_conversion.nullable_output else ''
+                    nullability = '?' if output_conversion.nullable_output \
+                        else ''
                     promiseType = 'Future<Map<String, dynamic>' + \
                         nullability + '>'
                 else:
@@ -1777,7 +1768,7 @@
             dictionary_argument = info.dictionaryArgumentName()
             codeTemplate = self._promiseToFutureCode(argsNames,
                                                      dictionary_argument)
-            if self._nnbd and info.type_nullable:
+            if info.type_nullable:
                 promiseType += '?'
             self._members_emitter.Emit(
                 codeTemplate,
@@ -1852,8 +1843,7 @@
 
             if output_conversion:
                 call = '%s(%s)' % (output_conversion.function_name, call)
-                if self._nnbd and output_conversion.nullable_output and \
-                        not info.type_nullable:
+                if output_conversion.nullable_output and not info.type_nullable:
                     # Return type of operation is not nullable while conversion
                     # is, so we need to assert non-null.
                     call += '!'
@@ -1904,7 +1894,7 @@
             html_name.startswith('_')) else True
 
         nullsafe_return_type = return_type;
-        if self._nnbd and info.type_nullable:
+        if info.type_nullable:
             nullsafe_return_type += '?'
 
         declaration = '%s%s%s %s(%s)' % (
@@ -1970,18 +1960,15 @@
             return_type = self.SecureOutputType(idl_type)
             native_type = self._NarrowToImplementationType(idl_type)
 
-            null_union = '' if self._nnbd and not nullable else '|Null'
+            null_union = '' if not nullable else '|Null'
             if native_type != return_type:
                 anns = anns + [
                     "@Returns('%s%s')" % (native_type, null_union),
                     "@Creates('%s')" % native_type,
                 ]
-        if dart_type == 'dynamic' or \
-            (not self._nnbd and dart_type == 'Object') or \
-            (self._nnbd and dart_type == 'Object?'):
-            # If we're generating nnbd code, we emit non-nullable Object
-            # annotations but exclude nullable Object annotations since that's
-            # the default.
+        if dart_type == 'dynamic' or dart_type == 'Object?':
+            # We emit non-nullable Object annotations but exclude nullable
+            # Object annotations since that's the default.
 
             def js_type_annotation(ann):
                 return re.search('^@.*Returns', ann) or re.search(
@@ -2097,7 +2084,7 @@
         emitters = library_emitter.Emit(
             self._template,
             AUXILIARY_DIR=massage_path(auxiliary_dir),
-            NULLABLE='?' if global_options_hack.nnbd else '')
+            NULLABLE='?')
         if isinstance(emitters, tuple):
             imports_emitter, map_emitter = emitters
         else:
diff --git a/tools/dom/src/AttributeMap.dart b/tools/dom/src/AttributeMap.dart
index 71579e5..88f3bd4 100644
--- a/tools/dom/src/AttributeMap.dart
+++ b/tools/dom/src/AttributeMap.dart
@@ -16,7 +16,7 @@
   }
 
   Map<K, V> cast<K, V>() => Map.castFrom<String, String, K, V>(this);
-  bool containsValue(Object value) {
+  bool containsValue(Object? value) {
     for (var v in this.values) {
       if (value == v) {
         return true;
@@ -29,7 +29,7 @@
     if (!containsKey(key)) {
       this[key] = ifAbsent();
     }
-    return this[key];
+    return this[key] as String;
   }
 
   void clear() {
@@ -41,7 +41,7 @@
   void forEach(void f(String key, String value)) {
     for (var key in keys) {
       var value = this[key];
-      f(key, value);
+      f(key, value as String);
     }
   }
 
@@ -50,7 +50,7 @@
     var attributes = _element._attributes;
     var keys = <String>[];
     for (int i = 0, len = attributes.length; i < len; i++) {
-      _Attr attr = attributes[i];
+      _Attr attr = attributes[i] as _Attr;
       if (_matches(attr)) {
         keys.add(attr.name);
       }
@@ -63,7 +63,7 @@
     var attributes = _element._attributes;
     var values = <String>[];
     for (int i = 0, len = attributes.length; i < len; i++) {
-      _Attr attr = attributes[i];
+      _Attr attr = attributes[i] as _Attr;
       if (_matches(attr)) {
         values.add(attr.value);
       }
@@ -95,12 +95,12 @@
 class _ElementAttributeMap extends _AttributeMap {
   _ElementAttributeMap(Element element) : super(element);
 
-  bool containsKey(Object key) {
-    return _element._hasAttribute(key);
+  bool containsKey(Object? key) {
+    return key is String && _element._hasAttribute(key);
   }
 
-  String operator [](Object key) {
-    return _element.getAttribute(key);
+  String? operator [](Object? key) {
+    return _element.getAttribute(key as String);
   }
 
   void operator []=(String key, String value) {
@@ -108,7 +108,7 @@
   }
 
   @pragma('dart2js:tryInline')
-  String remove(Object key) => key is String ? _remove(_element, key) : null;
+  String? remove(Object? key) => key is String ? _remove(_element, key) : null;
 
   /**
    * The number of {key, value} pairs in the map.
@@ -122,8 +122,8 @@
   // Inline this because almost all call sites of [remove] do not use [value],
   // and the annotations on the `getAttribute` call allow it to be removed.
   @pragma('dart2js:tryInline')
-  static String _remove(Element element, String key) {
-    String value = JS(
+  static String? _remove(Element element, String key) {
+    String? value = JS(
         // throws:null(1) is not accurate since [key] could be malformed, but
         // [key] is checked again by `removeAttributeNS`.
         'returns:String|Null;depends:all;effects:none;throws:null(1)',
@@ -139,16 +139,16 @@
  * Wrapper to expose namespaced attributes as a typed map.
  */
 class _NamespacedAttributeMap extends _AttributeMap {
-  final String _namespace;
+  final String? _namespace;
 
   _NamespacedAttributeMap(Element element, this._namespace) : super(element);
 
-  bool containsKey(Object key) {
-    return _element._hasAttributeNS(_namespace, key);
+  bool containsKey(Object? key) {
+    return key is String && _element._hasAttributeNS(_namespace, key);
   }
 
-  String operator [](Object key) {
-    return _element.getAttributeNS(_namespace, key);
+  String? operator [](Object? key) {
+    return _element.getAttributeNS(_namespace, key as String);
   }
 
   void operator []=(String key, String value) {
@@ -156,7 +156,7 @@
   }
 
   @pragma('dart2js:tryInline')
-  String remove(Object key) =>
+  String? remove(Object? key) =>
       key is String ? _remove(_namespace, _element, key) : null;
 
   /**
@@ -172,8 +172,8 @@
   // returned [value], and the annotations on the `getAttributeNS` call allow it
   // to be removed.
   @pragma('dart2js:tryInline')
-  static String _remove(String namespace, Element element, String key) {
-    String value = JS(
+  static String? _remove(String? namespace, Element element, String key) {
+    String? value = JS(
         // throws:null(1) is not accurate since [key] could be malformed, but
         // [key] is checked again by `removeAttributeNS`.
         'returns:String|Null;depends:all;effects:none;throws:null(1)',
@@ -205,11 +205,12 @@
 
   Map<K, V> cast<K, V>() => Map.castFrom<String, String, K, V>(this);
   // TODO: Use lazy iterator when it is available on Map.
-  bool containsValue(Object value) => values.any((v) => v == value);
+  bool containsValue(Object? value) => values.any((v) => v == value);
 
-  bool containsKey(Object key) => _attributes.containsKey(_attr(key));
+  bool containsKey(Object? key) =>
+      _attributes.containsKey(_attr(key as String));
 
-  String operator [](Object key) => _attributes[_attr(key)];
+  String? operator [](Object? key) => _attributes[_attr(key as String)];
 
   void operator []=(String key, String value) {
     _attributes[_attr(key)] = value;
@@ -218,7 +219,7 @@
   String putIfAbsent(String key, String ifAbsent()) =>
       _attributes.putIfAbsent(_attr(key), ifAbsent);
 
-  String remove(Object key) => _attributes.remove(_attr(key));
+  String? remove(Object? key) => _attributes.remove(_attr(key as String));
 
   void clear() {
     // Needs to operate on a snapshot since we are mutating the collection.
diff --git a/tools/dom/src/CrossFrameTypes.dart b/tools/dom/src/CrossFrameTypes.dart
index a2aa545..7d210a3 100644
--- a/tools/dom/src/CrossFrameTypes.dart
+++ b/tools/dom/src/CrossFrameTypes.dart
@@ -61,7 +61,7 @@
    *     WindowBase otherWindow = thisWindow.open('http://www.example.com/', 'foo');
    *     print(otherWindow.opener == thisWindow); // 'true'
    */
-  WindowBase get opener;
+  WindowBase? get opener;
 
   /**
    * A reference to the parent of this window.
@@ -75,7 +75,7 @@
    *
    *     print(window.parent == window) // 'true'
    */
-  WindowBase get parent;
+  WindowBase? get parent;
 
   /**
    * A reference to the topmost window in the window hierarchy.
@@ -96,7 +96,7 @@
    *
    *     print(window.top == window) // 'true'
    */
-  WindowBase get top;
+  WindowBase? get top;
 
   // Methods.
   /**
@@ -142,7 +142,7 @@
    *   from WHATWG.
    */
   void postMessage(var message, String targetOrigin,
-      [List<MessagePort> messagePorts]);
+      [List<MessagePort>? messagePorts]);
 }
 
 abstract class LocationBase {
diff --git a/tools/dom/src/CssClassSet.dart b/tools/dom/src/CssClassSet.dart
index d1507bc..6a76202 100644
--- a/tools/dom/src/CssClassSet.dart
+++ b/tools/dom/src/CssClassSet.dart
@@ -24,7 +24,7 @@
    * non-empty string containing no whitespace.  To toggle multiple classes, use
    * [toggleAll].
    */
-  bool toggle(String value, [bool shouldAdd]);
+  bool toggle(String value, [bool? shouldAdd]);
 
   /**
    * Returns [:true:] if classes cannot be added or removed from this
@@ -41,7 +41,7 @@
    * [value] must be a valid 'token' representing a single class, i.e. a
    * non-empty string containing no whitespace.
    */
-  bool contains(Object value);
+  bool contains(Object? value);
 
   /**
    * Add the class [value] to element.
@@ -72,7 +72,7 @@
    * non-empty string containing no whitespace.  To remove multiple classes, use
    * [removeAll].
    */
-  bool remove(Object value);
+  bool remove(Object? value);
 
   /**
    * Add all classes specified in [iterable] to element.
@@ -94,7 +94,7 @@
    * Each element of [iterable] must be a valid 'token' representing a single
    * class, i.e. a non-empty string containing no whitespace.
    */
-  void removeAll(Iterable<Object> iterable);
+  void removeAll(Iterable<Object?> iterable);
 
   /**
    * Toggles all classes specified in [iterable] on element.
@@ -109,5 +109,5 @@
    * Each element of [iterable] must be a valid 'token' representing a single
    * class, i.e. a non-empty string containing no whitespace.
    */
-  void toggleAll(Iterable<String> iterable, [bool shouldAdd]);
+  void toggleAll(Iterable<String> iterable, [bool? shouldAdd]);
 }
diff --git a/tools/dom/src/CssRectangle.dart b/tools/dom/src/CssRectangle.dart
index 9cdef06..d26aac7 100644
--- a/tools/dom/src/CssRectangle.dart
+++ b/tools/dom/src/CssRectangle.dart
@@ -75,9 +75,9 @@
 class _ContentCssListRect extends _ContentCssRect {
   List<Element> _elementList;
 
-  _ContentCssListRect(List<Element> elementList) : super(elementList.first) {
-    _elementList = elementList;
-  }
+  _ContentCssListRect(List<Element> elementList)
+      : _elementList = elementList,
+        super(elementList.first);
 
   /**
    * Set the height to `newHeight`.
@@ -299,7 +299,7 @@
    * Returns the intersection of this and `other`, or `null` if they don't
    * intersect.
    */
-  Rectangle<num> intersection(Rectangle<num> other) {
+  Rectangle<num>? intersection(Rectangle<num> other) {
     var x0 = max(left, other.left);
     var x1 = min(left + width, other.left + other.width);
 
diff --git a/tools/dom/src/Dimension.dart b/tools/dom/src/Dimension.dart
index 502b68d..7ed02192 100644
--- a/tools/dom/src/Dimension.dart
+++ b/tools/dom/src/Dimension.dart
@@ -57,7 +57,9 @@
    * `inherit` or invalid CSS will cause this constructor to throw a
    * FormatError.
    */
-  Dimension.css(String cssValue) {
+  Dimension.css(String cssValue)
+      : _unit = '',
+        _value = 0 {
     if (cssValue == '') cssValue = '0px';
     if (cssValue.endsWith('%')) {
       _unit = '%';
diff --git a/tools/dom/src/EventStreamProvider.dart b/tools/dom/src/EventStreamProvider.dart
index 83b8c07..fe01be9 100644
--- a/tools/dom/src/EventStreamProvider.dart
+++ b/tools/dom/src/EventStreamProvider.dart
@@ -34,7 +34,7 @@
    * * [EventTarget.addEventListener](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener)
    *   from MDN.
    */
-  Stream<T> forTarget(EventTarget e, {bool useCapture: false}) =>
+  Stream<T> forTarget(EventTarget? e, {bool useCapture: false}) =>
       new _EventStream<T>(e, _eventType, useCapture);
 
   /**
@@ -126,7 +126,7 @@
  * Adapter for exposing DOM events as Dart streams.
  */
 class _EventStream<T extends Event> extends Stream<T> {
-  final EventTarget _target;
+  final EventTarget? _target;
   final String _eventType;
   final bool _useCapture;
 
@@ -134,16 +134,16 @@
 
   // DOM events are inherently multi-subscribers.
   Stream<T> asBroadcastStream(
-          {void onListen(StreamSubscription<T> subscription),
-          void onCancel(StreamSubscription<T> subscription)}) =>
+          {void onListen(StreamSubscription<T> subscription)?,
+          void onCancel(StreamSubscription<T> subscription)?}) =>
       this;
   bool get isBroadcast => true;
 
   // TODO(9757): Inlining should be smart and inline only when inlining would
   // enable scalar replacement of an immediately allocated receiver.
   @pragma('dart2js:tryInline')
-  StreamSubscription<T> listen(void onData(T event),
-      {Function onError, void onDone(), bool cancelOnError}) {
+  StreamSubscription<T> listen(void onData(T event)?,
+      {Function? onError, void onDone()?, bool? cancelOnError}) {
     return new _EventStreamSubscription<T>(
         this._target, this._eventType, onData, this._useCapture);
   }
@@ -194,8 +194,8 @@
       });
 
   // Delegate all regular Stream behavior to a wrapped Stream.
-  StreamSubscription<T> listen(void onData(T event),
-      {Function onError, void onDone(), bool cancelOnError}) {
+  StreamSubscription<T> listen(void onData(T event)?,
+      {Function? onError, void onDone()?, bool? cancelOnError}) {
     var pool = new _StreamPool<T>.broadcast();
     for (var target in _targetList) {
       pool.add(new _EventStream<T>(target, _eventType, _useCapture));
@@ -213,8 +213,8 @@
   }
 
   Stream<T> asBroadcastStream(
-          {void onListen(StreamSubscription<T> subscription),
-          void onCancel(StreamSubscription<T> subscription)}) =>
+          {void onListen(StreamSubscription<T> subscription)?,
+          void onCancel(StreamSubscription<T> subscription)?}) =>
       this;
   bool get isBroadcast => true;
 }
@@ -225,9 +225,9 @@
 
 class _EventStreamSubscription<T extends Event> extends StreamSubscription<T> {
   int _pauseCount = 0;
-  EventTarget _target;
+  EventTarget? _target;
   final String _eventType;
-  EventListener _onData;
+  EventListener? _onData;
   final bool _useCapture;
 
   // TODO(leafp): It would be better to write this as
@@ -240,7 +240,7 @@
   // which are typed correctly.  But this currently runs afoul of restrictions
   // on is checks for compatibility with the VM.
   _EventStreamSubscription(
-      this._target, this._eventType, void onData(T event), this._useCapture)
+      this._target, this._eventType, void onData(T event)?, this._useCapture)
       : _onData = onData == null
             ? null
             : _wrapZone<Event>((e) => (onData as dynamic)(e)) {
@@ -248,18 +248,23 @@
   }
 
   Future cancel() {
-    if (_canceled) return null;
+    // Check for strong mode. This function can no longer return null in strong
+    // mode, so only return null in weak mode to preserve synchronous timing.
+    // See issue 41653 for more details.
+    dynamic emptyFuture =
+        typeAcceptsNull<Event>() ? null : Future<void>.value();
+    if (_canceled) return emptyFuture as Future;
 
     _unlisten();
     // Clear out the target to indicate this is complete.
     _target = null;
     _onData = null;
-    return null;
+    return emptyFuture as Future;
   }
 
   bool get _canceled => _target == null;
 
-  void onData(void handleData(T event)) {
+  void onData(void handleData(T event)?) {
     if (_canceled) {
       throw new StateError("Subscription has been canceled.");
     }
@@ -272,12 +277,12 @@
   }
 
   /// Has no effect.
-  void onError(Function handleError) {}
+  void onError(Function? handleError) {}
 
   /// Has no effect.
-  void onDone(void handleDone()) {}
+  void onDone(void handleDone()?) {}
 
-  void pause([Future resumeSignal]) {
+  void pause([Future? resumeSignal]) {
     if (_canceled) return;
     ++_pauseCount;
     _unlisten();
@@ -297,17 +302,17 @@
 
   void _tryResume() {
     if (_onData != null && !isPaused) {
-      _target.addEventListener(_eventType, _onData, _useCapture);
+      _target!.addEventListener(_eventType, _onData, _useCapture);
     }
   }
 
   void _unlisten() {
     if (_onData != null) {
-      _target.removeEventListener(_eventType, _onData, _useCapture);
+      _target!.removeEventListener(_eventType, _onData, _useCapture);
     }
   }
 
-  Future<E> asFuture<E>([E futureValue]) {
+  Future<E> asFuture<E>([E? futureValue]) {
     // We just need a future that will never succeed or fail.
     var completer = new Completer<E>();
     return completer.future;
@@ -332,21 +337,20 @@
   /** The type of event this stream is providing (e.g. "keydown"). */
   String _type;
 
-  _CustomEventStreamImpl(String type) {
-    _type = type;
-    _streamController = new StreamController.broadcast(sync: true);
-  }
+  _CustomEventStreamImpl(String type)
+      : _type = type,
+        _streamController = new StreamController.broadcast(sync: true);
 
   // Delegate all regular Stream behavior to our wrapped Stream.
-  StreamSubscription<T> listen(void onData(T event),
-      {Function onError, void onDone(), bool cancelOnError}) {
+  StreamSubscription<T> listen(void onData(T event)?,
+      {Function? onError, void onDone()?, bool? cancelOnError}) {
     return _streamController.stream.listen(onData,
         onError: onError, onDone: onDone, cancelOnError: cancelOnError);
   }
 
   Stream<T> asBroadcastStream(
-          {void onListen(StreamSubscription<T> subscription),
-          void onCancel(StreamSubscription<T> subscription)}) =>
+          {void onListen(StreamSubscription<T> subscription)?,
+          void onCancel(StreamSubscription<T> subscription)?}) =>
       _streamController.stream;
 
   bool get isBroadcast => true;
@@ -362,7 +366,7 @@
 
   void add(KeyEvent event) {
     if (event.type == _type) {
-      event.currentTarget.dispatchEvent(event._parent);
+      event.currentTarget!.dispatchEvent(event._parent);
       _streamController.add(event);
     }
   }
@@ -374,7 +378,7 @@
  */
 // TODO (efortuna): Remove this when Issue 12218 is addressed.
 class _StreamPool<T> {
-  StreamController<T> _controller;
+  StreamController<T>? _controller;
 
   /// Subscriptions to the streams that make up the pool.
   var _subscriptions = new Map<Stream<T>, StreamSubscription<T>>();
@@ -394,7 +398,7 @@
   /**
    * The stream through which all events from streams in the pool are emitted.
    */
-  Stream<T> get stream => _controller.stream;
+  Stream<T> get stream => _controller!.stream;
 
   /**
    * Adds [stream] as a member of this pool.
@@ -405,8 +409,8 @@
    */
   void add(Stream<T> stream) {
     if (_subscriptions.containsKey(stream)) return;
-    _subscriptions[stream] = stream.listen(_controller.add,
-        onError: _controller.addError, onDone: () => remove(stream));
+    _subscriptions[stream] = stream.listen(_controller!.add,
+        onError: _controller!.addError, onDone: () => remove(stream));
   }
 
   /** Removes [stream] as a member of this pool. */
@@ -421,7 +425,7 @@
       subscription.cancel();
     }
     _subscriptions.clear();
-    _controller.close();
+    _controller!.close();
   }
 }
 
@@ -434,7 +438,7 @@
   final _eventTypeGetter;
   const _CustomEventStreamProvider(this._eventTypeGetter);
 
-  Stream<T> forTarget(EventTarget e, {bool useCapture: false}) {
+  Stream<T> forTarget(EventTarget? e, {bool useCapture: false}) {
     return new _EventStream<T>(e, _eventTypeGetter(e), useCapture);
   }
 
diff --git a/tools/dom/src/Html5NodeValidator.dart b/tools/dom/src/Html5NodeValidator.dart
index 8d04a1b..e6bdede 100644
--- a/tools/dom/src/Html5NodeValidator.dart
+++ b/tools/dom/src/Html5NodeValidator.dart
@@ -408,8 +408,8 @@
    * All known URI attributes will be validated against the UriPolicy, if
    * [uriPolicy] is null then a default UriPolicy will be used.
    */
-  _Html5NodeValidator({UriPolicy uriPolicy})
-      : uriPolicy = uriPolicy != null ? uriPolicy : new UriPolicy() {
+  _Html5NodeValidator({UriPolicy? uriPolicy})
+      : uriPolicy = uriPolicy ?? UriPolicy() {
     if (_attributeValidators.isEmpty) {
       for (var attr in _standardAttributes) {
         _attributeValidators[attr] = _standardAttributeValidator;
diff --git a/tools/dom/src/ImmutableListMixin.dart b/tools/dom/src/ImmutableListMixin.dart
index ecf5e7c..9910ebe 100644
--- a/tools/dom/src/ImmutableListMixin.dart
+++ b/tools/dom/src/ImmutableListMixin.dart
@@ -22,11 +22,11 @@
     throw new UnsupportedError("Cannot add to immutable List.");
   }
 
-  void sort([int compare(E a, E b)]) {
+  void sort([int compare(E a, E b)?]) {
     throw new UnsupportedError("Cannot sort immutable List.");
   }
 
-  void shuffle([Random random]) {
+  void shuffle([Random? random]) {
     throw new UnsupportedError("Cannot shuffle immutable List.");
   }
 
@@ -50,7 +50,7 @@
     throw new UnsupportedError("Cannot remove from immutable List.");
   }
 
-  bool remove(Object object) {
+  bool remove(Object? object) {
     throw new UnsupportedError("Cannot remove from immutable List.");
   }
 
@@ -74,7 +74,7 @@
     throw new UnsupportedError("Cannot modify an immutable List.");
   }
 
-  void fillRange(int start, int end, [E fillValue]) {
+  void fillRange(int start, int end, [E? fillValue]) {
     throw new UnsupportedError("Cannot modify an immutable List.");
   }
 }
diff --git a/tools/dom/src/KeyboardEventStream.dart b/tools/dom/src/KeyboardEventStream.dart
index 48f7a68..399c037 100644
--- a/tools/dom/src/KeyboardEventStream.dart
+++ b/tools/dom/src/KeyboardEventStream.dart
@@ -22,7 +22,7 @@
   final String _type;
 
   /** The element we are watching for events to happen on. */
-  final EventTarget _target;
+  final EventTarget? _target;
 
   // The distance to shift from upper case alphabet Roman letters to lower case.
   static final int _ROMAN_ALPHABET_OFFSET = "a".codeUnits[0] - "A".codeUnits[0];
@@ -65,7 +65,7 @@
 
   /** Return a stream for KeyEvents for the specified target. */
   // Note: this actually functions like a factory constructor.
-  CustomStream<KeyEvent> forTarget(EventTarget e, {bool useCapture: false}) {
+  CustomStream<KeyEvent> forTarget(EventTarget? e, {bool useCapture: false}) {
     var handler =
         new _KeyboardEventHandler.initializeAllEventListeners(_type, e);
     return handler._stream;
@@ -85,7 +85,8 @@
    * and charcodes when they are not provided.
    */
   _KeyboardEventHandler.initializeAllEventListeners(this._type, this._target)
-      : super(_EVENT_TYPE) {
+      : _stream = new _CustomKeyEventStreamImpl(_type),
+        super(_EVENT_TYPE) {
     Element.keyDownEvent
         .forTarget(_target, useCapture: true)
         .listen(processKeyDown);
@@ -95,7 +96,6 @@
     Element.keyUpEvent
         .forTarget(_target, useCapture: true)
         .listen(processKeyUp);
-    _stream = new _CustomKeyEventStreamImpl(_type);
   }
 
   /** Determine if caps lock is one of the currently depressed keys. */
@@ -337,7 +337,7 @@
         _keyIdentifier.containsKey(e._shadowKeyIdentifier)) {
       // This is needed for Safari Windows because it currently doesn't give a
       // keyCode/which for non printable keys.
-      e._shadowKeyCode = _keyIdentifier[e._shadowKeyIdentifier];
+      e._shadowKeyCode = _keyIdentifier[e._shadowKeyIdentifier]!;
     }
     e._shadowAltKey = _keyDownList.any((var element) => element.altKey);
     _stream.add(e);
@@ -346,7 +346,7 @@
   /** Handle keyup events. */
   void processKeyUp(KeyboardEvent event) {
     var e = new KeyEvent.wrap(event);
-    KeyboardEvent toRemove = null;
+    KeyboardEvent? toRemove = null;
     for (var key in _keyDownList) {
       if (key.keyCode == e.keyCode) {
         toRemove = key;
diff --git a/tools/dom/src/NodeValidatorBuilder.dart b/tools/dom/src/NodeValidatorBuilder.dart
index 92cfb3a..59f2b27 100644
--- a/tools/dom/src/NodeValidatorBuilder.dart
+++ b/tools/dom/src/NodeValidatorBuilder.dart
@@ -58,7 +58,7 @@
    * The UriPolicy can be used to restrict the locations the navigation elements
    * are allowed to direct to. By default this will use the default [UriPolicy].
    */
-  void allowNavigation([UriPolicy uriPolicy]) {
+  void allowNavigation([UriPolicy? uriPolicy]) {
     if (uriPolicy == null) {
       uriPolicy = new UriPolicy();
     }
@@ -71,7 +71,7 @@
    * The UriPolicy can be used to restrict the locations the images may be
    * loaded from. By default this will use the default [UriPolicy].
    */
-  void allowImages([UriPolicy uriPolicy]) {
+  void allowImages([UriPolicy? uriPolicy]) {
     if (uriPolicy == null) {
       uriPolicy = new UriPolicy();
     }
@@ -112,7 +112,7 @@
    * If [tagName] is not specified then this allows inline styles on all
    * elements. Otherwise tagName limits the styles to the specified elements.
    */
-  void allowInlineStyles({String tagName}) {
+  void allowInlineStyles({String? tagName}) {
     if (tagName == null) {
       tagName = '*';
     } else {
@@ -130,7 +130,7 @@
    * Common things which are not allowed are script elements, style attributes
    * and any script handlers.
    */
-  void allowHtml5({UriPolicy uriPolicy}) {
+  void allowHtml5({UriPolicy? uriPolicy}) {
     add(new _Html5NodeValidator(uriPolicy: uriPolicy));
   }
 
@@ -149,9 +149,9 @@
    * tag extensions.
    */
   void allowCustomElement(String tagName,
-      {UriPolicy uriPolicy,
-      Iterable<String> attributes,
-      Iterable<String> uriAttributes}) {
+      {UriPolicy? uriPolicy,
+      Iterable<String>? attributes,
+      Iterable<String>? uriAttributes}) {
     var tagNameUpper = tagName.toUpperCase();
     var attrs = attributes
         ?.map<String>((name) => '$tagNameUpper::${name.toLowerCase()}');
@@ -174,9 +174,9 @@
    * custom tags.
    */
   void allowTagExtension(String tagName, String baseName,
-      {UriPolicy uriPolicy,
-      Iterable<String> attributes,
-      Iterable<String> uriAttributes}) {
+      {UriPolicy? uriPolicy,
+      Iterable<String>? attributes,
+      Iterable<String>? uriAttributes}) {
     var baseNameUpper = baseName.toUpperCase();
     var tagNameUpper = tagName.toUpperCase();
     var attrs = attributes
@@ -192,9 +192,9 @@
   }
 
   void allowElement(String tagName,
-      {UriPolicy uriPolicy,
-      Iterable<String> attributes,
-      Iterable<String> uriAttributes}) {
+      {UriPolicy? uriPolicy,
+      Iterable<String>? attributes,
+      Iterable<String>? uriAttributes}) {
     allowCustomElement(tagName,
         uriPolicy: uriPolicy,
         attributes: attributes,
@@ -236,7 +236,7 @@
   final Set<String> allowedElements = new Set<String>();
   final Set<String> allowedAttributes = new Set<String>();
   final Set<String> allowedUriAttributes = new Set<String>();
-  final UriPolicy uriPolicy;
+  final UriPolicy? uriPolicy;
 
   factory _SimpleNodeValidator.allowNavigation(UriPolicy uriPolicy) {
     return new _SimpleNodeValidator(uriPolicy, allowedElements: const [
@@ -311,9 +311,9 @@
    * lowercase attribute name. For example `'IMG:src'`.
    */
   _SimpleNodeValidator(this.uriPolicy,
-      {Iterable<String> allowedElements,
-      Iterable<String> allowedAttributes,
-      Iterable<String> allowedUriAttributes}) {
+      {Iterable<String>? allowedElements,
+      Iterable<String>? allowedAttributes,
+      Iterable<String>? allowedUriAttributes}) {
     this.allowedElements.addAll(allowedElements ?? const []);
     allowedAttributes = allowedAttributes ?? const [];
     allowedUriAttributes = allowedUriAttributes ?? const [];
@@ -333,9 +333,9 @@
   bool allowsAttribute(Element element, String attributeName, String value) {
     var tagName = Element._safeTagName(element);
     if (allowedUriAttributes.contains('$tagName::$attributeName')) {
-      return uriPolicy.allowsUri(value);
+      return uriPolicy!.allowsUri(value);
     } else if (allowedUriAttributes.contains('*::$attributeName')) {
-      return uriPolicy.allowsUri(value);
+      return uriPolicy!.allowsUri(value);
     } else if (allowedAttributes.contains('$tagName::$attributeName')) {
       return true;
     } else if (allowedAttributes.contains('*::$attributeName')) {
@@ -356,8 +356,8 @@
   _CustomElementNodeValidator(
       UriPolicy uriPolicy,
       Iterable<String> allowedElements,
-      Iterable<String> allowedAttributes,
-      Iterable<String> allowedUriAttributes,
+      Iterable<String>? allowedAttributes,
+      Iterable<String>? allowedUriAttributes,
       bool allowTypeExtension,
       bool allowCustomTag)
       : this.allowTypeExtension = allowTypeExtension == true,
diff --git a/tools/dom/src/Validators.dart b/tools/dom/src/Validators.dart
index ce706ef..a498da9 100644
--- a/tools/dom/src/Validators.dart
+++ b/tools/dom/src/Validators.dart
@@ -19,7 +19,7 @@
    *
    * If a uriPolicy is not specified then the default uriPolicy will be used.
    */
-  factory NodeValidator({UriPolicy uriPolicy}) =>
+  factory NodeValidator({UriPolicy? uriPolicy}) =>
       new _Html5NodeValidator(uriPolicy: uriPolicy);
 
   factory NodeValidator.throws(NodeValidator base) =>
@@ -163,12 +163,12 @@
   _ValidatingTreeSanitizer(this.validator) {}
 
   void sanitizeTree(Node node) {
-    void walk(Node node, Node parent) {
+    void walk(Node node, Node? parent) {
       sanitizeNode(node, parent);
 
       var child = node.lastChild;
       while (null != child) {
-        Node nextChild;
+        Node? nextChild;
         try {
           // Child may be removed during the walk, and we may not even be able
           // to get its previousNode. But it's also possible that previousNode
@@ -199,7 +199,7 @@
   }
 
   /// Aggressively try to remove node.
-  void _removeNode(Node node, Node parent) {
+  void _removeNode(Node node, Node? parent) {
     // If we have the parent, it's presumably already passed more sanitization
     // or is the fragment, so ask it to remove the child. And if that fails
     // try to set the outer html.
@@ -212,7 +212,7 @@
   }
 
   /// Sanitize the element, assuming we can't trust anything about it.
-  void _sanitizeUntrustedElement(/* Element */ element, Node parent) {
+  void _sanitizeUntrustedElement(/* Element */ element, Node? parent) {
     // If the _hasCorruptedAttributes does not successfully return false,
     // then we consider it corrupted and remove.
     // TODO(alanknight): This is a workaround because on Firefox
@@ -261,8 +261,8 @@
   /// Having done basic sanity checking on the element, and computed the
   /// important attributes we want to check, remove it if it's not valid
   /// or not allowed, either as a whole or particular attributes.
-  void _sanitizeElement(Element element, Node parent, bool corrupted,
-      String text, String tag, Map attrs, String isAttr) {
+  void _sanitizeElement(Element element, Node? parent, bool corrupted,
+      String text, String tag, Map attrs, String? isAttr) {
     if (false != corrupted) {
       _removeNode(element, parent);
       window.console
@@ -304,7 +304,7 @@
   }
 
   /// Sanitize the node and its children recursively.
-  void sanitizeNode(Node node, Node parent) {
+  void sanitizeNode(Node node, Node? parent) {
     switch (node.nodeType) {
       case Node.ELEMENT_NODE:
         _sanitizeUntrustedElement(node, parent);
diff --git a/tools/dom/src/WrappedList.dart b/tools/dom/src/WrappedList.dart
index f3dcc53..65d0d94 100644
--- a/tools/dom/src/WrappedList.dart
+++ b/tools/dom/src/WrappedList.dart
@@ -26,7 +26,7 @@
     _list.add(element);
   }
 
-  bool remove(Object element) => _list.remove(element);
+  bool remove(Object? element) => _list.remove(element);
 
   void clear() {
     _list.clear();
@@ -34,7 +34,7 @@
 
   // List APIs
 
-  E operator [](int index) => _list[index];
+  E operator [](int index) => _list[index] as E;
 
   void operator []=(int index, E value) {
     _list[index] = value;
@@ -44,19 +44,23 @@
     _list.length = newLength;
   }
 
-  void sort([int compare(E a, E b)]) {
-    // Implicit downcast on argument from Node to E-extends-Node.
-    _list.sort((Node a, Node b) => compare(a, b));
+  void sort([int compare(E a, E b)?]) {
+    if (compare == null) {
+      _list.sort();
+    } else {
+      _list.sort((Node a, Node b) => compare(a as E, b as E));
+    }
   }
 
-  int indexOf(Object element, [int start = 0]) => _list.indexOf(element, start);
+  int indexOf(Object? element, [int start = 0]) =>
+      _list.indexOf(element as Node, start);
 
-  int lastIndexOf(Object element, [int start]) =>
-      _list.lastIndexOf(element, start);
+  int lastIndexOf(Object? element, [int? start]) =>
+      _list.lastIndexOf(element as Node, start);
 
   void insert(int index, E element) => _list.insert(index, element);
 
-  E removeAt(int index) => _list.removeAt(index);
+  E removeAt(int index) => _list.removeAt(index) as E;
 
   void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {
     _list.setRange(start, end, iterable, skipCount);
@@ -70,7 +74,7 @@
     _list.replaceRange(start, end, iterable);
   }
 
-  void fillRange(int start, int end, [E fillValue]) {
+  void fillRange(int start, int end, [E? fillValue]) {
     _list.fillRange(start, end, fillValue);
   }
 
@@ -89,5 +93,5 @@
     return _iterator.moveNext();
   }
 
-  E get current => _iterator.current;
+  E get current => _iterator.current as E;
 }
diff --git a/tools/dom/src/_ListIterators.dart b/tools/dom/src/_ListIterators.dart
index 0a9080e..74aaddc 100644
--- a/tools/dom/src/_ListIterators.dart
+++ b/tools/dom/src/_ListIterators.dart
@@ -9,7 +9,7 @@
   final List<T> _array;
   final int _length; // Cache array length for faster access.
   int _position;
-  T _current;
+  T? _current;
 
   FixedSizeListIterator(List<T> array)
       : _array = array,
@@ -28,14 +28,14 @@
     return false;
   }
 
-  T get current => _current;
+  T get current => _current as T;
 }
 
 // Iterator for arrays with variable size.
 class _VariableSizeListIterator<T> implements Iterator<T> {
   final List<T> _array;
   int _position;
-  T _current;
+  T? _current;
 
   _VariableSizeListIterator(List<T> array)
       : _array = array,
@@ -53,5 +53,5 @@
     return false;
   }
 
-  T get current => _current;
+  T get current => _current as T;
 }
diff --git a/tools/dom/src/dart2js_Console.dart b/tools/dom/src/dart2js_Console.dart
index 5ed9206..b3297d2 100644
--- a/tools/dom/src/dart2js_Console.dart
+++ b/tools/dom/src/dart2js_Console.dart
@@ -10,7 +10,7 @@
 
   bool get _isConsoleDefined => JS('bool', 'typeof console != "undefined"');
 
-  MemoryInfo get memory =>
+  MemoryInfo? get memory =>
       _isConsoleDefined ? JS('MemoryInfo', 'window.console.memory') : null;
 
   void assertCondition(bool condition, Object arg) => _isConsoleDefined
diff --git a/tools/dom/src/dart2js_Conversions.dart b/tools/dom/src/dart2js_Conversions.dart
index aa78ec1..cb943b4 100644
--- a/tools/dom/src/dart2js_Conversions.dart
+++ b/tools/dom/src/dart2js_Conversions.dart
@@ -10,12 +10,12 @@
 
 part of html;
 
-WindowBase _convertNativeToDart_Window(win) {
+WindowBase? _convertNativeToDart_Window(win) {
   if (win == null) return null;
   return _DOMWindowCrossFrame._createSafe(win);
 }
 
-EventTarget _convertNativeToDart_EventTarget(e) {
+EventTarget? _convertNativeToDart_EventTarget(e) {
   if (e == null) {
     return null;
   }
@@ -33,7 +33,7 @@
     return e;
 }
 
-EventTarget _convertDartToNative_EventTarget(e) {
+EventTarget? _convertDartToNative_EventTarget(e) {
   if (e is _DOMWindowCrossFrame) {
     return e._window;
   } else {
diff --git a/tools/dom/src/dart2js_CssClassSet.dart b/tools/dom/src/dart2js_CssClassSet.dart
index 5ae6795..00d80bc 100644
--- a/tools/dom/src/dart2js_CssClassSet.dart
+++ b/tools/dom/src/dart2js_CssClassSet.dart
@@ -54,7 +54,7 @@
    * TODO(sra): It seems wrong to collect a 'changed' flag like this when the
    * underlying toggle returns an 'is set' flag.
    */
-  bool toggle(String value, [bool shouldAdd]) => _sets.fold(
+  bool toggle(String value, [bool? shouldAdd]) => _sets.fold(
       false,
       (bool changed, CssClassSetImpl e) =>
           e.toggle(value, shouldAdd) || changed);
@@ -66,7 +66,7 @@
    * This is the Dart equivalent of jQuery's
    * [removeClass](http://api.jquery.com/removeClass/).
    */
-  bool remove(Object value) => _sets.fold(
+  bool remove(Object? value) => _sets.fold(
       false, (bool changed, CssClassSetImpl e) => e.remove(value) || changed);
 }
 
@@ -100,7 +100,7 @@
     _element.className = '';
   }
 
-  bool contains(Object value) {
+  bool contains(Object? value) {
     return _contains(_element, value);
   }
 
@@ -108,11 +108,11 @@
     return _add(_element, value);
   }
 
-  bool remove(Object value) {
+  bool remove(Object? value) {
     return value is String && _remove(_element, value);
   }
 
-  bool toggle(String value, [bool shouldAdd]) {
+  bool toggle(String value, [bool? shouldAdd]) {
     return _toggle(_element, value, shouldAdd);
   }
 
@@ -120,11 +120,11 @@
     _addAll(_element, iterable);
   }
 
-  void removeAll(Iterable<Object> iterable) {
+  void removeAll(Iterable<Object?> iterable) {
     _removeAll(_element, iterable);
   }
 
-  void retainAll(Iterable<Object> iterable) {
+  void retainAll(Iterable<Object?> iterable) {
     _removeWhere(_element, iterable.toSet().contains, false);
   }
 
@@ -136,7 +136,7 @@
     _removeWhere(_element, test, false);
   }
 
-  static bool _contains(Element _element, Object value) {
+  static bool _contains(Element _element, Object? value) {
     return value is String && _classListContains(_classListOf(_element), value);
   }
 
@@ -157,7 +157,7 @@
     return removed;
   }
 
-  static bool _toggle(Element _element, String value, bool shouldAdd) {
+  static bool _toggle(Element _element, String value, bool? shouldAdd) {
     // There is no value that can be passed as the second argument of
     // DomTokenList.toggle that behaves the same as passing one argument.
     // `null` is seen as false, meaning 'remove'.
@@ -171,13 +171,13 @@
     return _classListToggle1(list, value);
   }
 
-  static bool _toggleOnOff(Element _element, String value, bool shouldAdd) {
+  static bool _toggleOnOff(Element _element, String value, bool? shouldAdd) {
     DomTokenList list = _classListOf(_element);
     // IE's toggle does not take a second parameter. We would prefer:
     //
     //    return _classListToggle2(list, value, shouldAdd);
     //
-    if (shouldAdd) {
+    if (shouldAdd ?? false) {
       _classListAdd(list, value);
       return true;
     } else {
@@ -193,10 +193,10 @@
     }
   }
 
-  static void _removeAll(Element _element, Iterable<Object> iterable) {
+  static void _removeAll(Element _element, Iterable<Object?> iterable) {
     DomTokenList list = _classListOf(_element);
-    for (String value in iterable) {
-      _classListRemove(list, value);
+    for (Object? value in iterable) {
+      _classListRemove(list, value as String);
     }
   }
 
@@ -205,7 +205,7 @@
     DomTokenList list = _classListOf(_element);
     int i = 0;
     while (i < _classListLength(list)) {
-      String item = list.item(i);
+      String item = list.item(i)!;
       if (doRemove == test(item)) {
         _classListRemove(list, item);
       } else {
@@ -254,7 +254,7 @@
   }
 
   static bool _classListToggle2(
-      DomTokenList list, String value, bool shouldAdd) {
+      DomTokenList list, String value, bool? shouldAdd) {
     return JS('bool', '#.toggle(#, #)', list, value, shouldAdd);
   }
 }
diff --git a/tools/dom/src/dart2js_CustomElementSupport.dart b/tools/dom/src/dart2js_CustomElementSupport.dart
index 98c3c24..bbe6a37 100644
--- a/tools/dom/src/dart2js_CustomElementSupport.dart
+++ b/tools/dom/src/dart2js_CustomElementSupport.dart
@@ -66,7 +66,7 @@
   }
 }
 
-Function _registerCustomElement(context, document, String tag, [Map options]) {
+Function _registerCustomElement(context, document, String tag, [Map? options]) {
   // Function follows the same pattern as the following JavaScript code for
   // registering a custom element.
   //
@@ -82,7 +82,7 @@
   //    var e = document.createElement('x-foo');
 
   var extendsTagName = '';
-  Type type;
+  Type? type;
   if (options != null) {
     extendsTagName = options['extends'];
     type = options['prototype'];
@@ -162,7 +162,7 @@
   var _constructor;
   var _nativeType;
 
-  _JSElementUpgrader(Document document, Type type, String extendsTag) {
+  _JSElementUpgrader(Document document, Type type, String? extendsTag) {
     var interceptorClass = findInterceptorConstructorForType(type);
     if (interceptorClass == null) {
       throw new ArgumentError(type);
diff --git a/tools/dom/src/dart2js_DOMImplementation.dart b/tools/dom/src/dart2js_DOMImplementation.dart
index 393ec72..8016f6e 100644
--- a/tools/dom/src/dart2js_DOMImplementation.dart
+++ b/tools/dom/src/dart2js_DOMImplementation.dart
@@ -14,8 +14,8 @@
   // Fields.
   HistoryBase get history =>
       _HistoryCrossFrame._createSafe(JS('HistoryBase', '#.history', _window));
-  LocationBase get location => _LocationCrossFrame
-      ._createSafe(JS('LocationBase', '#.location', _window));
+  LocationBase get location => _LocationCrossFrame._createSafe(
+      JS('LocationBase', '#.location', _window));
 
   // TODO(vsm): Add frames to navigate subframes.  See 2312.
 
@@ -30,8 +30,7 @@
   // Methods.
   void close() => JS('void', '#.close()', _window);
 
-  void postMessage(var message, String targetOrigin,
-      [List messagePorts = null]) {
+  void postMessage(var message, String targetOrigin, [List? messagePorts]) {
     if (messagePorts == null) {
       JS('void', '#.postMessage(#,#)', _window,
           convertDartToNative_SerializedScriptValue(message), targetOrigin);
@@ -63,26 +62,26 @@
   Events get on => throw new UnsupportedError(
       'You can only attach EventListeners to your own window.');
   // TODO(efortuna): Remove this method. dartbug.com/16814
-  void _addEventListener(String type, EventListener listener,
-          [bool useCapture]) =>
+  void _addEventListener(String? type, EventListener? listener,
+          [bool? useCapture]) =>
       throw new UnsupportedError(
           'You can only attach EventListeners to your own window.');
   // TODO(efortuna): Remove this method. dartbug.com/16814
-  void addEventListener(String type, EventListener listener,
-          [bool useCapture]) =>
+  void addEventListener(String type, EventListener? listener,
+          [bool? useCapture]) =>
       throw new UnsupportedError(
           'You can only attach EventListeners to your own window.');
   // TODO(efortuna): Remove this method. dartbug.com/16814
   bool dispatchEvent(Event event) => throw new UnsupportedError(
       'You can only attach EventListeners to your own window.');
   // TODO(efortuna): Remove this method. dartbug.com/16814
-  void _removeEventListener(String type, EventListener listener,
-          [bool useCapture]) =>
+  void _removeEventListener(String? type, EventListener? listener,
+          [bool? useCapture]) =>
       throw new UnsupportedError(
           'You can only attach EventListeners to your own window.');
   // TODO(efortuna): Remove this method. dartbug.com/16814
-  void removeEventListener(String type, EventListener listener,
-          [bool useCapture]) =>
+  void removeEventListener(String type, EventListener? listener,
+          [bool? useCapture]) =>
       throw new UnsupportedError(
           'You can only attach EventListeners to your own window.');
 }
diff --git a/tools/dom/src/dart2js_KeyEvent.dart b/tools/dom/src/dart2js_KeyEvent.dart
index ad8c905..422c7ad 100644
--- a/tools/dom/src/dart2js_KeyEvent.dart
+++ b/tools/dom/src/dart2js_KeyEvent.dart
@@ -60,9 +60,10 @@
   bool get _realAltKey => JS('bool', '#.altKey', _parent);
 
   /** Shadows on top of the parent's currentTarget. */
-  EventTarget _currentTarget;
+  EventTarget? _currentTarget;
 
-  final InputDeviceCapabilities sourceCapabilities;
+  InputDeviceCapabilities? get sourceCapabilities =>
+      JS('InputDeviceCapabilities', '#.sourceCapabilities', this);
 
   /**
    * The value we want to use for this object's dispatch. Created here so it is
@@ -77,7 +78,12 @@
   }
 
   /** Construct a KeyEvent with [parent] as the event we're emulating. */
-  KeyEvent.wrap(KeyboardEvent parent) : super(parent) {
+  KeyEvent.wrap(KeyboardEvent parent)
+      : _parent = parent,
+        _shadowAltKey = false,
+        _shadowCharCode = 0,
+        _shadowKeyCode = 0,
+        super(parent) {
     _parent = parent;
     _shadowAltKey = _realAltKey;
     _shadowCharCode = _realCharCode;
@@ -87,7 +93,7 @@
 
   /** Programmatically create a new KeyEvent (and KeyboardEvent). */
   factory KeyEvent(String type,
-      {Window view,
+      {Window? view,
       bool canBubble: true,
       bool cancelable: true,
       int keyCode: 0,
@@ -97,12 +103,12 @@
       bool altKey: false,
       bool shiftKey: false,
       bool metaKey: false,
-      EventTarget currentTarget}) {
+      EventTarget? currentTarget}) {
     if (view == null) {
       view = window;
     }
 
-    var eventObj;
+    dynamic eventObj;
 
     // Currently this works on everything but Safari. Safari throws an
     // "Attempting to change access mechanism for an unconfigurable property"
@@ -119,17 +125,17 @@
     JS(
         'void',
         "Object.defineProperty(#, 'keyCode', {"
-        "  get : function() { return this.keyCodeVal; } })",
+            "  get : function() { return this.keyCodeVal; } })",
         eventObj);
     JS(
         'void',
         "Object.defineProperty(#, 'which', {"
-        "  get : function() { return this.keyCodeVal; } })",
+            "  get : function() { return this.keyCodeVal; } })",
         eventObj);
     JS(
         'void',
         "Object.defineProperty(#, 'charCode', {"
-        "  get : function() { return this.charCodeVal; } })",
+            "  get : function() { return this.charCodeVal; } })",
         eventObj);
 
     var keyIdentifier = _convertToHexString(charCode, keyCode);
@@ -152,10 +158,10 @@
   static bool get canUseDispatchEvent => JS(
       'bool',
       '(typeof document.body.dispatchEvent == "function")'
-      '&& document.body.dispatchEvent.length > 0');
+          '&& document.body.dispatchEvent.length > 0');
 
   /** The currently registered target for this event. */
-  EventTarget get currentTarget => _currentTarget;
+  EventTarget? get currentTarget => _currentTarget;
 
   // This is an experimental method to be sure.
   static String _convertToHexString(int charCode, int keyCode) {
@@ -198,9 +204,9 @@
   bool get metaKey => _parent.metaKey;
   /** True if the shift key was pressed during this event. */
   bool get shiftKey => _parent.shiftKey;
-  Window get view => _parent.view;
+  WindowBase? get view => _parent.view;
   void _initUIEvent(
-      String type, bool canBubble, bool cancelable, Window view, int detail) {
+      String type, bool canBubble, bool cancelable, Window? view, int detail) {
     throw new UnsupportedError("Cannot initialize a UI Event from a KeyEvent.");
   }
 
@@ -218,9 +224,9 @@
       String type,
       bool canBubble,
       bool cancelable,
-      Window view,
+      Window? view,
       String keyIdentifier,
-      int location,
+      int? location,
       bool ctrlKey,
       bool altKey,
       bool shiftKey,
diff --git a/tools/dom/src/dart2js_Platform.dart b/tools/dom/src/dart2js_Platform.dart
index 5988011..995f4f4 100644
--- a/tools/dom/src/dart2js_Platform.dart
+++ b/tools/dom/src/dart2js_Platform.dart
@@ -10,7 +10,7 @@
    * browser.  If false, using these types will generate a runtime
    * error.
    */
-  static final supportsTypedData = JS('bool', '!!(window.ArrayBuffer)');
+  static final bool supportsTypedData = JS('bool', '!!(window.ArrayBuffer)');
 
   /**
    * Returns true if SIMD types in dart:typed_data types are supported
diff --git a/tools/dom/src/dart2js_WrappedEvent.dart b/tools/dom/src/dart2js_WrappedEvent.dart
index 4d2ac28..dff9e38 100644
--- a/tools/dom/src/dart2js_WrappedEvent.dart
+++ b/tools/dom/src/dart2js_WrappedEvent.dart
@@ -11,7 +11,7 @@
   final Event wrapped;
 
   /** The CSS selector involved with event delegation. */
-  String _selector;
+  String? _selector;
 
   _WrappedEvent(this.wrapped);
 
@@ -21,7 +21,7 @@
 
   bool get composed => wrapped.composed;
 
-  EventTarget get currentTarget => wrapped.currentTarget;
+  EventTarget? get currentTarget => wrapped.currentTarget;
 
   bool get defaultPrevented => wrapped.defaultPrevented;
 
@@ -29,13 +29,13 @@
 
   bool get isTrusted => wrapped.isTrusted;
 
-  EventTarget get target => wrapped.target;
+  EventTarget? get target => wrapped.target;
 
-  double get timeStamp => wrapped.timeStamp;
+  double get timeStamp => wrapped.timeStamp as double;
 
   String get type => wrapped.type;
 
-  void _initEvent(String type, [bool bubbles, bool cancelable]) {
+  void _initEvent(String type, [bool? bubbles, bool? cancelable]) {
     throw new UnsupportedError('Cannot initialize this Event.');
   }
 
@@ -63,13 +63,12 @@
       throw new UnsupportedError('Cannot call matchingTarget if this Event did'
           ' not arise as a result of event delegation.');
     }
-    Element currentTarget = this.currentTarget;
-    Element target = this.target;
-    var matchedTarget;
+    Element? currentTarget = this.currentTarget as Element?;
+    Element? target = this.target as Element?;
     do {
-      if (target.matches(_selector)) return target;
+      if (target!.matches(_selector!)) return target;
       target = target.parent;
-    } while (target != null && target != currentTarget.parent);
+    } while (target != null && target != currentTarget!.parent);
     throw new StateError('No selector matched for populating matchedTarget.');
   }
 
@@ -83,7 +82,7 @@
    *   from W3C.
    */
   // https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#extensions-to-event
-  List<Node> get path => wrapped.path;
+  List<Node> get path => wrapped.path as List<Node>;
 
   dynamic get _get_currentTarget => wrapped._get_currentTarget;
 
diff --git a/tools/dom/src/native_DOMImplementation.dart b/tools/dom/src/native_DOMImplementation.dart
index ee81750..79f5d04 100644
--- a/tools/dom/src/native_DOMImplementation.dart
+++ b/tools/dom/src/native_DOMImplementation.dart
@@ -137,7 +137,7 @@
     return matches.toList();
   }
 
-  static setLibrary([String name]) {
+  static setLibrary([String? name]) {
     // Bust cache in case library list has changed. Ideally we would listen for
     // when libraries are loaded and invalidate based on that.
     _validCache = false;
@@ -1084,16 +1084,16 @@
     var history = _blink.BlinkWindow.instance.history_Getter_(this);
     return history is _HistoryCrossFrame
         ? history
-        : _blink.Blink_Utils
-            .setInstanceInterceptor(history, _HistoryCrossFrame);
+        : _blink.Blink_Utils.setInstanceInterceptor(
+            history, _HistoryCrossFrame);
   }
 
   LocationBase get location {
     var location = _blink.BlinkWindow.instance.location_Getter_(this);
     return location is _LocationCrossFrame
         ? location
-        : _blink.Blink_Utils
-            .setInstanceInterceptor(location, _LocationCrossFrame);
+        : _blink.Blink_Utils.setInstanceInterceptor(
+            location, _LocationCrossFrame);
   }
 
   bool get closed => _blink.BlinkWindow.instance.closed_Getter_(this);
@@ -1107,7 +1107,7 @@
   // Methods.
   void close() => _blink.BlinkWindow.instance.close_Callback_0_(this);
   void postMessage(Object message, String targetOrigin,
-          [List<MessagePort> transfer]) =>
+          [List<MessagePort>? transfer]) =>
       _blink.BlinkWindow.instance.postMessage_Callback_3_(
           this,
           convertDartToNative_SerializedScriptValue(message),
@@ -1122,12 +1122,12 @@
       'You can only attach EventListeners to your own window.');
   // TODO(efortuna): Remove this method. dartbug.com/16814
   void _addEventListener(
-          [String type, EventListener listener, bool useCapture]) =>
+          [String? type, EventListener? listener, bool? useCapture]) =>
       throw new UnsupportedError(
           'You can only attach EventListeners to your own window.');
   // TODO(efortuna): Remove this method. dartbug.com/16814
-  void addEventListener(String type, EventListener listener,
-          [bool useCapture]) =>
+  void addEventListener(String type, EventListener? listener,
+          [bool? useCapture]) =>
       throw new UnsupportedError(
           'You can only attach EventListeners to your own window.');
   // TODO(efortuna): Remove this method. dartbug.com/16814
@@ -1135,12 +1135,12 @@
       'You can only attach EventListeners to your own window.');
   // TODO(efortuna): Remove this method. dartbug.com/16814
   void _removeEventListener(
-          [String type, EventListener listener, bool useCapture]) =>
+          [String? type, EventListener? listener, bool? useCapture]) =>
       throw new UnsupportedError(
           'You can only attach EventListeners to your own window.');
   // TODO(efortuna): Remove this method. dartbug.com/16814
-  void removeEventListener(String type, EventListener listener,
-          [bool useCapture]) =>
+  void removeEventListener(String type, EventListener? listener,
+          [bool? useCapture]) =>
       throw new UnsupportedError(
           'You can only attach EventListeners to your own window.');
 }
@@ -1151,7 +1151,7 @@
   // Methods.
   void back() => _blink.BlinkHistory.instance.back_Callback_0_(this);
   void forward() => _blink.BlinkHistory.instance.forward_Callback_0_(this);
-  void go([int delta]) {
+  void go([int? delta]) {
     if (delta != null) {
       _blink.BlinkHistory.instance.go_Callback_1_(this, delta);
       return;
diff --git a/tools/dom/src/shared_SVGFactoryProviders.dart b/tools/dom/src/shared_SVGFactoryProviders.dart
index a4aab93..2c729f7 100644
--- a/tools/dom/src/shared_SVGFactoryProviders.dart
+++ b/tools/dom/src/shared_SVGFactoryProviders.dart
@@ -8,6 +8,6 @@
   static SvgElement createSvgElement_tag(String tag) {
     final Element temp =
         document.createElementNS("http://www.w3.org/2000/svg", tag);
-    return temp;
+    return temp as SvgElement;
   }
 }
diff --git a/tools/dom/src/shared_html.dart b/tools/dom/src/shared_html.dart
index f2aa8a9..f86f288 100644
--- a/tools/dom/src/shared_html.dart
+++ b/tools/dom/src/shared_html.dart
@@ -4,14 +4,15 @@
 
 part of dart.dom.html;
 
-void Function(T) _wrapZone<T>(void Function(T) callback) {
+void Function(T)? _wrapZone<T>(void Function(T)? callback) {
   // For performance reasons avoid wrapping if we are in the root zone.
   if (Zone.current == Zone.root) return callback;
   if (callback == null) return null;
   return Zone.current.bindUnaryCallbackGuarded(callback);
 }
 
-void Function(T1, T2) _wrapBinaryZone<T1, T2>(void Function(T1, T2) callback) {
+void Function(T1, T2)? _wrapBinaryZone<T1, T2>(
+    void Function(T1, T2)? callback) {
   // For performance reasons avoid wrapping if we are in the root zone.
   if (Zone.current == Zone.root) return callback;
   if (callback == null) return null;
@@ -35,7 +36,7 @@
  * For details about CSS selector syntax, see the
  * [CSS selector specification](http://www.w3.org/TR/css3-selectors/).
  */
-Element querySelector(String selectors) => document.querySelector(selectors);
+Element? querySelector(String selectors) => document.querySelector(selectors);
 
 /**
  * Finds all descendant elements of this document that match the specified
diff --git a/tools/migration/bin/test.dart b/tools/migration/bin/test.dart
index 561b100..875c5b7 100644
--- a/tools/migration/bin/test.dart
+++ b/tools/migration/bin/test.dart
@@ -36,6 +36,14 @@
   "vm": "dartk-weak-asserts-linux-release-x64",
 };
 
+const legacyConfigurations = {
+  "analyzer": "analyzer-asserts-linux",
+  "cfe": "cfe-linux",
+  "dart2js": "dart2js-hostasserts-linux-x64-d8",
+  "ddc": "dartdevk-checked-linux-release-chrome",
+  "vm": "dartk-checked-linux-release-x64",
+};
+
 final _failurePattern = RegExp(r"FAILED: [a-z0-9_-]+ [a-z0-9_-]+ (.*)");
 
 void main(List<String> arguments) async {
@@ -157,8 +165,15 @@
   // configuration. Otherwise, use the right named configuration.
   List<String> testArgs;
   if (Platform.isLinux || compiler != "ddc") {
-    var configurations = isStrong ? strongConfigurations : weakConfigurations;
-    var configuration = configurations[compiler];
+    String configuration;
+    if (isLegacy) {
+      configuration = legacyConfigurations[compiler];
+    } else if (isStrong) {
+      configuration = strongConfigurations[compiler];
+    } else {
+      configuration = weakConfigurations[compiler];
+    }
+
     if (!Platform.isLinux) {
       // TODO(rnystrom): We'll probably never need to run this script on
       // Windows, but if we do... do that.
diff --git a/utils/dartdevc/BUILD.gn b/utils/dartdevc/BUILD.gn
index 9591612..15bfe16 100644
--- a/utils/dartdevc/BUILD.gn
+++ b/utils/dartdevc/BUILD.gn
@@ -322,16 +322,13 @@
     ]
 
     if (invoker.sound_null_safety) {
-      args += [
-        "--nnbd-strong",
-      ]
+      args += [ "--nnbd-strong" ]
 
       outputs = [
         sdk_full_sound_dill,
         sdk_outline_sound_dill,
       ]
     } else {
-
       outputs = [
         sdk_full_dill,
         sdk_outline_dill,
@@ -387,7 +384,7 @@
       "$js_gen_dir/legacy/dart_sdk.js.map",
     ]
 
-    script = "../../pkg/dev_compiler/tool/compile_dartdevc_sdk.dart"
+    script = "../../pkg/dev_compiler/bin/dartdevc.dart"
 
     args = [
       "--multi-root-scheme",