From 7797c03170beb0f63d4eba3c5915b413aa6bf855 Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Wed, 1 Mar 2023 18:59:48 +0100 Subject: [PATCH 01/31] minor --- lib/theme/durations.dart | 25 +-- lib/widgets/aves_app.dart | 169 +++++++++--------- lib/widgets/collection/collection_grid.dart | 2 +- lib/widgets/collection/collection_page.dart | 6 +- .../draggable_scrollbar/arrow_clipper.dart | 38 ++++ .../draggable_scrollbar/notifications.dart | 10 ++ .../draggable_scrollbar/scroll_label.dart | 30 ++++ .../scrollbar.dart} | 115 +----------- .../basic/draggable_scrollbar/transition.dart | 31 ++++ lib/widgets/common/identity/scroll_thumb.dart | 3 +- .../common/providers/durations_provider.dart | 16 ++ .../providers/highlight_info_provider.dart | 21 +-- .../filter_grids/common/filter_grid_page.dart | 7 +- lib/widgets/navigation/nav_bar/floating.dart | 10 +- lib/widgets/navigation/nav_bar/nav_bar.dart | 4 +- 15 files changed, 236 insertions(+), 251 deletions(-) create mode 100644 lib/widgets/common/basic/draggable_scrollbar/arrow_clipper.dart create mode 100644 lib/widgets/common/basic/draggable_scrollbar/notifications.dart create mode 100644 lib/widgets/common/basic/draggable_scrollbar/scroll_label.dart rename lib/widgets/common/basic/{draggable_scrollbar.dart => draggable_scrollbar/scrollbar.dart} (78%) create mode 100644 lib/widgets/common/basic/draggable_scrollbar/transition.dart create mode 100644 lib/widgets/common/providers/durations_provider.dart diff --git a/lib/theme/durations.dart b/lib/theme/durations.dart index a91ba9123..058206239 100644 --- a/lib/theme/durations.dart +++ b/lib/theme/durations.dart @@ -1,7 +1,4 @@ -import 'package:aves/model/settings/enums/accessibility_animations.dart'; -import 'package:aves/model/settings/settings.dart'; -import 'package:flutter/widgets.dart'; -import 'package:provider/provider.dart'; +import 'package:flutter/foundation.dart'; class Durations { // Flutter animations (with margin) @@ -72,26 +69,6 @@ class Durations { static const mapIdleDebounceDelay = Duration(milliseconds: 100); } -class DurationsProvider extends StatelessWidget { - final Widget child; - - const DurationsProvider({ - super.key, - required this.child, - }); - - @override - Widget build(BuildContext context) { - return ProxyProvider( - update: (context, settings, __) { - final enabled = settings.accessibilityAnimations.animate; - return enabled ? DurationsData() : DurationsData.noAnimation(); - }, - child: child, - ); - } -} - @immutable class DurationsData { // common animations diff --git a/lib/widgets/aves_app.dart b/lib/widgets/aves_app.dart index f8e785b7c..211f883e2 100644 --- a/lib/widgets/aves_app.dart +++ b/lib/widgets/aves_app.dart @@ -33,6 +33,7 @@ import 'package:aves/widgets/common/basic/scaffold.dart'; import 'package:aves/widgets/common/behaviour/route_tracker.dart'; import 'package:aves/widgets/common/behaviour/routes.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; +import 'package:aves/widgets/common/providers/durations_provider.dart'; import 'package:aves/widgets/common/providers/highlight_info_provider.dart'; import 'package:aves/widgets/common/providers/media_query_data_provider.dart'; import 'package:aves/widgets/home_page.dart'; @@ -190,95 +191,87 @@ class _AvesAppState extends State with WidgetsBindingObserver { Widget build(BuildContext context) { // place the settings provider above `MaterialApp` // so it can be used during navigation transitions - return Provider.value( - value: widget.flavor, - child: ChangeNotifierProvider.value( - value: settings, - child: ListenableProvider>.value( - value: _appModeNotifier, - child: Provider.value( - value: _mediaStoreSource, - child: Provider.value( - value: _tvRailController, - child: DurationsProvider( - child: HighlightInfoProvider( - child: OverlaySupport( - child: FutureBuilder( - future: _appSetup, - builder: (context, snapshot) { - final initialized = !snapshot.hasError && snapshot.connectionState == ConnectionState.done; - if (initialized) { - AvesApp.showSystemUI(); - } - final home = initialized - ? _getFirstPage() - : AvesScaffold( - body: snapshot.hasError ? _buildError(snapshot.error!) : const SizedBox(), - ); - return Selector>( - selector: (context, s) => Tuple3( - s.locale, - s.initialized ? s.themeBrightness : SettingsDefaults.themeBrightness, - s.initialized ? s.enableDynamicColor : SettingsDefaults.enableDynamicColor, - ), - builder: (context, s, child) { - final settingsLocale = s.item1; - final themeBrightness = s.item2; - final enableDynamicColor = s.item3; - - Constants.updateStylesForLocale(settings.appliedLocale); - - return FutureBuilder( - future: _dynamicColorPaletteLoader, - builder: (context, snapshot) { - const defaultAccent = Themes.defaultAccent; - Color lightAccent = defaultAccent, darkAccent = defaultAccent; - if (enableDynamicColor) { - // `DynamicColorBuilder` from package `dynamic_color` provides light/dark - // palettes with a primary color from tones too dark/light (40/80), - // so we derive the color with adjusted tones (60/70) - final tonalPalette = snapshot.data?.primary; - lightAccent = Color(tonalPalette?.get(60) ?? defaultAccent.value); - darkAccent = Color(tonalPalette?.get(70) ?? defaultAccent.value); - } - final lightTheme = Themes.lightTheme(lightAccent, initialized); - final darkTheme = themeBrightness == AvesThemeBrightness.black ? Themes.blackTheme(darkAccent, initialized) : Themes.darkTheme(darkAccent, initialized); - return Shortcuts( - shortcuts: { - // handle Android TV remote `select` button - LogicalKeySet(LogicalKeyboardKey.select): const ActivateIntent(), - }, - child: MaterialApp( - navigatorKey: AvesApp.navigatorKey, - home: home, - navigatorObservers: _navigatorObservers, - builder: (context, child) => _decorateAppChild( - context: context, - initialized: initialized, - child: child, - ), - onGenerateTitle: (context) => context.l10n.appName, - theme: lightTheme, - darkTheme: darkTheme, - themeMode: themeBrightness.appThemeMode, - locale: settingsLocale, - localizationsDelegates: AppLocalizations.localizationsDelegates, - supportedLocales: AvesApp.supportedLocales, - // TODO TLAD remove custom scroll behavior when this is fixed: https://github.com/flutter/flutter/issues/82906 - scrollBehavior: StretchMaterialScrollBehavior(), - ), - ); - }, - ); - }, - ); - }, - ), - ), - ), + return MultiProvider( + providers: [ + Provider.value(value: widget.flavor), + ChangeNotifierProvider.value(value: settings), + ListenableProvider>.value(value: _appModeNotifier), + Provider.value(value: _mediaStoreSource), + Provider.value(value: _tvRailController), + DurationsProvider(), + HighlightInfoProvider(), + ], + child: OverlaySupport( + child: FutureBuilder( + future: _appSetup, + builder: (context, snapshot) { + final initialized = !snapshot.hasError && snapshot.connectionState == ConnectionState.done; + if (initialized) { + AvesApp.showSystemUI(); + } + final home = initialized + ? _getFirstPage() + : AvesScaffold( + body: snapshot.hasError ? _buildError(snapshot.error!) : const SizedBox(), + ); + return Selector>( + selector: (context, s) => Tuple3( + s.locale, + s.initialized ? s.themeBrightness : SettingsDefaults.themeBrightness, + s.initialized ? s.enableDynamicColor : SettingsDefaults.enableDynamicColor, ), - ), - ), + builder: (context, s, child) { + final settingsLocale = s.item1; + final themeBrightness = s.item2; + final enableDynamicColor = s.item3; + + Constants.updateStylesForLocale(settings.appliedLocale); + + return FutureBuilder( + future: _dynamicColorPaletteLoader, + builder: (context, snapshot) { + const defaultAccent = Themes.defaultAccent; + Color lightAccent = defaultAccent, darkAccent = defaultAccent; + if (enableDynamicColor) { + // `DynamicColorBuilder` from package `dynamic_color` provides light/dark + // palettes with a primary color from tones too dark/light (40/80), + // so we derive the color with adjusted tones (60/70) + final tonalPalette = snapshot.data?.primary; + lightAccent = Color(tonalPalette?.get(60) ?? defaultAccent.value); + darkAccent = Color(tonalPalette?.get(70) ?? defaultAccent.value); + } + final lightTheme = Themes.lightTheme(lightAccent, initialized); + final darkTheme = themeBrightness == AvesThemeBrightness.black ? Themes.blackTheme(darkAccent, initialized) : Themes.darkTheme(darkAccent, initialized); + return Shortcuts( + shortcuts: { + // handle Android TV remote `select` button + LogicalKeySet(LogicalKeyboardKey.select): const ActivateIntent(), + }, + child: MaterialApp( + navigatorKey: AvesApp.navigatorKey, + home: home, + navigatorObservers: _navigatorObservers, + builder: (context, child) => _decorateAppChild( + context: context, + initialized: initialized, + child: child, + ), + onGenerateTitle: (context) => context.l10n.appName, + theme: lightTheme, + darkTheme: darkTheme, + themeMode: themeBrightness.appThemeMode, + locale: settingsLocale, + localizationsDelegates: AppLocalizations.localizationsDelegates, + supportedLocales: AvesApp.supportedLocales, + // TODO TLAD remove custom scroll behavior when this is fixed: https://github.com/flutter/flutter/issues/82906 + scrollBehavior: StretchMaterialScrollBehavior(), + ), + ); + }, + ); + }, + ); + }, ), ), ); diff --git a/lib/widgets/collection/collection_grid.dart b/lib/widgets/collection/collection_grid.dart index bf0c69973..85435a667 100644 --- a/lib/widgets/collection/collection_grid.dart +++ b/lib/widgets/collection/collection_grid.dart @@ -19,7 +19,7 @@ import 'package:aves/widgets/collection/draggable_thumb_label.dart'; import 'package:aves/widgets/collection/grid/list_details_theme.dart'; import 'package:aves/widgets/collection/grid/section_layout.dart'; import 'package:aves/widgets/collection/grid/tile.dart'; -import 'package:aves/widgets/common/basic/draggable_scrollbar.dart'; +import 'package:aves/widgets/common/basic/draggable_scrollbar/scrollbar.dart'; import 'package:aves/widgets/common/basic/insets.dart'; import 'package:aves/widgets/common/behaviour/sloppy_scroll_physics.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; diff --git a/lib/widgets/collection/collection_page.dart b/lib/widgets/collection/collection_page.dart index 37d8cdb59..1b88caeba 100644 --- a/lib/widgets/collection/collection_page.dart +++ b/lib/widgets/collection/collection_page.dart @@ -14,7 +14,7 @@ import 'package:aves/model/source/collection_source.dart'; import 'package:aves/services/intent_service.dart'; import 'package:aves/theme/durations.dart'; import 'package:aves/widgets/collection/collection_grid.dart'; -import 'package:aves/widgets/common/basic/draggable_scrollbar.dart'; +import 'package:aves/widgets/common/basic/draggable_scrollbar/notifications.dart'; import 'package:aves/widgets/common/basic/insets.dart'; import 'package:aves/widgets/common/basic/scaffold.dart'; import 'package:aves/widgets/common/behaviour/pop/double_back.dart'; @@ -52,7 +52,7 @@ class CollectionPage extends StatefulWidget { class _CollectionPageState extends State { final List _subscriptions = []; late CollectionLens _collection; - final StreamController _draggableScrollBarEventStreamController = StreamController.broadcast(); + final StreamController _draggableScrollBarEventStreamController = StreamController.broadcast(); final DoubleBackPopHandler _doubleBackPopHandler = DoubleBackPopHandler(); @override @@ -146,7 +146,7 @@ class _CollectionPageState extends State { final canNavigate = context.select, bool>((v) => v.value.canNavigate); final showBottomNavigationBar = canNavigate && enableBottomNavigationBar; - return NotificationListener( + return NotificationListener( onNotification: (notification) { _draggableScrollBarEventStreamController.add(notification.event); return false; diff --git a/lib/widgets/common/basic/draggable_scrollbar/arrow_clipper.dart b/lib/widgets/common/basic/draggable_scrollbar/arrow_clipper.dart new file mode 100644 index 000000000..e665bcc68 --- /dev/null +++ b/lib/widgets/common/basic/draggable_scrollbar/arrow_clipper.dart @@ -0,0 +1,38 @@ +import 'package:flutter/rendering.dart'; + +class ArrowClipper extends CustomClipper { + @override + Path getClip(Size size) { + final path = Path(); + path.lineTo(0.0, size.height); + path.lineTo(size.width, size.height); + path.lineTo(size.width, 0.0); + path.lineTo(0.0, 0.0); + path.close(); + + const arrowWidth = 8.0; + final startPointX = (size.width - arrowWidth) / 2; + var startPointY = size.height / 2 - arrowWidth / 2; + path.moveTo(startPointX, startPointY); + path.lineTo(startPointX + arrowWidth / 2, startPointY - arrowWidth / 2); + path.lineTo(startPointX + arrowWidth, startPointY); + path.lineTo(startPointX + arrowWidth, startPointY + 1.0); + path.lineTo(startPointX + arrowWidth / 2, startPointY - arrowWidth / 2 + 1.0); + path.lineTo(startPointX, startPointY + 1.0); + path.close(); + + startPointY = size.height / 2 + arrowWidth / 2; + path.moveTo(startPointX + arrowWidth, startPointY); + path.lineTo(startPointX + arrowWidth / 2, startPointY + arrowWidth / 2); + path.lineTo(startPointX, startPointY); + path.lineTo(startPointX, startPointY - 1.0); + path.lineTo(startPointX + arrowWidth / 2, startPointY + arrowWidth / 2 - 1.0); + path.lineTo(startPointX + arrowWidth, startPointY - 1.0); + path.close(); + + return path; + } + + @override + bool shouldReclip(covariant CustomClipper oldClipper) => false; +} diff --git a/lib/widgets/common/basic/draggable_scrollbar/notifications.dart b/lib/widgets/common/basic/draggable_scrollbar/notifications.dart new file mode 100644 index 000000000..28ca11d23 --- /dev/null +++ b/lib/widgets/common/basic/draggable_scrollbar/notifications.dart @@ -0,0 +1,10 @@ +import 'package:flutter/widgets.dart'; + +@immutable +class DraggableScrollbarNotification extends Notification { + final DraggableScrollbarEvent event; + + const DraggableScrollbarNotification(this.event); +} + +enum DraggableScrollbarEvent { dragStart, dragEnd } diff --git a/lib/widgets/common/basic/draggable_scrollbar/scroll_label.dart b/lib/widgets/common/basic/draggable_scrollbar/scroll_label.dart new file mode 100644 index 000000000..e42c171be --- /dev/null +++ b/lib/widgets/common/basic/draggable_scrollbar/scroll_label.dart @@ -0,0 +1,30 @@ +import 'package:flutter/material.dart'; + +class ScrollLabel extends StatelessWidget { + final Animation animation; + final Color backgroundColor; + final Widget child; + + const ScrollLabel({ + super.key, + required this.child, + required this.animation, + required this.backgroundColor, + }); + + @override + Widget build(BuildContext context) { + return FadeTransition( + opacity: animation, + child: Container( + margin: const EdgeInsetsDirectional.only(end: 12.0), + child: Material( + elevation: 4.0, + color: backgroundColor, + borderRadius: const BorderRadius.all(Radius.circular(16)), + child: child, + ), + ), + ); + } +} diff --git a/lib/widgets/common/basic/draggable_scrollbar.dart b/lib/widgets/common/basic/draggable_scrollbar/scrollbar.dart similarity index 78% rename from lib/widgets/common/basic/draggable_scrollbar.dart rename to lib/widgets/common/basic/draggable_scrollbar/scrollbar.dart index 4e31017b7..564ed445b 100644 --- a/lib/widgets/common/basic/draggable_scrollbar.dart +++ b/lib/widgets/common/basic/draggable_scrollbar/scrollbar.dart @@ -1,7 +1,9 @@ import 'dart:async'; -import 'package:aves/widgets/common/extensions/build_context.dart'; -import 'package:flutter/material.dart'; +import 'package:aves/widgets/common/basic/draggable_scrollbar/notifications.dart'; +import 'package:aves/widgets/common/basic/draggable_scrollbar/scroll_label.dart'; +import 'package:aves/widgets/common/basic/draggable_scrollbar/transition.dart'; +import 'package:flutter/widgets.dart'; /* adapted from package `draggable_scrollbar` v0.0.4: @@ -109,35 +111,6 @@ class DraggableScrollbar extends StatefulWidget { } } -class ScrollLabel extends StatelessWidget { - final Animation animation; - final Color backgroundColor; - final Widget child; - - const ScrollLabel({ - super.key, - required this.child, - required this.animation, - required this.backgroundColor, - }); - - @override - Widget build(BuildContext context) { - return FadeTransition( - opacity: animation, - child: Container( - margin: const EdgeInsetsDirectional.only(end: 12.0), - child: Material( - elevation: 4.0, - color: backgroundColor, - borderRadius: const BorderRadius.all(Radius.circular(16)), - child: child, - ), - ), - ); - } -} - class _DraggableScrollbarState extends State with TickerProviderStateMixin { final ValueNotifier _thumbOffsetNotifier = ValueNotifier(0), _viewOffsetNotifier = ValueNotifier(0); bool _isDragInProcess = false; @@ -304,7 +277,7 @@ class _DraggableScrollbarState extends State with TickerProv } void _onVerticalDragStart() { - const DraggableScrollBarNotification(DraggableScrollBarEvent.dragStart).dispatch(context); + const DraggableScrollbarNotification(DraggableScrollbarEvent.dragStart).dispatch(context); _labelAnimationController.forward(); _fadeoutTimer?.cancel(); _showThumb(); @@ -326,7 +299,7 @@ class _DraggableScrollbarState extends State with TickerProv } void _onVerticalDragEnd() { - const DraggableScrollBarNotification(DraggableScrollBarEvent.dragEnd).dispatch(context); + const DraggableScrollbarNotification(DraggableScrollbarEvent.dragEnd).dispatch(context); _scheduleFadeout(); setState(() => _isDragInProcess = false); } @@ -373,79 +346,3 @@ class _DraggableScrollbarState extends State with TickerProv } } } - -///This cut 2 lines in arrow shape -class ArrowClipper extends CustomClipper { - @override - Path getClip(Size size) { - final path = Path(); - path.lineTo(0.0, size.height); - path.lineTo(size.width, size.height); - path.lineTo(size.width, 0.0); - path.lineTo(0.0, 0.0); - path.close(); - - const arrowWidth = 8.0; - final startPointX = (size.width - arrowWidth) / 2; - var startPointY = size.height / 2 - arrowWidth / 2; - path.moveTo(startPointX, startPointY); - path.lineTo(startPointX + arrowWidth / 2, startPointY - arrowWidth / 2); - path.lineTo(startPointX + arrowWidth, startPointY); - path.lineTo(startPointX + arrowWidth, startPointY + 1.0); - path.lineTo(startPointX + arrowWidth / 2, startPointY - arrowWidth / 2 + 1.0); - path.lineTo(startPointX, startPointY + 1.0); - path.close(); - - startPointY = size.height / 2 + arrowWidth / 2; - path.moveTo(startPointX + arrowWidth, startPointY); - path.lineTo(startPointX + arrowWidth / 2, startPointY + arrowWidth / 2); - path.lineTo(startPointX, startPointY); - path.lineTo(startPointX, startPointY - 1.0); - path.lineTo(startPointX + arrowWidth / 2, startPointY + arrowWidth / 2 - 1.0); - path.lineTo(startPointX + arrowWidth, startPointY - 1.0); - path.close(); - - return path; - } - - @override - bool shouldReclip(covariant CustomClipper oldClipper) => false; -} - -class SlideFadeTransition extends StatelessWidget { - final Animation animation; - final Widget child; - - const SlideFadeTransition({ - super.key, - required this.animation, - required this.child, - }); - - @override - Widget build(BuildContext context) { - return AnimatedBuilder( - animation: animation, - builder: (context, child) => animation.value == 0.0 ? Container() : child!, - child: SlideTransition( - position: Tween( - begin: Offset((context.isRtl ? -1 : 1) * .3, 0), - end: Offset.zero, - ).animate(animation), - child: FadeTransition( - opacity: animation, - child: child, - ), - ), - ); - } -} - -@immutable -class DraggableScrollBarNotification extends Notification { - final DraggableScrollBarEvent event; - - const DraggableScrollBarNotification(this.event); -} - -enum DraggableScrollBarEvent { dragStart, dragEnd } diff --git a/lib/widgets/common/basic/draggable_scrollbar/transition.dart b/lib/widgets/common/basic/draggable_scrollbar/transition.dart new file mode 100644 index 000000000..2eeb3a371 --- /dev/null +++ b/lib/widgets/common/basic/draggable_scrollbar/transition.dart @@ -0,0 +1,31 @@ +import 'package:aves/widgets/common/extensions/build_context.dart'; +import 'package:flutter/widgets.dart'; + +class SlideFadeTransition extends StatelessWidget { + final Animation animation; + final Widget child; + + const SlideFadeTransition({ + super.key, + required this.animation, + required this.child, + }); + + @override + Widget build(BuildContext context) { + return AnimatedBuilder( + animation: animation, + builder: (context, child) => animation.value == 0.0 ? Container() : child!, + child: SlideTransition( + position: Tween( + begin: Offset((context.isRtl ? -1 : 1) * .3, 0), + end: Offset.zero, + ).animate(animation), + child: FadeTransition( + opacity: animation, + child: child, + ), + ), + ); + } +} diff --git a/lib/widgets/common/identity/scroll_thumb.dart b/lib/widgets/common/identity/scroll_thumb.dart index 4fdf08c40..718abf288 100644 --- a/lib/widgets/common/identity/scroll_thumb.dart +++ b/lib/widgets/common/identity/scroll_thumb.dart @@ -1,4 +1,5 @@ -import 'package:aves/widgets/common/basic/draggable_scrollbar.dart'; +import 'package:aves/widgets/common/basic/draggable_scrollbar/arrow_clipper.dart'; +import 'package:aves/widgets/common/basic/draggable_scrollbar/scrollbar.dart'; import 'package:flutter/material.dart'; const double avesScrollThumbHeight = 48; diff --git a/lib/widgets/common/providers/durations_provider.dart b/lib/widgets/common/providers/durations_provider.dart new file mode 100644 index 000000000..4e1382e8f --- /dev/null +++ b/lib/widgets/common/providers/durations_provider.dart @@ -0,0 +1,16 @@ +import 'package:aves/model/settings/enums/accessibility_animations.dart'; +import 'package:aves/model/settings/settings.dart'; +import 'package:aves/theme/durations.dart'; +import 'package:provider/provider.dart'; + +class DurationsProvider extends ProxyProvider { + DurationsProvider({ + super.key, + super.child, + }) : super( + update: (context, settings, __) { + final enabled = settings.accessibilityAnimations.animate; + return enabled ? DurationsData() : DurationsData.noAnimation(); + }, + ); +} diff --git a/lib/widgets/common/providers/highlight_info_provider.dart b/lib/widgets/common/providers/highlight_info_provider.dart index cdcb7a980..9deccf7bb 100644 --- a/lib/widgets/common/providers/highlight_info_provider.dart +++ b/lib/widgets/common/providers/highlight_info_provider.dart @@ -1,20 +1,11 @@ import 'package:aves/model/highlight.dart'; -import 'package:flutter/widgets.dart'; import 'package:provider/provider.dart'; -class HighlightInfoProvider extends StatelessWidget { - final Widget child; - - const HighlightInfoProvider({ +class HighlightInfoProvider extends ChangeNotifierProvider { + HighlightInfoProvider({ super.key, - required this.child, - }); - - @override - Widget build(BuildContext context) { - return ChangeNotifierProvider( - create: (context) => HighlightInfo(), - child: child, - ); - } + super.child, + }) : super( + create: (context) => HighlightInfo(), + ); } diff --git a/lib/widgets/filter_grids/common/filter_grid_page.dart b/lib/widgets/filter_grids/common/filter_grid_page.dart index 9e6ca391a..38d773180 100644 --- a/lib/widgets/filter_grids/common/filter_grid_page.dart +++ b/lib/widgets/filter_grids/common/filter_grid_page.dart @@ -12,7 +12,8 @@ import 'package:aves/model/source/enums/enums.dart'; import 'package:aves/model/vaults/vaults.dart'; import 'package:aves/theme/colors.dart'; import 'package:aves/theme/durations.dart'; -import 'package:aves/widgets/common/basic/draggable_scrollbar.dart'; +import 'package:aves/widgets/common/basic/draggable_scrollbar/scrollbar.dart'; +import 'package:aves/widgets/common/basic/draggable_scrollbar/notifications.dart'; import 'package:aves/widgets/common/basic/insets.dart'; import 'package:aves/widgets/common/basic/scaffold.dart'; import 'package:aves/widgets/common/behaviour/pop/double_back.dart'; @@ -61,7 +62,7 @@ class FilterGridPage extends StatelessWidget { final QueryTest applyQuery; final Widget Function() emptyBuilder; final HeroType heroType; - final StreamController _draggableScrollBarEventStreamController = StreamController.broadcast(); + final StreamController _draggableScrollBarEventStreamController = StreamController.broadcast(); FilterGridPage({ super.key, @@ -145,7 +146,7 @@ class FilterGridPage extends StatelessWidget { final canNavigate = context.select, bool>((v) => v.value.canNavigate); final showBottomNavigationBar = canNavigate && enableBottomNavigationBar; - return NotificationListener( + return NotificationListener( onNotification: (notification) { _draggableScrollBarEventStreamController.add(notification.event); return false; diff --git a/lib/widgets/navigation/nav_bar/floating.dart b/lib/widgets/navigation/nav_bar/floating.dart index 9c2ae9946..6ebb4bfdd 100644 --- a/lib/widgets/navigation/nav_bar/floating.dart +++ b/lib/widgets/navigation/nav_bar/floating.dart @@ -1,12 +1,12 @@ import 'dart:async'; import 'dart:math'; -import 'package:aves/widgets/common/basic/draggable_scrollbar.dart'; +import 'package:aves/widgets/common/basic/draggable_scrollbar/notifications.dart'; import 'package:flutter/material.dart'; class FloatingNavBar extends StatefulWidget { final ScrollController? scrollController; - final Stream events; + final Stream events; final double childHeight; final Widget child; @@ -109,12 +109,12 @@ class _FloatingNavBarState extends State with SingleTickerProvid } } - void _onDraggableScrollBarEvent(DraggableScrollBarEvent event) { + void _onDraggableScrollBarEvent(DraggableScrollbarEvent event) { switch (event) { - case DraggableScrollBarEvent.dragStart: + case DraggableScrollbarEvent.dragStart: _isDragging = true; break; - case DraggableScrollBarEvent.dragEnd: + case DraggableScrollbarEvent.dragEnd: _isDragging = false; break; } diff --git a/lib/widgets/navigation/nav_bar/nav_bar.dart b/lib/widgets/navigation/nav_bar/nav_bar.dart index 899fc89d5..bd772bd6e 100644 --- a/lib/widgets/navigation/nav_bar/nav_bar.dart +++ b/lib/widgets/navigation/nav_bar/nav_bar.dart @@ -5,7 +5,7 @@ import 'package:aves/model/settings/settings.dart'; import 'package:aves/model/source/collection_lens.dart'; import 'package:aves/model/source/collection_source.dart'; import 'package:aves/widgets/collection/collection_page.dart'; -import 'package:aves/widgets/common/basic/draggable_scrollbar.dart'; +import 'package:aves/widgets/common/basic/draggable_scrollbar/notifications.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/common/extensions/media_query.dart'; import 'package:aves/widgets/common/identity/aves_app_bar.dart'; @@ -17,7 +17,7 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; class AppBottomNavBar extends StatefulWidget { - final Stream events; + final Stream events; // collection loaded in the `CollectionPage`, if any final CollectionLens? currentCollection; From 64e153ef5c761da032c074bbec25df017667af90 Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Wed, 1 Mar 2023 22:04:22 +0100 Subject: [PATCH 02/31] accessibility: fixed navigation with TalkBack --- CHANGELOG.md | 4 + lib/widgets/collection/app_bar.dart | 53 +++++------ .../quick_choosers/common/button.dart | 20 ++-- .../quick_choosers/share_chooser.dart | 2 +- .../action_controls/togglers/favourite.dart | 2 +- .../common/action_controls/togglers/mute.dart | 2 +- .../common/action_controls/togglers/play.dart | 2 +- .../togglers/title_search.dart | 2 +- .../basic/draggable_scrollbar/scrollbar.dart | 65 +++++++------ lib/widgets/common/basic/popup/container.dart | 35 +++++++ .../{menu.dart => popup/expansion_panel.dart} | 95 ++++++------------- .../menu_button.dart} | 0 lib/widgets/common/basic/popup/menu_row.dart | 55 +++++++++++ .../common/identity/aves_filter_chip.dart | 2 +- lib/widgets/debug/app_debug_page.dart | 2 +- .../entry_editors/rename_entry_set_page.dart | 2 +- .../dialogs/pick_dialogs/album_pick_page.dart | 2 +- lib/widgets/filter_grids/common/app_bar.dart | 2 +- lib/widgets/map/map_page.dart | 2 +- .../privacy/file_picker/file_picker_page.dart | 2 +- lib/widgets/settings/settings_page.dart | 2 +- lib/widgets/viewer/info/info_app_bar.dart | 2 +- .../viewer/overlay/viewer_buttons.dart | 84 +++++++--------- 23 files changed, 241 insertions(+), 198 deletions(-) create mode 100644 lib/widgets/common/basic/popup/container.dart rename lib/widgets/common/basic/{menu.dart => popup/expansion_panel.dart} (55%) rename lib/widgets/common/basic/{popup_menu_button.dart => popup/menu_button.dart} (100%) create mode 100644 lib/widgets/common/basic/popup/menu_row.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index c1f2f4ffd..4b2858f33 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +### Fixed + +- Accessibility: navigation with TalkBack + ## [v1.8.2] - 2023-02-28 ### Added diff --git a/lib/widgets/collection/app_bar.dart b/lib/widgets/collection/app_bar.dart index 684a5629b..d9206938a 100644 --- a/lib/widgets/collection/app_bar.dart +++ b/lib/widgets/collection/app_bar.dart @@ -23,7 +23,9 @@ import 'package:aves/widgets/common/action_controls/togglers/favourite.dart'; import 'package:aves/widgets/common/action_controls/togglers/title_search.dart'; import 'package:aves/widgets/common/app_bar/app_bar_subtitle.dart'; import 'package:aves/widgets/common/app_bar/app_bar_title.dart'; -import 'package:aves/widgets/common/basic/menu.dart'; +import 'package:aves/widgets/common/basic/popup/container.dart'; +import 'package:aves/widgets/common/basic/popup/expansion_panel.dart'; +import 'package:aves/widgets/common/basic/popup/menu_row.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/common/identity/aves_app_bar.dart'; import 'package:aves/widgets/common/identity/buttons/captioned_button.dart'; @@ -405,19 +407,15 @@ class _CollectionAppBarState extends State with SingleTickerPr }, ), if (isSelecting && !settings.isReadOnly && appMode == AppMode.main && !isTrash) - PopupMenuItem( + PopupMenuExpansionPanel( enabled: hasSelection, - padding: EdgeInsets.zero, - child: PopupMenuItemExpansionPanel( - enabled: hasSelection, - value: 'edit', - icon: AIcons.edit, - title: context.l10n.collectionActionEdit, - items: [ - _buildRotateAndFlipMenuItems(context, canApply: canApply), - ...EntrySetActions.edit.where((v) => isVisible(v) && !selectionQuickActions.contains(v)).map((action) => _toMenuItem(action, enabled: canApply(action), selection: selection)), - ], - ), + value: 'edit', + icon: AIcons.edit, + title: context.l10n.collectionActionEdit, + items: [ + _buildRotateAndFlipMenuItems(context, canApply: canApply), + ...EntrySetActions.edit.where((v) => isVisible(v) && !selectionQuickActions.contains(v)).map((action) => _toMenuItem(action, enabled: canApply(action), selection: selection)), + ], ), ]; @@ -529,7 +527,7 @@ class _CollectionAppBarState extends State with SingleTickerPr ); } - PopupMenuItem _buildRotateAndFlipMenuItems( + PopupMenuEntry _buildRotateAndFlipMenuItems( BuildContext context, { required bool Function(EntrySetAction action) canApply, }) { @@ -558,22 +556,17 @@ class _CollectionAppBarState extends State with SingleTickerPr ), ); - return PopupMenuItem( - child: TooltipTheme( - data: TooltipTheme.of(context).copyWith( - preferBelow: false, - ), - child: Row( - children: [ - buildDivider(), - buildItem(EntrySetAction.rotateCCW), - buildDivider(), - buildItem(EntrySetAction.rotateCW), - buildDivider(), - buildItem(EntrySetAction.flip), - buildDivider(), - ], - ), + return PopupMenuItemContainer( + child: Row( + children: [ + buildDivider(), + buildItem(EntrySetAction.rotateCCW), + buildDivider(), + buildItem(EntrySetAction.rotateCW), + buildDivider(), + buildItem(EntrySetAction.flip), + buildDivider(), + ], ), ); } diff --git a/lib/widgets/common/action_controls/quick_choosers/common/button.dart b/lib/widgets/common/action_controls/quick_choosers/common/button.dart index 4dcd42334..eddc578a2 100644 --- a/lib/widgets/common/action_controls/quick_choosers/common/button.dart +++ b/lib/widgets/common/action_controls/quick_choosers/common/button.dart @@ -56,6 +56,19 @@ abstract class ChooserQuickButtonState, U> exten Widget build(BuildContext context) { final _hasChooser = hasChooser; + Widget child = IconButton( + icon: icon, + onPressed: widget.onPressed, + focusNode: widget.focusNode, + tooltip: _hasChooser ? null : tooltip, + ); + if (_hasChooser) { + child = Semantics( + tooltip: tooltip, + child: child, + ); + } + return GestureDetector( behavior: HitTestBehavior.opaque, onLongPressStart: _hasChooser ? _showChooser : null, @@ -70,12 +83,7 @@ abstract class ChooserQuickButtonState, U> exten } : null, onLongPressCancel: _clearChooserOverlayEntry, - child: IconButton( - icon: icon, - onPressed: widget.onPressed, - focusNode: widget.focusNode, - tooltip: _hasChooser ? null : tooltip, - ), + child: child, ); } diff --git a/lib/widgets/common/action_controls/quick_choosers/share_chooser.dart b/lib/widgets/common/action_controls/quick_choosers/share_chooser.dart index 3600877e6..d9d8e6176 100644 --- a/lib/widgets/common/action_controls/quick_choosers/share_chooser.dart +++ b/lib/widgets/common/action_controls/quick_choosers/share_chooser.dart @@ -2,7 +2,7 @@ import 'dart:async'; import 'package:aves/model/actions/share_actions.dart'; import 'package:aves/widgets/common/action_controls/quick_choosers/common/menu.dart'; -import 'package:aves/widgets/common/basic/menu.dart'; +import 'package:aves/widgets/common/basic/popup/menu_row.dart'; import 'package:flutter/material.dart'; class ShareQuickChooser extends StatelessWidget { diff --git a/lib/widgets/common/action_controls/togglers/favourite.dart b/lib/widgets/common/action_controls/togglers/favourite.dart index c19c646d1..510853037 100644 --- a/lib/widgets/common/action_controls/togglers/favourite.dart +++ b/lib/widgets/common/action_controls/togglers/favourite.dart @@ -2,7 +2,7 @@ import 'package:aves/model/entry.dart'; import 'package:aves/model/favourites.dart'; import 'package:aves/theme/colors.dart'; import 'package:aves/theme/icons.dart'; -import 'package:aves/widgets/common/basic/menu.dart'; +import 'package:aves/widgets/common/basic/popup/menu_row.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/common/fx/sweeper.dart'; import 'package:aves/widgets/common/identity/buttons/captioned_button.dart'; diff --git a/lib/widgets/common/action_controls/togglers/mute.dart b/lib/widgets/common/action_controls/togglers/mute.dart index e42bcab80..7eec6faac 100644 --- a/lib/widgets/common/action_controls/togglers/mute.dart +++ b/lib/widgets/common/action_controls/togglers/mute.dart @@ -1,7 +1,7 @@ import 'dart:async'; import 'package:aves/theme/icons.dart'; -import 'package:aves/widgets/common/basic/menu.dart'; +import 'package:aves/widgets/common/basic/popup/menu_row.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/common/identity/buttons/captioned_button.dart'; import 'package:aves/widgets/viewer/video/controller.dart'; diff --git a/lib/widgets/common/action_controls/togglers/play.dart b/lib/widgets/common/action_controls/togglers/play.dart index 354da0ddf..e2f5bbe6b 100644 --- a/lib/widgets/common/action_controls/togglers/play.dart +++ b/lib/widgets/common/action_controls/togglers/play.dart @@ -2,7 +2,7 @@ import 'dart:async'; import 'package:aves/theme/durations.dart'; import 'package:aves/theme/icons.dart'; -import 'package:aves/widgets/common/basic/menu.dart'; +import 'package:aves/widgets/common/basic/popup/menu_row.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/common/identity/buttons/captioned_button.dart'; import 'package:aves/widgets/viewer/video/controller.dart'; diff --git a/lib/widgets/common/action_controls/togglers/title_search.dart b/lib/widgets/common/action_controls/togglers/title_search.dart index dfe577994..b7badcd93 100644 --- a/lib/widgets/common/action_controls/togglers/title_search.dart +++ b/lib/widgets/common/action_controls/togglers/title_search.dart @@ -1,6 +1,6 @@ import 'package:aves/model/query.dart'; import 'package:aves/theme/icons.dart'; -import 'package:aves/widgets/common/basic/menu.dart'; +import 'package:aves/widgets/common/basic/popup/menu_row.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/common/identity/buttons/captioned_button.dart'; import 'package:flutter/material.dart'; diff --git a/lib/widgets/common/basic/draggable_scrollbar/scrollbar.dart b/lib/widgets/common/basic/draggable_scrollbar/scrollbar.dart index 564ed445b..0813a93a3 100644 --- a/lib/widgets/common/basic/draggable_scrollbar/scrollbar.dart +++ b/lib/widgets/common/basic/draggable_scrollbar/scrollbar.dart @@ -212,37 +212,40 @@ class _DraggableScrollbarState extends State with TickerProv ), ); }), - RepaintBoundary( - child: GestureDetector( - onLongPressStart: (details) { - _longPressLastGlobalPosition = details.globalPosition; - _onVerticalDragStart(); - }, - onLongPressMoveUpdate: (details) { - final dy = (details.globalPosition - _longPressLastGlobalPosition).dy; - _longPressLastGlobalPosition = details.globalPosition; - _onVerticalDragUpdate(dy); - }, - onLongPressEnd: (_) => _onVerticalDragEnd(), - onVerticalDragStart: (_) => _onVerticalDragStart(), - onVerticalDragUpdate: (details) => _onVerticalDragUpdate(details.delta.dy), - onVerticalDragEnd: (_) => _onVerticalDragEnd(), - child: ValueListenableBuilder( - valueListenable: _thumbOffsetNotifier, - builder: (context, thumbOffset, child) => Container( - alignment: AlignmentDirectional.topEnd, - padding: EdgeInsets.only(top: thumbOffset) + widget.padding, - child: widget.scrollThumbBuilder( - widget.backgroundColor, - _thumbAnimation, - _labelAnimation, - widget.scrollThumbSize.height, - labelText: _isDragInProcess - ? ValueListenableBuilder( - valueListenable: _viewOffsetNotifier, - builder: (context, viewOffset, child) => widget.labelTextBuilder(viewOffset + thumbOffset), - ) - : null, + // exclude semantics, otherwise this layer will block access to content layers below when using TalkBack + ExcludeSemantics( + child: RepaintBoundary( + child: GestureDetector( + onLongPressStart: (details) { + _longPressLastGlobalPosition = details.globalPosition; + _onVerticalDragStart(); + }, + onLongPressMoveUpdate: (details) { + final dy = (details.globalPosition - _longPressLastGlobalPosition).dy; + _longPressLastGlobalPosition = details.globalPosition; + _onVerticalDragUpdate(dy); + }, + onLongPressEnd: (_) => _onVerticalDragEnd(), + onVerticalDragStart: (_) => _onVerticalDragStart(), + onVerticalDragUpdate: (details) => _onVerticalDragUpdate(details.delta.dy), + onVerticalDragEnd: (_) => _onVerticalDragEnd(), + child: ValueListenableBuilder( + valueListenable: _thumbOffsetNotifier, + builder: (context, thumbOffset, child) => Container( + alignment: AlignmentDirectional.topEnd, + padding: EdgeInsets.only(top: thumbOffset) + widget.padding, + child: widget.scrollThumbBuilder( + widget.backgroundColor, + _thumbAnimation, + _labelAnimation, + widget.scrollThumbSize.height, + labelText: _isDragInProcess + ? ValueListenableBuilder( + valueListenable: _viewOffsetNotifier, + builder: (context, viewOffset, child) => widget.labelTextBuilder(viewOffset + thumbOffset), + ) + : null, + ), ), ), ), diff --git a/lib/widgets/common/basic/popup/container.dart b/lib/widgets/common/basic/popup/container.dart new file mode 100644 index 000000000..eaa767536 --- /dev/null +++ b/lib/widgets/common/basic/popup/container.dart @@ -0,0 +1,35 @@ +import 'package:flutter/material.dart'; + +class PopupMenuItemContainer extends PopupMenuEntry { + final Widget child; + + const PopupMenuItemContainer({ + super.key, + this.height = kMinInteractiveDimension, + required this.child, + }); + + @override + final double height; + + @override + bool represents(void value) => false; + + @override + State createState() => _TransitionPopupMenuItemState(); +} + +class _TransitionPopupMenuItemState extends State { + @override + Widget build(BuildContext context) { + return TooltipTheme( + data: TooltipTheme.of(context).copyWith( + preferBelow: false, + ), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: widget.child, + ), + ); + } +} diff --git a/lib/widgets/common/basic/menu.dart b/lib/widgets/common/basic/popup/expansion_panel.dart similarity index 55% rename from lib/widgets/common/basic/menu.dart rename to lib/widgets/common/basic/popup/expansion_panel.dart index d25e30b83..50b887c3f 100644 --- a/lib/widgets/common/basic/menu.dart +++ b/lib/widgets/common/basic/popup/expansion_panel.dart @@ -1,62 +1,9 @@ import 'package:aves/theme/durations.dart'; +import 'package:aves/widgets/common/basic/popup/menu_row.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -class MenuRow extends StatelessWidget { - final String text; - final Widget? icon; - - const MenuRow({ - super.key, - required this.text, - this.icon, - }); - - @override - Widget build(BuildContext context) { - return Row( - mainAxisSize: MainAxisSize.min, - children: [ - if (icon != null) - Padding( - padding: const EdgeInsetsDirectional.only(end: 12), - child: IconTheme.merge( - data: IconThemeData( - color: ListTileTheme.of(context).iconColor, - ), - child: icon!, - ), - ), - Flexible( - child: Text(text), - ), - ], - ); - } -} - -// scale icons according to text scale -class MenuIconTheme extends StatelessWidget { - final Widget child; - - const MenuIconTheme({ - super.key, - required this.child, - }); - - @override - Widget build(BuildContext context) { - final iconTheme = IconTheme.of(context); - return IconTheme( - data: iconTheme.copyWith( - size: iconTheme.size! * MediaQuery.textScaleFactorOf(context), - ), - child: child, - ); - } -} - -class PopupMenuItemExpansionPanel extends StatefulWidget { +class PopupMenuExpansionPanel extends PopupMenuEntry { final bool enabled; final String value; final ValueNotifier expandedNotifier; @@ -64,9 +11,10 @@ class PopupMenuItemExpansionPanel extends StatefulWidget { final String title; final List> items; - PopupMenuItemExpansionPanel({ + PopupMenuExpansionPanel({ super.key, this.enabled = true, + this.height = kMinInteractiveDimension, required this.value, ValueNotifier? expandedNotifier, required this.icon, @@ -75,10 +23,16 @@ class PopupMenuItemExpansionPanel extends StatefulWidget { }) : expandedNotifier = expandedNotifier ?? ValueNotifier(null); @override - State> createState() => _PopupMenuItemExpansionPanelState(); + final double height; + + @override + bool represents(void value) => false; + + @override + State> createState() => _PopupMenuExpansionPanelState(); } -class _PopupMenuItemExpansionPanelState extends State> { +class _PopupMenuExpansionPanelState extends State> { // ref `_kMenuHorizontalPadding` used in `PopupMenuItem` static const double _horizontalPadding = 16; @@ -103,16 +57,23 @@ class _PopupMenuItemExpansionPanelState extends State DefaultTextStyle( - style: style, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: _horizontalPadding), - child: MenuRow( - text: widget.title, - icon: Icon(widget.icon), + headerBuilder: (context, isExpanded) { + return DefaultTextStyle( + style: style, + child: IconTheme.merge( + data: IconThemeData( + color: widget.enabled ? null : Theme.of(context).disabledColor, + ), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: _horizontalPadding), + child: MenuRow( + text: widget.title, + icon: Icon(widget.icon), + ), + ), ), - ), - ), + ); + }, body: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ diff --git a/lib/widgets/common/basic/popup_menu_button.dart b/lib/widgets/common/basic/popup/menu_button.dart similarity index 100% rename from lib/widgets/common/basic/popup_menu_button.dart rename to lib/widgets/common/basic/popup/menu_button.dart diff --git a/lib/widgets/common/basic/popup/menu_row.dart b/lib/widgets/common/basic/popup/menu_row.dart new file mode 100644 index 000000000..28442c841 --- /dev/null +++ b/lib/widgets/common/basic/popup/menu_row.dart @@ -0,0 +1,55 @@ +import 'package:flutter/material.dart'; + +class MenuRow extends StatelessWidget { + final String text; + final Widget? icon; + + const MenuRow({ + super.key, + required this.text, + this.icon, + }); + + @override + Widget build(BuildContext context) { + return Row( + mainAxisSize: MainAxisSize.min, + children: [ + if (icon != null) + Padding( + padding: const EdgeInsetsDirectional.only(end: 12), + child: IconTheme.merge( + data: IconThemeData( + color: ListTileTheme.of(context).iconColor, + ), + child: icon!, + ), + ), + Flexible( + child: Text(text), + ), + ], + ); + } +} + +// scale icons according to text scale +class MenuIconTheme extends StatelessWidget { + final Widget child; + + const MenuIconTheme({ + super.key, + required this.child, + }); + + @override + Widget build(BuildContext context) { + final iconTheme = IconTheme.of(context); + return IconTheme( + data: iconTheme.copyWith( + size: iconTheme.size! * MediaQuery.textScaleFactorOf(context), + ), + child: child, + ); + } +} diff --git a/lib/widgets/common/identity/aves_filter_chip.dart b/lib/widgets/common/identity/aves_filter_chip.dart index f37f7ed5a..49062e520 100644 --- a/lib/widgets/common/identity/aves_filter_chip.dart +++ b/lib/widgets/common/identity/aves_filter_chip.dart @@ -14,7 +14,7 @@ import 'package:aves/theme/colors.dart'; import 'package:aves/theme/durations.dart'; import 'package:aves/theme/icons.dart'; import 'package:aves/widgets/collection/filter_bar.dart'; -import 'package:aves/widgets/common/basic/menu.dart'; +import 'package:aves/widgets/common/basic/popup/menu_row.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/common/providers/media_query_data_provider.dart'; import 'package:aves/widgets/filter_grids/common/action_delegates/chip.dart'; diff --git a/lib/widgets/debug/app_debug_page.dart b/lib/widgets/debug/app_debug_page.dart index 63fbd4870..51d102076 100644 --- a/lib/widgets/debug/app_debug_page.dart +++ b/lib/widgets/debug/app_debug_page.dart @@ -8,7 +8,7 @@ import 'package:aves/model/source/collection_source.dart'; import 'package:aves/services/analysis_service.dart'; import 'package:aves/theme/durations.dart'; import 'package:aves/utils/android_file_utils.dart'; -import 'package:aves/widgets/common/basic/menu.dart'; +import 'package:aves/widgets/common/basic/popup/menu_row.dart'; import 'package:aves/widgets/common/basic/scaffold.dart'; import 'package:aves/widgets/common/behaviour/pop/scope.dart'; import 'package:aves/widgets/common/behaviour/pop/tv_navigation.dart'; diff --git a/lib/widgets/dialogs/entry_editors/rename_entry_set_page.dart b/lib/widgets/dialogs/entry_editors/rename_entry_set_page.dart index 331772cc2..5980f0993 100644 --- a/lib/widgets/dialogs/entry_editors/rename_entry_set_page.dart +++ b/lib/widgets/dialogs/entry_editors/rename_entry_set_page.dart @@ -7,7 +7,7 @@ import 'package:aves/theme/durations.dart'; import 'package:aves/theme/icons.dart'; import 'package:aves/utils/constants.dart'; import 'package:aves/widgets/collection/collection_grid.dart'; -import 'package:aves/widgets/common/basic/menu.dart'; +import 'package:aves/widgets/common/basic/popup/menu_row.dart'; import 'package:aves/widgets/common/basic/scaffold.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/common/grid/theme.dart'; diff --git a/lib/widgets/dialogs/pick_dialogs/album_pick_page.dart b/lib/widgets/dialogs/pick_dialogs/album_pick_page.dart index a391265e5..b36a59bcb 100644 --- a/lib/widgets/dialogs/pick_dialogs/album_pick_page.dart +++ b/lib/widgets/dialogs/pick_dialogs/album_pick_page.dart @@ -13,7 +13,7 @@ import 'package:aves/model/vaults/details.dart'; import 'package:aves/model/vaults/vaults.dart'; import 'package:aves/theme/durations.dart'; import 'package:aves/theme/icons.dart'; -import 'package:aves/widgets/common/basic/menu.dart'; +import 'package:aves/widgets/common/basic/popup/menu_row.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/common/identity/aves_filter_chip.dart'; import 'package:aves/widgets/common/identity/buttons/captioned_button.dart'; diff --git a/lib/widgets/filter_grids/common/app_bar.dart b/lib/widgets/filter_grids/common/app_bar.dart index 8312628c4..1a1d7ffe6 100644 --- a/lib/widgets/filter_grids/common/app_bar.dart +++ b/lib/widgets/filter_grids/common/app_bar.dart @@ -11,7 +11,7 @@ import 'package:aves/theme/durations.dart'; import 'package:aves/widgets/common/action_controls/togglers/title_search.dart'; import 'package:aves/widgets/common/app_bar/app_bar_subtitle.dart'; import 'package:aves/widgets/common/app_bar/app_bar_title.dart'; -import 'package:aves/widgets/common/basic/menu.dart'; +import 'package:aves/widgets/common/basic/popup/menu_row.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/common/identity/aves_app_bar.dart'; import 'package:aves/widgets/common/identity/buttons/captioned_button.dart'; diff --git a/lib/widgets/map/map_page.dart b/lib/widgets/map/map_page.dart index cb708fb97..be56ab1ed 100644 --- a/lib/widgets/map/map_page.dart +++ b/lib/widgets/map/map_page.dart @@ -18,7 +18,7 @@ import 'package:aves/utils/debouncer.dart'; import 'package:aves/widgets/collection/collection_page.dart'; import 'package:aves/widgets/collection/entry_set_action_delegate.dart'; import 'package:aves/widgets/common/basic/insets.dart'; -import 'package:aves/widgets/common/basic/menu.dart'; +import 'package:aves/widgets/common/basic/popup/menu_row.dart'; import 'package:aves/widgets/common/basic/scaffold.dart'; import 'package:aves/widgets/common/behaviour/routes.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; diff --git a/lib/widgets/settings/privacy/file_picker/file_picker_page.dart b/lib/widgets/settings/privacy/file_picker/file_picker_page.dart index c20b29b25..c41580e78 100644 --- a/lib/widgets/settings/privacy/file_picker/file_picker_page.dart +++ b/lib/widgets/settings/privacy/file_picker/file_picker_page.dart @@ -6,7 +6,7 @@ import 'package:aves/theme/durations.dart'; import 'package:aves/theme/icons.dart'; import 'package:aves/utils/android_file_utils.dart'; import 'package:aves/utils/constants.dart'; -import 'package:aves/widgets/common/basic/menu.dart'; +import 'package:aves/widgets/common/basic/popup/menu_row.dart'; import 'package:aves/widgets/common/basic/scaffold.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/common/identity/buttons/outlined_button.dart'; diff --git a/lib/widgets/settings/settings_page.dart b/lib/widgets/settings/settings_page.dart index 166ee11ed..cdb23c642 100644 --- a/lib/widgets/settings/settings_page.dart +++ b/lib/widgets/settings/settings_page.dart @@ -12,7 +12,7 @@ import 'package:aves/theme/icons.dart'; import 'package:aves/widgets/common/action_mixins/feedback.dart'; import 'package:aves/widgets/common/app_bar/app_bar_title.dart'; import 'package:aves/widgets/common/basic/insets.dart'; -import 'package:aves/widgets/common/basic/menu.dart'; +import 'package:aves/widgets/common/basic/popup/menu_row.dart'; import 'package:aves/widgets/common/basic/scaffold.dart'; import 'package:aves/widgets/common/behaviour/pop/scope.dart'; import 'package:aves/widgets/common/behaviour/pop/tv_navigation.dart'; diff --git a/lib/widgets/viewer/info/info_app_bar.dart b/lib/widgets/viewer/info/info_app_bar.dart index 03ccc2f30..1b2bb745e 100644 --- a/lib/widgets/viewer/info/info_app_bar.dart +++ b/lib/widgets/viewer/info/info_app_bar.dart @@ -6,7 +6,7 @@ import 'package:aves/theme/durations.dart'; import 'package:aves/theme/icons.dart'; import 'package:aves/widgets/common/app_bar/app_bar_title.dart'; import 'package:aves/widgets/common/app_bar/sliver_app_bar_title.dart'; -import 'package:aves/widgets/common/basic/menu.dart'; +import 'package:aves/widgets/common/basic/popup/menu_row.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/viewer/action/entry_info_action_delegate.dart'; import 'package:aves/widgets/viewer/info/info_search.dart'; diff --git a/lib/widgets/viewer/overlay/viewer_buttons.dart b/lib/widgets/viewer/overlay/viewer_buttons.dart index a02bb9899..bd1342a86 100644 --- a/lib/widgets/viewer/overlay/viewer_buttons.dart +++ b/lib/widgets/viewer/overlay/viewer_buttons.dart @@ -11,8 +11,10 @@ import 'package:aves/widgets/common/action_controls/quick_choosers/tag_button.da import 'package:aves/widgets/common/action_controls/togglers/favourite.dart'; import 'package:aves/widgets/common/action_controls/togglers/mute.dart'; import 'package:aves/widgets/common/action_controls/togglers/play.dart'; -import 'package:aves/widgets/common/basic/menu.dart'; -import 'package:aves/widgets/common/basic/popup_menu_button.dart'; +import 'package:aves/widgets/common/basic/popup/container.dart'; +import 'package:aves/widgets/common/basic/popup/expansion_panel.dart'; +import 'package:aves/widgets/common/basic/popup/menu_button.dart'; +import 'package:aves/widgets/common/basic/popup/menu_row.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/common/identity/buttons/captioned_button.dart'; import 'package:aves/widgets/common/identity/buttons/overlay_button.dart'; @@ -231,32 +233,26 @@ class ViewerButtonRowContent extends StatelessWidget { if (pageEntry.canRotate || pageEntry.canFlip) _buildRotateAndFlipMenuItems(context), ...topLevelActions.map((action) => _buildPopupMenuItem(context, action, videoController)), if (exportActions.isNotEmpty) - PopupMenuItem( - padding: EdgeInsets.zero, - child: PopupMenuItemExpansionPanel( - value: 'export', - expandedNotifier: _popupExpandedNotifier, - icon: AIcons.export, - title: context.l10n.entryActionExport, - items: [ - ...exportInternalActions.map((action) => _buildPopupMenuItem(context, action, videoController)).toList(), - if (exportInternalActions.isNotEmpty && exportExternalActions.isNotEmpty) const PopupMenuDivider(height: 0), - ...exportExternalActions.map((action) => _buildPopupMenuItem(context, action, videoController)).toList(), - ], - ), + PopupMenuExpansionPanel( + value: 'export', + expandedNotifier: _popupExpandedNotifier, + icon: AIcons.export, + title: context.l10n.entryActionExport, + items: [ + ...exportInternalActions.map((action) => _buildPopupMenuItem(context, action, videoController)).toList(), + if (exportInternalActions.isNotEmpty && exportExternalActions.isNotEmpty) const PopupMenuDivider(height: 0), + ...exportExternalActions.map((action) => _buildPopupMenuItem(context, action, videoController)).toList(), + ], ), if (videoActions.isNotEmpty) - PopupMenuItem( - padding: EdgeInsets.zero, - child: PopupMenuItemExpansionPanel( - value: 'video', - expandedNotifier: _popupExpandedNotifier, - icon: AIcons.video, - title: context.l10n.settingsVideoSectionTitle, - items: [ - ...videoActions.map((action) => _buildPopupMenuItem(context, action, videoController)).toList(), - ], - ), + PopupMenuExpansionPanel( + value: 'video', + expandedNotifier: _popupExpandedNotifier, + icon: AIcons.video, + title: context.l10n.settingsVideoSectionTitle, + items: [ + ...videoActions.map((action) => _buildPopupMenuItem(context, action, videoController)).toList(), + ], ), if (!kReleaseMode) ...[ const PopupMenuDivider(), @@ -357,7 +353,7 @@ class ViewerButtonRowContent extends StatelessWidget { ); } - PopupMenuItem _buildRotateAndFlipMenuItems(BuildContext context) { + PopupMenuEntry _buildRotateAndFlipMenuItems(BuildContext context) { Widget buildDivider() => const SizedBox( height: 16, child: VerticalDivider( @@ -383,29 +379,17 @@ class ViewerButtonRowContent extends StatelessWidget { ), ); - return PopupMenuItem( - padding: EdgeInsets.zero, - child: IconTheme.merge( - data: IconThemeData( - color: ListTileTheme.of(context).iconColor, - ), - child: ColoredBox( - color: PopupMenuTheme.of(context).color!, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Row( - children: [ - buildDivider(), - buildItem(EntryAction.rotateCCW), - buildDivider(), - buildItem(EntryAction.rotateCW), - buildDivider(), - buildItem(EntryAction.flip), - buildDivider(), - ], - ), - ), - ), + return PopupMenuItemContainer( + child: Row( + children: [ + buildDivider(), + buildItem(EntryAction.rotateCCW), + buildDivider(), + buildItem(EntryAction.rotateCW), + buildDivider(), + buildItem(EntryAction.flip), + buildDivider(), + ], ), ); } From cd343a743aea0814c36167c823abac62bc62b9f7 Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Wed, 1 Mar 2023 22:26:30 +0100 Subject: [PATCH 03/31] upgraded Flutter to stable v3.7.6 --- .flutter | 2 +- CHANGELOG.md | 4 ++++ pubspec.lock | 10 +++++----- pubspec.yaml | 2 +- shaders.sksl.json | 2 +- 5 files changed, 12 insertions(+), 8 deletions(-) diff --git a/.flutter b/.flutter index c07f78888..12cb4eb7a 160000 --- a/.flutter +++ b/.flutter @@ -1 +1 @@ -Subproject commit c07f7888888435fd9df505aa2efc38d3cf65681b +Subproject commit 12cb4eb7a009f52b347b62ade7cb4854b926af72 diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b2858f33..04954e13c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +### Changed + +- upgraded Flutter to stable v3.7.6 + ### Fixed - Accessibility: navigation with TalkBack diff --git a/pubspec.lock b/pubspec.lock index 55417180e..149ce2fd8 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -760,10 +760,10 @@ packages: dependency: transitive description: name: node_preamble - sha256: "8ebdbaa3b96d5285d068f80772390d27c21e1fa10fb2df6627b1b9415043608d" + sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "2.0.2" overlay_support: dependency: "direct main" description: @@ -1198,10 +1198,10 @@ packages: dependency: "direct main" description: name: sqflite - sha256: "78324387dc81df14f78df06019175a86a2ee0437624166c382e145d0a7fd9a4f" + sha256: "851d5040552cf911f4cabda08d003eca76b27da3ed0002978272e27c8fbf8ecc" url: "https://pub.dev" source: hosted - version: "2.2.4+1" + version: "2.2.5" sqflite_common: dependency: transitive description: @@ -1493,4 +1493,4 @@ packages: version: "3.1.1" sdks: dart: ">=2.19.0 <3.0.0" - flutter: ">=3.7.5" + flutter: ">=3.7.6" diff --git a/pubspec.yaml b/pubspec.yaml index 9386fd121..eface67c8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -13,7 +13,7 @@ publish_to: none environment: # this project bundles Flutter SDK via `flutter_wrapper` # cf https://github.com/passsy/flutter_wrapper - flutter: 3.7.5 + flutter: 3.7.6 sdk: ">=2.19.0 <3.0.0" # following https://github.blog/2021-09-01-improving-git-protocol-security-github/ diff --git a/shaders.sksl.json b/shaders.sksl.json index 820012c6f..d8517ada6 100644 --- a/shaders.sksl.json +++ b/shaders.sksl.json @@ -1 +1 @@ -{"platform":"android","name":"SM G970N","engineRevision":"0f359063c487ee70787e58b4b011cbb3c2f53fd6","data":{"AYQQ5AADQAAAOAEARAFQJAABBADIB7777777777777777777777767YAAAAAAAAAAAAOQAAAAAAAQAAAABAMQAAAAA":"CgAAAExTS1PMAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQ0IHVsb2NhbE1hdHJpeF9TMDsKaW4gZmxvYXQyIGluUG9zaXRpb247CmluIGhhbGY0IGluQ29sb3I7CmluIGZsb2F0NCBpbkNpcmNsZUVkZ2U7Cm91dCBmbG9hdDQgdmluQ2lyY2xlRWRnZV9TMDsKb3V0IGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBDaXJjbGVHZW9tZXRyeVByb2Nlc3NvcgoJdmluQ2lyY2xlRWRnZV9TMCA9IGluQ2lyY2xlRWRnZTsKCXZpbkNvbG9yX1MwID0gaW5Db2xvcjsKCWZsb2F0MiBfdG1wXzBfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247CglmbG9hdDIgX3RtcF8xX2luUG9zaXRpb24gPSB1bG9jYWxNYXRyaXhfUzAueHogKiBpblBvc2l0aW9uICsgdWxvY2FsTWF0cml4X1MwLnl3OwoJc2tfUG9zaXRpb24gPSBfdG1wXzBfaW5Qb3NpdGlvbi54eTAxOwp9CgAAAAB7AgAAaW4gZmxvYXQ0IHZpbkNpcmNsZUVkZ2VfUzA7CmluIGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgQ2lyY2xlR2VvbWV0cnlQcm9jZXNzb3IKCWZsb2F0NCBjaXJjbGVFZGdlOwoJY2lyY2xlRWRnZSA9IHZpbkNpcmNsZUVkZ2VfUzA7CgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdmluQ29sb3JfUzA7CglmbG9hdCBkID0gbGVuZ3RoKGNpcmNsZUVkZ2UueHkpOwoJaGFsZiBkaXN0YW5jZVRvT3V0ZXJFZGdlID0gaGFsZihjaXJjbGVFZGdlLnogKiAoMS4wIC0gZCkpOwoJaGFsZiBlZGdlQWxwaGEgPSBzYXR1cmF0ZShkaXN0YW5jZVRvT3V0ZXJFZGdlKTsKCWhhbGYgZGlzdGFuY2VUb0lubmVyRWRnZSA9IGhhbGYoY2lyY2xlRWRnZS56ICogKGQgLSBjaXJjbGVFZGdlLncpKTsKCWhhbGYgaW5uZXJBbHBoYSA9IHNhdHVyYXRlKGRpc3RhbmNlVG9Jbm5lckVkZ2UpOwoJZWRnZUFscGhhICo9IGlubmVyQWxwaGE7CgloYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KGVkZ2VBbHBoYSk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRDb3ZlcmFnZV9TMDsKCX0KfQoAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAKAAAAaW5Qb3NpdGlvbgAABwAAAGluQ29sb3IADAAAAGluQ2lyY2xlRWRnZQAAAAA=","B2AAQAAABQAAIAABBYAAB7777777777774ABICAAAAAAAAAAAAAABUABAAAAAEAAAAAIBEABAAAAA":"CgAAAExTS1MOAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBpblBvc2l0aW9uOwppbiBoYWxmIGluQ292ZXJhZ2U7Cm91dCBoYWxmIHZpbkNvdmVyYWdlX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBEZWZhdWx0R2VvbWV0cnlQcm9jZXNzb3IKCWZsb2F0MiBfdG1wXzFfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247Cgl2aW5Db3ZlcmFnZV9TMCA9IGluQ292ZXJhZ2U7Cglza19Qb3NpdGlvbiA9IF90bXBfMV9pblBvc2l0aW9uLnh5MDE7Cn0KAAAAAAAATQEAAHVuaWZvcm0gaGFsZjQgdUNvbG9yX1MwOwppbiBoYWxmIHZpbkNvdmVyYWdlX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgRGVmYXVsdEdlb21ldHJ5UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdUNvbG9yX1MwOwoJaGFsZiBhbHBoYSA9IDEuMDsKCWFscGhhID0gdmluQ292ZXJhZ2VfUzA7CgloYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KGFscGhhKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAACAAAACgAAAGluUG9zaXRpb24AAAoAAABpbkNvdmVyYWdlAAAAAAAA","HUIAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAAAAAALUAQAAEAQAAAAGQCBAMQAAAIAAAAAACQAGAAAAAQAAAAAAAQQGAAAAA":"CgAAAExTS1M2AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBmbG9hdDIgbG9jYWxDb29yZDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cgl7CgkJdlRyYW5zZm9ybWVkQ29vcmRzXzJfUzAgPSBmbG9hdDN4Mih1bWF0cml4X1MxKSAqIGxvY2FsQ29vcmQueHkxOwoJfQp9CgAAAAAAAHADAAB1bmlmb3JtIGZsb2F0NCB1Y2xhbXBfUzFfYzA7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKdW5pZm9ybSBzYW1wbGVyMkQgdVRleHR1cmVTYW1wbGVyXzBfUzE7CmluIGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKaGFsZjQgVGV4dHVyZUVmZmVjdF9TMV9jMChoYWxmNCBfaW5wdXQpIAp7CglmbG9hdDIgaW5Db29yZCA9IHZUcmFuc2Zvcm1lZENvb3Jkc18yX1MwOwoJZmxvYXQyIHN1YnNldENvb3JkOwoJc3Vic2V0Q29vcmQueCA9IGluQ29vcmQueDsKCXN1YnNldENvb3JkLnkgPSBpbkNvb3JkLnk7CglmbG9hdDIgY2xhbXBlZENvb3JkOwoJY2xhbXBlZENvb3JkLnggPSBzdWJzZXRDb29yZC54OwoJY2xhbXBlZENvb3JkLnkgPSBjbGFtcChzdWJzZXRDb29yZC55LCB1Y2xhbXBfUzFfYzAueSwgdWNsYW1wX1MxX2MwLncpOwoJaGFsZjQgdGV4dHVyZUNvbG9yID0gc2FtcGxlKHVUZXh0dXJlU2FtcGxlcl8wX1MxLCBjbGFtcGVkQ29vcmQpOwoJcmV0dXJuIHRleHR1cmVDb2xvcjsKfQpoYWxmNCBNYXRyaXhFZmZlY3RfUzEoaGFsZjQgX2lucHV0KSAKewoJcmV0dXJuIFRleHR1cmVFZmZlY3RfUzFfYzAoX2lucHV0KTsKfQp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMCA9IGhhbGY0KDEpOwoJY29uc3QgaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNCgxKTsKCWhhbGY0IG91dHB1dF9TMTsKCW91dHB1dF9TMSA9IE1hdHJpeEVmZmVjdF9TMShvdXRwdXRDb2xvcl9TMCk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0X1MxICogb3V0cHV0Q292ZXJhZ2VfUzA7Cgl9Cn0KAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAIAAAAcG9zaXRpb24KAAAAbG9jYWxDb29yZAAAAAAAAA==","HWQACAAAABAAADAAAIOAAAAADIIAAIRODAAP577774DSAIAA737777YBAAAAAAAAAAAHEADZAAAAAAIAAAAAAOQAAAAAAAQAAAABAMQAAAAAA":"CgAAAExTS1ONAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gZmxvYXQgY292ZXJhZ2U7CmluIGhhbGY0IGNvbG9yOwppbiBmbG9hdDQgZ2VvbVN1YnNldDsKZmxhdCBvdXQgaGFsZjQgdmNvbG9yX1MwOwpvdXQgZmxvYXQgdmNvdmVyYWdlX1MwOwpmbGF0IG91dCBmbG9hdDQgdmdlb21TdWJzZXRfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJZmxvYXQyIHBvc2l0aW9uID0gcG9zaXRpb24ueHk7Cgl2Y29sb3JfUzAgPSBjb2xvcjsKCXZjb3ZlcmFnZV9TMCA9IGNvdmVyYWdlOwoJdmdlb21TdWJzZXRfUzAgPSBnZW9tU3Vic2V0OwoJc2tfUG9zaXRpb24gPSBwb3NpdGlvbi54eTAxOwp9CgAAAAEAAAAIBAAAdW5pZm9ybSBmbG9hdDQgdWlubmVyUmVjdF9TMTsKdW5pZm9ybSBoYWxmMiB1cmFkaXVzUGx1c0hhbGZfUzE7CmZsYXQgaW4gaGFsZjQgdmNvbG9yX1MwOwppbiBmbG9hdCB2Y292ZXJhZ2VfUzA7CmZsYXQgaW4gZmxvYXQ0IHZnZW9tU3Vic2V0X1MwOwpoYWxmNCBDaXJjdWxhclJSZWN0X1MxKGhhbGY0IF9pbnB1dCkgCnsKCWZsb2F0MiBkeHkwID0gdWlubmVyUmVjdF9TMS5MVCAtIHNrX0ZyYWdDb29yZC54eTsKCWZsb2F0MiBkeHkxID0gc2tfRnJhZ0Nvb3JkLnh5IC0gdWlubmVyUmVjdF9TMS5SQjsKCWZsb2F0MiBkeHkgPSBtYXgobWF4KGR4eTAsIGR4eTEpLCAwLjApOwoJaGFsZiBhbHBoYSA9IGhhbGYoc2F0dXJhdGUodXJhZGl1c1BsdXNIYWxmX1MxLnggLSBsZW5ndGgoZHh5KSkpOwoJcmV0dXJuIF9pbnB1dCAqIGFscGhhOwp9CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBRdWFkUGVyRWRnZUFBR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2Y29sb3JfUzA7CglmbG9hdCBjb3ZlcmFnZSA9IHZjb3ZlcmFnZV9TMDsKCWZsb2F0NCBnZW9TdWJzZXQ7CglnZW9TdWJzZXQgPSB2Z2VvbVN1YnNldF9TMDsKCWhhbGY0IGRpc3RzNCA9IGNsYW1wKGhhbGY0KDEsIDEsIC0xLCAtMSkgKiBoYWxmNChza19GcmFnQ29vcmQueHl4eSAtIGdlb1N1YnNldCksIDAsIDEpOwoJaGFsZjIgZGlzdHMyID0gZGlzdHM0Lnh5ICsgZGlzdHM0Lnp3IC0gMTsKCWhhbGYgc3Vic2V0Q292ZXJhZ2UgPSBkaXN0czIueCAqIGRpc3RzMi55OwoJY292ZXJhZ2UgPSBtaW4oY292ZXJhZ2UsIHN1YnNldENvdmVyYWdlKTsKCWhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoaGFsZihjb3ZlcmFnZSkpOwoJaGFsZjQgb3V0cHV0X1MxOwoJb3V0cHV0X1MxID0gQ2lyY3VsYXJSUmVjdF9TMShvdXRwdXRDb3ZlcmFnZV9TMCk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRfUzE7Cgl9Cn0KAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAIAAAAcG9zaXRpb24IAAAAY292ZXJhZ2UFAAAAY29sb3IAAAAKAAAAZ2VvbVN1YnNldAAAAAAAAA==","AYTRVAADQAAAOAEARAFQJAABBADAAAILBYAACCYUQD777777777767YAAAAAAAAAAAAOQAAAAAAAQAAAABAMQAAAAA":"CgAAAExTS1NyAgAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQ0IHVsb2NhbE1hdHJpeF9TMDsKaW4gZmxvYXQyIGluUG9zaXRpb247CmluIGhhbGY0IGluQ29sb3I7CmluIGZsb2F0NCBpbkNpcmNsZUVkZ2U7CmluIGhhbGYzIGluQ2xpcFBsYW5lOwppbiBoYWxmMyBpbklzZWN0UGxhbmU7Cm91dCBmbG9hdDQgdmluQ2lyY2xlRWRnZV9TMDsKb3V0IGhhbGYzIHZpbkNsaXBQbGFuZV9TMDsKb3V0IGhhbGYzIHZpbklzZWN0UGxhbmVfUzA7Cm91dCBoYWxmNCB2aW5Db2xvcl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgQ2lyY2xlR2VvbWV0cnlQcm9jZXNzb3IKCXZpbkNpcmNsZUVkZ2VfUzAgPSBpbkNpcmNsZUVkZ2U7Cgl2aW5DbGlwUGxhbmVfUzAgPSBpbkNsaXBQbGFuZTsKCXZpbklzZWN0UGxhbmVfUzAgPSBpbklzZWN0UGxhbmU7Cgl2aW5Db2xvcl9TMCA9IGluQ29sb3I7CglmbG9hdDIgX3RtcF8wX2luUG9zaXRpb24gPSBpblBvc2l0aW9uOwoJZmxvYXQyIF90bXBfMV9pblBvc2l0aW9uID0gdWxvY2FsTWF0cml4X1MwLnh6ICogaW5Qb3NpdGlvbiArIHVsb2NhbE1hdHJpeF9TMC55dzsKCXNrX1Bvc2l0aW9uID0gX3RtcF8wX2luUG9zaXRpb24ueHkwMTsKfQoAAAAAAADdAwAAaW4gZmxvYXQ0IHZpbkNpcmNsZUVkZ2VfUzA7CmluIGhhbGYzIHZpbkNsaXBQbGFuZV9TMDsKaW4gaGFsZjMgdmluSXNlY3RQbGFuZV9TMDsKaW4gaGFsZjQgdmluQ29sb3JfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBDaXJjbGVHZW9tZXRyeVByb2Nlc3NvcgoJZmxvYXQ0IGNpcmNsZUVkZ2U7CgljaXJjbGVFZGdlID0gdmluQ2lyY2xlRWRnZV9TMDsKCWhhbGYzIGNsaXBQbGFuZTsKCWNsaXBQbGFuZSA9IHZpbkNsaXBQbGFuZV9TMDsKCWhhbGYzIGlzZWN0UGxhbmU7Cglpc2VjdFBsYW5lID0gdmluSXNlY3RQbGFuZV9TMDsKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2aW5Db2xvcl9TMDsKCWZsb2F0IGQgPSBsZW5ndGgoY2lyY2xlRWRnZS54eSk7CgloYWxmIGRpc3RhbmNlVG9PdXRlckVkZ2UgPSBoYWxmKGNpcmNsZUVkZ2UueiAqICgxLjAgLSBkKSk7CgloYWxmIGVkZ2VBbHBoYSA9IHNhdHVyYXRlKGRpc3RhbmNlVG9PdXRlckVkZ2UpOwoJaGFsZiBkaXN0YW5jZVRvSW5uZXJFZGdlID0gaGFsZihjaXJjbGVFZGdlLnogKiAoZCAtIGNpcmNsZUVkZ2UudykpOwoJaGFsZiBpbm5lckFscGhhID0gc2F0dXJhdGUoZGlzdGFuY2VUb0lubmVyRWRnZSk7CgllZGdlQWxwaGEgKj0gaW5uZXJBbHBoYTsKCWhhbGYgY2xpcCA9IGhhbGYoc2F0dXJhdGUoY2lyY2xlRWRnZS56ICogZG90KGNpcmNsZUVkZ2UueHksIGNsaXBQbGFuZS54eSkgKyBjbGlwUGxhbmUueikpOwoJY2xpcCAqPSBoYWxmKHNhdHVyYXRlKGNpcmNsZUVkZ2UueiAqIGRvdChjaXJjbGVFZGdlLnh5LCBpc2VjdFBsYW5lLnh5KSArIGlzZWN0UGxhbmUueikpOwoJZWRnZUFscGhhICo9IGNsaXA7CgloYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KGVkZ2VBbHBoYSk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRDb3ZlcmFnZV9TMDsKCX0KfQoAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAoAAABpblBvc2l0aW9uAAAHAAAAaW5Db2xvcgAMAAAAaW5DaXJjbGVFZGdlCwAAAGluQ2xpcFBsYW5lAAwAAABpbklzZWN0UGxhbmUAAAAA","HVIAAAAAABIAAGAAAQ4AAAH477776R24EAAAIOBQAD6P7777777777YDAAAAAAAAAAAFIBQU7BTXIAAAAAACAWXW3ZEQAAAADAAAAAGATHIBICYCAAAEBP2LBIPAAAAAIAAAAAEARRALJ3F5SMAAAABQAAAABABTUEURMBAAACAH5FYUHQAAAAAAAEAAAAAZ4RGGRCQFAEAAAAAAAAAGARP2LVJPAAAAAAAAEAAAABSKRXZFAUHQAAAAAAAAAACAA4AAAACAAAAAAACCAYAA":"CgAAAExTS1OAAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMV9jMF9jMTsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBoYWxmNCBjb2xvcjsKaW4gZmxvYXQyIGxvY2FsQ29vcmQ7CmZsYXQgb3V0IGhhbGY0IHZjb2xvcl9TMDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfNV9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgl2Y29sb3JfUzAgPSBjb2xvcjsKCXNrX1Bvc2l0aW9uID0gcG9zaXRpb24ueHkwMTsKCXsKCQl2VHJhbnNmb3JtZWRDb29yZHNfNV9TMCA9IGZsb2F0M3gyKHVtYXRyaXhfUzFfYzBfYzEpICogbG9jYWxDb29yZC54eTE7Cgl9Cn0KAAAAAIIGAAB1bmlmb3JtIGhhbGY0IHVzdGFydF9TMV9jMF9jMDsKdW5pZm9ybSBoYWxmNCB1ZW5kX1MxX2MwX2MwOwp1bmlmb3JtIGZsb2F0M3gzIHVtYXRyaXhfUzFfYzBfYzE7CnVuaWZvcm0gaGFsZjQgdWxlZnRCb3JkZXJDb2xvcl9TMV9jMDsKdW5pZm9ybSBoYWxmNCB1cmlnaHRCb3JkZXJDb2xvcl9TMV9jMDsKZmxhdCBpbiBoYWxmNCB2Y29sb3JfUzA7CmluIGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfNV9TMDsKaGFsZjQgU2luZ2xlSW50ZXJ2YWxDb2xvcml6ZXJfUzFfYzBfYzAoaGFsZjQgX2lucHV0LCBmbG9hdDIgX2Nvb3JkcykgCnsKCWhhbGY0IF90bXBfMF9pbkNvbG9yID0gX2lucHV0OwoJZmxvYXQyIF90bXBfMV9jb29yZHMgPSBfY29vcmRzOwoJcmV0dXJuIGhhbGY0KG1peCh1c3RhcnRfUzFfYzBfYzAsIHVlbmRfUzFfYzBfYzAsIGhhbGYoX3RtcF8xX2Nvb3Jkcy54KSkpOwp9CmhhbGY0IExpbmVhckxheW91dF9TMV9jMF9jMV9jMChoYWxmNCBfaW5wdXQpIAp7CgloYWxmNCBfdG1wXzJfaW5Db2xvciA9IF9pbnB1dDsKCWZsb2F0MiBfdG1wXzNfY29vcmRzID0gdlRyYW5zZm9ybWVkQ29vcmRzXzVfUzA7CglyZXR1cm4gaGFsZjQoaGFsZjQoaGFsZihfdG1wXzNfY29vcmRzLngpICsgMWUtMDUsIDEuMCwgMC4wLCAwLjApKTsKfQpoYWxmNCBNYXRyaXhFZmZlY3RfUzFfYzBfYzEoaGFsZjQgX2lucHV0KSAKewoJcmV0dXJuIExpbmVhckxheW91dF9TMV9jMF9jMV9jMChfaW5wdXQpOwp9CmhhbGY0IENsYW1wZWRHcmFkaWVudF9TMV9jMChoYWxmNCBfaW5wdXQpIAp7CgloYWxmNCBfdG1wXzRfaW5Db2xvciA9IF9pbnB1dDsKCWhhbGY0IHQgPSBNYXRyaXhFZmZlY3RfUzFfYzBfYzEoX3RtcF80X2luQ29sb3IpOwoJaGFsZjQgb3V0Q29sb3I7CglpZiAoIWJvb2woaW50KDEpKSAmJiB0LnkgPCAwLjApIAoJewoJCW91dENvbG9yID0gaGFsZjQoMC4wKTsKCX0KCWVsc2UgaWYgKHQueCA8IDAuMCkgCgl7CgkJb3V0Q29sb3IgPSB1bGVmdEJvcmRlckNvbG9yX1MxX2MwOwoJfQoJZWxzZSBpZiAodC54ID4gMS4wKSAKCXsKCQlvdXRDb2xvciA9IHVyaWdodEJvcmRlckNvbG9yX1MxX2MwOwoJfQoJZWxzZSAKCXsKCQlvdXRDb2xvciA9IFNpbmdsZUludGVydmFsQ29sb3JpemVyX1MxX2MwX2MwKF90bXBfNF9pbkNvbG9yLCBmbG9hdDIoaGFsZjIodC54LCAwLjApKSk7Cgl9CglyZXR1cm4gaGFsZjQob3V0Q29sb3IpOwp9CmhhbGY0IERpc2FibGVDb3ZlcmFnZUFzQWxwaGFfUzEoaGFsZjQgX2lucHV0KSAKewoJX2lucHV0ID0gQ2xhbXBlZEdyYWRpZW50X1MxX2MwKF9pbnB1dCk7CgloYWxmNCBfdG1wXzVfaW5Db2xvciA9IF9pbnB1dDsKCXJldHVybiBoYWxmNChfaW5wdXQpOwp9CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBRdWFkUGVyRWRnZUFBR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2Y29sb3JfUzA7Cgljb25zdCBoYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KDEpOwoJaGFsZjQgb3V0cHV0X1MxOwoJb3V0cHV0X1MxID0gRGlzYWJsZUNvdmVyYWdlQXNBbHBoYV9TMShvdXRwdXRDb2xvcl9TMCk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0X1MxICogb3V0cHV0Q292ZXJhZ2VfUzA7Cgl9Cn0KAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAgAAABwb3NpdGlvbgUAAABjb2xvcgAAAAoAAABsb2NhbENvb3JkAAAAAAAA","HUJAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAQAAAAAAQQGABZAA6IAAAAACAAAAAADUAAAAAAAEAAAAAIDEAAAAAAA":"CgAAAExTS1PlAAAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gZmxvYXQyIGxvY2FsQ29vcmQ7Cm91dCBmbG9hdDIgdmxvY2FsQ29vcmRfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJdmxvY2FsQ29vcmRfUzAgPSBsb2NhbENvb3JkOwoJc2tfUG9zaXRpb24gPSBwb3NpdGlvbi54eTAxOwp9CgAAAAEAAAAuAwAAdW5pZm9ybSBmbG9hdDQgdWlubmVyUmVjdF9TMTsKdW5pZm9ybSBoYWxmMiB1cmFkaXVzUGx1c0hhbGZfUzE7CnVuaWZvcm0gc2FtcGxlcjJEIHVUZXh0dXJlU2FtcGxlcl8wX1MwOwppbiBmbG9hdDIgdmxvY2FsQ29vcmRfUzA7CmhhbGY0IENpcmN1bGFyUlJlY3RfUzEoaGFsZjQgX2lucHV0KSAKewoJZmxvYXQyIGR4eTAgPSB1aW5uZXJSZWN0X1MxLkxUIC0gc2tfRnJhZ0Nvb3JkLnh5OwoJZmxvYXQyIGR4eTEgPSBza19GcmFnQ29vcmQueHkgLSB1aW5uZXJSZWN0X1MxLlJCOwoJZmxvYXQyIGR4eSA9IG1heChtYXgoZHh5MCwgZHh5MSksIDAuMCk7CgloYWxmIGFscGhhID0gaGFsZihzYXR1cmF0ZSh1cmFkaXVzUGx1c0hhbGZfUzEueCAtIGxlbmd0aChkeHkpKSk7CglyZXR1cm4gX2lucHV0ICogYWxwaGE7Cn0Kdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJaGFsZjQgb3V0cHV0Q29sb3JfUzAgPSBoYWxmNCgxKTsKCWZsb2F0MiB0ZXhDb29yZDsKCXRleENvb3JkID0gdmxvY2FsQ29vcmRfUzA7CglvdXRwdXRDb2xvcl9TMCA9ICgoc2FtcGxlKHVUZXh0dXJlU2FtcGxlcl8wX1MwLCB0ZXhDb29yZCkgKiBoYWxmNCgxKSkpOwoJY29uc3QgaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNCgxKTsKCWhhbGY0IG91dHB1dF9TMTsKCW91dHB1dF9TMSA9IENpcmN1bGFyUlJlY3RfUzEob3V0cHV0Q292ZXJhZ2VfUzApOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dENvbG9yX1MwICogb3V0cHV0X1MxOwoJfQp9CgAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAIAAAAcG9zaXRpb24KAAAAbG9jYWxDb29yZAAAAAAAAA==","HUQACAAAAAMAADAAAIOAAAH677776IZOCAAP577777777777777777YBAAAAAAAAAAAHEADZAAAAAAIAAAAAAOQAAAAAAAQAAAABAMQAAAAAA":"CgAAAExTS1PPAAAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gaGFsZjQgY29sb3I7Cm91dCBoYWxmNCB2Y29sb3JfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJdmNvbG9yX1MwID0gY29sb3I7Cglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cn0KAAEAAACbAgAAdW5pZm9ybSBmbG9hdDQgdWlubmVyUmVjdF9TMTsKdW5pZm9ybSBoYWxmMiB1cmFkaXVzUGx1c0hhbGZfUzE7CmluIGhhbGY0IHZjb2xvcl9TMDsKaGFsZjQgQ2lyY3VsYXJSUmVjdF9TMShoYWxmNCBfaW5wdXQpIAp7CglmbG9hdDIgZHh5MCA9IHVpbm5lclJlY3RfUzEuTFQgLSBza19GcmFnQ29vcmQueHk7CglmbG9hdDIgZHh5MSA9IHNrX0ZyYWdDb29yZC54eSAtIHVpbm5lclJlY3RfUzEuUkI7CglmbG9hdDIgZHh5ID0gbWF4KG1heChkeHkwLCBkeHkxKSwgMC4wKTsKCWhhbGYgYWxwaGEgPSBoYWxmKHNhdHVyYXRlKHVyYWRpdXNQbHVzSGFsZl9TMS54IC0gbGVuZ3RoKGR4eSkpKTsKCXJldHVybiBfaW5wdXQgKiBhbHBoYTsKfQp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdmNvbG9yX1MwOwoJY29uc3QgaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNCgxKTsKCWhhbGY0IG91dHB1dF9TMTsKCW91dHB1dF9TMSA9IENpcmN1bGFyUlJlY3RfUzEob3V0cHV0Q292ZXJhZ2VfUzApOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dENvbG9yX1MwICogb3V0cHV0X1MxOwoJfQp9CgABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAgAAABwb3NpdGlvbgUAAABjb2xvcgAAAAAAAAA=","AYQA5AADQAAAOAEARAFQJAABBADIB7777777777777777777777767YAAAAAAAAAACAAYQADAAAEAFEURUKQKAAAYAAAAAAAAIAAAABSCICWKY2FAEAAAMAAAAAAAAAAAAAIADQAAAAIAAAAAAAIIDAAAA":"CgAAAExTS1PMAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQ0IHVsb2NhbE1hdHJpeF9TMDsKaW4gZmxvYXQyIGluUG9zaXRpb247CmluIGhhbGY0IGluQ29sb3I7CmluIGZsb2F0NCBpbkNpcmNsZUVkZ2U7Cm91dCBmbG9hdDQgdmluQ2lyY2xlRWRnZV9TMDsKb3V0IGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBDaXJjbGVHZW9tZXRyeVByb2Nlc3NvcgoJdmluQ2lyY2xlRWRnZV9TMCA9IGluQ2lyY2xlRWRnZTsKCXZpbkNvbG9yX1MwID0gaW5Db2xvcjsKCWZsb2F0MiBfdG1wXzBfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247CglmbG9hdDIgX3RtcF8xX2luUG9zaXRpb24gPSB1bG9jYWxNYXRyaXhfUzAueHogKiBpblBvc2l0aW9uICsgdWxvY2FsTWF0cml4X1MwLnl3OwoJc2tfUG9zaXRpb24gPSBfdG1wXzBfaW5Qb3NpdGlvbi54eTAxOwp9CgEAAAB+BQAAY29uc3QgaW50IGtGaWxsQldfUzFfYzAgPSAwOwpjb25zdCBpbnQga0ludmVyc2VGaWxsQldfUzFfYzAgPSAyOwpjb25zdCBpbnQga0ludmVyc2VGaWxsQUFfUzFfYzAgPSAzOwp1bmlmb3JtIGZsb2F0NCB1cmVjdFVuaWZvcm1fUzFfYzA7CmluIGZsb2F0NCB2aW5DaXJjbGVFZGdlX1MwOwppbiBoYWxmNCB2aW5Db2xvcl9TMDsKaGFsZjQgUmVjdF9TMV9jMChoYWxmNCBfaW5wdXQpIAp7CgloYWxmNCBfdG1wXzBfaW5Db2xvciA9IF9pbnB1dDsKCWhhbGYgY292ZXJhZ2U7CglpZiAoaW50KDEpID09IGtGaWxsQldfUzFfYzAgfHwgaW50KDEpID09IGtJbnZlcnNlRmlsbEJXX1MxX2MwKSAKCXsKCQljb3ZlcmFnZSA9IGhhbGYoYWxsKGdyZWF0ZXJUaGFuKGZsb2F0NChza19GcmFnQ29vcmQueHksIHVyZWN0VW5pZm9ybV9TMV9jMC56dyksIGZsb2F0NCh1cmVjdFVuaWZvcm1fUzFfYzAueHksIHNrX0ZyYWdDb29yZC54eSkpKSk7Cgl9CgllbHNlIAoJewoJCWhhbGY0IGRpc3RzNCA9IHNhdHVyYXRlKGhhbGY0KDEuMCwgMS4wLCAtMS4wLCAtMS4wKSAqIGhhbGY0KHNrX0ZyYWdDb29yZC54eXh5IC0gdXJlY3RVbmlmb3JtX1MxX2MwKSk7CgkJaGFsZjIgZGlzdHMyID0gKGRpc3RzNC54eSArIGRpc3RzNC56dykgLSAxLjA7CgkJY292ZXJhZ2UgPSBkaXN0czIueCAqIGRpc3RzMi55OwoJfQoJaWYgKGludCgxKSA9PSBrSW52ZXJzZUZpbGxCV19TMV9jMCB8fCBpbnQoMSkgPT0ga0ludmVyc2VGaWxsQUFfUzFfYzApIAoJewoJCWNvdmVyYWdlID0gMS4wIC0gY292ZXJhZ2U7Cgl9CglyZXR1cm4gaGFsZjQoaGFsZjQoY292ZXJhZ2UpKTsKfQpoYWxmNCBCbGVuZF9TMShoYWxmNCBfc3JjLCBoYWxmNCBfZHN0KSAKewoJcmV0dXJuIGJsZW5kX21vZHVsYXRlKFJlY3RfUzFfYzAoX3NyYyksIF9zcmMpOwp9CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBDaXJjbGVHZW9tZXRyeVByb2Nlc3NvcgoJZmxvYXQ0IGNpcmNsZUVkZ2U7CgljaXJjbGVFZGdlID0gdmluQ2lyY2xlRWRnZV9TMDsKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2aW5Db2xvcl9TMDsKCWZsb2F0IGQgPSBsZW5ndGgoY2lyY2xlRWRnZS54eSk7CgloYWxmIGRpc3RhbmNlVG9PdXRlckVkZ2UgPSBoYWxmKGNpcmNsZUVkZ2UueiAqICgxLjAgLSBkKSk7CgloYWxmIGVkZ2VBbHBoYSA9IHNhdHVyYXRlKGRpc3RhbmNlVG9PdXRlckVkZ2UpOwoJaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNChlZGdlQWxwaGEpOwoJaGFsZjQgb3V0cHV0X1MxOwoJb3V0cHV0X1MxID0gQmxlbmRfUzEob3V0cHV0Q292ZXJhZ2VfUzAsIGhhbGY0KDEpKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dF9TMTsKCX0KfQoAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAADAAAACgAAAGluUG9zaXRpb24AAAcAAABpbkNvbG9yAAwAAABpbkNpcmNsZUVkZ2UAAAAA","HUIAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAAAAAALUAQMAAAAAAAAAEAAAABJYQAAAAAAAAIAAAAAWCBAAAABAAAAANAECAZAAAAAAAAAAAFAAMAAAABAAAAAAABBAM":"CgAAAExTS1M2AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBmbG9hdDIgbG9jYWxDb29yZDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cgl7CgkJdlRyYW5zZm9ybWVkQ29vcmRzXzJfUzAgPSBmbG9hdDN4Mih1bWF0cml4X1MxKSAqIGxvY2FsQ29vcmQueHkxOwoJfQp9CgAAAAAAAPAEAAB1bmlmb3JtIGZsb2F0M3gzIHVtYXRyaXhfUzFfYzBfYzA7CnVuaWZvcm0gaGFsZjIgdUluY3JlbWVudF9TMV9jMDsKdW5pZm9ybSBoYWxmMiB1T2Zmc2V0c0FuZEtlcm5lbF9TMV9jMFsxM107CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKdW5pZm9ybSBzYW1wbGVyMkQgdVRleHR1cmVTYW1wbGVyXzBfUzE7CmluIGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKaGFsZjQgVGV4dHVyZUVmZmVjdF9TMV9jMF9jMF9jMChoYWxmNCBfaW5wdXQsIGZsb2F0MiBfY29vcmRzKSAKewoJcmV0dXJuIHNhbXBsZSh1VGV4dHVyZVNhbXBsZXJfMF9TMSwgX2Nvb3Jkcyk7Cn0KaGFsZjQgTWF0cml4RWZmZWN0X1MxX2MwX2MwKGhhbGY0IF9pbnB1dCwgZmxvYXQyIF9jb29yZHMpIAp7CglyZXR1cm4gVGV4dHVyZUVmZmVjdF9TMV9jMF9jMF9jMChfaW5wdXQsIGZsb2F0M3gyKHVtYXRyaXhfUzFfYzBfYzApICogX2Nvb3Jkcy54eTEpOwp9CmhhbGY0IFNtb290aF9TMV9jMChoYWxmNCBfaW5wdXQsIGZsb2F0MiBjb29yZCwgaGFsZjIgb2Zmc2V0QW5kS2VybmVsKSAKewoJcmV0dXJuIE1hdHJpeEVmZmVjdF9TMV9jMF9jMChfaW5wdXQsIChjb29yZCArIG9mZnNldEFuZEtlcm5lbC54ICogdUluY3JlbWVudF9TMV9jMCkpICogb2Zmc2V0QW5kS2VybmVsLnk7Cn0KaGFsZjQgR2F1c3NpYW5Db252b2x1dGlvbl9TMV9jMChoYWxmNCBfaW5wdXQpIAp7CgloYWxmNCBjb2xvciA9IGhhbGY0KDApOwoJZmxvYXQyIGNvb3JkID0gdlRyYW5zZm9ybWVkQ29vcmRzXzJfUzA7Cglmb3IgKGludCBpPTA7IGk8MTM7ICsraSkgCgl7CgkJY29sb3IgKz0gU21vb3RoX1MxX2MwKF9pbnB1dCwgY29vcmQsIHVPZmZzZXRzQW5kS2VybmVsX1MxX2MwW2ldKTsKCX0KCXJldHVybiBjb2xvcjsKfQpoYWxmNCBNYXRyaXhFZmZlY3RfUzEoaGFsZjQgX2lucHV0KSAKewoJcmV0dXJuIEdhdXNzaWFuQ29udm9sdXRpb25fUzFfYzAoX2lucHV0KTsKfQp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMCA9IGhhbGY0KDEpOwoJY29uc3QgaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNCgxKTsKCWhhbGY0IG91dHB1dF9TMTsKCW91dHB1dF9TMSA9IE1hdHJpeEVmZmVjdF9TMShvdXRwdXRDb2xvcl9TMCk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0X1MxICogb3V0cHV0Q292ZXJhZ2VfUzA7Cgl9Cn0KAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAIAAAAcG9zaXRpb24KAAAAbG9jYWxDb29yZAAAAAAAAA==","HTQAAGAABBYAAAEIXBAAAGEAMAAAAAAAAAAAAAAAQAHAAAAAQAAAAAAAQQGAAAAA":"CgAAAExTS1M/AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBpblBvc2l0aW9uOwppbiBoYWxmNCBpbkNvbG9yOwppbiBmbG9hdDQgaW5RdWFkRWRnZTsKb3V0IGZsb2F0NCB2UXVhZEVkZ2VfUzA7Cm91dCBoYWxmNCB2aW5Db2xvcl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZEVkZ2UKCXZRdWFkRWRnZV9TMCA9IGluUXVhZEVkZ2U7Cgl2aW5Db2xvcl9TMCA9IGluQ29sb3I7CglmbG9hdDIgX3RtcF8wX2luUG9zaXRpb24gPSBpblBvc2l0aW9uOwoJc2tfUG9zaXRpb24gPSBfdG1wXzBfaW5Qb3NpdGlvbi54eTAxOwp9CgABAAAABQMAAGluIGZsb2F0NCB2UXVhZEVkZ2VfUzA7CmluIGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgUXVhZEVkZ2UKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2aW5Db2xvcl9TMDsKCWhhbGYgZWRnZUFscGhhOwoJaGFsZjIgZHV2ZHggPSBoYWxmMihkRmR4KHZRdWFkRWRnZV9TMC54eSkpOwoJaGFsZjIgZHV2ZHkgPSBoYWxmMihkRmR5KHZRdWFkRWRnZV9TMC54eSkpOwoJaWYgKHZRdWFkRWRnZV9TMC56ID4gMC4wICYmIHZRdWFkRWRnZV9TMC53ID4gMC4wKSAKCXsKCQllZGdlQWxwaGEgPSBoYWxmKG1pbihtaW4odlF1YWRFZGdlX1MwLnosIHZRdWFkRWRnZV9TMC53KSArIDAuNSwgMS4wKSk7Cgl9CgllbHNlIAoJewoJCWhhbGYyIGdGID0gaGFsZjIoaGFsZigyLjAqdlF1YWRFZGdlX1MwLngqZHV2ZHgueCAtIGR1dmR4LnkpLCAgICAgICAgICAgICAgICAgaGFsZigyLjAqdlF1YWRFZGdlX1MwLngqZHV2ZHkueCAtIGR1dmR5LnkpKTsKCQllZGdlQWxwaGEgPSBoYWxmKHZRdWFkRWRnZV9TMC54KnZRdWFkRWRnZV9TMC54IC0gdlF1YWRFZGdlX1MwLnkpOwoJCWVkZ2VBbHBoYSA9IHNhdHVyYXRlKDAuNSAtIGVkZ2VBbHBoYSAvIGxlbmd0aChnRikpOwoJfQoJaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNChlZGdlQWxwaGEpOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dENvbG9yX1MwICogb3V0cHV0Q292ZXJhZ2VfUzA7Cgl9Cn0KAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAKAAAAaW5Qb3NpdGlvbgAABwAAAGluQ29sb3IACgAAAGluUXVhZEVkZ2UAAAAAAAA=","HWQACAAAABAAADAAAIOAAAAADIIAAIRODAAP577774DSAIAA737777YBAAAAAAAAAAAKAAYAAAACAAAAAAACCAYAAA":"CgAAAExTS1ONAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gZmxvYXQgY292ZXJhZ2U7CmluIGhhbGY0IGNvbG9yOwppbiBmbG9hdDQgZ2VvbVN1YnNldDsKZmxhdCBvdXQgaGFsZjQgdmNvbG9yX1MwOwpvdXQgZmxvYXQgdmNvdmVyYWdlX1MwOwpmbGF0IG91dCBmbG9hdDQgdmdlb21TdWJzZXRfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJZmxvYXQyIHBvc2l0aW9uID0gcG9zaXRpb24ueHk7Cgl2Y29sb3JfUzAgPSBjb2xvcjsKCXZjb3ZlcmFnZV9TMCA9IGNvdmVyYWdlOwoJdmdlb21TdWJzZXRfUzAgPSBnZW9tU3Vic2V0OwoJc2tfUG9zaXRpb24gPSBwb3NpdGlvbi54eTAxOwp9CgAAAAEAAAB5AgAAZmxhdCBpbiBoYWxmNCB2Y29sb3JfUzA7CmluIGZsb2F0IHZjb3ZlcmFnZV9TMDsKZmxhdCBpbiBmbG9hdDQgdmdlb21TdWJzZXRfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBRdWFkUGVyRWRnZUFBR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2Y29sb3JfUzA7CglmbG9hdCBjb3ZlcmFnZSA9IHZjb3ZlcmFnZV9TMDsKCWZsb2F0NCBnZW9TdWJzZXQ7CglnZW9TdWJzZXQgPSB2Z2VvbVN1YnNldF9TMDsKCWhhbGY0IGRpc3RzNCA9IGNsYW1wKGhhbGY0KDEsIDEsIC0xLCAtMSkgKiBoYWxmNChza19GcmFnQ29vcmQueHl4eSAtIGdlb1N1YnNldCksIDAsIDEpOwoJaGFsZjIgZGlzdHMyID0gZGlzdHM0Lnh5ICsgZGlzdHM0Lnp3IC0gMTsKCWhhbGYgc3Vic2V0Q292ZXJhZ2UgPSBkaXN0czIueCAqIGRpc3RzMi55OwoJY292ZXJhZ2UgPSBtaW4oY292ZXJhZ2UsIHN1YnNldENvdmVyYWdlKTsKCWhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoaGFsZihjb3ZlcmFnZSkpOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dENvbG9yX1MwICogb3V0cHV0Q292ZXJhZ2VfUzA7Cgl9Cn0KAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAIAAAAcG9zaXRpb24IAAAAY292ZXJhZ2UFAAAAY29sb3IAAAAKAAAAZ2VvbVN1YnNldAAAAAAAAA==","HUQAAAAAAAMAADAAAIOAAAH677776IZOCAAP577777777777777777YBAAAAAAAAAAADEAANAAAAALHCKLMRAAAAAAAAABAAAAAGJBCFLQVBWAQAAAAAAQAAAAAMACQCAACAAAAA2AIBAEIAAAAAAAAAAAAIADQAAAAIAAAAAAAIIDAAAAAA":"CgAAAExTS1PUAAAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gaGFsZjQgY29sb3I7CmZsYXQgb3V0IGhhbGY0IHZjb2xvcl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgl2Y29sb3JfUzAgPSBjb2xvcjsKCXNrX1Bvc2l0aW9uID0gcG9zaXRpb24ueHkwMTsKfQoBAAAAeAQAAHVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMV9jMF9jMDsKdW5pZm9ybSBoYWxmNCB1Y2lyY2xlRGF0YV9TMV9jMDsKdW5pZm9ybSBzYW1wbGVyMkQgdVRleHR1cmVTYW1wbGVyXzBfUzE7CmZsYXQgaW4gaGFsZjQgdmNvbG9yX1MwOwpoYWxmNCBUZXh0dXJlRWZmZWN0X1MxX2MwX2MwX2MwKGhhbGY0IF9pbnB1dCwgZmxvYXQyIF9jb29yZHMpIAp7CglyZXR1cm4gc2FtcGxlKHVUZXh0dXJlU2FtcGxlcl8wX1MxLCBfY29vcmRzKS4wMDByOwp9CmhhbGY0IE1hdHJpeEVmZmVjdF9TMV9jMF9jMChoYWxmNCBfaW5wdXQsIGZsb2F0MiBfY29vcmRzKSAKewoJcmV0dXJuIFRleHR1cmVFZmZlY3RfUzFfYzBfYzBfYzAoX2lucHV0LCBmbG9hdDN4Mih1bWF0cml4X1MxX2MwX2MwKSAqIF9jb29yZHMueHkxKTsKfQpoYWxmNCBDaXJjbGVCbHVyX1MxX2MwKGhhbGY0IF9pbnB1dCkgCnsKCWhhbGY0IF90bXBfMF9pbkNvbG9yID0gX2lucHV0OwoJaGFsZjIgdmVjID0gaGFsZjIoKHNrX0ZyYWdDb29yZC54eSAtIGZsb2F0Mih1Y2lyY2xlRGF0YV9TMV9jMC54eSkpICogZmxvYXQodWNpcmNsZURhdGFfUzFfYzAudykpOwoJaGFsZiBkaXN0ID0gbGVuZ3RoKHZlYykgKyAoMC41IC0gdWNpcmNsZURhdGFfUzFfYzAueikgKiB1Y2lyY2xlRGF0YV9TMV9jMC53OwoJcmV0dXJuIGhhbGY0KE1hdHJpeEVmZmVjdF9TMV9jMF9jMChfdG1wXzBfaW5Db2xvciwgZmxvYXQyKGhhbGYyKGRpc3QsIDAuNSkpKS53d3d3KTsKfQpoYWxmNCBCbGVuZF9TMShoYWxmNCBfc3JjLCBoYWxmNCBfZHN0KSAKewoJcmV0dXJuIGJsZW5kX21vZHVsYXRlKENpcmNsZUJsdXJfUzFfYzAoX3NyYyksIF9zcmMpOwp9CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBRdWFkUGVyRWRnZUFBR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2Y29sb3JfUzA7Cgljb25zdCBoYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KDEpOwoJaGFsZjQgb3V0cHV0X1MxOwoJb3V0cHV0X1MxID0gQmxlbmRfUzEob3V0cHV0Q292ZXJhZ2VfUzAsIGhhbGY0KDEpKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dF9TMTsKCX0KfQoBAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAgAAABwb3NpdGlvbgUAAABjb2xvcgAAAAAAAAA=","AYQA5AADQAAAOAEARAFQJAABBADIB7777777777777777777777767YAAAAAAAAAAAAOQAAAAAAAQAAAABAMQAAAAA":"CgAAAExTS1PMAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQ0IHVsb2NhbE1hdHJpeF9TMDsKaW4gZmxvYXQyIGluUG9zaXRpb247CmluIGhhbGY0IGluQ29sb3I7CmluIGZsb2F0NCBpbkNpcmNsZUVkZ2U7Cm91dCBmbG9hdDQgdmluQ2lyY2xlRWRnZV9TMDsKb3V0IGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBDaXJjbGVHZW9tZXRyeVByb2Nlc3NvcgoJdmluQ2lyY2xlRWRnZV9TMCA9IGluQ2lyY2xlRWRnZTsKCXZpbkNvbG9yX1MwID0gaW5Db2xvcjsKCWZsb2F0MiBfdG1wXzBfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247CglmbG9hdDIgX3RtcF8xX2luUG9zaXRpb24gPSB1bG9jYWxNYXRyaXhfUzAueHogKiBpblBvc2l0aW9uICsgdWxvY2FsTWF0cml4X1MwLnl3OwoJc2tfUG9zaXRpb24gPSBfdG1wXzBfaW5Qb3NpdGlvbi54eTAxOwp9CgAAAADqAQAAaW4gZmxvYXQ0IHZpbkNpcmNsZUVkZ2VfUzA7CmluIGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgQ2lyY2xlR2VvbWV0cnlQcm9jZXNzb3IKCWZsb2F0NCBjaXJjbGVFZGdlOwoJY2lyY2xlRWRnZSA9IHZpbkNpcmNsZUVkZ2VfUzA7CgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdmluQ29sb3JfUzA7CglmbG9hdCBkID0gbGVuZ3RoKGNpcmNsZUVkZ2UueHkpOwoJaGFsZiBkaXN0YW5jZVRvT3V0ZXJFZGdlID0gaGFsZihjaXJjbGVFZGdlLnogKiAoMS4wIC0gZCkpOwoJaGFsZiBlZGdlQWxwaGEgPSBzYXR1cmF0ZShkaXN0YW5jZVRvT3V0ZXJFZGdlKTsKCWhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoZWRnZUFscGhhKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAKAAAAaW5Qb3NpdGlvbgAABwAAAGluQ29sb3IADAAAAGluQ2lyY2xlRWRnZQAAAAA=","FAAQMYAAMAAAEADAAABAEYAAAICIAB5AABQAAAQAMAAAEATAAABAIIGAAEDCBYQCA4AAAAAAEAB5AAAAACQHEB4XIQAQAADQAAAABAAAAAAABAEMVDOMCJKRAAAAAHAAAAAAAAAAACQAGAAAAAQAAAAAAAQQGAAA":"CgAAAExTS1PUCwAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0NCByYWRpaV9zZWxlY3RvcjsKaW4gZmxvYXQ0IGNvcm5lcl9hbmRfcmFkaXVzX291dHNldHM7CmluIGZsb2F0NCBhYV9ibG9hdF9hbmRfY292ZXJhZ2U7CmluIGZsb2F0NCByYWRpaV94OwppbiBmbG9hdDQgcmFkaWlfeTsKaW4gZmxvYXQ0IHNrZXc7CmluIGZsb2F0MiB0cmFuc2xhdGVfYW5kX2xvY2Fscm90YXRlOwppbiBoYWxmNCBjb2xvcjsKZmxhdCBvdXQgaGFsZjQgdmNvbG9yX1MwOwpvdXQgZmxvYXQyIHZhcmNjb29yZF9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgRmlsbFJSZWN0T3A6OlByb2Nlc3NvcgoJdmNvbG9yX1MwID0gY29sb3I7CglmbG9hdCBhYV9ibG9hdF9tdWx0aXBsaWVyID0gMTsKCWZsb2F0MiBjb3JuZXIgPSBjb3JuZXJfYW5kX3JhZGl1c19vdXRzZXRzLnh5OwoJZmxvYXQyIHJhZGl1c19vdXRzZXQgPSBjb3JuZXJfYW5kX3JhZGl1c19vdXRzZXRzLnp3OwoJZmxvYXQyIGFhX2Jsb2F0X2RpcmVjdGlvbiA9IGFhX2Jsb2F0X2FuZF9jb3ZlcmFnZS54eTsKCWZsb2F0IGlzX2xpbmVhcl9jb3ZlcmFnZSA9IGFhX2Jsb2F0X2FuZF9jb3ZlcmFnZS53OwoJZmxvYXQyIHBpeGVsbGVuZ3RoID0gaW52ZXJzZXNxcnQoZmxvYXQyKGRvdChza2V3Lnh6LCBza2V3Lnh6KSwgZG90KHNrZXcueXcsIHNrZXcueXcpKSk7CglmbG9hdDQgbm9ybWFsaXplZF9heGlzX2RpcnMgPSBza2V3ICogcGl4ZWxsZW5ndGgueHl4eTsKCWZsb2F0MiBheGlzd2lkdGhzID0gKGFicyhub3JtYWxpemVkX2F4aXNfZGlycy54eSkgKyBhYnMobm9ybWFsaXplZF9heGlzX2RpcnMuencpKTsKCWZsb2F0MiBhYV9ibG9hdHJhZGl1cyA9IGF4aXN3aWR0aHMgKiBwaXhlbGxlbmd0aCAqIC41OwoJZmxvYXQ0IHJhZGlpX2FuZF9uZWlnaGJvcnMgPSByYWRpaV9zZWxlY3RvciogZmxvYXQ0eDQocmFkaWlfeCwgcmFkaWlfeSwgcmFkaWlfeC55eHd6LCByYWRpaV95Lnd6eXgpOwoJZmxvYXQyIHJhZGlpID0gcmFkaWlfYW5kX25laWdoYm9ycy54eTsKCWZsb2F0MiBuZWlnaGJvcl9yYWRpaSA9IHJhZGlpX2FuZF9uZWlnaGJvcnMuenc7CglmbG9hdCBjb3ZlcmFnZV9tdWx0aXBsaWVyID0gMTsKCWlmIChhbnkoZ3JlYXRlclRoYW4oYWFfYmxvYXRyYWRpdXMsIGZsb2F0MigxKSkpKSAKCXsKCQljb3JuZXIgPSBtYXgoYWJzKGNvcm5lciksIGFhX2Jsb2F0cmFkaXVzKSAqIHNpZ24oY29ybmVyKTsKCQljb3ZlcmFnZV9tdWx0aXBsaWVyID0gMSAvIChtYXgoYWFfYmxvYXRyYWRpdXMueCwgMSkgKiBtYXgoYWFfYmxvYXRyYWRpdXMueSwgMSkpOwoJCXJhZGlpID0gZmxvYXQyKDApOwoJfQoJZmxvYXQgY292ZXJhZ2UgPSBhYV9ibG9hdF9hbmRfY292ZXJhZ2UuejsKCWlmIChhbnkobGVzc1RoYW4ocmFkaWksIGFhX2Jsb2F0cmFkaXVzICogMS41KSkpIAoJewoJCXJhZGlpID0gZmxvYXQyKDApOwoJCWFhX2Jsb2F0X2RpcmVjdGlvbiA9IHNpZ24oY29ybmVyKTsKCQlpZiAoY292ZXJhZ2UgPiAuNSkgCgkJewoJCQlhYV9ibG9hdF9kaXJlY3Rpb24gPSAtYWFfYmxvYXRfZGlyZWN0aW9uOwoJCX0KCQlpc19saW5lYXJfY292ZXJhZ2UgPSAxOwoJfQoJZWxzZSAKCXsKCQlyYWRpaSA9IGNsYW1wKHJhZGlpLCBwaXhlbGxlbmd0aCAqIDEuNSwgMiAtIHBpeGVsbGVuZ3RoICogMS41KTsKCQluZWlnaGJvcl9yYWRpaSA9IGNsYW1wKG5laWdoYm9yX3JhZGlpLCBwaXhlbGxlbmd0aCAqIDEuNSwgMiAtIHBpeGVsbGVuZ3RoICogMS41KTsKCQlmbG9hdDIgc3BhY2luZyA9IDIgLSByYWRpaSAtIG5laWdoYm9yX3JhZGlpOwoJCWZsb2F0MiBleHRyYV9wYWQgPSBtYXgocGl4ZWxsZW5ndGggKiAuMDYyNSAtIHNwYWNpbmcsIGZsb2F0MigwKSk7CgkJcmFkaWkgLT0gZXh0cmFfcGFkICogLjU7Cgl9CglmbG9hdDIgYWFfb3V0c2V0ID0gYWFfYmxvYXRfZGlyZWN0aW9uICogYWFfYmxvYXRyYWRpdXMgKiBhYV9ibG9hdF9tdWx0aXBsaWVyOwoJZmxvYXQyIHZlcnRleHBvcyA9IGNvcm5lciArIHJhZGl1c19vdXRzZXQgKiByYWRpaSArIGFhX291dHNldDsKCWlmIChjb3ZlcmFnZSA+IC41KSAKCXsKCQlpZiAoYWFfYmxvYXRfZGlyZWN0aW9uLnggIT0gMCAmJiB2ZXJ0ZXhwb3MueCAqIGNvcm5lci54IDwgMCkgCgkJewoJCQlmbG9hdCBiYWNrc2V0ID0gYWJzKHZlcnRleHBvcy54KTsKCQkJdmVydGV4cG9zLnggPSAwOwoJCQl2ZXJ0ZXhwb3MueSArPSBiYWNrc2V0ICogc2lnbihjb3JuZXIueSkgKiBwaXhlbGxlbmd0aC55L3BpeGVsbGVuZ3RoLng7CgkJCWNvdmVyYWdlID0gKGNvdmVyYWdlIC0gLjUpICogYWJzKGNvcm5lci54KSAvIChhYnMoY29ybmVyLngpICsgYmFja3NldCkgKyAuNTsKCQl9CgkJaWYgKGFhX2Jsb2F0X2RpcmVjdGlvbi55ICE9IDAgJiYgdmVydGV4cG9zLnkgKiBjb3JuZXIueSA8IDApIAoJCXsKCQkJZmxvYXQgYmFja3NldCA9IGFicyh2ZXJ0ZXhwb3MueSk7CgkJCXZlcnRleHBvcy55ID0gMDsKCQkJdmVydGV4cG9zLnggKz0gYmFja3NldCAqIHNpZ24oY29ybmVyLngpICogcGl4ZWxsZW5ndGgueC9waXhlbGxlbmd0aC55OwoJCQljb3ZlcmFnZSA9IChjb3ZlcmFnZSAtIC41KSAqIGFicyhjb3JuZXIueSkgLyAoYWJzKGNvcm5lci55KSArIGJhY2tzZXQpICsgLjU7CgkJfQoJfQoJZmxvYXQyeDIgc2tld21hdHJpeCA9IGZsb2F0MngyKHNrZXcueHksIHNrZXcuencpOwoJZmxvYXQyIGRldmNvb3JkID0gdmVydGV4cG9zICogc2tld21hdHJpeCArIHRyYW5zbGF0ZV9hbmRfbG9jYWxyb3RhdGUueHk7CglpZiAoMCAhPSBpc19saW5lYXJfY292ZXJhZ2UpIAoJewoJCXZhcmNjb29yZF9TMC54eSA9IGZsb2F0MigwLCBjb3ZlcmFnZSAqIGNvdmVyYWdlX211bHRpcGxpZXIpOwoJfQoJZWxzZSAKCXsKCQlmbG9hdDIgYXJjY29vcmQgPSAxIC0gYWJzKHJhZGl1c19vdXRzZXQpICsgYWFfb3V0c2V0L3JhZGlpICogY29ybmVyOwoJCXZhcmNjb29yZF9TMC54eSA9IGZsb2F0MihhcmNjb29yZC54KzEsIGFyY2Nvb3JkLnkpOwoJfQoJc2tfUG9zaXRpb24gPSBkZXZjb29yZC54eTAxOwp9CgEAAABRBQAAY29uc3QgaW50IGtGaWxsQUFfUzFfYzAgPSAxOwpjb25zdCBpbnQga0ludmVyc2VGaWxsQldfUzFfYzAgPSAyOwpjb25zdCBpbnQga0ludmVyc2VGaWxsQUFfUzFfYzAgPSAzOwp1bmlmb3JtIGZsb2F0NCB1Y2lyY2xlX1MxX2MwOwpmbGF0IGluIGhhbGY0IHZjb2xvcl9TMDsKaW4gZmxvYXQyIHZhcmNjb29yZF9TMDsKaGFsZjQgQ2lyY2xlX1MxX2MwKGhhbGY0IF9pbnB1dCkgCnsKCWhhbGY0IF90bXBfMF9pbkNvbG9yID0gX2lucHV0OwoJaGFsZiBkOwoJaWYgKGludCgzKSA9PSBrSW52ZXJzZUZpbGxCV19TMV9jMCB8fCBpbnQoMykgPT0ga0ludmVyc2VGaWxsQUFfUzFfYzApIAoJewoJCWQgPSBoYWxmKChsZW5ndGgoKHVjaXJjbGVfUzFfYzAueHkgLSBza19GcmFnQ29vcmQueHkpICogdWNpcmNsZV9TMV9jMC53KSAtIDEuMCkgKiB1Y2lyY2xlX1MxX2MwLnopOwoJfQoJZWxzZSAKCXsKCQlkID0gaGFsZigoMS4wIC0gbGVuZ3RoKCh1Y2lyY2xlX1MxX2MwLnh5IC0gc2tfRnJhZ0Nvb3JkLnh5KSAqIHVjaXJjbGVfUzFfYzAudykpICogdWNpcmNsZV9TMV9jMC56KTsKCX0KCXJldHVybiBoYWxmNChoYWxmNChpbnQoMykgPT0ga0ZpbGxBQV9TMV9jMCB8fCBpbnQoMykgPT0ga0ludmVyc2VGaWxsQUFfUzFfYzAgPyBzYXR1cmF0ZShkKSA6IGhhbGYoZCA+IDAuNSA/IDEgOiAwKSkpOwp9CmhhbGY0IEJsZW5kX1MxKGhhbGY0IF9zcmMsIGhhbGY0IF9kc3QpIAp7CglyZXR1cm4gYmxlbmRfbW9kdWxhdGUoX3NyYywgQ2lyY2xlX1MxX2MwKF9zcmMpKTsKfQp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgRmlsbFJSZWN0T3A6OlByb2Nlc3NvcgoJaGFsZjQgb3V0cHV0Q29sb3JfUzA7CglvdXRwdXRDb2xvcl9TMCA9IHZjb2xvcl9TMDsKCWZsb2F0IHhfcGx1c18xPXZhcmNjb29yZF9TMC54LCB5PXZhcmNjb29yZF9TMC55OwoJaGFsZiBjb3ZlcmFnZTsKCWlmICgwID09IHhfcGx1c18xKSAKCXsKCQljb3ZlcmFnZSA9IGhhbGYoeSk7Cgl9CgllbHNlIAoJewoJCWZsb2F0IGZuID0geF9wbHVzXzEgKiAoeF9wbHVzXzEgLSAyKTsKCQlmbiA9IGZtYSh5LHksIGZuKTsKCQlmbG9hdCBmbndpZHRoID0gZndpZHRoKGZuKTsKCQljb3ZlcmFnZSA9IC41IC0gaGFsZihmbi9mbndpZHRoKTsKCQljb3ZlcmFnZSA9IGNsYW1wKGNvdmVyYWdlLCAwLCAxKTsKCX0KCWhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoY292ZXJhZ2UpOwoJaGFsZjQgb3V0cHV0X1MxOwoJb3V0cHV0X1MxID0gQmxlbmRfUzEob3V0cHV0Q292ZXJhZ2VfUzAsIGhhbGY0KDEpKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dF9TMTsKCX0KfQoAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAACAAAAA4AAAByYWRpaV9zZWxlY3RvcgAAGQAAAGNvcm5lcl9hbmRfcmFkaXVzX291dHNldHMAAAAVAAAAYWFfYmxvYXRfYW5kX2NvdmVyYWdlAAAABwAAAHJhZGlpX3gABwAAAHJhZGlpX3kABAAAAHNrZXcZAAAAdHJhbnNsYXRlX2FuZF9sb2NhbHJvdGF0ZQAAAAUAAABjb2xvcgAAAAAAAAA=","HUIAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAAAAAALUAQMAAAAAAABAEAAAABJYQAAAAAACAIAAAAAWCBAAAIBAAAAANAECAZAAAAQAAAAAAFAAMAAAABAAAAAAABBAM":"CgAAAExTS1M2AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBmbG9hdDIgbG9jYWxDb29yZDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cgl7CgkJdlRyYW5zZm9ybWVkQ29vcmRzXzJfUzAgPSBmbG9hdDN4Mih1bWF0cml4X1MxKSAqIGxvY2FsQ29vcmQueHkxOwoJfQp9CgAAAAAAAC8GAAB1bmlmb3JtIGZsb2F0NCB1Y2xhbXBfUzFfYzBfYzBfYzA7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMV9jMF9jMDsKdW5pZm9ybSBoYWxmMiB1SW5jcmVtZW50X1MxX2MwOwp1bmlmb3JtIGhhbGYyIHVPZmZzZXRzQW5kS2VybmVsX1MxX2MwWzEzXTsKdW5pZm9ybSBmbG9hdDN4MyB1bWF0cml4X1MxOwp1bmlmb3JtIHNhbXBsZXIyRCB1VGV4dHVyZVNhbXBsZXJfMF9TMTsKaW4gZmxvYXQyIHZUcmFuc2Zvcm1lZENvb3Jkc18yX1MwOwpoYWxmNCBUZXh0dXJlRWZmZWN0X1MxX2MwX2MwX2MwKGhhbGY0IF9pbnB1dCwgZmxvYXQyIF9jb29yZHMpIAp7CglmbG9hdDIgaW5Db29yZCA9IF9jb29yZHM7CglmbG9hdDIgc3Vic2V0Q29vcmQ7CglzdWJzZXRDb29yZC54ID0gaW5Db29yZC54OwoJc3Vic2V0Q29vcmQueSA9IGluQ29vcmQueTsKCWZsb2F0MiBjbGFtcGVkQ29vcmQ7CgljbGFtcGVkQ29vcmQueCA9IHN1YnNldENvb3JkLng7CgljbGFtcGVkQ29vcmQueSA9IGNsYW1wKHN1YnNldENvb3JkLnksIHVjbGFtcF9TMV9jMF9jMF9jMC55LCB1Y2xhbXBfUzFfYzBfYzBfYzAudyk7CgloYWxmNCB0ZXh0dXJlQ29sb3IgPSBzYW1wbGUodVRleHR1cmVTYW1wbGVyXzBfUzEsIGNsYW1wZWRDb29yZCk7CglyZXR1cm4gdGV4dHVyZUNvbG9yOwp9CmhhbGY0IE1hdHJpeEVmZmVjdF9TMV9jMF9jMChoYWxmNCBfaW5wdXQsIGZsb2F0MiBfY29vcmRzKSAKewoJcmV0dXJuIFRleHR1cmVFZmZlY3RfUzFfYzBfYzBfYzAoX2lucHV0LCBmbG9hdDN4Mih1bWF0cml4X1MxX2MwX2MwKSAqIF9jb29yZHMueHkxKTsKfQpoYWxmNCBTbW9vdGhfUzFfYzAoaGFsZjQgX2lucHV0LCBmbG9hdDIgY29vcmQsIGhhbGYyIG9mZnNldEFuZEtlcm5lbCkgCnsKCXJldHVybiBNYXRyaXhFZmZlY3RfUzFfYzBfYzAoX2lucHV0LCAoY29vcmQgKyBvZmZzZXRBbmRLZXJuZWwueCAqIHVJbmNyZW1lbnRfUzFfYzApKSAqIG9mZnNldEFuZEtlcm5lbC55Owp9CmhhbGY0IEdhdXNzaWFuQ29udm9sdXRpb25fUzFfYzAoaGFsZjQgX2lucHV0KSAKewoJaGFsZjQgY29sb3IgPSBoYWxmNCgwKTsKCWZsb2F0MiBjb29yZCA9IHZUcmFuc2Zvcm1lZENvb3Jkc18yX1MwOwoJZm9yIChpbnQgaT0wOyBpPDEzOyArK2kpIAoJewoJCWNvbG9yICs9IFNtb290aF9TMV9jMChfaW5wdXQsIGNvb3JkLCB1T2Zmc2V0c0FuZEtlcm5lbF9TMV9jMFtpXSk7Cgl9CglyZXR1cm4gY29sb3I7Cn0KaGFsZjQgTWF0cml4RWZmZWN0X1MxKGhhbGY0IF9pbnB1dCkgCnsKCXJldHVybiBHYXVzc2lhbkNvbnZvbHV0aW9uX1MxX2MwKF9pbnB1dCk7Cn0Kdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJaGFsZjQgb3V0cHV0Q29sb3JfUzAgPSBoYWxmNCgxKTsKCWNvbnN0IGhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoMSk7CgloYWxmNCBvdXRwdXRfUzE7CglvdXRwdXRfUzEgPSBNYXRyaXhFZmZlY3RfUzEob3V0cHV0Q29sb3JfUzApOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dF9TMSAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAgAAABwb3NpdGlvbgoAAABsb2NhbENvb3JkAAAAAAAA","CMRQCIAABBYAAAEIXBAAACDQMAABRAFAAAAAAAAAAAAAAAEABYAAAAEAAAAAAAEEBQAAAAA":"CgAAAExTS1MyAgAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQ0IHVsb2NhbE1hdHJpeF9TMDsKaW4gZmxvYXQyIGluUG9zaXRpb247CmluIGhhbGY0IGluQ29sb3I7CmluIGZsb2F0MiBpbkVsbGlwc2VPZmZzZXQ7CmluIGZsb2F0NCBpbkVsbGlwc2VSYWRpaTsKb3V0IGZsb2F0MiB2RWxsaXBzZU9mZnNldHNfUzA7Cm91dCBmbG9hdDQgdkVsbGlwc2VSYWRpaV9TMDsKb3V0IGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBFbGxpcHNlR2VvbWV0cnlQcm9jZXNzb3IKCXZFbGxpcHNlT2Zmc2V0c19TMCA9IGluRWxsaXBzZU9mZnNldDsKCXZFbGxpcHNlUmFkaWlfUzAgPSBpbkVsbGlwc2VSYWRpaTsKCXZpbkNvbG9yX1MwID0gaW5Db2xvcjsKCWZsb2F0MiBfdG1wXzBfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247CglmbG9hdDIgX3RtcF8xX2luUG9zaXRpb24gPSB1bG9jYWxNYXRyaXhfUzAueHogKiBpblBvc2l0aW9uICsgdWxvY2FsTWF0cml4X1MwLnl3OwoJc2tfUG9zaXRpb24gPSBfdG1wXzBfaW5Qb3NpdGlvbi54eTAxOwp9CgAAAAAAAHIDAABpbiBmbG9hdDIgdkVsbGlwc2VPZmZzZXRzX1MwOwppbiBmbG9hdDQgdkVsbGlwc2VSYWRpaV9TMDsKaW4gaGFsZjQgdmluQ29sb3JfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBFbGxpcHNlR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2aW5Db2xvcl9TMDsKCWZsb2F0MiBvZmZzZXQgPSB2RWxsaXBzZU9mZnNldHNfUzAueHk7CglvZmZzZXQgKj0gdkVsbGlwc2VSYWRpaV9TMC54eTsKCWZsb2F0IHRlc3QgPSBkb3Qob2Zmc2V0LCBvZmZzZXQpIC0gMS4wOwoJZmxvYXQyIGdyYWQgPSAyLjAqb2Zmc2V0KnZFbGxpcHNlUmFkaWlfUzAueHk7CglmbG9hdCBncmFkX2RvdCA9IGRvdChncmFkLCBncmFkKTsKCWdyYWRfZG90ID0gbWF4KGdyYWRfZG90LCAxLjE3NTVlLTM4KTsKCWZsb2F0IGludmxlbiA9IGludmVyc2VzcXJ0KGdyYWRfZG90KTsKCWZsb2F0IGVkZ2VBbHBoYSA9IHNhdHVyYXRlKDAuNS10ZXN0Kmludmxlbik7CglvZmZzZXQgPSB2RWxsaXBzZU9mZnNldHNfUzAueHkqdkVsbGlwc2VSYWRpaV9TMC56dzsKCXRlc3QgPSBkb3Qob2Zmc2V0LCBvZmZzZXQpIC0gMS4wOwoJZ3JhZCA9IDIuMCpvZmZzZXQqdkVsbGlwc2VSYWRpaV9TMC56dzsKCWdyYWRfZG90ID0gZG90KGdyYWQsIGdyYWQpOwoJaW52bGVuID0gaW52ZXJzZXNxcnQoZ3JhZF9kb3QpOwoJZWRnZUFscGhhICo9IHNhdHVyYXRlKDAuNSt0ZXN0Kmludmxlbik7CgloYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KGhhbGYoZWRnZUFscGhhKSk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRDb3ZlcmFnZV9TMDsKCX0KfQoAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAEAAAACgAAAGluUG9zaXRpb24AAAcAAABpbkNvbG9yAA8AAABpbkVsbGlwc2VPZmZzZXQADgAAAGluRWxsaXBzZVJhZGlpAAAAAAAA","EADQAAAAAEAAAAAUAABQAAQPAAABCFYMAAKAUEAAAAAAAAABAAAAAAAAAAANAAIAAAABAAAAACAJAAIAAAAA":"CgAAAExTS1NyAgAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQyIHVBdGxhc0RpbWVuc2lvbnNJbnZfUzA7CmluIGZsb2F0MyBpblBvc2l0aW9uOwppbiBoYWxmNCBpbkNvbG9yOwppbiB1c2hvcnQyIGluVGV4dHVyZUNvb3JkczsKb3V0IGZsb2F0MiB2VGV4dHVyZUNvb3Jkc19TMDsKZmxhdCBvdXQgZmxvYXQgdlRleEluZGV4X1MwOwpvdXQgZmxvYXQyIHZJbnRUZXh0dXJlQ29vcmRzX1MwOwpvdXQgaGFsZjQgdmluQ29sb3JfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIERpc3RhbmNlRmllbGRQYXRoCglpbnQgdGV4SWR4ID0gMDsKCWZsb2F0MiB1bm9ybVRleENvb3JkcyA9IGZsb2F0MihpblRleHR1cmVDb29yZHMueCwgaW5UZXh0dXJlQ29vcmRzLnkpOwoJdlRleHR1cmVDb29yZHNfUzAgPSB1bm9ybVRleENvb3JkcyAqIHVBdGxhc0RpbWVuc2lvbnNJbnZfUzA7Cgl2VGV4SW5kZXhfUzAgPSBmbG9hdCh0ZXhJZHgpOwoJdkludFRleHR1cmVDb29yZHNfUzAgPSB1bm9ybVRleENvb3JkczsKCXZpbkNvbG9yX1MwID0gaW5Db2xvcjsKCWZsb2F0MyBfdG1wXzFfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247Cglza19Qb3NpdGlvbiA9IGluUG9zaXRpb24ueHkwejsKfQoAAAAAAACfAgAAdW5pZm9ybSBzYW1wbGVyMkQgdVRleHR1cmVTYW1wbGVyXzBfUzA7CmluIGZsb2F0MiB2VGV4dHVyZUNvb3Jkc19TMDsKZmxhdCBpbiBmbG9hdCB2VGV4SW5kZXhfUzA7CmluIGZsb2F0MiB2SW50VGV4dHVyZUNvb3Jkc19TMDsKaW4gaGFsZjQgdmluQ29sb3JfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBEaXN0YW5jZUZpZWxkUGF0aAoJaGFsZjQgb3V0cHV0Q29sb3JfUzA7CglvdXRwdXRDb2xvcl9TMCA9IHZpbkNvbG9yX1MwOwoJZmxvYXQyIHV2ID0gdlRleHR1cmVDb29yZHNfUzA7CgloYWxmNCB0ZXhDb2xvcjsKCXsKCQl0ZXhDb2xvciA9IHNhbXBsZSh1VGV4dHVyZVNhbXBsZXJfMF9TMCwgdXYpLnJycnI7Cgl9CgloYWxmIGRpc3RhbmNlID0gNy45Njg3NSoodGV4Q29sb3IuciAtIDAuNTAxOTYwNzg0MzEpOwoJaGFsZiBhZndpZHRoOwoJYWZ3aWR0aCA9IGFicygwLjY1KmhhbGYoZEZkeCh2SW50VGV4dHVyZUNvb3Jkc19TMC54KSkpOwoJaGFsZiB2YWwgPSBzbW9vdGhzdGVwKC1hZndpZHRoLCBhZndpZHRoLCBkaXN0YW5jZSk7CgloYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KHZhbCk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRDb3ZlcmFnZV9TMDsKCX0KfQoAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAKAAAAaW5Qb3NpdGlvbgAABwAAAGluQ29sb3IADwAAAGluVGV4dHVyZUNvb3JkcwAAAAAA","GEMAAAYAAEHAAAARC4EAAAQWBQAAAAAAAAAQAAAAIBCAAAGQAEAAAAAQAAAABAEQAEAAAAA":"CgAAAExTS1NUAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBpblBvc2l0aW9uOwppbiBoYWxmNCBpbkNvbG9yOwppbiBoYWxmMyBpblNoYWRvd1BhcmFtczsKb3V0IGhhbGYzIHZpblNoYWRvd1BhcmFtc19TMDsKb3V0IGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBSUmVjdFNoYWRvdwoJdmluU2hhZG93UGFyYW1zX1MwID0gaW5TaGFkb3dQYXJhbXM7Cgl2aW5Db2xvcl9TMCA9IGluQ29sb3I7CglmbG9hdDIgX3RtcF8wX2luUG9zaXRpb24gPSBpblBvc2l0aW9uOwoJc2tfUG9zaXRpb24gPSBfdG1wXzBfaW5Qb3NpdGlvbi54eTAxOwp9CgAAAAALAgAAdW5pZm9ybSBzYW1wbGVyMkQgdVRleHR1cmVTYW1wbGVyXzBfUzA7CmluIGhhbGYzIHZpblNoYWRvd1BhcmFtc19TMDsKaW4gaGFsZjQgdmluQ29sb3JfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBSUmVjdFNoYWRvdwoJaGFsZjMgc2hhZG93UGFyYW1zOwoJc2hhZG93UGFyYW1zID0gdmluU2hhZG93UGFyYW1zX1MwOwoJaGFsZjQgb3V0cHV0Q29sb3JfUzA7CglvdXRwdXRDb2xvcl9TMCA9IHZpbkNvbG9yX1MwOwoJaGFsZiBkID0gbGVuZ3RoKHNoYWRvd1BhcmFtcy54eSk7CglmbG9hdDIgdXYgPSBmbG9hdDIoc2hhZG93UGFyYW1zLnogKiAoMS4wIC0gZCksIDAuNSk7CgloYWxmIGZhY3RvciA9IHNhbXBsZSh1VGV4dHVyZVNhbXBsZXJfMF9TMCwgdXYpLjAwMHIuYTsKCWhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoZmFjdG9yKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAoAAABpblBvc2l0aW9uAAAHAAAAaW5Db2xvcgAOAAAAaW5TaGFkb3dQYXJhbXMAAAAAAAA=","HUJAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAQAAAAAEQQGABZAA6IAAAAACAAAAAADUAAAAAAAEAAAAAIDEAAAAAAA":"CgAAAExTS1PlAAAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gZmxvYXQyIGxvY2FsQ29vcmQ7Cm91dCBmbG9hdDIgdmxvY2FsQ29vcmRfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJdmxvY2FsQ29vcmRfUzAgPSBsb2NhbENvb3JkOwoJc2tfUG9zaXRpb24gPSBwb3NpdGlvbi54eTAxOwp9CgAAAAEAAAA3AwAAdW5pZm9ybSBmbG9hdDQgdWlubmVyUmVjdF9TMTsKdW5pZm9ybSBoYWxmMiB1cmFkaXVzUGx1c0hhbGZfUzE7CnVuaWZvcm0gc2FtcGxlckV4dGVybmFsT0VTIHVUZXh0dXJlU2FtcGxlcl8wX1MwOwppbiBmbG9hdDIgdmxvY2FsQ29vcmRfUzA7CmhhbGY0IENpcmN1bGFyUlJlY3RfUzEoaGFsZjQgX2lucHV0KSAKewoJZmxvYXQyIGR4eTAgPSB1aW5uZXJSZWN0X1MxLkxUIC0gc2tfRnJhZ0Nvb3JkLnh5OwoJZmxvYXQyIGR4eTEgPSBza19GcmFnQ29vcmQueHkgLSB1aW5uZXJSZWN0X1MxLlJCOwoJZmxvYXQyIGR4eSA9IG1heChtYXgoZHh5MCwgZHh5MSksIDAuMCk7CgloYWxmIGFscGhhID0gaGFsZihzYXR1cmF0ZSh1cmFkaXVzUGx1c0hhbGZfUzEueCAtIGxlbmd0aChkeHkpKSk7CglyZXR1cm4gX2lucHV0ICogYWxwaGE7Cn0Kdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJaGFsZjQgb3V0cHV0Q29sb3JfUzAgPSBoYWxmNCgxKTsKCWZsb2F0MiB0ZXhDb29yZDsKCXRleENvb3JkID0gdmxvY2FsQ29vcmRfUzA7CglvdXRwdXRDb2xvcl9TMCA9ICgoc2FtcGxlKHVUZXh0dXJlU2FtcGxlcl8wX1MwLCB0ZXhDb29yZCkgKiBoYWxmNCgxKSkpOwoJY29uc3QgaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNCgxKTsKCWhhbGY0IG91dHB1dF9TMTsKCW91dHB1dF9TMSA9IENpcmN1bGFyUlJlY3RfUzEob3V0cHV0Q292ZXJhZ2VfUzApOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dENvbG9yX1MwICogb3V0cHV0X1MxOwoJfQp9CgABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAgAAABwb3NpdGlvbgoAAABsb2NhbENvb3JkAAAAAAAA","HVIACAAAABQAAGAAAQ4AAAAAGQQAARC4GAAAIOCAAD6P7777777777YDAAAAAAAAAAAFIBQU7BTXIAAAAAACAAAAAAQFV5W6JEAAAAAYAAAABQEZ2AKAWAQAABAL6SYKDYAAAACAAAAAAQEGIAAAAACAWTWL3EYAAAADAAAAACADHIJJCYCAAAEAP2LRIPAAAAAIAAAAAAABTALI3F5SOAIAABQAAAAAABTUEUZMBAAAAAH5FYUXQAAAAAAAEAAAAAZMRGOQCQFQEAAAAAAAAAGARL2LXJHAAEAAAAAEAAAABSCQX5FQUHQAAAAAAAAAACAA4AAAABAACAAAACCAYAAAAA":"CgAAAExTS1PrAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMV9jMF9jMF9jMTsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBmbG9hdCBjb3ZlcmFnZTsKaW4gaGFsZjQgY29sb3I7CmluIGZsb2F0MiBsb2NhbENvb3JkOwpmbGF0IG91dCBoYWxmNCB2Y29sb3JfUzA7Cm91dCBmbG9hdCB2Y292ZXJhZ2VfUzA7Cm91dCBmbG9hdDIgdlRyYW5zZm9ybWVkQ29vcmRzXzZfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJZmxvYXQyIHBvc2l0aW9uID0gcG9zaXRpb24ueHk7Cgl2Y29sb3JfUzAgPSBjb2xvcjsKCXZjb3ZlcmFnZV9TMCA9IGNvdmVyYWdlOwoJc2tfUG9zaXRpb24gPSBwb3NpdGlvbi54eTAxOwoJewoJCXZUcmFuc2Zvcm1lZENvb3Jkc182X1MwID0gZmxvYXQzeDIodW1hdHJpeF9TMV9jMF9jMF9jMSkgKiBsb2NhbENvb3JkLnh5MTsKCX0KfQoAAAAAAMMHAAB1bmlmb3JtIGhhbGY0IHVzdGFydF9TMV9jMF9jMF9jMDsKdW5pZm9ybSBoYWxmNCB1ZW5kX1MxX2MwX2MwX2MwOwp1bmlmb3JtIGZsb2F0M3gzIHVtYXRyaXhfUzFfYzBfYzBfYzE7CnVuaWZvcm0gaGFsZjQgdWxlZnRCb3JkZXJDb2xvcl9TMV9jMF9jMDsKdW5pZm9ybSBoYWxmNCB1cmlnaHRCb3JkZXJDb2xvcl9TMV9jMF9jMDsKZmxhdCBpbiBoYWxmNCB2Y29sb3JfUzA7CmluIGZsb2F0IHZjb3ZlcmFnZV9TMDsKaW4gZmxvYXQyIHZUcmFuc2Zvcm1lZENvb3Jkc182X1MwOwpoYWxmNCBTaW5nbGVJbnRlcnZhbENvbG9yaXplcl9TMV9jMF9jMF9jMChoYWxmNCBfaW5wdXQsIGZsb2F0MiBfY29vcmRzKSAKewoJaGFsZjQgX3RtcF8wX2luQ29sb3IgPSBfaW5wdXQ7CglmbG9hdDIgX3RtcF8xX2Nvb3JkcyA9IF9jb29yZHM7CglyZXR1cm4gaGFsZjQobWl4KHVzdGFydF9TMV9jMF9jMF9jMCwgdWVuZF9TMV9jMF9jMF9jMCwgaGFsZihfdG1wXzFfY29vcmRzLngpKSk7Cn0KaGFsZjQgTGluZWFyTGF5b3V0X1MxX2MwX2MwX2MxX2MwKGhhbGY0IF9pbnB1dCkgCnsKCWhhbGY0IF90bXBfMl9pbkNvbG9yID0gX2lucHV0OwoJZmxvYXQyIF90bXBfM19jb29yZHMgPSB2VHJhbnNmb3JtZWRDb29yZHNfNl9TMDsKCXJldHVybiBoYWxmNChoYWxmNChoYWxmKF90bXBfM19jb29yZHMueCkgKyAxZS0wNSwgMS4wLCAwLjAsIDAuMCkpOwp9CmhhbGY0IE1hdHJpeEVmZmVjdF9TMV9jMF9jMF9jMShoYWxmNCBfaW5wdXQpIAp7CglyZXR1cm4gTGluZWFyTGF5b3V0X1MxX2MwX2MwX2MxX2MwKF9pbnB1dCk7Cn0KaGFsZjQgQ2xhbXBlZEdyYWRpZW50X1MxX2MwX2MwKGhhbGY0IF9pbnB1dCkgCnsKCWhhbGY0IF90bXBfNF9pbkNvbG9yID0gX2lucHV0OwoJaGFsZjQgdCA9IE1hdHJpeEVmZmVjdF9TMV9jMF9jMF9jMShfdG1wXzRfaW5Db2xvcik7CgloYWxmNCBvdXRDb2xvcjsKCWlmICghYm9vbChpbnQoMSkpICYmIHQueSA8IDAuMCkgCgl7CgkJb3V0Q29sb3IgPSBoYWxmNCgwLjApOwoJfQoJZWxzZSBpZiAodC54IDwgMC4wKSAKCXsKCQlvdXRDb2xvciA9IHVsZWZ0Qm9yZGVyQ29sb3JfUzFfYzBfYzA7Cgl9CgllbHNlIGlmICh0LnggPiAxLjApIAoJewoJCW91dENvbG9yID0gdXJpZ2h0Qm9yZGVyQ29sb3JfUzFfYzBfYzA7Cgl9CgllbHNlIAoJewoJCW91dENvbG9yID0gU2luZ2xlSW50ZXJ2YWxDb2xvcml6ZXJfUzFfYzBfYzBfYzAoX3RtcF80X2luQ29sb3IsIGZsb2F0MihoYWxmMih0LngsIDAuMCkpKTsKCX0KCXJldHVybiBoYWxmNChvdXRDb2xvcik7Cn0KaGFsZjQgY29sb3JfeGZvcm1fUzFfYzAoZmxvYXQ0IGNvbG9yKSAKewoJY29sb3IucmdiICo9IGNvbG9yLmE7CglyZXR1cm4gaGFsZjQoY29sb3IpOwp9CmhhbGY0IENvbG9yU3BhY2VYZm9ybV9TMV9jMChoYWxmNCBfaW5wdXQpIAp7CglyZXR1cm4gY29sb3JfeGZvcm1fUzFfYzAoQ2xhbXBlZEdyYWRpZW50X1MxX2MwX2MwKF9pbnB1dCkpOwp9CmhhbGY0IERpc2FibGVDb3ZlcmFnZUFzQWxwaGFfUzEoaGFsZjQgX2lucHV0KSAKewoJX2lucHV0ID0gQ29sb3JTcGFjZVhmb3JtX1MxX2MwKF9pbnB1dCk7CgloYWxmNCBfdG1wXzVfaW5Db2xvciA9IF9pbnB1dDsKCXJldHVybiBoYWxmNChfaW5wdXQpOwp9CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBRdWFkUGVyRWRnZUFBR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2Y29sb3JfUzA7CglmbG9hdCBjb3ZlcmFnZSA9IHZjb3ZlcmFnZV9TMDsKCWhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoaGFsZihjb3ZlcmFnZSkpOwoJaGFsZjQgb3V0cHV0X1MxOwoJb3V0cHV0X1MxID0gRGlzYWJsZUNvdmVyYWdlQXNBbHBoYV9TMShvdXRwdXRDb2xvcl9TMCk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gKGhhbGY0KDEuMCkgLSBvdXRwdXRfUzEpICogb3V0cHV0Q292ZXJhZ2VfUzA7Cgl9Cn0KAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAEAAAACAAAAHBvc2l0aW9uCAAAAGNvdmVyYWdlBQAAAGNvbG9yAAAACgAAAGxvY2FsQ29vcmQAAAAAAAA=","HVJAAAAAABIAAGAAAQ4AAAH477776R24EAAAIOBQAD6P7777777777YDAAAAABAAAAAABBAMABAAOAAAABAAAAAAABBAMAAA":"CgAAAExTS1MjAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gaGFsZjQgY29sb3I7CmluIGZsb2F0MiBsb2NhbENvb3JkOwpmbGF0IG91dCBoYWxmNCB2Y29sb3JfUzA7Cm91dCBmbG9hdDIgdmxvY2FsQ29vcmRfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJdmNvbG9yX1MwID0gY29sb3I7Cgl2bG9jYWxDb29yZF9TMCA9IGxvY2FsQ29vcmQ7Cglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cn0KAAAAAADQAQAAdW5pZm9ybSBzYW1wbGVyMkQgdVRleHR1cmVTYW1wbGVyXzBfUzA7CmZsYXQgaW4gaGFsZjQgdmNvbG9yX1MwOwppbiBmbG9hdDIgdmxvY2FsQ29vcmRfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBRdWFkUGVyRWRnZUFBR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2Y29sb3JfUzA7CglmbG9hdDIgdGV4Q29vcmQ7Cgl0ZXhDb29yZCA9IHZsb2NhbENvb3JkX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSAoKHNhbXBsZSh1VGV4dHVyZVNhbXBsZXJfMF9TMCwgdGV4Q29vcmQpICogb3V0cHV0Q29sb3JfUzApKTsKCWNvbnN0IGhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoMSk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRDb3ZlcmFnZV9TMDsKCX0KfQoAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAgAAABwb3NpdGlvbgUAAABjb2xvcgAAAAoAAABsb2NhbENvb3JkAAAAAAAA","HUIAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAAAAAALUAQBAEAQAAAAGQCBAMQACAIAAAAAACQAGAAAAAQAAAAAAAQQGAAAAA":"CgAAAExTS1M2AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBmbG9hdDIgbG9jYWxDb29yZDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cgl7CgkJdlRyYW5zZm9ybWVkQ29vcmRzXzJfUzAgPSBmbG9hdDN4Mih1bWF0cml4X1MxKSAqIGxvY2FsQ29vcmQueHkxOwoJfQp9CgAAAAAAAE0DAAB1bmlmb3JtIGZsb2F0NCB1Y2xhbXBfUzFfYzA7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKdW5pZm9ybSBzYW1wbGVyMkQgdVRleHR1cmVTYW1wbGVyXzBfUzE7CmluIGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKaGFsZjQgVGV4dHVyZUVmZmVjdF9TMV9jMChoYWxmNCBfaW5wdXQpIAp7CglmbG9hdDIgaW5Db29yZCA9IHZUcmFuc2Zvcm1lZENvb3Jkc18yX1MwOwoJZmxvYXQyIHN1YnNldENvb3JkOwoJc3Vic2V0Q29vcmQueCA9IGluQ29vcmQueDsKCXN1YnNldENvb3JkLnkgPSBpbkNvb3JkLnk7CglmbG9hdDIgY2xhbXBlZENvb3JkOwoJY2xhbXBlZENvb3JkID0gY2xhbXAoc3Vic2V0Q29vcmQsIHVjbGFtcF9TMV9jMC54eSwgdWNsYW1wX1MxX2MwLnp3KTsKCWhhbGY0IHRleHR1cmVDb2xvciA9IHNhbXBsZSh1VGV4dHVyZVNhbXBsZXJfMF9TMSwgY2xhbXBlZENvb3JkKTsKCXJldHVybiB0ZXh0dXJlQ29sb3I7Cn0KaGFsZjQgTWF0cml4RWZmZWN0X1MxKGhhbGY0IF9pbnB1dCkgCnsKCXJldHVybiBUZXh0dXJlRWZmZWN0X1MxX2MwKF9pbnB1dCk7Cn0Kdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJaGFsZjQgb3V0cHV0Q29sb3JfUzAgPSBoYWxmNCgxKTsKCWNvbnN0IGhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoMSk7CgloYWxmNCBvdXRwdXRfUzE7CglvdXRwdXRfUzEgPSBNYXRyaXhFZmZlY3RfUzEob3V0cHV0Q29sb3JfUzApOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dF9TMSAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAACAAAACAAAAHBvc2l0aW9uCgAAAGxvY2FsQ29vcmQAAAAAAAA=","DAQAAAAAAABGAABAYAAQAIHCAIAYAQUBAEAAAAAAEAAAAAAAAAAAAAB2AAAAAAACAAAAAEBSAAAAA":"CgAAAExTS1MWAgAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQyIHVBdGxhc1NpemVJbnZfUzA7CmluIGZsb2F0MiBpblBvc2l0aW9uOwppbiBoYWxmNCBpbkNvbG9yOwppbiB1c2hvcnQyIGluVGV4dHVyZUNvb3JkczsKb3V0IGZsb2F0MiB2VGV4dHVyZUNvb3Jkc19TMDsKZmxhdCBvdXQgZmxvYXQgdlRleEluZGV4X1MwOwpvdXQgaGFsZjQgdmluQ29sb3JfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIEJpdG1hcFRleHQKCWludCB0ZXhJZHggPSAwOwoJZmxvYXQyIHVub3JtVGV4Q29vcmRzID0gZmxvYXQyKGluVGV4dHVyZUNvb3Jkcy54LCBpblRleHR1cmVDb29yZHMueSk7Cgl2VGV4dHVyZUNvb3Jkc19TMCA9IHVub3JtVGV4Q29vcmRzICogdUF0bGFzU2l6ZUludl9TMDsKCXZUZXhJbmRleF9TMCA9IGZsb2F0KHRleElkeCk7Cgl2aW5Db2xvcl9TMCA9IGluQ29sb3I7CglmbG9hdDIgX3RtcF8xX2luUG9zaXRpb24gPSBpblBvc2l0aW9uOwoJc2tfUG9zaXRpb24gPSBpblBvc2l0aW9uLnh5MDE7Cn0KAAAAAAAAsQEAAHVuaWZvcm0gc2FtcGxlcjJEIHVUZXh0dXJlU2FtcGxlcl8wX1MwOwppbiBmbG9hdDIgdlRleHR1cmVDb29yZHNfUzA7CmZsYXQgaW4gZmxvYXQgdlRleEluZGV4X1MwOwppbiBoYWxmNCB2aW5Db2xvcl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIEJpdG1hcFRleHQKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2aW5Db2xvcl9TMDsKCWhhbGY0IHRleENvbG9yOwoJewoJCXRleENvbG9yID0gc2FtcGxlKHVUZXh0dXJlU2FtcGxlcl8wX1MwLCB2VGV4dHVyZUNvb3Jkc19TMCkucnJycjsKCX0KCWhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gdGV4Q29sb3I7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRDb3ZlcmFnZV9TMDsKCX0KfQoAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAoAAABpblBvc2l0aW9uAAAHAAAAaW5Db2xvcgAPAAAAaW5UZXh0dXJlQ29vcmRzAAAAAAA=","AYQA5AADQAAAOAEARAFQJAABBADIB7777777777777777777777767YAAAAAAAAAACABZQA6AAAEAAAAAAAIADQAAAAIAAAAAAAIIDA":"CgAAAExTS1PMAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQ0IHVsb2NhbE1hdHJpeF9TMDsKaW4gZmxvYXQyIGluUG9zaXRpb247CmluIGhhbGY0IGluQ29sb3I7CmluIGZsb2F0NCBpbkNpcmNsZUVkZ2U7Cm91dCBmbG9hdDQgdmluQ2lyY2xlRWRnZV9TMDsKb3V0IGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBDaXJjbGVHZW9tZXRyeVByb2Nlc3NvcgoJdmluQ2lyY2xlRWRnZV9TMCA9IGluQ2lyY2xlRWRnZTsKCXZpbkNvbG9yX1MwID0gaW5Db2xvcjsKCWZsb2F0MiBfdG1wXzBfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247CglmbG9hdDIgX3RtcF8xX2luUG9zaXRpb24gPSB1bG9jYWxNYXRyaXhfUzAueHogKiBpblBvc2l0aW9uICsgdWxvY2FsTWF0cml4X1MwLnl3OwoJc2tfUG9zaXRpb24gPSBfdG1wXzBfaW5Qb3NpdGlvbi54eTAxOwp9CgEAAACPAwAAdW5pZm9ybSBmbG9hdDQgdWlubmVyUmVjdF9TMTsKdW5pZm9ybSBoYWxmMiB1cmFkaXVzUGx1c0hhbGZfUzE7CmluIGZsb2F0NCB2aW5DaXJjbGVFZGdlX1MwOwppbiBoYWxmNCB2aW5Db2xvcl9TMDsKaGFsZjQgQ2lyY3VsYXJSUmVjdF9TMShoYWxmNCBfaW5wdXQpIAp7CglmbG9hdDIgZHh5MCA9IHVpbm5lclJlY3RfUzEuTFQgLSBza19GcmFnQ29vcmQueHk7CglmbG9hdDIgZHh5MSA9IHNrX0ZyYWdDb29yZC54eSAtIHVpbm5lclJlY3RfUzEuUkI7CglmbG9hdDIgZHh5ID0gbWF4KG1heChkeHkwLCBkeHkxKSwgMC4wKTsKCWhhbGYgYWxwaGEgPSBoYWxmKHNhdHVyYXRlKHVyYWRpdXNQbHVzSGFsZl9TMS54IC0gbGVuZ3RoKGR4eSkpKTsKCWFscGhhID0gMS4wIC0gYWxwaGE7CglyZXR1cm4gX2lucHV0ICogYWxwaGE7Cn0Kdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIENpcmNsZUdlb21ldHJ5UHJvY2Vzc29yCglmbG9hdDQgY2lyY2xlRWRnZTsKCWNpcmNsZUVkZ2UgPSB2aW5DaXJjbGVFZGdlX1MwOwoJaGFsZjQgb3V0cHV0Q29sb3JfUzA7CglvdXRwdXRDb2xvcl9TMCA9IHZpbkNvbG9yX1MwOwoJZmxvYXQgZCA9IGxlbmd0aChjaXJjbGVFZGdlLnh5KTsKCWhhbGYgZGlzdGFuY2VUb091dGVyRWRnZSA9IGhhbGYoY2lyY2xlRWRnZS56ICogKDEuMCAtIGQpKTsKCWhhbGYgZWRnZUFscGhhID0gc2F0dXJhdGUoZGlzdGFuY2VUb091dGVyRWRnZSk7CgloYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KGVkZ2VBbHBoYSk7CgloYWxmNCBvdXRwdXRfUzE7CglvdXRwdXRfUzEgPSBDaXJjdWxhclJSZWN0X1MxKG91dHB1dENvdmVyYWdlX1MwKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dF9TMTsKCX0KfQoAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAKAAAAaW5Qb3NpdGlvbgAABwAAAGluQ29sb3IADAAAAGluQ2lyY2xlRWRnZQAAAAA=","DASAAAAAQAAWAABAYAAQBYH7777Z6QQBAEAAAAAAEAAAAAAAEBSAAAB2AAAAAAACAAAAAEBSAAAAA":"CgAAAExTS1PVAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQyIHVBdGxhc1NpemVJbnZfUzA7CmluIGZsb2F0MiBpblBvc2l0aW9uOwppbiB1c2hvcnQyIGluVGV4dHVyZUNvb3JkczsKb3V0IGZsb2F0MiB2VGV4dHVyZUNvb3Jkc19TMDsKZmxhdCBvdXQgZmxvYXQgdlRleEluZGV4X1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBCaXRtYXBUZXh0CglpbnQgdGV4SWR4ID0gMDsKCWZsb2F0MiB1bm9ybVRleENvb3JkcyA9IGZsb2F0MihpblRleHR1cmVDb29yZHMueCwgaW5UZXh0dXJlQ29vcmRzLnkpOwoJdlRleHR1cmVDb29yZHNfUzAgPSB1bm9ybVRleENvb3JkcyAqIHVBdGxhc1NpemVJbnZfUzA7Cgl2VGV4SW5kZXhfUzAgPSBmbG9hdCh0ZXhJZHgpOwoJZmxvYXQyIF90bXBfMV9pblBvc2l0aW9uID0gaW5Qb3NpdGlvbjsKCXNrX1Bvc2l0aW9uID0gaW5Qb3NpdGlvbi54eTAxOwp9CgAAAAAAAADgAQAAdW5pZm9ybSBoYWxmNCB1Q29sb3JfUzA7CnVuaWZvcm0gc2FtcGxlcjJEIHVUZXh0dXJlU2FtcGxlcl8wX1MwOwppbiBmbG9hdDIgdlRleHR1cmVDb29yZHNfUzA7CmZsYXQgaW4gZmxvYXQgdlRleEluZGV4X1MwOwp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgQml0bWFwVGV4dAoJaGFsZjQgb3V0cHV0Q29sb3JfUzA7CglvdXRwdXRDb2xvcl9TMCA9IHVDb2xvcl9TMDsKCWhhbGY0IHRleENvbG9yOwoJewoJCXRleENvbG9yID0gc2FtcGxlKHVUZXh0dXJlU2FtcGxlcl8wX1MwLCB2VGV4dHVyZUNvb3Jkc19TMCk7Cgl9CglvdXRwdXRDb2xvcl9TMCA9IG91dHB1dENvbG9yX1MwICogdGV4Q29sb3I7Cgljb25zdCBoYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KDEpOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dENvbG9yX1MwICogb3V0cHV0Q292ZXJhZ2VfUzA7Cgl9Cn0KAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAKAAAAaW5Qb3NpdGlvbgAADwAAAGluVGV4dHVyZUNvb3JkcwAAAAAA","HUIAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAAAAAALUAQMAAAAAAIAAEAAAABJYQAAAAAQAAIAAAAAWCBACAABAAAAANAECAZAAEAAAAAAAAFAAMAAAABAAAAAAABBAM":"CgAAAExTS1M2AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBmbG9hdDIgbG9jYWxDb29yZDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cgl7CgkJdlRyYW5zZm9ybWVkQ29vcmRzXzJfUzAgPSBmbG9hdDN4Mih1bWF0cml4X1MxKSAqIGxvY2FsQ29vcmQueHkxOwoJfQp9CgAAAAAAAC8GAAB1bmlmb3JtIGZsb2F0NCB1Y2xhbXBfUzFfYzBfYzBfYzA7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMV9jMF9jMDsKdW5pZm9ybSBoYWxmMiB1SW5jcmVtZW50X1MxX2MwOwp1bmlmb3JtIGhhbGYyIHVPZmZzZXRzQW5kS2VybmVsX1MxX2MwWzEzXTsKdW5pZm9ybSBmbG9hdDN4MyB1bWF0cml4X1MxOwp1bmlmb3JtIHNhbXBsZXIyRCB1VGV4dHVyZVNhbXBsZXJfMF9TMTsKaW4gZmxvYXQyIHZUcmFuc2Zvcm1lZENvb3Jkc18yX1MwOwpoYWxmNCBUZXh0dXJlRWZmZWN0X1MxX2MwX2MwX2MwKGhhbGY0IF9pbnB1dCwgZmxvYXQyIF9jb29yZHMpIAp7CglmbG9hdDIgaW5Db29yZCA9IF9jb29yZHM7CglmbG9hdDIgc3Vic2V0Q29vcmQ7CglzdWJzZXRDb29yZC54ID0gaW5Db29yZC54OwoJc3Vic2V0Q29vcmQueSA9IGluQ29vcmQueTsKCWZsb2F0MiBjbGFtcGVkQ29vcmQ7CgljbGFtcGVkQ29vcmQueCA9IGNsYW1wKHN1YnNldENvb3JkLngsIHVjbGFtcF9TMV9jMF9jMF9jMC54LCB1Y2xhbXBfUzFfYzBfYzBfYzAueik7CgljbGFtcGVkQ29vcmQueSA9IHN1YnNldENvb3JkLnk7CgloYWxmNCB0ZXh0dXJlQ29sb3IgPSBzYW1wbGUodVRleHR1cmVTYW1wbGVyXzBfUzEsIGNsYW1wZWRDb29yZCk7CglyZXR1cm4gdGV4dHVyZUNvbG9yOwp9CmhhbGY0IE1hdHJpeEVmZmVjdF9TMV9jMF9jMChoYWxmNCBfaW5wdXQsIGZsb2F0MiBfY29vcmRzKSAKewoJcmV0dXJuIFRleHR1cmVFZmZlY3RfUzFfYzBfYzBfYzAoX2lucHV0LCBmbG9hdDN4Mih1bWF0cml4X1MxX2MwX2MwKSAqIF9jb29yZHMueHkxKTsKfQpoYWxmNCBTbW9vdGhfUzFfYzAoaGFsZjQgX2lucHV0LCBmbG9hdDIgY29vcmQsIGhhbGYyIG9mZnNldEFuZEtlcm5lbCkgCnsKCXJldHVybiBNYXRyaXhFZmZlY3RfUzFfYzBfYzAoX2lucHV0LCAoY29vcmQgKyBvZmZzZXRBbmRLZXJuZWwueCAqIHVJbmNyZW1lbnRfUzFfYzApKSAqIG9mZnNldEFuZEtlcm5lbC55Owp9CmhhbGY0IEdhdXNzaWFuQ29udm9sdXRpb25fUzFfYzAoaGFsZjQgX2lucHV0KSAKewoJaGFsZjQgY29sb3IgPSBoYWxmNCgwKTsKCWZsb2F0MiBjb29yZCA9IHZUcmFuc2Zvcm1lZENvb3Jkc18yX1MwOwoJZm9yIChpbnQgaT0wOyBpPDEzOyArK2kpIAoJewoJCWNvbG9yICs9IFNtb290aF9TMV9jMChfaW5wdXQsIGNvb3JkLCB1T2Zmc2V0c0FuZEtlcm5lbF9TMV9jMFtpXSk7Cgl9CglyZXR1cm4gY29sb3I7Cn0KaGFsZjQgTWF0cml4RWZmZWN0X1MxKGhhbGY0IF9pbnB1dCkgCnsKCXJldHVybiBHYXVzc2lhbkNvbnZvbHV0aW9uX1MxX2MwKF9pbnB1dCk7Cn0Kdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJaGFsZjQgb3V0cHV0Q29sb3JfUzAgPSBoYWxmNCgxKTsKCWNvbnN0IGhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoMSk7CgloYWxmNCBvdXRwdXRfUzE7CglvdXRwdXRfUzEgPSBNYXRyaXhFZmZlY3RfUzEob3V0cHV0Q29sb3JfUzApOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dF9TMSAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAgAAABwb3NpdGlvbgoAAABsb2NhbENvb3JkAAAAAAAA","DAQAAAAAAABGAABAYAAQAIHCAIAYAQUBAEAAAAAAEAAAAAAAAAAAAIAD2AAAAAAQAVSWGRIBAAADAAAAACAAAAAAQCGEIQOZLBIQAAAABQAAAAAAAAAAAAFAAMAAAABAAAAAAABBAMAAA":"CgAAAExTS1MWAgAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQyIHVBdGxhc1NpemVJbnZfUzA7CmluIGZsb2F0MiBpblBvc2l0aW9uOwppbiBoYWxmNCBpbkNvbG9yOwppbiB1c2hvcnQyIGluVGV4dHVyZUNvb3JkczsKb3V0IGZsb2F0MiB2VGV4dHVyZUNvb3Jkc19TMDsKZmxhdCBvdXQgZmxvYXQgdlRleEluZGV4X1MwOwpvdXQgaGFsZjQgdmluQ29sb3JfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIEJpdG1hcFRleHQKCWludCB0ZXhJZHggPSAwOwoJZmxvYXQyIHVub3JtVGV4Q29vcmRzID0gZmxvYXQyKGluVGV4dHVyZUNvb3Jkcy54LCBpblRleHR1cmVDb29yZHMueSk7Cgl2VGV4dHVyZUNvb3Jkc19TMCA9IHVub3JtVGV4Q29vcmRzICogdUF0bGFzU2l6ZUludl9TMDsKCXZUZXhJbmRleF9TMCA9IGZsb2F0KHRleElkeCk7Cgl2aW5Db2xvcl9TMCA9IGluQ29sb3I7CglmbG9hdDIgX3RtcF8xX2luUG9zaXRpb24gPSBpblBvc2l0aW9uOwoJc2tfUG9zaXRpb24gPSBpblBvc2l0aW9uLnh5MDE7Cn0KAAABAAAARQUAAGNvbnN0IGludCBrRmlsbEJXX1MxX2MwID0gMDsKY29uc3QgaW50IGtJbnZlcnNlRmlsbEJXX1MxX2MwID0gMjsKY29uc3QgaW50IGtJbnZlcnNlRmlsbEFBX1MxX2MwID0gMzsKdW5pZm9ybSBmbG9hdDQgdXJlY3RVbmlmb3JtX1MxX2MwOwp1bmlmb3JtIHNhbXBsZXIyRCB1VGV4dHVyZVNhbXBsZXJfMF9TMDsKaW4gZmxvYXQyIHZUZXh0dXJlQ29vcmRzX1MwOwpmbGF0IGluIGZsb2F0IHZUZXhJbmRleF9TMDsKaW4gaGFsZjQgdmluQ29sb3JfUzA7CmhhbGY0IFJlY3RfUzFfYzAoaGFsZjQgX2lucHV0KSAKewoJaGFsZjQgX3RtcF8wX2luQ29sb3IgPSBfaW5wdXQ7CgloYWxmIGNvdmVyYWdlOwoJaWYgKGludCgxKSA9PSBrRmlsbEJXX1MxX2MwIHx8IGludCgxKSA9PSBrSW52ZXJzZUZpbGxCV19TMV9jMCkgCgl7CgkJY292ZXJhZ2UgPSBoYWxmKGFsbChncmVhdGVyVGhhbihmbG9hdDQoc2tfRnJhZ0Nvb3JkLnh5LCB1cmVjdFVuaWZvcm1fUzFfYzAuencpLCBmbG9hdDQodXJlY3RVbmlmb3JtX1MxX2MwLnh5LCBza19GcmFnQ29vcmQueHkpKSkpOwoJfQoJZWxzZSAKCXsKCQloYWxmNCBkaXN0czQgPSBzYXR1cmF0ZShoYWxmNCgxLjAsIDEuMCwgLTEuMCwgLTEuMCkgKiBoYWxmNChza19GcmFnQ29vcmQueHl4eSAtIHVyZWN0VW5pZm9ybV9TMV9jMCkpOwoJCWhhbGYyIGRpc3RzMiA9IChkaXN0czQueHkgKyBkaXN0czQuencpIC0gMS4wOwoJCWNvdmVyYWdlID0gZGlzdHMyLnggKiBkaXN0czIueTsKCX0KCWlmIChpbnQoMSkgPT0ga0ludmVyc2VGaWxsQldfUzFfYzAgfHwgaW50KDEpID09IGtJbnZlcnNlRmlsbEFBX1MxX2MwKSAKCXsKCQljb3ZlcmFnZSA9IDEuMCAtIGNvdmVyYWdlOwoJfQoJcmV0dXJuIGhhbGY0KGhhbGY0KGNvdmVyYWdlKSk7Cn0KaGFsZjQgQmxlbmRfUzEoaGFsZjQgX3NyYywgaGFsZjQgX2RzdCkgCnsKCXJldHVybiBibGVuZF9tb2R1bGF0ZShSZWN0X1MxX2MwKF9zcmMpLCBfc3JjKTsKfQp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgQml0bWFwVGV4dAoJaGFsZjQgb3V0cHV0Q29sb3JfUzA7CglvdXRwdXRDb2xvcl9TMCA9IHZpbkNvbG9yX1MwOwoJaGFsZjQgdGV4Q29sb3I7Cgl7CgkJdGV4Q29sb3IgPSBzYW1wbGUodVRleHR1cmVTYW1wbGVyXzBfUzAsIHZUZXh0dXJlQ29vcmRzX1MwKS5ycnJyOwoJfQoJaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSB0ZXhDb2xvcjsKCWhhbGY0IG91dHB1dF9TMTsKCW91dHB1dF9TMSA9IEJsZW5kX1MxKG91dHB1dENvdmVyYWdlX1MwLCBoYWxmNCgxKSk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRfUzE7Cgl9Cn0KAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAKAAAAaW5Qb3NpdGlvbgAABwAAAGluQ29sb3IADwAAAGluVGV4dHVyZUNvb3JkcwAAAAAA","AYQA5AADQAAAOAEARAFQJAABBADIB7777777777777777777777767YAAAAAAAAAACABYQA6AAAEAAAAAAAIADQAAAAIAAAAAAAIIDA":"CgAAAExTS1PMAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQ0IHVsb2NhbE1hdHJpeF9TMDsKaW4gZmxvYXQyIGluUG9zaXRpb247CmluIGhhbGY0IGluQ29sb3I7CmluIGZsb2F0NCBpbkNpcmNsZUVkZ2U7Cm91dCBmbG9hdDQgdmluQ2lyY2xlRWRnZV9TMDsKb3V0IGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBDaXJjbGVHZW9tZXRyeVByb2Nlc3NvcgoJdmluQ2lyY2xlRWRnZV9TMCA9IGluQ2lyY2xlRWRnZTsKCXZpbkNvbG9yX1MwID0gaW5Db2xvcjsKCWZsb2F0MiBfdG1wXzBfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247CglmbG9hdDIgX3RtcF8xX2luUG9zaXRpb24gPSB1bG9jYWxNYXRyaXhfUzAueHogKiBpblBvc2l0aW9uICsgdWxvY2FsTWF0cml4X1MwLnl3OwoJc2tfUG9zaXRpb24gPSBfdG1wXzBfaW5Qb3NpdGlvbi54eTAxOwp9CgEAAAB5AwAAdW5pZm9ybSBmbG9hdDQgdWlubmVyUmVjdF9TMTsKdW5pZm9ybSBoYWxmMiB1cmFkaXVzUGx1c0hhbGZfUzE7CmluIGZsb2F0NCB2aW5DaXJjbGVFZGdlX1MwOwppbiBoYWxmNCB2aW5Db2xvcl9TMDsKaGFsZjQgQ2lyY3VsYXJSUmVjdF9TMShoYWxmNCBfaW5wdXQpIAp7CglmbG9hdDIgZHh5MCA9IHVpbm5lclJlY3RfUzEuTFQgLSBza19GcmFnQ29vcmQueHk7CglmbG9hdDIgZHh5MSA9IHNrX0ZyYWdDb29yZC54eSAtIHVpbm5lclJlY3RfUzEuUkI7CglmbG9hdDIgZHh5ID0gbWF4KG1heChkeHkwLCBkeHkxKSwgMC4wKTsKCWhhbGYgYWxwaGEgPSBoYWxmKHNhdHVyYXRlKHVyYWRpdXNQbHVzSGFsZl9TMS54IC0gbGVuZ3RoKGR4eSkpKTsKCXJldHVybiBfaW5wdXQgKiBhbHBoYTsKfQp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgQ2lyY2xlR2VvbWV0cnlQcm9jZXNzb3IKCWZsb2F0NCBjaXJjbGVFZGdlOwoJY2lyY2xlRWRnZSA9IHZpbkNpcmNsZUVkZ2VfUzA7CgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdmluQ29sb3JfUzA7CglmbG9hdCBkID0gbGVuZ3RoKGNpcmNsZUVkZ2UueHkpOwoJaGFsZiBkaXN0YW5jZVRvT3V0ZXJFZGdlID0gaGFsZihjaXJjbGVFZGdlLnogKiAoMS4wIC0gZCkpOwoJaGFsZiBlZGdlQWxwaGEgPSBzYXR1cmF0ZShkaXN0YW5jZVRvT3V0ZXJFZGdlKTsKCWhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoZWRnZUFscGhhKTsKCWhhbGY0IG91dHB1dF9TMTsKCW91dHB1dF9TMSA9IENpcmN1bGFyUlJlY3RfUzEob3V0cHV0Q292ZXJhZ2VfUzApOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dENvbG9yX1MwICogb3V0cHV0X1MxOwoJfQp9CgAAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAADAAAACgAAAGluUG9zaXRpb24AAAcAAABpbkNvbG9yAAwAAABpbkNpcmNsZUVkZ2UAAAAA","HUIAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAAAAAALUAQBAAAQAAAAGQCBAMQACAAAAAAAACQAGAAAAAQAAAAAAAQQGAAAAA":"CgAAAExTS1M2AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBmbG9hdDIgbG9jYWxDb29yZDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cgl7CgkJdlRyYW5zZm9ybWVkQ29vcmRzXzJfUzAgPSBmbG9hdDN4Mih1bWF0cml4X1MxKSAqIGxvY2FsQ29vcmQueHkxOwoJfQp9CgAAAAAAAHADAAB1bmlmb3JtIGZsb2F0NCB1Y2xhbXBfUzFfYzA7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKdW5pZm9ybSBzYW1wbGVyMkQgdVRleHR1cmVTYW1wbGVyXzBfUzE7CmluIGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKaGFsZjQgVGV4dHVyZUVmZmVjdF9TMV9jMChoYWxmNCBfaW5wdXQpIAp7CglmbG9hdDIgaW5Db29yZCA9IHZUcmFuc2Zvcm1lZENvb3Jkc18yX1MwOwoJZmxvYXQyIHN1YnNldENvb3JkOwoJc3Vic2V0Q29vcmQueCA9IGluQ29vcmQueDsKCXN1YnNldENvb3JkLnkgPSBpbkNvb3JkLnk7CglmbG9hdDIgY2xhbXBlZENvb3JkOwoJY2xhbXBlZENvb3JkLnggPSBjbGFtcChzdWJzZXRDb29yZC54LCB1Y2xhbXBfUzFfYzAueCwgdWNsYW1wX1MxX2MwLnopOwoJY2xhbXBlZENvb3JkLnkgPSBzdWJzZXRDb29yZC55OwoJaGFsZjQgdGV4dHVyZUNvbG9yID0gc2FtcGxlKHVUZXh0dXJlU2FtcGxlcl8wX1MxLCBjbGFtcGVkQ29vcmQpOwoJcmV0dXJuIHRleHR1cmVDb2xvcjsKfQpoYWxmNCBNYXRyaXhFZmZlY3RfUzEoaGFsZjQgX2lucHV0KSAKewoJcmV0dXJuIFRleHR1cmVFZmZlY3RfUzFfYzAoX2lucHV0KTsKfQp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMCA9IGhhbGY0KDEpOwoJY29uc3QgaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNCgxKTsKCWhhbGY0IG91dHB1dF9TMTsKCW91dHB1dF9TMSA9IE1hdHJpeEVmZmVjdF9TMShvdXRwdXRDb2xvcl9TMCk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0X1MxICogb3V0cHV0Q292ZXJhZ2VfUzA7Cgl9Cn0KAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAIAAAAcG9zaXRpb24KAAAAbG9jYWxDb29yZAAAAAAAAA==","HUIAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAAAAAADUAANAAAAAAAAAIAAAABLAIABAAAAABAEGABBAMAAAAAAAAAAAAB2AAAAAAACAAAAAEBSAAAAA":"CgAAAExTS1M8AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMV9jMDsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBmbG9hdDIgbG9jYWxDb29yZDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfM19TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cgl7CgkJdlRyYW5zZm9ybWVkQ29vcmRzXzNfUzAgPSBmbG9hdDN4Mih1bWF0cml4X1MxX2MwKSAqIGxvY2FsQ29vcmQueHkxOwoJfQp9CgAAAAC2AgAAdW5pZm9ybSBmbG9hdDN4MyB1bWF0cml4X1MxX2MwOwp1bmlmb3JtIHNhbXBsZXIyRCB1VGV4dHVyZVNhbXBsZXJfMF9TMTsKaW4gZmxvYXQyIHZUcmFuc2Zvcm1lZENvb3Jkc18zX1MwOwpoYWxmNCBUZXh0dXJlRWZmZWN0X1MxX2MwX2MwKGhhbGY0IF9pbnB1dCkgCnsKCXJldHVybiBzYW1wbGUodVRleHR1cmVTYW1wbGVyXzBfUzEsIHZUcmFuc2Zvcm1lZENvb3Jkc18zX1MwKTsKfQpoYWxmNCBNYXRyaXhFZmZlY3RfUzFfYzAoaGFsZjQgX2lucHV0KSAKewoJcmV0dXJuIFRleHR1cmVFZmZlY3RfUzFfYzBfYzAoX2lucHV0KTsKfQpoYWxmNCBCbGVuZF9TMShoYWxmNCBfc3JjLCBoYWxmNCBfZHN0KSAKewoJcmV0dXJuIGJsZW5kX21vZHVsYXRlKE1hdHJpeEVmZmVjdF9TMV9jMChfc3JjKSwgX3NyYyk7Cn0Kdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJaGFsZjQgb3V0cHV0Q29sb3JfUzAgPSBoYWxmNCgxKTsKCWNvbnN0IGhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoMSk7CgloYWxmNCBvdXRwdXRfUzE7CglvdXRwdXRfUzEgPSBCbGVuZF9TMShvdXRwdXRDb2xvcl9TMCwgaGFsZjQoMSkpOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dF9TMSAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAIAAAAcG9zaXRpb24KAAAAbG9jYWxDb29yZAAAAAAAAA==","FAAQMYAAMAAAEADAAABAEYAAAICIAB5AABQAAAQAMAAAEATAAABAIIGAAEDCBYQCA4AAAAAAEAKPABAAAAAAB2AAAAAAACAAAAAEBSAAAAAAA":"CgAAAExTS1PUCwAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0NCByYWRpaV9zZWxlY3RvcjsKaW4gZmxvYXQ0IGNvcm5lcl9hbmRfcmFkaXVzX291dHNldHM7CmluIGZsb2F0NCBhYV9ibG9hdF9hbmRfY292ZXJhZ2U7CmluIGZsb2F0NCByYWRpaV94OwppbiBmbG9hdDQgcmFkaWlfeTsKaW4gZmxvYXQ0IHNrZXc7CmluIGZsb2F0MiB0cmFuc2xhdGVfYW5kX2xvY2Fscm90YXRlOwppbiBoYWxmNCBjb2xvcjsKZmxhdCBvdXQgaGFsZjQgdmNvbG9yX1MwOwpvdXQgZmxvYXQyIHZhcmNjb29yZF9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgRmlsbFJSZWN0T3A6OlByb2Nlc3NvcgoJdmNvbG9yX1MwID0gY29sb3I7CglmbG9hdCBhYV9ibG9hdF9tdWx0aXBsaWVyID0gMTsKCWZsb2F0MiBjb3JuZXIgPSBjb3JuZXJfYW5kX3JhZGl1c19vdXRzZXRzLnh5OwoJZmxvYXQyIHJhZGl1c19vdXRzZXQgPSBjb3JuZXJfYW5kX3JhZGl1c19vdXRzZXRzLnp3OwoJZmxvYXQyIGFhX2Jsb2F0X2RpcmVjdGlvbiA9IGFhX2Jsb2F0X2FuZF9jb3ZlcmFnZS54eTsKCWZsb2F0IGlzX2xpbmVhcl9jb3ZlcmFnZSA9IGFhX2Jsb2F0X2FuZF9jb3ZlcmFnZS53OwoJZmxvYXQyIHBpeGVsbGVuZ3RoID0gaW52ZXJzZXNxcnQoZmxvYXQyKGRvdChza2V3Lnh6LCBza2V3Lnh6KSwgZG90KHNrZXcueXcsIHNrZXcueXcpKSk7CglmbG9hdDQgbm9ybWFsaXplZF9heGlzX2RpcnMgPSBza2V3ICogcGl4ZWxsZW5ndGgueHl4eTsKCWZsb2F0MiBheGlzd2lkdGhzID0gKGFicyhub3JtYWxpemVkX2F4aXNfZGlycy54eSkgKyBhYnMobm9ybWFsaXplZF9heGlzX2RpcnMuencpKTsKCWZsb2F0MiBhYV9ibG9hdHJhZGl1cyA9IGF4aXN3aWR0aHMgKiBwaXhlbGxlbmd0aCAqIC41OwoJZmxvYXQ0IHJhZGlpX2FuZF9uZWlnaGJvcnMgPSByYWRpaV9zZWxlY3RvciogZmxvYXQ0eDQocmFkaWlfeCwgcmFkaWlfeSwgcmFkaWlfeC55eHd6LCByYWRpaV95Lnd6eXgpOwoJZmxvYXQyIHJhZGlpID0gcmFkaWlfYW5kX25laWdoYm9ycy54eTsKCWZsb2F0MiBuZWlnaGJvcl9yYWRpaSA9IHJhZGlpX2FuZF9uZWlnaGJvcnMuenc7CglmbG9hdCBjb3ZlcmFnZV9tdWx0aXBsaWVyID0gMTsKCWlmIChhbnkoZ3JlYXRlclRoYW4oYWFfYmxvYXRyYWRpdXMsIGZsb2F0MigxKSkpKSAKCXsKCQljb3JuZXIgPSBtYXgoYWJzKGNvcm5lciksIGFhX2Jsb2F0cmFkaXVzKSAqIHNpZ24oY29ybmVyKTsKCQljb3ZlcmFnZV9tdWx0aXBsaWVyID0gMSAvIChtYXgoYWFfYmxvYXRyYWRpdXMueCwgMSkgKiBtYXgoYWFfYmxvYXRyYWRpdXMueSwgMSkpOwoJCXJhZGlpID0gZmxvYXQyKDApOwoJfQoJZmxvYXQgY292ZXJhZ2UgPSBhYV9ibG9hdF9hbmRfY292ZXJhZ2UuejsKCWlmIChhbnkobGVzc1RoYW4ocmFkaWksIGFhX2Jsb2F0cmFkaXVzICogMS41KSkpIAoJewoJCXJhZGlpID0gZmxvYXQyKDApOwoJCWFhX2Jsb2F0X2RpcmVjdGlvbiA9IHNpZ24oY29ybmVyKTsKCQlpZiAoY292ZXJhZ2UgPiAuNSkgCgkJewoJCQlhYV9ibG9hdF9kaXJlY3Rpb24gPSAtYWFfYmxvYXRfZGlyZWN0aW9uOwoJCX0KCQlpc19saW5lYXJfY292ZXJhZ2UgPSAxOwoJfQoJZWxzZSAKCXsKCQlyYWRpaSA9IGNsYW1wKHJhZGlpLCBwaXhlbGxlbmd0aCAqIDEuNSwgMiAtIHBpeGVsbGVuZ3RoICogMS41KTsKCQluZWlnaGJvcl9yYWRpaSA9IGNsYW1wKG5laWdoYm9yX3JhZGlpLCBwaXhlbGxlbmd0aCAqIDEuNSwgMiAtIHBpeGVsbGVuZ3RoICogMS41KTsKCQlmbG9hdDIgc3BhY2luZyA9IDIgLSByYWRpaSAtIG5laWdoYm9yX3JhZGlpOwoJCWZsb2F0MiBleHRyYV9wYWQgPSBtYXgocGl4ZWxsZW5ndGggKiAuMDYyNSAtIHNwYWNpbmcsIGZsb2F0MigwKSk7CgkJcmFkaWkgLT0gZXh0cmFfcGFkICogLjU7Cgl9CglmbG9hdDIgYWFfb3V0c2V0ID0gYWFfYmxvYXRfZGlyZWN0aW9uICogYWFfYmxvYXRyYWRpdXMgKiBhYV9ibG9hdF9tdWx0aXBsaWVyOwoJZmxvYXQyIHZlcnRleHBvcyA9IGNvcm5lciArIHJhZGl1c19vdXRzZXQgKiByYWRpaSArIGFhX291dHNldDsKCWlmIChjb3ZlcmFnZSA+IC41KSAKCXsKCQlpZiAoYWFfYmxvYXRfZGlyZWN0aW9uLnggIT0gMCAmJiB2ZXJ0ZXhwb3MueCAqIGNvcm5lci54IDwgMCkgCgkJewoJCQlmbG9hdCBiYWNrc2V0ID0gYWJzKHZlcnRleHBvcy54KTsKCQkJdmVydGV4cG9zLnggPSAwOwoJCQl2ZXJ0ZXhwb3MueSArPSBiYWNrc2V0ICogc2lnbihjb3JuZXIueSkgKiBwaXhlbGxlbmd0aC55L3BpeGVsbGVuZ3RoLng7CgkJCWNvdmVyYWdlID0gKGNvdmVyYWdlIC0gLjUpICogYWJzKGNvcm5lci54KSAvIChhYnMoY29ybmVyLngpICsgYmFja3NldCkgKyAuNTsKCQl9CgkJaWYgKGFhX2Jsb2F0X2RpcmVjdGlvbi55ICE9IDAgJiYgdmVydGV4cG9zLnkgKiBjb3JuZXIueSA8IDApIAoJCXsKCQkJZmxvYXQgYmFja3NldCA9IGFicyh2ZXJ0ZXhwb3MueSk7CgkJCXZlcnRleHBvcy55ID0gMDsKCQkJdmVydGV4cG9zLnggKz0gYmFja3NldCAqIHNpZ24oY29ybmVyLngpICogcGl4ZWxsZW5ndGgueC9waXhlbGxlbmd0aC55OwoJCQljb3ZlcmFnZSA9IChjb3ZlcmFnZSAtIC41KSAqIGFicyhjb3JuZXIueSkgLyAoYWJzKGNvcm5lci55KSArIGJhY2tzZXQpICsgLjU7CgkJfQoJfQoJZmxvYXQyeDIgc2tld21hdHJpeCA9IGZsb2F0MngyKHNrZXcueHksIHNrZXcuencpOwoJZmxvYXQyIGRldmNvb3JkID0gdmVydGV4cG9zICogc2tld21hdHJpeCArIHRyYW5zbGF0ZV9hbmRfbG9jYWxyb3RhdGUueHk7CglpZiAoMCAhPSBpc19saW5lYXJfY292ZXJhZ2UpIAoJewoJCXZhcmNjb29yZF9TMC54eSA9IGZsb2F0MigwLCBjb3ZlcmFnZSAqIGNvdmVyYWdlX211bHRpcGxpZXIpOwoJfQoJZWxzZSAKCXsKCQlmbG9hdDIgYXJjY29vcmQgPSAxIC0gYWJzKHJhZGl1c19vdXRzZXQpICsgYWFfb3V0c2V0L3JhZGlpICogY29ybmVyOwoJCXZhcmNjb29yZF9TMC54eSA9IGZsb2F0MihhcmNjb29yZC54KzEsIGFyY2Nvb3JkLnkpOwoJfQoJc2tfUG9zaXRpb24gPSBkZXZjb29yZC54eTAxOwp9CgEAAACbBAAAdW5pZm9ybSBmbG9hdDQgdWlubmVyUmVjdF9TMTsKdW5pZm9ybSBmbG9hdDIgdWludlJhZGlpWFlfUzE7CmZsYXQgaW4gaGFsZjQgdmNvbG9yX1MwOwppbiBmbG9hdDIgdmFyY2Nvb3JkX1MwOwpoYWxmNCBFbGxpcHRpY2FsUlJlY3RfUzEoaGFsZjQgX2lucHV0KSAKewoJZmxvYXQyIGR4eTAgPSB1aW5uZXJSZWN0X1MxLkxUIC0gc2tfRnJhZ0Nvb3JkLnh5OwoJZmxvYXQyIGR4eTEgPSBza19GcmFnQ29vcmQueHkgLSB1aW5uZXJSZWN0X1MxLlJCOwoJZmxvYXQyIGR4eSA9IG1heChtYXgoZHh5MCwgZHh5MSksIDAuMCk7CglmbG9hdDIgWiA9IGR4eSAqIHVpbnZSYWRpaVhZX1MxLnh5OwoJaGFsZiBpbXBsaWNpdCA9IGhhbGYoZG90KFosIGR4eSkgLSAxLjApOwoJaGFsZiBncmFkX2RvdCA9IGhhbGYoNC4wICogZG90KFosIFopKTsKCWdyYWRfZG90ID0gbWF4KGdyYWRfZG90LCAxLjBlLTQpOwoJaGFsZiBhcHByb3hfZGlzdCA9IGltcGxpY2l0ICogaGFsZihpbnZlcnNlc3FydChncmFkX2RvdCkpOwoJaGFsZiBhbHBoYSA9IGNsYW1wKDAuNSArIGFwcHJveF9kaXN0LCAwLjAsIDEuMCk7CglyZXR1cm4gX2lucHV0ICogYWxwaGE7Cn0Kdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIEZpbGxSUmVjdE9wOjpQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2Y29sb3JfUzA7CglmbG9hdCB4X3BsdXNfMT12YXJjY29vcmRfUzAueCwgeT12YXJjY29vcmRfUzAueTsKCWhhbGYgY292ZXJhZ2U7CglpZiAoMCA9PSB4X3BsdXNfMSkgCgl7CgkJY292ZXJhZ2UgPSBoYWxmKHkpOwoJfQoJZWxzZSAKCXsKCQlmbG9hdCBmbiA9IHhfcGx1c18xICogKHhfcGx1c18xIC0gMik7CgkJZm4gPSBmbWEoeSx5LCBmbik7CgkJZmxvYXQgZm53aWR0aCA9IGZ3aWR0aChmbik7CgkJY292ZXJhZ2UgPSAuNSAtIGhhbGYoZm4vZm53aWR0aCk7CgkJY292ZXJhZ2UgPSBjbGFtcChjb3ZlcmFnZSwgMCwgMSk7Cgl9CgloYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KGNvdmVyYWdlKTsKCWhhbGY0IG91dHB1dF9TMTsKCW91dHB1dF9TMSA9IEVsbGlwdGljYWxSUmVjdF9TMShvdXRwdXRDb3ZlcmFnZV9TMCk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRfUzE7Cgl9Cn0KAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAIAAAADgAAAHJhZGlpX3NlbGVjdG9yAAAZAAAAY29ybmVyX2FuZF9yYWRpdXNfb3V0c2V0cwAAABUAAABhYV9ibG9hdF9hbmRfY292ZXJhZ2UAAAAHAAAAcmFkaWlfeAAHAAAAcmFkaWlfeQAEAAAAc2tldxkAAAB0cmFuc2xhdGVfYW5kX2xvY2Fscm90YXRlAAAABQAAAGNvbG9yAAAAAAAAAA==","HUQAAAAAAAMAADAAAIOAAAH677776IZOCAAP577777777777777777YBAAAAAAAAAAAHEADBAAAAAAIAAAAAAOQAAAAAAAQAAAABAMQAAAAAA":"CgAAAExTS1PUAAAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gaGFsZjQgY29sb3I7CmZsYXQgb3V0IGhhbGY0IHZjb2xvcl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgl2Y29sb3JfUzAgPSBjb2xvcjsKCXNrX1Bvc2l0aW9uID0gcG9zaXRpb24ueHkwMTsKfQoBAAAA+wIAAHVuaWZvcm0gZmxvYXQ0IHVpbm5lclJlY3RfUzE7CnVuaWZvcm0gaGFsZjIgdXJhZGl1c1BsdXNIYWxmX1MxOwpmbGF0IGluIGhhbGY0IHZjb2xvcl9TMDsKaGFsZjQgQ2lyY3VsYXJSUmVjdF9TMShoYWxmNCBfaW5wdXQpIAp7CglmbG9hdCBkeDAgPSB1aW5uZXJSZWN0X1MxLkwgLSBza19GcmFnQ29vcmQueDsKCWZsb2F0MiBkeHkxID0gc2tfRnJhZ0Nvb3JkLnh5IC0gdWlubmVyUmVjdF9TMS5SQjsKCWZsb2F0MiBkeHkgPSBtYXgoZmxvYXQyKG1heChkeDAsIGR4eTEueCksIGR4eTEueSksIDAuMCk7CgloYWxmIHRvcEFscGhhID0gaGFsZihzYXR1cmF0ZShza19GcmFnQ29vcmQueSAtIHVpbm5lclJlY3RfUzEuVCkpOwoJaGFsZiBhbHBoYSA9IHRvcEFscGhhICogaGFsZihzYXR1cmF0ZSh1cmFkaXVzUGx1c0hhbGZfUzEueCAtIGxlbmd0aChkeHkpKSk7CglyZXR1cm4gX2lucHV0ICogYWxwaGE7Cn0Kdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJaGFsZjQgb3V0cHV0Q29sb3JfUzA7CglvdXRwdXRDb2xvcl9TMCA9IHZjb2xvcl9TMDsKCWNvbnN0IGhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoMSk7CgloYWxmNCBvdXRwdXRfUzE7CglvdXRwdXRfUzEgPSBDaXJjdWxhclJSZWN0X1MxKG91dHB1dENvdmVyYWdlX1MwKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dF9TMTsKCX0KfQoAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAIAAAAcG9zaXRpb24FAAAAY29sb3IAAAAAAAAA","FAAQMYAAMAAAEADAAABAEYAAAICIAB5AABQAAAQAMAAAEATAAABAIIGAAEDCBYQCA4AAAAAAEADZABYAAAIAAAAAACQAGAAAAAQAAAAAAAQQG":"CgAAAExTS1PUCwAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0NCByYWRpaV9zZWxlY3RvcjsKaW4gZmxvYXQ0IGNvcm5lcl9hbmRfcmFkaXVzX291dHNldHM7CmluIGZsb2F0NCBhYV9ibG9hdF9hbmRfY292ZXJhZ2U7CmluIGZsb2F0NCByYWRpaV94OwppbiBmbG9hdDQgcmFkaWlfeTsKaW4gZmxvYXQ0IHNrZXc7CmluIGZsb2F0MiB0cmFuc2xhdGVfYW5kX2xvY2Fscm90YXRlOwppbiBoYWxmNCBjb2xvcjsKZmxhdCBvdXQgaGFsZjQgdmNvbG9yX1MwOwpvdXQgZmxvYXQyIHZhcmNjb29yZF9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgRmlsbFJSZWN0T3A6OlByb2Nlc3NvcgoJdmNvbG9yX1MwID0gY29sb3I7CglmbG9hdCBhYV9ibG9hdF9tdWx0aXBsaWVyID0gMTsKCWZsb2F0MiBjb3JuZXIgPSBjb3JuZXJfYW5kX3JhZGl1c19vdXRzZXRzLnh5OwoJZmxvYXQyIHJhZGl1c19vdXRzZXQgPSBjb3JuZXJfYW5kX3JhZGl1c19vdXRzZXRzLnp3OwoJZmxvYXQyIGFhX2Jsb2F0X2RpcmVjdGlvbiA9IGFhX2Jsb2F0X2FuZF9jb3ZlcmFnZS54eTsKCWZsb2F0IGlzX2xpbmVhcl9jb3ZlcmFnZSA9IGFhX2Jsb2F0X2FuZF9jb3ZlcmFnZS53OwoJZmxvYXQyIHBpeGVsbGVuZ3RoID0gaW52ZXJzZXNxcnQoZmxvYXQyKGRvdChza2V3Lnh6LCBza2V3Lnh6KSwgZG90KHNrZXcueXcsIHNrZXcueXcpKSk7CglmbG9hdDQgbm9ybWFsaXplZF9heGlzX2RpcnMgPSBza2V3ICogcGl4ZWxsZW5ndGgueHl4eTsKCWZsb2F0MiBheGlzd2lkdGhzID0gKGFicyhub3JtYWxpemVkX2F4aXNfZGlycy54eSkgKyBhYnMobm9ybWFsaXplZF9heGlzX2RpcnMuencpKTsKCWZsb2F0MiBhYV9ibG9hdHJhZGl1cyA9IGF4aXN3aWR0aHMgKiBwaXhlbGxlbmd0aCAqIC41OwoJZmxvYXQ0IHJhZGlpX2FuZF9uZWlnaGJvcnMgPSByYWRpaV9zZWxlY3RvciogZmxvYXQ0eDQocmFkaWlfeCwgcmFkaWlfeSwgcmFkaWlfeC55eHd6LCByYWRpaV95Lnd6eXgpOwoJZmxvYXQyIHJhZGlpID0gcmFkaWlfYW5kX25laWdoYm9ycy54eTsKCWZsb2F0MiBuZWlnaGJvcl9yYWRpaSA9IHJhZGlpX2FuZF9uZWlnaGJvcnMuenc7CglmbG9hdCBjb3ZlcmFnZV9tdWx0aXBsaWVyID0gMTsKCWlmIChhbnkoZ3JlYXRlclRoYW4oYWFfYmxvYXRyYWRpdXMsIGZsb2F0MigxKSkpKSAKCXsKCQljb3JuZXIgPSBtYXgoYWJzKGNvcm5lciksIGFhX2Jsb2F0cmFkaXVzKSAqIHNpZ24oY29ybmVyKTsKCQljb3ZlcmFnZV9tdWx0aXBsaWVyID0gMSAvIChtYXgoYWFfYmxvYXRyYWRpdXMueCwgMSkgKiBtYXgoYWFfYmxvYXRyYWRpdXMueSwgMSkpOwoJCXJhZGlpID0gZmxvYXQyKDApOwoJfQoJZmxvYXQgY292ZXJhZ2UgPSBhYV9ibG9hdF9hbmRfY292ZXJhZ2UuejsKCWlmIChhbnkobGVzc1RoYW4ocmFkaWksIGFhX2Jsb2F0cmFkaXVzICogMS41KSkpIAoJewoJCXJhZGlpID0gZmxvYXQyKDApOwoJCWFhX2Jsb2F0X2RpcmVjdGlvbiA9IHNpZ24oY29ybmVyKTsKCQlpZiAoY292ZXJhZ2UgPiAuNSkgCgkJewoJCQlhYV9ibG9hdF9kaXJlY3Rpb24gPSAtYWFfYmxvYXRfZGlyZWN0aW9uOwoJCX0KCQlpc19saW5lYXJfY292ZXJhZ2UgPSAxOwoJfQoJZWxzZSAKCXsKCQlyYWRpaSA9IGNsYW1wKHJhZGlpLCBwaXhlbGxlbmd0aCAqIDEuNSwgMiAtIHBpeGVsbGVuZ3RoICogMS41KTsKCQluZWlnaGJvcl9yYWRpaSA9IGNsYW1wKG5laWdoYm9yX3JhZGlpLCBwaXhlbGxlbmd0aCAqIDEuNSwgMiAtIHBpeGVsbGVuZ3RoICogMS41KTsKCQlmbG9hdDIgc3BhY2luZyA9IDIgLSByYWRpaSAtIG5laWdoYm9yX3JhZGlpOwoJCWZsb2F0MiBleHRyYV9wYWQgPSBtYXgocGl4ZWxsZW5ndGggKiAuMDYyNSAtIHNwYWNpbmcsIGZsb2F0MigwKSk7CgkJcmFkaWkgLT0gZXh0cmFfcGFkICogLjU7Cgl9CglmbG9hdDIgYWFfb3V0c2V0ID0gYWFfYmxvYXRfZGlyZWN0aW9uICogYWFfYmxvYXRyYWRpdXMgKiBhYV9ibG9hdF9tdWx0aXBsaWVyOwoJZmxvYXQyIHZlcnRleHBvcyA9IGNvcm5lciArIHJhZGl1c19vdXRzZXQgKiByYWRpaSArIGFhX291dHNldDsKCWlmIChjb3ZlcmFnZSA+IC41KSAKCXsKCQlpZiAoYWFfYmxvYXRfZGlyZWN0aW9uLnggIT0gMCAmJiB2ZXJ0ZXhwb3MueCAqIGNvcm5lci54IDwgMCkgCgkJewoJCQlmbG9hdCBiYWNrc2V0ID0gYWJzKHZlcnRleHBvcy54KTsKCQkJdmVydGV4cG9zLnggPSAwOwoJCQl2ZXJ0ZXhwb3MueSArPSBiYWNrc2V0ICogc2lnbihjb3JuZXIueSkgKiBwaXhlbGxlbmd0aC55L3BpeGVsbGVuZ3RoLng7CgkJCWNvdmVyYWdlID0gKGNvdmVyYWdlIC0gLjUpICogYWJzKGNvcm5lci54KSAvIChhYnMoY29ybmVyLngpICsgYmFja3NldCkgKyAuNTsKCQl9CgkJaWYgKGFhX2Jsb2F0X2RpcmVjdGlvbi55ICE9IDAgJiYgdmVydGV4cG9zLnkgKiBjb3JuZXIueSA8IDApIAoJCXsKCQkJZmxvYXQgYmFja3NldCA9IGFicyh2ZXJ0ZXhwb3MueSk7CgkJCXZlcnRleHBvcy55ID0gMDsKCQkJdmVydGV4cG9zLnggKz0gYmFja3NldCAqIHNpZ24oY29ybmVyLngpICogcGl4ZWxsZW5ndGgueC9waXhlbGxlbmd0aC55OwoJCQljb3ZlcmFnZSA9IChjb3ZlcmFnZSAtIC41KSAqIGFicyhjb3JuZXIueSkgLyAoYWJzKGNvcm5lci55KSArIGJhY2tzZXQpICsgLjU7CgkJfQoJfQoJZmxvYXQyeDIgc2tld21hdHJpeCA9IGZsb2F0MngyKHNrZXcueHksIHNrZXcuencpOwoJZmxvYXQyIGRldmNvb3JkID0gdmVydGV4cG9zICogc2tld21hdHJpeCArIHRyYW5zbGF0ZV9hbmRfbG9jYWxyb3RhdGUueHk7CglpZiAoMCAhPSBpc19saW5lYXJfY292ZXJhZ2UpIAoJewoJCXZhcmNjb29yZF9TMC54eSA9IGZsb2F0MigwLCBjb3ZlcmFnZSAqIGNvdmVyYWdlX211bHRpcGxpZXIpOwoJfQoJZWxzZSAKCXsKCQlmbG9hdDIgYXJjY29vcmQgPSAxIC0gYWJzKHJhZGl1c19vdXRzZXQpICsgYWFfb3V0c2V0L3JhZGlpICogY29ybmVyOwoJCXZhcmNjb29yZF9TMC54eSA9IGZsb2F0MihhcmNjb29yZC54KzEsIGFyY2Nvb3JkLnkpOwoJfQoJc2tfUG9zaXRpb24gPSBkZXZjb29yZC54eTAxOwp9CgEAAADUAwAAdW5pZm9ybSBmbG9hdDQgdWlubmVyUmVjdF9TMTsKdW5pZm9ybSBoYWxmMiB1cmFkaXVzUGx1c0hhbGZfUzE7CmZsYXQgaW4gaGFsZjQgdmNvbG9yX1MwOwppbiBmbG9hdDIgdmFyY2Nvb3JkX1MwOwpoYWxmNCBDaXJjdWxhclJSZWN0X1MxKGhhbGY0IF9pbnB1dCkgCnsKCWZsb2F0MiBkeHkwID0gdWlubmVyUmVjdF9TMS5MVCAtIHNrX0ZyYWdDb29yZC54eTsKCWZsb2F0MiBkeHkxID0gc2tfRnJhZ0Nvb3JkLnh5IC0gdWlubmVyUmVjdF9TMS5SQjsKCWZsb2F0MiBkeHkgPSBtYXgobWF4KGR4eTAsIGR4eTEpLCAwLjApOwoJaGFsZiBhbHBoYSA9IGhhbGYoc2F0dXJhdGUodXJhZGl1c1BsdXNIYWxmX1MxLnggLSBsZW5ndGgoZHh5KSkpOwoJcmV0dXJuIF9pbnB1dCAqIGFscGhhOwp9CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBGaWxsUlJlY3RPcDo6UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdmNvbG9yX1MwOwoJZmxvYXQgeF9wbHVzXzE9dmFyY2Nvb3JkX1MwLngsIHk9dmFyY2Nvb3JkX1MwLnk7CgloYWxmIGNvdmVyYWdlOwoJaWYgKDAgPT0geF9wbHVzXzEpIAoJewoJCWNvdmVyYWdlID0gaGFsZih5KTsKCX0KCWVsc2UgCgl7CgkJZmxvYXQgZm4gPSB4X3BsdXNfMSAqICh4X3BsdXNfMSAtIDIpOwoJCWZuID0gZm1hKHkseSwgZm4pOwoJCWZsb2F0IGZud2lkdGggPSBmd2lkdGgoZm4pOwoJCWNvdmVyYWdlID0gLjUgLSBoYWxmKGZuL2Zud2lkdGgpOwoJCWNvdmVyYWdlID0gY2xhbXAoY292ZXJhZ2UsIDAsIDEpOwoJfQoJaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNChjb3ZlcmFnZSk7CgloYWxmNCBvdXRwdXRfUzE7CglvdXRwdXRfUzEgPSBDaXJjdWxhclJSZWN0X1MxKG91dHB1dENvdmVyYWdlX1MwKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dF9TMTsKCX0KfQoBAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAACAAAAA4AAAByYWRpaV9zZWxlY3RvcgAAGQAAAGNvcm5lcl9hbmRfcmFkaXVzX291dHNldHMAAAAVAAAAYWFfYmxvYXRfYW5kX2NvdmVyYWdlAAAABwAAAHJhZGlpX3gABwAAAHJhZGlpX3kABAAAAHNrZXcZAAAAdHJhbnNsYXRlX2FuZF9sb2NhbHJvdGF0ZQAAAAUAAABjb2xvcgAAAAAAAAA=","HVIAAAAAABIAAGAAAQ4AAAH477776R24EAAAIOBQAD6P7777777777YDAAAAAAAAAAAFQBQU7BTXIAAAAAAAAAACAAAAAVQEAAQAAAAAQCDAEQQGAAAAAAAAAAAA4IAPAAACAAAAAAAEABYAAAAEAAAAAAAEEBQA":"CgAAAExTS1N6AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMV9jMDsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBoYWxmNCBjb2xvcjsKaW4gZmxvYXQyIGxvY2FsQ29vcmQ7CmZsYXQgb3V0IGhhbGY0IHZjb2xvcl9TMDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfM19TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgl2Y29sb3JfUzAgPSBjb2xvcjsKCXNrX1Bvc2l0aW9uID0gcG9zaXRpb24ueHkwMTsKCXsKCQl2VHJhbnNmb3JtZWRDb29yZHNfM19TMCA9IGZsb2F0M3gyKHVtYXRyaXhfUzFfYzApICogbG9jYWxDb29yZC54eTE7Cgl9Cn0KAAABAAAArAQAAHVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMV9jMDsKdW5pZm9ybSBmbG9hdDQgdWlubmVyUmVjdF9TMjsKdW5pZm9ybSBoYWxmMiB1cmFkaXVzUGx1c0hhbGZfUzI7CnVuaWZvcm0gc2FtcGxlckV4dGVybmFsT0VTIHVUZXh0dXJlU2FtcGxlcl8wX1MxOwpmbGF0IGluIGhhbGY0IHZjb2xvcl9TMDsKaW4gZmxvYXQyIHZUcmFuc2Zvcm1lZENvb3Jkc18zX1MwOwpoYWxmNCBUZXh0dXJlRWZmZWN0X1MxX2MwX2MwKGhhbGY0IF9pbnB1dCkgCnsKCXJldHVybiBzYW1wbGUodVRleHR1cmVTYW1wbGVyXzBfUzEsIHZUcmFuc2Zvcm1lZENvb3Jkc18zX1MwKTsKfQpoYWxmNCBNYXRyaXhFZmZlY3RfUzFfYzAoaGFsZjQgX2lucHV0KSAKewoJcmV0dXJuIFRleHR1cmVFZmZlY3RfUzFfYzBfYzAoX2lucHV0KTsKfQpoYWxmNCBEaXNhYmxlQ292ZXJhZ2VBc0FscGhhX1MxKGhhbGY0IF9pbnB1dCkgCnsKCV9pbnB1dCA9IE1hdHJpeEVmZmVjdF9TMV9jMChfaW5wdXQpOwoJaGFsZjQgX3RtcF8wX2luQ29sb3IgPSBfaW5wdXQ7CglyZXR1cm4gaGFsZjQoX2lucHV0KTsKfQpoYWxmNCBDaXJjdWxhclJSZWN0X1MyKGhhbGY0IF9pbnB1dCkgCnsKCWZsb2F0MiBkeHkwID0gdWlubmVyUmVjdF9TMi5MVCAtIHNrX0ZyYWdDb29yZC54eTsKCWZsb2F0MiBkeHkxID0gc2tfRnJhZ0Nvb3JkLnh5IC0gdWlubmVyUmVjdF9TMi5SQjsKCWZsb2F0MiBkeHkgPSBtYXgobWF4KGR4eTAsIGR4eTEpLCAwLjApOwoJaGFsZiBhbHBoYSA9IGhhbGYoc2F0dXJhdGUodXJhZGl1c1BsdXNIYWxmX1MyLnggLSBsZW5ndGgoZHh5KSkpOwoJcmV0dXJuIF9pbnB1dCAqIGFscGhhOwp9CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBRdWFkUGVyRWRnZUFBR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2Y29sb3JfUzA7Cgljb25zdCBoYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KDEpOwoJaGFsZjQgb3V0cHV0X1MxOwoJb3V0cHV0X1MxID0gRGlzYWJsZUNvdmVyYWdlQXNBbHBoYV9TMShvdXRwdXRDb2xvcl9TMCk7CgloYWxmNCBvdXRwdXRfUzI7CglvdXRwdXRfUzIgPSBDaXJjdWxhclJSZWN0X1MyKG91dHB1dENvdmVyYWdlX1MwKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRfUzEgKiBvdXRwdXRfUzI7Cgl9Cn0KAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAIAAAAcG9zaXRpb24FAAAAY29sb3IAAAAKAAAAbG9jYWxDb29yZAAAAAAAAA==","HVIAAAAAABIAAGAAAQ4AAAH477776R24EAAAIOBQAD6P7777777777YDAAAAAAAAAAAGIBIAAABAAAAANAEAAAAAAAAAAAAAABAAOAAAABAAAAAAABBAMAAAAA":"CgAAAExTS1N0AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBoYWxmNCBjb2xvcjsKaW4gZmxvYXQyIGxvY2FsQ29vcmQ7CmZsYXQgb3V0IGhhbGY0IHZjb2xvcl9TMDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgl2Y29sb3JfUzAgPSBjb2xvcjsKCXNrX1Bvc2l0aW9uID0gcG9zaXRpb24ueHkwMTsKCXsKCQl2VHJhbnNmb3JtZWRDb29yZHNfMl9TMCA9IGZsb2F0M3gyKHVtYXRyaXhfUzEpICogbG9jYWxDb29yZC54eTE7Cgl9Cn0KAAAAAHMCAAB1bmlmb3JtIGZsb2F0M3gzIHVtYXRyaXhfUzE7CnVuaWZvcm0gc2FtcGxlcjJEIHVUZXh0dXJlU2FtcGxlcl8wX1MxOwpmbGF0IGluIGhhbGY0IHZjb2xvcl9TMDsKaW4gZmxvYXQyIHZUcmFuc2Zvcm1lZENvb3Jkc18yX1MwOwpoYWxmNCBUZXh0dXJlRWZmZWN0X1MxX2MwKGhhbGY0IF9pbnB1dCkgCnsKCXJldHVybiBzYW1wbGUodVRleHR1cmVTYW1wbGVyXzBfUzEsIHZUcmFuc2Zvcm1lZENvb3Jkc18yX1MwKS5ycnJyOwp9CmhhbGY0IE1hdHJpeEVmZmVjdF9TMShoYWxmNCBfaW5wdXQpIAp7CglyZXR1cm4gVGV4dHVyZUVmZmVjdF9TMV9jMChfaW5wdXQpOwp9CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBRdWFkUGVyRWRnZUFBR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2Y29sb3JfUzA7Cgljb25zdCBoYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KDEpOwoJaGFsZjQgb3V0cHV0X1MxOwoJb3V0cHV0X1MxID0gTWF0cml4RWZmZWN0X1MxKG91dHB1dENvdmVyYWdlX1MwKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dF9TMTsKCX0KfQoAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAIAAAAcG9zaXRpb24FAAAAY29sb3IAAAAKAAAAbG9jYWxDb29yZAAAAAAAAA==","B2ABSAAABQAAIAABBYAAB7777777777774ABICAAAAAAAAAAAAAABUABAAAAAEAAAAAIBEABAAAAA":"CgAAAExTS1N4AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gaGFsZjQgdUNvbG9yX1MwOwppbiBmbG9hdDIgaW5Qb3NpdGlvbjsKaW4gaGFsZiBpbkNvdmVyYWdlOwpvdXQgaGFsZjQgdmNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBEZWZhdWx0R2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IGNvbG9yID0gdUNvbG9yX1MwOwoJY29sb3IgPSBjb2xvciAqIGluQ292ZXJhZ2U7Cgl2Y29sb3JfUzAgPSBjb2xvcjsKCWZsb2F0MiBfdG1wXzFfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247CglmbG9hdDIgX3RtcF8zX2luUG9zaXRpb24gPSBpblBvc2l0aW9uOwoJc2tfUG9zaXRpb24gPSBfdG1wXzFfaW5Qb3NpdGlvbi54eTAxOwp9CgAAAAAGAQAAaW4gaGFsZjQgdmNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgRGVmYXVsdEdlb21ldHJ5UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdmNvbG9yX1MwOwoJY29uc3QgaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNCgxKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAKAAAAaW5Qb3NpdGlvbgAACgAAAGluQ292ZXJhZ2UAAAAAAAA=","HUJAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAQAAAAAAQQGACQAGAAAAAQAAAAAAAQQGAAA":"CgAAAExTS1PlAAAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gZmxvYXQyIGxvY2FsQ29vcmQ7Cm91dCBmbG9hdDIgdmxvY2FsQ29vcmRfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJdmxvY2FsQ29vcmRfUzAgPSBsb2NhbENvb3JkOwoJc2tfUG9zaXRpb24gPSBwb3NpdGlvbi54eTAxOwp9CgAAAAAAAACfAQAAdW5pZm9ybSBzYW1wbGVyMkQgdVRleHR1cmVTYW1wbGVyXzBfUzA7CmluIGZsb2F0MiB2bG9jYWxDb29yZF9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJaGFsZjQgb3V0cHV0Q29sb3JfUzAgPSBoYWxmNCgxKTsKCWZsb2F0MiB0ZXhDb29yZDsKCXRleENvb3JkID0gdmxvY2FsQ29vcmRfUzA7CglvdXRwdXRDb2xvcl9TMCA9ICgoc2FtcGxlKHVUZXh0dXJlU2FtcGxlcl8wX1MwLCB0ZXhDb29yZCkgKiBoYWxmNCgxKSkpOwoJY29uc3QgaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNCgxKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAgAAABwb3NpdGlvbgoAAABsb2NhbENvb3JkAAAAAAAA","HUQAAAAAAAMAADAAAIOAAAH677776IZOCAAP577777777777777777YBAAAAAAAAAAAKAAYAAAACAAAAAAACCAYAAA":"CgAAAExTS1PUAAAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gaGFsZjQgY29sb3I7CmZsYXQgb3V0IGhhbGY0IHZjb2xvcl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgl2Y29sb3JfUzAgPSBjb2xvcjsKCXNrX1Bvc2l0aW9uID0gcG9zaXRpb24ueHkwMTsKfQoAAAAAEQEAAGZsYXQgaW4gaGFsZjQgdmNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdmNvbG9yX1MwOwoJY29uc3QgaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNCgxKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAACAAAACAAAAHBvc2l0aW9uBQAAAGNvbG9yAAAAAAAAAA==","HUQACAAAAAMAADAAAIOAAAH677776IZOCAAP577777777777777777YBAAAAAAAAAAAKAAYAAAACAAAAAAACCAYAAA":"CgAAAExTS1PPAAAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gaGFsZjQgY29sb3I7Cm91dCBoYWxmNCB2Y29sb3JfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJdmNvbG9yX1MwID0gY29sb3I7Cglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cn0KAAAAAAAMAQAAaW4gaGFsZjQgdmNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdmNvbG9yX1MwOwoJY29uc3QgaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNCgxKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAACAAAACAAAAHBvc2l0aW9uBQAAAGNvbG9yAAAAAAAAAA==","BYIBQAAABQAAIAABBYAAAEIXBAAP777777777777AAAAAAAAAAAABUABAAAAAEAAAAAIBEABAAAAA":"CgAAAExTS1M+AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBpblBvc2l0aW9uOwppbiBoYWxmNCBpbkNvbG9yOwpvdXQgaGFsZjQgdmNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBEZWZhdWx0R2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IGNvbG9yID0gaW5Db2xvcjsKCXZjb2xvcl9TMCA9IGNvbG9yOwoJZmxvYXQyIF90bXBfMV9pblBvc2l0aW9uID0gaW5Qb3NpdGlvbjsKCWZsb2F0MiBfdG1wXzNfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247Cglza19Qb3NpdGlvbiA9IF90bXBfMV9pblBvc2l0aW9uLnh5MDE7Cn0KAAAAAAAABgEAAGluIGhhbGY0IHZjb2xvcl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIERlZmF1bHRHZW9tZXRyeVByb2Nlc3NvcgoJaGFsZjQgb3V0cHV0Q29sb3JfUzA7CglvdXRwdXRDb2xvcl9TMCA9IHZjb2xvcl9TMDsKCWNvbnN0IGhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoMSk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRDb3ZlcmFnZV9TMDsKCX0KfQoAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAACAAAACgAAAGluUG9zaXRpb24AAAcAAABpbkNvbG9yAAAAAAA=","DAQAAAAAAABGAABAYAAQAIHCAIAYAQUBAEAAAAAAEAAAAAAAAAAAAIAHSADQAAAQAAAAAAFAAMAAAABAAAAAAABBAM":"CgAAAExTS1MWAgAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQyIHVBdGxhc1NpemVJbnZfUzA7CmluIGZsb2F0MiBpblBvc2l0aW9uOwppbiBoYWxmNCBpbkNvbG9yOwppbiB1c2hvcnQyIGluVGV4dHVyZUNvb3JkczsKb3V0IGZsb2F0MiB2VGV4dHVyZUNvb3Jkc19TMDsKZmxhdCBvdXQgZmxvYXQgdlRleEluZGV4X1MwOwpvdXQgaGFsZjQgdmluQ29sb3JfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIEJpdG1hcFRleHQKCWludCB0ZXhJZHggPSAwOwoJZmxvYXQyIHVub3JtVGV4Q29vcmRzID0gZmxvYXQyKGluVGV4dHVyZUNvb3Jkcy54LCBpblRleHR1cmVDb29yZHMueSk7Cgl2VGV4dHVyZUNvb3Jkc19TMCA9IHVub3JtVGV4Q29vcmRzICogdUF0bGFzU2l6ZUludl9TMDsKCXZUZXhJbmRleF9TMCA9IGZsb2F0KHRleElkeCk7Cgl2aW5Db2xvcl9TMCA9IGluQ29sb3I7CglmbG9hdDIgX3RtcF8xX2luUG9zaXRpb24gPSBpblBvc2l0aW9uOwoJc2tfUG9zaXRpb24gPSBpblBvc2l0aW9uLnh5MDE7Cn0KAAABAAAAQAMAAHVuaWZvcm0gZmxvYXQ0IHVpbm5lclJlY3RfUzE7CnVuaWZvcm0gaGFsZjIgdXJhZGl1c1BsdXNIYWxmX1MxOwp1bmlmb3JtIHNhbXBsZXIyRCB1VGV4dHVyZVNhbXBsZXJfMF9TMDsKaW4gZmxvYXQyIHZUZXh0dXJlQ29vcmRzX1MwOwpmbGF0IGluIGZsb2F0IHZUZXhJbmRleF9TMDsKaW4gaGFsZjQgdmluQ29sb3JfUzA7CmhhbGY0IENpcmN1bGFyUlJlY3RfUzEoaGFsZjQgX2lucHV0KSAKewoJZmxvYXQyIGR4eTAgPSB1aW5uZXJSZWN0X1MxLkxUIC0gc2tfRnJhZ0Nvb3JkLnh5OwoJZmxvYXQyIGR4eTEgPSBza19GcmFnQ29vcmQueHkgLSB1aW5uZXJSZWN0X1MxLlJCOwoJZmxvYXQyIGR4eSA9IG1heChtYXgoZHh5MCwgZHh5MSksIDAuMCk7CgloYWxmIGFscGhhID0gaGFsZihzYXR1cmF0ZSh1cmFkaXVzUGx1c0hhbGZfUzEueCAtIGxlbmd0aChkeHkpKSk7CglyZXR1cm4gX2lucHV0ICogYWxwaGE7Cn0Kdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIEJpdG1hcFRleHQKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2aW5Db2xvcl9TMDsKCWhhbGY0IHRleENvbG9yOwoJewoJCXRleENvbG9yID0gc2FtcGxlKHVUZXh0dXJlU2FtcGxlcl8wX1MwLCB2VGV4dHVyZUNvb3Jkc19TMCkucnJycjsKCX0KCWhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gdGV4Q29sb3I7CgloYWxmNCBvdXRwdXRfUzE7CglvdXRwdXRfUzEgPSBDaXJjdWxhclJSZWN0X1MxKG91dHB1dENvdmVyYWdlX1MwKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dF9TMTsKCX0KfQoBAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAoAAABpblBvc2l0aW9uAAAHAAAAaW5Db2xvcgAPAAAAaW5UZXh0dXJlQ29vcmRzAAAAAAA=","HUIAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAAAAAADUAANAAAAAAIBAIAAAABLCIIBAAAAABAEGABBAMAACAIAAAAAAAB2AAAAAAACAAAAAEBSAAAAA":"CgAAAExTS1M8AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMV9jMDsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBmbG9hdDIgbG9jYWxDb29yZDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfM19TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cgl7CgkJdlRyYW5zZm9ybWVkQ29vcmRzXzNfUzAgPSBmbG9hdDN4Mih1bWF0cml4X1MxX2MwKSAqIGxvY2FsQ29vcmQueHkxOwoJfQp9CgAAAADJAwAAdW5pZm9ybSBmbG9hdDQgdWNsYW1wX1MxX2MwX2MwOwp1bmlmb3JtIGZsb2F0M3gzIHVtYXRyaXhfUzFfYzA7CnVuaWZvcm0gc2FtcGxlcjJEIHVUZXh0dXJlU2FtcGxlcl8wX1MxOwppbiBmbG9hdDIgdlRyYW5zZm9ybWVkQ29vcmRzXzNfUzA7CmhhbGY0IFRleHR1cmVFZmZlY3RfUzFfYzBfYzAoaGFsZjQgX2lucHV0KSAKewoJZmxvYXQyIGluQ29vcmQgPSB2VHJhbnNmb3JtZWRDb29yZHNfM19TMDsKCWZsb2F0MiBzdWJzZXRDb29yZDsKCXN1YnNldENvb3JkLnggPSBpbkNvb3JkLng7CglzdWJzZXRDb29yZC55ID0gaW5Db29yZC55OwoJZmxvYXQyIGNsYW1wZWRDb29yZDsKCWNsYW1wZWRDb29yZCA9IGNsYW1wKHN1YnNldENvb3JkLCB1Y2xhbXBfUzFfYzBfYzAueHksIHVjbGFtcF9TMV9jMF9jMC56dyk7CgloYWxmNCB0ZXh0dXJlQ29sb3IgPSBzYW1wbGUodVRleHR1cmVTYW1wbGVyXzBfUzEsIGNsYW1wZWRDb29yZCk7CglyZXR1cm4gdGV4dHVyZUNvbG9yOwp9CmhhbGY0IE1hdHJpeEVmZmVjdF9TMV9jMChoYWxmNCBfaW5wdXQpIAp7CglyZXR1cm4gVGV4dHVyZUVmZmVjdF9TMV9jMF9jMChfaW5wdXQpOwp9CmhhbGY0IEJsZW5kX1MxKGhhbGY0IF9zcmMsIGhhbGY0IF9kc3QpIAp7CglyZXR1cm4gYmxlbmRfbW9kdWxhdGUoTWF0cml4RWZmZWN0X1MxX2MwKF9zcmMpLCBfc3JjKTsKfQp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMCA9IGhhbGY0KDEpOwoJY29uc3QgaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNCgxKTsKCWhhbGY0IG91dHB1dF9TMTsKCW91dHB1dF9TMSA9IEJsZW5kX1MxKG91dHB1dENvbG9yX1MwLCBoYWxmNCgxKSk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0X1MxICogb3V0cHV0Q292ZXJhZ2VfUzA7Cgl9Cn0KAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAIAAAAcG9zaXRpb24KAAAAbG9jYWxDb29yZAAAAAAAAA==","HUJAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAQAAAAAAQQGAAZAADIAAAACU53QJEKAAAAAAMAAAAAIAAAAAAGIRDFB2XASAUAABQAAAAAAAAAAAAADUAAAAAAAEAAAAAIDEAAA":"CgAAAExTS1PlAAAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gZmxvYXQyIGxvY2FsQ29vcmQ7Cm91dCBmbG9hdDIgdmxvY2FsQ29vcmRfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJdmxvY2FsQ29vcmRfUzAgPSBsb2NhbENvb3JkOwoJc2tfUG9zaXRpb24gPSBwb3NpdGlvbi54eTAxOwp9CgAAAAEAAACrBAAAY29uc3QgaW50IGtGaWxsQUFfUzFfYzAgPSAxOwpjb25zdCBpbnQga0ludmVyc2VGaWxsQldfUzFfYzAgPSAyOwpjb25zdCBpbnQga0ludmVyc2VGaWxsQUFfUzFfYzAgPSAzOwp1bmlmb3JtIGZsb2F0NCB1Y2lyY2xlX1MxX2MwOwp1bmlmb3JtIHNhbXBsZXIyRCB1VGV4dHVyZVNhbXBsZXJfMF9TMDsKaW4gZmxvYXQyIHZsb2NhbENvb3JkX1MwOwpoYWxmNCBDaXJjbGVfUzFfYzAoaGFsZjQgX2lucHV0KSAKewoJaGFsZjQgX3RtcF8wX2luQ29sb3IgPSBfaW5wdXQ7CgloYWxmIGQ7CglpZiAoaW50KDEpID09IGtJbnZlcnNlRmlsbEJXX1MxX2MwIHx8IGludCgxKSA9PSBrSW52ZXJzZUZpbGxBQV9TMV9jMCkgCgl7CgkJZCA9IGhhbGYoKGxlbmd0aCgodWNpcmNsZV9TMV9jMC54eSAtIHNrX0ZyYWdDb29yZC54eSkgKiB1Y2lyY2xlX1MxX2MwLncpIC0gMS4wKSAqIHVjaXJjbGVfUzFfYzAueik7Cgl9CgllbHNlIAoJewoJCWQgPSBoYWxmKCgxLjAgLSBsZW5ndGgoKHVjaXJjbGVfUzFfYzAueHkgLSBza19GcmFnQ29vcmQueHkpICogdWNpcmNsZV9TMV9jMC53KSkgKiB1Y2lyY2xlX1MxX2MwLnopOwoJfQoJcmV0dXJuIGhhbGY0KGhhbGY0KGludCgxKSA9PSBrRmlsbEFBX1MxX2MwIHx8IGludCgxKSA9PSBrSW52ZXJzZUZpbGxBQV9TMV9jMCA/IHNhdHVyYXRlKGQpIDogaGFsZihkID4gMC41ID8gMSA6IDApKSk7Cn0KaGFsZjQgQmxlbmRfUzEoaGFsZjQgX3NyYywgaGFsZjQgX2RzdCkgCnsKCXJldHVybiBibGVuZF9tb2R1bGF0ZShfc3JjLCBDaXJjbGVfUzFfYzAoX3NyYykpOwp9CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBRdWFkUGVyRWRnZUFBR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwID0gaGFsZjQoMSk7CglmbG9hdDIgdGV4Q29vcmQ7Cgl0ZXhDb29yZCA9IHZsb2NhbENvb3JkX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSAoKHNhbXBsZSh1VGV4dHVyZVNhbXBsZXJfMF9TMCwgdGV4Q29vcmQpICogaGFsZjQoMSkpKTsKCWNvbnN0IGhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoMSk7CgloYWxmNCBvdXRwdXRfUzE7CglvdXRwdXRfUzEgPSBCbGVuZF9TMShvdXRwdXRDb3ZlcmFnZV9TMCwgaGFsZjQoMSkpOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dENvbG9yX1MwICogb3V0cHV0X1MxOwoJfQp9CgABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAgAAABwb3NpdGlvbgoAAABsb2NhbENvb3JkAAAAAAAA","AYAA5AADQAAAOAEARAFQJAABBADIB7777777777777777777777767YAAAAAAAAAAAAOQAAAAAAAQAAAABAMQAAAAA":"CgAAAExTS1OCAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBpblBvc2l0aW9uOwppbiBoYWxmNCBpbkNvbG9yOwppbiBmbG9hdDQgaW5DaXJjbGVFZGdlOwpvdXQgZmxvYXQ0IHZpbkNpcmNsZUVkZ2VfUzA7Cm91dCBoYWxmNCB2aW5Db2xvcl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgQ2lyY2xlR2VvbWV0cnlQcm9jZXNzb3IKCXZpbkNpcmNsZUVkZ2VfUzAgPSBpbkNpcmNsZUVkZ2U7Cgl2aW5Db2xvcl9TMCA9IGluQ29sb3I7CglmbG9hdDIgX3RtcF8wX2luUG9zaXRpb24gPSBpblBvc2l0aW9uOwoJZmxvYXQyIF90bXBfMl9pblBvc2l0aW9uID0gaW5Qb3NpdGlvbjsKCXNrX1Bvc2l0aW9uID0gX3RtcF8wX2luUG9zaXRpb24ueHkwMTsKfQoAAAAAAADqAQAAaW4gZmxvYXQ0IHZpbkNpcmNsZUVkZ2VfUzA7CmluIGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgQ2lyY2xlR2VvbWV0cnlQcm9jZXNzb3IKCWZsb2F0NCBjaXJjbGVFZGdlOwoJY2lyY2xlRWRnZSA9IHZpbkNpcmNsZUVkZ2VfUzA7CgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdmluQ29sb3JfUzA7CglmbG9hdCBkID0gbGVuZ3RoKGNpcmNsZUVkZ2UueHkpOwoJaGFsZiBkaXN0YW5jZVRvT3V0ZXJFZGdlID0gaGFsZihjaXJjbGVFZGdlLnogKiAoMS4wIC0gZCkpOwoJaGFsZiBlZGdlQWxwaGEgPSBzYXR1cmF0ZShkaXN0YW5jZVRvT3V0ZXJFZGdlKTsKCWhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoZWRnZUFscGhhKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAKAAAAaW5Qb3NpdGlvbgAABwAAAGluQ29sb3IADAAAAGluQ2lyY2xlRWRnZQAAAAA=","AYQA5AADQAAAOAEARAFQJAABBADIB7777777777777777777777767YAAAAAAAAAAAAB3QA6AAAEAAAAAAAMAAPEAEAAABAAAAAAB2AAAAAAACAAAAAEBSAAAA":"CgAAAExTS1PMAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQ0IHVsb2NhbE1hdHJpeF9TMDsKaW4gZmxvYXQyIGluUG9zaXRpb247CmluIGhhbGY0IGluQ29sb3I7CmluIGZsb2F0NCBpbkNpcmNsZUVkZ2U7Cm91dCBmbG9hdDQgdmluQ2lyY2xlRWRnZV9TMDsKb3V0IGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBDaXJjbGVHZW9tZXRyeVByb2Nlc3NvcgoJdmluQ2lyY2xlRWRnZV9TMCA9IGluQ2lyY2xlRWRnZTsKCXZpbkNvbG9yX1MwID0gaW5Db2xvcjsKCWZsb2F0MiBfdG1wXzBfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247CglmbG9hdDIgX3RtcF8xX2luUG9zaXRpb24gPSB1bG9jYWxNYXRyaXhfUzAueHogKiBpblBvc2l0aW9uICsgdWxvY2FsTWF0cml4X1MwLnl3OwoJc2tfUG9zaXRpb24gPSBfdG1wXzBfaW5Qb3NpdGlvbi54eTAxOwp9CgEAAAAeBQAAdW5pZm9ybSBmbG9hdDQgdWlubmVyUmVjdF9TMTsKdW5pZm9ybSBoYWxmMiB1cmFkaXVzUGx1c0hhbGZfUzE7CnVuaWZvcm0gZmxvYXQ0IHVpbm5lclJlY3RfUzI7CnVuaWZvcm0gaGFsZjIgdXJhZGl1c1BsdXNIYWxmX1MyOwppbiBmbG9hdDQgdmluQ2lyY2xlRWRnZV9TMDsKaW4gaGFsZjQgdmluQ29sb3JfUzA7CmhhbGY0IENpcmN1bGFyUlJlY3RfUzEoaGFsZjQgX2lucHV0KSAKewoJZmxvYXQyIGR4eTAgPSB1aW5uZXJSZWN0X1MxLkxUIC0gc2tfRnJhZ0Nvb3JkLnh5OwoJZmxvYXQyIGR4eTEgPSBza19GcmFnQ29vcmQueHkgLSB1aW5uZXJSZWN0X1MxLlJCOwoJZmxvYXQyIGR4eSA9IG1heChtYXgoZHh5MCwgZHh5MSksIDAuMCk7CgloYWxmIGFscGhhID0gaGFsZihzYXR1cmF0ZSh1cmFkaXVzUGx1c0hhbGZfUzEueCAtIGxlbmd0aChkeHkpKSk7CglhbHBoYSA9IDEuMCAtIGFscGhhOwoJcmV0dXJuIF9pbnB1dCAqIGFscGhhOwp9CmhhbGY0IENpcmN1bGFyUlJlY3RfUzIoaGFsZjQgX2lucHV0KSAKewoJZmxvYXQyIGR4eTAgPSB1aW5uZXJSZWN0X1MyLkxUIC0gc2tfRnJhZ0Nvb3JkLnh5OwoJZmxvYXQyIGR4eTEgPSBza19GcmFnQ29vcmQueHkgLSB1aW5uZXJSZWN0X1MyLlJCOwoJZmxvYXQyIGR4eSA9IG1heChtYXgoZHh5MCwgZHh5MSksIDAuMCk7CgloYWxmIGFscGhhID0gaGFsZihzYXR1cmF0ZSh1cmFkaXVzUGx1c0hhbGZfUzIueCAtIGxlbmd0aChkeHkpKSk7CglyZXR1cm4gX2lucHV0ICogYWxwaGE7Cn0Kdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIENpcmNsZUdlb21ldHJ5UHJvY2Vzc29yCglmbG9hdDQgY2lyY2xlRWRnZTsKCWNpcmNsZUVkZ2UgPSB2aW5DaXJjbGVFZGdlX1MwOwoJaGFsZjQgb3V0cHV0Q29sb3JfUzA7CglvdXRwdXRDb2xvcl9TMCA9IHZpbkNvbG9yX1MwOwoJZmxvYXQgZCA9IGxlbmd0aChjaXJjbGVFZGdlLnh5KTsKCWhhbGYgZGlzdGFuY2VUb091dGVyRWRnZSA9IGhhbGYoY2lyY2xlRWRnZS56ICogKDEuMCAtIGQpKTsKCWhhbGYgZWRnZUFscGhhID0gc2F0dXJhdGUoZGlzdGFuY2VUb091dGVyRWRnZSk7CgloYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KGVkZ2VBbHBoYSk7CgloYWxmNCBvdXRwdXRfUzE7CglvdXRwdXRfUzEgPSBDaXJjdWxhclJSZWN0X1MxKG91dHB1dENvdmVyYWdlX1MwKTsKCWhhbGY0IG91dHB1dF9TMjsKCW91dHB1dF9TMiA9IENpcmN1bGFyUlJlY3RfUzIob3V0cHV0X1MxKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dF9TMjsKCX0KfQoAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAADAAAACgAAAGluUG9zaXRpb24AAAcAAABpbkNvbG9yAAwAAABpbkNpcmNsZUVkZ2UAAAAA","HVJAAAAAABIAAGAAAQ4AAAH477776R24EAAAIOBQAD6P7777777777YDAAAAABAAAAAABBAMADSAB4QAAAAAEAAAAAAHIAAAAAAAIAAAAAQGIAAAAAAA":"CgAAAExTS1MjAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gaGFsZjQgY29sb3I7CmluIGZsb2F0MiBsb2NhbENvb3JkOwpmbGF0IG91dCBoYWxmNCB2Y29sb3JfUzA7Cm91dCBmbG9hdDIgdmxvY2FsQ29vcmRfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJdmNvbG9yX1MwID0gY29sb3I7Cgl2bG9jYWxDb29yZF9TMCA9IGxvY2FsQ29vcmQ7Cglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cn0KAAEAAABfAwAAdW5pZm9ybSBmbG9hdDQgdWlubmVyUmVjdF9TMTsKdW5pZm9ybSBoYWxmMiB1cmFkaXVzUGx1c0hhbGZfUzE7CnVuaWZvcm0gc2FtcGxlcjJEIHVUZXh0dXJlU2FtcGxlcl8wX1MwOwpmbGF0IGluIGhhbGY0IHZjb2xvcl9TMDsKaW4gZmxvYXQyIHZsb2NhbENvb3JkX1MwOwpoYWxmNCBDaXJjdWxhclJSZWN0X1MxKGhhbGY0IF9pbnB1dCkgCnsKCWZsb2F0MiBkeHkwID0gdWlubmVyUmVjdF9TMS5MVCAtIHNrX0ZyYWdDb29yZC54eTsKCWZsb2F0MiBkeHkxID0gc2tfRnJhZ0Nvb3JkLnh5IC0gdWlubmVyUmVjdF9TMS5SQjsKCWZsb2F0MiBkeHkgPSBtYXgobWF4KGR4eTAsIGR4eTEpLCAwLjApOwoJaGFsZiBhbHBoYSA9IGhhbGYoc2F0dXJhdGUodXJhZGl1c1BsdXNIYWxmX1MxLnggLSBsZW5ndGgoZHh5KSkpOwoJcmV0dXJuIF9pbnB1dCAqIGFscGhhOwp9CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBRdWFkUGVyRWRnZUFBR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2Y29sb3JfUzA7CglmbG9hdDIgdGV4Q29vcmQ7Cgl0ZXhDb29yZCA9IHZsb2NhbENvb3JkX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSAoKHNhbXBsZSh1VGV4dHVyZVNhbXBsZXJfMF9TMCwgdGV4Q29vcmQpICogb3V0cHV0Q29sb3JfUzApKTsKCWNvbnN0IGhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoMSk7CgloYWxmNCBvdXRwdXRfUzE7CglvdXRwdXRfUzEgPSBDaXJjdWxhclJSZWN0X1MxKG91dHB1dENvdmVyYWdlX1MwKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dF9TMTsKCX0KfQoAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAIAAAAcG9zaXRpb24FAAAAY29sb3IAAAAKAAAAbG9jYWxDb29yZAAAAAAAAA==","FAAQMYAAMAAAEADAAABAEYAAAICIAB5AABQAAAQAMAAAEATAAABAIIGAAEDCBYQCA4AAAAAAAA5AAAAAAABAAAAACAZAAAAA":"CgAAAExTS1PUCwAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0NCByYWRpaV9zZWxlY3RvcjsKaW4gZmxvYXQ0IGNvcm5lcl9hbmRfcmFkaXVzX291dHNldHM7CmluIGZsb2F0NCBhYV9ibG9hdF9hbmRfY292ZXJhZ2U7CmluIGZsb2F0NCByYWRpaV94OwppbiBmbG9hdDQgcmFkaWlfeTsKaW4gZmxvYXQ0IHNrZXc7CmluIGZsb2F0MiB0cmFuc2xhdGVfYW5kX2xvY2Fscm90YXRlOwppbiBoYWxmNCBjb2xvcjsKZmxhdCBvdXQgaGFsZjQgdmNvbG9yX1MwOwpvdXQgZmxvYXQyIHZhcmNjb29yZF9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgRmlsbFJSZWN0T3A6OlByb2Nlc3NvcgoJdmNvbG9yX1MwID0gY29sb3I7CglmbG9hdCBhYV9ibG9hdF9tdWx0aXBsaWVyID0gMTsKCWZsb2F0MiBjb3JuZXIgPSBjb3JuZXJfYW5kX3JhZGl1c19vdXRzZXRzLnh5OwoJZmxvYXQyIHJhZGl1c19vdXRzZXQgPSBjb3JuZXJfYW5kX3JhZGl1c19vdXRzZXRzLnp3OwoJZmxvYXQyIGFhX2Jsb2F0X2RpcmVjdGlvbiA9IGFhX2Jsb2F0X2FuZF9jb3ZlcmFnZS54eTsKCWZsb2F0IGlzX2xpbmVhcl9jb3ZlcmFnZSA9IGFhX2Jsb2F0X2FuZF9jb3ZlcmFnZS53OwoJZmxvYXQyIHBpeGVsbGVuZ3RoID0gaW52ZXJzZXNxcnQoZmxvYXQyKGRvdChza2V3Lnh6LCBza2V3Lnh6KSwgZG90KHNrZXcueXcsIHNrZXcueXcpKSk7CglmbG9hdDQgbm9ybWFsaXplZF9heGlzX2RpcnMgPSBza2V3ICogcGl4ZWxsZW5ndGgueHl4eTsKCWZsb2F0MiBheGlzd2lkdGhzID0gKGFicyhub3JtYWxpemVkX2F4aXNfZGlycy54eSkgKyBhYnMobm9ybWFsaXplZF9heGlzX2RpcnMuencpKTsKCWZsb2F0MiBhYV9ibG9hdHJhZGl1cyA9IGF4aXN3aWR0aHMgKiBwaXhlbGxlbmd0aCAqIC41OwoJZmxvYXQ0IHJhZGlpX2FuZF9uZWlnaGJvcnMgPSByYWRpaV9zZWxlY3RvciogZmxvYXQ0eDQocmFkaWlfeCwgcmFkaWlfeSwgcmFkaWlfeC55eHd6LCByYWRpaV95Lnd6eXgpOwoJZmxvYXQyIHJhZGlpID0gcmFkaWlfYW5kX25laWdoYm9ycy54eTsKCWZsb2F0MiBuZWlnaGJvcl9yYWRpaSA9IHJhZGlpX2FuZF9uZWlnaGJvcnMuenc7CglmbG9hdCBjb3ZlcmFnZV9tdWx0aXBsaWVyID0gMTsKCWlmIChhbnkoZ3JlYXRlclRoYW4oYWFfYmxvYXRyYWRpdXMsIGZsb2F0MigxKSkpKSAKCXsKCQljb3JuZXIgPSBtYXgoYWJzKGNvcm5lciksIGFhX2Jsb2F0cmFkaXVzKSAqIHNpZ24oY29ybmVyKTsKCQljb3ZlcmFnZV9tdWx0aXBsaWVyID0gMSAvIChtYXgoYWFfYmxvYXRyYWRpdXMueCwgMSkgKiBtYXgoYWFfYmxvYXRyYWRpdXMueSwgMSkpOwoJCXJhZGlpID0gZmxvYXQyKDApOwoJfQoJZmxvYXQgY292ZXJhZ2UgPSBhYV9ibG9hdF9hbmRfY292ZXJhZ2UuejsKCWlmIChhbnkobGVzc1RoYW4ocmFkaWksIGFhX2Jsb2F0cmFkaXVzICogMS41KSkpIAoJewoJCXJhZGlpID0gZmxvYXQyKDApOwoJCWFhX2Jsb2F0X2RpcmVjdGlvbiA9IHNpZ24oY29ybmVyKTsKCQlpZiAoY292ZXJhZ2UgPiAuNSkgCgkJewoJCQlhYV9ibG9hdF9kaXJlY3Rpb24gPSAtYWFfYmxvYXRfZGlyZWN0aW9uOwoJCX0KCQlpc19saW5lYXJfY292ZXJhZ2UgPSAxOwoJfQoJZWxzZSAKCXsKCQlyYWRpaSA9IGNsYW1wKHJhZGlpLCBwaXhlbGxlbmd0aCAqIDEuNSwgMiAtIHBpeGVsbGVuZ3RoICogMS41KTsKCQluZWlnaGJvcl9yYWRpaSA9IGNsYW1wKG5laWdoYm9yX3JhZGlpLCBwaXhlbGxlbmd0aCAqIDEuNSwgMiAtIHBpeGVsbGVuZ3RoICogMS41KTsKCQlmbG9hdDIgc3BhY2luZyA9IDIgLSByYWRpaSAtIG5laWdoYm9yX3JhZGlpOwoJCWZsb2F0MiBleHRyYV9wYWQgPSBtYXgocGl4ZWxsZW5ndGggKiAuMDYyNSAtIHNwYWNpbmcsIGZsb2F0MigwKSk7CgkJcmFkaWkgLT0gZXh0cmFfcGFkICogLjU7Cgl9CglmbG9hdDIgYWFfb3V0c2V0ID0gYWFfYmxvYXRfZGlyZWN0aW9uICogYWFfYmxvYXRyYWRpdXMgKiBhYV9ibG9hdF9tdWx0aXBsaWVyOwoJZmxvYXQyIHZlcnRleHBvcyA9IGNvcm5lciArIHJhZGl1c19vdXRzZXQgKiByYWRpaSArIGFhX291dHNldDsKCWlmIChjb3ZlcmFnZSA+IC41KSAKCXsKCQlpZiAoYWFfYmxvYXRfZGlyZWN0aW9uLnggIT0gMCAmJiB2ZXJ0ZXhwb3MueCAqIGNvcm5lci54IDwgMCkgCgkJewoJCQlmbG9hdCBiYWNrc2V0ID0gYWJzKHZlcnRleHBvcy54KTsKCQkJdmVydGV4cG9zLnggPSAwOwoJCQl2ZXJ0ZXhwb3MueSArPSBiYWNrc2V0ICogc2lnbihjb3JuZXIueSkgKiBwaXhlbGxlbmd0aC55L3BpeGVsbGVuZ3RoLng7CgkJCWNvdmVyYWdlID0gKGNvdmVyYWdlIC0gLjUpICogYWJzKGNvcm5lci54KSAvIChhYnMoY29ybmVyLngpICsgYmFja3NldCkgKyAuNTsKCQl9CgkJaWYgKGFhX2Jsb2F0X2RpcmVjdGlvbi55ICE9IDAgJiYgdmVydGV4cG9zLnkgKiBjb3JuZXIueSA8IDApIAoJCXsKCQkJZmxvYXQgYmFja3NldCA9IGFicyh2ZXJ0ZXhwb3MueSk7CgkJCXZlcnRleHBvcy55ID0gMDsKCQkJdmVydGV4cG9zLnggKz0gYmFja3NldCAqIHNpZ24oY29ybmVyLngpICogcGl4ZWxsZW5ndGgueC9waXhlbGxlbmd0aC55OwoJCQljb3ZlcmFnZSA9IChjb3ZlcmFnZSAtIC41KSAqIGFicyhjb3JuZXIueSkgLyAoYWJzKGNvcm5lci55KSArIGJhY2tzZXQpICsgLjU7CgkJfQoJfQoJZmxvYXQyeDIgc2tld21hdHJpeCA9IGZsb2F0MngyKHNrZXcueHksIHNrZXcuencpOwoJZmxvYXQyIGRldmNvb3JkID0gdmVydGV4cG9zICogc2tld21hdHJpeCArIHRyYW5zbGF0ZV9hbmRfbG9jYWxyb3RhdGUueHk7CglpZiAoMCAhPSBpc19saW5lYXJfY292ZXJhZ2UpIAoJewoJCXZhcmNjb29yZF9TMC54eSA9IGZsb2F0MigwLCBjb3ZlcmFnZSAqIGNvdmVyYWdlX211bHRpcGxpZXIpOwoJfQoJZWxzZSAKCXsKCQlmbG9hdDIgYXJjY29vcmQgPSAxIC0gYWJzKHJhZGl1c19vdXRzZXQpICsgYWFfb3V0c2V0L3JhZGlpICogY29ybmVyOwoJCXZhcmNjb29yZF9TMC54eSA9IGZsb2F0MihhcmNjb29yZC54KzEsIGFyY2Nvb3JkLnkpOwoJfQoJc2tfUG9zaXRpb24gPSBkZXZjb29yZC54eTAxOwp9CgAAAABFAgAAZmxhdCBpbiBoYWxmNCB2Y29sb3JfUzA7CmluIGZsb2F0MiB2YXJjY29vcmRfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBGaWxsUlJlY3RPcDo6UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdmNvbG9yX1MwOwoJZmxvYXQgeF9wbHVzXzE9dmFyY2Nvb3JkX1MwLngsIHk9dmFyY2Nvb3JkX1MwLnk7CgloYWxmIGNvdmVyYWdlOwoJaWYgKDAgPT0geF9wbHVzXzEpIAoJewoJCWNvdmVyYWdlID0gaGFsZih5KTsKCX0KCWVsc2UgCgl7CgkJZmxvYXQgZm4gPSB4X3BsdXNfMSAqICh4X3BsdXNfMSAtIDIpOwoJCWZuID0gZm1hKHkseSwgZm4pOwoJCWZsb2F0IGZud2lkdGggPSBmd2lkdGgoZm4pOwoJCWNvdmVyYWdlID0gLjUgLSBoYWxmKGZuL2Zud2lkdGgpOwoJCWNvdmVyYWdlID0gY2xhbXAoY292ZXJhZ2UsIDAsIDEpOwoJfQoJaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNChjb3ZlcmFnZSk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRDb3ZlcmFnZV9TMDsKCX0KfQoAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAACAAAAA4AAAByYWRpaV9zZWxlY3RvcgAAGQAAAGNvcm5lcl9hbmRfcmFkaXVzX291dHNldHMAAAAVAAAAYWFfYmxvYXRfYW5kX2NvdmVyYWdlAAAABwAAAHJhZGlpX3gABwAAAHJhZGlpX3kABAAAAHNrZXcZAAAAdHJhbnNsYXRlX2FuZF9sb2NhbHJvdGF0ZQAAAAUAAABjb2xvcgAAAAAAAAA=","HVIAAAAAABIAAGAAAQ4AAAH477776R24EAAAIOBQAD6P7777777777YDAAAAAAAAAAAFIBQU7BTXIAAAAAACAAAAAAQFV5W6JEAAAAAYAAAABQEZ2AKAWAQAABAL6SYKDYAAAACAAAAAAQEGIAAAAACAWTWL3EYAAAADAAAAACADHIJJCYCAAAEAP2LRIPAAAAAIAAAAAAABTALI3F5SOAIAABQAAAAAABTUEUZMBAAAAAH5FYUXQAAAAAAAEAAAAAZMRGOQCQFQEAAAAAAAAAGARL2LXJHAAEAAAAAEAAAABSCQX5FQUHQAAAAAAAAAACAA4AAAACAAAAAAACCAYAAAAA":"CgAAAExTS1OGAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMV9jMF9jMF9jMTsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBoYWxmNCBjb2xvcjsKaW4gZmxvYXQyIGxvY2FsQ29vcmQ7CmZsYXQgb3V0IGhhbGY0IHZjb2xvcl9TMDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfNl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgl2Y29sb3JfUzAgPSBjb2xvcjsKCXNrX1Bvc2l0aW9uID0gcG9zaXRpb24ueHkwMTsKCXsKCQl2VHJhbnNmb3JtZWRDb29yZHNfNl9TMCA9IGZsb2F0M3gyKHVtYXRyaXhfUzFfYzBfYzBfYzEpICogbG9jYWxDb29yZC54eTE7Cgl9Cn0KAAAAAAAAdgcAAHVuaWZvcm0gaGFsZjQgdXN0YXJ0X1MxX2MwX2MwX2MwOwp1bmlmb3JtIGhhbGY0IHVlbmRfUzFfYzBfYzBfYzA7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMV9jMF9jMF9jMTsKdW5pZm9ybSBoYWxmNCB1bGVmdEJvcmRlckNvbG9yX1MxX2MwX2MwOwp1bmlmb3JtIGhhbGY0IHVyaWdodEJvcmRlckNvbG9yX1MxX2MwX2MwOwpmbGF0IGluIGhhbGY0IHZjb2xvcl9TMDsKaW4gZmxvYXQyIHZUcmFuc2Zvcm1lZENvb3Jkc182X1MwOwpoYWxmNCBTaW5nbGVJbnRlcnZhbENvbG9yaXplcl9TMV9jMF9jMF9jMChoYWxmNCBfaW5wdXQsIGZsb2F0MiBfY29vcmRzKSAKewoJaGFsZjQgX3RtcF8wX2luQ29sb3IgPSBfaW5wdXQ7CglmbG9hdDIgX3RtcF8xX2Nvb3JkcyA9IF9jb29yZHM7CglyZXR1cm4gaGFsZjQobWl4KHVzdGFydF9TMV9jMF9jMF9jMCwgdWVuZF9TMV9jMF9jMF9jMCwgaGFsZihfdG1wXzFfY29vcmRzLngpKSk7Cn0KaGFsZjQgTGluZWFyTGF5b3V0X1MxX2MwX2MwX2MxX2MwKGhhbGY0IF9pbnB1dCkgCnsKCWhhbGY0IF90bXBfMl9pbkNvbG9yID0gX2lucHV0OwoJZmxvYXQyIF90bXBfM19jb29yZHMgPSB2VHJhbnNmb3JtZWRDb29yZHNfNl9TMDsKCXJldHVybiBoYWxmNChoYWxmNChoYWxmKF90bXBfM19jb29yZHMueCkgKyAxZS0wNSwgMS4wLCAwLjAsIDAuMCkpOwp9CmhhbGY0IE1hdHJpeEVmZmVjdF9TMV9jMF9jMF9jMShoYWxmNCBfaW5wdXQpIAp7CglyZXR1cm4gTGluZWFyTGF5b3V0X1MxX2MwX2MwX2MxX2MwKF9pbnB1dCk7Cn0KaGFsZjQgQ2xhbXBlZEdyYWRpZW50X1MxX2MwX2MwKGhhbGY0IF9pbnB1dCkgCnsKCWhhbGY0IF90bXBfNF9pbkNvbG9yID0gX2lucHV0OwoJaGFsZjQgdCA9IE1hdHJpeEVmZmVjdF9TMV9jMF9jMF9jMShfdG1wXzRfaW5Db2xvcik7CgloYWxmNCBvdXRDb2xvcjsKCWlmICghYm9vbChpbnQoMSkpICYmIHQueSA8IDAuMCkgCgl7CgkJb3V0Q29sb3IgPSBoYWxmNCgwLjApOwoJfQoJZWxzZSBpZiAodC54IDwgMC4wKSAKCXsKCQlvdXRDb2xvciA9IHVsZWZ0Qm9yZGVyQ29sb3JfUzFfYzBfYzA7Cgl9CgllbHNlIGlmICh0LnggPiAxLjApIAoJewoJCW91dENvbG9yID0gdXJpZ2h0Qm9yZGVyQ29sb3JfUzFfYzBfYzA7Cgl9CgllbHNlIAoJewoJCW91dENvbG9yID0gU2luZ2xlSW50ZXJ2YWxDb2xvcml6ZXJfUzFfYzBfYzBfYzAoX3RtcF80X2luQ29sb3IsIGZsb2F0MihoYWxmMih0LngsIDAuMCkpKTsKCX0KCXJldHVybiBoYWxmNChvdXRDb2xvcik7Cn0KaGFsZjQgY29sb3JfeGZvcm1fUzFfYzAoZmxvYXQ0IGNvbG9yKSAKewoJY29sb3IucmdiICo9IGNvbG9yLmE7CglyZXR1cm4gaGFsZjQoY29sb3IpOwp9CmhhbGY0IENvbG9yU3BhY2VYZm9ybV9TMV9jMChoYWxmNCBfaW5wdXQpIAp7CglyZXR1cm4gY29sb3JfeGZvcm1fUzFfYzAoQ2xhbXBlZEdyYWRpZW50X1MxX2MwX2MwKF9pbnB1dCkpOwp9CmhhbGY0IERpc2FibGVDb3ZlcmFnZUFzQWxwaGFfUzEoaGFsZjQgX2lucHV0KSAKewoJX2lucHV0ID0gQ29sb3JTcGFjZVhmb3JtX1MxX2MwKF9pbnB1dCk7CgloYWxmNCBfdG1wXzVfaW5Db2xvciA9IF9pbnB1dDsKCXJldHVybiBoYWxmNChfaW5wdXQpOwp9CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBRdWFkUGVyRWRnZUFBR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2Y29sb3JfUzA7Cgljb25zdCBoYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KDEpOwoJaGFsZjQgb3V0cHV0X1MxOwoJb3V0cHV0X1MxID0gRGlzYWJsZUNvdmVyYWdlQXNBbHBoYV9TMShvdXRwdXRDb2xvcl9TMCk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0X1MxICogb3V0cHV0Q292ZXJhZ2VfUzA7Cgl9Cn0KAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAgAAABwb3NpdGlvbgUAAABjb2xvcgAAAAoAAABsb2NhbENvb3JkAAAAAAAA"}} \ No newline at end of file +{"platform":"android","name":"SM G970N","engineRevision":"ada363ee93b17cfe31587b5102679885cb40837e","data":{"HUQAAAAAAAMAADAAAIOAAAH677776IZOCAAP577777777777777777YBAAAAAAAAAAAHEADBAAAAAAIAAAAAAOQAAAAAAAQAAAABAMQAAAAAA":"CgAAAExTS1PUAAAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gaGFsZjQgY29sb3I7CmZsYXQgb3V0IGhhbGY0IHZjb2xvcl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgl2Y29sb3JfUzAgPSBjb2xvcjsKCXNrX1Bvc2l0aW9uID0gcG9zaXRpb24ueHkwMTsKfQoBAAAA+wIAAHVuaWZvcm0gZmxvYXQ0IHVpbm5lclJlY3RfUzE7CnVuaWZvcm0gaGFsZjIgdXJhZGl1c1BsdXNIYWxmX1MxOwpmbGF0IGluIGhhbGY0IHZjb2xvcl9TMDsKaGFsZjQgQ2lyY3VsYXJSUmVjdF9TMShoYWxmNCBfaW5wdXQpIAp7CglmbG9hdCBkeDAgPSB1aW5uZXJSZWN0X1MxLkwgLSBza19GcmFnQ29vcmQueDsKCWZsb2F0MiBkeHkxID0gc2tfRnJhZ0Nvb3JkLnh5IC0gdWlubmVyUmVjdF9TMS5SQjsKCWZsb2F0MiBkeHkgPSBtYXgoZmxvYXQyKG1heChkeDAsIGR4eTEueCksIGR4eTEueSksIDAuMCk7CgloYWxmIHRvcEFscGhhID0gaGFsZihzYXR1cmF0ZShza19GcmFnQ29vcmQueSAtIHVpbm5lclJlY3RfUzEuVCkpOwoJaGFsZiBhbHBoYSA9IHRvcEFscGhhICogaGFsZihzYXR1cmF0ZSh1cmFkaXVzUGx1c0hhbGZfUzEueCAtIGxlbmd0aChkeHkpKSk7CglyZXR1cm4gX2lucHV0ICogYWxwaGE7Cn0Kdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJaGFsZjQgb3V0cHV0Q29sb3JfUzA7CglvdXRwdXRDb2xvcl9TMCA9IHZjb2xvcl9TMDsKCWNvbnN0IGhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoMSk7CgloYWxmNCBvdXRwdXRfUzE7CglvdXRwdXRfUzEgPSBDaXJjdWxhclJSZWN0X1MxKG91dHB1dENvdmVyYWdlX1MwKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dF9TMTsKCX0KfQoAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAIAAAAcG9zaXRpb24FAAAAY29sb3IAAAAAAAAA","DAQAAAAAAABGAABAYAAQAIHCAIAYAQUBAEAAAAAAEAAAAAAAAAAAAIAHSADQAAAQAAAAAAFAAMAAAABAAAAAAABBAM":"CgAAAExTS1MWAgAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQyIHVBdGxhc1NpemVJbnZfUzA7CmluIGZsb2F0MiBpblBvc2l0aW9uOwppbiBoYWxmNCBpbkNvbG9yOwppbiB1c2hvcnQyIGluVGV4dHVyZUNvb3JkczsKb3V0IGZsb2F0MiB2VGV4dHVyZUNvb3Jkc19TMDsKZmxhdCBvdXQgZmxvYXQgdlRleEluZGV4X1MwOwpvdXQgaGFsZjQgdmluQ29sb3JfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIEJpdG1hcFRleHQKCWludCB0ZXhJZHggPSAwOwoJZmxvYXQyIHVub3JtVGV4Q29vcmRzID0gZmxvYXQyKGluVGV4dHVyZUNvb3Jkcy54LCBpblRleHR1cmVDb29yZHMueSk7Cgl2VGV4dHVyZUNvb3Jkc19TMCA9IHVub3JtVGV4Q29vcmRzICogdUF0bGFzU2l6ZUludl9TMDsKCXZUZXhJbmRleF9TMCA9IGZsb2F0KHRleElkeCk7Cgl2aW5Db2xvcl9TMCA9IGluQ29sb3I7CglmbG9hdDIgX3RtcF8xX2luUG9zaXRpb24gPSBpblBvc2l0aW9uOwoJc2tfUG9zaXRpb24gPSBpblBvc2l0aW9uLnh5MDE7Cn0KAAABAAAAQAMAAHVuaWZvcm0gZmxvYXQ0IHVpbm5lclJlY3RfUzE7CnVuaWZvcm0gaGFsZjIgdXJhZGl1c1BsdXNIYWxmX1MxOwp1bmlmb3JtIHNhbXBsZXIyRCB1VGV4dHVyZVNhbXBsZXJfMF9TMDsKaW4gZmxvYXQyIHZUZXh0dXJlQ29vcmRzX1MwOwpmbGF0IGluIGZsb2F0IHZUZXhJbmRleF9TMDsKaW4gaGFsZjQgdmluQ29sb3JfUzA7CmhhbGY0IENpcmN1bGFyUlJlY3RfUzEoaGFsZjQgX2lucHV0KSAKewoJZmxvYXQyIGR4eTAgPSB1aW5uZXJSZWN0X1MxLkxUIC0gc2tfRnJhZ0Nvb3JkLnh5OwoJZmxvYXQyIGR4eTEgPSBza19GcmFnQ29vcmQueHkgLSB1aW5uZXJSZWN0X1MxLlJCOwoJZmxvYXQyIGR4eSA9IG1heChtYXgoZHh5MCwgZHh5MSksIDAuMCk7CgloYWxmIGFscGhhID0gaGFsZihzYXR1cmF0ZSh1cmFkaXVzUGx1c0hhbGZfUzEueCAtIGxlbmd0aChkeHkpKSk7CglyZXR1cm4gX2lucHV0ICogYWxwaGE7Cn0Kdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIEJpdG1hcFRleHQKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2aW5Db2xvcl9TMDsKCWhhbGY0IHRleENvbG9yOwoJewoJCXRleENvbG9yID0gc2FtcGxlKHVUZXh0dXJlU2FtcGxlcl8wX1MwLCB2VGV4dHVyZUNvb3Jkc19TMCkucnJycjsKCX0KCWhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gdGV4Q29sb3I7CgloYWxmNCBvdXRwdXRfUzE7CglvdXRwdXRfUzEgPSBDaXJjdWxhclJSZWN0X1MxKG91dHB1dENvdmVyYWdlX1MwKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dF9TMTsKCX0KfQoBAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAoAAABpblBvc2l0aW9uAAAHAAAAaW5Db2xvcgAPAAAAaW5UZXh0dXJlQ29vcmRzAAAAAAA=","AYTRVAADQAAAOAEARAFQJAABBADAAAILBYAACCYUQD777777777767YAAAAAAAAAAAAOQAAAAAAAQAAAABAMQAAAAA":"CgAAAExTS1NyAgAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQ0IHVsb2NhbE1hdHJpeF9TMDsKaW4gZmxvYXQyIGluUG9zaXRpb247CmluIGhhbGY0IGluQ29sb3I7CmluIGZsb2F0NCBpbkNpcmNsZUVkZ2U7CmluIGhhbGYzIGluQ2xpcFBsYW5lOwppbiBoYWxmMyBpbklzZWN0UGxhbmU7Cm91dCBmbG9hdDQgdmluQ2lyY2xlRWRnZV9TMDsKb3V0IGhhbGYzIHZpbkNsaXBQbGFuZV9TMDsKb3V0IGhhbGYzIHZpbklzZWN0UGxhbmVfUzA7Cm91dCBoYWxmNCB2aW5Db2xvcl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgQ2lyY2xlR2VvbWV0cnlQcm9jZXNzb3IKCXZpbkNpcmNsZUVkZ2VfUzAgPSBpbkNpcmNsZUVkZ2U7Cgl2aW5DbGlwUGxhbmVfUzAgPSBpbkNsaXBQbGFuZTsKCXZpbklzZWN0UGxhbmVfUzAgPSBpbklzZWN0UGxhbmU7Cgl2aW5Db2xvcl9TMCA9IGluQ29sb3I7CglmbG9hdDIgX3RtcF8wX2luUG9zaXRpb24gPSBpblBvc2l0aW9uOwoJZmxvYXQyIF90bXBfMV9pblBvc2l0aW9uID0gdWxvY2FsTWF0cml4X1MwLnh6ICogaW5Qb3NpdGlvbiArIHVsb2NhbE1hdHJpeF9TMC55dzsKCXNrX1Bvc2l0aW9uID0gX3RtcF8wX2luUG9zaXRpb24ueHkwMTsKfQoAAAAAAADdAwAAaW4gZmxvYXQ0IHZpbkNpcmNsZUVkZ2VfUzA7CmluIGhhbGYzIHZpbkNsaXBQbGFuZV9TMDsKaW4gaGFsZjMgdmluSXNlY3RQbGFuZV9TMDsKaW4gaGFsZjQgdmluQ29sb3JfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBDaXJjbGVHZW9tZXRyeVByb2Nlc3NvcgoJZmxvYXQ0IGNpcmNsZUVkZ2U7CgljaXJjbGVFZGdlID0gdmluQ2lyY2xlRWRnZV9TMDsKCWhhbGYzIGNsaXBQbGFuZTsKCWNsaXBQbGFuZSA9IHZpbkNsaXBQbGFuZV9TMDsKCWhhbGYzIGlzZWN0UGxhbmU7Cglpc2VjdFBsYW5lID0gdmluSXNlY3RQbGFuZV9TMDsKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2aW5Db2xvcl9TMDsKCWZsb2F0IGQgPSBsZW5ndGgoY2lyY2xlRWRnZS54eSk7CgloYWxmIGRpc3RhbmNlVG9PdXRlckVkZ2UgPSBoYWxmKGNpcmNsZUVkZ2UueiAqICgxLjAgLSBkKSk7CgloYWxmIGVkZ2VBbHBoYSA9IHNhdHVyYXRlKGRpc3RhbmNlVG9PdXRlckVkZ2UpOwoJaGFsZiBkaXN0YW5jZVRvSW5uZXJFZGdlID0gaGFsZihjaXJjbGVFZGdlLnogKiAoZCAtIGNpcmNsZUVkZ2UudykpOwoJaGFsZiBpbm5lckFscGhhID0gc2F0dXJhdGUoZGlzdGFuY2VUb0lubmVyRWRnZSk7CgllZGdlQWxwaGEgKj0gaW5uZXJBbHBoYTsKCWhhbGYgY2xpcCA9IGhhbGYoc2F0dXJhdGUoY2lyY2xlRWRnZS56ICogZG90KGNpcmNsZUVkZ2UueHksIGNsaXBQbGFuZS54eSkgKyBjbGlwUGxhbmUueikpOwoJY2xpcCAqPSBoYWxmKHNhdHVyYXRlKGNpcmNsZUVkZ2UueiAqIGRvdChjaXJjbGVFZGdlLnh5LCBpc2VjdFBsYW5lLnh5KSArIGlzZWN0UGxhbmUueikpOwoJZWRnZUFscGhhICo9IGNsaXA7CgloYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KGVkZ2VBbHBoYSk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRDb3ZlcmFnZV9TMDsKCX0KfQoAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAoAAABpblBvc2l0aW9uAAAHAAAAaW5Db2xvcgAMAAAAaW5DaXJjbGVFZGdlCwAAAGluQ2xpcFBsYW5lAAwAAABpbklzZWN0UGxhbmUAAAAA","HUIAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAAAAAADUAANAAAAAAIBAIAAAABLCIIBAAAAABAEGABBAMAACAIAAAAAAAB2AAAAAAACAAAAAEBSAAAAA":"CgAAAExTS1M8AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMV9jMDsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBmbG9hdDIgbG9jYWxDb29yZDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfM19TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cgl7CgkJdlRyYW5zZm9ybWVkQ29vcmRzXzNfUzAgPSBmbG9hdDN4Mih1bWF0cml4X1MxX2MwKSAqIGxvY2FsQ29vcmQueHkxOwoJfQp9CgAAAADJAwAAdW5pZm9ybSBmbG9hdDQgdWNsYW1wX1MxX2MwX2MwOwp1bmlmb3JtIGZsb2F0M3gzIHVtYXRyaXhfUzFfYzA7CnVuaWZvcm0gc2FtcGxlcjJEIHVUZXh0dXJlU2FtcGxlcl8wX1MxOwppbiBmbG9hdDIgdlRyYW5zZm9ybWVkQ29vcmRzXzNfUzA7CmhhbGY0IFRleHR1cmVFZmZlY3RfUzFfYzBfYzAoaGFsZjQgX2lucHV0KSAKewoJZmxvYXQyIGluQ29vcmQgPSB2VHJhbnNmb3JtZWRDb29yZHNfM19TMDsKCWZsb2F0MiBzdWJzZXRDb29yZDsKCXN1YnNldENvb3JkLnggPSBpbkNvb3JkLng7CglzdWJzZXRDb29yZC55ID0gaW5Db29yZC55OwoJZmxvYXQyIGNsYW1wZWRDb29yZDsKCWNsYW1wZWRDb29yZCA9IGNsYW1wKHN1YnNldENvb3JkLCB1Y2xhbXBfUzFfYzBfYzAueHksIHVjbGFtcF9TMV9jMF9jMC56dyk7CgloYWxmNCB0ZXh0dXJlQ29sb3IgPSBzYW1wbGUodVRleHR1cmVTYW1wbGVyXzBfUzEsIGNsYW1wZWRDb29yZCk7CglyZXR1cm4gdGV4dHVyZUNvbG9yOwp9CmhhbGY0IE1hdHJpeEVmZmVjdF9TMV9jMChoYWxmNCBfaW5wdXQpIAp7CglyZXR1cm4gVGV4dHVyZUVmZmVjdF9TMV9jMF9jMChfaW5wdXQpOwp9CmhhbGY0IEJsZW5kX1MxKGhhbGY0IF9zcmMsIGhhbGY0IF9kc3QpIAp7CglyZXR1cm4gYmxlbmRfbW9kdWxhdGUoTWF0cml4RWZmZWN0X1MxX2MwKF9zcmMpLCBfc3JjKTsKfQp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMCA9IGhhbGY0KDEpOwoJY29uc3QgaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNCgxKTsKCWhhbGY0IG91dHB1dF9TMTsKCW91dHB1dF9TMSA9IEJsZW5kX1MxKG91dHB1dENvbG9yX1MwLCBoYWxmNCgxKSk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0X1MxICogb3V0cHV0Q292ZXJhZ2VfUzA7Cgl9Cn0KAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAIAAAAcG9zaXRpb24KAAAAbG9jYWxDb29yZAAAAAAAAA==","HUIAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAAAAAALUAQMAAAAAAIAAEAAAABJYQAAAAAQAAIAAAAAWCBACAABAAAAANAECAZAAEAAAAAAAAFAAMAAAABAAAAAAABBAM":"CgAAAExTS1M2AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBmbG9hdDIgbG9jYWxDb29yZDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cgl7CgkJdlRyYW5zZm9ybWVkQ29vcmRzXzJfUzAgPSBmbG9hdDN4Mih1bWF0cml4X1MxKSAqIGxvY2FsQ29vcmQueHkxOwoJfQp9CgAAAAAAAC8GAAB1bmlmb3JtIGZsb2F0NCB1Y2xhbXBfUzFfYzBfYzBfYzA7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMV9jMF9jMDsKdW5pZm9ybSBoYWxmMiB1SW5jcmVtZW50X1MxX2MwOwp1bmlmb3JtIGhhbGYyIHVPZmZzZXRzQW5kS2VybmVsX1MxX2MwWzEzXTsKdW5pZm9ybSBmbG9hdDN4MyB1bWF0cml4X1MxOwp1bmlmb3JtIHNhbXBsZXIyRCB1VGV4dHVyZVNhbXBsZXJfMF9TMTsKaW4gZmxvYXQyIHZUcmFuc2Zvcm1lZENvb3Jkc18yX1MwOwpoYWxmNCBUZXh0dXJlRWZmZWN0X1MxX2MwX2MwX2MwKGhhbGY0IF9pbnB1dCwgZmxvYXQyIF9jb29yZHMpIAp7CglmbG9hdDIgaW5Db29yZCA9IF9jb29yZHM7CglmbG9hdDIgc3Vic2V0Q29vcmQ7CglzdWJzZXRDb29yZC54ID0gaW5Db29yZC54OwoJc3Vic2V0Q29vcmQueSA9IGluQ29vcmQueTsKCWZsb2F0MiBjbGFtcGVkQ29vcmQ7CgljbGFtcGVkQ29vcmQueCA9IGNsYW1wKHN1YnNldENvb3JkLngsIHVjbGFtcF9TMV9jMF9jMF9jMC54LCB1Y2xhbXBfUzFfYzBfYzBfYzAueik7CgljbGFtcGVkQ29vcmQueSA9IHN1YnNldENvb3JkLnk7CgloYWxmNCB0ZXh0dXJlQ29sb3IgPSBzYW1wbGUodVRleHR1cmVTYW1wbGVyXzBfUzEsIGNsYW1wZWRDb29yZCk7CglyZXR1cm4gdGV4dHVyZUNvbG9yOwp9CmhhbGY0IE1hdHJpeEVmZmVjdF9TMV9jMF9jMChoYWxmNCBfaW5wdXQsIGZsb2F0MiBfY29vcmRzKSAKewoJcmV0dXJuIFRleHR1cmVFZmZlY3RfUzFfYzBfYzBfYzAoX2lucHV0LCBmbG9hdDN4Mih1bWF0cml4X1MxX2MwX2MwKSAqIF9jb29yZHMueHkxKTsKfQpoYWxmNCBTbW9vdGhfUzFfYzAoaGFsZjQgX2lucHV0LCBmbG9hdDIgY29vcmQsIGhhbGYyIG9mZnNldEFuZEtlcm5lbCkgCnsKCXJldHVybiBNYXRyaXhFZmZlY3RfUzFfYzBfYzAoX2lucHV0LCAoY29vcmQgKyBvZmZzZXRBbmRLZXJuZWwueCAqIHVJbmNyZW1lbnRfUzFfYzApKSAqIG9mZnNldEFuZEtlcm5lbC55Owp9CmhhbGY0IEdhdXNzaWFuQ29udm9sdXRpb25fUzFfYzAoaGFsZjQgX2lucHV0KSAKewoJaGFsZjQgY29sb3IgPSBoYWxmNCgwKTsKCWZsb2F0MiBjb29yZCA9IHZUcmFuc2Zvcm1lZENvb3Jkc18yX1MwOwoJZm9yIChpbnQgaT0wOyBpPDEzOyArK2kpIAoJewoJCWNvbG9yICs9IFNtb290aF9TMV9jMChfaW5wdXQsIGNvb3JkLCB1T2Zmc2V0c0FuZEtlcm5lbF9TMV9jMFtpXSk7Cgl9CglyZXR1cm4gY29sb3I7Cn0KaGFsZjQgTWF0cml4RWZmZWN0X1MxKGhhbGY0IF9pbnB1dCkgCnsKCXJldHVybiBHYXVzc2lhbkNvbnZvbHV0aW9uX1MxX2MwKF9pbnB1dCk7Cn0Kdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJaGFsZjQgb3V0cHV0Q29sb3JfUzAgPSBoYWxmNCgxKTsKCWNvbnN0IGhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoMSk7CgloYWxmNCBvdXRwdXRfUzE7CglvdXRwdXRfUzEgPSBNYXRyaXhFZmZlY3RfUzEob3V0cHV0Q29sb3JfUzApOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dF9TMSAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAgAAABwb3NpdGlvbgoAAABsb2NhbENvb3JkAAAAAAAA","AYQA5AADQAAAOAEARAFQJAABBADIB7777777777777777777777767YAAAAAAAAAACABZQA6AAAEAAAAAAAIADQAAAAIAAAAAAAIIDA":"CgAAAExTS1PMAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQ0IHVsb2NhbE1hdHJpeF9TMDsKaW4gZmxvYXQyIGluUG9zaXRpb247CmluIGhhbGY0IGluQ29sb3I7CmluIGZsb2F0NCBpbkNpcmNsZUVkZ2U7Cm91dCBmbG9hdDQgdmluQ2lyY2xlRWRnZV9TMDsKb3V0IGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBDaXJjbGVHZW9tZXRyeVByb2Nlc3NvcgoJdmluQ2lyY2xlRWRnZV9TMCA9IGluQ2lyY2xlRWRnZTsKCXZpbkNvbG9yX1MwID0gaW5Db2xvcjsKCWZsb2F0MiBfdG1wXzBfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247CglmbG9hdDIgX3RtcF8xX2luUG9zaXRpb24gPSB1bG9jYWxNYXRyaXhfUzAueHogKiBpblBvc2l0aW9uICsgdWxvY2FsTWF0cml4X1MwLnl3OwoJc2tfUG9zaXRpb24gPSBfdG1wXzBfaW5Qb3NpdGlvbi54eTAxOwp9CgEAAACPAwAAdW5pZm9ybSBmbG9hdDQgdWlubmVyUmVjdF9TMTsKdW5pZm9ybSBoYWxmMiB1cmFkaXVzUGx1c0hhbGZfUzE7CmluIGZsb2F0NCB2aW5DaXJjbGVFZGdlX1MwOwppbiBoYWxmNCB2aW5Db2xvcl9TMDsKaGFsZjQgQ2lyY3VsYXJSUmVjdF9TMShoYWxmNCBfaW5wdXQpIAp7CglmbG9hdDIgZHh5MCA9IHVpbm5lclJlY3RfUzEuTFQgLSBza19GcmFnQ29vcmQueHk7CglmbG9hdDIgZHh5MSA9IHNrX0ZyYWdDb29yZC54eSAtIHVpbm5lclJlY3RfUzEuUkI7CglmbG9hdDIgZHh5ID0gbWF4KG1heChkeHkwLCBkeHkxKSwgMC4wKTsKCWhhbGYgYWxwaGEgPSBoYWxmKHNhdHVyYXRlKHVyYWRpdXNQbHVzSGFsZl9TMS54IC0gbGVuZ3RoKGR4eSkpKTsKCWFscGhhID0gMS4wIC0gYWxwaGE7CglyZXR1cm4gX2lucHV0ICogYWxwaGE7Cn0Kdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIENpcmNsZUdlb21ldHJ5UHJvY2Vzc29yCglmbG9hdDQgY2lyY2xlRWRnZTsKCWNpcmNsZUVkZ2UgPSB2aW5DaXJjbGVFZGdlX1MwOwoJaGFsZjQgb3V0cHV0Q29sb3JfUzA7CglvdXRwdXRDb2xvcl9TMCA9IHZpbkNvbG9yX1MwOwoJZmxvYXQgZCA9IGxlbmd0aChjaXJjbGVFZGdlLnh5KTsKCWhhbGYgZGlzdGFuY2VUb091dGVyRWRnZSA9IGhhbGYoY2lyY2xlRWRnZS56ICogKDEuMCAtIGQpKTsKCWhhbGYgZWRnZUFscGhhID0gc2F0dXJhdGUoZGlzdGFuY2VUb091dGVyRWRnZSk7CgloYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KGVkZ2VBbHBoYSk7CgloYWxmNCBvdXRwdXRfUzE7CglvdXRwdXRfUzEgPSBDaXJjdWxhclJSZWN0X1MxKG91dHB1dENvdmVyYWdlX1MwKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dF9TMTsKCX0KfQoAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAKAAAAaW5Qb3NpdGlvbgAABwAAAGluQ29sb3IADAAAAGluQ2lyY2xlRWRnZQAAAAA=","BYIBQAAABQAAIAABBYAAAEIXBAAP777777777777AAAAAAAAAAAABUABAAAAAEAAAAAIBEABAAAAA":"CgAAAExTS1M+AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBpblBvc2l0aW9uOwppbiBoYWxmNCBpbkNvbG9yOwpvdXQgaGFsZjQgdmNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBEZWZhdWx0R2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IGNvbG9yID0gaW5Db2xvcjsKCXZjb2xvcl9TMCA9IGNvbG9yOwoJZmxvYXQyIF90bXBfMV9pblBvc2l0aW9uID0gaW5Qb3NpdGlvbjsKCWZsb2F0MiBfdG1wXzNfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247Cglza19Qb3NpdGlvbiA9IF90bXBfMV9pblBvc2l0aW9uLnh5MDE7Cn0KAAAAAAAABgEAAGluIGhhbGY0IHZjb2xvcl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIERlZmF1bHRHZW9tZXRyeVByb2Nlc3NvcgoJaGFsZjQgb3V0cHV0Q29sb3JfUzA7CglvdXRwdXRDb2xvcl9TMCA9IHZjb2xvcl9TMDsKCWNvbnN0IGhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoMSk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRDb3ZlcmFnZV9TMDsKCX0KfQoAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAACAAAACgAAAGluUG9zaXRpb24AAAcAAABpbkNvbG9yAAAAAAA=","B2ABSAAABQAAIAABBYAAB7777777777774ABICAAAAAAAAAAAAAABUABAAAAAEAAAAAIBEABAAAAA":"CgAAAExTS1N4AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gaGFsZjQgdUNvbG9yX1MwOwppbiBmbG9hdDIgaW5Qb3NpdGlvbjsKaW4gaGFsZiBpbkNvdmVyYWdlOwpvdXQgaGFsZjQgdmNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBEZWZhdWx0R2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IGNvbG9yID0gdUNvbG9yX1MwOwoJY29sb3IgPSBjb2xvciAqIGluQ292ZXJhZ2U7Cgl2Y29sb3JfUzAgPSBjb2xvcjsKCWZsb2F0MiBfdG1wXzFfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247CglmbG9hdDIgX3RtcF8zX2luUG9zaXRpb24gPSBpblBvc2l0aW9uOwoJc2tfUG9zaXRpb24gPSBfdG1wXzFfaW5Qb3NpdGlvbi54eTAxOwp9CgAAAAAGAQAAaW4gaGFsZjQgdmNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgRGVmYXVsdEdlb21ldHJ5UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdmNvbG9yX1MwOwoJY29uc3QgaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNCgxKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAKAAAAaW5Qb3NpdGlvbgAACgAAAGluQ292ZXJhZ2UAAAAAAAA=","FAAQMYAAMAAAEADAAABAEYAAAICIAB5AABQAAAQAMAAAEATAAABAIIGAAEDCBYQCA4AAAAAAEAKPABAAAAAAB2AAAAAAACAAAAAEBSAAAAAAA":"CgAAAExTS1PUCwAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0NCByYWRpaV9zZWxlY3RvcjsKaW4gZmxvYXQ0IGNvcm5lcl9hbmRfcmFkaXVzX291dHNldHM7CmluIGZsb2F0NCBhYV9ibG9hdF9hbmRfY292ZXJhZ2U7CmluIGZsb2F0NCByYWRpaV94OwppbiBmbG9hdDQgcmFkaWlfeTsKaW4gZmxvYXQ0IHNrZXc7CmluIGZsb2F0MiB0cmFuc2xhdGVfYW5kX2xvY2Fscm90YXRlOwppbiBoYWxmNCBjb2xvcjsKZmxhdCBvdXQgaGFsZjQgdmNvbG9yX1MwOwpvdXQgZmxvYXQyIHZhcmNjb29yZF9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgRmlsbFJSZWN0T3A6OlByb2Nlc3NvcgoJdmNvbG9yX1MwID0gY29sb3I7CglmbG9hdCBhYV9ibG9hdF9tdWx0aXBsaWVyID0gMTsKCWZsb2F0MiBjb3JuZXIgPSBjb3JuZXJfYW5kX3JhZGl1c19vdXRzZXRzLnh5OwoJZmxvYXQyIHJhZGl1c19vdXRzZXQgPSBjb3JuZXJfYW5kX3JhZGl1c19vdXRzZXRzLnp3OwoJZmxvYXQyIGFhX2Jsb2F0X2RpcmVjdGlvbiA9IGFhX2Jsb2F0X2FuZF9jb3ZlcmFnZS54eTsKCWZsb2F0IGlzX2xpbmVhcl9jb3ZlcmFnZSA9IGFhX2Jsb2F0X2FuZF9jb3ZlcmFnZS53OwoJZmxvYXQyIHBpeGVsbGVuZ3RoID0gaW52ZXJzZXNxcnQoZmxvYXQyKGRvdChza2V3Lnh6LCBza2V3Lnh6KSwgZG90KHNrZXcueXcsIHNrZXcueXcpKSk7CglmbG9hdDQgbm9ybWFsaXplZF9heGlzX2RpcnMgPSBza2V3ICogcGl4ZWxsZW5ndGgueHl4eTsKCWZsb2F0MiBheGlzd2lkdGhzID0gKGFicyhub3JtYWxpemVkX2F4aXNfZGlycy54eSkgKyBhYnMobm9ybWFsaXplZF9heGlzX2RpcnMuencpKTsKCWZsb2F0MiBhYV9ibG9hdHJhZGl1cyA9IGF4aXN3aWR0aHMgKiBwaXhlbGxlbmd0aCAqIC41OwoJZmxvYXQ0IHJhZGlpX2FuZF9uZWlnaGJvcnMgPSByYWRpaV9zZWxlY3RvciogZmxvYXQ0eDQocmFkaWlfeCwgcmFkaWlfeSwgcmFkaWlfeC55eHd6LCByYWRpaV95Lnd6eXgpOwoJZmxvYXQyIHJhZGlpID0gcmFkaWlfYW5kX25laWdoYm9ycy54eTsKCWZsb2F0MiBuZWlnaGJvcl9yYWRpaSA9IHJhZGlpX2FuZF9uZWlnaGJvcnMuenc7CglmbG9hdCBjb3ZlcmFnZV9tdWx0aXBsaWVyID0gMTsKCWlmIChhbnkoZ3JlYXRlclRoYW4oYWFfYmxvYXRyYWRpdXMsIGZsb2F0MigxKSkpKSAKCXsKCQljb3JuZXIgPSBtYXgoYWJzKGNvcm5lciksIGFhX2Jsb2F0cmFkaXVzKSAqIHNpZ24oY29ybmVyKTsKCQljb3ZlcmFnZV9tdWx0aXBsaWVyID0gMSAvIChtYXgoYWFfYmxvYXRyYWRpdXMueCwgMSkgKiBtYXgoYWFfYmxvYXRyYWRpdXMueSwgMSkpOwoJCXJhZGlpID0gZmxvYXQyKDApOwoJfQoJZmxvYXQgY292ZXJhZ2UgPSBhYV9ibG9hdF9hbmRfY292ZXJhZ2UuejsKCWlmIChhbnkobGVzc1RoYW4ocmFkaWksIGFhX2Jsb2F0cmFkaXVzICogMS41KSkpIAoJewoJCXJhZGlpID0gZmxvYXQyKDApOwoJCWFhX2Jsb2F0X2RpcmVjdGlvbiA9IHNpZ24oY29ybmVyKTsKCQlpZiAoY292ZXJhZ2UgPiAuNSkgCgkJewoJCQlhYV9ibG9hdF9kaXJlY3Rpb24gPSAtYWFfYmxvYXRfZGlyZWN0aW9uOwoJCX0KCQlpc19saW5lYXJfY292ZXJhZ2UgPSAxOwoJfQoJZWxzZSAKCXsKCQlyYWRpaSA9IGNsYW1wKHJhZGlpLCBwaXhlbGxlbmd0aCAqIDEuNSwgMiAtIHBpeGVsbGVuZ3RoICogMS41KTsKCQluZWlnaGJvcl9yYWRpaSA9IGNsYW1wKG5laWdoYm9yX3JhZGlpLCBwaXhlbGxlbmd0aCAqIDEuNSwgMiAtIHBpeGVsbGVuZ3RoICogMS41KTsKCQlmbG9hdDIgc3BhY2luZyA9IDIgLSByYWRpaSAtIG5laWdoYm9yX3JhZGlpOwoJCWZsb2F0MiBleHRyYV9wYWQgPSBtYXgocGl4ZWxsZW5ndGggKiAuMDYyNSAtIHNwYWNpbmcsIGZsb2F0MigwKSk7CgkJcmFkaWkgLT0gZXh0cmFfcGFkICogLjU7Cgl9CglmbG9hdDIgYWFfb3V0c2V0ID0gYWFfYmxvYXRfZGlyZWN0aW9uICogYWFfYmxvYXRyYWRpdXMgKiBhYV9ibG9hdF9tdWx0aXBsaWVyOwoJZmxvYXQyIHZlcnRleHBvcyA9IGNvcm5lciArIHJhZGl1c19vdXRzZXQgKiByYWRpaSArIGFhX291dHNldDsKCWlmIChjb3ZlcmFnZSA+IC41KSAKCXsKCQlpZiAoYWFfYmxvYXRfZGlyZWN0aW9uLnggIT0gMCAmJiB2ZXJ0ZXhwb3MueCAqIGNvcm5lci54IDwgMCkgCgkJewoJCQlmbG9hdCBiYWNrc2V0ID0gYWJzKHZlcnRleHBvcy54KTsKCQkJdmVydGV4cG9zLnggPSAwOwoJCQl2ZXJ0ZXhwb3MueSArPSBiYWNrc2V0ICogc2lnbihjb3JuZXIueSkgKiBwaXhlbGxlbmd0aC55L3BpeGVsbGVuZ3RoLng7CgkJCWNvdmVyYWdlID0gKGNvdmVyYWdlIC0gLjUpICogYWJzKGNvcm5lci54KSAvIChhYnMoY29ybmVyLngpICsgYmFja3NldCkgKyAuNTsKCQl9CgkJaWYgKGFhX2Jsb2F0X2RpcmVjdGlvbi55ICE9IDAgJiYgdmVydGV4cG9zLnkgKiBjb3JuZXIueSA8IDApIAoJCXsKCQkJZmxvYXQgYmFja3NldCA9IGFicyh2ZXJ0ZXhwb3MueSk7CgkJCXZlcnRleHBvcy55ID0gMDsKCQkJdmVydGV4cG9zLnggKz0gYmFja3NldCAqIHNpZ24oY29ybmVyLngpICogcGl4ZWxsZW5ndGgueC9waXhlbGxlbmd0aC55OwoJCQljb3ZlcmFnZSA9IChjb3ZlcmFnZSAtIC41KSAqIGFicyhjb3JuZXIueSkgLyAoYWJzKGNvcm5lci55KSArIGJhY2tzZXQpICsgLjU7CgkJfQoJfQoJZmxvYXQyeDIgc2tld21hdHJpeCA9IGZsb2F0MngyKHNrZXcueHksIHNrZXcuencpOwoJZmxvYXQyIGRldmNvb3JkID0gdmVydGV4cG9zICogc2tld21hdHJpeCArIHRyYW5zbGF0ZV9hbmRfbG9jYWxyb3RhdGUueHk7CglpZiAoMCAhPSBpc19saW5lYXJfY292ZXJhZ2UpIAoJewoJCXZhcmNjb29yZF9TMC54eSA9IGZsb2F0MigwLCBjb3ZlcmFnZSAqIGNvdmVyYWdlX211bHRpcGxpZXIpOwoJfQoJZWxzZSAKCXsKCQlmbG9hdDIgYXJjY29vcmQgPSAxIC0gYWJzKHJhZGl1c19vdXRzZXQpICsgYWFfb3V0c2V0L3JhZGlpICogY29ybmVyOwoJCXZhcmNjb29yZF9TMC54eSA9IGZsb2F0MihhcmNjb29yZC54KzEsIGFyY2Nvb3JkLnkpOwoJfQoJc2tfUG9zaXRpb24gPSBkZXZjb29yZC54eTAxOwp9CgEAAACbBAAAdW5pZm9ybSBmbG9hdDQgdWlubmVyUmVjdF9TMTsKdW5pZm9ybSBmbG9hdDIgdWludlJhZGlpWFlfUzE7CmZsYXQgaW4gaGFsZjQgdmNvbG9yX1MwOwppbiBmbG9hdDIgdmFyY2Nvb3JkX1MwOwpoYWxmNCBFbGxpcHRpY2FsUlJlY3RfUzEoaGFsZjQgX2lucHV0KSAKewoJZmxvYXQyIGR4eTAgPSB1aW5uZXJSZWN0X1MxLkxUIC0gc2tfRnJhZ0Nvb3JkLnh5OwoJZmxvYXQyIGR4eTEgPSBza19GcmFnQ29vcmQueHkgLSB1aW5uZXJSZWN0X1MxLlJCOwoJZmxvYXQyIGR4eSA9IG1heChtYXgoZHh5MCwgZHh5MSksIDAuMCk7CglmbG9hdDIgWiA9IGR4eSAqIHVpbnZSYWRpaVhZX1MxLnh5OwoJaGFsZiBpbXBsaWNpdCA9IGhhbGYoZG90KFosIGR4eSkgLSAxLjApOwoJaGFsZiBncmFkX2RvdCA9IGhhbGYoNC4wICogZG90KFosIFopKTsKCWdyYWRfZG90ID0gbWF4KGdyYWRfZG90LCAxLjBlLTQpOwoJaGFsZiBhcHByb3hfZGlzdCA9IGltcGxpY2l0ICogaGFsZihpbnZlcnNlc3FydChncmFkX2RvdCkpOwoJaGFsZiBhbHBoYSA9IGNsYW1wKDAuNSArIGFwcHJveF9kaXN0LCAwLjAsIDEuMCk7CglyZXR1cm4gX2lucHV0ICogYWxwaGE7Cn0Kdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIEZpbGxSUmVjdE9wOjpQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2Y29sb3JfUzA7CglmbG9hdCB4X3BsdXNfMT12YXJjY29vcmRfUzAueCwgeT12YXJjY29vcmRfUzAueTsKCWhhbGYgY292ZXJhZ2U7CglpZiAoMCA9PSB4X3BsdXNfMSkgCgl7CgkJY292ZXJhZ2UgPSBoYWxmKHkpOwoJfQoJZWxzZSAKCXsKCQlmbG9hdCBmbiA9IHhfcGx1c18xICogKHhfcGx1c18xIC0gMik7CgkJZm4gPSBmbWEoeSx5LCBmbik7CgkJZmxvYXQgZm53aWR0aCA9IGZ3aWR0aChmbik7CgkJY292ZXJhZ2UgPSAuNSAtIGhhbGYoZm4vZm53aWR0aCk7CgkJY292ZXJhZ2UgPSBjbGFtcChjb3ZlcmFnZSwgMCwgMSk7Cgl9CgloYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KGNvdmVyYWdlKTsKCWhhbGY0IG91dHB1dF9TMTsKCW91dHB1dF9TMSA9IEVsbGlwdGljYWxSUmVjdF9TMShvdXRwdXRDb3ZlcmFnZV9TMCk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRfUzE7Cgl9Cn0KAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAIAAAADgAAAHJhZGlpX3NlbGVjdG9yAAAZAAAAY29ybmVyX2FuZF9yYWRpdXNfb3V0c2V0cwAAABUAAABhYV9ibG9hdF9hbmRfY292ZXJhZ2UAAAAHAAAAcmFkaWlfeAAHAAAAcmFkaWlfeQAEAAAAc2tldxkAAAB0cmFuc2xhdGVfYW5kX2xvY2Fscm90YXRlAAAABQAAAGNvbG9yAAAAAAAAAA==","FAAQMYAAMAAAEADAAABAEYAAAICIAB5AABQAAAQAMAAAEATAAABAIIGAAEDCBYQCA4AAAAAAAA5AAAAAAABAAAAACAZAAAAA":"CgAAAExTS1PUCwAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0NCByYWRpaV9zZWxlY3RvcjsKaW4gZmxvYXQ0IGNvcm5lcl9hbmRfcmFkaXVzX291dHNldHM7CmluIGZsb2F0NCBhYV9ibG9hdF9hbmRfY292ZXJhZ2U7CmluIGZsb2F0NCByYWRpaV94OwppbiBmbG9hdDQgcmFkaWlfeTsKaW4gZmxvYXQ0IHNrZXc7CmluIGZsb2F0MiB0cmFuc2xhdGVfYW5kX2xvY2Fscm90YXRlOwppbiBoYWxmNCBjb2xvcjsKZmxhdCBvdXQgaGFsZjQgdmNvbG9yX1MwOwpvdXQgZmxvYXQyIHZhcmNjb29yZF9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgRmlsbFJSZWN0T3A6OlByb2Nlc3NvcgoJdmNvbG9yX1MwID0gY29sb3I7CglmbG9hdCBhYV9ibG9hdF9tdWx0aXBsaWVyID0gMTsKCWZsb2F0MiBjb3JuZXIgPSBjb3JuZXJfYW5kX3JhZGl1c19vdXRzZXRzLnh5OwoJZmxvYXQyIHJhZGl1c19vdXRzZXQgPSBjb3JuZXJfYW5kX3JhZGl1c19vdXRzZXRzLnp3OwoJZmxvYXQyIGFhX2Jsb2F0X2RpcmVjdGlvbiA9IGFhX2Jsb2F0X2FuZF9jb3ZlcmFnZS54eTsKCWZsb2F0IGlzX2xpbmVhcl9jb3ZlcmFnZSA9IGFhX2Jsb2F0X2FuZF9jb3ZlcmFnZS53OwoJZmxvYXQyIHBpeGVsbGVuZ3RoID0gaW52ZXJzZXNxcnQoZmxvYXQyKGRvdChza2V3Lnh6LCBza2V3Lnh6KSwgZG90KHNrZXcueXcsIHNrZXcueXcpKSk7CglmbG9hdDQgbm9ybWFsaXplZF9heGlzX2RpcnMgPSBza2V3ICogcGl4ZWxsZW5ndGgueHl4eTsKCWZsb2F0MiBheGlzd2lkdGhzID0gKGFicyhub3JtYWxpemVkX2F4aXNfZGlycy54eSkgKyBhYnMobm9ybWFsaXplZF9heGlzX2RpcnMuencpKTsKCWZsb2F0MiBhYV9ibG9hdHJhZGl1cyA9IGF4aXN3aWR0aHMgKiBwaXhlbGxlbmd0aCAqIC41OwoJZmxvYXQ0IHJhZGlpX2FuZF9uZWlnaGJvcnMgPSByYWRpaV9zZWxlY3RvciogZmxvYXQ0eDQocmFkaWlfeCwgcmFkaWlfeSwgcmFkaWlfeC55eHd6LCByYWRpaV95Lnd6eXgpOwoJZmxvYXQyIHJhZGlpID0gcmFkaWlfYW5kX25laWdoYm9ycy54eTsKCWZsb2F0MiBuZWlnaGJvcl9yYWRpaSA9IHJhZGlpX2FuZF9uZWlnaGJvcnMuenc7CglmbG9hdCBjb3ZlcmFnZV9tdWx0aXBsaWVyID0gMTsKCWlmIChhbnkoZ3JlYXRlclRoYW4oYWFfYmxvYXRyYWRpdXMsIGZsb2F0MigxKSkpKSAKCXsKCQljb3JuZXIgPSBtYXgoYWJzKGNvcm5lciksIGFhX2Jsb2F0cmFkaXVzKSAqIHNpZ24oY29ybmVyKTsKCQljb3ZlcmFnZV9tdWx0aXBsaWVyID0gMSAvIChtYXgoYWFfYmxvYXRyYWRpdXMueCwgMSkgKiBtYXgoYWFfYmxvYXRyYWRpdXMueSwgMSkpOwoJCXJhZGlpID0gZmxvYXQyKDApOwoJfQoJZmxvYXQgY292ZXJhZ2UgPSBhYV9ibG9hdF9hbmRfY292ZXJhZ2UuejsKCWlmIChhbnkobGVzc1RoYW4ocmFkaWksIGFhX2Jsb2F0cmFkaXVzICogMS41KSkpIAoJewoJCXJhZGlpID0gZmxvYXQyKDApOwoJCWFhX2Jsb2F0X2RpcmVjdGlvbiA9IHNpZ24oY29ybmVyKTsKCQlpZiAoY292ZXJhZ2UgPiAuNSkgCgkJewoJCQlhYV9ibG9hdF9kaXJlY3Rpb24gPSAtYWFfYmxvYXRfZGlyZWN0aW9uOwoJCX0KCQlpc19saW5lYXJfY292ZXJhZ2UgPSAxOwoJfQoJZWxzZSAKCXsKCQlyYWRpaSA9IGNsYW1wKHJhZGlpLCBwaXhlbGxlbmd0aCAqIDEuNSwgMiAtIHBpeGVsbGVuZ3RoICogMS41KTsKCQluZWlnaGJvcl9yYWRpaSA9IGNsYW1wKG5laWdoYm9yX3JhZGlpLCBwaXhlbGxlbmd0aCAqIDEuNSwgMiAtIHBpeGVsbGVuZ3RoICogMS41KTsKCQlmbG9hdDIgc3BhY2luZyA9IDIgLSByYWRpaSAtIG5laWdoYm9yX3JhZGlpOwoJCWZsb2F0MiBleHRyYV9wYWQgPSBtYXgocGl4ZWxsZW5ndGggKiAuMDYyNSAtIHNwYWNpbmcsIGZsb2F0MigwKSk7CgkJcmFkaWkgLT0gZXh0cmFfcGFkICogLjU7Cgl9CglmbG9hdDIgYWFfb3V0c2V0ID0gYWFfYmxvYXRfZGlyZWN0aW9uICogYWFfYmxvYXRyYWRpdXMgKiBhYV9ibG9hdF9tdWx0aXBsaWVyOwoJZmxvYXQyIHZlcnRleHBvcyA9IGNvcm5lciArIHJhZGl1c19vdXRzZXQgKiByYWRpaSArIGFhX291dHNldDsKCWlmIChjb3ZlcmFnZSA+IC41KSAKCXsKCQlpZiAoYWFfYmxvYXRfZGlyZWN0aW9uLnggIT0gMCAmJiB2ZXJ0ZXhwb3MueCAqIGNvcm5lci54IDwgMCkgCgkJewoJCQlmbG9hdCBiYWNrc2V0ID0gYWJzKHZlcnRleHBvcy54KTsKCQkJdmVydGV4cG9zLnggPSAwOwoJCQl2ZXJ0ZXhwb3MueSArPSBiYWNrc2V0ICogc2lnbihjb3JuZXIueSkgKiBwaXhlbGxlbmd0aC55L3BpeGVsbGVuZ3RoLng7CgkJCWNvdmVyYWdlID0gKGNvdmVyYWdlIC0gLjUpICogYWJzKGNvcm5lci54KSAvIChhYnMoY29ybmVyLngpICsgYmFja3NldCkgKyAuNTsKCQl9CgkJaWYgKGFhX2Jsb2F0X2RpcmVjdGlvbi55ICE9IDAgJiYgdmVydGV4cG9zLnkgKiBjb3JuZXIueSA8IDApIAoJCXsKCQkJZmxvYXQgYmFja3NldCA9IGFicyh2ZXJ0ZXhwb3MueSk7CgkJCXZlcnRleHBvcy55ID0gMDsKCQkJdmVydGV4cG9zLnggKz0gYmFja3NldCAqIHNpZ24oY29ybmVyLngpICogcGl4ZWxsZW5ndGgueC9waXhlbGxlbmd0aC55OwoJCQljb3ZlcmFnZSA9IChjb3ZlcmFnZSAtIC41KSAqIGFicyhjb3JuZXIueSkgLyAoYWJzKGNvcm5lci55KSArIGJhY2tzZXQpICsgLjU7CgkJfQoJfQoJZmxvYXQyeDIgc2tld21hdHJpeCA9IGZsb2F0MngyKHNrZXcueHksIHNrZXcuencpOwoJZmxvYXQyIGRldmNvb3JkID0gdmVydGV4cG9zICogc2tld21hdHJpeCArIHRyYW5zbGF0ZV9hbmRfbG9jYWxyb3RhdGUueHk7CglpZiAoMCAhPSBpc19saW5lYXJfY292ZXJhZ2UpIAoJewoJCXZhcmNjb29yZF9TMC54eSA9IGZsb2F0MigwLCBjb3ZlcmFnZSAqIGNvdmVyYWdlX211bHRpcGxpZXIpOwoJfQoJZWxzZSAKCXsKCQlmbG9hdDIgYXJjY29vcmQgPSAxIC0gYWJzKHJhZGl1c19vdXRzZXQpICsgYWFfb3V0c2V0L3JhZGlpICogY29ybmVyOwoJCXZhcmNjb29yZF9TMC54eSA9IGZsb2F0MihhcmNjb29yZC54KzEsIGFyY2Nvb3JkLnkpOwoJfQoJc2tfUG9zaXRpb24gPSBkZXZjb29yZC54eTAxOwp9CgAAAABFAgAAZmxhdCBpbiBoYWxmNCB2Y29sb3JfUzA7CmluIGZsb2F0MiB2YXJjY29vcmRfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBGaWxsUlJlY3RPcDo6UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdmNvbG9yX1MwOwoJZmxvYXQgeF9wbHVzXzE9dmFyY2Nvb3JkX1MwLngsIHk9dmFyY2Nvb3JkX1MwLnk7CgloYWxmIGNvdmVyYWdlOwoJaWYgKDAgPT0geF9wbHVzXzEpIAoJewoJCWNvdmVyYWdlID0gaGFsZih5KTsKCX0KCWVsc2UgCgl7CgkJZmxvYXQgZm4gPSB4X3BsdXNfMSAqICh4X3BsdXNfMSAtIDIpOwoJCWZuID0gZm1hKHkseSwgZm4pOwoJCWZsb2F0IGZud2lkdGggPSBmd2lkdGgoZm4pOwoJCWNvdmVyYWdlID0gLjUgLSBoYWxmKGZuL2Zud2lkdGgpOwoJCWNvdmVyYWdlID0gY2xhbXAoY292ZXJhZ2UsIDAsIDEpOwoJfQoJaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNChjb3ZlcmFnZSk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRDb3ZlcmFnZV9TMDsKCX0KfQoAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAACAAAAA4AAAByYWRpaV9zZWxlY3RvcgAAGQAAAGNvcm5lcl9hbmRfcmFkaXVzX291dHNldHMAAAAVAAAAYWFfYmxvYXRfYW5kX2NvdmVyYWdlAAAABwAAAHJhZGlpX3gABwAAAHJhZGlpX3kABAAAAHNrZXcZAAAAdHJhbnNsYXRlX2FuZF9sb2NhbHJvdGF0ZQAAAAUAAABjb2xvcgAAAAAAAAA=","AYAA5AADQAAAOAEARAFQJAABBADIB7777777777777777777777767YAAAAAAAAAAAAOQAAAAAAAQAAAABAMQAAAAA":"CgAAAExTS1OCAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBpblBvc2l0aW9uOwppbiBoYWxmNCBpbkNvbG9yOwppbiBmbG9hdDQgaW5DaXJjbGVFZGdlOwpvdXQgZmxvYXQ0IHZpbkNpcmNsZUVkZ2VfUzA7Cm91dCBoYWxmNCB2aW5Db2xvcl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgQ2lyY2xlR2VvbWV0cnlQcm9jZXNzb3IKCXZpbkNpcmNsZUVkZ2VfUzAgPSBpbkNpcmNsZUVkZ2U7Cgl2aW5Db2xvcl9TMCA9IGluQ29sb3I7CglmbG9hdDIgX3RtcF8wX2luUG9zaXRpb24gPSBpblBvc2l0aW9uOwoJZmxvYXQyIF90bXBfMl9pblBvc2l0aW9uID0gaW5Qb3NpdGlvbjsKCXNrX1Bvc2l0aW9uID0gX3RtcF8wX2luUG9zaXRpb24ueHkwMTsKfQoAAAAAAADqAQAAaW4gZmxvYXQ0IHZpbkNpcmNsZUVkZ2VfUzA7CmluIGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgQ2lyY2xlR2VvbWV0cnlQcm9jZXNzb3IKCWZsb2F0NCBjaXJjbGVFZGdlOwoJY2lyY2xlRWRnZSA9IHZpbkNpcmNsZUVkZ2VfUzA7CgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdmluQ29sb3JfUzA7CglmbG9hdCBkID0gbGVuZ3RoKGNpcmNsZUVkZ2UueHkpOwoJaGFsZiBkaXN0YW5jZVRvT3V0ZXJFZGdlID0gaGFsZihjaXJjbGVFZGdlLnogKiAoMS4wIC0gZCkpOwoJaGFsZiBlZGdlQWxwaGEgPSBzYXR1cmF0ZShkaXN0YW5jZVRvT3V0ZXJFZGdlKTsKCWhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoZWRnZUFscGhhKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAKAAAAaW5Qb3NpdGlvbgAABwAAAGluQ29sb3IADAAAAGluQ2lyY2xlRWRnZQAAAAA=","CMRQCIAABBYAAAEIXBAAACDQMAABRAFAAAAAAAAAAAAAAAEABYAAAAEAAAAAAAEEBQAAAAA":"CgAAAExTS1MyAgAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQ0IHVsb2NhbE1hdHJpeF9TMDsKaW4gZmxvYXQyIGluUG9zaXRpb247CmluIGhhbGY0IGluQ29sb3I7CmluIGZsb2F0MiBpbkVsbGlwc2VPZmZzZXQ7CmluIGZsb2F0NCBpbkVsbGlwc2VSYWRpaTsKb3V0IGZsb2F0MiB2RWxsaXBzZU9mZnNldHNfUzA7Cm91dCBmbG9hdDQgdkVsbGlwc2VSYWRpaV9TMDsKb3V0IGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBFbGxpcHNlR2VvbWV0cnlQcm9jZXNzb3IKCXZFbGxpcHNlT2Zmc2V0c19TMCA9IGluRWxsaXBzZU9mZnNldDsKCXZFbGxpcHNlUmFkaWlfUzAgPSBpbkVsbGlwc2VSYWRpaTsKCXZpbkNvbG9yX1MwID0gaW5Db2xvcjsKCWZsb2F0MiBfdG1wXzBfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247CglmbG9hdDIgX3RtcF8xX2luUG9zaXRpb24gPSB1bG9jYWxNYXRyaXhfUzAueHogKiBpblBvc2l0aW9uICsgdWxvY2FsTWF0cml4X1MwLnl3OwoJc2tfUG9zaXRpb24gPSBfdG1wXzBfaW5Qb3NpdGlvbi54eTAxOwp9CgAAAAAAAHIDAABpbiBmbG9hdDIgdkVsbGlwc2VPZmZzZXRzX1MwOwppbiBmbG9hdDQgdkVsbGlwc2VSYWRpaV9TMDsKaW4gaGFsZjQgdmluQ29sb3JfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBFbGxpcHNlR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2aW5Db2xvcl9TMDsKCWZsb2F0MiBvZmZzZXQgPSB2RWxsaXBzZU9mZnNldHNfUzAueHk7CglvZmZzZXQgKj0gdkVsbGlwc2VSYWRpaV9TMC54eTsKCWZsb2F0IHRlc3QgPSBkb3Qob2Zmc2V0LCBvZmZzZXQpIC0gMS4wOwoJZmxvYXQyIGdyYWQgPSAyLjAqb2Zmc2V0KnZFbGxpcHNlUmFkaWlfUzAueHk7CglmbG9hdCBncmFkX2RvdCA9IGRvdChncmFkLCBncmFkKTsKCWdyYWRfZG90ID0gbWF4KGdyYWRfZG90LCAxLjE3NTVlLTM4KTsKCWZsb2F0IGludmxlbiA9IGludmVyc2VzcXJ0KGdyYWRfZG90KTsKCWZsb2F0IGVkZ2VBbHBoYSA9IHNhdHVyYXRlKDAuNS10ZXN0Kmludmxlbik7CglvZmZzZXQgPSB2RWxsaXBzZU9mZnNldHNfUzAueHkqdkVsbGlwc2VSYWRpaV9TMC56dzsKCXRlc3QgPSBkb3Qob2Zmc2V0LCBvZmZzZXQpIC0gMS4wOwoJZ3JhZCA9IDIuMCpvZmZzZXQqdkVsbGlwc2VSYWRpaV9TMC56dzsKCWdyYWRfZG90ID0gZG90KGdyYWQsIGdyYWQpOwoJaW52bGVuID0gaW52ZXJzZXNxcnQoZ3JhZF9kb3QpOwoJZWRnZUFscGhhICo9IHNhdHVyYXRlKDAuNSt0ZXN0Kmludmxlbik7CgloYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KGhhbGYoZWRnZUFscGhhKSk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRDb3ZlcmFnZV9TMDsKCX0KfQoAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAEAAAACgAAAGluUG9zaXRpb24AAAcAAABpbkNvbG9yAA8AAABpbkVsbGlwc2VPZmZzZXQADgAAAGluRWxsaXBzZVJhZGlpAAAAAAAA","AYQA5AADQAAAOAEARAFQJAABBADIB7777777777777777777777767YAAAAAAAAAAAAOQAAAAAAAQAAAABAMQAAAAA":"CgAAAExTS1PMAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQ0IHVsb2NhbE1hdHJpeF9TMDsKaW4gZmxvYXQyIGluUG9zaXRpb247CmluIGhhbGY0IGluQ29sb3I7CmluIGZsb2F0NCBpbkNpcmNsZUVkZ2U7Cm91dCBmbG9hdDQgdmluQ2lyY2xlRWRnZV9TMDsKb3V0IGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBDaXJjbGVHZW9tZXRyeVByb2Nlc3NvcgoJdmluQ2lyY2xlRWRnZV9TMCA9IGluQ2lyY2xlRWRnZTsKCXZpbkNvbG9yX1MwID0gaW5Db2xvcjsKCWZsb2F0MiBfdG1wXzBfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247CglmbG9hdDIgX3RtcF8xX2luUG9zaXRpb24gPSB1bG9jYWxNYXRyaXhfUzAueHogKiBpblBvc2l0aW9uICsgdWxvY2FsTWF0cml4X1MwLnl3OwoJc2tfUG9zaXRpb24gPSBfdG1wXzBfaW5Qb3NpdGlvbi54eTAxOwp9CgAAAADqAQAAaW4gZmxvYXQ0IHZpbkNpcmNsZUVkZ2VfUzA7CmluIGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgQ2lyY2xlR2VvbWV0cnlQcm9jZXNzb3IKCWZsb2F0NCBjaXJjbGVFZGdlOwoJY2lyY2xlRWRnZSA9IHZpbkNpcmNsZUVkZ2VfUzA7CgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdmluQ29sb3JfUzA7CglmbG9hdCBkID0gbGVuZ3RoKGNpcmNsZUVkZ2UueHkpOwoJaGFsZiBkaXN0YW5jZVRvT3V0ZXJFZGdlID0gaGFsZihjaXJjbGVFZGdlLnogKiAoMS4wIC0gZCkpOwoJaGFsZiBlZGdlQWxwaGEgPSBzYXR1cmF0ZShkaXN0YW5jZVRvT3V0ZXJFZGdlKTsKCWhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoZWRnZUFscGhhKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAKAAAAaW5Qb3NpdGlvbgAABwAAAGluQ29sb3IADAAAAGluQ2lyY2xlRWRnZQAAAAA=","HVJAAAAAABIAAGAAAQ4AAAH477776R24EAAAIOBQAD6P7777777777YDAAAAABAAAAAABBAMADSAB4QAAAAAEAAAAAAHIAAAAAAAIAAAAAQGIAAAAAAA":"CgAAAExTS1MjAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gaGFsZjQgY29sb3I7CmluIGZsb2F0MiBsb2NhbENvb3JkOwpmbGF0IG91dCBoYWxmNCB2Y29sb3JfUzA7Cm91dCBmbG9hdDIgdmxvY2FsQ29vcmRfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJdmNvbG9yX1MwID0gY29sb3I7Cgl2bG9jYWxDb29yZF9TMCA9IGxvY2FsQ29vcmQ7Cglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cn0KAAEAAABfAwAAdW5pZm9ybSBmbG9hdDQgdWlubmVyUmVjdF9TMTsKdW5pZm9ybSBoYWxmMiB1cmFkaXVzUGx1c0hhbGZfUzE7CnVuaWZvcm0gc2FtcGxlcjJEIHVUZXh0dXJlU2FtcGxlcl8wX1MwOwpmbGF0IGluIGhhbGY0IHZjb2xvcl9TMDsKaW4gZmxvYXQyIHZsb2NhbENvb3JkX1MwOwpoYWxmNCBDaXJjdWxhclJSZWN0X1MxKGhhbGY0IF9pbnB1dCkgCnsKCWZsb2F0MiBkeHkwID0gdWlubmVyUmVjdF9TMS5MVCAtIHNrX0ZyYWdDb29yZC54eTsKCWZsb2F0MiBkeHkxID0gc2tfRnJhZ0Nvb3JkLnh5IC0gdWlubmVyUmVjdF9TMS5SQjsKCWZsb2F0MiBkeHkgPSBtYXgobWF4KGR4eTAsIGR4eTEpLCAwLjApOwoJaGFsZiBhbHBoYSA9IGhhbGYoc2F0dXJhdGUodXJhZGl1c1BsdXNIYWxmX1MxLnggLSBsZW5ndGgoZHh5KSkpOwoJcmV0dXJuIF9pbnB1dCAqIGFscGhhOwp9CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBRdWFkUGVyRWRnZUFBR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2Y29sb3JfUzA7CglmbG9hdDIgdGV4Q29vcmQ7Cgl0ZXhDb29yZCA9IHZsb2NhbENvb3JkX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSAoKHNhbXBsZSh1VGV4dHVyZVNhbXBsZXJfMF9TMCwgdGV4Q29vcmQpICogb3V0cHV0Q29sb3JfUzApKTsKCWNvbnN0IGhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoMSk7CgloYWxmNCBvdXRwdXRfUzE7CglvdXRwdXRfUzEgPSBDaXJjdWxhclJSZWN0X1MxKG91dHB1dENvdmVyYWdlX1MwKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dF9TMTsKCX0KfQoAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAIAAAAcG9zaXRpb24FAAAAY29sb3IAAAAKAAAAbG9jYWxDb29yZAAAAAAAAA==","AYQA5AADQAAAOAEARAFQJAABBADIB7777777777777777777777767YAAAAAAAAAACAAYQADAAAEAFEURUKQKAAAYAAAAAAAAIAAAABSCICWKY2FAEAAAMAAAAAAAAAAAAAIADQAAAAIAAAAAAAIIDAAAA":"CgAAAExTS1PMAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQ0IHVsb2NhbE1hdHJpeF9TMDsKaW4gZmxvYXQyIGluUG9zaXRpb247CmluIGhhbGY0IGluQ29sb3I7CmluIGZsb2F0NCBpbkNpcmNsZUVkZ2U7Cm91dCBmbG9hdDQgdmluQ2lyY2xlRWRnZV9TMDsKb3V0IGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBDaXJjbGVHZW9tZXRyeVByb2Nlc3NvcgoJdmluQ2lyY2xlRWRnZV9TMCA9IGluQ2lyY2xlRWRnZTsKCXZpbkNvbG9yX1MwID0gaW5Db2xvcjsKCWZsb2F0MiBfdG1wXzBfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247CglmbG9hdDIgX3RtcF8xX2luUG9zaXRpb24gPSB1bG9jYWxNYXRyaXhfUzAueHogKiBpblBvc2l0aW9uICsgdWxvY2FsTWF0cml4X1MwLnl3OwoJc2tfUG9zaXRpb24gPSBfdG1wXzBfaW5Qb3NpdGlvbi54eTAxOwp9CgEAAAB+BQAAY29uc3QgaW50IGtGaWxsQldfUzFfYzAgPSAwOwpjb25zdCBpbnQga0ludmVyc2VGaWxsQldfUzFfYzAgPSAyOwpjb25zdCBpbnQga0ludmVyc2VGaWxsQUFfUzFfYzAgPSAzOwp1bmlmb3JtIGZsb2F0NCB1cmVjdFVuaWZvcm1fUzFfYzA7CmluIGZsb2F0NCB2aW5DaXJjbGVFZGdlX1MwOwppbiBoYWxmNCB2aW5Db2xvcl9TMDsKaGFsZjQgUmVjdF9TMV9jMChoYWxmNCBfaW5wdXQpIAp7CgloYWxmNCBfdG1wXzBfaW5Db2xvciA9IF9pbnB1dDsKCWhhbGYgY292ZXJhZ2U7CglpZiAoaW50KDEpID09IGtGaWxsQldfUzFfYzAgfHwgaW50KDEpID09IGtJbnZlcnNlRmlsbEJXX1MxX2MwKSAKCXsKCQljb3ZlcmFnZSA9IGhhbGYoYWxsKGdyZWF0ZXJUaGFuKGZsb2F0NChza19GcmFnQ29vcmQueHksIHVyZWN0VW5pZm9ybV9TMV9jMC56dyksIGZsb2F0NCh1cmVjdFVuaWZvcm1fUzFfYzAueHksIHNrX0ZyYWdDb29yZC54eSkpKSk7Cgl9CgllbHNlIAoJewoJCWhhbGY0IGRpc3RzNCA9IHNhdHVyYXRlKGhhbGY0KDEuMCwgMS4wLCAtMS4wLCAtMS4wKSAqIGhhbGY0KHNrX0ZyYWdDb29yZC54eXh5IC0gdXJlY3RVbmlmb3JtX1MxX2MwKSk7CgkJaGFsZjIgZGlzdHMyID0gKGRpc3RzNC54eSArIGRpc3RzNC56dykgLSAxLjA7CgkJY292ZXJhZ2UgPSBkaXN0czIueCAqIGRpc3RzMi55OwoJfQoJaWYgKGludCgxKSA9PSBrSW52ZXJzZUZpbGxCV19TMV9jMCB8fCBpbnQoMSkgPT0ga0ludmVyc2VGaWxsQUFfUzFfYzApIAoJewoJCWNvdmVyYWdlID0gMS4wIC0gY292ZXJhZ2U7Cgl9CglyZXR1cm4gaGFsZjQoaGFsZjQoY292ZXJhZ2UpKTsKfQpoYWxmNCBCbGVuZF9TMShoYWxmNCBfc3JjLCBoYWxmNCBfZHN0KSAKewoJcmV0dXJuIGJsZW5kX21vZHVsYXRlKFJlY3RfUzFfYzAoX3NyYyksIF9zcmMpOwp9CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBDaXJjbGVHZW9tZXRyeVByb2Nlc3NvcgoJZmxvYXQ0IGNpcmNsZUVkZ2U7CgljaXJjbGVFZGdlID0gdmluQ2lyY2xlRWRnZV9TMDsKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2aW5Db2xvcl9TMDsKCWZsb2F0IGQgPSBsZW5ndGgoY2lyY2xlRWRnZS54eSk7CgloYWxmIGRpc3RhbmNlVG9PdXRlckVkZ2UgPSBoYWxmKGNpcmNsZUVkZ2UueiAqICgxLjAgLSBkKSk7CgloYWxmIGVkZ2VBbHBoYSA9IHNhdHVyYXRlKGRpc3RhbmNlVG9PdXRlckVkZ2UpOwoJaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNChlZGdlQWxwaGEpOwoJaGFsZjQgb3V0cHV0X1MxOwoJb3V0cHV0X1MxID0gQmxlbmRfUzEob3V0cHV0Q292ZXJhZ2VfUzAsIGhhbGY0KDEpKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dF9TMTsKCX0KfQoAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAADAAAACgAAAGluUG9zaXRpb24AAAcAAABpbkNvbG9yAAwAAABpbkNpcmNsZUVkZ2UAAAAA","HUIAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAAAAAALUAQAAEAQAAAAGQCBAMQAAAIAAAAAACQAGAAAAAQAAAAAAAQQGAAAAA":"CgAAAExTS1M2AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBmbG9hdDIgbG9jYWxDb29yZDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cgl7CgkJdlRyYW5zZm9ybWVkQ29vcmRzXzJfUzAgPSBmbG9hdDN4Mih1bWF0cml4X1MxKSAqIGxvY2FsQ29vcmQueHkxOwoJfQp9CgAAAAAAAHADAAB1bmlmb3JtIGZsb2F0NCB1Y2xhbXBfUzFfYzA7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKdW5pZm9ybSBzYW1wbGVyMkQgdVRleHR1cmVTYW1wbGVyXzBfUzE7CmluIGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKaGFsZjQgVGV4dHVyZUVmZmVjdF9TMV9jMChoYWxmNCBfaW5wdXQpIAp7CglmbG9hdDIgaW5Db29yZCA9IHZUcmFuc2Zvcm1lZENvb3Jkc18yX1MwOwoJZmxvYXQyIHN1YnNldENvb3JkOwoJc3Vic2V0Q29vcmQueCA9IGluQ29vcmQueDsKCXN1YnNldENvb3JkLnkgPSBpbkNvb3JkLnk7CglmbG9hdDIgY2xhbXBlZENvb3JkOwoJY2xhbXBlZENvb3JkLnggPSBzdWJzZXRDb29yZC54OwoJY2xhbXBlZENvb3JkLnkgPSBjbGFtcChzdWJzZXRDb29yZC55LCB1Y2xhbXBfUzFfYzAueSwgdWNsYW1wX1MxX2MwLncpOwoJaGFsZjQgdGV4dHVyZUNvbG9yID0gc2FtcGxlKHVUZXh0dXJlU2FtcGxlcl8wX1MxLCBjbGFtcGVkQ29vcmQpOwoJcmV0dXJuIHRleHR1cmVDb2xvcjsKfQpoYWxmNCBNYXRyaXhFZmZlY3RfUzEoaGFsZjQgX2lucHV0KSAKewoJcmV0dXJuIFRleHR1cmVFZmZlY3RfUzFfYzAoX2lucHV0KTsKfQp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMCA9IGhhbGY0KDEpOwoJY29uc3QgaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNCgxKTsKCWhhbGY0IG91dHB1dF9TMTsKCW91dHB1dF9TMSA9IE1hdHJpeEVmZmVjdF9TMShvdXRwdXRDb2xvcl9TMCk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0X1MxICogb3V0cHV0Q292ZXJhZ2VfUzA7Cgl9Cn0KAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAIAAAAcG9zaXRpb24KAAAAbG9jYWxDb29yZAAAAAAAAA==","HUJAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAQAAAAAAQQGABZAA6IAAAAACAAAAAADUAAAAAAAEAAAAAIDEAAAAAAA":"CgAAAExTS1PlAAAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gZmxvYXQyIGxvY2FsQ29vcmQ7Cm91dCBmbG9hdDIgdmxvY2FsQ29vcmRfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJdmxvY2FsQ29vcmRfUzAgPSBsb2NhbENvb3JkOwoJc2tfUG9zaXRpb24gPSBwb3NpdGlvbi54eTAxOwp9CgAAAAEAAAAuAwAAdW5pZm9ybSBmbG9hdDQgdWlubmVyUmVjdF9TMTsKdW5pZm9ybSBoYWxmMiB1cmFkaXVzUGx1c0hhbGZfUzE7CnVuaWZvcm0gc2FtcGxlcjJEIHVUZXh0dXJlU2FtcGxlcl8wX1MwOwppbiBmbG9hdDIgdmxvY2FsQ29vcmRfUzA7CmhhbGY0IENpcmN1bGFyUlJlY3RfUzEoaGFsZjQgX2lucHV0KSAKewoJZmxvYXQyIGR4eTAgPSB1aW5uZXJSZWN0X1MxLkxUIC0gc2tfRnJhZ0Nvb3JkLnh5OwoJZmxvYXQyIGR4eTEgPSBza19GcmFnQ29vcmQueHkgLSB1aW5uZXJSZWN0X1MxLlJCOwoJZmxvYXQyIGR4eSA9IG1heChtYXgoZHh5MCwgZHh5MSksIDAuMCk7CgloYWxmIGFscGhhID0gaGFsZihzYXR1cmF0ZSh1cmFkaXVzUGx1c0hhbGZfUzEueCAtIGxlbmd0aChkeHkpKSk7CglyZXR1cm4gX2lucHV0ICogYWxwaGE7Cn0Kdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJaGFsZjQgb3V0cHV0Q29sb3JfUzAgPSBoYWxmNCgxKTsKCWZsb2F0MiB0ZXhDb29yZDsKCXRleENvb3JkID0gdmxvY2FsQ29vcmRfUzA7CglvdXRwdXRDb2xvcl9TMCA9ICgoc2FtcGxlKHVUZXh0dXJlU2FtcGxlcl8wX1MwLCB0ZXhDb29yZCkgKiBoYWxmNCgxKSkpOwoJY29uc3QgaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNCgxKTsKCWhhbGY0IG91dHB1dF9TMTsKCW91dHB1dF9TMSA9IENpcmN1bGFyUlJlY3RfUzEob3V0cHV0Q292ZXJhZ2VfUzApOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dENvbG9yX1MwICogb3V0cHV0X1MxOwoJfQp9CgAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAIAAAAcG9zaXRpb24KAAAAbG9jYWxDb29yZAAAAAAAAA==","HUJAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAQAAAAAAQQGAAZAADIAAAACU53QJEKAAAAAAMAAAAAIAAAAAAGIRDFB2XASAUAABQAAAAAAAAAAAAADUAAAAAAAEAAAAAIDEAAA":"CgAAAExTS1PlAAAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gZmxvYXQyIGxvY2FsQ29vcmQ7Cm91dCBmbG9hdDIgdmxvY2FsQ29vcmRfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJdmxvY2FsQ29vcmRfUzAgPSBsb2NhbENvb3JkOwoJc2tfUG9zaXRpb24gPSBwb3NpdGlvbi54eTAxOwp9CgAAAAEAAACrBAAAY29uc3QgaW50IGtGaWxsQUFfUzFfYzAgPSAxOwpjb25zdCBpbnQga0ludmVyc2VGaWxsQldfUzFfYzAgPSAyOwpjb25zdCBpbnQga0ludmVyc2VGaWxsQUFfUzFfYzAgPSAzOwp1bmlmb3JtIGZsb2F0NCB1Y2lyY2xlX1MxX2MwOwp1bmlmb3JtIHNhbXBsZXIyRCB1VGV4dHVyZVNhbXBsZXJfMF9TMDsKaW4gZmxvYXQyIHZsb2NhbENvb3JkX1MwOwpoYWxmNCBDaXJjbGVfUzFfYzAoaGFsZjQgX2lucHV0KSAKewoJaGFsZjQgX3RtcF8wX2luQ29sb3IgPSBfaW5wdXQ7CgloYWxmIGQ7CglpZiAoaW50KDEpID09IGtJbnZlcnNlRmlsbEJXX1MxX2MwIHx8IGludCgxKSA9PSBrSW52ZXJzZUZpbGxBQV9TMV9jMCkgCgl7CgkJZCA9IGhhbGYoKGxlbmd0aCgodWNpcmNsZV9TMV9jMC54eSAtIHNrX0ZyYWdDb29yZC54eSkgKiB1Y2lyY2xlX1MxX2MwLncpIC0gMS4wKSAqIHVjaXJjbGVfUzFfYzAueik7Cgl9CgllbHNlIAoJewoJCWQgPSBoYWxmKCgxLjAgLSBsZW5ndGgoKHVjaXJjbGVfUzFfYzAueHkgLSBza19GcmFnQ29vcmQueHkpICogdWNpcmNsZV9TMV9jMC53KSkgKiB1Y2lyY2xlX1MxX2MwLnopOwoJfQoJcmV0dXJuIGhhbGY0KGhhbGY0KGludCgxKSA9PSBrRmlsbEFBX1MxX2MwIHx8IGludCgxKSA9PSBrSW52ZXJzZUZpbGxBQV9TMV9jMCA/IHNhdHVyYXRlKGQpIDogaGFsZihkID4gMC41ID8gMSA6IDApKSk7Cn0KaGFsZjQgQmxlbmRfUzEoaGFsZjQgX3NyYywgaGFsZjQgX2RzdCkgCnsKCXJldHVybiBibGVuZF9tb2R1bGF0ZShfc3JjLCBDaXJjbGVfUzFfYzAoX3NyYykpOwp9CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBRdWFkUGVyRWRnZUFBR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwID0gaGFsZjQoMSk7CglmbG9hdDIgdGV4Q29vcmQ7Cgl0ZXhDb29yZCA9IHZsb2NhbENvb3JkX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSAoKHNhbXBsZSh1VGV4dHVyZVNhbXBsZXJfMF9TMCwgdGV4Q29vcmQpICogaGFsZjQoMSkpKTsKCWNvbnN0IGhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoMSk7CgloYWxmNCBvdXRwdXRfUzE7CglvdXRwdXRfUzEgPSBCbGVuZF9TMShvdXRwdXRDb3ZlcmFnZV9TMCwgaGFsZjQoMSkpOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dENvbG9yX1MwICogb3V0cHV0X1MxOwoJfQp9CgABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAgAAABwb3NpdGlvbgoAAABsb2NhbENvb3JkAAAAAAAA","HVIAAAAAABIAAGAAAQ4AAAH477776R24EAAAIOBQAD6P7777777777YDAAAAAAAAAAAFIBQU7BTXIAAAAAACAWXW3ZEQAAAADAAAAAGATHIBICYCAAAEBP2LBIPAAAAAIAAAAAEARRALJ3F5SMAAAABQAAAABABTUEURMBAAACAH5FYUHQAAAAAAAEAAAAAZ4RGGRCQFAEAAAAAAAAAGARP2LVJPAAAAAAAAEAAAABSKRXZFAUHQAAAAAAAAAACAA4AAAACAAAAAAACCAYAA":"CgAAAExTS1OAAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMV9jMF9jMTsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBoYWxmNCBjb2xvcjsKaW4gZmxvYXQyIGxvY2FsQ29vcmQ7CmZsYXQgb3V0IGhhbGY0IHZjb2xvcl9TMDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfNV9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgl2Y29sb3JfUzAgPSBjb2xvcjsKCXNrX1Bvc2l0aW9uID0gcG9zaXRpb24ueHkwMTsKCXsKCQl2VHJhbnNmb3JtZWRDb29yZHNfNV9TMCA9IGZsb2F0M3gyKHVtYXRyaXhfUzFfYzBfYzEpICogbG9jYWxDb29yZC54eTE7Cgl9Cn0KAAAAAIIGAAB1bmlmb3JtIGhhbGY0IHVzdGFydF9TMV9jMF9jMDsKdW5pZm9ybSBoYWxmNCB1ZW5kX1MxX2MwX2MwOwp1bmlmb3JtIGZsb2F0M3gzIHVtYXRyaXhfUzFfYzBfYzE7CnVuaWZvcm0gaGFsZjQgdWxlZnRCb3JkZXJDb2xvcl9TMV9jMDsKdW5pZm9ybSBoYWxmNCB1cmlnaHRCb3JkZXJDb2xvcl9TMV9jMDsKZmxhdCBpbiBoYWxmNCB2Y29sb3JfUzA7CmluIGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfNV9TMDsKaGFsZjQgU2luZ2xlSW50ZXJ2YWxDb2xvcml6ZXJfUzFfYzBfYzAoaGFsZjQgX2lucHV0LCBmbG9hdDIgX2Nvb3JkcykgCnsKCWhhbGY0IF90bXBfMF9pbkNvbG9yID0gX2lucHV0OwoJZmxvYXQyIF90bXBfMV9jb29yZHMgPSBfY29vcmRzOwoJcmV0dXJuIGhhbGY0KG1peCh1c3RhcnRfUzFfYzBfYzAsIHVlbmRfUzFfYzBfYzAsIGhhbGYoX3RtcF8xX2Nvb3Jkcy54KSkpOwp9CmhhbGY0IExpbmVhckxheW91dF9TMV9jMF9jMV9jMChoYWxmNCBfaW5wdXQpIAp7CgloYWxmNCBfdG1wXzJfaW5Db2xvciA9IF9pbnB1dDsKCWZsb2F0MiBfdG1wXzNfY29vcmRzID0gdlRyYW5zZm9ybWVkQ29vcmRzXzVfUzA7CglyZXR1cm4gaGFsZjQoaGFsZjQoaGFsZihfdG1wXzNfY29vcmRzLngpICsgMWUtMDUsIDEuMCwgMC4wLCAwLjApKTsKfQpoYWxmNCBNYXRyaXhFZmZlY3RfUzFfYzBfYzEoaGFsZjQgX2lucHV0KSAKewoJcmV0dXJuIExpbmVhckxheW91dF9TMV9jMF9jMV9jMChfaW5wdXQpOwp9CmhhbGY0IENsYW1wZWRHcmFkaWVudF9TMV9jMChoYWxmNCBfaW5wdXQpIAp7CgloYWxmNCBfdG1wXzRfaW5Db2xvciA9IF9pbnB1dDsKCWhhbGY0IHQgPSBNYXRyaXhFZmZlY3RfUzFfYzBfYzEoX3RtcF80X2luQ29sb3IpOwoJaGFsZjQgb3V0Q29sb3I7CglpZiAoIWJvb2woaW50KDEpKSAmJiB0LnkgPCAwLjApIAoJewoJCW91dENvbG9yID0gaGFsZjQoMC4wKTsKCX0KCWVsc2UgaWYgKHQueCA8IDAuMCkgCgl7CgkJb3V0Q29sb3IgPSB1bGVmdEJvcmRlckNvbG9yX1MxX2MwOwoJfQoJZWxzZSBpZiAodC54ID4gMS4wKSAKCXsKCQlvdXRDb2xvciA9IHVyaWdodEJvcmRlckNvbG9yX1MxX2MwOwoJfQoJZWxzZSAKCXsKCQlvdXRDb2xvciA9IFNpbmdsZUludGVydmFsQ29sb3JpemVyX1MxX2MwX2MwKF90bXBfNF9pbkNvbG9yLCBmbG9hdDIoaGFsZjIodC54LCAwLjApKSk7Cgl9CglyZXR1cm4gaGFsZjQob3V0Q29sb3IpOwp9CmhhbGY0IERpc2FibGVDb3ZlcmFnZUFzQWxwaGFfUzEoaGFsZjQgX2lucHV0KSAKewoJX2lucHV0ID0gQ2xhbXBlZEdyYWRpZW50X1MxX2MwKF9pbnB1dCk7CgloYWxmNCBfdG1wXzVfaW5Db2xvciA9IF9pbnB1dDsKCXJldHVybiBoYWxmNChfaW5wdXQpOwp9CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBRdWFkUGVyRWRnZUFBR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2Y29sb3JfUzA7Cgljb25zdCBoYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KDEpOwoJaGFsZjQgb3V0cHV0X1MxOwoJb3V0cHV0X1MxID0gRGlzYWJsZUNvdmVyYWdlQXNBbHBoYV9TMShvdXRwdXRDb2xvcl9TMCk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0X1MxICogb3V0cHV0Q292ZXJhZ2VfUzA7Cgl9Cn0KAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAgAAABwb3NpdGlvbgUAAABjb2xvcgAAAAoAAABsb2NhbENvb3JkAAAAAAAA","FAAQMYAAMAAAEADAAABAEYAAAICIAB5AABQAAAQAMAAAEATAAABAIIGAAEDCBYQCA4AAAAAAEADZABYAAAIAAAAAACQAGAAAAAQAAAAAAAQQG":"CgAAAExTS1PUCwAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0NCByYWRpaV9zZWxlY3RvcjsKaW4gZmxvYXQ0IGNvcm5lcl9hbmRfcmFkaXVzX291dHNldHM7CmluIGZsb2F0NCBhYV9ibG9hdF9hbmRfY292ZXJhZ2U7CmluIGZsb2F0NCByYWRpaV94OwppbiBmbG9hdDQgcmFkaWlfeTsKaW4gZmxvYXQ0IHNrZXc7CmluIGZsb2F0MiB0cmFuc2xhdGVfYW5kX2xvY2Fscm90YXRlOwppbiBoYWxmNCBjb2xvcjsKZmxhdCBvdXQgaGFsZjQgdmNvbG9yX1MwOwpvdXQgZmxvYXQyIHZhcmNjb29yZF9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgRmlsbFJSZWN0T3A6OlByb2Nlc3NvcgoJdmNvbG9yX1MwID0gY29sb3I7CglmbG9hdCBhYV9ibG9hdF9tdWx0aXBsaWVyID0gMTsKCWZsb2F0MiBjb3JuZXIgPSBjb3JuZXJfYW5kX3JhZGl1c19vdXRzZXRzLnh5OwoJZmxvYXQyIHJhZGl1c19vdXRzZXQgPSBjb3JuZXJfYW5kX3JhZGl1c19vdXRzZXRzLnp3OwoJZmxvYXQyIGFhX2Jsb2F0X2RpcmVjdGlvbiA9IGFhX2Jsb2F0X2FuZF9jb3ZlcmFnZS54eTsKCWZsb2F0IGlzX2xpbmVhcl9jb3ZlcmFnZSA9IGFhX2Jsb2F0X2FuZF9jb3ZlcmFnZS53OwoJZmxvYXQyIHBpeGVsbGVuZ3RoID0gaW52ZXJzZXNxcnQoZmxvYXQyKGRvdChza2V3Lnh6LCBza2V3Lnh6KSwgZG90KHNrZXcueXcsIHNrZXcueXcpKSk7CglmbG9hdDQgbm9ybWFsaXplZF9heGlzX2RpcnMgPSBza2V3ICogcGl4ZWxsZW5ndGgueHl4eTsKCWZsb2F0MiBheGlzd2lkdGhzID0gKGFicyhub3JtYWxpemVkX2F4aXNfZGlycy54eSkgKyBhYnMobm9ybWFsaXplZF9heGlzX2RpcnMuencpKTsKCWZsb2F0MiBhYV9ibG9hdHJhZGl1cyA9IGF4aXN3aWR0aHMgKiBwaXhlbGxlbmd0aCAqIC41OwoJZmxvYXQ0IHJhZGlpX2FuZF9uZWlnaGJvcnMgPSByYWRpaV9zZWxlY3RvciogZmxvYXQ0eDQocmFkaWlfeCwgcmFkaWlfeSwgcmFkaWlfeC55eHd6LCByYWRpaV95Lnd6eXgpOwoJZmxvYXQyIHJhZGlpID0gcmFkaWlfYW5kX25laWdoYm9ycy54eTsKCWZsb2F0MiBuZWlnaGJvcl9yYWRpaSA9IHJhZGlpX2FuZF9uZWlnaGJvcnMuenc7CglmbG9hdCBjb3ZlcmFnZV9tdWx0aXBsaWVyID0gMTsKCWlmIChhbnkoZ3JlYXRlclRoYW4oYWFfYmxvYXRyYWRpdXMsIGZsb2F0MigxKSkpKSAKCXsKCQljb3JuZXIgPSBtYXgoYWJzKGNvcm5lciksIGFhX2Jsb2F0cmFkaXVzKSAqIHNpZ24oY29ybmVyKTsKCQljb3ZlcmFnZV9tdWx0aXBsaWVyID0gMSAvIChtYXgoYWFfYmxvYXRyYWRpdXMueCwgMSkgKiBtYXgoYWFfYmxvYXRyYWRpdXMueSwgMSkpOwoJCXJhZGlpID0gZmxvYXQyKDApOwoJfQoJZmxvYXQgY292ZXJhZ2UgPSBhYV9ibG9hdF9hbmRfY292ZXJhZ2UuejsKCWlmIChhbnkobGVzc1RoYW4ocmFkaWksIGFhX2Jsb2F0cmFkaXVzICogMS41KSkpIAoJewoJCXJhZGlpID0gZmxvYXQyKDApOwoJCWFhX2Jsb2F0X2RpcmVjdGlvbiA9IHNpZ24oY29ybmVyKTsKCQlpZiAoY292ZXJhZ2UgPiAuNSkgCgkJewoJCQlhYV9ibG9hdF9kaXJlY3Rpb24gPSAtYWFfYmxvYXRfZGlyZWN0aW9uOwoJCX0KCQlpc19saW5lYXJfY292ZXJhZ2UgPSAxOwoJfQoJZWxzZSAKCXsKCQlyYWRpaSA9IGNsYW1wKHJhZGlpLCBwaXhlbGxlbmd0aCAqIDEuNSwgMiAtIHBpeGVsbGVuZ3RoICogMS41KTsKCQluZWlnaGJvcl9yYWRpaSA9IGNsYW1wKG5laWdoYm9yX3JhZGlpLCBwaXhlbGxlbmd0aCAqIDEuNSwgMiAtIHBpeGVsbGVuZ3RoICogMS41KTsKCQlmbG9hdDIgc3BhY2luZyA9IDIgLSByYWRpaSAtIG5laWdoYm9yX3JhZGlpOwoJCWZsb2F0MiBleHRyYV9wYWQgPSBtYXgocGl4ZWxsZW5ndGggKiAuMDYyNSAtIHNwYWNpbmcsIGZsb2F0MigwKSk7CgkJcmFkaWkgLT0gZXh0cmFfcGFkICogLjU7Cgl9CglmbG9hdDIgYWFfb3V0c2V0ID0gYWFfYmxvYXRfZGlyZWN0aW9uICogYWFfYmxvYXRyYWRpdXMgKiBhYV9ibG9hdF9tdWx0aXBsaWVyOwoJZmxvYXQyIHZlcnRleHBvcyA9IGNvcm5lciArIHJhZGl1c19vdXRzZXQgKiByYWRpaSArIGFhX291dHNldDsKCWlmIChjb3ZlcmFnZSA+IC41KSAKCXsKCQlpZiAoYWFfYmxvYXRfZGlyZWN0aW9uLnggIT0gMCAmJiB2ZXJ0ZXhwb3MueCAqIGNvcm5lci54IDwgMCkgCgkJewoJCQlmbG9hdCBiYWNrc2V0ID0gYWJzKHZlcnRleHBvcy54KTsKCQkJdmVydGV4cG9zLnggPSAwOwoJCQl2ZXJ0ZXhwb3MueSArPSBiYWNrc2V0ICogc2lnbihjb3JuZXIueSkgKiBwaXhlbGxlbmd0aC55L3BpeGVsbGVuZ3RoLng7CgkJCWNvdmVyYWdlID0gKGNvdmVyYWdlIC0gLjUpICogYWJzKGNvcm5lci54KSAvIChhYnMoY29ybmVyLngpICsgYmFja3NldCkgKyAuNTsKCQl9CgkJaWYgKGFhX2Jsb2F0X2RpcmVjdGlvbi55ICE9IDAgJiYgdmVydGV4cG9zLnkgKiBjb3JuZXIueSA8IDApIAoJCXsKCQkJZmxvYXQgYmFja3NldCA9IGFicyh2ZXJ0ZXhwb3MueSk7CgkJCXZlcnRleHBvcy55ID0gMDsKCQkJdmVydGV4cG9zLnggKz0gYmFja3NldCAqIHNpZ24oY29ybmVyLngpICogcGl4ZWxsZW5ndGgueC9waXhlbGxlbmd0aC55OwoJCQljb3ZlcmFnZSA9IChjb3ZlcmFnZSAtIC41KSAqIGFicyhjb3JuZXIueSkgLyAoYWJzKGNvcm5lci55KSArIGJhY2tzZXQpICsgLjU7CgkJfQoJfQoJZmxvYXQyeDIgc2tld21hdHJpeCA9IGZsb2F0MngyKHNrZXcueHksIHNrZXcuencpOwoJZmxvYXQyIGRldmNvb3JkID0gdmVydGV4cG9zICogc2tld21hdHJpeCArIHRyYW5zbGF0ZV9hbmRfbG9jYWxyb3RhdGUueHk7CglpZiAoMCAhPSBpc19saW5lYXJfY292ZXJhZ2UpIAoJewoJCXZhcmNjb29yZF9TMC54eSA9IGZsb2F0MigwLCBjb3ZlcmFnZSAqIGNvdmVyYWdlX211bHRpcGxpZXIpOwoJfQoJZWxzZSAKCXsKCQlmbG9hdDIgYXJjY29vcmQgPSAxIC0gYWJzKHJhZGl1c19vdXRzZXQpICsgYWFfb3V0c2V0L3JhZGlpICogY29ybmVyOwoJCXZhcmNjb29yZF9TMC54eSA9IGZsb2F0MihhcmNjb29yZC54KzEsIGFyY2Nvb3JkLnkpOwoJfQoJc2tfUG9zaXRpb24gPSBkZXZjb29yZC54eTAxOwp9CgEAAADUAwAAdW5pZm9ybSBmbG9hdDQgdWlubmVyUmVjdF9TMTsKdW5pZm9ybSBoYWxmMiB1cmFkaXVzUGx1c0hhbGZfUzE7CmZsYXQgaW4gaGFsZjQgdmNvbG9yX1MwOwppbiBmbG9hdDIgdmFyY2Nvb3JkX1MwOwpoYWxmNCBDaXJjdWxhclJSZWN0X1MxKGhhbGY0IF9pbnB1dCkgCnsKCWZsb2F0MiBkeHkwID0gdWlubmVyUmVjdF9TMS5MVCAtIHNrX0ZyYWdDb29yZC54eTsKCWZsb2F0MiBkeHkxID0gc2tfRnJhZ0Nvb3JkLnh5IC0gdWlubmVyUmVjdF9TMS5SQjsKCWZsb2F0MiBkeHkgPSBtYXgobWF4KGR4eTAsIGR4eTEpLCAwLjApOwoJaGFsZiBhbHBoYSA9IGhhbGYoc2F0dXJhdGUodXJhZGl1c1BsdXNIYWxmX1MxLnggLSBsZW5ndGgoZHh5KSkpOwoJcmV0dXJuIF9pbnB1dCAqIGFscGhhOwp9CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBGaWxsUlJlY3RPcDo6UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdmNvbG9yX1MwOwoJZmxvYXQgeF9wbHVzXzE9dmFyY2Nvb3JkX1MwLngsIHk9dmFyY2Nvb3JkX1MwLnk7CgloYWxmIGNvdmVyYWdlOwoJaWYgKDAgPT0geF9wbHVzXzEpIAoJewoJCWNvdmVyYWdlID0gaGFsZih5KTsKCX0KCWVsc2UgCgl7CgkJZmxvYXQgZm4gPSB4X3BsdXNfMSAqICh4X3BsdXNfMSAtIDIpOwoJCWZuID0gZm1hKHkseSwgZm4pOwoJCWZsb2F0IGZud2lkdGggPSBmd2lkdGgoZm4pOwoJCWNvdmVyYWdlID0gLjUgLSBoYWxmKGZuL2Zud2lkdGgpOwoJCWNvdmVyYWdlID0gY2xhbXAoY292ZXJhZ2UsIDAsIDEpOwoJfQoJaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNChjb3ZlcmFnZSk7CgloYWxmNCBvdXRwdXRfUzE7CglvdXRwdXRfUzEgPSBDaXJjdWxhclJSZWN0X1MxKG91dHB1dENvdmVyYWdlX1MwKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dF9TMTsKCX0KfQoBAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAACAAAAA4AAAByYWRpaV9zZWxlY3RvcgAAGQAAAGNvcm5lcl9hbmRfcmFkaXVzX291dHNldHMAAAAVAAAAYWFfYmxvYXRfYW5kX2NvdmVyYWdlAAAABwAAAHJhZGlpX3gABwAAAHJhZGlpX3kABAAAAHNrZXcZAAAAdHJhbnNsYXRlX2FuZF9sb2NhbHJvdGF0ZQAAAAUAAABjb2xvcgAAAAAAAAA=","DAQAAAAAAABGAABAYAAQAIHCAIAYAQUBAEAAAAAAEAAAAAAAAAAAAAB2AAAAAAACAAAAAEBSAAAAA":"CgAAAExTS1MWAgAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQyIHVBdGxhc1NpemVJbnZfUzA7CmluIGZsb2F0MiBpblBvc2l0aW9uOwppbiBoYWxmNCBpbkNvbG9yOwppbiB1c2hvcnQyIGluVGV4dHVyZUNvb3JkczsKb3V0IGZsb2F0MiB2VGV4dHVyZUNvb3Jkc19TMDsKZmxhdCBvdXQgZmxvYXQgdlRleEluZGV4X1MwOwpvdXQgaGFsZjQgdmluQ29sb3JfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIEJpdG1hcFRleHQKCWludCB0ZXhJZHggPSAwOwoJZmxvYXQyIHVub3JtVGV4Q29vcmRzID0gZmxvYXQyKGluVGV4dHVyZUNvb3Jkcy54LCBpblRleHR1cmVDb29yZHMueSk7Cgl2VGV4dHVyZUNvb3Jkc19TMCA9IHVub3JtVGV4Q29vcmRzICogdUF0bGFzU2l6ZUludl9TMDsKCXZUZXhJbmRleF9TMCA9IGZsb2F0KHRleElkeCk7Cgl2aW5Db2xvcl9TMCA9IGluQ29sb3I7CglmbG9hdDIgX3RtcF8xX2luUG9zaXRpb24gPSBpblBvc2l0aW9uOwoJc2tfUG9zaXRpb24gPSBpblBvc2l0aW9uLnh5MDE7Cn0KAAAAAAAAsQEAAHVuaWZvcm0gc2FtcGxlcjJEIHVUZXh0dXJlU2FtcGxlcl8wX1MwOwppbiBmbG9hdDIgdlRleHR1cmVDb29yZHNfUzA7CmZsYXQgaW4gZmxvYXQgdlRleEluZGV4X1MwOwppbiBoYWxmNCB2aW5Db2xvcl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIEJpdG1hcFRleHQKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2aW5Db2xvcl9TMDsKCWhhbGY0IHRleENvbG9yOwoJewoJCXRleENvbG9yID0gc2FtcGxlKHVUZXh0dXJlU2FtcGxlcl8wX1MwLCB2VGV4dHVyZUNvb3Jkc19TMCkucnJycjsKCX0KCWhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gdGV4Q29sb3I7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRDb3ZlcmFnZV9TMDsKCX0KfQoAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAoAAABpblBvc2l0aW9uAAAHAAAAaW5Db2xvcgAPAAAAaW5UZXh0dXJlQ29vcmRzAAAAAAA=","HUIAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAAAAAALUAQBAEAQAAAAGQCBAMQACAIAAAAAACQAGAAAAAQAAAAAAAQQGAAAAA":"CgAAAExTS1M2AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBmbG9hdDIgbG9jYWxDb29yZDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cgl7CgkJdlRyYW5zZm9ybWVkQ29vcmRzXzJfUzAgPSBmbG9hdDN4Mih1bWF0cml4X1MxKSAqIGxvY2FsQ29vcmQueHkxOwoJfQp9CgAAAAAAAE0DAAB1bmlmb3JtIGZsb2F0NCB1Y2xhbXBfUzFfYzA7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKdW5pZm9ybSBzYW1wbGVyMkQgdVRleHR1cmVTYW1wbGVyXzBfUzE7CmluIGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKaGFsZjQgVGV4dHVyZUVmZmVjdF9TMV9jMChoYWxmNCBfaW5wdXQpIAp7CglmbG9hdDIgaW5Db29yZCA9IHZUcmFuc2Zvcm1lZENvb3Jkc18yX1MwOwoJZmxvYXQyIHN1YnNldENvb3JkOwoJc3Vic2V0Q29vcmQueCA9IGluQ29vcmQueDsKCXN1YnNldENvb3JkLnkgPSBpbkNvb3JkLnk7CglmbG9hdDIgY2xhbXBlZENvb3JkOwoJY2xhbXBlZENvb3JkID0gY2xhbXAoc3Vic2V0Q29vcmQsIHVjbGFtcF9TMV9jMC54eSwgdWNsYW1wX1MxX2MwLnp3KTsKCWhhbGY0IHRleHR1cmVDb2xvciA9IHNhbXBsZSh1VGV4dHVyZVNhbXBsZXJfMF9TMSwgY2xhbXBlZENvb3JkKTsKCXJldHVybiB0ZXh0dXJlQ29sb3I7Cn0KaGFsZjQgTWF0cml4RWZmZWN0X1MxKGhhbGY0IF9pbnB1dCkgCnsKCXJldHVybiBUZXh0dXJlRWZmZWN0X1MxX2MwKF9pbnB1dCk7Cn0Kdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJaGFsZjQgb3V0cHV0Q29sb3JfUzAgPSBoYWxmNCgxKTsKCWNvbnN0IGhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoMSk7CgloYWxmNCBvdXRwdXRfUzE7CglvdXRwdXRfUzEgPSBNYXRyaXhFZmZlY3RfUzEob3V0cHV0Q29sb3JfUzApOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dF9TMSAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAACAAAACAAAAHBvc2l0aW9uCgAAAGxvY2FsQ29vcmQAAAAAAAA=","HVJAAAAAABIAAGAAAQ4AAAH477776R24EAAAIOBQAD6P7777777777YDAAAAABAAAAAABBAMABAAOAAAABAAAAAAABBAMAAA":"CgAAAExTS1MjAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gaGFsZjQgY29sb3I7CmluIGZsb2F0MiBsb2NhbENvb3JkOwpmbGF0IG91dCBoYWxmNCB2Y29sb3JfUzA7Cm91dCBmbG9hdDIgdmxvY2FsQ29vcmRfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJdmNvbG9yX1MwID0gY29sb3I7Cgl2bG9jYWxDb29yZF9TMCA9IGxvY2FsQ29vcmQ7Cglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cn0KAAAAAADQAQAAdW5pZm9ybSBzYW1wbGVyMkQgdVRleHR1cmVTYW1wbGVyXzBfUzA7CmZsYXQgaW4gaGFsZjQgdmNvbG9yX1MwOwppbiBmbG9hdDIgdmxvY2FsQ29vcmRfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBRdWFkUGVyRWRnZUFBR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2Y29sb3JfUzA7CglmbG9hdDIgdGV4Q29vcmQ7Cgl0ZXhDb29yZCA9IHZsb2NhbENvb3JkX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSAoKHNhbXBsZSh1VGV4dHVyZVNhbXBsZXJfMF9TMCwgdGV4Q29vcmQpICogb3V0cHV0Q29sb3JfUzApKTsKCWNvbnN0IGhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoMSk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRDb3ZlcmFnZV9TMDsKCX0KfQoAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAgAAABwb3NpdGlvbgUAAABjb2xvcgAAAAoAAABsb2NhbENvb3JkAAAAAAAA","HUIAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAAAAAALUAQBAAAQAAAAGQCBAMQACAAAAAAAACQAGAAAAAQAAAAAAAQQGAAAAA":"CgAAAExTS1M2AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBmbG9hdDIgbG9jYWxDb29yZDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cgl7CgkJdlRyYW5zZm9ybWVkQ29vcmRzXzJfUzAgPSBmbG9hdDN4Mih1bWF0cml4X1MxKSAqIGxvY2FsQ29vcmQueHkxOwoJfQp9CgAAAAAAAHADAAB1bmlmb3JtIGZsb2F0NCB1Y2xhbXBfUzFfYzA7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKdW5pZm9ybSBzYW1wbGVyMkQgdVRleHR1cmVTYW1wbGVyXzBfUzE7CmluIGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKaGFsZjQgVGV4dHVyZUVmZmVjdF9TMV9jMChoYWxmNCBfaW5wdXQpIAp7CglmbG9hdDIgaW5Db29yZCA9IHZUcmFuc2Zvcm1lZENvb3Jkc18yX1MwOwoJZmxvYXQyIHN1YnNldENvb3JkOwoJc3Vic2V0Q29vcmQueCA9IGluQ29vcmQueDsKCXN1YnNldENvb3JkLnkgPSBpbkNvb3JkLnk7CglmbG9hdDIgY2xhbXBlZENvb3JkOwoJY2xhbXBlZENvb3JkLnggPSBjbGFtcChzdWJzZXRDb29yZC54LCB1Y2xhbXBfUzFfYzAueCwgdWNsYW1wX1MxX2MwLnopOwoJY2xhbXBlZENvb3JkLnkgPSBzdWJzZXRDb29yZC55OwoJaGFsZjQgdGV4dHVyZUNvbG9yID0gc2FtcGxlKHVUZXh0dXJlU2FtcGxlcl8wX1MxLCBjbGFtcGVkQ29vcmQpOwoJcmV0dXJuIHRleHR1cmVDb2xvcjsKfQpoYWxmNCBNYXRyaXhFZmZlY3RfUzEoaGFsZjQgX2lucHV0KSAKewoJcmV0dXJuIFRleHR1cmVFZmZlY3RfUzFfYzAoX2lucHV0KTsKfQp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMCA9IGhhbGY0KDEpOwoJY29uc3QgaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNCgxKTsKCWhhbGY0IG91dHB1dF9TMTsKCW91dHB1dF9TMSA9IE1hdHJpeEVmZmVjdF9TMShvdXRwdXRDb2xvcl9TMCk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0X1MxICogb3V0cHV0Q292ZXJhZ2VfUzA7Cgl9Cn0KAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAIAAAAcG9zaXRpb24KAAAAbG9jYWxDb29yZAAAAAAAAA==","EADQAAAAAEAAAAAUAABQAAQPAAABCFYMAAKAUEAAAAAAAAABAAAAAAAAAAANAAIAAAABAAAAACAJAAIAAAAA":"CgAAAExTS1NyAgAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQyIHVBdGxhc0RpbWVuc2lvbnNJbnZfUzA7CmluIGZsb2F0MyBpblBvc2l0aW9uOwppbiBoYWxmNCBpbkNvbG9yOwppbiB1c2hvcnQyIGluVGV4dHVyZUNvb3JkczsKb3V0IGZsb2F0MiB2VGV4dHVyZUNvb3Jkc19TMDsKZmxhdCBvdXQgZmxvYXQgdlRleEluZGV4X1MwOwpvdXQgZmxvYXQyIHZJbnRUZXh0dXJlQ29vcmRzX1MwOwpvdXQgaGFsZjQgdmluQ29sb3JfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIERpc3RhbmNlRmllbGRQYXRoCglpbnQgdGV4SWR4ID0gMDsKCWZsb2F0MiB1bm9ybVRleENvb3JkcyA9IGZsb2F0MihpblRleHR1cmVDb29yZHMueCwgaW5UZXh0dXJlQ29vcmRzLnkpOwoJdlRleHR1cmVDb29yZHNfUzAgPSB1bm9ybVRleENvb3JkcyAqIHVBdGxhc0RpbWVuc2lvbnNJbnZfUzA7Cgl2VGV4SW5kZXhfUzAgPSBmbG9hdCh0ZXhJZHgpOwoJdkludFRleHR1cmVDb29yZHNfUzAgPSB1bm9ybVRleENvb3JkczsKCXZpbkNvbG9yX1MwID0gaW5Db2xvcjsKCWZsb2F0MyBfdG1wXzFfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247Cglza19Qb3NpdGlvbiA9IGluUG9zaXRpb24ueHkwejsKfQoAAAAAAACfAgAAdW5pZm9ybSBzYW1wbGVyMkQgdVRleHR1cmVTYW1wbGVyXzBfUzA7CmluIGZsb2F0MiB2VGV4dHVyZUNvb3Jkc19TMDsKZmxhdCBpbiBmbG9hdCB2VGV4SW5kZXhfUzA7CmluIGZsb2F0MiB2SW50VGV4dHVyZUNvb3Jkc19TMDsKaW4gaGFsZjQgdmluQ29sb3JfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBEaXN0YW5jZUZpZWxkUGF0aAoJaGFsZjQgb3V0cHV0Q29sb3JfUzA7CglvdXRwdXRDb2xvcl9TMCA9IHZpbkNvbG9yX1MwOwoJZmxvYXQyIHV2ID0gdlRleHR1cmVDb29yZHNfUzA7CgloYWxmNCB0ZXhDb2xvcjsKCXsKCQl0ZXhDb2xvciA9IHNhbXBsZSh1VGV4dHVyZVNhbXBsZXJfMF9TMCwgdXYpLnJycnI7Cgl9CgloYWxmIGRpc3RhbmNlID0gNy45Njg3NSoodGV4Q29sb3IuciAtIDAuNTAxOTYwNzg0MzEpOwoJaGFsZiBhZndpZHRoOwoJYWZ3aWR0aCA9IGFicygwLjY1KmhhbGYoZEZkeCh2SW50VGV4dHVyZUNvb3Jkc19TMC54KSkpOwoJaGFsZiB2YWwgPSBzbW9vdGhzdGVwKC1hZndpZHRoLCBhZndpZHRoLCBkaXN0YW5jZSk7CgloYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KHZhbCk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRDb3ZlcmFnZV9TMDsKCX0KfQoAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAKAAAAaW5Qb3NpdGlvbgAABwAAAGluQ29sb3IADwAAAGluVGV4dHVyZUNvb3JkcwAAAAAA","HTQAAGAABBYAAAEIXBAAAGEAMAAAAAAAAAAAAAAAQAHAAAAAQAAAAAAAQQGAAAAA":"CgAAAExTS1M/AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBpblBvc2l0aW9uOwppbiBoYWxmNCBpbkNvbG9yOwppbiBmbG9hdDQgaW5RdWFkRWRnZTsKb3V0IGZsb2F0NCB2UXVhZEVkZ2VfUzA7Cm91dCBoYWxmNCB2aW5Db2xvcl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZEVkZ2UKCXZRdWFkRWRnZV9TMCA9IGluUXVhZEVkZ2U7Cgl2aW5Db2xvcl9TMCA9IGluQ29sb3I7CglmbG9hdDIgX3RtcF8wX2luUG9zaXRpb24gPSBpblBvc2l0aW9uOwoJc2tfUG9zaXRpb24gPSBfdG1wXzBfaW5Qb3NpdGlvbi54eTAxOwp9CgABAAAABQMAAGluIGZsb2F0NCB2UXVhZEVkZ2VfUzA7CmluIGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgUXVhZEVkZ2UKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2aW5Db2xvcl9TMDsKCWhhbGYgZWRnZUFscGhhOwoJaGFsZjIgZHV2ZHggPSBoYWxmMihkRmR4KHZRdWFkRWRnZV9TMC54eSkpOwoJaGFsZjIgZHV2ZHkgPSBoYWxmMihkRmR5KHZRdWFkRWRnZV9TMC54eSkpOwoJaWYgKHZRdWFkRWRnZV9TMC56ID4gMC4wICYmIHZRdWFkRWRnZV9TMC53ID4gMC4wKSAKCXsKCQllZGdlQWxwaGEgPSBoYWxmKG1pbihtaW4odlF1YWRFZGdlX1MwLnosIHZRdWFkRWRnZV9TMC53KSArIDAuNSwgMS4wKSk7Cgl9CgllbHNlIAoJewoJCWhhbGYyIGdGID0gaGFsZjIoaGFsZigyLjAqdlF1YWRFZGdlX1MwLngqZHV2ZHgueCAtIGR1dmR4LnkpLCAgICAgICAgICAgICAgICAgaGFsZigyLjAqdlF1YWRFZGdlX1MwLngqZHV2ZHkueCAtIGR1dmR5LnkpKTsKCQllZGdlQWxwaGEgPSBoYWxmKHZRdWFkRWRnZV9TMC54KnZRdWFkRWRnZV9TMC54IC0gdlF1YWRFZGdlX1MwLnkpOwoJCWVkZ2VBbHBoYSA9IHNhdHVyYXRlKDAuNSAtIGVkZ2VBbHBoYSAvIGxlbmd0aChnRikpOwoJfQoJaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNChlZGdlQWxwaGEpOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dENvbG9yX1MwICogb3V0cHV0Q292ZXJhZ2VfUzA7Cgl9Cn0KAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAKAAAAaW5Qb3NpdGlvbgAABwAAAGluQ29sb3IACgAAAGluUXVhZEVkZ2UAAAAAAAA=","HUIAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAAAAAADUAANAAAAAAAAAIAAAABLAIABAAAAABAEGABBAMAAAAAAAAAAAAB2AAAAAAACAAAAAEBSAAAAA":"CgAAAExTS1M8AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMV9jMDsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBmbG9hdDIgbG9jYWxDb29yZDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfM19TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cgl7CgkJdlRyYW5zZm9ybWVkQ29vcmRzXzNfUzAgPSBmbG9hdDN4Mih1bWF0cml4X1MxX2MwKSAqIGxvY2FsQ29vcmQueHkxOwoJfQp9CgAAAAC2AgAAdW5pZm9ybSBmbG9hdDN4MyB1bWF0cml4X1MxX2MwOwp1bmlmb3JtIHNhbXBsZXIyRCB1VGV4dHVyZVNhbXBsZXJfMF9TMTsKaW4gZmxvYXQyIHZUcmFuc2Zvcm1lZENvb3Jkc18zX1MwOwpoYWxmNCBUZXh0dXJlRWZmZWN0X1MxX2MwX2MwKGhhbGY0IF9pbnB1dCkgCnsKCXJldHVybiBzYW1wbGUodVRleHR1cmVTYW1wbGVyXzBfUzEsIHZUcmFuc2Zvcm1lZENvb3Jkc18zX1MwKTsKfQpoYWxmNCBNYXRyaXhFZmZlY3RfUzFfYzAoaGFsZjQgX2lucHV0KSAKewoJcmV0dXJuIFRleHR1cmVFZmZlY3RfUzFfYzBfYzAoX2lucHV0KTsKfQpoYWxmNCBCbGVuZF9TMShoYWxmNCBfc3JjLCBoYWxmNCBfZHN0KSAKewoJcmV0dXJuIGJsZW5kX21vZHVsYXRlKE1hdHJpeEVmZmVjdF9TMV9jMChfc3JjKSwgX3NyYyk7Cn0Kdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJaGFsZjQgb3V0cHV0Q29sb3JfUzAgPSBoYWxmNCgxKTsKCWNvbnN0IGhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoMSk7CgloYWxmNCBvdXRwdXRfUzE7CglvdXRwdXRfUzEgPSBCbGVuZF9TMShvdXRwdXRDb2xvcl9TMCwgaGFsZjQoMSkpOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dF9TMSAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAIAAAAcG9zaXRpb24KAAAAbG9jYWxDb29yZAAAAAAAAA==","AYQQ5AADQAAAOAEARAFQJAABBADIB7777777777777777777777767YAAAAAAAAAAAAOQAAAAAAAQAAAABAMQAAAAA":"CgAAAExTS1PMAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQ0IHVsb2NhbE1hdHJpeF9TMDsKaW4gZmxvYXQyIGluUG9zaXRpb247CmluIGhhbGY0IGluQ29sb3I7CmluIGZsb2F0NCBpbkNpcmNsZUVkZ2U7Cm91dCBmbG9hdDQgdmluQ2lyY2xlRWRnZV9TMDsKb3V0IGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBDaXJjbGVHZW9tZXRyeVByb2Nlc3NvcgoJdmluQ2lyY2xlRWRnZV9TMCA9IGluQ2lyY2xlRWRnZTsKCXZpbkNvbG9yX1MwID0gaW5Db2xvcjsKCWZsb2F0MiBfdG1wXzBfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247CglmbG9hdDIgX3RtcF8xX2luUG9zaXRpb24gPSB1bG9jYWxNYXRyaXhfUzAueHogKiBpblBvc2l0aW9uICsgdWxvY2FsTWF0cml4X1MwLnl3OwoJc2tfUG9zaXRpb24gPSBfdG1wXzBfaW5Qb3NpdGlvbi54eTAxOwp9CgAAAAB7AgAAaW4gZmxvYXQ0IHZpbkNpcmNsZUVkZ2VfUzA7CmluIGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgQ2lyY2xlR2VvbWV0cnlQcm9jZXNzb3IKCWZsb2F0NCBjaXJjbGVFZGdlOwoJY2lyY2xlRWRnZSA9IHZpbkNpcmNsZUVkZ2VfUzA7CgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdmluQ29sb3JfUzA7CglmbG9hdCBkID0gbGVuZ3RoKGNpcmNsZUVkZ2UueHkpOwoJaGFsZiBkaXN0YW5jZVRvT3V0ZXJFZGdlID0gaGFsZihjaXJjbGVFZGdlLnogKiAoMS4wIC0gZCkpOwoJaGFsZiBlZGdlQWxwaGEgPSBzYXR1cmF0ZShkaXN0YW5jZVRvT3V0ZXJFZGdlKTsKCWhhbGYgZGlzdGFuY2VUb0lubmVyRWRnZSA9IGhhbGYoY2lyY2xlRWRnZS56ICogKGQgLSBjaXJjbGVFZGdlLncpKTsKCWhhbGYgaW5uZXJBbHBoYSA9IHNhdHVyYXRlKGRpc3RhbmNlVG9Jbm5lckVkZ2UpOwoJZWRnZUFscGhhICo9IGlubmVyQWxwaGE7CgloYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KGVkZ2VBbHBoYSk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRDb3ZlcmFnZV9TMDsKCX0KfQoAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAKAAAAaW5Qb3NpdGlvbgAABwAAAGluQ29sb3IADAAAAGluQ2lyY2xlRWRnZQAAAAA=","HUIAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAAAAAALUAQMAAAAAAAAAEAAAABJYQAAAAAAAAIAAAAAWCBAAAABAAAAANAECAZAAAAAAAAAAAFAAMAAAABAAAAAAABBAM":"CgAAAExTS1M2AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBmbG9hdDIgbG9jYWxDb29yZDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cgl7CgkJdlRyYW5zZm9ybWVkQ29vcmRzXzJfUzAgPSBmbG9hdDN4Mih1bWF0cml4X1MxKSAqIGxvY2FsQ29vcmQueHkxOwoJfQp9CgAAAAAAAPAEAAB1bmlmb3JtIGZsb2F0M3gzIHVtYXRyaXhfUzFfYzBfYzA7CnVuaWZvcm0gaGFsZjIgdUluY3JlbWVudF9TMV9jMDsKdW5pZm9ybSBoYWxmMiB1T2Zmc2V0c0FuZEtlcm5lbF9TMV9jMFsxM107CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKdW5pZm9ybSBzYW1wbGVyMkQgdVRleHR1cmVTYW1wbGVyXzBfUzE7CmluIGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKaGFsZjQgVGV4dHVyZUVmZmVjdF9TMV9jMF9jMF9jMChoYWxmNCBfaW5wdXQsIGZsb2F0MiBfY29vcmRzKSAKewoJcmV0dXJuIHNhbXBsZSh1VGV4dHVyZVNhbXBsZXJfMF9TMSwgX2Nvb3Jkcyk7Cn0KaGFsZjQgTWF0cml4RWZmZWN0X1MxX2MwX2MwKGhhbGY0IF9pbnB1dCwgZmxvYXQyIF9jb29yZHMpIAp7CglyZXR1cm4gVGV4dHVyZUVmZmVjdF9TMV9jMF9jMF9jMChfaW5wdXQsIGZsb2F0M3gyKHVtYXRyaXhfUzFfYzBfYzApICogX2Nvb3Jkcy54eTEpOwp9CmhhbGY0IFNtb290aF9TMV9jMChoYWxmNCBfaW5wdXQsIGZsb2F0MiBjb29yZCwgaGFsZjIgb2Zmc2V0QW5kS2VybmVsKSAKewoJcmV0dXJuIE1hdHJpeEVmZmVjdF9TMV9jMF9jMChfaW5wdXQsIChjb29yZCArIG9mZnNldEFuZEtlcm5lbC54ICogdUluY3JlbWVudF9TMV9jMCkpICogb2Zmc2V0QW5kS2VybmVsLnk7Cn0KaGFsZjQgR2F1c3NpYW5Db252b2x1dGlvbl9TMV9jMChoYWxmNCBfaW5wdXQpIAp7CgloYWxmNCBjb2xvciA9IGhhbGY0KDApOwoJZmxvYXQyIGNvb3JkID0gdlRyYW5zZm9ybWVkQ29vcmRzXzJfUzA7Cglmb3IgKGludCBpPTA7IGk8MTM7ICsraSkgCgl7CgkJY29sb3IgKz0gU21vb3RoX1MxX2MwKF9pbnB1dCwgY29vcmQsIHVPZmZzZXRzQW5kS2VybmVsX1MxX2MwW2ldKTsKCX0KCXJldHVybiBjb2xvcjsKfQpoYWxmNCBNYXRyaXhFZmZlY3RfUzEoaGFsZjQgX2lucHV0KSAKewoJcmV0dXJuIEdhdXNzaWFuQ29udm9sdXRpb25fUzFfYzAoX2lucHV0KTsKfQp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMCA9IGhhbGY0KDEpOwoJY29uc3QgaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNCgxKTsKCWhhbGY0IG91dHB1dF9TMTsKCW91dHB1dF9TMSA9IE1hdHJpeEVmZmVjdF9TMShvdXRwdXRDb2xvcl9TMCk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0X1MxICogb3V0cHV0Q292ZXJhZ2VfUzA7Cgl9Cn0KAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAIAAAAcG9zaXRpb24KAAAAbG9jYWxDb29yZAAAAAAAAA==","DASAAAAAQAAWAABAYAAQBYH7777Z6QQBAEAAAAAAEAAAAAAAEBSAAAB2AAAAAAACAAAAAEBSAAAAA":"CgAAAExTS1PVAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQyIHVBdGxhc1NpemVJbnZfUzA7CmluIGZsb2F0MiBpblBvc2l0aW9uOwppbiB1c2hvcnQyIGluVGV4dHVyZUNvb3JkczsKb3V0IGZsb2F0MiB2VGV4dHVyZUNvb3Jkc19TMDsKZmxhdCBvdXQgZmxvYXQgdlRleEluZGV4X1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBCaXRtYXBUZXh0CglpbnQgdGV4SWR4ID0gMDsKCWZsb2F0MiB1bm9ybVRleENvb3JkcyA9IGZsb2F0MihpblRleHR1cmVDb29yZHMueCwgaW5UZXh0dXJlQ29vcmRzLnkpOwoJdlRleHR1cmVDb29yZHNfUzAgPSB1bm9ybVRleENvb3JkcyAqIHVBdGxhc1NpemVJbnZfUzA7Cgl2VGV4SW5kZXhfUzAgPSBmbG9hdCh0ZXhJZHgpOwoJZmxvYXQyIF90bXBfMV9pblBvc2l0aW9uID0gaW5Qb3NpdGlvbjsKCXNrX1Bvc2l0aW9uID0gaW5Qb3NpdGlvbi54eTAxOwp9CgAAAAAAAADgAQAAdW5pZm9ybSBoYWxmNCB1Q29sb3JfUzA7CnVuaWZvcm0gc2FtcGxlcjJEIHVUZXh0dXJlU2FtcGxlcl8wX1MwOwppbiBmbG9hdDIgdlRleHR1cmVDb29yZHNfUzA7CmZsYXQgaW4gZmxvYXQgdlRleEluZGV4X1MwOwp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgQml0bWFwVGV4dAoJaGFsZjQgb3V0cHV0Q29sb3JfUzA7CglvdXRwdXRDb2xvcl9TMCA9IHVDb2xvcl9TMDsKCWhhbGY0IHRleENvbG9yOwoJewoJCXRleENvbG9yID0gc2FtcGxlKHVUZXh0dXJlU2FtcGxlcl8wX1MwLCB2VGV4dHVyZUNvb3Jkc19TMCk7Cgl9CglvdXRwdXRDb2xvcl9TMCA9IG91dHB1dENvbG9yX1MwICogdGV4Q29sb3I7Cgljb25zdCBoYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KDEpOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dENvbG9yX1MwICogb3V0cHV0Q292ZXJhZ2VfUzA7Cgl9Cn0KAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAKAAAAaW5Qb3NpdGlvbgAADwAAAGluVGV4dHVyZUNvb3JkcwAAAAAA","HUIAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAAAAAALUAQMAAAAAAABAEAAAABJYQAAAAAACAIAAAAAWCBAAAIBAAAAANAECAZAAAAQAAAAAAFAAMAAAABAAAAAAABBAM":"CgAAAExTS1M2AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBmbG9hdDIgbG9jYWxDb29yZDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cgl7CgkJdlRyYW5zZm9ybWVkQ29vcmRzXzJfUzAgPSBmbG9hdDN4Mih1bWF0cml4X1MxKSAqIGxvY2FsQ29vcmQueHkxOwoJfQp9CgAAAAAAAC8GAAB1bmlmb3JtIGZsb2F0NCB1Y2xhbXBfUzFfYzBfYzBfYzA7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMV9jMF9jMDsKdW5pZm9ybSBoYWxmMiB1SW5jcmVtZW50X1MxX2MwOwp1bmlmb3JtIGhhbGYyIHVPZmZzZXRzQW5kS2VybmVsX1MxX2MwWzEzXTsKdW5pZm9ybSBmbG9hdDN4MyB1bWF0cml4X1MxOwp1bmlmb3JtIHNhbXBsZXIyRCB1VGV4dHVyZVNhbXBsZXJfMF9TMTsKaW4gZmxvYXQyIHZUcmFuc2Zvcm1lZENvb3Jkc18yX1MwOwpoYWxmNCBUZXh0dXJlRWZmZWN0X1MxX2MwX2MwX2MwKGhhbGY0IF9pbnB1dCwgZmxvYXQyIF9jb29yZHMpIAp7CglmbG9hdDIgaW5Db29yZCA9IF9jb29yZHM7CglmbG9hdDIgc3Vic2V0Q29vcmQ7CglzdWJzZXRDb29yZC54ID0gaW5Db29yZC54OwoJc3Vic2V0Q29vcmQueSA9IGluQ29vcmQueTsKCWZsb2F0MiBjbGFtcGVkQ29vcmQ7CgljbGFtcGVkQ29vcmQueCA9IHN1YnNldENvb3JkLng7CgljbGFtcGVkQ29vcmQueSA9IGNsYW1wKHN1YnNldENvb3JkLnksIHVjbGFtcF9TMV9jMF9jMF9jMC55LCB1Y2xhbXBfUzFfYzBfYzBfYzAudyk7CgloYWxmNCB0ZXh0dXJlQ29sb3IgPSBzYW1wbGUodVRleHR1cmVTYW1wbGVyXzBfUzEsIGNsYW1wZWRDb29yZCk7CglyZXR1cm4gdGV4dHVyZUNvbG9yOwp9CmhhbGY0IE1hdHJpeEVmZmVjdF9TMV9jMF9jMChoYWxmNCBfaW5wdXQsIGZsb2F0MiBfY29vcmRzKSAKewoJcmV0dXJuIFRleHR1cmVFZmZlY3RfUzFfYzBfYzBfYzAoX2lucHV0LCBmbG9hdDN4Mih1bWF0cml4X1MxX2MwX2MwKSAqIF9jb29yZHMueHkxKTsKfQpoYWxmNCBTbW9vdGhfUzFfYzAoaGFsZjQgX2lucHV0LCBmbG9hdDIgY29vcmQsIGhhbGYyIG9mZnNldEFuZEtlcm5lbCkgCnsKCXJldHVybiBNYXRyaXhFZmZlY3RfUzFfYzBfYzAoX2lucHV0LCAoY29vcmQgKyBvZmZzZXRBbmRLZXJuZWwueCAqIHVJbmNyZW1lbnRfUzFfYzApKSAqIG9mZnNldEFuZEtlcm5lbC55Owp9CmhhbGY0IEdhdXNzaWFuQ29udm9sdXRpb25fUzFfYzAoaGFsZjQgX2lucHV0KSAKewoJaGFsZjQgY29sb3IgPSBoYWxmNCgwKTsKCWZsb2F0MiBjb29yZCA9IHZUcmFuc2Zvcm1lZENvb3Jkc18yX1MwOwoJZm9yIChpbnQgaT0wOyBpPDEzOyArK2kpIAoJewoJCWNvbG9yICs9IFNtb290aF9TMV9jMChfaW5wdXQsIGNvb3JkLCB1T2Zmc2V0c0FuZEtlcm5lbF9TMV9jMFtpXSk7Cgl9CglyZXR1cm4gY29sb3I7Cn0KaGFsZjQgTWF0cml4RWZmZWN0X1MxKGhhbGY0IF9pbnB1dCkgCnsKCXJldHVybiBHYXVzc2lhbkNvbnZvbHV0aW9uX1MxX2MwKF9pbnB1dCk7Cn0Kdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJaGFsZjQgb3V0cHV0Q29sb3JfUzAgPSBoYWxmNCgxKTsKCWNvbnN0IGhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoMSk7CgloYWxmNCBvdXRwdXRfUzE7CglvdXRwdXRfUzEgPSBNYXRyaXhFZmZlY3RfUzEob3V0cHV0Q29sb3JfUzApOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dF9TMSAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAgAAABwb3NpdGlvbgoAAABsb2NhbENvb3JkAAAAAAAA","HUJAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAQAAAAAAQQGACQAGAAAAAQAAAAAAAQQGAAA":"CgAAAExTS1PlAAAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gZmxvYXQyIGxvY2FsQ29vcmQ7Cm91dCBmbG9hdDIgdmxvY2FsQ29vcmRfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJdmxvY2FsQ29vcmRfUzAgPSBsb2NhbENvb3JkOwoJc2tfUG9zaXRpb24gPSBwb3NpdGlvbi54eTAxOwp9CgAAAAAAAACfAQAAdW5pZm9ybSBzYW1wbGVyMkQgdVRleHR1cmVTYW1wbGVyXzBfUzA7CmluIGZsb2F0MiB2bG9jYWxDb29yZF9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJaGFsZjQgb3V0cHV0Q29sb3JfUzAgPSBoYWxmNCgxKTsKCWZsb2F0MiB0ZXhDb29yZDsKCXRleENvb3JkID0gdmxvY2FsQ29vcmRfUzA7CglvdXRwdXRDb2xvcl9TMCA9ICgoc2FtcGxlKHVUZXh0dXJlU2FtcGxlcl8wX1MwLCB0ZXhDb29yZCkgKiBoYWxmNCgxKSkpOwoJY29uc3QgaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNCgxKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAgAAABwb3NpdGlvbgoAAABsb2NhbENvb3JkAAAAAAAA","AYQA5AADQAAAOAEARAFQJAABBADIB7777777777777777777777767YAAAAAAAAAAAAB3QA6AAAEAAAAAAAMAAPEAEAAABAAAAAAB2AAAAAAACAAAAAEBSAAAA":"CgAAAExTS1PMAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQ0IHVsb2NhbE1hdHJpeF9TMDsKaW4gZmxvYXQyIGluUG9zaXRpb247CmluIGhhbGY0IGluQ29sb3I7CmluIGZsb2F0NCBpbkNpcmNsZUVkZ2U7Cm91dCBmbG9hdDQgdmluQ2lyY2xlRWRnZV9TMDsKb3V0IGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBDaXJjbGVHZW9tZXRyeVByb2Nlc3NvcgoJdmluQ2lyY2xlRWRnZV9TMCA9IGluQ2lyY2xlRWRnZTsKCXZpbkNvbG9yX1MwID0gaW5Db2xvcjsKCWZsb2F0MiBfdG1wXzBfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247CglmbG9hdDIgX3RtcF8xX2luUG9zaXRpb24gPSB1bG9jYWxNYXRyaXhfUzAueHogKiBpblBvc2l0aW9uICsgdWxvY2FsTWF0cml4X1MwLnl3OwoJc2tfUG9zaXRpb24gPSBfdG1wXzBfaW5Qb3NpdGlvbi54eTAxOwp9CgEAAAAeBQAAdW5pZm9ybSBmbG9hdDQgdWlubmVyUmVjdF9TMTsKdW5pZm9ybSBoYWxmMiB1cmFkaXVzUGx1c0hhbGZfUzE7CnVuaWZvcm0gZmxvYXQ0IHVpbm5lclJlY3RfUzI7CnVuaWZvcm0gaGFsZjIgdXJhZGl1c1BsdXNIYWxmX1MyOwppbiBmbG9hdDQgdmluQ2lyY2xlRWRnZV9TMDsKaW4gaGFsZjQgdmluQ29sb3JfUzA7CmhhbGY0IENpcmN1bGFyUlJlY3RfUzEoaGFsZjQgX2lucHV0KSAKewoJZmxvYXQyIGR4eTAgPSB1aW5uZXJSZWN0X1MxLkxUIC0gc2tfRnJhZ0Nvb3JkLnh5OwoJZmxvYXQyIGR4eTEgPSBza19GcmFnQ29vcmQueHkgLSB1aW5uZXJSZWN0X1MxLlJCOwoJZmxvYXQyIGR4eSA9IG1heChtYXgoZHh5MCwgZHh5MSksIDAuMCk7CgloYWxmIGFscGhhID0gaGFsZihzYXR1cmF0ZSh1cmFkaXVzUGx1c0hhbGZfUzEueCAtIGxlbmd0aChkeHkpKSk7CglhbHBoYSA9IDEuMCAtIGFscGhhOwoJcmV0dXJuIF9pbnB1dCAqIGFscGhhOwp9CmhhbGY0IENpcmN1bGFyUlJlY3RfUzIoaGFsZjQgX2lucHV0KSAKewoJZmxvYXQyIGR4eTAgPSB1aW5uZXJSZWN0X1MyLkxUIC0gc2tfRnJhZ0Nvb3JkLnh5OwoJZmxvYXQyIGR4eTEgPSBza19GcmFnQ29vcmQueHkgLSB1aW5uZXJSZWN0X1MyLlJCOwoJZmxvYXQyIGR4eSA9IG1heChtYXgoZHh5MCwgZHh5MSksIDAuMCk7CgloYWxmIGFscGhhID0gaGFsZihzYXR1cmF0ZSh1cmFkaXVzUGx1c0hhbGZfUzIueCAtIGxlbmd0aChkeHkpKSk7CglyZXR1cm4gX2lucHV0ICogYWxwaGE7Cn0Kdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIENpcmNsZUdlb21ldHJ5UHJvY2Vzc29yCglmbG9hdDQgY2lyY2xlRWRnZTsKCWNpcmNsZUVkZ2UgPSB2aW5DaXJjbGVFZGdlX1MwOwoJaGFsZjQgb3V0cHV0Q29sb3JfUzA7CglvdXRwdXRDb2xvcl9TMCA9IHZpbkNvbG9yX1MwOwoJZmxvYXQgZCA9IGxlbmd0aChjaXJjbGVFZGdlLnh5KTsKCWhhbGYgZGlzdGFuY2VUb091dGVyRWRnZSA9IGhhbGYoY2lyY2xlRWRnZS56ICogKDEuMCAtIGQpKTsKCWhhbGYgZWRnZUFscGhhID0gc2F0dXJhdGUoZGlzdGFuY2VUb091dGVyRWRnZSk7CgloYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KGVkZ2VBbHBoYSk7CgloYWxmNCBvdXRwdXRfUzE7CglvdXRwdXRfUzEgPSBDaXJjdWxhclJSZWN0X1MxKG91dHB1dENvdmVyYWdlX1MwKTsKCWhhbGY0IG91dHB1dF9TMjsKCW91dHB1dF9TMiA9IENpcmN1bGFyUlJlY3RfUzIob3V0cHV0X1MxKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dF9TMjsKCX0KfQoAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAADAAAACgAAAGluUG9zaXRpb24AAAcAAABpbkNvbG9yAAwAAABpbkNpcmNsZUVkZ2UAAAAA","HVIAAAAAABIAAGAAAQ4AAAH477776R24EAAAIOBQAD6P7777777777YDAAAAAAAAAAAGIBIAAABAAAAANAEAAAAAAAAAAAAAABAAOAAAABAAAAAAABBAMAAAAA":"CgAAAExTS1N0AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBoYWxmNCBjb2xvcjsKaW4gZmxvYXQyIGxvY2FsQ29vcmQ7CmZsYXQgb3V0IGhhbGY0IHZjb2xvcl9TMDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgl2Y29sb3JfUzAgPSBjb2xvcjsKCXNrX1Bvc2l0aW9uID0gcG9zaXRpb24ueHkwMTsKCXsKCQl2VHJhbnNmb3JtZWRDb29yZHNfMl9TMCA9IGZsb2F0M3gyKHVtYXRyaXhfUzEpICogbG9jYWxDb29yZC54eTE7Cgl9Cn0KAAAAAHMCAAB1bmlmb3JtIGZsb2F0M3gzIHVtYXRyaXhfUzE7CnVuaWZvcm0gc2FtcGxlcjJEIHVUZXh0dXJlU2FtcGxlcl8wX1MxOwpmbGF0IGluIGhhbGY0IHZjb2xvcl9TMDsKaW4gZmxvYXQyIHZUcmFuc2Zvcm1lZENvb3Jkc18yX1MwOwpoYWxmNCBUZXh0dXJlRWZmZWN0X1MxX2MwKGhhbGY0IF9pbnB1dCkgCnsKCXJldHVybiBzYW1wbGUodVRleHR1cmVTYW1wbGVyXzBfUzEsIHZUcmFuc2Zvcm1lZENvb3Jkc18yX1MwKS5ycnJyOwp9CmhhbGY0IE1hdHJpeEVmZmVjdF9TMShoYWxmNCBfaW5wdXQpIAp7CglyZXR1cm4gVGV4dHVyZUVmZmVjdF9TMV9jMChfaW5wdXQpOwp9CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBRdWFkUGVyRWRnZUFBR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2Y29sb3JfUzA7Cgljb25zdCBoYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KDEpOwoJaGFsZjQgb3V0cHV0X1MxOwoJb3V0cHV0X1MxID0gTWF0cml4RWZmZWN0X1MxKG91dHB1dENvdmVyYWdlX1MwKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dF9TMTsKCX0KfQoAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAIAAAAcG9zaXRpb24FAAAAY29sb3IAAAAKAAAAbG9jYWxDb29yZAAAAAAAAA==","HWQACAAAABAAADAAAIOAAAAADIIAAIRODAAP577774DSAIAA737777YBAAAAAAAAAAAHEADZAAAAAAIAAAAAAOQAAAAAAAQAAAABAMQAAAAAA":"CgAAAExTS1ONAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gZmxvYXQgY292ZXJhZ2U7CmluIGhhbGY0IGNvbG9yOwppbiBmbG9hdDQgZ2VvbVN1YnNldDsKZmxhdCBvdXQgaGFsZjQgdmNvbG9yX1MwOwpvdXQgZmxvYXQgdmNvdmVyYWdlX1MwOwpmbGF0IG91dCBmbG9hdDQgdmdlb21TdWJzZXRfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJZmxvYXQyIHBvc2l0aW9uID0gcG9zaXRpb24ueHk7Cgl2Y29sb3JfUzAgPSBjb2xvcjsKCXZjb3ZlcmFnZV9TMCA9IGNvdmVyYWdlOwoJdmdlb21TdWJzZXRfUzAgPSBnZW9tU3Vic2V0OwoJc2tfUG9zaXRpb24gPSBwb3NpdGlvbi54eTAxOwp9CgAAAAEAAAAIBAAAdW5pZm9ybSBmbG9hdDQgdWlubmVyUmVjdF9TMTsKdW5pZm9ybSBoYWxmMiB1cmFkaXVzUGx1c0hhbGZfUzE7CmZsYXQgaW4gaGFsZjQgdmNvbG9yX1MwOwppbiBmbG9hdCB2Y292ZXJhZ2VfUzA7CmZsYXQgaW4gZmxvYXQ0IHZnZW9tU3Vic2V0X1MwOwpoYWxmNCBDaXJjdWxhclJSZWN0X1MxKGhhbGY0IF9pbnB1dCkgCnsKCWZsb2F0MiBkeHkwID0gdWlubmVyUmVjdF9TMS5MVCAtIHNrX0ZyYWdDb29yZC54eTsKCWZsb2F0MiBkeHkxID0gc2tfRnJhZ0Nvb3JkLnh5IC0gdWlubmVyUmVjdF9TMS5SQjsKCWZsb2F0MiBkeHkgPSBtYXgobWF4KGR4eTAsIGR4eTEpLCAwLjApOwoJaGFsZiBhbHBoYSA9IGhhbGYoc2F0dXJhdGUodXJhZGl1c1BsdXNIYWxmX1MxLnggLSBsZW5ndGgoZHh5KSkpOwoJcmV0dXJuIF9pbnB1dCAqIGFscGhhOwp9CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBRdWFkUGVyRWRnZUFBR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2Y29sb3JfUzA7CglmbG9hdCBjb3ZlcmFnZSA9IHZjb3ZlcmFnZV9TMDsKCWZsb2F0NCBnZW9TdWJzZXQ7CglnZW9TdWJzZXQgPSB2Z2VvbVN1YnNldF9TMDsKCWhhbGY0IGRpc3RzNCA9IGNsYW1wKGhhbGY0KDEsIDEsIC0xLCAtMSkgKiBoYWxmNChza19GcmFnQ29vcmQueHl4eSAtIGdlb1N1YnNldCksIDAsIDEpOwoJaGFsZjIgZGlzdHMyID0gZGlzdHM0Lnh5ICsgZGlzdHM0Lnp3IC0gMTsKCWhhbGYgc3Vic2V0Q292ZXJhZ2UgPSBkaXN0czIueCAqIGRpc3RzMi55OwoJY292ZXJhZ2UgPSBtaW4oY292ZXJhZ2UsIHN1YnNldENvdmVyYWdlKTsKCWhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoaGFsZihjb3ZlcmFnZSkpOwoJaGFsZjQgb3V0cHV0X1MxOwoJb3V0cHV0X1MxID0gQ2lyY3VsYXJSUmVjdF9TMShvdXRwdXRDb3ZlcmFnZV9TMCk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRfUzE7Cgl9Cn0KAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAIAAAAcG9zaXRpb24IAAAAY292ZXJhZ2UFAAAAY29sb3IAAAAKAAAAZ2VvbVN1YnNldAAAAAAAAA==","B2AAQAAABQAAIAABBYAAB7777777777774ABICAAAAAAAAAAAAAABUABAAAAAEAAAAAIBEABAAAAA":"CgAAAExTS1MOAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBpblBvc2l0aW9uOwppbiBoYWxmIGluQ292ZXJhZ2U7Cm91dCBoYWxmIHZpbkNvdmVyYWdlX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBEZWZhdWx0R2VvbWV0cnlQcm9jZXNzb3IKCWZsb2F0MiBfdG1wXzFfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247Cgl2aW5Db3ZlcmFnZV9TMCA9IGluQ292ZXJhZ2U7Cglza19Qb3NpdGlvbiA9IF90bXBfMV9pblBvc2l0aW9uLnh5MDE7Cn0KAAAAAAAATQEAAHVuaWZvcm0gaGFsZjQgdUNvbG9yX1MwOwppbiBoYWxmIHZpbkNvdmVyYWdlX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgRGVmYXVsdEdlb21ldHJ5UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdUNvbG9yX1MwOwoJaGFsZiBhbHBoYSA9IDEuMDsKCWFscGhhID0gdmluQ292ZXJhZ2VfUzA7CgloYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KGFscGhhKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAACAAAACgAAAGluUG9zaXRpb24AAAoAAABpbkNvdmVyYWdlAAAAAAAA","HUQACAAAAAMAADAAAIOAAAH677776IZOCAAP577777777777777777YBAAAAAAAAAAAKAAYAAAACAAAAAAACCAYAAA":"CgAAAExTS1PPAAAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gaGFsZjQgY29sb3I7Cm91dCBoYWxmNCB2Y29sb3JfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJdmNvbG9yX1MwID0gY29sb3I7Cglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cn0KAAAAAAAMAQAAaW4gaGFsZjQgdmNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdmNvbG9yX1MwOwoJY29uc3QgaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNCgxKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAACAAAACAAAAHBvc2l0aW9uBQAAAGNvbG9yAAAAAAAAAA==","HUQACAAAAAMAADAAAIOAAAH677776IZOCAAP577777777777777777YBAAAAAAAAAAAHEADZAAAAAAIAAAAAAOQAAAAAAAQAAAABAMQAAAAAA":"CgAAAExTS1PPAAAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gaGFsZjQgY29sb3I7Cm91dCBoYWxmNCB2Y29sb3JfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJdmNvbG9yX1MwID0gY29sb3I7Cglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cn0KAAEAAACbAgAAdW5pZm9ybSBmbG9hdDQgdWlubmVyUmVjdF9TMTsKdW5pZm9ybSBoYWxmMiB1cmFkaXVzUGx1c0hhbGZfUzE7CmluIGhhbGY0IHZjb2xvcl9TMDsKaGFsZjQgQ2lyY3VsYXJSUmVjdF9TMShoYWxmNCBfaW5wdXQpIAp7CglmbG9hdDIgZHh5MCA9IHVpbm5lclJlY3RfUzEuTFQgLSBza19GcmFnQ29vcmQueHk7CglmbG9hdDIgZHh5MSA9IHNrX0ZyYWdDb29yZC54eSAtIHVpbm5lclJlY3RfUzEuUkI7CglmbG9hdDIgZHh5ID0gbWF4KG1heChkeHkwLCBkeHkxKSwgMC4wKTsKCWhhbGYgYWxwaGEgPSBoYWxmKHNhdHVyYXRlKHVyYWRpdXNQbHVzSGFsZl9TMS54IC0gbGVuZ3RoKGR4eSkpKTsKCXJldHVybiBfaW5wdXQgKiBhbHBoYTsKfQp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdmNvbG9yX1MwOwoJY29uc3QgaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNCgxKTsKCWhhbGY0IG91dHB1dF9TMTsKCW91dHB1dF9TMSA9IENpcmN1bGFyUlJlY3RfUzEob3V0cHV0Q292ZXJhZ2VfUzApOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dENvbG9yX1MwICogb3V0cHV0X1MxOwoJfQp9CgABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAgAAABwb3NpdGlvbgUAAABjb2xvcgAAAAAAAAA=","HVIAAAAAABIAAGAAAQ4AAAH477776R24EAAAIOBQAD6P7777777777YDAAAAAAAAAAAFQBQU7BTXIAAAAAAAAAACAAAAAVQEAAQAAAAAQCDAEQQGAAAAAAAAAAAA4IAPAAACAAAAAAAEABYAAAAEAAAAAAAEEBQA":"CgAAAExTS1N6AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMV9jMDsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBoYWxmNCBjb2xvcjsKaW4gZmxvYXQyIGxvY2FsQ29vcmQ7CmZsYXQgb3V0IGhhbGY0IHZjb2xvcl9TMDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfM19TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgl2Y29sb3JfUzAgPSBjb2xvcjsKCXNrX1Bvc2l0aW9uID0gcG9zaXRpb24ueHkwMTsKCXsKCQl2VHJhbnNmb3JtZWRDb29yZHNfM19TMCA9IGZsb2F0M3gyKHVtYXRyaXhfUzFfYzApICogbG9jYWxDb29yZC54eTE7Cgl9Cn0KAAABAAAArAQAAHVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMV9jMDsKdW5pZm9ybSBmbG9hdDQgdWlubmVyUmVjdF9TMjsKdW5pZm9ybSBoYWxmMiB1cmFkaXVzUGx1c0hhbGZfUzI7CnVuaWZvcm0gc2FtcGxlckV4dGVybmFsT0VTIHVUZXh0dXJlU2FtcGxlcl8wX1MxOwpmbGF0IGluIGhhbGY0IHZjb2xvcl9TMDsKaW4gZmxvYXQyIHZUcmFuc2Zvcm1lZENvb3Jkc18zX1MwOwpoYWxmNCBUZXh0dXJlRWZmZWN0X1MxX2MwX2MwKGhhbGY0IF9pbnB1dCkgCnsKCXJldHVybiBzYW1wbGUodVRleHR1cmVTYW1wbGVyXzBfUzEsIHZUcmFuc2Zvcm1lZENvb3Jkc18zX1MwKTsKfQpoYWxmNCBNYXRyaXhFZmZlY3RfUzFfYzAoaGFsZjQgX2lucHV0KSAKewoJcmV0dXJuIFRleHR1cmVFZmZlY3RfUzFfYzBfYzAoX2lucHV0KTsKfQpoYWxmNCBEaXNhYmxlQ292ZXJhZ2VBc0FscGhhX1MxKGhhbGY0IF9pbnB1dCkgCnsKCV9pbnB1dCA9IE1hdHJpeEVmZmVjdF9TMV9jMChfaW5wdXQpOwoJaGFsZjQgX3RtcF8wX2luQ29sb3IgPSBfaW5wdXQ7CglyZXR1cm4gaGFsZjQoX2lucHV0KTsKfQpoYWxmNCBDaXJjdWxhclJSZWN0X1MyKGhhbGY0IF9pbnB1dCkgCnsKCWZsb2F0MiBkeHkwID0gdWlubmVyUmVjdF9TMi5MVCAtIHNrX0ZyYWdDb29yZC54eTsKCWZsb2F0MiBkeHkxID0gc2tfRnJhZ0Nvb3JkLnh5IC0gdWlubmVyUmVjdF9TMi5SQjsKCWZsb2F0MiBkeHkgPSBtYXgobWF4KGR4eTAsIGR4eTEpLCAwLjApOwoJaGFsZiBhbHBoYSA9IGhhbGYoc2F0dXJhdGUodXJhZGl1c1BsdXNIYWxmX1MyLnggLSBsZW5ndGgoZHh5KSkpOwoJcmV0dXJuIF9pbnB1dCAqIGFscGhhOwp9CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBRdWFkUGVyRWRnZUFBR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2Y29sb3JfUzA7Cgljb25zdCBoYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KDEpOwoJaGFsZjQgb3V0cHV0X1MxOwoJb3V0cHV0X1MxID0gRGlzYWJsZUNvdmVyYWdlQXNBbHBoYV9TMShvdXRwdXRDb2xvcl9TMCk7CgloYWxmNCBvdXRwdXRfUzI7CglvdXRwdXRfUzIgPSBDaXJjdWxhclJSZWN0X1MyKG91dHB1dENvdmVyYWdlX1MwKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRfUzEgKiBvdXRwdXRfUzI7Cgl9Cn0KAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAIAAAAcG9zaXRpb24FAAAAY29sb3IAAAAKAAAAbG9jYWxDb29yZAAAAAAAAA==","FAAQMYAAMAAAEADAAABAEYAAAICIAB5AABQAAAQAMAAAEATAAABAIIGAAEDCBYQCA4AAAAAAEAB5AAAAACQHEB4XIQAQAADQAAAABAAAAAAABAEMVDOMCJKRAAAAAHAAAAAAAAAAACQAGAAAAAQAAAAAAAQQGAAA":"CgAAAExTS1PUCwAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0NCByYWRpaV9zZWxlY3RvcjsKaW4gZmxvYXQ0IGNvcm5lcl9hbmRfcmFkaXVzX291dHNldHM7CmluIGZsb2F0NCBhYV9ibG9hdF9hbmRfY292ZXJhZ2U7CmluIGZsb2F0NCByYWRpaV94OwppbiBmbG9hdDQgcmFkaWlfeTsKaW4gZmxvYXQ0IHNrZXc7CmluIGZsb2F0MiB0cmFuc2xhdGVfYW5kX2xvY2Fscm90YXRlOwppbiBoYWxmNCBjb2xvcjsKZmxhdCBvdXQgaGFsZjQgdmNvbG9yX1MwOwpvdXQgZmxvYXQyIHZhcmNjb29yZF9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgRmlsbFJSZWN0T3A6OlByb2Nlc3NvcgoJdmNvbG9yX1MwID0gY29sb3I7CglmbG9hdCBhYV9ibG9hdF9tdWx0aXBsaWVyID0gMTsKCWZsb2F0MiBjb3JuZXIgPSBjb3JuZXJfYW5kX3JhZGl1c19vdXRzZXRzLnh5OwoJZmxvYXQyIHJhZGl1c19vdXRzZXQgPSBjb3JuZXJfYW5kX3JhZGl1c19vdXRzZXRzLnp3OwoJZmxvYXQyIGFhX2Jsb2F0X2RpcmVjdGlvbiA9IGFhX2Jsb2F0X2FuZF9jb3ZlcmFnZS54eTsKCWZsb2F0IGlzX2xpbmVhcl9jb3ZlcmFnZSA9IGFhX2Jsb2F0X2FuZF9jb3ZlcmFnZS53OwoJZmxvYXQyIHBpeGVsbGVuZ3RoID0gaW52ZXJzZXNxcnQoZmxvYXQyKGRvdChza2V3Lnh6LCBza2V3Lnh6KSwgZG90KHNrZXcueXcsIHNrZXcueXcpKSk7CglmbG9hdDQgbm9ybWFsaXplZF9heGlzX2RpcnMgPSBza2V3ICogcGl4ZWxsZW5ndGgueHl4eTsKCWZsb2F0MiBheGlzd2lkdGhzID0gKGFicyhub3JtYWxpemVkX2F4aXNfZGlycy54eSkgKyBhYnMobm9ybWFsaXplZF9heGlzX2RpcnMuencpKTsKCWZsb2F0MiBhYV9ibG9hdHJhZGl1cyA9IGF4aXN3aWR0aHMgKiBwaXhlbGxlbmd0aCAqIC41OwoJZmxvYXQ0IHJhZGlpX2FuZF9uZWlnaGJvcnMgPSByYWRpaV9zZWxlY3RvciogZmxvYXQ0eDQocmFkaWlfeCwgcmFkaWlfeSwgcmFkaWlfeC55eHd6LCByYWRpaV95Lnd6eXgpOwoJZmxvYXQyIHJhZGlpID0gcmFkaWlfYW5kX25laWdoYm9ycy54eTsKCWZsb2F0MiBuZWlnaGJvcl9yYWRpaSA9IHJhZGlpX2FuZF9uZWlnaGJvcnMuenc7CglmbG9hdCBjb3ZlcmFnZV9tdWx0aXBsaWVyID0gMTsKCWlmIChhbnkoZ3JlYXRlclRoYW4oYWFfYmxvYXRyYWRpdXMsIGZsb2F0MigxKSkpKSAKCXsKCQljb3JuZXIgPSBtYXgoYWJzKGNvcm5lciksIGFhX2Jsb2F0cmFkaXVzKSAqIHNpZ24oY29ybmVyKTsKCQljb3ZlcmFnZV9tdWx0aXBsaWVyID0gMSAvIChtYXgoYWFfYmxvYXRyYWRpdXMueCwgMSkgKiBtYXgoYWFfYmxvYXRyYWRpdXMueSwgMSkpOwoJCXJhZGlpID0gZmxvYXQyKDApOwoJfQoJZmxvYXQgY292ZXJhZ2UgPSBhYV9ibG9hdF9hbmRfY292ZXJhZ2UuejsKCWlmIChhbnkobGVzc1RoYW4ocmFkaWksIGFhX2Jsb2F0cmFkaXVzICogMS41KSkpIAoJewoJCXJhZGlpID0gZmxvYXQyKDApOwoJCWFhX2Jsb2F0X2RpcmVjdGlvbiA9IHNpZ24oY29ybmVyKTsKCQlpZiAoY292ZXJhZ2UgPiAuNSkgCgkJewoJCQlhYV9ibG9hdF9kaXJlY3Rpb24gPSAtYWFfYmxvYXRfZGlyZWN0aW9uOwoJCX0KCQlpc19saW5lYXJfY292ZXJhZ2UgPSAxOwoJfQoJZWxzZSAKCXsKCQlyYWRpaSA9IGNsYW1wKHJhZGlpLCBwaXhlbGxlbmd0aCAqIDEuNSwgMiAtIHBpeGVsbGVuZ3RoICogMS41KTsKCQluZWlnaGJvcl9yYWRpaSA9IGNsYW1wKG5laWdoYm9yX3JhZGlpLCBwaXhlbGxlbmd0aCAqIDEuNSwgMiAtIHBpeGVsbGVuZ3RoICogMS41KTsKCQlmbG9hdDIgc3BhY2luZyA9IDIgLSByYWRpaSAtIG5laWdoYm9yX3JhZGlpOwoJCWZsb2F0MiBleHRyYV9wYWQgPSBtYXgocGl4ZWxsZW5ndGggKiAuMDYyNSAtIHNwYWNpbmcsIGZsb2F0MigwKSk7CgkJcmFkaWkgLT0gZXh0cmFfcGFkICogLjU7Cgl9CglmbG9hdDIgYWFfb3V0c2V0ID0gYWFfYmxvYXRfZGlyZWN0aW9uICogYWFfYmxvYXRyYWRpdXMgKiBhYV9ibG9hdF9tdWx0aXBsaWVyOwoJZmxvYXQyIHZlcnRleHBvcyA9IGNvcm5lciArIHJhZGl1c19vdXRzZXQgKiByYWRpaSArIGFhX291dHNldDsKCWlmIChjb3ZlcmFnZSA+IC41KSAKCXsKCQlpZiAoYWFfYmxvYXRfZGlyZWN0aW9uLnggIT0gMCAmJiB2ZXJ0ZXhwb3MueCAqIGNvcm5lci54IDwgMCkgCgkJewoJCQlmbG9hdCBiYWNrc2V0ID0gYWJzKHZlcnRleHBvcy54KTsKCQkJdmVydGV4cG9zLnggPSAwOwoJCQl2ZXJ0ZXhwb3MueSArPSBiYWNrc2V0ICogc2lnbihjb3JuZXIueSkgKiBwaXhlbGxlbmd0aC55L3BpeGVsbGVuZ3RoLng7CgkJCWNvdmVyYWdlID0gKGNvdmVyYWdlIC0gLjUpICogYWJzKGNvcm5lci54KSAvIChhYnMoY29ybmVyLngpICsgYmFja3NldCkgKyAuNTsKCQl9CgkJaWYgKGFhX2Jsb2F0X2RpcmVjdGlvbi55ICE9IDAgJiYgdmVydGV4cG9zLnkgKiBjb3JuZXIueSA8IDApIAoJCXsKCQkJZmxvYXQgYmFja3NldCA9IGFicyh2ZXJ0ZXhwb3MueSk7CgkJCXZlcnRleHBvcy55ID0gMDsKCQkJdmVydGV4cG9zLnggKz0gYmFja3NldCAqIHNpZ24oY29ybmVyLngpICogcGl4ZWxsZW5ndGgueC9waXhlbGxlbmd0aC55OwoJCQljb3ZlcmFnZSA9IChjb3ZlcmFnZSAtIC41KSAqIGFicyhjb3JuZXIueSkgLyAoYWJzKGNvcm5lci55KSArIGJhY2tzZXQpICsgLjU7CgkJfQoJfQoJZmxvYXQyeDIgc2tld21hdHJpeCA9IGZsb2F0MngyKHNrZXcueHksIHNrZXcuencpOwoJZmxvYXQyIGRldmNvb3JkID0gdmVydGV4cG9zICogc2tld21hdHJpeCArIHRyYW5zbGF0ZV9hbmRfbG9jYWxyb3RhdGUueHk7CglpZiAoMCAhPSBpc19saW5lYXJfY292ZXJhZ2UpIAoJewoJCXZhcmNjb29yZF9TMC54eSA9IGZsb2F0MigwLCBjb3ZlcmFnZSAqIGNvdmVyYWdlX211bHRpcGxpZXIpOwoJfQoJZWxzZSAKCXsKCQlmbG9hdDIgYXJjY29vcmQgPSAxIC0gYWJzKHJhZGl1c19vdXRzZXQpICsgYWFfb3V0c2V0L3JhZGlpICogY29ybmVyOwoJCXZhcmNjb29yZF9TMC54eSA9IGZsb2F0MihhcmNjb29yZC54KzEsIGFyY2Nvb3JkLnkpOwoJfQoJc2tfUG9zaXRpb24gPSBkZXZjb29yZC54eTAxOwp9CgEAAABRBQAAY29uc3QgaW50IGtGaWxsQUFfUzFfYzAgPSAxOwpjb25zdCBpbnQga0ludmVyc2VGaWxsQldfUzFfYzAgPSAyOwpjb25zdCBpbnQga0ludmVyc2VGaWxsQUFfUzFfYzAgPSAzOwp1bmlmb3JtIGZsb2F0NCB1Y2lyY2xlX1MxX2MwOwpmbGF0IGluIGhhbGY0IHZjb2xvcl9TMDsKaW4gZmxvYXQyIHZhcmNjb29yZF9TMDsKaGFsZjQgQ2lyY2xlX1MxX2MwKGhhbGY0IF9pbnB1dCkgCnsKCWhhbGY0IF90bXBfMF9pbkNvbG9yID0gX2lucHV0OwoJaGFsZiBkOwoJaWYgKGludCgzKSA9PSBrSW52ZXJzZUZpbGxCV19TMV9jMCB8fCBpbnQoMykgPT0ga0ludmVyc2VGaWxsQUFfUzFfYzApIAoJewoJCWQgPSBoYWxmKChsZW5ndGgoKHVjaXJjbGVfUzFfYzAueHkgLSBza19GcmFnQ29vcmQueHkpICogdWNpcmNsZV9TMV9jMC53KSAtIDEuMCkgKiB1Y2lyY2xlX1MxX2MwLnopOwoJfQoJZWxzZSAKCXsKCQlkID0gaGFsZigoMS4wIC0gbGVuZ3RoKCh1Y2lyY2xlX1MxX2MwLnh5IC0gc2tfRnJhZ0Nvb3JkLnh5KSAqIHVjaXJjbGVfUzFfYzAudykpICogdWNpcmNsZV9TMV9jMC56KTsKCX0KCXJldHVybiBoYWxmNChoYWxmNChpbnQoMykgPT0ga0ZpbGxBQV9TMV9jMCB8fCBpbnQoMykgPT0ga0ludmVyc2VGaWxsQUFfUzFfYzAgPyBzYXR1cmF0ZShkKSA6IGhhbGYoZCA+IDAuNSA/IDEgOiAwKSkpOwp9CmhhbGY0IEJsZW5kX1MxKGhhbGY0IF9zcmMsIGhhbGY0IF9kc3QpIAp7CglyZXR1cm4gYmxlbmRfbW9kdWxhdGUoX3NyYywgQ2lyY2xlX1MxX2MwKF9zcmMpKTsKfQp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgRmlsbFJSZWN0T3A6OlByb2Nlc3NvcgoJaGFsZjQgb3V0cHV0Q29sb3JfUzA7CglvdXRwdXRDb2xvcl9TMCA9IHZjb2xvcl9TMDsKCWZsb2F0IHhfcGx1c18xPXZhcmNjb29yZF9TMC54LCB5PXZhcmNjb29yZF9TMC55OwoJaGFsZiBjb3ZlcmFnZTsKCWlmICgwID09IHhfcGx1c18xKSAKCXsKCQljb3ZlcmFnZSA9IGhhbGYoeSk7Cgl9CgllbHNlIAoJewoJCWZsb2F0IGZuID0geF9wbHVzXzEgKiAoeF9wbHVzXzEgLSAyKTsKCQlmbiA9IGZtYSh5LHksIGZuKTsKCQlmbG9hdCBmbndpZHRoID0gZndpZHRoKGZuKTsKCQljb3ZlcmFnZSA9IC41IC0gaGFsZihmbi9mbndpZHRoKTsKCQljb3ZlcmFnZSA9IGNsYW1wKGNvdmVyYWdlLCAwLCAxKTsKCX0KCWhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoY292ZXJhZ2UpOwoJaGFsZjQgb3V0cHV0X1MxOwoJb3V0cHV0X1MxID0gQmxlbmRfUzEob3V0cHV0Q292ZXJhZ2VfUzAsIGhhbGY0KDEpKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dF9TMTsKCX0KfQoAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAACAAAAA4AAAByYWRpaV9zZWxlY3RvcgAAGQAAAGNvcm5lcl9hbmRfcmFkaXVzX291dHNldHMAAAAVAAAAYWFfYmxvYXRfYW5kX2NvdmVyYWdlAAAABwAAAHJhZGlpX3gABwAAAHJhZGlpX3kABAAAAHNrZXcZAAAAdHJhbnNsYXRlX2FuZF9sb2NhbHJvdGF0ZQAAAAUAAABjb2xvcgAAAAAAAAA=","GEMAAAYAAEHAAAARC4EAAAQWBQAAAAAAAAAQAAAAIBCAAAGQAEAAAAAQAAAABAEQAEAAAAA":"CgAAAExTS1NUAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBpblBvc2l0aW9uOwppbiBoYWxmNCBpbkNvbG9yOwppbiBoYWxmMyBpblNoYWRvd1BhcmFtczsKb3V0IGhhbGYzIHZpblNoYWRvd1BhcmFtc19TMDsKb3V0IGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBSUmVjdFNoYWRvdwoJdmluU2hhZG93UGFyYW1zX1MwID0gaW5TaGFkb3dQYXJhbXM7Cgl2aW5Db2xvcl9TMCA9IGluQ29sb3I7CglmbG9hdDIgX3RtcF8wX2luUG9zaXRpb24gPSBpblBvc2l0aW9uOwoJc2tfUG9zaXRpb24gPSBfdG1wXzBfaW5Qb3NpdGlvbi54eTAxOwp9CgAAAAALAgAAdW5pZm9ybSBzYW1wbGVyMkQgdVRleHR1cmVTYW1wbGVyXzBfUzA7CmluIGhhbGYzIHZpblNoYWRvd1BhcmFtc19TMDsKaW4gaGFsZjQgdmluQ29sb3JfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBSUmVjdFNoYWRvdwoJaGFsZjMgc2hhZG93UGFyYW1zOwoJc2hhZG93UGFyYW1zID0gdmluU2hhZG93UGFyYW1zX1MwOwoJaGFsZjQgb3V0cHV0Q29sb3JfUzA7CglvdXRwdXRDb2xvcl9TMCA9IHZpbkNvbG9yX1MwOwoJaGFsZiBkID0gbGVuZ3RoKHNoYWRvd1BhcmFtcy54eSk7CglmbG9hdDIgdXYgPSBmbG9hdDIoc2hhZG93UGFyYW1zLnogKiAoMS4wIC0gZCksIDAuNSk7CgloYWxmIGZhY3RvciA9IHNhbXBsZSh1VGV4dHVyZVNhbXBsZXJfMF9TMCwgdXYpLjAwMHIuYTsKCWhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoZmFjdG9yKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAoAAABpblBvc2l0aW9uAAAHAAAAaW5Db2xvcgAOAAAAaW5TaGFkb3dQYXJhbXMAAAAAAAA=","AYQA5AADQAAAOAEARAFQJAABBADIB7777777777777777777777767YAAAAAAAAAACABYQA6AAAEAAAAAAAIADQAAAAIAAAAAAAIIDA":"CgAAAExTS1PMAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQ0IHVsb2NhbE1hdHJpeF9TMDsKaW4gZmxvYXQyIGluUG9zaXRpb247CmluIGhhbGY0IGluQ29sb3I7CmluIGZsb2F0NCBpbkNpcmNsZUVkZ2U7Cm91dCBmbG9hdDQgdmluQ2lyY2xlRWRnZV9TMDsKb3V0IGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBDaXJjbGVHZW9tZXRyeVByb2Nlc3NvcgoJdmluQ2lyY2xlRWRnZV9TMCA9IGluQ2lyY2xlRWRnZTsKCXZpbkNvbG9yX1MwID0gaW5Db2xvcjsKCWZsb2F0MiBfdG1wXzBfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247CglmbG9hdDIgX3RtcF8xX2luUG9zaXRpb24gPSB1bG9jYWxNYXRyaXhfUzAueHogKiBpblBvc2l0aW9uICsgdWxvY2FsTWF0cml4X1MwLnl3OwoJc2tfUG9zaXRpb24gPSBfdG1wXzBfaW5Qb3NpdGlvbi54eTAxOwp9CgEAAAB5AwAAdW5pZm9ybSBmbG9hdDQgdWlubmVyUmVjdF9TMTsKdW5pZm9ybSBoYWxmMiB1cmFkaXVzUGx1c0hhbGZfUzE7CmluIGZsb2F0NCB2aW5DaXJjbGVFZGdlX1MwOwppbiBoYWxmNCB2aW5Db2xvcl9TMDsKaGFsZjQgQ2lyY3VsYXJSUmVjdF9TMShoYWxmNCBfaW5wdXQpIAp7CglmbG9hdDIgZHh5MCA9IHVpbm5lclJlY3RfUzEuTFQgLSBza19GcmFnQ29vcmQueHk7CglmbG9hdDIgZHh5MSA9IHNrX0ZyYWdDb29yZC54eSAtIHVpbm5lclJlY3RfUzEuUkI7CglmbG9hdDIgZHh5ID0gbWF4KG1heChkeHkwLCBkeHkxKSwgMC4wKTsKCWhhbGYgYWxwaGEgPSBoYWxmKHNhdHVyYXRlKHVyYWRpdXNQbHVzSGFsZl9TMS54IC0gbGVuZ3RoKGR4eSkpKTsKCXJldHVybiBfaW5wdXQgKiBhbHBoYTsKfQp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgQ2lyY2xlR2VvbWV0cnlQcm9jZXNzb3IKCWZsb2F0NCBjaXJjbGVFZGdlOwoJY2lyY2xlRWRnZSA9IHZpbkNpcmNsZUVkZ2VfUzA7CgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdmluQ29sb3JfUzA7CglmbG9hdCBkID0gbGVuZ3RoKGNpcmNsZUVkZ2UueHkpOwoJaGFsZiBkaXN0YW5jZVRvT3V0ZXJFZGdlID0gaGFsZihjaXJjbGVFZGdlLnogKiAoMS4wIC0gZCkpOwoJaGFsZiBlZGdlQWxwaGEgPSBzYXR1cmF0ZShkaXN0YW5jZVRvT3V0ZXJFZGdlKTsKCWhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoZWRnZUFscGhhKTsKCWhhbGY0IG91dHB1dF9TMTsKCW91dHB1dF9TMSA9IENpcmN1bGFyUlJlY3RfUzEob3V0cHV0Q292ZXJhZ2VfUzApOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dENvbG9yX1MwICogb3V0cHV0X1MxOwoJfQp9CgAAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAADAAAACgAAAGluUG9zaXRpb24AAAcAAABpbkNvbG9yAAwAAABpbkNpcmNsZUVkZ2UAAAAA","HVIACAAAABQAAGAAAQ4AAAAAGQQAARC4GAAAIOCAAD6P7777777777YDAAAAAAAAAAAFIBQU7BTXIAAAAAACAAAAAAQFV5W6JEAAAAAYAAAABQEZ2AKAWAQAABAL6SYKDYAAAACAAAAAAQEGIAAAAACAWTWL3EYAAAADAAAAACADHIJJCYCAAAEAP2LRIPAAAAAIAAAAAAABTALI3F5SOAIAABQAAAAAABTUEUZMBAAAAAH5FYUXQAAAAAAAEAAAAAZMRGOQCQFQEAAAAAAAAAGARL2LXJHAAEAAAAAEAAAABSCQX5FQUHQAAAAAAAAAACAA4AAAABAACAAAACCAYAAAAA":"CgAAAExTS1PrAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMV9jMF9jMF9jMTsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBmbG9hdCBjb3ZlcmFnZTsKaW4gaGFsZjQgY29sb3I7CmluIGZsb2F0MiBsb2NhbENvb3JkOwpmbGF0IG91dCBoYWxmNCB2Y29sb3JfUzA7Cm91dCBmbG9hdCB2Y292ZXJhZ2VfUzA7Cm91dCBmbG9hdDIgdlRyYW5zZm9ybWVkQ29vcmRzXzZfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJZmxvYXQyIHBvc2l0aW9uID0gcG9zaXRpb24ueHk7Cgl2Y29sb3JfUzAgPSBjb2xvcjsKCXZjb3ZlcmFnZV9TMCA9IGNvdmVyYWdlOwoJc2tfUG9zaXRpb24gPSBwb3NpdGlvbi54eTAxOwoJewoJCXZUcmFuc2Zvcm1lZENvb3Jkc182X1MwID0gZmxvYXQzeDIodW1hdHJpeF9TMV9jMF9jMF9jMSkgKiBsb2NhbENvb3JkLnh5MTsKCX0KfQoAAAAAAMMHAAB1bmlmb3JtIGhhbGY0IHVzdGFydF9TMV9jMF9jMF9jMDsKdW5pZm9ybSBoYWxmNCB1ZW5kX1MxX2MwX2MwX2MwOwp1bmlmb3JtIGZsb2F0M3gzIHVtYXRyaXhfUzFfYzBfYzBfYzE7CnVuaWZvcm0gaGFsZjQgdWxlZnRCb3JkZXJDb2xvcl9TMV9jMF9jMDsKdW5pZm9ybSBoYWxmNCB1cmlnaHRCb3JkZXJDb2xvcl9TMV9jMF9jMDsKZmxhdCBpbiBoYWxmNCB2Y29sb3JfUzA7CmluIGZsb2F0IHZjb3ZlcmFnZV9TMDsKaW4gZmxvYXQyIHZUcmFuc2Zvcm1lZENvb3Jkc182X1MwOwpoYWxmNCBTaW5nbGVJbnRlcnZhbENvbG9yaXplcl9TMV9jMF9jMF9jMChoYWxmNCBfaW5wdXQsIGZsb2F0MiBfY29vcmRzKSAKewoJaGFsZjQgX3RtcF8wX2luQ29sb3IgPSBfaW5wdXQ7CglmbG9hdDIgX3RtcF8xX2Nvb3JkcyA9IF9jb29yZHM7CglyZXR1cm4gaGFsZjQobWl4KHVzdGFydF9TMV9jMF9jMF9jMCwgdWVuZF9TMV9jMF9jMF9jMCwgaGFsZihfdG1wXzFfY29vcmRzLngpKSk7Cn0KaGFsZjQgTGluZWFyTGF5b3V0X1MxX2MwX2MwX2MxX2MwKGhhbGY0IF9pbnB1dCkgCnsKCWhhbGY0IF90bXBfMl9pbkNvbG9yID0gX2lucHV0OwoJZmxvYXQyIF90bXBfM19jb29yZHMgPSB2VHJhbnNmb3JtZWRDb29yZHNfNl9TMDsKCXJldHVybiBoYWxmNChoYWxmNChoYWxmKF90bXBfM19jb29yZHMueCkgKyAxZS0wNSwgMS4wLCAwLjAsIDAuMCkpOwp9CmhhbGY0IE1hdHJpeEVmZmVjdF9TMV9jMF9jMF9jMShoYWxmNCBfaW5wdXQpIAp7CglyZXR1cm4gTGluZWFyTGF5b3V0X1MxX2MwX2MwX2MxX2MwKF9pbnB1dCk7Cn0KaGFsZjQgQ2xhbXBlZEdyYWRpZW50X1MxX2MwX2MwKGhhbGY0IF9pbnB1dCkgCnsKCWhhbGY0IF90bXBfNF9pbkNvbG9yID0gX2lucHV0OwoJaGFsZjQgdCA9IE1hdHJpeEVmZmVjdF9TMV9jMF9jMF9jMShfdG1wXzRfaW5Db2xvcik7CgloYWxmNCBvdXRDb2xvcjsKCWlmICghYm9vbChpbnQoMSkpICYmIHQueSA8IDAuMCkgCgl7CgkJb3V0Q29sb3IgPSBoYWxmNCgwLjApOwoJfQoJZWxzZSBpZiAodC54IDwgMC4wKSAKCXsKCQlvdXRDb2xvciA9IHVsZWZ0Qm9yZGVyQ29sb3JfUzFfYzBfYzA7Cgl9CgllbHNlIGlmICh0LnggPiAxLjApIAoJewoJCW91dENvbG9yID0gdXJpZ2h0Qm9yZGVyQ29sb3JfUzFfYzBfYzA7Cgl9CgllbHNlIAoJewoJCW91dENvbG9yID0gU2luZ2xlSW50ZXJ2YWxDb2xvcml6ZXJfUzFfYzBfYzBfYzAoX3RtcF80X2luQ29sb3IsIGZsb2F0MihoYWxmMih0LngsIDAuMCkpKTsKCX0KCXJldHVybiBoYWxmNChvdXRDb2xvcik7Cn0KaGFsZjQgY29sb3JfeGZvcm1fUzFfYzAoZmxvYXQ0IGNvbG9yKSAKewoJY29sb3IucmdiICo9IGNvbG9yLmE7CglyZXR1cm4gaGFsZjQoY29sb3IpOwp9CmhhbGY0IENvbG9yU3BhY2VYZm9ybV9TMV9jMChoYWxmNCBfaW5wdXQpIAp7CglyZXR1cm4gY29sb3JfeGZvcm1fUzFfYzAoQ2xhbXBlZEdyYWRpZW50X1MxX2MwX2MwKF9pbnB1dCkpOwp9CmhhbGY0IERpc2FibGVDb3ZlcmFnZUFzQWxwaGFfUzEoaGFsZjQgX2lucHV0KSAKewoJX2lucHV0ID0gQ29sb3JTcGFjZVhmb3JtX1MxX2MwKF9pbnB1dCk7CgloYWxmNCBfdG1wXzVfaW5Db2xvciA9IF9pbnB1dDsKCXJldHVybiBoYWxmNChfaW5wdXQpOwp9CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBRdWFkUGVyRWRnZUFBR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2Y29sb3JfUzA7CglmbG9hdCBjb3ZlcmFnZSA9IHZjb3ZlcmFnZV9TMDsKCWhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoaGFsZihjb3ZlcmFnZSkpOwoJaGFsZjQgb3V0cHV0X1MxOwoJb3V0cHV0X1MxID0gRGlzYWJsZUNvdmVyYWdlQXNBbHBoYV9TMShvdXRwdXRDb2xvcl9TMCk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gKGhhbGY0KDEuMCkgLSBvdXRwdXRfUzEpICogb3V0cHV0Q292ZXJhZ2VfUzA7Cgl9Cn0KAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAEAAAACAAAAHBvc2l0aW9uCAAAAGNvdmVyYWdlBQAAAGNvbG9yAAAACgAAAGxvY2FsQ29vcmQAAAAAAAA=","HUQAAAAAAAMAADAAAIOAAAH677776IZOCAAP577777777777777777YBAAAAAAAAAAAKAAYAAAACAAAAAAACCAYAAA":"CgAAAExTS1PUAAAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gaGFsZjQgY29sb3I7CmZsYXQgb3V0IGhhbGY0IHZjb2xvcl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgl2Y29sb3JfUzAgPSBjb2xvcjsKCXNrX1Bvc2l0aW9uID0gcG9zaXRpb24ueHkwMTsKfQoAAAAAEQEAAGZsYXQgaW4gaGFsZjQgdmNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdmNvbG9yX1MwOwoJY29uc3QgaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNCgxKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAACAAAACAAAAHBvc2l0aW9uBQAAAGNvbG9yAAAAAAAAAA==","HUQAAAAAAAMAADAAAIOAAAH677776IZOCAAP577777777777777777YBAAAAAAAAAAADEAANAAAAALHCKLMRAAAAAAAAABAAAAAGJBCFLQVBWAQAAAAAAQAAAAAMACQCAACAAAAA2AIBAEIAAAAAAAAAAAAIADQAAAAIAAAAAAAIIDAAAAAA":"CgAAAExTS1PUAAAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gaGFsZjQgY29sb3I7CmZsYXQgb3V0IGhhbGY0IHZjb2xvcl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgl2Y29sb3JfUzAgPSBjb2xvcjsKCXNrX1Bvc2l0aW9uID0gcG9zaXRpb24ueHkwMTsKfQoBAAAAeAQAAHVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMV9jMF9jMDsKdW5pZm9ybSBoYWxmNCB1Y2lyY2xlRGF0YV9TMV9jMDsKdW5pZm9ybSBzYW1wbGVyMkQgdVRleHR1cmVTYW1wbGVyXzBfUzE7CmZsYXQgaW4gaGFsZjQgdmNvbG9yX1MwOwpoYWxmNCBUZXh0dXJlRWZmZWN0X1MxX2MwX2MwX2MwKGhhbGY0IF9pbnB1dCwgZmxvYXQyIF9jb29yZHMpIAp7CglyZXR1cm4gc2FtcGxlKHVUZXh0dXJlU2FtcGxlcl8wX1MxLCBfY29vcmRzKS4wMDByOwp9CmhhbGY0IE1hdHJpeEVmZmVjdF9TMV9jMF9jMChoYWxmNCBfaW5wdXQsIGZsb2F0MiBfY29vcmRzKSAKewoJcmV0dXJuIFRleHR1cmVFZmZlY3RfUzFfYzBfYzBfYzAoX2lucHV0LCBmbG9hdDN4Mih1bWF0cml4X1MxX2MwX2MwKSAqIF9jb29yZHMueHkxKTsKfQpoYWxmNCBDaXJjbGVCbHVyX1MxX2MwKGhhbGY0IF9pbnB1dCkgCnsKCWhhbGY0IF90bXBfMF9pbkNvbG9yID0gX2lucHV0OwoJaGFsZjIgdmVjID0gaGFsZjIoKHNrX0ZyYWdDb29yZC54eSAtIGZsb2F0Mih1Y2lyY2xlRGF0YV9TMV9jMC54eSkpICogZmxvYXQodWNpcmNsZURhdGFfUzFfYzAudykpOwoJaGFsZiBkaXN0ID0gbGVuZ3RoKHZlYykgKyAoMC41IC0gdWNpcmNsZURhdGFfUzFfYzAueikgKiB1Y2lyY2xlRGF0YV9TMV9jMC53OwoJcmV0dXJuIGhhbGY0KE1hdHJpeEVmZmVjdF9TMV9jMF9jMChfdG1wXzBfaW5Db2xvciwgZmxvYXQyKGhhbGYyKGRpc3QsIDAuNSkpKS53d3d3KTsKfQpoYWxmNCBCbGVuZF9TMShoYWxmNCBfc3JjLCBoYWxmNCBfZHN0KSAKewoJcmV0dXJuIGJsZW5kX21vZHVsYXRlKENpcmNsZUJsdXJfUzFfYzAoX3NyYyksIF9zcmMpOwp9CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBRdWFkUGVyRWRnZUFBR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2Y29sb3JfUzA7Cgljb25zdCBoYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KDEpOwoJaGFsZjQgb3V0cHV0X1MxOwoJb3V0cHV0X1MxID0gQmxlbmRfUzEob3V0cHV0Q292ZXJhZ2VfUzAsIGhhbGY0KDEpKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dF9TMTsKCX0KfQoBAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAgAAABwb3NpdGlvbgUAAABjb2xvcgAAAAAAAAA=","HWQACAAAABAAADAAAIOAAAAADIIAAIRODAAP577774DSAIAA737777YBAAAAAAAAAAAKAAYAAAACAAAAAAACCAYAAA":"CgAAAExTS1ONAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gZmxvYXQgY292ZXJhZ2U7CmluIGhhbGY0IGNvbG9yOwppbiBmbG9hdDQgZ2VvbVN1YnNldDsKZmxhdCBvdXQgaGFsZjQgdmNvbG9yX1MwOwpvdXQgZmxvYXQgdmNvdmVyYWdlX1MwOwpmbGF0IG91dCBmbG9hdDQgdmdlb21TdWJzZXRfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJZmxvYXQyIHBvc2l0aW9uID0gcG9zaXRpb24ueHk7Cgl2Y29sb3JfUzAgPSBjb2xvcjsKCXZjb3ZlcmFnZV9TMCA9IGNvdmVyYWdlOwoJdmdlb21TdWJzZXRfUzAgPSBnZW9tU3Vic2V0OwoJc2tfUG9zaXRpb24gPSBwb3NpdGlvbi54eTAxOwp9CgAAAAEAAAB5AgAAZmxhdCBpbiBoYWxmNCB2Y29sb3JfUzA7CmluIGZsb2F0IHZjb3ZlcmFnZV9TMDsKZmxhdCBpbiBmbG9hdDQgdmdlb21TdWJzZXRfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBRdWFkUGVyRWRnZUFBR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2Y29sb3JfUzA7CglmbG9hdCBjb3ZlcmFnZSA9IHZjb3ZlcmFnZV9TMDsKCWZsb2F0NCBnZW9TdWJzZXQ7CglnZW9TdWJzZXQgPSB2Z2VvbVN1YnNldF9TMDsKCWhhbGY0IGRpc3RzNCA9IGNsYW1wKGhhbGY0KDEsIDEsIC0xLCAtMSkgKiBoYWxmNChza19GcmFnQ29vcmQueHl4eSAtIGdlb1N1YnNldCksIDAsIDEpOwoJaGFsZjIgZGlzdHMyID0gZGlzdHM0Lnh5ICsgZGlzdHM0Lnp3IC0gMTsKCWhhbGYgc3Vic2V0Q292ZXJhZ2UgPSBkaXN0czIueCAqIGRpc3RzMi55OwoJY292ZXJhZ2UgPSBtaW4oY292ZXJhZ2UsIHN1YnNldENvdmVyYWdlKTsKCWhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoaGFsZihjb3ZlcmFnZSkpOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dENvbG9yX1MwICogb3V0cHV0Q292ZXJhZ2VfUzA7Cgl9Cn0KAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAIAAAAcG9zaXRpb24IAAAAY292ZXJhZ2UFAAAAY29sb3IAAAAKAAAAZ2VvbVN1YnNldAAAAAAAAA==","DAQAAAAAAABGAABAYAAQAIHCAIAYAQUBAEAAAAAAEAAAAAAAAAAAAIAD2AAAAAAQAVSWGRIBAAADAAAAACAAAAAAQCGEIQOZLBIQAAAABQAAAAAAAAAAAAFAAMAAAABAAAAAAABBAMAAA":"CgAAAExTS1MWAgAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQyIHVBdGxhc1NpemVJbnZfUzA7CmluIGZsb2F0MiBpblBvc2l0aW9uOwppbiBoYWxmNCBpbkNvbG9yOwppbiB1c2hvcnQyIGluVGV4dHVyZUNvb3JkczsKb3V0IGZsb2F0MiB2VGV4dHVyZUNvb3Jkc19TMDsKZmxhdCBvdXQgZmxvYXQgdlRleEluZGV4X1MwOwpvdXQgaGFsZjQgdmluQ29sb3JfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIEJpdG1hcFRleHQKCWludCB0ZXhJZHggPSAwOwoJZmxvYXQyIHVub3JtVGV4Q29vcmRzID0gZmxvYXQyKGluVGV4dHVyZUNvb3Jkcy54LCBpblRleHR1cmVDb29yZHMueSk7Cgl2VGV4dHVyZUNvb3Jkc19TMCA9IHVub3JtVGV4Q29vcmRzICogdUF0bGFzU2l6ZUludl9TMDsKCXZUZXhJbmRleF9TMCA9IGZsb2F0KHRleElkeCk7Cgl2aW5Db2xvcl9TMCA9IGluQ29sb3I7CglmbG9hdDIgX3RtcF8xX2luUG9zaXRpb24gPSBpblBvc2l0aW9uOwoJc2tfUG9zaXRpb24gPSBpblBvc2l0aW9uLnh5MDE7Cn0KAAABAAAARQUAAGNvbnN0IGludCBrRmlsbEJXX1MxX2MwID0gMDsKY29uc3QgaW50IGtJbnZlcnNlRmlsbEJXX1MxX2MwID0gMjsKY29uc3QgaW50IGtJbnZlcnNlRmlsbEFBX1MxX2MwID0gMzsKdW5pZm9ybSBmbG9hdDQgdXJlY3RVbmlmb3JtX1MxX2MwOwp1bmlmb3JtIHNhbXBsZXIyRCB1VGV4dHVyZVNhbXBsZXJfMF9TMDsKaW4gZmxvYXQyIHZUZXh0dXJlQ29vcmRzX1MwOwpmbGF0IGluIGZsb2F0IHZUZXhJbmRleF9TMDsKaW4gaGFsZjQgdmluQ29sb3JfUzA7CmhhbGY0IFJlY3RfUzFfYzAoaGFsZjQgX2lucHV0KSAKewoJaGFsZjQgX3RtcF8wX2luQ29sb3IgPSBfaW5wdXQ7CgloYWxmIGNvdmVyYWdlOwoJaWYgKGludCgxKSA9PSBrRmlsbEJXX1MxX2MwIHx8IGludCgxKSA9PSBrSW52ZXJzZUZpbGxCV19TMV9jMCkgCgl7CgkJY292ZXJhZ2UgPSBoYWxmKGFsbChncmVhdGVyVGhhbihmbG9hdDQoc2tfRnJhZ0Nvb3JkLnh5LCB1cmVjdFVuaWZvcm1fUzFfYzAuencpLCBmbG9hdDQodXJlY3RVbmlmb3JtX1MxX2MwLnh5LCBza19GcmFnQ29vcmQueHkpKSkpOwoJfQoJZWxzZSAKCXsKCQloYWxmNCBkaXN0czQgPSBzYXR1cmF0ZShoYWxmNCgxLjAsIDEuMCwgLTEuMCwgLTEuMCkgKiBoYWxmNChza19GcmFnQ29vcmQueHl4eSAtIHVyZWN0VW5pZm9ybV9TMV9jMCkpOwoJCWhhbGYyIGRpc3RzMiA9IChkaXN0czQueHkgKyBkaXN0czQuencpIC0gMS4wOwoJCWNvdmVyYWdlID0gZGlzdHMyLnggKiBkaXN0czIueTsKCX0KCWlmIChpbnQoMSkgPT0ga0ludmVyc2VGaWxsQldfUzFfYzAgfHwgaW50KDEpID09IGtJbnZlcnNlRmlsbEFBX1MxX2MwKSAKCXsKCQljb3ZlcmFnZSA9IDEuMCAtIGNvdmVyYWdlOwoJfQoJcmV0dXJuIGhhbGY0KGhhbGY0KGNvdmVyYWdlKSk7Cn0KaGFsZjQgQmxlbmRfUzEoaGFsZjQgX3NyYywgaGFsZjQgX2RzdCkgCnsKCXJldHVybiBibGVuZF9tb2R1bGF0ZShSZWN0X1MxX2MwKF9zcmMpLCBfc3JjKTsKfQp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgQml0bWFwVGV4dAoJaGFsZjQgb3V0cHV0Q29sb3JfUzA7CglvdXRwdXRDb2xvcl9TMCA9IHZpbkNvbG9yX1MwOwoJaGFsZjQgdGV4Q29sb3I7Cgl7CgkJdGV4Q29sb3IgPSBzYW1wbGUodVRleHR1cmVTYW1wbGVyXzBfUzAsIHZUZXh0dXJlQ29vcmRzX1MwKS5ycnJyOwoJfQoJaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSB0ZXhDb2xvcjsKCWhhbGY0IG91dHB1dF9TMTsKCW91dHB1dF9TMSA9IEJsZW5kX1MxKG91dHB1dENvdmVyYWdlX1MwLCBoYWxmNCgxKSk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRfUzE7Cgl9Cn0KAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAKAAAAaW5Qb3NpdGlvbgAABwAAAGluQ29sb3IADwAAAGluVGV4dHVyZUNvb3JkcwAAAAAA"}} \ No newline at end of file From bed111a165ede30e4575ad7e21993a634c86a229 Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Fri, 3 Mar 2023 18:17:51 +0100 Subject: [PATCH 04/31] accessibility: disable accessibility nav in app media query --- CHANGELOG.md | 1 + lib/widgets/about/bug_report.dart | 2 +- lib/widgets/aves_app.dart | 49 ++++++++++++++++++++----------- 3 files changed, 34 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 04954e13c..ede6aa10c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ All notable changes to this project will be documented in this file. ### Fixed +- Accessibility: using accessibility services keeping snack bar beyond countdown - Accessibility: navigation with TalkBack ## [v1.8.2] - 2023-02-28 diff --git a/lib/widgets/about/bug_report.dart b/lib/widgets/about/bug_report.dart index 3506dad8c..390e49b0b 100644 --- a/lib/widgets/about/bug_report.dart +++ b/lib/widgets/about/bug_report.dart @@ -161,7 +161,7 @@ class _BugReportState extends State with FeedbackMixin { 'System locales: ${WidgetsBinding.instance.window.locales.join(', ')}', 'Aves locale: ${settings.locale ?? 'system'} -> ${settings.appliedLocale}', 'Installer: ${packageInfo.installerStore}', - 'Accessibility: accessibleNavigation=${accessibility.accessibleNavigation}, disableAnimations=${accessibility.disableAnimations}', + 'Error reporting: ${settings.isErrorReportingAllowed}', ].join('\n'); } diff --git a/lib/widgets/aves_app.dart b/lib/widgets/aves_app.dart index 211f883e2..6e1b3dfdf 100644 --- a/lib/widgets/aves_app.dart +++ b/lib/widgets/aves_app.dart @@ -247,24 +247,39 @@ class _AvesAppState extends State with WidgetsBindingObserver { // handle Android TV remote `select` button LogicalKeySet(LogicalKeyboardKey.select): const ActivateIntent(), }, - child: MaterialApp( - navigatorKey: AvesApp.navigatorKey, - home: home, - navigatorObservers: _navigatorObservers, - builder: (context, child) => _decorateAppChild( - context: context, - initialized: initialized, - child: child, + child: MediaQuery.fromWindow( + child: Builder( + builder: (context) { + return MediaQuery( + data: MediaQuery.of(context).copyWith( + // disable accessible navigation, as it impacts snack bar action timer + // for all users of apps registered as accessibility services, + // even though they are not for accessibility purposes (like TalkBack is) + accessibleNavigation: false, + ), + child: MaterialApp( + navigatorKey: AvesApp.navigatorKey, + home: home, + navigatorObservers: _navigatorObservers, + builder: (context, child) => _decorateAppChild( + context: context, + initialized: initialized, + child: child, + ), + onGenerateTitle: (context) => context.l10n.appName, + theme: lightTheme, + darkTheme: darkTheme, + themeMode: themeBrightness.appThemeMode, + locale: settingsLocale, + localizationsDelegates: AppLocalizations.localizationsDelegates, + supportedLocales: AvesApp.supportedLocales, + // TODO TLAD remove custom scroll behavior when this is fixed: https://github.com/flutter/flutter/issues/82906 + scrollBehavior: StretchMaterialScrollBehavior(), + useInheritedMediaQuery: true, + ), + ); + }, ), - onGenerateTitle: (context) => context.l10n.appName, - theme: lightTheme, - darkTheme: darkTheme, - themeMode: themeBrightness.appThemeMode, - locale: settingsLocale, - localizationsDelegates: AppLocalizations.localizationsDelegates, - supportedLocales: AvesApp.supportedLocales, - // TODO TLAD remove custom scroll behavior when this is fixed: https://github.com/flutter/flutter/issues/82906 - scrollBehavior: StretchMaterialScrollBehavior(), ), ); }, From e82d042fc7d5329a74ea18e8845cadb69b50a510 Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Fri, 3 Mar 2023 18:28:02 +0100 Subject: [PATCH 05/31] static analysis --- lib/widgets/about/bug_report.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/widgets/about/bug_report.dart b/lib/widgets/about/bug_report.dart index 390e49b0b..3cd1f7d33 100644 --- a/lib/widgets/about/bug_report.dart +++ b/lib/widgets/about/bug_report.dart @@ -1,6 +1,5 @@ import 'dart:convert'; import 'dart:io'; -import 'dart:ui'; import 'package:aves/app_flavor.dart'; import 'package:aves/flutter_version.dart'; @@ -142,7 +141,6 @@ class _BugReportState extends State with FeedbackMixin { } Future _getInfo(BuildContext context) async { - final accessibility = window.accessibilityFeatures; final packageInfo = await PackageInfo.fromPlatform(); final androidInfo = await DeviceInfoPlugin().androidInfo; final flavor = context.read().toString().split('.')[1]; From 2183ff7cd7e1b8e2a866df603b9068eaece26329 Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Fri, 3 Mar 2023 20:27:12 +0100 Subject: [PATCH 06/31] #543 vaults: custom pattern lock --- CHANGELOG.md | 4 + lib/l10n/app_en.arb | 10 +- lib/model/vaults/enums.dart | 4 +- lib/model/vaults/vaults.dart | 21 ++++ lib/utils/dependencies.dart | 5 + .../filter_editors/edit_vault_dialog.dart | 1 + .../filter_editors/password_dialog.dart | 52 +++++---- .../filter_editors/pattern_dialog.dart | 75 ++++++++++++ .../dialogs/filter_editors/pin_dialog.dart | 50 ++++---- pubspec.lock | 8 ++ pubspec.yaml | 1 + untranslated.json | 108 ++++++++++++++++++ 12 files changed, 286 insertions(+), 53 deletions(-) create mode 100644 lib/widgets/dialogs/filter_editors/pattern_dialog.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index ede6aa10c..cd566af0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +### Added + +- Vaults: custom pattern lock + ### Changed - upgraded Flutter to stable v3.7.6 diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index a2bcaa31a..63827cd32 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -226,7 +226,8 @@ "unitSystemMetric": "Metric", "unitSystemImperial": "Imperial", - "vaultLockTypePin": "Pin", + "vaultLockTypePattern": "Pattern", + "vaultLockTypePin": "PIN", "vaultLockTypePassword": "Password", "videoControlsPlay": "Play", @@ -384,8 +385,11 @@ "vaultDialogLockModeWhenScreenOff": "Lock when screen turns off", "vaultDialogLockTypeLabel": "Lock type", - "pinDialogEnter": "Enter pin", - "pinDialogConfirm": "Confirm pin", + "patternDialogEnter": "Enter pattern", + "patternDialogConfirm": "Confirm pattern", + + "pinDialogEnter": "Enter PIN", + "pinDialogConfirm": "Confirm PIN", "passwordDialogEnter": "Enter password", "passwordDialogConfirm": "Confirm password", diff --git a/lib/model/vaults/enums.dart b/lib/model/vaults/enums.dart index 339f4c9f7..27752a438 100644 --- a/lib/model/vaults/enums.dart +++ b/lib/model/vaults/enums.dart @@ -1,13 +1,15 @@ import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:flutter/widgets.dart'; -enum VaultLockType { system, pin, password } +enum VaultLockType { system, pattern, pin, password } extension ExtraVaultLockType on VaultLockType { String getText(BuildContext context) { switch (this) { case VaultLockType.system: return context.l10n.settingsSystemDefault; + case VaultLockType.pattern: + return context.l10n.vaultLockTypePattern; case VaultLockType.pin: return context.l10n.vaultLockTypePin; case VaultLockType.password: diff --git a/lib/model/vaults/vaults.dart b/lib/model/vaults/vaults.dart index 015a08ac2..902a9aa0d 100644 --- a/lib/model/vaults/vaults.dart +++ b/lib/model/vaults/vaults.dart @@ -7,6 +7,7 @@ import 'package:aves/services/common/services.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/dialogs/aves_dialog.dart'; import 'package:aves/widgets/dialogs/filter_editors/password_dialog.dart'; +import 'package:aves/widgets/dialogs/filter_editors/pattern_dialog.dart'; import 'package:aves/widgets/dialogs/filter_editors/pin_dialog.dart'; import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; @@ -160,6 +161,16 @@ class Vaults extends ChangeNotifier { } } break; + case VaultLockType.pattern: + final pattern = await showDialog( + context: context, + builder: (context) => const PatternDialog(needConfirmation: false), + routeSettings: const RouteSettings(name: PatternDialog.routeName), + ); + if (pattern != null) { + confirmed = pattern == await securityService.readValue(details.passKey); + } + break; case VaultLockType.pin: final pin = await showDialog( context: context, @@ -211,6 +222,16 @@ class Vaults extends ChangeNotifier { } } break; + case VaultLockType.pattern: + final pattern = await showDialog( + context: context, + builder: (context) => const PatternDialog(needConfirmation: true), + routeSettings: const RouteSettings(name: PatternDialog.routeName), + ); + if (pattern != null) { + return await securityService.writeValue(details.passKey, pattern); + } + break; case VaultLockType.pin: final pin = await showDialog( context: context, diff --git a/lib/utils/dependencies.dart b/lib/utils/dependencies.dart index 9219ac084..564d43c57 100644 --- a/lib/utils/dependencies.dart +++ b/lib/utils/dependencies.dart @@ -260,6 +260,11 @@ class Dependencies { license: apache2, sourceUrl: 'https://github.com/zesage/panorama', ), + Dependency( + name: 'Pattern Lock', + license: apache2, + sourceUrl: 'https://github.com/qwert2603/pattern_lock', + ), Dependency( name: 'Percent Indicator', license: bsd2, diff --git a/lib/widgets/dialogs/filter_editors/edit_vault_dialog.dart b/lib/widgets/dialogs/filter_editors/edit_vault_dialog.dart index 52c81df08..165a8c055 100644 --- a/lib/widgets/dialogs/filter_editors/edit_vault_dialog.dart +++ b/lib/widgets/dialogs/filter_editors/edit_vault_dialog.dart @@ -39,6 +39,7 @@ class _EditVaultDialogState extends State { final List _lockTypeOptions = [ if (device.canAuthenticateUser) VaultLockType.system, if (device.canUseCrypto) ...[ + VaultLockType.pattern, VaultLockType.pin, VaultLockType.password, ], diff --git a/lib/widgets/dialogs/filter_editors/password_dialog.dart b/lib/widgets/dialogs/filter_editors/password_dialog.dart index 80b075e6b..08f4864e8 100644 --- a/lib/widgets/dialogs/filter_editors/password_dialog.dart +++ b/lib/widgets/dialogs/filter_editors/password_dialog.dart @@ -41,31 +41,7 @@ class _PasswordDialogState extends State { controller: _controller, focusNode: _focusNode, obscureText: true, - onSubmitted: (password) { - if (widget.needConfirmation) { - if (_confirming) { - final match = _firstPassword == password; - Navigator.maybeOf(context)?.pop(match ? password : null); - if (!match) { - showDialog( - context: context, - builder: (context) => AvesDialog( - content: Text(context.l10n.genericFailureFeedback), - actions: const [OkButton()], - ), - routeSettings: const RouteSettings(name: AvesDialog.warningRouteName), - ); - } - } else { - _firstPassword = password; - _controller.clear(); - setState(() => _confirming = true); - WidgetsBinding.instance.addPostFrameCallback((_) => _focusNode.requestFocus()); - } - } else { - Navigator.maybeOf(context)?.pop(password); - } - }, + onSubmitted: _submit, autofillHints: const [AutofillHints.password], ), ), @@ -73,4 +49,30 @@ class _PasswordDialogState extends State { ), ); } + + void _submit(String password) { + if (widget.needConfirmation) { + if (_confirming) { + final match = _firstPassword == password; + Navigator.maybeOf(context)?.pop(match ? password : null); + if (!match) { + showDialog( + context: context, + builder: (context) => AvesDialog( + content: Text(context.l10n.genericFailureFeedback), + actions: const [OkButton()], + ), + routeSettings: const RouteSettings(name: AvesDialog.warningRouteName), + ); + } + } else { + _firstPassword = password; + _controller.clear(); + setState(() => _confirming = true); + WidgetsBinding.instance.addPostFrameCallback((_) => _focusNode.requestFocus()); + } + } else { + Navigator.maybeOf(context)?.pop(password); + } + } } diff --git a/lib/widgets/dialogs/filter_editors/pattern_dialog.dart b/lib/widgets/dialogs/filter_editors/pattern_dialog.dart new file mode 100644 index 000000000..f77241c9d --- /dev/null +++ b/lib/widgets/dialogs/filter_editors/pattern_dialog.dart @@ -0,0 +1,75 @@ +import 'package:aves/widgets/common/extensions/build_context.dart'; +import 'package:aves/widgets/dialogs/aves_dialog.dart'; +import 'package:flutter/material.dart'; +import 'package:pattern_lock/pattern_lock.dart'; +import 'package:provider/provider.dart'; + +class PatternDialog extends StatefulWidget { + static const routeName = '/dialog/pattern'; + + final bool needConfirmation; + + const PatternDialog({ + super.key, + required this.needConfirmation, + }); + + @override + State createState() => _PatternDialogState(); +} + +class _PatternDialogState extends State { + bool _confirming = false; + String? _firstPattern; + + @override + Widget build(BuildContext context) { + final colorScheme = Theme.of(context).colorScheme; + return AvesDialog( + content: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text(_confirming ? context.l10n.patternDialogConfirm : context.l10n.patternDialogEnter), + Padding( + padding: const EdgeInsets.symmetric(vertical: 16), + child: SizedBox.square( + dimension: context.select((mq) => mq.size.shortestSide / 2), + child: PatternLock( + relativePadding: .4, + selectedColor: colorScheme.secondary, + notSelectedColor: colorScheme.onBackground, + pointRadius: 8, + fillPoints: true, + onInputComplete: (input) => _submit(input.join()), + ), + ), + ), + ], + ), + ); + } + + void _submit(String pattern) { + if (widget.needConfirmation) { + if (_confirming) { + final match = _firstPattern == pattern; + Navigator.maybeOf(context)?.pop(match ? pattern : null); + if (!match) { + showDialog( + context: context, + builder: (context) => AvesDialog( + content: Text(context.l10n.genericFailureFeedback), + actions: const [OkButton()], + ), + routeSettings: const RouteSettings(name: AvesDialog.warningRouteName), + ); + } + } else { + _firstPattern = pattern; + setState(() => _confirming = true); + } + } else { + Navigator.maybeOf(context)?.pop(pattern); + } + } +} diff --git a/lib/widgets/dialogs/filter_editors/pin_dialog.dart b/lib/widgets/dialogs/filter_editors/pin_dialog.dart index 7394061c0..52098c5b7 100644 --- a/lib/widgets/dialogs/filter_editors/pin_dialog.dart +++ b/lib/widgets/dialogs/filter_editors/pin_dialog.dart @@ -38,30 +38,7 @@ class _PinDialogState extends State { controller: _controller, obscureText: true, onChanged: (v) {}, - onCompleted: (pin) { - if (widget.needConfirmation) { - if (_confirming) { - final match = _firstPin == pin; - Navigator.maybeOf(context)?.pop(match ? pin : null); - if (!match) { - showDialog( - context: context, - builder: (context) => AvesDialog( - content: Text(context.l10n.genericFailureFeedback), - actions: const [OkButton()], - ), - routeSettings: const RouteSettings(name: AvesDialog.warningRouteName), - ); - } - } else { - _firstPin = pin; - _controller.clear(); - setState(() => _confirming = true); - } - } else { - Navigator.maybeOf(context)?.pop(pin); - } - }, + onCompleted: _submit, animationType: AnimationType.scale, keyboardType: TextInputType.number, autoFocus: true, @@ -80,4 +57,29 @@ class _PinDialogState extends State { ), ); } + + void _submit(String pin) { + if (widget.needConfirmation) { + if (_confirming) { + final match = _firstPin == pin; + Navigator.maybeOf(context)?.pop(match ? pin : null); + if (!match) { + showDialog( + context: context, + builder: (context) => AvesDialog( + content: Text(context.l10n.genericFailureFeedback), + actions: const [OkButton()], + ), + routeSettings: const RouteSettings(name: AvesDialog.warningRouteName), + ); + } + } else { + _firstPin = pin; + _controller.clear(); + setState(() => _confirming = true); + } + } else { + Navigator.maybeOf(context)?.pop(pin); + } + } } diff --git a/pubspec.lock b/pubspec.lock index 149ce2fd8..4583f1972 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -853,6 +853,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + pattern_lock: + dependency: "direct main" + description: + name: pattern_lock + sha256: "7929f877bcc82744ba2c0d55aaad1ff7cf09744f516b4853363fd29a1d7f539f" + url: "https://pub.dev" + source: hosted + version: "2.0.0" pdf: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index eface67c8..e4c188594 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -80,6 +80,7 @@ dependencies: url: https://github.com/deckerst/aves_panorama.git ref: aves path: + pattern_lock: pdf: percent_indicator: permission_handler: diff --git a/untranslated.json b/untranslated.json index 385066706..ea94407bc 100644 --- a/untranslated.json +++ b/untranslated.json @@ -136,6 +136,7 @@ "themeBrightnessBlack", "unitSystemMetric", "unitSystemImperial", + "vaultLockTypePattern", "vaultLockTypePin", "vaultLockTypePassword", "videoControlsPlay", @@ -195,6 +196,8 @@ "configureVaultDialogTitle", "vaultDialogLockModeWhenScreenOff", "vaultDialogLockTypeLabel", + "patternDialogEnter", + "patternDialogConfirm", "pinDialogEnter", "pinDialogConfirm", "passwordDialogEnter", @@ -688,6 +691,7 @@ "themeBrightnessBlack", "unitSystemMetric", "unitSystemImperial", + "vaultLockTypePattern", "vaultLockTypePin", "vaultLockTypePassword", "videoControlsPlay", @@ -747,6 +751,8 @@ "configureVaultDialogTitle", "vaultDialogLockModeWhenScreenOff", "vaultDialogLockTypeLabel", + "patternDialogEnter", + "patternDialogConfirm", "pinDialogEnter", "pinDialogConfirm", "passwordDialogEnter", @@ -1170,6 +1176,7 @@ "albumTierVaults", "lengthUnitPixel", "lengthUnitPercent", + "vaultLockTypePattern", "vaultLockTypePin", "vaultLockTypePassword", "newVaultWarningDialogMessage", @@ -1177,6 +1184,8 @@ "configureVaultDialogTitle", "vaultDialogLockModeWhenScreenOff", "vaultDialogLockTypeLabel", + "patternDialogEnter", + "patternDialogConfirm", "pinDialogEnter", "pinDialogConfirm", "passwordDialogEnter", @@ -1200,6 +1209,7 @@ "albumTierVaults", "lengthUnitPixel", "lengthUnitPercent", + "vaultLockTypePattern", "vaultLockTypePin", "vaultLockTypePassword", "newVaultWarningDialogMessage", @@ -1207,6 +1217,8 @@ "configureVaultDialogTitle", "vaultDialogLockModeWhenScreenOff", "vaultDialogLockTypeLabel", + "patternDialogEnter", + "patternDialogConfirm", "pinDialogEnter", "pinDialogConfirm", "passwordDialogEnter", @@ -1224,12 +1236,27 @@ "el": [ "chipActionGoToPlacePage", + "vaultLockTypePattern", + "patternDialogEnter", + "patternDialogConfirm", "exportEntryDialogWriteMetadata", "drawerPlacePage", "placePageTitle", "placeEmpty" ], + "es": [ + "vaultLockTypePattern", + "patternDialogEnter", + "patternDialogConfirm" + ], + + "eu": [ + "vaultLockTypePattern", + "patternDialogEnter", + "patternDialogConfirm" + ], + "fa": [ "clearTooltip", "chipActionGoToPlacePage", @@ -1269,6 +1296,7 @@ "lengthUnitPixel", "lengthUnitPercent", "nameConflictStrategySkip", + "vaultLockTypePattern", "vaultLockTypePin", "vaultLockTypePassword", "videoControlsNone", @@ -1315,6 +1343,8 @@ "configureVaultDialogTitle", "vaultDialogLockModeWhenScreenOff", "vaultDialogLockTypeLabel", + "patternDialogEnter", + "patternDialogConfirm", "pinDialogEnter", "pinDialogConfirm", "passwordDialogEnter", @@ -1698,6 +1728,12 @@ "filePickerUseThisFolder" ], + "fr": [ + "vaultLockTypePattern", + "patternDialogEnter", + "patternDialogConfirm" + ], + "gl": [ "columnCount", "chipActionGoToPlacePage", @@ -1731,6 +1767,7 @@ "themeBrightnessLight", "themeBrightnessDark", "themeBrightnessBlack", + "vaultLockTypePattern", "vaultLockTypePin", "vaultLockTypePassword", "videoPlaybackSkip", @@ -1783,6 +1820,8 @@ "configureVaultDialogTitle", "vaultDialogLockModeWhenScreenOff", "vaultDialogLockTypeLabel", + "patternDialogEnter", + "patternDialogConfirm", "pinDialogEnter", "pinDialogConfirm", "passwordDialogEnter", @@ -2353,6 +2392,7 @@ "themeBrightnessBlack", "unitSystemMetric", "unitSystemImperial", + "vaultLockTypePattern", "vaultLockTypePin", "vaultLockTypePassword", "videoControlsPlay", @@ -2412,6 +2452,8 @@ "configureVaultDialogTitle", "vaultDialogLockModeWhenScreenOff", "vaultDialogLockTypeLabel", + "patternDialogEnter", + "patternDialogConfirm", "pinDialogEnter", "pinDialogConfirm", "passwordDialogEnter", @@ -2827,10 +2869,19 @@ "filePickerUseThisFolder" ], + "id": [ + "vaultLockTypePattern", + "patternDialogEnter", + "patternDialogConfirm" + ], + "it": [ "chipActionGoToPlacePage", "lengthUnitPixel", "lengthUnitPercent", + "vaultLockTypePattern", + "patternDialogEnter", + "patternDialogConfirm", "exportEntryDialogWriteMetadata", "drawerPlacePage", "placePageTitle", @@ -2855,6 +2906,7 @@ "lengthUnitPercent", "subtitlePositionTop", "subtitlePositionBottom", + "vaultLockTypePattern", "vaultLockTypePin", "vaultLockTypePassword", "newVaultWarningDialogMessage", @@ -2862,6 +2914,8 @@ "configureVaultDialogTitle", "vaultDialogLockModeWhenScreenOff", "vaultDialogLockTypeLabel", + "patternDialogEnter", + "patternDialogConfirm", "pinDialogEnter", "pinDialogConfirm", "passwordDialogEnter", @@ -2884,6 +2938,12 @@ "settingsWidgetDisplayedItem" ], + "ko": [ + "vaultLockTypePattern", + "patternDialogEnter", + "patternDialogConfirm" + ], + "lt": [ "columnCount", "chipActionGoToPlacePage", @@ -2896,6 +2956,7 @@ "keepScreenOnVideoPlayback", "lengthUnitPixel", "lengthUnitPercent", + "vaultLockTypePattern", "vaultLockTypePin", "vaultLockTypePassword", "newVaultWarningDialogMessage", @@ -2903,6 +2964,8 @@ "configureVaultDialogTitle", "vaultDialogLockModeWhenScreenOff", "vaultDialogLockTypeLabel", + "patternDialogEnter", + "patternDialogConfirm", "pinDialogEnter", "pinDialogConfirm", "passwordDialogEnter", @@ -2932,6 +2995,7 @@ "albumTierVaults", "lengthUnitPixel", "lengthUnitPercent", + "vaultLockTypePattern", "vaultLockTypePin", "vaultLockTypePassword", "newVaultWarningDialogMessage", @@ -2939,6 +3003,8 @@ "configureVaultDialogTitle", "vaultDialogLockModeWhenScreenOff", "vaultDialogLockTypeLabel", + "patternDialogEnter", + "patternDialogConfirm", "pinDialogEnter", "pinDialogConfirm", "passwordDialogEnter", @@ -2975,6 +3041,7 @@ "lengthUnitPercent", "subtitlePositionTop", "subtitlePositionBottom", + "vaultLockTypePattern", "vaultLockTypePin", "vaultLockTypePassword", "widgetDisplayedItemRandom", @@ -2984,6 +3051,8 @@ "configureVaultDialogTitle", "vaultDialogLockModeWhenScreenOff", "vaultDialogLockTypeLabel", + "patternDialogEnter", + "patternDialogConfirm", "pinDialogEnter", "pinDialogConfirm", "passwordDialogEnter", @@ -3026,6 +3095,7 @@ "displayRefreshRatePreferLowest", "lengthUnitPixel", "lengthUnitPercent", + "vaultLockTypePattern", "vaultLockTypePin", "vaultLockTypePassword", "wallpaperTargetHome", @@ -3036,6 +3106,8 @@ "configureVaultDialogTitle", "vaultDialogLockModeWhenScreenOff", "vaultDialogLockTypeLabel", + "patternDialogEnter", + "patternDialogConfirm", "pinDialogEnter", "pinDialogConfirm", "passwordDialogEnter", @@ -3323,6 +3395,12 @@ "wallpaperUseScrollEffect" ], + "pl": [ + "vaultLockTypePattern", + "patternDialogEnter", + "patternDialogConfirm" + ], + "pt": [ "columnCount", "chipActionGoToPlacePage", @@ -3331,8 +3409,11 @@ "albumTierVaults", "lengthUnitPixel", "lengthUnitPercent", + "vaultLockTypePattern", "vaultLockTypePin", "newVaultWarningDialogMessage", + "patternDialogEnter", + "patternDialogConfirm", "passwordDialogConfirm", "authenticateToConfigureVault", "authenticateToUnlockVault", @@ -3351,6 +3432,9 @@ "chipActionGoToPlacePage", "lengthUnitPixel", "lengthUnitPercent", + "vaultLockTypePattern", + "patternDialogEnter", + "patternDialogConfirm", "exportEntryDialogWriteMetadata", "drawerPlacePage", "placePageTitle", @@ -3363,6 +3447,9 @@ "filterLocatedLabel", "filterTaggedLabel", "lengthUnitPixel", + "vaultLockTypePattern", + "patternDialogEnter", + "patternDialogConfirm", "authenticateToConfigureVault", "authenticateToUnlockVault", "exportEntryDialogWriteMetadata", @@ -3390,6 +3477,7 @@ "coordinateDms", "lengthUnitPixel", "lengthUnitPercent", + "vaultLockTypePattern", "vaultLockTypePin", "vaultLockTypePassword", "otherDirectoryDescription", @@ -3404,6 +3492,8 @@ "configureVaultDialogTitle", "vaultDialogLockModeWhenScreenOff", "vaultDialogLockTypeLabel", + "patternDialogEnter", + "patternDialogConfirm", "pinDialogEnter", "pinDialogConfirm", "passwordDialogEnter", @@ -3808,6 +3898,7 @@ "albumTierVaults", "lengthUnitPixel", "lengthUnitPercent", + "vaultLockTypePattern", "vaultLockTypePin", "vaultLockTypePassword", "newVaultWarningDialogMessage", @@ -3815,6 +3906,8 @@ "configureVaultDialogTitle", "vaultDialogLockModeWhenScreenOff", "vaultDialogLockTypeLabel", + "patternDialogEnter", + "patternDialogConfirm", "pinDialogEnter", "pinDialogConfirm", "passwordDialogEnter", @@ -4153,6 +4246,7 @@ "albumTierVaults", "lengthUnitPixel", "lengthUnitPercent", + "vaultLockTypePattern", "vaultLockTypePin", "vaultLockTypePassword", "newVaultWarningDialogMessage", @@ -4160,6 +4254,8 @@ "configureVaultDialogTitle", "vaultDialogLockModeWhenScreenOff", "vaultDialogLockTypeLabel", + "patternDialogEnter", + "patternDialogConfirm", "pinDialogEnter", "pinDialogConfirm", "passwordDialogEnter", @@ -4175,6 +4271,12 @@ "settingsDisablingBinWarningDialogMessage" ], + "uk": [ + "vaultLockTypePattern", + "patternDialogEnter", + "patternDialogConfirm" + ], + "zh": [ "chipActionGoToPlacePage", "chipActionLock", @@ -4185,6 +4287,7 @@ "albumTierVaults", "lengthUnitPixel", "lengthUnitPercent", + "vaultLockTypePattern", "vaultLockTypePin", "vaultLockTypePassword", "newVaultWarningDialogMessage", @@ -4192,6 +4295,8 @@ "configureVaultDialogTitle", "vaultDialogLockModeWhenScreenOff", "vaultDialogLockTypeLabel", + "patternDialogEnter", + "patternDialogConfirm", "pinDialogEnter", "pinDialogConfirm", "passwordDialogEnter", @@ -4224,6 +4329,7 @@ "albumTierVaults", "lengthUnitPixel", "lengthUnitPercent", + "vaultLockTypePattern", "vaultLockTypePin", "vaultLockTypePassword", "newVaultWarningDialogMessage", @@ -4231,6 +4337,8 @@ "configureVaultDialogTitle", "vaultDialogLockModeWhenScreenOff", "vaultDialogLockTypeLabel", + "patternDialogEnter", + "patternDialogConfirm", "pinDialogEnter", "pinDialogConfirm", "passwordDialogEnter", From 655d2518905264af930a024304d47f497782cd0a Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Sun, 5 Mar 2023 23:05:58 +0100 Subject: [PATCH 07/31] #478 picture-in-picture --- CHANGELOG.md | 2 + android/app/src/main/AndroidManifest.xml | 1 + .../aves/channel/calls/MediaSessionHandler.kt | 12 +- .../streams/MediaCommandStreamHandler.kt | 12 ++ lib/l10n/app_en.arb | 1 + lib/model/device.dart | 9 +- lib/model/settings/defaults.dart | 1 + lib/model/settings/settings.dart | 10 ++ lib/services/media/media_session_service.dart | 22 +++- lib/utils/dependencies.dart | 5 + lib/widgets/aves_app.dart | 1 - .../common/tile_extent_controller.dart | 4 +- lib/widgets/settings/video/video.dart | 14 +++ .../viewer/entry_horizontal_pager.dart | 110 ++++++++++++------ lib/widgets/viewer/entry_viewer_page.dart | 12 +- lib/widgets/viewer/entry_viewer_stack.dart | 105 +++++++++++++---- lib/widgets/viewer/notifications.dart | 6 + lib/widgets/viewer/video/conductor.dart | 26 ++++- lib/widgets/viewer/video/controller.dart | 5 - .../viewer/visual/entry_page_view.dart | 6 + .../lib/aves_report_platform.dart | 5 +- pubspec.lock | 9 ++ pubspec.yaml | 4 + untranslated.json | 49 ++++++-- 24 files changed, 341 insertions(+), 90 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cd566af0a..401ba61df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ All notable changes to this project will be documented in this file. ### Added - Vaults: custom pattern lock +- Video: picture-in-picture +- Video: handle skip next/previous media buttons ### Changed diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index ef519cae2..f7b14d5d6 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -96,6 +96,7 @@ This change eventually prevents building the app with Flutter v3.3.3. android:exported="true" android:hardwareAccelerated="true" android:launchMode="singleTop" + android:supportsPictureInPicture="true" android:theme="@style/NormalTheme" android:windowSoftInputMode="adjustResize"> diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/MediaSessionHandler.kt b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/MediaSessionHandler.kt index 779213671..f78099e0c 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/MediaSessionHandler.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/MediaSessionHandler.kt @@ -65,11 +65,13 @@ class MediaSessionHandler(private val context: Context, private val mediaCommand val stateString = call.argument("state") val positionMillis = call.argument("positionMillis")?.toLong() val playbackSpeed = call.argument("playbackSpeed")?.toFloat() + val canSkipToNext = call.argument("canSkipToNext") + val canSkipToPrevious = call.argument("canSkipToPrevious") - if (uri == null || title == null || durationMillis == null || stateString == null || positionMillis == null || playbackSpeed == null) { + if (uri == null || title == null || durationMillis == null || stateString == null || positionMillis == null || playbackSpeed == null || canSkipToNext == null || canSkipToPrevious == null) { result.error( "updateSession-args", "missing arguments: uri=$uri, title=$title, durationMillis=$durationMillis" + - ", stateString=$stateString, positionMillis=$positionMillis, playbackSpeed=$playbackSpeed", null + ", stateString=$stateString, positionMillis=$positionMillis, playbackSpeed=$playbackSpeed, canSkipToNext=$canSkipToNext, canSkipToPrevious=$canSkipToPrevious", null ) return } @@ -90,6 +92,12 @@ class MediaSessionHandler(private val context: Context, private val mediaCommand } else { actions or PlaybackStateCompat.ACTION_PLAY } + if (canSkipToNext) { + actions = actions or PlaybackStateCompat.ACTION_SKIP_TO_NEXT + } + if (canSkipToPrevious) { + actions = actions or PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS + } val playbackState = PlaybackStateCompat.Builder() .setState( diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/channel/streams/MediaCommandStreamHandler.kt b/android/app/src/main/kotlin/deckers/thibault/aves/channel/streams/MediaCommandStreamHandler.kt index b81815622..49273098f 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/channel/streams/MediaCommandStreamHandler.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/channel/streams/MediaCommandStreamHandler.kt @@ -46,6 +46,16 @@ class MediaCommandStreamHandler : EventChannel.StreamHandler, MediaSessionCompat success(hashMapOf(KEY_COMMAND to COMMAND_PAUSE)) } + override fun onSkipToNext() { + super.onSkipToNext() + success(hashMapOf(KEY_COMMAND to COMMAND_SKIP_TO_NEXT)) + } + + override fun onSkipToPrevious() { + super.onSkipToPrevious() + success(hashMapOf(KEY_COMMAND to COMMAND_SKIP_TO_PREVIOUS)) + } + override fun onStop() { super.onStop() success(hashMapOf(KEY_COMMAND to COMMAND_STOP)) @@ -70,6 +80,8 @@ class MediaCommandStreamHandler : EventChannel.StreamHandler, MediaSessionCompat const val COMMAND_PLAY = "play" const val COMMAND_PAUSE = "pause" + const val COMMAND_SKIP_TO_NEXT = "skip_to_next" + const val COMMAND_SKIP_TO_PREVIOUS = "skip_to_previous" const val COMMAND_STOP = "stop" const val COMMAND_SEEK = "seek" } diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 63827cd32..f11aeb838 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -793,6 +793,7 @@ "settingsVideoSectionTitle": "Video", "settingsVideoShowVideos": "Show videos", "settingsVideoEnableHardwareAcceleration": "Hardware acceleration", + "settingsVideoEnablePip": "Picture-in-picture", "settingsVideoAutoPlay": "Auto play", "settingsVideoLoopModeTile": "Loop mode", "settingsVideoLoopModeDialogTitle": "Loop Mode", diff --git a/lib/model/device.dart b/lib/model/device.dart index e49802885..1601324ab 100644 --- a/lib/model/device.dart +++ b/lib/model/device.dart @@ -1,5 +1,6 @@ import 'package:aves/services/common/services.dart'; import 'package:device_info_plus/device_info_plus.dart'; +import 'package:floating/floating.dart'; import 'package:local_auth/local_auth.dart'; import 'package:package_info_plus/package_info_plus.dart'; @@ -9,7 +10,7 @@ class Device { late final String _userAgent; late final bool _canAuthenticateUser, _canGrantDirectoryAccess, _canPinShortcut, _canPrint; late final bool _canRenderFlagEmojis, _canRequestManageMedia, _canSetLockScreenWallpaper, _canUseCrypto; - late final bool _hasGeocoder, _isDynamicColorAvailable, _isTelevision, _showPinShortcutFeedback, _supportEdgeToEdgeUIMode; + late final bool _hasGeocoder, _isDynamicColorAvailable, _isTelevision, _showPinShortcutFeedback, _supportEdgeToEdgeUIMode, _supportPictureInPicture; String get userAgent => _userAgent; @@ -41,6 +42,8 @@ class Device { bool get supportEdgeToEdgeUIMode => _supportEdgeToEdgeUIMode; + bool get supportPictureInPicture => _supportPictureInPicture; + Device._private(); Future init() async { @@ -53,6 +56,10 @@ class Device { final auth = LocalAuthentication(); _canAuthenticateUser = await auth.canCheckBiometrics || await auth.isDeviceSupported(); + final floating = Floating(); + _supportPictureInPicture = await floating.isPipAvailable; + floating.dispose(); + final capabilities = await deviceService.getCapabilities(); _canGrantDirectoryAccess = capabilities['canGrantDirectoryAccess'] ?? false; _canPinShortcut = capabilities['canPinShortcut'] ?? false; diff --git a/lib/model/settings/defaults.dart b/lib/model/settings/defaults.dart index 554faccd8..a1908aab2 100644 --- a/lib/model/settings/defaults.dart +++ b/lib/model/settings/defaults.dart @@ -90,6 +90,7 @@ class SettingsDefaults { // video static const enableVideoHardwareAcceleration = true; + static const enableVideoPip = false; static const videoAutoPlayMode = VideoAutoPlayMode.disabled; static const videoLoopMode = VideoLoopMode.shortOnly; static const videoShowRawTimedText = false; diff --git a/lib/model/settings/settings.dart b/lib/model/settings/settings.dart index e89a34383..9d19757ab 100644 --- a/lib/model/settings/settings.dart +++ b/lib/model/settings/settings.dart @@ -133,6 +133,7 @@ class Settings extends ChangeNotifier { // video static const enableVideoHardwareAccelerationKey = 'video_hwaccel_mediacodec'; + static const enableVideoPipKey = 'video_pip'; static const videoAutoPlayModeKey = 'video_auto_play_mode'; static const videoLoopModeKey = 'video_loop'; static const videoControlsKey = 'video_controls'; @@ -284,6 +285,7 @@ class Settings extends ChangeNotifier { viewerGestureSideTapNext = false; viewerUseCutout = true; viewerMaxBrightness = false; + enableVideoPip = false; videoControls = VideoControls.none; videoGestureDoubleTapTogglePlay = false; videoGestureSideDoubleTapSeek = false; @@ -298,6 +300,9 @@ class Settings extends ChangeNotifier { if (viewerUseCutout != SettingsDefaults.viewerUseCutout && !await windowService.isCutoutAware()) { _set(viewerUseCutoutKey, null); } + if (enableVideoPip && !device.supportPictureInPicture) { + _set(enableVideoPipKey, null); + } } // app @@ -655,6 +660,10 @@ class Settings extends ChangeNotifier { set enableVideoHardwareAcceleration(bool newValue) => _set(enableVideoHardwareAccelerationKey, newValue); + bool get enableVideoPip => getBool(enableVideoPipKey) ?? SettingsDefaults.enableVideoPip; + + set enableVideoPip(bool newValue) => _set(enableVideoPipKey, newValue); + VideoAutoPlayMode get videoAutoPlayMode => getEnumOrDefault(videoAutoPlayModeKey, SettingsDefaults.videoAutoPlayMode, VideoAutoPlayMode.values); set videoAutoPlayMode(VideoAutoPlayMode newValue) => _set(videoAutoPlayModeKey, newValue.toString()); @@ -1078,6 +1087,7 @@ class Settings extends ChangeNotifier { case viewerUseCutoutKey: case viewerMaxBrightnessKey: case enableMotionPhotoAutoPlayKey: + case enableVideoPipKey: case enableVideoHardwareAccelerationKey: case videoGestureDoubleTapTogglePlayKey: case videoGestureSideDoubleTapSeekKey: diff --git a/lib/services/media/media_session_service.dart b/lib/services/media/media_session_service.dart index b453716e0..643c19297 100644 --- a/lib/services/media/media_session_service.dart +++ b/lib/services/media/media_session_service.dart @@ -11,7 +11,11 @@ import 'package:get_it/get_it.dart'; abstract class MediaSessionService { Stream get mediaCommands; - Future update(AvesVideoController controller); + Future update({ + required AvesVideoController controller, + required bool canSkipToNext, + required bool canSkipToPrevious, + }); Future release(); } @@ -38,7 +42,11 @@ class PlatformMediaSessionService implements MediaSessionService, Disposable { Stream get mediaCommands => _streamController.stream.where((event) => event is MediaCommandEvent).cast(); @override - Future update(AvesVideoController controller) async { + Future update({ + required AvesVideoController controller, + required bool canSkipToNext, + required bool canSkipToPrevious, + }) async { final entry = controller.entry; try { await _platformObject.invokeMethod('update', { @@ -48,6 +56,8 @@ class PlatformMediaSessionService implements MediaSessionService, Disposable { 'state': _toPlatformState(controller.status), 'positionMillis': controller.currentPosition, 'playbackSpeed': controller.speed, + 'canSkipToNext': canSkipToNext, + 'canSkipToPrevious': canSkipToPrevious, }); } on PlatformException catch (e, stack) { await reportService.recordError(e, stack); @@ -88,6 +98,12 @@ class PlatformMediaSessionService implements MediaSessionService, Disposable { case 'pause': event = const MediaCommandEvent(MediaCommand.pause); break; + case 'skip_to_next': + event = const MediaCommandEvent(MediaCommand.skipToNext); + break; + case 'skip_to_previous': + event = const MediaCommandEvent(MediaCommand.skipToPrevious); + break; case 'stop': event = const MediaCommandEvent(MediaCommand.stop); break; @@ -104,7 +120,7 @@ class PlatformMediaSessionService implements MediaSessionService, Disposable { } } -enum MediaCommand { play, pause, stop, seek } +enum MediaCommand { play, pause, skipToNext, skipToPrevious, stop, seek } @immutable class MediaCommandEvent extends Equatable { diff --git a/lib/utils/dependencies.dart b/lib/utils/dependencies.dart index 564d43c57..0b33a9f47 100644 --- a/lib/utils/dependencies.dart +++ b/lib/utils/dependencies.dart @@ -75,6 +75,11 @@ class Dependencies { license: mit, sourceUrl: 'https://github.com/deckerst/fijkplayer', ), + Dependency( + name: 'Floating', + license: mit, + sourceUrl: 'https://github.com/wrbl606/floating', + ), Dependency( name: 'Flutter Display Mode', license: mit, diff --git a/lib/widgets/aves_app.dart b/lib/widgets/aves_app.dart index 6e1b3dfdf..a2ad8684a 100644 --- a/lib/widgets/aves_app.dart +++ b/lib/widgets/aves_app.dart @@ -362,7 +362,6 @@ class _AvesAppState extends State with WidgetsBindingObserver { @override void didChangeAppLifecycleState(AppLifecycleState state) { - debugPrint('$runtimeType lifecycle ${state.name}'); reportService.log('Lifecycle ${state.name}'); switch (state) { case AppLifecycleState.inactive: diff --git a/lib/widgets/common/tile_extent_controller.dart b/lib/widgets/common/tile_extent_controller.dart index e32d8662d..924ecbdf3 100644 --- a/lib/widgets/common/tile_extent_controller.dart +++ b/lib/widgets/common/tile_extent_controller.dart @@ -87,14 +87,14 @@ class TileExtentController { int _effectiveColumnCountForExtent(double extent) { if (extent > 0) { final columnCount = _columnCountForExtent(extent); - final countMin = _effectiveColumnCountMin(); final countMax = _effectiveColumnCountMax(); + final countMin = min(_effectiveColumnCountMin(), countMax); return columnCount.round().clamp(countMin, countMax); } return columnCountDefault; } - double get effectiveExtentMin => _extentForColumnCount(_effectiveColumnCountMax()); + double get effectiveExtentMin => min(_extentForColumnCount(_effectiveColumnCountMax()), effectiveExtentMax); double get effectiveExtentMax => _extentForColumnCount(_effectiveColumnCountMin()); diff --git a/lib/widgets/settings/video/video.dart b/lib/widgets/settings/video/video.dart index d7c3b978e..3fa9a5760 100644 --- a/lib/widgets/settings/video/video.dart +++ b/lib/widgets/settings/video/video.dart @@ -1,5 +1,6 @@ import 'dart:async'; +import 'package:aves/model/device.dart'; import 'package:aves/model/filters/mime.dart'; import 'package:aves/model/settings/enums/enums.dart'; import 'package:aves/model/settings/enums/video_auto_play_mode.dart'; @@ -40,6 +41,7 @@ class VideoSection extends SettingsSection { return [ if (!standalonePage) SettingsTileVideoShowVideos(), SettingsTileVideoEnableHardwareAcceleration(), + if (!settings.useTvLayout && device.supportPictureInPicture) SettingsTileVideoEnablePip(), SettingsTileVideoEnableAutoPlay(), SettingsTileVideoLoopMode(), if (!settings.useTvLayout) SettingsTileVideoControls(), @@ -72,6 +74,18 @@ class SettingsTileVideoEnableHardwareAcceleration extends SettingsTile { ); } +class SettingsTileVideoEnablePip extends SettingsTile { + @override + String title(BuildContext context) => context.l10n.settingsVideoEnablePip; + + @override + Widget build(BuildContext context) => SettingsSwitchListTile( + selector: (context, s) => s.enableVideoPip, + onChanged: (v) => settings.enableVideoPip = v, + title: title(context), + ); +} + class SettingsTileVideoEnableAutoPlay extends SettingsTile { @override String title(BuildContext context) => context.l10n.settingsVideoAutoPlay; diff --git a/lib/widgets/viewer/entry_horizontal_pager.dart b/lib/widgets/viewer/entry_horizontal_pager.dart index fcf6e6017..099ec2f92 100644 --- a/lib/widgets/viewer/entry_horizontal_pager.dart +++ b/lib/widgets/viewer/entry_horizontal_pager.dart @@ -3,11 +3,13 @@ import 'package:aves/model/settings/enums/accessibility_animations.dart'; import 'package:aves/model/settings/enums/viewer_transition.dart'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/model/source/collection_lens.dart'; -import 'package:aves_magnifier/aves_magnifier.dart'; import 'package:aves/widgets/viewer/controller.dart'; import 'package:aves/widgets/viewer/multipage/conductor.dart'; +import 'package:aves/widgets/viewer/notifications.dart'; import 'package:aves/widgets/viewer/page_entry_builder.dart'; import 'package:aves/widgets/viewer/visual/entry_page_view.dart'; +import 'package:aves_magnifier/aves_magnifier.dart'; +import 'package:collection/collection.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; @@ -45,40 +47,43 @@ class _MultiEntryScrollerState extends State with AutomaticK return MagnifierGestureDetectorScope( axis: const [Axis.horizontal, Axis.vertical], - child: PageView.builder( - // key is expected by test driver - key: const Key('horizontal-pageview'), - scrollDirection: Axis.horizontal, - controller: pageController, - physics: MagnifierScrollerPhysics( - gestureSettings: context.select((mq) => mq.gestureSettings), - parent: const BouncingScrollPhysics(), + child: NotificationListener( + onNotification: _handleNotification, + child: PageView.builder( + // key is expected by test driver + key: const Key('horizontal-pageview'), + scrollDirection: Axis.horizontal, + controller: pageController, + physics: MagnifierScrollerPhysics( + gestureSettings: context.select((mq) => mq.gestureSettings), + parent: const BouncingScrollPhysics(), + ), + onPageChanged: widget.onPageChanged, + itemBuilder: (context, index) { + final mainEntry = entries[index % entries.length]; + + final child = mainEntry.isMultiPage + ? PageEntryBuilder( + multiPageController: context.read().getController(mainEntry), + builder: (pageEntry) => _buildViewer(mainEntry, pageEntry: pageEntry), + ) + : _buildViewer(mainEntry); + + return Selector( + selector: (context, s) => s.accessibilityAnimations.animate, + builder: (context, animate, child) { + if (!animate) return child!; + return AnimatedBuilder( + animation: pageController, + builder: viewerController.transition.builder(pageController, index), + child: child, + ); + }, + child: child, + ); + }, + itemCount: viewerController.repeat ? null : entries.length, ), - onPageChanged: widget.onPageChanged, - itemBuilder: (context, index) { - final mainEntry = entries[index % entries.length]; - - final child = mainEntry.isMultiPage - ? PageEntryBuilder( - multiPageController: context.read().getController(mainEntry), - builder: (pageEntry) => _buildViewer(mainEntry, pageEntry: pageEntry), - ) - : _buildViewer(mainEntry); - - return Selector( - selector: (context, s) => s.accessibilityAnimations.animate, - builder: (context, animate, child) { - if (!animate) return child!; - return AnimatedBuilder( - animation: pageController, - builder: viewerController.transition.builder(pageController, index), - child: child, - ); - }, - child: child, - ); - }, - itemCount: viewerController.repeat ? null : entries.length, ), ); } @@ -94,6 +99,43 @@ class _MultiEntryScrollerState extends State with AutomaticK ); } + bool _handleNotification(dynamic notification) { + if (notification is ShowPreviousVideoNotification) { + _showPreviousVideo(); + } else if (notification is ShowNextVideoNotification) { + _showNextVideo(); + } else { + return false; + } + return true; + } + + void _showPreviousVideo() { + final currentIndex = pageController.page?.round(); + if (currentIndex != null) { + final previousVideoEntry = entries.take(currentIndex).lastWhereOrNull((entry) => entry.isVideo); + if (previousVideoEntry != null) { + final previousIndex = entries.indexOf(previousVideoEntry); + if (previousIndex != -1) { + ShowEntryNotification(animate: false, index: previousIndex).dispatch(context); + } + } + } + } + + void _showNextVideo() { + final currentIndex = pageController.page?.round(); + if (currentIndex != null) { + final nextVideoEntry = entries.skip(currentIndex + 1).firstWhereOrNull((entry) => entry.isVideo); + if (nextVideoEntry != null) { + final nextIndex = entries.indexOf(nextVideoEntry); + if (nextIndex != -1) { + ShowEntryNotification(animate: false, index: nextIndex).dispatch(context); + } + } + } + } + @override bool get wantKeepAlive => true; } diff --git a/lib/widgets/viewer/entry_viewer_page.dart b/lib/widgets/viewer/entry_viewer_page.dart index fc860189d..89fc4dc6e 100644 --- a/lib/widgets/viewer/entry_viewer_page.dart +++ b/lib/widgets/viewer/entry_viewer_page.dart @@ -41,12 +41,14 @@ class _EntryViewerPageState extends State { @override Widget build(BuildContext context) { + final collection = widget.collection; return AvesScaffold( body: ViewStateConductorProvider( child: VideoConductorProvider( + collection: collection, child: MultiPageConductorProvider( child: EntryViewerStack( - collection: widget.collection, + collection: collection, initialEntry: widget.initialEntry, viewerController: _viewerController, ), @@ -86,17 +88,19 @@ class ViewStateConductorProvider extends StatelessWidget { } class VideoConductorProvider extends StatelessWidget { + final CollectionLens? collection; final Widget? child; const VideoConductorProvider({ super.key, - this.child, + this.collection, + required this.child, }); @override Widget build(BuildContext context) { return Provider( - create: (context) => VideoConductor(), + create: (context) => VideoConductor(collection: collection), dispose: (context, value) => value.dispose(), child: child, ); @@ -108,7 +112,7 @@ class MultiPageConductorProvider extends StatelessWidget { const MultiPageConductorProvider({ super.key, - this.child, + required this.child, }); @override diff --git a/lib/widgets/viewer/entry_viewer_stack.dart b/lib/widgets/viewer/entry_viewer_stack.dart index b805798fa..b00ef23d8 100644 --- a/lib/widgets/viewer/entry_viewer_stack.dart +++ b/lib/widgets/viewer/entry_viewer_stack.dart @@ -34,6 +34,7 @@ import 'package:aves/widgets/viewer/video_action_delegate.dart'; import 'package:aves/widgets/viewer/visual/conductor.dart'; import 'package:aves/widgets/viewer/visual/controller_mixin.dart'; import 'package:collection/collection.dart'; +import 'package:floating/floating.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; @@ -58,6 +59,7 @@ class EntryViewerStack extends StatefulWidget { } class _EntryViewerStackState extends State with EntryViewControllerMixin, FeedbackMixin, SingleTickerProviderStateMixin, WidgetsBindingObserver { + final Floating _floating = Floating(); late int _currentEntryIndex; late ValueNotifier _currentVerticalPage; late PageController _horizontalPager, _verticalPager; @@ -159,6 +161,7 @@ class _EntryViewerStackState extends State with EntryViewContr @override void dispose() { + _floating.dispose(); cleanEntryControllers(entryNotifier.value); _videoActionDelegate.dispose(); _overlayAnimationController.dispose(); @@ -183,9 +186,10 @@ class _EntryViewerStackState extends State with EntryViewContr void didChangeAppLifecycleState(AppLifecycleState state) { switch (state) { case AppLifecycleState.inactive: + _onAppInactive(); + break; case AppLifecycleState.paused: case AppLifecycleState.detached: - viewerController.autopilot = false; pauseVideoControllers(); break; case AppLifecycleState.resumed: @@ -194,6 +198,17 @@ class _EntryViewerStackState extends State with EntryViewContr } } + Future _onAppInactive() async { + viewerController.autopilot = false; + bool enabledPip = false; + if (settings.enableVideoPip) { + enabledPip |= await _enablePictureInPicture(); + } + if (!enabledPip) { + await pauseVideoControllers(); + } + } + @override Widget build(BuildContext context) { final viewStateConductor = context.read(); @@ -209,29 +224,38 @@ class _EntryViewerStackState extends State with EntryViewContr child: LayoutBuilder( builder: (context, constraints) { final availableSize = Size(constraints.maxWidth, constraints.maxHeight); - return Stack( - children: [ - ViewerVerticalPageView( - collection: collection, - entryNotifier: entryNotifier, - viewerController: viewerController, - overlayOpacity: _overlayInitialized - ? _overlayOpacity - : settings.showOverlayOnOpening - ? kAlwaysCompleteAnimation - : kAlwaysDismissedAnimation, - verticalPager: _verticalPager, - horizontalPager: _horizontalPager, - onVerticalPageChanged: _onVerticalPageChanged, - onHorizontalPageChanged: _onHorizontalPageChanged, - onImagePageRequested: () => _goToVerticalPage(imagePage), - onViewDisposed: (mainEntry, pageEntry) => viewStateConductor.reset(pageEntry ?? mainEntry), - ), - ..._buildOverlays(availableSize).map(_decorateOverlay), - const TopGestureAreaProtector(), - const SideGestureAreaProtector(), - const BottomGestureAreaProtector(), - ], + final viewer = ViewerVerticalPageView( + collection: collection, + entryNotifier: entryNotifier, + viewerController: viewerController, + overlayOpacity: _overlayInitialized + ? _overlayOpacity + : settings.showOverlayOnOpening + ? kAlwaysCompleteAnimation + : kAlwaysDismissedAnimation, + verticalPager: _verticalPager, + horizontalPager: _horizontalPager, + onVerticalPageChanged: _onVerticalPageChanged, + onHorizontalPageChanged: _onHorizontalPageChanged, + onImagePageRequested: () => _goToVerticalPage(imagePage), + onViewDisposed: (mainEntry, pageEntry) => viewStateConductor.reset(pageEntry ?? mainEntry), + ); + return StreamBuilder( + stream: _floating.pipStatus$, + builder: (context, snapshot) { + var pipEnabled = snapshot.data == PiPStatus.enabled; + return Stack( + children: [ + viewer, + if (!pipEnabled) ...[ + ..._buildOverlays(availableSize).map(_decorateOverlay), + const TopGestureAreaProtector(), + const SideGestureAreaProtector(), + const BottomGestureAreaProtector(), + ], + ], + ); + }, ); }, ), @@ -708,6 +732,39 @@ class _EntryViewerStackState extends State with EntryViewContr } } + Future _enablePictureInPicture() async { + final videoController = context.read().getPlayingController(); + if (videoController != null) { + final targetEntry = videoController.entry; + final entrySize = targetEntry.displaySize; + final aspectRatio = Rational(entrySize.width.round(), entrySize.height.round()); + + final mq = context.read(); + final viewSize = mq.size * mq.devicePixelRatio; + final fittedSize = applyBoxFit(BoxFit.contain, entrySize, viewSize).destination; + final sourceRectHint = Rectangle( + ((viewSize.width - fittedSize.width) / 2).round(), + ((viewSize.height - fittedSize.height) / 2).round(), + fittedSize.width.round(), + fittedSize.height.round(), + ); + + try { + final status = await _floating.enable( + aspectRatio: aspectRatio, + sourceRectHint: sourceRectHint, + ); + await reportService.log('Enabled picture-in-picture with status=$status'); + return status == PiPStatus.enabled; + } on PlatformException catch (e, stack) { + if (e.message != 'Activity must be resumed to enter picture-in-picture') { + await reportService.recordError(e, stack); + } + } + } + return false; + } + // overlay Future _initOverlay() async { diff --git a/lib/widgets/viewer/notifications.dart b/lib/widgets/viewer/notifications.dart index a8d0736ed..74850f6dd 100644 --- a/lib/widgets/viewer/notifications.dart +++ b/lib/widgets/viewer/notifications.dart @@ -40,6 +40,12 @@ class ShowEntryNotification extends Notification { }); } +@immutable +class ShowPreviousVideoNotification extends Notification {} + +@immutable +class ShowNextVideoNotification extends Notification {} + @immutable class ToggleOverlayNotification extends Notification { final bool? visible; diff --git a/lib/widgets/viewer/video/conductor.dart b/lib/widgets/viewer/video/conductor.dart index 08389e802..82abe32c3 100644 --- a/lib/widgets/viewer/video/conductor.dart +++ b/lib/widgets/viewer/video/conductor.dart @@ -3,18 +3,20 @@ import 'dart:async'; import 'package:aves/model/entry.dart'; import 'package:aves/model/settings/enums/enums.dart'; import 'package:aves/model/settings/settings.dart'; +import 'package:aves/model/source/collection_lens.dart'; import 'package:aves/services/common/services.dart'; import 'package:aves/widgets/viewer/video/controller.dart'; import 'package:aves/widgets/viewer/video/fijkplayer.dart'; import 'package:collection/collection.dart'; class VideoConductor { + final CollectionLens? _collection; final List _controllers = []; final List _subscriptions = []; static const _defaultMaxControllerCount = 3; - VideoConductor(); + VideoConductor({CollectionLens? collection}) : _collection = collection; Future dispose() async { await disposeAll(); @@ -33,7 +35,7 @@ class VideoConductor { _controllers.remove(controller); } else { controller = IjkPlayerAvesVideoController(entry, persistPlayback: true); - _subscriptions.add(controller.statusStream.listen(_onControllerStatusChanged)); + _subscriptions.add(controller.statusStream.listen((event) => _onControllerStatusChanged(controller!, event))); } _controllers.insert(0, controller); while (_controllers.length > (maxControllerCount ?? _defaultMaxControllerCount)) { @@ -42,11 +44,29 @@ class VideoConductor { return controller; } + AvesVideoController? getPlayingController() => _controllers.firstWhereOrNull((c) => c.isPlaying); + AvesVideoController? getController(AvesEntry entry) { return _controllers.firstWhereOrNull((c) => c.entry.uri == entry.uri && c.entry.pageId == entry.pageId); } - Future _onControllerStatusChanged(VideoStatus status) async { + Future _onControllerStatusChanged(AvesVideoController controller, VideoStatus status) async { + bool canSkipToNext = false, canSkipToPrevious = false; + final entries = _collection?.sortedEntries; + if (entries != null) { + final currentIndex = entries.indexOf(controller.entry); + if (currentIndex != -1) { + bool isVideo(AvesEntry entry) => entry.isVideo; + canSkipToPrevious = entries.take(currentIndex).lastWhereOrNull(isVideo) != null; + canSkipToNext = entries.skip(currentIndex + 1).firstWhereOrNull(isVideo) != null; + } + } + + await mediaSessionService.update( + controller: controller, + canSkipToNext: canSkipToNext, + canSkipToPrevious: canSkipToPrevious, + ); if (settings.keepScreenOn == KeepScreenOn.videoPlayback) { await windowService.keepScreenOn(status == VideoStatus.playing); } diff --git a/lib/widgets/viewer/video/controller.dart b/lib/widgets/viewer/video/controller.dart index f450388e2..a41fb6d01 100644 --- a/lib/widgets/viewer/video/controller.dart +++ b/lib/widgets/viewer/video/controller.dart @@ -10,7 +10,6 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; abstract class AvesVideoController { - final List _subscriptions = []; final AvesEntry _entry; final bool persistPlayback; @@ -22,14 +21,10 @@ abstract class AvesVideoController { AvesVideoController(AvesEntry entry, {required this.persistPlayback}) : _entry = entry { entry.visualChangeNotifier.addListener(onVisualChanged); - _subscriptions.add(statusStream.listen((event) => mediaSessionService.update(this))); } @mustCallSuper Future dispose() async { - _subscriptions - ..forEach((sub) => sub.cancel()) - ..clear(); entry.visualChangeNotifier.removeListener(onVisualChanged); await _savePlaybackState(); } diff --git a/lib/widgets/viewer/visual/entry_page_view.dart b/lib/widgets/viewer/visual/entry_page_view.dart index e5712ed24..2198bce5c 100644 --- a/lib/widgets/viewer/visual/entry_page_view.dart +++ b/lib/widgets/viewer/visual/entry_page_view.dart @@ -450,6 +450,12 @@ class _EntryPageViewState extends State with SingleTickerProvider case MediaCommand.pause: videoController.pause(); break; + case MediaCommand.skipToNext: + ShowNextVideoNotification().dispatch(context); + break; + case MediaCommand.skipToPrevious: + ShowPreviousVideoNotification().dispatch(context); + break; case MediaCommand.stop: videoController.pause(); break; diff --git a/plugins/aves_report_crashlytics/lib/aves_report_platform.dart b/plugins/aves_report_crashlytics/lib/aves_report_platform.dart index 51c739ff0..cc501c381 100644 --- a/plugins/aves_report_crashlytics/lib/aves_report_platform.dart +++ b/plugins/aves_report_crashlytics/lib/aves_report_platform.dart @@ -55,7 +55,10 @@ class PlatformReportService extends ReportService { } @override - Future log(String message) async => _instance?.log(message); + Future log(String message) async { + debugPrint('Report log=$message'); + await _instance?.log(message); + } @override Future setCustomKey(String key, Object value) async => _instance?.setCustomKey(key, value); diff --git a/pubspec.lock b/pubspec.lock index 4583f1972..8b108b7a2 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -373,6 +373,15 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.2" + floating: + dependency: "direct main" + description: + path: "." + ref: source-rect-hint + resolved-ref: "84b2f7997da4393dedf3f2e09dd990e5d5492161" + url: "https://github.com/deckerst/floating.git" + source: git + version: "1.1.3" fluster: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index e4c188594..7b37b2d71 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -60,6 +60,10 @@ dependencies: url: https://github.com/deckerst/fijkplayer.git ref: aves flex_color_picker: + floating: + git: + url: https://github.com/deckerst/floating.git + ref: source-rect-hint fluster: flutter_displaymode: flutter_highlight: diff --git a/untranslated.json b/untranslated.json index ea94407bc..c3206618f 100644 --- a/untranslated.json +++ b/untranslated.json @@ -479,6 +479,7 @@ "settingsVideoSectionTitle", "settingsVideoShowVideos", "settingsVideoEnableHardwareAcceleration", + "settingsVideoEnablePip", "settingsVideoAutoPlay", "settingsVideoLoopModeTile", "settingsVideoLoopModeDialogTitle", @@ -1034,6 +1035,7 @@ "settingsVideoSectionTitle", "settingsVideoShowVideos", "settingsVideoEnableHardwareAcceleration", + "settingsVideoEnablePip", "settingsVideoAutoPlay", "settingsVideoLoopModeTile", "settingsVideoLoopModeDialogTitle", @@ -1198,6 +1200,7 @@ "placePageTitle", "placeEmpty", "settingsConfirmationVaultDataLoss", + "settingsVideoEnablePip", "settingsDisablingBinWarningDialogMessage" ], @@ -1231,6 +1234,7 @@ "placePageTitle", "placeEmpty", "settingsConfirmationVaultDataLoss", + "settingsVideoEnablePip", "settingsDisablingBinWarningDialogMessage" ], @@ -1242,19 +1246,22 @@ "exportEntryDialogWriteMetadata", "drawerPlacePage", "placePageTitle", - "placeEmpty" + "placeEmpty", + "settingsVideoEnablePip" ], "es": [ "vaultLockTypePattern", "patternDialogEnter", - "patternDialogConfirm" + "patternDialogConfirm", + "settingsVideoEnablePip" ], "eu": [ "vaultLockTypePattern", "patternDialogEnter", - "patternDialogConfirm" + "patternDialogConfirm", + "settingsVideoEnablePip" ], "fa": [ @@ -1596,6 +1603,7 @@ "settingsVideoSectionTitle", "settingsVideoShowVideos", "settingsVideoEnableHardwareAcceleration", + "settingsVideoEnablePip", "settingsVideoAutoPlay", "settingsVideoLoopModeTile", "settingsVideoLoopModeDialogTitle", @@ -1731,7 +1739,8 @@ "fr": [ "vaultLockTypePattern", "patternDialogEnter", - "patternDialogConfirm" + "patternDialogConfirm", + "settingsVideoEnablePip" ], "gl": [ @@ -2103,6 +2112,7 @@ "settingsVideoSectionTitle", "settingsVideoShowVideos", "settingsVideoEnableHardwareAcceleration", + "settingsVideoEnablePip", "settingsVideoAutoPlay", "settingsVideoLoopModeTile", "settingsVideoLoopModeDialogTitle", @@ -2735,6 +2745,7 @@ "settingsVideoSectionTitle", "settingsVideoShowVideos", "settingsVideoEnableHardwareAcceleration", + "settingsVideoEnablePip", "settingsVideoAutoPlay", "settingsVideoLoopModeTile", "settingsVideoLoopModeDialogTitle", @@ -2872,7 +2883,8 @@ "id": [ "vaultLockTypePattern", "patternDialogEnter", - "patternDialogConfirm" + "patternDialogConfirm", + "settingsVideoEnablePip" ], "it": [ @@ -2885,7 +2897,8 @@ "exportEntryDialogWriteMetadata", "drawerPlacePage", "placePageTitle", - "placeEmpty" + "placeEmpty", + "settingsVideoEnablePip" ], "ja": [ @@ -2931,6 +2944,7 @@ "settingsModificationWarningDialogMessage", "settingsConfirmationVaultDataLoss", "settingsViewerShowDescription", + "settingsVideoEnablePip", "settingsVideoGestureVerticalDragBrightnessVolume", "settingsDisablingBinWarningDialogMessage", "settingsAccessibilityShowPinchGestureAlternatives", @@ -2941,7 +2955,8 @@ "ko": [ "vaultLockTypePattern", "patternDialogEnter", - "patternDialogConfirm" + "patternDialogConfirm", + "settingsVideoEnablePip" ], "lt": [ @@ -2981,6 +2996,7 @@ "settingsModificationWarningDialogMessage", "settingsConfirmationVaultDataLoss", "settingsViewerShowDescription", + "settingsVideoEnablePip", "settingsVideoGestureVerticalDragBrightnessVolume", "settingsDisablingBinWarningDialogMessage", "settingsAccessibilityShowPinchGestureAlternatives", @@ -3017,6 +3033,7 @@ "placePageTitle", "placeEmpty", "settingsConfirmationVaultDataLoss", + "settingsVideoEnablePip", "settingsDisablingBinWarningDialogMessage" ], @@ -3069,6 +3086,7 @@ "settingsConfirmationVaultDataLoss", "settingsViewerShowRatingTags", "settingsViewerShowDescription", + "settingsVideoEnablePip", "settingsSubtitleThemeTextPositionTile", "settingsSubtitleThemeTextPositionDialogTitle", "settingsVideoGestureVerticalDragBrightnessVolume", @@ -3325,6 +3343,7 @@ "settingsVideoSectionTitle", "settingsVideoShowVideos", "settingsVideoEnableHardwareAcceleration", + "settingsVideoEnablePip", "settingsVideoAutoPlay", "settingsVideoLoopModeTile", "settingsVideoLoopModeDialogTitle", @@ -3398,7 +3417,8 @@ "pl": [ "vaultLockTypePattern", "patternDialogEnter", - "patternDialogConfirm" + "patternDialogConfirm", + "settingsVideoEnablePip" ], "pt": [ @@ -3424,6 +3444,7 @@ "placePageTitle", "placeEmpty", "settingsConfirmationVaultDataLoss", + "settingsVideoEnablePip", "settingsVideoGestureVerticalDragBrightnessVolume", "settingsDisablingBinWarningDialogMessage" ], @@ -3438,7 +3459,8 @@ "exportEntryDialogWriteMetadata", "drawerPlacePage", "placePageTitle", - "placeEmpty" + "placeEmpty", + "settingsVideoEnablePip" ], "ru": [ @@ -3459,6 +3481,7 @@ "placeEmpty", "settingsModificationWarningDialogMessage", "settingsConfirmationVaultDataLoss", + "settingsVideoEnablePip", "settingsVideoGestureVerticalDragBrightnessVolume", "settingsDisablingBinWarningDialogMessage" ], @@ -3749,6 +3772,7 @@ "settingsVideoSectionTitle", "settingsVideoShowVideos", "settingsVideoEnableHardwareAcceleration", + "settingsVideoEnablePip", "settingsVideoAutoPlay", "settingsVideoLoopModeTile", "settingsVideoLoopModeDialogTitle", @@ -4104,6 +4128,7 @@ "settingsVideoSectionTitle", "settingsVideoShowVideos", "settingsVideoEnableHardwareAcceleration", + "settingsVideoEnablePip", "settingsVideoAutoPlay", "settingsVideoLoopModeTile", "settingsVideoLoopModeDialogTitle", @@ -4268,13 +4293,15 @@ "placePageTitle", "placeEmpty", "settingsConfirmationVaultDataLoss", + "settingsVideoEnablePip", "settingsDisablingBinWarningDialogMessage" ], "uk": [ "vaultLockTypePattern", "patternDialogEnter", - "patternDialogConfirm" + "patternDialogConfirm", + "settingsVideoEnablePip" ], "zh": [ @@ -4312,6 +4339,7 @@ "settingsModificationWarningDialogMessage", "settingsConfirmationVaultDataLoss", "settingsViewerShowDescription", + "settingsVideoEnablePip", "settingsVideoGestureVerticalDragBrightnessVolume", "settingsDisablingBinWarningDialogMessage", "settingsAccessibilityShowPinchGestureAlternatives", @@ -4354,6 +4382,7 @@ "settingsModificationWarningDialogMessage", "settingsConfirmationVaultDataLoss", "settingsViewerShowDescription", + "settingsVideoEnablePip", "settingsVideoGestureVerticalDragBrightnessVolume", "settingsDisablingBinWarningDialogMessage", "settingsAccessibilityShowPinchGestureAlternatives", From 09cf4fef3e3d08841458ff0eab9148a8f72447c6 Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Wed, 8 Mar 2023 14:24:56 +0100 Subject: [PATCH 08/31] thumb zoom prep --- lib/theme/icons.dart | 1 + lib/widgets/collection/collection_grid.dart | 138 +++++++++++------- lib/widgets/collection/grid/tile.dart | 23 +-- .../color.dart} | 0 .../reselectable_radio.dart} | 0 .../slider.dart} | 0 lib/widgets/common/grid/overlay.dart | 64 ++++---- lib/widgets/common/grid/theme.dart | 5 +- .../common/thumbnail/notifications.dart | 9 ++ lib/widgets/common/thumbnail/overlay.dart | 43 ++++++ .../dialogs/aves_selection_dialog.dart | 2 +- .../cover_selection_dialog.dart | 2 +- .../dialogs/pick_dialogs/app_pick_page.dart | 2 +- .../language/locale_selection_page.dart | 2 +- .../settings/video/subtitle_theme.dart | 4 +- lib/widgets/viewer/entry_viewer_page.dart | 82 ++--------- lib/widgets/viewer/providers.dart | 41 ++++++ lib/widgets/viewer/screen_saver_page.dart | 22 +-- lib/widgets/viewer/slideshow_page.dart | 33 +++-- lib/widgets/wallpaper_page.dart | 17 ++- 20 files changed, 271 insertions(+), 219 deletions(-) rename lib/widgets/common/basic/{color_list_tile.dart => list_tiles/color.dart} (100%) rename lib/widgets/common/basic/{reselectable_radio_list_tile.dart => list_tiles/reselectable_radio.dart} (100%) rename lib/widgets/common/basic/{slider_list_tile.dart => list_tiles/slider.dart} (100%) create mode 100644 lib/widgets/common/thumbnail/notifications.dart create mode 100644 lib/widgets/viewer/providers.dart diff --git a/lib/theme/icons.dart b/lib/theme/icons.dart index 4a5504249..35a2d3fe9 100644 --- a/lib/theme/icons.dart +++ b/lib/theme/icons.dart @@ -125,6 +125,7 @@ class AIcons { static const IconData setCover = MdiIcons.imageEditOutline; static const IconData share = Icons.share_outlined; static const IconData show = Icons.visibility_outlined; + static const IconData showFullscreen = MdiIcons.arrowExpand; static const IconData slideshow = Icons.slideshow_outlined; static const IconData speed = Icons.speed_outlined; static const IconData stats = Icons.donut_small_outlined; diff --git a/lib/widgets/collection/collection_grid.dart b/lib/widgets/collection/collection_grid.dart index 85435a667..ab7d37a03 100644 --- a/lib/widgets/collection/collection_grid.dart +++ b/lib/widgets/collection/collection_grid.dart @@ -5,6 +5,7 @@ import 'package:aves/model/entry.dart'; import 'package:aves/model/favourites.dart'; import 'package:aves/model/filters/favourite.dart'; import 'package:aves/model/filters/mime.dart'; +import 'package:aves/model/selection.dart'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/model/source/collection_lens.dart'; import 'package:aves/model/source/collection_source.dart'; @@ -21,6 +22,7 @@ import 'package:aves/widgets/collection/grid/section_layout.dart'; import 'package:aves/widgets/collection/grid/tile.dart'; import 'package:aves/widgets/common/basic/draggable_scrollbar/scrollbar.dart'; import 'package:aves/widgets/common/basic/insets.dart'; +import 'package:aves/widgets/common/behaviour/routes.dart'; import 'package:aves/widgets/common/behaviour/sloppy_scroll_physics.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/common/extensions/media_query.dart'; @@ -39,8 +41,10 @@ import 'package:aves/widgets/common/identity/scroll_thumb.dart'; import 'package:aves/widgets/common/providers/tile_extent_controller_provider.dart'; import 'package:aves/widgets/common/thumbnail/decorated.dart'; import 'package:aves/widgets/common/thumbnail/image.dart'; +import 'package:aves/widgets/common/thumbnail/notifications.dart'; import 'package:aves/widgets/common/tile_extent_controller.dart'; import 'package:aves/widgets/navigation/nav_bar/nav_bar.dart'; +import 'package:aves/widgets/viewer/entry_viewer_page.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; @@ -152,58 +156,64 @@ class _CollectionGridContentState extends State<_CollectionGridContent> { tileAnimationDelay = Duration.zero; } - return StreamBuilder( - stream: source.eventBus.on(), - builder: (context, snapshot) => SectionedEntryListLayoutProvider( - collection: collection, - selectable: selectable, - scrollableWidth: scrollableWidth, - tileLayout: tileLayout, - columnCount: columnCount, - spacing: tileSpacing, - horizontalPadding: horizontalPadding, - tileExtent: thumbnailExtent, - tileBuilder: (entry, tileSize) { - final extent = tileSize.shortestSide; - return AnimatedBuilder( - animation: favourites, - builder: (context, child) { - Widget tile = InteractiveTile( - key: ValueKey(entry.id), - collection: collection, - entry: entry, - thumbnailExtent: extent, - tileLayout: tileLayout, - isScrollingNotifier: _isScrollingNotifier, - ); - if (!settings.useTvLayout) return tile; + return NotificationListener( + onNotification: (notification) { + _goToViewer(collection, notification.entry); + return true; + }, + child: StreamBuilder( + stream: source.eventBus.on(), + builder: (context, snapshot) => SectionedEntryListLayoutProvider( + collection: collection, + selectable: selectable, + scrollableWidth: scrollableWidth, + tileLayout: tileLayout, + columnCount: columnCount, + spacing: tileSpacing, + horizontalPadding: horizontalPadding, + tileExtent: thumbnailExtent, + tileBuilder: (entry, tileSize) { + final extent = tileSize.shortestSide; + return AnimatedBuilder( + animation: favourites, + builder: (context, child) { + Widget tile = InteractiveTile( + key: ValueKey(entry.id), + collection: collection, + entry: entry, + thumbnailExtent: extent, + tileLayout: tileLayout, + isScrollingNotifier: _isScrollingNotifier, + ); + if (!settings.useTvLayout) return tile; - return Focus( - onFocusChange: (focused) { - if (focused) { - _focusedItemNotifier.value = entry; - } else if (_focusedItemNotifier.value == entry) { - _focusedItemNotifier.value = null; - } - }, - child: ValueListenableBuilder( - valueListenable: _focusedItemNotifier, - builder: (context, focusedItem, child) { - return AnimatedScale( - scale: focusedItem == entry ? 1 : .9, - curve: Curves.fastOutSlowIn, - duration: context.select((v) => v.tvImageFocusAnimation), - child: child!, - ); + return Focus( + onFocusChange: (focused) { + if (focused) { + _focusedItemNotifier.value = entry; + } else if (_focusedItemNotifier.value == entry) { + _focusedItemNotifier.value = null; + } }, - child: tile, - ), - ); - }, - ); - }, - tileAnimationDelay: tileAnimationDelay, - child: child!, + child: ValueListenableBuilder( + valueListenable: _focusedItemNotifier, + builder: (context, focusedItem, child) { + return AnimatedScale( + scale: focusedItem == entry ? 1 : .9, + curve: Curves.fastOutSlowIn, + duration: context.select((v) => v.tvImageFocusAnimation), + child: child!, + ); + }, + child: tile, + ), + ); + }, + ); + }, + tileAnimationDelay: tileAnimationDelay, + child: child!, + ), ), ); }, @@ -227,6 +237,34 @@ class _CollectionGridContentState extends State<_CollectionGridContent> { }, ); } + + void _goToViewer(CollectionLens collection, AvesEntry entry) { + final selection = context.read>(); + Navigator.maybeOf(context)?.push( + TransparentMaterialPageRoute( + settings: const RouteSettings(name: EntryViewerPage.routeName), + pageBuilder: (context, a, sa) { + final viewerCollection = collection.copyWith( + listenToSource: false, + ); + assert(viewerCollection.sortedEntries.map((entry) => entry.id).contains(entry.id)); + Widget child = EntryViewerPage( + collection: viewerCollection, + initialEntry: entry, + ); + + if (selection.isSelecting) { + child = ChangeNotifierProvider>.value( + value: selection, + child: child, + ); + } + + return child; + }, + ), + ); + } } class _CollectionSectionedContent extends StatefulWidget { diff --git a/lib/widgets/collection/grid/tile.dart b/lib/widgets/collection/grid/tile.dart index 9f18792cb..64eddc2c0 100644 --- a/lib/widgets/collection/grid/tile.dart +++ b/lib/widgets/collection/grid/tile.dart @@ -6,10 +6,9 @@ import 'package:aves/model/source/enums/enums.dart'; import 'package:aves/services/intent_service.dart'; import 'package:aves/widgets/collection/grid/list_details.dart'; import 'package:aves/widgets/collection/grid/list_details_theme.dart'; -import 'package:aves/widgets/common/behaviour/routes.dart'; import 'package:aves/widgets/common/grid/scaling.dart'; import 'package:aves/widgets/common/thumbnail/decorated.dart'; -import 'package:aves/widgets/viewer/entry_viewer_page.dart'; +import 'package:aves/widgets/common/thumbnail/notifications.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; @@ -40,7 +39,7 @@ class InteractiveTile extends StatelessWidget { if (selection.isSelecting) { selection.toggleSelection(entry); } else { - _goToViewer(context); + OpenViewerNotification(entry).dispatch(context); } break; case AppMode.pickSingleMediaExternal: @@ -79,24 +78,6 @@ class InteractiveTile extends StatelessWidget { ), ); } - - void _goToViewer(BuildContext context) { - Navigator.maybeOf(context)?.push( - TransparentMaterialPageRoute( - settings: const RouteSettings(name: EntryViewerPage.routeName), - pageBuilder: (context, a, sa) { - final viewerCollection = collection.copyWith( - listenToSource: false, - ); - assert(viewerCollection.sortedEntries.map((entry) => entry.id).contains(entry.id)); - return EntryViewerPage( - collection: viewerCollection, - initialEntry: entry, - ); - }, - ), - ); - } } class Tile extends StatelessWidget { diff --git a/lib/widgets/common/basic/color_list_tile.dart b/lib/widgets/common/basic/list_tiles/color.dart similarity index 100% rename from lib/widgets/common/basic/color_list_tile.dart rename to lib/widgets/common/basic/list_tiles/color.dart diff --git a/lib/widgets/common/basic/reselectable_radio_list_tile.dart b/lib/widgets/common/basic/list_tiles/reselectable_radio.dart similarity index 100% rename from lib/widgets/common/basic/reselectable_radio_list_tile.dart rename to lib/widgets/common/basic/list_tiles/reselectable_radio.dart diff --git a/lib/widgets/common/basic/slider_list_tile.dart b/lib/widgets/common/basic/list_tiles/slider.dart similarity index 100% rename from lib/widgets/common/basic/slider_list_tile.dart rename to lib/widgets/common/basic/list_tiles/slider.dart diff --git a/lib/widgets/common/grid/overlay.dart b/lib/widgets/common/grid/overlay.dart index a1ba82ad8..28501f925 100644 --- a/lib/widgets/common/grid/overlay.dart +++ b/lib/widgets/common/grid/overlay.dart @@ -22,44 +22,38 @@ class GridItemSelectionOverlay extends StatelessWidget { @override Widget build(BuildContext context) { final isSelecting = context.select, bool>((selection) => selection.isSelecting); - final child = isSelecting - ? Selector, bool>( - selector: (context, selection) => selection.isSelected([item]), - builder: (context, isSelected, child) { - var child = isSelecting - ? OverlayIcon( + return AnimatedSwitcher( + duration: duration, + child: isSelecting + ? Selector, bool>( + selector: (context, selection) => selection.isSelected([item]), + builder: (context, isSelected, child) { + return AnimatedContainer( + alignment: AlignmentDirectional.topEnd, + padding: padding, + decoration: BoxDecoration( + color: isSelected ? Theme.of(context).colorScheme.secondary.withOpacity(.6) : Colors.transparent, + borderRadius: borderRadius, + ), + duration: duration, + child: AnimatedSwitcher( + duration: duration, + switchInCurve: Curves.easeOutBack, + switchOutCurve: Curves.easeOutBack, + transitionBuilder: (child, animation) => ScaleTransition( + scale: animation, + child: child, + ), + child: OverlayIcon( key: ValueKey(isSelected), icon: isSelected ? AIcons.selected : AIcons.unselected, margin: EdgeInsets.zero, - ) - : const SizedBox(); - child = AnimatedSwitcher( - duration: duration, - switchInCurve: Curves.easeOutBack, - switchOutCurve: Curves.easeOutBack, - transitionBuilder: (child, animation) => ScaleTransition( - scale: animation, - child: child, - ), - child: child, - ); - child = AnimatedContainer( - alignment: AlignmentDirectional.topEnd, - padding: padding, - decoration: BoxDecoration( - color: isSelected ? Theme.of(context).colorScheme.secondary.withOpacity(.6) : Colors.transparent, - borderRadius: borderRadius, - ), - duration: duration, - child: child, - ); - return child; - }, - ) - : const SizedBox(); - return AnimatedSwitcher( - duration: duration, - child: child, + ), + ), + ); + }, + ) + : const SizedBox(), ); } } diff --git a/lib/widgets/common/grid/theme.dart b/lib/widgets/common/grid/theme.dart index 4076bd32e..2e7bdd1ef 100644 --- a/lib/widgets/common/grid/theme.dart +++ b/lib/widgets/common/grid/theme.dart @@ -30,10 +30,12 @@ class GridTheme extends StatelessWidget { final fontSize = (iconSize * .7).floorToDouble(); iconSize *= mq.textScaleFactor; final highlightBorderWidth = extent * .1; + final interactiveDimension = min(iconSize * 2, kMinInteractiveDimension); return GridThemeData( iconSize: iconSize, fontSize: fontSize, highlightBorderWidth: highlightBorderWidth, + interactiveDimension: interactiveDimension, showFavourite: settings.showThumbnailFavourite, locationIcon: showLocation ? settings.thumbnailLocationIcon : ThumbnailOverlayLocationIcon.none, tagIcon: settings.thumbnailTagIcon, @@ -52,7 +54,7 @@ class GridTheme extends StatelessWidget { typedef GridThemeIconBuilder = List Function(BuildContext context, AvesEntry entry); class GridThemeData { - final double iconSize, fontSize, highlightBorderWidth; + final double iconSize, fontSize, highlightBorderWidth, interactiveDimension; final bool showFavourite, showMotionPhoto, showRating, showRaw, showTrash, showVideoDuration; final bool showLocated, showUnlocated, showTagged, showUntagged; late final GridThemeIconBuilder iconBuilder; @@ -61,6 +63,7 @@ class GridThemeData { required this.iconSize, required this.fontSize, required this.highlightBorderWidth, + required this.interactiveDimension, required this.showFavourite, required ThumbnailOverlayLocationIcon locationIcon, required ThumbnailOverlayTagIcon tagIcon, diff --git a/lib/widgets/common/thumbnail/notifications.dart b/lib/widgets/common/thumbnail/notifications.dart new file mode 100644 index 000000000..b52226070 --- /dev/null +++ b/lib/widgets/common/thumbnail/notifications.dart @@ -0,0 +1,9 @@ +import 'package:aves/model/entry.dart'; +import 'package:flutter/widgets.dart'; + +@immutable +class OpenViewerNotification extends Notification { + final AvesEntry entry; + + const OpenViewerNotification(this.entry); +} diff --git a/lib/widgets/common/thumbnail/overlay.dart b/lib/widgets/common/thumbnail/overlay.dart index aa3b639d6..ed64484d5 100644 --- a/lib/widgets/common/thumbnail/overlay.dart +++ b/lib/widgets/common/thumbnail/overlay.dart @@ -2,6 +2,9 @@ import 'dart:math'; import 'package:aves/model/entry.dart'; import 'package:aves/model/highlight.dart'; +import 'package:aves/model/selection.dart'; +import 'package:aves/theme/durations.dart'; +import 'package:aves/theme/icons.dart'; import 'package:aves/widgets/common/fx/sweeper.dart'; import 'package:aves/widgets/common/grid/theme.dart'; import 'package:flutter/material.dart'; @@ -70,3 +73,43 @@ class _ThumbnailHighlightOverlayState extends State { ); } } + +class ThumbnailZoomOverlay extends StatelessWidget { + final VoidCallback? onZoom; + + const ThumbnailZoomOverlay({ + super.key, + this.onZoom, + }); + + static const alignment = AlignmentDirectional.bottomEnd; + static const duration = Durations.thumbnailOverlayAnimation; + + @override + Widget build(BuildContext context) { + final isSelecting = context.select, bool>((selection) => selection.isSelecting); + final interactiveDimension = context.select((t) => t.interactiveDimension); + return AnimatedSwitcher( + duration: duration, + child: isSelecting + ? Align( + alignment: alignment, + child: GestureDetector( + onTap: onZoom, + child: Container( + alignment: alignment, + padding: const EdgeInsets.symmetric(vertical: 1, horizontal: 2), + width: interactiveDimension, + height: interactiveDimension, + child: Icon( + AIcons.showFullscreen, + size: context.select((t) => t.iconSize), + color: Colors.white70, + ), + ), + ), + ) + : const SizedBox(), + ); + } +} diff --git a/lib/widgets/dialogs/aves_selection_dialog.dart b/lib/widgets/dialogs/aves_selection_dialog.dart index bede0ca1c..068ef5dd6 100644 --- a/lib/widgets/dialogs/aves_selection_dialog.dart +++ b/lib/widgets/dialogs/aves_selection_dialog.dart @@ -1,5 +1,5 @@ import 'package:aves/theme/durations.dart'; -import 'package:aves/widgets/common/basic/reselectable_radio_list_tile.dart'; +import 'package:aves/widgets/common/basic/list_tiles/reselectable_radio.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; diff --git a/lib/widgets/dialogs/filter_editors/cover_selection_dialog.dart b/lib/widgets/dialogs/filter_editors/cover_selection_dialog.dart index 3dde93755..afbeb28f2 100644 --- a/lib/widgets/dialogs/filter_editors/cover_selection_dialog.dart +++ b/lib/widgets/dialogs/filter_editors/cover_selection_dialog.dart @@ -10,7 +10,7 @@ import 'package:aves/model/source/collection_lens.dart'; import 'package:aves/model/source/collection_source.dart'; import 'package:aves/theme/icons.dart'; import 'package:aves/utils/constants.dart'; -import 'package:aves/widgets/common/basic/color_list_tile.dart'; +import 'package:aves/widgets/common/basic/list_tiles/color.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/common/fx/borders.dart'; import 'package:aves/widgets/dialogs/aves_dialog.dart'; diff --git a/lib/widgets/dialogs/pick_dialogs/app_pick_page.dart b/lib/widgets/dialogs/pick_dialogs/app_pick_page.dart index e49e7334b..2b9799064 100644 --- a/lib/widgets/dialogs/pick_dialogs/app_pick_page.dart +++ b/lib/widgets/dialogs/pick_dialogs/app_pick_page.dart @@ -2,8 +2,8 @@ import 'package:aves/image_providers/app_icon_image_provider.dart'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/services/common/services.dart'; import 'package:aves/utils/android_file_utils.dart'; +import 'package:aves/widgets/common/basic/list_tiles/reselectable_radio.dart'; import 'package:aves/widgets/common/basic/query_bar.dart'; -import 'package:aves/widgets/common/basic/reselectable_radio_list_tile.dart'; import 'package:aves/widgets/common/basic/scaffold.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:collection/collection.dart'; diff --git a/lib/widgets/settings/language/locale_selection_page.dart b/lib/widgets/settings/language/locale_selection_page.dart index 8c95015f5..b1d02fe13 100644 --- a/lib/widgets/settings/language/locale_selection_page.dart +++ b/lib/widgets/settings/language/locale_selection_page.dart @@ -2,8 +2,8 @@ import 'dart:collection'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/widgets/aves_app.dart'; +import 'package:aves/widgets/common/basic/list_tiles/reselectable_radio.dart'; import 'package:aves/widgets/common/basic/query_bar.dart'; -import 'package:aves/widgets/common/basic/reselectable_radio_list_tile.dart'; import 'package:aves/widgets/common/basic/scaffold.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/settings/language/locale_tile.dart'; diff --git a/lib/widgets/settings/video/subtitle_theme.dart b/lib/widgets/settings/video/subtitle_theme.dart index 220edce07..5121d0377 100644 --- a/lib/widgets/settings/video/subtitle_theme.dart +++ b/lib/widgets/settings/video/subtitle_theme.dart @@ -1,9 +1,9 @@ import 'package:aves/model/settings/enums/enums.dart'; import 'package:aves/model/settings/enums/subtitle_position.dart'; import 'package:aves/model/settings/settings.dart'; -import 'package:aves/widgets/common/basic/color_list_tile.dart'; +import 'package:aves/widgets/common/basic/list_tiles/color.dart'; +import 'package:aves/widgets/common/basic/list_tiles/slider.dart'; import 'package:aves/widgets/common/basic/scaffold.dart'; -import 'package:aves/widgets/common/basic/slider_list_tile.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/settings/common/tiles.dart'; import 'package:aves/widgets/settings/video/subtitle_sample.dart'; diff --git a/lib/widgets/viewer/entry_viewer_page.dart b/lib/widgets/viewer/entry_viewer_page.dart index 89fc4dc6e..1efca6ae1 100644 --- a/lib/widgets/viewer/entry_viewer_page.dart +++ b/lib/widgets/viewer/entry_viewer_page.dart @@ -3,10 +3,8 @@ import 'package:aves/model/source/collection_lens.dart'; import 'package:aves/widgets/common/basic/scaffold.dart'; import 'package:aves/widgets/viewer/controller.dart'; import 'package:aves/widgets/viewer/entry_viewer_stack.dart'; -import 'package:aves/widgets/viewer/multipage/conductor.dart'; import 'package:aves/widgets/viewer/overlay/bottom.dart'; -import 'package:aves/widgets/viewer/video/conductor.dart'; -import 'package:aves/widgets/viewer/visual/conductor.dart'; +import 'package:aves/widgets/viewer/providers.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; @@ -43,16 +41,16 @@ class _EntryViewerPageState extends State { Widget build(BuildContext context) { final collection = widget.collection; return AvesScaffold( - body: ViewStateConductorProvider( - child: VideoConductorProvider( + body: MultiProvider( + providers: [ + ViewStateConductorProvider(), + VideoConductorProvider(collection: collection), + MultiPageConductorProvider(), + ], + child: EntryViewerStack( collection: collection, - child: MultiPageConductorProvider( - child: EntryViewerStack( - collection: collection, - initialEntry: widget.initialEntry, - viewerController: _viewerController, - ), - ), + initialEntry: widget.initialEntry, + viewerController: _viewerController, ), ), backgroundColor: Navigator.canPop(context) @@ -64,63 +62,3 @@ class _EntryViewerPageState extends State { ); } } - -class ViewStateConductorProvider extends StatelessWidget { - final Widget? child; - - const ViewStateConductorProvider({ - super.key, - this.child, - }); - - @override - Widget build(BuildContext context) { - return ProxyProvider( - create: (context) => ViewStateConductor(), - update: (context, mq, value) { - value!.viewportSize = mq.size; - return value; - }, - dispose: (context, value) => value.dispose(), - child: child, - ); - } -} - -class VideoConductorProvider extends StatelessWidget { - final CollectionLens? collection; - final Widget? child; - - const VideoConductorProvider({ - super.key, - this.collection, - required this.child, - }); - - @override - Widget build(BuildContext context) { - return Provider( - create: (context) => VideoConductor(collection: collection), - dispose: (context, value) => value.dispose(), - child: child, - ); - } -} - -class MultiPageConductorProvider extends StatelessWidget { - final Widget? child; - - const MultiPageConductorProvider({ - super.key, - required this.child, - }); - - @override - Widget build(BuildContext context) { - return Provider( - create: (context) => MultiPageConductor(), - dispose: (context, value) => value.dispose(), - child: child, - ); - } -} diff --git a/lib/widgets/viewer/providers.dart b/lib/widgets/viewer/providers.dart new file mode 100644 index 000000000..1a76a0a35 --- /dev/null +++ b/lib/widgets/viewer/providers.dart @@ -0,0 +1,41 @@ +import 'package:aves/model/source/collection_lens.dart'; +import 'package:aves/widgets/viewer/multipage/conductor.dart'; +import 'package:aves/widgets/viewer/video/conductor.dart'; +import 'package:aves/widgets/viewer/visual/conductor.dart'; +import 'package:flutter/widgets.dart'; +import 'package:provider/provider.dart'; + +class ViewStateConductorProvider extends ProxyProvider { + ViewStateConductorProvider({ + super.key, + super.child, + }) : super( + create: (context) => ViewStateConductor(), + update: (context, mq, value) { + value!.viewportSize = mq.size; + return value; + }, + dispose: (context, value) => value.dispose(), + ); +} + +class VideoConductorProvider extends Provider { + VideoConductorProvider({ + super.key, + CollectionLens? collection, + super.child, + }) : super( + create: (context) => VideoConductor(collection: collection), + dispose: (context, value) => value.dispose(), + ); +} + +class MultiPageConductorProvider extends Provider { + MultiPageConductorProvider({ + super.key, + super.child, + }) : super( + create: (context) => MultiPageConductor(), + dispose: (context, value) => value.dispose(), + ); +} diff --git a/lib/widgets/viewer/screen_saver_page.dart b/lib/widgets/viewer/screen_saver_page.dart index 61ec663e4..bad726db5 100644 --- a/lib/widgets/viewer/screen_saver_page.dart +++ b/lib/widgets/viewer/screen_saver_page.dart @@ -8,10 +8,11 @@ import 'package:aves/widgets/common/basic/scaffold.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/common/identity/empty.dart'; import 'package:aves/widgets/viewer/controller.dart'; -import 'package:aves/widgets/viewer/entry_viewer_page.dart'; import 'package:aves/widgets/viewer/entry_viewer_stack.dart'; +import 'package:aves/widgets/viewer/providers.dart'; import 'package:aves_magnifier/aves_magnifier.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; class ScreenSaverPage extends StatefulWidget { static const routeName = '/screen_saver'; @@ -80,15 +81,16 @@ class _ScreenSaverPageState extends State with WidgetsBindingOb alignment: Alignment.center, ); } else { - child = ViewStateConductorProvider( - child: VideoConductorProvider( - child: MultiPageConductorProvider( - child: EntryViewerStack( - collection: collection, - initialEntry: entries.first, - viewerController: _viewerController, - ), - ), + child = MultiProvider( + providers: [ + ViewStateConductorProvider(), + VideoConductorProvider(), + MultiPageConductorProvider(), + ], + child: EntryViewerStack( + collection: collection, + initialEntry: entries.first, + viewerController: _viewerController, ), ); } diff --git a/lib/widgets/viewer/slideshow_page.dart b/lib/widgets/viewer/slideshow_page.dart index e070459f5..eccf250bf 100644 --- a/lib/widgets/viewer/slideshow_page.dart +++ b/lib/widgets/viewer/slideshow_page.dart @@ -14,8 +14,8 @@ import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/common/identity/empty.dart'; import 'package:aves/widgets/settings/viewer/slideshow.dart'; import 'package:aves/widgets/viewer/controller.dart'; -import 'package:aves/widgets/viewer/entry_viewer_page.dart'; import 'package:aves/widgets/viewer/entry_viewer_stack.dart'; +import 'package:aves/widgets/viewer/providers.dart'; import 'package:aves_magnifier/aves_magnifier.dart'; import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; @@ -69,21 +69,22 @@ class _SlideshowPageState extends State { text: context.l10n.collectionEmptyImages, alignment: Alignment.center, ) - : ViewStateConductorProvider( - child: VideoConductorProvider( - child: MultiPageConductorProvider( - child: NotificationListener( - onNotification: (notification) { - _onActionSelected(notification.action); - return true; - }, - child: EntryViewerStack( - key: ValueKey(_viewerController), - collection: _slideshowCollection, - initialEntry: initialEntry, - viewerController: _viewerController, - ), - ), + : MultiProvider( + providers: [ + ViewStateConductorProvider(), + VideoConductorProvider(), + MultiPageConductorProvider(), + ], + child: NotificationListener( + onNotification: (notification) { + _onActionSelected(notification.action); + return true; + }, + child: EntryViewerStack( + key: ValueKey(_viewerController), + collection: _slideshowCollection, + initialEntry: initialEntry, + viewerController: _viewerController, ), ), ), diff --git a/lib/widgets/wallpaper_page.dart b/lib/widgets/wallpaper_page.dart index 59371a258..e052b4e8e 100644 --- a/lib/widgets/wallpaper_page.dart +++ b/lib/widgets/wallpaper_page.dart @@ -8,12 +8,12 @@ import 'package:aves/widgets/common/basic/insets.dart'; import 'package:aves/widgets/common/basic/scaffold.dart'; import 'package:aves/widgets/viewer/controller.dart'; import 'package:aves/widgets/viewer/entry_horizontal_pager.dart'; -import 'package:aves/widgets/viewer/entry_viewer_page.dart'; import 'package:aves/widgets/viewer/multipage/conductor.dart'; import 'package:aves/widgets/viewer/notifications.dart'; import 'package:aves/widgets/viewer/overlay/bottom.dart'; import 'package:aves/widgets/viewer/overlay/video/video.dart'; import 'package:aves/widgets/viewer/page_entry_builder.dart'; +import 'package:aves/widgets/viewer/providers.dart'; import 'package:aves/widgets/viewer/video/conductor.dart'; import 'package:aves/widgets/viewer/video/controller.dart'; import 'package:aves/widgets/viewer/video_action_delegate.dart'; @@ -37,13 +37,14 @@ class WallpaperPage extends StatelessWidget { Widget build(BuildContext context) { return AvesScaffold( body: entry != null - ? ViewStateConductorProvider( - child: VideoConductorProvider( - child: MultiPageConductorProvider( - child: EntryEditor( - entry: entry!, - ), - ), + ? MultiProvider( + providers: [ + ViewStateConductorProvider(), + VideoConductorProvider(), + MultiPageConductorProvider(), + ], + child: EntryEditor( + entry: entry!, ), ) : const SizedBox(), From 433ac537dd91ccbabe7132b3669d69bb9e19d3b0 Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Wed, 8 Mar 2023 19:56:56 +0100 Subject: [PATCH 09/31] #197 preview button when selecting items --- CHANGELOG.md | 1 + lib/app_mode.dart | 5 + lib/widgets/collection/collection_grid.dart | 7 +- .../common/basic/text/animated_diff.dart | 130 ++---------------- lib/widgets/common/grid/overlay.dart | 2 +- lib/widgets/common/map/buttons/panel.dart | 2 + lib/widgets/common/thumbnail/decorated.dart | 7 +- .../viewer/action/entry_action_delegate.dart | 13 +- .../action/entry_info_action_delegate.dart | 16 ++- lib/widgets/viewer/entry_viewer_stack.dart | 19 ++- lib/widgets/viewer/info/basic_section.dart | 11 +- lib/widgets/viewer/info/info_app_bar.dart | 12 +- lib/widgets/viewer/info/location_section.dart | 7 +- lib/widgets/viewer/overlay/bottom.dart | 54 ++++---- .../viewer/overlay/selection_button.dart | 83 +++++++++++ .../viewer/overlay/viewer_buttons.dart | 19 ++- plugins/aves_map/lib/src/theme.dart | 2 +- 17 files changed, 225 insertions(+), 165 deletions(-) create mode 100644 lib/widgets/viewer/overlay/selection_button.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index 401ba61df..3ca45d2f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ All notable changes to this project will be documented in this file. ### Added +- Collection: preview button when selecting items - Vaults: custom pattern lock - Video: picture-in-picture - Video: handle skip next/previous media buttons diff --git a/lib/app_mode.dart b/lib/app_mode.dart index 925c3d967..99dd00ef4 100644 --- a/lib/app_mode.dart +++ b/lib/app_mode.dart @@ -19,6 +19,11 @@ extension ExtraAppMode on AppMode { AppMode.pickMultipleMediaExternal, }.contains(this); + bool get canEditEntry => { + AppMode.main, + AppMode.view, + }.contains(this); + bool get canSelectMedia => { AppMode.main, AppMode.pickMultipleMediaExternal, diff --git a/lib/widgets/collection/collection_grid.dart b/lib/widgets/collection/collection_grid.dart index ab7d37a03..5909acd79 100644 --- a/lib/widgets/collection/collection_grid.dart +++ b/lib/widgets/collection/collection_grid.dart @@ -254,8 +254,11 @@ class _CollectionGridContentState extends State<_CollectionGridContent> { ); if (selection.isSelecting) { - child = ChangeNotifierProvider>.value( - value: selection, + child = MultiProvider( + providers: [ + ListenableProvider>.value(value: ValueNotifier(AppMode.pickMediaInternal)), + ChangeNotifierProvider>.value(value: selection), + ], child: child, ); } diff --git a/lib/widgets/common/basic/text/animated_diff.dart b/lib/widgets/common/basic/text/animated_diff.dart index 624ed7d3b..8ac807e14 100644 --- a/lib/widgets/common/basic/text/animated_diff.dart +++ b/lib/widgets/common/basic/text/animated_diff.dart @@ -73,8 +73,8 @@ class _AnimatedDiffTextState extends State with SingleTickerPr children: _diffs.map((diff) { final oldText = diff.item1; final newText = diff.item2; - final oldWidth = diff.item3; - final newWidth = diff.item4; + final oldSize = diff.item3; + final newSize = diff.item4; final text = (_animation.value == 0 ? oldText : newText) ?? ''; return WidgetSpan( child: AnimatedSize( @@ -91,9 +91,10 @@ class _AnimatedDiffTextState extends State with SingleTickerPr children: [ ...previousChildren.map( (child) => ConstrainedBox( - constraints: BoxConstraints( - maxWidth: min(oldWidth, newWidth), - ), + constraints: BoxConstraints.tight(Size( + min(oldSize.width, newSize.width), + min(oldSize.height, newSize.height), + )), child: child, ), ), @@ -116,14 +117,16 @@ class _AnimatedDiffTextState extends State with SingleTickerPr ); } - double textWidth(String text) { + Size textSize(String text) { final para = RenderParagraph( TextSpan(text: text, style: widget.textStyle), textDirection: Directionality.of(context), textScaleFactor: MediaQuery.textScaleFactorOf(context), strutStyle: widget.strutStyle, )..layout(const BoxConstraints(), parentUsesSize: true); - return para.getMaxIntrinsicWidth(double.infinity); + final width = para.getMaxIntrinsicWidth(double.infinity); + final height = para.getMaxIntrinsicHeight(double.infinity); + return Size(width, height); } // use an adaptation of Google's `Diff Match and Patch` @@ -140,15 +143,15 @@ class _AnimatedDiffTextState extends State with SingleTickerPr ..clear() ..addAll(d.map((diff) { final text = diff.text; + final size = textSize(text); switch (diff.operation) { case Operation.delete: - return Tuple4(text, null, textWidth(text), .0); + return Tuple4(text, null, size, Size.zero); case Operation.insert: - return Tuple4(null, text, .0, textWidth(text)); + return Tuple4(null, text, Size.zero, size); case Operation.equal: default: - final width = textWidth(text); - return Tuple4(text, text, width, width); + return Tuple4(text, text, size, size); } }).fold>([], (prev, v) { if (prev.isNotEmpty) { @@ -168,109 +171,6 @@ class _AnimatedDiffTextState extends State with SingleTickerPr return [...prev, v]; })); } - -// void _computeDiff(String oldText, String newText) { -// final oldCharacters = oldText.characters.toList(); -// final newCharacters = newText.characters.toList(); -// final diffResult = calculateListDiff(oldCharacters, newCharacters, detectMoves: false); -// final updates = diffResult.getUpdatesWithData().toList(); -// List diffs = []; -// DataDiffUpdate? pendingUpdate; -// int lastPos = oldCharacters.length; -// void addKeep(int pos) { -// if (pos < lastPos) { -// final text = oldCharacters.sublist(pos, lastPos).join(); -// final width = textWidth(text); -// diffs.insert(0, Tuple4(text, text, width, width)); -// lastPos = pos; -// } -// } -// -// void commit(DataDiffUpdate? update) { -// update?.when( -// insert: (pos, data) { -// addKeep(pos); -// diffs.insert(0, Tuple4(null, data, 0, textWidth(data))); -// lastPos = pos; -// }, -// remove: (pos, data) { -// addKeep(pos + data.length); -// diffs.insert(0, Tuple4(data, null, textWidth(data), 0)); -// lastPos = pos; -// }, -// change: (pos, oldData, newData) { -// addKeep(pos + oldData.length); -// diffs.insert(0, Tuple4(oldData, newData, textWidth(oldData), textWidth(newData))); -// lastPos = pos; -// }, -// move: (from, to, data) { -// assert(false, '`move` update: from=$from, to=$from, data=$data'); -// }, -// ); -// } -// -// for (var update in updates) { -// update.when( -// insert: (pos, data) { -// if (pendingUpdate == null) { -// pendingUpdate = update; -// return; -// } -// if (pendingUpdate is DataInsert) { -// final pendingInsert = pendingUpdate as DataInsert; -// if (pendingInsert.position == pos) { -// // merge insertions -// pendingUpdate = DataInsert(position: pos, data: data + pendingInsert.data); -// return; -// } -// } else if (pendingUpdate is DataRemove) { -// final pendingRemove = pendingUpdate as DataRemove; -// if (pendingRemove.position == pos) { -// // convert to change -// pendingUpdate = DataChange(position: pos, oldData: pendingRemove.data, newData: data); -// return; -// } -// } else if (pendingUpdate is DataChange) { -// final pendingChange = pendingUpdate as DataChange; -// if (pendingChange.position == pos) { -// // merge changes -// pendingUpdate = DataChange(position: pos, oldData: pendingChange.oldData, newData: data + pendingChange.newData); -// return; -// } -// } -// commit(pendingUpdate); -// pendingUpdate = update; -// }, -// remove: (pos, data) { -// if (pendingUpdate == null) { -// pendingUpdate = update; -// return; -// } -// if (pendingUpdate is DataRemove) { -// final pendingRemove = pendingUpdate as DataRemove; -// if (pendingRemove.position == pos + data.length) { -// // merge removals -// pendingUpdate = DataRemove(position: pos, data: data + pendingRemove.data); -// return; -// } -// } -// commit(pendingUpdate); -// pendingUpdate = update; -// }, -// change: (pos, oldData, newData) { -// assert(false, '`change` update: from=$pos, oldData=$oldData, newData=$newData'); -// }, -// move: (from, to, data) { -// assert(false, '`move` update: from=$from, to=$from, data=$data'); -// }, -// ); -// } -// commit(pendingUpdate); -// addKeep(0); -// _diffs -// ..clear() -// ..addAll(diffs); -// } } -typedef _TextDiff = Tuple4; +typedef _TextDiff = Tuple4; diff --git a/lib/widgets/common/grid/overlay.dart b/lib/widgets/common/grid/overlay.dart index 28501f925..2961dff2b 100644 --- a/lib/widgets/common/grid/overlay.dart +++ b/lib/widgets/common/grid/overlay.dart @@ -26,7 +26,7 @@ class GridItemSelectionOverlay extends StatelessWidget { duration: duration, child: isSelecting ? Selector, bool>( - selector: (context, selection) => selection.isSelected([item]), + selector: (context, selection) => selection.isSelected({item}), builder: (context, isSelected, child) { return AnimatedContainer( alignment: AlignmentDirectional.topEnd, diff --git a/lib/widgets/common/map/buttons/panel.dart b/lib/widgets/common/map/buttons/panel.dart index 7e37cb822..9d72ae6e7 100644 --- a/lib/widgets/common/map/buttons/panel.dart +++ b/lib/widgets/common/map/buttons/panel.dart @@ -51,6 +51,8 @@ class MapButtonPanel extends StatelessWidget { ); } break; + case MapNavigationButton.none: + break; } final showCoordinateFilter = context.select((v) => v.showCoordinateFilter); diff --git a/lib/widgets/common/thumbnail/decorated.dart b/lib/widgets/common/thumbnail/decorated.dart index 9871d3502..93ccf66ac 100644 --- a/lib/widgets/common/thumbnail/decorated.dart +++ b/lib/widgets/common/thumbnail/decorated.dart @@ -2,6 +2,7 @@ import 'package:aves/model/entry.dart'; import 'package:aves/widgets/common/fx/borders.dart'; import 'package:aves/widgets/common/grid/overlay.dart'; import 'package:aves/widgets/common/thumbnail/image.dart'; +import 'package:aves/widgets/common/thumbnail/notifications.dart'; import 'package:aves/widgets/common/thumbnail/overlay.dart'; import 'package:flutter/material.dart'; @@ -44,11 +45,15 @@ class DecoratedThumbnail extends StatelessWidget { children: [ child, ThumbnailEntryOverlay(entry: entry), - if (selectable) + if (selectable) ...[ GridItemSelectionOverlay( item: entry, padding: const EdgeInsets.all(2), ), + ThumbnailZoomOverlay( + onZoom: () => OpenViewerNotification(entry).dispatch(context), + ), + ], if (highlightable) ThumbnailHighlightOverlay(entry: entry), ], ); diff --git a/lib/widgets/viewer/action/entry_action_delegate.dart b/lib/widgets/viewer/action/entry_action_delegate.dart index e984f6e32..ca4322671 100644 --- a/lib/widgets/viewer/action/entry_action_delegate.dart +++ b/lib/widgets/viewer/action/entry_action_delegate.dart @@ -47,7 +47,10 @@ class EntryActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMix EntryActionDelegate(this.mainEntry, this.pageEntry, this.collection); - bool isVisible(EntryAction action) { + bool isVisible({ + required AppMode appMode, + required EntryAction action, + }) { if (mainEntry.trashed) { switch (action) { case EntryAction.delete: @@ -60,7 +63,7 @@ class EntryActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMix } } else { final targetEntry = EntryActions.pageActions.contains(action) ? pageEntry : mainEntry; - final canWrite = !settings.isReadOnly; + final canWrite = appMode.canEditEntry && !settings.isReadOnly; switch (action) { case EntryAction.toggleFavourite: return collection != null; @@ -120,7 +123,11 @@ class EntryActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMix case EntryAction.showGeoTiffOnMap: case EntryAction.convertMotionPhotoToStillImage: case EntryAction.viewMotionPhotoVideo: - return _metadataActionDelegate.isVisible(targetEntry, action); + return _metadataActionDelegate.isVisible( + appMode: appMode, + targetEntry: targetEntry, + action: action, + ); case EntryAction.debug: return kDebugMode; } diff --git a/lib/widgets/viewer/action/entry_info_action_delegate.dart b/lib/widgets/viewer/action/entry_info_action_delegate.dart index 59d1cbb74..78dfe9374 100644 --- a/lib/widgets/viewer/action/entry_info_action_delegate.dart +++ b/lib/widgets/viewer/action/entry_info_action_delegate.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'dart:convert'; +import 'package:aves/app_mode.dart'; import 'package:aves/model/actions/entry_actions.dart'; import 'package:aves/model/actions/events.dart'; import 'package:aves/model/entry.dart'; @@ -29,8 +30,12 @@ class EntryInfoActionDelegate with FeedbackMixin, PermissionAwareMixin, EntryEdi Stream> get eventStream => _eventStreamController.stream; - bool isVisible(AvesEntry targetEntry, EntryAction action) { - final canWrite = !settings.isReadOnly; + bool isVisible({ + required AppMode appMode, + required AvesEntry targetEntry, + required EntryAction action, + }) { + final canWrite = appMode.canEditEntry && !settings.isReadOnly; switch (action) { // general case EntryAction.editDate: @@ -39,16 +44,17 @@ class EntryInfoActionDelegate with FeedbackMixin, PermissionAwareMixin, EntryEdi case EntryAction.editRating: case EntryAction.editTags: case EntryAction.removeMetadata: - case EntryAction.exportMetadata: return canWrite; + case EntryAction.exportMetadata: + return true; // GeoTIFF case EntryAction.showGeoTiffOnMap: - return targetEntry.isGeotiff; + return appMode.canNavigate && targetEntry.isGeotiff; // motion photo case EntryAction.convertMotionPhotoToStillImage: return canWrite && targetEntry.isMotionPhoto; case EntryAction.viewMotionPhotoVideo: - return targetEntry.isMotionPhoto; + return appMode.canNavigate && targetEntry.isMotionPhoto; default: return false; } diff --git a/lib/widgets/viewer/entry_viewer_stack.dart b/lib/widgets/viewer/entry_viewer_stack.dart index b00ef23d8..9cf35d55d 100644 --- a/lib/widgets/viewer/entry_viewer_stack.dart +++ b/lib/widgets/viewer/entry_viewer_stack.dart @@ -562,12 +562,19 @@ class _EntryViewerStackState extends State with EntryViewContr void _onVerticalPageChanged(int page) { _currentVerticalPage.value = page; - if (page == transitionPage) { - dismissFeedback(context); - _popVisual(); - } else if (page == infoPage) { - // prevent hero when viewer is offscreen - _heroInfoNotifier.value = null; + switch (page) { + case transitionPage: + dismissFeedback(context); + _popVisual(); + break; + case imagePage: + reportService.log('Nav move to Image page'); + break; + case infoPage: + reportService.log('Nav move to Info page'); + // prevent hero when viewer is offscreen + _heroInfoNotifier.value = null; + break; } } diff --git a/lib/widgets/viewer/info/basic_section.dart b/lib/widgets/viewer/info/basic_section.dart index 1f3d8e7e4..4f081f3d2 100644 --- a/lib/widgets/viewer/info/basic_section.dart +++ b/lib/widgets/viewer/info/basic_section.dart @@ -150,11 +150,20 @@ class _BasicSectionState extends State { } Widget _buildEditButtons(BuildContext context) { + final appMode = context.watch>().value; final entry = widget.entry; final children = [ EntryAction.editRating, EntryAction.editTags, - ].where((v) => actionDelegate.canApply(entry, v)).map((v) => _buildEditMetadataButton(context, v)).toList(); + ] + .where((v) => actionDelegate.isVisible( + appMode: appMode, + targetEntry: entry, + action: v, + )) + .where((v) => actionDelegate.canApply(entry, v)) + .map((v) => _buildEditMetadataButton(context, v)) + .toList(); return children.isEmpty ? const SizedBox() diff --git a/lib/widgets/viewer/info/info_app_bar.dart b/lib/widgets/viewer/info/info_app_bar.dart index 1b2bb745e..c306074ee 100644 --- a/lib/widgets/viewer/info/info_app_bar.dart +++ b/lib/widgets/viewer/info/info_app_bar.dart @@ -1,3 +1,4 @@ +import 'package:aves/app_mode.dart'; import 'package:aves/model/actions/entry_actions.dart'; import 'package:aves/model/entry.dart'; import 'package:aves/model/settings/settings.dart'; @@ -14,6 +15,7 @@ import 'package:aves/widgets/viewer/info/metadata/metadata_dir.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; +import 'package:provider/provider.dart'; class InfoAppBar extends StatelessWidget { final AvesEntry entry; @@ -33,8 +35,14 @@ class InfoAppBar extends StatelessWidget { @override Widget build(BuildContext context) { - final commonActions = EntryActions.commonMetadataActions.where((v) => actionDelegate.isVisible(entry, v)); - final formatSpecificActions = EntryActions.formatSpecificMetadataActions.where((v) => actionDelegate.isVisible(entry, v)); + final appMode = context.watch>().value; + bool isVisible(EntryAction action) => actionDelegate.isVisible( + appMode: appMode, + targetEntry: entry, + action: action, + ); + final commonActions = EntryActions.commonMetadataActions.where(isVisible); + final formatSpecificActions = EntryActions.formatSpecificMetadataActions.where(isVisible); final useTvLayout = settings.useTvLayout; return SliverAppBar( leading: useTvLayout diff --git a/lib/widgets/viewer/info/location_section.dart b/lib/widgets/viewer/info/location_section.dart index 2742cd701..208d270fe 100644 --- a/lib/widgets/viewer/info/location_section.dart +++ b/lib/widgets/viewer/info/location_section.dart @@ -1,3 +1,4 @@ +import 'package:aves/app_mode.dart'; import 'package:aves/model/entry.dart'; import 'package:aves/model/filters/location.dart'; import 'package:aves/model/settings/enums/coordinate_format.dart'; @@ -13,6 +14,7 @@ import 'package:aves/widgets/map/map_page.dart'; import 'package:aves/widgets/viewer/info/common.dart'; import 'package:aves_map/aves_map.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; class LocationSection extends StatefulWidget { final CollectionLens? collection; @@ -72,6 +74,7 @@ class _LocationSectionState extends State { Widget build(BuildContext context) { if (!entry.hasGps) return const SizedBox(); + final canNavigate = context.select, bool>((v) => v.value.canNavigate); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -79,7 +82,7 @@ class _LocationSectionState extends State { MapTheme( interactive: false, showCoordinateFilter: false, - navigationButton: MapNavigationButton.map, + navigationButton: canNavigate ? MapNavigationButton.map : MapNavigationButton.none, visualDensity: VisualDensity.compact, mapHeight: 200, child: GeoMap( @@ -87,7 +90,7 @@ class _LocationSectionState extends State { entries: [entry], isAnimatingNotifier: widget.isScrollingNotifier, onUserZoomChange: (zoom) => settings.infoMapZoom = zoom.roundToDouble(), - onMarkerTap: collection != null ? (location, entry) => _openMapPage(context) : null, + onMarkerTap: collection != null && canNavigate ? (location, entry) => _openMapPage(context) : null, openMapPage: collection != null ? _openMapPage : null, ), ), diff --git a/lib/widgets/viewer/overlay/bottom.dart b/lib/widgets/viewer/overlay/bottom.dart index a48dbb36e..e23aa29a7 100644 --- a/lib/widgets/viewer/overlay/bottom.dart +++ b/lib/widgets/viewer/overlay/bottom.dart @@ -2,6 +2,7 @@ import 'dart:math'; import 'package:aves/app_mode.dart'; import 'package:aves/model/entry.dart'; +import 'package:aves/model/selection.dart'; import 'package:aves/model/settings/settings.dart'; import 'package:aves/model/source/collection_lens.dart'; import 'package:aves/widgets/common/extensions/media_query.dart'; @@ -9,6 +10,7 @@ import 'package:aves/widgets/viewer/entry_vertical_pager.dart'; import 'package:aves/widgets/viewer/multipage/controller.dart'; import 'package:aves/widgets/viewer/notifications.dart'; import 'package:aves/widgets/viewer/overlay/multipage.dart'; +import 'package:aves/widgets/viewer/overlay/selection_button.dart'; import 'package:aves/widgets/viewer/overlay/thumbnail_preview.dart'; import 'package:aves/widgets/viewer/overlay/viewer_buttons.dart'; import 'package:aves/widgets/viewer/overlay/wallpaper_buttons.dart'; @@ -183,30 +185,36 @@ class _BottomOverlayContentState extends State<_BottomOverlayContent> { ]), builder: (context, child) { final viewInsetsPadding = (widget.viewInsets ?? EdgeInsets.zero) + (widget.viewPadding ?? EdgeInsets.zero); - final viewerButtonRow = FocusableActionDetector( - focusNode: _buttonRowFocusScopeNode, - shortcuts: settings.useTvLayout ? const {SingleActivator(LogicalKeyboardKey.arrowUp): TvShowLessInfoIntent()} : null, - actions: {TvShowLessInfoIntent: CallbackAction(onInvoke: (intent) => TvShowLessInfoNotification().dispatch(context))}, - child: SafeArea( - top: false, - bottom: false, - minimum: EdgeInsets.only( - left: viewInsetsPadding.left, - right: viewInsetsPadding.right, - ), - child: isWallpaperMode - ? WallpaperButtons( - entry: pageEntry, - scale: _buttonScale, - ) - : ViewerButtons( - mainEntry: mainEntry, - pageEntry: pageEntry, - collection: widget.collection, - scale: _buttonScale, + final selection = context.read?>(); + final viewerButtonRow = (selection?.isSelecting ?? false) + ? SelectionButton( + mainEntry: mainEntry, + scale: _buttonScale, + ) + : FocusableActionDetector( + focusNode: _buttonRowFocusScopeNode, + shortcuts: settings.useTvLayout ? const {SingleActivator(LogicalKeyboardKey.arrowUp): TvShowLessInfoIntent()} : null, + actions: {TvShowLessInfoIntent: CallbackAction(onInvoke: (intent) => TvShowLessInfoNotification().dispatch(context))}, + child: SafeArea( + top: false, + bottom: false, + minimum: EdgeInsets.only( + left: viewInsetsPadding.left, + right: viewInsetsPadding.right, ), - ), - ); + child: isWallpaperMode + ? WallpaperButtons( + entry: pageEntry, + scale: _buttonScale, + ) + : ViewerButtons( + mainEntry: mainEntry, + pageEntry: pageEntry, + collection: widget.collection, + scale: _buttonScale, + ), + ), + ); final showMultiPageOverlay = mainEntry.isMultiPage && multiPageController != null; final collapsedPageScroller = mainEntry.isMotionPhoto; diff --git a/lib/widgets/viewer/overlay/selection_button.dart b/lib/widgets/viewer/overlay/selection_button.dart new file mode 100644 index 000000000..ad2f1b899 --- /dev/null +++ b/lib/widgets/viewer/overlay/selection_button.dart @@ -0,0 +1,83 @@ +import 'package:aves/model/entry.dart'; +import 'package:aves/model/selection.dart'; +import 'package:aves/theme/durations.dart'; +import 'package:aves/theme/icons.dart'; +import 'package:aves/utils/constants.dart'; +import 'package:aves/widgets/common/basic/text/animated_diff.dart'; +import 'package:aves/widgets/common/extensions/build_context.dart'; +import 'package:aves/widgets/common/identity/buttons/overlay_button.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class SelectionButton extends StatelessWidget { + final AvesEntry mainEntry; + final Animation scale; + + static const double padding = 8; + static const duration = Durations.thumbnailOverlayAnimation; + + const SelectionButton({ + super.key, + required this.mainEntry, + required this.scale, + }); + + @override + Widget build(BuildContext context) { + final l10n = context.l10n; + final selection = context.read>(); + return SafeArea( + top: false, + bottom: false, + child: Padding( + padding: const EdgeInsets.only(left: padding, right: padding, bottom: padding), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + const Spacer(), + ScalingOverlayTextButton( + scale: scale, + onPressed: () => selection.toggleSelection(mainEntry), + child: Selector?, int>( + selector: (context, selection) => selection?.selectedItems.length ?? 0, + builder: (context, count, child) { + return Row( + mainAxisSize: MainAxisSize.min, + children: [ + AnimatedDiffText( + count == 0 ? l10n.collectionSelectPageTitle : l10n.itemCount(count), + duration: duration, + ), + const Padding( + padding: EdgeInsets.symmetric(horizontal: 8), + child: Text(Constants.separator), + ), + Selector, bool>( + selector: (context, selection) => selection.isSelected({mainEntry}), + builder: (context, isSelected, child) { + return AnimatedSwitcher( + duration: duration, + switchInCurve: Curves.easeOutBack, + switchOutCurve: Curves.easeOutBack, + transitionBuilder: (child, animation) => ScaleTransition( + scale: animation, + child: child, + ), + child: Icon( + isSelected ? AIcons.selected : AIcons.unselected, + key: ValueKey(isSelected), + ), + ); + }, + ), + ], + ); + }, + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/widgets/viewer/overlay/viewer_buttons.dart b/lib/widgets/viewer/overlay/viewer_buttons.dart index bd1342a86..41208da65 100644 --- a/lib/widgets/viewer/overlay/viewer_buttons.dart +++ b/lib/widgets/viewer/overlay/viewer_buttons.dart @@ -1,3 +1,4 @@ +import 'package:aves/app_mode.dart'; import 'package:aves/model/actions/entry_actions.dart'; import 'package:aves/model/entry.dart'; import 'package:aves/model/settings/settings.dart'; @@ -61,6 +62,12 @@ class ViewerButtons extends StatelessWidget { ); } + final appMode = context.watch>().value; + bool isVisible(EntryAction action) => actionDelegate.isVisible( + appMode: appMode, + action: action, + ); + final trashed = mainEntry.trashed; return SafeArea( top: false, @@ -72,9 +79,9 @@ class ViewerButtons extends StatelessWidget { return Selector( selector: (context, s) => s.isRotationLocked, builder: (context, s, child) { - final quickActions = (trashed ? EntryActions.trashed : settings.viewerQuickActions).where(actionDelegate.isVisible).where(actionDelegate.canApply).take(availableCount - 1).toList(); + final quickActions = (trashed ? EntryActions.trashed : settings.viewerQuickActions).where(isVisible).where(actionDelegate.canApply).take(availableCount - 1).toList(); List getMenuActions(List categoryActions) { - return categoryActions.where((action) => !quickActions.contains(action)).where(actionDelegate.isVisible).toList(); + return categoryActions.where((action) => !quickActions.contains(action)).where(isVisible).toList(); } return ViewerButtonRowContent( @@ -109,6 +116,7 @@ class _TvButtonRowContent extends StatelessWidget { @override Widget build(BuildContext context) { + final appMode = context.watch>().value; return Selector( selector: (context, vc) => vc.getController(pageEntry), builder: (context, videoController, child) { @@ -120,7 +128,12 @@ class _TvButtonRowContent extends StatelessWidget { ...EntryActions.export, ...EntryActions.videoPlayback, ...EntryActions.video, - ].where(actionDelegate.isVisible).map((action) { + ] + .where((action) => actionDelegate.isVisible( + appMode: appMode, + action: action, + )) + .map((action) { final enabled = actionDelegate.canApply(action); return CaptionedButton( scale: scale, diff --git a/plugins/aves_map/lib/src/theme.dart b/plugins/aves_map/lib/src/theme.dart index e0daabd63..b05e60ad1 100644 --- a/plugins/aves_map/lib/src/theme.dart +++ b/plugins/aves_map/lib/src/theme.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -enum MapNavigationButton { back, map } +enum MapNavigationButton { back, map, none } class MapThemeData { final bool interactive, showCoordinateFilter; From 851bad8517958718adb6b01ec5082df810261ace Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Wed, 8 Mar 2023 22:35:31 +0100 Subject: [PATCH 10/31] package upgrade --- plugins/aves_report_crashlytics/pubspec.lock | 20 +-- plugins/aves_services_google/pubspec.lock | 20 +-- pubspec.lock | 131 +++++++++---------- pubspec.yaml | 3 - 4 files changed, 85 insertions(+), 89 deletions(-) diff --git a/plugins/aves_report_crashlytics/pubspec.lock b/plugins/aves_report_crashlytics/pubspec.lock index 60ad44254..ec6cd74a7 100644 --- a/plugins/aves_report_crashlytics/pubspec.lock +++ b/plugins/aves_report_crashlytics/pubspec.lock @@ -5,10 +5,10 @@ packages: dependency: transitive description: name: _flutterfire_internals - sha256: "64fcb0dbca4386356386c085142fa6e79c00a3326ceaa778a2d25f5d9ba61441" + sha256: cb3a948a1eebbf8efd987c43f95418269930e912a88bc7b6a5a7658423133635 url: "https://pub.dev" source: hosted - version: "1.0.16" + version: "1.0.17" async: dependency: transitive description: @@ -68,10 +68,10 @@ packages: dependency: "direct main" description: name: firebase_core - sha256: fe30ac230f12f8836bb97e6e09197340d3c584526825b1746ea362a82e1e43f7 + sha256: "1c121a478af23755b0b93fd4aa70d3bd32a587dd51ef0a3979091ac0d2317d32" url: "https://pub.dev" source: hosted - version: "2.7.0" + version: "2.7.1" firebase_core_platform_interface: dependency: transitive description: @@ -84,26 +84,26 @@ packages: dependency: transitive description: name: firebase_core_web - sha256: "291fbcace608aca6c860652e1358ef89752be8cc3ef227f8bbcd1e62775b833a" + sha256: "0c1cf1f1022d2245ac117443bb95207952ca770281524d2908e323bc063fb8ff" url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.2.2" firebase_crashlytics: dependency: "direct main" description: name: firebase_crashlytics - sha256: "816bbb920316c8fe257b460b8856b01e274e867a729961bf7a3be6322cdf13e1" + sha256: d4190479611f42a34a04630d9188f30b592b65013d0f19c408d5249998429864 url: "https://pub.dev" source: hosted - version: "3.0.15" + version: "3.0.16" firebase_crashlytics_platform_interface: dependency: transitive description: name: firebase_crashlytics_platform_interface - sha256: "120e47b9bac3654848d1bdc60b8027f3574b53ee0b81b1a2e5e76ddaa58f6645" + sha256: "667955b348b7729ed3d987956021a97fcdd05957df7c27b2d855e6b3f70e9521" url: "https://pub.dev" source: hosted - version: "3.3.15" + version: "3.3.16" flutter: dependency: "direct main" description: flutter diff --git a/plugins/aves_services_google/pubspec.lock b/plugins/aves_services_google/pubspec.lock index f1ecb9e69..4b7953c5b 100644 --- a/plugins/aves_services_google/pubspec.lock +++ b/plugins/aves_services_google/pubspec.lock @@ -135,10 +135,10 @@ packages: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: "4bef634684b2c7f3468c77c766c831229af829a0cd2d4ee6c1b99558bd14e5d2" + sha256: c224ac897bed083dabf11f238dd11a239809b446740be0c2044608c50029ffdf url: "https://pub.dev" source: hosted - version: "2.0.8" + version: "2.0.9" flutter_web_plugins: dependency: transitive description: flutter @@ -148,34 +148,34 @@ packages: dependency: "direct main" description: name: google_api_availability - sha256: a1f58c5213abae549fb1e1451bc68eb499da7033039f77bc289fd6faca384295 + sha256: "1642876fa87515fd5e4074458f22d6ba4518919c5abce16baaa2878c3c555678" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "4.0.0" google_maps_flutter: dependency: "direct main" description: name: google_maps_flutter - sha256: e4f117747e210e68fe34196c93040e0712ba8aa91f8813fe8cb3f52ad667e70b + sha256: "24392ef192f3b00bcd93151375676805a9933574423a5bd5509a0ead2e8a4215" url: "https://pub.dev" source: hosted - version: "2.2.4" + version: "2.2.5" google_maps_flutter_android: dependency: "direct main" description: name: google_maps_flutter_android - sha256: "69bac3fd18db5638763b06e04c2f2ff2e65e0a76fe93e0e211d8a77afaca033f" + sha256: a8ee18649a67750cbd477a6867a1bf9c4154c5e9f69d722c8b53a627a6d58303 url: "https://pub.dev" source: hosted - version: "2.4.6" + version: "2.4.9" google_maps_flutter_ios: dependency: transitive description: name: google_maps_flutter_ios - sha256: "7ed57e6f1351aebf1442dea0028f2c880989ead866eaf25e9121237c622d4af0" + sha256: e9ad74415a222573625a2c1717adc1e375b18e8ce660fc12db734d1bda1132d4 url: "https://pub.dev" source: hosted - version: "2.1.14" + version: "2.2.1" google_maps_flutter_platform_interface: dependency: "direct main" description: diff --git a/pubspec.lock b/pubspec.lock index 8b108b7a2..1c504215b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,26 +5,26 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - sha256: e440ac42679dfc04bbbefb58ed225c994bc7e07fccc8a68ec7d3631a127e5da9 + sha256: "98d1d33ed129b372846e862de23a0fc365745f4d7b5e786ce667fcbbb7ac5c07" url: "https://pub.dev" source: hosted - version: "54.0.0" + version: "55.0.0" _flutterfire_internals: dependency: transitive description: name: _flutterfire_internals - sha256: "64fcb0dbca4386356386c085142fa6e79c00a3326ceaa778a2d25f5d9ba61441" + sha256: cb3a948a1eebbf8efd987c43f95418269930e912a88bc7b6a5a7658423133635 url: "https://pub.dev" source: hosted - version: "1.0.16" + version: "1.0.17" analyzer: dependency: transitive description: name: analyzer - sha256: "2c2e3721ee9fb36de92faa060f3480c81b23e904352b087e5c64224b1a044427" + sha256: "881348aed9b0b425882c97732629a6a31093c8ff20fc4b3b03fb9d3d50a3a126" url: "https://pub.dev" source: hosted - version: "5.6.0" + version: "5.7.1" archive: dependency: transitive description: @@ -321,10 +321,10 @@ packages: dependency: transitive description: name: firebase_core - sha256: fe30ac230f12f8836bb97e6e09197340d3c584526825b1746ea362a82e1e43f7 + sha256: "1c121a478af23755b0b93fd4aa70d3bd32a587dd51ef0a3979091ac0d2317d32" url: "https://pub.dev" source: hosted - version: "2.7.0" + version: "2.7.1" firebase_core_platform_interface: dependency: transitive description: @@ -337,26 +337,26 @@ packages: dependency: transitive description: name: firebase_core_web - sha256: "291fbcace608aca6c860652e1358ef89752be8cc3ef227f8bbcd1e62775b833a" + sha256: "0c1cf1f1022d2245ac117443bb95207952ca770281524d2908e323bc063fb8ff" url: "https://pub.dev" source: hosted - version: "2.2.1" + version: "2.2.2" firebase_crashlytics: dependency: transitive description: name: firebase_crashlytics - sha256: "816bbb920316c8fe257b460b8856b01e274e867a729961bf7a3be6322cdf13e1" + sha256: d4190479611f42a34a04630d9188f30b592b65013d0f19c408d5249998429864 url: "https://pub.dev" source: hosted - version: "3.0.15" + version: "3.0.16" firebase_crashlytics_platform_interface: dependency: transitive description: name: firebase_crashlytics_platform_interface - sha256: "120e47b9bac3654848d1bdc60b8027f3574b53ee0b81b1a2e5e76ddaa58f6645" + sha256: "667955b348b7729ed3d987956021a97fcdd05957df7c27b2d855e6b3f70e9521" url: "https://pub.dev" source: hosted - version: "3.3.15" + version: "3.3.16" flex_color_picker: dependency: "direct main" description: @@ -376,12 +376,11 @@ packages: floating: dependency: "direct main" description: - path: "." - ref: source-rect-hint - resolved-ref: "84b2f7997da4393dedf3f2e09dd990e5d5492161" - url: "https://github.com/deckerst/floating.git" - source: git - version: "1.1.3" + name: floating + sha256: c6380d9cbf628370c68749fa1f0675bc5b69d9a5b923b84660e79b3e6c9a47ec + url: "https://pub.dev" + source: hosted + version: "2.0.0" fluster: dependency: "direct main" description: @@ -457,10 +456,10 @@ packages: dependency: transitive description: name: flutter_plugin_android_lifecycle - sha256: "4bef634684b2c7f3468c77c766c831229af829a0cd2d4ee6c1b99558bd14e5d2" + sha256: c224ac897bed083dabf11f238dd11a239809b446740be0c2044608c50029ffdf url: "https://pub.dev" source: hosted - version: "2.0.8" + version: "2.0.9" flutter_staggered_animations: dependency: "direct main" description: @@ -512,34 +511,34 @@ packages: dependency: transitive description: name: google_api_availability - sha256: a1f58c5213abae549fb1e1451bc68eb499da7033039f77bc289fd6faca384295 + sha256: "1642876fa87515fd5e4074458f22d6ba4518919c5abce16baaa2878c3c555678" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "4.0.0" google_maps_flutter: dependency: transitive description: name: google_maps_flutter - sha256: e4f117747e210e68fe34196c93040e0712ba8aa91f8813fe8cb3f52ad667e70b + sha256: "24392ef192f3b00bcd93151375676805a9933574423a5bd5509a0ead2e8a4215" url: "https://pub.dev" source: hosted - version: "2.2.4" + version: "2.2.5" google_maps_flutter_android: dependency: transitive description: name: google_maps_flutter_android - sha256: "69bac3fd18db5638763b06e04c2f2ff2e65e0a76fe93e0e211d8a77afaca033f" + sha256: a8ee18649a67750cbd477a6867a1bf9c4154c5e9f69d722c8b53a627a6d58303 url: "https://pub.dev" source: hosted - version: "2.4.6" + version: "2.4.9" google_maps_flutter_ios: dependency: transitive description: name: google_maps_flutter_ios - sha256: "7ed57e6f1351aebf1442dea0028f2c880989ead866eaf25e9121237c622d4af0" + sha256: e9ad74415a222573625a2c1717adc1e375b18e8ce660fc12db734d1bda1132d4 url: "https://pub.dev" source: hosted - version: "2.1.14" + version: "2.2.1" google_maps_flutter_platform_interface: dependency: transitive description: @@ -640,26 +639,26 @@ packages: dependency: "direct main" description: name: local_auth - sha256: "1625a217c599db02044df992509eb52584cfdaa8219958d516b74f644ef2c626" + sha256: "0cf238be2bfa51a6c9e7e9cfc11c05ea39f2a3a4d3e5bb255d0ebc917da24401" url: "https://pub.dev" source: hosted - version: "2.1.5" + version: "2.1.6" local_auth_android: dependency: transitive description: name: local_auth_android - sha256: "9106024549f411fea2543630582ae7937fcb97ce197755a6d985b23b980410c7" + sha256: "2ccfadbb6fbc63e6674ad58a350b06188829e62669d67a0c752c4e43cb88272a" url: "https://pub.dev" source: hosted - version: "1.0.19" + version: "1.0.21" local_auth_ios: dependency: transitive description: name: local_auth_ios - sha256: "14e7822264fbb6842240e09ff32a60e2ca2b1c3207de8adf2f56c149cccd49fd" + sha256: "604078f6492fe7730fc5bb8e4f2cfe2bc287a9b499ea0ff30a29925fc1873728" url: "https://pub.dev" source: hosted - version: "1.0.13" + version: "1.1.1" local_auth_platform_interface: dependency: transitive description: @@ -672,10 +671,10 @@ packages: dependency: transitive description: name: local_auth_windows - sha256: "69c4a6b1201e7b5467e7180c7dd84cf96c308982680cc1778984552bea84b0bc" + sha256: bfe0deede77fb36faa62799977074f35ac096d7cafce0c29a44a173d2a2a4b94 url: "https://pub.dev" source: hosted - version: "1.0.6" + version: "1.0.7" logging: dependency: transitive description: @@ -842,10 +841,10 @@ packages: dependency: transitive description: name: path_provider_linux - sha256: "525ad5e07622d19447ad740b1ed5070031f7a5437f44355ae915ff56e986429a" + sha256: "2ae08f2216225427e64ad224a24354221c2c7907e448e6e0e8b57b1eb9f10ad1" url: "https://pub.dev" source: hosted - version: "2.1.9" + version: "2.1.10" path_provider_platform_interface: dependency: transitive description: @@ -858,10 +857,10 @@ packages: dependency: transitive description: name: path_provider_windows - sha256: "642ddf65fde5404f83267e8459ddb4556316d3ee6d511ed193357e25caa3632d" + sha256: f53720498d5a543f9607db4b0e997c4b5438884de25b0f73098cc2671a51b130 url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.1.5" pattern_lock: dependency: "direct main" description: @@ -882,10 +881,10 @@ packages: dependency: "direct main" description: name: percent_indicator - sha256: cec41f67181fbd5322aa68b355621d1a4eea827426b8eeb613f6cbe195ff7b4a + sha256: c37099ad833a883c9d71782321cb65c3a848c21b6939b6185f0ff6640d05814c url: "https://pub.dev" source: hosted - version: "4.2.2" + version: "4.2.3" permission_handler: dependency: "direct main" description: @@ -1098,26 +1097,26 @@ packages: dependency: transitive description: name: shared_preferences_android - sha256: a51a4f9375097f94df1c6e0a49c0374440d31ab026b59d58a7e7660675879db4 + sha256: ad423a80fe7b4e48b50d6111b3ea1027af0e959e49d485712e134863d9c1c521 url: "https://pub.dev" source: hosted - version: "2.0.16" + version: "2.0.17" shared_preferences_foundation: dependency: transitive description: name: shared_preferences_foundation - sha256: "6b84fdf06b32bb336f972d373cd38b63734f3461ba56ac2ba01b56d052796259" + sha256: "1e755f8583229f185cfca61b1d80fb2344c9d660e1c69ede5450d8f478fa5310" url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.1.5" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux - sha256: d7fb71e6e20cd3dfffcc823a28da3539b392e53ed5fc5c2b90b55fdaa8a7e8fa + sha256: "3a59ed10890a8409ad0faad7bb2957dab4b92b8fbe553257b05d30ed8af2c707" url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.1.5" shared_preferences_platform_interface: dependency: "direct dev" description: @@ -1130,18 +1129,18 @@ packages: dependency: transitive description: name: shared_preferences_web - sha256: "6737b757e49ba93de2a233df229d0b6a87728cea1684da828cbc718b65dcf9d7" + sha256: "0dc2633f215a3d4aa3184c9b2c5766f4711e4e5a6b256e62aafee41f89f1bfb8" url: "https://pub.dev" source: hosted - version: "2.0.5" + version: "2.0.6" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows - sha256: bd014168e8484837c39ef21065b78f305810ceabc1d4f90be6e3b392ce81b46d + sha256: "71bcd669bb9cdb6b39f22c4a7728b6d49e934f6cba73157ffa5a54f1eed67436" url: "https://pub.dev" source: hosted - version: "2.1.4" + version: "2.1.5" shelf: dependency: transitive description: @@ -1360,34 +1359,34 @@ packages: dependency: transitive description: name: url_launcher_android - sha256: "1f4d9ebe86f333c15d318f81dcdc08b01d45da44af74552608455ebdc08d9732" + sha256: "845530e5e05db5500c1a4c1446785d60cbd8f9bd45e21e7dd643a3273bb4bbd1" url: "https://pub.dev" source: hosted - version: "6.0.24" + version: "6.0.25" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: c9cd648d2f7ab56968e049d4e9116f96a85517f1dd806b96a86ea1018a3a82e5 + sha256: "7ab1e5b646623d6a2537aa59d5d039f90eebef75a7c25e105f6f75de1f7750c3" url: "https://pub.dev" source: hosted - version: "6.1.1" + version: "6.1.2" url_launcher_linux: dependency: transitive description: name: url_launcher_linux - sha256: e29039160ab3730e42f3d811dc2a6d5f2864b90a70fb765ea60144b03307f682 + sha256: "206fb8334a700ef7754d6a9ed119e7349bc830448098f21a69bf1b4ed038cabc" url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.4" url_launcher_macos: dependency: transitive description: name: url_launcher_macos - sha256: "2dddb3291a57b074dade66b5e07e64401dd2487caefd4e9e2f467138d8c7eb06" + sha256: "0ef2b4f97942a16523e51256b799e9aa1843da6c60c55eefbfa9dbc2dcb8331a" url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.4" url_launcher_platform_interface: dependency: transitive description: @@ -1400,18 +1399,18 @@ packages: dependency: transitive description: name: url_launcher_web - sha256: "574cfbe2390666003c3a1d129bdc4574aaa6728f0c00a4829a81c316de69dd9b" + sha256: "81fe91b6c4f84f222d186a9d23c73157dc4c8e1c71489c4d08be1ad3b228f1aa" url: "https://pub.dev" source: hosted - version: "2.0.15" + version: "2.0.16" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - sha256: "97c9067950a0d09cbd93e2e3f0383d1403989362b97102fbf446473a48079a4b" + sha256: a83ba3607a507758669cfafb03f9de09bf6e6280c14d9b9cb18f013e406dcacd url: "https://pub.dev" source: hosted - version: "3.0.4" + version: "3.0.5" vector_math: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 7b37b2d71..77caefdee 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -61,9 +61,6 @@ dependencies: ref: aves flex_color_picker: floating: - git: - url: https://github.com/deckerst/floating.git - ref: source-rect-hint fluster: flutter_displaymode: flutter_highlight: From e331d636db9c799a084a1a79f18906fc798071f0 Mon Sep 17 00:00:00 2001 From: "Weblate (bot)" Date: Wed, 8 Mar 2023 22:59:29 +0100 Subject: [PATCH 11/31] l10n by weblate (#541) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Translate-URL: https://hosted.weblate.org/projects/aves/app-android/ckb/ Translate-URL: https://hosted.weblate.org/projects/aves/app-android/eu/ Translate-URL: https://hosted.weblate.org/projects/aves/app-android/he/ Translate-URL: https://hosted.weblate.org/projects/aves/app-android/pl/ Translate-URL: https://hosted.weblate.org/projects/aves/app-android/sk/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/ar/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/ckb/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/cs/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/de/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/el/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/es/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/eu/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/fa/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/fr/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/he/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/id/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/it/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/ja/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/ko/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/lt/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/nb_NO/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/nl/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/nn/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/pl/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/pt/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/ro/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/ru/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/sk/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/th/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/tr/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/uk/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/zh_Hans/ Translate-URL: https://hosted.weblate.org/projects/aves/app-main/zh_Hant/ Translate-URL: https://hosted.weblate.org/projects/aves/store-full-description/eu/ Translate-URL: https://hosted.weblate.org/projects/aves/store-full-description/id/ Translate-URL: https://hosted.weblate.org/projects/aves/store-full-description/pl/ Translate-URL: https://hosted.weblate.org/projects/aves/store-full-description/ru/ Translate-URL: https://hosted.weblate.org/projects/aves/store-full-description/sk/ Translate-URL: https://hosted.weblate.org/projects/aves/store-short-description/eu/ Translate-URL: https://hosted.weblate.org/projects/aves/store-short-description/sk/ Translation: Aves/App - Android Translation: Aves/App - Main Translation: Aves/Store - Full description Translation: Aves/Store - Short description Co-authored-by: Aitor Salaberria Co-authored-by: Allan Nordhøy Co-authored-by: Eduardo Malaspina Co-authored-by: Eric Co-authored-by: Felipe Nogueira Co-authored-by: GoRaN Co-authored-by: Idj Co-authored-by: Igor Sorocean Co-authored-by: Jan Co-authored-by: Jonatas de Almeida Barros Co-authored-by: Linerly Co-authored-by: Martin Frandel Co-authored-by: MeFinity Co-authored-by: Nattapong K Co-authored-by: Oğuz Ersen Co-authored-by: Salih Ail Co-authored-by: Skrripy Co-authored-by: Thibault Deckers Co-authored-by: Tijolinho Co-authored-by: Translator-3000 Co-authored-by: gallegonovato Co-authored-by: glemco Co-authored-by: kaajjo Co-authored-by: kha84 Co-authored-by: rehork Co-authored-by: slasb37 Co-authored-by: tryvseu Co-authored-by: vesp --- .../metadata/android/ru/full_description.txt | 2 +- lib/l10n/app_es.arb | 10 +++- lib/l10n/app_eu.arb | 10 +++- lib/l10n/app_fr.arb | 10 +++- lib/l10n/app_id.arb | 10 +++- lib/l10n/app_ko.arb | 10 +++- lib/l10n/app_nb.arb | 56 ++++++++++++++++++- lib/l10n/app_pl.arb | 10 +++- lib/l10n/app_pt.arb | 56 ++++++++++++++++++- lib/l10n/app_ru.arb | 16 +++++- lib/l10n/app_uk.arb | 10 +++- 11 files changed, 189 insertions(+), 11 deletions(-) diff --git a/fastlane/metadata/android/ru/full_description.txt b/fastlane/metadata/android/ru/full_description.txt index 4192d2677..158e533fd 100644 --- a/fastlane/metadata/android/ru/full_description.txt +++ b/fastlane/metadata/android/ru/full_description.txt @@ -2,4 +2,4 @@ Навигация и поиск важные части Aves. Пользователи могут легко переходить от альбомов к фотографиям, тэгам, картам и т.д. -Aves интегрируется с Android (начиная с версии API 19 до 33, т.е. от KitKat до Android 13) предлагая такие возможности как виджеты, пользовательские ярлыки, скринсейвер и поддержку глобального поиска. Он так же работает как диалоговое окно для просмотра и выбора медиа. \ No newline at end of file +Aves интегрируется с Android (от KitKat до Android 13, включая Android TV) предлагая такие возможности как виджеты, пользовательские ярлыки, скринсейвер и поддержку глобального поиска. Он так же работает как диалоговое окно для просмотра и выбора медиа. \ No newline at end of file diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 8031d784f..144ce676f 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -1262,5 +1262,13 @@ "lengthUnitPercent": "%", "@lengthUnitPercent": {}, "exportEntryDialogWriteMetadata": "Escribir metadatos", - "@exportEntryDialogWriteMetadata": {} + "@exportEntryDialogWriteMetadata": {}, + "vaultLockTypePattern": "Patrón", + "@vaultLockTypePattern": {}, + "patternDialogEnter": "Introduzca el patrón", + "@patternDialogEnter": {}, + "patternDialogConfirm": "Confirme el patrón", + "@patternDialogConfirm": {}, + "settingsVideoEnablePip": "Imagen-en-imagen", + "@settingsVideoEnablePip": {} } diff --git a/lib/l10n/app_eu.arb b/lib/l10n/app_eu.arb index 61bcc6d3d..18ea879b1 100644 --- a/lib/l10n/app_eu.arb +++ b/lib/l10n/app_eu.arb @@ -1420,5 +1420,13 @@ "vaultLockTypePassword": "Pasahitza", "@vaultLockTypePassword": {}, "drawerPlacePage": "Lekuak", - "@drawerPlacePage": {} + "@drawerPlacePage": {}, + "vaultLockTypePattern": "Patroia", + "@vaultLockTypePattern": {}, + "patternDialogEnter": "Sartu patroia", + "@patternDialogEnter": {}, + "patternDialogConfirm": "Konfirmatu patroia", + "@patternDialogConfirm": {}, + "settingsVideoEnablePip": "Bideoa leihotxoan", + "@settingsVideoEnablePip": {} } diff --git a/lib/l10n/app_fr.arb b/lib/l10n/app_fr.arb index 492486a6d..683e0d56c 100644 --- a/lib/l10n/app_fr.arb +++ b/lib/l10n/app_fr.arb @@ -1262,5 +1262,13 @@ "lengthUnitPercent": "%", "@lengthUnitPercent": {}, "exportEntryDialogWriteMetadata": "Écrire les métadonnées", - "@exportEntryDialogWriteMetadata": {} + "@exportEntryDialogWriteMetadata": {}, + "patternDialogEnter": "Entrez votre modèle", + "@patternDialogEnter": {}, + "patternDialogConfirm": "Confirmez votre modèle", + "@patternDialogConfirm": {}, + "vaultLockTypePattern": "Modèle", + "@vaultLockTypePattern": {}, + "settingsVideoEnablePip": "Picture-in-picture", + "@settingsVideoEnablePip": {} } diff --git a/lib/l10n/app_id.arb b/lib/l10n/app_id.arb index 06a8173b4..dae849ca4 100644 --- a/lib/l10n/app_id.arb +++ b/lib/l10n/app_id.arb @@ -1262,5 +1262,13 @@ "lengthUnitPixel": "px", "@lengthUnitPixel": {}, "lengthUnitPercent": "%", - "@lengthUnitPercent": {} + "@lengthUnitPercent": {}, + "vaultLockTypePattern": "Pola", + "@vaultLockTypePattern": {}, + "patternDialogConfirm": "Konfirmasi pola", + "@patternDialogConfirm": {}, + "patternDialogEnter": "Masukkan pola", + "@patternDialogEnter": {}, + "settingsVideoEnablePip": "Gambar dalam gambar", + "@settingsVideoEnablePip": {} } diff --git a/lib/l10n/app_ko.arb b/lib/l10n/app_ko.arb index 28f48e43d..c5cfc5467 100644 --- a/lib/l10n/app_ko.arb +++ b/lib/l10n/app_ko.arb @@ -1262,5 +1262,13 @@ "lengthUnitPercent": "%", "@lengthUnitPercent": {}, "exportEntryDialogWriteMetadata": "메타데이터 저장", - "@exportEntryDialogWriteMetadata": {} + "@exportEntryDialogWriteMetadata": {}, + "patternDialogConfirm": "패턴을 확인하세요", + "@patternDialogConfirm": {}, + "patternDialogEnter": "패턴을 입력하세요", + "@patternDialogEnter": {}, + "vaultLockTypePattern": "패턴", + "@vaultLockTypePattern": {}, + "settingsVideoEnablePip": "PIP 모드", + "@settingsVideoEnablePip": {} } diff --git a/lib/l10n/app_nb.arb b/lib/l10n/app_nb.arb index 69cb53c56..b35b9e78a 100644 --- a/lib/l10n/app_nb.arb +++ b/lib/l10n/app_nb.arb @@ -1366,5 +1366,59 @@ "tooManyItemsErrorDialogMessage": "Prøv igjen med færre elementer.", "@tooManyItemsErrorDialogMessage": {}, "settingsVideoGestureVerticalDragBrightnessVolume": "Dra opp eller ned for å justere lys-/lydstyrke", - "@settingsVideoGestureVerticalDragBrightnessVolume": {} + "@settingsVideoGestureVerticalDragBrightnessVolume": {}, + "settingsDisablingBinWarningDialogMessage": "Elementer i papirkurven vil bli slettet for godt.", + "@settingsDisablingBinWarningDialogMessage": {}, + "chipActionLock": "Lås", + "@chipActionLock": {}, + "chipActionGoToPlacePage": "Vis i «Steder»", + "@chipActionGoToPlacePage": {}, + "chipActionCreateVault": "Opprett hvelv", + "@chipActionCreateVault": {}, + "chipActionConfigureVault": "Sett opp hvelv", + "@chipActionConfigureVault": {}, + "albumTierVaults": "Hvelv", + "@albumTierVaults": {}, + "lengthUnitPixel": "px", + "@lengthUnitPixel": {}, + "newVaultDialogTitle": "Nytt hvelv", + "@newVaultDialogTitle": {}, + "configureVaultDialogTitle": "Sett opp hvelv", + "@configureVaultDialogTitle": {}, + "pinDialogEnter": "Skriv inn PIN", + "@pinDialogEnter": {}, + "pinDialogConfirm": "Bekreft PIN", + "@pinDialogConfirm": {}, + "passwordDialogEnter": "Skriv inn passord", + "@passwordDialogEnter": {}, + "passwordDialogConfirm": "Bekreft passord", + "@passwordDialogConfirm": {}, + "authenticateToConfigureVault": "Identitetsbekreft for å sette opp hvelv", + "@authenticateToConfigureVault": {}, + "authenticateToUnlockVault": "Identitetsbekreft for å låse opp hvelv", + "@authenticateToUnlockVault": {}, + "vaultBinUsageDialogMessage": "Noen hvelv bruker papirkurven.", + "@vaultBinUsageDialogMessage": {}, + "newVaultWarningDialogMessage": "Elementer i hvelv er kun tilgjengelig for dette programmet, og ikke andre.\n\nHvis du avinstallerer dette programmet, eller tømmer denne programdataen vil du miste alle disse elementene.", + "@newVaultWarningDialogMessage": {}, + "drawerPlacePage": "Steder", + "@drawerPlacePage": {}, + "vaultLockTypePin": "PIN", + "@vaultLockTypePin": {}, + "vaultLockTypePassword": "Passord", + "@vaultLockTypePassword": {}, + "exportEntryDialogWriteMetadata": "Skriv metadata", + "@exportEntryDialogWriteMetadata": {}, + "placeEmpty": "Ingen steder", + "@placeEmpty": {}, + "vaultDialogLockModeWhenScreenOff": "Lås når skjermen skrur seg av", + "@vaultDialogLockModeWhenScreenOff": {}, + "vaultDialogLockTypeLabel": "Låsetype", + "@vaultDialogLockTypeLabel": {}, + "placePageTitle": "Steder", + "@placePageTitle": {}, + "settingsConfirmationVaultDataLoss": "Vis advarsel om hvelv-datatap", + "@settingsConfirmationVaultDataLoss": {}, + "lengthUnitPercent": "%", + "@lengthUnitPercent": {} } diff --git a/lib/l10n/app_pl.arb b/lib/l10n/app_pl.arb index 8bb84d038..a1d678f5f 100644 --- a/lib/l10n/app_pl.arb +++ b/lib/l10n/app_pl.arb @@ -1420,5 +1420,13 @@ "lengthUnitPercent": "%", "@lengthUnitPercent": {}, "placePageTitle": "Miejsca", - "@placePageTitle": {} + "@placePageTitle": {}, + "vaultLockTypePattern": "Wzór", + "@vaultLockTypePattern": {}, + "patternDialogEnter": "Ustaw wzór", + "@patternDialogEnter": {}, + "patternDialogConfirm": "Potwierdź wzór", + "@patternDialogConfirm": {}, + "settingsVideoEnablePip": "Obraz w obrazie", + "@settingsVideoEnablePip": {} } diff --git a/lib/l10n/app_pt.arb b/lib/l10n/app_pt.arb index 4309913e8..898acfcb6 100644 --- a/lib/l10n/app_pt.arb +++ b/lib/l10n/app_pt.arb @@ -1216,5 +1216,59 @@ "pinDialogConfirm": "Confirme o PIN", "@pinDialogConfirm": {}, "passwordDialogEnter": "Digite a senha", - "@passwordDialogEnter": {} + "@passwordDialogEnter": {}, + "columnCount": "{count, plural, =1{1 coluna} other{{count} colunas}}", + "@columnCount": { + "placeholders": { + "count": {} + } + }, + "settingsDisablingBinWarningDialogMessage": "Os itens na lixeira serão excluídos para sempre.", + "@settingsDisablingBinWarningDialogMessage": {}, + "vaultLockTypePin": "PIN", + "@vaultLockTypePin": {}, + "chipActionCreateVault": "Criar cofre", + "@chipActionCreateVault": {}, + "chipActionConfigureVault": "Configurar cofre", + "@chipActionConfigureVault": {}, + "albumTierVaults": "Cofres", + "@albumTierVaults": {}, + "lengthUnitPixel": "pixels", + "@lengthUnitPixel": {}, + "lengthUnitPercent": "%", + "@lengthUnitPercent": {}, + "exportEntryDialogWriteMetadata": "Escrever metadados", + "@exportEntryDialogWriteMetadata": {}, + "chipActionGoToPlacePage": "Exibir em Lugares", + "@chipActionGoToPlacePage": {}, + "placePageTitle": "Lugares", + "@placePageTitle": {}, + "drawerPlacePage": "Lugares", + "@drawerPlacePage": {}, + "placeEmpty": "Sem lugares", + "@placeEmpty": {}, + "tooManyItemsErrorDialogMessage": "Tente novamente com menos itens.", + "@tooManyItemsErrorDialogMessage": {}, + "settingsVideoGestureVerticalDragBrightnessVolume": "Deslize para cima ou para baixo para ajustar o brilho/volume", + "@settingsVideoGestureVerticalDragBrightnessVolume": {}, + "passwordDialogConfirm": "Confirmar senha", + "@passwordDialogConfirm": {}, + "authenticateToConfigureVault": "Autentique-se para configurar o cofre", + "@authenticateToConfigureVault": {}, + "authenticateToUnlockVault": "Autentique-se para desbloquear o cofre", + "@authenticateToUnlockVault": {}, + "vaultBinUsageDialogMessage": "Alguns cofres estão usando a lixeira.", + "@vaultBinUsageDialogMessage": {}, + "newVaultWarningDialogMessage": "Os itens nos cofres estão disponíveis apenas para este aplicativo e nenhum outro.\n\nSe você desinstalar este aplicativo ou limpar os dados do aplicativo, perderá todos esses itens.", + "@newVaultWarningDialogMessage": {}, + "settingsConfirmationVaultDataLoss": "Mostrar aviso de perda de dados do cofre", + "@settingsConfirmationVaultDataLoss": {}, + "patternDialogEnter": "Inserir padrão", + "@patternDialogEnter": {}, + "patternDialogConfirm": "Confirmar padrão", + "@patternDialogConfirm": {}, + "vaultLockTypePattern": "Padrão", + "@vaultLockTypePattern": {}, + "settingsVideoEnablePip": "Picture-in-picture", + "@settingsVideoEnablePip": {} } diff --git a/lib/l10n/app_ru.arb b/lib/l10n/app_ru.arb index 8b648cb9c..aec8a7e4e 100644 --- a/lib/l10n/app_ru.arb +++ b/lib/l10n/app_ru.arb @@ -1230,5 +1230,19 @@ "albumTierVaults": "Хранилища", "@albumTierVaults": {}, "newVaultWarningDialogMessage": "Элементы внутри хранилищ доступны только для этого приложения, и никакого другого.\n\nЕсли вы удалите приложение или очистите его данные, то вы потеряете все содержимое внутри хранилищ.", - "@newVaultWarningDialogMessage": {} + "@newVaultWarningDialogMessage": {}, + "filterLocatedLabel": "С местоположением", + "@filterLocatedLabel": {}, + "filterTaggedLabel": "С тэгами", + "@filterTaggedLabel": {}, + "chipActionGoToPlacePage": "Показать в местах", + "@chipActionGoToPlacePage": {}, + "settingsModificationWarningDialogMessage": "Другие настройки будут изменены.", + "@settingsModificationWarningDialogMessage": {}, + "placePageTitle": "Локации", + "@placePageTitle": {}, + "settingsDisablingBinWarningDialogMessage": "Элементы в корзине будут удалены навсегда.", + "@settingsDisablingBinWarningDialogMessage": {}, + "lengthUnitPixel": "пикс.", + "@lengthUnitPixel": {} } diff --git a/lib/l10n/app_uk.arb b/lib/l10n/app_uk.arb index cde3638cb..8657b80a9 100644 --- a/lib/l10n/app_uk.arb +++ b/lib/l10n/app_uk.arb @@ -1420,5 +1420,13 @@ "lengthUnitPixel": "px", "@lengthUnitPixel": {}, "lengthUnitPercent": "%", - "@lengthUnitPercent": {} + "@lengthUnitPercent": {}, + "settingsVideoEnablePip": "Картинка в картинці", + "@settingsVideoEnablePip": {}, + "vaultLockTypePattern": "Шаблон", + "@vaultLockTypePattern": {}, + "patternDialogEnter": "Введіть шаблон", + "@patternDialogEnter": {}, + "patternDialogConfirm": "Підтвердіть шаблон", + "@patternDialogConfirm": {} } From de6138ebaf837c05151d7104b31f04a06a84b57b Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Wed, 8 Mar 2023 23:03:29 +0100 Subject: [PATCH 12/31] l10n --- lib/widgets/about/translators.dart | 1 + untranslated.json | 115 +---------------------------- 2 files changed, 3 insertions(+), 113 deletions(-) diff --git a/lib/widgets/about/translators.dart b/lib/widgets/about/translators.dart index 1d28e96bf..001668e5a 100644 --- a/lib/widgets/about/translators.dart +++ b/lib/widgets/about/translators.dart @@ -49,6 +49,7 @@ class AboutTranslators extends StatelessWidget { Contributor('Aitor Salaberria', 'trslbrr@gmail.com'), Contributor('Felipe Nogueira', 'contato.fnog@gmail.com'), Contributor('kaajjo', 'claymanoff@gmail.com'), + Contributor('Eduardo Malaspina', 'vaio0@swismail.com'), // Contributor('SAMIRAH AIL', 'samiratalzahrani@gmail.com'), // Arabic // Contributor('Salih Ail', 'rrrfff444@gmail.com'), // Arabic // Contributor('امیر جهانگرد', 'ijahangard.a@gmail.com'), // Persian diff --git a/untranslated.json b/untranslated.json index c3206618f..29a841a46 100644 --- a/untranslated.json +++ b/untranslated.json @@ -1250,20 +1250,6 @@ "settingsVideoEnablePip" ], - "es": [ - "vaultLockTypePattern", - "patternDialogEnter", - "patternDialogConfirm", - "settingsVideoEnablePip" - ], - - "eu": [ - "vaultLockTypePattern", - "patternDialogEnter", - "patternDialogConfirm", - "settingsVideoEnablePip" - ], - "fa": [ "clearTooltip", "chipActionGoToPlacePage", @@ -1736,13 +1722,6 @@ "filePickerUseThisFolder" ], - "fr": [ - "vaultLockTypePattern", - "patternDialogEnter", - "patternDialogConfirm", - "settingsVideoEnablePip" - ], - "gl": [ "columnCount", "chipActionGoToPlacePage", @@ -2880,13 +2859,6 @@ "filePickerUseThisFolder" ], - "id": [ - "vaultLockTypePattern", - "patternDialogEnter", - "patternDialogConfirm", - "settingsVideoEnablePip" - ], - "it": [ "chipActionGoToPlacePage", "lengthUnitPixel", @@ -2952,13 +2924,6 @@ "settingsWidgetDisplayedItem" ], - "ko": [ - "vaultLockTypePattern", - "patternDialogEnter", - "patternDialogConfirm", - "settingsVideoEnablePip" - ], - "lt": [ "columnCount", "chipActionGoToPlacePage", @@ -3004,37 +2969,10 @@ ], "nb": [ - "chipActionGoToPlacePage", - "chipActionLock", - "chipActionCreateVault", - "chipActionConfigureVault", - "albumTierVaults", - "lengthUnitPixel", - "lengthUnitPercent", "vaultLockTypePattern", - "vaultLockTypePin", - "vaultLockTypePassword", - "newVaultWarningDialogMessage", - "newVaultDialogTitle", - "configureVaultDialogTitle", - "vaultDialogLockModeWhenScreenOff", - "vaultDialogLockTypeLabel", "patternDialogEnter", "patternDialogConfirm", - "pinDialogEnter", - "pinDialogConfirm", - "passwordDialogEnter", - "passwordDialogConfirm", - "authenticateToConfigureVault", - "authenticateToUnlockVault", - "vaultBinUsageDialogMessage", - "exportEntryDialogWriteMetadata", - "drawerPlacePage", - "placePageTitle", - "placeEmpty", - "settingsConfirmationVaultDataLoss", - "settingsVideoEnablePip", - "settingsDisablingBinWarningDialogMessage" + "settingsVideoEnablePip" ], "nl": [ @@ -3414,41 +3352,6 @@ "wallpaperUseScrollEffect" ], - "pl": [ - "vaultLockTypePattern", - "patternDialogEnter", - "patternDialogConfirm", - "settingsVideoEnablePip" - ], - - "pt": [ - "columnCount", - "chipActionGoToPlacePage", - "chipActionCreateVault", - "chipActionConfigureVault", - "albumTierVaults", - "lengthUnitPixel", - "lengthUnitPercent", - "vaultLockTypePattern", - "vaultLockTypePin", - "newVaultWarningDialogMessage", - "patternDialogEnter", - "patternDialogConfirm", - "passwordDialogConfirm", - "authenticateToConfigureVault", - "authenticateToUnlockVault", - "vaultBinUsageDialogMessage", - "exportEntryDialogWriteMetadata", - "tooManyItemsErrorDialogMessage", - "drawerPlacePage", - "placePageTitle", - "placeEmpty", - "settingsConfirmationVaultDataLoss", - "settingsVideoEnablePip", - "settingsVideoGestureVerticalDragBrightnessVolume", - "settingsDisablingBinWarningDialogMessage" - ], - "ro": [ "chipActionGoToPlacePage", "lengthUnitPixel", @@ -3464,11 +3367,7 @@ ], "ru": [ - "chipActionGoToPlacePage", "chipActionLock", - "filterLocatedLabel", - "filterTaggedLabel", - "lengthUnitPixel", "vaultLockTypePattern", "patternDialogEnter", "patternDialogConfirm", @@ -3477,13 +3376,10 @@ "exportEntryDialogWriteMetadata", "tooManyItemsErrorDialogMessage", "drawerPlacePage", - "placePageTitle", "placeEmpty", - "settingsModificationWarningDialogMessage", "settingsConfirmationVaultDataLoss", "settingsVideoEnablePip", - "settingsVideoGestureVerticalDragBrightnessVolume", - "settingsDisablingBinWarningDialogMessage" + "settingsVideoGestureVerticalDragBrightnessVolume" ], "sk": [ @@ -4297,13 +4193,6 @@ "settingsDisablingBinWarningDialogMessage" ], - "uk": [ - "vaultLockTypePattern", - "patternDialogEnter", - "patternDialogConfirm", - "settingsVideoEnablePip" - ], - "zh": [ "chipActionGoToPlacePage", "chipActionLock", From 102e3974e738c4512f83514c4be62899708610b3 Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Thu, 9 Mar 2023 18:22:43 +0100 Subject: [PATCH 13/31] upgraded Flutter to stable v3.7.7 --- .flutter | 2 +- CHANGELOG.md | 2 +- pubspec.lock | 2 +- pubspec.yaml | 2 +- shaders.sksl.json | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.flutter b/.flutter index 12cb4eb7a..2ad6cd72c 160000 --- a/.flutter +++ b/.flutter @@ -1 +1 @@ -Subproject commit 12cb4eb7a009f52b347b62ade7cb4854b926af72 +Subproject commit 2ad6cd72c040113b47ee9055e722606a490ef0da diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ca45d2f6..e7516ea77 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,7 @@ All notable changes to this project will be documented in this file. ### Changed -- upgraded Flutter to stable v3.7.6 +- upgraded Flutter to stable v3.7.7 ### Fixed diff --git a/pubspec.lock b/pubspec.lock index 1c504215b..33e622d23 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1509,4 +1509,4 @@ packages: version: "3.1.1" sdks: dart: ">=2.19.0 <3.0.0" - flutter: ">=3.7.6" + flutter: ">=3.7.7" diff --git a/pubspec.yaml b/pubspec.yaml index 77caefdee..955b8efb7 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -13,7 +13,7 @@ publish_to: none environment: # this project bundles Flutter SDK via `flutter_wrapper` # cf https://github.com/passsy/flutter_wrapper - flutter: 3.7.6 + flutter: 3.7.7 sdk: ">=2.19.0 <3.0.0" # following https://github.blog/2021-09-01-improving-git-protocol-security-github/ diff --git a/shaders.sksl.json b/shaders.sksl.json index d8517ada6..ca79c9285 100644 --- a/shaders.sksl.json +++ b/shaders.sksl.json @@ -1 +1 @@ -{"platform":"android","name":"SM G970N","engineRevision":"ada363ee93b17cfe31587b5102679885cb40837e","data":{"HUQAAAAAAAMAADAAAIOAAAH677776IZOCAAP577777777777777777YBAAAAAAAAAAAHEADBAAAAAAIAAAAAAOQAAAAAAAQAAAABAMQAAAAAA":"CgAAAExTS1PUAAAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gaGFsZjQgY29sb3I7CmZsYXQgb3V0IGhhbGY0IHZjb2xvcl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgl2Y29sb3JfUzAgPSBjb2xvcjsKCXNrX1Bvc2l0aW9uID0gcG9zaXRpb24ueHkwMTsKfQoBAAAA+wIAAHVuaWZvcm0gZmxvYXQ0IHVpbm5lclJlY3RfUzE7CnVuaWZvcm0gaGFsZjIgdXJhZGl1c1BsdXNIYWxmX1MxOwpmbGF0IGluIGhhbGY0IHZjb2xvcl9TMDsKaGFsZjQgQ2lyY3VsYXJSUmVjdF9TMShoYWxmNCBfaW5wdXQpIAp7CglmbG9hdCBkeDAgPSB1aW5uZXJSZWN0X1MxLkwgLSBza19GcmFnQ29vcmQueDsKCWZsb2F0MiBkeHkxID0gc2tfRnJhZ0Nvb3JkLnh5IC0gdWlubmVyUmVjdF9TMS5SQjsKCWZsb2F0MiBkeHkgPSBtYXgoZmxvYXQyKG1heChkeDAsIGR4eTEueCksIGR4eTEueSksIDAuMCk7CgloYWxmIHRvcEFscGhhID0gaGFsZihzYXR1cmF0ZShza19GcmFnQ29vcmQueSAtIHVpbm5lclJlY3RfUzEuVCkpOwoJaGFsZiBhbHBoYSA9IHRvcEFscGhhICogaGFsZihzYXR1cmF0ZSh1cmFkaXVzUGx1c0hhbGZfUzEueCAtIGxlbmd0aChkeHkpKSk7CglyZXR1cm4gX2lucHV0ICogYWxwaGE7Cn0Kdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJaGFsZjQgb3V0cHV0Q29sb3JfUzA7CglvdXRwdXRDb2xvcl9TMCA9IHZjb2xvcl9TMDsKCWNvbnN0IGhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoMSk7CgloYWxmNCBvdXRwdXRfUzE7CglvdXRwdXRfUzEgPSBDaXJjdWxhclJSZWN0X1MxKG91dHB1dENvdmVyYWdlX1MwKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dF9TMTsKCX0KfQoAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAIAAAAcG9zaXRpb24FAAAAY29sb3IAAAAAAAAA","DAQAAAAAAABGAABAYAAQAIHCAIAYAQUBAEAAAAAAEAAAAAAAAAAAAIAHSADQAAAQAAAAAAFAAMAAAABAAAAAAABBAM":"CgAAAExTS1MWAgAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQyIHVBdGxhc1NpemVJbnZfUzA7CmluIGZsb2F0MiBpblBvc2l0aW9uOwppbiBoYWxmNCBpbkNvbG9yOwppbiB1c2hvcnQyIGluVGV4dHVyZUNvb3JkczsKb3V0IGZsb2F0MiB2VGV4dHVyZUNvb3Jkc19TMDsKZmxhdCBvdXQgZmxvYXQgdlRleEluZGV4X1MwOwpvdXQgaGFsZjQgdmluQ29sb3JfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIEJpdG1hcFRleHQKCWludCB0ZXhJZHggPSAwOwoJZmxvYXQyIHVub3JtVGV4Q29vcmRzID0gZmxvYXQyKGluVGV4dHVyZUNvb3Jkcy54LCBpblRleHR1cmVDb29yZHMueSk7Cgl2VGV4dHVyZUNvb3Jkc19TMCA9IHVub3JtVGV4Q29vcmRzICogdUF0bGFzU2l6ZUludl9TMDsKCXZUZXhJbmRleF9TMCA9IGZsb2F0KHRleElkeCk7Cgl2aW5Db2xvcl9TMCA9IGluQ29sb3I7CglmbG9hdDIgX3RtcF8xX2luUG9zaXRpb24gPSBpblBvc2l0aW9uOwoJc2tfUG9zaXRpb24gPSBpblBvc2l0aW9uLnh5MDE7Cn0KAAABAAAAQAMAAHVuaWZvcm0gZmxvYXQ0IHVpbm5lclJlY3RfUzE7CnVuaWZvcm0gaGFsZjIgdXJhZGl1c1BsdXNIYWxmX1MxOwp1bmlmb3JtIHNhbXBsZXIyRCB1VGV4dHVyZVNhbXBsZXJfMF9TMDsKaW4gZmxvYXQyIHZUZXh0dXJlQ29vcmRzX1MwOwpmbGF0IGluIGZsb2F0IHZUZXhJbmRleF9TMDsKaW4gaGFsZjQgdmluQ29sb3JfUzA7CmhhbGY0IENpcmN1bGFyUlJlY3RfUzEoaGFsZjQgX2lucHV0KSAKewoJZmxvYXQyIGR4eTAgPSB1aW5uZXJSZWN0X1MxLkxUIC0gc2tfRnJhZ0Nvb3JkLnh5OwoJZmxvYXQyIGR4eTEgPSBza19GcmFnQ29vcmQueHkgLSB1aW5uZXJSZWN0X1MxLlJCOwoJZmxvYXQyIGR4eSA9IG1heChtYXgoZHh5MCwgZHh5MSksIDAuMCk7CgloYWxmIGFscGhhID0gaGFsZihzYXR1cmF0ZSh1cmFkaXVzUGx1c0hhbGZfUzEueCAtIGxlbmd0aChkeHkpKSk7CglyZXR1cm4gX2lucHV0ICogYWxwaGE7Cn0Kdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIEJpdG1hcFRleHQKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2aW5Db2xvcl9TMDsKCWhhbGY0IHRleENvbG9yOwoJewoJCXRleENvbG9yID0gc2FtcGxlKHVUZXh0dXJlU2FtcGxlcl8wX1MwLCB2VGV4dHVyZUNvb3Jkc19TMCkucnJycjsKCX0KCWhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gdGV4Q29sb3I7CgloYWxmNCBvdXRwdXRfUzE7CglvdXRwdXRfUzEgPSBDaXJjdWxhclJSZWN0X1MxKG91dHB1dENvdmVyYWdlX1MwKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dF9TMTsKCX0KfQoBAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAoAAABpblBvc2l0aW9uAAAHAAAAaW5Db2xvcgAPAAAAaW5UZXh0dXJlQ29vcmRzAAAAAAA=","AYTRVAADQAAAOAEARAFQJAABBADAAAILBYAACCYUQD777777777767YAAAAAAAAAAAAOQAAAAAAAQAAAABAMQAAAAA":"CgAAAExTS1NyAgAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQ0IHVsb2NhbE1hdHJpeF9TMDsKaW4gZmxvYXQyIGluUG9zaXRpb247CmluIGhhbGY0IGluQ29sb3I7CmluIGZsb2F0NCBpbkNpcmNsZUVkZ2U7CmluIGhhbGYzIGluQ2xpcFBsYW5lOwppbiBoYWxmMyBpbklzZWN0UGxhbmU7Cm91dCBmbG9hdDQgdmluQ2lyY2xlRWRnZV9TMDsKb3V0IGhhbGYzIHZpbkNsaXBQbGFuZV9TMDsKb3V0IGhhbGYzIHZpbklzZWN0UGxhbmVfUzA7Cm91dCBoYWxmNCB2aW5Db2xvcl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgQ2lyY2xlR2VvbWV0cnlQcm9jZXNzb3IKCXZpbkNpcmNsZUVkZ2VfUzAgPSBpbkNpcmNsZUVkZ2U7Cgl2aW5DbGlwUGxhbmVfUzAgPSBpbkNsaXBQbGFuZTsKCXZpbklzZWN0UGxhbmVfUzAgPSBpbklzZWN0UGxhbmU7Cgl2aW5Db2xvcl9TMCA9IGluQ29sb3I7CglmbG9hdDIgX3RtcF8wX2luUG9zaXRpb24gPSBpblBvc2l0aW9uOwoJZmxvYXQyIF90bXBfMV9pblBvc2l0aW9uID0gdWxvY2FsTWF0cml4X1MwLnh6ICogaW5Qb3NpdGlvbiArIHVsb2NhbE1hdHJpeF9TMC55dzsKCXNrX1Bvc2l0aW9uID0gX3RtcF8wX2luUG9zaXRpb24ueHkwMTsKfQoAAAAAAADdAwAAaW4gZmxvYXQ0IHZpbkNpcmNsZUVkZ2VfUzA7CmluIGhhbGYzIHZpbkNsaXBQbGFuZV9TMDsKaW4gaGFsZjMgdmluSXNlY3RQbGFuZV9TMDsKaW4gaGFsZjQgdmluQ29sb3JfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBDaXJjbGVHZW9tZXRyeVByb2Nlc3NvcgoJZmxvYXQ0IGNpcmNsZUVkZ2U7CgljaXJjbGVFZGdlID0gdmluQ2lyY2xlRWRnZV9TMDsKCWhhbGYzIGNsaXBQbGFuZTsKCWNsaXBQbGFuZSA9IHZpbkNsaXBQbGFuZV9TMDsKCWhhbGYzIGlzZWN0UGxhbmU7Cglpc2VjdFBsYW5lID0gdmluSXNlY3RQbGFuZV9TMDsKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2aW5Db2xvcl9TMDsKCWZsb2F0IGQgPSBsZW5ndGgoY2lyY2xlRWRnZS54eSk7CgloYWxmIGRpc3RhbmNlVG9PdXRlckVkZ2UgPSBoYWxmKGNpcmNsZUVkZ2UueiAqICgxLjAgLSBkKSk7CgloYWxmIGVkZ2VBbHBoYSA9IHNhdHVyYXRlKGRpc3RhbmNlVG9PdXRlckVkZ2UpOwoJaGFsZiBkaXN0YW5jZVRvSW5uZXJFZGdlID0gaGFsZihjaXJjbGVFZGdlLnogKiAoZCAtIGNpcmNsZUVkZ2UudykpOwoJaGFsZiBpbm5lckFscGhhID0gc2F0dXJhdGUoZGlzdGFuY2VUb0lubmVyRWRnZSk7CgllZGdlQWxwaGEgKj0gaW5uZXJBbHBoYTsKCWhhbGYgY2xpcCA9IGhhbGYoc2F0dXJhdGUoY2lyY2xlRWRnZS56ICogZG90KGNpcmNsZUVkZ2UueHksIGNsaXBQbGFuZS54eSkgKyBjbGlwUGxhbmUueikpOwoJY2xpcCAqPSBoYWxmKHNhdHVyYXRlKGNpcmNsZUVkZ2UueiAqIGRvdChjaXJjbGVFZGdlLnh5LCBpc2VjdFBsYW5lLnh5KSArIGlzZWN0UGxhbmUueikpOwoJZWRnZUFscGhhICo9IGNsaXA7CgloYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KGVkZ2VBbHBoYSk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRDb3ZlcmFnZV9TMDsKCX0KfQoAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAoAAABpblBvc2l0aW9uAAAHAAAAaW5Db2xvcgAMAAAAaW5DaXJjbGVFZGdlCwAAAGluQ2xpcFBsYW5lAAwAAABpbklzZWN0UGxhbmUAAAAA","HUIAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAAAAAADUAANAAAAAAIBAIAAAABLCIIBAAAAABAEGABBAMAACAIAAAAAAAB2AAAAAAACAAAAAEBSAAAAA":"CgAAAExTS1M8AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMV9jMDsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBmbG9hdDIgbG9jYWxDb29yZDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfM19TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cgl7CgkJdlRyYW5zZm9ybWVkQ29vcmRzXzNfUzAgPSBmbG9hdDN4Mih1bWF0cml4X1MxX2MwKSAqIGxvY2FsQ29vcmQueHkxOwoJfQp9CgAAAADJAwAAdW5pZm9ybSBmbG9hdDQgdWNsYW1wX1MxX2MwX2MwOwp1bmlmb3JtIGZsb2F0M3gzIHVtYXRyaXhfUzFfYzA7CnVuaWZvcm0gc2FtcGxlcjJEIHVUZXh0dXJlU2FtcGxlcl8wX1MxOwppbiBmbG9hdDIgdlRyYW5zZm9ybWVkQ29vcmRzXzNfUzA7CmhhbGY0IFRleHR1cmVFZmZlY3RfUzFfYzBfYzAoaGFsZjQgX2lucHV0KSAKewoJZmxvYXQyIGluQ29vcmQgPSB2VHJhbnNmb3JtZWRDb29yZHNfM19TMDsKCWZsb2F0MiBzdWJzZXRDb29yZDsKCXN1YnNldENvb3JkLnggPSBpbkNvb3JkLng7CglzdWJzZXRDb29yZC55ID0gaW5Db29yZC55OwoJZmxvYXQyIGNsYW1wZWRDb29yZDsKCWNsYW1wZWRDb29yZCA9IGNsYW1wKHN1YnNldENvb3JkLCB1Y2xhbXBfUzFfYzBfYzAueHksIHVjbGFtcF9TMV9jMF9jMC56dyk7CgloYWxmNCB0ZXh0dXJlQ29sb3IgPSBzYW1wbGUodVRleHR1cmVTYW1wbGVyXzBfUzEsIGNsYW1wZWRDb29yZCk7CglyZXR1cm4gdGV4dHVyZUNvbG9yOwp9CmhhbGY0IE1hdHJpeEVmZmVjdF9TMV9jMChoYWxmNCBfaW5wdXQpIAp7CglyZXR1cm4gVGV4dHVyZUVmZmVjdF9TMV9jMF9jMChfaW5wdXQpOwp9CmhhbGY0IEJsZW5kX1MxKGhhbGY0IF9zcmMsIGhhbGY0IF9kc3QpIAp7CglyZXR1cm4gYmxlbmRfbW9kdWxhdGUoTWF0cml4RWZmZWN0X1MxX2MwKF9zcmMpLCBfc3JjKTsKfQp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMCA9IGhhbGY0KDEpOwoJY29uc3QgaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNCgxKTsKCWhhbGY0IG91dHB1dF9TMTsKCW91dHB1dF9TMSA9IEJsZW5kX1MxKG91dHB1dENvbG9yX1MwLCBoYWxmNCgxKSk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0X1MxICogb3V0cHV0Q292ZXJhZ2VfUzA7Cgl9Cn0KAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAIAAAAcG9zaXRpb24KAAAAbG9jYWxDb29yZAAAAAAAAA==","HUIAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAAAAAALUAQMAAAAAAIAAEAAAABJYQAAAAAQAAIAAAAAWCBACAABAAAAANAECAZAAEAAAAAAAAFAAMAAAABAAAAAAABBAM":"CgAAAExTS1M2AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBmbG9hdDIgbG9jYWxDb29yZDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cgl7CgkJdlRyYW5zZm9ybWVkQ29vcmRzXzJfUzAgPSBmbG9hdDN4Mih1bWF0cml4X1MxKSAqIGxvY2FsQ29vcmQueHkxOwoJfQp9CgAAAAAAAC8GAAB1bmlmb3JtIGZsb2F0NCB1Y2xhbXBfUzFfYzBfYzBfYzA7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMV9jMF9jMDsKdW5pZm9ybSBoYWxmMiB1SW5jcmVtZW50X1MxX2MwOwp1bmlmb3JtIGhhbGYyIHVPZmZzZXRzQW5kS2VybmVsX1MxX2MwWzEzXTsKdW5pZm9ybSBmbG9hdDN4MyB1bWF0cml4X1MxOwp1bmlmb3JtIHNhbXBsZXIyRCB1VGV4dHVyZVNhbXBsZXJfMF9TMTsKaW4gZmxvYXQyIHZUcmFuc2Zvcm1lZENvb3Jkc18yX1MwOwpoYWxmNCBUZXh0dXJlRWZmZWN0X1MxX2MwX2MwX2MwKGhhbGY0IF9pbnB1dCwgZmxvYXQyIF9jb29yZHMpIAp7CglmbG9hdDIgaW5Db29yZCA9IF9jb29yZHM7CglmbG9hdDIgc3Vic2V0Q29vcmQ7CglzdWJzZXRDb29yZC54ID0gaW5Db29yZC54OwoJc3Vic2V0Q29vcmQueSA9IGluQ29vcmQueTsKCWZsb2F0MiBjbGFtcGVkQ29vcmQ7CgljbGFtcGVkQ29vcmQueCA9IGNsYW1wKHN1YnNldENvb3JkLngsIHVjbGFtcF9TMV9jMF9jMF9jMC54LCB1Y2xhbXBfUzFfYzBfYzBfYzAueik7CgljbGFtcGVkQ29vcmQueSA9IHN1YnNldENvb3JkLnk7CgloYWxmNCB0ZXh0dXJlQ29sb3IgPSBzYW1wbGUodVRleHR1cmVTYW1wbGVyXzBfUzEsIGNsYW1wZWRDb29yZCk7CglyZXR1cm4gdGV4dHVyZUNvbG9yOwp9CmhhbGY0IE1hdHJpeEVmZmVjdF9TMV9jMF9jMChoYWxmNCBfaW5wdXQsIGZsb2F0MiBfY29vcmRzKSAKewoJcmV0dXJuIFRleHR1cmVFZmZlY3RfUzFfYzBfYzBfYzAoX2lucHV0LCBmbG9hdDN4Mih1bWF0cml4X1MxX2MwX2MwKSAqIF9jb29yZHMueHkxKTsKfQpoYWxmNCBTbW9vdGhfUzFfYzAoaGFsZjQgX2lucHV0LCBmbG9hdDIgY29vcmQsIGhhbGYyIG9mZnNldEFuZEtlcm5lbCkgCnsKCXJldHVybiBNYXRyaXhFZmZlY3RfUzFfYzBfYzAoX2lucHV0LCAoY29vcmQgKyBvZmZzZXRBbmRLZXJuZWwueCAqIHVJbmNyZW1lbnRfUzFfYzApKSAqIG9mZnNldEFuZEtlcm5lbC55Owp9CmhhbGY0IEdhdXNzaWFuQ29udm9sdXRpb25fUzFfYzAoaGFsZjQgX2lucHV0KSAKewoJaGFsZjQgY29sb3IgPSBoYWxmNCgwKTsKCWZsb2F0MiBjb29yZCA9IHZUcmFuc2Zvcm1lZENvb3Jkc18yX1MwOwoJZm9yIChpbnQgaT0wOyBpPDEzOyArK2kpIAoJewoJCWNvbG9yICs9IFNtb290aF9TMV9jMChfaW5wdXQsIGNvb3JkLCB1T2Zmc2V0c0FuZEtlcm5lbF9TMV9jMFtpXSk7Cgl9CglyZXR1cm4gY29sb3I7Cn0KaGFsZjQgTWF0cml4RWZmZWN0X1MxKGhhbGY0IF9pbnB1dCkgCnsKCXJldHVybiBHYXVzc2lhbkNvbnZvbHV0aW9uX1MxX2MwKF9pbnB1dCk7Cn0Kdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJaGFsZjQgb3V0cHV0Q29sb3JfUzAgPSBoYWxmNCgxKTsKCWNvbnN0IGhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoMSk7CgloYWxmNCBvdXRwdXRfUzE7CglvdXRwdXRfUzEgPSBNYXRyaXhFZmZlY3RfUzEob3V0cHV0Q29sb3JfUzApOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dF9TMSAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAgAAABwb3NpdGlvbgoAAABsb2NhbENvb3JkAAAAAAAA","AYQA5AADQAAAOAEARAFQJAABBADIB7777777777777777777777767YAAAAAAAAAACABZQA6AAAEAAAAAAAIADQAAAAIAAAAAAAIIDA":"CgAAAExTS1PMAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQ0IHVsb2NhbE1hdHJpeF9TMDsKaW4gZmxvYXQyIGluUG9zaXRpb247CmluIGhhbGY0IGluQ29sb3I7CmluIGZsb2F0NCBpbkNpcmNsZUVkZ2U7Cm91dCBmbG9hdDQgdmluQ2lyY2xlRWRnZV9TMDsKb3V0IGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBDaXJjbGVHZW9tZXRyeVByb2Nlc3NvcgoJdmluQ2lyY2xlRWRnZV9TMCA9IGluQ2lyY2xlRWRnZTsKCXZpbkNvbG9yX1MwID0gaW5Db2xvcjsKCWZsb2F0MiBfdG1wXzBfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247CglmbG9hdDIgX3RtcF8xX2luUG9zaXRpb24gPSB1bG9jYWxNYXRyaXhfUzAueHogKiBpblBvc2l0aW9uICsgdWxvY2FsTWF0cml4X1MwLnl3OwoJc2tfUG9zaXRpb24gPSBfdG1wXzBfaW5Qb3NpdGlvbi54eTAxOwp9CgEAAACPAwAAdW5pZm9ybSBmbG9hdDQgdWlubmVyUmVjdF9TMTsKdW5pZm9ybSBoYWxmMiB1cmFkaXVzUGx1c0hhbGZfUzE7CmluIGZsb2F0NCB2aW5DaXJjbGVFZGdlX1MwOwppbiBoYWxmNCB2aW5Db2xvcl9TMDsKaGFsZjQgQ2lyY3VsYXJSUmVjdF9TMShoYWxmNCBfaW5wdXQpIAp7CglmbG9hdDIgZHh5MCA9IHVpbm5lclJlY3RfUzEuTFQgLSBza19GcmFnQ29vcmQueHk7CglmbG9hdDIgZHh5MSA9IHNrX0ZyYWdDb29yZC54eSAtIHVpbm5lclJlY3RfUzEuUkI7CglmbG9hdDIgZHh5ID0gbWF4KG1heChkeHkwLCBkeHkxKSwgMC4wKTsKCWhhbGYgYWxwaGEgPSBoYWxmKHNhdHVyYXRlKHVyYWRpdXNQbHVzSGFsZl9TMS54IC0gbGVuZ3RoKGR4eSkpKTsKCWFscGhhID0gMS4wIC0gYWxwaGE7CglyZXR1cm4gX2lucHV0ICogYWxwaGE7Cn0Kdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIENpcmNsZUdlb21ldHJ5UHJvY2Vzc29yCglmbG9hdDQgY2lyY2xlRWRnZTsKCWNpcmNsZUVkZ2UgPSB2aW5DaXJjbGVFZGdlX1MwOwoJaGFsZjQgb3V0cHV0Q29sb3JfUzA7CglvdXRwdXRDb2xvcl9TMCA9IHZpbkNvbG9yX1MwOwoJZmxvYXQgZCA9IGxlbmd0aChjaXJjbGVFZGdlLnh5KTsKCWhhbGYgZGlzdGFuY2VUb091dGVyRWRnZSA9IGhhbGYoY2lyY2xlRWRnZS56ICogKDEuMCAtIGQpKTsKCWhhbGYgZWRnZUFscGhhID0gc2F0dXJhdGUoZGlzdGFuY2VUb091dGVyRWRnZSk7CgloYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KGVkZ2VBbHBoYSk7CgloYWxmNCBvdXRwdXRfUzE7CglvdXRwdXRfUzEgPSBDaXJjdWxhclJSZWN0X1MxKG91dHB1dENvdmVyYWdlX1MwKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dF9TMTsKCX0KfQoAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAKAAAAaW5Qb3NpdGlvbgAABwAAAGluQ29sb3IADAAAAGluQ2lyY2xlRWRnZQAAAAA=","BYIBQAAABQAAIAABBYAAAEIXBAAP777777777777AAAAAAAAAAAABUABAAAAAEAAAAAIBEABAAAAA":"CgAAAExTS1M+AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBpblBvc2l0aW9uOwppbiBoYWxmNCBpbkNvbG9yOwpvdXQgaGFsZjQgdmNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBEZWZhdWx0R2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IGNvbG9yID0gaW5Db2xvcjsKCXZjb2xvcl9TMCA9IGNvbG9yOwoJZmxvYXQyIF90bXBfMV9pblBvc2l0aW9uID0gaW5Qb3NpdGlvbjsKCWZsb2F0MiBfdG1wXzNfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247Cglza19Qb3NpdGlvbiA9IF90bXBfMV9pblBvc2l0aW9uLnh5MDE7Cn0KAAAAAAAABgEAAGluIGhhbGY0IHZjb2xvcl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIERlZmF1bHRHZW9tZXRyeVByb2Nlc3NvcgoJaGFsZjQgb3V0cHV0Q29sb3JfUzA7CglvdXRwdXRDb2xvcl9TMCA9IHZjb2xvcl9TMDsKCWNvbnN0IGhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoMSk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRDb3ZlcmFnZV9TMDsKCX0KfQoAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAACAAAACgAAAGluUG9zaXRpb24AAAcAAABpbkNvbG9yAAAAAAA=","B2ABSAAABQAAIAABBYAAB7777777777774ABICAAAAAAAAAAAAAABUABAAAAAEAAAAAIBEABAAAAA":"CgAAAExTS1N4AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gaGFsZjQgdUNvbG9yX1MwOwppbiBmbG9hdDIgaW5Qb3NpdGlvbjsKaW4gaGFsZiBpbkNvdmVyYWdlOwpvdXQgaGFsZjQgdmNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBEZWZhdWx0R2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IGNvbG9yID0gdUNvbG9yX1MwOwoJY29sb3IgPSBjb2xvciAqIGluQ292ZXJhZ2U7Cgl2Y29sb3JfUzAgPSBjb2xvcjsKCWZsb2F0MiBfdG1wXzFfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247CglmbG9hdDIgX3RtcF8zX2luUG9zaXRpb24gPSBpblBvc2l0aW9uOwoJc2tfUG9zaXRpb24gPSBfdG1wXzFfaW5Qb3NpdGlvbi54eTAxOwp9CgAAAAAGAQAAaW4gaGFsZjQgdmNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgRGVmYXVsdEdlb21ldHJ5UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdmNvbG9yX1MwOwoJY29uc3QgaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNCgxKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAKAAAAaW5Qb3NpdGlvbgAACgAAAGluQ292ZXJhZ2UAAAAAAAA=","FAAQMYAAMAAAEADAAABAEYAAAICIAB5AABQAAAQAMAAAEATAAABAIIGAAEDCBYQCA4AAAAAAEAKPABAAAAAAB2AAAAAAACAAAAAEBSAAAAAAA":"CgAAAExTS1PUCwAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0NCByYWRpaV9zZWxlY3RvcjsKaW4gZmxvYXQ0IGNvcm5lcl9hbmRfcmFkaXVzX291dHNldHM7CmluIGZsb2F0NCBhYV9ibG9hdF9hbmRfY292ZXJhZ2U7CmluIGZsb2F0NCByYWRpaV94OwppbiBmbG9hdDQgcmFkaWlfeTsKaW4gZmxvYXQ0IHNrZXc7CmluIGZsb2F0MiB0cmFuc2xhdGVfYW5kX2xvY2Fscm90YXRlOwppbiBoYWxmNCBjb2xvcjsKZmxhdCBvdXQgaGFsZjQgdmNvbG9yX1MwOwpvdXQgZmxvYXQyIHZhcmNjb29yZF9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgRmlsbFJSZWN0T3A6OlByb2Nlc3NvcgoJdmNvbG9yX1MwID0gY29sb3I7CglmbG9hdCBhYV9ibG9hdF9tdWx0aXBsaWVyID0gMTsKCWZsb2F0MiBjb3JuZXIgPSBjb3JuZXJfYW5kX3JhZGl1c19vdXRzZXRzLnh5OwoJZmxvYXQyIHJhZGl1c19vdXRzZXQgPSBjb3JuZXJfYW5kX3JhZGl1c19vdXRzZXRzLnp3OwoJZmxvYXQyIGFhX2Jsb2F0X2RpcmVjdGlvbiA9IGFhX2Jsb2F0X2FuZF9jb3ZlcmFnZS54eTsKCWZsb2F0IGlzX2xpbmVhcl9jb3ZlcmFnZSA9IGFhX2Jsb2F0X2FuZF9jb3ZlcmFnZS53OwoJZmxvYXQyIHBpeGVsbGVuZ3RoID0gaW52ZXJzZXNxcnQoZmxvYXQyKGRvdChza2V3Lnh6LCBza2V3Lnh6KSwgZG90KHNrZXcueXcsIHNrZXcueXcpKSk7CglmbG9hdDQgbm9ybWFsaXplZF9heGlzX2RpcnMgPSBza2V3ICogcGl4ZWxsZW5ndGgueHl4eTsKCWZsb2F0MiBheGlzd2lkdGhzID0gKGFicyhub3JtYWxpemVkX2F4aXNfZGlycy54eSkgKyBhYnMobm9ybWFsaXplZF9heGlzX2RpcnMuencpKTsKCWZsb2F0MiBhYV9ibG9hdHJhZGl1cyA9IGF4aXN3aWR0aHMgKiBwaXhlbGxlbmd0aCAqIC41OwoJZmxvYXQ0IHJhZGlpX2FuZF9uZWlnaGJvcnMgPSByYWRpaV9zZWxlY3RvciogZmxvYXQ0eDQocmFkaWlfeCwgcmFkaWlfeSwgcmFkaWlfeC55eHd6LCByYWRpaV95Lnd6eXgpOwoJZmxvYXQyIHJhZGlpID0gcmFkaWlfYW5kX25laWdoYm9ycy54eTsKCWZsb2F0MiBuZWlnaGJvcl9yYWRpaSA9IHJhZGlpX2FuZF9uZWlnaGJvcnMuenc7CglmbG9hdCBjb3ZlcmFnZV9tdWx0aXBsaWVyID0gMTsKCWlmIChhbnkoZ3JlYXRlclRoYW4oYWFfYmxvYXRyYWRpdXMsIGZsb2F0MigxKSkpKSAKCXsKCQljb3JuZXIgPSBtYXgoYWJzKGNvcm5lciksIGFhX2Jsb2F0cmFkaXVzKSAqIHNpZ24oY29ybmVyKTsKCQljb3ZlcmFnZV9tdWx0aXBsaWVyID0gMSAvIChtYXgoYWFfYmxvYXRyYWRpdXMueCwgMSkgKiBtYXgoYWFfYmxvYXRyYWRpdXMueSwgMSkpOwoJCXJhZGlpID0gZmxvYXQyKDApOwoJfQoJZmxvYXQgY292ZXJhZ2UgPSBhYV9ibG9hdF9hbmRfY292ZXJhZ2UuejsKCWlmIChhbnkobGVzc1RoYW4ocmFkaWksIGFhX2Jsb2F0cmFkaXVzICogMS41KSkpIAoJewoJCXJhZGlpID0gZmxvYXQyKDApOwoJCWFhX2Jsb2F0X2RpcmVjdGlvbiA9IHNpZ24oY29ybmVyKTsKCQlpZiAoY292ZXJhZ2UgPiAuNSkgCgkJewoJCQlhYV9ibG9hdF9kaXJlY3Rpb24gPSAtYWFfYmxvYXRfZGlyZWN0aW9uOwoJCX0KCQlpc19saW5lYXJfY292ZXJhZ2UgPSAxOwoJfQoJZWxzZSAKCXsKCQlyYWRpaSA9IGNsYW1wKHJhZGlpLCBwaXhlbGxlbmd0aCAqIDEuNSwgMiAtIHBpeGVsbGVuZ3RoICogMS41KTsKCQluZWlnaGJvcl9yYWRpaSA9IGNsYW1wKG5laWdoYm9yX3JhZGlpLCBwaXhlbGxlbmd0aCAqIDEuNSwgMiAtIHBpeGVsbGVuZ3RoICogMS41KTsKCQlmbG9hdDIgc3BhY2luZyA9IDIgLSByYWRpaSAtIG5laWdoYm9yX3JhZGlpOwoJCWZsb2F0MiBleHRyYV9wYWQgPSBtYXgocGl4ZWxsZW5ndGggKiAuMDYyNSAtIHNwYWNpbmcsIGZsb2F0MigwKSk7CgkJcmFkaWkgLT0gZXh0cmFfcGFkICogLjU7Cgl9CglmbG9hdDIgYWFfb3V0c2V0ID0gYWFfYmxvYXRfZGlyZWN0aW9uICogYWFfYmxvYXRyYWRpdXMgKiBhYV9ibG9hdF9tdWx0aXBsaWVyOwoJZmxvYXQyIHZlcnRleHBvcyA9IGNvcm5lciArIHJhZGl1c19vdXRzZXQgKiByYWRpaSArIGFhX291dHNldDsKCWlmIChjb3ZlcmFnZSA+IC41KSAKCXsKCQlpZiAoYWFfYmxvYXRfZGlyZWN0aW9uLnggIT0gMCAmJiB2ZXJ0ZXhwb3MueCAqIGNvcm5lci54IDwgMCkgCgkJewoJCQlmbG9hdCBiYWNrc2V0ID0gYWJzKHZlcnRleHBvcy54KTsKCQkJdmVydGV4cG9zLnggPSAwOwoJCQl2ZXJ0ZXhwb3MueSArPSBiYWNrc2V0ICogc2lnbihjb3JuZXIueSkgKiBwaXhlbGxlbmd0aC55L3BpeGVsbGVuZ3RoLng7CgkJCWNvdmVyYWdlID0gKGNvdmVyYWdlIC0gLjUpICogYWJzKGNvcm5lci54KSAvIChhYnMoY29ybmVyLngpICsgYmFja3NldCkgKyAuNTsKCQl9CgkJaWYgKGFhX2Jsb2F0X2RpcmVjdGlvbi55ICE9IDAgJiYgdmVydGV4cG9zLnkgKiBjb3JuZXIueSA8IDApIAoJCXsKCQkJZmxvYXQgYmFja3NldCA9IGFicyh2ZXJ0ZXhwb3MueSk7CgkJCXZlcnRleHBvcy55ID0gMDsKCQkJdmVydGV4cG9zLnggKz0gYmFja3NldCAqIHNpZ24oY29ybmVyLngpICogcGl4ZWxsZW5ndGgueC9waXhlbGxlbmd0aC55OwoJCQljb3ZlcmFnZSA9IChjb3ZlcmFnZSAtIC41KSAqIGFicyhjb3JuZXIueSkgLyAoYWJzKGNvcm5lci55KSArIGJhY2tzZXQpICsgLjU7CgkJfQoJfQoJZmxvYXQyeDIgc2tld21hdHJpeCA9IGZsb2F0MngyKHNrZXcueHksIHNrZXcuencpOwoJZmxvYXQyIGRldmNvb3JkID0gdmVydGV4cG9zICogc2tld21hdHJpeCArIHRyYW5zbGF0ZV9hbmRfbG9jYWxyb3RhdGUueHk7CglpZiAoMCAhPSBpc19saW5lYXJfY292ZXJhZ2UpIAoJewoJCXZhcmNjb29yZF9TMC54eSA9IGZsb2F0MigwLCBjb3ZlcmFnZSAqIGNvdmVyYWdlX211bHRpcGxpZXIpOwoJfQoJZWxzZSAKCXsKCQlmbG9hdDIgYXJjY29vcmQgPSAxIC0gYWJzKHJhZGl1c19vdXRzZXQpICsgYWFfb3V0c2V0L3JhZGlpICogY29ybmVyOwoJCXZhcmNjb29yZF9TMC54eSA9IGZsb2F0MihhcmNjb29yZC54KzEsIGFyY2Nvb3JkLnkpOwoJfQoJc2tfUG9zaXRpb24gPSBkZXZjb29yZC54eTAxOwp9CgEAAACbBAAAdW5pZm9ybSBmbG9hdDQgdWlubmVyUmVjdF9TMTsKdW5pZm9ybSBmbG9hdDIgdWludlJhZGlpWFlfUzE7CmZsYXQgaW4gaGFsZjQgdmNvbG9yX1MwOwppbiBmbG9hdDIgdmFyY2Nvb3JkX1MwOwpoYWxmNCBFbGxpcHRpY2FsUlJlY3RfUzEoaGFsZjQgX2lucHV0KSAKewoJZmxvYXQyIGR4eTAgPSB1aW5uZXJSZWN0X1MxLkxUIC0gc2tfRnJhZ0Nvb3JkLnh5OwoJZmxvYXQyIGR4eTEgPSBza19GcmFnQ29vcmQueHkgLSB1aW5uZXJSZWN0X1MxLlJCOwoJZmxvYXQyIGR4eSA9IG1heChtYXgoZHh5MCwgZHh5MSksIDAuMCk7CglmbG9hdDIgWiA9IGR4eSAqIHVpbnZSYWRpaVhZX1MxLnh5OwoJaGFsZiBpbXBsaWNpdCA9IGhhbGYoZG90KFosIGR4eSkgLSAxLjApOwoJaGFsZiBncmFkX2RvdCA9IGhhbGYoNC4wICogZG90KFosIFopKTsKCWdyYWRfZG90ID0gbWF4KGdyYWRfZG90LCAxLjBlLTQpOwoJaGFsZiBhcHByb3hfZGlzdCA9IGltcGxpY2l0ICogaGFsZihpbnZlcnNlc3FydChncmFkX2RvdCkpOwoJaGFsZiBhbHBoYSA9IGNsYW1wKDAuNSArIGFwcHJveF9kaXN0LCAwLjAsIDEuMCk7CglyZXR1cm4gX2lucHV0ICogYWxwaGE7Cn0Kdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIEZpbGxSUmVjdE9wOjpQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2Y29sb3JfUzA7CglmbG9hdCB4X3BsdXNfMT12YXJjY29vcmRfUzAueCwgeT12YXJjY29vcmRfUzAueTsKCWhhbGYgY292ZXJhZ2U7CglpZiAoMCA9PSB4X3BsdXNfMSkgCgl7CgkJY292ZXJhZ2UgPSBoYWxmKHkpOwoJfQoJZWxzZSAKCXsKCQlmbG9hdCBmbiA9IHhfcGx1c18xICogKHhfcGx1c18xIC0gMik7CgkJZm4gPSBmbWEoeSx5LCBmbik7CgkJZmxvYXQgZm53aWR0aCA9IGZ3aWR0aChmbik7CgkJY292ZXJhZ2UgPSAuNSAtIGhhbGYoZm4vZm53aWR0aCk7CgkJY292ZXJhZ2UgPSBjbGFtcChjb3ZlcmFnZSwgMCwgMSk7Cgl9CgloYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KGNvdmVyYWdlKTsKCWhhbGY0IG91dHB1dF9TMTsKCW91dHB1dF9TMSA9IEVsbGlwdGljYWxSUmVjdF9TMShvdXRwdXRDb3ZlcmFnZV9TMCk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRfUzE7Cgl9Cn0KAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAIAAAADgAAAHJhZGlpX3NlbGVjdG9yAAAZAAAAY29ybmVyX2FuZF9yYWRpdXNfb3V0c2V0cwAAABUAAABhYV9ibG9hdF9hbmRfY292ZXJhZ2UAAAAHAAAAcmFkaWlfeAAHAAAAcmFkaWlfeQAEAAAAc2tldxkAAAB0cmFuc2xhdGVfYW5kX2xvY2Fscm90YXRlAAAABQAAAGNvbG9yAAAAAAAAAA==","FAAQMYAAMAAAEADAAABAEYAAAICIAB5AABQAAAQAMAAAEATAAABAIIGAAEDCBYQCA4AAAAAAAA5AAAAAAABAAAAACAZAAAAA":"CgAAAExTS1PUCwAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0NCByYWRpaV9zZWxlY3RvcjsKaW4gZmxvYXQ0IGNvcm5lcl9hbmRfcmFkaXVzX291dHNldHM7CmluIGZsb2F0NCBhYV9ibG9hdF9hbmRfY292ZXJhZ2U7CmluIGZsb2F0NCByYWRpaV94OwppbiBmbG9hdDQgcmFkaWlfeTsKaW4gZmxvYXQ0IHNrZXc7CmluIGZsb2F0MiB0cmFuc2xhdGVfYW5kX2xvY2Fscm90YXRlOwppbiBoYWxmNCBjb2xvcjsKZmxhdCBvdXQgaGFsZjQgdmNvbG9yX1MwOwpvdXQgZmxvYXQyIHZhcmNjb29yZF9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgRmlsbFJSZWN0T3A6OlByb2Nlc3NvcgoJdmNvbG9yX1MwID0gY29sb3I7CglmbG9hdCBhYV9ibG9hdF9tdWx0aXBsaWVyID0gMTsKCWZsb2F0MiBjb3JuZXIgPSBjb3JuZXJfYW5kX3JhZGl1c19vdXRzZXRzLnh5OwoJZmxvYXQyIHJhZGl1c19vdXRzZXQgPSBjb3JuZXJfYW5kX3JhZGl1c19vdXRzZXRzLnp3OwoJZmxvYXQyIGFhX2Jsb2F0X2RpcmVjdGlvbiA9IGFhX2Jsb2F0X2FuZF9jb3ZlcmFnZS54eTsKCWZsb2F0IGlzX2xpbmVhcl9jb3ZlcmFnZSA9IGFhX2Jsb2F0X2FuZF9jb3ZlcmFnZS53OwoJZmxvYXQyIHBpeGVsbGVuZ3RoID0gaW52ZXJzZXNxcnQoZmxvYXQyKGRvdChza2V3Lnh6LCBza2V3Lnh6KSwgZG90KHNrZXcueXcsIHNrZXcueXcpKSk7CglmbG9hdDQgbm9ybWFsaXplZF9heGlzX2RpcnMgPSBza2V3ICogcGl4ZWxsZW5ndGgueHl4eTsKCWZsb2F0MiBheGlzd2lkdGhzID0gKGFicyhub3JtYWxpemVkX2F4aXNfZGlycy54eSkgKyBhYnMobm9ybWFsaXplZF9heGlzX2RpcnMuencpKTsKCWZsb2F0MiBhYV9ibG9hdHJhZGl1cyA9IGF4aXN3aWR0aHMgKiBwaXhlbGxlbmd0aCAqIC41OwoJZmxvYXQ0IHJhZGlpX2FuZF9uZWlnaGJvcnMgPSByYWRpaV9zZWxlY3RvciogZmxvYXQ0eDQocmFkaWlfeCwgcmFkaWlfeSwgcmFkaWlfeC55eHd6LCByYWRpaV95Lnd6eXgpOwoJZmxvYXQyIHJhZGlpID0gcmFkaWlfYW5kX25laWdoYm9ycy54eTsKCWZsb2F0MiBuZWlnaGJvcl9yYWRpaSA9IHJhZGlpX2FuZF9uZWlnaGJvcnMuenc7CglmbG9hdCBjb3ZlcmFnZV9tdWx0aXBsaWVyID0gMTsKCWlmIChhbnkoZ3JlYXRlclRoYW4oYWFfYmxvYXRyYWRpdXMsIGZsb2F0MigxKSkpKSAKCXsKCQljb3JuZXIgPSBtYXgoYWJzKGNvcm5lciksIGFhX2Jsb2F0cmFkaXVzKSAqIHNpZ24oY29ybmVyKTsKCQljb3ZlcmFnZV9tdWx0aXBsaWVyID0gMSAvIChtYXgoYWFfYmxvYXRyYWRpdXMueCwgMSkgKiBtYXgoYWFfYmxvYXRyYWRpdXMueSwgMSkpOwoJCXJhZGlpID0gZmxvYXQyKDApOwoJfQoJZmxvYXQgY292ZXJhZ2UgPSBhYV9ibG9hdF9hbmRfY292ZXJhZ2UuejsKCWlmIChhbnkobGVzc1RoYW4ocmFkaWksIGFhX2Jsb2F0cmFkaXVzICogMS41KSkpIAoJewoJCXJhZGlpID0gZmxvYXQyKDApOwoJCWFhX2Jsb2F0X2RpcmVjdGlvbiA9IHNpZ24oY29ybmVyKTsKCQlpZiAoY292ZXJhZ2UgPiAuNSkgCgkJewoJCQlhYV9ibG9hdF9kaXJlY3Rpb24gPSAtYWFfYmxvYXRfZGlyZWN0aW9uOwoJCX0KCQlpc19saW5lYXJfY292ZXJhZ2UgPSAxOwoJfQoJZWxzZSAKCXsKCQlyYWRpaSA9IGNsYW1wKHJhZGlpLCBwaXhlbGxlbmd0aCAqIDEuNSwgMiAtIHBpeGVsbGVuZ3RoICogMS41KTsKCQluZWlnaGJvcl9yYWRpaSA9IGNsYW1wKG5laWdoYm9yX3JhZGlpLCBwaXhlbGxlbmd0aCAqIDEuNSwgMiAtIHBpeGVsbGVuZ3RoICogMS41KTsKCQlmbG9hdDIgc3BhY2luZyA9IDIgLSByYWRpaSAtIG5laWdoYm9yX3JhZGlpOwoJCWZsb2F0MiBleHRyYV9wYWQgPSBtYXgocGl4ZWxsZW5ndGggKiAuMDYyNSAtIHNwYWNpbmcsIGZsb2F0MigwKSk7CgkJcmFkaWkgLT0gZXh0cmFfcGFkICogLjU7Cgl9CglmbG9hdDIgYWFfb3V0c2V0ID0gYWFfYmxvYXRfZGlyZWN0aW9uICogYWFfYmxvYXRyYWRpdXMgKiBhYV9ibG9hdF9tdWx0aXBsaWVyOwoJZmxvYXQyIHZlcnRleHBvcyA9IGNvcm5lciArIHJhZGl1c19vdXRzZXQgKiByYWRpaSArIGFhX291dHNldDsKCWlmIChjb3ZlcmFnZSA+IC41KSAKCXsKCQlpZiAoYWFfYmxvYXRfZGlyZWN0aW9uLnggIT0gMCAmJiB2ZXJ0ZXhwb3MueCAqIGNvcm5lci54IDwgMCkgCgkJewoJCQlmbG9hdCBiYWNrc2V0ID0gYWJzKHZlcnRleHBvcy54KTsKCQkJdmVydGV4cG9zLnggPSAwOwoJCQl2ZXJ0ZXhwb3MueSArPSBiYWNrc2V0ICogc2lnbihjb3JuZXIueSkgKiBwaXhlbGxlbmd0aC55L3BpeGVsbGVuZ3RoLng7CgkJCWNvdmVyYWdlID0gKGNvdmVyYWdlIC0gLjUpICogYWJzKGNvcm5lci54KSAvIChhYnMoY29ybmVyLngpICsgYmFja3NldCkgKyAuNTsKCQl9CgkJaWYgKGFhX2Jsb2F0X2RpcmVjdGlvbi55ICE9IDAgJiYgdmVydGV4cG9zLnkgKiBjb3JuZXIueSA8IDApIAoJCXsKCQkJZmxvYXQgYmFja3NldCA9IGFicyh2ZXJ0ZXhwb3MueSk7CgkJCXZlcnRleHBvcy55ID0gMDsKCQkJdmVydGV4cG9zLnggKz0gYmFja3NldCAqIHNpZ24oY29ybmVyLngpICogcGl4ZWxsZW5ndGgueC9waXhlbGxlbmd0aC55OwoJCQljb3ZlcmFnZSA9IChjb3ZlcmFnZSAtIC41KSAqIGFicyhjb3JuZXIueSkgLyAoYWJzKGNvcm5lci55KSArIGJhY2tzZXQpICsgLjU7CgkJfQoJfQoJZmxvYXQyeDIgc2tld21hdHJpeCA9IGZsb2F0MngyKHNrZXcueHksIHNrZXcuencpOwoJZmxvYXQyIGRldmNvb3JkID0gdmVydGV4cG9zICogc2tld21hdHJpeCArIHRyYW5zbGF0ZV9hbmRfbG9jYWxyb3RhdGUueHk7CglpZiAoMCAhPSBpc19saW5lYXJfY292ZXJhZ2UpIAoJewoJCXZhcmNjb29yZF9TMC54eSA9IGZsb2F0MigwLCBjb3ZlcmFnZSAqIGNvdmVyYWdlX211bHRpcGxpZXIpOwoJfQoJZWxzZSAKCXsKCQlmbG9hdDIgYXJjY29vcmQgPSAxIC0gYWJzKHJhZGl1c19vdXRzZXQpICsgYWFfb3V0c2V0L3JhZGlpICogY29ybmVyOwoJCXZhcmNjb29yZF9TMC54eSA9IGZsb2F0MihhcmNjb29yZC54KzEsIGFyY2Nvb3JkLnkpOwoJfQoJc2tfUG9zaXRpb24gPSBkZXZjb29yZC54eTAxOwp9CgAAAABFAgAAZmxhdCBpbiBoYWxmNCB2Y29sb3JfUzA7CmluIGZsb2F0MiB2YXJjY29vcmRfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBGaWxsUlJlY3RPcDo6UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdmNvbG9yX1MwOwoJZmxvYXQgeF9wbHVzXzE9dmFyY2Nvb3JkX1MwLngsIHk9dmFyY2Nvb3JkX1MwLnk7CgloYWxmIGNvdmVyYWdlOwoJaWYgKDAgPT0geF9wbHVzXzEpIAoJewoJCWNvdmVyYWdlID0gaGFsZih5KTsKCX0KCWVsc2UgCgl7CgkJZmxvYXQgZm4gPSB4X3BsdXNfMSAqICh4X3BsdXNfMSAtIDIpOwoJCWZuID0gZm1hKHkseSwgZm4pOwoJCWZsb2F0IGZud2lkdGggPSBmd2lkdGgoZm4pOwoJCWNvdmVyYWdlID0gLjUgLSBoYWxmKGZuL2Zud2lkdGgpOwoJCWNvdmVyYWdlID0gY2xhbXAoY292ZXJhZ2UsIDAsIDEpOwoJfQoJaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNChjb3ZlcmFnZSk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRDb3ZlcmFnZV9TMDsKCX0KfQoAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAACAAAAA4AAAByYWRpaV9zZWxlY3RvcgAAGQAAAGNvcm5lcl9hbmRfcmFkaXVzX291dHNldHMAAAAVAAAAYWFfYmxvYXRfYW5kX2NvdmVyYWdlAAAABwAAAHJhZGlpX3gABwAAAHJhZGlpX3kABAAAAHNrZXcZAAAAdHJhbnNsYXRlX2FuZF9sb2NhbHJvdGF0ZQAAAAUAAABjb2xvcgAAAAAAAAA=","AYAA5AADQAAAOAEARAFQJAABBADIB7777777777777777777777767YAAAAAAAAAAAAOQAAAAAAAQAAAABAMQAAAAA":"CgAAAExTS1OCAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBpblBvc2l0aW9uOwppbiBoYWxmNCBpbkNvbG9yOwppbiBmbG9hdDQgaW5DaXJjbGVFZGdlOwpvdXQgZmxvYXQ0IHZpbkNpcmNsZUVkZ2VfUzA7Cm91dCBoYWxmNCB2aW5Db2xvcl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgQ2lyY2xlR2VvbWV0cnlQcm9jZXNzb3IKCXZpbkNpcmNsZUVkZ2VfUzAgPSBpbkNpcmNsZUVkZ2U7Cgl2aW5Db2xvcl9TMCA9IGluQ29sb3I7CglmbG9hdDIgX3RtcF8wX2luUG9zaXRpb24gPSBpblBvc2l0aW9uOwoJZmxvYXQyIF90bXBfMl9pblBvc2l0aW9uID0gaW5Qb3NpdGlvbjsKCXNrX1Bvc2l0aW9uID0gX3RtcF8wX2luUG9zaXRpb24ueHkwMTsKfQoAAAAAAADqAQAAaW4gZmxvYXQ0IHZpbkNpcmNsZUVkZ2VfUzA7CmluIGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgQ2lyY2xlR2VvbWV0cnlQcm9jZXNzb3IKCWZsb2F0NCBjaXJjbGVFZGdlOwoJY2lyY2xlRWRnZSA9IHZpbkNpcmNsZUVkZ2VfUzA7CgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdmluQ29sb3JfUzA7CglmbG9hdCBkID0gbGVuZ3RoKGNpcmNsZUVkZ2UueHkpOwoJaGFsZiBkaXN0YW5jZVRvT3V0ZXJFZGdlID0gaGFsZihjaXJjbGVFZGdlLnogKiAoMS4wIC0gZCkpOwoJaGFsZiBlZGdlQWxwaGEgPSBzYXR1cmF0ZShkaXN0YW5jZVRvT3V0ZXJFZGdlKTsKCWhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoZWRnZUFscGhhKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAKAAAAaW5Qb3NpdGlvbgAABwAAAGluQ29sb3IADAAAAGluQ2lyY2xlRWRnZQAAAAA=","CMRQCIAABBYAAAEIXBAAACDQMAABRAFAAAAAAAAAAAAAAAEABYAAAAEAAAAAAAEEBQAAAAA":"CgAAAExTS1MyAgAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQ0IHVsb2NhbE1hdHJpeF9TMDsKaW4gZmxvYXQyIGluUG9zaXRpb247CmluIGhhbGY0IGluQ29sb3I7CmluIGZsb2F0MiBpbkVsbGlwc2VPZmZzZXQ7CmluIGZsb2F0NCBpbkVsbGlwc2VSYWRpaTsKb3V0IGZsb2F0MiB2RWxsaXBzZU9mZnNldHNfUzA7Cm91dCBmbG9hdDQgdkVsbGlwc2VSYWRpaV9TMDsKb3V0IGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBFbGxpcHNlR2VvbWV0cnlQcm9jZXNzb3IKCXZFbGxpcHNlT2Zmc2V0c19TMCA9IGluRWxsaXBzZU9mZnNldDsKCXZFbGxpcHNlUmFkaWlfUzAgPSBpbkVsbGlwc2VSYWRpaTsKCXZpbkNvbG9yX1MwID0gaW5Db2xvcjsKCWZsb2F0MiBfdG1wXzBfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247CglmbG9hdDIgX3RtcF8xX2luUG9zaXRpb24gPSB1bG9jYWxNYXRyaXhfUzAueHogKiBpblBvc2l0aW9uICsgdWxvY2FsTWF0cml4X1MwLnl3OwoJc2tfUG9zaXRpb24gPSBfdG1wXzBfaW5Qb3NpdGlvbi54eTAxOwp9CgAAAAAAAHIDAABpbiBmbG9hdDIgdkVsbGlwc2VPZmZzZXRzX1MwOwppbiBmbG9hdDQgdkVsbGlwc2VSYWRpaV9TMDsKaW4gaGFsZjQgdmluQ29sb3JfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBFbGxpcHNlR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2aW5Db2xvcl9TMDsKCWZsb2F0MiBvZmZzZXQgPSB2RWxsaXBzZU9mZnNldHNfUzAueHk7CglvZmZzZXQgKj0gdkVsbGlwc2VSYWRpaV9TMC54eTsKCWZsb2F0IHRlc3QgPSBkb3Qob2Zmc2V0LCBvZmZzZXQpIC0gMS4wOwoJZmxvYXQyIGdyYWQgPSAyLjAqb2Zmc2V0KnZFbGxpcHNlUmFkaWlfUzAueHk7CglmbG9hdCBncmFkX2RvdCA9IGRvdChncmFkLCBncmFkKTsKCWdyYWRfZG90ID0gbWF4KGdyYWRfZG90LCAxLjE3NTVlLTM4KTsKCWZsb2F0IGludmxlbiA9IGludmVyc2VzcXJ0KGdyYWRfZG90KTsKCWZsb2F0IGVkZ2VBbHBoYSA9IHNhdHVyYXRlKDAuNS10ZXN0Kmludmxlbik7CglvZmZzZXQgPSB2RWxsaXBzZU9mZnNldHNfUzAueHkqdkVsbGlwc2VSYWRpaV9TMC56dzsKCXRlc3QgPSBkb3Qob2Zmc2V0LCBvZmZzZXQpIC0gMS4wOwoJZ3JhZCA9IDIuMCpvZmZzZXQqdkVsbGlwc2VSYWRpaV9TMC56dzsKCWdyYWRfZG90ID0gZG90KGdyYWQsIGdyYWQpOwoJaW52bGVuID0gaW52ZXJzZXNxcnQoZ3JhZF9kb3QpOwoJZWRnZUFscGhhICo9IHNhdHVyYXRlKDAuNSt0ZXN0Kmludmxlbik7CgloYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KGhhbGYoZWRnZUFscGhhKSk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRDb3ZlcmFnZV9TMDsKCX0KfQoAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAEAAAACgAAAGluUG9zaXRpb24AAAcAAABpbkNvbG9yAA8AAABpbkVsbGlwc2VPZmZzZXQADgAAAGluRWxsaXBzZVJhZGlpAAAAAAAA","AYQA5AADQAAAOAEARAFQJAABBADIB7777777777777777777777767YAAAAAAAAAAAAOQAAAAAAAQAAAABAMQAAAAA":"CgAAAExTS1PMAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQ0IHVsb2NhbE1hdHJpeF9TMDsKaW4gZmxvYXQyIGluUG9zaXRpb247CmluIGhhbGY0IGluQ29sb3I7CmluIGZsb2F0NCBpbkNpcmNsZUVkZ2U7Cm91dCBmbG9hdDQgdmluQ2lyY2xlRWRnZV9TMDsKb3V0IGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBDaXJjbGVHZW9tZXRyeVByb2Nlc3NvcgoJdmluQ2lyY2xlRWRnZV9TMCA9IGluQ2lyY2xlRWRnZTsKCXZpbkNvbG9yX1MwID0gaW5Db2xvcjsKCWZsb2F0MiBfdG1wXzBfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247CglmbG9hdDIgX3RtcF8xX2luUG9zaXRpb24gPSB1bG9jYWxNYXRyaXhfUzAueHogKiBpblBvc2l0aW9uICsgdWxvY2FsTWF0cml4X1MwLnl3OwoJc2tfUG9zaXRpb24gPSBfdG1wXzBfaW5Qb3NpdGlvbi54eTAxOwp9CgAAAADqAQAAaW4gZmxvYXQ0IHZpbkNpcmNsZUVkZ2VfUzA7CmluIGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgQ2lyY2xlR2VvbWV0cnlQcm9jZXNzb3IKCWZsb2F0NCBjaXJjbGVFZGdlOwoJY2lyY2xlRWRnZSA9IHZpbkNpcmNsZUVkZ2VfUzA7CgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdmluQ29sb3JfUzA7CglmbG9hdCBkID0gbGVuZ3RoKGNpcmNsZUVkZ2UueHkpOwoJaGFsZiBkaXN0YW5jZVRvT3V0ZXJFZGdlID0gaGFsZihjaXJjbGVFZGdlLnogKiAoMS4wIC0gZCkpOwoJaGFsZiBlZGdlQWxwaGEgPSBzYXR1cmF0ZShkaXN0YW5jZVRvT3V0ZXJFZGdlKTsKCWhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoZWRnZUFscGhhKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAKAAAAaW5Qb3NpdGlvbgAABwAAAGluQ29sb3IADAAAAGluQ2lyY2xlRWRnZQAAAAA=","HVJAAAAAABIAAGAAAQ4AAAH477776R24EAAAIOBQAD6P7777777777YDAAAAABAAAAAABBAMADSAB4QAAAAAEAAAAAAHIAAAAAAAIAAAAAQGIAAAAAAA":"CgAAAExTS1MjAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gaGFsZjQgY29sb3I7CmluIGZsb2F0MiBsb2NhbENvb3JkOwpmbGF0IG91dCBoYWxmNCB2Y29sb3JfUzA7Cm91dCBmbG9hdDIgdmxvY2FsQ29vcmRfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJdmNvbG9yX1MwID0gY29sb3I7Cgl2bG9jYWxDb29yZF9TMCA9IGxvY2FsQ29vcmQ7Cglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cn0KAAEAAABfAwAAdW5pZm9ybSBmbG9hdDQgdWlubmVyUmVjdF9TMTsKdW5pZm9ybSBoYWxmMiB1cmFkaXVzUGx1c0hhbGZfUzE7CnVuaWZvcm0gc2FtcGxlcjJEIHVUZXh0dXJlU2FtcGxlcl8wX1MwOwpmbGF0IGluIGhhbGY0IHZjb2xvcl9TMDsKaW4gZmxvYXQyIHZsb2NhbENvb3JkX1MwOwpoYWxmNCBDaXJjdWxhclJSZWN0X1MxKGhhbGY0IF9pbnB1dCkgCnsKCWZsb2F0MiBkeHkwID0gdWlubmVyUmVjdF9TMS5MVCAtIHNrX0ZyYWdDb29yZC54eTsKCWZsb2F0MiBkeHkxID0gc2tfRnJhZ0Nvb3JkLnh5IC0gdWlubmVyUmVjdF9TMS5SQjsKCWZsb2F0MiBkeHkgPSBtYXgobWF4KGR4eTAsIGR4eTEpLCAwLjApOwoJaGFsZiBhbHBoYSA9IGhhbGYoc2F0dXJhdGUodXJhZGl1c1BsdXNIYWxmX1MxLnggLSBsZW5ndGgoZHh5KSkpOwoJcmV0dXJuIF9pbnB1dCAqIGFscGhhOwp9CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBRdWFkUGVyRWRnZUFBR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2Y29sb3JfUzA7CglmbG9hdDIgdGV4Q29vcmQ7Cgl0ZXhDb29yZCA9IHZsb2NhbENvb3JkX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSAoKHNhbXBsZSh1VGV4dHVyZVNhbXBsZXJfMF9TMCwgdGV4Q29vcmQpICogb3V0cHV0Q29sb3JfUzApKTsKCWNvbnN0IGhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoMSk7CgloYWxmNCBvdXRwdXRfUzE7CglvdXRwdXRfUzEgPSBDaXJjdWxhclJSZWN0X1MxKG91dHB1dENvdmVyYWdlX1MwKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dF9TMTsKCX0KfQoAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAIAAAAcG9zaXRpb24FAAAAY29sb3IAAAAKAAAAbG9jYWxDb29yZAAAAAAAAA==","AYQA5AADQAAAOAEARAFQJAABBADIB7777777777777777777777767YAAAAAAAAAACAAYQADAAAEAFEURUKQKAAAYAAAAAAAAIAAAABSCICWKY2FAEAAAMAAAAAAAAAAAAAIADQAAAAIAAAAAAAIIDAAAA":"CgAAAExTS1PMAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQ0IHVsb2NhbE1hdHJpeF9TMDsKaW4gZmxvYXQyIGluUG9zaXRpb247CmluIGhhbGY0IGluQ29sb3I7CmluIGZsb2F0NCBpbkNpcmNsZUVkZ2U7Cm91dCBmbG9hdDQgdmluQ2lyY2xlRWRnZV9TMDsKb3V0IGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBDaXJjbGVHZW9tZXRyeVByb2Nlc3NvcgoJdmluQ2lyY2xlRWRnZV9TMCA9IGluQ2lyY2xlRWRnZTsKCXZpbkNvbG9yX1MwID0gaW5Db2xvcjsKCWZsb2F0MiBfdG1wXzBfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247CglmbG9hdDIgX3RtcF8xX2luUG9zaXRpb24gPSB1bG9jYWxNYXRyaXhfUzAueHogKiBpblBvc2l0aW9uICsgdWxvY2FsTWF0cml4X1MwLnl3OwoJc2tfUG9zaXRpb24gPSBfdG1wXzBfaW5Qb3NpdGlvbi54eTAxOwp9CgEAAAB+BQAAY29uc3QgaW50IGtGaWxsQldfUzFfYzAgPSAwOwpjb25zdCBpbnQga0ludmVyc2VGaWxsQldfUzFfYzAgPSAyOwpjb25zdCBpbnQga0ludmVyc2VGaWxsQUFfUzFfYzAgPSAzOwp1bmlmb3JtIGZsb2F0NCB1cmVjdFVuaWZvcm1fUzFfYzA7CmluIGZsb2F0NCB2aW5DaXJjbGVFZGdlX1MwOwppbiBoYWxmNCB2aW5Db2xvcl9TMDsKaGFsZjQgUmVjdF9TMV9jMChoYWxmNCBfaW5wdXQpIAp7CgloYWxmNCBfdG1wXzBfaW5Db2xvciA9IF9pbnB1dDsKCWhhbGYgY292ZXJhZ2U7CglpZiAoaW50KDEpID09IGtGaWxsQldfUzFfYzAgfHwgaW50KDEpID09IGtJbnZlcnNlRmlsbEJXX1MxX2MwKSAKCXsKCQljb3ZlcmFnZSA9IGhhbGYoYWxsKGdyZWF0ZXJUaGFuKGZsb2F0NChza19GcmFnQ29vcmQueHksIHVyZWN0VW5pZm9ybV9TMV9jMC56dyksIGZsb2F0NCh1cmVjdFVuaWZvcm1fUzFfYzAueHksIHNrX0ZyYWdDb29yZC54eSkpKSk7Cgl9CgllbHNlIAoJewoJCWhhbGY0IGRpc3RzNCA9IHNhdHVyYXRlKGhhbGY0KDEuMCwgMS4wLCAtMS4wLCAtMS4wKSAqIGhhbGY0KHNrX0ZyYWdDb29yZC54eXh5IC0gdXJlY3RVbmlmb3JtX1MxX2MwKSk7CgkJaGFsZjIgZGlzdHMyID0gKGRpc3RzNC54eSArIGRpc3RzNC56dykgLSAxLjA7CgkJY292ZXJhZ2UgPSBkaXN0czIueCAqIGRpc3RzMi55OwoJfQoJaWYgKGludCgxKSA9PSBrSW52ZXJzZUZpbGxCV19TMV9jMCB8fCBpbnQoMSkgPT0ga0ludmVyc2VGaWxsQUFfUzFfYzApIAoJewoJCWNvdmVyYWdlID0gMS4wIC0gY292ZXJhZ2U7Cgl9CglyZXR1cm4gaGFsZjQoaGFsZjQoY292ZXJhZ2UpKTsKfQpoYWxmNCBCbGVuZF9TMShoYWxmNCBfc3JjLCBoYWxmNCBfZHN0KSAKewoJcmV0dXJuIGJsZW5kX21vZHVsYXRlKFJlY3RfUzFfYzAoX3NyYyksIF9zcmMpOwp9CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBDaXJjbGVHZW9tZXRyeVByb2Nlc3NvcgoJZmxvYXQ0IGNpcmNsZUVkZ2U7CgljaXJjbGVFZGdlID0gdmluQ2lyY2xlRWRnZV9TMDsKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2aW5Db2xvcl9TMDsKCWZsb2F0IGQgPSBsZW5ndGgoY2lyY2xlRWRnZS54eSk7CgloYWxmIGRpc3RhbmNlVG9PdXRlckVkZ2UgPSBoYWxmKGNpcmNsZUVkZ2UueiAqICgxLjAgLSBkKSk7CgloYWxmIGVkZ2VBbHBoYSA9IHNhdHVyYXRlKGRpc3RhbmNlVG9PdXRlckVkZ2UpOwoJaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNChlZGdlQWxwaGEpOwoJaGFsZjQgb3V0cHV0X1MxOwoJb3V0cHV0X1MxID0gQmxlbmRfUzEob3V0cHV0Q292ZXJhZ2VfUzAsIGhhbGY0KDEpKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dF9TMTsKCX0KfQoAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAADAAAACgAAAGluUG9zaXRpb24AAAcAAABpbkNvbG9yAAwAAABpbkNpcmNsZUVkZ2UAAAAA","HUIAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAAAAAALUAQAAEAQAAAAGQCBAMQAAAIAAAAAACQAGAAAAAQAAAAAAAQQGAAAAA":"CgAAAExTS1M2AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBmbG9hdDIgbG9jYWxDb29yZDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cgl7CgkJdlRyYW5zZm9ybWVkQ29vcmRzXzJfUzAgPSBmbG9hdDN4Mih1bWF0cml4X1MxKSAqIGxvY2FsQ29vcmQueHkxOwoJfQp9CgAAAAAAAHADAAB1bmlmb3JtIGZsb2F0NCB1Y2xhbXBfUzFfYzA7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKdW5pZm9ybSBzYW1wbGVyMkQgdVRleHR1cmVTYW1wbGVyXzBfUzE7CmluIGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKaGFsZjQgVGV4dHVyZUVmZmVjdF9TMV9jMChoYWxmNCBfaW5wdXQpIAp7CglmbG9hdDIgaW5Db29yZCA9IHZUcmFuc2Zvcm1lZENvb3Jkc18yX1MwOwoJZmxvYXQyIHN1YnNldENvb3JkOwoJc3Vic2V0Q29vcmQueCA9IGluQ29vcmQueDsKCXN1YnNldENvb3JkLnkgPSBpbkNvb3JkLnk7CglmbG9hdDIgY2xhbXBlZENvb3JkOwoJY2xhbXBlZENvb3JkLnggPSBzdWJzZXRDb29yZC54OwoJY2xhbXBlZENvb3JkLnkgPSBjbGFtcChzdWJzZXRDb29yZC55LCB1Y2xhbXBfUzFfYzAueSwgdWNsYW1wX1MxX2MwLncpOwoJaGFsZjQgdGV4dHVyZUNvbG9yID0gc2FtcGxlKHVUZXh0dXJlU2FtcGxlcl8wX1MxLCBjbGFtcGVkQ29vcmQpOwoJcmV0dXJuIHRleHR1cmVDb2xvcjsKfQpoYWxmNCBNYXRyaXhFZmZlY3RfUzEoaGFsZjQgX2lucHV0KSAKewoJcmV0dXJuIFRleHR1cmVFZmZlY3RfUzFfYzAoX2lucHV0KTsKfQp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMCA9IGhhbGY0KDEpOwoJY29uc3QgaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNCgxKTsKCWhhbGY0IG91dHB1dF9TMTsKCW91dHB1dF9TMSA9IE1hdHJpeEVmZmVjdF9TMShvdXRwdXRDb2xvcl9TMCk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0X1MxICogb3V0cHV0Q292ZXJhZ2VfUzA7Cgl9Cn0KAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAIAAAAcG9zaXRpb24KAAAAbG9jYWxDb29yZAAAAAAAAA==","HUJAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAQAAAAAAQQGABZAA6IAAAAACAAAAAADUAAAAAAAEAAAAAIDEAAAAAAA":"CgAAAExTS1PlAAAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gZmxvYXQyIGxvY2FsQ29vcmQ7Cm91dCBmbG9hdDIgdmxvY2FsQ29vcmRfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJdmxvY2FsQ29vcmRfUzAgPSBsb2NhbENvb3JkOwoJc2tfUG9zaXRpb24gPSBwb3NpdGlvbi54eTAxOwp9CgAAAAEAAAAuAwAAdW5pZm9ybSBmbG9hdDQgdWlubmVyUmVjdF9TMTsKdW5pZm9ybSBoYWxmMiB1cmFkaXVzUGx1c0hhbGZfUzE7CnVuaWZvcm0gc2FtcGxlcjJEIHVUZXh0dXJlU2FtcGxlcl8wX1MwOwppbiBmbG9hdDIgdmxvY2FsQ29vcmRfUzA7CmhhbGY0IENpcmN1bGFyUlJlY3RfUzEoaGFsZjQgX2lucHV0KSAKewoJZmxvYXQyIGR4eTAgPSB1aW5uZXJSZWN0X1MxLkxUIC0gc2tfRnJhZ0Nvb3JkLnh5OwoJZmxvYXQyIGR4eTEgPSBza19GcmFnQ29vcmQueHkgLSB1aW5uZXJSZWN0X1MxLlJCOwoJZmxvYXQyIGR4eSA9IG1heChtYXgoZHh5MCwgZHh5MSksIDAuMCk7CgloYWxmIGFscGhhID0gaGFsZihzYXR1cmF0ZSh1cmFkaXVzUGx1c0hhbGZfUzEueCAtIGxlbmd0aChkeHkpKSk7CglyZXR1cm4gX2lucHV0ICogYWxwaGE7Cn0Kdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJaGFsZjQgb3V0cHV0Q29sb3JfUzAgPSBoYWxmNCgxKTsKCWZsb2F0MiB0ZXhDb29yZDsKCXRleENvb3JkID0gdmxvY2FsQ29vcmRfUzA7CglvdXRwdXRDb2xvcl9TMCA9ICgoc2FtcGxlKHVUZXh0dXJlU2FtcGxlcl8wX1MwLCB0ZXhDb29yZCkgKiBoYWxmNCgxKSkpOwoJY29uc3QgaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNCgxKTsKCWhhbGY0IG91dHB1dF9TMTsKCW91dHB1dF9TMSA9IENpcmN1bGFyUlJlY3RfUzEob3V0cHV0Q292ZXJhZ2VfUzApOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dENvbG9yX1MwICogb3V0cHV0X1MxOwoJfQp9CgAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAIAAAAcG9zaXRpb24KAAAAbG9jYWxDb29yZAAAAAAAAA==","HUJAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAQAAAAAAQQGAAZAADIAAAACU53QJEKAAAAAAMAAAAAIAAAAAAGIRDFB2XASAUAABQAAAAAAAAAAAAADUAAAAAAAEAAAAAIDEAAA":"CgAAAExTS1PlAAAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gZmxvYXQyIGxvY2FsQ29vcmQ7Cm91dCBmbG9hdDIgdmxvY2FsQ29vcmRfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJdmxvY2FsQ29vcmRfUzAgPSBsb2NhbENvb3JkOwoJc2tfUG9zaXRpb24gPSBwb3NpdGlvbi54eTAxOwp9CgAAAAEAAACrBAAAY29uc3QgaW50IGtGaWxsQUFfUzFfYzAgPSAxOwpjb25zdCBpbnQga0ludmVyc2VGaWxsQldfUzFfYzAgPSAyOwpjb25zdCBpbnQga0ludmVyc2VGaWxsQUFfUzFfYzAgPSAzOwp1bmlmb3JtIGZsb2F0NCB1Y2lyY2xlX1MxX2MwOwp1bmlmb3JtIHNhbXBsZXIyRCB1VGV4dHVyZVNhbXBsZXJfMF9TMDsKaW4gZmxvYXQyIHZsb2NhbENvb3JkX1MwOwpoYWxmNCBDaXJjbGVfUzFfYzAoaGFsZjQgX2lucHV0KSAKewoJaGFsZjQgX3RtcF8wX2luQ29sb3IgPSBfaW5wdXQ7CgloYWxmIGQ7CglpZiAoaW50KDEpID09IGtJbnZlcnNlRmlsbEJXX1MxX2MwIHx8IGludCgxKSA9PSBrSW52ZXJzZUZpbGxBQV9TMV9jMCkgCgl7CgkJZCA9IGhhbGYoKGxlbmd0aCgodWNpcmNsZV9TMV9jMC54eSAtIHNrX0ZyYWdDb29yZC54eSkgKiB1Y2lyY2xlX1MxX2MwLncpIC0gMS4wKSAqIHVjaXJjbGVfUzFfYzAueik7Cgl9CgllbHNlIAoJewoJCWQgPSBoYWxmKCgxLjAgLSBsZW5ndGgoKHVjaXJjbGVfUzFfYzAueHkgLSBza19GcmFnQ29vcmQueHkpICogdWNpcmNsZV9TMV9jMC53KSkgKiB1Y2lyY2xlX1MxX2MwLnopOwoJfQoJcmV0dXJuIGhhbGY0KGhhbGY0KGludCgxKSA9PSBrRmlsbEFBX1MxX2MwIHx8IGludCgxKSA9PSBrSW52ZXJzZUZpbGxBQV9TMV9jMCA/IHNhdHVyYXRlKGQpIDogaGFsZihkID4gMC41ID8gMSA6IDApKSk7Cn0KaGFsZjQgQmxlbmRfUzEoaGFsZjQgX3NyYywgaGFsZjQgX2RzdCkgCnsKCXJldHVybiBibGVuZF9tb2R1bGF0ZShfc3JjLCBDaXJjbGVfUzFfYzAoX3NyYykpOwp9CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBRdWFkUGVyRWRnZUFBR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwID0gaGFsZjQoMSk7CglmbG9hdDIgdGV4Q29vcmQ7Cgl0ZXhDb29yZCA9IHZsb2NhbENvb3JkX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSAoKHNhbXBsZSh1VGV4dHVyZVNhbXBsZXJfMF9TMCwgdGV4Q29vcmQpICogaGFsZjQoMSkpKTsKCWNvbnN0IGhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoMSk7CgloYWxmNCBvdXRwdXRfUzE7CglvdXRwdXRfUzEgPSBCbGVuZF9TMShvdXRwdXRDb3ZlcmFnZV9TMCwgaGFsZjQoMSkpOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dENvbG9yX1MwICogb3V0cHV0X1MxOwoJfQp9CgABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAgAAABwb3NpdGlvbgoAAABsb2NhbENvb3JkAAAAAAAA","HVIAAAAAABIAAGAAAQ4AAAH477776R24EAAAIOBQAD6P7777777777YDAAAAAAAAAAAFIBQU7BTXIAAAAAACAWXW3ZEQAAAADAAAAAGATHIBICYCAAAEBP2LBIPAAAAAIAAAAAEARRALJ3F5SMAAAABQAAAABABTUEURMBAAACAH5FYUHQAAAAAAAEAAAAAZ4RGGRCQFAEAAAAAAAAAGARP2LVJPAAAAAAAAEAAAABSKRXZFAUHQAAAAAAAAAACAA4AAAACAAAAAAACCAYAA":"CgAAAExTS1OAAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMV9jMF9jMTsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBoYWxmNCBjb2xvcjsKaW4gZmxvYXQyIGxvY2FsQ29vcmQ7CmZsYXQgb3V0IGhhbGY0IHZjb2xvcl9TMDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfNV9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgl2Y29sb3JfUzAgPSBjb2xvcjsKCXNrX1Bvc2l0aW9uID0gcG9zaXRpb24ueHkwMTsKCXsKCQl2VHJhbnNmb3JtZWRDb29yZHNfNV9TMCA9IGZsb2F0M3gyKHVtYXRyaXhfUzFfYzBfYzEpICogbG9jYWxDb29yZC54eTE7Cgl9Cn0KAAAAAIIGAAB1bmlmb3JtIGhhbGY0IHVzdGFydF9TMV9jMF9jMDsKdW5pZm9ybSBoYWxmNCB1ZW5kX1MxX2MwX2MwOwp1bmlmb3JtIGZsb2F0M3gzIHVtYXRyaXhfUzFfYzBfYzE7CnVuaWZvcm0gaGFsZjQgdWxlZnRCb3JkZXJDb2xvcl9TMV9jMDsKdW5pZm9ybSBoYWxmNCB1cmlnaHRCb3JkZXJDb2xvcl9TMV9jMDsKZmxhdCBpbiBoYWxmNCB2Y29sb3JfUzA7CmluIGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfNV9TMDsKaGFsZjQgU2luZ2xlSW50ZXJ2YWxDb2xvcml6ZXJfUzFfYzBfYzAoaGFsZjQgX2lucHV0LCBmbG9hdDIgX2Nvb3JkcykgCnsKCWhhbGY0IF90bXBfMF9pbkNvbG9yID0gX2lucHV0OwoJZmxvYXQyIF90bXBfMV9jb29yZHMgPSBfY29vcmRzOwoJcmV0dXJuIGhhbGY0KG1peCh1c3RhcnRfUzFfYzBfYzAsIHVlbmRfUzFfYzBfYzAsIGhhbGYoX3RtcF8xX2Nvb3Jkcy54KSkpOwp9CmhhbGY0IExpbmVhckxheW91dF9TMV9jMF9jMV9jMChoYWxmNCBfaW5wdXQpIAp7CgloYWxmNCBfdG1wXzJfaW5Db2xvciA9IF9pbnB1dDsKCWZsb2F0MiBfdG1wXzNfY29vcmRzID0gdlRyYW5zZm9ybWVkQ29vcmRzXzVfUzA7CglyZXR1cm4gaGFsZjQoaGFsZjQoaGFsZihfdG1wXzNfY29vcmRzLngpICsgMWUtMDUsIDEuMCwgMC4wLCAwLjApKTsKfQpoYWxmNCBNYXRyaXhFZmZlY3RfUzFfYzBfYzEoaGFsZjQgX2lucHV0KSAKewoJcmV0dXJuIExpbmVhckxheW91dF9TMV9jMF9jMV9jMChfaW5wdXQpOwp9CmhhbGY0IENsYW1wZWRHcmFkaWVudF9TMV9jMChoYWxmNCBfaW5wdXQpIAp7CgloYWxmNCBfdG1wXzRfaW5Db2xvciA9IF9pbnB1dDsKCWhhbGY0IHQgPSBNYXRyaXhFZmZlY3RfUzFfYzBfYzEoX3RtcF80X2luQ29sb3IpOwoJaGFsZjQgb3V0Q29sb3I7CglpZiAoIWJvb2woaW50KDEpKSAmJiB0LnkgPCAwLjApIAoJewoJCW91dENvbG9yID0gaGFsZjQoMC4wKTsKCX0KCWVsc2UgaWYgKHQueCA8IDAuMCkgCgl7CgkJb3V0Q29sb3IgPSB1bGVmdEJvcmRlckNvbG9yX1MxX2MwOwoJfQoJZWxzZSBpZiAodC54ID4gMS4wKSAKCXsKCQlvdXRDb2xvciA9IHVyaWdodEJvcmRlckNvbG9yX1MxX2MwOwoJfQoJZWxzZSAKCXsKCQlvdXRDb2xvciA9IFNpbmdsZUludGVydmFsQ29sb3JpemVyX1MxX2MwX2MwKF90bXBfNF9pbkNvbG9yLCBmbG9hdDIoaGFsZjIodC54LCAwLjApKSk7Cgl9CglyZXR1cm4gaGFsZjQob3V0Q29sb3IpOwp9CmhhbGY0IERpc2FibGVDb3ZlcmFnZUFzQWxwaGFfUzEoaGFsZjQgX2lucHV0KSAKewoJX2lucHV0ID0gQ2xhbXBlZEdyYWRpZW50X1MxX2MwKF9pbnB1dCk7CgloYWxmNCBfdG1wXzVfaW5Db2xvciA9IF9pbnB1dDsKCXJldHVybiBoYWxmNChfaW5wdXQpOwp9CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBRdWFkUGVyRWRnZUFBR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2Y29sb3JfUzA7Cgljb25zdCBoYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KDEpOwoJaGFsZjQgb3V0cHV0X1MxOwoJb3V0cHV0X1MxID0gRGlzYWJsZUNvdmVyYWdlQXNBbHBoYV9TMShvdXRwdXRDb2xvcl9TMCk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0X1MxICogb3V0cHV0Q292ZXJhZ2VfUzA7Cgl9Cn0KAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAgAAABwb3NpdGlvbgUAAABjb2xvcgAAAAoAAABsb2NhbENvb3JkAAAAAAAA","FAAQMYAAMAAAEADAAABAEYAAAICIAB5AABQAAAQAMAAAEATAAABAIIGAAEDCBYQCA4AAAAAAEADZABYAAAIAAAAAACQAGAAAAAQAAAAAAAQQG":"CgAAAExTS1PUCwAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0NCByYWRpaV9zZWxlY3RvcjsKaW4gZmxvYXQ0IGNvcm5lcl9hbmRfcmFkaXVzX291dHNldHM7CmluIGZsb2F0NCBhYV9ibG9hdF9hbmRfY292ZXJhZ2U7CmluIGZsb2F0NCByYWRpaV94OwppbiBmbG9hdDQgcmFkaWlfeTsKaW4gZmxvYXQ0IHNrZXc7CmluIGZsb2F0MiB0cmFuc2xhdGVfYW5kX2xvY2Fscm90YXRlOwppbiBoYWxmNCBjb2xvcjsKZmxhdCBvdXQgaGFsZjQgdmNvbG9yX1MwOwpvdXQgZmxvYXQyIHZhcmNjb29yZF9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgRmlsbFJSZWN0T3A6OlByb2Nlc3NvcgoJdmNvbG9yX1MwID0gY29sb3I7CglmbG9hdCBhYV9ibG9hdF9tdWx0aXBsaWVyID0gMTsKCWZsb2F0MiBjb3JuZXIgPSBjb3JuZXJfYW5kX3JhZGl1c19vdXRzZXRzLnh5OwoJZmxvYXQyIHJhZGl1c19vdXRzZXQgPSBjb3JuZXJfYW5kX3JhZGl1c19vdXRzZXRzLnp3OwoJZmxvYXQyIGFhX2Jsb2F0X2RpcmVjdGlvbiA9IGFhX2Jsb2F0X2FuZF9jb3ZlcmFnZS54eTsKCWZsb2F0IGlzX2xpbmVhcl9jb3ZlcmFnZSA9IGFhX2Jsb2F0X2FuZF9jb3ZlcmFnZS53OwoJZmxvYXQyIHBpeGVsbGVuZ3RoID0gaW52ZXJzZXNxcnQoZmxvYXQyKGRvdChza2V3Lnh6LCBza2V3Lnh6KSwgZG90KHNrZXcueXcsIHNrZXcueXcpKSk7CglmbG9hdDQgbm9ybWFsaXplZF9heGlzX2RpcnMgPSBza2V3ICogcGl4ZWxsZW5ndGgueHl4eTsKCWZsb2F0MiBheGlzd2lkdGhzID0gKGFicyhub3JtYWxpemVkX2F4aXNfZGlycy54eSkgKyBhYnMobm9ybWFsaXplZF9heGlzX2RpcnMuencpKTsKCWZsb2F0MiBhYV9ibG9hdHJhZGl1cyA9IGF4aXN3aWR0aHMgKiBwaXhlbGxlbmd0aCAqIC41OwoJZmxvYXQ0IHJhZGlpX2FuZF9uZWlnaGJvcnMgPSByYWRpaV9zZWxlY3RvciogZmxvYXQ0eDQocmFkaWlfeCwgcmFkaWlfeSwgcmFkaWlfeC55eHd6LCByYWRpaV95Lnd6eXgpOwoJZmxvYXQyIHJhZGlpID0gcmFkaWlfYW5kX25laWdoYm9ycy54eTsKCWZsb2F0MiBuZWlnaGJvcl9yYWRpaSA9IHJhZGlpX2FuZF9uZWlnaGJvcnMuenc7CglmbG9hdCBjb3ZlcmFnZV9tdWx0aXBsaWVyID0gMTsKCWlmIChhbnkoZ3JlYXRlclRoYW4oYWFfYmxvYXRyYWRpdXMsIGZsb2F0MigxKSkpKSAKCXsKCQljb3JuZXIgPSBtYXgoYWJzKGNvcm5lciksIGFhX2Jsb2F0cmFkaXVzKSAqIHNpZ24oY29ybmVyKTsKCQljb3ZlcmFnZV9tdWx0aXBsaWVyID0gMSAvIChtYXgoYWFfYmxvYXRyYWRpdXMueCwgMSkgKiBtYXgoYWFfYmxvYXRyYWRpdXMueSwgMSkpOwoJCXJhZGlpID0gZmxvYXQyKDApOwoJfQoJZmxvYXQgY292ZXJhZ2UgPSBhYV9ibG9hdF9hbmRfY292ZXJhZ2UuejsKCWlmIChhbnkobGVzc1RoYW4ocmFkaWksIGFhX2Jsb2F0cmFkaXVzICogMS41KSkpIAoJewoJCXJhZGlpID0gZmxvYXQyKDApOwoJCWFhX2Jsb2F0X2RpcmVjdGlvbiA9IHNpZ24oY29ybmVyKTsKCQlpZiAoY292ZXJhZ2UgPiAuNSkgCgkJewoJCQlhYV9ibG9hdF9kaXJlY3Rpb24gPSAtYWFfYmxvYXRfZGlyZWN0aW9uOwoJCX0KCQlpc19saW5lYXJfY292ZXJhZ2UgPSAxOwoJfQoJZWxzZSAKCXsKCQlyYWRpaSA9IGNsYW1wKHJhZGlpLCBwaXhlbGxlbmd0aCAqIDEuNSwgMiAtIHBpeGVsbGVuZ3RoICogMS41KTsKCQluZWlnaGJvcl9yYWRpaSA9IGNsYW1wKG5laWdoYm9yX3JhZGlpLCBwaXhlbGxlbmd0aCAqIDEuNSwgMiAtIHBpeGVsbGVuZ3RoICogMS41KTsKCQlmbG9hdDIgc3BhY2luZyA9IDIgLSByYWRpaSAtIG5laWdoYm9yX3JhZGlpOwoJCWZsb2F0MiBleHRyYV9wYWQgPSBtYXgocGl4ZWxsZW5ndGggKiAuMDYyNSAtIHNwYWNpbmcsIGZsb2F0MigwKSk7CgkJcmFkaWkgLT0gZXh0cmFfcGFkICogLjU7Cgl9CglmbG9hdDIgYWFfb3V0c2V0ID0gYWFfYmxvYXRfZGlyZWN0aW9uICogYWFfYmxvYXRyYWRpdXMgKiBhYV9ibG9hdF9tdWx0aXBsaWVyOwoJZmxvYXQyIHZlcnRleHBvcyA9IGNvcm5lciArIHJhZGl1c19vdXRzZXQgKiByYWRpaSArIGFhX291dHNldDsKCWlmIChjb3ZlcmFnZSA+IC41KSAKCXsKCQlpZiAoYWFfYmxvYXRfZGlyZWN0aW9uLnggIT0gMCAmJiB2ZXJ0ZXhwb3MueCAqIGNvcm5lci54IDwgMCkgCgkJewoJCQlmbG9hdCBiYWNrc2V0ID0gYWJzKHZlcnRleHBvcy54KTsKCQkJdmVydGV4cG9zLnggPSAwOwoJCQl2ZXJ0ZXhwb3MueSArPSBiYWNrc2V0ICogc2lnbihjb3JuZXIueSkgKiBwaXhlbGxlbmd0aC55L3BpeGVsbGVuZ3RoLng7CgkJCWNvdmVyYWdlID0gKGNvdmVyYWdlIC0gLjUpICogYWJzKGNvcm5lci54KSAvIChhYnMoY29ybmVyLngpICsgYmFja3NldCkgKyAuNTsKCQl9CgkJaWYgKGFhX2Jsb2F0X2RpcmVjdGlvbi55ICE9IDAgJiYgdmVydGV4cG9zLnkgKiBjb3JuZXIueSA8IDApIAoJCXsKCQkJZmxvYXQgYmFja3NldCA9IGFicyh2ZXJ0ZXhwb3MueSk7CgkJCXZlcnRleHBvcy55ID0gMDsKCQkJdmVydGV4cG9zLnggKz0gYmFja3NldCAqIHNpZ24oY29ybmVyLngpICogcGl4ZWxsZW5ndGgueC9waXhlbGxlbmd0aC55OwoJCQljb3ZlcmFnZSA9IChjb3ZlcmFnZSAtIC41KSAqIGFicyhjb3JuZXIueSkgLyAoYWJzKGNvcm5lci55KSArIGJhY2tzZXQpICsgLjU7CgkJfQoJfQoJZmxvYXQyeDIgc2tld21hdHJpeCA9IGZsb2F0MngyKHNrZXcueHksIHNrZXcuencpOwoJZmxvYXQyIGRldmNvb3JkID0gdmVydGV4cG9zICogc2tld21hdHJpeCArIHRyYW5zbGF0ZV9hbmRfbG9jYWxyb3RhdGUueHk7CglpZiAoMCAhPSBpc19saW5lYXJfY292ZXJhZ2UpIAoJewoJCXZhcmNjb29yZF9TMC54eSA9IGZsb2F0MigwLCBjb3ZlcmFnZSAqIGNvdmVyYWdlX211bHRpcGxpZXIpOwoJfQoJZWxzZSAKCXsKCQlmbG9hdDIgYXJjY29vcmQgPSAxIC0gYWJzKHJhZGl1c19vdXRzZXQpICsgYWFfb3V0c2V0L3JhZGlpICogY29ybmVyOwoJCXZhcmNjb29yZF9TMC54eSA9IGZsb2F0MihhcmNjb29yZC54KzEsIGFyY2Nvb3JkLnkpOwoJfQoJc2tfUG9zaXRpb24gPSBkZXZjb29yZC54eTAxOwp9CgEAAADUAwAAdW5pZm9ybSBmbG9hdDQgdWlubmVyUmVjdF9TMTsKdW5pZm9ybSBoYWxmMiB1cmFkaXVzUGx1c0hhbGZfUzE7CmZsYXQgaW4gaGFsZjQgdmNvbG9yX1MwOwppbiBmbG9hdDIgdmFyY2Nvb3JkX1MwOwpoYWxmNCBDaXJjdWxhclJSZWN0X1MxKGhhbGY0IF9pbnB1dCkgCnsKCWZsb2F0MiBkeHkwID0gdWlubmVyUmVjdF9TMS5MVCAtIHNrX0ZyYWdDb29yZC54eTsKCWZsb2F0MiBkeHkxID0gc2tfRnJhZ0Nvb3JkLnh5IC0gdWlubmVyUmVjdF9TMS5SQjsKCWZsb2F0MiBkeHkgPSBtYXgobWF4KGR4eTAsIGR4eTEpLCAwLjApOwoJaGFsZiBhbHBoYSA9IGhhbGYoc2F0dXJhdGUodXJhZGl1c1BsdXNIYWxmX1MxLnggLSBsZW5ndGgoZHh5KSkpOwoJcmV0dXJuIF9pbnB1dCAqIGFscGhhOwp9CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBGaWxsUlJlY3RPcDo6UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdmNvbG9yX1MwOwoJZmxvYXQgeF9wbHVzXzE9dmFyY2Nvb3JkX1MwLngsIHk9dmFyY2Nvb3JkX1MwLnk7CgloYWxmIGNvdmVyYWdlOwoJaWYgKDAgPT0geF9wbHVzXzEpIAoJewoJCWNvdmVyYWdlID0gaGFsZih5KTsKCX0KCWVsc2UgCgl7CgkJZmxvYXQgZm4gPSB4X3BsdXNfMSAqICh4X3BsdXNfMSAtIDIpOwoJCWZuID0gZm1hKHkseSwgZm4pOwoJCWZsb2F0IGZud2lkdGggPSBmd2lkdGgoZm4pOwoJCWNvdmVyYWdlID0gLjUgLSBoYWxmKGZuL2Zud2lkdGgpOwoJCWNvdmVyYWdlID0gY2xhbXAoY292ZXJhZ2UsIDAsIDEpOwoJfQoJaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNChjb3ZlcmFnZSk7CgloYWxmNCBvdXRwdXRfUzE7CglvdXRwdXRfUzEgPSBDaXJjdWxhclJSZWN0X1MxKG91dHB1dENvdmVyYWdlX1MwKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dF9TMTsKCX0KfQoBAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAACAAAAA4AAAByYWRpaV9zZWxlY3RvcgAAGQAAAGNvcm5lcl9hbmRfcmFkaXVzX291dHNldHMAAAAVAAAAYWFfYmxvYXRfYW5kX2NvdmVyYWdlAAAABwAAAHJhZGlpX3gABwAAAHJhZGlpX3kABAAAAHNrZXcZAAAAdHJhbnNsYXRlX2FuZF9sb2NhbHJvdGF0ZQAAAAUAAABjb2xvcgAAAAAAAAA=","DAQAAAAAAABGAABAYAAQAIHCAIAYAQUBAEAAAAAAEAAAAAAAAAAAAAB2AAAAAAACAAAAAEBSAAAAA":"CgAAAExTS1MWAgAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQyIHVBdGxhc1NpemVJbnZfUzA7CmluIGZsb2F0MiBpblBvc2l0aW9uOwppbiBoYWxmNCBpbkNvbG9yOwppbiB1c2hvcnQyIGluVGV4dHVyZUNvb3JkczsKb3V0IGZsb2F0MiB2VGV4dHVyZUNvb3Jkc19TMDsKZmxhdCBvdXQgZmxvYXQgdlRleEluZGV4X1MwOwpvdXQgaGFsZjQgdmluQ29sb3JfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIEJpdG1hcFRleHQKCWludCB0ZXhJZHggPSAwOwoJZmxvYXQyIHVub3JtVGV4Q29vcmRzID0gZmxvYXQyKGluVGV4dHVyZUNvb3Jkcy54LCBpblRleHR1cmVDb29yZHMueSk7Cgl2VGV4dHVyZUNvb3Jkc19TMCA9IHVub3JtVGV4Q29vcmRzICogdUF0bGFzU2l6ZUludl9TMDsKCXZUZXhJbmRleF9TMCA9IGZsb2F0KHRleElkeCk7Cgl2aW5Db2xvcl9TMCA9IGluQ29sb3I7CglmbG9hdDIgX3RtcF8xX2luUG9zaXRpb24gPSBpblBvc2l0aW9uOwoJc2tfUG9zaXRpb24gPSBpblBvc2l0aW9uLnh5MDE7Cn0KAAAAAAAAsQEAAHVuaWZvcm0gc2FtcGxlcjJEIHVUZXh0dXJlU2FtcGxlcl8wX1MwOwppbiBmbG9hdDIgdlRleHR1cmVDb29yZHNfUzA7CmZsYXQgaW4gZmxvYXQgdlRleEluZGV4X1MwOwppbiBoYWxmNCB2aW5Db2xvcl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIEJpdG1hcFRleHQKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2aW5Db2xvcl9TMDsKCWhhbGY0IHRleENvbG9yOwoJewoJCXRleENvbG9yID0gc2FtcGxlKHVUZXh0dXJlU2FtcGxlcl8wX1MwLCB2VGV4dHVyZUNvb3Jkc19TMCkucnJycjsKCX0KCWhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gdGV4Q29sb3I7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRDb3ZlcmFnZV9TMDsKCX0KfQoAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAoAAABpblBvc2l0aW9uAAAHAAAAaW5Db2xvcgAPAAAAaW5UZXh0dXJlQ29vcmRzAAAAAAA=","HUIAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAAAAAALUAQBAEAQAAAAGQCBAMQACAIAAAAAACQAGAAAAAQAAAAAAAQQGAAAAA":"CgAAAExTS1M2AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBmbG9hdDIgbG9jYWxDb29yZDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cgl7CgkJdlRyYW5zZm9ybWVkQ29vcmRzXzJfUzAgPSBmbG9hdDN4Mih1bWF0cml4X1MxKSAqIGxvY2FsQ29vcmQueHkxOwoJfQp9CgAAAAAAAE0DAAB1bmlmb3JtIGZsb2F0NCB1Y2xhbXBfUzFfYzA7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKdW5pZm9ybSBzYW1wbGVyMkQgdVRleHR1cmVTYW1wbGVyXzBfUzE7CmluIGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKaGFsZjQgVGV4dHVyZUVmZmVjdF9TMV9jMChoYWxmNCBfaW5wdXQpIAp7CglmbG9hdDIgaW5Db29yZCA9IHZUcmFuc2Zvcm1lZENvb3Jkc18yX1MwOwoJZmxvYXQyIHN1YnNldENvb3JkOwoJc3Vic2V0Q29vcmQueCA9IGluQ29vcmQueDsKCXN1YnNldENvb3JkLnkgPSBpbkNvb3JkLnk7CglmbG9hdDIgY2xhbXBlZENvb3JkOwoJY2xhbXBlZENvb3JkID0gY2xhbXAoc3Vic2V0Q29vcmQsIHVjbGFtcF9TMV9jMC54eSwgdWNsYW1wX1MxX2MwLnp3KTsKCWhhbGY0IHRleHR1cmVDb2xvciA9IHNhbXBsZSh1VGV4dHVyZVNhbXBsZXJfMF9TMSwgY2xhbXBlZENvb3JkKTsKCXJldHVybiB0ZXh0dXJlQ29sb3I7Cn0KaGFsZjQgTWF0cml4RWZmZWN0X1MxKGhhbGY0IF9pbnB1dCkgCnsKCXJldHVybiBUZXh0dXJlRWZmZWN0X1MxX2MwKF9pbnB1dCk7Cn0Kdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJaGFsZjQgb3V0cHV0Q29sb3JfUzAgPSBoYWxmNCgxKTsKCWNvbnN0IGhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoMSk7CgloYWxmNCBvdXRwdXRfUzE7CglvdXRwdXRfUzEgPSBNYXRyaXhFZmZlY3RfUzEob3V0cHV0Q29sb3JfUzApOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dF9TMSAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAACAAAACAAAAHBvc2l0aW9uCgAAAGxvY2FsQ29vcmQAAAAAAAA=","HVJAAAAAABIAAGAAAQ4AAAH477776R24EAAAIOBQAD6P7777777777YDAAAAABAAAAAABBAMABAAOAAAABAAAAAAABBAMAAA":"CgAAAExTS1MjAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gaGFsZjQgY29sb3I7CmluIGZsb2F0MiBsb2NhbENvb3JkOwpmbGF0IG91dCBoYWxmNCB2Y29sb3JfUzA7Cm91dCBmbG9hdDIgdmxvY2FsQ29vcmRfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJdmNvbG9yX1MwID0gY29sb3I7Cgl2bG9jYWxDb29yZF9TMCA9IGxvY2FsQ29vcmQ7Cglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cn0KAAAAAADQAQAAdW5pZm9ybSBzYW1wbGVyMkQgdVRleHR1cmVTYW1wbGVyXzBfUzA7CmZsYXQgaW4gaGFsZjQgdmNvbG9yX1MwOwppbiBmbG9hdDIgdmxvY2FsQ29vcmRfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBRdWFkUGVyRWRnZUFBR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2Y29sb3JfUzA7CglmbG9hdDIgdGV4Q29vcmQ7Cgl0ZXhDb29yZCA9IHZsb2NhbENvb3JkX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSAoKHNhbXBsZSh1VGV4dHVyZVNhbXBsZXJfMF9TMCwgdGV4Q29vcmQpICogb3V0cHV0Q29sb3JfUzApKTsKCWNvbnN0IGhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoMSk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRDb3ZlcmFnZV9TMDsKCX0KfQoAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAgAAABwb3NpdGlvbgUAAABjb2xvcgAAAAoAAABsb2NhbENvb3JkAAAAAAAA","HUIAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAAAAAALUAQBAAAQAAAAGQCBAMQACAAAAAAAACQAGAAAAAQAAAAAAAQQGAAAAA":"CgAAAExTS1M2AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBmbG9hdDIgbG9jYWxDb29yZDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cgl7CgkJdlRyYW5zZm9ybWVkQ29vcmRzXzJfUzAgPSBmbG9hdDN4Mih1bWF0cml4X1MxKSAqIGxvY2FsQ29vcmQueHkxOwoJfQp9CgAAAAAAAHADAAB1bmlmb3JtIGZsb2F0NCB1Y2xhbXBfUzFfYzA7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKdW5pZm9ybSBzYW1wbGVyMkQgdVRleHR1cmVTYW1wbGVyXzBfUzE7CmluIGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKaGFsZjQgVGV4dHVyZUVmZmVjdF9TMV9jMChoYWxmNCBfaW5wdXQpIAp7CglmbG9hdDIgaW5Db29yZCA9IHZUcmFuc2Zvcm1lZENvb3Jkc18yX1MwOwoJZmxvYXQyIHN1YnNldENvb3JkOwoJc3Vic2V0Q29vcmQueCA9IGluQ29vcmQueDsKCXN1YnNldENvb3JkLnkgPSBpbkNvb3JkLnk7CglmbG9hdDIgY2xhbXBlZENvb3JkOwoJY2xhbXBlZENvb3JkLnggPSBjbGFtcChzdWJzZXRDb29yZC54LCB1Y2xhbXBfUzFfYzAueCwgdWNsYW1wX1MxX2MwLnopOwoJY2xhbXBlZENvb3JkLnkgPSBzdWJzZXRDb29yZC55OwoJaGFsZjQgdGV4dHVyZUNvbG9yID0gc2FtcGxlKHVUZXh0dXJlU2FtcGxlcl8wX1MxLCBjbGFtcGVkQ29vcmQpOwoJcmV0dXJuIHRleHR1cmVDb2xvcjsKfQpoYWxmNCBNYXRyaXhFZmZlY3RfUzEoaGFsZjQgX2lucHV0KSAKewoJcmV0dXJuIFRleHR1cmVFZmZlY3RfUzFfYzAoX2lucHV0KTsKfQp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMCA9IGhhbGY0KDEpOwoJY29uc3QgaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNCgxKTsKCWhhbGY0IG91dHB1dF9TMTsKCW91dHB1dF9TMSA9IE1hdHJpeEVmZmVjdF9TMShvdXRwdXRDb2xvcl9TMCk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0X1MxICogb3V0cHV0Q292ZXJhZ2VfUzA7Cgl9Cn0KAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAIAAAAcG9zaXRpb24KAAAAbG9jYWxDb29yZAAAAAAAAA==","EADQAAAAAEAAAAAUAABQAAQPAAABCFYMAAKAUEAAAAAAAAABAAAAAAAAAAANAAIAAAABAAAAACAJAAIAAAAA":"CgAAAExTS1NyAgAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQyIHVBdGxhc0RpbWVuc2lvbnNJbnZfUzA7CmluIGZsb2F0MyBpblBvc2l0aW9uOwppbiBoYWxmNCBpbkNvbG9yOwppbiB1c2hvcnQyIGluVGV4dHVyZUNvb3JkczsKb3V0IGZsb2F0MiB2VGV4dHVyZUNvb3Jkc19TMDsKZmxhdCBvdXQgZmxvYXQgdlRleEluZGV4X1MwOwpvdXQgZmxvYXQyIHZJbnRUZXh0dXJlQ29vcmRzX1MwOwpvdXQgaGFsZjQgdmluQ29sb3JfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIERpc3RhbmNlRmllbGRQYXRoCglpbnQgdGV4SWR4ID0gMDsKCWZsb2F0MiB1bm9ybVRleENvb3JkcyA9IGZsb2F0MihpblRleHR1cmVDb29yZHMueCwgaW5UZXh0dXJlQ29vcmRzLnkpOwoJdlRleHR1cmVDb29yZHNfUzAgPSB1bm9ybVRleENvb3JkcyAqIHVBdGxhc0RpbWVuc2lvbnNJbnZfUzA7Cgl2VGV4SW5kZXhfUzAgPSBmbG9hdCh0ZXhJZHgpOwoJdkludFRleHR1cmVDb29yZHNfUzAgPSB1bm9ybVRleENvb3JkczsKCXZpbkNvbG9yX1MwID0gaW5Db2xvcjsKCWZsb2F0MyBfdG1wXzFfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247Cglza19Qb3NpdGlvbiA9IGluUG9zaXRpb24ueHkwejsKfQoAAAAAAACfAgAAdW5pZm9ybSBzYW1wbGVyMkQgdVRleHR1cmVTYW1wbGVyXzBfUzA7CmluIGZsb2F0MiB2VGV4dHVyZUNvb3Jkc19TMDsKZmxhdCBpbiBmbG9hdCB2VGV4SW5kZXhfUzA7CmluIGZsb2F0MiB2SW50VGV4dHVyZUNvb3Jkc19TMDsKaW4gaGFsZjQgdmluQ29sb3JfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBEaXN0YW5jZUZpZWxkUGF0aAoJaGFsZjQgb3V0cHV0Q29sb3JfUzA7CglvdXRwdXRDb2xvcl9TMCA9IHZpbkNvbG9yX1MwOwoJZmxvYXQyIHV2ID0gdlRleHR1cmVDb29yZHNfUzA7CgloYWxmNCB0ZXhDb2xvcjsKCXsKCQl0ZXhDb2xvciA9IHNhbXBsZSh1VGV4dHVyZVNhbXBsZXJfMF9TMCwgdXYpLnJycnI7Cgl9CgloYWxmIGRpc3RhbmNlID0gNy45Njg3NSoodGV4Q29sb3IuciAtIDAuNTAxOTYwNzg0MzEpOwoJaGFsZiBhZndpZHRoOwoJYWZ3aWR0aCA9IGFicygwLjY1KmhhbGYoZEZkeCh2SW50VGV4dHVyZUNvb3Jkc19TMC54KSkpOwoJaGFsZiB2YWwgPSBzbW9vdGhzdGVwKC1hZndpZHRoLCBhZndpZHRoLCBkaXN0YW5jZSk7CgloYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KHZhbCk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRDb3ZlcmFnZV9TMDsKCX0KfQoAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAKAAAAaW5Qb3NpdGlvbgAABwAAAGluQ29sb3IADwAAAGluVGV4dHVyZUNvb3JkcwAAAAAA","HTQAAGAABBYAAAEIXBAAAGEAMAAAAAAAAAAAAAAAQAHAAAAAQAAAAAAAQQGAAAAA":"CgAAAExTS1M/AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBpblBvc2l0aW9uOwppbiBoYWxmNCBpbkNvbG9yOwppbiBmbG9hdDQgaW5RdWFkRWRnZTsKb3V0IGZsb2F0NCB2UXVhZEVkZ2VfUzA7Cm91dCBoYWxmNCB2aW5Db2xvcl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZEVkZ2UKCXZRdWFkRWRnZV9TMCA9IGluUXVhZEVkZ2U7Cgl2aW5Db2xvcl9TMCA9IGluQ29sb3I7CglmbG9hdDIgX3RtcF8wX2luUG9zaXRpb24gPSBpblBvc2l0aW9uOwoJc2tfUG9zaXRpb24gPSBfdG1wXzBfaW5Qb3NpdGlvbi54eTAxOwp9CgABAAAABQMAAGluIGZsb2F0NCB2UXVhZEVkZ2VfUzA7CmluIGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgUXVhZEVkZ2UKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2aW5Db2xvcl9TMDsKCWhhbGYgZWRnZUFscGhhOwoJaGFsZjIgZHV2ZHggPSBoYWxmMihkRmR4KHZRdWFkRWRnZV9TMC54eSkpOwoJaGFsZjIgZHV2ZHkgPSBoYWxmMihkRmR5KHZRdWFkRWRnZV9TMC54eSkpOwoJaWYgKHZRdWFkRWRnZV9TMC56ID4gMC4wICYmIHZRdWFkRWRnZV9TMC53ID4gMC4wKSAKCXsKCQllZGdlQWxwaGEgPSBoYWxmKG1pbihtaW4odlF1YWRFZGdlX1MwLnosIHZRdWFkRWRnZV9TMC53KSArIDAuNSwgMS4wKSk7Cgl9CgllbHNlIAoJewoJCWhhbGYyIGdGID0gaGFsZjIoaGFsZigyLjAqdlF1YWRFZGdlX1MwLngqZHV2ZHgueCAtIGR1dmR4LnkpLCAgICAgICAgICAgICAgICAgaGFsZigyLjAqdlF1YWRFZGdlX1MwLngqZHV2ZHkueCAtIGR1dmR5LnkpKTsKCQllZGdlQWxwaGEgPSBoYWxmKHZRdWFkRWRnZV9TMC54KnZRdWFkRWRnZV9TMC54IC0gdlF1YWRFZGdlX1MwLnkpOwoJCWVkZ2VBbHBoYSA9IHNhdHVyYXRlKDAuNSAtIGVkZ2VBbHBoYSAvIGxlbmd0aChnRikpOwoJfQoJaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNChlZGdlQWxwaGEpOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dENvbG9yX1MwICogb3V0cHV0Q292ZXJhZ2VfUzA7Cgl9Cn0KAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAKAAAAaW5Qb3NpdGlvbgAABwAAAGluQ29sb3IACgAAAGluUXVhZEVkZ2UAAAAAAAA=","HUIAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAAAAAADUAANAAAAAAAAAIAAAABLAIABAAAAABAEGABBAMAAAAAAAAAAAAB2AAAAAAACAAAAAEBSAAAAA":"CgAAAExTS1M8AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMV9jMDsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBmbG9hdDIgbG9jYWxDb29yZDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfM19TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cgl7CgkJdlRyYW5zZm9ybWVkQ29vcmRzXzNfUzAgPSBmbG9hdDN4Mih1bWF0cml4X1MxX2MwKSAqIGxvY2FsQ29vcmQueHkxOwoJfQp9CgAAAAC2AgAAdW5pZm9ybSBmbG9hdDN4MyB1bWF0cml4X1MxX2MwOwp1bmlmb3JtIHNhbXBsZXIyRCB1VGV4dHVyZVNhbXBsZXJfMF9TMTsKaW4gZmxvYXQyIHZUcmFuc2Zvcm1lZENvb3Jkc18zX1MwOwpoYWxmNCBUZXh0dXJlRWZmZWN0X1MxX2MwX2MwKGhhbGY0IF9pbnB1dCkgCnsKCXJldHVybiBzYW1wbGUodVRleHR1cmVTYW1wbGVyXzBfUzEsIHZUcmFuc2Zvcm1lZENvb3Jkc18zX1MwKTsKfQpoYWxmNCBNYXRyaXhFZmZlY3RfUzFfYzAoaGFsZjQgX2lucHV0KSAKewoJcmV0dXJuIFRleHR1cmVFZmZlY3RfUzFfYzBfYzAoX2lucHV0KTsKfQpoYWxmNCBCbGVuZF9TMShoYWxmNCBfc3JjLCBoYWxmNCBfZHN0KSAKewoJcmV0dXJuIGJsZW5kX21vZHVsYXRlKE1hdHJpeEVmZmVjdF9TMV9jMChfc3JjKSwgX3NyYyk7Cn0Kdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJaGFsZjQgb3V0cHV0Q29sb3JfUzAgPSBoYWxmNCgxKTsKCWNvbnN0IGhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoMSk7CgloYWxmNCBvdXRwdXRfUzE7CglvdXRwdXRfUzEgPSBCbGVuZF9TMShvdXRwdXRDb2xvcl9TMCwgaGFsZjQoMSkpOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dF9TMSAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAIAAAAcG9zaXRpb24KAAAAbG9jYWxDb29yZAAAAAAAAA==","AYQQ5AADQAAAOAEARAFQJAABBADIB7777777777777777777777767YAAAAAAAAAAAAOQAAAAAAAQAAAABAMQAAAAA":"CgAAAExTS1PMAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQ0IHVsb2NhbE1hdHJpeF9TMDsKaW4gZmxvYXQyIGluUG9zaXRpb247CmluIGhhbGY0IGluQ29sb3I7CmluIGZsb2F0NCBpbkNpcmNsZUVkZ2U7Cm91dCBmbG9hdDQgdmluQ2lyY2xlRWRnZV9TMDsKb3V0IGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBDaXJjbGVHZW9tZXRyeVByb2Nlc3NvcgoJdmluQ2lyY2xlRWRnZV9TMCA9IGluQ2lyY2xlRWRnZTsKCXZpbkNvbG9yX1MwID0gaW5Db2xvcjsKCWZsb2F0MiBfdG1wXzBfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247CglmbG9hdDIgX3RtcF8xX2luUG9zaXRpb24gPSB1bG9jYWxNYXRyaXhfUzAueHogKiBpblBvc2l0aW9uICsgdWxvY2FsTWF0cml4X1MwLnl3OwoJc2tfUG9zaXRpb24gPSBfdG1wXzBfaW5Qb3NpdGlvbi54eTAxOwp9CgAAAAB7AgAAaW4gZmxvYXQ0IHZpbkNpcmNsZUVkZ2VfUzA7CmluIGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgQ2lyY2xlR2VvbWV0cnlQcm9jZXNzb3IKCWZsb2F0NCBjaXJjbGVFZGdlOwoJY2lyY2xlRWRnZSA9IHZpbkNpcmNsZUVkZ2VfUzA7CgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdmluQ29sb3JfUzA7CglmbG9hdCBkID0gbGVuZ3RoKGNpcmNsZUVkZ2UueHkpOwoJaGFsZiBkaXN0YW5jZVRvT3V0ZXJFZGdlID0gaGFsZihjaXJjbGVFZGdlLnogKiAoMS4wIC0gZCkpOwoJaGFsZiBlZGdlQWxwaGEgPSBzYXR1cmF0ZShkaXN0YW5jZVRvT3V0ZXJFZGdlKTsKCWhhbGYgZGlzdGFuY2VUb0lubmVyRWRnZSA9IGhhbGYoY2lyY2xlRWRnZS56ICogKGQgLSBjaXJjbGVFZGdlLncpKTsKCWhhbGYgaW5uZXJBbHBoYSA9IHNhdHVyYXRlKGRpc3RhbmNlVG9Jbm5lckVkZ2UpOwoJZWRnZUFscGhhICo9IGlubmVyQWxwaGE7CgloYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KGVkZ2VBbHBoYSk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRDb3ZlcmFnZV9TMDsKCX0KfQoAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAKAAAAaW5Qb3NpdGlvbgAABwAAAGluQ29sb3IADAAAAGluQ2lyY2xlRWRnZQAAAAA=","HUIAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAAAAAALUAQMAAAAAAAAAEAAAABJYQAAAAAAAAIAAAAAWCBAAAABAAAAANAECAZAAAAAAAAAAAFAAMAAAABAAAAAAABBAM":"CgAAAExTS1M2AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBmbG9hdDIgbG9jYWxDb29yZDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cgl7CgkJdlRyYW5zZm9ybWVkQ29vcmRzXzJfUzAgPSBmbG9hdDN4Mih1bWF0cml4X1MxKSAqIGxvY2FsQ29vcmQueHkxOwoJfQp9CgAAAAAAAPAEAAB1bmlmb3JtIGZsb2F0M3gzIHVtYXRyaXhfUzFfYzBfYzA7CnVuaWZvcm0gaGFsZjIgdUluY3JlbWVudF9TMV9jMDsKdW5pZm9ybSBoYWxmMiB1T2Zmc2V0c0FuZEtlcm5lbF9TMV9jMFsxM107CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKdW5pZm9ybSBzYW1wbGVyMkQgdVRleHR1cmVTYW1wbGVyXzBfUzE7CmluIGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKaGFsZjQgVGV4dHVyZUVmZmVjdF9TMV9jMF9jMF9jMChoYWxmNCBfaW5wdXQsIGZsb2F0MiBfY29vcmRzKSAKewoJcmV0dXJuIHNhbXBsZSh1VGV4dHVyZVNhbXBsZXJfMF9TMSwgX2Nvb3Jkcyk7Cn0KaGFsZjQgTWF0cml4RWZmZWN0X1MxX2MwX2MwKGhhbGY0IF9pbnB1dCwgZmxvYXQyIF9jb29yZHMpIAp7CglyZXR1cm4gVGV4dHVyZUVmZmVjdF9TMV9jMF9jMF9jMChfaW5wdXQsIGZsb2F0M3gyKHVtYXRyaXhfUzFfYzBfYzApICogX2Nvb3Jkcy54eTEpOwp9CmhhbGY0IFNtb290aF9TMV9jMChoYWxmNCBfaW5wdXQsIGZsb2F0MiBjb29yZCwgaGFsZjIgb2Zmc2V0QW5kS2VybmVsKSAKewoJcmV0dXJuIE1hdHJpeEVmZmVjdF9TMV9jMF9jMChfaW5wdXQsIChjb29yZCArIG9mZnNldEFuZEtlcm5lbC54ICogdUluY3JlbWVudF9TMV9jMCkpICogb2Zmc2V0QW5kS2VybmVsLnk7Cn0KaGFsZjQgR2F1c3NpYW5Db252b2x1dGlvbl9TMV9jMChoYWxmNCBfaW5wdXQpIAp7CgloYWxmNCBjb2xvciA9IGhhbGY0KDApOwoJZmxvYXQyIGNvb3JkID0gdlRyYW5zZm9ybWVkQ29vcmRzXzJfUzA7Cglmb3IgKGludCBpPTA7IGk8MTM7ICsraSkgCgl7CgkJY29sb3IgKz0gU21vb3RoX1MxX2MwKF9pbnB1dCwgY29vcmQsIHVPZmZzZXRzQW5kS2VybmVsX1MxX2MwW2ldKTsKCX0KCXJldHVybiBjb2xvcjsKfQpoYWxmNCBNYXRyaXhFZmZlY3RfUzEoaGFsZjQgX2lucHV0KSAKewoJcmV0dXJuIEdhdXNzaWFuQ29udm9sdXRpb25fUzFfYzAoX2lucHV0KTsKfQp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMCA9IGhhbGY0KDEpOwoJY29uc3QgaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNCgxKTsKCWhhbGY0IG91dHB1dF9TMTsKCW91dHB1dF9TMSA9IE1hdHJpeEVmZmVjdF9TMShvdXRwdXRDb2xvcl9TMCk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0X1MxICogb3V0cHV0Q292ZXJhZ2VfUzA7Cgl9Cn0KAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAIAAAAcG9zaXRpb24KAAAAbG9jYWxDb29yZAAAAAAAAA==","DASAAAAAQAAWAABAYAAQBYH7777Z6QQBAEAAAAAAEAAAAAAAEBSAAAB2AAAAAAACAAAAAEBSAAAAA":"CgAAAExTS1PVAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQyIHVBdGxhc1NpemVJbnZfUzA7CmluIGZsb2F0MiBpblBvc2l0aW9uOwppbiB1c2hvcnQyIGluVGV4dHVyZUNvb3JkczsKb3V0IGZsb2F0MiB2VGV4dHVyZUNvb3Jkc19TMDsKZmxhdCBvdXQgZmxvYXQgdlRleEluZGV4X1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBCaXRtYXBUZXh0CglpbnQgdGV4SWR4ID0gMDsKCWZsb2F0MiB1bm9ybVRleENvb3JkcyA9IGZsb2F0MihpblRleHR1cmVDb29yZHMueCwgaW5UZXh0dXJlQ29vcmRzLnkpOwoJdlRleHR1cmVDb29yZHNfUzAgPSB1bm9ybVRleENvb3JkcyAqIHVBdGxhc1NpemVJbnZfUzA7Cgl2VGV4SW5kZXhfUzAgPSBmbG9hdCh0ZXhJZHgpOwoJZmxvYXQyIF90bXBfMV9pblBvc2l0aW9uID0gaW5Qb3NpdGlvbjsKCXNrX1Bvc2l0aW9uID0gaW5Qb3NpdGlvbi54eTAxOwp9CgAAAAAAAADgAQAAdW5pZm9ybSBoYWxmNCB1Q29sb3JfUzA7CnVuaWZvcm0gc2FtcGxlcjJEIHVUZXh0dXJlU2FtcGxlcl8wX1MwOwppbiBmbG9hdDIgdlRleHR1cmVDb29yZHNfUzA7CmZsYXQgaW4gZmxvYXQgdlRleEluZGV4X1MwOwp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgQml0bWFwVGV4dAoJaGFsZjQgb3V0cHV0Q29sb3JfUzA7CglvdXRwdXRDb2xvcl9TMCA9IHVDb2xvcl9TMDsKCWhhbGY0IHRleENvbG9yOwoJewoJCXRleENvbG9yID0gc2FtcGxlKHVUZXh0dXJlU2FtcGxlcl8wX1MwLCB2VGV4dHVyZUNvb3Jkc19TMCk7Cgl9CglvdXRwdXRDb2xvcl9TMCA9IG91dHB1dENvbG9yX1MwICogdGV4Q29sb3I7Cgljb25zdCBoYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KDEpOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dENvbG9yX1MwICogb3V0cHV0Q292ZXJhZ2VfUzA7Cgl9Cn0KAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAKAAAAaW5Qb3NpdGlvbgAADwAAAGluVGV4dHVyZUNvb3JkcwAAAAAA","HUIAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAAAAAALUAQMAAAAAAABAEAAAABJYQAAAAAACAIAAAAAWCBAAAIBAAAAANAECAZAAAAQAAAAAAFAAMAAAABAAAAAAABBAM":"CgAAAExTS1M2AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBmbG9hdDIgbG9jYWxDb29yZDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cgl7CgkJdlRyYW5zZm9ybWVkQ29vcmRzXzJfUzAgPSBmbG9hdDN4Mih1bWF0cml4X1MxKSAqIGxvY2FsQ29vcmQueHkxOwoJfQp9CgAAAAAAAC8GAAB1bmlmb3JtIGZsb2F0NCB1Y2xhbXBfUzFfYzBfYzBfYzA7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMV9jMF9jMDsKdW5pZm9ybSBoYWxmMiB1SW5jcmVtZW50X1MxX2MwOwp1bmlmb3JtIGhhbGYyIHVPZmZzZXRzQW5kS2VybmVsX1MxX2MwWzEzXTsKdW5pZm9ybSBmbG9hdDN4MyB1bWF0cml4X1MxOwp1bmlmb3JtIHNhbXBsZXIyRCB1VGV4dHVyZVNhbXBsZXJfMF9TMTsKaW4gZmxvYXQyIHZUcmFuc2Zvcm1lZENvb3Jkc18yX1MwOwpoYWxmNCBUZXh0dXJlRWZmZWN0X1MxX2MwX2MwX2MwKGhhbGY0IF9pbnB1dCwgZmxvYXQyIF9jb29yZHMpIAp7CglmbG9hdDIgaW5Db29yZCA9IF9jb29yZHM7CglmbG9hdDIgc3Vic2V0Q29vcmQ7CglzdWJzZXRDb29yZC54ID0gaW5Db29yZC54OwoJc3Vic2V0Q29vcmQueSA9IGluQ29vcmQueTsKCWZsb2F0MiBjbGFtcGVkQ29vcmQ7CgljbGFtcGVkQ29vcmQueCA9IHN1YnNldENvb3JkLng7CgljbGFtcGVkQ29vcmQueSA9IGNsYW1wKHN1YnNldENvb3JkLnksIHVjbGFtcF9TMV9jMF9jMF9jMC55LCB1Y2xhbXBfUzFfYzBfYzBfYzAudyk7CgloYWxmNCB0ZXh0dXJlQ29sb3IgPSBzYW1wbGUodVRleHR1cmVTYW1wbGVyXzBfUzEsIGNsYW1wZWRDb29yZCk7CglyZXR1cm4gdGV4dHVyZUNvbG9yOwp9CmhhbGY0IE1hdHJpeEVmZmVjdF9TMV9jMF9jMChoYWxmNCBfaW5wdXQsIGZsb2F0MiBfY29vcmRzKSAKewoJcmV0dXJuIFRleHR1cmVFZmZlY3RfUzFfYzBfYzBfYzAoX2lucHV0LCBmbG9hdDN4Mih1bWF0cml4X1MxX2MwX2MwKSAqIF9jb29yZHMueHkxKTsKfQpoYWxmNCBTbW9vdGhfUzFfYzAoaGFsZjQgX2lucHV0LCBmbG9hdDIgY29vcmQsIGhhbGYyIG9mZnNldEFuZEtlcm5lbCkgCnsKCXJldHVybiBNYXRyaXhFZmZlY3RfUzFfYzBfYzAoX2lucHV0LCAoY29vcmQgKyBvZmZzZXRBbmRLZXJuZWwueCAqIHVJbmNyZW1lbnRfUzFfYzApKSAqIG9mZnNldEFuZEtlcm5lbC55Owp9CmhhbGY0IEdhdXNzaWFuQ29udm9sdXRpb25fUzFfYzAoaGFsZjQgX2lucHV0KSAKewoJaGFsZjQgY29sb3IgPSBoYWxmNCgwKTsKCWZsb2F0MiBjb29yZCA9IHZUcmFuc2Zvcm1lZENvb3Jkc18yX1MwOwoJZm9yIChpbnQgaT0wOyBpPDEzOyArK2kpIAoJewoJCWNvbG9yICs9IFNtb290aF9TMV9jMChfaW5wdXQsIGNvb3JkLCB1T2Zmc2V0c0FuZEtlcm5lbF9TMV9jMFtpXSk7Cgl9CglyZXR1cm4gY29sb3I7Cn0KaGFsZjQgTWF0cml4RWZmZWN0X1MxKGhhbGY0IF9pbnB1dCkgCnsKCXJldHVybiBHYXVzc2lhbkNvbnZvbHV0aW9uX1MxX2MwKF9pbnB1dCk7Cn0Kdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJaGFsZjQgb3V0cHV0Q29sb3JfUzAgPSBoYWxmNCgxKTsKCWNvbnN0IGhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoMSk7CgloYWxmNCBvdXRwdXRfUzE7CglvdXRwdXRfUzEgPSBNYXRyaXhFZmZlY3RfUzEob3V0cHV0Q29sb3JfUzApOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dF9TMSAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAgAAABwb3NpdGlvbgoAAABsb2NhbENvb3JkAAAAAAAA","HUJAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAQAAAAAAQQGACQAGAAAAAQAAAAAAAQQGAAA":"CgAAAExTS1PlAAAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gZmxvYXQyIGxvY2FsQ29vcmQ7Cm91dCBmbG9hdDIgdmxvY2FsQ29vcmRfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJdmxvY2FsQ29vcmRfUzAgPSBsb2NhbENvb3JkOwoJc2tfUG9zaXRpb24gPSBwb3NpdGlvbi54eTAxOwp9CgAAAAAAAACfAQAAdW5pZm9ybSBzYW1wbGVyMkQgdVRleHR1cmVTYW1wbGVyXzBfUzA7CmluIGZsb2F0MiB2bG9jYWxDb29yZF9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJaGFsZjQgb3V0cHV0Q29sb3JfUzAgPSBoYWxmNCgxKTsKCWZsb2F0MiB0ZXhDb29yZDsKCXRleENvb3JkID0gdmxvY2FsQ29vcmRfUzA7CglvdXRwdXRDb2xvcl9TMCA9ICgoc2FtcGxlKHVUZXh0dXJlU2FtcGxlcl8wX1MwLCB0ZXhDb29yZCkgKiBoYWxmNCgxKSkpOwoJY29uc3QgaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNCgxKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAgAAABwb3NpdGlvbgoAAABsb2NhbENvb3JkAAAAAAAA","AYQA5AADQAAAOAEARAFQJAABBADIB7777777777777777777777767YAAAAAAAAAAAAB3QA6AAAEAAAAAAAMAAPEAEAAABAAAAAAB2AAAAAAACAAAAAEBSAAAA":"CgAAAExTS1PMAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQ0IHVsb2NhbE1hdHJpeF9TMDsKaW4gZmxvYXQyIGluUG9zaXRpb247CmluIGhhbGY0IGluQ29sb3I7CmluIGZsb2F0NCBpbkNpcmNsZUVkZ2U7Cm91dCBmbG9hdDQgdmluQ2lyY2xlRWRnZV9TMDsKb3V0IGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBDaXJjbGVHZW9tZXRyeVByb2Nlc3NvcgoJdmluQ2lyY2xlRWRnZV9TMCA9IGluQ2lyY2xlRWRnZTsKCXZpbkNvbG9yX1MwID0gaW5Db2xvcjsKCWZsb2F0MiBfdG1wXzBfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247CglmbG9hdDIgX3RtcF8xX2luUG9zaXRpb24gPSB1bG9jYWxNYXRyaXhfUzAueHogKiBpblBvc2l0aW9uICsgdWxvY2FsTWF0cml4X1MwLnl3OwoJc2tfUG9zaXRpb24gPSBfdG1wXzBfaW5Qb3NpdGlvbi54eTAxOwp9CgEAAAAeBQAAdW5pZm9ybSBmbG9hdDQgdWlubmVyUmVjdF9TMTsKdW5pZm9ybSBoYWxmMiB1cmFkaXVzUGx1c0hhbGZfUzE7CnVuaWZvcm0gZmxvYXQ0IHVpbm5lclJlY3RfUzI7CnVuaWZvcm0gaGFsZjIgdXJhZGl1c1BsdXNIYWxmX1MyOwppbiBmbG9hdDQgdmluQ2lyY2xlRWRnZV9TMDsKaW4gaGFsZjQgdmluQ29sb3JfUzA7CmhhbGY0IENpcmN1bGFyUlJlY3RfUzEoaGFsZjQgX2lucHV0KSAKewoJZmxvYXQyIGR4eTAgPSB1aW5uZXJSZWN0X1MxLkxUIC0gc2tfRnJhZ0Nvb3JkLnh5OwoJZmxvYXQyIGR4eTEgPSBza19GcmFnQ29vcmQueHkgLSB1aW5uZXJSZWN0X1MxLlJCOwoJZmxvYXQyIGR4eSA9IG1heChtYXgoZHh5MCwgZHh5MSksIDAuMCk7CgloYWxmIGFscGhhID0gaGFsZihzYXR1cmF0ZSh1cmFkaXVzUGx1c0hhbGZfUzEueCAtIGxlbmd0aChkeHkpKSk7CglhbHBoYSA9IDEuMCAtIGFscGhhOwoJcmV0dXJuIF9pbnB1dCAqIGFscGhhOwp9CmhhbGY0IENpcmN1bGFyUlJlY3RfUzIoaGFsZjQgX2lucHV0KSAKewoJZmxvYXQyIGR4eTAgPSB1aW5uZXJSZWN0X1MyLkxUIC0gc2tfRnJhZ0Nvb3JkLnh5OwoJZmxvYXQyIGR4eTEgPSBza19GcmFnQ29vcmQueHkgLSB1aW5uZXJSZWN0X1MyLlJCOwoJZmxvYXQyIGR4eSA9IG1heChtYXgoZHh5MCwgZHh5MSksIDAuMCk7CgloYWxmIGFscGhhID0gaGFsZihzYXR1cmF0ZSh1cmFkaXVzUGx1c0hhbGZfUzIueCAtIGxlbmd0aChkeHkpKSk7CglyZXR1cm4gX2lucHV0ICogYWxwaGE7Cn0Kdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIENpcmNsZUdlb21ldHJ5UHJvY2Vzc29yCglmbG9hdDQgY2lyY2xlRWRnZTsKCWNpcmNsZUVkZ2UgPSB2aW5DaXJjbGVFZGdlX1MwOwoJaGFsZjQgb3V0cHV0Q29sb3JfUzA7CglvdXRwdXRDb2xvcl9TMCA9IHZpbkNvbG9yX1MwOwoJZmxvYXQgZCA9IGxlbmd0aChjaXJjbGVFZGdlLnh5KTsKCWhhbGYgZGlzdGFuY2VUb091dGVyRWRnZSA9IGhhbGYoY2lyY2xlRWRnZS56ICogKDEuMCAtIGQpKTsKCWhhbGYgZWRnZUFscGhhID0gc2F0dXJhdGUoZGlzdGFuY2VUb091dGVyRWRnZSk7CgloYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KGVkZ2VBbHBoYSk7CgloYWxmNCBvdXRwdXRfUzE7CglvdXRwdXRfUzEgPSBDaXJjdWxhclJSZWN0X1MxKG91dHB1dENvdmVyYWdlX1MwKTsKCWhhbGY0IG91dHB1dF9TMjsKCW91dHB1dF9TMiA9IENpcmN1bGFyUlJlY3RfUzIob3V0cHV0X1MxKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dF9TMjsKCX0KfQoAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAADAAAACgAAAGluUG9zaXRpb24AAAcAAABpbkNvbG9yAAwAAABpbkNpcmNsZUVkZ2UAAAAA","HVIAAAAAABIAAGAAAQ4AAAH477776R24EAAAIOBQAD6P7777777777YDAAAAAAAAAAAGIBIAAABAAAAANAEAAAAAAAAAAAAAABAAOAAAABAAAAAAABBAMAAAAA":"CgAAAExTS1N0AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBoYWxmNCBjb2xvcjsKaW4gZmxvYXQyIGxvY2FsQ29vcmQ7CmZsYXQgb3V0IGhhbGY0IHZjb2xvcl9TMDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgl2Y29sb3JfUzAgPSBjb2xvcjsKCXNrX1Bvc2l0aW9uID0gcG9zaXRpb24ueHkwMTsKCXsKCQl2VHJhbnNmb3JtZWRDb29yZHNfMl9TMCA9IGZsb2F0M3gyKHVtYXRyaXhfUzEpICogbG9jYWxDb29yZC54eTE7Cgl9Cn0KAAAAAHMCAAB1bmlmb3JtIGZsb2F0M3gzIHVtYXRyaXhfUzE7CnVuaWZvcm0gc2FtcGxlcjJEIHVUZXh0dXJlU2FtcGxlcl8wX1MxOwpmbGF0IGluIGhhbGY0IHZjb2xvcl9TMDsKaW4gZmxvYXQyIHZUcmFuc2Zvcm1lZENvb3Jkc18yX1MwOwpoYWxmNCBUZXh0dXJlRWZmZWN0X1MxX2MwKGhhbGY0IF9pbnB1dCkgCnsKCXJldHVybiBzYW1wbGUodVRleHR1cmVTYW1wbGVyXzBfUzEsIHZUcmFuc2Zvcm1lZENvb3Jkc18yX1MwKS5ycnJyOwp9CmhhbGY0IE1hdHJpeEVmZmVjdF9TMShoYWxmNCBfaW5wdXQpIAp7CglyZXR1cm4gVGV4dHVyZUVmZmVjdF9TMV9jMChfaW5wdXQpOwp9CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBRdWFkUGVyRWRnZUFBR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2Y29sb3JfUzA7Cgljb25zdCBoYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KDEpOwoJaGFsZjQgb3V0cHV0X1MxOwoJb3V0cHV0X1MxID0gTWF0cml4RWZmZWN0X1MxKG91dHB1dENvdmVyYWdlX1MwKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dF9TMTsKCX0KfQoAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAIAAAAcG9zaXRpb24FAAAAY29sb3IAAAAKAAAAbG9jYWxDb29yZAAAAAAAAA==","HWQACAAAABAAADAAAIOAAAAADIIAAIRODAAP577774DSAIAA737777YBAAAAAAAAAAAHEADZAAAAAAIAAAAAAOQAAAAAAAQAAAABAMQAAAAAA":"CgAAAExTS1ONAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gZmxvYXQgY292ZXJhZ2U7CmluIGhhbGY0IGNvbG9yOwppbiBmbG9hdDQgZ2VvbVN1YnNldDsKZmxhdCBvdXQgaGFsZjQgdmNvbG9yX1MwOwpvdXQgZmxvYXQgdmNvdmVyYWdlX1MwOwpmbGF0IG91dCBmbG9hdDQgdmdlb21TdWJzZXRfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJZmxvYXQyIHBvc2l0aW9uID0gcG9zaXRpb24ueHk7Cgl2Y29sb3JfUzAgPSBjb2xvcjsKCXZjb3ZlcmFnZV9TMCA9IGNvdmVyYWdlOwoJdmdlb21TdWJzZXRfUzAgPSBnZW9tU3Vic2V0OwoJc2tfUG9zaXRpb24gPSBwb3NpdGlvbi54eTAxOwp9CgAAAAEAAAAIBAAAdW5pZm9ybSBmbG9hdDQgdWlubmVyUmVjdF9TMTsKdW5pZm9ybSBoYWxmMiB1cmFkaXVzUGx1c0hhbGZfUzE7CmZsYXQgaW4gaGFsZjQgdmNvbG9yX1MwOwppbiBmbG9hdCB2Y292ZXJhZ2VfUzA7CmZsYXQgaW4gZmxvYXQ0IHZnZW9tU3Vic2V0X1MwOwpoYWxmNCBDaXJjdWxhclJSZWN0X1MxKGhhbGY0IF9pbnB1dCkgCnsKCWZsb2F0MiBkeHkwID0gdWlubmVyUmVjdF9TMS5MVCAtIHNrX0ZyYWdDb29yZC54eTsKCWZsb2F0MiBkeHkxID0gc2tfRnJhZ0Nvb3JkLnh5IC0gdWlubmVyUmVjdF9TMS5SQjsKCWZsb2F0MiBkeHkgPSBtYXgobWF4KGR4eTAsIGR4eTEpLCAwLjApOwoJaGFsZiBhbHBoYSA9IGhhbGYoc2F0dXJhdGUodXJhZGl1c1BsdXNIYWxmX1MxLnggLSBsZW5ndGgoZHh5KSkpOwoJcmV0dXJuIF9pbnB1dCAqIGFscGhhOwp9CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBRdWFkUGVyRWRnZUFBR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2Y29sb3JfUzA7CglmbG9hdCBjb3ZlcmFnZSA9IHZjb3ZlcmFnZV9TMDsKCWZsb2F0NCBnZW9TdWJzZXQ7CglnZW9TdWJzZXQgPSB2Z2VvbVN1YnNldF9TMDsKCWhhbGY0IGRpc3RzNCA9IGNsYW1wKGhhbGY0KDEsIDEsIC0xLCAtMSkgKiBoYWxmNChza19GcmFnQ29vcmQueHl4eSAtIGdlb1N1YnNldCksIDAsIDEpOwoJaGFsZjIgZGlzdHMyID0gZGlzdHM0Lnh5ICsgZGlzdHM0Lnp3IC0gMTsKCWhhbGYgc3Vic2V0Q292ZXJhZ2UgPSBkaXN0czIueCAqIGRpc3RzMi55OwoJY292ZXJhZ2UgPSBtaW4oY292ZXJhZ2UsIHN1YnNldENvdmVyYWdlKTsKCWhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoaGFsZihjb3ZlcmFnZSkpOwoJaGFsZjQgb3V0cHV0X1MxOwoJb3V0cHV0X1MxID0gQ2lyY3VsYXJSUmVjdF9TMShvdXRwdXRDb3ZlcmFnZV9TMCk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRfUzE7Cgl9Cn0KAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAIAAAAcG9zaXRpb24IAAAAY292ZXJhZ2UFAAAAY29sb3IAAAAKAAAAZ2VvbVN1YnNldAAAAAAAAA==","B2AAQAAABQAAIAABBYAAB7777777777774ABICAAAAAAAAAAAAAABUABAAAAAEAAAAAIBEABAAAAA":"CgAAAExTS1MOAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBpblBvc2l0aW9uOwppbiBoYWxmIGluQ292ZXJhZ2U7Cm91dCBoYWxmIHZpbkNvdmVyYWdlX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBEZWZhdWx0R2VvbWV0cnlQcm9jZXNzb3IKCWZsb2F0MiBfdG1wXzFfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247Cgl2aW5Db3ZlcmFnZV9TMCA9IGluQ292ZXJhZ2U7Cglza19Qb3NpdGlvbiA9IF90bXBfMV9pblBvc2l0aW9uLnh5MDE7Cn0KAAAAAAAATQEAAHVuaWZvcm0gaGFsZjQgdUNvbG9yX1MwOwppbiBoYWxmIHZpbkNvdmVyYWdlX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgRGVmYXVsdEdlb21ldHJ5UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdUNvbG9yX1MwOwoJaGFsZiBhbHBoYSA9IDEuMDsKCWFscGhhID0gdmluQ292ZXJhZ2VfUzA7CgloYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KGFscGhhKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAACAAAACgAAAGluUG9zaXRpb24AAAoAAABpbkNvdmVyYWdlAAAAAAAA","HUQACAAAAAMAADAAAIOAAAH677776IZOCAAP577777777777777777YBAAAAAAAAAAAKAAYAAAACAAAAAAACCAYAAA":"CgAAAExTS1PPAAAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gaGFsZjQgY29sb3I7Cm91dCBoYWxmNCB2Y29sb3JfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJdmNvbG9yX1MwID0gY29sb3I7Cglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cn0KAAAAAAAMAQAAaW4gaGFsZjQgdmNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdmNvbG9yX1MwOwoJY29uc3QgaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNCgxKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAACAAAACAAAAHBvc2l0aW9uBQAAAGNvbG9yAAAAAAAAAA==","HUQACAAAAAMAADAAAIOAAAH677776IZOCAAP577777777777777777YBAAAAAAAAAAAHEADZAAAAAAIAAAAAAOQAAAAAAAQAAAABAMQAAAAAA":"CgAAAExTS1PPAAAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gaGFsZjQgY29sb3I7Cm91dCBoYWxmNCB2Y29sb3JfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJdmNvbG9yX1MwID0gY29sb3I7Cglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cn0KAAEAAACbAgAAdW5pZm9ybSBmbG9hdDQgdWlubmVyUmVjdF9TMTsKdW5pZm9ybSBoYWxmMiB1cmFkaXVzUGx1c0hhbGZfUzE7CmluIGhhbGY0IHZjb2xvcl9TMDsKaGFsZjQgQ2lyY3VsYXJSUmVjdF9TMShoYWxmNCBfaW5wdXQpIAp7CglmbG9hdDIgZHh5MCA9IHVpbm5lclJlY3RfUzEuTFQgLSBza19GcmFnQ29vcmQueHk7CglmbG9hdDIgZHh5MSA9IHNrX0ZyYWdDb29yZC54eSAtIHVpbm5lclJlY3RfUzEuUkI7CglmbG9hdDIgZHh5ID0gbWF4KG1heChkeHkwLCBkeHkxKSwgMC4wKTsKCWhhbGYgYWxwaGEgPSBoYWxmKHNhdHVyYXRlKHVyYWRpdXNQbHVzSGFsZl9TMS54IC0gbGVuZ3RoKGR4eSkpKTsKCXJldHVybiBfaW5wdXQgKiBhbHBoYTsKfQp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdmNvbG9yX1MwOwoJY29uc3QgaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNCgxKTsKCWhhbGY0IG91dHB1dF9TMTsKCW91dHB1dF9TMSA9IENpcmN1bGFyUlJlY3RfUzEob3V0cHV0Q292ZXJhZ2VfUzApOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dENvbG9yX1MwICogb3V0cHV0X1MxOwoJfQp9CgABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAgAAABwb3NpdGlvbgUAAABjb2xvcgAAAAAAAAA=","HVIAAAAAABIAAGAAAQ4AAAH477776R24EAAAIOBQAD6P7777777777YDAAAAAAAAAAAFQBQU7BTXIAAAAAAAAAACAAAAAVQEAAQAAAAAQCDAEQQGAAAAAAAAAAAA4IAPAAACAAAAAAAEABYAAAAEAAAAAAAEEBQA":"CgAAAExTS1N6AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMV9jMDsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBoYWxmNCBjb2xvcjsKaW4gZmxvYXQyIGxvY2FsQ29vcmQ7CmZsYXQgb3V0IGhhbGY0IHZjb2xvcl9TMDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfM19TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgl2Y29sb3JfUzAgPSBjb2xvcjsKCXNrX1Bvc2l0aW9uID0gcG9zaXRpb24ueHkwMTsKCXsKCQl2VHJhbnNmb3JtZWRDb29yZHNfM19TMCA9IGZsb2F0M3gyKHVtYXRyaXhfUzFfYzApICogbG9jYWxDb29yZC54eTE7Cgl9Cn0KAAABAAAArAQAAHVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMV9jMDsKdW5pZm9ybSBmbG9hdDQgdWlubmVyUmVjdF9TMjsKdW5pZm9ybSBoYWxmMiB1cmFkaXVzUGx1c0hhbGZfUzI7CnVuaWZvcm0gc2FtcGxlckV4dGVybmFsT0VTIHVUZXh0dXJlU2FtcGxlcl8wX1MxOwpmbGF0IGluIGhhbGY0IHZjb2xvcl9TMDsKaW4gZmxvYXQyIHZUcmFuc2Zvcm1lZENvb3Jkc18zX1MwOwpoYWxmNCBUZXh0dXJlRWZmZWN0X1MxX2MwX2MwKGhhbGY0IF9pbnB1dCkgCnsKCXJldHVybiBzYW1wbGUodVRleHR1cmVTYW1wbGVyXzBfUzEsIHZUcmFuc2Zvcm1lZENvb3Jkc18zX1MwKTsKfQpoYWxmNCBNYXRyaXhFZmZlY3RfUzFfYzAoaGFsZjQgX2lucHV0KSAKewoJcmV0dXJuIFRleHR1cmVFZmZlY3RfUzFfYzBfYzAoX2lucHV0KTsKfQpoYWxmNCBEaXNhYmxlQ292ZXJhZ2VBc0FscGhhX1MxKGhhbGY0IF9pbnB1dCkgCnsKCV9pbnB1dCA9IE1hdHJpeEVmZmVjdF9TMV9jMChfaW5wdXQpOwoJaGFsZjQgX3RtcF8wX2luQ29sb3IgPSBfaW5wdXQ7CglyZXR1cm4gaGFsZjQoX2lucHV0KTsKfQpoYWxmNCBDaXJjdWxhclJSZWN0X1MyKGhhbGY0IF9pbnB1dCkgCnsKCWZsb2F0MiBkeHkwID0gdWlubmVyUmVjdF9TMi5MVCAtIHNrX0ZyYWdDb29yZC54eTsKCWZsb2F0MiBkeHkxID0gc2tfRnJhZ0Nvb3JkLnh5IC0gdWlubmVyUmVjdF9TMi5SQjsKCWZsb2F0MiBkeHkgPSBtYXgobWF4KGR4eTAsIGR4eTEpLCAwLjApOwoJaGFsZiBhbHBoYSA9IGhhbGYoc2F0dXJhdGUodXJhZGl1c1BsdXNIYWxmX1MyLnggLSBsZW5ndGgoZHh5KSkpOwoJcmV0dXJuIF9pbnB1dCAqIGFscGhhOwp9CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBRdWFkUGVyRWRnZUFBR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2Y29sb3JfUzA7Cgljb25zdCBoYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KDEpOwoJaGFsZjQgb3V0cHV0X1MxOwoJb3V0cHV0X1MxID0gRGlzYWJsZUNvdmVyYWdlQXNBbHBoYV9TMShvdXRwdXRDb2xvcl9TMCk7CgloYWxmNCBvdXRwdXRfUzI7CglvdXRwdXRfUzIgPSBDaXJjdWxhclJSZWN0X1MyKG91dHB1dENvdmVyYWdlX1MwKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRfUzEgKiBvdXRwdXRfUzI7Cgl9Cn0KAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAIAAAAcG9zaXRpb24FAAAAY29sb3IAAAAKAAAAbG9jYWxDb29yZAAAAAAAAA==","FAAQMYAAMAAAEADAAABAEYAAAICIAB5AABQAAAQAMAAAEATAAABAIIGAAEDCBYQCA4AAAAAAEAB5AAAAACQHEB4XIQAQAADQAAAABAAAAAAABAEMVDOMCJKRAAAAAHAAAAAAAAAAACQAGAAAAAQAAAAAAAQQGAAA":"CgAAAExTS1PUCwAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0NCByYWRpaV9zZWxlY3RvcjsKaW4gZmxvYXQ0IGNvcm5lcl9hbmRfcmFkaXVzX291dHNldHM7CmluIGZsb2F0NCBhYV9ibG9hdF9hbmRfY292ZXJhZ2U7CmluIGZsb2F0NCByYWRpaV94OwppbiBmbG9hdDQgcmFkaWlfeTsKaW4gZmxvYXQ0IHNrZXc7CmluIGZsb2F0MiB0cmFuc2xhdGVfYW5kX2xvY2Fscm90YXRlOwppbiBoYWxmNCBjb2xvcjsKZmxhdCBvdXQgaGFsZjQgdmNvbG9yX1MwOwpvdXQgZmxvYXQyIHZhcmNjb29yZF9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgRmlsbFJSZWN0T3A6OlByb2Nlc3NvcgoJdmNvbG9yX1MwID0gY29sb3I7CglmbG9hdCBhYV9ibG9hdF9tdWx0aXBsaWVyID0gMTsKCWZsb2F0MiBjb3JuZXIgPSBjb3JuZXJfYW5kX3JhZGl1c19vdXRzZXRzLnh5OwoJZmxvYXQyIHJhZGl1c19vdXRzZXQgPSBjb3JuZXJfYW5kX3JhZGl1c19vdXRzZXRzLnp3OwoJZmxvYXQyIGFhX2Jsb2F0X2RpcmVjdGlvbiA9IGFhX2Jsb2F0X2FuZF9jb3ZlcmFnZS54eTsKCWZsb2F0IGlzX2xpbmVhcl9jb3ZlcmFnZSA9IGFhX2Jsb2F0X2FuZF9jb3ZlcmFnZS53OwoJZmxvYXQyIHBpeGVsbGVuZ3RoID0gaW52ZXJzZXNxcnQoZmxvYXQyKGRvdChza2V3Lnh6LCBza2V3Lnh6KSwgZG90KHNrZXcueXcsIHNrZXcueXcpKSk7CglmbG9hdDQgbm9ybWFsaXplZF9heGlzX2RpcnMgPSBza2V3ICogcGl4ZWxsZW5ndGgueHl4eTsKCWZsb2F0MiBheGlzd2lkdGhzID0gKGFicyhub3JtYWxpemVkX2F4aXNfZGlycy54eSkgKyBhYnMobm9ybWFsaXplZF9heGlzX2RpcnMuencpKTsKCWZsb2F0MiBhYV9ibG9hdHJhZGl1cyA9IGF4aXN3aWR0aHMgKiBwaXhlbGxlbmd0aCAqIC41OwoJZmxvYXQ0IHJhZGlpX2FuZF9uZWlnaGJvcnMgPSByYWRpaV9zZWxlY3RvciogZmxvYXQ0eDQocmFkaWlfeCwgcmFkaWlfeSwgcmFkaWlfeC55eHd6LCByYWRpaV95Lnd6eXgpOwoJZmxvYXQyIHJhZGlpID0gcmFkaWlfYW5kX25laWdoYm9ycy54eTsKCWZsb2F0MiBuZWlnaGJvcl9yYWRpaSA9IHJhZGlpX2FuZF9uZWlnaGJvcnMuenc7CglmbG9hdCBjb3ZlcmFnZV9tdWx0aXBsaWVyID0gMTsKCWlmIChhbnkoZ3JlYXRlclRoYW4oYWFfYmxvYXRyYWRpdXMsIGZsb2F0MigxKSkpKSAKCXsKCQljb3JuZXIgPSBtYXgoYWJzKGNvcm5lciksIGFhX2Jsb2F0cmFkaXVzKSAqIHNpZ24oY29ybmVyKTsKCQljb3ZlcmFnZV9tdWx0aXBsaWVyID0gMSAvIChtYXgoYWFfYmxvYXRyYWRpdXMueCwgMSkgKiBtYXgoYWFfYmxvYXRyYWRpdXMueSwgMSkpOwoJCXJhZGlpID0gZmxvYXQyKDApOwoJfQoJZmxvYXQgY292ZXJhZ2UgPSBhYV9ibG9hdF9hbmRfY292ZXJhZ2UuejsKCWlmIChhbnkobGVzc1RoYW4ocmFkaWksIGFhX2Jsb2F0cmFkaXVzICogMS41KSkpIAoJewoJCXJhZGlpID0gZmxvYXQyKDApOwoJCWFhX2Jsb2F0X2RpcmVjdGlvbiA9IHNpZ24oY29ybmVyKTsKCQlpZiAoY292ZXJhZ2UgPiAuNSkgCgkJewoJCQlhYV9ibG9hdF9kaXJlY3Rpb24gPSAtYWFfYmxvYXRfZGlyZWN0aW9uOwoJCX0KCQlpc19saW5lYXJfY292ZXJhZ2UgPSAxOwoJfQoJZWxzZSAKCXsKCQlyYWRpaSA9IGNsYW1wKHJhZGlpLCBwaXhlbGxlbmd0aCAqIDEuNSwgMiAtIHBpeGVsbGVuZ3RoICogMS41KTsKCQluZWlnaGJvcl9yYWRpaSA9IGNsYW1wKG5laWdoYm9yX3JhZGlpLCBwaXhlbGxlbmd0aCAqIDEuNSwgMiAtIHBpeGVsbGVuZ3RoICogMS41KTsKCQlmbG9hdDIgc3BhY2luZyA9IDIgLSByYWRpaSAtIG5laWdoYm9yX3JhZGlpOwoJCWZsb2F0MiBleHRyYV9wYWQgPSBtYXgocGl4ZWxsZW5ndGggKiAuMDYyNSAtIHNwYWNpbmcsIGZsb2F0MigwKSk7CgkJcmFkaWkgLT0gZXh0cmFfcGFkICogLjU7Cgl9CglmbG9hdDIgYWFfb3V0c2V0ID0gYWFfYmxvYXRfZGlyZWN0aW9uICogYWFfYmxvYXRyYWRpdXMgKiBhYV9ibG9hdF9tdWx0aXBsaWVyOwoJZmxvYXQyIHZlcnRleHBvcyA9IGNvcm5lciArIHJhZGl1c19vdXRzZXQgKiByYWRpaSArIGFhX291dHNldDsKCWlmIChjb3ZlcmFnZSA+IC41KSAKCXsKCQlpZiAoYWFfYmxvYXRfZGlyZWN0aW9uLnggIT0gMCAmJiB2ZXJ0ZXhwb3MueCAqIGNvcm5lci54IDwgMCkgCgkJewoJCQlmbG9hdCBiYWNrc2V0ID0gYWJzKHZlcnRleHBvcy54KTsKCQkJdmVydGV4cG9zLnggPSAwOwoJCQl2ZXJ0ZXhwb3MueSArPSBiYWNrc2V0ICogc2lnbihjb3JuZXIueSkgKiBwaXhlbGxlbmd0aC55L3BpeGVsbGVuZ3RoLng7CgkJCWNvdmVyYWdlID0gKGNvdmVyYWdlIC0gLjUpICogYWJzKGNvcm5lci54KSAvIChhYnMoY29ybmVyLngpICsgYmFja3NldCkgKyAuNTsKCQl9CgkJaWYgKGFhX2Jsb2F0X2RpcmVjdGlvbi55ICE9IDAgJiYgdmVydGV4cG9zLnkgKiBjb3JuZXIueSA8IDApIAoJCXsKCQkJZmxvYXQgYmFja3NldCA9IGFicyh2ZXJ0ZXhwb3MueSk7CgkJCXZlcnRleHBvcy55ID0gMDsKCQkJdmVydGV4cG9zLnggKz0gYmFja3NldCAqIHNpZ24oY29ybmVyLngpICogcGl4ZWxsZW5ndGgueC9waXhlbGxlbmd0aC55OwoJCQljb3ZlcmFnZSA9IChjb3ZlcmFnZSAtIC41KSAqIGFicyhjb3JuZXIueSkgLyAoYWJzKGNvcm5lci55KSArIGJhY2tzZXQpICsgLjU7CgkJfQoJfQoJZmxvYXQyeDIgc2tld21hdHJpeCA9IGZsb2F0MngyKHNrZXcueHksIHNrZXcuencpOwoJZmxvYXQyIGRldmNvb3JkID0gdmVydGV4cG9zICogc2tld21hdHJpeCArIHRyYW5zbGF0ZV9hbmRfbG9jYWxyb3RhdGUueHk7CglpZiAoMCAhPSBpc19saW5lYXJfY292ZXJhZ2UpIAoJewoJCXZhcmNjb29yZF9TMC54eSA9IGZsb2F0MigwLCBjb3ZlcmFnZSAqIGNvdmVyYWdlX211bHRpcGxpZXIpOwoJfQoJZWxzZSAKCXsKCQlmbG9hdDIgYXJjY29vcmQgPSAxIC0gYWJzKHJhZGl1c19vdXRzZXQpICsgYWFfb3V0c2V0L3JhZGlpICogY29ybmVyOwoJCXZhcmNjb29yZF9TMC54eSA9IGZsb2F0MihhcmNjb29yZC54KzEsIGFyY2Nvb3JkLnkpOwoJfQoJc2tfUG9zaXRpb24gPSBkZXZjb29yZC54eTAxOwp9CgEAAABRBQAAY29uc3QgaW50IGtGaWxsQUFfUzFfYzAgPSAxOwpjb25zdCBpbnQga0ludmVyc2VGaWxsQldfUzFfYzAgPSAyOwpjb25zdCBpbnQga0ludmVyc2VGaWxsQUFfUzFfYzAgPSAzOwp1bmlmb3JtIGZsb2F0NCB1Y2lyY2xlX1MxX2MwOwpmbGF0IGluIGhhbGY0IHZjb2xvcl9TMDsKaW4gZmxvYXQyIHZhcmNjb29yZF9TMDsKaGFsZjQgQ2lyY2xlX1MxX2MwKGhhbGY0IF9pbnB1dCkgCnsKCWhhbGY0IF90bXBfMF9pbkNvbG9yID0gX2lucHV0OwoJaGFsZiBkOwoJaWYgKGludCgzKSA9PSBrSW52ZXJzZUZpbGxCV19TMV9jMCB8fCBpbnQoMykgPT0ga0ludmVyc2VGaWxsQUFfUzFfYzApIAoJewoJCWQgPSBoYWxmKChsZW5ndGgoKHVjaXJjbGVfUzFfYzAueHkgLSBza19GcmFnQ29vcmQueHkpICogdWNpcmNsZV9TMV9jMC53KSAtIDEuMCkgKiB1Y2lyY2xlX1MxX2MwLnopOwoJfQoJZWxzZSAKCXsKCQlkID0gaGFsZigoMS4wIC0gbGVuZ3RoKCh1Y2lyY2xlX1MxX2MwLnh5IC0gc2tfRnJhZ0Nvb3JkLnh5KSAqIHVjaXJjbGVfUzFfYzAudykpICogdWNpcmNsZV9TMV9jMC56KTsKCX0KCXJldHVybiBoYWxmNChoYWxmNChpbnQoMykgPT0ga0ZpbGxBQV9TMV9jMCB8fCBpbnQoMykgPT0ga0ludmVyc2VGaWxsQUFfUzFfYzAgPyBzYXR1cmF0ZShkKSA6IGhhbGYoZCA+IDAuNSA/IDEgOiAwKSkpOwp9CmhhbGY0IEJsZW5kX1MxKGhhbGY0IF9zcmMsIGhhbGY0IF9kc3QpIAp7CglyZXR1cm4gYmxlbmRfbW9kdWxhdGUoX3NyYywgQ2lyY2xlX1MxX2MwKF9zcmMpKTsKfQp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgRmlsbFJSZWN0T3A6OlByb2Nlc3NvcgoJaGFsZjQgb3V0cHV0Q29sb3JfUzA7CglvdXRwdXRDb2xvcl9TMCA9IHZjb2xvcl9TMDsKCWZsb2F0IHhfcGx1c18xPXZhcmNjb29yZF9TMC54LCB5PXZhcmNjb29yZF9TMC55OwoJaGFsZiBjb3ZlcmFnZTsKCWlmICgwID09IHhfcGx1c18xKSAKCXsKCQljb3ZlcmFnZSA9IGhhbGYoeSk7Cgl9CgllbHNlIAoJewoJCWZsb2F0IGZuID0geF9wbHVzXzEgKiAoeF9wbHVzXzEgLSAyKTsKCQlmbiA9IGZtYSh5LHksIGZuKTsKCQlmbG9hdCBmbndpZHRoID0gZndpZHRoKGZuKTsKCQljb3ZlcmFnZSA9IC41IC0gaGFsZihmbi9mbndpZHRoKTsKCQljb3ZlcmFnZSA9IGNsYW1wKGNvdmVyYWdlLCAwLCAxKTsKCX0KCWhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoY292ZXJhZ2UpOwoJaGFsZjQgb3V0cHV0X1MxOwoJb3V0cHV0X1MxID0gQmxlbmRfUzEob3V0cHV0Q292ZXJhZ2VfUzAsIGhhbGY0KDEpKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dF9TMTsKCX0KfQoAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAACAAAAA4AAAByYWRpaV9zZWxlY3RvcgAAGQAAAGNvcm5lcl9hbmRfcmFkaXVzX291dHNldHMAAAAVAAAAYWFfYmxvYXRfYW5kX2NvdmVyYWdlAAAABwAAAHJhZGlpX3gABwAAAHJhZGlpX3kABAAAAHNrZXcZAAAAdHJhbnNsYXRlX2FuZF9sb2NhbHJvdGF0ZQAAAAUAAABjb2xvcgAAAAAAAAA=","GEMAAAYAAEHAAAARC4EAAAQWBQAAAAAAAAAQAAAAIBCAAAGQAEAAAAAQAAAABAEQAEAAAAA":"CgAAAExTS1NUAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBpblBvc2l0aW9uOwppbiBoYWxmNCBpbkNvbG9yOwppbiBoYWxmMyBpblNoYWRvd1BhcmFtczsKb3V0IGhhbGYzIHZpblNoYWRvd1BhcmFtc19TMDsKb3V0IGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBSUmVjdFNoYWRvdwoJdmluU2hhZG93UGFyYW1zX1MwID0gaW5TaGFkb3dQYXJhbXM7Cgl2aW5Db2xvcl9TMCA9IGluQ29sb3I7CglmbG9hdDIgX3RtcF8wX2luUG9zaXRpb24gPSBpblBvc2l0aW9uOwoJc2tfUG9zaXRpb24gPSBfdG1wXzBfaW5Qb3NpdGlvbi54eTAxOwp9CgAAAAALAgAAdW5pZm9ybSBzYW1wbGVyMkQgdVRleHR1cmVTYW1wbGVyXzBfUzA7CmluIGhhbGYzIHZpblNoYWRvd1BhcmFtc19TMDsKaW4gaGFsZjQgdmluQ29sb3JfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBSUmVjdFNoYWRvdwoJaGFsZjMgc2hhZG93UGFyYW1zOwoJc2hhZG93UGFyYW1zID0gdmluU2hhZG93UGFyYW1zX1MwOwoJaGFsZjQgb3V0cHV0Q29sb3JfUzA7CglvdXRwdXRDb2xvcl9TMCA9IHZpbkNvbG9yX1MwOwoJaGFsZiBkID0gbGVuZ3RoKHNoYWRvd1BhcmFtcy54eSk7CglmbG9hdDIgdXYgPSBmbG9hdDIoc2hhZG93UGFyYW1zLnogKiAoMS4wIC0gZCksIDAuNSk7CgloYWxmIGZhY3RvciA9IHNhbXBsZSh1VGV4dHVyZVNhbXBsZXJfMF9TMCwgdXYpLjAwMHIuYTsKCWhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoZmFjdG9yKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAoAAABpblBvc2l0aW9uAAAHAAAAaW5Db2xvcgAOAAAAaW5TaGFkb3dQYXJhbXMAAAAAAAA=","AYQA5AADQAAAOAEARAFQJAABBADIB7777777777777777777777767YAAAAAAAAAACABYQA6AAAEAAAAAAAIADQAAAAIAAAAAAAIIDA":"CgAAAExTS1PMAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQ0IHVsb2NhbE1hdHJpeF9TMDsKaW4gZmxvYXQyIGluUG9zaXRpb247CmluIGhhbGY0IGluQ29sb3I7CmluIGZsb2F0NCBpbkNpcmNsZUVkZ2U7Cm91dCBmbG9hdDQgdmluQ2lyY2xlRWRnZV9TMDsKb3V0IGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBDaXJjbGVHZW9tZXRyeVByb2Nlc3NvcgoJdmluQ2lyY2xlRWRnZV9TMCA9IGluQ2lyY2xlRWRnZTsKCXZpbkNvbG9yX1MwID0gaW5Db2xvcjsKCWZsb2F0MiBfdG1wXzBfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247CglmbG9hdDIgX3RtcF8xX2luUG9zaXRpb24gPSB1bG9jYWxNYXRyaXhfUzAueHogKiBpblBvc2l0aW9uICsgdWxvY2FsTWF0cml4X1MwLnl3OwoJc2tfUG9zaXRpb24gPSBfdG1wXzBfaW5Qb3NpdGlvbi54eTAxOwp9CgEAAAB5AwAAdW5pZm9ybSBmbG9hdDQgdWlubmVyUmVjdF9TMTsKdW5pZm9ybSBoYWxmMiB1cmFkaXVzUGx1c0hhbGZfUzE7CmluIGZsb2F0NCB2aW5DaXJjbGVFZGdlX1MwOwppbiBoYWxmNCB2aW5Db2xvcl9TMDsKaGFsZjQgQ2lyY3VsYXJSUmVjdF9TMShoYWxmNCBfaW5wdXQpIAp7CglmbG9hdDIgZHh5MCA9IHVpbm5lclJlY3RfUzEuTFQgLSBza19GcmFnQ29vcmQueHk7CglmbG9hdDIgZHh5MSA9IHNrX0ZyYWdDb29yZC54eSAtIHVpbm5lclJlY3RfUzEuUkI7CglmbG9hdDIgZHh5ID0gbWF4KG1heChkeHkwLCBkeHkxKSwgMC4wKTsKCWhhbGYgYWxwaGEgPSBoYWxmKHNhdHVyYXRlKHVyYWRpdXNQbHVzSGFsZl9TMS54IC0gbGVuZ3RoKGR4eSkpKTsKCXJldHVybiBfaW5wdXQgKiBhbHBoYTsKfQp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgQ2lyY2xlR2VvbWV0cnlQcm9jZXNzb3IKCWZsb2F0NCBjaXJjbGVFZGdlOwoJY2lyY2xlRWRnZSA9IHZpbkNpcmNsZUVkZ2VfUzA7CgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdmluQ29sb3JfUzA7CglmbG9hdCBkID0gbGVuZ3RoKGNpcmNsZUVkZ2UueHkpOwoJaGFsZiBkaXN0YW5jZVRvT3V0ZXJFZGdlID0gaGFsZihjaXJjbGVFZGdlLnogKiAoMS4wIC0gZCkpOwoJaGFsZiBlZGdlQWxwaGEgPSBzYXR1cmF0ZShkaXN0YW5jZVRvT3V0ZXJFZGdlKTsKCWhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoZWRnZUFscGhhKTsKCWhhbGY0IG91dHB1dF9TMTsKCW91dHB1dF9TMSA9IENpcmN1bGFyUlJlY3RfUzEob3V0cHV0Q292ZXJhZ2VfUzApOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dENvbG9yX1MwICogb3V0cHV0X1MxOwoJfQp9CgAAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAADAAAACgAAAGluUG9zaXRpb24AAAcAAABpbkNvbG9yAAwAAABpbkNpcmNsZUVkZ2UAAAAA","HVIACAAAABQAAGAAAQ4AAAAAGQQAARC4GAAAIOCAAD6P7777777777YDAAAAAAAAAAAFIBQU7BTXIAAAAAACAAAAAAQFV5W6JEAAAAAYAAAABQEZ2AKAWAQAABAL6SYKDYAAAACAAAAAAQEGIAAAAACAWTWL3EYAAAADAAAAACADHIJJCYCAAAEAP2LRIPAAAAAIAAAAAAABTALI3F5SOAIAABQAAAAAABTUEUZMBAAAAAH5FYUXQAAAAAAAEAAAAAZMRGOQCQFQEAAAAAAAAAGARL2LXJHAAEAAAAAEAAAABSCQX5FQUHQAAAAAAAAAACAA4AAAABAACAAAACCAYAAAAA":"CgAAAExTS1PrAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMV9jMF9jMF9jMTsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBmbG9hdCBjb3ZlcmFnZTsKaW4gaGFsZjQgY29sb3I7CmluIGZsb2F0MiBsb2NhbENvb3JkOwpmbGF0IG91dCBoYWxmNCB2Y29sb3JfUzA7Cm91dCBmbG9hdCB2Y292ZXJhZ2VfUzA7Cm91dCBmbG9hdDIgdlRyYW5zZm9ybWVkQ29vcmRzXzZfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJZmxvYXQyIHBvc2l0aW9uID0gcG9zaXRpb24ueHk7Cgl2Y29sb3JfUzAgPSBjb2xvcjsKCXZjb3ZlcmFnZV9TMCA9IGNvdmVyYWdlOwoJc2tfUG9zaXRpb24gPSBwb3NpdGlvbi54eTAxOwoJewoJCXZUcmFuc2Zvcm1lZENvb3Jkc182X1MwID0gZmxvYXQzeDIodW1hdHJpeF9TMV9jMF9jMF9jMSkgKiBsb2NhbENvb3JkLnh5MTsKCX0KfQoAAAAAAMMHAAB1bmlmb3JtIGhhbGY0IHVzdGFydF9TMV9jMF9jMF9jMDsKdW5pZm9ybSBoYWxmNCB1ZW5kX1MxX2MwX2MwX2MwOwp1bmlmb3JtIGZsb2F0M3gzIHVtYXRyaXhfUzFfYzBfYzBfYzE7CnVuaWZvcm0gaGFsZjQgdWxlZnRCb3JkZXJDb2xvcl9TMV9jMF9jMDsKdW5pZm9ybSBoYWxmNCB1cmlnaHRCb3JkZXJDb2xvcl9TMV9jMF9jMDsKZmxhdCBpbiBoYWxmNCB2Y29sb3JfUzA7CmluIGZsb2F0IHZjb3ZlcmFnZV9TMDsKaW4gZmxvYXQyIHZUcmFuc2Zvcm1lZENvb3Jkc182X1MwOwpoYWxmNCBTaW5nbGVJbnRlcnZhbENvbG9yaXplcl9TMV9jMF9jMF9jMChoYWxmNCBfaW5wdXQsIGZsb2F0MiBfY29vcmRzKSAKewoJaGFsZjQgX3RtcF8wX2luQ29sb3IgPSBfaW5wdXQ7CglmbG9hdDIgX3RtcF8xX2Nvb3JkcyA9IF9jb29yZHM7CglyZXR1cm4gaGFsZjQobWl4KHVzdGFydF9TMV9jMF9jMF9jMCwgdWVuZF9TMV9jMF9jMF9jMCwgaGFsZihfdG1wXzFfY29vcmRzLngpKSk7Cn0KaGFsZjQgTGluZWFyTGF5b3V0X1MxX2MwX2MwX2MxX2MwKGhhbGY0IF9pbnB1dCkgCnsKCWhhbGY0IF90bXBfMl9pbkNvbG9yID0gX2lucHV0OwoJZmxvYXQyIF90bXBfM19jb29yZHMgPSB2VHJhbnNmb3JtZWRDb29yZHNfNl9TMDsKCXJldHVybiBoYWxmNChoYWxmNChoYWxmKF90bXBfM19jb29yZHMueCkgKyAxZS0wNSwgMS4wLCAwLjAsIDAuMCkpOwp9CmhhbGY0IE1hdHJpeEVmZmVjdF9TMV9jMF9jMF9jMShoYWxmNCBfaW5wdXQpIAp7CglyZXR1cm4gTGluZWFyTGF5b3V0X1MxX2MwX2MwX2MxX2MwKF9pbnB1dCk7Cn0KaGFsZjQgQ2xhbXBlZEdyYWRpZW50X1MxX2MwX2MwKGhhbGY0IF9pbnB1dCkgCnsKCWhhbGY0IF90bXBfNF9pbkNvbG9yID0gX2lucHV0OwoJaGFsZjQgdCA9IE1hdHJpeEVmZmVjdF9TMV9jMF9jMF9jMShfdG1wXzRfaW5Db2xvcik7CgloYWxmNCBvdXRDb2xvcjsKCWlmICghYm9vbChpbnQoMSkpICYmIHQueSA8IDAuMCkgCgl7CgkJb3V0Q29sb3IgPSBoYWxmNCgwLjApOwoJfQoJZWxzZSBpZiAodC54IDwgMC4wKSAKCXsKCQlvdXRDb2xvciA9IHVsZWZ0Qm9yZGVyQ29sb3JfUzFfYzBfYzA7Cgl9CgllbHNlIGlmICh0LnggPiAxLjApIAoJewoJCW91dENvbG9yID0gdXJpZ2h0Qm9yZGVyQ29sb3JfUzFfYzBfYzA7Cgl9CgllbHNlIAoJewoJCW91dENvbG9yID0gU2luZ2xlSW50ZXJ2YWxDb2xvcml6ZXJfUzFfYzBfYzBfYzAoX3RtcF80X2luQ29sb3IsIGZsb2F0MihoYWxmMih0LngsIDAuMCkpKTsKCX0KCXJldHVybiBoYWxmNChvdXRDb2xvcik7Cn0KaGFsZjQgY29sb3JfeGZvcm1fUzFfYzAoZmxvYXQ0IGNvbG9yKSAKewoJY29sb3IucmdiICo9IGNvbG9yLmE7CglyZXR1cm4gaGFsZjQoY29sb3IpOwp9CmhhbGY0IENvbG9yU3BhY2VYZm9ybV9TMV9jMChoYWxmNCBfaW5wdXQpIAp7CglyZXR1cm4gY29sb3JfeGZvcm1fUzFfYzAoQ2xhbXBlZEdyYWRpZW50X1MxX2MwX2MwKF9pbnB1dCkpOwp9CmhhbGY0IERpc2FibGVDb3ZlcmFnZUFzQWxwaGFfUzEoaGFsZjQgX2lucHV0KSAKewoJX2lucHV0ID0gQ29sb3JTcGFjZVhmb3JtX1MxX2MwKF9pbnB1dCk7CgloYWxmNCBfdG1wXzVfaW5Db2xvciA9IF9pbnB1dDsKCXJldHVybiBoYWxmNChfaW5wdXQpOwp9CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBRdWFkUGVyRWRnZUFBR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2Y29sb3JfUzA7CglmbG9hdCBjb3ZlcmFnZSA9IHZjb3ZlcmFnZV9TMDsKCWhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoaGFsZihjb3ZlcmFnZSkpOwoJaGFsZjQgb3V0cHV0X1MxOwoJb3V0cHV0X1MxID0gRGlzYWJsZUNvdmVyYWdlQXNBbHBoYV9TMShvdXRwdXRDb2xvcl9TMCk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gKGhhbGY0KDEuMCkgLSBvdXRwdXRfUzEpICogb3V0cHV0Q292ZXJhZ2VfUzA7Cgl9Cn0KAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAEAAAACAAAAHBvc2l0aW9uCAAAAGNvdmVyYWdlBQAAAGNvbG9yAAAACgAAAGxvY2FsQ29vcmQAAAAAAAA=","HUQAAAAAAAMAADAAAIOAAAH677776IZOCAAP577777777777777777YBAAAAAAAAAAAKAAYAAAACAAAAAAACCAYAAA":"CgAAAExTS1PUAAAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gaGFsZjQgY29sb3I7CmZsYXQgb3V0IGhhbGY0IHZjb2xvcl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgl2Y29sb3JfUzAgPSBjb2xvcjsKCXNrX1Bvc2l0aW9uID0gcG9zaXRpb24ueHkwMTsKfQoAAAAAEQEAAGZsYXQgaW4gaGFsZjQgdmNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdmNvbG9yX1MwOwoJY29uc3QgaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNCgxKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAACAAAACAAAAHBvc2l0aW9uBQAAAGNvbG9yAAAAAAAAAA==","HUQAAAAAAAMAADAAAIOAAAH677776IZOCAAP577777777777777777YBAAAAAAAAAAADEAANAAAAALHCKLMRAAAAAAAAABAAAAAGJBCFLQVBWAQAAAAAAQAAAAAMACQCAACAAAAA2AIBAEIAAAAAAAAAAAAIADQAAAAIAAAAAAAIIDAAAAAA":"CgAAAExTS1PUAAAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gaGFsZjQgY29sb3I7CmZsYXQgb3V0IGhhbGY0IHZjb2xvcl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgl2Y29sb3JfUzAgPSBjb2xvcjsKCXNrX1Bvc2l0aW9uID0gcG9zaXRpb24ueHkwMTsKfQoBAAAAeAQAAHVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMV9jMF9jMDsKdW5pZm9ybSBoYWxmNCB1Y2lyY2xlRGF0YV9TMV9jMDsKdW5pZm9ybSBzYW1wbGVyMkQgdVRleHR1cmVTYW1wbGVyXzBfUzE7CmZsYXQgaW4gaGFsZjQgdmNvbG9yX1MwOwpoYWxmNCBUZXh0dXJlRWZmZWN0X1MxX2MwX2MwX2MwKGhhbGY0IF9pbnB1dCwgZmxvYXQyIF9jb29yZHMpIAp7CglyZXR1cm4gc2FtcGxlKHVUZXh0dXJlU2FtcGxlcl8wX1MxLCBfY29vcmRzKS4wMDByOwp9CmhhbGY0IE1hdHJpeEVmZmVjdF9TMV9jMF9jMChoYWxmNCBfaW5wdXQsIGZsb2F0MiBfY29vcmRzKSAKewoJcmV0dXJuIFRleHR1cmVFZmZlY3RfUzFfYzBfYzBfYzAoX2lucHV0LCBmbG9hdDN4Mih1bWF0cml4X1MxX2MwX2MwKSAqIF9jb29yZHMueHkxKTsKfQpoYWxmNCBDaXJjbGVCbHVyX1MxX2MwKGhhbGY0IF9pbnB1dCkgCnsKCWhhbGY0IF90bXBfMF9pbkNvbG9yID0gX2lucHV0OwoJaGFsZjIgdmVjID0gaGFsZjIoKHNrX0ZyYWdDb29yZC54eSAtIGZsb2F0Mih1Y2lyY2xlRGF0YV9TMV9jMC54eSkpICogZmxvYXQodWNpcmNsZURhdGFfUzFfYzAudykpOwoJaGFsZiBkaXN0ID0gbGVuZ3RoKHZlYykgKyAoMC41IC0gdWNpcmNsZURhdGFfUzFfYzAueikgKiB1Y2lyY2xlRGF0YV9TMV9jMC53OwoJcmV0dXJuIGhhbGY0KE1hdHJpeEVmZmVjdF9TMV9jMF9jMChfdG1wXzBfaW5Db2xvciwgZmxvYXQyKGhhbGYyKGRpc3QsIDAuNSkpKS53d3d3KTsKfQpoYWxmNCBCbGVuZF9TMShoYWxmNCBfc3JjLCBoYWxmNCBfZHN0KSAKewoJcmV0dXJuIGJsZW5kX21vZHVsYXRlKENpcmNsZUJsdXJfUzFfYzAoX3NyYyksIF9zcmMpOwp9CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBRdWFkUGVyRWRnZUFBR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2Y29sb3JfUzA7Cgljb25zdCBoYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KDEpOwoJaGFsZjQgb3V0cHV0X1MxOwoJb3V0cHV0X1MxID0gQmxlbmRfUzEob3V0cHV0Q292ZXJhZ2VfUzAsIGhhbGY0KDEpKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dF9TMTsKCX0KfQoBAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAgAAABwb3NpdGlvbgUAAABjb2xvcgAAAAAAAAA=","HWQACAAAABAAADAAAIOAAAAADIIAAIRODAAP577774DSAIAA737777YBAAAAAAAAAAAKAAYAAAACAAAAAAACCAYAAA":"CgAAAExTS1ONAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gZmxvYXQgY292ZXJhZ2U7CmluIGhhbGY0IGNvbG9yOwppbiBmbG9hdDQgZ2VvbVN1YnNldDsKZmxhdCBvdXQgaGFsZjQgdmNvbG9yX1MwOwpvdXQgZmxvYXQgdmNvdmVyYWdlX1MwOwpmbGF0IG91dCBmbG9hdDQgdmdlb21TdWJzZXRfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJZmxvYXQyIHBvc2l0aW9uID0gcG9zaXRpb24ueHk7Cgl2Y29sb3JfUzAgPSBjb2xvcjsKCXZjb3ZlcmFnZV9TMCA9IGNvdmVyYWdlOwoJdmdlb21TdWJzZXRfUzAgPSBnZW9tU3Vic2V0OwoJc2tfUG9zaXRpb24gPSBwb3NpdGlvbi54eTAxOwp9CgAAAAEAAAB5AgAAZmxhdCBpbiBoYWxmNCB2Y29sb3JfUzA7CmluIGZsb2F0IHZjb3ZlcmFnZV9TMDsKZmxhdCBpbiBmbG9hdDQgdmdlb21TdWJzZXRfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBRdWFkUGVyRWRnZUFBR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2Y29sb3JfUzA7CglmbG9hdCBjb3ZlcmFnZSA9IHZjb3ZlcmFnZV9TMDsKCWZsb2F0NCBnZW9TdWJzZXQ7CglnZW9TdWJzZXQgPSB2Z2VvbVN1YnNldF9TMDsKCWhhbGY0IGRpc3RzNCA9IGNsYW1wKGhhbGY0KDEsIDEsIC0xLCAtMSkgKiBoYWxmNChza19GcmFnQ29vcmQueHl4eSAtIGdlb1N1YnNldCksIDAsIDEpOwoJaGFsZjIgZGlzdHMyID0gZGlzdHM0Lnh5ICsgZGlzdHM0Lnp3IC0gMTsKCWhhbGYgc3Vic2V0Q292ZXJhZ2UgPSBkaXN0czIueCAqIGRpc3RzMi55OwoJY292ZXJhZ2UgPSBtaW4oY292ZXJhZ2UsIHN1YnNldENvdmVyYWdlKTsKCWhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoaGFsZihjb3ZlcmFnZSkpOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dENvbG9yX1MwICogb3V0cHV0Q292ZXJhZ2VfUzA7Cgl9Cn0KAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAIAAAAcG9zaXRpb24IAAAAY292ZXJhZ2UFAAAAY29sb3IAAAAKAAAAZ2VvbVN1YnNldAAAAAAAAA==","DAQAAAAAAABGAABAYAAQAIHCAIAYAQUBAEAAAAAAEAAAAAAAAAAAAIAD2AAAAAAQAVSWGRIBAAADAAAAACAAAAAAQCGEIQOZLBIQAAAABQAAAAAAAAAAAAFAAMAAAABAAAAAAABBAMAAA":"CgAAAExTS1MWAgAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQyIHVBdGxhc1NpemVJbnZfUzA7CmluIGZsb2F0MiBpblBvc2l0aW9uOwppbiBoYWxmNCBpbkNvbG9yOwppbiB1c2hvcnQyIGluVGV4dHVyZUNvb3JkczsKb3V0IGZsb2F0MiB2VGV4dHVyZUNvb3Jkc19TMDsKZmxhdCBvdXQgZmxvYXQgdlRleEluZGV4X1MwOwpvdXQgaGFsZjQgdmluQ29sb3JfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIEJpdG1hcFRleHQKCWludCB0ZXhJZHggPSAwOwoJZmxvYXQyIHVub3JtVGV4Q29vcmRzID0gZmxvYXQyKGluVGV4dHVyZUNvb3Jkcy54LCBpblRleHR1cmVDb29yZHMueSk7Cgl2VGV4dHVyZUNvb3Jkc19TMCA9IHVub3JtVGV4Q29vcmRzICogdUF0bGFzU2l6ZUludl9TMDsKCXZUZXhJbmRleF9TMCA9IGZsb2F0KHRleElkeCk7Cgl2aW5Db2xvcl9TMCA9IGluQ29sb3I7CglmbG9hdDIgX3RtcF8xX2luUG9zaXRpb24gPSBpblBvc2l0aW9uOwoJc2tfUG9zaXRpb24gPSBpblBvc2l0aW9uLnh5MDE7Cn0KAAABAAAARQUAAGNvbnN0IGludCBrRmlsbEJXX1MxX2MwID0gMDsKY29uc3QgaW50IGtJbnZlcnNlRmlsbEJXX1MxX2MwID0gMjsKY29uc3QgaW50IGtJbnZlcnNlRmlsbEFBX1MxX2MwID0gMzsKdW5pZm9ybSBmbG9hdDQgdXJlY3RVbmlmb3JtX1MxX2MwOwp1bmlmb3JtIHNhbXBsZXIyRCB1VGV4dHVyZVNhbXBsZXJfMF9TMDsKaW4gZmxvYXQyIHZUZXh0dXJlQ29vcmRzX1MwOwpmbGF0IGluIGZsb2F0IHZUZXhJbmRleF9TMDsKaW4gaGFsZjQgdmluQ29sb3JfUzA7CmhhbGY0IFJlY3RfUzFfYzAoaGFsZjQgX2lucHV0KSAKewoJaGFsZjQgX3RtcF8wX2luQ29sb3IgPSBfaW5wdXQ7CgloYWxmIGNvdmVyYWdlOwoJaWYgKGludCgxKSA9PSBrRmlsbEJXX1MxX2MwIHx8IGludCgxKSA9PSBrSW52ZXJzZUZpbGxCV19TMV9jMCkgCgl7CgkJY292ZXJhZ2UgPSBoYWxmKGFsbChncmVhdGVyVGhhbihmbG9hdDQoc2tfRnJhZ0Nvb3JkLnh5LCB1cmVjdFVuaWZvcm1fUzFfYzAuencpLCBmbG9hdDQodXJlY3RVbmlmb3JtX1MxX2MwLnh5LCBza19GcmFnQ29vcmQueHkpKSkpOwoJfQoJZWxzZSAKCXsKCQloYWxmNCBkaXN0czQgPSBzYXR1cmF0ZShoYWxmNCgxLjAsIDEuMCwgLTEuMCwgLTEuMCkgKiBoYWxmNChza19GcmFnQ29vcmQueHl4eSAtIHVyZWN0VW5pZm9ybV9TMV9jMCkpOwoJCWhhbGYyIGRpc3RzMiA9IChkaXN0czQueHkgKyBkaXN0czQuencpIC0gMS4wOwoJCWNvdmVyYWdlID0gZGlzdHMyLnggKiBkaXN0czIueTsKCX0KCWlmIChpbnQoMSkgPT0ga0ludmVyc2VGaWxsQldfUzFfYzAgfHwgaW50KDEpID09IGtJbnZlcnNlRmlsbEFBX1MxX2MwKSAKCXsKCQljb3ZlcmFnZSA9IDEuMCAtIGNvdmVyYWdlOwoJfQoJcmV0dXJuIGhhbGY0KGhhbGY0KGNvdmVyYWdlKSk7Cn0KaGFsZjQgQmxlbmRfUzEoaGFsZjQgX3NyYywgaGFsZjQgX2RzdCkgCnsKCXJldHVybiBibGVuZF9tb2R1bGF0ZShSZWN0X1MxX2MwKF9zcmMpLCBfc3JjKTsKfQp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgQml0bWFwVGV4dAoJaGFsZjQgb3V0cHV0Q29sb3JfUzA7CglvdXRwdXRDb2xvcl9TMCA9IHZpbkNvbG9yX1MwOwoJaGFsZjQgdGV4Q29sb3I7Cgl7CgkJdGV4Q29sb3IgPSBzYW1wbGUodVRleHR1cmVTYW1wbGVyXzBfUzAsIHZUZXh0dXJlQ29vcmRzX1MwKS5ycnJyOwoJfQoJaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSB0ZXhDb2xvcjsKCWhhbGY0IG91dHB1dF9TMTsKCW91dHB1dF9TMSA9IEJsZW5kX1MxKG91dHB1dENvdmVyYWdlX1MwLCBoYWxmNCgxKSk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRfUzE7Cgl9Cn0KAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAKAAAAaW5Qb3NpdGlvbgAABwAAAGluQ29sb3IADwAAAGluVGV4dHVyZUNvb3JkcwAAAAAA"}} \ No newline at end of file +{"platform":"android","name":"SM G970N","engineRevision":"1837b5be5f0f1376a1ccf383950e83a80177fb4e","data":{"HWQACAAAABAAADAAAIOAAAAADIIAAIRODAAP577774DSAIAA737777YBAAAAAAAAAAAHEADZAAAAAAIAAAAAAOQAAAAAAAQAAAABAMQAAAAAA":"CgAAAExTS1ONAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gZmxvYXQgY292ZXJhZ2U7CmluIGhhbGY0IGNvbG9yOwppbiBmbG9hdDQgZ2VvbVN1YnNldDsKZmxhdCBvdXQgaGFsZjQgdmNvbG9yX1MwOwpvdXQgZmxvYXQgdmNvdmVyYWdlX1MwOwpmbGF0IG91dCBmbG9hdDQgdmdlb21TdWJzZXRfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJZmxvYXQyIHBvc2l0aW9uID0gcG9zaXRpb24ueHk7Cgl2Y29sb3JfUzAgPSBjb2xvcjsKCXZjb3ZlcmFnZV9TMCA9IGNvdmVyYWdlOwoJdmdlb21TdWJzZXRfUzAgPSBnZW9tU3Vic2V0OwoJc2tfUG9zaXRpb24gPSBwb3NpdGlvbi54eTAxOwp9CgAAAAEAAAAIBAAAdW5pZm9ybSBmbG9hdDQgdWlubmVyUmVjdF9TMTsKdW5pZm9ybSBoYWxmMiB1cmFkaXVzUGx1c0hhbGZfUzE7CmZsYXQgaW4gaGFsZjQgdmNvbG9yX1MwOwppbiBmbG9hdCB2Y292ZXJhZ2VfUzA7CmZsYXQgaW4gZmxvYXQ0IHZnZW9tU3Vic2V0X1MwOwpoYWxmNCBDaXJjdWxhclJSZWN0X1MxKGhhbGY0IF9pbnB1dCkgCnsKCWZsb2F0MiBkeHkwID0gdWlubmVyUmVjdF9TMS5MVCAtIHNrX0ZyYWdDb29yZC54eTsKCWZsb2F0MiBkeHkxID0gc2tfRnJhZ0Nvb3JkLnh5IC0gdWlubmVyUmVjdF9TMS5SQjsKCWZsb2F0MiBkeHkgPSBtYXgobWF4KGR4eTAsIGR4eTEpLCAwLjApOwoJaGFsZiBhbHBoYSA9IGhhbGYoc2F0dXJhdGUodXJhZGl1c1BsdXNIYWxmX1MxLnggLSBsZW5ndGgoZHh5KSkpOwoJcmV0dXJuIF9pbnB1dCAqIGFscGhhOwp9CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBRdWFkUGVyRWRnZUFBR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2Y29sb3JfUzA7CglmbG9hdCBjb3ZlcmFnZSA9IHZjb3ZlcmFnZV9TMDsKCWZsb2F0NCBnZW9TdWJzZXQ7CglnZW9TdWJzZXQgPSB2Z2VvbVN1YnNldF9TMDsKCWhhbGY0IGRpc3RzNCA9IGNsYW1wKGhhbGY0KDEsIDEsIC0xLCAtMSkgKiBoYWxmNChza19GcmFnQ29vcmQueHl4eSAtIGdlb1N1YnNldCksIDAsIDEpOwoJaGFsZjIgZGlzdHMyID0gZGlzdHM0Lnh5ICsgZGlzdHM0Lnp3IC0gMTsKCWhhbGYgc3Vic2V0Q292ZXJhZ2UgPSBkaXN0czIueCAqIGRpc3RzMi55OwoJY292ZXJhZ2UgPSBtaW4oY292ZXJhZ2UsIHN1YnNldENvdmVyYWdlKTsKCWhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoaGFsZihjb3ZlcmFnZSkpOwoJaGFsZjQgb3V0cHV0X1MxOwoJb3V0cHV0X1MxID0gQ2lyY3VsYXJSUmVjdF9TMShvdXRwdXRDb3ZlcmFnZV9TMCk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRfUzE7Cgl9Cn0KAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAIAAAAcG9zaXRpb24IAAAAY292ZXJhZ2UFAAAAY29sb3IAAAAKAAAAZ2VvbVN1YnNldAAAAAAAAA==","HUQAAAAAAAMAADAAAIOAAAH677776IZOCAAP577777777777777777YBAAAAAAAAAAAHEADZAAAAAAIAAAAAAOQAAAAAAAQAAAABAMQAAAAAA":"CgAAAExTS1PUAAAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gaGFsZjQgY29sb3I7CmZsYXQgb3V0IGhhbGY0IHZjb2xvcl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgl2Y29sb3JfUzAgPSBjb2xvcjsKCXNrX1Bvc2l0aW9uID0gcG9zaXRpb24ueHkwMTsKfQoBAAAAoAIAAHVuaWZvcm0gZmxvYXQ0IHVpbm5lclJlY3RfUzE7CnVuaWZvcm0gaGFsZjIgdXJhZGl1c1BsdXNIYWxmX1MxOwpmbGF0IGluIGhhbGY0IHZjb2xvcl9TMDsKaGFsZjQgQ2lyY3VsYXJSUmVjdF9TMShoYWxmNCBfaW5wdXQpIAp7CglmbG9hdDIgZHh5MCA9IHVpbm5lclJlY3RfUzEuTFQgLSBza19GcmFnQ29vcmQueHk7CglmbG9hdDIgZHh5MSA9IHNrX0ZyYWdDb29yZC54eSAtIHVpbm5lclJlY3RfUzEuUkI7CglmbG9hdDIgZHh5ID0gbWF4KG1heChkeHkwLCBkeHkxKSwgMC4wKTsKCWhhbGYgYWxwaGEgPSBoYWxmKHNhdHVyYXRlKHVyYWRpdXNQbHVzSGFsZl9TMS54IC0gbGVuZ3RoKGR4eSkpKTsKCXJldHVybiBfaW5wdXQgKiBhbHBoYTsKfQp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdmNvbG9yX1MwOwoJY29uc3QgaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNCgxKTsKCWhhbGY0IG91dHB1dF9TMTsKCW91dHB1dF9TMSA9IENpcmN1bGFyUlJlY3RfUzEob3V0cHV0Q292ZXJhZ2VfUzApOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dENvbG9yX1MwICogb3V0cHV0X1MxOwoJfQp9CgEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAACAAAACAAAAHBvc2l0aW9uBQAAAGNvbG9yAAAAAAAAAA==","HVJAAAAAABIAAGAAAQ4AAAH477776R24EAAAIOBQAD6P7777777777YDAAAAABAAAAAABBAMABAAOAAAABAAAAAAABBAMAAA":"CgAAAExTS1MjAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gaGFsZjQgY29sb3I7CmluIGZsb2F0MiBsb2NhbENvb3JkOwpmbGF0IG91dCBoYWxmNCB2Y29sb3JfUzA7Cm91dCBmbG9hdDIgdmxvY2FsQ29vcmRfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJdmNvbG9yX1MwID0gY29sb3I7Cgl2bG9jYWxDb29yZF9TMCA9IGxvY2FsQ29vcmQ7Cglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cn0KAAAAAADQAQAAdW5pZm9ybSBzYW1wbGVyMkQgdVRleHR1cmVTYW1wbGVyXzBfUzA7CmZsYXQgaW4gaGFsZjQgdmNvbG9yX1MwOwppbiBmbG9hdDIgdmxvY2FsQ29vcmRfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBRdWFkUGVyRWRnZUFBR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2Y29sb3JfUzA7CglmbG9hdDIgdGV4Q29vcmQ7Cgl0ZXhDb29yZCA9IHZsb2NhbENvb3JkX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSAoKHNhbXBsZSh1VGV4dHVyZVNhbXBsZXJfMF9TMCwgdGV4Q29vcmQpICogb3V0cHV0Q29sb3JfUzApKTsKCWNvbnN0IGhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoMSk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRDb3ZlcmFnZV9TMDsKCX0KfQoAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAgAAABwb3NpdGlvbgUAAABjb2xvcgAAAAoAAABsb2NhbENvb3JkAAAAAAAA","HUJAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAQAAAAAAQQGACQAGAAAAAQAAAAAAAQQGAAA":"CgAAAExTS1PlAAAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gZmxvYXQyIGxvY2FsQ29vcmQ7Cm91dCBmbG9hdDIgdmxvY2FsQ29vcmRfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJdmxvY2FsQ29vcmRfUzAgPSBsb2NhbENvb3JkOwoJc2tfUG9zaXRpb24gPSBwb3NpdGlvbi54eTAxOwp9CgAAAAAAAACfAQAAdW5pZm9ybSBzYW1wbGVyMkQgdVRleHR1cmVTYW1wbGVyXzBfUzA7CmluIGZsb2F0MiB2bG9jYWxDb29yZF9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJaGFsZjQgb3V0cHV0Q29sb3JfUzAgPSBoYWxmNCgxKTsKCWZsb2F0MiB0ZXhDb29yZDsKCXRleENvb3JkID0gdmxvY2FsQ29vcmRfUzA7CglvdXRwdXRDb2xvcl9TMCA9ICgoc2FtcGxlKHVUZXh0dXJlU2FtcGxlcl8wX1MwLCB0ZXhDb29yZCkgKiBoYWxmNCgxKSkpOwoJY29uc3QgaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNCgxKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAgAAABwb3NpdGlvbgoAAABsb2NhbENvb3JkAAAAAAAA","HUIAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAAAAAALUAQBAAAQAAAAGQCBAMQACAAAAAAAACQAGAAAAAQAAAAAAAQQGAAAAA":"CgAAAExTS1M2AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBmbG9hdDIgbG9jYWxDb29yZDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cgl7CgkJdlRyYW5zZm9ybWVkQ29vcmRzXzJfUzAgPSBmbG9hdDN4Mih1bWF0cml4X1MxKSAqIGxvY2FsQ29vcmQueHkxOwoJfQp9CgAAAAAAAHADAAB1bmlmb3JtIGZsb2F0NCB1Y2xhbXBfUzFfYzA7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKdW5pZm9ybSBzYW1wbGVyMkQgdVRleHR1cmVTYW1wbGVyXzBfUzE7CmluIGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKaGFsZjQgVGV4dHVyZUVmZmVjdF9TMV9jMChoYWxmNCBfaW5wdXQpIAp7CglmbG9hdDIgaW5Db29yZCA9IHZUcmFuc2Zvcm1lZENvb3Jkc18yX1MwOwoJZmxvYXQyIHN1YnNldENvb3JkOwoJc3Vic2V0Q29vcmQueCA9IGluQ29vcmQueDsKCXN1YnNldENvb3JkLnkgPSBpbkNvb3JkLnk7CglmbG9hdDIgY2xhbXBlZENvb3JkOwoJY2xhbXBlZENvb3JkLnggPSBjbGFtcChzdWJzZXRDb29yZC54LCB1Y2xhbXBfUzFfYzAueCwgdWNsYW1wX1MxX2MwLnopOwoJY2xhbXBlZENvb3JkLnkgPSBzdWJzZXRDb29yZC55OwoJaGFsZjQgdGV4dHVyZUNvbG9yID0gc2FtcGxlKHVUZXh0dXJlU2FtcGxlcl8wX1MxLCBjbGFtcGVkQ29vcmQpOwoJcmV0dXJuIHRleHR1cmVDb2xvcjsKfQpoYWxmNCBNYXRyaXhFZmZlY3RfUzEoaGFsZjQgX2lucHV0KSAKewoJcmV0dXJuIFRleHR1cmVFZmZlY3RfUzFfYzAoX2lucHV0KTsKfQp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMCA9IGhhbGY0KDEpOwoJY29uc3QgaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNCgxKTsKCWhhbGY0IG91dHB1dF9TMTsKCW91dHB1dF9TMSA9IE1hdHJpeEVmZmVjdF9TMShvdXRwdXRDb2xvcl9TMCk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0X1MxICogb3V0cHV0Q292ZXJhZ2VfUzA7Cgl9Cn0KAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAIAAAAcG9zaXRpb24KAAAAbG9jYWxDb29yZAAAAAAAAA==","HVIAAAAAABIAAGAAAQ4AAAH477776R24EAAAIOBQAD6P7777777777YDAAAAAAAAAAAFQBQU7BTXIAAAAAAAAAACAAAAAVQEAAQAAAAAQCDAEQQGAAAAAAAAAAAA4IAPAAACAAAAAAAEABYAAAAEAAAAAAAEEBQA":"CgAAAExTS1N6AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMV9jMDsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBoYWxmNCBjb2xvcjsKaW4gZmxvYXQyIGxvY2FsQ29vcmQ7CmZsYXQgb3V0IGhhbGY0IHZjb2xvcl9TMDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfM19TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgl2Y29sb3JfUzAgPSBjb2xvcjsKCXNrX1Bvc2l0aW9uID0gcG9zaXRpb24ueHkwMTsKCXsKCQl2VHJhbnNmb3JtZWRDb29yZHNfM19TMCA9IGZsb2F0M3gyKHVtYXRyaXhfUzFfYzApICogbG9jYWxDb29yZC54eTE7Cgl9Cn0KAAABAAAArAQAAHVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMV9jMDsKdW5pZm9ybSBmbG9hdDQgdWlubmVyUmVjdF9TMjsKdW5pZm9ybSBoYWxmMiB1cmFkaXVzUGx1c0hhbGZfUzI7CnVuaWZvcm0gc2FtcGxlckV4dGVybmFsT0VTIHVUZXh0dXJlU2FtcGxlcl8wX1MxOwpmbGF0IGluIGhhbGY0IHZjb2xvcl9TMDsKaW4gZmxvYXQyIHZUcmFuc2Zvcm1lZENvb3Jkc18zX1MwOwpoYWxmNCBUZXh0dXJlRWZmZWN0X1MxX2MwX2MwKGhhbGY0IF9pbnB1dCkgCnsKCXJldHVybiBzYW1wbGUodVRleHR1cmVTYW1wbGVyXzBfUzEsIHZUcmFuc2Zvcm1lZENvb3Jkc18zX1MwKTsKfQpoYWxmNCBNYXRyaXhFZmZlY3RfUzFfYzAoaGFsZjQgX2lucHV0KSAKewoJcmV0dXJuIFRleHR1cmVFZmZlY3RfUzFfYzBfYzAoX2lucHV0KTsKfQpoYWxmNCBEaXNhYmxlQ292ZXJhZ2VBc0FscGhhX1MxKGhhbGY0IF9pbnB1dCkgCnsKCV9pbnB1dCA9IE1hdHJpeEVmZmVjdF9TMV9jMChfaW5wdXQpOwoJaGFsZjQgX3RtcF8wX2luQ29sb3IgPSBfaW5wdXQ7CglyZXR1cm4gaGFsZjQoX2lucHV0KTsKfQpoYWxmNCBDaXJjdWxhclJSZWN0X1MyKGhhbGY0IF9pbnB1dCkgCnsKCWZsb2F0MiBkeHkwID0gdWlubmVyUmVjdF9TMi5MVCAtIHNrX0ZyYWdDb29yZC54eTsKCWZsb2F0MiBkeHkxID0gc2tfRnJhZ0Nvb3JkLnh5IC0gdWlubmVyUmVjdF9TMi5SQjsKCWZsb2F0MiBkeHkgPSBtYXgobWF4KGR4eTAsIGR4eTEpLCAwLjApOwoJaGFsZiBhbHBoYSA9IGhhbGYoc2F0dXJhdGUodXJhZGl1c1BsdXNIYWxmX1MyLnggLSBsZW5ndGgoZHh5KSkpOwoJcmV0dXJuIF9pbnB1dCAqIGFscGhhOwp9CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBRdWFkUGVyRWRnZUFBR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2Y29sb3JfUzA7Cgljb25zdCBoYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KDEpOwoJaGFsZjQgb3V0cHV0X1MxOwoJb3V0cHV0X1MxID0gRGlzYWJsZUNvdmVyYWdlQXNBbHBoYV9TMShvdXRwdXRDb2xvcl9TMCk7CgloYWxmNCBvdXRwdXRfUzI7CglvdXRwdXRfUzIgPSBDaXJjdWxhclJSZWN0X1MyKG91dHB1dENvdmVyYWdlX1MwKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRfUzEgKiBvdXRwdXRfUzI7Cgl9Cn0KAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAIAAAAcG9zaXRpb24FAAAAY29sb3IAAAAKAAAAbG9jYWxDb29yZAAAAAAAAA==","HUIAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAAAAAALUAQAAEAQAAAAGQCBAMQAAAIAAAAAACQAGAAAAAQAAAAAAAQQGAAAAA":"CgAAAExTS1M2AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBmbG9hdDIgbG9jYWxDb29yZDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cgl7CgkJdlRyYW5zZm9ybWVkQ29vcmRzXzJfUzAgPSBmbG9hdDN4Mih1bWF0cml4X1MxKSAqIGxvY2FsQ29vcmQueHkxOwoJfQp9CgAAAAAAAHADAAB1bmlmb3JtIGZsb2F0NCB1Y2xhbXBfUzFfYzA7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKdW5pZm9ybSBzYW1wbGVyMkQgdVRleHR1cmVTYW1wbGVyXzBfUzE7CmluIGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKaGFsZjQgVGV4dHVyZUVmZmVjdF9TMV9jMChoYWxmNCBfaW5wdXQpIAp7CglmbG9hdDIgaW5Db29yZCA9IHZUcmFuc2Zvcm1lZENvb3Jkc18yX1MwOwoJZmxvYXQyIHN1YnNldENvb3JkOwoJc3Vic2V0Q29vcmQueCA9IGluQ29vcmQueDsKCXN1YnNldENvb3JkLnkgPSBpbkNvb3JkLnk7CglmbG9hdDIgY2xhbXBlZENvb3JkOwoJY2xhbXBlZENvb3JkLnggPSBzdWJzZXRDb29yZC54OwoJY2xhbXBlZENvb3JkLnkgPSBjbGFtcChzdWJzZXRDb29yZC55LCB1Y2xhbXBfUzFfYzAueSwgdWNsYW1wX1MxX2MwLncpOwoJaGFsZjQgdGV4dHVyZUNvbG9yID0gc2FtcGxlKHVUZXh0dXJlU2FtcGxlcl8wX1MxLCBjbGFtcGVkQ29vcmQpOwoJcmV0dXJuIHRleHR1cmVDb2xvcjsKfQpoYWxmNCBNYXRyaXhFZmZlY3RfUzEoaGFsZjQgX2lucHV0KSAKewoJcmV0dXJuIFRleHR1cmVFZmZlY3RfUzFfYzAoX2lucHV0KTsKfQp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMCA9IGhhbGY0KDEpOwoJY29uc3QgaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNCgxKTsKCWhhbGY0IG91dHB1dF9TMTsKCW91dHB1dF9TMSA9IE1hdHJpeEVmZmVjdF9TMShvdXRwdXRDb2xvcl9TMCk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0X1MxICogb3V0cHV0Q292ZXJhZ2VfUzA7Cgl9Cn0KAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAIAAAAcG9zaXRpb24KAAAAbG9jYWxDb29yZAAAAAAAAA==","AYQA5AADQAAAOAEARAFQJAABBADIB7777777777777777777777767YAAAAAAAAAAAAOQAAAAAAAQAAAABAMQAAAAA":"CgAAAExTS1PMAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQ0IHVsb2NhbE1hdHJpeF9TMDsKaW4gZmxvYXQyIGluUG9zaXRpb247CmluIGhhbGY0IGluQ29sb3I7CmluIGZsb2F0NCBpbkNpcmNsZUVkZ2U7Cm91dCBmbG9hdDQgdmluQ2lyY2xlRWRnZV9TMDsKb3V0IGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBDaXJjbGVHZW9tZXRyeVByb2Nlc3NvcgoJdmluQ2lyY2xlRWRnZV9TMCA9IGluQ2lyY2xlRWRnZTsKCXZpbkNvbG9yX1MwID0gaW5Db2xvcjsKCWZsb2F0MiBfdG1wXzBfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247CglmbG9hdDIgX3RtcF8xX2luUG9zaXRpb24gPSB1bG9jYWxNYXRyaXhfUzAueHogKiBpblBvc2l0aW9uICsgdWxvY2FsTWF0cml4X1MwLnl3OwoJc2tfUG9zaXRpb24gPSBfdG1wXzBfaW5Qb3NpdGlvbi54eTAxOwp9CgAAAADqAQAAaW4gZmxvYXQ0IHZpbkNpcmNsZUVkZ2VfUzA7CmluIGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgQ2lyY2xlR2VvbWV0cnlQcm9jZXNzb3IKCWZsb2F0NCBjaXJjbGVFZGdlOwoJY2lyY2xlRWRnZSA9IHZpbkNpcmNsZUVkZ2VfUzA7CgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdmluQ29sb3JfUzA7CglmbG9hdCBkID0gbGVuZ3RoKGNpcmNsZUVkZ2UueHkpOwoJaGFsZiBkaXN0YW5jZVRvT3V0ZXJFZGdlID0gaGFsZihjaXJjbGVFZGdlLnogKiAoMS4wIC0gZCkpOwoJaGFsZiBlZGdlQWxwaGEgPSBzYXR1cmF0ZShkaXN0YW5jZVRvT3V0ZXJFZGdlKTsKCWhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoZWRnZUFscGhhKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAKAAAAaW5Qb3NpdGlvbgAABwAAAGluQ29sb3IADAAAAGluQ2lyY2xlRWRnZQAAAAA=","DASAAAAAQAAWAABAYAAQBYH7777Z6QQBAEAAAAAAEAAAAAAAEBSAAAB2AAAAAAACAAAAAEBSAAAAA":"CgAAAExTS1PVAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQyIHVBdGxhc1NpemVJbnZfUzA7CmluIGZsb2F0MiBpblBvc2l0aW9uOwppbiB1c2hvcnQyIGluVGV4dHVyZUNvb3JkczsKb3V0IGZsb2F0MiB2VGV4dHVyZUNvb3Jkc19TMDsKZmxhdCBvdXQgZmxvYXQgdlRleEluZGV4X1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBCaXRtYXBUZXh0CglpbnQgdGV4SWR4ID0gMDsKCWZsb2F0MiB1bm9ybVRleENvb3JkcyA9IGZsb2F0MihpblRleHR1cmVDb29yZHMueCwgaW5UZXh0dXJlQ29vcmRzLnkpOwoJdlRleHR1cmVDb29yZHNfUzAgPSB1bm9ybVRleENvb3JkcyAqIHVBdGxhc1NpemVJbnZfUzA7Cgl2VGV4SW5kZXhfUzAgPSBmbG9hdCh0ZXhJZHgpOwoJZmxvYXQyIF90bXBfMV9pblBvc2l0aW9uID0gaW5Qb3NpdGlvbjsKCXNrX1Bvc2l0aW9uID0gaW5Qb3NpdGlvbi54eTAxOwp9CgAAAAAAAADgAQAAdW5pZm9ybSBoYWxmNCB1Q29sb3JfUzA7CnVuaWZvcm0gc2FtcGxlcjJEIHVUZXh0dXJlU2FtcGxlcl8wX1MwOwppbiBmbG9hdDIgdlRleHR1cmVDb29yZHNfUzA7CmZsYXQgaW4gZmxvYXQgdlRleEluZGV4X1MwOwp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgQml0bWFwVGV4dAoJaGFsZjQgb3V0cHV0Q29sb3JfUzA7CglvdXRwdXRDb2xvcl9TMCA9IHVDb2xvcl9TMDsKCWhhbGY0IHRleENvbG9yOwoJewoJCXRleENvbG9yID0gc2FtcGxlKHVUZXh0dXJlU2FtcGxlcl8wX1MwLCB2VGV4dHVyZUNvb3Jkc19TMCk7Cgl9CglvdXRwdXRDb2xvcl9TMCA9IG91dHB1dENvbG9yX1MwICogdGV4Q29sb3I7Cgljb25zdCBoYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KDEpOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dENvbG9yX1MwICogb3V0cHV0Q292ZXJhZ2VfUzA7Cgl9Cn0KAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAKAAAAaW5Qb3NpdGlvbgAADwAAAGluVGV4dHVyZUNvb3JkcwAAAAAA","AYQQ5AADQAAAOAEARAFQJAABBADIB7777777777777777777777767YAAAAAAAAAAAAOQAAAAAAAQAAAABAMQAAAAA":"CgAAAExTS1PMAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQ0IHVsb2NhbE1hdHJpeF9TMDsKaW4gZmxvYXQyIGluUG9zaXRpb247CmluIGhhbGY0IGluQ29sb3I7CmluIGZsb2F0NCBpbkNpcmNsZUVkZ2U7Cm91dCBmbG9hdDQgdmluQ2lyY2xlRWRnZV9TMDsKb3V0IGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBDaXJjbGVHZW9tZXRyeVByb2Nlc3NvcgoJdmluQ2lyY2xlRWRnZV9TMCA9IGluQ2lyY2xlRWRnZTsKCXZpbkNvbG9yX1MwID0gaW5Db2xvcjsKCWZsb2F0MiBfdG1wXzBfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247CglmbG9hdDIgX3RtcF8xX2luUG9zaXRpb24gPSB1bG9jYWxNYXRyaXhfUzAueHogKiBpblBvc2l0aW9uICsgdWxvY2FsTWF0cml4X1MwLnl3OwoJc2tfUG9zaXRpb24gPSBfdG1wXzBfaW5Qb3NpdGlvbi54eTAxOwp9CgAAAAB7AgAAaW4gZmxvYXQ0IHZpbkNpcmNsZUVkZ2VfUzA7CmluIGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgQ2lyY2xlR2VvbWV0cnlQcm9jZXNzb3IKCWZsb2F0NCBjaXJjbGVFZGdlOwoJY2lyY2xlRWRnZSA9IHZpbkNpcmNsZUVkZ2VfUzA7CgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdmluQ29sb3JfUzA7CglmbG9hdCBkID0gbGVuZ3RoKGNpcmNsZUVkZ2UueHkpOwoJaGFsZiBkaXN0YW5jZVRvT3V0ZXJFZGdlID0gaGFsZihjaXJjbGVFZGdlLnogKiAoMS4wIC0gZCkpOwoJaGFsZiBlZGdlQWxwaGEgPSBzYXR1cmF0ZShkaXN0YW5jZVRvT3V0ZXJFZGdlKTsKCWhhbGYgZGlzdGFuY2VUb0lubmVyRWRnZSA9IGhhbGYoY2lyY2xlRWRnZS56ICogKGQgLSBjaXJjbGVFZGdlLncpKTsKCWhhbGYgaW5uZXJBbHBoYSA9IHNhdHVyYXRlKGRpc3RhbmNlVG9Jbm5lckVkZ2UpOwoJZWRnZUFscGhhICo9IGlubmVyQWxwaGE7CgloYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KGVkZ2VBbHBoYSk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRDb3ZlcmFnZV9TMDsKCX0KfQoAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAKAAAAaW5Qb3NpdGlvbgAABwAAAGluQ29sb3IADAAAAGluQ2lyY2xlRWRnZQAAAAA=","FAAQMYAAMAAAEADAAABAEYAAAICIAB5AABQAAAQAMAAAEATAAABAIIGAAEDCBYQCA4AAAAAAEADZABYAAAIAAAAAACQAGAAAAAQAAAAAAAQQG":"CgAAAExTS1PUCwAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0NCByYWRpaV9zZWxlY3RvcjsKaW4gZmxvYXQ0IGNvcm5lcl9hbmRfcmFkaXVzX291dHNldHM7CmluIGZsb2F0NCBhYV9ibG9hdF9hbmRfY292ZXJhZ2U7CmluIGZsb2F0NCByYWRpaV94OwppbiBmbG9hdDQgcmFkaWlfeTsKaW4gZmxvYXQ0IHNrZXc7CmluIGZsb2F0MiB0cmFuc2xhdGVfYW5kX2xvY2Fscm90YXRlOwppbiBoYWxmNCBjb2xvcjsKZmxhdCBvdXQgaGFsZjQgdmNvbG9yX1MwOwpvdXQgZmxvYXQyIHZhcmNjb29yZF9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgRmlsbFJSZWN0T3A6OlByb2Nlc3NvcgoJdmNvbG9yX1MwID0gY29sb3I7CglmbG9hdCBhYV9ibG9hdF9tdWx0aXBsaWVyID0gMTsKCWZsb2F0MiBjb3JuZXIgPSBjb3JuZXJfYW5kX3JhZGl1c19vdXRzZXRzLnh5OwoJZmxvYXQyIHJhZGl1c19vdXRzZXQgPSBjb3JuZXJfYW5kX3JhZGl1c19vdXRzZXRzLnp3OwoJZmxvYXQyIGFhX2Jsb2F0X2RpcmVjdGlvbiA9IGFhX2Jsb2F0X2FuZF9jb3ZlcmFnZS54eTsKCWZsb2F0IGlzX2xpbmVhcl9jb3ZlcmFnZSA9IGFhX2Jsb2F0X2FuZF9jb3ZlcmFnZS53OwoJZmxvYXQyIHBpeGVsbGVuZ3RoID0gaW52ZXJzZXNxcnQoZmxvYXQyKGRvdChza2V3Lnh6LCBza2V3Lnh6KSwgZG90KHNrZXcueXcsIHNrZXcueXcpKSk7CglmbG9hdDQgbm9ybWFsaXplZF9heGlzX2RpcnMgPSBza2V3ICogcGl4ZWxsZW5ndGgueHl4eTsKCWZsb2F0MiBheGlzd2lkdGhzID0gKGFicyhub3JtYWxpemVkX2F4aXNfZGlycy54eSkgKyBhYnMobm9ybWFsaXplZF9heGlzX2RpcnMuencpKTsKCWZsb2F0MiBhYV9ibG9hdHJhZGl1cyA9IGF4aXN3aWR0aHMgKiBwaXhlbGxlbmd0aCAqIC41OwoJZmxvYXQ0IHJhZGlpX2FuZF9uZWlnaGJvcnMgPSByYWRpaV9zZWxlY3RvciogZmxvYXQ0eDQocmFkaWlfeCwgcmFkaWlfeSwgcmFkaWlfeC55eHd6LCByYWRpaV95Lnd6eXgpOwoJZmxvYXQyIHJhZGlpID0gcmFkaWlfYW5kX25laWdoYm9ycy54eTsKCWZsb2F0MiBuZWlnaGJvcl9yYWRpaSA9IHJhZGlpX2FuZF9uZWlnaGJvcnMuenc7CglmbG9hdCBjb3ZlcmFnZV9tdWx0aXBsaWVyID0gMTsKCWlmIChhbnkoZ3JlYXRlclRoYW4oYWFfYmxvYXRyYWRpdXMsIGZsb2F0MigxKSkpKSAKCXsKCQljb3JuZXIgPSBtYXgoYWJzKGNvcm5lciksIGFhX2Jsb2F0cmFkaXVzKSAqIHNpZ24oY29ybmVyKTsKCQljb3ZlcmFnZV9tdWx0aXBsaWVyID0gMSAvIChtYXgoYWFfYmxvYXRyYWRpdXMueCwgMSkgKiBtYXgoYWFfYmxvYXRyYWRpdXMueSwgMSkpOwoJCXJhZGlpID0gZmxvYXQyKDApOwoJfQoJZmxvYXQgY292ZXJhZ2UgPSBhYV9ibG9hdF9hbmRfY292ZXJhZ2UuejsKCWlmIChhbnkobGVzc1RoYW4ocmFkaWksIGFhX2Jsb2F0cmFkaXVzICogMS41KSkpIAoJewoJCXJhZGlpID0gZmxvYXQyKDApOwoJCWFhX2Jsb2F0X2RpcmVjdGlvbiA9IHNpZ24oY29ybmVyKTsKCQlpZiAoY292ZXJhZ2UgPiAuNSkgCgkJewoJCQlhYV9ibG9hdF9kaXJlY3Rpb24gPSAtYWFfYmxvYXRfZGlyZWN0aW9uOwoJCX0KCQlpc19saW5lYXJfY292ZXJhZ2UgPSAxOwoJfQoJZWxzZSAKCXsKCQlyYWRpaSA9IGNsYW1wKHJhZGlpLCBwaXhlbGxlbmd0aCAqIDEuNSwgMiAtIHBpeGVsbGVuZ3RoICogMS41KTsKCQluZWlnaGJvcl9yYWRpaSA9IGNsYW1wKG5laWdoYm9yX3JhZGlpLCBwaXhlbGxlbmd0aCAqIDEuNSwgMiAtIHBpeGVsbGVuZ3RoICogMS41KTsKCQlmbG9hdDIgc3BhY2luZyA9IDIgLSByYWRpaSAtIG5laWdoYm9yX3JhZGlpOwoJCWZsb2F0MiBleHRyYV9wYWQgPSBtYXgocGl4ZWxsZW5ndGggKiAuMDYyNSAtIHNwYWNpbmcsIGZsb2F0MigwKSk7CgkJcmFkaWkgLT0gZXh0cmFfcGFkICogLjU7Cgl9CglmbG9hdDIgYWFfb3V0c2V0ID0gYWFfYmxvYXRfZGlyZWN0aW9uICogYWFfYmxvYXRyYWRpdXMgKiBhYV9ibG9hdF9tdWx0aXBsaWVyOwoJZmxvYXQyIHZlcnRleHBvcyA9IGNvcm5lciArIHJhZGl1c19vdXRzZXQgKiByYWRpaSArIGFhX291dHNldDsKCWlmIChjb3ZlcmFnZSA+IC41KSAKCXsKCQlpZiAoYWFfYmxvYXRfZGlyZWN0aW9uLnggIT0gMCAmJiB2ZXJ0ZXhwb3MueCAqIGNvcm5lci54IDwgMCkgCgkJewoJCQlmbG9hdCBiYWNrc2V0ID0gYWJzKHZlcnRleHBvcy54KTsKCQkJdmVydGV4cG9zLnggPSAwOwoJCQl2ZXJ0ZXhwb3MueSArPSBiYWNrc2V0ICogc2lnbihjb3JuZXIueSkgKiBwaXhlbGxlbmd0aC55L3BpeGVsbGVuZ3RoLng7CgkJCWNvdmVyYWdlID0gKGNvdmVyYWdlIC0gLjUpICogYWJzKGNvcm5lci54KSAvIChhYnMoY29ybmVyLngpICsgYmFja3NldCkgKyAuNTsKCQl9CgkJaWYgKGFhX2Jsb2F0X2RpcmVjdGlvbi55ICE9IDAgJiYgdmVydGV4cG9zLnkgKiBjb3JuZXIueSA8IDApIAoJCXsKCQkJZmxvYXQgYmFja3NldCA9IGFicyh2ZXJ0ZXhwb3MueSk7CgkJCXZlcnRleHBvcy55ID0gMDsKCQkJdmVydGV4cG9zLnggKz0gYmFja3NldCAqIHNpZ24oY29ybmVyLngpICogcGl4ZWxsZW5ndGgueC9waXhlbGxlbmd0aC55OwoJCQljb3ZlcmFnZSA9IChjb3ZlcmFnZSAtIC41KSAqIGFicyhjb3JuZXIueSkgLyAoYWJzKGNvcm5lci55KSArIGJhY2tzZXQpICsgLjU7CgkJfQoJfQoJZmxvYXQyeDIgc2tld21hdHJpeCA9IGZsb2F0MngyKHNrZXcueHksIHNrZXcuencpOwoJZmxvYXQyIGRldmNvb3JkID0gdmVydGV4cG9zICogc2tld21hdHJpeCArIHRyYW5zbGF0ZV9hbmRfbG9jYWxyb3RhdGUueHk7CglpZiAoMCAhPSBpc19saW5lYXJfY292ZXJhZ2UpIAoJewoJCXZhcmNjb29yZF9TMC54eSA9IGZsb2F0MigwLCBjb3ZlcmFnZSAqIGNvdmVyYWdlX211bHRpcGxpZXIpOwoJfQoJZWxzZSAKCXsKCQlmbG9hdDIgYXJjY29vcmQgPSAxIC0gYWJzKHJhZGl1c19vdXRzZXQpICsgYWFfb3V0c2V0L3JhZGlpICogY29ybmVyOwoJCXZhcmNjb29yZF9TMC54eSA9IGZsb2F0MihhcmNjb29yZC54KzEsIGFyY2Nvb3JkLnkpOwoJfQoJc2tfUG9zaXRpb24gPSBkZXZjb29yZC54eTAxOwp9CgEAAADUAwAAdW5pZm9ybSBmbG9hdDQgdWlubmVyUmVjdF9TMTsKdW5pZm9ybSBoYWxmMiB1cmFkaXVzUGx1c0hhbGZfUzE7CmZsYXQgaW4gaGFsZjQgdmNvbG9yX1MwOwppbiBmbG9hdDIgdmFyY2Nvb3JkX1MwOwpoYWxmNCBDaXJjdWxhclJSZWN0X1MxKGhhbGY0IF9pbnB1dCkgCnsKCWZsb2F0MiBkeHkwID0gdWlubmVyUmVjdF9TMS5MVCAtIHNrX0ZyYWdDb29yZC54eTsKCWZsb2F0MiBkeHkxID0gc2tfRnJhZ0Nvb3JkLnh5IC0gdWlubmVyUmVjdF9TMS5SQjsKCWZsb2F0MiBkeHkgPSBtYXgobWF4KGR4eTAsIGR4eTEpLCAwLjApOwoJaGFsZiBhbHBoYSA9IGhhbGYoc2F0dXJhdGUodXJhZGl1c1BsdXNIYWxmX1MxLnggLSBsZW5ndGgoZHh5KSkpOwoJcmV0dXJuIF9pbnB1dCAqIGFscGhhOwp9CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBGaWxsUlJlY3RPcDo6UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdmNvbG9yX1MwOwoJZmxvYXQgeF9wbHVzXzE9dmFyY2Nvb3JkX1MwLngsIHk9dmFyY2Nvb3JkX1MwLnk7CgloYWxmIGNvdmVyYWdlOwoJaWYgKDAgPT0geF9wbHVzXzEpIAoJewoJCWNvdmVyYWdlID0gaGFsZih5KTsKCX0KCWVsc2UgCgl7CgkJZmxvYXQgZm4gPSB4X3BsdXNfMSAqICh4X3BsdXNfMSAtIDIpOwoJCWZuID0gZm1hKHkseSwgZm4pOwoJCWZsb2F0IGZud2lkdGggPSBmd2lkdGgoZm4pOwoJCWNvdmVyYWdlID0gLjUgLSBoYWxmKGZuL2Zud2lkdGgpOwoJCWNvdmVyYWdlID0gY2xhbXAoY292ZXJhZ2UsIDAsIDEpOwoJfQoJaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNChjb3ZlcmFnZSk7CgloYWxmNCBvdXRwdXRfUzE7CglvdXRwdXRfUzEgPSBDaXJjdWxhclJSZWN0X1MxKG91dHB1dENvdmVyYWdlX1MwKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dF9TMTsKCX0KfQoBAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAACAAAAA4AAAByYWRpaV9zZWxlY3RvcgAAGQAAAGNvcm5lcl9hbmRfcmFkaXVzX291dHNldHMAAAAVAAAAYWFfYmxvYXRfYW5kX2NvdmVyYWdlAAAABwAAAHJhZGlpX3gABwAAAHJhZGlpX3kABAAAAHNrZXcZAAAAdHJhbnNsYXRlX2FuZF9sb2NhbHJvdGF0ZQAAAAUAAABjb2xvcgAAAAAAAAA=","B2AAQAAABQAAIAABBYAAB7777777777774ABICAAAAAAAAAAAAAABUABAAAAAEAAAAAIBEABAAAAA":"CgAAAExTS1MOAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBpblBvc2l0aW9uOwppbiBoYWxmIGluQ292ZXJhZ2U7Cm91dCBoYWxmIHZpbkNvdmVyYWdlX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBEZWZhdWx0R2VvbWV0cnlQcm9jZXNzb3IKCWZsb2F0MiBfdG1wXzFfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247Cgl2aW5Db3ZlcmFnZV9TMCA9IGluQ292ZXJhZ2U7Cglza19Qb3NpdGlvbiA9IF90bXBfMV9pblBvc2l0aW9uLnh5MDE7Cn0KAAAAAAAATQEAAHVuaWZvcm0gaGFsZjQgdUNvbG9yX1MwOwppbiBoYWxmIHZpbkNvdmVyYWdlX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgRGVmYXVsdEdlb21ldHJ5UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdUNvbG9yX1MwOwoJaGFsZiBhbHBoYSA9IDEuMDsKCWFscGhhID0gdmluQ292ZXJhZ2VfUzA7CgloYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KGFscGhhKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAACAAAACgAAAGluUG9zaXRpb24AAAoAAABpbkNvdmVyYWdlAAAAAAAA","HUQACAAAAAMAADAAAIOAAAH677776IZOCAAP577777777777777777YBAAAAAAAAAAAHEADZAAAAAAIAAAAAAOQAAAAAAAQAAAABAMQAAAAAA":"CgAAAExTS1PPAAAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gaGFsZjQgY29sb3I7Cm91dCBoYWxmNCB2Y29sb3JfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJdmNvbG9yX1MwID0gY29sb3I7Cglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cn0KAAEAAACbAgAAdW5pZm9ybSBmbG9hdDQgdWlubmVyUmVjdF9TMTsKdW5pZm9ybSBoYWxmMiB1cmFkaXVzUGx1c0hhbGZfUzE7CmluIGhhbGY0IHZjb2xvcl9TMDsKaGFsZjQgQ2lyY3VsYXJSUmVjdF9TMShoYWxmNCBfaW5wdXQpIAp7CglmbG9hdDIgZHh5MCA9IHVpbm5lclJlY3RfUzEuTFQgLSBza19GcmFnQ29vcmQueHk7CglmbG9hdDIgZHh5MSA9IHNrX0ZyYWdDb29yZC54eSAtIHVpbm5lclJlY3RfUzEuUkI7CglmbG9hdDIgZHh5ID0gbWF4KG1heChkeHkwLCBkeHkxKSwgMC4wKTsKCWhhbGYgYWxwaGEgPSBoYWxmKHNhdHVyYXRlKHVyYWRpdXNQbHVzSGFsZl9TMS54IC0gbGVuZ3RoKGR4eSkpKTsKCXJldHVybiBfaW5wdXQgKiBhbHBoYTsKfQp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdmNvbG9yX1MwOwoJY29uc3QgaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNCgxKTsKCWhhbGY0IG91dHB1dF9TMTsKCW91dHB1dF9TMSA9IENpcmN1bGFyUlJlY3RfUzEob3V0cHV0Q292ZXJhZ2VfUzApOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dENvbG9yX1MwICogb3V0cHV0X1MxOwoJfQp9CgABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAgAAABwb3NpdGlvbgUAAABjb2xvcgAAAAAAAAA=","HUJAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAQAAAAAAQQGAAZAADIAAAACU53QJEKAAAAAAMAAAAAIAAAAAAGIRDFB2XASAUAABQAAAAAAAAAAAAADUAAAAAAAEAAAAAIDEAAA":"CgAAAExTS1PlAAAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gZmxvYXQyIGxvY2FsQ29vcmQ7Cm91dCBmbG9hdDIgdmxvY2FsQ29vcmRfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJdmxvY2FsQ29vcmRfUzAgPSBsb2NhbENvb3JkOwoJc2tfUG9zaXRpb24gPSBwb3NpdGlvbi54eTAxOwp9CgAAAAEAAACrBAAAY29uc3QgaW50IGtGaWxsQUFfUzFfYzAgPSAxOwpjb25zdCBpbnQga0ludmVyc2VGaWxsQldfUzFfYzAgPSAyOwpjb25zdCBpbnQga0ludmVyc2VGaWxsQUFfUzFfYzAgPSAzOwp1bmlmb3JtIGZsb2F0NCB1Y2lyY2xlX1MxX2MwOwp1bmlmb3JtIHNhbXBsZXIyRCB1VGV4dHVyZVNhbXBsZXJfMF9TMDsKaW4gZmxvYXQyIHZsb2NhbENvb3JkX1MwOwpoYWxmNCBDaXJjbGVfUzFfYzAoaGFsZjQgX2lucHV0KSAKewoJaGFsZjQgX3RtcF8wX2luQ29sb3IgPSBfaW5wdXQ7CgloYWxmIGQ7CglpZiAoaW50KDEpID09IGtJbnZlcnNlRmlsbEJXX1MxX2MwIHx8IGludCgxKSA9PSBrSW52ZXJzZUZpbGxBQV9TMV9jMCkgCgl7CgkJZCA9IGhhbGYoKGxlbmd0aCgodWNpcmNsZV9TMV9jMC54eSAtIHNrX0ZyYWdDb29yZC54eSkgKiB1Y2lyY2xlX1MxX2MwLncpIC0gMS4wKSAqIHVjaXJjbGVfUzFfYzAueik7Cgl9CgllbHNlIAoJewoJCWQgPSBoYWxmKCgxLjAgLSBsZW5ndGgoKHVjaXJjbGVfUzFfYzAueHkgLSBza19GcmFnQ29vcmQueHkpICogdWNpcmNsZV9TMV9jMC53KSkgKiB1Y2lyY2xlX1MxX2MwLnopOwoJfQoJcmV0dXJuIGhhbGY0KGhhbGY0KGludCgxKSA9PSBrRmlsbEFBX1MxX2MwIHx8IGludCgxKSA9PSBrSW52ZXJzZUZpbGxBQV9TMV9jMCA/IHNhdHVyYXRlKGQpIDogaGFsZihkID4gMC41ID8gMSA6IDApKSk7Cn0KaGFsZjQgQmxlbmRfUzEoaGFsZjQgX3NyYywgaGFsZjQgX2RzdCkgCnsKCXJldHVybiBibGVuZF9tb2R1bGF0ZShfc3JjLCBDaXJjbGVfUzFfYzAoX3NyYykpOwp9CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBRdWFkUGVyRWRnZUFBR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwID0gaGFsZjQoMSk7CglmbG9hdDIgdGV4Q29vcmQ7Cgl0ZXhDb29yZCA9IHZsb2NhbENvb3JkX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSAoKHNhbXBsZSh1VGV4dHVyZVNhbXBsZXJfMF9TMCwgdGV4Q29vcmQpICogaGFsZjQoMSkpKTsKCWNvbnN0IGhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoMSk7CgloYWxmNCBvdXRwdXRfUzE7CglvdXRwdXRfUzEgPSBCbGVuZF9TMShvdXRwdXRDb3ZlcmFnZV9TMCwgaGFsZjQoMSkpOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dENvbG9yX1MwICogb3V0cHV0X1MxOwoJfQp9CgABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAgAAABwb3NpdGlvbgoAAABsb2NhbENvb3JkAAAAAAAA","DAQAAAAAAABGAABAYAAQAIHCAIAYAQUBAEAAAAAAEAAAAAAAAAAAAAB2AAAAAAACAAAAAEBSAAAAA":"CgAAAExTS1MWAgAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQyIHVBdGxhc1NpemVJbnZfUzA7CmluIGZsb2F0MiBpblBvc2l0aW9uOwppbiBoYWxmNCBpbkNvbG9yOwppbiB1c2hvcnQyIGluVGV4dHVyZUNvb3JkczsKb3V0IGZsb2F0MiB2VGV4dHVyZUNvb3Jkc19TMDsKZmxhdCBvdXQgZmxvYXQgdlRleEluZGV4X1MwOwpvdXQgaGFsZjQgdmluQ29sb3JfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIEJpdG1hcFRleHQKCWludCB0ZXhJZHggPSAwOwoJZmxvYXQyIHVub3JtVGV4Q29vcmRzID0gZmxvYXQyKGluVGV4dHVyZUNvb3Jkcy54LCBpblRleHR1cmVDb29yZHMueSk7Cgl2VGV4dHVyZUNvb3Jkc19TMCA9IHVub3JtVGV4Q29vcmRzICogdUF0bGFzU2l6ZUludl9TMDsKCXZUZXhJbmRleF9TMCA9IGZsb2F0KHRleElkeCk7Cgl2aW5Db2xvcl9TMCA9IGluQ29sb3I7CglmbG9hdDIgX3RtcF8xX2luUG9zaXRpb24gPSBpblBvc2l0aW9uOwoJc2tfUG9zaXRpb24gPSBpblBvc2l0aW9uLnh5MDE7Cn0KAAAAAAAAsQEAAHVuaWZvcm0gc2FtcGxlcjJEIHVUZXh0dXJlU2FtcGxlcl8wX1MwOwppbiBmbG9hdDIgdlRleHR1cmVDb29yZHNfUzA7CmZsYXQgaW4gZmxvYXQgdlRleEluZGV4X1MwOwppbiBoYWxmNCB2aW5Db2xvcl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIEJpdG1hcFRleHQKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2aW5Db2xvcl9TMDsKCWhhbGY0IHRleENvbG9yOwoJewoJCXRleENvbG9yID0gc2FtcGxlKHVUZXh0dXJlU2FtcGxlcl8wX1MwLCB2VGV4dHVyZUNvb3Jkc19TMCkucnJycjsKCX0KCWhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gdGV4Q29sb3I7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRDb3ZlcmFnZV9TMDsKCX0KfQoAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAoAAABpblBvc2l0aW9uAAAHAAAAaW5Db2xvcgAPAAAAaW5UZXh0dXJlQ29vcmRzAAAAAAA=","HUIAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAAAAAALUAQMAAAAAAIAAEAAAABJYQAAAAAQAAIAAAAAWCBACAABAAAAANAECAZAAEAAAAAAAAFAAMAAAABAAAAAAABBAM":"CgAAAExTS1M2AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBmbG9hdDIgbG9jYWxDb29yZDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cgl7CgkJdlRyYW5zZm9ybWVkQ29vcmRzXzJfUzAgPSBmbG9hdDN4Mih1bWF0cml4X1MxKSAqIGxvY2FsQ29vcmQueHkxOwoJfQp9CgAAAAAAAC8GAAB1bmlmb3JtIGZsb2F0NCB1Y2xhbXBfUzFfYzBfYzBfYzA7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMV9jMF9jMDsKdW5pZm9ybSBoYWxmMiB1SW5jcmVtZW50X1MxX2MwOwp1bmlmb3JtIGhhbGYyIHVPZmZzZXRzQW5kS2VybmVsX1MxX2MwWzEzXTsKdW5pZm9ybSBmbG9hdDN4MyB1bWF0cml4X1MxOwp1bmlmb3JtIHNhbXBsZXIyRCB1VGV4dHVyZVNhbXBsZXJfMF9TMTsKaW4gZmxvYXQyIHZUcmFuc2Zvcm1lZENvb3Jkc18yX1MwOwpoYWxmNCBUZXh0dXJlRWZmZWN0X1MxX2MwX2MwX2MwKGhhbGY0IF9pbnB1dCwgZmxvYXQyIF9jb29yZHMpIAp7CglmbG9hdDIgaW5Db29yZCA9IF9jb29yZHM7CglmbG9hdDIgc3Vic2V0Q29vcmQ7CglzdWJzZXRDb29yZC54ID0gaW5Db29yZC54OwoJc3Vic2V0Q29vcmQueSA9IGluQ29vcmQueTsKCWZsb2F0MiBjbGFtcGVkQ29vcmQ7CgljbGFtcGVkQ29vcmQueCA9IGNsYW1wKHN1YnNldENvb3JkLngsIHVjbGFtcF9TMV9jMF9jMF9jMC54LCB1Y2xhbXBfUzFfYzBfYzBfYzAueik7CgljbGFtcGVkQ29vcmQueSA9IHN1YnNldENvb3JkLnk7CgloYWxmNCB0ZXh0dXJlQ29sb3IgPSBzYW1wbGUodVRleHR1cmVTYW1wbGVyXzBfUzEsIGNsYW1wZWRDb29yZCk7CglyZXR1cm4gdGV4dHVyZUNvbG9yOwp9CmhhbGY0IE1hdHJpeEVmZmVjdF9TMV9jMF9jMChoYWxmNCBfaW5wdXQsIGZsb2F0MiBfY29vcmRzKSAKewoJcmV0dXJuIFRleHR1cmVFZmZlY3RfUzFfYzBfYzBfYzAoX2lucHV0LCBmbG9hdDN4Mih1bWF0cml4X1MxX2MwX2MwKSAqIF9jb29yZHMueHkxKTsKfQpoYWxmNCBTbW9vdGhfUzFfYzAoaGFsZjQgX2lucHV0LCBmbG9hdDIgY29vcmQsIGhhbGYyIG9mZnNldEFuZEtlcm5lbCkgCnsKCXJldHVybiBNYXRyaXhFZmZlY3RfUzFfYzBfYzAoX2lucHV0LCAoY29vcmQgKyBvZmZzZXRBbmRLZXJuZWwueCAqIHVJbmNyZW1lbnRfUzFfYzApKSAqIG9mZnNldEFuZEtlcm5lbC55Owp9CmhhbGY0IEdhdXNzaWFuQ29udm9sdXRpb25fUzFfYzAoaGFsZjQgX2lucHV0KSAKewoJaGFsZjQgY29sb3IgPSBoYWxmNCgwKTsKCWZsb2F0MiBjb29yZCA9IHZUcmFuc2Zvcm1lZENvb3Jkc18yX1MwOwoJZm9yIChpbnQgaT0wOyBpPDEzOyArK2kpIAoJewoJCWNvbG9yICs9IFNtb290aF9TMV9jMChfaW5wdXQsIGNvb3JkLCB1T2Zmc2V0c0FuZEtlcm5lbF9TMV9jMFtpXSk7Cgl9CglyZXR1cm4gY29sb3I7Cn0KaGFsZjQgTWF0cml4RWZmZWN0X1MxKGhhbGY0IF9pbnB1dCkgCnsKCXJldHVybiBHYXVzc2lhbkNvbnZvbHV0aW9uX1MxX2MwKF9pbnB1dCk7Cn0Kdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJaGFsZjQgb3V0cHV0Q29sb3JfUzAgPSBoYWxmNCgxKTsKCWNvbnN0IGhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoMSk7CgloYWxmNCBvdXRwdXRfUzE7CglvdXRwdXRfUzEgPSBNYXRyaXhFZmZlY3RfUzEob3V0cHV0Q29sb3JfUzApOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dF9TMSAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAgAAABwb3NpdGlvbgoAAABsb2NhbENvb3JkAAAAAAAA","HVIAAAAAABIAAGAAAQ4AAAH477776R24EAAAIOBQAD6P7777777777YDAAAAAAAAAAAFIBQU7BTXIAAAAAACAAAAAAQFV5W6JEAAAAAYAAAABQEZ2AKAWAQAABAL6SYKDYAAAACAAAAAAQEGIAAAAACAWTWL3EYAAAADAAAAACADHIJJCYCAAAEAP2LRIPAAAAAIAAAAAAABTALI3F5SOAIAABQAAAAAABTUEUZMBAAAAAH5FYUXQAAAAAAAEAAAAAZMRGOQCQFQEAAAAAAAAAGARL2LXJHAAEAAAAAEAAAABSCQX5FQUHQAAAAAAAAAACAA4AAAACAAAAAAACCAYAAAAA":"CgAAAExTS1OGAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMV9jMF9jMF9jMTsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBoYWxmNCBjb2xvcjsKaW4gZmxvYXQyIGxvY2FsQ29vcmQ7CmZsYXQgb3V0IGhhbGY0IHZjb2xvcl9TMDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfNl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgl2Y29sb3JfUzAgPSBjb2xvcjsKCXNrX1Bvc2l0aW9uID0gcG9zaXRpb24ueHkwMTsKCXsKCQl2VHJhbnNmb3JtZWRDb29yZHNfNl9TMCA9IGZsb2F0M3gyKHVtYXRyaXhfUzFfYzBfYzBfYzEpICogbG9jYWxDb29yZC54eTE7Cgl9Cn0KAAAAAAAAdgcAAHVuaWZvcm0gaGFsZjQgdXN0YXJ0X1MxX2MwX2MwX2MwOwp1bmlmb3JtIGhhbGY0IHVlbmRfUzFfYzBfYzBfYzA7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMV9jMF9jMF9jMTsKdW5pZm9ybSBoYWxmNCB1bGVmdEJvcmRlckNvbG9yX1MxX2MwX2MwOwp1bmlmb3JtIGhhbGY0IHVyaWdodEJvcmRlckNvbG9yX1MxX2MwX2MwOwpmbGF0IGluIGhhbGY0IHZjb2xvcl9TMDsKaW4gZmxvYXQyIHZUcmFuc2Zvcm1lZENvb3Jkc182X1MwOwpoYWxmNCBTaW5nbGVJbnRlcnZhbENvbG9yaXplcl9TMV9jMF9jMF9jMChoYWxmNCBfaW5wdXQsIGZsb2F0MiBfY29vcmRzKSAKewoJaGFsZjQgX3RtcF8wX2luQ29sb3IgPSBfaW5wdXQ7CglmbG9hdDIgX3RtcF8xX2Nvb3JkcyA9IF9jb29yZHM7CglyZXR1cm4gaGFsZjQobWl4KHVzdGFydF9TMV9jMF9jMF9jMCwgdWVuZF9TMV9jMF9jMF9jMCwgaGFsZihfdG1wXzFfY29vcmRzLngpKSk7Cn0KaGFsZjQgTGluZWFyTGF5b3V0X1MxX2MwX2MwX2MxX2MwKGhhbGY0IF9pbnB1dCkgCnsKCWhhbGY0IF90bXBfMl9pbkNvbG9yID0gX2lucHV0OwoJZmxvYXQyIF90bXBfM19jb29yZHMgPSB2VHJhbnNmb3JtZWRDb29yZHNfNl9TMDsKCXJldHVybiBoYWxmNChoYWxmNChoYWxmKF90bXBfM19jb29yZHMueCkgKyAxZS0wNSwgMS4wLCAwLjAsIDAuMCkpOwp9CmhhbGY0IE1hdHJpeEVmZmVjdF9TMV9jMF9jMF9jMShoYWxmNCBfaW5wdXQpIAp7CglyZXR1cm4gTGluZWFyTGF5b3V0X1MxX2MwX2MwX2MxX2MwKF9pbnB1dCk7Cn0KaGFsZjQgQ2xhbXBlZEdyYWRpZW50X1MxX2MwX2MwKGhhbGY0IF9pbnB1dCkgCnsKCWhhbGY0IF90bXBfNF9pbkNvbG9yID0gX2lucHV0OwoJaGFsZjQgdCA9IE1hdHJpeEVmZmVjdF9TMV9jMF9jMF9jMShfdG1wXzRfaW5Db2xvcik7CgloYWxmNCBvdXRDb2xvcjsKCWlmICghYm9vbChpbnQoMSkpICYmIHQueSA8IDAuMCkgCgl7CgkJb3V0Q29sb3IgPSBoYWxmNCgwLjApOwoJfQoJZWxzZSBpZiAodC54IDwgMC4wKSAKCXsKCQlvdXRDb2xvciA9IHVsZWZ0Qm9yZGVyQ29sb3JfUzFfYzBfYzA7Cgl9CgllbHNlIGlmICh0LnggPiAxLjApIAoJewoJCW91dENvbG9yID0gdXJpZ2h0Qm9yZGVyQ29sb3JfUzFfYzBfYzA7Cgl9CgllbHNlIAoJewoJCW91dENvbG9yID0gU2luZ2xlSW50ZXJ2YWxDb2xvcml6ZXJfUzFfYzBfYzBfYzAoX3RtcF80X2luQ29sb3IsIGZsb2F0MihoYWxmMih0LngsIDAuMCkpKTsKCX0KCXJldHVybiBoYWxmNChvdXRDb2xvcik7Cn0KaGFsZjQgY29sb3JfeGZvcm1fUzFfYzAoZmxvYXQ0IGNvbG9yKSAKewoJY29sb3IucmdiICo9IGNvbG9yLmE7CglyZXR1cm4gaGFsZjQoY29sb3IpOwp9CmhhbGY0IENvbG9yU3BhY2VYZm9ybV9TMV9jMChoYWxmNCBfaW5wdXQpIAp7CglyZXR1cm4gY29sb3JfeGZvcm1fUzFfYzAoQ2xhbXBlZEdyYWRpZW50X1MxX2MwX2MwKF9pbnB1dCkpOwp9CmhhbGY0IERpc2FibGVDb3ZlcmFnZUFzQWxwaGFfUzEoaGFsZjQgX2lucHV0KSAKewoJX2lucHV0ID0gQ29sb3JTcGFjZVhmb3JtX1MxX2MwKF9pbnB1dCk7CgloYWxmNCBfdG1wXzVfaW5Db2xvciA9IF9pbnB1dDsKCXJldHVybiBoYWxmNChfaW5wdXQpOwp9CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBRdWFkUGVyRWRnZUFBR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2Y29sb3JfUzA7Cgljb25zdCBoYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KDEpOwoJaGFsZjQgb3V0cHV0X1MxOwoJb3V0cHV0X1MxID0gRGlzYWJsZUNvdmVyYWdlQXNBbHBoYV9TMShvdXRwdXRDb2xvcl9TMCk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0X1MxICogb3V0cHV0Q292ZXJhZ2VfUzA7Cgl9Cn0KAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAgAAABwb3NpdGlvbgUAAABjb2xvcgAAAAoAAABsb2NhbENvb3JkAAAAAAAA","HUJAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAQAAAAAAQQGABZAA6IAAAAACAAAAAADUAAAAAAAEAAAAAIDEAAAAAAA":"CgAAAExTS1PlAAAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gZmxvYXQyIGxvY2FsQ29vcmQ7Cm91dCBmbG9hdDIgdmxvY2FsQ29vcmRfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJdmxvY2FsQ29vcmRfUzAgPSBsb2NhbENvb3JkOwoJc2tfUG9zaXRpb24gPSBwb3NpdGlvbi54eTAxOwp9CgAAAAEAAAAuAwAAdW5pZm9ybSBmbG9hdDQgdWlubmVyUmVjdF9TMTsKdW5pZm9ybSBoYWxmMiB1cmFkaXVzUGx1c0hhbGZfUzE7CnVuaWZvcm0gc2FtcGxlcjJEIHVUZXh0dXJlU2FtcGxlcl8wX1MwOwppbiBmbG9hdDIgdmxvY2FsQ29vcmRfUzA7CmhhbGY0IENpcmN1bGFyUlJlY3RfUzEoaGFsZjQgX2lucHV0KSAKewoJZmxvYXQyIGR4eTAgPSB1aW5uZXJSZWN0X1MxLkxUIC0gc2tfRnJhZ0Nvb3JkLnh5OwoJZmxvYXQyIGR4eTEgPSBza19GcmFnQ29vcmQueHkgLSB1aW5uZXJSZWN0X1MxLlJCOwoJZmxvYXQyIGR4eSA9IG1heChtYXgoZHh5MCwgZHh5MSksIDAuMCk7CgloYWxmIGFscGhhID0gaGFsZihzYXR1cmF0ZSh1cmFkaXVzUGx1c0hhbGZfUzEueCAtIGxlbmd0aChkeHkpKSk7CglyZXR1cm4gX2lucHV0ICogYWxwaGE7Cn0Kdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJaGFsZjQgb3V0cHV0Q29sb3JfUzAgPSBoYWxmNCgxKTsKCWZsb2F0MiB0ZXhDb29yZDsKCXRleENvb3JkID0gdmxvY2FsQ29vcmRfUzA7CglvdXRwdXRDb2xvcl9TMCA9ICgoc2FtcGxlKHVUZXh0dXJlU2FtcGxlcl8wX1MwLCB0ZXhDb29yZCkgKiBoYWxmNCgxKSkpOwoJY29uc3QgaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNCgxKTsKCWhhbGY0IG91dHB1dF9TMTsKCW91dHB1dF9TMSA9IENpcmN1bGFyUlJlY3RfUzEob3V0cHV0Q292ZXJhZ2VfUzApOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dENvbG9yX1MwICogb3V0cHV0X1MxOwoJfQp9CgAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAIAAAAcG9zaXRpb24KAAAAbG9jYWxDb29yZAAAAAAAAA==","B2ABSAAABQAAIAABBYAAB7777777777774ABICAAAAAAAAAAAAAABUABAAAAAEAAAAAIBEABAAAAA":"CgAAAExTS1N4AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gaGFsZjQgdUNvbG9yX1MwOwppbiBmbG9hdDIgaW5Qb3NpdGlvbjsKaW4gaGFsZiBpbkNvdmVyYWdlOwpvdXQgaGFsZjQgdmNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBEZWZhdWx0R2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IGNvbG9yID0gdUNvbG9yX1MwOwoJY29sb3IgPSBjb2xvciAqIGluQ292ZXJhZ2U7Cgl2Y29sb3JfUzAgPSBjb2xvcjsKCWZsb2F0MiBfdG1wXzFfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247CglmbG9hdDIgX3RtcF8zX2luUG9zaXRpb24gPSBpblBvc2l0aW9uOwoJc2tfUG9zaXRpb24gPSBfdG1wXzFfaW5Qb3NpdGlvbi54eTAxOwp9CgAAAAAGAQAAaW4gaGFsZjQgdmNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgRGVmYXVsdEdlb21ldHJ5UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdmNvbG9yX1MwOwoJY29uc3QgaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNCgxKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAKAAAAaW5Qb3NpdGlvbgAACgAAAGluQ292ZXJhZ2UAAAAAAAA=","HVIACAAAABQAAGAAAQ4AAAAAGQQAARC4GAAAIOCAAD6P7777777777YDAAAAAAAAAAAFIBQU7BTXIAAAAAACAAAAAAQFV5W6JEAAAAAYAAAABQEZ2AKAWAQAABAL6SYKDYAAAACAAAAAAQEGIAAAAACAWTWL3EYAAAADAAAAACADHIJJCYCAAAEAP2LRIPAAAAAIAAAAAAABTALI3F5SOAIAABQAAAAAABTUEUZMBAAAAAH5FYUXQAAAAAAAEAAAAAZMRGOQCQFQEAAAAAAAAAGARL2LXJHAAEAAAAAEAAAABSCQX5FQUHQAAAAAAAAAACAA4AAAABAACAAAACCAYAAAAA":"CgAAAExTS1PrAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMV9jMF9jMF9jMTsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBmbG9hdCBjb3ZlcmFnZTsKaW4gaGFsZjQgY29sb3I7CmluIGZsb2F0MiBsb2NhbENvb3JkOwpmbGF0IG91dCBoYWxmNCB2Y29sb3JfUzA7Cm91dCBmbG9hdCB2Y292ZXJhZ2VfUzA7Cm91dCBmbG9hdDIgdlRyYW5zZm9ybWVkQ29vcmRzXzZfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJZmxvYXQyIHBvc2l0aW9uID0gcG9zaXRpb24ueHk7Cgl2Y29sb3JfUzAgPSBjb2xvcjsKCXZjb3ZlcmFnZV9TMCA9IGNvdmVyYWdlOwoJc2tfUG9zaXRpb24gPSBwb3NpdGlvbi54eTAxOwoJewoJCXZUcmFuc2Zvcm1lZENvb3Jkc182X1MwID0gZmxvYXQzeDIodW1hdHJpeF9TMV9jMF9jMF9jMSkgKiBsb2NhbENvb3JkLnh5MTsKCX0KfQoAAAAAAMMHAAB1bmlmb3JtIGhhbGY0IHVzdGFydF9TMV9jMF9jMF9jMDsKdW5pZm9ybSBoYWxmNCB1ZW5kX1MxX2MwX2MwX2MwOwp1bmlmb3JtIGZsb2F0M3gzIHVtYXRyaXhfUzFfYzBfYzBfYzE7CnVuaWZvcm0gaGFsZjQgdWxlZnRCb3JkZXJDb2xvcl9TMV9jMF9jMDsKdW5pZm9ybSBoYWxmNCB1cmlnaHRCb3JkZXJDb2xvcl9TMV9jMF9jMDsKZmxhdCBpbiBoYWxmNCB2Y29sb3JfUzA7CmluIGZsb2F0IHZjb3ZlcmFnZV9TMDsKaW4gZmxvYXQyIHZUcmFuc2Zvcm1lZENvb3Jkc182X1MwOwpoYWxmNCBTaW5nbGVJbnRlcnZhbENvbG9yaXplcl9TMV9jMF9jMF9jMChoYWxmNCBfaW5wdXQsIGZsb2F0MiBfY29vcmRzKSAKewoJaGFsZjQgX3RtcF8wX2luQ29sb3IgPSBfaW5wdXQ7CglmbG9hdDIgX3RtcF8xX2Nvb3JkcyA9IF9jb29yZHM7CglyZXR1cm4gaGFsZjQobWl4KHVzdGFydF9TMV9jMF9jMF9jMCwgdWVuZF9TMV9jMF9jMF9jMCwgaGFsZihfdG1wXzFfY29vcmRzLngpKSk7Cn0KaGFsZjQgTGluZWFyTGF5b3V0X1MxX2MwX2MwX2MxX2MwKGhhbGY0IF9pbnB1dCkgCnsKCWhhbGY0IF90bXBfMl9pbkNvbG9yID0gX2lucHV0OwoJZmxvYXQyIF90bXBfM19jb29yZHMgPSB2VHJhbnNmb3JtZWRDb29yZHNfNl9TMDsKCXJldHVybiBoYWxmNChoYWxmNChoYWxmKF90bXBfM19jb29yZHMueCkgKyAxZS0wNSwgMS4wLCAwLjAsIDAuMCkpOwp9CmhhbGY0IE1hdHJpeEVmZmVjdF9TMV9jMF9jMF9jMShoYWxmNCBfaW5wdXQpIAp7CglyZXR1cm4gTGluZWFyTGF5b3V0X1MxX2MwX2MwX2MxX2MwKF9pbnB1dCk7Cn0KaGFsZjQgQ2xhbXBlZEdyYWRpZW50X1MxX2MwX2MwKGhhbGY0IF9pbnB1dCkgCnsKCWhhbGY0IF90bXBfNF9pbkNvbG9yID0gX2lucHV0OwoJaGFsZjQgdCA9IE1hdHJpeEVmZmVjdF9TMV9jMF9jMF9jMShfdG1wXzRfaW5Db2xvcik7CgloYWxmNCBvdXRDb2xvcjsKCWlmICghYm9vbChpbnQoMSkpICYmIHQueSA8IDAuMCkgCgl7CgkJb3V0Q29sb3IgPSBoYWxmNCgwLjApOwoJfQoJZWxzZSBpZiAodC54IDwgMC4wKSAKCXsKCQlvdXRDb2xvciA9IHVsZWZ0Qm9yZGVyQ29sb3JfUzFfYzBfYzA7Cgl9CgllbHNlIGlmICh0LnggPiAxLjApIAoJewoJCW91dENvbG9yID0gdXJpZ2h0Qm9yZGVyQ29sb3JfUzFfYzBfYzA7Cgl9CgllbHNlIAoJewoJCW91dENvbG9yID0gU2luZ2xlSW50ZXJ2YWxDb2xvcml6ZXJfUzFfYzBfYzBfYzAoX3RtcF80X2luQ29sb3IsIGZsb2F0MihoYWxmMih0LngsIDAuMCkpKTsKCX0KCXJldHVybiBoYWxmNChvdXRDb2xvcik7Cn0KaGFsZjQgY29sb3JfeGZvcm1fUzFfYzAoZmxvYXQ0IGNvbG9yKSAKewoJY29sb3IucmdiICo9IGNvbG9yLmE7CglyZXR1cm4gaGFsZjQoY29sb3IpOwp9CmhhbGY0IENvbG9yU3BhY2VYZm9ybV9TMV9jMChoYWxmNCBfaW5wdXQpIAp7CglyZXR1cm4gY29sb3JfeGZvcm1fUzFfYzAoQ2xhbXBlZEdyYWRpZW50X1MxX2MwX2MwKF9pbnB1dCkpOwp9CmhhbGY0IERpc2FibGVDb3ZlcmFnZUFzQWxwaGFfUzEoaGFsZjQgX2lucHV0KSAKewoJX2lucHV0ID0gQ29sb3JTcGFjZVhmb3JtX1MxX2MwKF9pbnB1dCk7CgloYWxmNCBfdG1wXzVfaW5Db2xvciA9IF9pbnB1dDsKCXJldHVybiBoYWxmNChfaW5wdXQpOwp9CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBRdWFkUGVyRWRnZUFBR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2Y29sb3JfUzA7CglmbG9hdCBjb3ZlcmFnZSA9IHZjb3ZlcmFnZV9TMDsKCWhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoaGFsZihjb3ZlcmFnZSkpOwoJaGFsZjQgb3V0cHV0X1MxOwoJb3V0cHV0X1MxID0gRGlzYWJsZUNvdmVyYWdlQXNBbHBoYV9TMShvdXRwdXRDb2xvcl9TMCk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gKGhhbGY0KDEuMCkgLSBvdXRwdXRfUzEpICogb3V0cHV0Q292ZXJhZ2VfUzA7Cgl9Cn0KAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAEAAAACAAAAHBvc2l0aW9uCAAAAGNvdmVyYWdlBQAAAGNvbG9yAAAACgAAAGxvY2FsQ29vcmQAAAAAAAA=","HUQAAAAAAAMAADAAAIOAAAH677776IZOCAAP577777777777777777YBAAAAAAAAAAADEAANAAAAALHCKLMRAAAAAAAAABAAAAAGJBCFLQVBWAQAAAAAAQAAAAAMACQCAACAAAAA2AIBAEIAAAAAAAAAAAAIADQAAAAIAAAAAAAIIDAAAAAA":"CgAAAExTS1PUAAAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gaGFsZjQgY29sb3I7CmZsYXQgb3V0IGhhbGY0IHZjb2xvcl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgl2Y29sb3JfUzAgPSBjb2xvcjsKCXNrX1Bvc2l0aW9uID0gcG9zaXRpb24ueHkwMTsKfQoBAAAAeAQAAHVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMV9jMF9jMDsKdW5pZm9ybSBoYWxmNCB1Y2lyY2xlRGF0YV9TMV9jMDsKdW5pZm9ybSBzYW1wbGVyMkQgdVRleHR1cmVTYW1wbGVyXzBfUzE7CmZsYXQgaW4gaGFsZjQgdmNvbG9yX1MwOwpoYWxmNCBUZXh0dXJlRWZmZWN0X1MxX2MwX2MwX2MwKGhhbGY0IF9pbnB1dCwgZmxvYXQyIF9jb29yZHMpIAp7CglyZXR1cm4gc2FtcGxlKHVUZXh0dXJlU2FtcGxlcl8wX1MxLCBfY29vcmRzKS4wMDByOwp9CmhhbGY0IE1hdHJpeEVmZmVjdF9TMV9jMF9jMChoYWxmNCBfaW5wdXQsIGZsb2F0MiBfY29vcmRzKSAKewoJcmV0dXJuIFRleHR1cmVFZmZlY3RfUzFfYzBfYzBfYzAoX2lucHV0LCBmbG9hdDN4Mih1bWF0cml4X1MxX2MwX2MwKSAqIF9jb29yZHMueHkxKTsKfQpoYWxmNCBDaXJjbGVCbHVyX1MxX2MwKGhhbGY0IF9pbnB1dCkgCnsKCWhhbGY0IF90bXBfMF9pbkNvbG9yID0gX2lucHV0OwoJaGFsZjIgdmVjID0gaGFsZjIoKHNrX0ZyYWdDb29yZC54eSAtIGZsb2F0Mih1Y2lyY2xlRGF0YV9TMV9jMC54eSkpICogZmxvYXQodWNpcmNsZURhdGFfUzFfYzAudykpOwoJaGFsZiBkaXN0ID0gbGVuZ3RoKHZlYykgKyAoMC41IC0gdWNpcmNsZURhdGFfUzFfYzAueikgKiB1Y2lyY2xlRGF0YV9TMV9jMC53OwoJcmV0dXJuIGhhbGY0KE1hdHJpeEVmZmVjdF9TMV9jMF9jMChfdG1wXzBfaW5Db2xvciwgZmxvYXQyKGhhbGYyKGRpc3QsIDAuNSkpKS53d3d3KTsKfQpoYWxmNCBCbGVuZF9TMShoYWxmNCBfc3JjLCBoYWxmNCBfZHN0KSAKewoJcmV0dXJuIGJsZW5kX21vZHVsYXRlKENpcmNsZUJsdXJfUzFfYzAoX3NyYyksIF9zcmMpOwp9CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBRdWFkUGVyRWRnZUFBR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2Y29sb3JfUzA7Cgljb25zdCBoYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KDEpOwoJaGFsZjQgb3V0cHV0X1MxOwoJb3V0cHV0X1MxID0gQmxlbmRfUzEob3V0cHV0Q292ZXJhZ2VfUzAsIGhhbGY0KDEpKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dF9TMTsKCX0KfQoBAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAgAAABwb3NpdGlvbgUAAABjb2xvcgAAAAAAAAA=","EADQAAAAAEAAAAAUAABQAAQPAAABCFYMAAKAUEAAAAAAAAABAAAAAAAAAAANAAIAAAABAAAAACAJAAIAAAAA":"CgAAAExTS1NyAgAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQyIHVBdGxhc0RpbWVuc2lvbnNJbnZfUzA7CmluIGZsb2F0MyBpblBvc2l0aW9uOwppbiBoYWxmNCBpbkNvbG9yOwppbiB1c2hvcnQyIGluVGV4dHVyZUNvb3JkczsKb3V0IGZsb2F0MiB2VGV4dHVyZUNvb3Jkc19TMDsKZmxhdCBvdXQgZmxvYXQgdlRleEluZGV4X1MwOwpvdXQgZmxvYXQyIHZJbnRUZXh0dXJlQ29vcmRzX1MwOwpvdXQgaGFsZjQgdmluQ29sb3JfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIERpc3RhbmNlRmllbGRQYXRoCglpbnQgdGV4SWR4ID0gMDsKCWZsb2F0MiB1bm9ybVRleENvb3JkcyA9IGZsb2F0MihpblRleHR1cmVDb29yZHMueCwgaW5UZXh0dXJlQ29vcmRzLnkpOwoJdlRleHR1cmVDb29yZHNfUzAgPSB1bm9ybVRleENvb3JkcyAqIHVBdGxhc0RpbWVuc2lvbnNJbnZfUzA7Cgl2VGV4SW5kZXhfUzAgPSBmbG9hdCh0ZXhJZHgpOwoJdkludFRleHR1cmVDb29yZHNfUzAgPSB1bm9ybVRleENvb3JkczsKCXZpbkNvbG9yX1MwID0gaW5Db2xvcjsKCWZsb2F0MyBfdG1wXzFfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247Cglza19Qb3NpdGlvbiA9IGluUG9zaXRpb24ueHkwejsKfQoAAAAAAACfAgAAdW5pZm9ybSBzYW1wbGVyMkQgdVRleHR1cmVTYW1wbGVyXzBfUzA7CmluIGZsb2F0MiB2VGV4dHVyZUNvb3Jkc19TMDsKZmxhdCBpbiBmbG9hdCB2VGV4SW5kZXhfUzA7CmluIGZsb2F0MiB2SW50VGV4dHVyZUNvb3Jkc19TMDsKaW4gaGFsZjQgdmluQ29sb3JfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBEaXN0YW5jZUZpZWxkUGF0aAoJaGFsZjQgb3V0cHV0Q29sb3JfUzA7CglvdXRwdXRDb2xvcl9TMCA9IHZpbkNvbG9yX1MwOwoJZmxvYXQyIHV2ID0gdlRleHR1cmVDb29yZHNfUzA7CgloYWxmNCB0ZXhDb2xvcjsKCXsKCQl0ZXhDb2xvciA9IHNhbXBsZSh1VGV4dHVyZVNhbXBsZXJfMF9TMCwgdXYpLnJycnI7Cgl9CgloYWxmIGRpc3RhbmNlID0gNy45Njg3NSoodGV4Q29sb3IuciAtIDAuNTAxOTYwNzg0MzEpOwoJaGFsZiBhZndpZHRoOwoJYWZ3aWR0aCA9IGFicygwLjY1KmhhbGYoZEZkeCh2SW50VGV4dHVyZUNvb3Jkc19TMC54KSkpOwoJaGFsZiB2YWwgPSBzbW9vdGhzdGVwKC1hZndpZHRoLCBhZndpZHRoLCBkaXN0YW5jZSk7CgloYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KHZhbCk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRDb3ZlcmFnZV9TMDsKCX0KfQoAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAKAAAAaW5Qb3NpdGlvbgAABwAAAGluQ29sb3IADwAAAGluVGV4dHVyZUNvb3JkcwAAAAAA","GEMAAAYAAEHAAAARC4EAAAQWBQAAAAAAAAAQAAAAIBCAAAGQAEAAAAAQAAAABAEQAEAAAAA":"CgAAAExTS1NUAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBpblBvc2l0aW9uOwppbiBoYWxmNCBpbkNvbG9yOwppbiBoYWxmMyBpblNoYWRvd1BhcmFtczsKb3V0IGhhbGYzIHZpblNoYWRvd1BhcmFtc19TMDsKb3V0IGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBSUmVjdFNoYWRvdwoJdmluU2hhZG93UGFyYW1zX1MwID0gaW5TaGFkb3dQYXJhbXM7Cgl2aW5Db2xvcl9TMCA9IGluQ29sb3I7CglmbG9hdDIgX3RtcF8wX2luUG9zaXRpb24gPSBpblBvc2l0aW9uOwoJc2tfUG9zaXRpb24gPSBfdG1wXzBfaW5Qb3NpdGlvbi54eTAxOwp9CgAAAAALAgAAdW5pZm9ybSBzYW1wbGVyMkQgdVRleHR1cmVTYW1wbGVyXzBfUzA7CmluIGhhbGYzIHZpblNoYWRvd1BhcmFtc19TMDsKaW4gaGFsZjQgdmluQ29sb3JfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBSUmVjdFNoYWRvdwoJaGFsZjMgc2hhZG93UGFyYW1zOwoJc2hhZG93UGFyYW1zID0gdmluU2hhZG93UGFyYW1zX1MwOwoJaGFsZjQgb3V0cHV0Q29sb3JfUzA7CglvdXRwdXRDb2xvcl9TMCA9IHZpbkNvbG9yX1MwOwoJaGFsZiBkID0gbGVuZ3RoKHNoYWRvd1BhcmFtcy54eSk7CglmbG9hdDIgdXYgPSBmbG9hdDIoc2hhZG93UGFyYW1zLnogKiAoMS4wIC0gZCksIDAuNSk7CgloYWxmIGZhY3RvciA9IHNhbXBsZSh1VGV4dHVyZVNhbXBsZXJfMF9TMCwgdXYpLjAwMHIuYTsKCWhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoZmFjdG9yKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAoAAABpblBvc2l0aW9uAAAHAAAAaW5Db2xvcgAOAAAAaW5TaGFkb3dQYXJhbXMAAAAAAAA=","HVIAAAAAABIAAGAAAQ4AAAH477776R24EAAAIOBQAD6P7777777777YDAAAAAAAAAAAGIBIAAABAAAAANAEAAAAAAAAAAAAAABAAOAAAABAAAAAAABBAMAAAAA":"CgAAAExTS1N0AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBoYWxmNCBjb2xvcjsKaW4gZmxvYXQyIGxvY2FsQ29vcmQ7CmZsYXQgb3V0IGhhbGY0IHZjb2xvcl9TMDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgl2Y29sb3JfUzAgPSBjb2xvcjsKCXNrX1Bvc2l0aW9uID0gcG9zaXRpb24ueHkwMTsKCXsKCQl2VHJhbnNmb3JtZWRDb29yZHNfMl9TMCA9IGZsb2F0M3gyKHVtYXRyaXhfUzEpICogbG9jYWxDb29yZC54eTE7Cgl9Cn0KAAAAAHMCAAB1bmlmb3JtIGZsb2F0M3gzIHVtYXRyaXhfUzE7CnVuaWZvcm0gc2FtcGxlcjJEIHVUZXh0dXJlU2FtcGxlcl8wX1MxOwpmbGF0IGluIGhhbGY0IHZjb2xvcl9TMDsKaW4gZmxvYXQyIHZUcmFuc2Zvcm1lZENvb3Jkc18yX1MwOwpoYWxmNCBUZXh0dXJlRWZmZWN0X1MxX2MwKGhhbGY0IF9pbnB1dCkgCnsKCXJldHVybiBzYW1wbGUodVRleHR1cmVTYW1wbGVyXzBfUzEsIHZUcmFuc2Zvcm1lZENvb3Jkc18yX1MwKS5ycnJyOwp9CmhhbGY0IE1hdHJpeEVmZmVjdF9TMShoYWxmNCBfaW5wdXQpIAp7CglyZXR1cm4gVGV4dHVyZUVmZmVjdF9TMV9jMChfaW5wdXQpOwp9CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBRdWFkUGVyRWRnZUFBR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2Y29sb3JfUzA7Cgljb25zdCBoYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KDEpOwoJaGFsZjQgb3V0cHV0X1MxOwoJb3V0cHV0X1MxID0gTWF0cml4RWZmZWN0X1MxKG91dHB1dENvdmVyYWdlX1MwKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dF9TMTsKCX0KfQoAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAIAAAAcG9zaXRpb24FAAAAY29sb3IAAAAKAAAAbG9jYWxDb29yZAAAAAAAAA==","AYQA5AADQAAAOAEARAFQJAABBADIB7777777777777777777777767YAAAAAAAAAACAAYQADAAAEAFEURUKQKAAAYAAAAAAAAIAAAABSCICWKY2FAEAAAMAAAAAAAAAAAAAIADQAAAAIAAAAAAAIIDAAAA":"CgAAAExTS1PMAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQ0IHVsb2NhbE1hdHJpeF9TMDsKaW4gZmxvYXQyIGluUG9zaXRpb247CmluIGhhbGY0IGluQ29sb3I7CmluIGZsb2F0NCBpbkNpcmNsZUVkZ2U7Cm91dCBmbG9hdDQgdmluQ2lyY2xlRWRnZV9TMDsKb3V0IGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBDaXJjbGVHZW9tZXRyeVByb2Nlc3NvcgoJdmluQ2lyY2xlRWRnZV9TMCA9IGluQ2lyY2xlRWRnZTsKCXZpbkNvbG9yX1MwID0gaW5Db2xvcjsKCWZsb2F0MiBfdG1wXzBfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247CglmbG9hdDIgX3RtcF8xX2luUG9zaXRpb24gPSB1bG9jYWxNYXRyaXhfUzAueHogKiBpblBvc2l0aW9uICsgdWxvY2FsTWF0cml4X1MwLnl3OwoJc2tfUG9zaXRpb24gPSBfdG1wXzBfaW5Qb3NpdGlvbi54eTAxOwp9CgEAAAB+BQAAY29uc3QgaW50IGtGaWxsQldfUzFfYzAgPSAwOwpjb25zdCBpbnQga0ludmVyc2VGaWxsQldfUzFfYzAgPSAyOwpjb25zdCBpbnQga0ludmVyc2VGaWxsQUFfUzFfYzAgPSAzOwp1bmlmb3JtIGZsb2F0NCB1cmVjdFVuaWZvcm1fUzFfYzA7CmluIGZsb2F0NCB2aW5DaXJjbGVFZGdlX1MwOwppbiBoYWxmNCB2aW5Db2xvcl9TMDsKaGFsZjQgUmVjdF9TMV9jMChoYWxmNCBfaW5wdXQpIAp7CgloYWxmNCBfdG1wXzBfaW5Db2xvciA9IF9pbnB1dDsKCWhhbGYgY292ZXJhZ2U7CglpZiAoaW50KDEpID09IGtGaWxsQldfUzFfYzAgfHwgaW50KDEpID09IGtJbnZlcnNlRmlsbEJXX1MxX2MwKSAKCXsKCQljb3ZlcmFnZSA9IGhhbGYoYWxsKGdyZWF0ZXJUaGFuKGZsb2F0NChza19GcmFnQ29vcmQueHksIHVyZWN0VW5pZm9ybV9TMV9jMC56dyksIGZsb2F0NCh1cmVjdFVuaWZvcm1fUzFfYzAueHksIHNrX0ZyYWdDb29yZC54eSkpKSk7Cgl9CgllbHNlIAoJewoJCWhhbGY0IGRpc3RzNCA9IHNhdHVyYXRlKGhhbGY0KDEuMCwgMS4wLCAtMS4wLCAtMS4wKSAqIGhhbGY0KHNrX0ZyYWdDb29yZC54eXh5IC0gdXJlY3RVbmlmb3JtX1MxX2MwKSk7CgkJaGFsZjIgZGlzdHMyID0gKGRpc3RzNC54eSArIGRpc3RzNC56dykgLSAxLjA7CgkJY292ZXJhZ2UgPSBkaXN0czIueCAqIGRpc3RzMi55OwoJfQoJaWYgKGludCgxKSA9PSBrSW52ZXJzZUZpbGxCV19TMV9jMCB8fCBpbnQoMSkgPT0ga0ludmVyc2VGaWxsQUFfUzFfYzApIAoJewoJCWNvdmVyYWdlID0gMS4wIC0gY292ZXJhZ2U7Cgl9CglyZXR1cm4gaGFsZjQoaGFsZjQoY292ZXJhZ2UpKTsKfQpoYWxmNCBCbGVuZF9TMShoYWxmNCBfc3JjLCBoYWxmNCBfZHN0KSAKewoJcmV0dXJuIGJsZW5kX21vZHVsYXRlKFJlY3RfUzFfYzAoX3NyYyksIF9zcmMpOwp9CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBDaXJjbGVHZW9tZXRyeVByb2Nlc3NvcgoJZmxvYXQ0IGNpcmNsZUVkZ2U7CgljaXJjbGVFZGdlID0gdmluQ2lyY2xlRWRnZV9TMDsKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2aW5Db2xvcl9TMDsKCWZsb2F0IGQgPSBsZW5ndGgoY2lyY2xlRWRnZS54eSk7CgloYWxmIGRpc3RhbmNlVG9PdXRlckVkZ2UgPSBoYWxmKGNpcmNsZUVkZ2UueiAqICgxLjAgLSBkKSk7CgloYWxmIGVkZ2VBbHBoYSA9IHNhdHVyYXRlKGRpc3RhbmNlVG9PdXRlckVkZ2UpOwoJaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNChlZGdlQWxwaGEpOwoJaGFsZjQgb3V0cHV0X1MxOwoJb3V0cHV0X1MxID0gQmxlbmRfUzEob3V0cHV0Q292ZXJhZ2VfUzAsIGhhbGY0KDEpKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dF9TMTsKCX0KfQoAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAADAAAACgAAAGluUG9zaXRpb24AAAcAAABpbkNvbG9yAAwAAABpbkNpcmNsZUVkZ2UAAAAA","HTQAAGAABBYAAAEIXBAAAGEAMAAAAAAAAAAAAAAAQAHAAAAAQAAAAAAAQQGAAAAA":"CgAAAExTS1M/AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBpblBvc2l0aW9uOwppbiBoYWxmNCBpbkNvbG9yOwppbiBmbG9hdDQgaW5RdWFkRWRnZTsKb3V0IGZsb2F0NCB2UXVhZEVkZ2VfUzA7Cm91dCBoYWxmNCB2aW5Db2xvcl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZEVkZ2UKCXZRdWFkRWRnZV9TMCA9IGluUXVhZEVkZ2U7Cgl2aW5Db2xvcl9TMCA9IGluQ29sb3I7CglmbG9hdDIgX3RtcF8wX2luUG9zaXRpb24gPSBpblBvc2l0aW9uOwoJc2tfUG9zaXRpb24gPSBfdG1wXzBfaW5Qb3NpdGlvbi54eTAxOwp9CgABAAAABQMAAGluIGZsb2F0NCB2UXVhZEVkZ2VfUzA7CmluIGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgUXVhZEVkZ2UKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2aW5Db2xvcl9TMDsKCWhhbGYgZWRnZUFscGhhOwoJaGFsZjIgZHV2ZHggPSBoYWxmMihkRmR4KHZRdWFkRWRnZV9TMC54eSkpOwoJaGFsZjIgZHV2ZHkgPSBoYWxmMihkRmR5KHZRdWFkRWRnZV9TMC54eSkpOwoJaWYgKHZRdWFkRWRnZV9TMC56ID4gMC4wICYmIHZRdWFkRWRnZV9TMC53ID4gMC4wKSAKCXsKCQllZGdlQWxwaGEgPSBoYWxmKG1pbihtaW4odlF1YWRFZGdlX1MwLnosIHZRdWFkRWRnZV9TMC53KSArIDAuNSwgMS4wKSk7Cgl9CgllbHNlIAoJewoJCWhhbGYyIGdGID0gaGFsZjIoaGFsZigyLjAqdlF1YWRFZGdlX1MwLngqZHV2ZHgueCAtIGR1dmR4LnkpLCAgICAgICAgICAgICAgICAgaGFsZigyLjAqdlF1YWRFZGdlX1MwLngqZHV2ZHkueCAtIGR1dmR5LnkpKTsKCQllZGdlQWxwaGEgPSBoYWxmKHZRdWFkRWRnZV9TMC54KnZRdWFkRWRnZV9TMC54IC0gdlF1YWRFZGdlX1MwLnkpOwoJCWVkZ2VBbHBoYSA9IHNhdHVyYXRlKDAuNSAtIGVkZ2VBbHBoYSAvIGxlbmd0aChnRikpOwoJfQoJaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNChlZGdlQWxwaGEpOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dENvbG9yX1MwICogb3V0cHV0Q292ZXJhZ2VfUzA7Cgl9Cn0KAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAKAAAAaW5Qb3NpdGlvbgAABwAAAGluQ29sb3IACgAAAGluUXVhZEVkZ2UAAAAAAAA=","FAAQMYAAMAAAEADAAABAEYAAAICIAB5AABQAAAQAMAAAEATAAABAIIGAAEDCBYQCA4AAAAAAEAKPABAAAAAAB2AAAAAAACAAAAAEBSAAAAAAA":"CgAAAExTS1PUCwAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0NCByYWRpaV9zZWxlY3RvcjsKaW4gZmxvYXQ0IGNvcm5lcl9hbmRfcmFkaXVzX291dHNldHM7CmluIGZsb2F0NCBhYV9ibG9hdF9hbmRfY292ZXJhZ2U7CmluIGZsb2F0NCByYWRpaV94OwppbiBmbG9hdDQgcmFkaWlfeTsKaW4gZmxvYXQ0IHNrZXc7CmluIGZsb2F0MiB0cmFuc2xhdGVfYW5kX2xvY2Fscm90YXRlOwppbiBoYWxmNCBjb2xvcjsKZmxhdCBvdXQgaGFsZjQgdmNvbG9yX1MwOwpvdXQgZmxvYXQyIHZhcmNjb29yZF9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgRmlsbFJSZWN0T3A6OlByb2Nlc3NvcgoJdmNvbG9yX1MwID0gY29sb3I7CglmbG9hdCBhYV9ibG9hdF9tdWx0aXBsaWVyID0gMTsKCWZsb2F0MiBjb3JuZXIgPSBjb3JuZXJfYW5kX3JhZGl1c19vdXRzZXRzLnh5OwoJZmxvYXQyIHJhZGl1c19vdXRzZXQgPSBjb3JuZXJfYW5kX3JhZGl1c19vdXRzZXRzLnp3OwoJZmxvYXQyIGFhX2Jsb2F0X2RpcmVjdGlvbiA9IGFhX2Jsb2F0X2FuZF9jb3ZlcmFnZS54eTsKCWZsb2F0IGlzX2xpbmVhcl9jb3ZlcmFnZSA9IGFhX2Jsb2F0X2FuZF9jb3ZlcmFnZS53OwoJZmxvYXQyIHBpeGVsbGVuZ3RoID0gaW52ZXJzZXNxcnQoZmxvYXQyKGRvdChza2V3Lnh6LCBza2V3Lnh6KSwgZG90KHNrZXcueXcsIHNrZXcueXcpKSk7CglmbG9hdDQgbm9ybWFsaXplZF9heGlzX2RpcnMgPSBza2V3ICogcGl4ZWxsZW5ndGgueHl4eTsKCWZsb2F0MiBheGlzd2lkdGhzID0gKGFicyhub3JtYWxpemVkX2F4aXNfZGlycy54eSkgKyBhYnMobm9ybWFsaXplZF9heGlzX2RpcnMuencpKTsKCWZsb2F0MiBhYV9ibG9hdHJhZGl1cyA9IGF4aXN3aWR0aHMgKiBwaXhlbGxlbmd0aCAqIC41OwoJZmxvYXQ0IHJhZGlpX2FuZF9uZWlnaGJvcnMgPSByYWRpaV9zZWxlY3RvciogZmxvYXQ0eDQocmFkaWlfeCwgcmFkaWlfeSwgcmFkaWlfeC55eHd6LCByYWRpaV95Lnd6eXgpOwoJZmxvYXQyIHJhZGlpID0gcmFkaWlfYW5kX25laWdoYm9ycy54eTsKCWZsb2F0MiBuZWlnaGJvcl9yYWRpaSA9IHJhZGlpX2FuZF9uZWlnaGJvcnMuenc7CglmbG9hdCBjb3ZlcmFnZV9tdWx0aXBsaWVyID0gMTsKCWlmIChhbnkoZ3JlYXRlclRoYW4oYWFfYmxvYXRyYWRpdXMsIGZsb2F0MigxKSkpKSAKCXsKCQljb3JuZXIgPSBtYXgoYWJzKGNvcm5lciksIGFhX2Jsb2F0cmFkaXVzKSAqIHNpZ24oY29ybmVyKTsKCQljb3ZlcmFnZV9tdWx0aXBsaWVyID0gMSAvIChtYXgoYWFfYmxvYXRyYWRpdXMueCwgMSkgKiBtYXgoYWFfYmxvYXRyYWRpdXMueSwgMSkpOwoJCXJhZGlpID0gZmxvYXQyKDApOwoJfQoJZmxvYXQgY292ZXJhZ2UgPSBhYV9ibG9hdF9hbmRfY292ZXJhZ2UuejsKCWlmIChhbnkobGVzc1RoYW4ocmFkaWksIGFhX2Jsb2F0cmFkaXVzICogMS41KSkpIAoJewoJCXJhZGlpID0gZmxvYXQyKDApOwoJCWFhX2Jsb2F0X2RpcmVjdGlvbiA9IHNpZ24oY29ybmVyKTsKCQlpZiAoY292ZXJhZ2UgPiAuNSkgCgkJewoJCQlhYV9ibG9hdF9kaXJlY3Rpb24gPSAtYWFfYmxvYXRfZGlyZWN0aW9uOwoJCX0KCQlpc19saW5lYXJfY292ZXJhZ2UgPSAxOwoJfQoJZWxzZSAKCXsKCQlyYWRpaSA9IGNsYW1wKHJhZGlpLCBwaXhlbGxlbmd0aCAqIDEuNSwgMiAtIHBpeGVsbGVuZ3RoICogMS41KTsKCQluZWlnaGJvcl9yYWRpaSA9IGNsYW1wKG5laWdoYm9yX3JhZGlpLCBwaXhlbGxlbmd0aCAqIDEuNSwgMiAtIHBpeGVsbGVuZ3RoICogMS41KTsKCQlmbG9hdDIgc3BhY2luZyA9IDIgLSByYWRpaSAtIG5laWdoYm9yX3JhZGlpOwoJCWZsb2F0MiBleHRyYV9wYWQgPSBtYXgocGl4ZWxsZW5ndGggKiAuMDYyNSAtIHNwYWNpbmcsIGZsb2F0MigwKSk7CgkJcmFkaWkgLT0gZXh0cmFfcGFkICogLjU7Cgl9CglmbG9hdDIgYWFfb3V0c2V0ID0gYWFfYmxvYXRfZGlyZWN0aW9uICogYWFfYmxvYXRyYWRpdXMgKiBhYV9ibG9hdF9tdWx0aXBsaWVyOwoJZmxvYXQyIHZlcnRleHBvcyA9IGNvcm5lciArIHJhZGl1c19vdXRzZXQgKiByYWRpaSArIGFhX291dHNldDsKCWlmIChjb3ZlcmFnZSA+IC41KSAKCXsKCQlpZiAoYWFfYmxvYXRfZGlyZWN0aW9uLnggIT0gMCAmJiB2ZXJ0ZXhwb3MueCAqIGNvcm5lci54IDwgMCkgCgkJewoJCQlmbG9hdCBiYWNrc2V0ID0gYWJzKHZlcnRleHBvcy54KTsKCQkJdmVydGV4cG9zLnggPSAwOwoJCQl2ZXJ0ZXhwb3MueSArPSBiYWNrc2V0ICogc2lnbihjb3JuZXIueSkgKiBwaXhlbGxlbmd0aC55L3BpeGVsbGVuZ3RoLng7CgkJCWNvdmVyYWdlID0gKGNvdmVyYWdlIC0gLjUpICogYWJzKGNvcm5lci54KSAvIChhYnMoY29ybmVyLngpICsgYmFja3NldCkgKyAuNTsKCQl9CgkJaWYgKGFhX2Jsb2F0X2RpcmVjdGlvbi55ICE9IDAgJiYgdmVydGV4cG9zLnkgKiBjb3JuZXIueSA8IDApIAoJCXsKCQkJZmxvYXQgYmFja3NldCA9IGFicyh2ZXJ0ZXhwb3MueSk7CgkJCXZlcnRleHBvcy55ID0gMDsKCQkJdmVydGV4cG9zLnggKz0gYmFja3NldCAqIHNpZ24oY29ybmVyLngpICogcGl4ZWxsZW5ndGgueC9waXhlbGxlbmd0aC55OwoJCQljb3ZlcmFnZSA9IChjb3ZlcmFnZSAtIC41KSAqIGFicyhjb3JuZXIueSkgLyAoYWJzKGNvcm5lci55KSArIGJhY2tzZXQpICsgLjU7CgkJfQoJfQoJZmxvYXQyeDIgc2tld21hdHJpeCA9IGZsb2F0MngyKHNrZXcueHksIHNrZXcuencpOwoJZmxvYXQyIGRldmNvb3JkID0gdmVydGV4cG9zICogc2tld21hdHJpeCArIHRyYW5zbGF0ZV9hbmRfbG9jYWxyb3RhdGUueHk7CglpZiAoMCAhPSBpc19saW5lYXJfY292ZXJhZ2UpIAoJewoJCXZhcmNjb29yZF9TMC54eSA9IGZsb2F0MigwLCBjb3ZlcmFnZSAqIGNvdmVyYWdlX211bHRpcGxpZXIpOwoJfQoJZWxzZSAKCXsKCQlmbG9hdDIgYXJjY29vcmQgPSAxIC0gYWJzKHJhZGl1c19vdXRzZXQpICsgYWFfb3V0c2V0L3JhZGlpICogY29ybmVyOwoJCXZhcmNjb29yZF9TMC54eSA9IGZsb2F0MihhcmNjb29yZC54KzEsIGFyY2Nvb3JkLnkpOwoJfQoJc2tfUG9zaXRpb24gPSBkZXZjb29yZC54eTAxOwp9CgEAAACbBAAAdW5pZm9ybSBmbG9hdDQgdWlubmVyUmVjdF9TMTsKdW5pZm9ybSBmbG9hdDIgdWludlJhZGlpWFlfUzE7CmZsYXQgaW4gaGFsZjQgdmNvbG9yX1MwOwppbiBmbG9hdDIgdmFyY2Nvb3JkX1MwOwpoYWxmNCBFbGxpcHRpY2FsUlJlY3RfUzEoaGFsZjQgX2lucHV0KSAKewoJZmxvYXQyIGR4eTAgPSB1aW5uZXJSZWN0X1MxLkxUIC0gc2tfRnJhZ0Nvb3JkLnh5OwoJZmxvYXQyIGR4eTEgPSBza19GcmFnQ29vcmQueHkgLSB1aW5uZXJSZWN0X1MxLlJCOwoJZmxvYXQyIGR4eSA9IG1heChtYXgoZHh5MCwgZHh5MSksIDAuMCk7CglmbG9hdDIgWiA9IGR4eSAqIHVpbnZSYWRpaVhZX1MxLnh5OwoJaGFsZiBpbXBsaWNpdCA9IGhhbGYoZG90KFosIGR4eSkgLSAxLjApOwoJaGFsZiBncmFkX2RvdCA9IGhhbGYoNC4wICogZG90KFosIFopKTsKCWdyYWRfZG90ID0gbWF4KGdyYWRfZG90LCAxLjBlLTQpOwoJaGFsZiBhcHByb3hfZGlzdCA9IGltcGxpY2l0ICogaGFsZihpbnZlcnNlc3FydChncmFkX2RvdCkpOwoJaGFsZiBhbHBoYSA9IGNsYW1wKDAuNSArIGFwcHJveF9kaXN0LCAwLjAsIDEuMCk7CglyZXR1cm4gX2lucHV0ICogYWxwaGE7Cn0Kdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIEZpbGxSUmVjdE9wOjpQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2Y29sb3JfUzA7CglmbG9hdCB4X3BsdXNfMT12YXJjY29vcmRfUzAueCwgeT12YXJjY29vcmRfUzAueTsKCWhhbGYgY292ZXJhZ2U7CglpZiAoMCA9PSB4X3BsdXNfMSkgCgl7CgkJY292ZXJhZ2UgPSBoYWxmKHkpOwoJfQoJZWxzZSAKCXsKCQlmbG9hdCBmbiA9IHhfcGx1c18xICogKHhfcGx1c18xIC0gMik7CgkJZm4gPSBmbWEoeSx5LCBmbik7CgkJZmxvYXQgZm53aWR0aCA9IGZ3aWR0aChmbik7CgkJY292ZXJhZ2UgPSAuNSAtIGhhbGYoZm4vZm53aWR0aCk7CgkJY292ZXJhZ2UgPSBjbGFtcChjb3ZlcmFnZSwgMCwgMSk7Cgl9CgloYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KGNvdmVyYWdlKTsKCWhhbGY0IG91dHB1dF9TMTsKCW91dHB1dF9TMSA9IEVsbGlwdGljYWxSUmVjdF9TMShvdXRwdXRDb3ZlcmFnZV9TMCk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRfUzE7Cgl9Cn0KAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAIAAAADgAAAHJhZGlpX3NlbGVjdG9yAAAZAAAAY29ybmVyX2FuZF9yYWRpdXNfb3V0c2V0cwAAABUAAABhYV9ibG9hdF9hbmRfY292ZXJhZ2UAAAAHAAAAcmFkaWlfeAAHAAAAcmFkaWlfeQAEAAAAc2tldxkAAAB0cmFuc2xhdGVfYW5kX2xvY2Fscm90YXRlAAAABQAAAGNvbG9yAAAAAAAAAA==","HUIAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAAAAAADUAANAAAAAAAAAIAAAABLAIABAAAAABAEGABBAMAAAAAAAAAAAAB2AAAAAAACAAAAAEBSAAAAA":"CgAAAExTS1M8AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMV9jMDsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBmbG9hdDIgbG9jYWxDb29yZDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfM19TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cgl7CgkJdlRyYW5zZm9ybWVkQ29vcmRzXzNfUzAgPSBmbG9hdDN4Mih1bWF0cml4X1MxX2MwKSAqIGxvY2FsQ29vcmQueHkxOwoJfQp9CgAAAAC2AgAAdW5pZm9ybSBmbG9hdDN4MyB1bWF0cml4X1MxX2MwOwp1bmlmb3JtIHNhbXBsZXIyRCB1VGV4dHVyZVNhbXBsZXJfMF9TMTsKaW4gZmxvYXQyIHZUcmFuc2Zvcm1lZENvb3Jkc18zX1MwOwpoYWxmNCBUZXh0dXJlRWZmZWN0X1MxX2MwX2MwKGhhbGY0IF9pbnB1dCkgCnsKCXJldHVybiBzYW1wbGUodVRleHR1cmVTYW1wbGVyXzBfUzEsIHZUcmFuc2Zvcm1lZENvb3Jkc18zX1MwKTsKfQpoYWxmNCBNYXRyaXhFZmZlY3RfUzFfYzAoaGFsZjQgX2lucHV0KSAKewoJcmV0dXJuIFRleHR1cmVFZmZlY3RfUzFfYzBfYzAoX2lucHV0KTsKfQpoYWxmNCBCbGVuZF9TMShoYWxmNCBfc3JjLCBoYWxmNCBfZHN0KSAKewoJcmV0dXJuIGJsZW5kX21vZHVsYXRlKE1hdHJpeEVmZmVjdF9TMV9jMChfc3JjKSwgX3NyYyk7Cn0Kdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJaGFsZjQgb3V0cHV0Q29sb3JfUzAgPSBoYWxmNCgxKTsKCWNvbnN0IGhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoMSk7CgloYWxmNCBvdXRwdXRfUzE7CglvdXRwdXRfUzEgPSBCbGVuZF9TMShvdXRwdXRDb2xvcl9TMCwgaGFsZjQoMSkpOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dF9TMSAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAIAAAAcG9zaXRpb24KAAAAbG9jYWxDb29yZAAAAAAAAA==","HUIAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAAAAAADUAANAAAAAAIBAIAAAABLCIIBAAAAABAEGABBAMAACAIAAAAAAAB2AAAAAAACAAAAAEBSAAAAA":"CgAAAExTS1M8AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMV9jMDsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBmbG9hdDIgbG9jYWxDb29yZDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfM19TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cgl7CgkJdlRyYW5zZm9ybWVkQ29vcmRzXzNfUzAgPSBmbG9hdDN4Mih1bWF0cml4X1MxX2MwKSAqIGxvY2FsQ29vcmQueHkxOwoJfQp9CgAAAADJAwAAdW5pZm9ybSBmbG9hdDQgdWNsYW1wX1MxX2MwX2MwOwp1bmlmb3JtIGZsb2F0M3gzIHVtYXRyaXhfUzFfYzA7CnVuaWZvcm0gc2FtcGxlcjJEIHVUZXh0dXJlU2FtcGxlcl8wX1MxOwppbiBmbG9hdDIgdlRyYW5zZm9ybWVkQ29vcmRzXzNfUzA7CmhhbGY0IFRleHR1cmVFZmZlY3RfUzFfYzBfYzAoaGFsZjQgX2lucHV0KSAKewoJZmxvYXQyIGluQ29vcmQgPSB2VHJhbnNmb3JtZWRDb29yZHNfM19TMDsKCWZsb2F0MiBzdWJzZXRDb29yZDsKCXN1YnNldENvb3JkLnggPSBpbkNvb3JkLng7CglzdWJzZXRDb29yZC55ID0gaW5Db29yZC55OwoJZmxvYXQyIGNsYW1wZWRDb29yZDsKCWNsYW1wZWRDb29yZCA9IGNsYW1wKHN1YnNldENvb3JkLCB1Y2xhbXBfUzFfYzBfYzAueHksIHVjbGFtcF9TMV9jMF9jMC56dyk7CgloYWxmNCB0ZXh0dXJlQ29sb3IgPSBzYW1wbGUodVRleHR1cmVTYW1wbGVyXzBfUzEsIGNsYW1wZWRDb29yZCk7CglyZXR1cm4gdGV4dHVyZUNvbG9yOwp9CmhhbGY0IE1hdHJpeEVmZmVjdF9TMV9jMChoYWxmNCBfaW5wdXQpIAp7CglyZXR1cm4gVGV4dHVyZUVmZmVjdF9TMV9jMF9jMChfaW5wdXQpOwp9CmhhbGY0IEJsZW5kX1MxKGhhbGY0IF9zcmMsIGhhbGY0IF9kc3QpIAp7CglyZXR1cm4gYmxlbmRfbW9kdWxhdGUoTWF0cml4RWZmZWN0X1MxX2MwKF9zcmMpLCBfc3JjKTsKfQp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMCA9IGhhbGY0KDEpOwoJY29uc3QgaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNCgxKTsKCWhhbGY0IG91dHB1dF9TMTsKCW91dHB1dF9TMSA9IEJsZW5kX1MxKG91dHB1dENvbG9yX1MwLCBoYWxmNCgxKSk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0X1MxICogb3V0cHV0Q292ZXJhZ2VfUzA7Cgl9Cn0KAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAIAAAAcG9zaXRpb24KAAAAbG9jYWxDb29yZAAAAAAAAA==","HWQACAAAABAAADAAAIOAAAAADIIAAIRODAAP577774DSAIAA737777YBAAAAAAAAAAAKAAYAAAACAAAAAAACCAYAAA":"CgAAAExTS1ONAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gZmxvYXQgY292ZXJhZ2U7CmluIGhhbGY0IGNvbG9yOwppbiBmbG9hdDQgZ2VvbVN1YnNldDsKZmxhdCBvdXQgaGFsZjQgdmNvbG9yX1MwOwpvdXQgZmxvYXQgdmNvdmVyYWdlX1MwOwpmbGF0IG91dCBmbG9hdDQgdmdlb21TdWJzZXRfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJZmxvYXQyIHBvc2l0aW9uID0gcG9zaXRpb24ueHk7Cgl2Y29sb3JfUzAgPSBjb2xvcjsKCXZjb3ZlcmFnZV9TMCA9IGNvdmVyYWdlOwoJdmdlb21TdWJzZXRfUzAgPSBnZW9tU3Vic2V0OwoJc2tfUG9zaXRpb24gPSBwb3NpdGlvbi54eTAxOwp9CgAAAAEAAAB5AgAAZmxhdCBpbiBoYWxmNCB2Y29sb3JfUzA7CmluIGZsb2F0IHZjb3ZlcmFnZV9TMDsKZmxhdCBpbiBmbG9hdDQgdmdlb21TdWJzZXRfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBRdWFkUGVyRWRnZUFBR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2Y29sb3JfUzA7CglmbG9hdCBjb3ZlcmFnZSA9IHZjb3ZlcmFnZV9TMDsKCWZsb2F0NCBnZW9TdWJzZXQ7CglnZW9TdWJzZXQgPSB2Z2VvbVN1YnNldF9TMDsKCWhhbGY0IGRpc3RzNCA9IGNsYW1wKGhhbGY0KDEsIDEsIC0xLCAtMSkgKiBoYWxmNChza19GcmFnQ29vcmQueHl4eSAtIGdlb1N1YnNldCksIDAsIDEpOwoJaGFsZjIgZGlzdHMyID0gZGlzdHM0Lnh5ICsgZGlzdHM0Lnp3IC0gMTsKCWhhbGYgc3Vic2V0Q292ZXJhZ2UgPSBkaXN0czIueCAqIGRpc3RzMi55OwoJY292ZXJhZ2UgPSBtaW4oY292ZXJhZ2UsIHN1YnNldENvdmVyYWdlKTsKCWhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoaGFsZihjb3ZlcmFnZSkpOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dENvbG9yX1MwICogb3V0cHV0Q292ZXJhZ2VfUzA7Cgl9Cn0KAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAIAAAAcG9zaXRpb24IAAAAY292ZXJhZ2UFAAAAY29sb3IAAAAKAAAAZ2VvbVN1YnNldAAAAAAAAA==","AYQA5AADQAAAOAEARAFQJAABBADIB7777777777777777777777767YAAAAAAAAAACABYQA6AAAEAAAAAAAIADQAAAAIAAAAAAAIIDA":"CgAAAExTS1PMAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQ0IHVsb2NhbE1hdHJpeF9TMDsKaW4gZmxvYXQyIGluUG9zaXRpb247CmluIGhhbGY0IGluQ29sb3I7CmluIGZsb2F0NCBpbkNpcmNsZUVkZ2U7Cm91dCBmbG9hdDQgdmluQ2lyY2xlRWRnZV9TMDsKb3V0IGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBDaXJjbGVHZW9tZXRyeVByb2Nlc3NvcgoJdmluQ2lyY2xlRWRnZV9TMCA9IGluQ2lyY2xlRWRnZTsKCXZpbkNvbG9yX1MwID0gaW5Db2xvcjsKCWZsb2F0MiBfdG1wXzBfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247CglmbG9hdDIgX3RtcF8xX2luUG9zaXRpb24gPSB1bG9jYWxNYXRyaXhfUzAueHogKiBpblBvc2l0aW9uICsgdWxvY2FsTWF0cml4X1MwLnl3OwoJc2tfUG9zaXRpb24gPSBfdG1wXzBfaW5Qb3NpdGlvbi54eTAxOwp9CgEAAAB5AwAAdW5pZm9ybSBmbG9hdDQgdWlubmVyUmVjdF9TMTsKdW5pZm9ybSBoYWxmMiB1cmFkaXVzUGx1c0hhbGZfUzE7CmluIGZsb2F0NCB2aW5DaXJjbGVFZGdlX1MwOwppbiBoYWxmNCB2aW5Db2xvcl9TMDsKaGFsZjQgQ2lyY3VsYXJSUmVjdF9TMShoYWxmNCBfaW5wdXQpIAp7CglmbG9hdDIgZHh5MCA9IHVpbm5lclJlY3RfUzEuTFQgLSBza19GcmFnQ29vcmQueHk7CglmbG9hdDIgZHh5MSA9IHNrX0ZyYWdDb29yZC54eSAtIHVpbm5lclJlY3RfUzEuUkI7CglmbG9hdDIgZHh5ID0gbWF4KG1heChkeHkwLCBkeHkxKSwgMC4wKTsKCWhhbGYgYWxwaGEgPSBoYWxmKHNhdHVyYXRlKHVyYWRpdXNQbHVzSGFsZl9TMS54IC0gbGVuZ3RoKGR4eSkpKTsKCXJldHVybiBfaW5wdXQgKiBhbHBoYTsKfQp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgQ2lyY2xlR2VvbWV0cnlQcm9jZXNzb3IKCWZsb2F0NCBjaXJjbGVFZGdlOwoJY2lyY2xlRWRnZSA9IHZpbkNpcmNsZUVkZ2VfUzA7CgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdmluQ29sb3JfUzA7CglmbG9hdCBkID0gbGVuZ3RoKGNpcmNsZUVkZ2UueHkpOwoJaGFsZiBkaXN0YW5jZVRvT3V0ZXJFZGdlID0gaGFsZihjaXJjbGVFZGdlLnogKiAoMS4wIC0gZCkpOwoJaGFsZiBlZGdlQWxwaGEgPSBzYXR1cmF0ZShkaXN0YW5jZVRvT3V0ZXJFZGdlKTsKCWhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoZWRnZUFscGhhKTsKCWhhbGY0IG91dHB1dF9TMTsKCW91dHB1dF9TMSA9IENpcmN1bGFyUlJlY3RfUzEob3V0cHV0Q292ZXJhZ2VfUzApOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dENvbG9yX1MwICogb3V0cHV0X1MxOwoJfQp9CgAAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAADAAAACgAAAGluUG9zaXRpb24AAAcAAABpbkNvbG9yAAwAAABpbkNpcmNsZUVkZ2UAAAAA","AYTRVAADQAAAOAEARAFQJAABBADAAAILBYAACCYUQD777777777767YAAAAAAAAAAAAOQAAAAAAAQAAAABAMQAAAAA":"CgAAAExTS1NyAgAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQ0IHVsb2NhbE1hdHJpeF9TMDsKaW4gZmxvYXQyIGluUG9zaXRpb247CmluIGhhbGY0IGluQ29sb3I7CmluIGZsb2F0NCBpbkNpcmNsZUVkZ2U7CmluIGhhbGYzIGluQ2xpcFBsYW5lOwppbiBoYWxmMyBpbklzZWN0UGxhbmU7Cm91dCBmbG9hdDQgdmluQ2lyY2xlRWRnZV9TMDsKb3V0IGhhbGYzIHZpbkNsaXBQbGFuZV9TMDsKb3V0IGhhbGYzIHZpbklzZWN0UGxhbmVfUzA7Cm91dCBoYWxmNCB2aW5Db2xvcl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgQ2lyY2xlR2VvbWV0cnlQcm9jZXNzb3IKCXZpbkNpcmNsZUVkZ2VfUzAgPSBpbkNpcmNsZUVkZ2U7Cgl2aW5DbGlwUGxhbmVfUzAgPSBpbkNsaXBQbGFuZTsKCXZpbklzZWN0UGxhbmVfUzAgPSBpbklzZWN0UGxhbmU7Cgl2aW5Db2xvcl9TMCA9IGluQ29sb3I7CglmbG9hdDIgX3RtcF8wX2luUG9zaXRpb24gPSBpblBvc2l0aW9uOwoJZmxvYXQyIF90bXBfMV9pblBvc2l0aW9uID0gdWxvY2FsTWF0cml4X1MwLnh6ICogaW5Qb3NpdGlvbiArIHVsb2NhbE1hdHJpeF9TMC55dzsKCXNrX1Bvc2l0aW9uID0gX3RtcF8wX2luUG9zaXRpb24ueHkwMTsKfQoAAAAAAADdAwAAaW4gZmxvYXQ0IHZpbkNpcmNsZUVkZ2VfUzA7CmluIGhhbGYzIHZpbkNsaXBQbGFuZV9TMDsKaW4gaGFsZjMgdmluSXNlY3RQbGFuZV9TMDsKaW4gaGFsZjQgdmluQ29sb3JfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBDaXJjbGVHZW9tZXRyeVByb2Nlc3NvcgoJZmxvYXQ0IGNpcmNsZUVkZ2U7CgljaXJjbGVFZGdlID0gdmluQ2lyY2xlRWRnZV9TMDsKCWhhbGYzIGNsaXBQbGFuZTsKCWNsaXBQbGFuZSA9IHZpbkNsaXBQbGFuZV9TMDsKCWhhbGYzIGlzZWN0UGxhbmU7Cglpc2VjdFBsYW5lID0gdmluSXNlY3RQbGFuZV9TMDsKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2aW5Db2xvcl9TMDsKCWZsb2F0IGQgPSBsZW5ndGgoY2lyY2xlRWRnZS54eSk7CgloYWxmIGRpc3RhbmNlVG9PdXRlckVkZ2UgPSBoYWxmKGNpcmNsZUVkZ2UueiAqICgxLjAgLSBkKSk7CgloYWxmIGVkZ2VBbHBoYSA9IHNhdHVyYXRlKGRpc3RhbmNlVG9PdXRlckVkZ2UpOwoJaGFsZiBkaXN0YW5jZVRvSW5uZXJFZGdlID0gaGFsZihjaXJjbGVFZGdlLnogKiAoZCAtIGNpcmNsZUVkZ2UudykpOwoJaGFsZiBpbm5lckFscGhhID0gc2F0dXJhdGUoZGlzdGFuY2VUb0lubmVyRWRnZSk7CgllZGdlQWxwaGEgKj0gaW5uZXJBbHBoYTsKCWhhbGYgY2xpcCA9IGhhbGYoc2F0dXJhdGUoY2lyY2xlRWRnZS56ICogZG90KGNpcmNsZUVkZ2UueHksIGNsaXBQbGFuZS54eSkgKyBjbGlwUGxhbmUueikpOwoJY2xpcCAqPSBoYWxmKHNhdHVyYXRlKGNpcmNsZUVkZ2UueiAqIGRvdChjaXJjbGVFZGdlLnh5LCBpc2VjdFBsYW5lLnh5KSArIGlzZWN0UGxhbmUueikpOwoJZWRnZUFscGhhICo9IGNsaXA7CgloYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KGVkZ2VBbHBoYSk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRDb3ZlcmFnZV9TMDsKCX0KfQoAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAoAAABpblBvc2l0aW9uAAAHAAAAaW5Db2xvcgAMAAAAaW5DaXJjbGVFZGdlCwAAAGluQ2xpcFBsYW5lAAwAAABpbklzZWN0UGxhbmUAAAAA","HUQAAAAAAAMAADAAAIOAAAH677776IZOCAAP577777777777777777YBAAAAAAAAAAAKAAYAAAACAAAAAAACCAYAAA":"CgAAAExTS1PUAAAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gaGFsZjQgY29sb3I7CmZsYXQgb3V0IGhhbGY0IHZjb2xvcl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgl2Y29sb3JfUzAgPSBjb2xvcjsKCXNrX1Bvc2l0aW9uID0gcG9zaXRpb24ueHkwMTsKfQoAAAAAEQEAAGZsYXQgaW4gaGFsZjQgdmNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdmNvbG9yX1MwOwoJY29uc3QgaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNCgxKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAACAAAACAAAAHBvc2l0aW9uBQAAAGNvbG9yAAAAAAAAAA==","AYAA5AADQAAAOAEARAFQJAABBADIB7777777777777777777777767YAAAAAAAAAAAAOQAAAAAAAQAAAABAMQAAAAA":"CgAAAExTS1OCAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBpblBvc2l0aW9uOwppbiBoYWxmNCBpbkNvbG9yOwppbiBmbG9hdDQgaW5DaXJjbGVFZGdlOwpvdXQgZmxvYXQ0IHZpbkNpcmNsZUVkZ2VfUzA7Cm91dCBoYWxmNCB2aW5Db2xvcl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgQ2lyY2xlR2VvbWV0cnlQcm9jZXNzb3IKCXZpbkNpcmNsZUVkZ2VfUzAgPSBpbkNpcmNsZUVkZ2U7Cgl2aW5Db2xvcl9TMCA9IGluQ29sb3I7CglmbG9hdDIgX3RtcF8wX2luUG9zaXRpb24gPSBpblBvc2l0aW9uOwoJZmxvYXQyIF90bXBfMl9pblBvc2l0aW9uID0gaW5Qb3NpdGlvbjsKCXNrX1Bvc2l0aW9uID0gX3RtcF8wX2luUG9zaXRpb24ueHkwMTsKfQoAAAAAAADqAQAAaW4gZmxvYXQ0IHZpbkNpcmNsZUVkZ2VfUzA7CmluIGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgQ2lyY2xlR2VvbWV0cnlQcm9jZXNzb3IKCWZsb2F0NCBjaXJjbGVFZGdlOwoJY2lyY2xlRWRnZSA9IHZpbkNpcmNsZUVkZ2VfUzA7CgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdmluQ29sb3JfUzA7CglmbG9hdCBkID0gbGVuZ3RoKGNpcmNsZUVkZ2UueHkpOwoJaGFsZiBkaXN0YW5jZVRvT3V0ZXJFZGdlID0gaGFsZihjaXJjbGVFZGdlLnogKiAoMS4wIC0gZCkpOwoJaGFsZiBlZGdlQWxwaGEgPSBzYXR1cmF0ZShkaXN0YW5jZVRvT3V0ZXJFZGdlKTsKCWhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoZWRnZUFscGhhKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAKAAAAaW5Qb3NpdGlvbgAABwAAAGluQ29sb3IADAAAAGluQ2lyY2xlRWRnZQAAAAA=","FAAQMYAAMAAAEADAAABAEYAAAICIAB5AABQAAAQAMAAAEATAAABAIIGAAEDCBYQCA4AAAAAAEAB5AAAAACQHEB4XIQAQAADQAAAABAAAAAAABAEMVDOMCJKRAAAAAHAAAAAAAAAAACQAGAAAAAQAAAAAAAQQGAAA":"CgAAAExTS1PUCwAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0NCByYWRpaV9zZWxlY3RvcjsKaW4gZmxvYXQ0IGNvcm5lcl9hbmRfcmFkaXVzX291dHNldHM7CmluIGZsb2F0NCBhYV9ibG9hdF9hbmRfY292ZXJhZ2U7CmluIGZsb2F0NCByYWRpaV94OwppbiBmbG9hdDQgcmFkaWlfeTsKaW4gZmxvYXQ0IHNrZXc7CmluIGZsb2F0MiB0cmFuc2xhdGVfYW5kX2xvY2Fscm90YXRlOwppbiBoYWxmNCBjb2xvcjsKZmxhdCBvdXQgaGFsZjQgdmNvbG9yX1MwOwpvdXQgZmxvYXQyIHZhcmNjb29yZF9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgRmlsbFJSZWN0T3A6OlByb2Nlc3NvcgoJdmNvbG9yX1MwID0gY29sb3I7CglmbG9hdCBhYV9ibG9hdF9tdWx0aXBsaWVyID0gMTsKCWZsb2F0MiBjb3JuZXIgPSBjb3JuZXJfYW5kX3JhZGl1c19vdXRzZXRzLnh5OwoJZmxvYXQyIHJhZGl1c19vdXRzZXQgPSBjb3JuZXJfYW5kX3JhZGl1c19vdXRzZXRzLnp3OwoJZmxvYXQyIGFhX2Jsb2F0X2RpcmVjdGlvbiA9IGFhX2Jsb2F0X2FuZF9jb3ZlcmFnZS54eTsKCWZsb2F0IGlzX2xpbmVhcl9jb3ZlcmFnZSA9IGFhX2Jsb2F0X2FuZF9jb3ZlcmFnZS53OwoJZmxvYXQyIHBpeGVsbGVuZ3RoID0gaW52ZXJzZXNxcnQoZmxvYXQyKGRvdChza2V3Lnh6LCBza2V3Lnh6KSwgZG90KHNrZXcueXcsIHNrZXcueXcpKSk7CglmbG9hdDQgbm9ybWFsaXplZF9heGlzX2RpcnMgPSBza2V3ICogcGl4ZWxsZW5ndGgueHl4eTsKCWZsb2F0MiBheGlzd2lkdGhzID0gKGFicyhub3JtYWxpemVkX2F4aXNfZGlycy54eSkgKyBhYnMobm9ybWFsaXplZF9heGlzX2RpcnMuencpKTsKCWZsb2F0MiBhYV9ibG9hdHJhZGl1cyA9IGF4aXN3aWR0aHMgKiBwaXhlbGxlbmd0aCAqIC41OwoJZmxvYXQ0IHJhZGlpX2FuZF9uZWlnaGJvcnMgPSByYWRpaV9zZWxlY3RvciogZmxvYXQ0eDQocmFkaWlfeCwgcmFkaWlfeSwgcmFkaWlfeC55eHd6LCByYWRpaV95Lnd6eXgpOwoJZmxvYXQyIHJhZGlpID0gcmFkaWlfYW5kX25laWdoYm9ycy54eTsKCWZsb2F0MiBuZWlnaGJvcl9yYWRpaSA9IHJhZGlpX2FuZF9uZWlnaGJvcnMuenc7CglmbG9hdCBjb3ZlcmFnZV9tdWx0aXBsaWVyID0gMTsKCWlmIChhbnkoZ3JlYXRlclRoYW4oYWFfYmxvYXRyYWRpdXMsIGZsb2F0MigxKSkpKSAKCXsKCQljb3JuZXIgPSBtYXgoYWJzKGNvcm5lciksIGFhX2Jsb2F0cmFkaXVzKSAqIHNpZ24oY29ybmVyKTsKCQljb3ZlcmFnZV9tdWx0aXBsaWVyID0gMSAvIChtYXgoYWFfYmxvYXRyYWRpdXMueCwgMSkgKiBtYXgoYWFfYmxvYXRyYWRpdXMueSwgMSkpOwoJCXJhZGlpID0gZmxvYXQyKDApOwoJfQoJZmxvYXQgY292ZXJhZ2UgPSBhYV9ibG9hdF9hbmRfY292ZXJhZ2UuejsKCWlmIChhbnkobGVzc1RoYW4ocmFkaWksIGFhX2Jsb2F0cmFkaXVzICogMS41KSkpIAoJewoJCXJhZGlpID0gZmxvYXQyKDApOwoJCWFhX2Jsb2F0X2RpcmVjdGlvbiA9IHNpZ24oY29ybmVyKTsKCQlpZiAoY292ZXJhZ2UgPiAuNSkgCgkJewoJCQlhYV9ibG9hdF9kaXJlY3Rpb24gPSAtYWFfYmxvYXRfZGlyZWN0aW9uOwoJCX0KCQlpc19saW5lYXJfY292ZXJhZ2UgPSAxOwoJfQoJZWxzZSAKCXsKCQlyYWRpaSA9IGNsYW1wKHJhZGlpLCBwaXhlbGxlbmd0aCAqIDEuNSwgMiAtIHBpeGVsbGVuZ3RoICogMS41KTsKCQluZWlnaGJvcl9yYWRpaSA9IGNsYW1wKG5laWdoYm9yX3JhZGlpLCBwaXhlbGxlbmd0aCAqIDEuNSwgMiAtIHBpeGVsbGVuZ3RoICogMS41KTsKCQlmbG9hdDIgc3BhY2luZyA9IDIgLSByYWRpaSAtIG5laWdoYm9yX3JhZGlpOwoJCWZsb2F0MiBleHRyYV9wYWQgPSBtYXgocGl4ZWxsZW5ndGggKiAuMDYyNSAtIHNwYWNpbmcsIGZsb2F0MigwKSk7CgkJcmFkaWkgLT0gZXh0cmFfcGFkICogLjU7Cgl9CglmbG9hdDIgYWFfb3V0c2V0ID0gYWFfYmxvYXRfZGlyZWN0aW9uICogYWFfYmxvYXRyYWRpdXMgKiBhYV9ibG9hdF9tdWx0aXBsaWVyOwoJZmxvYXQyIHZlcnRleHBvcyA9IGNvcm5lciArIHJhZGl1c19vdXRzZXQgKiByYWRpaSArIGFhX291dHNldDsKCWlmIChjb3ZlcmFnZSA+IC41KSAKCXsKCQlpZiAoYWFfYmxvYXRfZGlyZWN0aW9uLnggIT0gMCAmJiB2ZXJ0ZXhwb3MueCAqIGNvcm5lci54IDwgMCkgCgkJewoJCQlmbG9hdCBiYWNrc2V0ID0gYWJzKHZlcnRleHBvcy54KTsKCQkJdmVydGV4cG9zLnggPSAwOwoJCQl2ZXJ0ZXhwb3MueSArPSBiYWNrc2V0ICogc2lnbihjb3JuZXIueSkgKiBwaXhlbGxlbmd0aC55L3BpeGVsbGVuZ3RoLng7CgkJCWNvdmVyYWdlID0gKGNvdmVyYWdlIC0gLjUpICogYWJzKGNvcm5lci54KSAvIChhYnMoY29ybmVyLngpICsgYmFja3NldCkgKyAuNTsKCQl9CgkJaWYgKGFhX2Jsb2F0X2RpcmVjdGlvbi55ICE9IDAgJiYgdmVydGV4cG9zLnkgKiBjb3JuZXIueSA8IDApIAoJCXsKCQkJZmxvYXQgYmFja3NldCA9IGFicyh2ZXJ0ZXhwb3MueSk7CgkJCXZlcnRleHBvcy55ID0gMDsKCQkJdmVydGV4cG9zLnggKz0gYmFja3NldCAqIHNpZ24oY29ybmVyLngpICogcGl4ZWxsZW5ndGgueC9waXhlbGxlbmd0aC55OwoJCQljb3ZlcmFnZSA9IChjb3ZlcmFnZSAtIC41KSAqIGFicyhjb3JuZXIueSkgLyAoYWJzKGNvcm5lci55KSArIGJhY2tzZXQpICsgLjU7CgkJfQoJfQoJZmxvYXQyeDIgc2tld21hdHJpeCA9IGZsb2F0MngyKHNrZXcueHksIHNrZXcuencpOwoJZmxvYXQyIGRldmNvb3JkID0gdmVydGV4cG9zICogc2tld21hdHJpeCArIHRyYW5zbGF0ZV9hbmRfbG9jYWxyb3RhdGUueHk7CglpZiAoMCAhPSBpc19saW5lYXJfY292ZXJhZ2UpIAoJewoJCXZhcmNjb29yZF9TMC54eSA9IGZsb2F0MigwLCBjb3ZlcmFnZSAqIGNvdmVyYWdlX211bHRpcGxpZXIpOwoJfQoJZWxzZSAKCXsKCQlmbG9hdDIgYXJjY29vcmQgPSAxIC0gYWJzKHJhZGl1c19vdXRzZXQpICsgYWFfb3V0c2V0L3JhZGlpICogY29ybmVyOwoJCXZhcmNjb29yZF9TMC54eSA9IGZsb2F0MihhcmNjb29yZC54KzEsIGFyY2Nvb3JkLnkpOwoJfQoJc2tfUG9zaXRpb24gPSBkZXZjb29yZC54eTAxOwp9CgEAAABRBQAAY29uc3QgaW50IGtGaWxsQUFfUzFfYzAgPSAxOwpjb25zdCBpbnQga0ludmVyc2VGaWxsQldfUzFfYzAgPSAyOwpjb25zdCBpbnQga0ludmVyc2VGaWxsQUFfUzFfYzAgPSAzOwp1bmlmb3JtIGZsb2F0NCB1Y2lyY2xlX1MxX2MwOwpmbGF0IGluIGhhbGY0IHZjb2xvcl9TMDsKaW4gZmxvYXQyIHZhcmNjb29yZF9TMDsKaGFsZjQgQ2lyY2xlX1MxX2MwKGhhbGY0IF9pbnB1dCkgCnsKCWhhbGY0IF90bXBfMF9pbkNvbG9yID0gX2lucHV0OwoJaGFsZiBkOwoJaWYgKGludCgzKSA9PSBrSW52ZXJzZUZpbGxCV19TMV9jMCB8fCBpbnQoMykgPT0ga0ludmVyc2VGaWxsQUFfUzFfYzApIAoJewoJCWQgPSBoYWxmKChsZW5ndGgoKHVjaXJjbGVfUzFfYzAueHkgLSBza19GcmFnQ29vcmQueHkpICogdWNpcmNsZV9TMV9jMC53KSAtIDEuMCkgKiB1Y2lyY2xlX1MxX2MwLnopOwoJfQoJZWxzZSAKCXsKCQlkID0gaGFsZigoMS4wIC0gbGVuZ3RoKCh1Y2lyY2xlX1MxX2MwLnh5IC0gc2tfRnJhZ0Nvb3JkLnh5KSAqIHVjaXJjbGVfUzFfYzAudykpICogdWNpcmNsZV9TMV9jMC56KTsKCX0KCXJldHVybiBoYWxmNChoYWxmNChpbnQoMykgPT0ga0ZpbGxBQV9TMV9jMCB8fCBpbnQoMykgPT0ga0ludmVyc2VGaWxsQUFfUzFfYzAgPyBzYXR1cmF0ZShkKSA6IGhhbGYoZCA+IDAuNSA/IDEgOiAwKSkpOwp9CmhhbGY0IEJsZW5kX1MxKGhhbGY0IF9zcmMsIGhhbGY0IF9kc3QpIAp7CglyZXR1cm4gYmxlbmRfbW9kdWxhdGUoX3NyYywgQ2lyY2xlX1MxX2MwKF9zcmMpKTsKfQp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgRmlsbFJSZWN0T3A6OlByb2Nlc3NvcgoJaGFsZjQgb3V0cHV0Q29sb3JfUzA7CglvdXRwdXRDb2xvcl9TMCA9IHZjb2xvcl9TMDsKCWZsb2F0IHhfcGx1c18xPXZhcmNjb29yZF9TMC54LCB5PXZhcmNjb29yZF9TMC55OwoJaGFsZiBjb3ZlcmFnZTsKCWlmICgwID09IHhfcGx1c18xKSAKCXsKCQljb3ZlcmFnZSA9IGhhbGYoeSk7Cgl9CgllbHNlIAoJewoJCWZsb2F0IGZuID0geF9wbHVzXzEgKiAoeF9wbHVzXzEgLSAyKTsKCQlmbiA9IGZtYSh5LHksIGZuKTsKCQlmbG9hdCBmbndpZHRoID0gZndpZHRoKGZuKTsKCQljb3ZlcmFnZSA9IC41IC0gaGFsZihmbi9mbndpZHRoKTsKCQljb3ZlcmFnZSA9IGNsYW1wKGNvdmVyYWdlLCAwLCAxKTsKCX0KCWhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoY292ZXJhZ2UpOwoJaGFsZjQgb3V0cHV0X1MxOwoJb3V0cHV0X1MxID0gQmxlbmRfUzEob3V0cHV0Q292ZXJhZ2VfUzAsIGhhbGY0KDEpKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dF9TMTsKCX0KfQoAAAABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAACAAAAA4AAAByYWRpaV9zZWxlY3RvcgAAGQAAAGNvcm5lcl9hbmRfcmFkaXVzX291dHNldHMAAAAVAAAAYWFfYmxvYXRfYW5kX2NvdmVyYWdlAAAABwAAAHJhZGlpX3gABwAAAHJhZGlpX3kABAAAAHNrZXcZAAAAdHJhbnNsYXRlX2FuZF9sb2NhbHJvdGF0ZQAAAAUAAABjb2xvcgAAAAAAAAA=","HUQACAAAAAMAADAAAIOAAAH677776IZOCAAP577777777777777777YBAAAAAAAAAAAKAAYAAAACAAAAAAACCAYAAA":"CgAAAExTS1PPAAAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBwb3NpdGlvbjsKaW4gaGFsZjQgY29sb3I7Cm91dCBoYWxmNCB2Y29sb3JfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJdmNvbG9yX1MwID0gY29sb3I7Cglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cn0KAAAAAAAMAQAAaW4gaGFsZjQgdmNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdmNvbG9yX1MwOwoJY29uc3QgaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNCgxKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAACAAAACAAAAHBvc2l0aW9uBQAAAGNvbG9yAAAAAAAAAA==","FAAQMYAAMAAAEADAAABAEYAAAICIAB5AABQAAAQAMAAAEATAAABAIIGAAEDCBYQCA4AAAAAAAA5AAAAAAABAAAAACAZAAAAA":"CgAAAExTS1PUCwAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0NCByYWRpaV9zZWxlY3RvcjsKaW4gZmxvYXQ0IGNvcm5lcl9hbmRfcmFkaXVzX291dHNldHM7CmluIGZsb2F0NCBhYV9ibG9hdF9hbmRfY292ZXJhZ2U7CmluIGZsb2F0NCByYWRpaV94OwppbiBmbG9hdDQgcmFkaWlfeTsKaW4gZmxvYXQ0IHNrZXc7CmluIGZsb2F0MiB0cmFuc2xhdGVfYW5kX2xvY2Fscm90YXRlOwppbiBoYWxmNCBjb2xvcjsKZmxhdCBvdXQgaGFsZjQgdmNvbG9yX1MwOwpvdXQgZmxvYXQyIHZhcmNjb29yZF9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgRmlsbFJSZWN0T3A6OlByb2Nlc3NvcgoJdmNvbG9yX1MwID0gY29sb3I7CglmbG9hdCBhYV9ibG9hdF9tdWx0aXBsaWVyID0gMTsKCWZsb2F0MiBjb3JuZXIgPSBjb3JuZXJfYW5kX3JhZGl1c19vdXRzZXRzLnh5OwoJZmxvYXQyIHJhZGl1c19vdXRzZXQgPSBjb3JuZXJfYW5kX3JhZGl1c19vdXRzZXRzLnp3OwoJZmxvYXQyIGFhX2Jsb2F0X2RpcmVjdGlvbiA9IGFhX2Jsb2F0X2FuZF9jb3ZlcmFnZS54eTsKCWZsb2F0IGlzX2xpbmVhcl9jb3ZlcmFnZSA9IGFhX2Jsb2F0X2FuZF9jb3ZlcmFnZS53OwoJZmxvYXQyIHBpeGVsbGVuZ3RoID0gaW52ZXJzZXNxcnQoZmxvYXQyKGRvdChza2V3Lnh6LCBza2V3Lnh6KSwgZG90KHNrZXcueXcsIHNrZXcueXcpKSk7CglmbG9hdDQgbm9ybWFsaXplZF9heGlzX2RpcnMgPSBza2V3ICogcGl4ZWxsZW5ndGgueHl4eTsKCWZsb2F0MiBheGlzd2lkdGhzID0gKGFicyhub3JtYWxpemVkX2F4aXNfZGlycy54eSkgKyBhYnMobm9ybWFsaXplZF9heGlzX2RpcnMuencpKTsKCWZsb2F0MiBhYV9ibG9hdHJhZGl1cyA9IGF4aXN3aWR0aHMgKiBwaXhlbGxlbmd0aCAqIC41OwoJZmxvYXQ0IHJhZGlpX2FuZF9uZWlnaGJvcnMgPSByYWRpaV9zZWxlY3RvciogZmxvYXQ0eDQocmFkaWlfeCwgcmFkaWlfeSwgcmFkaWlfeC55eHd6LCByYWRpaV95Lnd6eXgpOwoJZmxvYXQyIHJhZGlpID0gcmFkaWlfYW5kX25laWdoYm9ycy54eTsKCWZsb2F0MiBuZWlnaGJvcl9yYWRpaSA9IHJhZGlpX2FuZF9uZWlnaGJvcnMuenc7CglmbG9hdCBjb3ZlcmFnZV9tdWx0aXBsaWVyID0gMTsKCWlmIChhbnkoZ3JlYXRlclRoYW4oYWFfYmxvYXRyYWRpdXMsIGZsb2F0MigxKSkpKSAKCXsKCQljb3JuZXIgPSBtYXgoYWJzKGNvcm5lciksIGFhX2Jsb2F0cmFkaXVzKSAqIHNpZ24oY29ybmVyKTsKCQljb3ZlcmFnZV9tdWx0aXBsaWVyID0gMSAvIChtYXgoYWFfYmxvYXRyYWRpdXMueCwgMSkgKiBtYXgoYWFfYmxvYXRyYWRpdXMueSwgMSkpOwoJCXJhZGlpID0gZmxvYXQyKDApOwoJfQoJZmxvYXQgY292ZXJhZ2UgPSBhYV9ibG9hdF9hbmRfY292ZXJhZ2UuejsKCWlmIChhbnkobGVzc1RoYW4ocmFkaWksIGFhX2Jsb2F0cmFkaXVzICogMS41KSkpIAoJewoJCXJhZGlpID0gZmxvYXQyKDApOwoJCWFhX2Jsb2F0X2RpcmVjdGlvbiA9IHNpZ24oY29ybmVyKTsKCQlpZiAoY292ZXJhZ2UgPiAuNSkgCgkJewoJCQlhYV9ibG9hdF9kaXJlY3Rpb24gPSAtYWFfYmxvYXRfZGlyZWN0aW9uOwoJCX0KCQlpc19saW5lYXJfY292ZXJhZ2UgPSAxOwoJfQoJZWxzZSAKCXsKCQlyYWRpaSA9IGNsYW1wKHJhZGlpLCBwaXhlbGxlbmd0aCAqIDEuNSwgMiAtIHBpeGVsbGVuZ3RoICogMS41KTsKCQluZWlnaGJvcl9yYWRpaSA9IGNsYW1wKG5laWdoYm9yX3JhZGlpLCBwaXhlbGxlbmd0aCAqIDEuNSwgMiAtIHBpeGVsbGVuZ3RoICogMS41KTsKCQlmbG9hdDIgc3BhY2luZyA9IDIgLSByYWRpaSAtIG5laWdoYm9yX3JhZGlpOwoJCWZsb2F0MiBleHRyYV9wYWQgPSBtYXgocGl4ZWxsZW5ndGggKiAuMDYyNSAtIHNwYWNpbmcsIGZsb2F0MigwKSk7CgkJcmFkaWkgLT0gZXh0cmFfcGFkICogLjU7Cgl9CglmbG9hdDIgYWFfb3V0c2V0ID0gYWFfYmxvYXRfZGlyZWN0aW9uICogYWFfYmxvYXRyYWRpdXMgKiBhYV9ibG9hdF9tdWx0aXBsaWVyOwoJZmxvYXQyIHZlcnRleHBvcyA9IGNvcm5lciArIHJhZGl1c19vdXRzZXQgKiByYWRpaSArIGFhX291dHNldDsKCWlmIChjb3ZlcmFnZSA+IC41KSAKCXsKCQlpZiAoYWFfYmxvYXRfZGlyZWN0aW9uLnggIT0gMCAmJiB2ZXJ0ZXhwb3MueCAqIGNvcm5lci54IDwgMCkgCgkJewoJCQlmbG9hdCBiYWNrc2V0ID0gYWJzKHZlcnRleHBvcy54KTsKCQkJdmVydGV4cG9zLnggPSAwOwoJCQl2ZXJ0ZXhwb3MueSArPSBiYWNrc2V0ICogc2lnbihjb3JuZXIueSkgKiBwaXhlbGxlbmd0aC55L3BpeGVsbGVuZ3RoLng7CgkJCWNvdmVyYWdlID0gKGNvdmVyYWdlIC0gLjUpICogYWJzKGNvcm5lci54KSAvIChhYnMoY29ybmVyLngpICsgYmFja3NldCkgKyAuNTsKCQl9CgkJaWYgKGFhX2Jsb2F0X2RpcmVjdGlvbi55ICE9IDAgJiYgdmVydGV4cG9zLnkgKiBjb3JuZXIueSA8IDApIAoJCXsKCQkJZmxvYXQgYmFja3NldCA9IGFicyh2ZXJ0ZXhwb3MueSk7CgkJCXZlcnRleHBvcy55ID0gMDsKCQkJdmVydGV4cG9zLnggKz0gYmFja3NldCAqIHNpZ24oY29ybmVyLngpICogcGl4ZWxsZW5ndGgueC9waXhlbGxlbmd0aC55OwoJCQljb3ZlcmFnZSA9IChjb3ZlcmFnZSAtIC41KSAqIGFicyhjb3JuZXIueSkgLyAoYWJzKGNvcm5lci55KSArIGJhY2tzZXQpICsgLjU7CgkJfQoJfQoJZmxvYXQyeDIgc2tld21hdHJpeCA9IGZsb2F0MngyKHNrZXcueHksIHNrZXcuencpOwoJZmxvYXQyIGRldmNvb3JkID0gdmVydGV4cG9zICogc2tld21hdHJpeCArIHRyYW5zbGF0ZV9hbmRfbG9jYWxyb3RhdGUueHk7CglpZiAoMCAhPSBpc19saW5lYXJfY292ZXJhZ2UpIAoJewoJCXZhcmNjb29yZF9TMC54eSA9IGZsb2F0MigwLCBjb3ZlcmFnZSAqIGNvdmVyYWdlX211bHRpcGxpZXIpOwoJfQoJZWxzZSAKCXsKCQlmbG9hdDIgYXJjY29vcmQgPSAxIC0gYWJzKHJhZGl1c19vdXRzZXQpICsgYWFfb3V0c2V0L3JhZGlpICogY29ybmVyOwoJCXZhcmNjb29yZF9TMC54eSA9IGZsb2F0MihhcmNjb29yZC54KzEsIGFyY2Nvb3JkLnkpOwoJfQoJc2tfUG9zaXRpb24gPSBkZXZjb29yZC54eTAxOwp9CgAAAABFAgAAZmxhdCBpbiBoYWxmNCB2Y29sb3JfUzA7CmluIGZsb2F0MiB2YXJjY29vcmRfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBGaWxsUlJlY3RPcDo6UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMDsKCW91dHB1dENvbG9yX1MwID0gdmNvbG9yX1MwOwoJZmxvYXQgeF9wbHVzXzE9dmFyY2Nvb3JkX1MwLngsIHk9dmFyY2Nvb3JkX1MwLnk7CgloYWxmIGNvdmVyYWdlOwoJaWYgKDAgPT0geF9wbHVzXzEpIAoJewoJCWNvdmVyYWdlID0gaGFsZih5KTsKCX0KCWVsc2UgCgl7CgkJZmxvYXQgZm4gPSB4X3BsdXNfMSAqICh4X3BsdXNfMSAtIDIpOwoJCWZuID0gZm1hKHkseSwgZm4pOwoJCWZsb2F0IGZud2lkdGggPSBmd2lkdGgoZm4pOwoJCWNvdmVyYWdlID0gLjUgLSBoYWxmKGZuL2Zud2lkdGgpOwoJCWNvdmVyYWdlID0gY2xhbXAoY292ZXJhZ2UsIDAsIDEpOwoJfQoJaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNChjb3ZlcmFnZSk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRDb3ZlcmFnZV9TMDsKCX0KfQoAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAACAAAAA4AAAByYWRpaV9zZWxlY3RvcgAAGQAAAGNvcm5lcl9hbmRfcmFkaXVzX291dHNldHMAAAAVAAAAYWFfYmxvYXRfYW5kX2NvdmVyYWdlAAAABwAAAHJhZGlpX3gABwAAAHJhZGlpX3kABAAAAHNrZXcZAAAAdHJhbnNsYXRlX2FuZF9sb2NhbHJvdGF0ZQAAAAUAAABjb2xvcgAAAAAAAAA=","DAQAAAAAAABGAABAYAAQAIHCAIAYAQUBAEAAAAAAEAAAAAAAAAAAAIAD2AAAAAAQAVSWGRIBAAADAAAAACAAAAAAQCGEIQOZLBIQAAAABQAAAAAAAAAAAAFAAMAAAABAAAAAAABBAMAAA":"CgAAAExTS1MWAgAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQyIHVBdGxhc1NpemVJbnZfUzA7CmluIGZsb2F0MiBpblBvc2l0aW9uOwppbiBoYWxmNCBpbkNvbG9yOwppbiB1c2hvcnQyIGluVGV4dHVyZUNvb3JkczsKb3V0IGZsb2F0MiB2VGV4dHVyZUNvb3Jkc19TMDsKZmxhdCBvdXQgZmxvYXQgdlRleEluZGV4X1MwOwpvdXQgaGFsZjQgdmluQ29sb3JfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIEJpdG1hcFRleHQKCWludCB0ZXhJZHggPSAwOwoJZmxvYXQyIHVub3JtVGV4Q29vcmRzID0gZmxvYXQyKGluVGV4dHVyZUNvb3Jkcy54LCBpblRleHR1cmVDb29yZHMueSk7Cgl2VGV4dHVyZUNvb3Jkc19TMCA9IHVub3JtVGV4Q29vcmRzICogdUF0bGFzU2l6ZUludl9TMDsKCXZUZXhJbmRleF9TMCA9IGZsb2F0KHRleElkeCk7Cgl2aW5Db2xvcl9TMCA9IGluQ29sb3I7CglmbG9hdDIgX3RtcF8xX2luUG9zaXRpb24gPSBpblBvc2l0aW9uOwoJc2tfUG9zaXRpb24gPSBpblBvc2l0aW9uLnh5MDE7Cn0KAAABAAAARQUAAGNvbnN0IGludCBrRmlsbEJXX1MxX2MwID0gMDsKY29uc3QgaW50IGtJbnZlcnNlRmlsbEJXX1MxX2MwID0gMjsKY29uc3QgaW50IGtJbnZlcnNlRmlsbEFBX1MxX2MwID0gMzsKdW5pZm9ybSBmbG9hdDQgdXJlY3RVbmlmb3JtX1MxX2MwOwp1bmlmb3JtIHNhbXBsZXIyRCB1VGV4dHVyZVNhbXBsZXJfMF9TMDsKaW4gZmxvYXQyIHZUZXh0dXJlQ29vcmRzX1MwOwpmbGF0IGluIGZsb2F0IHZUZXhJbmRleF9TMDsKaW4gaGFsZjQgdmluQ29sb3JfUzA7CmhhbGY0IFJlY3RfUzFfYzAoaGFsZjQgX2lucHV0KSAKewoJaGFsZjQgX3RtcF8wX2luQ29sb3IgPSBfaW5wdXQ7CgloYWxmIGNvdmVyYWdlOwoJaWYgKGludCgxKSA9PSBrRmlsbEJXX1MxX2MwIHx8IGludCgxKSA9PSBrSW52ZXJzZUZpbGxCV19TMV9jMCkgCgl7CgkJY292ZXJhZ2UgPSBoYWxmKGFsbChncmVhdGVyVGhhbihmbG9hdDQoc2tfRnJhZ0Nvb3JkLnh5LCB1cmVjdFVuaWZvcm1fUzFfYzAuencpLCBmbG9hdDQodXJlY3RVbmlmb3JtX1MxX2MwLnh5LCBza19GcmFnQ29vcmQueHkpKSkpOwoJfQoJZWxzZSAKCXsKCQloYWxmNCBkaXN0czQgPSBzYXR1cmF0ZShoYWxmNCgxLjAsIDEuMCwgLTEuMCwgLTEuMCkgKiBoYWxmNChza19GcmFnQ29vcmQueHl4eSAtIHVyZWN0VW5pZm9ybV9TMV9jMCkpOwoJCWhhbGYyIGRpc3RzMiA9IChkaXN0czQueHkgKyBkaXN0czQuencpIC0gMS4wOwoJCWNvdmVyYWdlID0gZGlzdHMyLnggKiBkaXN0czIueTsKCX0KCWlmIChpbnQoMSkgPT0ga0ludmVyc2VGaWxsQldfUzFfYzAgfHwgaW50KDEpID09IGtJbnZlcnNlRmlsbEFBX1MxX2MwKSAKCXsKCQljb3ZlcmFnZSA9IDEuMCAtIGNvdmVyYWdlOwoJfQoJcmV0dXJuIGhhbGY0KGhhbGY0KGNvdmVyYWdlKSk7Cn0KaGFsZjQgQmxlbmRfUzEoaGFsZjQgX3NyYywgaGFsZjQgX2RzdCkgCnsKCXJldHVybiBibGVuZF9tb2R1bGF0ZShSZWN0X1MxX2MwKF9zcmMpLCBfc3JjKTsKfQp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgQml0bWFwVGV4dAoJaGFsZjQgb3V0cHV0Q29sb3JfUzA7CglvdXRwdXRDb2xvcl9TMCA9IHZpbkNvbG9yX1MwOwoJaGFsZjQgdGV4Q29sb3I7Cgl7CgkJdGV4Q29sb3IgPSBzYW1wbGUodVRleHR1cmVTYW1wbGVyXzBfUzAsIHZUZXh0dXJlQ29vcmRzX1MwKS5ycnJyOwoJfQoJaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSB0ZXhDb2xvcjsKCWhhbGY0IG91dHB1dF9TMTsKCW91dHB1dF9TMSA9IEJsZW5kX1MxKG91dHB1dENvdmVyYWdlX1MwLCBoYWxmNCgxKSk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRfUzE7Cgl9Cn0KAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAKAAAAaW5Qb3NpdGlvbgAABwAAAGluQ29sb3IADwAAAGluVGV4dHVyZUNvb3JkcwAAAAAA","AYQA5AADQAAAOAEARAFQJAABBADIB7777777777777777777777767YAAAAAAAAAACABZQA6AAAEAAAAAAAIADQAAAAIAAAAAAAIIDA":"CgAAAExTS1PMAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQ0IHVsb2NhbE1hdHJpeF9TMDsKaW4gZmxvYXQyIGluUG9zaXRpb247CmluIGhhbGY0IGluQ29sb3I7CmluIGZsb2F0NCBpbkNpcmNsZUVkZ2U7Cm91dCBmbG9hdDQgdmluQ2lyY2xlRWRnZV9TMDsKb3V0IGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBDaXJjbGVHZW9tZXRyeVByb2Nlc3NvcgoJdmluQ2lyY2xlRWRnZV9TMCA9IGluQ2lyY2xlRWRnZTsKCXZpbkNvbG9yX1MwID0gaW5Db2xvcjsKCWZsb2F0MiBfdG1wXzBfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247CglmbG9hdDIgX3RtcF8xX2luUG9zaXRpb24gPSB1bG9jYWxNYXRyaXhfUzAueHogKiBpblBvc2l0aW9uICsgdWxvY2FsTWF0cml4X1MwLnl3OwoJc2tfUG9zaXRpb24gPSBfdG1wXzBfaW5Qb3NpdGlvbi54eTAxOwp9CgEAAACPAwAAdW5pZm9ybSBmbG9hdDQgdWlubmVyUmVjdF9TMTsKdW5pZm9ybSBoYWxmMiB1cmFkaXVzUGx1c0hhbGZfUzE7CmluIGZsb2F0NCB2aW5DaXJjbGVFZGdlX1MwOwppbiBoYWxmNCB2aW5Db2xvcl9TMDsKaGFsZjQgQ2lyY3VsYXJSUmVjdF9TMShoYWxmNCBfaW5wdXQpIAp7CglmbG9hdDIgZHh5MCA9IHVpbm5lclJlY3RfUzEuTFQgLSBza19GcmFnQ29vcmQueHk7CglmbG9hdDIgZHh5MSA9IHNrX0ZyYWdDb29yZC54eSAtIHVpbm5lclJlY3RfUzEuUkI7CglmbG9hdDIgZHh5ID0gbWF4KG1heChkeHkwLCBkeHkxKSwgMC4wKTsKCWhhbGYgYWxwaGEgPSBoYWxmKHNhdHVyYXRlKHVyYWRpdXNQbHVzSGFsZl9TMS54IC0gbGVuZ3RoKGR4eSkpKTsKCWFscGhhID0gMS4wIC0gYWxwaGE7CglyZXR1cm4gX2lucHV0ICogYWxwaGE7Cn0Kdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIENpcmNsZUdlb21ldHJ5UHJvY2Vzc29yCglmbG9hdDQgY2lyY2xlRWRnZTsKCWNpcmNsZUVkZ2UgPSB2aW5DaXJjbGVFZGdlX1MwOwoJaGFsZjQgb3V0cHV0Q29sb3JfUzA7CglvdXRwdXRDb2xvcl9TMCA9IHZpbkNvbG9yX1MwOwoJZmxvYXQgZCA9IGxlbmd0aChjaXJjbGVFZGdlLnh5KTsKCWhhbGYgZGlzdGFuY2VUb091dGVyRWRnZSA9IGhhbGYoY2lyY2xlRWRnZS56ICogKDEuMCAtIGQpKTsKCWhhbGYgZWRnZUFscGhhID0gc2F0dXJhdGUoZGlzdGFuY2VUb091dGVyRWRnZSk7CgloYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KGVkZ2VBbHBoYSk7CgloYWxmNCBvdXRwdXRfUzE7CglvdXRwdXRfUzEgPSBDaXJjdWxhclJSZWN0X1MxKG91dHB1dENvdmVyYWdlX1MwKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dF9TMTsKCX0KfQoAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAKAAAAaW5Qb3NpdGlvbgAABwAAAGluQ29sb3IADAAAAGluQ2lyY2xlRWRnZQAAAAA=","AYQA5AADQAAAOAEARAFQJAABBADIB7777777777777777777777767YAAAAAAAAAAAAB3QA6AAAEAAAAAAAMAAPEAEAAABAAAAAAB2AAAAAAACAAAAAEBSAAAA":"CgAAAExTS1PMAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQ0IHVsb2NhbE1hdHJpeF9TMDsKaW4gZmxvYXQyIGluUG9zaXRpb247CmluIGhhbGY0IGluQ29sb3I7CmluIGZsb2F0NCBpbkNpcmNsZUVkZ2U7Cm91dCBmbG9hdDQgdmluQ2lyY2xlRWRnZV9TMDsKb3V0IGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBDaXJjbGVHZW9tZXRyeVByb2Nlc3NvcgoJdmluQ2lyY2xlRWRnZV9TMCA9IGluQ2lyY2xlRWRnZTsKCXZpbkNvbG9yX1MwID0gaW5Db2xvcjsKCWZsb2F0MiBfdG1wXzBfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247CglmbG9hdDIgX3RtcF8xX2luUG9zaXRpb24gPSB1bG9jYWxNYXRyaXhfUzAueHogKiBpblBvc2l0aW9uICsgdWxvY2FsTWF0cml4X1MwLnl3OwoJc2tfUG9zaXRpb24gPSBfdG1wXzBfaW5Qb3NpdGlvbi54eTAxOwp9CgEAAAAeBQAAdW5pZm9ybSBmbG9hdDQgdWlubmVyUmVjdF9TMTsKdW5pZm9ybSBoYWxmMiB1cmFkaXVzUGx1c0hhbGZfUzE7CnVuaWZvcm0gZmxvYXQ0IHVpbm5lclJlY3RfUzI7CnVuaWZvcm0gaGFsZjIgdXJhZGl1c1BsdXNIYWxmX1MyOwppbiBmbG9hdDQgdmluQ2lyY2xlRWRnZV9TMDsKaW4gaGFsZjQgdmluQ29sb3JfUzA7CmhhbGY0IENpcmN1bGFyUlJlY3RfUzEoaGFsZjQgX2lucHV0KSAKewoJZmxvYXQyIGR4eTAgPSB1aW5uZXJSZWN0X1MxLkxUIC0gc2tfRnJhZ0Nvb3JkLnh5OwoJZmxvYXQyIGR4eTEgPSBza19GcmFnQ29vcmQueHkgLSB1aW5uZXJSZWN0X1MxLlJCOwoJZmxvYXQyIGR4eSA9IG1heChtYXgoZHh5MCwgZHh5MSksIDAuMCk7CgloYWxmIGFscGhhID0gaGFsZihzYXR1cmF0ZSh1cmFkaXVzUGx1c0hhbGZfUzEueCAtIGxlbmd0aChkeHkpKSk7CglhbHBoYSA9IDEuMCAtIGFscGhhOwoJcmV0dXJuIF9pbnB1dCAqIGFscGhhOwp9CmhhbGY0IENpcmN1bGFyUlJlY3RfUzIoaGFsZjQgX2lucHV0KSAKewoJZmxvYXQyIGR4eTAgPSB1aW5uZXJSZWN0X1MyLkxUIC0gc2tfRnJhZ0Nvb3JkLnh5OwoJZmxvYXQyIGR4eTEgPSBza19GcmFnQ29vcmQueHkgLSB1aW5uZXJSZWN0X1MyLlJCOwoJZmxvYXQyIGR4eSA9IG1heChtYXgoZHh5MCwgZHh5MSksIDAuMCk7CgloYWxmIGFscGhhID0gaGFsZihzYXR1cmF0ZSh1cmFkaXVzUGx1c0hhbGZfUzIueCAtIGxlbmd0aChkeHkpKSk7CglyZXR1cm4gX2lucHV0ICogYWxwaGE7Cn0Kdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIENpcmNsZUdlb21ldHJ5UHJvY2Vzc29yCglmbG9hdDQgY2lyY2xlRWRnZTsKCWNpcmNsZUVkZ2UgPSB2aW5DaXJjbGVFZGdlX1MwOwoJaGFsZjQgb3V0cHV0Q29sb3JfUzA7CglvdXRwdXRDb2xvcl9TMCA9IHZpbkNvbG9yX1MwOwoJZmxvYXQgZCA9IGxlbmd0aChjaXJjbGVFZGdlLnh5KTsKCWhhbGYgZGlzdGFuY2VUb091dGVyRWRnZSA9IGhhbGYoY2lyY2xlRWRnZS56ICogKDEuMCAtIGQpKTsKCWhhbGYgZWRnZUFscGhhID0gc2F0dXJhdGUoZGlzdGFuY2VUb091dGVyRWRnZSk7CgloYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KGVkZ2VBbHBoYSk7CgloYWxmNCBvdXRwdXRfUzE7CglvdXRwdXRfUzEgPSBDaXJjdWxhclJSZWN0X1MxKG91dHB1dENvdmVyYWdlX1MwKTsKCWhhbGY0IG91dHB1dF9TMjsKCW91dHB1dF9TMiA9IENpcmN1bGFyUlJlY3RfUzIob3V0cHV0X1MxKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dF9TMjsKCX0KfQoAAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAADAAAACgAAAGluUG9zaXRpb24AAAcAAABpbkNvbG9yAAwAAABpbkNpcmNsZUVkZ2UAAAAA","HUIAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAAAAAALUAQMAAAAAAABAEAAAABJYQAAAAAACAIAAAAAWCBAAAIBAAAAANAECAZAAAAQAAAAAAFAAMAAAABAAAAAAABBAM":"CgAAAExTS1M2AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBmbG9hdDIgbG9jYWxDb29yZDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cgl7CgkJdlRyYW5zZm9ybWVkQ29vcmRzXzJfUzAgPSBmbG9hdDN4Mih1bWF0cml4X1MxKSAqIGxvY2FsQ29vcmQueHkxOwoJfQp9CgAAAAAAAC8GAAB1bmlmb3JtIGZsb2F0NCB1Y2xhbXBfUzFfYzBfYzBfYzA7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMV9jMF9jMDsKdW5pZm9ybSBoYWxmMiB1SW5jcmVtZW50X1MxX2MwOwp1bmlmb3JtIGhhbGYyIHVPZmZzZXRzQW5kS2VybmVsX1MxX2MwWzEzXTsKdW5pZm9ybSBmbG9hdDN4MyB1bWF0cml4X1MxOwp1bmlmb3JtIHNhbXBsZXIyRCB1VGV4dHVyZVNhbXBsZXJfMF9TMTsKaW4gZmxvYXQyIHZUcmFuc2Zvcm1lZENvb3Jkc18yX1MwOwpoYWxmNCBUZXh0dXJlRWZmZWN0X1MxX2MwX2MwX2MwKGhhbGY0IF9pbnB1dCwgZmxvYXQyIF9jb29yZHMpIAp7CglmbG9hdDIgaW5Db29yZCA9IF9jb29yZHM7CglmbG9hdDIgc3Vic2V0Q29vcmQ7CglzdWJzZXRDb29yZC54ID0gaW5Db29yZC54OwoJc3Vic2V0Q29vcmQueSA9IGluQ29vcmQueTsKCWZsb2F0MiBjbGFtcGVkQ29vcmQ7CgljbGFtcGVkQ29vcmQueCA9IHN1YnNldENvb3JkLng7CgljbGFtcGVkQ29vcmQueSA9IGNsYW1wKHN1YnNldENvb3JkLnksIHVjbGFtcF9TMV9jMF9jMF9jMC55LCB1Y2xhbXBfUzFfYzBfYzBfYzAudyk7CgloYWxmNCB0ZXh0dXJlQ29sb3IgPSBzYW1wbGUodVRleHR1cmVTYW1wbGVyXzBfUzEsIGNsYW1wZWRDb29yZCk7CglyZXR1cm4gdGV4dHVyZUNvbG9yOwp9CmhhbGY0IE1hdHJpeEVmZmVjdF9TMV9jMF9jMChoYWxmNCBfaW5wdXQsIGZsb2F0MiBfY29vcmRzKSAKewoJcmV0dXJuIFRleHR1cmVFZmZlY3RfUzFfYzBfYzBfYzAoX2lucHV0LCBmbG9hdDN4Mih1bWF0cml4X1MxX2MwX2MwKSAqIF9jb29yZHMueHkxKTsKfQpoYWxmNCBTbW9vdGhfUzFfYzAoaGFsZjQgX2lucHV0LCBmbG9hdDIgY29vcmQsIGhhbGYyIG9mZnNldEFuZEtlcm5lbCkgCnsKCXJldHVybiBNYXRyaXhFZmZlY3RfUzFfYzBfYzAoX2lucHV0LCAoY29vcmQgKyBvZmZzZXRBbmRLZXJuZWwueCAqIHVJbmNyZW1lbnRfUzFfYzApKSAqIG9mZnNldEFuZEtlcm5lbC55Owp9CmhhbGY0IEdhdXNzaWFuQ29udm9sdXRpb25fUzFfYzAoaGFsZjQgX2lucHV0KSAKewoJaGFsZjQgY29sb3IgPSBoYWxmNCgwKTsKCWZsb2F0MiBjb29yZCA9IHZUcmFuc2Zvcm1lZENvb3Jkc18yX1MwOwoJZm9yIChpbnQgaT0wOyBpPDEzOyArK2kpIAoJewoJCWNvbG9yICs9IFNtb290aF9TMV9jMChfaW5wdXQsIGNvb3JkLCB1T2Zmc2V0c0FuZEtlcm5lbF9TMV9jMFtpXSk7Cgl9CglyZXR1cm4gY29sb3I7Cn0KaGFsZjQgTWF0cml4RWZmZWN0X1MxKGhhbGY0IF9pbnB1dCkgCnsKCXJldHVybiBHYXVzc2lhbkNvbnZvbHV0aW9uX1MxX2MwKF9pbnB1dCk7Cn0Kdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJaGFsZjQgb3V0cHV0Q29sb3JfUzAgPSBoYWxmNCgxKTsKCWNvbnN0IGhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoMSk7CgloYWxmNCBvdXRwdXRfUzE7CglvdXRwdXRfUzEgPSBNYXRyaXhFZmZlY3RfUzEob3V0cHV0Q29sb3JfUzApOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dF9TMSAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAgAAABwb3NpdGlvbgoAAABsb2NhbENvb3JkAAAAAAAA","HVIAAAAAABIAAGAAAQ4AAAH477776R24EAAAIOBQAD6P7777777777YDAAAAAAAAAAAFIBQU7BTXIAAAAAACAWXW3ZEQAAAADAAAAAGATHIBICYCAAAEBP2LBIPAAAAAIAAAAAEARRALJ3F5SMAAAABQAAAABABTUEURMBAAACAH5FYUHQAAAAAAAEAAAAAZ4RGGRCQFAEAAAAAAAAAGARP2LVJPAAAAAAAAEAAAABSKRXZFAUHQAAAAAAAAAACAA4AAAACAAAAAAACCAYAA":"CgAAAExTS1OAAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMV9jMF9jMTsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBoYWxmNCBjb2xvcjsKaW4gZmxvYXQyIGxvY2FsQ29vcmQ7CmZsYXQgb3V0IGhhbGY0IHZjb2xvcl9TMDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfNV9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgl2Y29sb3JfUzAgPSBjb2xvcjsKCXNrX1Bvc2l0aW9uID0gcG9zaXRpb24ueHkwMTsKCXsKCQl2VHJhbnNmb3JtZWRDb29yZHNfNV9TMCA9IGZsb2F0M3gyKHVtYXRyaXhfUzFfYzBfYzEpICogbG9jYWxDb29yZC54eTE7Cgl9Cn0KAAAAAIIGAAB1bmlmb3JtIGhhbGY0IHVzdGFydF9TMV9jMF9jMDsKdW5pZm9ybSBoYWxmNCB1ZW5kX1MxX2MwX2MwOwp1bmlmb3JtIGZsb2F0M3gzIHVtYXRyaXhfUzFfYzBfYzE7CnVuaWZvcm0gaGFsZjQgdWxlZnRCb3JkZXJDb2xvcl9TMV9jMDsKdW5pZm9ybSBoYWxmNCB1cmlnaHRCb3JkZXJDb2xvcl9TMV9jMDsKZmxhdCBpbiBoYWxmNCB2Y29sb3JfUzA7CmluIGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfNV9TMDsKaGFsZjQgU2luZ2xlSW50ZXJ2YWxDb2xvcml6ZXJfUzFfYzBfYzAoaGFsZjQgX2lucHV0LCBmbG9hdDIgX2Nvb3JkcykgCnsKCWhhbGY0IF90bXBfMF9pbkNvbG9yID0gX2lucHV0OwoJZmxvYXQyIF90bXBfMV9jb29yZHMgPSBfY29vcmRzOwoJcmV0dXJuIGhhbGY0KG1peCh1c3RhcnRfUzFfYzBfYzAsIHVlbmRfUzFfYzBfYzAsIGhhbGYoX3RtcF8xX2Nvb3Jkcy54KSkpOwp9CmhhbGY0IExpbmVhckxheW91dF9TMV9jMF9jMV9jMChoYWxmNCBfaW5wdXQpIAp7CgloYWxmNCBfdG1wXzJfaW5Db2xvciA9IF9pbnB1dDsKCWZsb2F0MiBfdG1wXzNfY29vcmRzID0gdlRyYW5zZm9ybWVkQ29vcmRzXzVfUzA7CglyZXR1cm4gaGFsZjQoaGFsZjQoaGFsZihfdG1wXzNfY29vcmRzLngpICsgMWUtMDUsIDEuMCwgMC4wLCAwLjApKTsKfQpoYWxmNCBNYXRyaXhFZmZlY3RfUzFfYzBfYzEoaGFsZjQgX2lucHV0KSAKewoJcmV0dXJuIExpbmVhckxheW91dF9TMV9jMF9jMV9jMChfaW5wdXQpOwp9CmhhbGY0IENsYW1wZWRHcmFkaWVudF9TMV9jMChoYWxmNCBfaW5wdXQpIAp7CgloYWxmNCBfdG1wXzRfaW5Db2xvciA9IF9pbnB1dDsKCWhhbGY0IHQgPSBNYXRyaXhFZmZlY3RfUzFfYzBfYzEoX3RtcF80X2luQ29sb3IpOwoJaGFsZjQgb3V0Q29sb3I7CglpZiAoIWJvb2woaW50KDEpKSAmJiB0LnkgPCAwLjApIAoJewoJCW91dENvbG9yID0gaGFsZjQoMC4wKTsKCX0KCWVsc2UgaWYgKHQueCA8IDAuMCkgCgl7CgkJb3V0Q29sb3IgPSB1bGVmdEJvcmRlckNvbG9yX1MxX2MwOwoJfQoJZWxzZSBpZiAodC54ID4gMS4wKSAKCXsKCQlvdXRDb2xvciA9IHVyaWdodEJvcmRlckNvbG9yX1MxX2MwOwoJfQoJZWxzZSAKCXsKCQlvdXRDb2xvciA9IFNpbmdsZUludGVydmFsQ29sb3JpemVyX1MxX2MwX2MwKF90bXBfNF9pbkNvbG9yLCBmbG9hdDIoaGFsZjIodC54LCAwLjApKSk7Cgl9CglyZXR1cm4gaGFsZjQob3V0Q29sb3IpOwp9CmhhbGY0IERpc2FibGVDb3ZlcmFnZUFzQWxwaGFfUzEoaGFsZjQgX2lucHV0KSAKewoJX2lucHV0ID0gQ2xhbXBlZEdyYWRpZW50X1MxX2MwKF9pbnB1dCk7CgloYWxmNCBfdG1wXzVfaW5Db2xvciA9IF9pbnB1dDsKCXJldHVybiBoYWxmNChfaW5wdXQpOwp9CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBRdWFkUGVyRWRnZUFBR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2Y29sb3JfUzA7Cgljb25zdCBoYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KDEpOwoJaGFsZjQgb3V0cHV0X1MxOwoJb3V0cHV0X1MxID0gRGlzYWJsZUNvdmVyYWdlQXNBbHBoYV9TMShvdXRwdXRDb2xvcl9TMCk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0X1MxICogb3V0cHV0Q292ZXJhZ2VfUzA7Cgl9Cn0KAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAgAAABwb3NpdGlvbgUAAABjb2xvcgAAAAoAAABsb2NhbENvb3JkAAAAAAAA","BYIBQAAABQAAIAABBYAAAEIXBAAP777777777777AAAAAAAAAAAABUABAAAAAEAAAAAIBEABAAAAA":"CgAAAExTS1M+AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CmluIGZsb2F0MiBpblBvc2l0aW9uOwppbiBoYWxmNCBpbkNvbG9yOwpvdXQgaGFsZjQgdmNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBEZWZhdWx0R2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IGNvbG9yID0gaW5Db2xvcjsKCXZjb2xvcl9TMCA9IGNvbG9yOwoJZmxvYXQyIF90bXBfMV9pblBvc2l0aW9uID0gaW5Qb3NpdGlvbjsKCWZsb2F0MiBfdG1wXzNfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247Cglza19Qb3NpdGlvbiA9IF90bXBfMV9pblBvc2l0aW9uLnh5MDE7Cn0KAAAAAAAABgEAAGluIGhhbGY0IHZjb2xvcl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIERlZmF1bHRHZW9tZXRyeVByb2Nlc3NvcgoJaGFsZjQgb3V0cHV0Q29sb3JfUzA7CglvdXRwdXRDb2xvcl9TMCA9IHZjb2xvcl9TMDsKCWNvbnN0IGhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoMSk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRDb3ZlcmFnZV9TMDsKCX0KfQoAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAACAAAACgAAAGluUG9zaXRpb24AAAcAAABpbkNvbG9yAAAAAAA=","DAQAAAAAAABGAABAYAAQAIHCAIAYAQUBAEAAAAAAEAAAAAAAAAAAAIAHSADQAAAQAAAAAAFAAMAAAABAAAAAAABBAM":"CgAAAExTS1MWAgAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQyIHVBdGxhc1NpemVJbnZfUzA7CmluIGZsb2F0MiBpblBvc2l0aW9uOwppbiBoYWxmNCBpbkNvbG9yOwppbiB1c2hvcnQyIGluVGV4dHVyZUNvb3JkczsKb3V0IGZsb2F0MiB2VGV4dHVyZUNvb3Jkc19TMDsKZmxhdCBvdXQgZmxvYXQgdlRleEluZGV4X1MwOwpvdXQgaGFsZjQgdmluQ29sb3JfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIEJpdG1hcFRleHQKCWludCB0ZXhJZHggPSAwOwoJZmxvYXQyIHVub3JtVGV4Q29vcmRzID0gZmxvYXQyKGluVGV4dHVyZUNvb3Jkcy54LCBpblRleHR1cmVDb29yZHMueSk7Cgl2VGV4dHVyZUNvb3Jkc19TMCA9IHVub3JtVGV4Q29vcmRzICogdUF0bGFzU2l6ZUludl9TMDsKCXZUZXhJbmRleF9TMCA9IGZsb2F0KHRleElkeCk7Cgl2aW5Db2xvcl9TMCA9IGluQ29sb3I7CglmbG9hdDIgX3RtcF8xX2luUG9zaXRpb24gPSBpblBvc2l0aW9uOwoJc2tfUG9zaXRpb24gPSBpblBvc2l0aW9uLnh5MDE7Cn0KAAABAAAAQAMAAHVuaWZvcm0gZmxvYXQ0IHVpbm5lclJlY3RfUzE7CnVuaWZvcm0gaGFsZjIgdXJhZGl1c1BsdXNIYWxmX1MxOwp1bmlmb3JtIHNhbXBsZXIyRCB1VGV4dHVyZVNhbXBsZXJfMF9TMDsKaW4gZmxvYXQyIHZUZXh0dXJlQ29vcmRzX1MwOwpmbGF0IGluIGZsb2F0IHZUZXhJbmRleF9TMDsKaW4gaGFsZjQgdmluQ29sb3JfUzA7CmhhbGY0IENpcmN1bGFyUlJlY3RfUzEoaGFsZjQgX2lucHV0KSAKewoJZmxvYXQyIGR4eTAgPSB1aW5uZXJSZWN0X1MxLkxUIC0gc2tfRnJhZ0Nvb3JkLnh5OwoJZmxvYXQyIGR4eTEgPSBza19GcmFnQ29vcmQueHkgLSB1aW5uZXJSZWN0X1MxLlJCOwoJZmxvYXQyIGR4eSA9IG1heChtYXgoZHh5MCwgZHh5MSksIDAuMCk7CgloYWxmIGFscGhhID0gaGFsZihzYXR1cmF0ZSh1cmFkaXVzUGx1c0hhbGZfUzEueCAtIGxlbmd0aChkeHkpKSk7CglyZXR1cm4gX2lucHV0ICogYWxwaGE7Cn0Kdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIEJpdG1hcFRleHQKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2aW5Db2xvcl9TMDsKCWhhbGY0IHRleENvbG9yOwoJewoJCXRleENvbG9yID0gc2FtcGxlKHVUZXh0dXJlU2FtcGxlcl8wX1MwLCB2VGV4dHVyZUNvb3Jkc19TMCkucnJycjsKCX0KCWhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gdGV4Q29sb3I7CgloYWxmNCBvdXRwdXRfUzE7CglvdXRwdXRfUzEgPSBDaXJjdWxhclJSZWN0X1MxKG91dHB1dENvdmVyYWdlX1MwKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dF9TMTsKCX0KfQoBAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAoAAABpblBvc2l0aW9uAAAHAAAAaW5Db2xvcgAPAAAAaW5UZXh0dXJlQ29vcmRzAAAAAAA=","HUIAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAAAAAALUAQMAAAAAAAAAEAAAABJYQAAAAAAAAIAAAAAWCBAAAABAAAAANAECAZAAAAAAAAAAAFAAMAAAABAAAAAAABBAM":"CgAAAExTS1M2AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBmbG9hdDIgbG9jYWxDb29yZDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cgl7CgkJdlRyYW5zZm9ybWVkQ29vcmRzXzJfUzAgPSBmbG9hdDN4Mih1bWF0cml4X1MxKSAqIGxvY2FsQ29vcmQueHkxOwoJfQp9CgAAAAAAAPAEAAB1bmlmb3JtIGZsb2F0M3gzIHVtYXRyaXhfUzFfYzBfYzA7CnVuaWZvcm0gaGFsZjIgdUluY3JlbWVudF9TMV9jMDsKdW5pZm9ybSBoYWxmMiB1T2Zmc2V0c0FuZEtlcm5lbF9TMV9jMFsxM107CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKdW5pZm9ybSBzYW1wbGVyMkQgdVRleHR1cmVTYW1wbGVyXzBfUzE7CmluIGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKaGFsZjQgVGV4dHVyZUVmZmVjdF9TMV9jMF9jMF9jMChoYWxmNCBfaW5wdXQsIGZsb2F0MiBfY29vcmRzKSAKewoJcmV0dXJuIHNhbXBsZSh1VGV4dHVyZVNhbXBsZXJfMF9TMSwgX2Nvb3Jkcyk7Cn0KaGFsZjQgTWF0cml4RWZmZWN0X1MxX2MwX2MwKGhhbGY0IF9pbnB1dCwgZmxvYXQyIF9jb29yZHMpIAp7CglyZXR1cm4gVGV4dHVyZUVmZmVjdF9TMV9jMF9jMF9jMChfaW5wdXQsIGZsb2F0M3gyKHVtYXRyaXhfUzFfYzBfYzApICogX2Nvb3Jkcy54eTEpOwp9CmhhbGY0IFNtb290aF9TMV9jMChoYWxmNCBfaW5wdXQsIGZsb2F0MiBjb29yZCwgaGFsZjIgb2Zmc2V0QW5kS2VybmVsKSAKewoJcmV0dXJuIE1hdHJpeEVmZmVjdF9TMV9jMF9jMChfaW5wdXQsIChjb29yZCArIG9mZnNldEFuZEtlcm5lbC54ICogdUluY3JlbWVudF9TMV9jMCkpICogb2Zmc2V0QW5kS2VybmVsLnk7Cn0KaGFsZjQgR2F1c3NpYW5Db252b2x1dGlvbl9TMV9jMChoYWxmNCBfaW5wdXQpIAp7CgloYWxmNCBjb2xvciA9IGhhbGY0KDApOwoJZmxvYXQyIGNvb3JkID0gdlRyYW5zZm9ybWVkQ29vcmRzXzJfUzA7Cglmb3IgKGludCBpPTA7IGk8MTM7ICsraSkgCgl7CgkJY29sb3IgKz0gU21vb3RoX1MxX2MwKF9pbnB1dCwgY29vcmQsIHVPZmZzZXRzQW5kS2VybmVsX1MxX2MwW2ldKTsKCX0KCXJldHVybiBjb2xvcjsKfQpoYWxmNCBNYXRyaXhFZmZlY3RfUzEoaGFsZjQgX2lucHV0KSAKewoJcmV0dXJuIEdhdXNzaWFuQ29udm9sdXRpb25fUzFfYzAoX2lucHV0KTsKfQp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCgloYWxmNCBvdXRwdXRDb2xvcl9TMCA9IGhhbGY0KDEpOwoJY29uc3QgaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNCgxKTsKCWhhbGY0IG91dHB1dF9TMTsKCW91dHB1dF9TMSA9IE1hdHJpeEVmZmVjdF9TMShvdXRwdXRDb2xvcl9TMCk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0X1MxICogb3V0cHV0Q292ZXJhZ2VfUzA7Cgl9Cn0KAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAIAAAAcG9zaXRpb24KAAAAbG9jYWxDb29yZAAAAAAAAA==","DBAAAAAAAABGAABAYAAQAIHCAIAYAQUBAEAAAAAAIAAAAAAAAAAAAAAAAAAAAOQAAAAAAAQAAAABAMQAAAAA":"CgAAAExTS1NVAgAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQyIHVBdGxhc1NpemVJbnZfUzA7CmluIGZsb2F0MiBpblBvc2l0aW9uOwppbiBoYWxmNCBpbkNvbG9yOwppbiB1c2hvcnQyIGluVGV4dHVyZUNvb3JkczsKb3V0IGZsb2F0MiB2VGV4dHVyZUNvb3Jkc19TMDsKZmxhdCBvdXQgZmxvYXQgdlRleEluZGV4X1MwOwpvdXQgaGFsZjQgdmluQ29sb3JfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBQcmltaXRpdmUgUHJvY2Vzc29yIEJpdG1hcFRleHQKCWludDIgY29vcmRzID0gaW50MihpblRleHR1cmVDb29yZHMueCwgaW5UZXh0dXJlQ29vcmRzLnkpOwoJaW50IHRleElkeCA9IGNvb3Jkcy54ID4+IDEzOwoJZmxvYXQyIHVub3JtVGV4Q29vcmRzID0gZmxvYXQyKGNvb3Jkcy54ICYgMHgxRkZGLCBjb29yZHMueSk7Cgl2VGV4dHVyZUNvb3Jkc19TMCA9IHVub3JtVGV4Q29vcmRzICogdUF0bGFzU2l6ZUludl9TMDsKCXZUZXhJbmRleF9TMCA9IGZsb2F0KHRleElkeCk7Cgl2aW5Db2xvcl9TMCA9IGluQ29sb3I7CglmbG9hdDIgX3RtcF8xX2luUG9zaXRpb24gPSBpblBvc2l0aW9uOwoJc2tfUG9zaXRpb24gPSBpblBvc2l0aW9uLnh5MDE7Cn0KAAAAAAAAAEICAAB1bmlmb3JtIHNhbXBsZXIyRCB1VGV4dHVyZVNhbXBsZXJfMF9TMDsKdW5pZm9ybSBzYW1wbGVyMkQgdVRleHR1cmVTYW1wbGVyXzFfUzA7CmluIGZsb2F0MiB2VGV4dHVyZUNvb3Jkc19TMDsKZmxhdCBpbiBmbG9hdCB2VGV4SW5kZXhfUzA7CmluIGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gU3RhZ2UgMCwgQml0bWFwVGV4dAoJaGFsZjQgb3V0cHV0Q29sb3JfUzA7CglvdXRwdXRDb2xvcl9TMCA9IHZpbkNvbG9yX1MwOwoJaGFsZjQgdGV4Q29sb3I7CglpZiAodlRleEluZGV4X1MwID09IDApIAoJewoJCXRleENvbG9yID0gc2FtcGxlKHVUZXh0dXJlU2FtcGxlcl8wX1MwLCB2VGV4dHVyZUNvb3Jkc19TMCkucnJycjsKCX0KCWVsc2UgCgl7CgkJdGV4Q29sb3IgPSBzYW1wbGUodVRleHR1cmVTYW1wbGVyXzFfUzAsIHZUZXh0dXJlQ29vcmRzX1MwKS5ycnJyOwoJfQoJaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSB0ZXhDb2xvcjsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAKAAAAaW5Qb3NpdGlvbgAABwAAAGluQ29sb3IADwAAAGluVGV4dHVyZUNvb3JkcwAAAAAA","CMRQCIAABBYAAAEIXBAAACDQMAABRAFAAAAAAAAAAAAAAAEABYAAAAEAAAAAAAEEBQAAAAA":"CgAAAExTS1MyAgAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQ0IHVsb2NhbE1hdHJpeF9TMDsKaW4gZmxvYXQyIGluUG9zaXRpb247CmluIGhhbGY0IGluQ29sb3I7CmluIGZsb2F0MiBpbkVsbGlwc2VPZmZzZXQ7CmluIGZsb2F0NCBpbkVsbGlwc2VSYWRpaTsKb3V0IGZsb2F0MiB2RWxsaXBzZU9mZnNldHNfUzA7Cm91dCBmbG9hdDQgdkVsbGlwc2VSYWRpaV9TMDsKb3V0IGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBFbGxpcHNlR2VvbWV0cnlQcm9jZXNzb3IKCXZFbGxpcHNlT2Zmc2V0c19TMCA9IGluRWxsaXBzZU9mZnNldDsKCXZFbGxpcHNlUmFkaWlfUzAgPSBpbkVsbGlwc2VSYWRpaTsKCXZpbkNvbG9yX1MwID0gaW5Db2xvcjsKCWZsb2F0MiBfdG1wXzBfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247CglmbG9hdDIgX3RtcF8xX2luUG9zaXRpb24gPSB1bG9jYWxNYXRyaXhfUzAueHogKiBpblBvc2l0aW9uICsgdWxvY2FsTWF0cml4X1MwLnl3OwoJc2tfUG9zaXRpb24gPSBfdG1wXzBfaW5Qb3NpdGlvbi54eTAxOwp9CgAAAAAAAHIDAABpbiBmbG9hdDIgdkVsbGlwc2VPZmZzZXRzX1MwOwppbiBmbG9hdDQgdkVsbGlwc2VSYWRpaV9TMDsKaW4gaGFsZjQgdmluQ29sb3JfUzA7CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBFbGxpcHNlR2VvbWV0cnlQcm9jZXNzb3IKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2aW5Db2xvcl9TMDsKCWZsb2F0MiBvZmZzZXQgPSB2RWxsaXBzZU9mZnNldHNfUzAueHk7CglvZmZzZXQgKj0gdkVsbGlwc2VSYWRpaV9TMC54eTsKCWZsb2F0IHRlc3QgPSBkb3Qob2Zmc2V0LCBvZmZzZXQpIC0gMS4wOwoJZmxvYXQyIGdyYWQgPSAyLjAqb2Zmc2V0KnZFbGxpcHNlUmFkaWlfUzAueHk7CglmbG9hdCBncmFkX2RvdCA9IGRvdChncmFkLCBncmFkKTsKCWdyYWRfZG90ID0gbWF4KGdyYWRfZG90LCAxLjE3NTVlLTM4KTsKCWZsb2F0IGludmxlbiA9IGludmVyc2VzcXJ0KGdyYWRfZG90KTsKCWZsb2F0IGVkZ2VBbHBoYSA9IHNhdHVyYXRlKDAuNS10ZXN0Kmludmxlbik7CglvZmZzZXQgPSB2RWxsaXBzZU9mZnNldHNfUzAueHkqdkVsbGlwc2VSYWRpaV9TMC56dzsKCXRlc3QgPSBkb3Qob2Zmc2V0LCBvZmZzZXQpIC0gMS4wOwoJZ3JhZCA9IDIuMCpvZmZzZXQqdkVsbGlwc2VSYWRpaV9TMC56dzsKCWdyYWRfZG90ID0gZG90KGdyYWQsIGdyYWQpOwoJaW52bGVuID0gaW52ZXJzZXNxcnQoZ3JhZF9kb3QpOwoJZWRnZUFscGhhICo9IHNhdHVyYXRlKDAuNSt0ZXN0Kmludmxlbik7CgloYWxmNCBvdXRwdXRDb3ZlcmFnZV9TMCA9IGhhbGY0KGhhbGYoZWRnZUFscGhhKSk7Cgl7CgkJLy8gWGZlciBQcm9jZXNzb3I6IFBvcnRlciBEdWZmCgkJc2tfRnJhZ0NvbG9yID0gb3V0cHV0Q29sb3JfUzAgKiBvdXRwdXRDb3ZlcmFnZV9TMDsKCX0KfQoAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAEAAAACgAAAGluUG9zaXRpb24AAAcAAABpbkNvbG9yAA8AAABpbkVsbGlwc2VPZmZzZXQADgAAAGluRWxsaXBzZVJhZGlpAAAAAAAA","HUIAAAAAAAQAADAAAIOAAAH677777777777QGHAQAD7P7777777777YBAAAAAAAAAAALUAQBAEAQAAAAGQCBAMQACAIAAAAAACQAGAAAAAQAAAAAAAQQGAAAAA":"CgAAAExTS1M2AQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKaW4gZmxvYXQyIHBvc2l0aW9uOwppbiBmbG9hdDIgbG9jYWxDb29yZDsKb3V0IGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKdm9pZCBtYWluKCkgCnsKCS8vIFByaW1pdGl2ZSBQcm9jZXNzb3IgUXVhZFBlckVkZ2VBQUdlb21ldHJ5UHJvY2Vzc29yCglza19Qb3NpdGlvbiA9IHBvc2l0aW9uLnh5MDE7Cgl7CgkJdlRyYW5zZm9ybWVkQ29vcmRzXzJfUzAgPSBmbG9hdDN4Mih1bWF0cml4X1MxKSAqIGxvY2FsQ29vcmQueHkxOwoJfQp9CgAAAAAAAE0DAAB1bmlmb3JtIGZsb2F0NCB1Y2xhbXBfUzFfYzA7CnVuaWZvcm0gZmxvYXQzeDMgdW1hdHJpeF9TMTsKdW5pZm9ybSBzYW1wbGVyMkQgdVRleHR1cmVTYW1wbGVyXzBfUzE7CmluIGZsb2F0MiB2VHJhbnNmb3JtZWRDb29yZHNfMl9TMDsKaGFsZjQgVGV4dHVyZUVmZmVjdF9TMV9jMChoYWxmNCBfaW5wdXQpIAp7CglmbG9hdDIgaW5Db29yZCA9IHZUcmFuc2Zvcm1lZENvb3Jkc18yX1MwOwoJZmxvYXQyIHN1YnNldENvb3JkOwoJc3Vic2V0Q29vcmQueCA9IGluQ29vcmQueDsKCXN1YnNldENvb3JkLnkgPSBpbkNvb3JkLnk7CglmbG9hdDIgY2xhbXBlZENvb3JkOwoJY2xhbXBlZENvb3JkID0gY2xhbXAoc3Vic2V0Q29vcmQsIHVjbGFtcF9TMV9jMC54eSwgdWNsYW1wX1MxX2MwLnp3KTsKCWhhbGY0IHRleHR1cmVDb2xvciA9IHNhbXBsZSh1VGV4dHVyZVNhbXBsZXJfMF9TMSwgY2xhbXBlZENvb3JkKTsKCXJldHVybiB0ZXh0dXJlQ29sb3I7Cn0KaGFsZjQgTWF0cml4RWZmZWN0X1MxKGhhbGY0IF9pbnB1dCkgCnsKCXJldHVybiBUZXh0dXJlRWZmZWN0X1MxX2MwKF9pbnB1dCk7Cn0Kdm9pZCBtYWluKCkgCnsKCS8vIFN0YWdlIDAsIFF1YWRQZXJFZGdlQUFHZW9tZXRyeVByb2Nlc3NvcgoJaGFsZjQgb3V0cHV0Q29sb3JfUzAgPSBoYWxmNCgxKTsKCWNvbnN0IGhhbGY0IG91dHB1dENvdmVyYWdlX1MwID0gaGFsZjQoMSk7CgloYWxmNCBvdXRwdXRfUzE7CglvdXRwdXRfUzEgPSBNYXRyaXhFZmZlY3RfUzEob3V0cHV0Q29sb3JfUzApOwoJewoJCS8vIFhmZXIgUHJvY2Vzc29yOiBQb3J0ZXIgRHVmZgoJCXNrX0ZyYWdDb2xvciA9IG91dHB1dF9TMSAqIG91dHB1dENvdmVyYWdlX1MwOwoJfQp9CgAAAAAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAACAAAACAAAAHBvc2l0aW9uCgAAAGxvY2FsQ29vcmQAAAAAAAA=","AYQA5AADQAAAOAEARAFQJAABBADIB7777777777777777777777767YAAAAAAAAAACAFBQATAAAAAAFAAMAAAABAAAAAAABBAMAAAAA":"CgAAAExTS1PMAQAAdW5pZm9ybSBmbG9hdDQgc2tfUlRBZGp1c3Q7CnVuaWZvcm0gZmxvYXQ0IHVsb2NhbE1hdHJpeF9TMDsKaW4gZmxvYXQyIGluUG9zaXRpb247CmluIGhhbGY0IGluQ29sb3I7CmluIGZsb2F0NCBpbkNpcmNsZUVkZ2U7Cm91dCBmbG9hdDQgdmluQ2lyY2xlRWRnZV9TMDsKb3V0IGhhbGY0IHZpbkNvbG9yX1MwOwp2b2lkIG1haW4oKSAKewoJLy8gUHJpbWl0aXZlIFByb2Nlc3NvciBDaXJjbGVHZW9tZXRyeVByb2Nlc3NvcgoJdmluQ2lyY2xlRWRnZV9TMCA9IGluQ2lyY2xlRWRnZTsKCXZpbkNvbG9yX1MwID0gaW5Db2xvcjsKCWZsb2F0MiBfdG1wXzBfaW5Qb3NpdGlvbiA9IGluUG9zaXRpb247CglmbG9hdDIgX3RtcF8xX2luUG9zaXRpb24gPSB1bG9jYWxNYXRyaXhfUzAueHogKiBpblBvc2l0aW9uICsgdWxvY2FsTWF0cml4X1MwLnl3OwoJc2tfUG9zaXRpb24gPSBfdG1wXzBfaW5Qb3NpdGlvbi54eTAxOwp9CgEAAABABAAAdW5pZm9ybSBmbG9hdDQgdWlubmVyUmVjdF9TMTsKdW5pZm9ybSBmbG9hdDIgdWludlJhZGlpWFlfUzE7CmluIGZsb2F0NCB2aW5DaXJjbGVFZGdlX1MwOwppbiBoYWxmNCB2aW5Db2xvcl9TMDsKaGFsZjQgRWxsaXB0aWNhbFJSZWN0X1MxKGhhbGY0IF9pbnB1dCkgCnsKCWZsb2F0MiBkeHkwID0gdWlubmVyUmVjdF9TMS5MVCAtIHNrX0ZyYWdDb29yZC54eTsKCWZsb2F0MiBkeHkxID0gc2tfRnJhZ0Nvb3JkLnh5IC0gdWlubmVyUmVjdF9TMS5SQjsKCWZsb2F0MiBkeHkgPSBtYXgobWF4KGR4eTAsIGR4eTEpLCAwLjApOwoJZmxvYXQyIFogPSBkeHkgKiB1aW52UmFkaWlYWV9TMS54eTsKCWhhbGYgaW1wbGljaXQgPSBoYWxmKGRvdChaLCBkeHkpIC0gMS4wKTsKCWhhbGYgZ3JhZF9kb3QgPSBoYWxmKDQuMCAqIGRvdChaLCBaKSk7CglncmFkX2RvdCA9IG1heChncmFkX2RvdCwgMS4wZS00KTsKCWhhbGYgYXBwcm94X2Rpc3QgPSBpbXBsaWNpdCAqIGhhbGYoaW52ZXJzZXNxcnQoZ3JhZF9kb3QpKTsKCWhhbGYgYWxwaGEgPSBjbGFtcCgwLjUgKyBhcHByb3hfZGlzdCwgMC4wLCAxLjApOwoJcmV0dXJuIF9pbnB1dCAqIGFscGhhOwp9CnZvaWQgbWFpbigpIAp7CgkvLyBTdGFnZSAwLCBDaXJjbGVHZW9tZXRyeVByb2Nlc3NvcgoJZmxvYXQ0IGNpcmNsZUVkZ2U7CgljaXJjbGVFZGdlID0gdmluQ2lyY2xlRWRnZV9TMDsKCWhhbGY0IG91dHB1dENvbG9yX1MwOwoJb3V0cHV0Q29sb3JfUzAgPSB2aW5Db2xvcl9TMDsKCWZsb2F0IGQgPSBsZW5ndGgoY2lyY2xlRWRnZS54eSk7CgloYWxmIGRpc3RhbmNlVG9PdXRlckVkZ2UgPSBoYWxmKGNpcmNsZUVkZ2UueiAqICgxLjAgLSBkKSk7CgloYWxmIGVkZ2VBbHBoYSA9IHNhdHVyYXRlKGRpc3RhbmNlVG9PdXRlckVkZ2UpOwoJaGFsZjQgb3V0cHV0Q292ZXJhZ2VfUzAgPSBoYWxmNChlZGdlQWxwaGEpOwoJaGFsZjQgb3V0cHV0X1MxOwoJb3V0cHV0X1MxID0gRWxsaXB0aWNhbFJSZWN0X1MxKG91dHB1dENvdmVyYWdlX1MwKTsKCXsKCQkvLyBYZmVyIFByb2Nlc3NvcjogUG9ydGVyIER1ZmYKCQlza19GcmFnQ29sb3IgPSBvdXRwdXRDb2xvcl9TMCAqIG91dHB1dF9TMTsKCX0KfQoBAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAoAAABpblBvc2l0aW9uAAAHAAAAaW5Db2xvcgAMAAAAaW5DaXJjbGVFZGdlAAAAAA=="}} \ No newline at end of file From edab909fb0d92fee4ddb461a32ac9b90028b6969 Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Thu, 9 Mar 2023 19:11:22 +0100 Subject: [PATCH 14/31] screensaver: init fix --- lib/model/device.dart | 8 +++++++- lib/widgets/viewer/entry_viewer_stack.dart | 5 ++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/model/device.dart b/lib/model/device.dart index 1601324ab..22ce40c16 100644 --- a/lib/model/device.dart +++ b/lib/model/device.dart @@ -1,6 +1,7 @@ import 'package:aves/services/common/services.dart'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:floating/floating.dart'; +import 'package:flutter/services.dart'; import 'package:local_auth/local_auth.dart'; import 'package:package_info_plus/package_info_plus.dart'; @@ -57,7 +58,12 @@ class Device { _canAuthenticateUser = await auth.canCheckBiometrics || await auth.isDeviceSupported(); final floating = Floating(); - _supportPictureInPicture = await floating.isPipAvailable; + try { + _supportPictureInPicture = await floating.isPipAvailable; + } on PlatformException catch (_) { + // as of floating v2.0.0, plugin assumes activity and fails when bound via service + _supportPictureInPicture = false; + } floating.dispose(); final capabilities = await deviceService.getCapabilities(); diff --git a/lib/widgets/viewer/entry_viewer_stack.dart b/lib/widgets/viewer/entry_viewer_stack.dart index 9cf35d55d..427755218 100644 --- a/lib/widgets/viewer/entry_viewer_stack.dart +++ b/lib/widgets/viewer/entry_viewer_stack.dart @@ -3,6 +3,7 @@ import 'dart:math'; import 'package:aves/app_mode.dart'; import 'package:aves/model/actions/entry_actions.dart'; import 'package:aves/model/actions/move_type.dart'; +import 'package:aves/model/device.dart'; import 'package:aves/model/entry.dart'; import 'package:aves/model/filters/filters.dart'; import 'package:aves/model/filters/trash.dart'; @@ -241,7 +242,9 @@ class _EntryViewerStackState extends State with EntryViewContr onViewDisposed: (mainEntry, pageEntry) => viewStateConductor.reset(pageEntry ?? mainEntry), ); return StreamBuilder( - stream: _floating.pipStatus$, + // as of floating v2.0.0, plugin assumes activity and fails when bound via service + // so we do not access status stream directly, but check for support first + stream: device.supportPictureInPicture ? _floating.pipStatus$ : Stream.value(PiPStatus.disabled), builder: (context, snapshot) { var pipEnabled = snapshot.data == PiPStatus.enabled; return Stack( From d671030cb3de31e6213715e7e534fa5cd4f8e949 Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Thu, 9 Mar 2023 19:56:30 +0100 Subject: [PATCH 15/31] wallpaper: fixed video playback, session, controls --- .../deckers/thibault/aves/WallpaperActivity.kt | 15 +++++++++++++++ lib/widgets/home_page.dart | 5 ++++- lib/widgets/viewer/entry_viewer_stack.dart | 8 ++++---- lib/widgets/viewer/overlay/viewer_buttons.dart | 4 +++- lib/widgets/wallpaper_page.dart | 17 ++++++++++++----- 5 files changed, 38 insertions(+), 11 deletions(-) diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/WallpaperActivity.kt b/android/app/src/main/kotlin/deckers/thibault/aves/WallpaperActivity.kt index 202e73090..3c0b0d1f6 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/WallpaperActivity.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/WallpaperActivity.kt @@ -13,17 +13,20 @@ import deckers.thibault.aves.channel.calls.* import deckers.thibault.aves.channel.calls.window.ActivityWindowHandler import deckers.thibault.aves.channel.calls.window.WindowHandler import deckers.thibault.aves.channel.streams.ImageByteStreamHandler +import deckers.thibault.aves.channel.streams.MediaCommandStreamHandler import deckers.thibault.aves.utils.FlutterUtils import deckers.thibault.aves.utils.FlutterUtils.enableSoftwareRendering import deckers.thibault.aves.utils.LogUtils import deckers.thibault.aves.utils.getParcelableExtraCompat import io.flutter.embedding.android.FlutterFragmentActivity import io.flutter.embedding.engine.FlutterEngine +import io.flutter.plugin.common.EventChannel import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodChannel class WallpaperActivity : FlutterFragmentActivity() { private lateinit var intentDataMap: MutableMap + private lateinit var mediaSessionHandler: MediaSessionHandler override fun onCreate(savedInstanceState: Bundle?) { if (FlutterUtils.isSoftwareRenderingRequired()) { @@ -42,12 +45,19 @@ class WallpaperActivity : FlutterFragmentActivity() { super.configureFlutterEngine(flutterEngine) val messenger = flutterEngine.dartExecutor + // notification: platform -> dart + val mediaCommandStreamHandler = MediaCommandStreamHandler().apply { + EventChannel(messenger, MediaCommandStreamHandler.CHANNEL).setStreamHandler(this) + } + // dart -> platform -> dart // - need Context + mediaSessionHandler = MediaSessionHandler(this, mediaCommandStreamHandler) MethodChannel(messenger, DeviceHandler.CHANNEL).setMethodCallHandler(DeviceHandler(this)) MethodChannel(messenger, EmbeddedDataHandler.CHANNEL).setMethodCallHandler(EmbeddedDataHandler(this)) MethodChannel(messenger, MediaFetchBytesHandler.CHANNEL, AvesByteSendingMethodCodec.INSTANCE).setMethodCallHandler(MediaFetchBytesHandler(this)) MethodChannel(messenger, MediaFetchObjectHandler.CHANNEL).setMethodCallHandler(MediaFetchObjectHandler(this)) + MethodChannel(messenger, MediaSessionHandler.CHANNEL).setMethodCallHandler(mediaSessionHandler) MethodChannel(messenger, MetadataFetchHandler.CHANNEL).setMethodCallHandler(MetadataFetchHandler(this)) MethodChannel(messenger, StorageHandler.CHANNEL).setMethodCallHandler(StorageHandler(this)) // - need ContextWrapper @@ -79,6 +89,11 @@ class WallpaperActivity : FlutterFragmentActivity() { } } + override fun onDestroy() { + mediaSessionHandler.dispose() + super.onDestroy() + } + private fun onMethodCall(call: MethodCall, result: MethodChannel.Result) { when (call.method) { "getIntentData" -> { diff --git a/lib/widgets/home_page.dart b/lib/widgets/home_page.dart index be46586ce..e03454aaf 100644 --- a/lib/widgets/home_page.dart +++ b/lib/widgets/home_page.dart @@ -229,9 +229,12 @@ class _HomePageState extends State { } } break; + case AppMode.setWallpaper: + // for video playback storage + await metadataDb.init(); + break; case AppMode.pickMediaInternal: case AppMode.pickFilterInternal: - case AppMode.setWallpaper: case AppMode.slideshow: break; } diff --git a/lib/widgets/viewer/entry_viewer_stack.dart b/lib/widgets/viewer/entry_viewer_stack.dart index 427755218..d52c28ed6 100644 --- a/lib/widgets/viewer/entry_viewer_stack.dart +++ b/lib/widgets/viewer/entry_viewer_stack.dart @@ -483,6 +483,10 @@ class _EntryViewerStackState extends State with EntryViewContr } } else if (notification is ToggleOverlayNotification) { _overlayVisible.value = notification.visible ?? !_overlayVisible.value; + } else if (notification is VideoActionNotification) { + final controller = notification.controller; + final action = notification.action; + _onVideoAction(context, controller, action); } else if (notification is TvShowLessInfoNotification) { if (_overlayVisible.value) { _overlayVisible.value = false; @@ -503,10 +507,6 @@ class _EntryViewerStackState extends State with EntryViewContr _goToHorizontalPageByDelta(delta: 1, animate: notification.animate); } else if (notification is ShowEntryNotification) { _goToHorizontalPageByIndex(page: notification.index, animate: notification.animate); - } else if (notification is VideoActionNotification) { - final controller = notification.controller; - final action = notification.action; - _onVideoAction(context, controller, action); } else { return false; } diff --git a/lib/widgets/viewer/overlay/viewer_buttons.dart b/lib/widgets/viewer/overlay/viewer_buttons.dart index 41208da65..2ad237638 100644 --- a/lib/widgets/viewer/overlay/viewer_buttons.dart +++ b/lib/widgets/viewer/overlay/viewer_buttons.dart @@ -1,3 +1,5 @@ +import 'dart:math'; + import 'package:aves/app_mode.dart'; import 'package:aves/model/actions/entry_actions.dart'; import 'package:aves/model/entry.dart'; @@ -79,7 +81,7 @@ class ViewerButtons extends StatelessWidget { return Selector( selector: (context, s) => s.isRotationLocked, builder: (context, s, child) { - final quickActions = (trashed ? EntryActions.trashed : settings.viewerQuickActions).where(isVisible).where(actionDelegate.canApply).take(availableCount - 1).toList(); + final quickActions = (trashed ? EntryActions.trashed : settings.viewerQuickActions).where(isVisible).where(actionDelegate.canApply).take(max(0, availableCount - 1)).toList(); List getMenuActions(List categoryActions) { return categoryActions.where((action) => !quickActions.contains(action)).where(isVisible).toList(); } diff --git a/lib/widgets/wallpaper_page.dart b/lib/widgets/wallpaper_page.dart index e052b4e8e..81d347d08 100644 --- a/lib/widgets/wallpaper_page.dart +++ b/lib/widgets/wallpaper_page.dart @@ -1,3 +1,4 @@ +import 'package:aves/model/actions/entry_actions.dart'; import 'package:aves/model/entry.dart'; import 'package:aves/model/settings/enums/enums.dart'; import 'package:aves/model/settings/settings.dart'; @@ -130,6 +131,10 @@ class _EntryEditorState extends State with EntryViewControllerMixin onNotification: (dynamic notification) { if (notification is ToggleOverlayNotification) { _overlayVisible.value = notification.visible ?? !_overlayVisible.value; + } else if (notification is VideoActionNotification) { + final controller = notification.controller; + final action = notification.action; + _onVideoAction(context, controller, action); } return true; }, @@ -171,11 +176,7 @@ class _EntryEditorState extends State with EntryViewControllerMixin entry: targetEntry, controller: videoController, scale: _overlayVideoControlScale, - onActionSelected: (action) { - if (videoController != null) { - _videoActionDelegate.onActionSelected(context, videoController, action); - } - }, + onActionSelected: (action) => _onVideoAction(context, videoController, action), onActionMenuOpened: () { // if the menu is opened while overlay is hiding, // the popup menu button is disposed and menu items are ineffective, @@ -235,6 +236,12 @@ class _EntryEditorState extends State with EntryViewControllerMixin ); } + void _onVideoAction(BuildContext context, AvesVideoController? videoController, EntryAction action) { + if (videoController != null) { + _videoActionDelegate.onActionSelected(context, videoController, action); + } + } + // overlay Future _onOverlayVisibleChanged({bool animate = true}) async { From 1374b8d4923a8f3c0ea7e2c5570c6207aa3586fc Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Thu, 9 Mar 2023 20:50:59 +0100 Subject: [PATCH 16/31] fixed crash when using fingerprint on Android 8.1 --- CHANGELOG.md | 1 + .../app/src/main/res/values-night/styles.xml | 2 +- android/app/src/main/res/values/styles.xml | 2 +- .../viewer/visual/entry_page_view.dart | 36 +++++++++++-------- 4 files changed, 25 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e7516ea77..e5eeefb2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ All notable changes to this project will be documented in this file. - Accessibility: using accessibility services keeping snack bar beyond countdown - Accessibility: navigation with TalkBack +- Vaults: crash when using fingerprint on older Android versions ## [v1.8.2] - 2023-02-28 diff --git a/android/app/src/main/res/values-night/styles.xml b/android/app/src/main/res/values-night/styles.xml index 25046f02e..edd8ddab8 100644 --- a/android/app/src/main/res/values-night/styles.xml +++ b/android/app/src/main/res/values-night/styles.xml @@ -1,6 +1,6 @@ -