From c8f029386d88a62a9403c98adb52e519a5529ac3 Mon Sep 17 00:00:00 2001 From: Sergey Mikolaytis Date: Sat, 22 Jan 2022 14:01:35 +0300 Subject: [PATCH 01/78] Map devices, add some native api --- src/Avalonia.Input/IPenDevice.cs | 10 + src/Avalonia.Input/ITouchPadDevice.cs | 10 + src/Avalonia.Input/PenDevice.cs | 488 ++++++++++++++++++ src/Avalonia.Input/TouchPadDevice.cs | 488 ++++++++++++++++++ .../Interop/UnmanagedMethods.cs | 64 +++ .../Avalonia.Win32/WindowImpl.AppWndProc.cs | 155 ++++++ 6 files changed, 1215 insertions(+) create mode 100644 src/Avalonia.Input/IPenDevice.cs create mode 100644 src/Avalonia.Input/ITouchPadDevice.cs create mode 100644 src/Avalonia.Input/PenDevice.cs create mode 100644 src/Avalonia.Input/TouchPadDevice.cs diff --git a/src/Avalonia.Input/IPenDevice.cs b/src/Avalonia.Input/IPenDevice.cs new file mode 100644 index 0000000000..1cc0fcf76d --- /dev/null +++ b/src/Avalonia.Input/IPenDevice.cs @@ -0,0 +1,10 @@ +namespace Avalonia.Input +{ + /// + /// Represents a pen/stylus device. + /// + public interface IPenDevice : IPointerDevice + { + + } +} diff --git a/src/Avalonia.Input/ITouchPadDevice.cs b/src/Avalonia.Input/ITouchPadDevice.cs new file mode 100644 index 0000000000..ea6c57f948 --- /dev/null +++ b/src/Avalonia.Input/ITouchPadDevice.cs @@ -0,0 +1,10 @@ +namespace Avalonia.Input +{ + /// + /// Represents a touch pad device. + /// + public interface ITouchPadDevice : IPointerDevice + { + + } +} diff --git a/src/Avalonia.Input/PenDevice.cs b/src/Avalonia.Input/PenDevice.cs new file mode 100644 index 0000000000..dd3d60ebb9 --- /dev/null +++ b/src/Avalonia.Input/PenDevice.cs @@ -0,0 +1,488 @@ +using System; +using System.Linq; +using System.Reactive.Linq; +using Avalonia.Input.Raw; +using Avalonia.Interactivity; +using Avalonia.Platform; +using Avalonia.VisualTree; + +namespace Avalonia.Input +{ + /// + /// Represents a pen/stylus device. + /// + public class PenDevice : IPenDevice, IDisposable + { + private int _clickCount; + private Rect _lastClickRect; + private ulong _lastClickTime; + + private readonly Pointer _pointer; + private bool _disposed; + private PixelPoint? _position; + + public PenDevice(Pointer? pointer = null) + { + _pointer = pointer ?? new Pointer(Pointer.GetNextFreeId(), PointerType.Mouse, true); + } + + /// + /// Gets the control that is currently capturing by the mouse, if any. + /// + /// + /// When an element captures the mouse, it receives mouse input whether the cursor is + /// within the control's bounds or not. To set the mouse capture, call the + /// method. + /// + [Obsolete("Use IPointer instead")] + public IInputElement? Captured => _pointer.Captured; + + /// + /// Gets the mouse position, in screen coordinates. + /// + [Obsolete("Use events instead")] + public PixelPoint Position + { + get => _position ?? new PixelPoint(-1, -1); + protected set => _position = value; + } + + /// + /// Captures mouse input to the specified control. + /// + /// The control. + /// + /// When an element captures the mouse, it receives mouse input whether the cursor is + /// within the control's bounds or not. The current mouse capture control is exposed + /// by the property. + /// + public void Capture(IInputElement? control) + { + _pointer.Capture(control); + } + + /// + /// Gets the mouse position relative to a control. + /// + /// The control. + /// The mouse position in the control's coordinates. + public Point GetPosition(IVisual relativeTo) + { + relativeTo = relativeTo ?? throw new ArgumentNullException(nameof(relativeTo)); + + if (relativeTo.VisualRoot == null) + { + throw new InvalidOperationException("Control is not attached to visual tree."); + } + +#pragma warning disable CS0618 // Type or member is obsolete + var rootPoint = relativeTo.VisualRoot.PointToClient(Position); +#pragma warning restore CS0618 // Type or member is obsolete + var transform = relativeTo.VisualRoot.TransformToVisual(relativeTo); + return rootPoint * transform!.Value; + } + + public void ProcessRawEvent(RawInputEventArgs e) + { + if (!e.Handled && e is RawPointerEventArgs margs) + ProcessRawEvent(margs); + } + + public void TopLevelClosed(IInputRoot root) + { + ClearPointerOver(this, 0, root, PointerPointProperties.None, KeyModifiers.None); + } + + public void SceneInvalidated(IInputRoot root, Rect rect) + { + // Pointer is outside of the target area + if (_position == null ) + { + if (root.PointerOverElement != null) + ClearPointerOver(this, 0, root, PointerPointProperties.None, KeyModifiers.None); + return; + } + + + var clientPoint = root.PointToClient(_position.Value); + + if (rect.Contains(clientPoint)) + { + if (_pointer.Captured == null) + { + SetPointerOver(this, 0 /* TODO: proper timestamp */, root, clientPoint, + PointerPointProperties.None, KeyModifiers.None); + } + else + { + SetPointerOver(this, 0 /* TODO: proper timestamp */, root, _pointer.Captured, + PointerPointProperties.None, KeyModifiers.None); + } + } + } + + int ButtonCount(PointerPointProperties props) + { + var rv = 0; + if (props.IsLeftButtonPressed) + rv++; + if (props.IsMiddleButtonPressed) + rv++; + if (props.IsRightButtonPressed) + rv++; + if (props.IsXButton1Pressed) + rv++; + if (props.IsXButton2Pressed) + rv++; + return rv; + } + + private void ProcessRawEvent(RawPointerEventArgs e) + { + e = e ?? throw new ArgumentNullException(nameof(e)); + + var mouse = (PenDevice)e.Device; + if(mouse._disposed) + return; + + _position = e.Root.PointToScreen(e.Position); + var props = CreateProperties(e); + var keyModifiers = KeyModifiersUtils.ConvertToKey(e.InputModifiers); + switch (e.Type) + { + case RawPointerEventType.LeaveWindow: + LeaveWindow(mouse, e.Timestamp, e.Root, props, keyModifiers); + break; + case RawPointerEventType.LeftButtonDown: + case RawPointerEventType.RightButtonDown: + case RawPointerEventType.MiddleButtonDown: + case RawPointerEventType.XButton1Down: + case RawPointerEventType.XButton2Down: + if (ButtonCount(props) > 1) + e.Handled = MouseMove(mouse, e.Timestamp, e.Root, e.Position, props, keyModifiers); + else + e.Handled = MouseDown(mouse, e.Timestamp, e.Root, e.Position, + props, keyModifiers); + break; + case RawPointerEventType.LeftButtonUp: + case RawPointerEventType.RightButtonUp: + case RawPointerEventType.MiddleButtonUp: + case RawPointerEventType.XButton1Up: + case RawPointerEventType.XButton2Up: + if (ButtonCount(props) != 0) + e.Handled = MouseMove(mouse, e.Timestamp, e.Root, e.Position, props, keyModifiers); + else + e.Handled = MouseUp(mouse, e.Timestamp, e.Root, e.Position, props, keyModifiers); + break; + case RawPointerEventType.Move: + e.Handled = MouseMove(mouse, e.Timestamp, e.Root, e.Position, props, keyModifiers); + break; + case RawPointerEventType.Wheel: + e.Handled = MouseWheel(mouse, e.Timestamp, e.Root, e.Position, props, ((RawMouseWheelEventArgs)e).Delta, keyModifiers); + break; + } + } + + private void LeaveWindow(IPenDevice device, ulong timestamp, IInputRoot root, PointerPointProperties properties, + KeyModifiers inputModifiers) + { + device = device ?? throw new ArgumentNullException(nameof(device)); + root = root ?? throw new ArgumentNullException(nameof(root)); + + _position = null; + ClearPointerOver(this, timestamp, root, properties, inputModifiers); + } + + + PointerPointProperties CreateProperties(RawPointerEventArgs args) + { + + var kind = PointerUpdateKind.Other; + + if (args.Type == RawPointerEventType.LeftButtonDown) + kind = PointerUpdateKind.LeftButtonPressed; + if (args.Type == RawPointerEventType.MiddleButtonDown) + kind = PointerUpdateKind.MiddleButtonPressed; + if (args.Type == RawPointerEventType.RightButtonDown) + kind = PointerUpdateKind.RightButtonPressed; + if (args.Type == RawPointerEventType.XButton1Down) + kind = PointerUpdateKind.XButton1Pressed; + if (args.Type == RawPointerEventType.XButton2Down) + kind = PointerUpdateKind.XButton2Pressed; + if (args.Type == RawPointerEventType.LeftButtonUp) + kind = PointerUpdateKind.LeftButtonReleased; + if (args.Type == RawPointerEventType.MiddleButtonUp) + kind = PointerUpdateKind.MiddleButtonReleased; + if (args.Type == RawPointerEventType.RightButtonUp) + kind = PointerUpdateKind.RightButtonReleased; + if (args.Type == RawPointerEventType.XButton1Up) + kind = PointerUpdateKind.XButton1Released; + if (args.Type == RawPointerEventType.XButton2Up) + kind = PointerUpdateKind.XButton2Released; + + return new PointerPointProperties(args.InputModifiers, kind); + } + + private MouseButton _lastMouseDownButton; + private bool MouseDown(IPenDevice device, ulong timestamp, IInputElement root, Point p, + PointerPointProperties properties, + KeyModifiers inputModifiers) + { + device = device ?? throw new ArgumentNullException(nameof(device)); + root = root ?? throw new ArgumentNullException(nameof(root)); + + var hit = HitTest(root, p); + + if (hit != null) + { + _pointer.Capture(hit); + var source = GetSource(hit); + if (source != null) + { + var settings = AvaloniaLocator.Current.GetService(); + var doubleClickTime = settings?.DoubleClickTime.TotalMilliseconds ?? 500; + var doubleClickSize = settings?.DoubleClickSize ?? new Size(4, 4); + + if (!_lastClickRect.Contains(p) || timestamp - _lastClickTime > doubleClickTime) + { + _clickCount = 0; + } + + ++_clickCount; + _lastClickTime = timestamp; + _lastClickRect = new Rect(p, new Size()) + .Inflate(new Thickness(doubleClickSize.Width / 2, doubleClickSize.Height / 2)); + _lastMouseDownButton = properties.PointerUpdateKind.GetMouseButton(); + var e = new PointerPressedEventArgs(source, _pointer, root, p, timestamp, properties, inputModifiers, _clickCount); + source.RaiseEvent(e); + return e.Handled; + } + } + + return false; + } + + private bool MouseMove(IPenDevice device, ulong timestamp, IInputRoot root, Point p, PointerPointProperties properties, + KeyModifiers inputModifiers) + { + device = device ?? throw new ArgumentNullException(nameof(device)); + root = root ?? throw new ArgumentNullException(nameof(root)); + + IInputElement? source; + + if (_pointer.Captured == null) + { + source = SetPointerOver(this, timestamp, root, p, properties, inputModifiers); + } + else + { + SetPointerOver(this, timestamp, root, _pointer.Captured, properties, inputModifiers); + source = _pointer.Captured; + } + + if (source is object) + { + var e = new PointerEventArgs(InputElement.PointerMovedEvent, source, _pointer, root, + p, timestamp, properties, inputModifiers); + + source.RaiseEvent(e); + return e.Handled; + } + + return false; + } + + private bool MouseUp(IPenDevice device, ulong timestamp, IInputRoot root, Point p, PointerPointProperties props, + KeyModifiers inputModifiers) + { + device = device ?? throw new ArgumentNullException(nameof(device)); + root = root ?? throw new ArgumentNullException(nameof(root)); + + var hit = HitTest(root, p); + var source = GetSource(hit); + + if (source is not null) + { + var e = new PointerReleasedEventArgs(source, _pointer, root, p, timestamp, props, inputModifiers, + _lastMouseDownButton); + + source?.RaiseEvent(e); + _pointer.Capture(null); + return e.Handled; + } + + return false; + } + + private bool MouseWheel(IPenDevice device, ulong timestamp, IInputRoot root, Point p, + PointerPointProperties props, + Vector delta, KeyModifiers inputModifiers) + { + device = device ?? throw new ArgumentNullException(nameof(device)); + root = root ?? throw new ArgumentNullException(nameof(root)); + + var hit = HitTest(root, p); + var source = GetSource(hit); + + if (source is not null) + { + var e = new PointerWheelEventArgs(source, _pointer, root, p, timestamp, props, inputModifiers, delta); + + source?.RaiseEvent(e); + return e.Handled; + } + + return false; + } + + private IInteractive? GetSource(IVisual? hit) + { + if (hit is null) + return null; + + return _pointer.Captured ?? + (hit as IInteractive) ?? + hit.GetSelfAndVisualAncestors().OfType().FirstOrDefault(); + } + + private IInputElement? HitTest(IInputElement root, Point p) + { + root = root ?? throw new ArgumentNullException(nameof(root)); + + return _pointer.Captured ?? root.InputHitTest(p); + } + + PointerEventArgs CreateSimpleEvent(RoutedEvent ev, ulong timestamp, IInteractive? source, + PointerPointProperties properties, + KeyModifiers inputModifiers) + { + return new PointerEventArgs(ev, source, _pointer, null, default, + timestamp, properties, inputModifiers); + } + + private void ClearPointerOver(IPointerDevice device, ulong timestamp, IInputRoot root, + PointerPointProperties properties, + KeyModifiers inputModifiers) + { + device = device ?? throw new ArgumentNullException(nameof(device)); + root = root ?? throw new ArgumentNullException(nameof(root)); + + var element = root.PointerOverElement; + var e = CreateSimpleEvent(InputElement.PointerLeaveEvent, timestamp, element, properties, inputModifiers); + + if (element!=null && !element.IsAttachedToVisualTree) + { + // element has been removed from visual tree so do top down cleanup + if (root.IsPointerOver) + ClearChildrenPointerOver(e, root,true); + } + while (element != null) + { + e.Source = element; + e.Handled = false; + element.RaiseEvent(e); + element = (IInputElement?)element.VisualParent; + } + + root.PointerOverElement = null; + } + + private void ClearChildrenPointerOver(PointerEventArgs e, IInputElement element,bool clearRoot) + { + foreach (IInputElement el in element.VisualChildren) + { + if (el.IsPointerOver) + { + ClearChildrenPointerOver(e, el, true); + break; + } + } + if(clearRoot) + { + e.Source = element; + e.Handled = false; + element.RaiseEvent(e); + } + } + + private IInputElement? SetPointerOver(IPointerDevice device, ulong timestamp, IInputRoot root, Point p, + PointerPointProperties properties, + KeyModifiers inputModifiers) + { + device = device ?? throw new ArgumentNullException(nameof(device)); + root = root ?? throw new ArgumentNullException(nameof(root)); + + var element = root.InputHitTest(p); + + if (element != root.PointerOverElement) + { + if (element != null) + { + SetPointerOver(device, timestamp, root, element, properties, inputModifiers); + } + else + { + ClearPointerOver(device, timestamp, root, properties, inputModifiers); + } + } + + return element; + } + + private void SetPointerOver(IPointerDevice device, ulong timestamp, IInputRoot root, IInputElement element, + PointerPointProperties properties, + KeyModifiers inputModifiers) + { + device = device ?? throw new ArgumentNullException(nameof(device)); + root = root ?? throw new ArgumentNullException(nameof(root)); + element = element ?? throw new ArgumentNullException(nameof(element)); + + IInputElement? branch = null; + + IInputElement? el = element; + + while (el != null) + { + if (el.IsPointerOver) + { + branch = el; + break; + } + el = (IInputElement?)el.VisualParent; + } + + el = root.PointerOverElement; + + var e = CreateSimpleEvent(InputElement.PointerLeaveEvent, timestamp, el, properties, inputModifiers); + if (el!=null && branch!=null && !el.IsAttachedToVisualTree) + { + ClearChildrenPointerOver(e,branch,false); + } + + while (el != null && el != branch) + { + e.Source = el; + e.Handled = false; + el.RaiseEvent(e); + el = (IInputElement?)el.VisualParent; + } + + el = root.PointerOverElement = element; + e.RoutedEvent = InputElement.PointerEnterEvent; + + while (el != null && el != branch) + { + e.Source = el; + e.Handled = false; + el.RaiseEvent(e); + el = (IInputElement?)el.VisualParent; + } + } + + public void Dispose() + { + _disposed = true; + _pointer?.Dispose(); + } + } +} diff --git a/src/Avalonia.Input/TouchPadDevice.cs b/src/Avalonia.Input/TouchPadDevice.cs new file mode 100644 index 0000000000..fcd254f588 --- /dev/null +++ b/src/Avalonia.Input/TouchPadDevice.cs @@ -0,0 +1,488 @@ +using System; +using System.Linq; +using System.Reactive.Linq; +using Avalonia.Input.Raw; +using Avalonia.Interactivity; +using Avalonia.Platform; +using Avalonia.VisualTree; + +namespace Avalonia.Input +{ + /// + /// Represents a touch pad device. + /// + public class TouchPadDevice : ITouchPadDevice, IDisposable + { + private int _clickCount; + private Rect _lastClickRect; + private ulong _lastClickTime; + + private readonly Pointer _pointer; + private bool _disposed; + private PixelPoint? _position; + + public TouchPadDevice(Pointer? pointer = null) + { + _pointer = pointer ?? new Pointer(Pointer.GetNextFreeId(), PointerType.Mouse, true); + } + + /// + /// Gets the control that is currently capturing by the mouse, if any. + /// + /// + /// When an element captures the mouse, it receives mouse input whether the cursor is + /// within the control's bounds or not. To set the mouse capture, call the + /// method. + /// + [Obsolete("Use IPointer instead")] + public IInputElement? Captured => _pointer.Captured; + + /// + /// Gets the mouse position, in screen coordinates. + /// + [Obsolete("Use events instead")] + public PixelPoint Position + { + get => _position ?? new PixelPoint(-1, -1); + protected set => _position = value; + } + + /// + /// Captures mouse input to the specified control. + /// + /// The control. + /// + /// When an element captures the mouse, it receives mouse input whether the cursor is + /// within the control's bounds or not. The current mouse capture control is exposed + /// by the property. + /// + public void Capture(IInputElement? control) + { + _pointer.Capture(control); + } + + /// + /// Gets the mouse position relative to a control. + /// + /// The control. + /// The mouse position in the control's coordinates. + public Point GetPosition(IVisual relativeTo) + { + relativeTo = relativeTo ?? throw new ArgumentNullException(nameof(relativeTo)); + + if (relativeTo.VisualRoot == null) + { + throw new InvalidOperationException("Control is not attached to visual tree."); + } + +#pragma warning disable CS0618 // Type or member is obsolete + var rootPoint = relativeTo.VisualRoot.PointToClient(Position); +#pragma warning restore CS0618 // Type or member is obsolete + var transform = relativeTo.VisualRoot.TransformToVisual(relativeTo); + return rootPoint * transform!.Value; + } + + public void ProcessRawEvent(RawInputEventArgs e) + { + if (!e.Handled && e is RawPointerEventArgs margs) + ProcessRawEvent(margs); + } + + public void TopLevelClosed(IInputRoot root) + { + ClearPointerOver(this, 0, root, PointerPointProperties.None, KeyModifiers.None); + } + + public void SceneInvalidated(IInputRoot root, Rect rect) + { + // Pointer is outside of the target area + if (_position == null ) + { + if (root.PointerOverElement != null) + ClearPointerOver(this, 0, root, PointerPointProperties.None, KeyModifiers.None); + return; + } + + + var clientPoint = root.PointToClient(_position.Value); + + if (rect.Contains(clientPoint)) + { + if (_pointer.Captured == null) + { + SetPointerOver(this, 0 /* TODO: proper timestamp */, root, clientPoint, + PointerPointProperties.None, KeyModifiers.None); + } + else + { + SetPointerOver(this, 0 /* TODO: proper timestamp */, root, _pointer.Captured, + PointerPointProperties.None, KeyModifiers.None); + } + } + } + + int ButtonCount(PointerPointProperties props) + { + var rv = 0; + if (props.IsLeftButtonPressed) + rv++; + if (props.IsMiddleButtonPressed) + rv++; + if (props.IsRightButtonPressed) + rv++; + if (props.IsXButton1Pressed) + rv++; + if (props.IsXButton2Pressed) + rv++; + return rv; + } + + private void ProcessRawEvent(RawPointerEventArgs e) + { + e = e ?? throw new ArgumentNullException(nameof(e)); + + var mouse = (TouchPadDevice)e.Device; + if(mouse._disposed) + return; + + _position = e.Root.PointToScreen(e.Position); + var props = CreateProperties(e); + var keyModifiers = KeyModifiersUtils.ConvertToKey(e.InputModifiers); + switch (e.Type) + { + case RawPointerEventType.LeaveWindow: + LeaveWindow(mouse, e.Timestamp, e.Root, props, keyModifiers); + break; + case RawPointerEventType.LeftButtonDown: + case RawPointerEventType.RightButtonDown: + case RawPointerEventType.MiddleButtonDown: + case RawPointerEventType.XButton1Down: + case RawPointerEventType.XButton2Down: + if (ButtonCount(props) > 1) + e.Handled = MouseMove(mouse, e.Timestamp, e.Root, e.Position, props, keyModifiers); + else + e.Handled = MouseDown(mouse, e.Timestamp, e.Root, e.Position, + props, keyModifiers); + break; + case RawPointerEventType.LeftButtonUp: + case RawPointerEventType.RightButtonUp: + case RawPointerEventType.MiddleButtonUp: + case RawPointerEventType.XButton1Up: + case RawPointerEventType.XButton2Up: + if (ButtonCount(props) != 0) + e.Handled = MouseMove(mouse, e.Timestamp, e.Root, e.Position, props, keyModifiers); + else + e.Handled = MouseUp(mouse, e.Timestamp, e.Root, e.Position, props, keyModifiers); + break; + case RawPointerEventType.Move: + e.Handled = MouseMove(mouse, e.Timestamp, e.Root, e.Position, props, keyModifiers); + break; + case RawPointerEventType.Wheel: + e.Handled = MouseWheel(mouse, e.Timestamp, e.Root, e.Position, props, ((RawMouseWheelEventArgs)e).Delta, keyModifiers); + break; + } + } + + private void LeaveWindow(ITouchPadDevice device, ulong timestamp, IInputRoot root, PointerPointProperties properties, + KeyModifiers inputModifiers) + { + device = device ?? throw new ArgumentNullException(nameof(device)); + root = root ?? throw new ArgumentNullException(nameof(root)); + + _position = null; + ClearPointerOver(this, timestamp, root, properties, inputModifiers); + } + + + PointerPointProperties CreateProperties(RawPointerEventArgs args) + { + + var kind = PointerUpdateKind.Other; + + if (args.Type == RawPointerEventType.LeftButtonDown) + kind = PointerUpdateKind.LeftButtonPressed; + if (args.Type == RawPointerEventType.MiddleButtonDown) + kind = PointerUpdateKind.MiddleButtonPressed; + if (args.Type == RawPointerEventType.RightButtonDown) + kind = PointerUpdateKind.RightButtonPressed; + if (args.Type == RawPointerEventType.XButton1Down) + kind = PointerUpdateKind.XButton1Pressed; + if (args.Type == RawPointerEventType.XButton2Down) + kind = PointerUpdateKind.XButton2Pressed; + if (args.Type == RawPointerEventType.LeftButtonUp) + kind = PointerUpdateKind.LeftButtonReleased; + if (args.Type == RawPointerEventType.MiddleButtonUp) + kind = PointerUpdateKind.MiddleButtonReleased; + if (args.Type == RawPointerEventType.RightButtonUp) + kind = PointerUpdateKind.RightButtonReleased; + if (args.Type == RawPointerEventType.XButton1Up) + kind = PointerUpdateKind.XButton1Released; + if (args.Type == RawPointerEventType.XButton2Up) + kind = PointerUpdateKind.XButton2Released; + + return new PointerPointProperties(args.InputModifiers, kind); + } + + private MouseButton _lastMouseDownButton; + private bool MouseDown(ITouchPadDevice device, ulong timestamp, IInputElement root, Point p, + PointerPointProperties properties, + KeyModifiers inputModifiers) + { + device = device ?? throw new ArgumentNullException(nameof(device)); + root = root ?? throw new ArgumentNullException(nameof(root)); + + var hit = HitTest(root, p); + + if (hit != null) + { + _pointer.Capture(hit); + var source = GetSource(hit); + if (source != null) + { + var settings = AvaloniaLocator.Current.GetService(); + var doubleClickTime = settings?.DoubleClickTime.TotalMilliseconds ?? 500; + var doubleClickSize = settings?.DoubleClickSize ?? new Size(4, 4); + + if (!_lastClickRect.Contains(p) || timestamp - _lastClickTime > doubleClickTime) + { + _clickCount = 0; + } + + ++_clickCount; + _lastClickTime = timestamp; + _lastClickRect = new Rect(p, new Size()) + .Inflate(new Thickness(doubleClickSize.Width / 2, doubleClickSize.Height / 2)); + _lastMouseDownButton = properties.PointerUpdateKind.GetMouseButton(); + var e = new PointerPressedEventArgs(source, _pointer, root, p, timestamp, properties, inputModifiers, _clickCount); + source.RaiseEvent(e); + return e.Handled; + } + } + + return false; + } + + private bool MouseMove(ITouchPadDevice device, ulong timestamp, IInputRoot root, Point p, PointerPointProperties properties, + KeyModifiers inputModifiers) + { + device = device ?? throw new ArgumentNullException(nameof(device)); + root = root ?? throw new ArgumentNullException(nameof(root)); + + IInputElement? source; + + if (_pointer.Captured == null) + { + source = SetPointerOver(this, timestamp, root, p, properties, inputModifiers); + } + else + { + SetPointerOver(this, timestamp, root, _pointer.Captured, properties, inputModifiers); + source = _pointer.Captured; + } + + if (source is object) + { + var e = new PointerEventArgs(InputElement.PointerMovedEvent, source, _pointer, root, + p, timestamp, properties, inputModifiers); + + source.RaiseEvent(e); + return e.Handled; + } + + return false; + } + + private bool MouseUp(ITouchPadDevice device, ulong timestamp, IInputRoot root, Point p, PointerPointProperties props, + KeyModifiers inputModifiers) + { + device = device ?? throw new ArgumentNullException(nameof(device)); + root = root ?? throw new ArgumentNullException(nameof(root)); + + var hit = HitTest(root, p); + var source = GetSource(hit); + + if (source is not null) + { + var e = new PointerReleasedEventArgs(source, _pointer, root, p, timestamp, props, inputModifiers, + _lastMouseDownButton); + + source?.RaiseEvent(e); + _pointer.Capture(null); + return e.Handled; + } + + return false; + } + + private bool MouseWheel(ITouchPadDevice device, ulong timestamp, IInputRoot root, Point p, + PointerPointProperties props, + Vector delta, KeyModifiers inputModifiers) + { + device = device ?? throw new ArgumentNullException(nameof(device)); + root = root ?? throw new ArgumentNullException(nameof(root)); + + var hit = HitTest(root, p); + var source = GetSource(hit); + + if (source is not null) + { + var e = new PointerWheelEventArgs(source, _pointer, root, p, timestamp, props, inputModifiers, delta); + + source?.RaiseEvent(e); + return e.Handled; + } + + return false; + } + + private IInteractive? GetSource(IVisual? hit) + { + if (hit is null) + return null; + + return _pointer.Captured ?? + (hit as IInteractive) ?? + hit.GetSelfAndVisualAncestors().OfType().FirstOrDefault(); + } + + private IInputElement? HitTest(IInputElement root, Point p) + { + root = root ?? throw new ArgumentNullException(nameof(root)); + + return _pointer.Captured ?? root.InputHitTest(p); + } + + PointerEventArgs CreateSimpleEvent(RoutedEvent ev, ulong timestamp, IInteractive? source, + PointerPointProperties properties, + KeyModifiers inputModifiers) + { + return new PointerEventArgs(ev, source, _pointer, null, default, + timestamp, properties, inputModifiers); + } + + private void ClearPointerOver(IPointerDevice device, ulong timestamp, IInputRoot root, + PointerPointProperties properties, + KeyModifiers inputModifiers) + { + device = device ?? throw new ArgumentNullException(nameof(device)); + root = root ?? throw new ArgumentNullException(nameof(root)); + + var element = root.PointerOverElement; + var e = CreateSimpleEvent(InputElement.PointerLeaveEvent, timestamp, element, properties, inputModifiers); + + if (element!=null && !element.IsAttachedToVisualTree) + { + // element has been removed from visual tree so do top down cleanup + if (root.IsPointerOver) + ClearChildrenPointerOver(e, root,true); + } + while (element != null) + { + e.Source = element; + e.Handled = false; + element.RaiseEvent(e); + element = (IInputElement?)element.VisualParent; + } + + root.PointerOverElement = null; + } + + private void ClearChildrenPointerOver(PointerEventArgs e, IInputElement element,bool clearRoot) + { + foreach (IInputElement el in element.VisualChildren) + { + if (el.IsPointerOver) + { + ClearChildrenPointerOver(e, el, true); + break; + } + } + if(clearRoot) + { + e.Source = element; + e.Handled = false; + element.RaiseEvent(e); + } + } + + private IInputElement? SetPointerOver(IPointerDevice device, ulong timestamp, IInputRoot root, Point p, + PointerPointProperties properties, + KeyModifiers inputModifiers) + { + device = device ?? throw new ArgumentNullException(nameof(device)); + root = root ?? throw new ArgumentNullException(nameof(root)); + + var element = root.InputHitTest(p); + + if (element != root.PointerOverElement) + { + if (element != null) + { + SetPointerOver(device, timestamp, root, element, properties, inputModifiers); + } + else + { + ClearPointerOver(device, timestamp, root, properties, inputModifiers); + } + } + + return element; + } + + private void SetPointerOver(IPointerDevice device, ulong timestamp, IInputRoot root, IInputElement element, + PointerPointProperties properties, + KeyModifiers inputModifiers) + { + device = device ?? throw new ArgumentNullException(nameof(device)); + root = root ?? throw new ArgumentNullException(nameof(root)); + element = element ?? throw new ArgumentNullException(nameof(element)); + + IInputElement? branch = null; + + IInputElement? el = element; + + while (el != null) + { + if (el.IsPointerOver) + { + branch = el; + break; + } + el = (IInputElement?)el.VisualParent; + } + + el = root.PointerOverElement; + + var e = CreateSimpleEvent(InputElement.PointerLeaveEvent, timestamp, el, properties, inputModifiers); + if (el!=null && branch!=null && !el.IsAttachedToVisualTree) + { + ClearChildrenPointerOver(e,branch,false); + } + + while (el != null && el != branch) + { + e.Source = el; + e.Handled = false; + el.RaiseEvent(e); + el = (IInputElement?)el.VisualParent; + } + + el = root.PointerOverElement = element; + e.RoutedEvent = InputElement.PointerEnterEvent; + + while (el != null && el != branch) + { + e.Source = el; + e.Handled = false; + el.RaiseEvent(e); + el = (IInputElement?)el.VisualParent; + } + } + + public void Dispose() + { + _disposed = true; + _pointer?.Dispose(); + } + } +} diff --git a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs index c74c5fbc01..db81e8197f 100644 --- a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs +++ b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs @@ -514,6 +514,33 @@ namespace Avalonia.Win32.Interop CS_DROPSHADOW = 0x00020000 } + [Flags] + public enum PointerDeviceChangeFlags + { + PDC_ARRIVAL = 0x001, + PDC_REMOVAL = 0x002, + PDC_ORIENTATION_0 = 0x004, + PDC_ORIENTATION_90 = 0x008, + PDC_ORIENTATION_180 = 0x010, + PDC_ORIENTATION_270 = 0x020, + PDC_MODE_DEFAULT = 0x040, + PDC_MODE_CENTERED = 0x080, + PDC_MAPPING_CHANGE = 0x100, + PDC_RESOLUTION = 0x200, + PDC_ORIGIN = 0x400, + PDC_MODE_ASPECTRATIOPRESERVED = 0x800 + } + + public enum InputType + { + NONE = 0x00000000, + POINTER = 0x00000001, + TOUCH = 0x00000002, + PEN = 0x00000003, + MOUSE = 0x00000004, + TOUCHPAD = 0x00000005 + } + public enum WindowsMessage : uint { WM_NULL = 0x0000, @@ -689,6 +716,25 @@ namespace Avalonia.Win32.Interop WM_EXITSIZEMOVE = 0x0232, WM_DROPFILES = 0x0233, WM_MDIREFRESHMENU = 0x0234, + + WM_POINTERDEVICECHANGE = 0x0238, + WM_POINTERDEVICEINRANGE = 0x239, + WM_POINTERDEVICEOUTOFRANGE = 0x23A, + WM_NCPOINTERUPDATE = 0x0241, + WM_NCPOINTERDOWN = 0x0242, + WM_NCPOINTERUP = 0x0243, + WM_POINTERUPDATE = 0x0245, + WM_POINTERDOWN = 0x0246, + WM_POINTERUP = 0x0247, + WM_POINTERENTER = 0x0249, + WM_POINTERLEAVE = 0x024A, + WM_POINTERACTIVATE = 0x024B, + WM_POINTERCAPTURECHANGED = 0x024C, + WM_TOUCHHITTESTING = 0x024D, + WM_POINTERWHEEL = 0x024E, + WM_POINTERHWHEEL = 0x024F, + WM_POINTERHITTEST = 0x0250, + WM_IME_SETCONTEXT = 0x0281, WM_IME_NOTIFY = 0x0282, WM_IME_CONTROL = 0x0283, @@ -903,6 +949,24 @@ namespace Avalonia.Win32.Interop public const int SizeOf_BITMAPINFOHEADER = 40; + [DllImport("user32.dll", SetLastError = true)] + public static extern int EnableMouseInPointer(bool enable); + + [DllImport("user32.dll", SetLastError = true)] + public static extern bool GetPointerCursorId(uint pointerID, out uint cursorId); + + [DllImport("user32.dll", SetLastError = true)] + public static extern bool GetPointerType(uint pointerID, out InputType pointerType); + + [DllImport("user32.dll", SetLastError = true)] + public static extern void GetUnpredictedMessagePos(); + + [DllImport("user32.dll", SetLastError = true)] + public static extern bool IsMouseInPointerEnabled(); + + [DllImport("user32.dll", SetLastError = true)] + public static extern bool SkipPointerFrameMessages(uint pointerID); + [DllImport("user32.dll")] public static extern bool EnumDisplayMonitors(IntPtr hdc, IntPtr lprcClip, MonitorEnumDelegate lpfnEnum, IntPtr dwData); diff --git a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs index 88a0744e3e..e16901af2c 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs @@ -166,6 +166,10 @@ namespace Avalonia.Win32 case WindowsMessage.WM_MBUTTONDOWN: case WindowsMessage.WM_XBUTTONDOWN: { + if (BelowWin8) + { + break; + } shouldTakeFocus = ShouldTakeFocusOnClick; if (ShouldIgnoreTouchEmulatedMessage()) { @@ -195,6 +199,10 @@ namespace Avalonia.Win32 case WindowsMessage.WM_MBUTTONUP: case WindowsMessage.WM_XBUTTONUP: { + if (BelowWin8) + { + break; + } if (ShouldIgnoreTouchEmulatedMessage()) { break; @@ -219,11 +227,19 @@ namespace Avalonia.Win32 } // Mouse capture is lost case WindowsMessage.WM_CANCELMODE: + if (BelowWin8) + { + break; + } _mouseDevice.Capture(null); break; case WindowsMessage.WM_MOUSEMOVE: { + if (BelowWin8) + { + break; + } if (ShouldIgnoreTouchEmulatedMessage()) { break; @@ -254,6 +270,10 @@ namespace Avalonia.Win32 case WindowsMessage.WM_MOUSEWHEEL: { + if (BelowWin8) + { + break; + } e = new RawMouseWheelEventArgs( _mouseDevice, timestamp, @@ -265,6 +285,10 @@ namespace Avalonia.Win32 case WindowsMessage.WM_MOUSEHWHEEL: { + if (BelowWin8) + { + break; + } e = new RawMouseWheelEventArgs( _mouseDevice, timestamp, @@ -276,6 +300,10 @@ namespace Avalonia.Win32 case WindowsMessage.WM_MOUSELEAVE: { + if (BelowWin8) + { + break; + } _trackingMouse = false; e = new RawPointerEventArgs( _mouseDevice, @@ -291,6 +319,10 @@ namespace Avalonia.Win32 case WindowsMessage.WM_NCMBUTTONDOWN: case WindowsMessage.WM_NCXBUTTONDOWN: { + if (BelowWin8) + { + break; + } e = new RawPointerEventArgs( _mouseDevice, timestamp, @@ -311,6 +343,10 @@ namespace Avalonia.Win32 } case WindowsMessage.WM_TOUCH: { + if (BelowWin8) + { + break; + } var touchInputCount = wParam.ToInt32(); var pTouchInputs = stackalloc TOUCHINPUT[touchInputCount]; @@ -338,6 +374,117 @@ namespace Avalonia.Win32 break; } + + + + + + + + + + + + case WindowsMessage.WM_POINTERDEVICECHANGE: + case WindowsMessage.WM_POINTERDEVICEINRANGE: + case WindowsMessage.WM_POINTERDEVICEOUTOFRANGE: + { + + break; + } + case WindowsMessage.WM_NCPOINTERUPDATE: + case WindowsMessage.WM_NCPOINTERDOWN: + case WindowsMessage.WM_NCPOINTERUP: + { + + break; + } + case WindowsMessage.WM_POINTERUPDATE: + case WindowsMessage.WM_POINTERDOWN: + case WindowsMessage.WM_POINTERUP: + { + + break; + } + case WindowsMessage.WM_POINTERENTER: + case WindowsMessage.WM_POINTERLEAVE: + { + + break; + } + case WindowsMessage.WM_POINTERACTIVATE: + case WindowsMessage.WM_POINTERCAPTURECHANGED: + { + + break; + } + case WindowsMessage.WM_TOUCHHITTESTING: + { + + break; + } + case WindowsMessage.WM_POINTERWHEEL: + { + var pointerId = ToPointerId(wParam); + GetPointerType(pointerId, out var type); + IInputDevice device = _mouseDevice; + switch (type) + { + case InputType.PEN: + + break; + case InputType.TOUCH: + device = _touchDevice; + break; + case InputType.TOUCHPAD: + + break; + } + + + var delta = GetWheelDelta(wParam); + var point = PointFromLParam(lParam); + e = new RawMouseWheelEventArgs( + _mouseDevice, + timestamp, + _owner, + PointToClient(point), + new Vector(0, delta / wheelDelta), + GetMouseModifiers(wParam)); + break; + } + case WindowsMessage.WM_POINTERHWHEEL: + { + + break; + } + case WindowsMessage.WM_POINTERHITTEST: + { + + break; + } + + + + + + + + + + + + + + + + + + + + + + case WindowsMessage.WM_NCPAINT: { if (!HasFullDecorations) @@ -540,6 +687,14 @@ namespace Avalonia.Win32 } } + public static uint GetWheelDelta(IntPtr wParam) => HIWORD(wParam); + public static uint ToPointerId(IntPtr wParam) => LOWORD(wParam); + public static uint LOWORD(IntPtr param) => (uint)param & 0xffff; + public static uint HIWORD(IntPtr param) => (uint)param >> 16; + + + public bool BelowWin8 => Win32Platform.WindowsVersion < PlatformConstants.Windows8; + private void UpdateInputMethod(IntPtr hkl) { // note: for non-ime language, also create it so that emoji panel tracks cursor From 44fda62a9b93cb0f3f6c0096cbfc654f378ab919 Mon Sep 17 00:00:00 2001 From: Sergey Mikolaytis Date: Sat, 22 Jan 2022 16:56:47 +0300 Subject: [PATCH 02/78] Add PointerInfo, TouchInfo and PenInfo --- src/Avalonia.Input/ITouchPadDevice.cs | 10 - src/Avalonia.Input/TouchPadDevice.cs | 488 ------------------ .../Interop/UnmanagedMethods.cs | 166 +++++- .../Avalonia.Win32/WindowImpl.AppWndProc.cs | 14 +- src/Windows/Avalonia.Win32/WindowImpl.cs | 2 + 5 files changed, 159 insertions(+), 521 deletions(-) delete mode 100644 src/Avalonia.Input/ITouchPadDevice.cs delete mode 100644 src/Avalonia.Input/TouchPadDevice.cs diff --git a/src/Avalonia.Input/ITouchPadDevice.cs b/src/Avalonia.Input/ITouchPadDevice.cs deleted file mode 100644 index ea6c57f948..0000000000 --- a/src/Avalonia.Input/ITouchPadDevice.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Avalonia.Input -{ - /// - /// Represents a touch pad device. - /// - public interface ITouchPadDevice : IPointerDevice - { - - } -} diff --git a/src/Avalonia.Input/TouchPadDevice.cs b/src/Avalonia.Input/TouchPadDevice.cs deleted file mode 100644 index fcd254f588..0000000000 --- a/src/Avalonia.Input/TouchPadDevice.cs +++ /dev/null @@ -1,488 +0,0 @@ -using System; -using System.Linq; -using System.Reactive.Linq; -using Avalonia.Input.Raw; -using Avalonia.Interactivity; -using Avalonia.Platform; -using Avalonia.VisualTree; - -namespace Avalonia.Input -{ - /// - /// Represents a touch pad device. - /// - public class TouchPadDevice : ITouchPadDevice, IDisposable - { - private int _clickCount; - private Rect _lastClickRect; - private ulong _lastClickTime; - - private readonly Pointer _pointer; - private bool _disposed; - private PixelPoint? _position; - - public TouchPadDevice(Pointer? pointer = null) - { - _pointer = pointer ?? new Pointer(Pointer.GetNextFreeId(), PointerType.Mouse, true); - } - - /// - /// Gets the control that is currently capturing by the mouse, if any. - /// - /// - /// When an element captures the mouse, it receives mouse input whether the cursor is - /// within the control's bounds or not. To set the mouse capture, call the - /// method. - /// - [Obsolete("Use IPointer instead")] - public IInputElement? Captured => _pointer.Captured; - - /// - /// Gets the mouse position, in screen coordinates. - /// - [Obsolete("Use events instead")] - public PixelPoint Position - { - get => _position ?? new PixelPoint(-1, -1); - protected set => _position = value; - } - - /// - /// Captures mouse input to the specified control. - /// - /// The control. - /// - /// When an element captures the mouse, it receives mouse input whether the cursor is - /// within the control's bounds or not. The current mouse capture control is exposed - /// by the property. - /// - public void Capture(IInputElement? control) - { - _pointer.Capture(control); - } - - /// - /// Gets the mouse position relative to a control. - /// - /// The control. - /// The mouse position in the control's coordinates. - public Point GetPosition(IVisual relativeTo) - { - relativeTo = relativeTo ?? throw new ArgumentNullException(nameof(relativeTo)); - - if (relativeTo.VisualRoot == null) - { - throw new InvalidOperationException("Control is not attached to visual tree."); - } - -#pragma warning disable CS0618 // Type or member is obsolete - var rootPoint = relativeTo.VisualRoot.PointToClient(Position); -#pragma warning restore CS0618 // Type or member is obsolete - var transform = relativeTo.VisualRoot.TransformToVisual(relativeTo); - return rootPoint * transform!.Value; - } - - public void ProcessRawEvent(RawInputEventArgs e) - { - if (!e.Handled && e is RawPointerEventArgs margs) - ProcessRawEvent(margs); - } - - public void TopLevelClosed(IInputRoot root) - { - ClearPointerOver(this, 0, root, PointerPointProperties.None, KeyModifiers.None); - } - - public void SceneInvalidated(IInputRoot root, Rect rect) - { - // Pointer is outside of the target area - if (_position == null ) - { - if (root.PointerOverElement != null) - ClearPointerOver(this, 0, root, PointerPointProperties.None, KeyModifiers.None); - return; - } - - - var clientPoint = root.PointToClient(_position.Value); - - if (rect.Contains(clientPoint)) - { - if (_pointer.Captured == null) - { - SetPointerOver(this, 0 /* TODO: proper timestamp */, root, clientPoint, - PointerPointProperties.None, KeyModifiers.None); - } - else - { - SetPointerOver(this, 0 /* TODO: proper timestamp */, root, _pointer.Captured, - PointerPointProperties.None, KeyModifiers.None); - } - } - } - - int ButtonCount(PointerPointProperties props) - { - var rv = 0; - if (props.IsLeftButtonPressed) - rv++; - if (props.IsMiddleButtonPressed) - rv++; - if (props.IsRightButtonPressed) - rv++; - if (props.IsXButton1Pressed) - rv++; - if (props.IsXButton2Pressed) - rv++; - return rv; - } - - private void ProcessRawEvent(RawPointerEventArgs e) - { - e = e ?? throw new ArgumentNullException(nameof(e)); - - var mouse = (TouchPadDevice)e.Device; - if(mouse._disposed) - return; - - _position = e.Root.PointToScreen(e.Position); - var props = CreateProperties(e); - var keyModifiers = KeyModifiersUtils.ConvertToKey(e.InputModifiers); - switch (e.Type) - { - case RawPointerEventType.LeaveWindow: - LeaveWindow(mouse, e.Timestamp, e.Root, props, keyModifiers); - break; - case RawPointerEventType.LeftButtonDown: - case RawPointerEventType.RightButtonDown: - case RawPointerEventType.MiddleButtonDown: - case RawPointerEventType.XButton1Down: - case RawPointerEventType.XButton2Down: - if (ButtonCount(props) > 1) - e.Handled = MouseMove(mouse, e.Timestamp, e.Root, e.Position, props, keyModifiers); - else - e.Handled = MouseDown(mouse, e.Timestamp, e.Root, e.Position, - props, keyModifiers); - break; - case RawPointerEventType.LeftButtonUp: - case RawPointerEventType.RightButtonUp: - case RawPointerEventType.MiddleButtonUp: - case RawPointerEventType.XButton1Up: - case RawPointerEventType.XButton2Up: - if (ButtonCount(props) != 0) - e.Handled = MouseMove(mouse, e.Timestamp, e.Root, e.Position, props, keyModifiers); - else - e.Handled = MouseUp(mouse, e.Timestamp, e.Root, e.Position, props, keyModifiers); - break; - case RawPointerEventType.Move: - e.Handled = MouseMove(mouse, e.Timestamp, e.Root, e.Position, props, keyModifiers); - break; - case RawPointerEventType.Wheel: - e.Handled = MouseWheel(mouse, e.Timestamp, e.Root, e.Position, props, ((RawMouseWheelEventArgs)e).Delta, keyModifiers); - break; - } - } - - private void LeaveWindow(ITouchPadDevice device, ulong timestamp, IInputRoot root, PointerPointProperties properties, - KeyModifiers inputModifiers) - { - device = device ?? throw new ArgumentNullException(nameof(device)); - root = root ?? throw new ArgumentNullException(nameof(root)); - - _position = null; - ClearPointerOver(this, timestamp, root, properties, inputModifiers); - } - - - PointerPointProperties CreateProperties(RawPointerEventArgs args) - { - - var kind = PointerUpdateKind.Other; - - if (args.Type == RawPointerEventType.LeftButtonDown) - kind = PointerUpdateKind.LeftButtonPressed; - if (args.Type == RawPointerEventType.MiddleButtonDown) - kind = PointerUpdateKind.MiddleButtonPressed; - if (args.Type == RawPointerEventType.RightButtonDown) - kind = PointerUpdateKind.RightButtonPressed; - if (args.Type == RawPointerEventType.XButton1Down) - kind = PointerUpdateKind.XButton1Pressed; - if (args.Type == RawPointerEventType.XButton2Down) - kind = PointerUpdateKind.XButton2Pressed; - if (args.Type == RawPointerEventType.LeftButtonUp) - kind = PointerUpdateKind.LeftButtonReleased; - if (args.Type == RawPointerEventType.MiddleButtonUp) - kind = PointerUpdateKind.MiddleButtonReleased; - if (args.Type == RawPointerEventType.RightButtonUp) - kind = PointerUpdateKind.RightButtonReleased; - if (args.Type == RawPointerEventType.XButton1Up) - kind = PointerUpdateKind.XButton1Released; - if (args.Type == RawPointerEventType.XButton2Up) - kind = PointerUpdateKind.XButton2Released; - - return new PointerPointProperties(args.InputModifiers, kind); - } - - private MouseButton _lastMouseDownButton; - private bool MouseDown(ITouchPadDevice device, ulong timestamp, IInputElement root, Point p, - PointerPointProperties properties, - KeyModifiers inputModifiers) - { - device = device ?? throw new ArgumentNullException(nameof(device)); - root = root ?? throw new ArgumentNullException(nameof(root)); - - var hit = HitTest(root, p); - - if (hit != null) - { - _pointer.Capture(hit); - var source = GetSource(hit); - if (source != null) - { - var settings = AvaloniaLocator.Current.GetService(); - var doubleClickTime = settings?.DoubleClickTime.TotalMilliseconds ?? 500; - var doubleClickSize = settings?.DoubleClickSize ?? new Size(4, 4); - - if (!_lastClickRect.Contains(p) || timestamp - _lastClickTime > doubleClickTime) - { - _clickCount = 0; - } - - ++_clickCount; - _lastClickTime = timestamp; - _lastClickRect = new Rect(p, new Size()) - .Inflate(new Thickness(doubleClickSize.Width / 2, doubleClickSize.Height / 2)); - _lastMouseDownButton = properties.PointerUpdateKind.GetMouseButton(); - var e = new PointerPressedEventArgs(source, _pointer, root, p, timestamp, properties, inputModifiers, _clickCount); - source.RaiseEvent(e); - return e.Handled; - } - } - - return false; - } - - private bool MouseMove(ITouchPadDevice device, ulong timestamp, IInputRoot root, Point p, PointerPointProperties properties, - KeyModifiers inputModifiers) - { - device = device ?? throw new ArgumentNullException(nameof(device)); - root = root ?? throw new ArgumentNullException(nameof(root)); - - IInputElement? source; - - if (_pointer.Captured == null) - { - source = SetPointerOver(this, timestamp, root, p, properties, inputModifiers); - } - else - { - SetPointerOver(this, timestamp, root, _pointer.Captured, properties, inputModifiers); - source = _pointer.Captured; - } - - if (source is object) - { - var e = new PointerEventArgs(InputElement.PointerMovedEvent, source, _pointer, root, - p, timestamp, properties, inputModifiers); - - source.RaiseEvent(e); - return e.Handled; - } - - return false; - } - - private bool MouseUp(ITouchPadDevice device, ulong timestamp, IInputRoot root, Point p, PointerPointProperties props, - KeyModifiers inputModifiers) - { - device = device ?? throw new ArgumentNullException(nameof(device)); - root = root ?? throw new ArgumentNullException(nameof(root)); - - var hit = HitTest(root, p); - var source = GetSource(hit); - - if (source is not null) - { - var e = new PointerReleasedEventArgs(source, _pointer, root, p, timestamp, props, inputModifiers, - _lastMouseDownButton); - - source?.RaiseEvent(e); - _pointer.Capture(null); - return e.Handled; - } - - return false; - } - - private bool MouseWheel(ITouchPadDevice device, ulong timestamp, IInputRoot root, Point p, - PointerPointProperties props, - Vector delta, KeyModifiers inputModifiers) - { - device = device ?? throw new ArgumentNullException(nameof(device)); - root = root ?? throw new ArgumentNullException(nameof(root)); - - var hit = HitTest(root, p); - var source = GetSource(hit); - - if (source is not null) - { - var e = new PointerWheelEventArgs(source, _pointer, root, p, timestamp, props, inputModifiers, delta); - - source?.RaiseEvent(e); - return e.Handled; - } - - return false; - } - - private IInteractive? GetSource(IVisual? hit) - { - if (hit is null) - return null; - - return _pointer.Captured ?? - (hit as IInteractive) ?? - hit.GetSelfAndVisualAncestors().OfType().FirstOrDefault(); - } - - private IInputElement? HitTest(IInputElement root, Point p) - { - root = root ?? throw new ArgumentNullException(nameof(root)); - - return _pointer.Captured ?? root.InputHitTest(p); - } - - PointerEventArgs CreateSimpleEvent(RoutedEvent ev, ulong timestamp, IInteractive? source, - PointerPointProperties properties, - KeyModifiers inputModifiers) - { - return new PointerEventArgs(ev, source, _pointer, null, default, - timestamp, properties, inputModifiers); - } - - private void ClearPointerOver(IPointerDevice device, ulong timestamp, IInputRoot root, - PointerPointProperties properties, - KeyModifiers inputModifiers) - { - device = device ?? throw new ArgumentNullException(nameof(device)); - root = root ?? throw new ArgumentNullException(nameof(root)); - - var element = root.PointerOverElement; - var e = CreateSimpleEvent(InputElement.PointerLeaveEvent, timestamp, element, properties, inputModifiers); - - if (element!=null && !element.IsAttachedToVisualTree) - { - // element has been removed from visual tree so do top down cleanup - if (root.IsPointerOver) - ClearChildrenPointerOver(e, root,true); - } - while (element != null) - { - e.Source = element; - e.Handled = false; - element.RaiseEvent(e); - element = (IInputElement?)element.VisualParent; - } - - root.PointerOverElement = null; - } - - private void ClearChildrenPointerOver(PointerEventArgs e, IInputElement element,bool clearRoot) - { - foreach (IInputElement el in element.VisualChildren) - { - if (el.IsPointerOver) - { - ClearChildrenPointerOver(e, el, true); - break; - } - } - if(clearRoot) - { - e.Source = element; - e.Handled = false; - element.RaiseEvent(e); - } - } - - private IInputElement? SetPointerOver(IPointerDevice device, ulong timestamp, IInputRoot root, Point p, - PointerPointProperties properties, - KeyModifiers inputModifiers) - { - device = device ?? throw new ArgumentNullException(nameof(device)); - root = root ?? throw new ArgumentNullException(nameof(root)); - - var element = root.InputHitTest(p); - - if (element != root.PointerOverElement) - { - if (element != null) - { - SetPointerOver(device, timestamp, root, element, properties, inputModifiers); - } - else - { - ClearPointerOver(device, timestamp, root, properties, inputModifiers); - } - } - - return element; - } - - private void SetPointerOver(IPointerDevice device, ulong timestamp, IInputRoot root, IInputElement element, - PointerPointProperties properties, - KeyModifiers inputModifiers) - { - device = device ?? throw new ArgumentNullException(nameof(device)); - root = root ?? throw new ArgumentNullException(nameof(root)); - element = element ?? throw new ArgumentNullException(nameof(element)); - - IInputElement? branch = null; - - IInputElement? el = element; - - while (el != null) - { - if (el.IsPointerOver) - { - branch = el; - break; - } - el = (IInputElement?)el.VisualParent; - } - - el = root.PointerOverElement; - - var e = CreateSimpleEvent(InputElement.PointerLeaveEvent, timestamp, el, properties, inputModifiers); - if (el!=null && branch!=null && !el.IsAttachedToVisualTree) - { - ClearChildrenPointerOver(e,branch,false); - } - - while (el != null && el != branch) - { - e.Source = el; - e.Handled = false; - el.RaiseEvent(e); - el = (IInputElement?)el.VisualParent; - } - - el = root.PointerOverElement = element; - e.RoutedEvent = InputElement.PointerEnterEvent; - - while (el != null && el != branch) - { - e.Source = el; - e.Handled = false; - el.RaiseEvent(e); - el = (IInputElement?)el.VisualParent; - } - } - - public void Dispose() - { - _disposed = true; - _pointer?.Dispose(); - } - } -} diff --git a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs index db81e8197f..5aecd8e8f0 100644 --- a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs +++ b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs @@ -225,20 +225,17 @@ namespace Avalonia.Win32.Interop [Flags] public enum ModifierKeys { - MK_CONTROL = 0x0008, + MK_NONE = 0x0001, MK_LBUTTON = 0x0001, - - MK_MBUTTON = 0x0010, - MK_RBUTTON = 0x0002, - MK_SHIFT = 0x0004, - - MK_ALT = 0x0020, + MK_SHIFT = 0x0004, + MK_CONTROL = 0x0008, + MK_MBUTTON = 0x0010, + MK_ALT = 0x0020, MK_XBUTTON1 = 0x0020, - MK_XBUTTON2 = 0x0040 } @@ -531,14 +528,14 @@ namespace Avalonia.Win32.Interop PDC_MODE_ASPECTRATIOPRESERVED = 0x800 } - public enum InputType + public enum PointerInputType { - NONE = 0x00000000, - POINTER = 0x00000001, - TOUCH = 0x00000002, - PEN = 0x00000003, - MOUSE = 0x00000004, - TOUCHPAD = 0x00000005 + PT_NONE = 0x00000000, + PT_POINTER = 0x00000001, + PT_TOUCH = 0x00000002, + PT_PEN = 0x00000003, + PT_MOUSE = 0x00000004, + PT_TOUCHPAD = 0x00000005 } public enum WindowsMessage : uint @@ -882,6 +879,134 @@ namespace Avalonia.Win32.Interop SCF_ISSECURE = 0x00000001, } + [Flags] + public enum PointerFlags + { + POINTER_FLAG_NONE = 0x00000000, + POINTER_FLAG_NEW = 0x00000001, + POINTER_FLAG_INRANGE = 0x00000002, + POINTER_FLAG_INCONTACT = 0x00000004, + POINTER_FLAG_FIRSTBUTTON = 0x00000010, + POINTER_FLAG_SECONDBUTTON = 0x00000020, + POINTER_FLAG_THIRDBUTTON = 0x00000040, + POINTER_FLAG_FOURTHBUTTON = 0x00000080, + POINTER_FLAG_FIFTHBUTTON = 0x00000100, + POINTER_FLAG_PRIMARY = 0x00002000, + POINTER_FLAG_CONFIDENCE = 0x00000400, + POINTER_FLAG_CANCELED = 0x00000800, + POINTER_FLAG_DOWN = 0x00010000, + POINTER_FLAG_UPDATE = 0x00020000, + POINTER_FLAG_UP = 0x00040000, + POINTER_FLAG_WHEEL = 0x00080000, + POINTER_FLAG_HWHEEL = 0x00100000, + POINTER_FLAG_CAPTURECHANGED = 0x00200000, + POINTER_FLAG_HASTRANSFORM = 0x00400000 + } + + public enum PointerButtonChangeType : ulong + { + POINTER_CHANGE_NONE, + POINTER_CHANGE_FIRSTBUTTON_DOWN, + POINTER_CHANGE_FIRSTBUTTON_UP, + POINTER_CHANGE_SECONDBUTTON_DOWN, + POINTER_CHANGE_SECONDBUTTON_UP, + POINTER_CHANGE_THIRDBUTTON_DOWN, + POINTER_CHANGE_THIRDBUTTON_UP, + POINTER_CHANGE_FOURTHBUTTON_DOWN, + POINTER_CHANGE_FOURTHBUTTON_UP, + POINTER_CHANGE_FIFTHBUTTON_DOWN, + POINTER_CHANGE_FIFTHBUTTON_UP + } + + [Flags] + public enum PenFlags + { + PEN_FLAGS_NONE = 0x00000000, + PEN_FLAGS_BARREL = 0x00000001, + PEN_FLAGS_INVERTED = 0x00000002, + PEN_FLAGS_ERASER = 0x00000004, + } + + [Flags] + public enum PenMask + { + PEN_MASK_NONE = 0x00000000, + PEN_MASK_PRESSURE = 0x00000001, + PEN_MASK_ROTATION = 0x00000002, + PEN_MASK_TILT_X = 0x00000004, + PEN_MASK_TILT_Y = 0x00000008 + } + + [Flags] + public enum TouchFlags + { + TOUCH_FLAG_NONE = 0x00000000 + } + + [Flags] + public enum TouchMask + { + TOUCH_MASK_NONE = 0x00000000, + TOUCH_MASK_CONTACTAREA = 0x00000001, + TOUCH_MASK_ORIENTATION = 0x00000002, + TOUCH_MASK_PRESSURE = 0x00000004, + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct POINTER_TOUCH_INFO + { + public POINTER_INFO pointerInfo; + public TouchFlags touchFlags; + public TouchMask touchMask; + public int rcContactLeft; + public int rcContactTop; + public int rcContactRight; + public int rcContactBottom; + public int rcContactRawLeft; + public int rcContactRawTop; + public int rcContactRawRight; + public int rcContactRawBottom; + public uint orientation; + public uint pressure; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct POINTER_PEN_INFO + { + public POINTER_INFO pointerInfo; + public PenFlags penFlags; + public PenMask penMask; + public uint pressure; + public uint rotation; + public int tiltX; + public int tiltY; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct POINTER_INFO + { + public PointerInputType pointerType; + public uint pointerId; + public uint frameId; + public PointerFlags pointerFlags; + public IntPtr sourceDevice; + public IntPtr hwndTarget; + public int ptPixelLocationX; + public int ptPixelLocationY; + public int ptHimetricLocationX; + public int ptHimetricLocationY; + public int ptPixelLocationRawX; + public int ptPixelLocationRawY; + public int ptHimetricLocationRawX; + public int ptHimetricLocationRawY; + public uint dwTime; + public uint historyCount; + public int inputData; + public ModifierKeys dwKeyStates; + public UInt64 PerformanceCount; + public PointerButtonChangeType ButtonChangeType; + } + [StructLayout(LayoutKind.Sequential)] public struct RGBQUAD { @@ -956,7 +1081,16 @@ namespace Avalonia.Win32.Interop public static extern bool GetPointerCursorId(uint pointerID, out uint cursorId); [DllImport("user32.dll", SetLastError = true)] - public static extern bool GetPointerType(uint pointerID, out InputType pointerType); + public static extern bool GetPointerType(uint pointerID, out PointerInputType pointerType); + + [DllImport("User32.dll", SetLastError = true)] + public static extern bool GetPointerInfo(uint pointerID, out POINTER_INFO pointerInfo); + + [DllImport("User32.dll", SetLastError = true)] + public static extern bool GetPointerPenInfo(uint pointerID, out POINTER_PEN_INFO penInfo); + + [DllImport("User32.dll", SetLastError = true)] + public static extern bool GetPointerTouchInfo(uint pointerID, out POINTER_TOUCH_INFO touchInfo); [DllImport("user32.dll", SetLastError = true)] public static extern void GetUnpredictedMessagePos(); diff --git a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs index e16901af2c..8a0654a9ba 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs @@ -427,17 +427,17 @@ namespace Avalonia.Win32 { var pointerId = ToPointerId(wParam); GetPointerType(pointerId, out var type); - IInputDevice device = _mouseDevice; + IInputDevice device; switch (type) { - case InputType.PEN: - + case PointerInputType.PT_PEN: + device = _penDevice; break; - case InputType.TOUCH: + case PointerInputType.PT_TOUCH: device = _touchDevice; break; - case InputType.TOUCHPAD: - + default: + device = _mouseDevice; break; } @@ -445,7 +445,7 @@ namespace Avalonia.Win32 var delta = GetWheelDelta(wParam); var point = PointFromLParam(lParam); e = new RawMouseWheelEventArgs( - _mouseDevice, + device, timestamp, _owner, PointToClient(point), diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index e4f5268285..8f6a7e9741 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -64,6 +64,7 @@ namespace Avalonia.Win32 private const WindowStyles WindowStateMask = (WindowStyles.WS_MAXIMIZE | WindowStyles.WS_MINIMIZE); private readonly TouchDevice _touchDevice; private readonly MouseDevice _mouseDevice; + private readonly PenDevice _penDevice; private readonly ManagedDeferredRendererLock _rendererLock; private readonly FramebufferManager _framebuffer; private readonly IGlPlatformSurface _gl; @@ -96,6 +97,7 @@ namespace Avalonia.Win32 { _touchDevice = new TouchDevice(); _mouseDevice = new WindowsMouseDevice(); + _penDevice = new PenDevice(); #if USE_MANAGED_DRAG _managedDrag = new ManagedWindowResizeDragHelper(this, capture => From 1192e86d90f0d6f4df29acc442a21031e7fb0c3e Mon Sep 17 00:00:00 2001 From: Sergey Mikolaytis Date: Sat, 22 Jan 2022 18:39:36 +0300 Subject: [PATCH 03/78] Investigate all the messages and note short comments about them and provide a link to a documentation. In case anyone will need this in the future --- .../Interop/UnmanagedMethods.cs | 2 +- .../Avalonia.Win32/WindowImpl.AppWndProc.cs | 139 ++++++++++++------ src/Windows/Avalonia.Win32/WindowImpl.cs | 2 +- 3 files changed, 99 insertions(+), 44 deletions(-) diff --git a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs index 5aecd8e8f0..93457f7bbd 100644 --- a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs +++ b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs @@ -730,7 +730,7 @@ namespace Avalonia.Win32.Interop WM_TOUCHHITTESTING = 0x024D, WM_POINTERWHEEL = 0x024E, WM_POINTERHWHEEL = 0x024F, - WM_POINTERHITTEST = 0x0250, + DM_POINTERHITTEST = 0x0250, WM_IME_SETCONTEXT = 0x0281, WM_IME_NOTIFY = 0x0282, diff --git a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs index 8a0654a9ba..3587eddc85 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs @@ -227,10 +227,6 @@ namespace Avalonia.Win32 } // Mouse capture is lost case WindowsMessage.WM_CANCELMODE: - if (BelowWin8) - { - break; - } _mouseDevice.Capture(null); break; @@ -263,7 +259,8 @@ namespace Avalonia.Win32 timestamp, _owner, RawPointerEventType.Move, - DipFromLParam(lParam), GetMouseModifiers(wParam)); + DipFromLParam(lParam), + GetMouseModifiers(wParam)); break; } @@ -279,7 +276,8 @@ namespace Avalonia.Win32 timestamp, _owner, PointToClient(PointFromLParam(lParam)), - new Vector(0, (ToInt32(wParam) >> 16) / wheelDelta), GetMouseModifiers(wParam)); + new Vector(0, (ToInt32(wParam) >> 16) / wheelDelta), + GetMouseModifiers(wParam)); break; } @@ -294,7 +292,8 @@ namespace Avalonia.Win32 timestamp, _owner, PointToClient(PointFromLParam(lParam)), - new Vector(-(ToInt32(wParam) >> 16) / wheelDelta, 0), GetMouseModifiers(wParam)); + new Vector(-(ToInt32(wParam) >> 16) / wheelDelta, 0), + GetMouseModifiers(wParam)); break; } @@ -310,7 +309,8 @@ namespace Avalonia.Win32 timestamp, _owner, RawPointerEventType.LeaveWindow, - new Point(-1, -1), WindowsKeyboardDevice.Instance.Modifiers); + new Point(-1, -1), + WindowsKeyboardDevice.Instance.Modifiers); break; } @@ -386,16 +386,24 @@ namespace Avalonia.Win32 case WindowsMessage.WM_POINTERDEVICECHANGE: + { + //notifies about changes in the settings of a monitor that has a digitizer attached to it. + //https://docs.microsoft.com/en-us/previous-versions/windows/desktop/inputmsg/wm-pointerdevicechange + break; + } case WindowsMessage.WM_POINTERDEVICEINRANGE: case WindowsMessage.WM_POINTERDEVICEOUTOFRANGE: { - + //notifies about proximity of pointer device to the digitizer. + //contains pointer id and proximity. + //https://docs.microsoft.com/en-us/previous-versions/windows/desktop/inputmsg/wm-pointerdeviceinrange break; } case WindowsMessage.WM_NCPOINTERUPDATE: case WindowsMessage.WM_NCPOINTERDOWN: case WindowsMessage.WM_NCPOINTERUP: { + //NC stands for non-client area - window header and window border break; } @@ -407,60 +415,79 @@ namespace Avalonia.Win32 break; } case WindowsMessage.WM_POINTERENTER: - case WindowsMessage.WM_POINTERLEAVE: { + //this is not handled by WM_MOUSEENTER so I think there is no need to handle this too. + //but we can detect a new pointer by this message and calling IS_POINTER_NEW_WPARAM + //note: by using a pen there can be a pointer leave or enter inside a window coords + //when you are just lift up the pen above the display break; } - case WindowsMessage.WM_POINTERACTIVATE: - case WindowsMessage.WM_POINTERCAPTURECHANGED: + case WindowsMessage.WM_POINTERLEAVE: { + GetDeviceInfo(wParam, out var device, out var info); + var point = PointToClient(PointFromLParam(lParam)); + e = new RawPointerEventArgs( + device, + timestamp, + _owner, + RawPointerEventType.LeaveWindow, + point, + WindowsKeyboardDevice.Instance.Modifiers); break; } - case WindowsMessage.WM_TOUCHHITTESTING: + case WindowsMessage.WM_POINTERACTIVATE: { - + //occurs when a pointer activates an inactive window. + //we should handle this and return PA_ACTIVATE or PA_NOACTIVATE + //https://docs.microsoft.com/en-us/previous-versions/windows/desktop/inputmsg/wm-pointeractivate break; } + case WindowsMessage.WM_POINTERCAPTURECHANGED: + { + _mouseDevice.Capture(null); + return IntPtr.Zero; + } case WindowsMessage.WM_POINTERWHEEL: { - var pointerId = ToPointerId(wParam); - GetPointerType(pointerId, out var type); - IInputDevice device; - switch (type) - { - case PointerInputType.PT_PEN: - device = _penDevice; - break; - case PointerInputType.PT_TOUCH: - device = _touchDevice; - break; - default: - device = _mouseDevice; - break; - } - + GetDeviceInfo(wParam, out var device, out var info); - var delta = GetWheelDelta(wParam); - var point = PointFromLParam(lParam); - e = new RawMouseWheelEventArgs( - device, - timestamp, - _owner, - PointToClient(point), - new Vector(0, delta / wheelDelta), - GetMouseModifiers(wParam)); + var point = PointToClient(PointFromLParam(lParam)); + var modifiers = GetInputModifiers(info.dwKeyStates); + var delta = new Vector(0, GetWheelDelta(wParam) / wheelDelta); + e = new RawMouseWheelEventArgs(device, timestamp, _owner, point, delta, modifiers); break; } case WindowsMessage.WM_POINTERHWHEEL: { + GetDeviceInfo(wParam, out var device, out var info); + var point = PointToClient(PointFromLParam(lParam)); + var modifiers = GetInputModifiers(info.dwKeyStates); + var delta = new Vector(GetWheelDelta(wParam) / wheelDelta, 0); + e = new RawMouseWheelEventArgs(device, timestamp, _owner, point, delta, modifiers); break; } - case WindowsMessage.WM_POINTERHITTEST: + case WindowsMessage.DM_POINTERHITTEST: { - + //DM stands for direct manipulation. + //https://docs.microsoft.com/en-us/previous-versions/windows/desktop/directmanipulation/direct-manipulation-portal + break; + } + case WindowsMessage.WM_TOUCHHITTESTING: + { + //This is to determine the most probable touch target. + //provides an input bounding box and receives hit proximity + //https://docs.microsoft.com/en-us/previous-versions/windows/desktop/inputmsg/wm-touchhittesting + //https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-touch_hit_testing_input + break; + } + case WindowsMessage.WM_PARENTNOTIFY: + { + //This message is sent in a dialog scenarios. Contains mouse position in an old-way, + //but listed in the wm_pointer reference + //https://docs.microsoft.com/en-us/previous-versions/windows/desktop/inputmsg/wm-parentnotify break; } @@ -687,13 +714,36 @@ namespace Avalonia.Win32 } } + private void GetDeviceInfo(IntPtr wParam, out IInputDevice device, out POINTER_INFO info) + { + var pointerId = ToPointerId(wParam); + GetPointerType(pointerId, out var type);//ToDo we can cache this and invalidate in WM_POINTERDEVICECHANGE + switch (type) + { + case PointerInputType.PT_PEN: + device = _penDevice; + GetPointerPenInfo(pointerId, out var penInfo); + info = penInfo.pointerInfo; + break; + case PointerInputType.PT_TOUCH: + device = _touchDevice; + GetPointerTouchInfo(pointerId, out var touchInfo); + info = touchInfo.pointerInfo; + break; + default: + device = _mouseDevice; + GetPointerInfo(pointerId, out info); + break; + } + } + public static uint GetWheelDelta(IntPtr wParam) => HIWORD(wParam); public static uint ToPointerId(IntPtr wParam) => LOWORD(wParam); public static uint LOWORD(IntPtr param) => (uint)param & 0xffff; public static uint HIWORD(IntPtr param) => (uint)param >> 16; - public bool BelowWin8 => Win32Platform.WindowsVersion < PlatformConstants.Windows8; + public readonly bool BelowWin8 = Win32Platform.WindowsVersion < PlatformConstants.Windows8; private void UpdateInputMethod(IntPtr hkl) { @@ -747,6 +797,11 @@ namespace Avalonia.Win32 private static RawInputModifiers GetMouseModifiers(IntPtr wParam) { var keys = (ModifierKeys)ToInt32(wParam); + return GetInputModifiers(keys); + } + + private static RawInputModifiers GetInputModifiers(ModifierKeys keys) + { var modifiers = WindowsKeyboardDevice.Instance.Modifiers; if (keys.HasAllFlags(ModifierKeys.MK_LBUTTON)) diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 8f6a7e9741..0f99252d4d 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -76,7 +76,7 @@ namespace Avalonia.Win32 private bool _multitouch; private IInputRoot _owner; private WindowProperties _windowProperties; - private bool _trackingMouse; + private bool _trackingMouse;//ToDo - there is something missed. Needs investigation @Steven Kirk private bool _topmost; private double _scaling = 1; private WindowState _showWindowState; From 35a55c9a56dca3ccc957a559e0b50e1aa48fdab0 Mon Sep 17 00:00:00 2001 From: Sergey Mikolaytis Date: Sat, 22 Jan 2022 21:37:54 +0300 Subject: [PATCH 04/78] Enable WM_Pointer for mouse events, handle up/down events, some fixes --- .../Avalonia.Win32/WindowImpl.AppWndProc.cs | 73 +++++++++++++------ src/Windows/Avalonia.Win32/WindowImpl.cs | 5 ++ 2 files changed, 56 insertions(+), 22 deletions(-) diff --git a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs index 3587eddc85..5e31bba925 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs @@ -166,7 +166,7 @@ namespace Avalonia.Win32 case WindowsMessage.WM_MBUTTONDOWN: case WindowsMessage.WM_XBUTTONDOWN: { - if (BelowWin8) + if (Win8Plus) { break; } @@ -199,7 +199,7 @@ namespace Avalonia.Win32 case WindowsMessage.WM_MBUTTONUP: case WindowsMessage.WM_XBUTTONUP: { - if (BelowWin8) + if (Win8Plus) { break; } @@ -232,7 +232,7 @@ namespace Avalonia.Win32 case WindowsMessage.WM_MOUSEMOVE: { - if (BelowWin8) + if (Win8Plus) { break; } @@ -267,7 +267,7 @@ namespace Avalonia.Win32 case WindowsMessage.WM_MOUSEWHEEL: { - if (BelowWin8) + if (Win8Plus) { break; } @@ -283,7 +283,7 @@ namespace Avalonia.Win32 case WindowsMessage.WM_MOUSEHWHEEL: { - if (BelowWin8) + if (Win8Plus) { break; } @@ -299,7 +299,7 @@ namespace Avalonia.Win32 case WindowsMessage.WM_MOUSELEAVE: { - if (BelowWin8) + if (Win8Plus) { break; } @@ -319,7 +319,7 @@ namespace Avalonia.Win32 case WindowsMessage.WM_NCMBUTTONDOWN: case WindowsMessage.WM_NCXBUTTONDOWN: { - if (BelowWin8) + if (Win8Plus) { break; } @@ -343,7 +343,7 @@ namespace Avalonia.Win32 } case WindowsMessage.WM_TOUCH: { - if (BelowWin8) + if (Win8Plus) { break; } @@ -400,18 +400,53 @@ namespace Avalonia.Win32 break; } case WindowsMessage.WM_NCPOINTERUPDATE: - case WindowsMessage.WM_NCPOINTERDOWN: - case WindowsMessage.WM_NCPOINTERUP: { //NC stands for non-client area - window header and window border - + //As I found above in an old message handling - we dont need to handle NC pointer move/updates. + //All we need is pointer down and up. So this is skipped for now. break; } - case WindowsMessage.WM_POINTERUPDATE: + case WindowsMessage.WM_NCPOINTERDOWN: + case WindowsMessage.WM_NCPOINTERUP: case WindowsMessage.WM_POINTERDOWN: case WindowsMessage.WM_POINTERUP: { + GetDeviceInfo(wParam, out var device, out var info); + var point = PointToClient(PointFromLParam(lParam)); + var modifiers = GetInputModifiers(info.dwKeyStates); + var eventType = info.ButtonChangeType switch + { + PointerButtonChangeType.POINTER_CHANGE_FIRSTBUTTON_DOWN => RawPointerEventType.LeftButtonDown, + PointerButtonChangeType.POINTER_CHANGE_SECONDBUTTON_DOWN => RawPointerEventType.RightButtonDown, + PointerButtonChangeType.POINTER_CHANGE_THIRDBUTTON_DOWN => RawPointerEventType.MiddleButtonDown, + PointerButtonChangeType.POINTER_CHANGE_FOURTHBUTTON_DOWN => RawPointerEventType.XButton1Down, + PointerButtonChangeType.POINTER_CHANGE_FIFTHBUTTON_DOWN => RawPointerEventType.XButton2Down, + + PointerButtonChangeType.POINTER_CHANGE_FIRSTBUTTON_UP => RawPointerEventType.LeftButtonUp, + PointerButtonChangeType.POINTER_CHANGE_SECONDBUTTON_UP => RawPointerEventType.RightButtonUp, + PointerButtonChangeType.POINTER_CHANGE_THIRDBUTTON_UP => RawPointerEventType.MiddleButtonUp, + PointerButtonChangeType.POINTER_CHANGE_FOURTHBUTTON_UP => RawPointerEventType.XButton1Up, + PointerButtonChangeType.POINTER_CHANGE_FIFTHBUTTON_UP => RawPointerEventType.XButton2Up, + }; + if (eventType == RawPointerEventType.NonClientLeftButtonDown && + (WindowsMessage)msg == WindowsMessage.WM_NCPOINTERDOWN) + { + eventType = RawPointerEventType.NonClientLeftButtonDown; + } + e = new RawPointerEventArgs(device, timestamp, _owner, eventType, point, modifiers); + break; + } + case WindowsMessage.WM_POINTERUPDATE: + { + if (ShouldIgnoreTouchEmulatedMessage()) + { + break; + } + GetDeviceInfo(wParam, out var device, out var info); + var point = PointToClient(PointFromLParam(lParam)); + var modifiers = GetInputModifiers(info.dwKeyStates); + e = new RawPointerEventArgs(device, timestamp, _owner, RawPointerEventType.Move, point, modifiers); break; } case WindowsMessage.WM_POINTERENTER: @@ -455,7 +490,7 @@ namespace Avalonia.Win32 var point = PointToClient(PointFromLParam(lParam)); var modifiers = GetInputModifiers(info.dwKeyStates); - var delta = new Vector(0, GetWheelDelta(wParam) / wheelDelta); + var delta = new Vector(0, (ToInt32(wParam) >> 16) / wheelDelta); e = new RawMouseWheelEventArgs(device, timestamp, _owner, point, delta, modifiers); break; } @@ -465,7 +500,7 @@ namespace Avalonia.Win32 var point = PointToClient(PointFromLParam(lParam)); var modifiers = GetInputModifiers(info.dwKeyStates); - var delta = new Vector(GetWheelDelta(wParam) / wheelDelta, 0); + var delta = new Vector((ToInt32(wParam) >> 16) / wheelDelta, 0); e = new RawMouseWheelEventArgs(device, timestamp, _owner, point, delta, modifiers); break; } @@ -716,7 +751,7 @@ namespace Avalonia.Win32 private void GetDeviceInfo(IntPtr wParam, out IInputDevice device, out POINTER_INFO info) { - var pointerId = ToPointerId(wParam); + var pointerId = (uint)(ToInt32(wParam) & 0xFFFF); GetPointerType(pointerId, out var type);//ToDo we can cache this and invalidate in WM_POINTERDEVICECHANGE switch (type) { @@ -737,13 +772,7 @@ namespace Avalonia.Win32 } } - public static uint GetWheelDelta(IntPtr wParam) => HIWORD(wParam); - public static uint ToPointerId(IntPtr wParam) => LOWORD(wParam); - public static uint LOWORD(IntPtr param) => (uint)param & 0xffff; - public static uint HIWORD(IntPtr param) => (uint)param >> 16; - - - public readonly bool BelowWin8 = Win32Platform.WindowsVersion < PlatformConstants.Windows8; + public readonly bool Win8Plus = Win32Platform.WindowsVersion >= PlatformConstants.Windows8; private void UpdateInputMethod(IntPtr hkl) { diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 0f99252d4d..0ad198e991 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -126,6 +126,11 @@ namespace Avalonia.Win32 egl.Display is AngleWin32EglDisplay angleDisplay && angleDisplay.PlatformApi == AngleOptions.PlatformApi.DirectX11; + if (Win8Plus && !IsMouseInPointerEnabled()) + { + EnableMouseInPointer(true); + } + CreateWindow(); _framebuffer = new FramebufferManager(_hwnd); UpdateInputMethod(GetKeyboardLayout(0)); From 4cea62fd13701931ba7aedbb2b2f6fce9f9477a6 Mon Sep 17 00:00:00 2001 From: Sergey Mikolaytis Date: Sat, 22 Jan 2022 23:34:43 +0300 Subject: [PATCH 05/78] PenDevice tuning, Add pen properties to the PointerPointProperties --- src/Avalonia.Input/IKeyboardDevice.cs | 2 + src/Avalonia.Input/IPointer.cs | 3 +- src/Avalonia.Input/PenDevice.cs | 134 +++--------------- src/Avalonia.Input/PointerPoint.cs | 30 +++- src/Avalonia.Input/Raw/RawPointerEventArgs.cs | 8 +- .../Avalonia.Win32/WindowImpl.AppWndProc.cs | 64 +++------ 6 files changed, 72 insertions(+), 169 deletions(-) diff --git a/src/Avalonia.Input/IKeyboardDevice.cs b/src/Avalonia.Input/IKeyboardDevice.cs index 9506dc36fb..b3ea7c5f4f 100644 --- a/src/Avalonia.Input/IKeyboardDevice.cs +++ b/src/Avalonia.Input/IKeyboardDevice.cs @@ -47,6 +47,8 @@ namespace Avalonia.Input MiddleMouseButton = 64, XButton1MouseButton = 128, XButton2MouseButton = 256, + BarrelPenButton = 512, + PenEraser = 1024, KeyboardMask = Alt | Control | Shift | Meta } diff --git a/src/Avalonia.Input/IPointer.cs b/src/Avalonia.Input/IPointer.cs index 7af48cef82..361f3ac370 100644 --- a/src/Avalonia.Input/IPointer.cs +++ b/src/Avalonia.Input/IPointer.cs @@ -13,6 +13,7 @@ namespace Avalonia.Input public enum PointerType { Mouse, - Touch + Touch, + Pen } } diff --git a/src/Avalonia.Input/PenDevice.cs b/src/Avalonia.Input/PenDevice.cs index dd3d60ebb9..3c0f3c7709 100644 --- a/src/Avalonia.Input/PenDevice.cs +++ b/src/Avalonia.Input/PenDevice.cs @@ -3,7 +3,6 @@ using System.Linq; using System.Reactive.Linq; using Avalonia.Input.Raw; using Avalonia.Interactivity; -using Avalonia.Platform; using Avalonia.VisualTree; namespace Avalonia.Input @@ -13,17 +12,13 @@ namespace Avalonia.Input /// public class PenDevice : IPenDevice, IDisposable { - private int _clickCount; - private Rect _lastClickRect; - private ulong _lastClickTime; - private readonly Pointer _pointer; private bool _disposed; private PixelPoint? _position; public PenDevice(Pointer? pointer = null) { - _pointer = pointer ?? new Pointer(Pointer.GetNextFreeId(), PointerType.Mouse, true); + _pointer = pointer ?? new Pointer(Pointer.GetNextFreeId(), PointerType.Pen, true); } /// @@ -37,16 +32,6 @@ namespace Avalonia.Input [Obsolete("Use IPointer instead")] public IInputElement? Captured => _pointer.Captured; - /// - /// Gets the mouse position, in screen coordinates. - /// - [Obsolete("Use events instead")] - public PixelPoint Position - { - get => _position ?? new PixelPoint(-1, -1); - protected set => _position = value; - } - /// /// Captures mouse input to the specified control. /// @@ -76,7 +61,7 @@ namespace Avalonia.Input } #pragma warning disable CS0618 // Type or member is obsolete - var rootPoint = relativeTo.VisualRoot.PointToClient(Position); + var rootPoint = relativeTo.VisualRoot.PointToClient(_position ?? new PixelPoint(-1, -1)); #pragma warning restore CS0618 // Type or member is obsolete var transform = relativeTo.VisualRoot.TransformToVisual(relativeTo); return rootPoint * transform!.Value; @@ -120,29 +105,13 @@ namespace Avalonia.Input } } } - - int ButtonCount(PointerPointProperties props) - { - var rv = 0; - if (props.IsLeftButtonPressed) - rv++; - if (props.IsMiddleButtonPressed) - rv++; - if (props.IsRightButtonPressed) - rv++; - if (props.IsXButton1Pressed) - rv++; - if (props.IsXButton2Pressed) - rv++; - return rv; - } private void ProcessRawEvent(RawPointerEventArgs e) { e = e ?? throw new ArgumentNullException(nameof(e)); - var mouse = (PenDevice)e.Device; - if(mouse._disposed) + var pen = (PenDevice)e.Device; + if(pen._disposed) return; _position = e.Root.PointToScreen(e.Position); @@ -151,34 +120,16 @@ namespace Avalonia.Input switch (e.Type) { case RawPointerEventType.LeaveWindow: - LeaveWindow(mouse, e.Timestamp, e.Root, props, keyModifiers); + LeaveWindow(pen, e.Timestamp, e.Root, props, keyModifiers); break; - case RawPointerEventType.LeftButtonDown: - case RawPointerEventType.RightButtonDown: - case RawPointerEventType.MiddleButtonDown: - case RawPointerEventType.XButton1Down: - case RawPointerEventType.XButton2Down: - if (ButtonCount(props) > 1) - e.Handled = MouseMove(mouse, e.Timestamp, e.Root, e.Position, props, keyModifiers); - else - e.Handled = MouseDown(mouse, e.Timestamp, e.Root, e.Position, - props, keyModifiers); + case RawPointerEventType.PenBegin: + e.Handled = PenDown(pen, e.Timestamp, e.Root, e.Position, props, keyModifiers); break; - case RawPointerEventType.LeftButtonUp: - case RawPointerEventType.RightButtonUp: - case RawPointerEventType.MiddleButtonUp: - case RawPointerEventType.XButton1Up: - case RawPointerEventType.XButton2Up: - if (ButtonCount(props) != 0) - e.Handled = MouseMove(mouse, e.Timestamp, e.Root, e.Position, props, keyModifiers); - else - e.Handled = MouseUp(mouse, e.Timestamp, e.Root, e.Position, props, keyModifiers); + case RawPointerEventType.PenEnd: + e.Handled = PenUp(pen, e.Timestamp, e.Root, e.Position, props, keyModifiers); break; - case RawPointerEventType.Move: - e.Handled = MouseMove(mouse, e.Timestamp, e.Root, e.Position, props, keyModifiers); - break; - case RawPointerEventType.Wheel: - e.Handled = MouseWheel(mouse, e.Timestamp, e.Root, e.Position, props, ((RawMouseWheelEventArgs)e).Delta, keyModifiers); + case RawPointerEventType.PenUpdate: + e.Handled = PenMove(pen, e.Timestamp, e.Root, e.Position, props, keyModifiers); break; } } @@ -196,35 +147,18 @@ namespace Avalonia.Input PointerPointProperties CreateProperties(RawPointerEventArgs args) { - var kind = PointerUpdateKind.Other; - if (args.Type == RawPointerEventType.LeftButtonDown) + if (args.Type == RawPointerEventType.PenBegin) kind = PointerUpdateKind.LeftButtonPressed; - if (args.Type == RawPointerEventType.MiddleButtonDown) - kind = PointerUpdateKind.MiddleButtonPressed; - if (args.Type == RawPointerEventType.RightButtonDown) - kind = PointerUpdateKind.RightButtonPressed; - if (args.Type == RawPointerEventType.XButton1Down) - kind = PointerUpdateKind.XButton1Pressed; - if (args.Type == RawPointerEventType.XButton2Down) - kind = PointerUpdateKind.XButton2Pressed; - if (args.Type == RawPointerEventType.LeftButtonUp) + if (args.Type == RawPointerEventType.PenEnd) kind = PointerUpdateKind.LeftButtonReleased; - if (args.Type == RawPointerEventType.MiddleButtonUp) - kind = PointerUpdateKind.MiddleButtonReleased; - if (args.Type == RawPointerEventType.RightButtonUp) - kind = PointerUpdateKind.RightButtonReleased; - if (args.Type == RawPointerEventType.XButton1Up) - kind = PointerUpdateKind.XButton1Released; - if (args.Type == RawPointerEventType.XButton2Up) - kind = PointerUpdateKind.XButton2Released; return new PointerPointProperties(args.InputModifiers, kind); } private MouseButton _lastMouseDownButton; - private bool MouseDown(IPenDevice device, ulong timestamp, IInputElement root, Point p, + private bool PenDown(IPenDevice device, ulong timestamp, IInputElement root, Point p, PointerPointProperties properties, KeyModifiers inputModifiers) { @@ -239,21 +173,8 @@ namespace Avalonia.Input var source = GetSource(hit); if (source != null) { - var settings = AvaloniaLocator.Current.GetService(); - var doubleClickTime = settings?.DoubleClickTime.TotalMilliseconds ?? 500; - var doubleClickSize = settings?.DoubleClickSize ?? new Size(4, 4); - - if (!_lastClickRect.Contains(p) || timestamp - _lastClickTime > doubleClickTime) - { - _clickCount = 0; - } - - ++_clickCount; - _lastClickTime = timestamp; - _lastClickRect = new Rect(p, new Size()) - .Inflate(new Thickness(doubleClickSize.Width / 2, doubleClickSize.Height / 2)); _lastMouseDownButton = properties.PointerUpdateKind.GetMouseButton(); - var e = new PointerPressedEventArgs(source, _pointer, root, p, timestamp, properties, inputModifiers, _clickCount); + var e = new PointerPressedEventArgs(source, _pointer, root, p, timestamp, properties, inputModifiers, 1); source.RaiseEvent(e); return e.Handled; } @@ -262,7 +183,7 @@ namespace Avalonia.Input return false; } - private bool MouseMove(IPenDevice device, ulong timestamp, IInputRoot root, Point p, PointerPointProperties properties, + private bool PenMove(IPenDevice device, ulong timestamp, IInputRoot root, Point p, PointerPointProperties properties, KeyModifiers inputModifiers) { device = device ?? throw new ArgumentNullException(nameof(device)); @@ -292,7 +213,7 @@ namespace Avalonia.Input return false; } - private bool MouseUp(IPenDevice device, ulong timestamp, IInputRoot root, Point p, PointerPointProperties props, + private bool PenUp(IPenDevice device, ulong timestamp, IInputRoot root, Point p, PointerPointProperties props, KeyModifiers inputModifiers) { device = device ?? throw new ArgumentNullException(nameof(device)); @@ -314,27 +235,6 @@ namespace Avalonia.Input return false; } - private bool MouseWheel(IPenDevice device, ulong timestamp, IInputRoot root, Point p, - PointerPointProperties props, - Vector delta, KeyModifiers inputModifiers) - { - device = device ?? throw new ArgumentNullException(nameof(device)); - root = root ?? throw new ArgumentNullException(nameof(root)); - - var hit = HitTest(root, p); - var source = GetSource(hit); - - if (source is not null) - { - var e = new PointerWheelEventArgs(source, _pointer, root, p, timestamp, props, inputModifiers, delta); - - source?.RaiseEvent(e); - return e.Handled; - } - - return false; - } - private IInteractive? GetSource(IVisual? hit) { if (hit is null) diff --git a/src/Avalonia.Input/PointerPoint.cs b/src/Avalonia.Input/PointerPoint.cs index 9f8285a8e1..16fab7410c 100644 --- a/src/Avalonia.Input/PointerPoint.cs +++ b/src/Avalonia.Input/PointerPoint.cs @@ -20,6 +20,14 @@ namespace Avalonia.Input public bool IsRightButtonPressed { get; } public bool IsXButton1Pressed { get; } public bool IsXButton2Pressed { get; } + public bool IsBarrelButtonPressed { get; } + public bool IsEraser { get; } + + public float Twist { get; } + public float Pressure { get; } + public float XTilt { get; } + public float YTilt { get; } + public PointerUpdateKind PointerUpdateKind { get; } @@ -36,10 +44,12 @@ namespace Avalonia.Input IsRightButtonPressed = modifiers.HasAllFlags(RawInputModifiers.RightMouseButton); IsXButton1Pressed = modifiers.HasAllFlags(RawInputModifiers.XButton1MouseButton); IsXButton2Pressed = modifiers.HasAllFlags(RawInputModifiers.XButton2MouseButton); + IsBarrelButtonPressed = modifiers.HasAllFlags(RawInputModifiers.BarrelPenButton); + IsEraser = modifiers.HasAllFlags(RawInputModifiers.PenEraser); // The underlying input source might be reporting the previous state, // so make sure that we reflect the current state - + if (kind == PointerUpdateKind.LeftButtonPressed) IsLeftButtonPressed = true; if (kind == PointerUpdateKind.LeftButtonReleased) @@ -60,6 +70,20 @@ namespace Avalonia.Input IsXButton2Pressed = true; if (kind == PointerUpdateKind.XButton2Released) IsXButton2Pressed = false; + if (kind == PointerUpdateKind.BarrelButtonPressed) + IsBarrelButtonPressed = true; + if (kind == PointerUpdateKind.BarrelButtonReleased) + IsBarrelButtonPressed = false; + } + + public PointerPointProperties(RawInputModifiers modifiers, PointerUpdateKind kind, + float twist, float pressure, float xTilt, float yTilt + ) : this (modifiers, kind) + { + Twist = twist; + Pressure = pressure; + XTilt = xTilt; + YTilt = yTilt; } public static PointerPointProperties None { get; } = new PointerPointProperties(); @@ -77,7 +101,9 @@ namespace Avalonia.Input RightButtonReleased, XButton1Released, XButton2Released, - Other + Other, + BarrelButtonPressed, + BarrelButtonReleased } public static class PointerUpdateKindExtensions diff --git a/src/Avalonia.Input/Raw/RawPointerEventArgs.cs b/src/Avalonia.Input/Raw/RawPointerEventArgs.cs index 62a1dd5d84..ea160efef5 100644 --- a/src/Avalonia.Input/Raw/RawPointerEventArgs.cs +++ b/src/Avalonia.Input/Raw/RawPointerEventArgs.cs @@ -21,7 +21,13 @@ namespace Avalonia.Input.Raw TouchBegin, TouchUpdate, TouchEnd, - TouchCancel + TouchCancel, + PenBegin, + PenUpdate, + PenEnd, + PenCancel, + BarrelUp, + BarrelDown, } /// diff --git a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs index 5e31bba925..db11508ed7 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs @@ -374,17 +374,6 @@ namespace Avalonia.Win32 break; } - - - - - - - - - - - case WindowsMessage.WM_POINTERDEVICECHANGE: { //notifies about changes in the settings of a monitor that has a digitizer attached to it. @@ -414,7 +403,10 @@ namespace Avalonia.Win32 GetDeviceInfo(wParam, out var device, out var info); var point = PointToClient(PointFromLParam(lParam)); var modifiers = GetInputModifiers(info.dwKeyStates); - var eventType = info.ButtonChangeType switch + + if (info.ButtonChangeType != PointerButtonChangeType.POINTER_CHANGE_NONE) + { + var eventType = info.ButtonChangeType switch { PointerButtonChangeType.POINTER_CHANGE_FIRSTBUTTON_DOWN => RawPointerEventType.LeftButtonDown, PointerButtonChangeType.POINTER_CHANGE_SECONDBUTTON_DOWN => RawPointerEventType.RightButtonDown, @@ -428,12 +420,13 @@ namespace Avalonia.Win32 PointerButtonChangeType.POINTER_CHANGE_FOURTHBUTTON_UP => RawPointerEventType.XButton1Up, PointerButtonChangeType.POINTER_CHANGE_FIFTHBUTTON_UP => RawPointerEventType.XButton2Up, }; - if (eventType == RawPointerEventType.NonClientLeftButtonDown && - (WindowsMessage)msg == WindowsMessage.WM_NCPOINTERDOWN) - { - eventType = RawPointerEventType.NonClientLeftButtonDown; + if (eventType == RawPointerEventType.NonClientLeftButtonDown && + (WindowsMessage)msg == WindowsMessage.WM_NCPOINTERDOWN) + { + eventType = RawPointerEventType.NonClientLeftButtonDown; + } + e = new RawPointerEventArgs(device, timestamp, _owner, eventType, point, modifiers); } - e = new RawPointerEventArgs(device, timestamp, _owner, eventType, point, modifiers); break; } case WindowsMessage.WM_POINTERUPDATE: @@ -446,7 +439,8 @@ namespace Avalonia.Win32 var point = PointToClient(PointFromLParam(lParam)); var modifiers = GetInputModifiers(info.dwKeyStates); - e = new RawPointerEventArgs(device, timestamp, _owner, RawPointerEventType.Move, point, modifiers); + e = new RawPointerEventArgs( + device, timestamp, _owner, RawPointerEventType.Move, point, modifiers); break; } case WindowsMessage.WM_POINTERENTER: @@ -462,14 +456,10 @@ namespace Avalonia.Win32 { GetDeviceInfo(wParam, out var device, out var info); var point = PointToClient(PointFromLParam(lParam)); + var modifiers = GetInputModifiers(info.dwKeyStates); e = new RawPointerEventArgs( - device, - timestamp, - _owner, - RawPointerEventType.LeaveWindow, - point, - WindowsKeyboardDevice.Instance.Modifiers); + device, timestamp, _owner, RawPointerEventType.LeaveWindow, point, modifiers); break; } case WindowsMessage.WM_POINTERACTIVATE: @@ -520,33 +510,11 @@ namespace Avalonia.Win32 } case WindowsMessage.WM_PARENTNOTIFY: { - //This message is sent in a dialog scenarios. Contains mouse position in an old-way, - //but listed in the wm_pointer reference + //This message is sent in a dialog scenarios. Contains mouse position. + //Old message, but listed in the wm_pointer reference //https://docs.microsoft.com/en-us/previous-versions/windows/desktop/inputmsg/wm-parentnotify break; } - - - - - - - - - - - - - - - - - - - - - - case WindowsMessage.WM_NCPAINT: { if (!HasFullDecorations) From d3f3166914428a945d24b8369c2b6c18ff0aab34 Mon Sep 17 00:00:00 2001 From: Sergey Mikolaytis Date: Sun, 23 Jan 2022 14:16:35 +0300 Subject: [PATCH 06/78] Provide Pressure, Tilt, and other parameters to PointerPointProperties. Provide touch events (still a lot to do), use point position from pointer info. --- src/Avalonia.Input/PenDevice.cs | 25 ++-- src/Avalonia.Input/PointerPoint.cs | 12 +- src/Avalonia.Input/Raw/RawPointerEventArgs.cs | 4 - .../Interop/UnmanagedMethods.cs | 2 +- .../Avalonia.Win32/WindowImpl.AppWndProc.cs | 111 ++++++++++++------ 5 files changed, 98 insertions(+), 56 deletions(-) diff --git a/src/Avalonia.Input/PenDevice.cs b/src/Avalonia.Input/PenDevice.cs index 3c0f3c7709..c993e7fac4 100644 --- a/src/Avalonia.Input/PenDevice.cs +++ b/src/Avalonia.Input/PenDevice.cs @@ -32,6 +32,14 @@ namespace Avalonia.Input [Obsolete("Use IPointer instead")] public IInputElement? Captured => _pointer.Captured; + public bool IsEraser { get; set; } + public bool IsInverted { get; set; } + public bool IsBarrel { get; set; } + public int XTilt { get; set; } + public int YTilt { get; set; } + public uint Pressure { get; set; } + public uint Twist { get; set; } + /// /// Captures mouse input to the specified control. /// @@ -122,13 +130,13 @@ namespace Avalonia.Input case RawPointerEventType.LeaveWindow: LeaveWindow(pen, e.Timestamp, e.Root, props, keyModifiers); break; - case RawPointerEventType.PenBegin: + case RawPointerEventType.LeftButtonDown: e.Handled = PenDown(pen, e.Timestamp, e.Root, e.Position, props, keyModifiers); break; - case RawPointerEventType.PenEnd: + case RawPointerEventType.LeftButtonUp: e.Handled = PenUp(pen, e.Timestamp, e.Root, e.Position, props, keyModifiers); break; - case RawPointerEventType.PenUpdate: + case RawPointerEventType.Move: e.Handled = PenMove(pen, e.Timestamp, e.Root, e.Position, props, keyModifiers); break; } @@ -145,16 +153,17 @@ namespace Avalonia.Input } - PointerPointProperties CreateProperties(RawPointerEventArgs args) + private PointerPointProperties CreateProperties(RawPointerEventArgs args) { var kind = PointerUpdateKind.Other; - if (args.Type == RawPointerEventType.PenBegin) + if (args.Type == RawPointerEventType.LeftButtonDown) kind = PointerUpdateKind.LeftButtonPressed; - if (args.Type == RawPointerEventType.PenEnd) + if (args.Type == RawPointerEventType.LeftButtonUp) kind = PointerUpdateKind.LeftButtonReleased; - - return new PointerPointProperties(args.InputModifiers, kind); + + return new PointerPointProperties(args.InputModifiers, kind, + Twist, Pressure, XTilt, YTilt, IsEraser, IsInverted, IsBarrel); } private MouseButton _lastMouseDownButton; diff --git a/src/Avalonia.Input/PointerPoint.cs b/src/Avalonia.Input/PointerPoint.cs index 16fab7410c..07ef130fcc 100644 --- a/src/Avalonia.Input/PointerPoint.cs +++ b/src/Avalonia.Input/PointerPoint.cs @@ -22,6 +22,7 @@ namespace Avalonia.Input public bool IsXButton2Pressed { get; } public bool IsBarrelButtonPressed { get; } public bool IsEraser { get; } + public bool IsInverted { get; } public float Twist { get; } public float Pressure { get; } @@ -70,20 +71,19 @@ namespace Avalonia.Input IsXButton2Pressed = true; if (kind == PointerUpdateKind.XButton2Released) IsXButton2Pressed = false; - if (kind == PointerUpdateKind.BarrelButtonPressed) - IsBarrelButtonPressed = true; - if (kind == PointerUpdateKind.BarrelButtonReleased) - IsBarrelButtonPressed = false; } public PointerPointProperties(RawInputModifiers modifiers, PointerUpdateKind kind, - float twist, float pressure, float xTilt, float yTilt + float twist, float pressure, float xTilt, float yTilt, bool isEraser, bool isInverted, bool isBarrel ) : this (modifiers, kind) { Twist = twist; Pressure = pressure; XTilt = xTilt; YTilt = yTilt; + IsEraser = isEraser; + IsInverted = isInverted; + IsBarrelButtonPressed = isBarrel; } public static PointerPointProperties None { get; } = new PointerPointProperties(); @@ -102,8 +102,6 @@ namespace Avalonia.Input XButton1Released, XButton2Released, Other, - BarrelButtonPressed, - BarrelButtonReleased } public static class PointerUpdateKindExtensions diff --git a/src/Avalonia.Input/Raw/RawPointerEventArgs.cs b/src/Avalonia.Input/Raw/RawPointerEventArgs.cs index 6a35ec3fad..c75eb69bfd 100644 --- a/src/Avalonia.Input/Raw/RawPointerEventArgs.cs +++ b/src/Avalonia.Input/Raw/RawPointerEventArgs.cs @@ -22,10 +22,6 @@ namespace Avalonia.Input.Raw TouchUpdate, TouchEnd, TouchCancel, - PenBegin, - PenUpdate, - PenEnd, - PenCancel, BarrelUp, BarrelDown, Magnify, diff --git a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs index 93457f7bbd..b3cab5d052 100644 --- a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs +++ b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs @@ -1003,7 +1003,7 @@ namespace Avalonia.Win32.Interop public uint historyCount; public int inputData; public ModifierKeys dwKeyStates; - public UInt64 PerformanceCount; + public ulong PerformanceCount; public PointerButtonChangeType ButtonChangeType; } diff --git a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs index db11508ed7..34cd9acf25 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs @@ -22,8 +22,8 @@ namespace Avalonia.Win32 uint timestamp = unchecked((uint)GetMessageTime()); RawInputEventArgs e = null; var shouldTakeFocus = false; - - switch ((WindowsMessage)msg) + var message = (WindowsMessage)msg; + switch (message) { case WindowsMessage.WM_ACTIVATE: { @@ -180,7 +180,7 @@ namespace Avalonia.Win32 _mouseDevice, timestamp, _owner, - (WindowsMessage)msg switch + message switch { WindowsMessage.WM_LBUTTONDOWN => RawPointerEventType.LeftButtonDown, WindowsMessage.WM_RBUTTONDOWN => RawPointerEventType.RightButtonDown, @@ -212,7 +212,7 @@ namespace Avalonia.Win32 _mouseDevice, timestamp, _owner, - (WindowsMessage)msg switch + message switch { WindowsMessage.WM_LBUTTONUP => RawPointerEventType.LeftButtonUp, WindowsMessage.WM_RBUTTONUP => RawPointerEventType.RightButtonUp, @@ -327,7 +327,7 @@ namespace Avalonia.Win32 _mouseDevice, timestamp, _owner, - (WindowsMessage)msg switch + message switch { WindowsMessage.WM_NCLBUTTONDOWN => RawPointerEventType .NonClientLeftButtonDown, @@ -400,33 +400,13 @@ namespace Avalonia.Win32 case WindowsMessage.WM_POINTERDOWN: case WindowsMessage.WM_POINTERUP: { + var pointerId = (uint)(ToInt32(wParam) & 0xFFFF); GetDeviceInfo(wParam, out var device, out var info); - var point = PointToClient(PointFromLParam(lParam)); + var eventType = GetEventType(message, info); + var point = PointToClient(new PixelPoint(info.ptPixelLocationX, info.ptPixelLocationY)); var modifiers = GetInputModifiers(info.dwKeyStates); - if (info.ButtonChangeType != PointerButtonChangeType.POINTER_CHANGE_NONE) - { - var eventType = info.ButtonChangeType switch - { - PointerButtonChangeType.POINTER_CHANGE_FIRSTBUTTON_DOWN => RawPointerEventType.LeftButtonDown, - PointerButtonChangeType.POINTER_CHANGE_SECONDBUTTON_DOWN => RawPointerEventType.RightButtonDown, - PointerButtonChangeType.POINTER_CHANGE_THIRDBUTTON_DOWN => RawPointerEventType.MiddleButtonDown, - PointerButtonChangeType.POINTER_CHANGE_FOURTHBUTTON_DOWN => RawPointerEventType.XButton1Down, - PointerButtonChangeType.POINTER_CHANGE_FIFTHBUTTON_DOWN => RawPointerEventType.XButton2Down, - - PointerButtonChangeType.POINTER_CHANGE_FIRSTBUTTON_UP => RawPointerEventType.LeftButtonUp, - PointerButtonChangeType.POINTER_CHANGE_SECONDBUTTON_UP => RawPointerEventType.RightButtonUp, - PointerButtonChangeType.POINTER_CHANGE_THIRDBUTTON_UP => RawPointerEventType.MiddleButtonUp, - PointerButtonChangeType.POINTER_CHANGE_FOURTHBUTTON_UP => RawPointerEventType.XButton1Up, - PointerButtonChangeType.POINTER_CHANGE_FIFTHBUTTON_UP => RawPointerEventType.XButton2Up, - }; - if (eventType == RawPointerEventType.NonClientLeftButtonDown && - (WindowsMessage)msg == WindowsMessage.WM_NCPOINTERDOWN) - { - eventType = RawPointerEventType.NonClientLeftButtonDown; - } - e = new RawPointerEventArgs(device, timestamp, _owner, eventType, point, modifiers); - } + e = new RawPointerEventArgs(device, timestamp, _owner, eventType, point, modifiers); break; } case WindowsMessage.WM_POINTERUPDATE: @@ -436,11 +416,11 @@ namespace Avalonia.Win32 break; } GetDeviceInfo(wParam, out var device, out var info); - var point = PointToClient(PointFromLParam(lParam)); + var point = PointToClient(new PixelPoint(info.ptPixelLocationX, info.ptPixelLocationY)); var modifiers = GetInputModifiers(info.dwKeyStates); + var eventType = device is TouchDevice ? RawPointerEventType.TouchUpdate : RawPointerEventType.Move; - e = new RawPointerEventArgs( - device, timestamp, _owner, RawPointerEventType.Move, point, modifiers); + e = new RawPointerEventArgs(device, timestamp, _owner, eventType, point, modifiers); break; } case WindowsMessage.WM_POINTERENTER: @@ -455,7 +435,7 @@ namespace Avalonia.Win32 case WindowsMessage.WM_POINTERLEAVE: { GetDeviceInfo(wParam, out var device, out var info); - var point = PointToClient(PointFromLParam(lParam)); + var point = PointToClient(new PixelPoint(info.ptPixelLocationX, info.ptPixelLocationY)); var modifiers = GetInputModifiers(info.dwKeyStates); e = new RawPointerEventArgs( @@ -478,7 +458,7 @@ namespace Avalonia.Win32 { GetDeviceInfo(wParam, out var device, out var info); - var point = PointToClient(PointFromLParam(lParam)); + var point = PointToClient(new PixelPoint(info.ptPixelLocationX, info.ptPixelLocationY)); var modifiers = GetInputModifiers(info.dwKeyStates); var delta = new Vector(0, (ToInt32(wParam) >> 16) / wheelDelta); e = new RawMouseWheelEventArgs(device, timestamp, _owner, point, delta, modifiers); @@ -488,7 +468,7 @@ namespace Avalonia.Win32 { GetDeviceInfo(wParam, out var device, out var info); - var point = PointToClient(PointFromLParam(lParam)); + var point = PointToClient(new PixelPoint(info.ptPixelLocationX, info.ptPixelLocationY)); var modifiers = GetInputModifiers(info.dwKeyStates); var delta = new Vector((ToInt32(wParam) >> 16) / wheelDelta, 0); e = new RawMouseWheelEventArgs(device, timestamp, _owner, point, delta, modifiers); @@ -696,7 +676,7 @@ namespace Avalonia.Win32 { Input(e); - if ((WindowsMessage)msg == WindowsMessage.WM_KEYDOWN) + if (message == WindowsMessage.WM_KEYDOWN) { // Handling a WM_KEYDOWN message should cause the subsequent WM_CHAR message to // be ignored. This should be safe to do as WM_CHAR should only be produced in @@ -717,6 +697,44 @@ namespace Avalonia.Win32 } } + private static RawPointerEventType GetEventType(WindowsMessage message, POINTER_INFO info) + { + switch (info.pointerType) + { + case PointerInputType.PT_PEN: + return ToEventType(info.ButtonChangeType); + case PointerInputType.PT_TOUCH: + if (info.pointerFlags.HasFlag(PointerFlags.POINTER_FLAG_CANCELED) || + !info.pointerFlags.HasFlag(PointerFlags.POINTER_FLAG_CONFIDENCE)) + { + return RawPointerEventType.TouchCancel; + } + return message == WindowsMessage.WM_POINTERDOWN || message == WindowsMessage.WM_NCPOINTERDOWN + ? RawPointerEventType.TouchBegin + : RawPointerEventType.TouchEnd; + default: + var eventType = ToEventType(info.ButtonChangeType); + if (eventType == RawPointerEventType.LeftButtonDown && + message == WindowsMessage.WM_NCPOINTERDOWN) + { + eventType = RawPointerEventType.NonClientLeftButtonDown; + } + return eventType; + } + } + + private unsafe void ApplyPenInfo(POINTER_PEN_INFO penInfo) + { + _penDevice.IsBarrel = penInfo.penFlags.HasFlag(PenFlags.PEN_FLAGS_BARREL); + _penDevice.IsEraser = penInfo.penFlags.HasFlag(PenFlags.PEN_FLAGS_BARREL); + _penDevice.IsInverted = penInfo.penFlags.HasFlag(PenFlags.PEN_FLAGS_INVERTED); + + _penDevice.XTilt = penInfo.tiltX; + _penDevice.YTilt = penInfo.tiltY; + _penDevice.Pressure = penInfo.pressure; + _penDevice.Twist = penInfo.rotation; + } + private void GetDeviceInfo(IntPtr wParam, out IInputDevice device, out POINTER_INFO info) { var pointerId = (uint)(ToInt32(wParam) & 0xFFFF); @@ -727,6 +745,8 @@ namespace Avalonia.Win32 device = _penDevice; GetPointerPenInfo(pointerId, out var penInfo); info = penInfo.pointerInfo; + + ApplyPenInfo(penInfo); break; case PointerInputType.PT_TOUCH: device = _touchDevice; @@ -740,6 +760,25 @@ namespace Avalonia.Win32 } } + private static RawPointerEventType ToEventType(PointerButtonChangeType type) + { + return type switch + { + PointerButtonChangeType.POINTER_CHANGE_FIRSTBUTTON_DOWN => RawPointerEventType.LeftButtonDown, + PointerButtonChangeType.POINTER_CHANGE_SECONDBUTTON_DOWN => RawPointerEventType.RightButtonDown, + PointerButtonChangeType.POINTER_CHANGE_THIRDBUTTON_DOWN => RawPointerEventType.MiddleButtonDown, + PointerButtonChangeType.POINTER_CHANGE_FOURTHBUTTON_DOWN => RawPointerEventType.XButton1Down, + PointerButtonChangeType.POINTER_CHANGE_FIFTHBUTTON_DOWN => RawPointerEventType.XButton2Down, + + PointerButtonChangeType.POINTER_CHANGE_FIRSTBUTTON_UP => RawPointerEventType.LeftButtonUp, + PointerButtonChangeType.POINTER_CHANGE_SECONDBUTTON_UP => RawPointerEventType.RightButtonUp, + PointerButtonChangeType.POINTER_CHANGE_THIRDBUTTON_UP => RawPointerEventType.MiddleButtonUp, + PointerButtonChangeType.POINTER_CHANGE_FOURTHBUTTON_UP => RawPointerEventType.XButton1Up, + PointerButtonChangeType.POINTER_CHANGE_FIFTHBUTTON_UP => RawPointerEventType.XButton2Up, + _ => RawPointerEventType.Move + }; + } + public readonly bool Win8Plus = Win32Platform.WindowsVersion >= PlatformConstants.Windows8; private void UpdateInputMethod(IntPtr hkl) From c046165714c37e20b305cfae823347966cd95aca Mon Sep 17 00:00:00 2001 From: Sergey Mikolaytis Date: Sun, 23 Jan 2022 15:36:29 +0300 Subject: [PATCH 07/78] Add History fetch methods (will be implemented a bit later). Raise touch events. --- .../Interop/UnmanagedMethods.cs | 25 +++-- .../Avalonia.Win32/WindowImpl.AppWndProc.cs | 103 +++++++++++------- 2 files changed, 76 insertions(+), 52 deletions(-) diff --git a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs index b3cab5d052..d71efcb074 100644 --- a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs +++ b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs @@ -1074,32 +1074,35 @@ namespace Avalonia.Win32.Interop public const int SizeOf_BITMAPINFOHEADER = 40; + [DllImport("user32.dll", SetLastError = true)] + public static extern bool IsMouseInPointerEnabled(); + [DllImport("user32.dll", SetLastError = true)] public static extern int EnableMouseInPointer(bool enable); [DllImport("user32.dll", SetLastError = true)] - public static extern bool GetPointerCursorId(uint pointerID, out uint cursorId); + public static extern bool GetPointerCursorId(uint pointerId, out uint cursorId); [DllImport("user32.dll", SetLastError = true)] - public static extern bool GetPointerType(uint pointerID, out PointerInputType pointerType); + public static extern bool GetPointerType(uint pointerId, out PointerInputType pointerType); - [DllImport("User32.dll", SetLastError = true)] - public static extern bool GetPointerInfo(uint pointerID, out POINTER_INFO pointerInfo); + [DllImport("user32.dll", SetLastError = true)] + public static extern bool GetPointerInfo(uint pointerId, out POINTER_INFO pointerInfo); - [DllImport("User32.dll", SetLastError = true)] - public static extern bool GetPointerPenInfo(uint pointerID, out POINTER_PEN_INFO penInfo); + [DllImport("user32.dll", SetLastError = true)] + public static extern bool GetPointerInfoHistory(uint pointerId, ref int entriesCount, [MarshalAs(UnmanagedType.LPArray), In, Out] POINTER_INFO[] pointerInfos); - [DllImport("User32.dll", SetLastError = true)] - public static extern bool GetPointerTouchInfo(uint pointerID, out POINTER_TOUCH_INFO touchInfo); + [DllImport("user32.dll", SetLastError = true)] + public static extern bool GetPointerPenInfo(uint pointerId, out POINTER_PEN_INFO penInfo); [DllImport("user32.dll", SetLastError = true)] - public static extern void GetUnpredictedMessagePos(); + public static extern bool GetPointerPenInfoHistory(uint pointerId, ref int entriesCount, [MarshalAs(UnmanagedType.LPArray), In, Out] POINTER_PEN_INFO[] penInfos); [DllImport("user32.dll", SetLastError = true)] - public static extern bool IsMouseInPointerEnabled(); + public static extern bool GetPointerTouchInfo(uint pointerId, out POINTER_TOUCH_INFO touchInfo); [DllImport("user32.dll", SetLastError = true)] - public static extern bool SkipPointerFrameMessages(uint pointerID); + public static extern bool GetPointerTouchInfoHistory(uint pointerId, ref int entriesCount, [MarshalAs(UnmanagedType.LPArray), In, Out] POINTER_TOUCH_INFO[] touchInfos); [DllImport("user32.dll")] public static extern bool EnumDisplayMonitors(IntPtr hdc, IntPtr lprcClip, diff --git a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs index 34cd9acf25..fda68e1561 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs @@ -401,26 +401,41 @@ namespace Avalonia.Win32 case WindowsMessage.WM_POINTERUP: { var pointerId = (uint)(ToInt32(wParam) & 0xFFFF); - GetDeviceInfo(wParam, out var device, out var info); + GetDeviceInfo(wParam, out var device, out var info, ref timestamp); var eventType = GetEventType(message, info); var point = PointToClient(new PixelPoint(info.ptPixelLocationX, info.ptPixelLocationY)); var modifiers = GetInputModifiers(info.dwKeyStates); - e = new RawPointerEventArgs(device, timestamp, _owner, eventType, point, modifiers); + if (device is TouchDevice) + { + e = new RawTouchEventArgs(_touchDevice, timestamp, _owner, eventType, point, modifiers, info.pointerId); + } + else + { + e = new RawPointerEventArgs(device, timestamp, _owner, eventType, point, modifiers); + } break; } case WindowsMessage.WM_POINTERUPDATE: { - if (ShouldIgnoreTouchEmulatedMessage()) - { - break; - } - GetDeviceInfo(wParam, out var device, out var info); + GetDeviceInfo(wParam, out var device, out var info, ref timestamp); var point = PointToClient(new PixelPoint(info.ptPixelLocationX, info.ptPixelLocationY)); var modifiers = GetInputModifiers(info.dwKeyStates); - var eventType = device is TouchDevice ? RawPointerEventType.TouchUpdate : RawPointerEventType.Move; - e = new RawPointerEventArgs(device, timestamp, _owner, eventType, point, modifiers); + if (device is TouchDevice) + { + if (ShouldIgnoreTouchEmulatedMessage()) + { + break; + } + e = new RawTouchEventArgs(_touchDevice, timestamp, _owner, + RawPointerEventType.TouchUpdate, point, modifiers, info.pointerId); + } + else + { + e = new RawPointerEventArgs(device, timestamp, _owner, + RawPointerEventType.Move, point, modifiers); + } break; } case WindowsMessage.WM_POINTERENTER: @@ -434,7 +449,7 @@ namespace Avalonia.Win32 } case WindowsMessage.WM_POINTERLEAVE: { - GetDeviceInfo(wParam, out var device, out var info); + GetDeviceInfo(wParam, out var device, out var info, ref timestamp); var point = PointToClient(new PixelPoint(info.ptPixelLocationX, info.ptPixelLocationY)); var modifiers = GetInputModifiers(info.dwKeyStates); @@ -456,7 +471,7 @@ namespace Avalonia.Win32 } case WindowsMessage.WM_POINTERWHEEL: { - GetDeviceInfo(wParam, out var device, out var info); + GetDeviceInfo(wParam, out var device, out var info, ref timestamp); var point = PointToClient(new PixelPoint(info.ptPixelLocationX, info.ptPixelLocationY)); var modifiers = GetInputModifiers(info.dwKeyStates); @@ -466,7 +481,7 @@ namespace Avalonia.Win32 } case WindowsMessage.WM_POINTERHWHEEL: { - GetDeviceInfo(wParam, out var device, out var info); + GetDeviceInfo(wParam, out var device, out var info, ref timestamp); var point = PointToClient(new PixelPoint(info.ptPixelLocationX, info.ptPixelLocationY)); var modifiers = GetInputModifiers(info.dwKeyStates); @@ -697,36 +712,10 @@ namespace Avalonia.Win32 } } - private static RawPointerEventType GetEventType(WindowsMessage message, POINTER_INFO info) - { - switch (info.pointerType) - { - case PointerInputType.PT_PEN: - return ToEventType(info.ButtonChangeType); - case PointerInputType.PT_TOUCH: - if (info.pointerFlags.HasFlag(PointerFlags.POINTER_FLAG_CANCELED) || - !info.pointerFlags.HasFlag(PointerFlags.POINTER_FLAG_CONFIDENCE)) - { - return RawPointerEventType.TouchCancel; - } - return message == WindowsMessage.WM_POINTERDOWN || message == WindowsMessage.WM_NCPOINTERDOWN - ? RawPointerEventType.TouchBegin - : RawPointerEventType.TouchEnd; - default: - var eventType = ToEventType(info.ButtonChangeType); - if (eventType == RawPointerEventType.LeftButtonDown && - message == WindowsMessage.WM_NCPOINTERDOWN) - { - eventType = RawPointerEventType.NonClientLeftButtonDown; - } - return eventType; - } - } - private unsafe void ApplyPenInfo(POINTER_PEN_INFO penInfo) { _penDevice.IsBarrel = penInfo.penFlags.HasFlag(PenFlags.PEN_FLAGS_BARREL); - _penDevice.IsEraser = penInfo.penFlags.HasFlag(PenFlags.PEN_FLAGS_BARREL); + _penDevice.IsEraser = penInfo.penFlags.HasFlag(PenFlags.PEN_FLAGS_ERASER); _penDevice.IsInverted = penInfo.penFlags.HasFlag(PenFlags.PEN_FLAGS_INVERTED); _penDevice.XTilt = penInfo.tiltX; @@ -735,10 +724,11 @@ namespace Avalonia.Win32 _penDevice.Twist = penInfo.rotation; } - private void GetDeviceInfo(IntPtr wParam, out IInputDevice device, out POINTER_INFO info) + private void GetDeviceInfo(IntPtr wParam, out IInputDevice device, out POINTER_INFO info, ref uint timestamp) { var pointerId = (uint)(ToInt32(wParam) & 0xFFFF); - GetPointerType(pointerId, out var type);//ToDo we can cache this and invalidate in WM_POINTERDEVICECHANGE + GetPointerType(pointerId, out var type); + //GetPointerCursorId(pointerId, out var cursorId); switch (type) { case PointerInputType.PT_PEN: @@ -758,6 +748,37 @@ namespace Avalonia.Win32 GetPointerInfo(pointerId, out info); break; } + + if (info.dwTime != 0) + { + timestamp = info.dwTime; + } + } + + private static RawPointerEventType GetEventType(WindowsMessage message, POINTER_INFO info) + { + switch (info.pointerType) + { + case PointerInputType.PT_PEN: + return ToEventType(info.ButtonChangeType); + case PointerInputType.PT_TOUCH: + if (info.pointerFlags.HasFlag(PointerFlags.POINTER_FLAG_CANCELED) || + !info.pointerFlags.HasFlag(PointerFlags.POINTER_FLAG_CONFIDENCE)) + { + return RawPointerEventType.TouchCancel; + } + return message == WindowsMessage.WM_POINTERDOWN || message == WindowsMessage.WM_NCPOINTERDOWN + ? RawPointerEventType.TouchBegin + : RawPointerEventType.TouchEnd; + default: + var eventType = ToEventType(info.ButtonChangeType); + if (eventType == RawPointerEventType.LeftButtonDown && + message == WindowsMessage.WM_NCPOINTERDOWN) + { + eventType = RawPointerEventType.NonClientLeftButtonDown; + } + return eventType; + } } private static RawPointerEventType ToEventType(PointerButtonChangeType type) From cbc813235a80918b5f0a57ca54f5abe5b47b08cb Mon Sep 17 00:00:00 2001 From: Sergey Mikolaytis Date: Sun, 23 Jan 2022 16:35:25 +0300 Subject: [PATCH 08/78] Combine some message handlers --- .../Avalonia.Win32/WindowImpl.AppWndProc.cs | 68 +++++++------------ 1 file changed, 24 insertions(+), 44 deletions(-) diff --git a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs index fda68e1561..0266134199 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs @@ -399,26 +399,10 @@ namespace Avalonia.Win32 case WindowsMessage.WM_NCPOINTERUP: case WindowsMessage.WM_POINTERDOWN: case WindowsMessage.WM_POINTERUP: - { - var pointerId = (uint)(ToInt32(wParam) & 0xFFFF); - GetDeviceInfo(wParam, out var device, out var info, ref timestamp); - var eventType = GetEventType(message, info); - var point = PointToClient(new PixelPoint(info.ptPixelLocationX, info.ptPixelLocationY)); - var modifiers = GetInputModifiers(info.dwKeyStates); - - if (device is TouchDevice) - { - e = new RawTouchEventArgs(_touchDevice, timestamp, _owner, eventType, point, modifiers, info.pointerId); - } - else - { - e = new RawPointerEventArgs(device, timestamp, _owner, eventType, point, modifiers); - } - break; - } case WindowsMessage.WM_POINTERUPDATE: { - GetDeviceInfo(wParam, out var device, out var info, ref timestamp); + GetDevicePointerInfo(wParam, out var device, out var info, ref timestamp); + var eventType = GetEventType(message, info); var point = PointToClient(new PixelPoint(info.ptPixelLocationX, info.ptPixelLocationY)); var modifiers = GetInputModifiers(info.dwKeyStates); @@ -428,13 +412,11 @@ namespace Avalonia.Win32 { break; } - e = new RawTouchEventArgs(_touchDevice, timestamp, _owner, - RawPointerEventType.TouchUpdate, point, modifiers, info.pointerId); + e = new RawTouchEventArgs(_touchDevice, timestamp, _owner, eventType, point, modifiers, info.pointerId); } else { - e = new RawPointerEventArgs(device, timestamp, _owner, - RawPointerEventType.Move, point, modifiers); + e = new RawPointerEventArgs(device, timestamp, _owner, eventType, point, modifiers); } break; } @@ -449,7 +431,7 @@ namespace Avalonia.Win32 } case WindowsMessage.WM_POINTERLEAVE: { - GetDeviceInfo(wParam, out var device, out var info, ref timestamp); + GetDevicePointerInfo(wParam, out var device, out var info, ref timestamp); var point = PointToClient(new PixelPoint(info.ptPixelLocationX, info.ptPixelLocationY)); var modifiers = GetInputModifiers(info.dwKeyStates); @@ -457,6 +439,18 @@ namespace Avalonia.Win32 device, timestamp, _owner, RawPointerEventType.LeaveWindow, point, modifiers); break; } + case WindowsMessage.WM_POINTERWHEEL: + case WindowsMessage.WM_POINTERHWHEEL: + { + GetDevicePointerInfo(wParam, out var device, out var info, ref timestamp); + + var point = PointToClient(new PixelPoint(info.ptPixelLocationX, info.ptPixelLocationY)); + var modifiers = GetInputModifiers(info.dwKeyStates); + var val = (ToInt32(wParam) >> 16) / wheelDelta; + var delta = message == WindowsMessage.WM_POINTERHWHEEL ? new Vector(0, val) : new Vector(val, 0); + e = new RawMouseWheelEventArgs(device, timestamp, _owner, point, delta, modifiers); + break; + } case WindowsMessage.WM_POINTERACTIVATE: { //occurs when a pointer activates an inactive window. @@ -469,26 +463,6 @@ namespace Avalonia.Win32 _mouseDevice.Capture(null); return IntPtr.Zero; } - case WindowsMessage.WM_POINTERWHEEL: - { - GetDeviceInfo(wParam, out var device, out var info, ref timestamp); - - var point = PointToClient(new PixelPoint(info.ptPixelLocationX, info.ptPixelLocationY)); - var modifiers = GetInputModifiers(info.dwKeyStates); - var delta = new Vector(0, (ToInt32(wParam) >> 16) / wheelDelta); - e = new RawMouseWheelEventArgs(device, timestamp, _owner, point, delta, modifiers); - break; - } - case WindowsMessage.WM_POINTERHWHEEL: - { - GetDeviceInfo(wParam, out var device, out var info, ref timestamp); - - var point = PointToClient(new PixelPoint(info.ptPixelLocationX, info.ptPixelLocationY)); - var modifiers = GetInputModifiers(info.dwKeyStates); - var delta = new Vector((ToInt32(wParam) >> 16) / wheelDelta, 0); - e = new RawMouseWheelEventArgs(device, timestamp, _owner, point, delta, modifiers); - break; - } case WindowsMessage.DM_POINTERHITTEST: { //DM stands for direct manipulation. @@ -724,7 +698,7 @@ namespace Avalonia.Win32 _penDevice.Twist = penInfo.rotation; } - private void GetDeviceInfo(IntPtr wParam, out IInputDevice device, out POINTER_INFO info, ref uint timestamp) + private void GetDevicePointerInfo(IntPtr wParam, out IInputDevice device, out POINTER_INFO info, ref uint timestamp) { var pointerId = (uint)(ToInt32(wParam) & 0xFFFF); GetPointerType(pointerId, out var type); @@ -757,6 +731,12 @@ namespace Avalonia.Win32 private static RawPointerEventType GetEventType(WindowsMessage message, POINTER_INFO info) { + if (message == WindowsMessage.WM_POINTERUPDATE) + { + return info.pointerType == PointerInputType.PT_TOUCH + ? RawPointerEventType.TouchUpdate + : RawPointerEventType.Move; + } switch (info.pointerType) { case PointerInputType.PT_PEN: From c880572c5f711edb016a727f17003dabc2b1427f Mon Sep 17 00:00:00 2001 From: Sergey Mikolaytis Date: Sun, 23 Jan 2022 19:27:17 +0300 Subject: [PATCH 09/78] Handle history pointer infos for touch and pen --- .../Avalonia.Win32/WindowImpl.AppWndProc.cs | 58 ++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs index 0266134199..0aaa9d4ce0 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs @@ -402,6 +402,62 @@ namespace Avalonia.Win32 case WindowsMessage.WM_POINTERUPDATE: { GetDevicePointerInfo(wParam, out var device, out var info, ref timestamp); + + if (info.historyCount > 1) + { + if (info.pointerType == PointerInputType.PT_TOUCH) + { + if (ShouldIgnoreTouchEmulatedMessage()) + { + break; + } + + var pointerId = (uint)(ToInt32(wParam) & 0xFFFF); + var historyCount = (int)info.historyCount; + var historyTouchInfos = new POINTER_TOUCH_INFO[historyCount]; + if (GetPointerTouchInfoHistory(pointerId, ref historyCount, historyTouchInfos)) + { + //last info is the same as the current so skip it + for (int i = 0; i < historyCount - 1; i++) + { + var historyTouchInfo = historyTouchInfos[i]; + var historyInfo = historyTouchInfo.pointerInfo; + var historyEventType = GetEventType(message, historyInfo); + var historyPoint = PointToClient(new PixelPoint( + historyInfo.ptPixelLocationX, historyInfo.ptPixelLocationY)); + var historyModifiers = GetInputModifiers(historyInfo.dwKeyStates); + var historyTimestamp = historyInfo.dwTime == 0 ? timestamp : historyInfo.dwTime; + Input?.Invoke(new RawTouchEventArgs(_touchDevice, historyTimestamp, _owner, + historyEventType, historyPoint, historyModifiers, historyInfo.pointerId)); + } + } + } + else if (info.pointerType == PointerInputType.PT_PEN) + { + var pointerId = (uint)(ToInt32(wParam) & 0xFFFF); + var historyCount = (int)info.historyCount; + var historyPenInfos = new POINTER_PEN_INFO[historyCount]; + if (GetPointerPenInfoHistory(pointerId, ref historyCount, historyPenInfos)) + { + //last info is the same as the current so skip it + for (int i = 0; i < historyCount - 1; i++) + { + var historyPenInfo = historyPenInfos[i]; + var historyInfo = historyPenInfo.pointerInfo; + var historyEventType = GetEventType(message, historyInfo); + var historyPoint = PointToClient(new PixelPoint( + historyInfo.ptPixelLocationX, historyInfo.ptPixelLocationY)); + var historyModifiers = GetInputModifiers(historyInfo.dwKeyStates); + var historyTimestamp = historyInfo.dwTime == 0 ? timestamp : historyInfo.dwTime; + + ApplyPenInfo(historyPenInfo); + Input?.Invoke(new RawPointerEventArgs(_penDevice, historyTimestamp, _owner, + historyEventType, historyPoint, historyModifiers)); + } + } + } + } + var eventType = GetEventType(message, info); var point = PointToClient(new PixelPoint(info.ptPixelLocationX, info.ptPixelLocationY)); var modifiers = GetInputModifiers(info.dwKeyStates); @@ -447,7 +503,7 @@ namespace Avalonia.Win32 var point = PointToClient(new PixelPoint(info.ptPixelLocationX, info.ptPixelLocationY)); var modifiers = GetInputModifiers(info.dwKeyStates); var val = (ToInt32(wParam) >> 16) / wheelDelta; - var delta = message == WindowsMessage.WM_POINTERHWHEEL ? new Vector(0, val) : new Vector(val, 0); + var delta = message == WindowsMessage.WM_POINTERWHEEL ? new Vector(0, val) : new Vector(val, 0); e = new RawMouseWheelEventArgs(device, timestamp, _owner, point, delta, modifiers); break; } From 8cbd26ffdf6709e5e22487aeadc3d6b99f55af2c Mon Sep 17 00:00:00 2001 From: Sergey Mikolaytis Date: Sun, 23 Jan 2022 19:49:32 +0300 Subject: [PATCH 10/78] Remove redundant changes, improve tab control pointer type check --- src/Avalonia.Controls/TabControl.cs | 6 ++++-- src/Avalonia.Input/IKeyboardDevice.cs | 2 -- src/Avalonia.Input/PointerPoint.cs | 2 +- src/Avalonia.Input/Raw/RawPointerEventArgs.cs | 2 -- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/Avalonia.Controls/TabControl.cs b/src/Avalonia.Controls/TabControl.cs index 306a9d3e6a..955b29f3f9 100644 --- a/src/Avalonia.Controls/TabControl.cs +++ b/src/Avalonia.Controls/TabControl.cs @@ -211,7 +211,8 @@ namespace Avalonia.Controls { base.OnPointerPressed(e); - if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed && e.Pointer.Type == PointerType.Mouse) + if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed && + (e.Pointer.Type == PointerType.Mouse || e.Pointer.Type == PointerType.Pen)) { e.Handled = UpdateSelectionFromEventSource(e.Source); } @@ -219,7 +220,8 @@ namespace Avalonia.Controls protected override void OnPointerReleased(PointerReleasedEventArgs e) { - if (e.InitialPressMouseButton == MouseButton.Left && e.Pointer.Type != PointerType.Mouse) + if (e.InitialPressMouseButton == MouseButton.Left && + (e.Pointer.Type == PointerType.Mouse || e.Pointer.Type == PointerType.Pen)) { var container = GetContainerFromEventSource(e.Source); if (container != null diff --git a/src/Avalonia.Input/IKeyboardDevice.cs b/src/Avalonia.Input/IKeyboardDevice.cs index b3ea7c5f4f..9506dc36fb 100644 --- a/src/Avalonia.Input/IKeyboardDevice.cs +++ b/src/Avalonia.Input/IKeyboardDevice.cs @@ -47,8 +47,6 @@ namespace Avalonia.Input MiddleMouseButton = 64, XButton1MouseButton = 128, XButton2MouseButton = 256, - BarrelPenButton = 512, - PenEraser = 1024, KeyboardMask = Alt | Control | Shift | Meta } diff --git a/src/Avalonia.Input/PointerPoint.cs b/src/Avalonia.Input/PointerPoint.cs index 07ef130fcc..cdfcb8da3a 100644 --- a/src/Avalonia.Input/PointerPoint.cs +++ b/src/Avalonia.Input/PointerPoint.cs @@ -101,7 +101,7 @@ namespace Avalonia.Input RightButtonReleased, XButton1Released, XButton2Released, - Other, + Other } public static class PointerUpdateKindExtensions diff --git a/src/Avalonia.Input/Raw/RawPointerEventArgs.cs b/src/Avalonia.Input/Raw/RawPointerEventArgs.cs index c75eb69bfd..d6406121c7 100644 --- a/src/Avalonia.Input/Raw/RawPointerEventArgs.cs +++ b/src/Avalonia.Input/Raw/RawPointerEventArgs.cs @@ -22,8 +22,6 @@ namespace Avalonia.Input.Raw TouchUpdate, TouchEnd, TouchCancel, - BarrelUp, - BarrelDown, Magnify, Rotate, Swipe From 5127006d1b84880b03fbfca7a25889c376fcc8be Mon Sep 17 00:00:00 2001 From: Sergey Mikolaytis Date: Sun, 23 Jan 2022 22:12:34 +0300 Subject: [PATCH 11/78] fix touch issues --- .../GestureRecognizers/ScrollGestureRecognizer.cs | 2 +- src/Avalonia.Input/PointerPoint.cs | 2 -- src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs | 7 +++++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Avalonia.Input/GestureRecognizers/ScrollGestureRecognizer.cs b/src/Avalonia.Input/GestureRecognizers/ScrollGestureRecognizer.cs index f8cedb636f..1d97fdfe53 100644 --- a/src/Avalonia.Input/GestureRecognizers/ScrollGestureRecognizer.cs +++ b/src/Avalonia.Input/GestureRecognizers/ScrollGestureRecognizer.cs @@ -101,7 +101,7 @@ namespace Avalonia.Input.GestureRecognizers if (_scrolling) { var vector = _trackedRootPoint - rootPoint; - var elapsed = _lastMoveTimestamp.HasValue ? + var elapsed = _lastMoveTimestamp.HasValue && _lastMoveTimestamp < e.Timestamp ? TimeSpan.FromMilliseconds(e.Timestamp - _lastMoveTimestamp.Value) : TimeSpan.Zero; diff --git a/src/Avalonia.Input/PointerPoint.cs b/src/Avalonia.Input/PointerPoint.cs index cdfcb8da3a..728bb1c579 100644 --- a/src/Avalonia.Input/PointerPoint.cs +++ b/src/Avalonia.Input/PointerPoint.cs @@ -45,8 +45,6 @@ namespace Avalonia.Input IsRightButtonPressed = modifiers.HasAllFlags(RawInputModifiers.RightMouseButton); IsXButton1Pressed = modifiers.HasAllFlags(RawInputModifiers.XButton1MouseButton); IsXButton2Pressed = modifiers.HasAllFlags(RawInputModifiers.XButton2MouseButton); - IsBarrelButtonPressed = modifiers.HasAllFlags(RawInputModifiers.BarrelPenButton); - IsEraser = modifiers.HasAllFlags(RawInputModifiers.PenEraser); // The underlying input source might be reporting the previous state, // so make sure that we reflect the current state diff --git a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs index 0aaa9d4ce0..52981ac7ec 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs @@ -488,6 +488,10 @@ namespace Avalonia.Win32 case WindowsMessage.WM_POINTERLEAVE: { GetDevicePointerInfo(wParam, out var device, out var info, ref timestamp); + if (device is TouchDevice) + { + break; + } var point = PointToClient(new PixelPoint(info.ptPixelLocationX, info.ptPixelLocationY)); var modifiers = GetInputModifiers(info.dwKeyStates); @@ -798,8 +802,7 @@ namespace Avalonia.Win32 case PointerInputType.PT_PEN: return ToEventType(info.ButtonChangeType); case PointerInputType.PT_TOUCH: - if (info.pointerFlags.HasFlag(PointerFlags.POINTER_FLAG_CANCELED) || - !info.pointerFlags.HasFlag(PointerFlags.POINTER_FLAG_CONFIDENCE)) + if (info.pointerFlags.HasFlag(PointerFlags.POINTER_FLAG_CANCELED)) { return RawPointerEventType.TouchCancel; } From 8dee09b830462ed3e0c5d6197c44a95f2049a935 Mon Sep 17 00:00:00 2001 From: Sergey Mikolaytis Date: Sun, 23 Jan 2022 23:13:39 +0300 Subject: [PATCH 12/78] Allow double click for pen device --- src/Avalonia.Input/PenDevice.cs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/Avalonia.Input/PenDevice.cs b/src/Avalonia.Input/PenDevice.cs index c993e7fac4..aa4f89bb85 100644 --- a/src/Avalonia.Input/PenDevice.cs +++ b/src/Avalonia.Input/PenDevice.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Reactive.Linq; using Avalonia.Input.Raw; using Avalonia.Interactivity; +using Avalonia.Platform; using Avalonia.VisualTree; namespace Avalonia.Input @@ -12,6 +13,10 @@ namespace Avalonia.Input /// public class PenDevice : IPenDevice, IDisposable { + private int _clickCount; + private Rect _lastClickRect; + private ulong _lastClickTime; + private readonly Pointer _pointer; private bool _disposed; private PixelPoint? _position; @@ -182,8 +187,21 @@ namespace Avalonia.Input var source = GetSource(hit); if (source != null) { + var settings = AvaloniaLocator.Current.GetService(); + var doubleClickTime = settings?.DoubleClickTime.TotalMilliseconds ?? 500; + var doubleClickSize = settings?.DoubleClickSize ?? new Size(4, 4); + + if (!_lastClickRect.Contains(p) || timestamp - _lastClickTime > doubleClickTime) + { + _clickCount = 0; + } + + ++_clickCount; + _lastClickTime = timestamp; + _lastClickRect = new Rect(p, new Size()) + .Inflate(new Thickness(doubleClickSize.Width / 2, doubleClickSize.Height / 2)); _lastMouseDownButton = properties.PointerUpdateKind.GetMouseButton(); - var e = new PointerPressedEventArgs(source, _pointer, root, p, timestamp, properties, inputModifiers, 1); + var e = new PointerPressedEventArgs(source, _pointer, root, p, timestamp, properties, inputModifiers, _clickCount); source.RaiseEvent(e); return e.Handled; } From 600bb3198c775a76ac9034a5473fea795056be7b Mon Sep 17 00:00:00 2001 From: Max Katz Date: Sun, 23 Jan 2022 21:20:02 -0500 Subject: [PATCH 13/78] Add pressure preview --- samples/ControlCatalog/Pages/PointersPage.cs | 266 ++++++++++++------- 1 file changed, 169 insertions(+), 97 deletions(-) diff --git a/samples/ControlCatalog/Pages/PointersPage.cs b/samples/ControlCatalog/Pages/PointersPage.cs index 2901013cea..9702e8e3e7 100644 --- a/samples/ControlCatalog/Pages/PointersPage.cs +++ b/samples/ControlCatalog/Pages/PointersPage.cs @@ -1,3 +1,4 @@ +#nullable enable using System; using System.Collections.Generic; using System.Diagnostics; @@ -25,7 +26,8 @@ public class PointersPage : Decorator Items = new[] { new TabItem() { Header = "Contacts", Content = new PointerContactsTab() }, - new TabItem() { Header = "IntermediatePoints", Content = new PointerIntermediatePointsTab() } + new TabItem() { Header = "IntermediatePoints", Content = new PointerIntermediatePointsTab() }, + new TabItem() { Header = "Pressure", Content = new PointerPressureTab() } } }; } @@ -148,7 +150,7 @@ public class PointersPage : Decorator { Children = { - new PointerCanvas(slider, status), + new PointerCanvas(slider, status, true), new Border { Background = Brushes.LightYellow, @@ -182,140 +184,210 @@ public class PointersPage : Decorator } }; } + } - class PointerCanvas : Control + public class PointerPressureTab : Decorator + { + public PointerPressureTab() { - private readonly Slider _slider; - private readonly TextBlock _status; - private int _events; - private Stopwatch _stopwatch = Stopwatch.StartNew(); - private Dictionary _pointers = new(); - class PointerPoints + this[TextBlock.ForegroundProperty] = Brushes.Black; + + var status = new TextBlock() + { + HorizontalAlignment = HorizontalAlignment.Left, + VerticalAlignment = VerticalAlignment.Top, + FontSize = 12 + }; + Child = new Grid { - struct CanvasPoint + Children = { - public IBrush Brush; - public Point Point; - public double Radius; + new PointerCanvas(null, status, false), + status } + }; + } + } + + class PointerCanvas : Control + { + private readonly Slider? _slider; + private readonly TextBlock _status; + private readonly bool _drawPoints; + private int _events; + private Stopwatch _stopwatch = Stopwatch.StartNew(); + private IDisposable? _statusUpdated; + private Dictionary _pointers = new(); + private PointerPointProperties? _lastProperties; + class PointerPoints + { + struct CanvasPoint + { + public IBrush Brush; + public Point Point; + public double Radius; + public double Pressure; + } + + readonly CanvasPoint[] _points = new CanvasPoint[1000]; + int _index; - readonly CanvasPoint[] _points = new CanvasPoint[1000]; - int _index; - - public void Render(DrawingContext context) + public void Render(DrawingContext context, bool drawPoints) + { + + CanvasPoint? prev = null; + for (var c = 0; c < _points.Length; c++) { - - CanvasPoint? prev = null; - for (var c = 0; c < _points.Length; c++) + var i = (c + _index) % _points.Length; + var pt = _points[i]; + var thickness = pt.Pressure == 0 ? 1 : (pt.Pressure / 1024) * 5; + + if (drawPoints) { - var i = (c + _index) % _points.Length; - var pt = _points[i]; if (prev.HasValue && prev.Value.Brush != null && pt.Brush != null) - context.DrawLine(new Pen(Brushes.Black), prev.Value.Point, pt.Point); - prev = pt; + context.DrawLine(new Pen(Brushes.Black, thickness), prev.Value.Point, pt.Point); if (pt.Brush != null) context.DrawEllipse(pt.Brush, null, pt.Point, pt.Radius, pt.Radius); - } - - } - - void AddPoint(Point pt, IBrush brush, double radius) - { - _points[_index] = new CanvasPoint { Point = pt, Brush = brush, Radius = radius }; - _index = (_index + 1) % _points.Length; - } - - public void HandleEvent(PointerEventArgs e, Visual v) - { - e.Handled = true; - if (e.RoutedEvent == PointerPressedEvent) - AddPoint(e.GetPosition(v), Brushes.Green, 10); - else if (e.RoutedEvent == PointerReleasedEvent) - AddPoint(e.GetPosition(v), Brushes.Red, 10); else { - var pts = e.GetIntermediatePoints(v); - for (var c = 0; c < pts.Count; c++) - { - var pt = pts[c]; - AddPoint(pt.Position, c == pts.Count - 1 ? Brushes.Blue : Brushes.Black, - c == pts.Count - 1 ? 5 : 2); - } + if (prev.HasValue && prev.Value.Brush != null && pt.Brush != null) + context.DrawLine(new Pen(Brushes.Black, thickness, lineCap: PenLineCap.Round, lineJoin: PenLineJoin.Round), prev.Value.Point, pt.Point); } + prev = pt; } + } - - public PointerCanvas(Slider slider, TextBlock status) + + void AddPoint(Point pt, IBrush brush, double radius, float pressure) + { + _points[_index] = new CanvasPoint { Point = pt, Brush = brush, Radius = radius, Pressure = pressure }; + _index = (_index + 1) % _points.Length; + } + + public void HandleEvent(PointerEventArgs e, Visual v) { - _slider = slider; - _status = status; - DispatcherTimer.Run(() => + e.Handled = true; + var currentPoint = e.GetCurrentPoint(v); + if (e.RoutedEvent == PointerPressedEvent) + AddPoint(currentPoint.Position, Brushes.Green, 10, currentPoint.Properties.Pressure); + else if (e.RoutedEvent == PointerReleasedEvent) + AddPoint(currentPoint.Position, Brushes.Red, 10, currentPoint.Properties.Pressure); + else { - if (_stopwatch.Elapsed.TotalSeconds > 1) + var pts = e.GetIntermediatePoints(v); + for (var c = 0; c < pts.Count; c++) { - _status.Text = "Events per second: " + (_events / _stopwatch.Elapsed.TotalSeconds); - _stopwatch.Restart(); - _events = 0; + var pt = pts[c]; + AddPoint(pt.Position, c == pts.Count - 1 ? Brushes.Blue : Brushes.Black, + c == pts.Count - 1 ? 5 : 2, pt.Properties.Pressure); } - - return this.GetVisualRoot() != null; - }, TimeSpan.FromMilliseconds(10)); + } } + } + public PointerCanvas(Slider? slider, TextBlock status, bool drawPoints) + { + _slider = slider; + _status = status; + _drawPoints = drawPoints; + } - void HandleEvent(PointerEventArgs e) - { - _events++; - Thread.Sleep((int)_slider.Value); - InvalidateVisual(); + protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) + { + base.OnAttachedToVisualTree(e); - if (e.RoutedEvent == PointerReleasedEvent && e.Pointer.Type == PointerType.Touch) + _statusUpdated = DispatcherTimer.Run(() => + { + if (_stopwatch.Elapsed.TotalSeconds > 1) { - _pointers.Remove(e.Pointer.Id); - return; + _status.Text = $@"Events per second: {(_events / _stopwatch.Elapsed.TotalSeconds)} +PointerUpdateKind: {_lastProperties?.PointerUpdateKind} +IsLeftButtonPressed: {_lastProperties?.IsLeftButtonPressed} +IsRightButtonPressed: {_lastProperties?.IsRightButtonPressed} +IsMiddleButtonPressed: {_lastProperties?.IsMiddleButtonPressed} +IsXButton1Pressed: {_lastProperties?.IsXButton1Pressed} +IsXButton2Pressed: {_lastProperties?.IsXButton2Pressed} +IsBarrelButtonPressed: {_lastProperties?.IsBarrelButtonPressed} +IsEraser: {_lastProperties?.IsEraser} +IsInverted: {_lastProperties?.IsInverted} +Pressure: {_lastProperties?.Pressure} +XTilt: {_lastProperties?.XTilt} +YTilt: {_lastProperties?.YTilt} +Twist: {_lastProperties?.Twist}"; + _stopwatch.Restart(); + _events = 0; } - if (!_pointers.TryGetValue(e.Pointer.Id, out var pt)) - _pointers[e.Pointer.Id] = pt = new PointerPoints(); - pt.HandleEvent(e, this); - - - } - - public override void Render(DrawingContext context) + return true; + }, TimeSpan.FromMilliseconds(10)); + } + + protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e) + { + base.OnDetachedFromVisualTree(e); + + _statusUpdated?.Dispose(); + } + + void HandleEvent(PointerEventArgs e) + { + _events++; + if (_slider != null) { - context.FillRectangle(Brushes.White, Bounds); - foreach(var pt in _pointers.Values) - pt.Render(context); - base.Render(context); + Thread.Sleep((int)_slider.Value); } + InvalidateVisual(); - protected override void OnPointerPressed(PointerPressedEventArgs e) + if (e.RoutedEvent == PointerReleasedEvent && e.Pointer.Type == PointerType.Touch) { - if (e.ClickCount == 2) - { - _pointers.Clear(); - InvalidateVisual(); - return; - } - - HandleEvent(e); - base.OnPointerPressed(e); + _pointers.Remove(e.Pointer.Id); + return; } + + var lastPointer = e.GetCurrentPoint(this); + _lastProperties = lastPointer.Properties; - protected override void OnPointerMoved(PointerEventArgs e) + if (e.Pointer.Type != PointerType.Pen + || lastPointer.Properties.Pressure > 0) { - HandleEvent(e); - base.OnPointerMoved(e); + if (!_pointers.TryGetValue(e.Pointer.Id, out var pt)) + _pointers[e.Pointer.Id] = pt = new PointerPoints(); + pt.HandleEvent(e, this); } + } + + public override void Render(DrawingContext context) + { + context.FillRectangle(Brushes.White, Bounds); + foreach (var pt in _pointers.Values) + pt.Render(context, _drawPoints); + base.Render(context); + } - protected override void OnPointerReleased(PointerReleasedEventArgs e) + protected override void OnPointerPressed(PointerPressedEventArgs e) + { + if (e.ClickCount == 2) { - HandleEvent(e); - base.OnPointerReleased(e); + _pointers.Clear(); + InvalidateVisual(); + return; } + + HandleEvent(e); + base.OnPointerPressed(e); + } + + protected override void OnPointerMoved(PointerEventArgs e) + { + HandleEvent(e); + base.OnPointerMoved(e); + } + + protected override void OnPointerReleased(PointerReleasedEventArgs e) + { + HandleEvent(e); + base.OnPointerReleased(e); } - } } From bef72b3477574e8db361ee22f58cba6354ce435a Mon Sep 17 00:00:00 2001 From: Sergey Mikolaytis Date: Mon, 24 Jan 2022 11:39:13 +0300 Subject: [PATCH 14/78] fix some issues by requests --- src/Avalonia.Controls/TabControl.cs | 6 +-- .../ScrollGestureRecognizer.cs | 3 +- src/Avalonia.Input/MouseDevice.cs | 39 +++++++------------ src/Avalonia.Input/PenDevice.cs | 13 +++---- 4 files changed, 24 insertions(+), 37 deletions(-) diff --git a/src/Avalonia.Controls/TabControl.cs b/src/Avalonia.Controls/TabControl.cs index 955b29f3f9..306a9d3e6a 100644 --- a/src/Avalonia.Controls/TabControl.cs +++ b/src/Avalonia.Controls/TabControl.cs @@ -211,8 +211,7 @@ namespace Avalonia.Controls { base.OnPointerPressed(e); - if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed && - (e.Pointer.Type == PointerType.Mouse || e.Pointer.Type == PointerType.Pen)) + if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed && e.Pointer.Type == PointerType.Mouse) { e.Handled = UpdateSelectionFromEventSource(e.Source); } @@ -220,8 +219,7 @@ namespace Avalonia.Controls protected override void OnPointerReleased(PointerReleasedEventArgs e) { - if (e.InitialPressMouseButton == MouseButton.Left && - (e.Pointer.Type == PointerType.Mouse || e.Pointer.Type == PointerType.Pen)) + if (e.InitialPressMouseButton == MouseButton.Left && e.Pointer.Type != PointerType.Mouse) { var container = GetContainerFromEventSource(e.Source); if (container != null diff --git a/src/Avalonia.Input/GestureRecognizers/ScrollGestureRecognizer.cs b/src/Avalonia.Input/GestureRecognizers/ScrollGestureRecognizer.cs index 1d97fdfe53..889b7e3b82 100644 --- a/src/Avalonia.Input/GestureRecognizers/ScrollGestureRecognizer.cs +++ b/src/Avalonia.Input/GestureRecognizers/ScrollGestureRecognizer.cs @@ -66,7 +66,8 @@ namespace Avalonia.Input.GestureRecognizers public void PointerPressed(PointerPressedEventArgs e) { - if (e.Pointer.IsPrimary && e.Pointer.Type == PointerType.Touch) + if (e.Pointer.IsPrimary && + (e.Pointer.Type == PointerType.Touch || e.Pointer.Type == PointerType.Pen)) { EndGesture(); _tracking = e.Pointer; diff --git a/src/Avalonia.Input/MouseDevice.cs b/src/Avalonia.Input/MouseDevice.cs index 087a806f77..38f63402ba 100644 --- a/src/Avalonia.Input/MouseDevice.cs +++ b/src/Avalonia.Input/MouseDevice.cs @@ -205,31 +205,20 @@ namespace Avalonia.Input PointerPointProperties CreateProperties(RawPointerEventArgs args) { - - var kind = PointerUpdateKind.Other; - - if (args.Type == RawPointerEventType.LeftButtonDown) - kind = PointerUpdateKind.LeftButtonPressed; - if (args.Type == RawPointerEventType.MiddleButtonDown) - kind = PointerUpdateKind.MiddleButtonPressed; - if (args.Type == RawPointerEventType.RightButtonDown) - kind = PointerUpdateKind.RightButtonPressed; - if (args.Type == RawPointerEventType.XButton1Down) - kind = PointerUpdateKind.XButton1Pressed; - if (args.Type == RawPointerEventType.XButton2Down) - kind = PointerUpdateKind.XButton2Pressed; - if (args.Type == RawPointerEventType.LeftButtonUp) - kind = PointerUpdateKind.LeftButtonReleased; - if (args.Type == RawPointerEventType.MiddleButtonUp) - kind = PointerUpdateKind.MiddleButtonReleased; - if (args.Type == RawPointerEventType.RightButtonUp) - kind = PointerUpdateKind.RightButtonReleased; - if (args.Type == RawPointerEventType.XButton1Up) - kind = PointerUpdateKind.XButton1Released; - if (args.Type == RawPointerEventType.XButton2Up) - kind = PointerUpdateKind.XButton2Released; - - return new PointerPointProperties(args.InputModifiers, kind); + return new PointerPointProperties(args.InputModifiers, args.Type switch + { + RawPointerEventType.LeftButtonDown => PointerUpdateKind.LeftButtonPressed, + RawPointerEventType.MiddleButtonDown => PointerUpdateKind.MiddleButtonPressed, + RawPointerEventType.RightButtonDown => PointerUpdateKind.RightButtonPressed, + RawPointerEventType.XButton1Down => PointerUpdateKind.XButton1Pressed, + RawPointerEventType.XButton2Down => PointerUpdateKind.XButton2Pressed, + RawPointerEventType.LeftButtonUp => PointerUpdateKind.LeftButtonReleased, + RawPointerEventType.MiddleButtonUp => PointerUpdateKind.MiddleButtonReleased, + RawPointerEventType.RightButtonUp => PointerUpdateKind.RightButtonReleased, + RawPointerEventType.XButton1Up => PointerUpdateKind.XButton1Released, + RawPointerEventType.XButton2Up => PointerUpdateKind.XButton2Released, + _ => PointerUpdateKind.Other, + }); } private MouseButton _lastMouseDownButton; diff --git a/src/Avalonia.Input/PenDevice.cs b/src/Avalonia.Input/PenDevice.cs index aa4f89bb85..0fef462831 100644 --- a/src/Avalonia.Input/PenDevice.cs +++ b/src/Avalonia.Input/PenDevice.cs @@ -160,13 +160,12 @@ namespace Avalonia.Input private PointerPointProperties CreateProperties(RawPointerEventArgs args) { - var kind = PointerUpdateKind.Other; - - if (args.Type == RawPointerEventType.LeftButtonDown) - kind = PointerUpdateKind.LeftButtonPressed; - if (args.Type == RawPointerEventType.LeftButtonUp) - kind = PointerUpdateKind.LeftButtonReleased; - + var kind = args.Type switch + { + RawPointerEventType.LeftButtonDown => PointerUpdateKind.LeftButtonPressed, + RawPointerEventType.LeftButtonUp => PointerUpdateKind.LeftButtonReleased, + _ => PointerUpdateKind.Other, + }; return new PointerPointProperties(args.InputModifiers, kind, Twist, Pressure, XTilt, YTilt, IsEraser, IsInverted, IsBarrel); } From dc9fc4ab146432c1b07e0af563487c6b53a7a47d Mon Sep 17 00:00:00 2001 From: Sergey Mikolaytis Date: Mon, 24 Jan 2022 12:01:30 +0300 Subject: [PATCH 15/78] Handle Pointer History. Put into intermediate points. --- .../Avalonia.Win32/WindowImpl.AppWndProc.cs | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs index 52981ac7ec..7b5e42e490 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs @@ -402,6 +402,7 @@ namespace Avalonia.Win32 case WindowsMessage.WM_POINTERUPDATE: { GetDevicePointerInfo(wParam, out var device, out var info, ref timestamp); + Point[]? intermediatePoints = null; if (info.historyCount > 1) { @@ -456,6 +457,23 @@ namespace Avalonia.Win32 } } } + else + { + var pointerId = (uint)(ToInt32(wParam) & 0xFFFF); + var historyCount = (int)info.historyCount; + var historyInfos = new POINTER_INFO[historyCount]; + if (GetPointerInfoHistory(pointerId, ref historyCount, historyInfos)) + { + //last info is the same as the current so skip it + intermediatePoints = new Point[historyCount - 1]; + for (int i = 0;i < historyCount - 1; i++) + { + var historyInfo = historyInfos[i]; + intermediatePoints[i] = PointToClient(new PixelPoint( + historyInfo.ptPixelLocationX, historyInfo.ptPixelLocationY)); + } + } + } } var eventType = GetEventType(message, info); @@ -468,11 +486,17 @@ namespace Avalonia.Win32 { break; } - e = new RawTouchEventArgs(_touchDevice, timestamp, _owner, eventType, point, modifiers, info.pointerId); + e = new RawTouchEventArgs(_touchDevice, timestamp, _owner, eventType, point, modifiers, info.pointerId) + { + IntermediatePoints = intermediatePoints + }; } else { - e = new RawPointerEventArgs(device, timestamp, _owner, eventType, point, modifiers); + e = new RawPointerEventArgs(device, timestamp, _owner, eventType, point, modifiers) + { + IntermediatePoints = intermediatePoints + }; } break; } From f04adadc89f04ba881c0c3811786706038059b7e Mon Sep 17 00:00:00 2001 From: Sergey Mikolaytis Date: Mon, 24 Jan 2022 12:52:58 +0300 Subject: [PATCH 16/78] Release mouse capture if pen is close to digitizer. Release pen capture if pen is out of range of digitizer. --- src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs index 7b5e42e490..dd961aec48 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs @@ -381,13 +381,18 @@ namespace Avalonia.Win32 break; } case WindowsMessage.WM_POINTERDEVICEINRANGE: - case WindowsMessage.WM_POINTERDEVICEOUTOFRANGE: { + _mouseDevice.Capture(null); //notifies about proximity of pointer device to the digitizer. //contains pointer id and proximity. //https://docs.microsoft.com/en-us/previous-versions/windows/desktop/inputmsg/wm-pointerdeviceinrange break; } + case WindowsMessage.WM_POINTERDEVICEOUTOFRANGE: + { + _penDevice.Capture(null); + break; + } case WindowsMessage.WM_NCPOINTERUPDATE: { //NC stands for non-client area - window header and window border @@ -545,6 +550,7 @@ namespace Avalonia.Win32 case WindowsMessage.WM_POINTERCAPTURECHANGED: { _mouseDevice.Capture(null); + _penDevice.Capture(null); return IntPtr.Zero; } case WindowsMessage.DM_POINTERHITTEST: From 903685839645adf7aa55e718372b26797c75c25f Mon Sep 17 00:00:00 2001 From: Sergey Mikolaytis Date: Mon, 24 Jan 2022 17:02:22 +0300 Subject: [PATCH 17/78] fix MK_NONE --- src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs index d71efcb074..0431808a43 100644 --- a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs +++ b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs @@ -225,7 +225,7 @@ namespace Avalonia.Win32.Interop [Flags] public enum ModifierKeys { - MK_NONE = 0x0001, + MK_NONE = 0x0000, MK_LBUTTON = 0x0001, MK_RBUTTON = 0x0002, From c646343beee6da4f8568751ffd56bdd2da1f92ff Mon Sep 17 00:00:00 2001 From: Max Katz Date: Sun, 20 Mar 2022 23:54:04 -0400 Subject: [PATCH 18/78] WIP on intermediate points win --- src/Avalonia.Input/PointerEventArgs.cs | 3 +- src/Avalonia.Input/PointerPoint.cs | 17 +++ src/Avalonia.Input/Raw/RawPointerEventArgs.cs | 10 +- .../Avalonia.Win32/WindowImpl.AppWndProc.cs | 141 +++++++++++------- 4 files changed, 112 insertions(+), 59 deletions(-) diff --git a/src/Avalonia.Input/PointerEventArgs.cs b/src/Avalonia.Input/PointerEventArgs.cs index 0604d09dc4..a30c1c51dc 100644 --- a/src/Avalonia.Input/PointerEventArgs.cs +++ b/src/Avalonia.Input/PointerEventArgs.cs @@ -128,7 +128,8 @@ namespace Avalonia.Input for (var c = 0; c < previousPoints.Count; c++) { var pt = previousPoints[c]; - points[c] = new PointerPoint(Pointer, GetPosition(pt.Position, relativeTo), _properties); + var pointProperties = new PointerPointProperties(_properties, pt); + points[c] = new PointerPoint(Pointer, GetPosition(pt.Position, relativeTo), pointProperties); } points[points.Length - 1] = GetCurrentPoint(relativeTo); diff --git a/src/Avalonia.Input/PointerPoint.cs b/src/Avalonia.Input/PointerPoint.cs index 728bb1c579..ba69add7d8 100644 --- a/src/Avalonia.Input/PointerPoint.cs +++ b/src/Avalonia.Input/PointerPoint.cs @@ -84,6 +84,23 @@ namespace Avalonia.Input IsBarrelButtonPressed = isBarrel; } + internal PointerPointProperties(PointerPointProperties basedOn, Raw.RawPointerPoint rawPoint) + { + IsLeftButtonPressed = basedOn.IsLeftButtonPressed; + IsMiddleButtonPressed = basedOn.IsMiddleButtonPressed; + IsRightButtonPressed = basedOn.IsRightButtonPressed; + IsXButton1Pressed = basedOn.IsXButton1Pressed; + IsXButton2Pressed = basedOn.IsXButton2Pressed; + IsInverted = basedOn.IsInverted; + IsEraser = basedOn.IsEraser; + IsBarrelButtonPressed = basedOn.IsBarrelButtonPressed; + + Twist = rawPoint.Twist; + Pressure = rawPoint.Pressure; + XTilt = rawPoint.XTilt; + YTilt = rawPoint.YTilt; + } + public static PointerPointProperties None { get; } = new PointerPointProperties(); } diff --git a/src/Avalonia.Input/Raw/RawPointerEventArgs.cs b/src/Avalonia.Input/Raw/RawPointerEventArgs.cs index c157fa059c..cd99cdc23b 100644 --- a/src/Avalonia.Input/Raw/RawPointerEventArgs.cs +++ b/src/Avalonia.Input/Raw/RawPointerEventArgs.cs @@ -128,10 +128,16 @@ namespace Avalonia.Input.Raw /// Pointer position, in client DIPs. /// public Point Position { get; set; } - + + public float Twist { get; set; } + public float Pressure { get; set; } + public float XTilt { get; set; } + public float YTilt { get; set; } + + public RawPointerPoint() { - Position = default; + this = default; } } } diff --git a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs index 1ef3cbaba2..5c17caa13b 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs @@ -1,4 +1,6 @@ using System; +using System.Buffers; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Runtime.InteropServices; using System.Text; @@ -413,78 +415,105 @@ namespace Avalonia.Win32 case WindowsMessage.WM_POINTERUPDATE: { GetDevicePointerInfo(wParam, out var device, out var info, ref timestamp); - Point[]? intermediatePoints = null; + if (info.pointerType == PointerInputType.PT_TOUCH + && ShouldIgnoreTouchEmulatedMessage()) + { + break; + } + var historyCount = (int)info.historyCount; + Lazy> intermediatePoints = null; if (info.historyCount > 1) { - if (info.pointerType == PointerInputType.PT_TOUCH) + intermediatePoints = new Lazy>(() => { - if (ShouldIgnoreTouchEmulatedMessage()) + var list = new List(historyCount - 1); + if (info.pointerType == PointerInputType.PT_TOUCH) { - break; - } - - var pointerId = (uint)(ToInt32(wParam) & 0xFFFF); - var historyCount = (int)info.historyCount; - var historyTouchInfos = new POINTER_TOUCH_INFO[historyCount]; - if (GetPointerTouchInfoHistory(pointerId, ref historyCount, historyTouchInfos)) - { - //last info is the same as the current so skip it - for (int i = 0; i < historyCount - 1; i++) + var pointerId = (uint)(ToInt32(wParam) & 0xFFFF); + var historyTouchInfos = ArrayPool.Shared.Rent(historyCount); + try + { + if (GetPointerTouchInfoHistory(pointerId, ref historyCount, historyTouchInfos)) + { + //last info is the same as the current so skip it + for (int i = 0; i < historyCount - 1; i++) + { + var historyTouchInfo = historyTouchInfos[i]; + var historyInfo = historyTouchInfo.pointerInfo; + var historyPoint = PointToClient(new PixelPoint( + historyInfo.ptPixelLocationX, historyInfo.ptPixelLocationY)); + list.Add(new RawPointerPoint + { + Position = historyPoint, + }); + } + } + } + finally { - var historyTouchInfo = historyTouchInfos[i]; - var historyInfo = historyTouchInfo.pointerInfo; - var historyEventType = GetEventType(message, historyInfo); - var historyPoint = PointToClient(new PixelPoint( - historyInfo.ptPixelLocationX, historyInfo.ptPixelLocationY)); - var historyModifiers = GetInputModifiers(historyInfo.dwKeyStates); - var historyTimestamp = historyInfo.dwTime == 0 ? timestamp : historyInfo.dwTime; - Input?.Invoke(new RawTouchEventArgs(_touchDevice, historyTimestamp, _owner, - historyEventType, historyPoint, historyModifiers, historyInfo.pointerId)); + ArrayPool.Shared.Return(historyTouchInfos); } } - } - else if (info.pointerType == PointerInputType.PT_PEN) - { - var pointerId = (uint)(ToInt32(wParam) & 0xFFFF); - var historyCount = (int)info.historyCount; - var historyPenInfos = new POINTER_PEN_INFO[historyCount]; - if (GetPointerPenInfoHistory(pointerId, ref historyCount, historyPenInfos)) + else if (info.pointerType == PointerInputType.PT_PEN) { - //last info is the same as the current so skip it - for (int i = 0; i < historyCount - 1; i++) + var pointerId = (uint)(ToInt32(wParam) & 0xFFFF); + var historyPenInfos = ArrayPool.Shared.Rent(historyCount); + try { - var historyPenInfo = historyPenInfos[i]; - var historyInfo = historyPenInfo.pointerInfo; - var historyEventType = GetEventType(message, historyInfo); - var historyPoint = PointToClient(new PixelPoint( - historyInfo.ptPixelLocationX, historyInfo.ptPixelLocationY)); - var historyModifiers = GetInputModifiers(historyInfo.dwKeyStates); - var historyTimestamp = historyInfo.dwTime == 0 ? timestamp : historyInfo.dwTime; - - ApplyPenInfo(historyPenInfo); - Input?.Invoke(new RawPointerEventArgs(_penDevice, historyTimestamp, _owner, - historyEventType, historyPoint, historyModifiers)); + if (GetPointerPenInfoHistory(pointerId, ref historyCount, historyPenInfos)) + { + //last info is the same as the current so skip it + for (int i = 0; i < historyCount - 1; i++) + { + var historyPenInfo = historyPenInfos[i]; + var historyInfo = historyPenInfo.pointerInfo; + var historyPoint = PointToClient(new PixelPoint( + historyInfo.ptPixelLocationX, historyInfo.ptPixelLocationY)); + list.Add(new RawPointerPoint + { + Position = historyPoint, + Pressure = historyPenInfo.pressure, + Twist = historyPenInfo.rotation, + XTilt = historyPenInfo.tiltX, + YTilt = historyPenInfo.tiltX + }); + } + } + } + finally + { + ArrayPool.Shared.Return(historyPenInfos); } } - } - else - { - var pointerId = (uint)(ToInt32(wParam) & 0xFFFF); - var historyCount = (int)info.historyCount; - var historyInfos = new POINTER_INFO[historyCount]; - if (GetPointerInfoHistory(pointerId, ref historyCount, historyInfos)) + else { - //last info is the same as the current so skip it - intermediatePoints = new Point[historyCount - 1]; - for (int i = 0;i < historyCount - 1; i++) + var pointerId = (uint)(ToInt32(wParam) & 0xFFFF); + var historyInfos = ArrayPool.Shared.Rent(historyCount); + try + { + if (GetPointerInfoHistory(pointerId, ref historyCount, historyInfos)) + { + //last info is the same as the current so skip it + for (int i = 0; i < historyCount - 1; i++) + { + var historyInfo = historyInfos[i]; + var historyPoint = PointToClient(new PixelPoint( + historyInfo.ptPixelLocationX, historyInfo.ptPixelLocationY)); + list.Add(new RawPointerPoint + { + Position = historyPoint + }); + } + } + } + finally { - var historyInfo = historyInfos[i]; - intermediatePoints[i] = PointToClient(new PixelPoint( - historyInfo.ptPixelLocationX, historyInfo.ptPixelLocationY)); + ArrayPool.Shared.Return(historyInfos); } } - } + return list; + }); } var eventType = GetEventType(message, info); From d8f7dc5d1f2200a114404f9ed9cc7f34a58d0091 Mon Sep 17 00:00:00 2001 From: Max Katz Date: Thu, 24 Mar 2022 20:28:56 -0400 Subject: [PATCH 19/78] Make EnableWmPointerEvents optional --- src/Windows/Avalonia.Win32/Win32Platform.cs | 9 +++ .../Avalonia.Win32/WindowImpl.AppWndProc.cs | 66 +++++++++++++------ src/Windows/Avalonia.Win32/WindowImpl.cs | 14 ++-- 3 files changed, 61 insertions(+), 28 deletions(-) diff --git a/src/Windows/Avalonia.Win32/Win32Platform.cs b/src/Windows/Avalonia.Win32/Win32Platform.cs index 5cfbab40e4..25a6717122 100644 --- a/src/Windows/Avalonia.Win32/Win32Platform.cs +++ b/src/Windows/Avalonia.Win32/Win32Platform.cs @@ -63,8 +63,17 @@ namespace Avalonia /// /// Multitouch allows a surface (a touchpad or touchscreen) to recognize the presence of more than one point of contact with the surface at the same time. /// + [Obsolete("Multitouch is always enabled")] public bool? EnableMultitouch { get; set; } = true; + /// + /// Enables Win8+ WM_POINTER events support. The default value is false. + /// + /// + /// Required for extended Pen and Touch support. + /// + public bool? EnableWmPointerEvents { get; set; } = false; + /// /// Embeds popups to the window when set to true. The default value is false. /// diff --git a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs index 5c17caa13b..d52115425f 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs @@ -174,7 +174,7 @@ namespace Avalonia.Win32 case WindowsMessage.WM_MBUTTONDOWN: case WindowsMessage.WM_XBUTTONDOWN: { - if (Win8Plus) + if (_wmPointerEnabled) { break; } @@ -207,7 +207,7 @@ namespace Avalonia.Win32 case WindowsMessage.WM_MBUTTONUP: case WindowsMessage.WM_XBUTTONUP: { - if (Win8Plus) + if (_wmPointerEnabled) { break; } @@ -240,7 +240,7 @@ namespace Avalonia.Win32 case WindowsMessage.WM_MOUSEMOVE: { - if (Win8Plus) + if (_wmPointerEnabled) { break; } @@ -275,7 +275,7 @@ namespace Avalonia.Win32 case WindowsMessage.WM_MOUSEWHEEL: { - if (Win8Plus) + if (_wmPointerEnabled) { break; } @@ -291,7 +291,7 @@ namespace Avalonia.Win32 case WindowsMessage.WM_MOUSEHWHEEL: { - if (Win8Plus) + if (_wmPointerEnabled) { break; } @@ -307,7 +307,7 @@ namespace Avalonia.Win32 case WindowsMessage.WM_MOUSELEAVE: { - if (Win8Plus) + if (_wmPointerEnabled) { break; } @@ -327,7 +327,7 @@ namespace Avalonia.Win32 case WindowsMessage.WM_NCMBUTTONDOWN: case WindowsMessage.WM_NCXBUTTONDOWN: { - if (Win8Plus) + if (_wmPointerEnabled) { break; } @@ -351,7 +351,7 @@ namespace Avalonia.Win32 } case WindowsMessage.WM_TOUCH: { - if (Win8Plus) + if (_wmPointerEnabled) { break; } @@ -384,12 +384,20 @@ namespace Avalonia.Win32 } case WindowsMessage.WM_POINTERDEVICECHANGE: { + if (!_wmPointerEnabled) + { + break; + } //notifies about changes in the settings of a monitor that has a digitizer attached to it. //https://docs.microsoft.com/en-us/previous-versions/windows/desktop/inputmsg/wm-pointerdevicechange break; } case WindowsMessage.WM_POINTERDEVICEINRANGE: { + if (!_wmPointerEnabled) + { + break; + } _mouseDevice.Capture(null); //notifies about proximity of pointer device to the digitizer. //contains pointer id and proximity. @@ -398,11 +406,19 @@ namespace Avalonia.Win32 } case WindowsMessage.WM_POINTERDEVICEOUTOFRANGE: { + if (!_wmPointerEnabled) + { + break; + } _penDevice.Capture(null); break; } case WindowsMessage.WM_NCPOINTERUPDATE: { + if (!_wmPointerEnabled) + { + break; + } //NC stands for non-client area - window header and window border //As I found above in an old message handling - we dont need to handle NC pointer move/updates. //All we need is pointer down and up. So this is skipped for now. @@ -415,8 +431,7 @@ namespace Avalonia.Win32 case WindowsMessage.WM_POINTERUPDATE: { GetDevicePointerInfo(wParam, out var device, out var info, ref timestamp); - if (info.pointerType == PointerInputType.PT_TOUCH - && ShouldIgnoreTouchEmulatedMessage()) + if (!_wmPointerEnabled) { break; } @@ -522,10 +537,6 @@ namespace Avalonia.Win32 if (device is TouchDevice) { - if (ShouldIgnoreTouchEmulatedMessage()) - { - break; - } e = new RawTouchEventArgs(_touchDevice, timestamp, _owner, eventType, point, modifiers, info.pointerId) { IntermediatePoints = intermediatePoints @@ -542,6 +553,10 @@ namespace Avalonia.Win32 } case WindowsMessage.WM_POINTERENTER: { + if (!_wmPointerEnabled) + { + break; + } //this is not handled by WM_MOUSEENTER so I think there is no need to handle this too. //but we can detect a new pointer by this message and calling IS_POINTER_NEW_WPARAM @@ -552,6 +567,10 @@ namespace Avalonia.Win32 case WindowsMessage.WM_POINTERLEAVE: { GetDevicePointerInfo(wParam, out var device, out var info, ref timestamp); + if (!_wmPointerEnabled) + { + break; + } if (device is TouchDevice) { break; @@ -567,6 +586,10 @@ namespace Avalonia.Win32 case WindowsMessage.WM_POINTERHWHEEL: { GetDevicePointerInfo(wParam, out var device, out var info, ref timestamp); + if (!_wmPointerEnabled) + { + break; + } var point = PointToClient(new PixelPoint(info.ptPixelLocationX, info.ptPixelLocationY)); var modifiers = GetInputModifiers(info.dwKeyStates); @@ -577,6 +600,10 @@ namespace Avalonia.Win32 } case WindowsMessage.WM_POINTERACTIVATE: { + if (!_wmPointerEnabled) + { + break; + } //occurs when a pointer activates an inactive window. //we should handle this and return PA_ACTIVATE or PA_NOACTIVATE //https://docs.microsoft.com/en-us/previous-versions/windows/desktop/inputmsg/wm-pointeractivate @@ -584,6 +611,10 @@ namespace Avalonia.Win32 } case WindowsMessage.WM_POINTERCAPTURECHANGED: { + if (!_wmPointerEnabled) + { + break; + } _mouseDevice.Capture(null); _penDevice.Capture(null); return IntPtr.Zero; @@ -913,8 +944,6 @@ namespace Avalonia.Win32 }; } - public readonly bool Win8Plus = Win32Platform.WindowsVersion >= PlatformConstants.Windows8; - private void UpdateInputMethod(IntPtr hkl) { // note: for non-ime language, also create it so that emoji panel tracks cursor @@ -951,10 +980,7 @@ namespace Avalonia.Win32 private bool ShouldIgnoreTouchEmulatedMessage() { - if (!_multitouch) - { - return false; - } + // Note: GetMessageExtraInfo doesn't work with WM_POINTER events. // MI_WP_SIGNATURE // https://docs.microsoft.com/en-us/windows/win32/tablet/system-events-and-mouse-messages diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index becbbe7561..53dde352f7 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -75,7 +75,7 @@ namespace Avalonia.Win32 private WndProc _wndProcDelegate; private string _className; private IntPtr _hwnd; - private bool _multitouch; + private bool _wmPointerEnabled; private IInputRoot _owner; private WindowProperties _windowProperties; private bool _trackingMouse;//ToDo - there is something missed. Needs investigation @Steven Kirk @@ -128,7 +128,10 @@ namespace Avalonia.Win32 egl.Display is AngleWin32EglDisplay angleDisplay && angleDisplay.PlatformApi == AngleOptions.PlatformApi.DirectX11; - if (Win8Plus && !IsMouseInPointerEnabled()) + _wmPointerEnabled = Win32Platform.Options.EnableWmPointerEvents + ?? Win32Platform.WindowsVersion >= PlatformConstants.Windows8; + + if (_wmPointerEnabled && !IsMouseInPointerEnabled()) { EnableMouseInPointer(true); } @@ -795,12 +798,7 @@ namespace Avalonia.Win32 Handle = new WindowImplPlatformHandle(this); - _multitouch = Win32Platform.Options.EnableMultitouch ?? true; - - if (_multitouch) - { - RegisterTouchWindow(_hwnd, 0); - } + RegisterTouchWindow(_hwnd, 0); if (ShCoreAvailable && Win32Platform.WindowsVersion > PlatformConstants.Windows8) { From b599f295f6b94d01bec4d267bc6759da1d69833c Mon Sep 17 00:00:00 2001 From: Max Katz Date: Sat, 16 Apr 2022 01:10:45 -0400 Subject: [PATCH 20/78] Add RawPointerId to the RawPointerEventArgs --- src/Avalonia.Input/Raw/RawPointerEventArgs.cs | 5 ++++ src/Avalonia.Input/Raw/RawTouchEventArgs.cs | 17 ++++++++++--- src/Avalonia.Input/TouchDevice.cs | 13 +++++----- src/Shared/RawEventGrouping.cs | 12 ++++------ .../TouchDeviceTests.cs | 24 ++++++++++++------- 5 files changed, 45 insertions(+), 26 deletions(-) diff --git a/src/Avalonia.Input/Raw/RawPointerEventArgs.cs b/src/Avalonia.Input/Raw/RawPointerEventArgs.cs index 58ea076379..1faa20fbf1 100644 --- a/src/Avalonia.Input/Raw/RawPointerEventArgs.cs +++ b/src/Avalonia.Input/Raw/RawPointerEventArgs.cs @@ -87,6 +87,11 @@ namespace Avalonia.Input.Raw InputModifiers = inputModifiers; } + /// + /// Gets the raw pointer identifier. + /// + public long RawPointerId { get; set; } + /// /// Gets the pointer properties and position, in client DIPs. /// diff --git a/src/Avalonia.Input/Raw/RawTouchEventArgs.cs b/src/Avalonia.Input/Raw/RawTouchEventArgs.cs index 020b40e55b..6706a45f48 100644 --- a/src/Avalonia.Input/Raw/RawTouchEventArgs.cs +++ b/src/Avalonia.Input/Raw/RawTouchEventArgs.cs @@ -1,15 +1,26 @@ +using System; + namespace Avalonia.Input.Raw { public class RawTouchEventArgs : RawPointerEventArgs { public RawTouchEventArgs(IInputDevice device, ulong timestamp, IInputRoot root, RawPointerEventType type, Point position, RawInputModifiers inputModifiers, - long touchPointId) + long rawPointerId) : base(device, timestamp, root, type, position, inputModifiers) { - TouchPointId = touchPointId; + RawPointerId = rawPointerId; + } + + public RawTouchEventArgs(IInputDevice device, ulong timestamp, IInputRoot root, + RawPointerEventType type, RawPointerPoint point, RawInputModifiers inputModifiers, + long rawPointerId) + : base(device, timestamp, root, type, point, inputModifiers) + { + RawPointerId = rawPointerId; } - public long TouchPointId { get; set; } + [Obsolete("Use RawPointerId")] + public long TouchPointId { get => RawPointerId; set => RawPointerId = value; } } } diff --git a/src/Avalonia.Input/TouchDevice.cs b/src/Avalonia.Input/TouchDevice.cs index 54dcc4051e..e914d860fd 100644 --- a/src/Avalonia.Input/TouchDevice.cs +++ b/src/Avalonia.Input/TouchDevice.cs @@ -40,14 +40,14 @@ namespace Avalonia.Input { if (ev.Handled || _disposed) return; - var args = (RawTouchEventArgs)ev; - if (!_pointers.TryGetValue(args.TouchPointId, out var pointer)) + var args = (RawPointerEventArgs)ev; + if (!_pointers.TryGetValue(args.RawPointerId, out var pointer)) { if (args.Type == RawPointerEventType.TouchEnd) return; var hit = args.InputHitTestResult; - _pointers[args.TouchPointId] = pointer = new Pointer(Pointer.GetNextFreeId(), + _pointers[args.RawPointerId] = pointer = new Pointer(Pointer.GetNextFreeId(), PointerType.Touch, _pointers.Count == 0); pointer.Capture(hit); } @@ -88,7 +88,7 @@ namespace Avalonia.Input if (args.Type == RawPointerEventType.TouchEnd) { - _pointers.Remove(args.TouchPointId); + _pointers.Remove(args.RawPointerId); using (pointer) { target.RaiseEvent(new PointerReleasedEventArgs(target, pointer, @@ -101,7 +101,7 @@ namespace Avalonia.Input if (args.Type == RawPointerEventType.TouchCancel) { - _pointers.Remove(args.TouchPointId); + _pointers.Remove(args.RawPointerId); using (pointer) pointer.Capture(null); _lastPointer = null; @@ -129,8 +129,7 @@ namespace Avalonia.Input public IPointer? TryGetPointer(RawPointerEventArgs ev) { - return ev is RawTouchEventArgs args - && _pointers.TryGetValue(args.TouchPointId, out var pointer) + return _pointers.TryGetValue(ev.RawPointerId, out var pointer) ? pointer : null; } diff --git a/src/Shared/RawEventGrouping.cs b/src/Shared/RawEventGrouping.cs index 084593ffc6..966744888c 100644 --- a/src/Shared/RawEventGrouping.cs +++ b/src/Shared/RawEventGrouping.cs @@ -2,10 +2,8 @@ using System; using System.Collections.Generic; using Avalonia.Collections.Pooled; -using Avalonia.Input; using Avalonia.Input.Raw; using Avalonia.Threading; -using JetBrains.Annotations; namespace Avalonia; @@ -19,7 +17,7 @@ internal class RawEventGrouper : IDisposable private readonly Action _eventCallback; private readonly Queue _inputQueue = new(); private readonly Action _dispatchFromQueue; - readonly Dictionary _lastTouchPoints = new(); + readonly Dictionary _lastTouchPoints = new(); RawInputEventArgs? _lastEvent; public RawEventGrouper(Action eventCallback) @@ -49,7 +47,7 @@ internal class RawEventGrouper : IDisposable _lastEvent = null; if (ev is RawTouchEventArgs { Type: RawPointerEventType.TouchUpdate } touchUpdate) - _lastTouchPoints.Remove(touchUpdate.TouchPointId); + _lastTouchPoints.Remove(touchUpdate.RawPointerId); _eventCallback?.Invoke(ev); @@ -88,11 +86,11 @@ internal class RawEventGrouper : IDisposable { if (args is RawTouchEventArgs touchEvent) { - if (_lastTouchPoints.TryGetValue(touchEvent.TouchPointId, out var lastTouchEvent)) + if (_lastTouchPoints.TryGetValue(touchEvent.RawPointerId, out var lastTouchEvent)) MergeEvents(lastTouchEvent, touchEvent); else { - _lastTouchPoints[touchEvent.TouchPointId] = touchEvent; + _lastTouchPoints[touchEvent.RawPointerId] = touchEvent; AddToQueue(touchEvent); } } @@ -105,7 +103,7 @@ internal class RawEventGrouper : IDisposable { _lastTouchPoints.Clear(); if (args is RawTouchEventArgs { Type: RawPointerEventType.TouchUpdate } touchEvent) - _lastTouchPoints[touchEvent.TouchPointId] = touchEvent; + _lastTouchPoints[touchEvent.RawPointerId] = touchEvent; } AddToQueue(args); } diff --git a/tests/Avalonia.Input.UnitTests/TouchDeviceTests.cs b/tests/Avalonia.Input.UnitTests/TouchDeviceTests.cs index 80c5a45c1a..7b7d547346 100644 --- a/tests/Avalonia.Input.UnitTests/TouchDeviceTests.cs +++ b/tests/Avalonia.Input.UnitTests/TouchDeviceTests.cs @@ -219,30 +219,36 @@ namespace Avalonia.Input.UnitTests { for (int i = 0; i < touchPointIds.Length; i++) { - inputManager.ProcessInput(new RawTouchEventArgs(device, 0, + inputManager.ProcessInput(new RawPointerEventArgs(device, 0, root, type, new Point(0, 0), - RawInputModifiers.None, - touchPointIds[i])); + RawInputModifiers.None) + { + RawPointerId = touchPointIds[i] + }); } } private static void TapOnce(IInputManager inputManager, TouchDevice device, IInputRoot root, ulong timestamp = 0, long touchPointId = 0) { - inputManager.ProcessInput(new RawTouchEventArgs(device, timestamp, + inputManager.ProcessInput(new RawPointerEventArgs(device, timestamp, root, RawPointerEventType.TouchBegin, new Point(0, 0), - RawInputModifiers.None, - touchPointId)); - inputManager.ProcessInput(new RawTouchEventArgs(device, timestamp, + RawInputModifiers.None) + { + RawPointerId = touchPointId + }); + inputManager.ProcessInput(new RawPointerEventArgs(device, timestamp, root, RawPointerEventType.TouchEnd, new Point(0, 0), - RawInputModifiers.None, - touchPointId)); + RawInputModifiers.None) + { + RawPointerId = touchPointId + }); } } } From afb828d4ff3aac67f122b2badd6d5c7399c9081b Mon Sep 17 00:00:00 2001 From: Max Katz Date: Sat, 16 Apr 2022 04:00:29 -0400 Subject: [PATCH 21/78] Move IntermediatePoints creation and update RawInputModifiers --- src/Avalonia.Input/IKeyboardDevice.cs | 7 +- src/Avalonia.Input/PenDevice.cs | 404 ++++-------------- src/Avalonia.Input/PointerPoint.cs | 12 +- src/Avalonia.Input/Raw/RawPointerEventArgs.cs | 4 +- .../Avalonia.Win32/WindowImpl.AppWndProc.cs | 379 ++++++++-------- src/Windows/Avalonia.Win32/WindowImpl.cs | 7 + 6 files changed, 278 insertions(+), 535 deletions(-) diff --git a/src/Avalonia.Input/IKeyboardDevice.cs b/src/Avalonia.Input/IKeyboardDevice.cs index d0e84e5ad0..1b9a056272 100644 --- a/src/Avalonia.Input/IKeyboardDevice.cs +++ b/src/Avalonia.Input/IKeyboardDevice.cs @@ -42,12 +42,17 @@ namespace Avalonia.Input Control = 2, Shift = 4, Meta = 8, + LeftMouseButton = 16, RightMouseButton = 32, MiddleMouseButton = 64, XButton1MouseButton = 128, XButton2MouseButton = 256, - KeyboardMask = Alt | Control | Shift | Meta + KeyboardMask = Alt | Control | Shift | Meta, + + PenInverted = 512, + PenEraser = 1024, + PenBarrelButton = 2048 } public interface IKeyboardDevice : IInputDevice, INotifyPropertyChanged diff --git a/src/Avalonia.Input/PenDevice.cs b/src/Avalonia.Input/PenDevice.cs index 0fef462831..d22b48562c 100644 --- a/src/Avalonia.Input/PenDevice.cs +++ b/src/Avalonia.Input/PenDevice.cs @@ -1,8 +1,8 @@ using System; +using System.Collections.Generic; using System.Linq; using System.Reactive.Linq; using Avalonia.Input.Raw; -using Avalonia.Interactivity; using Avalonia.Platform; using Avalonia.VisualTree; @@ -13,72 +13,14 @@ namespace Avalonia.Input /// public class PenDevice : IPenDevice, IDisposable { + private readonly Dictionary _pointers = new(); + private readonly Dictionary _lastPositions = new(); private int _clickCount; private Rect _lastClickRect; private ulong _lastClickTime; + private MouseButton _lastMouseDownButton; - private readonly Pointer _pointer; private bool _disposed; - private PixelPoint? _position; - - public PenDevice(Pointer? pointer = null) - { - _pointer = pointer ?? new Pointer(Pointer.GetNextFreeId(), PointerType.Pen, true); - } - - /// - /// Gets the control that is currently capturing by the mouse, if any. - /// - /// - /// When an element captures the mouse, it receives mouse input whether the cursor is - /// within the control's bounds or not. To set the mouse capture, call the - /// method. - /// - [Obsolete("Use IPointer instead")] - public IInputElement? Captured => _pointer.Captured; - - public bool IsEraser { get; set; } - public bool IsInverted { get; set; } - public bool IsBarrel { get; set; } - public int XTilt { get; set; } - public int YTilt { get; set; } - public uint Pressure { get; set; } - public uint Twist { get; set; } - - /// - /// Captures mouse input to the specified control. - /// - /// The control. - /// - /// When an element captures the mouse, it receives mouse input whether the cursor is - /// within the control's bounds or not. The current mouse capture control is exposed - /// by the property. - /// - public void Capture(IInputElement? control) - { - _pointer.Capture(control); - } - - /// - /// Gets the mouse position relative to a control. - /// - /// The control. - /// The mouse position in the control's coordinates. - public Point GetPosition(IVisual relativeTo) - { - relativeTo = relativeTo ?? throw new ArgumentNullException(nameof(relativeTo)); - - if (relativeTo.VisualRoot == null) - { - throw new InvalidOperationException("Control is not attached to visual tree."); - } - -#pragma warning disable CS0618 // Type or member is obsolete - var rootPoint = relativeTo.VisualRoot.PointToClient(_position ?? new PixelPoint(-1, -1)); -#pragma warning restore CS0618 // Type or member is obsolete - var transform = relativeTo.VisualRoot.TransformToVisual(relativeTo); - return rootPoint * transform!.Value; - } public void ProcessRawEvent(RawInputEventArgs e) { @@ -86,151 +28,93 @@ namespace Avalonia.Input ProcessRawEvent(margs); } - public void TopLevelClosed(IInputRoot root) + private void ProcessRawEvent(RawPointerEventArgs e) { - ClearPointerOver(this, 0, root, PointerPointProperties.None, KeyModifiers.None); - } + e = e ?? throw new ArgumentNullException(nameof(e)); - public void SceneInvalidated(IInputRoot root, Rect rect) - { - // Pointer is outside of the target area - if (_position == null ) + if (!_pointers.TryGetValue(e.RawPointerId, out var pointer)) { - if (root.PointerOverElement != null) - ClearPointerOver(this, 0, root, PointerPointProperties.None, KeyModifiers.None); - return; - } - - - var clientPoint = root.PointToClient(_position.Value); + if (e.Type == RawPointerEventType.LeftButtonUp + || e.Type == RawPointerEventType.TouchEnd) + return; - if (rect.Contains(clientPoint)) - { - if (_pointer.Captured == null) - { - SetPointerOver(this, 0 /* TODO: proper timestamp */, root, clientPoint, - PointerPointProperties.None, KeyModifiers.None); - } - else - { - SetPointerOver(this, 0 /* TODO: proper timestamp */, root, _pointer.Captured, - PointerPointProperties.None, KeyModifiers.None); - } + _pointers[e.RawPointerId] = pointer = new Pointer(Pointer.GetNextFreeId(), + PointerType.Pen, _pointers.Count == 0); } - } - - private void ProcessRawEvent(RawPointerEventArgs e) - { - e = e ?? throw new ArgumentNullException(nameof(e)); - var pen = (PenDevice)e.Device; - if(pen._disposed) - return; + _lastPositions[e.RawPointerId] = e.Root.PointToScreen(e.Position); + + var props = new PointerPointProperties(e.InputModifiers, e.Type.ToUpdateKind(), + e.Point.Twist, e.Point.Pressure, e.Point.XTilt, e.Point.YTilt); + var keyModifiers = e.InputModifiers.ToKeyModifiers(); - _position = e.Root.PointToScreen(e.Position); - var props = CreateProperties(e); - var keyModifiers = KeyModifiersUtils.ConvertToKey(e.InputModifiers); + bool shouldReleasePointer = false; switch (e.Type) { case RawPointerEventType.LeaveWindow: - LeaveWindow(pen, e.Timestamp, e.Root, props, keyModifiers); + shouldReleasePointer = true; break; case RawPointerEventType.LeftButtonDown: - e.Handled = PenDown(pen, e.Timestamp, e.Root, e.Position, props, keyModifiers); + e.Handled = PenDown(pointer, e.Timestamp, e.Root, e.Position, props, keyModifiers, e.InputHitTestResult); break; case RawPointerEventType.LeftButtonUp: - e.Handled = PenUp(pen, e.Timestamp, e.Root, e.Position, props, keyModifiers); + e.Handled = PenUp(pointer, e.Timestamp, e.Root, e.Position, props, keyModifiers, e.InputHitTestResult); break; case RawPointerEventType.Move: - e.Handled = PenMove(pen, e.Timestamp, e.Root, e.Position, props, keyModifiers); + e.Handled = PenMove(pointer, e.Timestamp, e.Root, e.Position, props, keyModifiers, e.InputHitTestResult, e.IntermediatePoints); break; } - } - - private void LeaveWindow(IPenDevice device, ulong timestamp, IInputRoot root, PointerPointProperties properties, - KeyModifiers inputModifiers) - { - device = device ?? throw new ArgumentNullException(nameof(device)); - root = root ?? throw new ArgumentNullException(nameof(root)); - - _position = null; - ClearPointerOver(this, timestamp, root, properties, inputModifiers); - } - - private PointerPointProperties CreateProperties(RawPointerEventArgs args) - { - var kind = args.Type switch + if (shouldReleasePointer) { - RawPointerEventType.LeftButtonDown => PointerUpdateKind.LeftButtonPressed, - RawPointerEventType.LeftButtonUp => PointerUpdateKind.LeftButtonReleased, - _ => PointerUpdateKind.Other, - }; - return new PointerPointProperties(args.InputModifiers, kind, - Twist, Pressure, XTilt, YTilt, IsEraser, IsInverted, IsBarrel); + pointer.Dispose(); + _pointers.Remove(e.RawPointerId); + _lastPositions.Remove(e.RawPointerId); + } } - private MouseButton _lastMouseDownButton; - private bool PenDown(IPenDevice device, ulong timestamp, IInputElement root, Point p, - PointerPointProperties properties, - KeyModifiers inputModifiers) + private bool PenDown(Pointer pointer, ulong timestamp, + IInputElement root, Point p, PointerPointProperties properties, + KeyModifiers inputModifiers, IInputElement? hitTest) { - device = device ?? throw new ArgumentNullException(nameof(device)); - root = root ?? throw new ArgumentNullException(nameof(root)); - - var hit = HitTest(root, p); + var source = pointer.Captured ?? hitTest; - if (hit != null) + if (source != null) { - _pointer.Capture(hit); - var source = GetSource(hit); - if (source != null) - { - var settings = AvaloniaLocator.Current.GetService(); - var doubleClickTime = settings?.DoubleClickTime.TotalMilliseconds ?? 500; - var doubleClickSize = settings?.DoubleClickSize ?? new Size(4, 4); - - if (!_lastClickRect.Contains(p) || timestamp - _lastClickTime > doubleClickTime) - { - _clickCount = 0; - } + pointer.Capture(source); + var settings = AvaloniaLocator.Current.GetService(); + var doubleClickTime = settings?.DoubleClickTime.TotalMilliseconds ?? 500; + var doubleClickSize = settings?.DoubleClickSize ?? new Size(4, 4); - ++_clickCount; - _lastClickTime = timestamp; - _lastClickRect = new Rect(p, new Size()) - .Inflate(new Thickness(doubleClickSize.Width / 2, doubleClickSize.Height / 2)); - _lastMouseDownButton = properties.PointerUpdateKind.GetMouseButton(); - var e = new PointerPressedEventArgs(source, _pointer, root, p, timestamp, properties, inputModifiers, _clickCount); - source.RaiseEvent(e); - return e.Handled; + if (!_lastClickRect.Contains(p) || timestamp - _lastClickTime > doubleClickTime) + { + _clickCount = 0; } + + ++_clickCount; + _lastClickTime = timestamp; + _lastClickRect = new Rect(p, new Size()) + .Inflate(new Thickness(doubleClickSize.Width / 2, doubleClickSize.Height / 2)); + _lastMouseDownButton = properties.PointerUpdateKind.GetMouseButton(); + var e = new PointerPressedEventArgs(source, pointer, root, p, timestamp, properties, inputModifiers, _clickCount); + source.RaiseEvent(e); + return e.Handled; } return false; } - private bool PenMove(IPenDevice device, ulong timestamp, IInputRoot root, Point p, PointerPointProperties properties, - KeyModifiers inputModifiers) + private bool PenMove(Pointer pointer, ulong timestamp, + IInputRoot root, Point p, PointerPointProperties properties, + KeyModifiers inputModifiers, IInputElement? hitTest, + Lazy?>? intermediatePoints) { - device = device ?? throw new ArgumentNullException(nameof(device)); - root = root ?? throw new ArgumentNullException(nameof(root)); - - IInputElement? source; - - if (_pointer.Captured == null) - { - source = SetPointerOver(this, timestamp, root, p, properties, inputModifiers); - } - else - { - SetPointerOver(this, timestamp, root, _pointer.Captured, properties, inputModifiers); - source = _pointer.Captured; - } + var source = pointer.Captured ?? hitTest; - if (source is object) + if (source is not null) { - var e = new PointerEventArgs(InputElement.PointerMovedEvent, source, _pointer, root, - p, timestamp, properties, inputModifiers); + var e = new PointerEventArgs(InputElement.PointerMovedEvent, source, pointer, root, + p, timestamp, properties, inputModifiers, intermediatePoints); source.RaiseEvent(e); return e.Handled; @@ -239,176 +123,52 @@ namespace Avalonia.Input return false; } - private bool PenUp(IPenDevice device, ulong timestamp, IInputRoot root, Point p, PointerPointProperties props, - KeyModifiers inputModifiers) + private bool PenUp(Pointer pointer, ulong timestamp, + IInputElement root, Point p, PointerPointProperties properties, + KeyModifiers inputModifiers, IInputElement? hitTest) { - device = device ?? throw new ArgumentNullException(nameof(device)); - root = root ?? throw new ArgumentNullException(nameof(root)); - - var hit = HitTest(root, p); - var source = GetSource(hit); + var source = pointer.Captured ?? hitTest; if (source is not null) { - var e = new PointerReleasedEventArgs(source, _pointer, root, p, timestamp, props, inputModifiers, + var e = new PointerReleasedEventArgs(source, pointer, root, p, timestamp, properties, inputModifiers, _lastMouseDownButton); source?.RaiseEvent(e); - _pointer.Capture(null); + pointer.Capture(null); return e.Handled; } return false; } - private IInteractive? GetSource(IVisual? hit) - { - if (hit is null) - return null; - - return _pointer.Captured ?? - (hit as IInteractive) ?? - hit.GetSelfAndVisualAncestors().OfType().FirstOrDefault(); - } - - private IInputElement? HitTest(IInputElement root, Point p) - { - root = root ?? throw new ArgumentNullException(nameof(root)); - - return _pointer.Captured ?? root.InputHitTest(p); - } - - PointerEventArgs CreateSimpleEvent(RoutedEvent ev, ulong timestamp, IInteractive? source, - PointerPointProperties properties, - KeyModifiers inputModifiers) - { - return new PointerEventArgs(ev, source, _pointer, null, default, - timestamp, properties, inputModifiers); - } - - private void ClearPointerOver(IPointerDevice device, ulong timestamp, IInputRoot root, - PointerPointProperties properties, - KeyModifiers inputModifiers) - { - device = device ?? throw new ArgumentNullException(nameof(device)); - root = root ?? throw new ArgumentNullException(nameof(root)); - - var element = root.PointerOverElement; - var e = CreateSimpleEvent(InputElement.PointerLeaveEvent, timestamp, element, properties, inputModifiers); - - if (element!=null && !element.IsAttachedToVisualTree) - { - // element has been removed from visual tree so do top down cleanup - if (root.IsPointerOver) - ClearChildrenPointerOver(e, root,true); - } - while (element != null) - { - e.Source = element; - e.Handled = false; - element.RaiseEvent(e); - element = (IInputElement?)element.VisualParent; - } - - root.PointerOverElement = null; - } - - private void ClearChildrenPointerOver(PointerEventArgs e, IInputElement element,bool clearRoot) - { - foreach (IInputElement el in element.VisualChildren) - { - if (el.IsPointerOver) - { - ClearChildrenPointerOver(e, el, true); - break; - } - } - if(clearRoot) - { - e.Source = element; - e.Handled = false; - element.RaiseEvent(e); - } - } - - private IInputElement? SetPointerOver(IPointerDevice device, ulong timestamp, IInputRoot root, Point p, - PointerPointProperties properties, - KeyModifiers inputModifiers) + public void Dispose() { - device = device ?? throw new ArgumentNullException(nameof(device)); - root = root ?? throw new ArgumentNullException(nameof(root)); - - var element = root.InputHitTest(p); - - if (element != root.PointerOverElement) - { - if (element != null) - { - SetPointerOver(device, timestamp, root, element, properties, inputModifiers); - } - else - { - ClearPointerOver(device, timestamp, root, properties, inputModifiers); - } - } - - return element; + if (_disposed) + return; + var values = _pointers.Values.ToList(); + _pointers.Clear(); + _disposed = true; + foreach (var p in values) + p.Dispose(); } - private void SetPointerOver(IPointerDevice device, ulong timestamp, IInputRoot root, IInputElement element, - PointerPointProperties properties, - KeyModifiers inputModifiers) - { - device = device ?? throw new ArgumentNullException(nameof(device)); - root = root ?? throw new ArgumentNullException(nameof(root)); - element = element ?? throw new ArgumentNullException(nameof(element)); + [Obsolete] + IInputElement? IPointerDevice.Captured => _pointers.Values + .FirstOrDefault(p => p.IsPrimary)?.Captured; - IInputElement? branch = null; + [Obsolete] + void IPointerDevice.Capture(IInputElement? control) => _pointers.Values + .FirstOrDefault(p => p.IsPrimary)?.Capture(control); - IInputElement? el = element; + [Obsolete] + Point IPointerDevice.GetPosition(IVisual relativeTo) => new Point(-1, -1); - while (el != null) - { - if (el.IsPointerOver) - { - branch = el; - break; - } - el = (IInputElement?)el.VisualParent; - } - - el = root.PointerOverElement; - - var e = CreateSimpleEvent(InputElement.PointerLeaveEvent, timestamp, el, properties, inputModifiers); - if (el!=null && branch!=null && !el.IsAttachedToVisualTree) - { - ClearChildrenPointerOver(e,branch,false); - } - - while (el != null && el != branch) - { - e.Source = el; - e.Handled = false; - el.RaiseEvent(e); - el = (IInputElement?)el.VisualParent; - } - - el = root.PointerOverElement = element; - e.RoutedEvent = InputElement.PointerEnterEvent; - - while (el != null && el != branch) - { - e.Source = el; - e.Handled = false; - el.RaiseEvent(e); - el = (IInputElement?)el.VisualParent; - } - } - - public void Dispose() + public IPointer? TryGetPointer(RawPointerEventArgs ev) { - _disposed = true; - _pointer?.Dispose(); + return _pointers.TryGetValue(ev.RawPointerId, out var pointer) + ? pointer + : null; } } } diff --git a/src/Avalonia.Input/PointerPoint.cs b/src/Avalonia.Input/PointerPoint.cs index ba69add7d8..c704aa28c6 100644 --- a/src/Avalonia.Input/PointerPoint.cs +++ b/src/Avalonia.Input/PointerPoint.cs @@ -1,3 +1,5 @@ +using Avalonia.Input.Raw; + namespace Avalonia.Input { public sealed class PointerPoint @@ -45,6 +47,9 @@ namespace Avalonia.Input IsRightButtonPressed = modifiers.HasAllFlags(RawInputModifiers.RightMouseButton); IsXButton1Pressed = modifiers.HasAllFlags(RawInputModifiers.XButton1MouseButton); IsXButton2Pressed = modifiers.HasAllFlags(RawInputModifiers.XButton2MouseButton); + IsInverted = modifiers.HasAllFlags(RawInputModifiers.PenInverted); + IsEraser = modifiers.HasAllFlags(RawInputModifiers.PenEraser); + IsBarrelButtonPressed = modifiers.HasAllFlags(RawInputModifiers.PenBarrelButton); // The underlying input source might be reporting the previous state, // so make sure that we reflect the current state @@ -72,19 +77,16 @@ namespace Avalonia.Input } public PointerPointProperties(RawInputModifiers modifiers, PointerUpdateKind kind, - float twist, float pressure, float xTilt, float yTilt, bool isEraser, bool isInverted, bool isBarrel + float twist, float pressure, float xTilt, float yTilt ) : this (modifiers, kind) { Twist = twist; Pressure = pressure; XTilt = xTilt; YTilt = yTilt; - IsEraser = isEraser; - IsInverted = isInverted; - IsBarrelButtonPressed = isBarrel; } - internal PointerPointProperties(PointerPointProperties basedOn, Raw.RawPointerPoint rawPoint) + internal PointerPointProperties(PointerPointProperties basedOn, RawPointerPoint rawPoint) { IsLeftButtonPressed = basedOn.IsLeftButtonPressed; IsMiddleButtonPressed = basedOn.IsMiddleButtonPressed; diff --git a/src/Avalonia.Input/Raw/RawPointerEventArgs.cs b/src/Avalonia.Input/Raw/RawPointerEventArgs.cs index 1faa20fbf1..0e4e0ed3e2 100644 --- a/src/Avalonia.Input/Raw/RawPointerEventArgs.cs +++ b/src/Avalonia.Input/Raw/RawPointerEventArgs.cs @@ -56,11 +56,12 @@ namespace Avalonia.Input.Raw Contract.Requires(device != null); Contract.Requires(root != null); + Point = new RawPointerPoint(); Position = position; Type = type; InputModifiers = inputModifiers; } - + /// /// Initializes a new instance of the class. /// @@ -145,6 +146,7 @@ namespace Avalonia.Input.Raw public RawPointerPoint() { this = default; + Pressure = 0.5f; } } } diff --git a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs index d52115425f..6619c60152 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs @@ -380,48 +380,6 @@ namespace Avalonia.Win32 return IntPtr.Zero; } - break; - } - case WindowsMessage.WM_POINTERDEVICECHANGE: - { - if (!_wmPointerEnabled) - { - break; - } - //notifies about changes in the settings of a monitor that has a digitizer attached to it. - //https://docs.microsoft.com/en-us/previous-versions/windows/desktop/inputmsg/wm-pointerdevicechange - break; - } - case WindowsMessage.WM_POINTERDEVICEINRANGE: - { - if (!_wmPointerEnabled) - { - break; - } - _mouseDevice.Capture(null); - //notifies about proximity of pointer device to the digitizer. - //contains pointer id and proximity. - //https://docs.microsoft.com/en-us/previous-versions/windows/desktop/inputmsg/wm-pointerdeviceinrange - break; - } - case WindowsMessage.WM_POINTERDEVICEOUTOFRANGE: - { - if (!_wmPointerEnabled) - { - break; - } - _penDevice.Capture(null); - break; - } - case WindowsMessage.WM_NCPOINTERUPDATE: - { - if (!_wmPointerEnabled) - { - break; - } - //NC stands for non-client area - window header and window border - //As I found above in an old message handling - we dont need to handle NC pointer move/updates. - //All we need is pointer down and up. So this is skipped for now. break; } case WindowsMessage.WM_NCPOINTERDOWN: @@ -430,194 +388,92 @@ namespace Avalonia.Win32 case WindowsMessage.WM_POINTERUP: case WindowsMessage.WM_POINTERUPDATE: { - GetDevicePointerInfo(wParam, out var device, out var info, ref timestamp); if (!_wmPointerEnabled) { break; } - - var historyCount = (int)info.historyCount; - Lazy> intermediatePoints = null; - if (info.historyCount > 1) - { - intermediatePoints = new Lazy>(() => - { - var list = new List(historyCount - 1); - if (info.pointerType == PointerInputType.PT_TOUCH) - { - var pointerId = (uint)(ToInt32(wParam) & 0xFFFF); - var historyTouchInfos = ArrayPool.Shared.Rent(historyCount); - try - { - if (GetPointerTouchInfoHistory(pointerId, ref historyCount, historyTouchInfos)) - { - //last info is the same as the current so skip it - for (int i = 0; i < historyCount - 1; i++) - { - var historyTouchInfo = historyTouchInfos[i]; - var historyInfo = historyTouchInfo.pointerInfo; - var historyPoint = PointToClient(new PixelPoint( - historyInfo.ptPixelLocationX, historyInfo.ptPixelLocationY)); - list.Add(new RawPointerPoint - { - Position = historyPoint, - }); - } - } - } - finally - { - ArrayPool.Shared.Return(historyTouchInfos); - } - } - else if (info.pointerType == PointerInputType.PT_PEN) - { - var pointerId = (uint)(ToInt32(wParam) & 0xFFFF); - var historyPenInfos = ArrayPool.Shared.Rent(historyCount); - try - { - if (GetPointerPenInfoHistory(pointerId, ref historyCount, historyPenInfos)) - { - //last info is the same as the current so skip it - for (int i = 0; i < historyCount - 1; i++) - { - var historyPenInfo = historyPenInfos[i]; - var historyInfo = historyPenInfo.pointerInfo; - var historyPoint = PointToClient(new PixelPoint( - historyInfo.ptPixelLocationX, historyInfo.ptPixelLocationY)); - list.Add(new RawPointerPoint - { - Position = historyPoint, - Pressure = historyPenInfo.pressure, - Twist = historyPenInfo.rotation, - XTilt = historyPenInfo.tiltX, - YTilt = historyPenInfo.tiltX - }); - } - } - } - finally - { - ArrayPool.Shared.Return(historyPenInfos); - } - } - else - { - var pointerId = (uint)(ToInt32(wParam) & 0xFFFF); - var historyInfos = ArrayPool.Shared.Rent(historyCount); - try - { - if (GetPointerInfoHistory(pointerId, ref historyCount, historyInfos)) - { - //last info is the same as the current so skip it - for (int i = 0; i < historyCount - 1; i++) - { - var historyInfo = historyInfos[i]; - var historyPoint = PointToClient(new PixelPoint( - historyInfo.ptPixelLocationX, historyInfo.ptPixelLocationY)); - list.Add(new RawPointerPoint - { - Position = historyPoint - }); - } - } - } - finally - { - ArrayPool.Shared.Return(historyInfos); - } - } - return list; - }); - } - + GetDevicePointerInfo(wParam, out var device, out var info, out var point, out var modifiers, ref timestamp); var eventType = GetEventType(message, info); - var point = PointToClient(new PixelPoint(info.ptPixelLocationX, info.ptPixelLocationY)); - var modifiers = GetInputModifiers(info.dwKeyStates); - if (device is TouchDevice) - { - e = new RawTouchEventArgs(_touchDevice, timestamp, _owner, eventType, point, modifiers, info.pointerId) - { - IntermediatePoints = intermediatePoints - }; - } - else - { - e = new RawPointerEventArgs(device, timestamp, _owner, eventType, point, modifiers) - { - IntermediatePoints = intermediatePoints - }; - } - break; - } - case WindowsMessage.WM_POINTERENTER: - { - if (!_wmPointerEnabled) - { - break; - } - //this is not handled by WM_MOUSEENTER so I think there is no need to handle this too. - //but we can detect a new pointer by this message and calling IS_POINTER_NEW_WPARAM - - //note: by using a pen there can be a pointer leave or enter inside a window coords - //when you are just lift up the pen above the display + var args = CreatePointerArgs(device, timestamp, eventType, point, modifiers, info.pointerId); + args.IntermediatePoints = CreateLazyIntermediatePoints(info); + e = args; break; } + case WindowsMessage.WM_POINTERDEVICEOUTOFRANGE: case WindowsMessage.WM_POINTERLEAVE: + case WindowsMessage.WM_POINTERCAPTURECHANGED: { - GetDevicePointerInfo(wParam, out var device, out var info, ref timestamp); if (!_wmPointerEnabled) { break; } - if (device is TouchDevice) - { - break; - } - var point = PointToClient(new PixelPoint(info.ptPixelLocationX, info.ptPixelLocationY)); - var modifiers = GetInputModifiers(info.dwKeyStates); - - e = new RawPointerEventArgs( - device, timestamp, _owner, RawPointerEventType.LeaveWindow, point, modifiers); + GetDevicePointerInfo(wParam, out var device, out var info, out var point, out var modifiers, ref timestamp); + var eventType = device is TouchDevice ? RawPointerEventType.TouchCancel : RawPointerEventType.LeaveWindow; + e = CreatePointerArgs(device, timestamp, eventType, point, modifiers, info.pointerId); break; } case WindowsMessage.WM_POINTERWHEEL: case WindowsMessage.WM_POINTERHWHEEL: { - GetDevicePointerInfo(wParam, out var device, out var info, ref timestamp); if (!_wmPointerEnabled) { break; } + GetDevicePointerInfo(wParam, out var device, out var info, out var point, out var modifiers, ref timestamp); - var point = PointToClient(new PixelPoint(info.ptPixelLocationX, info.ptPixelLocationY)); - var modifiers = GetInputModifiers(info.dwKeyStates); var val = (ToInt32(wParam) >> 16) / wheelDelta; var delta = message == WindowsMessage.WM_POINTERWHEEL ? new Vector(0, val) : new Vector(val, 0); - e = new RawMouseWheelEventArgs(device, timestamp, _owner, point, delta, modifiers); + e = new RawMouseWheelEventArgs(device, timestamp, _owner, point.Position, delta, modifiers) + { + RawPointerId = info.pointerId + }; break; } - case WindowsMessage.WM_POINTERACTIVATE: + case WindowsMessage.WM_POINTERDEVICEINRANGE: { if (!_wmPointerEnabled) { break; } + + // Do not generate events, but release mouse capture on any other device input. + GetDevicePointerInfo(wParam, out var device, out var info, out var point, out var modifiers, ref timestamp); + if (device != _mouseDevice) + { + _mouseDevice.Capture(null); + return IntPtr.Zero; + } + break; + } + case WindowsMessage.WM_POINTERACTIVATE: + { //occurs when a pointer activates an inactive window. //we should handle this and return PA_ACTIVATE or PA_NOACTIVATE //https://docs.microsoft.com/en-us/previous-versions/windows/desktop/inputmsg/wm-pointeractivate break; } - case WindowsMessage.WM_POINTERCAPTURECHANGED: + case WindowsMessage.WM_POINTERDEVICECHANGE: { - if (!_wmPointerEnabled) - { - break; - } - _mouseDevice.Capture(null); - _penDevice.Capture(null); - return IntPtr.Zero; + //notifies about changes in the settings of a monitor that has a digitizer attached to it. + //https://docs.microsoft.com/en-us/previous-versions/windows/desktop/inputmsg/wm-pointerdevicechange + break; + } + case WindowsMessage.WM_NCPOINTERUPDATE: + { + //NC stands for non-client area - window header and window border + //As I found above in an old message handling - we dont need to handle NC pointer move/updates. + //All we need is pointer down and up. So this is skipped for now. + break; + } + case WindowsMessage.WM_POINTERENTER: + { + //this is not handled by WM_MOUSEENTER so I think there is no need to handle this too. + //but we can detect a new pointer by this message and calling IS_POINTER_NEW_WPARAM + + //note: by using a pen there can be a pointer leave or enter inside a window coords + //when you are just lift up the pen above the display + break; } case WindowsMessage.DM_POINTERHITTEST: { @@ -839,6 +695,11 @@ namespace Avalonia.Win32 _ignoreWmChar = e.Handled; } + if (s_intermediatePointsPooledList.Count > 0) + { + s_intermediatePointsPooledList.Dispose(); + } + if (e.Handled) { return IntPtr.Zero; @@ -851,40 +712,110 @@ namespace Avalonia.Win32 } } - private unsafe void ApplyPenInfo(POINTER_PEN_INFO penInfo) + private unsafe Lazy> CreateLazyIntermediatePoints(POINTER_INFO info) { - _penDevice.IsBarrel = penInfo.penFlags.HasFlag(PenFlags.PEN_FLAGS_BARREL); - _penDevice.IsEraser = penInfo.penFlags.HasFlag(PenFlags.PEN_FLAGS_ERASER); - _penDevice.IsInverted = penInfo.penFlags.HasFlag(PenFlags.PEN_FLAGS_INVERTED); - - _penDevice.XTilt = penInfo.tiltX; - _penDevice.YTilt = penInfo.tiltY; - _penDevice.Pressure = penInfo.pressure; - _penDevice.Twist = penInfo.rotation; + // Limit history size with reasonable value. + // With sizeof(POINTER_TOUCH_INFO) * 100 we can get maximum 14400 bytes. + var historyCount = Math.Min((int)info.historyCount, MaxPointerHistorySize); + if (historyCount > 1) + { + return new Lazy>(() => + { + s_intermediatePointsPooledList.Clear(); + s_intermediatePointsPooledList.Capacity = historyCount; + if (info.pointerType == PointerInputType.PT_TOUCH) + { + if (GetPointerTouchInfoHistory(info.pointerId, ref historyCount, s_historyTouchInfos)) + { + //last info is the same as the current so skip it + for (int i = 0; i < historyCount - 1; i++) + { + var historyTouchInfo = s_historyTouchInfos[i]; + s_intermediatePointsPooledList.Add(CreateRawPointerPoint(historyTouchInfo)); + } + } + } + else if (info.pointerType == PointerInputType.PT_PEN) + { + if (GetPointerPenInfoHistory(info.pointerId, ref historyCount, s_historyPenInfos)) + { + //last info is the same as the current so skip it + for (int i = 0; i < historyCount - 1; i++) + { + var historyPenInfo = s_historyPenInfos[i]; + s_intermediatePointsPooledList.Add(CreateRawPointerPoint(historyPenInfo)); + } + } + } + else + { + // Currently Windows does not return history info for mouse input, but we handle it just for case. + if (GetPointerInfoHistory(info.pointerId, ref historyCount, s_historyInfos)) + { + //last info is the same as the current so skip it + for (int i = 0; i < historyCount - 1; i++) + { + var historyInfo = s_historyInfos[i]; + s_intermediatePointsPooledList.Add(CreateRawPointerPoint(historyInfo)); + } + } + } + return s_intermediatePointsPooledList; + }); + } + + return null; + } + + private RawPointerEventArgs CreatePointerArgs(IInputDevice device, ulong timestamp, RawPointerEventType eventType, RawPointerPoint point, RawInputModifiers modifiers, uint rawPointerId) + { + return device is TouchDevice + ? new RawTouchEventArgs(device, timestamp, _owner, eventType, point, modifiers, rawPointerId) + : new RawPointerEventArgs(device, timestamp, _owner, eventType, point, modifiers) + { + RawPointerId = rawPointerId + }; } - private void GetDevicePointerInfo(IntPtr wParam, out IInputDevice device, out POINTER_INFO info, ref uint timestamp) + private void GetDevicePointerInfo(IntPtr wParam, + out IPointerDevice device, out POINTER_INFO info, out RawPointerPoint point, + out RawInputModifiers modifiers, ref uint timestamp) { var pointerId = (uint)(ToInt32(wParam) & 0xFFFF); GetPointerType(pointerId, out var type); - //GetPointerCursorId(pointerId, out var cursorId); + + modifiers = default; + switch (type) { case PointerInputType.PT_PEN: device = _penDevice; GetPointerPenInfo(pointerId, out var penInfo); info = penInfo.pointerInfo; - - ApplyPenInfo(penInfo); + point = CreateRawPointerPoint(penInfo); + if (penInfo.penFlags.HasFlag(PenFlags.PEN_FLAGS_BARREL)) + { + modifiers |= RawInputModifiers.PenBarrelButton; + } + if (penInfo.penFlags.HasFlag(PenFlags.PEN_FLAGS_ERASER)) + { + modifiers |= RawInputModifiers.PenEraser; + } + if (penInfo.penFlags.HasFlag(PenFlags.PEN_FLAGS_INVERTED)) + { + modifiers |= RawInputModifiers.PenInverted; + } break; case PointerInputType.PT_TOUCH: device = _touchDevice; GetPointerTouchInfo(pointerId, out var touchInfo); info = touchInfo.pointerInfo; + point = CreateRawPointerPoint(touchInfo); break; default: device = _mouseDevice; GetPointerInfo(pointerId, out info); + point = CreateRawPointerPoint(info); break; } @@ -892,6 +823,44 @@ namespace Avalonia.Win32 { timestamp = info.dwTime; } + + modifiers |= GetInputModifiers(info.dwKeyStates); + } + + private RawPointerPoint CreateRawPointerPoint(POINTER_INFO pointerInfo) + { + var point = PointToClient(new PixelPoint(pointerInfo.ptPixelLocationX, pointerInfo.ptPixelLocationY)); + return new RawPointerPoint + { + Position = point + }; + } + private RawPointerPoint CreateRawPointerPoint(POINTER_TOUCH_INFO info) + { + var pointerInfo = info.pointerInfo; + var point = PointToClient(new PixelPoint(pointerInfo.ptPixelLocationX, pointerInfo.ptPixelLocationY)); + return new RawPointerPoint + { + Position = point, + // POINTER_PEN_INFO.pressure is normalized to a range between 0 and 1024, with 512 as a default. + // But in our API we use range from 0.0 to 1.0. + Pressure = info.pressure / 1024f + }; + } + private RawPointerPoint CreateRawPointerPoint(POINTER_PEN_INFO info) + { + var pointerInfo = info.pointerInfo; + var point = PointToClient(new PixelPoint(pointerInfo.ptPixelLocationX, pointerInfo.ptPixelLocationY)); + return new RawPointerPoint + { + Position = point, + // POINTER_PEN_INFO.pressure is normalized to a range between 0 and 1024, with 512 as a default. + // But in our API we use range from 0.0 to 1.0. + Pressure = info.pressure / 1024f, + Twist = info.rotation, + XTilt = info.tiltX, + YTilt = info.tiltX + }; } private static RawPointerEventType GetEventType(WindowsMessage message, POINTER_INFO info) @@ -904,8 +873,6 @@ namespace Avalonia.Win32 } switch (info.pointerType) { - case PointerInputType.PT_PEN: - return ToEventType(info.ButtonChangeType); case PointerInputType.PT_TOUCH: if (info.pointerFlags.HasFlag(PointerFlags.POINTER_FLAG_CANCELED)) { diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 64295f8925..e0f6348c23 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -21,6 +21,7 @@ using Avalonia.Win32.OpenGl; using Avalonia.Win32.WinRT; using Avalonia.Win32.WinRT.Composition; using static Avalonia.Win32.Interop.UnmanagedMethods; +using Avalonia.Collections.Pooled; namespace Avalonia.Win32 { @@ -95,6 +96,12 @@ namespace Avalonia.Win32 private uint _langid; private bool _ignoreWmChar; + private const int MaxPointerHistorySize = 512; + private readonly static PooledList s_intermediatePointsPooledList = new(); + private readonly static POINTER_TOUCH_INFO[] s_historyTouchInfos = new POINTER_TOUCH_INFO[MaxPointerHistorySize]; + private readonly static POINTER_PEN_INFO[] s_historyPenInfos = new POINTER_PEN_INFO[MaxPointerHistorySize]; + private readonly static POINTER_INFO[] s_historyInfos = new POINTER_INFO[MaxPointerHistorySize]; + public WindowImpl() { _touchDevice = new TouchDevice(); From 99e444f5f19a9312ac4eb99076084b18b92040e3 Mon Sep 17 00:00:00 2001 From: Max Katz Date: Sat, 16 Apr 2022 04:01:07 -0400 Subject: [PATCH 22/78] Update documentation of pointer types --- src/Avalonia.Input/IPointer.cs | 40 +++++++++++- src/Avalonia.Input/PointerEventArgs.cs | 19 +++++- src/Avalonia.Input/PointerPoint.cs | 86 ++++++++++++++++++++++++-- 3 files changed, 138 insertions(+), 7 deletions(-) diff --git a/src/Avalonia.Input/IPointer.cs b/src/Avalonia.Input/IPointer.cs index 361f3ac370..98f7c81f02 100644 --- a/src/Avalonia.Input/IPointer.cs +++ b/src/Avalonia.Input/IPointer.cs @@ -1,15 +1,53 @@ namespace Avalonia.Input { + /// + /// Identifies specific pointer generated by input device. + /// + /// + /// Some devices, for instance, touchscreen might generate a pointer on each physical contact. + /// public interface IPointer { + /// + /// Gets a unique identifier for the input pointer. + /// int Id { get; } + + /// + /// Captures pointer input to the specified control. + /// + /// The control. + /// + /// When an element captures the pointer, it receives pointer input whether the cursor is + /// within the control's bounds or not. The current pointer capture control is exposed + /// by the property. + /// void Capture(IInputElement? control); + + /// + /// Gets the control that is currently capturing by the pointer, if any. + /// + /// + /// When an element captures the pointer, it receives pointer input whether the cursor is + /// within the control's bounds or not. To set the pointer capture, call the + /// method. + /// IInputElement? Captured { get; } + + /// + /// Gets the pointer device type. + /// PointerType Type { get; } + + /// + /// Gets a value that indicates whether the input is from the primary pointer when multiple pointers are registered. + /// bool IsPrimary { get; } - } + /// + /// Enumerates pointer device types. + /// public enum PointerType { Mouse, diff --git a/src/Avalonia.Input/PointerEventArgs.cs b/src/Avalonia.Input/PointerEventArgs.cs index 79335eb9fc..058c2f9cc1 100644 --- a/src/Avalonia.Input/PointerEventArgs.cs +++ b/src/Avalonia.Input/PointerEventArgs.cs @@ -67,7 +67,14 @@ namespace Avalonia.Input public IPointer? TryGetPointer(RawPointerEventArgs ev) => _ev.Pointer; } + /// + /// Gets specific pointer generated by input device. + /// public IPointer Pointer { get; } + + /// + /// Gets the time when the input occurred. + /// public ulong Timestamp { get; } private IPointerDevice? _device; @@ -91,7 +98,10 @@ namespace Avalonia.Input return mods; } } - + + /// + /// Gets a value that indicates which key modifiers were active at the time that the pointer event was initiated. + /// public KeyModifiers KeyModifiers { get; } private Point GetPosition(Point pt, IVisual? relativeTo) @@ -102,7 +112,12 @@ namespace Avalonia.Input return pt; return pt * _rootVisual.TransformToVisual(relativeTo) ?? default; } - + + /// + /// Gets the pointer position relative to a control. + /// + /// The control. + /// The pointer position in the control's coordinates. public Point GetPosition(IVisual? relativeTo) => GetPosition(_rootVisualPosition, relativeTo); [Obsolete("Use GetCurrentPoint")] diff --git a/src/Avalonia.Input/PointerPoint.cs b/src/Avalonia.Input/PointerPoint.cs index c704aa28c6..71145b5cb0 100644 --- a/src/Avalonia.Input/PointerPoint.cs +++ b/src/Avalonia.Input/PointerPoint.cs @@ -2,6 +2,9 @@ using Avalonia.Input.Raw; namespace Avalonia.Input { + /// + /// Provides basic properties for the input pointer associated with a single mouse, pen/stylus, or touch contact. + /// public sealed class PointerPoint { public PointerPoint(IPointer pointer, Point position, PointerPointProperties properties) @@ -10,34 +13,109 @@ namespace Avalonia.Input Position = position; Properties = properties; } + + /// + /// Gets specific pointer generated by input device. + /// public IPointer Pointer { get; } + + /// + /// Gets extended information about the input pointer. + /// public PointerPointProperties Properties { get; } + + /// + /// Gets the location of the pointer input in client coordinates. + /// public Point Position { get; } } + /// + /// Provides extended properties for a PointerPoint object. + /// public sealed class PointerPointProperties { + /// + /// Gets a value that indicates whether the pointer input was triggered by the primary action mode of an input device. + /// public bool IsLeftButtonPressed { get; } + + /// + /// Gets a value that indicates whether the pointer input was triggered by the tertiary action mode of an input device. + /// public bool IsMiddleButtonPressed { get; } + + /// + /// Gets a value that indicates whether the pointer input was triggered by the secondary action mode (if supported) of an input device. + /// public bool IsRightButtonPressed { get; } + + /// + /// Gets a value that indicates whether the pointer input was triggered by the first extended mouse button (XButton1). + /// public bool IsXButton1Pressed { get; } + + /// + /// Gets a value that indicates whether the pointer input was triggered by the second extended mouse button (XButton2). + /// public bool IsXButton2Pressed { get; } + + /// + /// Gets a value that indicates whether the barrel button of the pen/stylus device is pressed. + /// public bool IsBarrelButtonPressed { get; } + + /// + /// Gets a value that indicates whether the input is from a pen eraser. + /// public bool IsEraser { get; } + + /// + /// Gets a value that indicates whether the digitizer pen is inverted. + /// public bool IsInverted { get; } + /// + /// Gets the clockwise rotation in degrees of a pen device around its own major axis (such as when the user spins the pen in their fingers). + /// + /// + /// A value between 0.0 and 359.0 in degrees of rotation. The default value is 0.0. + /// public float Twist { get; } - public float Pressure { get; } + + /// + /// Gets a value that indicates the force that the pointer device (typically a pen/stylus) exerts on the surface of the digitizer. + /// + /// + /// A value from 0 to 1.0. The default value is 0.5. + /// + public float Pressure { get; } = 0.5f; + + /// + /// Gets the plane angle between the Y-Z plane and the plane that contains the Y axis and the axis of the input device (typically a pen/stylus). + /// + /// + /// The value is 0.0 when the finger or pen is perpendicular to the digitizer surface, between 0.0 and 90.0 when tilted to the right of perpendicular, and between 0.0 and -90.0 when tilted to the left of perpendicular. The default value is 0.0. + /// public float XTilt { get; } - public float YTilt { get; } + /// + /// Gets the plane angle between the X-Z plane and the plane that contains the X axis and the axis of the input device (typically a pen/stylus). + /// + /// + /// The value is 0.0 when the finger or pen is perpendicular to the digitizer surface, between 0.0 and 90.0 when tilted towards the user, and between 0.0 and -90.0 when tilted away from the user. The default value is 0.0. + /// + public float YTilt { get; } + /// + /// Gets the kind of pointer state change. + /// public PointerUpdateKind PointerUpdateKind { get; } private PointerPointProperties() - { + { } - + public PointerPointProperties(RawInputModifiers modifiers, PointerUpdateKind kind) { PointerUpdateKind = kind; From bd2578d68359abcc44eb83118b907f74abaf3ae2 Mon Sep 17 00:00:00 2001 From: Max Katz Date: Sat, 16 Apr 2022 04:31:57 -0400 Subject: [PATCH 23/78] Update control catalog pointers page --- samples/ControlCatalog.NetCore/Program.cs | 2 +- samples/ControlCatalog/MainView.xaml | 2 +- samples/ControlCatalog/Pages/PointerCanvas.cs | 221 ++++++++++ .../Pages/PointerContactsTab.cs | 109 +++++ samples/ControlCatalog/Pages/PointersPage.cs | 394 ------------------ .../ControlCatalog/Pages/PointersPage.xaml | 65 +++ .../ControlCatalog/Pages/PointersPage.xaml.cs | 76 ++++ 7 files changed, 473 insertions(+), 396 deletions(-) create mode 100644 samples/ControlCatalog/Pages/PointerCanvas.cs create mode 100644 samples/ControlCatalog/Pages/PointerContactsTab.cs delete mode 100644 samples/ControlCatalog/Pages/PointersPage.cs create mode 100644 samples/ControlCatalog/Pages/PointersPage.xaml create mode 100644 samples/ControlCatalog/Pages/PointersPage.xaml.cs diff --git a/samples/ControlCatalog.NetCore/Program.cs b/samples/ControlCatalog.NetCore/Program.cs index 4b81935452..08ac17d0c4 100644 --- a/samples/ControlCatalog.NetCore/Program.cs +++ b/samples/ControlCatalog.NetCore/Program.cs @@ -114,7 +114,7 @@ namespace ControlCatalog.NetCore }) .With(new Win32PlatformOptions { - EnableMultitouch = true + EnableWmPointerEvents = true }) .UseSkia() .UseManagedSystemDialogs() diff --git a/samples/ControlCatalog/MainView.xaml b/samples/ControlCatalog/MainView.xaml index 85f278b5fa..c61ba231e0 100644 --- a/samples/ControlCatalog/MainView.xaml +++ b/samples/ControlCatalog/MainView.xaml @@ -106,7 +106,7 @@ - + diff --git a/samples/ControlCatalog/Pages/PointerCanvas.cs b/samples/ControlCatalog/Pages/PointerCanvas.cs new file mode 100644 index 0000000000..b815a573f2 --- /dev/null +++ b/samples/ControlCatalog/Pages/PointerCanvas.cs @@ -0,0 +1,221 @@ +#nullable enable +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Threading; + +using Avalonia; +using Avalonia.Controls; +using Avalonia.Input; +using Avalonia.Media; +using Avalonia.Threading; + +namespace ControlCatalog.Pages; + +public class PointerCanvas : Control +{ + private readonly Stopwatch _stopwatch = Stopwatch.StartNew(); + private int _events; + private IDisposable? _statusUpdated; + private Dictionary _pointers = new(); + private PointerPointProperties? _lastProperties; + class PointerPoints + { + struct CanvasPoint + { + public IBrush Brush; + public Point Point; + public double Radius; + public double? Pressure; + } + + readonly CanvasPoint[] _points = new CanvasPoint[1000]; + int _index; + + public void Render(DrawingContext context, bool drawPoints) + { + CanvasPoint? prev = null; + for (var c = 0; c < _points.Length; c++) + { + var i = (c + _index) % _points.Length; + var pt = _points[i]; + var pressure = (pt.Pressure ?? prev?.Pressure ?? 0.5); + var thickness = pressure * 10; + var radius = pressure * pt.Radius; + + if (drawPoints) + { + if (pt.Brush != null) + { + context.DrawEllipse(pt.Brush, null, pt.Point, radius, radius); + } + } + else + { + if (prev.HasValue && prev.Value.Brush != null && pt.Brush != null + && prev.Value.Pressure != null && pt.Pressure != null) + { + var linePen = new Pen(Brushes.Black, thickness, null, PenLineCap.Round, PenLineJoin.Round); + context.DrawLine(linePen, prev.Value.Point, pt.Point); + } + } + prev = pt; + } + + } + + void AddPoint(Point pt, IBrush brush, double radius, float? pressure = null) + { + _points[_index] = new CanvasPoint { Point = pt, Brush = brush, Radius = radius, Pressure = pressure }; + _index = (_index + 1) % _points.Length; + } + + public void HandleEvent(PointerEventArgs e, Visual v) + { + e.Handled = true; + var currentPoint = e.GetCurrentPoint(v); + if (e.RoutedEvent == PointerPressedEvent) + AddPoint(currentPoint.Position, Brushes.Green, 10); + else if (e.RoutedEvent == PointerReleasedEvent) + AddPoint(currentPoint.Position, Brushes.Red, 10); + else + { + var pts = e.GetIntermediatePoints(v); + for (var c = 0; c < pts.Count; c++) + { + var pt = pts[c]; + AddPoint(pt.Position, c == pts.Count - 1 ? Brushes.Blue : Brushes.Black, + c == pts.Count - 1 ? 5 : 2, pt.Properties.Pressure); + } + } + } + } + + private int _threadSleep; + public static DirectProperty ThreadSleepProperty = + AvaloniaProperty.RegisterDirect(nameof(ThreadSleep), c => c.ThreadSleep, (c, v) => c.ThreadSleep = v); + + public int ThreadSleep + { + get => _threadSleep; + set => SetAndRaise(ThreadSleepProperty, ref _threadSleep, value); + } + + private bool _drawOnlyPoints; + public static DirectProperty DrawOnlyPointsProperty = + AvaloniaProperty.RegisterDirect(nameof(DrawOnlyPoints), c => c.DrawOnlyPoints, (c, v) => c.DrawOnlyPoints = v); + + public bool DrawOnlyPoints + { + get => _drawOnlyPoints; + set => SetAndRaise(DrawOnlyPointsProperty, ref _drawOnlyPoints, value); + } + + private string? _status; + public static DirectProperty StatusProperty = + AvaloniaProperty.RegisterDirect(nameof(DrawOnlyPoints), c => c.Status, (c, v) => c.Status = v, + defaultBindingMode: Avalonia.Data.BindingMode.TwoWay); + + public string? Status + { + get => _status; + set => SetAndRaise(StatusProperty, ref _status, value); + } + + protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) + { + base.OnAttachedToVisualTree(e); + + _statusUpdated = DispatcherTimer.Run(() => + { + if (_stopwatch.Elapsed.TotalSeconds > 1) + { + Status = $@"Events per second: {(_events / _stopwatch.Elapsed.TotalSeconds)} +PointerUpdateKind: {_lastProperties?.PointerUpdateKind} +IsLeftButtonPressed: {_lastProperties?.IsLeftButtonPressed} +IsRightButtonPressed: {_lastProperties?.IsRightButtonPressed} +IsMiddleButtonPressed: {_lastProperties?.IsMiddleButtonPressed} +IsXButton1Pressed: {_lastProperties?.IsXButton1Pressed} +IsXButton2Pressed: {_lastProperties?.IsXButton2Pressed} +IsBarrelButtonPressed: {_lastProperties?.IsBarrelButtonPressed} +IsEraser: {_lastProperties?.IsEraser} +IsInverted: {_lastProperties?.IsInverted} +Pressure: {_lastProperties?.Pressure} +XTilt: {_lastProperties?.XTilt} +YTilt: {_lastProperties?.YTilt} +Twist: {_lastProperties?.Twist}"; + _stopwatch.Restart(); + _events = 0; + } + + return true; + }, TimeSpan.FromMilliseconds(10)); + } + + protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e) + { + base.OnDetachedFromVisualTree(e); + + _statusUpdated?.Dispose(); + } + + void HandleEvent(PointerEventArgs e) + { + _events++; + if (_threadSleep != 0) + { + Thread.Sleep(_threadSleep); + } + InvalidateVisual(); + + if (e.RoutedEvent == PointerReleasedEvent && e.Pointer.Type == PointerType.Touch) + { + _pointers.Remove(e.Pointer.Id); + return; + } + + var lastPointer = e.GetCurrentPoint(this); + _lastProperties = lastPointer.Properties; + + if (e.Pointer.Type != PointerType.Pen + || lastPointer.Properties.Pressure > 0) + { + if (!_pointers.TryGetValue(e.Pointer.Id, out var pt)) + _pointers[e.Pointer.Id] = pt = new PointerPoints(); + pt.HandleEvent(e, this); + } + } + + public override void Render(DrawingContext context) + { + context.FillRectangle(Brushes.White, Bounds); + foreach (var pt in _pointers.Values) + pt.Render(context, _drawOnlyPoints); + base.Render(context); + } + + protected override void OnPointerPressed(PointerPressedEventArgs e) + { + if (e.ClickCount == 2) + { + _pointers.Clear(); + InvalidateVisual(); + return; + } + + HandleEvent(e); + base.OnPointerPressed(e); + } + + protected override void OnPointerMoved(PointerEventArgs e) + { + HandleEvent(e); + base.OnPointerMoved(e); + } + + protected override void OnPointerReleased(PointerReleasedEventArgs e) + { + HandleEvent(e); + base.OnPointerReleased(e); + } +} diff --git a/samples/ControlCatalog/Pages/PointerContactsTab.cs b/samples/ControlCatalog/Pages/PointerContactsTab.cs new file mode 100644 index 0000000000..b6aabebf99 --- /dev/null +++ b/samples/ControlCatalog/Pages/PointerContactsTab.cs @@ -0,0 +1,109 @@ +#nullable enable +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reactive.Linq; + +using Avalonia; +using Avalonia.Controls; +using Avalonia.Input; +using Avalonia.Media; +using Avalonia.Media.Immutable; + +namespace ControlCatalog.Pages; + +public class PointerContactsTab : Control +{ + class PointerInfo + { + public Point Point { get; set; } + public Color Color { get; set; } + } + + private static Color[] AllColors = new[] + { + Colors.Aqua, + Colors.Beige, + Colors.Chartreuse, + Colors.Coral, + Colors.Fuchsia, + Colors.Crimson, + Colors.Lavender, + Colors.Orange, + Colors.Orchid, + Colors.ForestGreen, + Colors.SteelBlue, + Colors.PapayaWhip, + Colors.PaleVioletRed, + Colors.Goldenrod, + Colors.Maroon, + Colors.Moccasin, + Colors.Navy, + Colors.Wheat, + Colors.Violet, + Colors.Sienna, + Colors.Indigo, + Colors.Honeydew + }; + + private Dictionary _pointers = new Dictionary(); + + public PointerContactsTab() + { + ClipToBounds = true; + } + + void UpdatePointer(PointerEventArgs e) + { + if (!_pointers.TryGetValue(e.Pointer, out var info)) + { + if (e.RoutedEvent == PointerMovedEvent) + return; + var colors = AllColors.Except(_pointers.Values.Select(c => c.Color)).ToArray(); + var color = colors[new Random().Next(0, colors.Length - 1)]; + _pointers[e.Pointer] = info = new PointerInfo { Color = color }; + } + + info.Point = e.GetPosition(this); + InvalidateVisual(); + } + + protected override void OnPointerPressed(PointerPressedEventArgs e) + { + UpdatePointer(e); + e.Pointer.Capture(this); + e.Handled = true; + base.OnPointerPressed(e); + } + + protected override void OnPointerMoved(PointerEventArgs e) + { + UpdatePointer(e); + e.Handled = true; + base.OnPointerMoved(e); + } + + protected override void OnPointerReleased(PointerReleasedEventArgs e) + { + _pointers.Remove(e.Pointer); + e.Handled = true; + InvalidateVisual(); + } + + protected override void OnPointerCaptureLost(PointerCaptureLostEventArgs e) + { + _pointers.Remove(e.Pointer); + InvalidateVisual(); + } + + public override void Render(DrawingContext context) + { + context.FillRectangle(Brushes.Transparent, new Rect(default, Bounds.Size)); + foreach (var pt in _pointers.Values) + { + var brush = new ImmutableSolidColorBrush(pt.Color); + + context.DrawEllipse(brush, null, pt.Point, 75, 75); + } + } +} diff --git a/samples/ControlCatalog/Pages/PointersPage.cs b/samples/ControlCatalog/Pages/PointersPage.cs deleted file mode 100644 index 0668c248c7..0000000000 --- a/samples/ControlCatalog/Pages/PointersPage.cs +++ /dev/null @@ -1,394 +0,0 @@ -#nullable enable -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Reactive.Linq; -using System.Runtime.InteropServices; -using System.Threading; -using Avalonia; -using Avalonia.Controls; -using Avalonia.Controls.Documents; -using Avalonia.Input; -using Avalonia.Layout; -using Avalonia.Media; -using Avalonia.Media.Immutable; -using Avalonia.Threading; -using Avalonia.VisualTree; - -namespace ControlCatalog.Pages; - -public class PointersPage : Decorator -{ - public PointersPage() - { - Child = new TabControl - { - Items = new[] - { - new TabItem() { Header = "Contacts", Content = new PointerContactsTab() }, - new TabItem() { Header = "IntermediatePoints", Content = new PointerIntermediatePointsTab() }, - new TabItem() { Header = "Pressure", Content = new PointerPressureTab() } - } - }; - } - - - class PointerContactsTab : Control - { - class PointerInfo - { - public Point Point { get; set; } - public Color Color { get; set; } - } - - private static Color[] AllColors = new[] - { - Colors.Aqua, - Colors.Beige, - Colors.Chartreuse, - Colors.Coral, - Colors.Fuchsia, - Colors.Crimson, - Colors.Lavender, - Colors.Orange, - Colors.Orchid, - Colors.ForestGreen, - Colors.SteelBlue, - Colors.PapayaWhip, - Colors.PaleVioletRed, - Colors.Goldenrod, - Colors.Maroon, - Colors.Moccasin, - Colors.Navy, - Colors.Wheat, - Colors.Violet, - Colors.Sienna, - Colors.Indigo, - Colors.Honeydew - }; - - private Dictionary _pointers = new Dictionary(); - - public PointerContactsTab() - { - ClipToBounds = true; - } - - void UpdatePointer(PointerEventArgs e) - { - if (!_pointers.TryGetValue(e.Pointer, out var info)) - { - if (e.RoutedEvent == PointerMovedEvent) - return; - var colors = AllColors.Except(_pointers.Values.Select(c => c.Color)).ToArray(); - var color = colors[new Random().Next(0, colors.Length - 1)]; - _pointers[e.Pointer] = info = new PointerInfo {Color = color}; - } - - info.Point = e.GetPosition(this); - InvalidateVisual(); - } - - protected override void OnPointerPressed(PointerPressedEventArgs e) - { - UpdatePointer(e); - e.Pointer.Capture(this); - e.Handled = true; - base.OnPointerPressed(e); - } - - protected override void OnPointerMoved(PointerEventArgs e) - { - UpdatePointer(e); - e.Handled = true; - base.OnPointerMoved(e); - } - - protected override void OnPointerReleased(PointerReleasedEventArgs e) - { - _pointers.Remove(e.Pointer); - e.Handled = true; - InvalidateVisual(); - } - - protected override void OnPointerCaptureLost(PointerCaptureLostEventArgs e) - { - _pointers.Remove(e.Pointer); - InvalidateVisual(); - } - - public override void Render(DrawingContext context) - { - context.FillRectangle(Brushes.Transparent, new Rect(default, Bounds.Size)); - foreach (var pt in _pointers.Values) - { - var brush = new ImmutableSolidColorBrush(pt.Color); - - context.DrawEllipse(brush, null, pt.Point, 75, 75); - } - } - } - - public class PointerIntermediatePointsTab : Decorator - { - public PointerIntermediatePointsTab() - { - this[TextElement.ForegroundProperty] = Brushes.Black; - var slider = new Slider - { - Margin = new Thickness(5), - Minimum = 0, - Maximum = 500 - }; - - var status = new TextBlock() - { - HorizontalAlignment = HorizontalAlignment.Left, - VerticalAlignment = VerticalAlignment.Top, - }; - Child = new Grid - { - Children = - { - new PointerCanvas(slider, status, true), - new Border - { - Background = Brushes.LightYellow, - Child = new StackPanel - { - Children = - { - new StackPanel - { - Orientation = Orientation.Horizontal, - Children = - { - new TextBlock { Text = "Thread sleep:" }, - new TextBlock() - { - [!TextBlock.TextProperty] =slider.GetObservable(Slider.ValueProperty) - .Select(x=>x.ToString()).ToBinding() - } - } - }, - slider - } - }, - - HorizontalAlignment = HorizontalAlignment.Right, - VerticalAlignment = VerticalAlignment.Top, - Width = 300, - Height = 60 - }, - status - } - }; - } - } - - public class PointerPressureTab : Decorator - { - public PointerPressureTab() - { - this[TextBlock.ForegroundProperty] = Brushes.Black; - - var status = new TextBlock() - { - HorizontalAlignment = HorizontalAlignment.Left, - VerticalAlignment = VerticalAlignment.Top, - FontSize = 12 - }; - Child = new Grid - { - Children = - { - new PointerCanvas(null, status, false), - status - } - }; - } - } - - class PointerCanvas : Control - { - private readonly Slider? _slider; - private readonly TextBlock _status; - private readonly bool _drawPoints; - private int _events; - private Stopwatch _stopwatch = Stopwatch.StartNew(); - private IDisposable? _statusUpdated; - private Dictionary _pointers = new(); - private PointerPointProperties? _lastProperties; - class PointerPoints - { - struct CanvasPoint - { - public IBrush Brush; - public Point Point; - public double Radius; - public double Pressure; - } - - readonly CanvasPoint[] _points = new CanvasPoint[1000]; - int _index; - - public void Render(DrawingContext context, bool drawPoints) - { - - CanvasPoint? prev = null; - for (var c = 0; c < _points.Length; c++) - { - var i = (c + _index) % _points.Length; - var pt = _points[i]; - var thickness = pt.Pressure == 0 ? 1 : (pt.Pressure / 1024) * 5; - - if (drawPoints) - { - if (prev.HasValue && prev.Value.Brush != null && pt.Brush != null) - context.DrawLine(new Pen(Brushes.Black, thickness), prev.Value.Point, pt.Point); - if (pt.Brush != null) - context.DrawEllipse(pt.Brush, null, pt.Point, pt.Radius, pt.Radius); - } - else - { - if (prev.HasValue && prev.Value.Brush != null && pt.Brush != null) - context.DrawLine(new Pen(Brushes.Black, thickness, lineCap: PenLineCap.Round, lineJoin: PenLineJoin.Round), prev.Value.Point, pt.Point); - } - prev = pt; - } - - } - - void AddPoint(Point pt, IBrush brush, double radius, float pressure) - { - _points[_index] = new CanvasPoint { Point = pt, Brush = brush, Radius = radius, Pressure = pressure }; - _index = (_index + 1) % _points.Length; - } - - public void HandleEvent(PointerEventArgs e, Visual v) - { - e.Handled = true; - var currentPoint = e.GetCurrentPoint(v); - if (e.RoutedEvent == PointerPressedEvent) - AddPoint(currentPoint.Position, Brushes.Green, 10, currentPoint.Properties.Pressure); - else if (e.RoutedEvent == PointerReleasedEvent) - AddPoint(currentPoint.Position, Brushes.Red, 10, currentPoint.Properties.Pressure); - else - { - var pts = e.GetIntermediatePoints(v); - for (var c = 0; c < pts.Count; c++) - { - var pt = pts[c]; - AddPoint(pt.Position, c == pts.Count - 1 ? Brushes.Blue : Brushes.Black, - c == pts.Count - 1 ? 5 : 2, pt.Properties.Pressure); - } - } - } - } - - public PointerCanvas(Slider? slider, TextBlock status, bool drawPoints) - { - _slider = slider; - _status = status; - _drawPoints = drawPoints; - } - - protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) - { - base.OnAttachedToVisualTree(e); - - _statusUpdated = DispatcherTimer.Run(() => - { - if (_stopwatch.Elapsed.TotalSeconds > 1) - { - _status.Text = $@"Events per second: {(_events / _stopwatch.Elapsed.TotalSeconds)} -PointerUpdateKind: {_lastProperties?.PointerUpdateKind} -IsLeftButtonPressed: {_lastProperties?.IsLeftButtonPressed} -IsRightButtonPressed: {_lastProperties?.IsRightButtonPressed} -IsMiddleButtonPressed: {_lastProperties?.IsMiddleButtonPressed} -IsXButton1Pressed: {_lastProperties?.IsXButton1Pressed} -IsXButton2Pressed: {_lastProperties?.IsXButton2Pressed} -IsBarrelButtonPressed: {_lastProperties?.IsBarrelButtonPressed} -IsEraser: {_lastProperties?.IsEraser} -IsInverted: {_lastProperties?.IsInverted} -Pressure: {_lastProperties?.Pressure} -XTilt: {_lastProperties?.XTilt} -YTilt: {_lastProperties?.YTilt} -Twist: {_lastProperties?.Twist}"; - _stopwatch.Restart(); - _events = 0; - } - - return true; - }, TimeSpan.FromMilliseconds(10)); - } - - protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e) - { - base.OnDetachedFromVisualTree(e); - - _statusUpdated?.Dispose(); - } - - void HandleEvent(PointerEventArgs e) - { - _events++; - if (_slider != null) - { - Thread.Sleep((int)_slider.Value); - } - InvalidateVisual(); - - if (e.RoutedEvent == PointerReleasedEvent && e.Pointer.Type == PointerType.Touch) - { - _pointers.Remove(e.Pointer.Id); - return; - } - - var lastPointer = e.GetCurrentPoint(this); - _lastProperties = lastPointer.Properties; - - if (e.Pointer.Type != PointerType.Pen - || lastPointer.Properties.Pressure > 0) - { - if (!_pointers.TryGetValue(e.Pointer.Id, out var pt)) - _pointers[e.Pointer.Id] = pt = new PointerPoints(); - pt.HandleEvent(e, this); - } - } - - public override void Render(DrawingContext context) - { - context.FillRectangle(Brushes.White, Bounds); - foreach (var pt in _pointers.Values) - pt.Render(context, _drawPoints); - base.Render(context); - } - - protected override void OnPointerPressed(PointerPressedEventArgs e) - { - if (e.ClickCount == 2) - { - _pointers.Clear(); - InvalidateVisual(); - return; - } - - HandleEvent(e); - base.OnPointerPressed(e); - } - - protected override void OnPointerMoved(PointerEventArgs e) - { - HandleEvent(e); - base.OnPointerMoved(e); - } - - protected override void OnPointerReleased(PointerReleasedEventArgs e) - { - HandleEvent(e); - base.OnPointerReleased(e); - } - } -} diff --git a/samples/ControlCatalog/Pages/PointersPage.xaml b/samples/ControlCatalog/Pages/PointersPage.xaml new file mode 100644 index 0000000000..1281ec77b6 --- /dev/null +++ b/samples/ControlCatalog/Pages/PointersPage.xaml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + Capture 1 + + + Capture 2 + + + + + diff --git a/samples/ControlCatalog/Pages/PointersPage.xaml.cs b/samples/ControlCatalog/Pages/PointersPage.xaml.cs new file mode 100644 index 0000000000..977cee3d58 --- /dev/null +++ b/samples/ControlCatalog/Pages/PointersPage.xaml.cs @@ -0,0 +1,76 @@ +using System; +using Avalonia; +using Avalonia.Controls; +using Avalonia.Input; +using Avalonia.Interactivity; +using Avalonia.Markup.Xaml; + +namespace ControlCatalog.Pages; + +public class PointersPage : UserControl +{ + public PointersPage() + { + this.InitializeComponent(); + + var border1 = this.Get("BorderCapture1"); + var border2 = this.Get("BorderCapture2"); + + border1.PointerPressed += Border_PointerPressed; + border1.PointerReleased += Border_PointerReleased; + border1.PointerCaptureLost += Border_PointerCaptureLost; + border1.PointerMoved += Border_PointerUpdated; + border1.PointerEnter += Border_PointerUpdated; + border1.PointerLeave += Border_PointerUpdated; + + border2.PointerPressed += Border_PointerPressed; + border2.PointerReleased += Border_PointerReleased; + border2.PointerCaptureLost += Border_PointerCaptureLost; + border2.PointerMoved += Border_PointerUpdated; + border2.PointerEnter += Border_PointerUpdated; + border2.PointerLeave += Border_PointerUpdated; + } + + private void Border_PointerUpdated(object sender, PointerEventArgs e) + { + var textBlock = (TextBlock)((Border)sender).Child; + var position = e.GetPosition((Border)sender); + textBlock.Text = @$"Captured: {e.Pointer.Captured == sender} +PointerId: {e.Pointer.Id} +Position: {(int)position.X} {(int)position.Y}"; + e.Handled = true; + } + + private void Border_PointerCaptureLost(object sender, PointerCaptureLostEventArgs e) + { + var textBlock = (TextBlock)((Border)sender).Child; + textBlock.Text = @$"Captured: {e.Pointer.Captured == sender} +PointerId: {e.Pointer.Id} +Position: ??? ???"; + e.Handled = true; + } + + private void Border_PointerReleased(object sender, PointerReleasedEventArgs e) + { + if (e.Pointer.Captured == sender) + { + e.Pointer.Capture(null); + e.Handled = true; + } + else + { + throw new InvalidOperationException("How?"); + } + } + + private void Border_PointerPressed(object sender, PointerPressedEventArgs e) + { + e.Pointer.Capture((Border)sender); + e.Handled = true; + } + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + } +} From e7b281e3fd9cb86db8fbabb2af933821b9eba809 Mon Sep 17 00:00:00 2001 From: Max Katz Date: Sat, 16 Apr 2022 04:32:06 -0400 Subject: [PATCH 24/78] Fix GetIntermediatePoints reverse order --- .../Avalonia.Win32/WindowImpl.AppWndProc.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs index 6619c60152..1f316a0995 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs @@ -714,8 +714,6 @@ namespace Avalonia.Win32 private unsafe Lazy> CreateLazyIntermediatePoints(POINTER_INFO info) { - // Limit history size with reasonable value. - // With sizeof(POINTER_TOUCH_INFO) * 100 we can get maximum 14400 bytes. var historyCount = Math.Min((int)info.historyCount, MaxPointerHistorySize); if (historyCount > 1) { @@ -723,12 +721,15 @@ namespace Avalonia.Win32 { s_intermediatePointsPooledList.Clear(); s_intermediatePointsPooledList.Capacity = historyCount; + + // Pointers in history are ordered from newest to oldest, so we need to reverse iteration. + // Also we skip the newest pointer, because original event arguments already contains it. + if (info.pointerType == PointerInputType.PT_TOUCH) { if (GetPointerTouchInfoHistory(info.pointerId, ref historyCount, s_historyTouchInfos)) { - //last info is the same as the current so skip it - for (int i = 0; i < historyCount - 1; i++) + for (int i = historyCount - 1; i >= 1; i--) { var historyTouchInfo = s_historyTouchInfos[i]; s_intermediatePointsPooledList.Add(CreateRawPointerPoint(historyTouchInfo)); @@ -739,8 +740,8 @@ namespace Avalonia.Win32 { if (GetPointerPenInfoHistory(info.pointerId, ref historyCount, s_historyPenInfos)) { - //last info is the same as the current so skip it - for (int i = 0; i < historyCount - 1; i++) + uint timestamp = 0; + for (int i = historyCount - 1; i >= 1; i--) { var historyPenInfo = s_historyPenInfos[i]; s_intermediatePointsPooledList.Add(CreateRawPointerPoint(historyPenInfo)); @@ -752,8 +753,7 @@ namespace Avalonia.Win32 // Currently Windows does not return history info for mouse input, but we handle it just for case. if (GetPointerInfoHistory(info.pointerId, ref historyCount, s_historyInfos)) { - //last info is the same as the current so skip it - for (int i = 0; i < historyCount - 1; i++) + for (int i = historyCount - 1; i >= 1; i--) { var historyInfo = s_historyInfos[i]; s_intermediatePointsPooledList.Add(CreateRawPointerPoint(historyInfo)); From a08ccd91cba6efec6367ebc9e7d1d3cce226ae6b Mon Sep 17 00:00:00 2001 From: Max Katz Date: Sun, 17 Apr 2022 03:44:22 -0400 Subject: [PATCH 25/78] Fix DataGrid scrolling --- src/Avalonia.Controls.DataGrid/DataGridCell.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Controls.DataGrid/DataGridCell.cs b/src/Avalonia.Controls.DataGrid/DataGridCell.cs index 67183781d3..ea7d91ed97 100644 --- a/src/Avalonia.Controls.DataGrid/DataGridCell.cs +++ b/src/Avalonia.Controls.DataGrid/DataGridCell.cs @@ -178,9 +178,9 @@ namespace Avalonia.Controls { var handled = OwningGrid.UpdateStateOnMouseLeftButtonDown(e, ColumnIndex, OwningRow.Slot, !e.Handled); - // Do not handle PointerPressed with touch, + // Do not handle PointerPressed with touch or pen, // so we can start scroll gesture on the same event. - if (e.Pointer.Type != PointerType.Touch) + if (e.Pointer.Type != PointerType.Touch && e.Pointer.Type != PointerType.Pen) { e.Handled = handled; } From f4cc30d4a10149d4a9d9f88578ee35b3ecfa0b0a Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Sun, 29 May 2022 22:28:28 +0200 Subject: [PATCH 26/78] Add failing test for Window.Width/Height. --- .../WindowTests.cs | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/Avalonia.Controls.UnitTests/WindowTests.cs b/tests/Avalonia.Controls.UnitTests/WindowTests.cs index 63ccf74c2b..a8c9b68d12 100644 --- a/tests/Avalonia.Controls.UnitTests/WindowTests.cs +++ b/tests/Avalonia.Controls.UnitTests/WindowTests.cs @@ -695,6 +695,31 @@ namespace Avalonia.Controls.UnitTests } } + [Fact] + public void Width_Height_Should_Not_Be_NaN_After_Show_With_SizeToContent_Manual() + { + using (UnitTestApplication.Start(TestServices.StyledWindow)) + { + var child = new Canvas + { + Width = 400, + Height = 800, + }; + + var target = new Window() + { + SizeToContent = SizeToContent.Manual, + Content = child + }; + + Show(target); + + // Values come from MockWindowingPlatform defaults. + Assert.Equal(800, target.Width); + Assert.Equal(600, target.Height); + } + } + [Fact] public void Width_Height_Should_Not_Be_NaN_After_Show_With_SizeToContent_WidthAndHeight() { @@ -712,6 +737,8 @@ namespace Avalonia.Controls.UnitTests Content = child }; + target.GetObservable(Window.WidthProperty).Subscribe(x => { }); + Show(target); Assert.Equal(400, target.Width); From 138be304a0d2c86c663846bfa7adfb1537058fd1 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 30 May 2022 11:53:34 +0200 Subject: [PATCH 27/78] Ensure Window.Width/Height is initialized. - Run resize logic if `Width`/`Height` are still NaN (i.e. not set up) - Always call base class `WindowBase.HandleResize` - In `WindowBase.HandleResize` don't run a layout pass if client size unchanged Fixes `Width_Height_Should_Not_Be_NaN_After_Show_With_SizeToContent_Manual`. --- src/Avalonia.Controls/Window.cs | 40 ++++++++++++++--------------- src/Avalonia.Controls/WindowBase.cs | 12 ++++++--- 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index a4f4534b88..9b49e866b8 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -991,28 +991,28 @@ namespace Avalonia.Controls /// protected sealed override void HandleResized(Size clientSize, PlatformResizeReason reason) { - if (ClientSize == clientSize) - return; - - var sizeToContent = SizeToContent; - - // If auto-sizing is enabled, and the resize came from a user resize (or the reason was - // unspecified) then turn off auto-resizing for any window dimension that is not equal - // to the requested size. - if (sizeToContent != SizeToContent.Manual && - CanResize && - reason == PlatformResizeReason.Unspecified || - reason == PlatformResizeReason.User) + if (ClientSize != clientSize || double.IsNaN(Width) || double.IsNaN(Height)) { - if (clientSize.Width != ClientSize.Width) - sizeToContent &= ~SizeToContent.Width; - if (clientSize.Height != ClientSize.Height) - sizeToContent &= ~SizeToContent.Height; - SizeToContent = sizeToContent; - } + var sizeToContent = SizeToContent; + + // If auto-sizing is enabled, and the resize came from a user resize (or the reason was + // unspecified) then turn off auto-resizing for any window dimension that is not equal + // to the requested size. + if (sizeToContent != SizeToContent.Manual && + CanResize && + reason == PlatformResizeReason.Unspecified || + reason == PlatformResizeReason.User) + { + if (clientSize.Width != ClientSize.Width) + sizeToContent &= ~SizeToContent.Width; + if (clientSize.Height != ClientSize.Height) + sizeToContent &= ~SizeToContent.Height; + SizeToContent = sizeToContent; + } - Width = clientSize.Width; - Height = clientSize.Height; + Width = clientSize.Width; + Height = clientSize.Height; + } base.HandleResized(clientSize, reason); } diff --git a/src/Avalonia.Controls/WindowBase.cs b/src/Avalonia.Controls/WindowBase.cs index 12ba143c8a..d5e54a5c08 100644 --- a/src/Avalonia.Controls/WindowBase.cs +++ b/src/Avalonia.Controls/WindowBase.cs @@ -217,10 +217,16 @@ namespace Avalonia.Controls /// The reason for the resize. protected override void HandleResized(Size clientSize, PlatformResizeReason reason) { - ClientSize = clientSize; FrameSize = PlatformImpl?.FrameSize; - LayoutManager.ExecuteLayoutPass(); - Renderer?.Resized(clientSize); + + if (ClientSize != clientSize) + { + ClientSize = clientSize; + LayoutManager.ExecuteLayoutPass(); + Renderer?.Resized(clientSize); + } + + System.Diagnostics.Debug.WriteLine($"HandleResized: ClientSize {ClientSize} | FrameSize {FrameSize}"); } /// From 67e6c41abcbaed905bba22446ee54b995a29bed1 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 30 May 2022 11:54:34 +0200 Subject: [PATCH 28/78] Use FrameSize for window startup location. ...if available. --- src/Avalonia.Controls/Window.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index 9b49e866b8..92f74530e2 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -871,10 +871,10 @@ namespace Avalonia.Controls var scaling = owner?.DesktopScaling ?? PlatformImpl?.DesktopScaling ?? 1; - // TODO: We really need non-client size here. - var rect = new PixelRect( - PixelPoint.Origin, - PixelSize.FromSize(ClientSize, scaling)); + // Use frame size, falling back to client size if the platform can't give it to us. + var rect = FrameSize.HasValue ? + new PixelRect(PixelSize.FromSize(FrameSize.Value, scaling)) : + new PixelRect(PixelSize.FromSize(ClientSize, scaling)); if (startupLocation == WindowStartupLocation.CenterScreen) { From 4c8240b7bf349ca5bc7f74344ba45af73b77f57c Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 30 May 2022 11:57:13 +0200 Subject: [PATCH 29/78] Added integration tests for WindowStartupLocation. --- samples/IntegrationTestApp/MainWindow.axaml | 17 ++ .../IntegrationTestApp/MainWindow.axaml.cs | 38 ++++ .../IntegrationTestApp/ShowWindowTest.axaml | 26 +++ .../ShowWindowTest.axaml.cs | 40 +++++ .../Avalonia.IntegrationTests.Appium.csproj | 4 + .../WindowTests.cs | 164 ++++++++++++++++++ 6 files changed, 289 insertions(+) create mode 100644 samples/IntegrationTestApp/ShowWindowTest.axaml create mode 100644 samples/IntegrationTestApp/ShowWindowTest.axaml.cs create mode 100644 tests/Avalonia.IntegrationTests.Appium/WindowTests.cs diff --git a/samples/IntegrationTestApp/MainWindow.axaml b/samples/IntegrationTestApp/MainWindow.axaml index 19ac68b15b..5151d80932 100644 --- a/samples/IntegrationTestApp/MainWindow.axaml +++ b/samples/IntegrationTestApp/MainWindow.axaml @@ -94,6 +94,23 @@ + + + + + + NonOwned + Owned + Modal + + + Manual + CenterScreen + CenterOwner + + + + diff --git a/samples/IntegrationTestApp/MainWindow.axaml.cs b/samples/IntegrationTestApp/MainWindow.axaml.cs index 9a612aa94d..580548a433 100644 --- a/samples/IntegrationTestApp/MainWindow.axaml.cs +++ b/samples/IntegrationTestApp/MainWindow.axaml.cs @@ -5,6 +5,7 @@ using Avalonia; using Avalonia.Controls; using Avalonia.Interactivity; using Avalonia.Markup.Xaml; +using Avalonia.VisualTree; namespace IntegrationTestApp { @@ -46,6 +47,41 @@ namespace IntegrationTestApp } } + private void ShowWindow() + { + var sizeTextBox = this.GetControl("ShowWindowSize"); + var modeComboBox = this.GetControl("ShowWindowMode"); + var locationComboBox = this.GetControl("ShowWindowLocation"); + var size = !string.IsNullOrWhiteSpace(sizeTextBox.Text) ? Size.Parse(sizeTextBox.Text) : (Size?)null; + var owner = (Window)this.GetVisualRoot()!; + + var window = new ShowWindowTest + { + WindowStartupLocation = (WindowStartupLocation)locationComboBox.SelectedIndex, + }; + + if (size.HasValue) + { + window.Width = size.Value.Width; + window.Height = size.Value.Height; + } + + sizeTextBox.Text = string.Empty; + + switch (modeComboBox.SelectedIndex) + { + case 0: + window.Show(); + break; + case 1: + window.Show(owner); + break; + case 2: + window.ShowDialog(owner); + break; + } + } + private void MenuClicked(object? sender, RoutedEventArgs e) { var clickedMenuItemTextBlock = this.FindControl("ClickedMenuItem"); @@ -64,6 +100,8 @@ namespace IntegrationTestApp this.FindControl("BasicListBox").SelectedIndex = -1; if (source?.Name == "MenuClickedMenuItemReset") this.FindControl("ClickedMenuItem").Text = "None"; + if (source?.Name == "ShowWindow") + ShowWindow(); } } } diff --git a/samples/IntegrationTestApp/ShowWindowTest.axaml b/samples/IntegrationTestApp/ShowWindowTest.axaml new file mode 100644 index 0000000000..e87ae0f32c --- /dev/null +++ b/samples/IntegrationTestApp/ShowWindowTest.axaml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/IntegrationTestApp/ShowWindowTest.axaml.cs b/samples/IntegrationTestApp/ShowWindowTest.axaml.cs new file mode 100644 index 0000000000..9b55864caa --- /dev/null +++ b/samples/IntegrationTestApp/ShowWindowTest.axaml.cs @@ -0,0 +1,40 @@ +using System; +using Avalonia.Controls; +using Avalonia.Interactivity; +using Avalonia.Markup.Xaml; +using Avalonia.Rendering; + +namespace IntegrationTestApp +{ + public class ShowWindowTest : Window + { + public ShowWindowTest() + { + InitializeComponent(); + } + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + } + + protected override void OnOpened(EventArgs e) + { + base.OnOpened(e); + this.GetControl("ClientSize").Text = $"{Width}, {Height}"; + this.GetControl("FrameSize").Text = $"{FrameSize}"; + this.GetControl("Position").Text = $"{Position}"; + this.GetControl("ScreenRect").Text = $"{Screens.ScreenFromVisual(this)?.WorkingArea}"; + this.GetControl("Scaling").Text = $"{((IRenderRoot)this).RenderScaling}"; + + if (Owner is not null) + { + var ownerRect = this.GetControl("OwnerRect"); + var owner = (Window)Owner; + ownerRect.Text = $"{owner.Position}, {owner.FrameSize}"; + } + } + + private void CloseWindow_Click(object sender, RoutedEventArgs e) => Close(); + } +} diff --git a/tests/Avalonia.IntegrationTests.Appium/Avalonia.IntegrationTests.Appium.csproj b/tests/Avalonia.IntegrationTests.Appium/Avalonia.IntegrationTests.Appium.csproj index 095f0e63e0..03d9332051 100644 --- a/tests/Avalonia.IntegrationTests.Appium/Avalonia.IntegrationTests.Appium.csproj +++ b/tests/Avalonia.IntegrationTests.Appium/Avalonia.IntegrationTests.Appium.csproj @@ -5,6 +5,10 @@ enable + + + + diff --git a/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs b/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs new file mode 100644 index 0000000000..771faa1925 --- /dev/null +++ b/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs @@ -0,0 +1,164 @@ +using System; +using System.Linq; +using System.Runtime.InteropServices; +using Avalonia.Controls; +using OpenQA.Selenium.Appium; +using Xunit; +using Xunit.Sdk; + +namespace Avalonia.IntegrationTests.Appium +{ + [Collection("Default")] + public class WindowTests + { + private readonly AppiumDriver _session; + + public WindowTests(TestAppFixture fixture) + { + _session = fixture.Session; + + var tabs = _session.FindElementByAccessibilityId("MainTabs"); + var tab = tabs.FindElementByName("Window"); + tab.Click(); + } + + [Theory] + [MemberData(nameof(StartupLocationData))] + public void StartupLocation(string? size, ShowWindowMode mode, WindowStartupLocation location) + { + var mainWindowHandle = GetCurrentWindowHandleHack(); + + try + { + var sizeTextBox = _session.FindElementByAccessibilityId("ShowWindowSize"); + var modeComboBox = _session.FindElementByAccessibilityId("ShowWindowMode"); + var locationComboBox = _session.FindElementByAccessibilityId("ShowWindowLocation"); + var showButton = _session.FindElementByAccessibilityId("ShowWindow"); + + if (size is not null) + sizeTextBox.SendKeys(size); + + modeComboBox.Click(); + _session.FindElementByName(mode.ToString()).SendClick(); + + locationComboBox.Click(); + _session.FindElementByName(location.ToString()).SendClick(); + + showButton.Click(); + SwitchToNewWindowHack(oldWindowHandle: mainWindowHandle); + + var clientSize = Size.Parse(_session.FindElementByAccessibilityId("ClientSize").Text); + var frameSize = Size.Parse(_session.FindElementByAccessibilityId("FrameSize").Text); + var position = PixelPoint.Parse(_session.FindElementByAccessibilityId("Position").Text); + var screenRect = PixelRect.Parse(_session.FindElementByAccessibilityId("ScreenRect").Text); + var scaling = double.Parse(_session.FindElementByAccessibilityId("Scaling").Text); + + Assert.True(frameSize.Width >= clientSize.Width, "Expected frame width >= client width."); + Assert.True(frameSize.Height > clientSize.Height, "Expected frame height > client height."); + + var frameRect = new PixelRect(position, PixelSize.FromSize(frameSize, scaling)); + + switch (location) + { + case WindowStartupLocation.CenterScreen: + { + var expected = screenRect.CenterRect(frameRect); + AssertCloseEnough(expected.Position, frameRect.Position); + break; + } + } + } + finally + { + try + { + var closeButton = _session.FindElementByAccessibilityId("CloseWindow"); + closeButton.Click(); + SwitchToMainWindowHack(mainWindowHandle); + } + catch { } + } + } + + public static TheoryData StartupLocationData() + { + var sizes = new[] { null, "400,300" }; + var data = new TheoryData(); + + foreach (var size in sizes) + { + foreach (var mode in Enum.GetValues()) + { + foreach (var location in Enum.GetValues()) + { + if (!(location == WindowStartupLocation.CenterOwner && mode == ShowWindowMode.NonOwned)) + { + data.Add(size, mode, location); + } + } + } + } + + return data; + } + + private string? GetCurrentWindowHandleHack() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + // HACK: WinAppDriver only seems to switch to a newly opened window if the window has an owner, + // otherwise the session remains targeting the previous window. Return the handle for the + // current window so we know which window to switch to when another is opened. + return _session.WindowHandles.Single(); + } + + return null; + } + + private void SwitchToNewWindowHack(string? oldWindowHandle) + { + if (oldWindowHandle is not null) + { + var newWindowHandle = _session.WindowHandles.FirstOrDefault(x => x != oldWindowHandle); + + // HACK: Looks like WinAppDriver only adds window handles for non-owned windows, but luckily + // non-owned windows is where we're having the problem, so if we find a window handle that + // isn't the main window handle then switch to it. + if (newWindowHandle is not null) + _session.SwitchTo().Window(newWindowHandle); + } + } + + private void SwitchToMainWindowHack(string? mainWindowHandle) + { + if (mainWindowHandle is not null) + _session.SwitchTo().Window(mainWindowHandle); + } + + private static void AssertCloseEnough(PixelPoint expected, PixelPoint actual) + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + // On win32, accurate frame information cannot be obtained until a window is shown but + // WindowStartupLocation needs to be calculated before the window is shown, meaning that + // the position of a centered window can be off by a bit. From initial testing, looks + // like this shouldn't be more than 10 pixels. + if (Math.Abs(expected.X - actual.X) > 10) + throw new EqualException(expected, actual); + if (Math.Abs(expected.Y - actual.Y) > 10) + throw new EqualException(expected, actual); + } + else + { + Assert.Equal(expected, actual); + } + } + + public enum ShowWindowMode + { + NonOwned, + Owned, + Modal + } + } +} From a2d83e8fae5a559bca83d87db7f5a30d901618ed Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 31 May 2022 13:11:07 +0100 Subject: [PATCH 30/78] [OSX] programatically implement child window relationship --- native/Avalonia.Native/src/OSX/AvnView.mm | 5 ++ native/Avalonia.Native/src/OSX/AvnWindow.mm | 38 +++++------ .../Avalonia.Native/src/OSX/WindowBaseImpl.h | 2 + .../Avalonia.Native/src/OSX/WindowBaseImpl.mm | 7 +- native/Avalonia.Native/src/OSX/WindowImpl.h | 8 ++- native/Avalonia.Native/src/OSX/WindowImpl.mm | 66 +++++++++++++------ .../Avalonia.Native/src/OSX/WindowProtocol.h | 1 - 7 files changed, 81 insertions(+), 46 deletions(-) diff --git a/native/Avalonia.Native/src/OSX/AvnView.mm b/native/Avalonia.Native/src/OSX/AvnView.mm index 5436ad22f3..bbb4d59adb 100644 --- a/native/Avalonia.Native/src/OSX/AvnView.mm +++ b/native/Avalonia.Native/src/OSX/AvnView.mm @@ -300,6 +300,11 @@ - (void)mouseDown:(NSEvent *)event { + if(_parent != nullptr) + { + _parent->BringToFront(); + } + _isLeftPressed = true; _lastMouseDownEvent = event; [self mouseEvent:event withType:LeftButtonDown]; diff --git a/native/Avalonia.Native/src/OSX/AvnWindow.mm b/native/Avalonia.Native/src/OSX/AvnWindow.mm index 590dc5e7ac..1445227cf5 100644 --- a/native/Avalonia.Native/src/OSX/AvnWindow.mm +++ b/native/Avalonia.Native/src/OSX/AvnWindow.mm @@ -183,6 +183,11 @@ return self; } +- (void)mouseDown:(NSEvent *)event +{ + _parent->BringToFront(); +} + - (BOOL)windowShouldClose:(NSWindow *)sender { auto window = dynamic_cast(_parent.getRaw()); @@ -209,7 +214,14 @@ { ComPtr parent = _parent; _parent = NULL; - [self restoreParentWindow]; + + auto window = dynamic_cast(parent.getRaw()); + + if(window != nullptr) + { + window->SetParent(nullptr); + } + parent->BaseEvents->Closed(); [parent->View onClosed]; } @@ -220,17 +232,11 @@ if(_canBecomeKeyWindow) { // If the window has a child window being shown as a dialog then don't allow it to become the key window. - for(NSWindow* uch in [self childWindows]) + auto parent = dynamic_cast(_parent.getRaw()); + + if(parent != nullptr) { - if (![uch conformsToProtocol:@protocol(AvnWindowProtocol)]) - { - continue; - } - - id ch = (id ) uch; - - if(ch.isDialog) - return false; + return parent->CanBecomeKeyWindow(); } return true; @@ -273,16 +279,6 @@ [super becomeKeyWindow]; } --(void) restoreParentWindow; -{ - auto parent = [self parentWindow]; - - if(parent != nil) - { - [parent removeChildWindow:self]; - } -} - - (void)windowDidMiniaturize:(NSNotification *)notification { auto parent = dynamic_cast(_parent.operator->()); diff --git a/native/Avalonia.Native/src/OSX/WindowBaseImpl.h b/native/Avalonia.Native/src/OSX/WindowBaseImpl.h index 83850e780c..62c0e2069d 100644 --- a/native/Avalonia.Native/src/OSX/WindowBaseImpl.h +++ b/native/Avalonia.Native/src/OSX/WindowBaseImpl.h @@ -99,6 +99,8 @@ BEGIN_INTERFACE_MAP() virtual bool IsDialog(); id GetWindowProtocol (); + + virtual void BringToFront (); protected: virtual NSWindowStyleMask GetStyle(); diff --git a/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm b/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm index 121679b942..77f0f47934 100644 --- a/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm +++ b/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm @@ -143,8 +143,6 @@ HRESULT WindowBaseImpl::Hide() { @autoreleasepool { if (Window != nullptr) { [Window orderOut:Window]; - - [GetWindowProtocol() restoreParentWindow]; } return S_OK; @@ -610,6 +608,11 @@ id WindowBaseImpl::GetWindowProtocol() { return (id ) Window; } +void WindowBaseImpl::BringToFront() +{ + // do nothing. +} + extern IAvnWindow* CreateAvnWindow(IAvnWindowEvents*events, IAvnGlContext* gl) { @autoreleasepool diff --git a/native/Avalonia.Native/src/OSX/WindowImpl.h b/native/Avalonia.Native/src/OSX/WindowImpl.h index 35627685a2..76d5cbf6ea 100644 --- a/native/Avalonia.Native/src/OSX/WindowImpl.h +++ b/native/Avalonia.Native/src/OSX/WindowImpl.h @@ -8,6 +8,7 @@ #import "WindowBaseImpl.h" #include "IWindowStateChanged.h" +#include class WindowImpl : public virtual WindowBaseImpl, public virtual IAvnWindow, public IWindowStateChanged { @@ -22,7 +23,8 @@ private: bool _transitioningWindowState; bool _isClientAreaExtended; bool _isDialog; - WindowImpl* _lastParent; + WindowImpl* _parent; + std::list _children; AvnExtendClientAreaChromeHints _extendClientHints; FORWARD_IUNKNOWN() @@ -91,6 +93,10 @@ BEGIN_INTERFACE_MAP() virtual bool IsDialog() override; virtual void OnInitialiseNSWindow() override; + + virtual void BringToFront () override; + + bool CanBecomeKeyWindow (); protected: virtual NSWindowStyleMask GetStyle() override; diff --git a/native/Avalonia.Native/src/OSX/WindowImpl.mm b/native/Avalonia.Native/src/OSX/WindowImpl.mm index ad804eb280..5333cb23c8 100644 --- a/native/Avalonia.Native/src/OSX/WindowImpl.mm +++ b/native/Avalonia.Native/src/OSX/WindowImpl.mm @@ -10,6 +10,7 @@ #include "WindowProtocol.h" WindowImpl::WindowImpl(IAvnWindowEvents *events, IAvnGlContext *gl) : WindowBaseImpl(events, gl) { + _children = std::list(); _isClientAreaExtended = false; _extendClientHints = AvnDefaultChrome; _fullScreenActive = false; @@ -20,7 +21,7 @@ WindowImpl::WindowImpl(IAvnWindowEvents *events, IAvnGlContext *gl) : WindowBase _lastWindowState = Normal; _actualWindowState = Normal; _lastTitle = @""; - _lastParent = nullptr; + _parent = nullptr; WindowEvents = events; } @@ -63,9 +64,9 @@ void WindowImpl::OnInitialiseNSWindow(){ SetExtendClientArea(true); } - if(_lastParent != nullptr) + if(_parent != nullptr) { - SetParent(_lastParent); + SetParent(_parent); } } @@ -96,33 +97,56 @@ HRESULT WindowImpl::SetParent(IAvnWindow *parent) { START_COM_CALL; @autoreleasepool { - if (parent == nullptr) - return E_POINTER; + if(_parent != nullptr) + { + _parent->_children.remove(this); + } auto cparent = dynamic_cast(parent); - if (cparent == nullptr) - return E_INVALIDARG; - - _lastParent = cparent; + _parent = cparent; - if(Window != nullptr){ - // If one tries to show a child window with a minimized parent window, then the parent window will be - // restored but macOS isn't kind enough to *tell* us that, so the window will be left in a non-interactive - // state. Detect this and explicitly restore the parent window ourselves to avoid this situation. - if (cparent->WindowState() == Minimized) - cparent->SetWindowState(Normal); - - [Window setCollectionBehavior:NSWindowCollectionBehaviorFullScreenAuxiliary]; - [cparent->Window addChildWindow:Window ordered:NSWindowAbove]; - - UpdateStyle(); + if(_parent != nullptr && Window != nullptr){ + // If one tries to show a child window with a minimized parent window, then the parent window will be + // restored but macOS isn't kind enough to *tell* us that, so the window will be left in a non-interactive + // state. Detect this and explicitly restore the parent window ourselves to avoid this situation. + if (cparent->WindowState() == Minimized) + cparent->SetWindowState(Normal); + + [Window setCollectionBehavior:NSWindowCollectionBehaviorFullScreenAuxiliary]; + + cparent->_children.push_back(this); + + UpdateStyle(); } return S_OK; } } +void WindowImpl::BringToFront() +{ + Activate(); + + for(auto iterator = _children.begin(); iterator != _children.end(); iterator++) + { + (*iterator)->BringToFront(); + } +} + +bool WindowImpl::CanBecomeKeyWindow() +{ + for(auto iterator = _children.begin(); iterator != _children.end(); iterator++) + { + if((*iterator)->IsDialog()) + { + return false; + } + } + + return true; +} + void WindowImpl::StartStateTransition() { _transitioningWindowState = true; } @@ -534,7 +558,7 @@ bool WindowImpl::IsDialog() { } NSWindowStyleMask WindowImpl::GetStyle() { - unsigned long s = this->_isDialog ? NSWindowStyleMaskDocModalWindow : NSWindowStyleMaskBorderless; + unsigned long s = NSWindowStyleMaskBorderless; switch (_decorations) { case SystemDecorationsNone: diff --git a/native/Avalonia.Native/src/OSX/WindowProtocol.h b/native/Avalonia.Native/src/OSX/WindowProtocol.h index 0e5c5869e7..cb5f86bdb9 100644 --- a/native/Avalonia.Native/src/OSX/WindowProtocol.h +++ b/native/Avalonia.Native/src/OSX/WindowProtocol.h @@ -11,7 +11,6 @@ @protocol AvnWindowProtocol -(void) pollModalSession: (NSModalSession _Nonnull) session; --(void) restoreParentWindow; -(bool) shouldTryToHandleEvents; -(void) setEnabled: (bool) enable; -(void) showAppMenuOnly; From dc1b6a669b8a90bc71344ea6b6df28e2b489e7a0 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 31 May 2022 13:50:01 +0100 Subject: [PATCH 31/78] [osx] make bringtofront work correctly for owned and modal windows. --- native/Avalonia.Native/src/OSX/AvnView.mm | 5 ----- native/Avalonia.Native/src/OSX/AvnWindow.mm | 9 +++------ native/Avalonia.Native/src/OSX/WindowImpl.mm | 9 ++++++++- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/native/Avalonia.Native/src/OSX/AvnView.mm b/native/Avalonia.Native/src/OSX/AvnView.mm index bbb4d59adb..5436ad22f3 100644 --- a/native/Avalonia.Native/src/OSX/AvnView.mm +++ b/native/Avalonia.Native/src/OSX/AvnView.mm @@ -300,11 +300,6 @@ - (void)mouseDown:(NSEvent *)event { - if(_parent != nullptr) - { - _parent->BringToFront(); - } - _isLeftPressed = true; _lastMouseDownEvent = event; [self mouseEvent:event withType:LeftButtonDown]; diff --git a/native/Avalonia.Native/src/OSX/AvnWindow.mm b/native/Avalonia.Native/src/OSX/AvnWindow.mm index 1445227cf5..60fdb26121 100644 --- a/native/Avalonia.Native/src/OSX/AvnWindow.mm +++ b/native/Avalonia.Native/src/OSX/AvnWindow.mm @@ -183,11 +183,6 @@ return self; } -- (void)mouseDown:(NSEvent *)event -{ - _parent->BringToFront(); -} - - (BOOL)windowShouldClose:(NSWindow *)sender { auto window = dynamic_cast(_parent.getRaw()); @@ -435,8 +430,10 @@ _parent->BaseEvents->RawMouseEvent(NonClientLeftButtonDown, static_cast([event timestamp] * 1000), AvnInputModifiersNone, point, delta); } + + _parent->BringToFront(); } - break; + break; case NSEventTypeMouseEntered: { diff --git a/native/Avalonia.Native/src/OSX/WindowImpl.mm b/native/Avalonia.Native/src/OSX/WindowImpl.mm index 5333cb23c8..8330f4ed86 100644 --- a/native/Avalonia.Native/src/OSX/WindowImpl.mm +++ b/native/Avalonia.Native/src/OSX/WindowImpl.mm @@ -126,7 +126,14 @@ HRESULT WindowImpl::SetParent(IAvnWindow *parent) { void WindowImpl::BringToFront() { - Activate(); + if(IsDialog()) + { + Activate(); + } + else + { + [Window orderFront:nullptr]; + } for(auto iterator = _children.begin(); iterator != _children.end(); iterator++) { From f7daa81fbe8d684c13d0d10c8fb2727734e2e480 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 31 May 2022 14:10:33 +0100 Subject: [PATCH 32/78] dont create nspanel / nswindow at show. --- native/Avalonia.Native/src/OSX/WindowBaseImpl.mm | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm b/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm index 77f0f47934..d105f4cf38 100644 --- a/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm +++ b/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm @@ -36,8 +36,10 @@ WindowBaseImpl::WindowBaseImpl(IAvnWindowBaseEvents *events, IAvnGlContext *gl) lastMaxSize = NSSize { CGFLOAT_MAX, CGFLOAT_MAX}; lastMinSize = NSSize { 0, 0 }; - Window = nullptr; lastMenu = nullptr; + + CreateNSWindow(false); + InitialiseNSWindow(); } HRESULT WindowBaseImpl::ObtainNSViewHandle(void **ret) { @@ -88,7 +90,6 @@ HRESULT WindowBaseImpl::Show(bool activate, bool isDialog) { START_COM_CALL; @autoreleasepool { - CreateNSWindow(isDialog); InitialiseNSWindow(); if(hasPosition) @@ -585,6 +586,7 @@ void WindowBaseImpl::InitialiseNSWindow() { [Window setOpaque:false]; + [Window setHasShadow:true]; [Window invalidateShadow]; if (lastMenu != nullptr) { From 041fdb6bc9bcb06711c7715692e2d5771ad6a2eb Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 31 May 2022 14:11:19 +0100 Subject: [PATCH 33/78] call bring to front when window is made key. --- native/Avalonia.Native/src/OSX/AvnWindow.mm | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/native/Avalonia.Native/src/OSX/AvnWindow.mm b/native/Avalonia.Native/src/OSX/AvnWindow.mm index 60fdb26121..52ee48317c 100644 --- a/native/Avalonia.Native/src/OSX/AvnWindow.mm +++ b/native/Avalonia.Native/src/OSX/AvnWindow.mm @@ -274,6 +274,11 @@ [super becomeKeyWindow]; } +- (void)windowDidBecomeKey:(NSNotification *)notification +{ + _parent->BringToFront(); +} + - (void)windowDidMiniaturize:(NSNotification *)notification { auto parent = dynamic_cast(_parent.operator->()); From 2ea49defb60cf0a8412dabde876a2d8c27e1d8c5 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 31 May 2022 14:28:44 +0100 Subject: [PATCH 34/78] [osx] easily support using nspanel from windowbaseimpl. --- native/Avalonia.Native/src/OSX/WindowBaseImpl.h | 2 +- native/Avalonia.Native/src/OSX/WindowBaseImpl.mm | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/native/Avalonia.Native/src/OSX/WindowBaseImpl.h b/native/Avalonia.Native/src/OSX/WindowBaseImpl.h index 62c0e2069d..4220811fc7 100644 --- a/native/Avalonia.Native/src/OSX/WindowBaseImpl.h +++ b/native/Avalonia.Native/src/OSX/WindowBaseImpl.h @@ -26,7 +26,7 @@ BEGIN_INTERFACE_MAP() virtual ~WindowBaseImpl(); - WindowBaseImpl(IAvnWindowBaseEvents *events, IAvnGlContext *gl); + WindowBaseImpl(IAvnWindowBaseEvents *events, IAvnGlContext *gl, bool usePanel = false); virtual HRESULT ObtainNSWindowHandle(void **ret) override; diff --git a/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm b/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm index d105f4cf38..e88c7f208c 100644 --- a/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm +++ b/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm @@ -21,7 +21,7 @@ WindowBaseImpl::~WindowBaseImpl() { Window = nullptr; } -WindowBaseImpl::WindowBaseImpl(IAvnWindowBaseEvents *events, IAvnGlContext *gl) { +WindowBaseImpl::WindowBaseImpl(IAvnWindowBaseEvents *events, IAvnGlContext *gl, bool usePanel) { _shown = false; _inResize = false; BaseEvents = events; @@ -38,7 +38,7 @@ WindowBaseImpl::WindowBaseImpl(IAvnWindowBaseEvents *events, IAvnGlContext *gl) lastMenu = nullptr; - CreateNSWindow(false); + CreateNSWindow(usePanel); InitialiseNSWindow(); } From 76abbc8fbef53c161763e0387d46ace4b22819e0 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 31 May 2022 16:34:22 +0100 Subject: [PATCH 35/78] ensure frameSize is refreshed when window is show. --- src/Avalonia.Controls/TopLevel.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs index 57fb82485c..f2e8cdb1cf 100644 --- a/src/Avalonia.Controls/TopLevel.cs +++ b/src/Avalonia.Controls/TopLevel.cs @@ -484,7 +484,11 @@ namespace Avalonia.Controls /// Raises the event. /// /// The event args. - protected virtual void OnOpened(EventArgs e) => Opened?.Invoke(this, e); + protected virtual void OnOpened(EventArgs e) + { + FrameSize = PlatformImpl?.FrameSize; + Opened?.Invoke(this, e); + } /// /// Raises the event. From 67b6811ca8d18ed7e4063cb712577a260a0de232 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 31 May 2022 16:34:33 +0100 Subject: [PATCH 36/78] add comment to show why test isnt working. --- samples/IntegrationTestApp/ShowWindowTest.axaml.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/IntegrationTestApp/ShowWindowTest.axaml.cs b/samples/IntegrationTestApp/ShowWindowTest.axaml.cs index 9b55864caa..f5f87c5c1c 100644 --- a/samples/IntegrationTestApp/ShowWindowTest.axaml.cs +++ b/samples/IntegrationTestApp/ShowWindowTest.axaml.cs @@ -25,7 +25,7 @@ namespace IntegrationTestApp this.GetControl("FrameSize").Text = $"{FrameSize}"; this.GetControl("Position").Text = $"{Position}"; this.GetControl("ScreenRect").Text = $"{Screens.ScreenFromVisual(this)?.WorkingArea}"; - this.GetControl("Scaling").Text = $"{((IRenderRoot)this).RenderScaling}"; + this.GetControl("Scaling").Text = $"{((IRenderRoot)this).RenderScaling}"; // TODO Use DesktopScaling from WindowImpl. if (Owner is not null) { From cef238d1950e7ec195f4d8f201181bde29b7f207 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Wed, 1 Jun 2022 10:10:43 +0100 Subject: [PATCH 37/78] dispatch bring to front parent when removing a child window. --- native/Avalonia.Native/src/OSX/WindowImpl.mm | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/native/Avalonia.Native/src/OSX/WindowImpl.mm b/native/Avalonia.Native/src/OSX/WindowImpl.mm index 8330f4ed86..7776b2912d 100644 --- a/native/Avalonia.Native/src/OSX/WindowImpl.mm +++ b/native/Avalonia.Native/src/OSX/WindowImpl.mm @@ -100,6 +100,11 @@ HRESULT WindowImpl::SetParent(IAvnWindow *parent) { if(_parent != nullptr) { _parent->_children.remove(this); + auto parent = _parent; + + dispatch_async(dispatch_get_main_queue(), ^{ + parent->BringToFront(); + }); } auto cparent = dynamic_cast(parent); From f017acae5685fe8b7c5f9fdf9cbd4308dea08c2e Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Wed, 1 Jun 2022 10:15:54 +0100 Subject: [PATCH 38/78] dialogs should not be minimizable. --- native/Avalonia.Native/src/OSX/WindowImpl.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native/Avalonia.Native/src/OSX/WindowImpl.mm b/native/Avalonia.Native/src/OSX/WindowImpl.mm index 7776b2912d..8520e3e470 100644 --- a/native/Avalonia.Native/src/OSX/WindowImpl.mm +++ b/native/Avalonia.Native/src/OSX/WindowImpl.mm @@ -590,7 +590,7 @@ NSWindowStyleMask WindowImpl::GetStyle() { break; } - if ([Window parentWindow] == nullptr) { + if (!IsDialog()) { s |= NSWindowStyleMaskMiniaturizable; } From 0d6e3a55f016bf521263735eac066d26bab37d47 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Wed, 1 Jun 2022 17:07:02 +0100 Subject: [PATCH 39/78] add test to show that osx chrome buttons are disabled when modal dialog is opened. --- .../WindowTests.cs | 59 ++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs b/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs index 771faa1925..a82c46b927 100644 --- a/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs +++ b/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs @@ -22,6 +22,63 @@ namespace Avalonia.IntegrationTests.Appium tab.Click(); } + [PlatformFact(SkipOnWindows = true)] + public void OSX_Parent_Window_Has_Disabled_ChromeButtons_When_Modal_Dialog_Shown() + { + var mainWindowHandle = GetCurrentWindowHandleHack(); + + try + { + var sizeTextBox = _session.FindElementByAccessibilityId("ShowWindowSize"); + var modeComboBox = _session.FindElementByAccessibilityId("ShowWindowMode"); + var locationComboBox = _session.FindElementByAccessibilityId("ShowWindowLocation"); + var showButton = _session.FindElementByAccessibilityId("ShowWindow"); + + var closeButton = + _session.FindElementByXPath( + "/XCUIElementTypeApplication/XCUIElementTypeWindow/XCUIElementTypeButton[1]"); + + var zoomButton = + _session.FindElementByXPath( + "/XCUIElementTypeApplication/XCUIElementTypeWindow/XCUIElementTypeButton[2]"); + + var miniturizeButton = + _session.FindElementByXPath( + "/XCUIElementTypeApplication/XCUIElementTypeWindow/XCUIElementTypeButton[3]"); + + + Assert.True(closeButton.Enabled); + Assert.True(zoomButton.Enabled); + Assert.True(miniturizeButton.Enabled); + + sizeTextBox.SendKeys("400, 400"); + + modeComboBox.Click(); + _session.FindElementByName(ShowWindowMode.Modal.ToString()).SendClick(); + + locationComboBox.Click(); + _session.FindElementByName(WindowStartupLocation.CenterOwner.ToString()).SendClick(); + + showButton.Click(); + + SwitchToNewWindowHack(oldWindowHandle: mainWindowHandle); + + Assert.False(closeButton.Enabled); + Assert.False(zoomButton.Enabled); + Assert.False(miniturizeButton.Enabled); + } + finally + { + try + { + var closeButton = _session.FindElementByAccessibilityId("CloseWindow"); + closeButton.Click(); + SwitchToMainWindowHack(mainWindowHandle); + } + catch { } + } + } + [Theory] [MemberData(nameof(StartupLocationData))] public void StartupLocation(string? size, ShowWindowMode mode, WindowStartupLocation location) @@ -52,7 +109,7 @@ namespace Avalonia.IntegrationTests.Appium var position = PixelPoint.Parse(_session.FindElementByAccessibilityId("Position").Text); var screenRect = PixelRect.Parse(_session.FindElementByAccessibilityId("ScreenRect").Text); var scaling = double.Parse(_session.FindElementByAccessibilityId("Scaling").Text); - + Assert.True(frameSize.Width >= clientSize.Width, "Expected frame width >= client width."); Assert.True(frameSize.Height > clientSize.Height, "Expected frame height > client height."); From b7397a7cdf710fe17d49ee3993196fefd734d74b Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Wed, 1 Jun 2022 17:56:36 +0100 Subject: [PATCH 40/78] add a11y identifiers for windows. --- samples/IntegrationTestApp/MainWindow.axaml | 1 + samples/IntegrationTestApp/ShowWindowTest.axaml | 1 + 2 files changed, 2 insertions(+) diff --git a/samples/IntegrationTestApp/MainWindow.axaml b/samples/IntegrationTestApp/MainWindow.axaml index 5151d80932..82348691e9 100644 --- a/samples/IntegrationTestApp/MainWindow.axaml +++ b/samples/IntegrationTestApp/MainWindow.axaml @@ -4,6 +4,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="IntegrationTestApp.MainWindow" + Name="MainWindow" Title="IntegrationTestApp"> diff --git a/samples/IntegrationTestApp/ShowWindowTest.axaml b/samples/IntegrationTestApp/ShowWindowTest.axaml index e87ae0f32c..2525bfc866 100644 --- a/samples/IntegrationTestApp/ShowWindowTest.axaml +++ b/samples/IntegrationTestApp/ShowWindowTest.axaml @@ -1,6 +1,7 @@ From a7713dcda9d0b40d9f1dbcbd21ce2d4cea94f9ef Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Wed, 1 Jun 2022 17:56:52 +0100 Subject: [PATCH 41/78] add a unit test for child window order osx. --- .../WindowTests.cs | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs b/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs index a82c46b927..1f5ac052ec 100644 --- a/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs +++ b/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs @@ -2,7 +2,9 @@ using System.Linq; using System.Runtime.InteropServices; using Avalonia.Controls; +using OpenQA.Selenium; using OpenQA.Selenium.Appium; +using SeleniumExtras.PageObjects; using Xunit; using Xunit.Sdk; @@ -21,6 +23,79 @@ namespace Avalonia.IntegrationTests.Appium var tab = tabs.FindElementByName("Window"); tab.Click(); } + + [PlatformFact(SkipOnWindows = true)] + public void OSX_WindowOrder_Modal_Dialog_Stays_InFront_Of_Parent() + { + var mainWindowHandle = GetCurrentWindowHandleHack(); + + try + { + var sizeTextBox = _session.FindElementByAccessibilityId("ShowWindowSize"); + var modeComboBox = _session.FindElementByAccessibilityId("ShowWindowMode"); + var locationComboBox = _session.FindElementByAccessibilityId("ShowWindowLocation"); + var showButton = _session.FindElementByAccessibilityId("ShowWindow"); + + var mainWindow = + _session.FindElementByAccessibilityId("MainWindow"); + + + + sizeTextBox.SendKeys("200, 100"); + + modeComboBox.Click(); + _session.FindElementByName(ShowWindowMode.Modal.ToString()).SendClick(); + + locationComboBox.Click(); + _session.FindElementByName(WindowStartupLocation.CenterOwner.ToString()).SendClick(); + + showButton.Click(); + + var secondaryWindow = _session.FindElementByAccessibilityId("SecondaryWindow"); + + mainWindow.Click(); + + var windows = _session.FindElements(By.XPath("XCUIElementTypeWindow")); + + int i = 0; + int mainWindowIndex = 0; + int secondaryWindowIndex = 0; + + foreach (var window in windows) + { + i++; + + var child = window.FindElementByXPath("XCUIElementTypeWindow"); + + switch (child.GetAttribute("identifier")) + { + case "MainWindow": + mainWindowIndex = i; + break; + + case "SecondaryWindow": + secondaryWindowIndex = i; + break; + } + + } + + Assert.Equal(1, secondaryWindowIndex); + Assert.Equal(2, mainWindowIndex); + + SwitchToNewWindowHack(oldWindowHandle: mainWindowHandle); + } + finally + { + try + { + var closeButton = _session.FindElementByAccessibilityId("CloseWindow"); + closeButton.Click(); + SwitchToMainWindowHack(mainWindowHandle); + } + catch { } + } + } [PlatformFact(SkipOnWindows = true)] public void OSX_Parent_Window_Has_Disabled_ChromeButtons_When_Modal_Dialog_Shown() From a70dadea18bd0ff1fb9e0b1a6fa657659eb608a4 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Wed, 1 Jun 2022 18:17:15 +0100 Subject: [PATCH 42/78] simplify test. --- .../WindowTests.cs | 42 +++++++------------ 1 file changed, 14 insertions(+), 28 deletions(-) diff --git a/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs b/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs index 1f5ac052ec..8d6be4d199 100644 --- a/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs +++ b/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using Avalonia.Controls; @@ -39,8 +40,6 @@ namespace Avalonia.IntegrationTests.Appium var mainWindow = _session.FindElementByAccessibilityId("MainWindow"); - - sizeTextBox.SendKeys("200, 100"); modeComboBox.Click(); @@ -51,37 +50,15 @@ namespace Avalonia.IntegrationTests.Appium showButton.Click(); - var secondaryWindow = _session.FindElementByAccessibilityId("SecondaryWindow"); - mainWindow.Click(); var windows = _session.FindElements(By.XPath("XCUIElementTypeWindow")); - int i = 0; - int mainWindowIndex = 0; - int secondaryWindowIndex = 0; + int mainWindowIndex = windows.GetWindowOrder("MainWindow"); + int secondaryWindowIndex = windows.GetWindowOrder("SecondaryWindow"); - foreach (var window in windows) - { - i++; - - var child = window.FindElementByXPath("XCUIElementTypeWindow"); - - switch (child.GetAttribute("identifier")) - { - case "MainWindow": - mainWindowIndex = i; - break; - - case "SecondaryWindow": - secondaryWindowIndex = i; - break; - } - - } - - Assert.Equal(1, secondaryWindowIndex); - Assert.Equal(2, mainWindowIndex); + Assert.Equal(0, secondaryWindowIndex); + Assert.Equal(1, mainWindowIndex); SwitchToNewWindowHack(oldWindowHandle: mainWindowHandle); } @@ -293,4 +270,13 @@ namespace Avalonia.IntegrationTests.Appium Modal } } + + static class Extensions + { + public static int GetWindowOrder(this IReadOnlyCollection elements, string identifier) + { + return elements.TakeWhile(x => + x.FindElementByXPath("XCUIElementTypeWindow")?.GetAttribute("identifier") != identifier).Count(); + } + } } From 1917def95927cb95d55a1d08ea14943cd5e03849 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 2 Jun 2022 14:15:02 +0100 Subject: [PATCH 43/78] full set of window tests for osx. --- .../ShowWindowTest.axaml.cs | 2 +- .../WindowTests.cs | 226 +++++++++++++----- 2 files changed, 165 insertions(+), 63 deletions(-) diff --git a/samples/IntegrationTestApp/ShowWindowTest.axaml.cs b/samples/IntegrationTestApp/ShowWindowTest.axaml.cs index f5f87c5c1c..3f45f1c5ad 100644 --- a/samples/IntegrationTestApp/ShowWindowTest.axaml.cs +++ b/samples/IntegrationTestApp/ShowWindowTest.axaml.cs @@ -25,7 +25,7 @@ namespace IntegrationTestApp this.GetControl("FrameSize").Text = $"{FrameSize}"; this.GetControl("Position").Text = $"{Position}"; this.GetControl("ScreenRect").Text = $"{Screens.ScreenFromVisual(this)?.WorkingArea}"; - this.GetControl("Scaling").Text = $"{((IRenderRoot)this).RenderScaling}"; // TODO Use DesktopScaling from WindowImpl. + this.GetControl("Scaling").Text = $"{PlatformImpl?.DesktopScaling}"; if (Owner is not null) { diff --git a/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs b/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs index 8d6be4d199..b027c17ff3 100644 --- a/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs +++ b/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Reactive.Disposables; using System.Runtime.InteropServices; using Avalonia.Controls; using OpenQA.Selenium; @@ -24,53 +25,117 @@ namespace Avalonia.IntegrationTests.Appium var tab = tabs.FindElementByName("Window"); tab.Click(); } + + private IDisposable OpenWindow(ShowWindowMode mode, WindowStartupLocation location, int width = 200, int height = 100) + { + var mainWindow = GetCurrentWindowHandleHack(); + var sizeTextBox = _session.FindElementByAccessibilityId("ShowWindowSize"); + var modeComboBox = _session.FindElementByAccessibilityId("ShowWindowMode"); + var locationComboBox = _session.FindElementByAccessibilityId("ShowWindowLocation"); + var showButton = _session.FindElementByAccessibilityId("ShowWindow"); + + sizeTextBox.SendKeys($"{width}, {height}"); + + modeComboBox.Click(); + _session.FindElementByName(mode.ToString()).SendClick(); + + locationComboBox.Click(); + _session.FindElementByName(location.ToString()).SendClick(); + + showButton.Click(); + + return Disposable.Create(() => + { + try + { + SwitchToNewWindowHack(mainWindow); + var closeButton = _session.FindElementByAccessibilityId("CloseWindow"); + closeButton.SendClick(); + } + catch { } + }); + } [PlatformFact(SkipOnWindows = true)] public void OSX_WindowOrder_Modal_Dialog_Stays_InFront_Of_Parent() { var mainWindowHandle = GetCurrentWindowHandleHack(); + var mainWindow = + _session.FindElementByAccessibilityId("MainWindow"); + try { - var sizeTextBox = _session.FindElementByAccessibilityId("ShowWindowSize"); - var modeComboBox = _session.FindElementByAccessibilityId("ShowWindowMode"); - var locationComboBox = _session.FindElementByAccessibilityId("ShowWindowLocation"); - var showButton = _session.FindElementByAccessibilityId("ShowWindow"); + using (OpenWindow(ShowWindowMode.Modal, WindowStartupLocation.CenterOwner)) + { + mainWindow.Click(); - var mainWindow = - _session.FindElementByAccessibilityId("MainWindow"); - - sizeTextBox.SendKeys("200, 100"); + var windows = _session.FindElements(By.XPath("XCUIElementTypeWindow")); - modeComboBox.Click(); - _session.FindElementByName(ShowWindowMode.Modal.ToString()).SendClick(); + int mainWindowIndex = windows.GetWindowOrder("MainWindow"); + int secondaryWindowIndex = windows.GetWindowOrder("SecondaryWindow"); - locationComboBox.Click(); - _session.FindElementByName(WindowStartupLocation.CenterOwner.ToString()).SendClick(); + Assert.Equal(0, secondaryWindowIndex); + Assert.Equal(1, mainWindowIndex); + } + } + finally + { + SwitchToMainWindowHack(mainWindowHandle); + } + } + + [PlatformFact(SkipOnWindows = true)] + public void OSX_WindowOrder_Owned_Dialog_Stays_InFront_Of_Parent() + { + var mainWindowHandle = GetCurrentWindowHandleHack(); + + var mainWindow = + _session.FindElementByAccessibilityId("MainWindow"); - showButton.Click(); + try + { + using (OpenWindow(ShowWindowMode.Owned, WindowStartupLocation.CenterOwner)) + { + mainWindow.Click(); + var windows = _session.FindElements(By.XPath("XCUIElementTypeWindow")); + + int mainWindowIndex = windows.GetWindowOrder("MainWindow"); + int secondaryWindowIndex = windows.GetWindowOrder("SecondaryWindow"); + + Assert.Equal(0, secondaryWindowIndex); + Assert.Equal(1, mainWindowIndex); + } + } + finally + { + SwitchToMainWindowHack(mainWindowHandle); + } + } + + [PlatformFact(SkipOnWindows = true)] + public void OSX_WindowOrder_NonOwned_Window_Does_Not_Stay_InFront_Of_Parent() + { + var mainWindow = + _session.FindElementByAccessibilityId("MainWindow"); + + using (OpenWindow(ShowWindowMode.NonOwned, WindowStartupLocation.CenterOwner, 1400)) + { mainWindow.Click(); + var secondaryWindow = + _session.FindElementByAccessibilityId("SecondaryWindow"); + var windows = _session.FindElements(By.XPath("XCUIElementTypeWindow")); int mainWindowIndex = windows.GetWindowOrder("MainWindow"); int secondaryWindowIndex = windows.GetWindowOrder("SecondaryWindow"); - - Assert.Equal(0, secondaryWindowIndex); - Assert.Equal(1, mainWindowIndex); - SwitchToNewWindowHack(oldWindowHandle: mainWindowHandle); - } - finally - { - try - { - var closeButton = _session.FindElementByAccessibilityId("CloseWindow"); - closeButton.Click(); - SwitchToMainWindowHack(mainWindowHandle); - } - catch { } + Assert.Equal(1, secondaryWindowIndex); + Assert.Equal(0, mainWindowIndex); + + secondaryWindow.SendClick(); } } @@ -81,53 +146,54 @@ namespace Avalonia.IntegrationTests.Appium try { - var sizeTextBox = _session.FindElementByAccessibilityId("ShowWindowSize"); - var modeComboBox = _session.FindElementByAccessibilityId("ShowWindowMode"); - var locationComboBox = _session.FindElementByAccessibilityId("ShowWindowLocation"); - var showButton = _session.FindElementByAccessibilityId("ShowWindow"); + var window = _session.FindWindowOuter("MainWindow"); - var closeButton = - _session.FindElementByXPath( - "/XCUIElementTypeApplication/XCUIElementTypeWindow/XCUIElementTypeButton[1]"); - - var zoomButton = - _session.FindElementByXPath( - "/XCUIElementTypeApplication/XCUIElementTypeWindow/XCUIElementTypeButton[2]"); - - var miniturizeButton = - _session.FindElementByXPath( - "/XCUIElementTypeApplication/XCUIElementTypeWindow/XCUIElementTypeButton[3]"); - + var (closeButton, zoomButton, miniturizeButton) + = window.GetChromeButtons(); Assert.True(closeButton.Enabled); Assert.True(zoomButton.Enabled); Assert.True(miniturizeButton.Enabled); - - sizeTextBox.SendKeys("400, 400"); - modeComboBox.Click(); - _session.FindElementByName(ShowWindowMode.Modal.ToString()).SendClick(); - - locationComboBox.Click(); - _session.FindElementByName(WindowStartupLocation.CenterOwner.ToString()).SendClick(); + using (OpenWindow(ShowWindowMode.Modal, WindowStartupLocation.CenterOwner)) + { + SwitchToNewWindowHack(oldWindowHandle: mainWindowHandle); - showButton.Click(); - - SwitchToNewWindowHack(oldWindowHandle: mainWindowHandle); - - Assert.False(closeButton.Enabled); - Assert.False(zoomButton.Enabled); - Assert.False(miniturizeButton.Enabled); + Assert.False(closeButton.Enabled); + Assert.False(zoomButton.Enabled); + Assert.False(miniturizeButton.Enabled); + } } finally { - try + SwitchToMainWindowHack(mainWindowHandle); + } + } + + [PlatformFact(SkipOnWindows = true)] + public void OSX_Minimize_Button_Disabled_Modal_Dialog() + { + var mainWindowHandle = GetCurrentWindowHandleHack(); + + try + { + using (OpenWindow(ShowWindowMode.Modal, WindowStartupLocation.CenterOwner)) { - var closeButton = _session.FindElementByAccessibilityId("CloseWindow"); - closeButton.Click(); - SwitchToMainWindowHack(mainWindowHandle); + var secondaryWindow = _session.FindWindowOuter("SecondaryWindow"); + + var (closeButton, zoomButton, miniturizeButton) + = secondaryWindow.GetChromeButtons(); + + Assert.True(closeButton.Enabled); + Assert.True(zoomButton.Enabled); + Assert.False(miniturizeButton.Enabled); + + SwitchToNewWindowHack(oldWindowHandle: mainWindowHandle); } - catch { } + } + finally + { + SwitchToMainWindowHack(mainWindowHandle); } } @@ -257,6 +323,13 @@ namespace Avalonia.IntegrationTests.Appium if (Math.Abs(expected.Y - actual.Y) > 10) throw new EqualException(expected, actual); } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + if (Math.Abs(expected.X - actual.X) > 15) + throw new EqualException(expected, actual); + if (Math.Abs(expected.Y - actual.Y) > 15) + throw new EqualException(expected, actual); + } else { Assert.Equal(expected, actual); @@ -278,5 +351,34 @@ namespace Avalonia.IntegrationTests.Appium return elements.TakeWhile(x => x.FindElementByXPath("XCUIElementTypeWindow")?.GetAttribute("identifier") != identifier).Count(); } + + public static AppiumWebElement? FindWindowInner(this AppiumDriver session, string identifier) + { + return session.FindElementsByXPath("XCUIElementTypeWindow") + .FirstOrDefault(x => x.GetAttribute("identifier") == identifier); + } + + public static AppiumWebElement? FindWindowOuter(this AppiumDriver session, string identifier) + { + var windows = session.FindElementsByXPath("XCUIElementTypeWindow"); + + var window = windows.FirstOrDefault(x=>x.FindElementsByXPath("XCUIElementTypeWindow").Any(x => x.GetAttribute("identifier") == identifier)); + + return window; + } + + public static (AppiumWebElement? closeButton, AppiumWebElement? zoomButton, AppiumWebElement? miniturizeButton) GetChromeButtons (this AppiumWebElement outerWindow) + { + var closeButton = + outerWindow.FindElementByXPath("XCUIElementTypeButton[1]"); + + var zoomButton = + outerWindow.FindElementByXPath("XCUIElementTypeButton[2]"); + + var miniturizeButton = + outerWindow.FindElementByXPath("XCUIElementTypeButton[3]"); + + return (closeButton, zoomButton, miniturizeButton); + } } } From 827692fa272aaa841d352d5aef3d5b5f9c5614dd Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 2 Jun 2022 22:36:22 +0100 Subject: [PATCH 44/78] add test for osx modal dialog window order when clicking resize grip of parent. --- .../WindowTests.cs | 41 ++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs b/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs index b027c17ff3..59e705bd9b 100644 --- a/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs +++ b/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs @@ -3,9 +3,11 @@ using System.Collections.Generic; using System.Linq; using System.Reactive.Disposables; using System.Runtime.InteropServices; +using System.Threading.Tasks; using Avalonia.Controls; using OpenQA.Selenium; using OpenQA.Selenium.Appium; +using OpenQA.Selenium.Interactions; using SeleniumExtras.PageObjects; using Xunit; using Xunit.Sdk; @@ -50,7 +52,7 @@ namespace Avalonia.IntegrationTests.Appium { SwitchToNewWindowHack(mainWindow); var closeButton = _session.FindElementByAccessibilityId("CloseWindow"); - closeButton.SendClick(); + closeButton.Click(); } catch { } }); @@ -85,6 +87,43 @@ namespace Avalonia.IntegrationTests.Appium } } + [PlatformFact(SkipOnWindows = true)] + public void OSX_WindowOrder_Modal_Dialog_Stays_InFront_Of_Parent_When_Clicking_Resize_Grip() + { + var mainWindowHandle = GetCurrentWindowHandleHack(); + + var mainWindow = + _session.FindWindowOuter("MainWindow"); + + try + { + using (OpenWindow(ShowWindowMode.Modal, WindowStartupLocation.CenterOwner)) + { + new Actions(_session) + .MoveToElement(mainWindow, 100, 1) + .ClickAndHold() + .Perform(); + + var windows = _session.FindElements(By.XPath("XCUIElementTypeWindow")); + + int mainWindowIndex = windows.GetWindowOrder("MainWindow"); + int secondaryWindowIndex = windows.GetWindowOrder("SecondaryWindow"); + + new Actions(_session) + .MoveToElement(mainWindow, 100, 1) + .Release() + .Perform(); + + Assert.Equal(0, secondaryWindowIndex); + Assert.Equal(1, mainWindowIndex); + } + } + finally + { + SwitchToMainWindowHack(mainWindowHandle); + } + } + [PlatformFact(SkipOnWindows = true)] public void OSX_WindowOrder_Owned_Dialog_Stays_InFront_Of_Parent() { From a0af269d36b6300e941b1d9196746c08668528ec Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 2 Jun 2022 23:02:37 +0100 Subject: [PATCH 45/78] reset app after most tests, add test for fullscreen mode with modal osx. --- .../WindowTests.cs | 72 +++++++++++++++---- 1 file changed, 59 insertions(+), 13 deletions(-) diff --git a/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs b/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs index 59e705bd9b..8bf429c2ed 100644 --- a/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs +++ b/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs @@ -84,6 +84,7 @@ namespace Avalonia.IntegrationTests.Appium finally { SwitchToMainWindowHack(mainWindowHandle); + _session.ResetApp(); } } @@ -121,6 +122,41 @@ namespace Avalonia.IntegrationTests.Appium finally { SwitchToMainWindowHack(mainWindowHandle); + _session.ResetApp(); + } + } + + [PlatformFact(SkipOnWindows = true)] + public void OSX_WindowOrder_Modal_Dialog_Stays_InFront_Of_Parent_When_In_Fullscreen() + { + var mainWindowHandle = GetCurrentWindowHandleHack(); + + var mainWindow = + _session.FindWindowOuter("MainWindow"); + + var buttons = mainWindow.GetChromeButtons(); + + buttons.zoomButton.Click(); + + Task.Delay(500).Wait(); + + try + { + using (OpenWindow(ShowWindowMode.Modal, WindowStartupLocation.CenterOwner)) + { + var windows = _session.FindElements(By.XPath("XCUIElementTypeWindow")); + + int mainWindowIndex = windows.GetWindowOrder("MainWindow"); + int secondaryWindowIndex = windows.GetWindowOrder("SecondaryWindow"); + + Assert.Equal(0, secondaryWindowIndex); + Assert.Equal(1, mainWindowIndex); + } + } + finally + { + SwitchToMainWindowHack(mainWindowHandle); + _session.ResetApp(); } } @@ -150,31 +186,39 @@ namespace Avalonia.IntegrationTests.Appium finally { SwitchToMainWindowHack(mainWindowHandle); + _session.ResetApp(); } } - + [PlatformFact(SkipOnWindows = true)] public void OSX_WindowOrder_NonOwned_Window_Does_Not_Stay_InFront_Of_Parent() { var mainWindow = _session.FindElementByAccessibilityId("MainWindow"); - using (OpenWindow(ShowWindowMode.NonOwned, WindowStartupLocation.CenterOwner, 1400)) + try { - mainWindow.Click(); - - var secondaryWindow = - _session.FindElementByAccessibilityId("SecondaryWindow"); + using (OpenWindow(ShowWindowMode.NonOwned, WindowStartupLocation.CenterOwner, 1400)) + { + mainWindow.Click(); - var windows = _session.FindElements(By.XPath("XCUIElementTypeWindow")); + var secondaryWindow = + _session.FindElementByAccessibilityId("SecondaryWindow"); - int mainWindowIndex = windows.GetWindowOrder("MainWindow"); - int secondaryWindowIndex = windows.GetWindowOrder("SecondaryWindow"); + var windows = _session.FindElements(By.XPath("XCUIElementTypeWindow")); - Assert.Equal(1, secondaryWindowIndex); - Assert.Equal(0, mainWindowIndex); - - secondaryWindow.SendClick(); + int mainWindowIndex = windows.GetWindowOrder("MainWindow"); + int secondaryWindowIndex = windows.GetWindowOrder("SecondaryWindow"); + + Assert.Equal(1, secondaryWindowIndex); + Assert.Equal(0, mainWindowIndex); + + secondaryWindow.SendClick(); + } + } + finally + { + _session.ResetApp(); } } @@ -206,6 +250,7 @@ namespace Avalonia.IntegrationTests.Appium finally { SwitchToMainWindowHack(mainWindowHandle); + _session.ResetApp(); } } @@ -233,6 +278,7 @@ namespace Avalonia.IntegrationTests.Appium finally { SwitchToMainWindowHack(mainWindowHandle); + _session.ResetApp(); } } From 860fcc524d4be5ad292ce09713f0dd9fd6ac7329 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Tue, 21 Jun 2022 13:46:35 +0200 Subject: [PATCH 46/78] Refactor how we show windows. Trying to make it a little less hacky. Only tested on Win32 so far. --- .../ElementExtensions.cs | 63 ++++++++ .../WindowTests.cs | 144 +++++++----------- 2 files changed, 114 insertions(+), 93 deletions(-) diff --git a/tests/Avalonia.IntegrationTests.Appium/ElementExtensions.cs b/tests/Avalonia.IntegrationTests.Appium/ElementExtensions.cs index 3eb8646835..07fea24a93 100644 --- a/tests/Avalonia.IntegrationTests.Appium/ElementExtensions.cs +++ b/tests/Avalonia.IntegrationTests.Appium/ElementExtensions.cs @@ -1,8 +1,12 @@ using System; using System.Collections.Generic; +using System.Linq; +using System.Reactive.Disposables; using System.Runtime.InteropServices; +using OpenQA.Selenium; using OpenQA.Selenium.Appium; using OpenQA.Selenium.Interactions; +using Xunit; namespace Avalonia.IntegrationTests.Appium { @@ -43,6 +47,65 @@ namespace Avalonia.IntegrationTests.Appium } } + /// + /// Clicks a button which is expected to open a new window. + /// + /// The button to click. + /// + /// An object which when disposed will cause the newly opened window to close. + /// + public static IDisposable OpenWindowWithClick(this AppiumWebElement element) + { + var session = element.WrappedDriver; + var oldHandle = session.CurrentWindowHandle; + var oldHandles = session.WindowHandles.ToList(); + var oldChildWindows = session.FindElements(By.XPath("//Window")); + + element.Click(); + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + var newHandle = session.WindowHandles.Except(oldHandles).SingleOrDefault(); + + if (newHandle is not null) + { + // A new top-level window was opened. We need to switch to it. + session.SwitchTo().Window(newHandle); + + return Disposable.Create(() => + { + session.Close(); + session.SwitchTo().Window(oldHandle); + }); + } + else + { + // If a new window handle hasn't been added to the session then it's likely + // that a child window was opened. These don't appear in session.WindowHandles + // so we have to use an XPath query to get hold of it. + var newChildWindows = session.FindElements(By.XPath("//Window")); + var childWindow = Assert.Single(newChildWindows.Except(oldChildWindows)); + + return Disposable.Create(() => + { + childWindow.SendKeys(Keys.Alt + Keys.F4 + Keys.Alt); + }); + } + } + else + { + var newHandle = session.CurrentWindowHandle; + + Assert.NotEqual(oldHandle, newHandle); + + return Disposable.Create(() => + { + session.Close(); + session.SwitchTo().Window(oldHandle); + }); + } + } + public static void SendClick(this AppiumWebElement element) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) diff --git a/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs b/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs index 8bf429c2ed..38d0d5ba1c 100644 --- a/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs +++ b/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs @@ -8,7 +8,6 @@ using Avalonia.Controls; using OpenQA.Selenium; using OpenQA.Selenium.Appium; using OpenQA.Selenium.Interactions; -using SeleniumExtras.PageObjects; using Xunit; using Xunit.Sdk; @@ -28,36 +27,33 @@ namespace Avalonia.IntegrationTests.Appium tab.Click(); } - private IDisposable OpenWindow(ShowWindowMode mode, WindowStartupLocation location, int width = 200, int height = 100) + [Theory] + [MemberData(nameof(StartupLocationData))] + public void StartupLocation(PixelSize? size, ShowWindowMode mode, WindowStartupLocation location) { - var mainWindow = GetCurrentWindowHandleHack(); - var sizeTextBox = _session.FindElementByAccessibilityId("ShowWindowSize"); - var modeComboBox = _session.FindElementByAccessibilityId("ShowWindowMode"); - var locationComboBox = _session.FindElementByAccessibilityId("ShowWindowLocation"); - var showButton = _session.FindElementByAccessibilityId("ShowWindow"); - - sizeTextBox.SendKeys($"{width}, {height}"); + using var window = OpenWindow(size, mode, location); + var clientSize = Size.Parse(_session.FindElementByAccessibilityId("ClientSize").Text); + var frameSize = Size.Parse(_session.FindElementByAccessibilityId("FrameSize").Text); + var position = PixelPoint.Parse(_session.FindElementByAccessibilityId("Position").Text); + var screenRect = PixelRect.Parse(_session.FindElementByAccessibilityId("ScreenRect").Text); + var scaling = double.Parse(_session.FindElementByAccessibilityId("Scaling").Text); - modeComboBox.Click(); - _session.FindElementByName(mode.ToString()).SendClick(); + Assert.True(frameSize.Width >= clientSize.Width, "Expected frame width >= client width."); + Assert.True(frameSize.Height > clientSize.Height, "Expected frame height > client height."); - locationComboBox.Click(); - _session.FindElementByName(location.ToString()).SendClick(); + var frameRect = new PixelRect(position, PixelSize.FromSize(frameSize, scaling)); - showButton.Click(); - - return Disposable.Create(() => + switch (location) { - try - { - SwitchToNewWindowHack(mainWindow); - var closeButton = _session.FindElementByAccessibilityId("CloseWindow"); - closeButton.Click(); - } - catch { } - }); + case WindowStartupLocation.CenterScreen: + { + var expected = screenRect.CenterRect(frameRect); + AssertCloseEnough(expected.Position, frameRect.Position); + break; + } + } } - + [PlatformFact(SkipOnWindows = true)] public void OSX_WindowOrder_Modal_Dialog_Stays_InFront_Of_Parent() { @@ -68,7 +64,7 @@ namespace Avalonia.IntegrationTests.Appium try { - using (OpenWindow(ShowWindowMode.Modal, WindowStartupLocation.CenterOwner)) + using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Modal, WindowStartupLocation.CenterOwner)) { mainWindow.Click(); @@ -98,7 +94,7 @@ namespace Avalonia.IntegrationTests.Appium try { - using (OpenWindow(ShowWindowMode.Modal, WindowStartupLocation.CenterOwner)) + using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Modal, WindowStartupLocation.CenterOwner)) { new Actions(_session) .MoveToElement(mainWindow, 100, 1) @@ -142,7 +138,7 @@ namespace Avalonia.IntegrationTests.Appium try { - using (OpenWindow(ShowWindowMode.Modal, WindowStartupLocation.CenterOwner)) + using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Modal, WindowStartupLocation.CenterOwner)) { var windows = _session.FindElements(By.XPath("XCUIElementTypeWindow")); @@ -170,7 +166,7 @@ namespace Avalonia.IntegrationTests.Appium try { - using (OpenWindow(ShowWindowMode.Owned, WindowStartupLocation.CenterOwner)) + using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Owned, WindowStartupLocation.CenterOwner)) { mainWindow.Click(); @@ -198,7 +194,7 @@ namespace Avalonia.IntegrationTests.Appium try { - using (OpenWindow(ShowWindowMode.NonOwned, WindowStartupLocation.CenterOwner, 1400)) + using (OpenWindow(new PixelSize(1400, 100), ShowWindowMode.NonOwned, WindowStartupLocation.CenterOwner)) { mainWindow.Click(); @@ -238,7 +234,7 @@ namespace Avalonia.IntegrationTests.Appium Assert.True(zoomButton.Enabled); Assert.True(miniturizeButton.Enabled); - using (OpenWindow(ShowWindowMode.Modal, WindowStartupLocation.CenterOwner)) + using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Modal, WindowStartupLocation.CenterOwner)) { SwitchToNewWindowHack(oldWindowHandle: mainWindowHandle); @@ -261,7 +257,7 @@ namespace Avalonia.IntegrationTests.Appium try { - using (OpenWindow(ShowWindowMode.Modal, WindowStartupLocation.CenterOwner)) + using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Modal, WindowStartupLocation.CenterOwner)) { var secondaryWindow = _session.FindWindowOuter("SecondaryWindow"); @@ -281,69 +277,11 @@ namespace Avalonia.IntegrationTests.Appium _session.ResetApp(); } } - - [Theory] - [MemberData(nameof(StartupLocationData))] - public void StartupLocation(string? size, ShowWindowMode mode, WindowStartupLocation location) - { - var mainWindowHandle = GetCurrentWindowHandleHack(); - - try - { - var sizeTextBox = _session.FindElementByAccessibilityId("ShowWindowSize"); - var modeComboBox = _session.FindElementByAccessibilityId("ShowWindowMode"); - var locationComboBox = _session.FindElementByAccessibilityId("ShowWindowLocation"); - var showButton = _session.FindElementByAccessibilityId("ShowWindow"); - - if (size is not null) - sizeTextBox.SendKeys(size); - - modeComboBox.Click(); - _session.FindElementByName(mode.ToString()).SendClick(); - - locationComboBox.Click(); - _session.FindElementByName(location.ToString()).SendClick(); - - showButton.Click(); - SwitchToNewWindowHack(oldWindowHandle: mainWindowHandle); - - var clientSize = Size.Parse(_session.FindElementByAccessibilityId("ClientSize").Text); - var frameSize = Size.Parse(_session.FindElementByAccessibilityId("FrameSize").Text); - var position = PixelPoint.Parse(_session.FindElementByAccessibilityId("Position").Text); - var screenRect = PixelRect.Parse(_session.FindElementByAccessibilityId("ScreenRect").Text); - var scaling = double.Parse(_session.FindElementByAccessibilityId("Scaling").Text); - - Assert.True(frameSize.Width >= clientSize.Width, "Expected frame width >= client width."); - Assert.True(frameSize.Height > clientSize.Height, "Expected frame height > client height."); - - var frameRect = new PixelRect(position, PixelSize.FromSize(frameSize, scaling)); - - switch (location) - { - case WindowStartupLocation.CenterScreen: - { - var expected = screenRect.CenterRect(frameRect); - AssertCloseEnough(expected.Position, frameRect.Position); - break; - } - } - } - finally - { - try - { - var closeButton = _session.FindElementByAccessibilityId("CloseWindow"); - closeButton.Click(); - SwitchToMainWindowHack(mainWindowHandle); - } - catch { } - } - } - public static TheoryData StartupLocationData() + public static TheoryData StartupLocationData() { - var sizes = new[] { null, "400,300" }; - var data = new TheoryData(); + var sizes = new PixelSize?[] { null, new PixelSize(400, 300) }; + var data = new TheoryData(); foreach (var size in sizes) { @@ -421,6 +359,26 @@ namespace Avalonia.IntegrationTests.Appium } } + private IDisposable OpenWindow(PixelSize? size, ShowWindowMode mode, WindowStartupLocation location) + { + var mainWindow = GetCurrentWindowHandleHack(); + var sizeTextBox = _session.FindElementByAccessibilityId("ShowWindowSize"); + var modeComboBox = _session.FindElementByAccessibilityId("ShowWindowMode"); + var locationComboBox = _session.FindElementByAccessibilityId("ShowWindowLocation"); + var showButton = _session.FindElementByAccessibilityId("ShowWindow"); + + if (size.HasValue) + sizeTextBox.SendKeys($"{size.Value.Width}, {size.Value.Height}"); + + modeComboBox.Click(); + _session.FindElementByName(mode.ToString()).SendClick(); + + locationComboBox.Click(); + _session.FindElementByName(location.ToString()).SendClick(); + + return showButton.OpenWindowWithClick(); + } + public enum ShowWindowMode { NonOwned, From 8c3424baa4e0beeb51a4b8a65fd7055be8507cd1 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 22 Jun 2022 10:36:49 +0200 Subject: [PATCH 47/78] Refactor OSX window tests a bit. Try not to rely on `_session.ResetApp();` because restoring the application state in the tests tends to show up more errors (which this change has done: https://github.com/AvaloniaUI/Avalonia/issues/8335#issuecomment-1162804733) --- samples/IntegrationTestApp/MainWindow.axaml | 2 + .../IntegrationTestApp/MainWindow.axaml.cs | 15 ++ .../IntegrationTestApp/ShowWindowTest.axaml | 2 - .../ShowWindowTest.axaml.cs | 2 - .../ElementExtensions.cs | 42 +++- .../WindowTests.cs | 210 ++++++------------ 6 files changed, 116 insertions(+), 157 deletions(-) diff --git a/samples/IntegrationTestApp/MainWindow.axaml b/samples/IntegrationTestApp/MainWindow.axaml index 82348691e9..aa2191c26b 100644 --- a/samples/IntegrationTestApp/MainWindow.axaml +++ b/samples/IntegrationTestApp/MainWindow.axaml @@ -110,6 +110,8 @@ CenterOwner + + diff --git a/samples/IntegrationTestApp/MainWindow.axaml.cs b/samples/IntegrationTestApp/MainWindow.axaml.cs index 580548a433..1aba10ec30 100644 --- a/samples/IntegrationTestApp/MainWindow.axaml.cs +++ b/samples/IntegrationTestApp/MainWindow.axaml.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using Avalonia; using Avalonia.Controls; +using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Interactivity; using Avalonia.Markup.Xaml; using Avalonia.VisualTree; @@ -82,6 +83,16 @@ namespace IntegrationTestApp } } + private void SendToBack() + { + var lifetime = (ClassicDesktopStyleApplicationLifetime)Application.Current!.ApplicationLifetime!; + + foreach (var window in lifetime.Windows) + { + window.Activate(); + } + } + private void MenuClicked(object? sender, RoutedEventArgs e) { var clickedMenuItemTextBlock = this.FindControl("ClickedMenuItem"); @@ -102,6 +113,10 @@ namespace IntegrationTestApp this.FindControl("ClickedMenuItem").Text = "None"; if (source?.Name == "ShowWindow") ShowWindow(); + if (source?.Name == "SendToBack") + SendToBack(); + if (source?.Name == "ExitFullscreen") + WindowState = WindowState.Normal; } } } diff --git a/samples/IntegrationTestApp/ShowWindowTest.axaml b/samples/IntegrationTestApp/ShowWindowTest.axaml index 2525bfc866..a263d8ab46 100644 --- a/samples/IntegrationTestApp/ShowWindowTest.axaml +++ b/samples/IntegrationTestApp/ShowWindowTest.axaml @@ -4,8 +4,6 @@ Name="SecondaryWindow" Title="Show Window Test"> - - diff --git a/samples/IntegrationTestApp/ShowWindowTest.axaml.cs b/samples/IntegrationTestApp/ShowWindowTest.axaml.cs index 3f45f1c5ad..720f7b1c12 100644 --- a/samples/IntegrationTestApp/ShowWindowTest.axaml.cs +++ b/samples/IntegrationTestApp/ShowWindowTest.axaml.cs @@ -34,7 +34,5 @@ namespace IntegrationTestApp ownerRect.Text = $"{owner.Position}, {owner.FrameSize}"; } } - - private void CloseWindow_Click(object sender, RoutedEventArgs e) => Close(); } } diff --git a/tests/Avalonia.IntegrationTests.Appium/ElementExtensions.cs b/tests/Avalonia.IntegrationTests.Appium/ElementExtensions.cs index 07fea24a93..16d37e4beb 100644 --- a/tests/Avalonia.IntegrationTests.Appium/ElementExtensions.cs +++ b/tests/Avalonia.IntegrationTests.Appium/ElementExtensions.cs @@ -15,6 +15,19 @@ namespace Avalonia.IntegrationTests.Appium public static IReadOnlyList GetChildren(this AppiumWebElement element) => element.FindElementsByXPath("*/*"); + public static (AppiumWebElement close, AppiumWebElement minimize, AppiumWebElement maximize) GetChromeButtons(this AppiumWebElement window) + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + var closeButton = window.FindElementByXPath("//XCUIElementTypeButton[1]"); + var fullscreenButton = window.FindElementByXPath("//XCUIElementTypeButton[2]"); + var minimizeButton = window.FindElementByXPath("//XCUIElementTypeButton[3]"); + return (closeButton, minimizeButton, fullscreenButton); + } + + throw new NotSupportedException("GetChromeButtons not supported on this platform."); + } + public static string GetComboBoxValue(this AppiumWebElement element) { return RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? @@ -57,14 +70,15 @@ namespace Avalonia.IntegrationTests.Appium public static IDisposable OpenWindowWithClick(this AppiumWebElement element) { var session = element.WrappedDriver; - var oldHandle = session.CurrentWindowHandle; - var oldHandles = session.WindowHandles.ToList(); - var oldChildWindows = session.FindElements(By.XPath("//Window")); - - element.Click(); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { + var oldHandle = session.CurrentWindowHandle; + var oldHandles = session.WindowHandles.ToList(); + var oldChildWindows = session.FindElements(By.XPath("//Window")); + + element.Click(); + var newHandle = session.WindowHandles.Except(oldHandles).SingleOrDefault(); if (newHandle is not null) @@ -94,14 +108,22 @@ namespace Avalonia.IntegrationTests.Appium } else { - var newHandle = session.CurrentWindowHandle; - - Assert.NotEqual(oldHandle, newHandle); + var oldWindows = session.FindElements(By.XPath("/XCUIElementTypeApplication/XCUIElementTypeWindow")); + var oldWindowTitles = oldWindows.ToDictionary(x => x.Text); + + element.Click(); + var newWindows = session.FindElements(By.XPath("/XCUIElementTypeApplication/XCUIElementTypeWindow")); + var newWindowTitles = newWindows.ToDictionary(x => x.Text); + var newWindowTitle = Assert.Single(newWindowTitles.Keys.Except(oldWindowTitles.Keys)); + var newWindow = (AppiumWebElement)newWindowTitles[newWindowTitle]; + return Disposable.Create(() => { - session.Close(); - session.SwitchTo().Window(oldHandle); + // TODO: We should be able to use Cmd+W here but Avalonia apps don't seem to have this shortcut + // set up by default. + var (close, _, _) = newWindow.GetChromeButtons(); + close!.Click(); }); } } diff --git a/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs b/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs index 38d0d5ba1c..e887a2afe8 100644 --- a/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs +++ b/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs @@ -57,82 +57,56 @@ namespace Avalonia.IntegrationTests.Appium [PlatformFact(SkipOnWindows = true)] public void OSX_WindowOrder_Modal_Dialog_Stays_InFront_Of_Parent() { - var mainWindowHandle = GetCurrentWindowHandleHack(); - - var mainWindow = - _session.FindElementByAccessibilityId("MainWindow"); + var mainWindow = _session.FindElementByAccessibilityId("MainWindow"); - try + using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Modal, WindowStartupLocation.CenterOwner)) { - using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Modal, WindowStartupLocation.CenterOwner)) - { - mainWindow.Click(); + mainWindow.Click(); - var windows = _session.FindElements(By.XPath("XCUIElementTypeWindow")); + var windows = _session.FindElements(By.XPath("XCUIElementTypeWindow")); - int mainWindowIndex = windows.GetWindowOrder("MainWindow"); - int secondaryWindowIndex = windows.GetWindowOrder("SecondaryWindow"); + int mainWindowIndex = windows.GetWindowOrder("MainWindow"); + int secondaryWindowIndex = windows.GetWindowOrder("SecondaryWindow"); - Assert.Equal(0, secondaryWindowIndex); - Assert.Equal(1, mainWindowIndex); - } - } - finally - { - SwitchToMainWindowHack(mainWindowHandle); - _session.ResetApp(); + Assert.Equal(0, secondaryWindowIndex); + Assert.Equal(1, mainWindowIndex); } } [PlatformFact(SkipOnWindows = true)] public void OSX_WindowOrder_Modal_Dialog_Stays_InFront_Of_Parent_When_Clicking_Resize_Grip() { - var mainWindowHandle = GetCurrentWindowHandleHack(); - - var mainWindow = - _session.FindWindowOuter("MainWindow"); + var mainWindow = _session.FindWindowOuter("MainWindow"); - try + using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Modal, WindowStartupLocation.CenterOwner)) { - using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Modal, WindowStartupLocation.CenterOwner)) - { - new Actions(_session) - .MoveToElement(mainWindow, 100, 1) - .ClickAndHold() - .Perform(); + new Actions(_session) + .MoveToElement(mainWindow, 100, 1) + .ClickAndHold() + .Perform(); - var windows = _session.FindElements(By.XPath("XCUIElementTypeWindow")); + var windows = _session.FindElements(By.XPath("XCUIElementTypeWindow")); - int mainWindowIndex = windows.GetWindowOrder("MainWindow"); - int secondaryWindowIndex = windows.GetWindowOrder("SecondaryWindow"); + int mainWindowIndex = windows.GetWindowOrder("MainWindow"); + int secondaryWindowIndex = windows.GetWindowOrder("SecondaryWindow"); - new Actions(_session) - .MoveToElement(mainWindow, 100, 1) - .Release() - .Perform(); + new Actions(_session) + .MoveToElement(mainWindow, 100, 1) + .Release() + .Perform(); - Assert.Equal(0, secondaryWindowIndex); - Assert.Equal(1, mainWindowIndex); - } - } - finally - { - SwitchToMainWindowHack(mainWindowHandle); - _session.ResetApp(); + Assert.Equal(0, secondaryWindowIndex); + Assert.Equal(1, mainWindowIndex); } } [PlatformFact(SkipOnWindows = true)] public void OSX_WindowOrder_Modal_Dialog_Stays_InFront_Of_Parent_When_In_Fullscreen() { - var mainWindowHandle = GetCurrentWindowHandleHack(); - - var mainWindow = - _session.FindWindowOuter("MainWindow"); - + var mainWindow = _session.FindWindowOuter("MainWindow"); var buttons = mainWindow.GetChromeButtons(); - buttons.zoomButton.Click(); + buttons.maximize.Click(); Task.Delay(500).Wait(); @@ -151,70 +125,51 @@ namespace Avalonia.IntegrationTests.Appium } finally { - SwitchToMainWindowHack(mainWindowHandle); - _session.ResetApp(); + _session.FindElementByAccessibilityId("ExitFullscreen").Click(); } } [PlatformFact(SkipOnWindows = true)] public void OSX_WindowOrder_Owned_Dialog_Stays_InFront_Of_Parent() { - var mainWindowHandle = GetCurrentWindowHandleHack(); - - var mainWindow = - _session.FindElementByAccessibilityId("MainWindow"); + var mainWindow = _session.FindElementByAccessibilityId("MainWindow"); - try + using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Owned, WindowStartupLocation.CenterOwner)) { - using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Owned, WindowStartupLocation.CenterOwner)) - { - mainWindow.Click(); + mainWindow.Click(); - var windows = _session.FindElements(By.XPath("XCUIElementTypeWindow")); + var windows = _session.FindElements(By.XPath("XCUIElementTypeWindow")); - int mainWindowIndex = windows.GetWindowOrder("MainWindow"); - int secondaryWindowIndex = windows.GetWindowOrder("SecondaryWindow"); + int mainWindowIndex = windows.GetWindowOrder("MainWindow"); + int secondaryWindowIndex = windows.GetWindowOrder("SecondaryWindow"); - Assert.Equal(0, secondaryWindowIndex); - Assert.Equal(1, mainWindowIndex); - } - } - finally - { - SwitchToMainWindowHack(mainWindowHandle); - _session.ResetApp(); + Assert.Equal(0, secondaryWindowIndex); + Assert.Equal(1, mainWindowIndex); } } [PlatformFact(SkipOnWindows = true)] public void OSX_WindowOrder_NonOwned_Window_Does_Not_Stay_InFront_Of_Parent() { - var mainWindow = - _session.FindElementByAccessibilityId("MainWindow"); + var mainWindow = _session.FindElementByAccessibilityId("MainWindow"); - try + using (OpenWindow(new PixelSize(1400, 100), ShowWindowMode.NonOwned, WindowStartupLocation.CenterOwner)) { - using (OpenWindow(new PixelSize(1400, 100), ShowWindowMode.NonOwned, WindowStartupLocation.CenterOwner)) - { - mainWindow.Click(); + mainWindow.Click(); - var secondaryWindow = - _session.FindElementByAccessibilityId("SecondaryWindow"); + var secondaryWindow = + _session.FindElementByAccessibilityId("SecondaryWindow"); - var windows = _session.FindElements(By.XPath("XCUIElementTypeWindow")); + var windows = _session.FindElements(By.XPath("XCUIElementTypeWindow")); - int mainWindowIndex = windows.GetWindowOrder("MainWindow"); - int secondaryWindowIndex = windows.GetWindowOrder("SecondaryWindow"); + int mainWindowIndex = windows.GetWindowOrder("MainWindow"); + int secondaryWindowIndex = windows.GetWindowOrder("SecondaryWindow"); - Assert.Equal(1, secondaryWindowIndex); - Assert.Equal(0, mainWindowIndex); + Assert.Equal(1, secondaryWindowIndex); + Assert.Equal(0, mainWindowIndex); - secondaryWindow.SendClick(); - } - } - finally - { - _session.ResetApp(); + var sendToBack = _session.FindElementByAccessibilityId("SendToBack"); + sendToBack.Click(); } } @@ -222,31 +177,22 @@ namespace Avalonia.IntegrationTests.Appium public void OSX_Parent_Window_Has_Disabled_ChromeButtons_When_Modal_Dialog_Shown() { var mainWindowHandle = GetCurrentWindowHandleHack(); - - try - { - var window = _session.FindWindowOuter("MainWindow"); + var window = _session.FindWindowOuter("MainWindow"); - var (closeButton, zoomButton, miniturizeButton) - = window.GetChromeButtons(); + var (closeButton, zoomButton, miniturizeButton) + = window.GetChromeButtons(); - Assert.True(closeButton.Enabled); - Assert.True(zoomButton.Enabled); - Assert.True(miniturizeButton.Enabled); + Assert.True(closeButton.Enabled); + Assert.True(zoomButton.Enabled); + Assert.True(miniturizeButton.Enabled); - using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Modal, WindowStartupLocation.CenterOwner)) - { - SwitchToNewWindowHack(oldWindowHandle: mainWindowHandle); - - Assert.False(closeButton.Enabled); - Assert.False(zoomButton.Enabled); - Assert.False(miniturizeButton.Enabled); - } - } - finally + using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Modal, WindowStartupLocation.CenterOwner)) { - SwitchToMainWindowHack(mainWindowHandle); - _session.ResetApp(); + SwitchToNewWindowHack(oldWindowHandle: mainWindowHandle); + + Assert.False(closeButton.Enabled); + Assert.False(zoomButton.Enabled); + Assert.False(miniturizeButton.Enabled); } } @@ -255,26 +201,18 @@ namespace Avalonia.IntegrationTests.Appium { var mainWindowHandle = GetCurrentWindowHandleHack(); - try + using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Modal, WindowStartupLocation.CenterOwner)) { - using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Modal, WindowStartupLocation.CenterOwner)) - { - var secondaryWindow = _session.FindWindowOuter("SecondaryWindow"); + var secondaryWindow = _session.FindWindowOuter("SecondaryWindow"); - var (closeButton, zoomButton, miniturizeButton) - = secondaryWindow.GetChromeButtons(); - - Assert.True(closeButton.Enabled); - Assert.True(zoomButton.Enabled); - Assert.False(miniturizeButton.Enabled); + var (closeButton, zoomButton, miniaturizeButton) + = secondaryWindow.GetChromeButtons(); - SwitchToNewWindowHack(oldWindowHandle: mainWindowHandle); - } - } - finally - { - SwitchToMainWindowHack(mainWindowHandle); - _session.ResetApp(); + Assert.True(closeButton.Enabled); + Assert.True(zoomButton.Enabled); + Assert.False(miniaturizeButton.Enabled); + + SwitchToNewWindowHack(oldWindowHandle: mainWindowHandle); } } @@ -409,19 +347,5 @@ namespace Avalonia.IntegrationTests.Appium return window; } - - public static (AppiumWebElement? closeButton, AppiumWebElement? zoomButton, AppiumWebElement? miniturizeButton) GetChromeButtons (this AppiumWebElement outerWindow) - { - var closeButton = - outerWindow.FindElementByXPath("XCUIElementTypeButton[1]"); - - var zoomButton = - outerWindow.FindElementByXPath("XCUIElementTypeButton[2]"); - - var miniturizeButton = - outerWindow.FindElementByXPath("XCUIElementTypeButton[3]"); - - return (closeButton, zoomButton, miniturizeButton); - } } } From 8b9e675bd4a8ee174c78d54062c1c0b04a22b845 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 22 Jun 2022 10:55:19 +0200 Subject: [PATCH 48/78] Refactor PlatformFact. To make it inclusive rather than exclusive. --- .../ButtonTests.cs | 2 +- .../ComboBoxTests.cs | 6 ++-- .../ListBoxTests.cs | 2 +- .../MenuTests.cs | 16 +++++----- .../NativeMenuTests.cs | 2 +- .../PlatformFactAttribute.cs | 32 +++++++++++++------ .../WindowTests.cs | 14 ++++---- 7 files changed, 43 insertions(+), 31 deletions(-) diff --git a/tests/Avalonia.IntegrationTests.Appium/ButtonTests.cs b/tests/Avalonia.IntegrationTests.Appium/ButtonTests.cs index 2ac859e091..6c630ae782 100644 --- a/tests/Avalonia.IntegrationTests.Appium/ButtonTests.cs +++ b/tests/Avalonia.IntegrationTests.Appium/ButtonTests.cs @@ -44,7 +44,7 @@ namespace Avalonia.IntegrationTests.Appium Assert.Equal("Button with TextBlock", button.Text); } - [PlatformFact(SkipOnOSX = true)] + [PlatformFact(TestPlatforms.Windows)] public void ButtonWithAcceleratorKey() { var button = _session.FindElementByAccessibilityId("ButtonWithAcceleratorKey"); diff --git a/tests/Avalonia.IntegrationTests.Appium/ComboBoxTests.cs b/tests/Avalonia.IntegrationTests.Appium/ComboBoxTests.cs index fad3e1eb9f..abdb4e2dd8 100644 --- a/tests/Avalonia.IntegrationTests.Appium/ComboBoxTests.cs +++ b/tests/Avalonia.IntegrationTests.Appium/ComboBoxTests.cs @@ -46,7 +46,7 @@ namespace Avalonia.IntegrationTests.Appium Assert.Equal("Item 0", comboBox.GetComboBoxValue()); } - [PlatformFact(SkipOnOSX = true)] + [PlatformFact(TestPlatforms.Windows)] public void Can_Change_Selection_With_Keyboard() { var comboBox = _session.FindElementByAccessibilityId("BasicComboBox"); @@ -63,7 +63,7 @@ namespace Avalonia.IntegrationTests.Appium Assert.Equal("Item 1", comboBox.GetComboBoxValue()); } - [PlatformFact(SkipOnOSX = true)] + [PlatformFact(TestPlatforms.Windows)] public void Can_Change_Selection_With_Keyboard_From_Unselected() { var comboBox = _session.FindElementByAccessibilityId("BasicComboBox"); @@ -80,7 +80,7 @@ namespace Avalonia.IntegrationTests.Appium Assert.Equal("Item 0", comboBox.GetComboBoxValue()); } - [PlatformFact(SkipOnOSX = true)] + [PlatformFact(TestPlatforms.Windows)] public void Can_Cancel_Keyboard_Selection_With_Escape() { var comboBox = _session.FindElementByAccessibilityId("BasicComboBox"); diff --git a/tests/Avalonia.IntegrationTests.Appium/ListBoxTests.cs b/tests/Avalonia.IntegrationTests.Appium/ListBoxTests.cs index 625742ac20..e2943b3349 100644 --- a/tests/Avalonia.IntegrationTests.Appium/ListBoxTests.cs +++ b/tests/Avalonia.IntegrationTests.Appium/ListBoxTests.cs @@ -61,7 +61,7 @@ namespace Avalonia.IntegrationTests.Appium } // appium-mac2-driver just hangs - [PlatformFact(SkipOnOSX = true)] + [PlatformFact(TestPlatforms.Windows)] public void Can_Select_Range_By_Shift_Clicking() { var listBox = GetTarget(); diff --git a/tests/Avalonia.IntegrationTests.Appium/MenuTests.cs b/tests/Avalonia.IntegrationTests.Appium/MenuTests.cs index 98fb335061..d1d231466f 100644 --- a/tests/Avalonia.IntegrationTests.Appium/MenuTests.cs +++ b/tests/Avalonia.IntegrationTests.Appium/MenuTests.cs @@ -57,7 +57,7 @@ namespace Avalonia.IntegrationTests.Appium Assert.Equal("_Grandchild", clickedMenuItem.Text); } - [PlatformFact(SkipOnOSX = true)] + [PlatformFact(TestPlatforms.Windows)] public void Select_Child_With_Alt_Arrow_Keys() { new Actions(_session) @@ -69,7 +69,7 @@ namespace Avalonia.IntegrationTests.Appium Assert.Equal("_Child 1", clickedMenuItem.Text); } - [PlatformFact(SkipOnOSX = true)] + [PlatformFact(TestPlatforms.Windows)] public void Select_Grandchild_With_Alt_Arrow_Keys() { new Actions(_session) @@ -81,7 +81,7 @@ namespace Avalonia.IntegrationTests.Appium Assert.Equal("_Grandchild", clickedMenuItem.Text); } - [PlatformFact(SkipOnOSX = true)] + [PlatformFact(TestPlatforms.Windows)] public void Select_Child_With_Alt_Access_Keys() { new Actions(_session) @@ -93,7 +93,7 @@ namespace Avalonia.IntegrationTests.Appium Assert.Equal("_Child 1", clickedMenuItem.Text); } - [PlatformFact(SkipOnOSX = true)] + [PlatformFact(TestPlatforms.Windows)] public void Select_Grandchild_With_Alt_Access_Keys() { new Actions(_session) @@ -105,7 +105,7 @@ namespace Avalonia.IntegrationTests.Appium Assert.Equal("_Grandchild", clickedMenuItem.Text); } - [PlatformFact(SkipOnOSX = true)] + [PlatformFact(TestPlatforms.Windows)] public void Select_Child_With_Click_Arrow_Keys() { var rootMenuItem = _session.FindElementByAccessibilityId("RootMenuItem"); @@ -119,7 +119,7 @@ namespace Avalonia.IntegrationTests.Appium Assert.Equal("_Child 1", clickedMenuItem.Text); } - [PlatformFact(SkipOnOSX = true)] + [PlatformFact(TestPlatforms.Windows)] public void Select_Grandchild_With_Click_Arrow_Keys() { var rootMenuItem = _session.FindElementByAccessibilityId("RootMenuItem"); @@ -133,7 +133,7 @@ namespace Avalonia.IntegrationTests.Appium Assert.Equal("_Grandchild", clickedMenuItem.Text); } - [PlatformFact(SkipOnOSX = true)] + [PlatformFact(TestPlatforms.Windows)] public void Child_AcceleratorKey() { var rootMenuItem = _session.FindElementByAccessibilityId("RootMenuItem"); @@ -145,7 +145,7 @@ namespace Avalonia.IntegrationTests.Appium Assert.Equal("Ctrl+O", childMenuItem.GetAttribute("AcceleratorKey")); } - [PlatformFact(SkipOnOSX = true)] + [PlatformFact(TestPlatforms.Windows)] public void PointerOver_Does_Not_Steal_Focus() { // Issue #7906 diff --git a/tests/Avalonia.IntegrationTests.Appium/NativeMenuTests.cs b/tests/Avalonia.IntegrationTests.Appium/NativeMenuTests.cs index fde01f0e41..7858c4cc81 100644 --- a/tests/Avalonia.IntegrationTests.Appium/NativeMenuTests.cs +++ b/tests/Avalonia.IntegrationTests.Appium/NativeMenuTests.cs @@ -17,7 +17,7 @@ namespace Avalonia.IntegrationTests.Appium tab.Click(); } - [PlatformFact(SkipOnWindows = true)] + [PlatformFact(TestPlatforms.MacOS)] public void View_Menu_Select_Button_Tab() { var tabs = _session.FindElementByAccessibilityId("MainTabs"); diff --git a/tests/Avalonia.IntegrationTests.Appium/PlatformFactAttribute.cs b/tests/Avalonia.IntegrationTests.Appium/PlatformFactAttribute.cs index 60338b92c2..53ae5d924f 100644 --- a/tests/Avalonia.IntegrationTests.Appium/PlatformFactAttribute.cs +++ b/tests/Avalonia.IntegrationTests.Appium/PlatformFactAttribute.cs @@ -5,21 +5,33 @@ using Xunit; namespace Avalonia.IntegrationTests.Appium { + [Flags] + internal enum TestPlatforms + { + Windows = 0x01, + MacOS = 0x02, + All = Windows | MacOS, + } + internal class PlatformFactAttribute : FactAttribute { + public PlatformFactAttribute(TestPlatforms platforms = TestPlatforms.All) => Platforms = platforms; + + public TestPlatforms Platforms { get; } + public override string? Skip { - get - { - if (SkipOnWindows && RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - return "Ignored on Windows"; - if (SkipOnOSX && RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - return "Ignored on MacOS"; - return null; - } + get => IsSupported() ? null : $"Ignored on {RuntimeInformation.OSDescription}"; set => throw new NotSupportedException(); } - public bool SkipOnOSX { get; set; } - public bool SkipOnWindows { get; set; } + + private bool IsSupported() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + return Platforms.HasAnyFlag(TestPlatforms.Windows); + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + return Platforms.HasAnyFlag(TestPlatforms.MacOS); + return false; + } } } diff --git a/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs b/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs index e887a2afe8..b759dafbeb 100644 --- a/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs +++ b/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs @@ -54,7 +54,7 @@ namespace Avalonia.IntegrationTests.Appium } } - [PlatformFact(SkipOnWindows = true)] + [PlatformFact(TestPlatforms.MacOS)] public void OSX_WindowOrder_Modal_Dialog_Stays_InFront_Of_Parent() { var mainWindow = _session.FindElementByAccessibilityId("MainWindow"); @@ -73,7 +73,7 @@ namespace Avalonia.IntegrationTests.Appium } } - [PlatformFact(SkipOnWindows = true)] + [PlatformFact(TestPlatforms.MacOS)] public void OSX_WindowOrder_Modal_Dialog_Stays_InFront_Of_Parent_When_Clicking_Resize_Grip() { var mainWindow = _session.FindWindowOuter("MainWindow"); @@ -100,7 +100,7 @@ namespace Avalonia.IntegrationTests.Appium } } - [PlatformFact(SkipOnWindows = true)] + [PlatformFact(TestPlatforms.MacOS)] public void OSX_WindowOrder_Modal_Dialog_Stays_InFront_Of_Parent_When_In_Fullscreen() { var mainWindow = _session.FindWindowOuter("MainWindow"); @@ -129,7 +129,7 @@ namespace Avalonia.IntegrationTests.Appium } } - [PlatformFact(SkipOnWindows = true)] + [PlatformFact(TestPlatforms.MacOS)] public void OSX_WindowOrder_Owned_Dialog_Stays_InFront_Of_Parent() { var mainWindow = _session.FindElementByAccessibilityId("MainWindow"); @@ -148,7 +148,7 @@ namespace Avalonia.IntegrationTests.Appium } } - [PlatformFact(SkipOnWindows = true)] + [PlatformFact(TestPlatforms.MacOS)] public void OSX_WindowOrder_NonOwned_Window_Does_Not_Stay_InFront_Of_Parent() { var mainWindow = _session.FindElementByAccessibilityId("MainWindow"); @@ -173,7 +173,7 @@ namespace Avalonia.IntegrationTests.Appium } } - [PlatformFact(SkipOnWindows = true)] + [PlatformFact(TestPlatforms.MacOS)] public void OSX_Parent_Window_Has_Disabled_ChromeButtons_When_Modal_Dialog_Shown() { var mainWindowHandle = GetCurrentWindowHandleHack(); @@ -196,7 +196,7 @@ namespace Avalonia.IntegrationTests.Appium } } - [PlatformFact(SkipOnWindows = true)] + [PlatformFact(TestPlatforms.MacOS)] public void OSX_Minimize_Button_Disabled_Modal_Dialog() { var mainWindowHandle = GetCurrentWindowHandleHack(); From 4f4f291b2d3220c59ec8ac80db1b31608fd1003d Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Fri, 24 Jun 2022 10:55:30 +0200 Subject: [PATCH 49/78] Move mac-specific tests to a separate file. And tidy stuff up a bit. --- .../WindowTests.cs | 226 ------------------ .../WindowTests_MacOS.cs | 210 ++++++++++++++++ 2 files changed, 210 insertions(+), 226 deletions(-) create mode 100644 tests/Avalonia.IntegrationTests.Appium/WindowTests_MacOS.cs diff --git a/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs b/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs index b759dafbeb..f1a625dbb4 100644 --- a/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs +++ b/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs @@ -1,13 +1,7 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Reactive.Disposables; using System.Runtime.InteropServices; -using System.Threading.Tasks; using Avalonia.Controls; -using OpenQA.Selenium; using OpenQA.Selenium.Appium; -using OpenQA.Selenium.Interactions; using Xunit; using Xunit.Sdk; @@ -53,168 +47,6 @@ namespace Avalonia.IntegrationTests.Appium } } } - - [PlatformFact(TestPlatforms.MacOS)] - public void OSX_WindowOrder_Modal_Dialog_Stays_InFront_Of_Parent() - { - var mainWindow = _session.FindElementByAccessibilityId("MainWindow"); - - using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Modal, WindowStartupLocation.CenterOwner)) - { - mainWindow.Click(); - - var windows = _session.FindElements(By.XPath("XCUIElementTypeWindow")); - - int mainWindowIndex = windows.GetWindowOrder("MainWindow"); - int secondaryWindowIndex = windows.GetWindowOrder("SecondaryWindow"); - - Assert.Equal(0, secondaryWindowIndex); - Assert.Equal(1, mainWindowIndex); - } - } - - [PlatformFact(TestPlatforms.MacOS)] - public void OSX_WindowOrder_Modal_Dialog_Stays_InFront_Of_Parent_When_Clicking_Resize_Grip() - { - var mainWindow = _session.FindWindowOuter("MainWindow"); - - using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Modal, WindowStartupLocation.CenterOwner)) - { - new Actions(_session) - .MoveToElement(mainWindow, 100, 1) - .ClickAndHold() - .Perform(); - - var windows = _session.FindElements(By.XPath("XCUIElementTypeWindow")); - - int mainWindowIndex = windows.GetWindowOrder("MainWindow"); - int secondaryWindowIndex = windows.GetWindowOrder("SecondaryWindow"); - - new Actions(_session) - .MoveToElement(mainWindow, 100, 1) - .Release() - .Perform(); - - Assert.Equal(0, secondaryWindowIndex); - Assert.Equal(1, mainWindowIndex); - } - } - - [PlatformFact(TestPlatforms.MacOS)] - public void OSX_WindowOrder_Modal_Dialog_Stays_InFront_Of_Parent_When_In_Fullscreen() - { - var mainWindow = _session.FindWindowOuter("MainWindow"); - var buttons = mainWindow.GetChromeButtons(); - - buttons.maximize.Click(); - - Task.Delay(500).Wait(); - - try - { - using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Modal, WindowStartupLocation.CenterOwner)) - { - var windows = _session.FindElements(By.XPath("XCUIElementTypeWindow")); - - int mainWindowIndex = windows.GetWindowOrder("MainWindow"); - int secondaryWindowIndex = windows.GetWindowOrder("SecondaryWindow"); - - Assert.Equal(0, secondaryWindowIndex); - Assert.Equal(1, mainWindowIndex); - } - } - finally - { - _session.FindElementByAccessibilityId("ExitFullscreen").Click(); - } - } - - [PlatformFact(TestPlatforms.MacOS)] - public void OSX_WindowOrder_Owned_Dialog_Stays_InFront_Of_Parent() - { - var mainWindow = _session.FindElementByAccessibilityId("MainWindow"); - - using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Owned, WindowStartupLocation.CenterOwner)) - { - mainWindow.Click(); - - var windows = _session.FindElements(By.XPath("XCUIElementTypeWindow")); - - int mainWindowIndex = windows.GetWindowOrder("MainWindow"); - int secondaryWindowIndex = windows.GetWindowOrder("SecondaryWindow"); - - Assert.Equal(0, secondaryWindowIndex); - Assert.Equal(1, mainWindowIndex); - } - } - - [PlatformFact(TestPlatforms.MacOS)] - public void OSX_WindowOrder_NonOwned_Window_Does_Not_Stay_InFront_Of_Parent() - { - var mainWindow = _session.FindElementByAccessibilityId("MainWindow"); - - using (OpenWindow(new PixelSize(1400, 100), ShowWindowMode.NonOwned, WindowStartupLocation.CenterOwner)) - { - mainWindow.Click(); - - var secondaryWindow = - _session.FindElementByAccessibilityId("SecondaryWindow"); - - var windows = _session.FindElements(By.XPath("XCUIElementTypeWindow")); - - int mainWindowIndex = windows.GetWindowOrder("MainWindow"); - int secondaryWindowIndex = windows.GetWindowOrder("SecondaryWindow"); - - Assert.Equal(1, secondaryWindowIndex); - Assert.Equal(0, mainWindowIndex); - - var sendToBack = _session.FindElementByAccessibilityId("SendToBack"); - sendToBack.Click(); - } - } - - [PlatformFact(TestPlatforms.MacOS)] - public void OSX_Parent_Window_Has_Disabled_ChromeButtons_When_Modal_Dialog_Shown() - { - var mainWindowHandle = GetCurrentWindowHandleHack(); - var window = _session.FindWindowOuter("MainWindow"); - - var (closeButton, zoomButton, miniturizeButton) - = window.GetChromeButtons(); - - Assert.True(closeButton.Enabled); - Assert.True(zoomButton.Enabled); - Assert.True(miniturizeButton.Enabled); - - using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Modal, WindowStartupLocation.CenterOwner)) - { - SwitchToNewWindowHack(oldWindowHandle: mainWindowHandle); - - Assert.False(closeButton.Enabled); - Assert.False(zoomButton.Enabled); - Assert.False(miniturizeButton.Enabled); - } - } - - [PlatformFact(TestPlatforms.MacOS)] - public void OSX_Minimize_Button_Disabled_Modal_Dialog() - { - var mainWindowHandle = GetCurrentWindowHandleHack(); - - using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Modal, WindowStartupLocation.CenterOwner)) - { - var secondaryWindow = _session.FindWindowOuter("SecondaryWindow"); - - var (closeButton, zoomButton, miniaturizeButton) - = secondaryWindow.GetChromeButtons(); - - Assert.True(closeButton.Enabled); - Assert.True(zoomButton.Enabled); - Assert.False(miniaturizeButton.Enabled); - - SwitchToNewWindowHack(oldWindowHandle: mainWindowHandle); - } - } public static TheoryData StartupLocationData() { @@ -238,39 +70,6 @@ namespace Avalonia.IntegrationTests.Appium return data; } - private string? GetCurrentWindowHandleHack() - { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - // HACK: WinAppDriver only seems to switch to a newly opened window if the window has an owner, - // otherwise the session remains targeting the previous window. Return the handle for the - // current window so we know which window to switch to when another is opened. - return _session.WindowHandles.Single(); - } - - return null; - } - - private void SwitchToNewWindowHack(string? oldWindowHandle) - { - if (oldWindowHandle is not null) - { - var newWindowHandle = _session.WindowHandles.FirstOrDefault(x => x != oldWindowHandle); - - // HACK: Looks like WinAppDriver only adds window handles for non-owned windows, but luckily - // non-owned windows is where we're having the problem, so if we find a window handle that - // isn't the main window handle then switch to it. - if (newWindowHandle is not null) - _session.SwitchTo().Window(newWindowHandle); - } - } - - private void SwitchToMainWindowHack(string? mainWindowHandle) - { - if (mainWindowHandle is not null) - _session.SwitchTo().Window(mainWindowHandle); - } - private static void AssertCloseEnough(PixelPoint expected, PixelPoint actual) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) @@ -299,7 +98,6 @@ namespace Avalonia.IntegrationTests.Appium private IDisposable OpenWindow(PixelSize? size, ShowWindowMode mode, WindowStartupLocation location) { - var mainWindow = GetCurrentWindowHandleHack(); var sizeTextBox = _session.FindElementByAccessibilityId("ShowWindowSize"); var modeComboBox = _session.FindElementByAccessibilityId("ShowWindowMode"); var locationComboBox = _session.FindElementByAccessibilityId("ShowWindowLocation"); @@ -324,28 +122,4 @@ namespace Avalonia.IntegrationTests.Appium Modal } } - - static class Extensions - { - public static int GetWindowOrder(this IReadOnlyCollection elements, string identifier) - { - return elements.TakeWhile(x => - x.FindElementByXPath("XCUIElementTypeWindow")?.GetAttribute("identifier") != identifier).Count(); - } - - public static AppiumWebElement? FindWindowInner(this AppiumDriver session, string identifier) - { - return session.FindElementsByXPath("XCUIElementTypeWindow") - .FirstOrDefault(x => x.GetAttribute("identifier") == identifier); - } - - public static AppiumWebElement? FindWindowOuter(this AppiumDriver session, string identifier) - { - var windows = session.FindElementsByXPath("XCUIElementTypeWindow"); - - var window = windows.FirstOrDefault(x=>x.FindElementsByXPath("XCUIElementTypeWindow").Any(x => x.GetAttribute("identifier") == identifier)); - - return window; - } - } } diff --git a/tests/Avalonia.IntegrationTests.Appium/WindowTests_MacOS.cs b/tests/Avalonia.IntegrationTests.Appium/WindowTests_MacOS.cs new file mode 100644 index 0000000000..a460dc1d68 --- /dev/null +++ b/tests/Avalonia.IntegrationTests.Appium/WindowTests_MacOS.cs @@ -0,0 +1,210 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using Avalonia.Controls; +using OpenQA.Selenium; +using OpenQA.Selenium.Appium; +using OpenQA.Selenium.Interactions; +using Xunit; + +namespace Avalonia.IntegrationTests.Appium +{ + [Collection("Default")] + public class WindowTests_MacOS + { + private readonly AppiumDriver _session; + + public WindowTests_MacOS(TestAppFixture fixture) + { + _session = fixture.Session; + + var tabs = _session.FindElementByAccessibilityId("MainTabs"); + var tab = tabs.FindElementByName("Window"); + tab.Click(); + } + + [PlatformFact(TestPlatforms.MacOS)] + public void WindowOrder_Modal_Dialog_Stays_InFront_Of_Parent() + { + var mainWindow = _session.FindElementByAccessibilityId("MainWindow"); + + using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Modal, WindowStartupLocation.CenterOwner)) + { + mainWindow.Click(); + + var windows = _session.FindElements(By.XPath("XCUIElementTypeWindow")); + var mainWindowIndex = GetWindowOrder(windows, "MainWindow"); + var secondaryWindowIndex = GetWindowOrder(windows, "SecondaryWindow"); + + Assert.Equal(0, secondaryWindowIndex); + Assert.Equal(1, mainWindowIndex); + } + } + + [PlatformFact(TestPlatforms.MacOS)] + public void WindowOrder_Modal_Dialog_Stays_InFront_Of_Parent_When_Clicking_Resize_Grip() + { + var mainWindow = FindWindow(_session, "MainWindow"); + + using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Modal, WindowStartupLocation.CenterOwner)) + { + new Actions(_session) + .MoveToElement(mainWindow, 100, 1) + .ClickAndHold() + .Perform(); + + var windows = _session.FindElements(By.XPath("XCUIElementTypeWindow")); + var mainWindowIndex = GetWindowOrder(windows, "MainWindow"); + var secondaryWindowIndex = GetWindowOrder(windows, "SecondaryWindow"); + + new Actions(_session) + .MoveToElement(mainWindow, 100, 1) + .Release() + .Perform(); + + Assert.Equal(0, secondaryWindowIndex); + Assert.Equal(1, mainWindowIndex); + } + } + + [PlatformFact(TestPlatforms.MacOS)] + public void WindowOrder_Modal_Dialog_Stays_InFront_Of_Parent_When_In_Fullscreen() + { + var mainWindow = FindWindow(_session, "MainWindow"); + var buttons = mainWindow.GetChromeButtons(); + + buttons.maximize.Click(); + + Thread.Sleep(500); + + try + { + using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Modal, WindowStartupLocation.CenterOwner)) + { + var windows = _session.FindElements(By.XPath("XCUIElementTypeWindow")); + var mainWindowIndex = GetWindowOrder(windows, "MainWindow"); + var secondaryWindowIndex = GetWindowOrder(windows, "SecondaryWindow"); + + Assert.Equal(0, secondaryWindowIndex); + Assert.Equal(1, mainWindowIndex); + } + } + finally + { + _session.FindElementByAccessibilityId("ExitFullscreen").Click(); + } + } + + [PlatformFact(TestPlatforms.MacOS)] + public void WindowOrder_Owned_Dialog_Stays_InFront_Of_Parent() + { + var mainWindow = _session.FindElementByAccessibilityId("MainWindow"); + + using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Owned, WindowStartupLocation.CenterOwner)) + { + mainWindow.Click(); + + var windows = _session.FindElements(By.XPath("XCUIElementTypeWindow")); + var mainWindowIndex = GetWindowOrder(windows, "MainWindow"); + var secondaryWindowIndex = GetWindowOrder(windows, "SecondaryWindow"); + + Assert.Equal(0, secondaryWindowIndex); + Assert.Equal(1, mainWindowIndex); + } + } + + [PlatformFact(TestPlatforms.MacOS)] + public void WindowOrder_NonOwned_Window_Does_Not_Stay_InFront_Of_Parent() + { + var mainWindow = _session.FindElementByAccessibilityId("MainWindow"); + + using (OpenWindow(new PixelSize(1400, 100), ShowWindowMode.NonOwned, WindowStartupLocation.CenterOwner)) + { + mainWindow.Click(); + + var windows = _session.FindElements(By.XPath("XCUIElementTypeWindow")); + var mainWindowIndex = GetWindowOrder(windows, "MainWindow"); + var secondaryWindowIndex = GetWindowOrder(windows, "SecondaryWindow"); + + Assert.Equal(1, secondaryWindowIndex); + Assert.Equal(0, mainWindowIndex); + + var sendToBack = _session.FindElementByAccessibilityId("SendToBack"); + sendToBack.Click(); + } + } + + [PlatformFact(TestPlatforms.MacOS)] + public void Parent_Window_Has_Disabled_ChromeButtons_When_Modal_Dialog_Shown() + { + var window = FindWindow(_session, "MainWindow"); + var (closeButton, miniaturizeButton, zoomButton) = window.GetChromeButtons(); + + Assert.True(closeButton.Enabled); + Assert.True(zoomButton.Enabled); + Assert.True(miniaturizeButton.Enabled); + + using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Modal, WindowStartupLocation.CenterOwner)) + { + Assert.False(closeButton.Enabled); + Assert.False(zoomButton.Enabled); + Assert.False(miniaturizeButton.Enabled); + } + } + + [PlatformFact(TestPlatforms.MacOS)] + public void Minimize_Button_Is_Disabled_On_Modal_Dialog() + { + using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Modal, WindowStartupLocation.CenterOwner)) + { + var secondaryWindow = FindWindow(_session, "SecondaryWindow"); + var (closeButton, miniaturizeButton, zoomButton) = secondaryWindow.GetChromeButtons(); + + Assert.True(closeButton.Enabled); + Assert.True(zoomButton.Enabled); + Assert.False(miniaturizeButton.Enabled); + } + } + + private IDisposable OpenWindow(PixelSize? size, ShowWindowMode mode, WindowStartupLocation location) + { + var sizeTextBox = _session.FindElementByAccessibilityId("ShowWindowSize"); + var modeComboBox = _session.FindElementByAccessibilityId("ShowWindowMode"); + var locationComboBox = _session.FindElementByAccessibilityId("ShowWindowLocation"); + var showButton = _session.FindElementByAccessibilityId("ShowWindow"); + + if (size.HasValue) + sizeTextBox.SendKeys($"{size.Value.Width}, {size.Value.Height}"); + + modeComboBox.Click(); + _session.FindElementByName(mode.ToString()).SendClick(); + + locationComboBox.Click(); + _session.FindElementByName(location.ToString()).SendClick(); + + return showButton.OpenWindowWithClick(); + } + + private static int GetWindowOrder(IReadOnlyCollection elements, string identifier) + { + return elements.TakeWhile(x => + x.FindElementByXPath("XCUIElementTypeWindow")?.GetAttribute("identifier") != identifier).Count(); + } + + private static AppiumWebElement FindWindow(AppiumDriver session, string identifier) + { + var windows = session.FindElementsByXPath("XCUIElementTypeWindow"); + return windows.First(x => + x.FindElementsByXPath("XCUIElementTypeWindow") + .Any(y => y.GetAttribute("identifier") == identifier)); + } + + public enum ShowWindowMode + { + NonOwned, + Owned, + Modal + } + } +} From be9c9cfaad64af21499f31fab2acda5091f01d43 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Fri, 24 Jun 2022 14:31:40 +0200 Subject: [PATCH 50/78] Remove debug code. --- src/Avalonia.Controls/WindowBase.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Avalonia.Controls/WindowBase.cs b/src/Avalonia.Controls/WindowBase.cs index d5e54a5c08..1b25806892 100644 --- a/src/Avalonia.Controls/WindowBase.cs +++ b/src/Avalonia.Controls/WindowBase.cs @@ -225,8 +225,6 @@ namespace Avalonia.Controls LayoutManager.ExecuteLayoutPass(); Renderer?.Resized(clientSize); } - - System.Diagnostics.Debug.WriteLine($"HandleResized: ClientSize {ClientSize} | FrameSize {FrameSize}"); } /// From 355ba94fa7c34b3f85ca4015cde8992c6dbe09f6 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Fri, 24 Jun 2022 16:53:58 +0200 Subject: [PATCH 51/78] Don't return FrameSize until window is shown. Since #8629, the content size isn't set until the window is shown, so we can't know the frame size. --- native/Avalonia.Native/src/OSX/WindowBaseImpl.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm b/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm index f133fa34f6..45d78b3926 100644 --- a/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm +++ b/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm @@ -224,7 +224,7 @@ HRESULT WindowBaseImpl::GetFrameSize(AvnSize *ret) { if (ret == nullptr) return E_POINTER; - if(Window != nullptr){ + if(Window != nullptr && _shown){ auto frame = [Window frame]; ret->Width = frame.size.width; ret->Height = frame.size.height; From 20ddbad2adf97e93765cbe89f6532a9b945242e2 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Fri, 24 Jun 2022 17:16:31 +0200 Subject: [PATCH 52/78] Fix window minimization. A non-client click was being received after the click to minimize the window, which caused a call to `_parent->BringToFront();`, meaning the window got immediately restored. Ignore clicks when the window is minimized. Fixes #8335 --- native/Avalonia.Native/src/OSX/AvnWindow.mm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/native/Avalonia.Native/src/OSX/AvnWindow.mm b/native/Avalonia.Native/src/OSX/AvnWindow.mm index ebd9f39d30..9569ea1cbe 100644 --- a/native/Avalonia.Native/src/OSX/AvnWindow.mm +++ b/native/Avalonia.Native/src/OSX/AvnWindow.mm @@ -440,6 +440,9 @@ { case NSEventTypeLeftMouseDown: { + if ([self isMiniaturized]) + break; + AvnView* view = _parent->View; NSPoint windowPoint = [event locationInWindow]; NSPoint viewPoint = [view convertPoint:windowPoint fromView:nil]; From 328aef882b8fe19452a8d3287d42c98b7b0fdf31 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Sat, 25 Jun 2022 01:20:18 +0200 Subject: [PATCH 53/78] Added failing tests for WindowState on mac. --- .../IntegrationTestApp/ShowWindowTest.axaml | 19 +++-- .../ShowWindowTest.axaml.cs | 4 +- .../WindowTests.cs | 70 ++++++++++++++++--- 3 files changed, 76 insertions(+), 17 deletions(-) diff --git a/samples/IntegrationTestApp/ShowWindowTest.axaml b/samples/IntegrationTestApp/ShowWindowTest.axaml index a263d8ab46..a861130cd0 100644 --- a/samples/IntegrationTestApp/ShowWindowTest.axaml +++ b/samples/IntegrationTestApp/ShowWindowTest.axaml @@ -3,15 +3,18 @@ x:Class="IntegrationTestApp.ShowWindowTest" Name="SecondaryWindow" Title="Show Window Test"> - + - + - + - + @@ -21,5 +24,13 @@ + + + + Normal + Minimized + Maximized + Fullscreen + diff --git a/samples/IntegrationTestApp/ShowWindowTest.axaml.cs b/samples/IntegrationTestApp/ShowWindowTest.axaml.cs index 720f7b1c12..69b6d64557 100644 --- a/samples/IntegrationTestApp/ShowWindowTest.axaml.cs +++ b/samples/IntegrationTestApp/ShowWindowTest.axaml.cs @@ -11,6 +11,7 @@ namespace IntegrationTestApp public ShowWindowTest() { InitializeComponent(); + DataContext = this; } private void InitializeComponent() @@ -21,9 +22,6 @@ namespace IntegrationTestApp protected override void OnOpened(EventArgs e) { base.OnOpened(e); - this.GetControl("ClientSize").Text = $"{Width}, {Height}"; - this.GetControl("FrameSize").Text = $"{FrameSize}"; - this.GetControl("Position").Text = $"{Position}"; this.GetControl("ScreenRect").Text = $"{Screens.ScreenFromVisual(this)?.WorkingArea}"; this.GetControl("Scaling").Text = $"{PlatformImpl?.DesktopScaling}"; diff --git a/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs b/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs index f1a625dbb4..727a0b5406 100644 --- a/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs +++ b/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs @@ -26,28 +26,60 @@ namespace Avalonia.IntegrationTests.Appium public void StartupLocation(PixelSize? size, ShowWindowMode mode, WindowStartupLocation location) { using var window = OpenWindow(size, mode, location); - var clientSize = Size.Parse(_session.FindElementByAccessibilityId("ClientSize").Text); - var frameSize = Size.Parse(_session.FindElementByAccessibilityId("FrameSize").Text); - var position = PixelPoint.Parse(_session.FindElementByAccessibilityId("Position").Text); - var screenRect = PixelRect.Parse(_session.FindElementByAccessibilityId("ScreenRect").Text); - var scaling = double.Parse(_session.FindElementByAccessibilityId("Scaling").Text); + var info = GetWindowInfo(); - Assert.True(frameSize.Width >= clientSize.Width, "Expected frame width >= client width."); - Assert.True(frameSize.Height > clientSize.Height, "Expected frame height > client height."); + Assert.True(info.FrameSize.Width >= info.ClientSize.Width, "Expected frame width >= client width."); + Assert.True(info.FrameSize.Height > info.ClientSize.Height, "Expected frame height > client height."); - var frameRect = new PixelRect(position, PixelSize.FromSize(frameSize, scaling)); + var frameRect = new PixelRect(info.Position, PixelSize.FromSize(info.FrameSize, info.Scaling)); switch (location) { case WindowStartupLocation.CenterScreen: { - var expected = screenRect.CenterRect(frameRect); + var expected = info.ScreenRect.CenterRect(frameRect); AssertCloseEnough(expected.Position, frameRect.Position); break; } } } - + + + [Theory] + [InlineData(ShowWindowMode.NonOwned)] + [InlineData(ShowWindowMode.Owned)] + [InlineData(ShowWindowMode.Modal)] + public void WindowState(ShowWindowMode mode) + { + using var window = OpenWindow(null, mode, WindowStartupLocation.Manual); + var windowState = _session.FindElementByAccessibilityId("WindowState"); + var original = GetWindowInfo(); + + Assert.Equal("Normal", windowState.GetComboBoxValue()); + + windowState.Click(); + _session.FindElementByName("Maximized").SendClick(); + Assert.Equal("Maximized", windowState.GetComboBoxValue()); + + windowState.Click(); + _session.FindElementByName("Normal").SendClick(); + + var current = GetWindowInfo(); + Assert.Equal(original.Position, current.Position); + Assert.Equal(original.FrameSize, current.FrameSize); + + windowState.Click(); + _session.FindElementByName("Fullscreen").SendClick(); + Assert.Equal("Fullscreen", windowState.GetComboBoxValue()); + + windowState.Click(); + _session.FindElementByName("Normal").SendClick(); + + current = GetWindowInfo(); + Assert.Equal(original.Position, current.Position); + Assert.Equal(original.FrameSize, current.FrameSize); + } + public static TheoryData StartupLocationData() { var sizes = new PixelSize?[] { null, new PixelSize(400, 300) }; @@ -115,11 +147,29 @@ namespace Avalonia.IntegrationTests.Appium return showButton.OpenWindowWithClick(); } + private WindowInfo GetWindowInfo() + { + return new( + Size.Parse(_session.FindElementByAccessibilityId("ClientSize").Text), + Size.Parse(_session.FindElementByAccessibilityId("FrameSize").Text), + PixelPoint.Parse(_session.FindElementByAccessibilityId("Position").Text), + PixelRect.Parse(_session.FindElementByAccessibilityId("ScreenRect").Text), + double.Parse(_session.FindElementByAccessibilityId("Scaling").Text)); + + } + public enum ShowWindowMode { NonOwned, Owned, Modal } + + private record WindowInfo( + Size ClientSize, + Size FrameSize, + PixelPoint Position, + PixelRect ScreenRect, + double Scaling); } } From dfa0c44269a05206bcbb288ea575ad4bc44c3ffa Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 27 Jun 2022 10:16:37 +0200 Subject: [PATCH 54/78] Set actualWindowState earlier. Previously, `_actualWindowState` was being set after the window state had finished changing, but `ExitFullScreenMode` calls `UpdateStyle` which expects `_actualWindowState` to be up-to-date, meaning that previously we ended up with an invalid size when exiting full screen mode programatically. --- native/Avalonia.Native/src/OSX/WindowImpl.mm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/native/Avalonia.Native/src/OSX/WindowImpl.mm b/native/Avalonia.Native/src/OSX/WindowImpl.mm index 6db586f3ca..5b0c7813f7 100644 --- a/native/Avalonia.Native/src/OSX/WindowImpl.mm +++ b/native/Avalonia.Native/src/OSX/WindowImpl.mm @@ -488,6 +488,8 @@ HRESULT WindowImpl::SetWindowState(AvnWindowState state) { } if (_shown) { + _actualWindowState = _lastWindowState; + switch (state) { case Maximized: if (currentState == FullScreen) { @@ -545,7 +547,6 @@ HRESULT WindowImpl::SetWindowState(AvnWindowState state) { break; } - _actualWindowState = _lastWindowState; WindowEvents->WindowStateChanged(_actualWindowState); } From 519e850bf838a42dbc8243c37ecf0348175424ed Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 27 Jun 2022 12:49:08 +0200 Subject: [PATCH 55/78] Correctly update position. `Window.Position` isn't an Avalonia property so doesn't auto-update, we need to listen for `PositionChanged`. --- samples/IntegrationTestApp/ShowWindowTest.axaml | 3 +-- samples/IntegrationTestApp/ShowWindowTest.axaml.cs | 2 ++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/samples/IntegrationTestApp/ShowWindowTest.axaml b/samples/IntegrationTestApp/ShowWindowTest.axaml index a861130cd0..40c1642e91 100644 --- a/samples/IntegrationTestApp/ShowWindowTest.axaml +++ b/samples/IntegrationTestApp/ShowWindowTest.axaml @@ -13,8 +13,7 @@ Text="{Binding FrameSize, Mode=OneWay}"/> - + diff --git a/samples/IntegrationTestApp/ShowWindowTest.axaml.cs b/samples/IntegrationTestApp/ShowWindowTest.axaml.cs index 69b6d64557..42df0b704f 100644 --- a/samples/IntegrationTestApp/ShowWindowTest.axaml.cs +++ b/samples/IntegrationTestApp/ShowWindowTest.axaml.cs @@ -12,6 +12,7 @@ namespace IntegrationTestApp { InitializeComponent(); DataContext = this; + PositionChanged += (s, e) => this.GetControl("Position").Text = $"{Position}"; } private void InitializeComponent() @@ -22,6 +23,7 @@ namespace IntegrationTestApp protected override void OnOpened(EventArgs e) { base.OnOpened(e); + this.GetControl("Position").Text = $"{Position}"; this.GetControl("ScreenRect").Text = $"{Screens.ScreenFromVisual(this)?.WorkingArea}"; this.GetControl("Scaling").Text = $"{PlatformImpl?.DesktopScaling}"; From 267710787e933c3719e20b3337b3f5e504f24edd Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 27 Jun 2022 12:51:36 +0200 Subject: [PATCH 56/78] Tweak tests. - Add a retry to `GetWindowInfo` - Owned windows can't go fullscreen on macOS. --- .../WindowTests.cs | 50 +++++++++++++------ 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs b/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs index 727a0b5406..d763848899 100644 --- a/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs +++ b/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs @@ -1,5 +1,6 @@ using System; using System.Runtime.InteropServices; +using System.Threading; using Avalonia.Controls; using OpenQA.Selenium.Appium; using Xunit; @@ -68,16 +69,24 @@ namespace Avalonia.IntegrationTests.Appium Assert.Equal(original.Position, current.Position); Assert.Equal(original.FrameSize, current.FrameSize); - windowState.Click(); - _session.FindElementByName("Fullscreen").SendClick(); - Assert.Equal("Fullscreen", windowState.GetComboBoxValue()); + // On macOS, only non-owned windows can go fullscreen. + if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || mode == ShowWindowMode.NonOwned) + { + windowState.Click(); + _session.FindElementByName("Fullscreen").SendClick(); + Assert.Equal("Fullscreen", windowState.GetComboBoxValue()); - windowState.Click(); - _session.FindElementByName("Normal").SendClick(); + current = GetWindowInfo(); + Assert.True(current.ClientSize.Width >= current.ScreenRect.Width); + Assert.True(current.ClientSize.Height >= current.ScreenRect.Height); - current = GetWindowInfo(); - Assert.Equal(original.Position, current.Position); - Assert.Equal(original.FrameSize, current.FrameSize); + windowState.Click(); + _session.FindElementByName("Normal").SendClick(); + + current = GetWindowInfo(); + Assert.Equal(original.Position, current.Position); + Assert.Equal(original.FrameSize, current.FrameSize); + } } public static TheoryData StartupLocationData() @@ -149,13 +158,26 @@ namespace Avalonia.IntegrationTests.Appium private WindowInfo GetWindowInfo() { - return new( - Size.Parse(_session.FindElementByAccessibilityId("ClientSize").Text), - Size.Parse(_session.FindElementByAccessibilityId("FrameSize").Text), - PixelPoint.Parse(_session.FindElementByAccessibilityId("Position").Text), - PixelRect.Parse(_session.FindElementByAccessibilityId("ScreenRect").Text), - double.Parse(_session.FindElementByAccessibilityId("Scaling").Text)); + var retry = 0; + for (;;) + { + try + { + return new( + Size.Parse(_session.FindElementByAccessibilityId("ClientSize").Text), + Size.Parse(_session.FindElementByAccessibilityId("FrameSize").Text), + PixelPoint.Parse(_session.FindElementByAccessibilityId("Position").Text), + PixelRect.Parse(_session.FindElementByAccessibilityId("ScreenRect").Text), + double.Parse(_session.FindElementByAccessibilityId("Scaling").Text)); + } + catch (OpenQA.Selenium.NoSuchElementException e) when (retry++ < 3) + { + // MacOS sometimes seems to need a bit of time to get itself back in order after switching out + // of fullscreen. + Thread.Sleep(1000); + } + } } public enum ShowWindowMode From 4b08e659f69a3133a22653d4a73c9a5c320bf3b7 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 27 Jun 2022 13:48:22 +0200 Subject: [PATCH 57/78] Revert "Fix window minimization." This reverts commit 20ddbad2adf97e93765cbe89f6532a9b945242e2. It didn't work with owned windows, there's something else going on here. --- native/Avalonia.Native/src/OSX/AvnWindow.mm | 3 --- 1 file changed, 3 deletions(-) diff --git a/native/Avalonia.Native/src/OSX/AvnWindow.mm b/native/Avalonia.Native/src/OSX/AvnWindow.mm index 9569ea1cbe..ebd9f39d30 100644 --- a/native/Avalonia.Native/src/OSX/AvnWindow.mm +++ b/native/Avalonia.Native/src/OSX/AvnWindow.mm @@ -440,9 +440,6 @@ { case NSEventTypeLeftMouseDown: { - if ([self isMiniaturized]) - break; - AvnView* view = _parent->View; NSPoint windowPoint = [event locationInWindow]; NSPoint viewPoint = [view convertPoint:windowPoint fromView:nil]; From 2822f5bfcb35344eabea8efbdaae526b32b2512c Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 27 Jun 2022 14:02:25 +0200 Subject: [PATCH 58/78] Fix window minimization attempt 2. The previous solution didn't work for owned windows. Hopefully this fixes the problem at its root: that `BringToFront` activates a window even if it's miniaturized. --- native/Avalonia.Native/src/OSX/WindowImpl.mm | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/native/Avalonia.Native/src/OSX/WindowImpl.mm b/native/Avalonia.Native/src/OSX/WindowImpl.mm index 5b0c7813f7..85a89955f4 100644 --- a/native/Avalonia.Native/src/OSX/WindowImpl.mm +++ b/native/Avalonia.Native/src/OSX/WindowImpl.mm @@ -119,13 +119,16 @@ void WindowImpl::BringToFront() { if(Window != nullptr) { - if(IsDialog()) + if (![Window isMiniaturized]) { - Activate(); - } - else - { - [Window orderFront:nullptr]; + if(IsDialog()) + { + Activate(); + } + else + { + [Window orderFront:nullptr]; + } } [Window invalidateShadow]; From cd04964c850545cafd54e42cbfc1cd64de145d86 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 27 Jun 2022 17:37:44 +0200 Subject: [PATCH 59/78] Added a retry to macOS window tests. MacOS sometimes seems to need a bit of time to get itself back in order after switching out of fullscreen. --- .../WindowTests_MacOS.cs | 42 +++++++++++++------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/tests/Avalonia.IntegrationTests.Appium/WindowTests_MacOS.cs b/tests/Avalonia.IntegrationTests.Appium/WindowTests_MacOS.cs index a460dc1d68..57c1476d95 100644 --- a/tests/Avalonia.IntegrationTests.Appium/WindowTests_MacOS.cs +++ b/tests/Avalonia.IntegrationTests.Appium/WindowTests_MacOS.cs @@ -17,11 +17,27 @@ namespace Avalonia.IntegrationTests.Appium public WindowTests_MacOS(TestAppFixture fixture) { + var retry = 0; + _session = fixture.Session; - var tabs = _session.FindElementByAccessibilityId("MainTabs"); - var tab = tabs.FindElementByName("Window"); - tab.Click(); + for (;;) + { + try + { + var tabs = _session.FindElementByAccessibilityId("MainTabs"); + var tab = tabs.FindElementByName("Window"); + tab.Click(); + return; + } + catch (WebDriverException e) when (retry++ < 3) + { + // MacOS sometimes seems to need a bit of time to get itself back in order after switching out + // of fullscreen. + Thread.Sleep(1000); + } + } + } [PlatformFact(TestPlatforms.MacOS)] @@ -41,7 +57,7 @@ namespace Avalonia.IntegrationTests.Appium Assert.Equal(1, mainWindowIndex); } } - + [PlatformFact(TestPlatforms.MacOS)] public void WindowOrder_Modal_Dialog_Stays_InFront_Of_Parent_When_Clicking_Resize_Grip() { @@ -57,7 +73,7 @@ namespace Avalonia.IntegrationTests.Appium var windows = _session.FindElements(By.XPath("XCUIElementTypeWindow")); var mainWindowIndex = GetWindowOrder(windows, "MainWindow"); var secondaryWindowIndex = GetWindowOrder(windows, "SecondaryWindow"); - + new Actions(_session) .MoveToElement(mainWindow, 100, 1) .Release() @@ -67,13 +83,13 @@ namespace Avalonia.IntegrationTests.Appium Assert.Equal(1, mainWindowIndex); } } - + [PlatformFact(TestPlatforms.MacOS)] public void WindowOrder_Modal_Dialog_Stays_InFront_Of_Parent_When_In_Fullscreen() { var mainWindow = FindWindow(_session, "MainWindow"); var buttons = mainWindow.GetChromeButtons(); - + buttons.maximize.Click(); Thread.Sleep(500); @@ -88,6 +104,8 @@ namespace Avalonia.IntegrationTests.Appium Assert.Equal(0, secondaryWindowIndex); Assert.Equal(1, mainWindowIndex); + + Thread.Sleep(5000); } } finally @@ -95,7 +113,7 @@ namespace Avalonia.IntegrationTests.Appium _session.FindElementByAccessibilityId("ExitFullscreen").Click(); } } - + [PlatformFact(TestPlatforms.MacOS)] public void WindowOrder_Owned_Dialog_Stays_InFront_Of_Parent() { @@ -140,7 +158,7 @@ namespace Avalonia.IntegrationTests.Appium { var window = FindWindow(_session, "MainWindow"); var (closeButton, miniaturizeButton, zoomButton) = window.GetChromeButtons(); - + Assert.True(closeButton.Enabled); Assert.True(zoomButton.Enabled); Assert.True(miniaturizeButton.Enabled); @@ -152,7 +170,7 @@ namespace Avalonia.IntegrationTests.Appium Assert.False(miniaturizeButton.Enabled); } } - + [PlatformFact(TestPlatforms.MacOS)] public void Minimize_Button_Is_Disabled_On_Modal_Dialog() { @@ -160,7 +178,7 @@ namespace Avalonia.IntegrationTests.Appium { var secondaryWindow = FindWindow(_session, "SecondaryWindow"); var (closeButton, miniaturizeButton, zoomButton) = secondaryWindow.GetChromeButtons(); - + Assert.True(closeButton.Enabled); Assert.True(zoomButton.Enabled); Assert.False(miniaturizeButton.Enabled); @@ -195,7 +213,7 @@ namespace Avalonia.IntegrationTests.Appium private static AppiumWebElement FindWindow(AppiumDriver session, string identifier) { var windows = session.FindElementsByXPath("XCUIElementTypeWindow"); - return windows.First(x => + return windows.First(x => x.FindElementsByXPath("XCUIElementTypeWindow") .Any(y => y.GetAttribute("identifier") == identifier)); } From 19c55102e5667f1bed4715f96b01a4f0a0abf81d Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 27 Jun 2022 18:52:45 +0200 Subject: [PATCH 60/78] Use manual window startup location in macOS tests. Seems to cause less flaky tests; `mainWindow.Click()` clicks the main window in the middle, where the secondary window is shown, so don't go out of our way to put the secondary window in front of where we're clicking. --- .../WindowTests_MacOS.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/Avalonia.IntegrationTests.Appium/WindowTests_MacOS.cs b/tests/Avalonia.IntegrationTests.Appium/WindowTests_MacOS.cs index 57c1476d95..c88f87562d 100644 --- a/tests/Avalonia.IntegrationTests.Appium/WindowTests_MacOS.cs +++ b/tests/Avalonia.IntegrationTests.Appium/WindowTests_MacOS.cs @@ -45,7 +45,7 @@ namespace Avalonia.IntegrationTests.Appium { var mainWindow = _session.FindElementByAccessibilityId("MainWindow"); - using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Modal, WindowStartupLocation.CenterOwner)) + using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Modal, WindowStartupLocation.Manual)) { mainWindow.Click(); @@ -63,7 +63,7 @@ namespace Avalonia.IntegrationTests.Appium { var mainWindow = FindWindow(_session, "MainWindow"); - using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Modal, WindowStartupLocation.CenterOwner)) + using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Modal, WindowStartupLocation.Manual)) { new Actions(_session) .MoveToElement(mainWindow, 100, 1) @@ -96,7 +96,7 @@ namespace Avalonia.IntegrationTests.Appium try { - using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Modal, WindowStartupLocation.CenterOwner)) + using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Modal, WindowStartupLocation.Manual)) { var windows = _session.FindElements(By.XPath("XCUIElementTypeWindow")); var mainWindowIndex = GetWindowOrder(windows, "MainWindow"); @@ -119,7 +119,7 @@ namespace Avalonia.IntegrationTests.Appium { var mainWindow = _session.FindElementByAccessibilityId("MainWindow"); - using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Owned, WindowStartupLocation.CenterOwner)) + using (OpenWindow(new PixelSize(200, 100), ShowWindowMode.Owned, WindowStartupLocation.Manual)) { mainWindow.Click(); @@ -137,7 +137,7 @@ namespace Avalonia.IntegrationTests.Appium { var mainWindow = _session.FindElementByAccessibilityId("MainWindow"); - using (OpenWindow(new PixelSize(1400, 100), ShowWindowMode.NonOwned, WindowStartupLocation.CenterOwner)) + using (OpenWindow(new PixelSize(1400, 100), ShowWindowMode.NonOwned, WindowStartupLocation.Manual)) { mainWindow.Click(); From 4f84950c41d00f97ecf0be91802b24c3800f4fc2 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 27 Jun 2022 21:33:26 +0200 Subject: [PATCH 61/78] Added tests for #8335. --- samples/IntegrationTestApp/MainWindow.axaml | 1 + .../IntegrationTestApp/MainWindow.axaml.cs | 17 +++++++++-- .../PlatformTheoryAttribute.cs | 29 +++++++++++++++++++ .../WindowTests_MacOS.cs | 26 +++++++++++++++++ 4 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 tests/Avalonia.IntegrationTests.Appium/PlatformTheoryAttribute.cs diff --git a/samples/IntegrationTestApp/MainWindow.axaml b/samples/IntegrationTestApp/MainWindow.axaml index aa2191c26b..3377979199 100644 --- a/samples/IntegrationTestApp/MainWindow.axaml +++ b/samples/IntegrationTestApp/MainWindow.axaml @@ -112,6 +112,7 @@ + diff --git a/samples/IntegrationTestApp/MainWindow.axaml.cs b/samples/IntegrationTestApp/MainWindow.axaml.cs index 1aba10ec30..9e180b12c5 100644 --- a/samples/IntegrationTestApp/MainWindow.axaml.cs +++ b/samples/IntegrationTestApp/MainWindow.axaml.cs @@ -82,7 +82,7 @@ namespace IntegrationTestApp break; } } - + private void SendToBack() { var lifetime = (ClassicDesktopStyleApplicationLifetime)Application.Current!.ApplicationLifetime!; @@ -92,7 +92,18 @@ namespace IntegrationTestApp window.Activate(); } } - + + private void RestoreAll() + { + var lifetime = (ClassicDesktopStyleApplicationLifetime)Application.Current!.ApplicationLifetime!; + + foreach (var window in lifetime.Windows) + { + if (window.WindowState == WindowState.Minimized) + window.WindowState = WindowState.Normal; + } + } + private void MenuClicked(object? sender, RoutedEventArgs e) { var clickedMenuItemTextBlock = this.FindControl("ClickedMenuItem"); @@ -117,6 +128,8 @@ namespace IntegrationTestApp SendToBack(); if (source?.Name == "ExitFullscreen") WindowState = WindowState.Normal; + if (source?.Name == "RestoreAll") + RestoreAll(); } } } diff --git a/tests/Avalonia.IntegrationTests.Appium/PlatformTheoryAttribute.cs b/tests/Avalonia.IntegrationTests.Appium/PlatformTheoryAttribute.cs new file mode 100644 index 0000000000..7ac30ee11b --- /dev/null +++ b/tests/Avalonia.IntegrationTests.Appium/PlatformTheoryAttribute.cs @@ -0,0 +1,29 @@ +using System; +using System.Linq; +using System.Runtime.InteropServices; +using Xunit; + +namespace Avalonia.IntegrationTests.Appium +{ + internal class PlatformTheoryAttribute : TheoryAttribute + { + public PlatformTheoryAttribute(TestPlatforms platforms = TestPlatforms.All) => Platforms = platforms; + + public TestPlatforms Platforms { get; } + + public override string? Skip + { + get => IsSupported() ? null : $"Ignored on {RuntimeInformation.OSDescription}"; + set => throw new NotSupportedException(); + } + + private bool IsSupported() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + return Platforms.HasAnyFlag(TestPlatforms.Windows); + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + return Platforms.HasAnyFlag(TestPlatforms.MacOS); + return false; + } + } +} diff --git a/tests/Avalonia.IntegrationTests.Appium/WindowTests_MacOS.cs b/tests/Avalonia.IntegrationTests.Appium/WindowTests_MacOS.cs index c88f87562d..15ca78fdac 100644 --- a/tests/Avalonia.IntegrationTests.Appium/WindowTests_MacOS.cs +++ b/tests/Avalonia.IntegrationTests.Appium/WindowTests_MacOS.cs @@ -185,6 +185,32 @@ namespace Avalonia.IntegrationTests.Appium } } + [PlatformTheory(TestPlatforms.MacOS)] + [InlineData(ShowWindowMode.NonOwned)] + [InlineData(ShowWindowMode.Owned)] + public void Minimize_Button_Minimizes_Window(ShowWindowMode mode) + { + using (OpenWindow(new PixelSize(200, 100), mode, WindowStartupLocation.Manual)) + { + var secondaryWindow = FindWindow(_session, "SecondaryWindow"); + var (_, miniaturizeButton, _) = secondaryWindow.GetChromeButtons(); + + miniaturizeButton.Click(); + Thread.Sleep(1000); + + var hittable = _session.FindElementsByXPath("/XCUIElementTypeApplication/XCUIElementTypeWindow") + .Select(x => x.GetAttribute("hittable")).ToList(); + Assert.Equal(new[] { "true", "false" }, hittable); + + _session.FindElementByAccessibilityId("RestoreAll").Click(); + Thread.Sleep(1000); + + hittable = _session.FindElementsByXPath("/XCUIElementTypeApplication/XCUIElementTypeWindow") + .Select(x => x.GetAttribute("hittable")).ToList(); + Assert.Equal(new[] { "true", "true" }, hittable); + } + } + private IDisposable OpenWindow(PixelSize? size, ShowWindowMode mode, WindowStartupLocation location) { var sizeTextBox = _session.FindElementByAccessibilityId("ShowWindowSize"); From 715633930496163c094e0fdaa34aea9dbc5c12ed Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 27 Jun 2022 22:25:27 +0200 Subject: [PATCH 62/78] Test CenterOwner window position. --- .../ShowWindowTest.axaml.cs | 6 ++- .../WindowTests.cs | 38 ++++++++++++++----- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/samples/IntegrationTestApp/ShowWindowTest.axaml.cs b/samples/IntegrationTestApp/ShowWindowTest.axaml.cs index 42df0b704f..001f186761 100644 --- a/samples/IntegrationTestApp/ShowWindowTest.axaml.cs +++ b/samples/IntegrationTestApp/ShowWindowTest.axaml.cs @@ -1,4 +1,5 @@ using System; +using Avalonia; using Avalonia.Controls; using Avalonia.Interactivity; using Avalonia.Markup.Xaml; @@ -23,15 +24,16 @@ namespace IntegrationTestApp protected override void OnOpened(EventArgs e) { base.OnOpened(e); + var scaling = PlatformImpl!.DesktopScaling; this.GetControl("Position").Text = $"{Position}"; this.GetControl("ScreenRect").Text = $"{Screens.ScreenFromVisual(this)?.WorkingArea}"; - this.GetControl("Scaling").Text = $"{PlatformImpl?.DesktopScaling}"; + this.GetControl("Scaling").Text = $"{scaling}"; if (Owner is not null) { var ownerRect = this.GetControl("OwnerRect"); var owner = (Window)Owner; - ownerRect.Text = $"{owner.Position}, {owner.FrameSize}"; + ownerRect.Text = $"{owner.Position}, {PixelSize.FromSize(owner.FrameSize!.Value, scaling)}"; } } } diff --git a/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs b/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs index d763848899..6a364e5fc0 100644 --- a/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs +++ b/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs @@ -24,11 +24,14 @@ namespace Avalonia.IntegrationTests.Appium [Theory] [MemberData(nameof(StartupLocationData))] - public void StartupLocation(PixelSize? size, ShowWindowMode mode, WindowStartupLocation location) + public void StartupLocation(Size? size, ShowWindowMode mode, WindowStartupLocation location) { using var window = OpenWindow(size, mode, location); var info = GetWindowInfo(); + if (size.HasValue) + Assert.Equal(size.Value, info.ClientSize); + Assert.True(info.FrameSize.Width >= info.ClientSize.Width, "Expected frame width >= client width."); Assert.True(info.FrameSize.Height > info.ClientSize.Height, "Expected frame height > client height."); @@ -37,11 +40,18 @@ namespace Avalonia.IntegrationTests.Appium switch (location) { case WindowStartupLocation.CenterScreen: - { - var expected = info.ScreenRect.CenterRect(frameRect); - AssertCloseEnough(expected.Position, frameRect.Position); - break; - } + { + var expected = info.ScreenRect.CenterRect(frameRect); + AssertCloseEnough(expected.Position, frameRect.Position); + break; + } + case WindowStartupLocation.CenterOwner: + { + Assert.NotNull(info.OwnerRect); + var expected = info.OwnerRect!.Value.CenterRect(frameRect); + AssertCloseEnough(expected.Position, frameRect.Position); + break; + } } } @@ -89,10 +99,10 @@ namespace Avalonia.IntegrationTests.Appium } } - public static TheoryData StartupLocationData() + public static TheoryData StartupLocationData() { - var sizes = new PixelSize?[] { null, new PixelSize(400, 300) }; - var data = new TheoryData(); + var sizes = new Size?[] { null, new Size(400, 300) }; + var data = new TheoryData(); foreach (var size in sizes) { @@ -137,7 +147,7 @@ namespace Avalonia.IntegrationTests.Appium } } - private IDisposable OpenWindow(PixelSize? size, ShowWindowMode mode, WindowStartupLocation location) + private IDisposable OpenWindow(Size? size, ShowWindowMode mode, WindowStartupLocation location) { var sizeTextBox = _session.FindElementByAccessibilityId("ShowWindowSize"); var modeComboBox = _session.FindElementByAccessibilityId("ShowWindowMode"); @@ -158,6 +168,12 @@ namespace Avalonia.IntegrationTests.Appium private WindowInfo GetWindowInfo() { + PixelRect? ReadOwnerRect() + { + var text = _session.FindElementByAccessibilityId("OwnerRect").Text; + return !string.IsNullOrWhiteSpace(text) ? PixelRect.Parse(text) : null; + } + var retry = 0; for (;;) @@ -168,6 +184,7 @@ namespace Avalonia.IntegrationTests.Appium Size.Parse(_session.FindElementByAccessibilityId("ClientSize").Text), Size.Parse(_session.FindElementByAccessibilityId("FrameSize").Text), PixelPoint.Parse(_session.FindElementByAccessibilityId("Position").Text), + ReadOwnerRect(), PixelRect.Parse(_session.FindElementByAccessibilityId("ScreenRect").Text), double.Parse(_session.FindElementByAccessibilityId("Scaling").Text)); } @@ -191,6 +208,7 @@ namespace Avalonia.IntegrationTests.Appium Size ClientSize, Size FrameSize, PixelPoint Position, + PixelRect? OwnerRect, PixelRect ScreenRect, double Scaling); } From 91fc1335a0bd0d97ddf3286eb912ef58462c0193 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 27 Jun 2022 23:00:52 +0200 Subject: [PATCH 63/78] Sigh, winappdriver. --- .../ElementExtensions.cs | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/tests/Avalonia.IntegrationTests.Appium/ElementExtensions.cs b/tests/Avalonia.IntegrationTests.Appium/ElementExtensions.cs index 16d37e4beb..4b361c6716 100644 --- a/tests/Avalonia.IntegrationTests.Appium/ElementExtensions.cs +++ b/tests/Avalonia.IntegrationTests.Appium/ElementExtensions.cs @@ -130,17 +130,10 @@ namespace Avalonia.IntegrationTests.Appium public static void SendClick(this AppiumWebElement element) { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - element.Click(); - } - else - { - // The Click() method seems to correspond to accessibilityPerformPress on macOS but certain controls - // such as list items don't support this action, so instead simulate a physical click as VoiceOver - // does. - new Actions(element.WrappedDriver).MoveToElement(element).Click().Perform(); - } + // The Click() method seems to correspond to accessibilityPerformPress on macOS but certain controls + // such as list items don't support this action, so instead simulate a physical click as VoiceOver + // does. On Windows, Click() seems to fail with the WindowState checkbox for some reason. + new Actions(element.WrappedDriver).MoveToElement(element).Click().Perform(); } public static void MovePointerOver(this AppiumWebElement element) From 4e63f19a0b24b699370b0bb78d7162d371d8f70f Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Mon, 27 Jun 2022 23:01:01 +0200 Subject: [PATCH 64/78] Account for scaling. --- tests/Avalonia.IntegrationTests.Appium/WindowTests.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs b/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs index 6a364e5fc0..2b10c302bc 100644 --- a/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs +++ b/tests/Avalonia.IntegrationTests.Appium/WindowTests.cs @@ -3,6 +3,7 @@ using System.Runtime.InteropServices; using System.Threading; using Avalonia.Controls; using OpenQA.Selenium.Appium; +using OpenQA.Selenium.Interactions; using Xunit; using Xunit.Sdk; @@ -87,8 +88,9 @@ namespace Avalonia.IntegrationTests.Appium Assert.Equal("Fullscreen", windowState.GetComboBoxValue()); current = GetWindowInfo(); - Assert.True(current.ClientSize.Width >= current.ScreenRect.Width); - Assert.True(current.ClientSize.Height >= current.ScreenRect.Height); + var clientSize = PixelSize.FromSize(current.ClientSize, current.Scaling); + Assert.True(clientSize.Width >= current.ScreenRect.Width); + Assert.True(clientSize.Height >= current.ScreenRect.Height); windowState.Click(); _session.FindElementByName("Normal").SendClick(); From 77e32f4bbeb80c0db97419aa848f63e053d5e588 Mon Sep 17 00:00:00 2001 From: Benedikt Stebner Date: Tue, 28 Jun 2022 09:00:21 +0200 Subject: [PATCH 65/78] Update to Unicode 14 --- .../Media/TextFormatting/TextFormatterImpl.cs | 8 +- .../Media/TextFormatting/Unicode/BiDi.trie.cs | 498 ++++++- .../TextFormatting/Unicode/BiDiAlgorithm.cs | 28 +- .../Media/TextFormatting/Unicode/BiDiData.cs | 25 +- .../Media/TextFormatting/Unicode/Codepoint.cs | 44 +- .../TextFormatting/Unicode/GraphemeBreak.cs | 7 + .../Unicode/GraphemeBreak.trie.cs | 422 +++++- .../TextFormatting/Unicode/LineBreakClass.cs | 1 - .../Unicode/LineBreakEnumerator.cs | 14 + .../Media/TextFormatting/Unicode/Script.cs | 5 + .../TextFormatting/Unicode/UnicodeData.cs | 42 +- .../Unicode/UnicodeData.trie.cs | 1192 +++++++++++++++-- .../TextFormatting/Unicode/UnicodeTrie.cs | 156 ++- .../Unicode/UnicodeTrieBuilder.cs | 14 +- src/Avalonia.Base/Utilities/ArrayBuilder.cs | 2 +- src/Avalonia.Base/Utilities/ArraySlice.cs | 2 +- src/Avalonia.Base/Utilities/BidiDictionary.cs | 40 + src/Skia/Avalonia.Skia/TextShaperImpl.cs | 2 +- .../Media/TextShaperImpl.cs | 2 +- .../TextFormatting/BiDiAlgorithmTests.cs | 2 +- .../Media/TextFormatting/BiDiClassTests.cs | 9 +- .../TextFormatting/BiDiTestDataGenerator.cs | 2 + .../GraphemeBreakClassTrieGenerator.cs | 9 +- .../GraphemeBreakClassTrieGeneratorTests.cs | 84 +- .../GraphemeBreakTestDataGenerator.cs | 108 ++ .../LineBreakEnumuratorTests.cs | 2 +- .../Media/TextFormatting/TestDataGenerator.cs | 85 -- .../TextFormatting/UnicodeDataGenerator.cs | 58 +- .../UnicodeDataGeneratorTests.cs | 4 +- .../TextFormatting/UnicodeEnumsGenerator.cs | 10 +- .../HarfBuzzTextShaperImpl.cs | 2 +- 31 files changed, 2417 insertions(+), 462 deletions(-) create mode 100644 src/Avalonia.Base/Media/TextFormatting/Unicode/GraphemeBreak.cs create mode 100644 src/Avalonia.Base/Utilities/BidiDictionary.cs create mode 100644 tests/Avalonia.Base.UnitTests/Media/TextFormatting/GraphemeBreakTestDataGenerator.cs delete mode 100644 tests/Avalonia.Base.UnitTests/Media/TextFormatting/TestDataGenerator.cs diff --git a/src/Avalonia.Base/Media/TextFormatting/TextFormatterImpl.cs b/src/Avalonia.Base/Media/TextFormatting/TextFormatterImpl.cs index 16caadb0dd..73dd3366aa 100644 --- a/src/Avalonia.Base/Media/TextFormatting/TextFormatterImpl.cs +++ b/src/Avalonia.Base/Media/TextFormatting/TextFormatterImpl.cs @@ -159,7 +159,6 @@ namespace Avalonia.Media.TextFormatting { var flowDirection = paragraphProperties.FlowDirection; var drawableTextRuns = new List(); - var biDiData = new BidiData((sbyte)flowDirection); foreach (var textRun in textRuns) @@ -174,10 +173,9 @@ namespace Avalonia.Media.TextFormatting { biDiData.Append(textRun.Text); } - } - var biDi = BidiAlgorithm.Instance.Value!; + var biDi = new BidiAlgorithm(); biDi.Process(biDiData); @@ -290,9 +288,7 @@ namespace Avalonia.Media.TextFormatting /// The text characters to form from. /// The bidi levels. /// - private static IEnumerable> CoalesceLevels( - IReadOnlyList textCharacters, - ReadOnlySlice levels) + private static IEnumerable> CoalesceLevels(IReadOnlyList textCharacters, ArraySlice levels) { if (levels.Length == 0) { diff --git a/src/Avalonia.Base/Media/TextFormatting/Unicode/BiDi.trie.cs b/src/Avalonia.Base/Media/TextFormatting/Unicode/BiDi.trie.cs index 7ce5453ec4..d489ad4106 100644 --- a/src/Avalonia.Base/Media/TextFormatting/Unicode/BiDi.trie.cs +++ b/src/Avalonia.Base/Media/TextFormatting/Unicode/BiDi.trie.cs @@ -1,42 +1,472 @@ using System; - namespace Avalonia.Media.TextFormatting.Unicode { - internal static class BiDiTrie + internal static class BidiTrie { public static ReadOnlySpan Data => new byte[] { - 0,16,0,0,0,0,0,0,0,0,174,224,0,68,12,187,243,236,157,11,176,85,85,25,199,151,115,207,189,247,156,203,227,94,244,132,151,128,58,122,53,184,10,74,112,26,206,61,64,105,130,89,22,163,121,85,12,17,38,26,7,197,72,37,152,166,59,56,142,132,236,64,144,16,196,212,6,26,167,98,34,197,158,71,83,10,134,116,116,236,161,165,4,50,38,61,40,64,137,178, - 28,109,6,164,255,102,175,205,93,44,246,99,61,247,62,192,254,102,126,243,173,189,246,218,235,251,214,183,190,253,60,251,156,51,171,129,144,91,193,87,192,157,224,1,176,14,172,7,143,3,7,172,144,208,63,3,191,0,207,130,223,130,109,224,79,224,85,240,23,176,15,188,5,246,131,183,3,182,63,4,26,115,225,253,247,193,186,51,192,96,208,1,206,7,99,64,23,184,24,92, - 10,38,131,43,193,117,96,6,152,5,230,128,249,96,30,88,0,22,129,101,224,223,121,66,222,5,7,65,174,64,200,80,212,141,6,99,193,90,44,175,134,94,227,150,115,132,124,15,108,4,143,131,39,192,102,240,28,93,126,17,188,194,44,191,6,118,211,246,251,193,219,116,251,67,57,111,44,141,141,132,20,192,0,112,6,24,12,58,26,123,251,63,191,209,107,127,24,109,47,108, - 244,236,249,246,29,212,141,109,244,180,203,4,148,39,49,203,159,68,249,74,186,124,53,244,245,180,252,5,232,91,192,92,112,144,246,227,128,30,44,47,4,75,193,125,76,63,142,65,30,162,253,62,194,245,191,193,176,189,31,115,253,61,133,229,167,192,211,24,239,211,116,204,91,176,252,124,163,231,203,75,92,251,237,88,126,148,137,141,3,118,161,110,15,215,110,31,150,107,200,143, - 183,104,253,255,160,79,107,242,202,5,232,211,105,253,155,232,107,64,147,55,239,131,154,188,249,60,139,182,27,78,245,72,170,29,134,49,168,27,23,80,239,80,182,129,223,180,168,197,232,227,232,247,83,96,50,184,6,244,96,28,27,193,13,40,223,8,22,162,188,24,204,199,24,230,96,121,62,184,131,250,114,119,147,55,110,159,217,76,185,22,192,38,112,15,221,118,37,244,55,185, - 237,107,224,48,234,182,210,242,90,102,204,223,13,104,91,19,96,67,200,118,47,48,229,223,131,29,133,248,88,241,125,252,153,234,61,224,128,164,95,239,128,67,92,157,19,149,203,77,92,46,55,29,159,3,110,31,141,200,131,45,180,175,124,75,111,223,173,76,185,198,113,38,214,13,5,91,209,231,11,76,191,127,104,234,221,39,55,198,196,229,231,104,187,137,46,239,68,249,175,180, - 159,55,160,255,195,249,234,128,119,154,142,221,127,30,51,184,223,59,25,36,139,1,57,101,98,80,19,56,126,56,25,36,139,1,201,98,208,144,197,32,139,1,201,98,208,144,197,32,139,1,201,98,208,144,197,160,94,99,176,179,201,187,174,117,159,9,56,2,237,115,205,189,229,66,179,247,44,205,95,190,150,62,163,217,203,212,13,96,218,59,96,16,150,75,180,110,24,179,110,36, - 182,185,144,46,143,133,254,40,45,175,198,115,156,75,104,249,49,250,156,232,114,44,95,213,236,61,183,115,151,175,109,246,158,211,77,231,108,29,224,158,33,221,200,173,119,50,72,22,3,146,197,160,33,139,65,22,3,146,197,160,33,139,65,22,3,146,197,160,225,196,141,193,205,184,198,107,193,53,104,255,130,247,185,178,10,231,182,28,95,247,29,212,141,4,31,1,75,209,247,189, - 96,46,103,227,81,172,187,28,117,183,195,135,175,130,187,184,235,205,53,117,240,252,184,212,223,99,6,88,71,203,165,0,182,131,246,86,66,166,128,89,96,61,248,73,107,239,250,255,50,229,18,24,209,134,207,186,193,15,192,223,64,251,0,66,38,130,59,193,19,224,101,80,60,29,109,17,163,85,125,97,31,122,45,88,119,90,60,175,11,182,251,96,159,222,114,55,202,171,192,203, - 224,69,216,43,130,182,126,98,253,216,162,27,62,172,203,236,147,180,98,208,157,197,159,100,249,71,82,139,65,119,150,127,36,237,252,187,2,231,128,25,253,78,221,249,143,187,62,88,210,124,236,231,221,43,155,123,223,79,89,207,189,167,229,112,92,197,93,223,60,88,135,207,219,54,98,12,223,134,95,235,221,103,134,205,222,251,97,63,106,238,93,239,62,111,124,146,46,255,146,174, - 255,21,244,175,153,54,47,49,101,135,121,87,104,71,115,239,251,131,238,251,104,187,2,218,57,13,158,253,61,204,186,127,161,252,110,72,91,7,28,196,186,92,222,43,187,244,205,123,253,223,79,183,41,230,143,125,239,111,8,179,236,112,156,21,177,206,1,195,177,126,20,215,102,12,181,55,14,250,99,224,19,116,253,228,152,190,156,0,174,102,182,153,134,242,76,174,143,155,176,124, - 27,173,155,39,209,255,135,35,222,107,236,65,63,11,21,124,117,100,200,123,122,57,213,78,138,108,166,121,177,138,241,229,225,58,240,203,225,120,30,251,218,79,21,223,169,116,20,120,4,49,216,0,126,200,196,162,70,143,115,19,66,252,168,209,245,155,19,190,119,219,72,245,34,58,151,223,247,215,53,123,250,73,140,97,170,1,159,182,129,45,121,79,63,7,253,59,240,74,130,115, - 226,104,242,26,124,221,29,227,239,114,197,220,255,99,29,238,51,14,71,13,57,240,25,238,29,212,207,130,107,90,188,119,78,95,207,247,230,206,110,58,158,197,52,135,28,142,21,1,159,1,214,20,222,7,174,25,96,106,139,119,237,193,214,181,50,227,156,137,242,46,193,207,44,157,147,148,189,121,239,251,19,81,12,44,68,175,255,0,214,159,29,210,230,60,90,63,34,166,143,161, - 17,140,118,191,71,81,16,107,91,166,237,198,115,237,251,23,188,239,144,248,223,23,25,26,192,69,220,186,75,4,109,14,213,160,127,193,27,223,104,166,110,52,37,23,98,127,116,4,147,90,226,109,250,251,250,108,170,167,67,207,101,142,127,53,212,213,40,61,45,225,239,232,187,251,210,93,96,9,88,1,86,211,62,106,76,155,26,248,22,237,99,43,152,89,72,63,223,55,193,159, - 77,17,108,67,187,109,33,60,19,179,237,166,83,0,66,240,112,54,150,110,128,155,197,35,122,10,45,183,41,210,151,161,155,246,87,161,148,24,42,71,232,36,85,50,156,116,209,229,33,160,200,232,34,104,23,164,200,216,169,112,36,35,211,48,22,2,123,83,143,142,167,66,73,70,22,80,251,61,71,237,183,37,99,184,174,165,45,128,190,33,245,109,22,40,6,228,126,137,214,85, - 24,92,241,203,238,118,126,217,109,235,226,231,57,223,214,197,173,231,235,216,126,109,137,237,254,235,221,126,82,34,50,151,65,115,47,130,169,237,101,125,209,177,201,82,62,197,9,139,125,156,196,205,93,84,155,147,81,84,198,42,51,47,39,155,4,29,59,220,243,212,196,58,216,39,202,10,76,228,116,57,164,60,241,36,39,31,66,133,146,163,243,92,162,229,34,213,21,74,89,130, - 92,157,83,182,64,94,144,18,83,206,113,62,229,50,8,31,131,184,152,71,229,38,223,71,80,91,191,141,232,253,168,201,57,74,115,206,77,230,254,201,156,183,73,197,33,237,243,131,12,34,177,240,219,250,231,15,31,190,159,160,62,211,20,223,126,144,31,113,99,14,235,75,100,123,25,255,210,138,81,154,115,35,50,31,42,125,232,138,238,124,184,215,3,46,113,109,88,123,166,108, - 235,74,84,222,7,249,25,180,63,216,244,69,182,255,176,253,82,116,255,54,33,58,115,26,151,71,108,255,170,199,31,83,194,231,135,175,77,238,207,42,99,59,145,142,173,182,124,229,207,217,62,110,126,185,90,196,151,180,207,227,190,196,229,83,216,190,46,146,59,170,249,101,35,54,97,115,22,54,95,113,146,246,117,134,170,109,209,57,139,186,206,83,149,176,115,94,92,78,197,29, - 183,101,175,59,85,69,212,127,157,188,79,235,188,147,132,61,62,167,202,100,92,107,149,84,91,187,200,4,232,241,208,230,237,149,21,8,219,150,173,15,18,19,54,146,68,87,100,198,196,174,227,183,79,66,194,108,217,142,135,74,31,124,127,34,109,117,109,165,33,38,99,31,117,126,23,57,215,171,94,7,152,18,247,125,161,100,228,225,129,85,242,208,64,211,199,90,95,76,206,169, - 136,29,222,166,236,62,24,180,191,233,30,59,253,235,21,182,157,104,126,242,207,224,221,119,98,76,73,26,199,219,168,99,174,104,63,42,54,248,253,89,231,90,223,164,36,225,71,208,121,214,166,45,214,102,212,185,159,247,69,117,31,147,221,71,109,156,219,147,190,214,10,242,39,204,47,118,189,106,223,182,198,19,53,71,65,99,50,45,188,141,168,117,54,99,200,183,211,149,160,249, - 87,201,81,153,57,143,219,71,131,252,75,83,252,227,174,234,179,31,221,103,70,166,182,119,197,189,94,20,133,125,47,215,149,160,207,29,101,9,123,239,119,4,248,52,56,7,92,20,209,174,157,27,91,123,8,67,40,21,114,71,169,74,22,148,252,235,214,176,246,225,219,47,199,246,203,142,110,175,43,236,92,4,221,99,200,206,179,104,110,70,221,215,132,105,86,68,62,3,9,178, - 39,226,135,136,191,81,219,203,32,227,187,168,255,114,156,215,81,37,157,29,252,119,30,76,248,109,90,244,199,26,157,115,21,1,218,13,115,34,141,93,180,63,81,223,121,17,189,94,145,181,159,148,184,126,179,223,151,58,222,167,194,168,42,201,143,234,34,125,160,91,160,251,65,247,133,110,133,238,15,61,0,186,13,154,208,109,223,135,229,34,150,207,132,30,8,61,8,186,29,122, - 48,244,251,153,118,68,58,6,101,14,95,226,230,48,106,93,82,241,247,125,182,97,211,70,254,219,20,27,182,147,28,127,146,241,211,57,86,37,57,183,182,108,242,251,188,219,63,95,23,134,168,63,73,30,3,162,150,195,234,76,217,246,251,230,115,68,214,166,200,123,97,58,34,155,195,162,249,16,135,138,68,109,103,195,158,136,63,54,199,43,98,63,204,23,190,94,182,223,168,49, - 152,176,225,111,103,162,141,138,77,217,88,233,140,209,244,56,121,159,117,250,178,33,236,59,221,201,157,23,39,28,246,190,31,63,238,112,58,223,207,159,70,237,79,165,246,103,96,121,58,45,207,68,249,243,199,248,149,164,164,121,223,163,123,141,88,175,215,216,73,29,227,69,236,154,56,231,156,8,247,53,186,231,184,176,24,165,113,238,246,237,218,236,219,212,184,162,226,110,82,162, - 108,196,249,28,118,30,76,99,94,227,108,199,181,211,181,231,47,219,20,27,253,71,197,43,106,126,249,114,26,34,58,135,105,251,108,211,166,232,254,166,154,163,65,219,201,230,76,84,223,34,231,5,155,34,122,204,78,43,215,69,246,199,164,37,42,199,194,252,17,201,207,36,198,34,234,135,168,63,162,62,203,216,21,21,145,220,77,34,151,69,237,217,222,175,85,226,33,114,92,11, - 138,91,82,49,228,219,132,249,97,226,120,172,42,113,190,218,144,184,123,35,255,25,174,143,238,189,150,201,251,45,219,251,130,72,174,155,234,91,71,252,152,166,113,14,243,69,118,44,113,191,77,104,234,88,99,67,146,176,35,179,159,152,122,95,67,245,184,47,115,110,240,197,84,63,65,253,138,74,146,57,162,98,203,100,158,185,199,110,153,92,176,121,220,78,251,51,104,94,252,99, - 78,82,191,53,19,246,251,51,124,125,84,187,52,126,39,135,95,167,251,187,68,38,252,115,223,27,181,53,246,122,24,159,42,238,254,20,149,79,162,121,154,86,110,197,249,152,100,28,195,16,253,189,60,27,168,198,218,214,252,37,145,59,174,4,221,151,120,117,5,124,78,153,63,250,57,229,16,250,251,143,67,168,46,74,156,251,138,33,243,93,150,232,163,221,0,188,152,232,211,164, - 63,178,162,107,199,196,189,167,159,27,58,247,178,238,246,46,252,181,11,155,151,65,215,51,186,231,147,56,191,252,255,71,24,14,46,3,227,193,40,112,5,205,233,82,0,21,9,74,41,83,214,164,162,73,145,209,174,176,117,30,159,123,175,74,174,123,175,139,92,15,61,21,250,6,232,105,208,36,52,230,37,138,223,95,24,174,136,252,166,127,208,182,252,61,181,123,254,208,141,165, - 10,113,191,75,25,151,255,162,231,70,209,253,167,72,46,45,85,201,164,35,223,55,170,88,102,74,2,54,42,145,20,58,112,126,196,119,97,250,64,183,72,127,39,166,34,137,13,137,182,121,211,176,42,153,53,172,139,204,134,190,25,250,139,208,183,64,127,9,122,14,244,109,208,183,66,207,133,190,29,122,30,244,151,161,137,196,184,158,197,54,207,72,110,67,52,249,7,108,254,29, - 54,247,66,239,129,126,3,122,31,244,126,232,55,161,15,64,255,211,176,79,95,235,172,146,133,157,93,228,110,232,69,208,14,244,98,232,37,208,95,135,190,7,122,41,244,10,232,123,161,151,67,47,131,94,9,253,13,232,85,208,247,65,223,15,189,26,250,1,232,53,157,102,125,140,99,7,108,110,135,205,157,208,175,38,108,155,128,67,176,123,208,170,93,95,108,143,69,206,70,199, - 5,85,114,246,5,93,228,92,232,115,160,135,65,127,8,186,19,122,56,52,73,120,30,236,197,72,86,108,231,129,174,232,218,77,235,247,173,125,127,116,255,15,73,213,182,202,239,108,235,92,159,134,137,191,158,239,51,41,49,53,143,182,238,143,226,226,104,99,159,172,199,227,150,234,113,36,109,31,146,242,223,244,248,249,237,85,37,169,248,155,154,195,184,216,198,197,92,103,174,77, - 140,67,39,31,85,164,30,198,171,147,7,186,199,255,52,206,223,166,8,242,39,105,177,241,31,145,50,232,94,255,164,109,95,20,87,100,234,101,250,213,17,21,159,85,125,20,181,21,214,214,190,252,31,0,0,255,255,0,0,0,255,255,99,102,0,0}; + 0, 0, 16, 0, 0, 0, 0, 0, 64, 180, 0, 0, 116, 3, 0, 0, 124, 3, 0, 0, 132, 3, 0, 0, 140, 3, 0, 0, 164, 3, 0, 0, 172, 3, 0, 0, 180, 3, 0, 0, 188, 3, 0, 0, 148, 3, 0, 0, 156, 3, 0, 0, 148, 3, 0, 0, 156, 3, 0, 0, 148, 3, 0, 0, 156, 3, 0, 0, 148, 3, 0, 0, 156, 3, 0, 0, 148, 3, 0, 0, 156, 3, 0, 0, 148, 3, 0, 0, 156, 3, 0, 0, 194, 3, 0, 0, 202, 3, 0, 0, + 210, 3, 0, 0, 218, 3, 0, 0, 226, 3, 0, 0, 234, 3, 0, 0, 230, 3, 0, 0, 238, 3, 0, 0, 246, 3, 0, 0, 254, 3, 0, 0, 249, 3, 0, 0, 1, 4, 0, 0, 148, 3, 0, 0, 156, 3, 0, 0, 148, 3, 0, 0, 156, 3, 0, 0, 9, 4, 0, 0, 17, 4, 0, 0, 148, 3, 0, 0, 156, 3, 0, 0, 148, 3, 0, 0, 156, 3, 0, 0, 148, 3, 0, 0, 156, 3, 0, 0, 23, 4, 0, 0, 31, 4, 0, 0, 39, 4, 0, 0, + 47, 4, 0, 0, 55, 4, 0, 0, 63, 4, 0, 0, 69, 4, 0, 0, 77, 4, 0, 0, 82, 4, 0, 0, 90, 4, 0, 0, 93, 4, 0, 0, 101, 4, 0, 0, 108, 4, 0, 0, 116, 4, 0, 0, 122, 4, 0, 0, 130, 4, 0, 0, 129, 4, 0, 0, 137, 4, 0, 0, 145, 4, 0, 0, 153, 4, 0, 0, 24, 9, 0, 0, 31, 9, 0, 0, 35, 9, 0, 0, 62, 4, 0, 0, 199, 9, 0, 0, 62, 4, 0, 0, 22, 11, 0, 0, 207, 9, 0, 0, + 161, 4, 0, 0, 163, 4, 0, 0, 171, 4, 0, 0, 179, 4, 0, 0, 187, 4, 0, 0, 188, 4, 0, 0, 196, 4, 0, 0, 204, 4, 0, 0, 212, 4, 0, 0, 188, 4, 0, 0, 220, 4, 0, 0, 225, 4, 0, 0, 212, 4, 0, 0, 188, 4, 0, 0, 233, 4, 0, 0, 241, 4, 0, 0, 187, 4, 0, 0, 249, 4, 0, 0, 1, 5, 0, 0, 179, 4, 0, 0, 9, 5, 0, 0, 148, 3, 0, 0, 17, 5, 0, 0, 21, 5, 0, 0, 29, 5, 0, 0, + 31, 5, 0, 0, 39, 5, 0, 0, 47, 5, 0, 0, 187, 4, 0, 0, 188, 4, 0, 0, 55, 5, 0, 0, 179, 4, 0, 0, 11, 4, 0, 0, 59, 5, 0, 0, 196, 4, 0, 0, 179, 4, 0, 0, 187, 4, 0, 0, 148, 3, 0, 0, 67, 5, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 73, 5, 0, 0, 81, 5, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 85, 5, 0, 0, 93, 5, 0, 0, 148, 3, 0, 0, 97, 5, 0, 0, 104, 5, 0, 0, + 148, 3, 0, 0, 112, 5, 0, 0, 120, 5, 0, 0, 127, 5, 0, 0, 8, 5, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 135, 5, 0, 0, 143, 5, 0, 0, 151, 5, 0, 0, 159, 5, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 167, 5, 0, 0, 148, 3, 0, 0, 175, 5, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 183, 5, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 191, 5, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 199, 5, 0, 0, 200, 4, 0, 0, 200, 4, 0, 0, 200, 4, 0, 0, 148, 3, 0, 0, 205, 5, 0, 0, 213, 5, 0, 0, 175, 5, 0, 0, 221, 5, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 228, 5, 0, 0, + 185, 4, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 236, 5, 0, 0, 244, 5, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 246, 5, 0, 0, 231, 9, 0, 0, 254, 5, 0, 0, 148, 3, 0, 0, 5, 6, 0, 0, 13, 6, 0, 0, 148, 3, 0, 0, 21, 6, 0, 0, 27, 11, 0, 0, 148, 3, 0, 0, 248, 4, 0, 0, 29, 6, 0, 0, 9, 5, 0, 0, 37, 6, 0, 0, 11, 4, 0, 0, 45, 6, 0, 0, + 148, 3, 0, 0, 52, 6, 0, 0, 148, 3, 0, 0, 57, 6, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 63, 6, 0, 0, 71, 6, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 226, 3, 0, 0, 226, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 78, 6, 0, 0, 86, 6, 0, 0, 90, 6, 0, 0, 98, 6, 0, 0, 163, 9, 0, 0, 223, 9, 0, 0, 106, 6, 0, 0, 114, 6, 0, 0, 171, 9, 0, 0, 175, 9, 0, 0, 130, 5, 0, 0, 122, 6, 0, 0, 130, 6, 0, 0, 138, 6, 0, 0, 148, 3, 0, 0, 146, 6, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, + 147, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 237, 9, 0, 0, 152, 6, 0, 0, 148, 3, 0, 0, 158, 6, 0, 0, 165, 6, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 11, 7, 0, 0, 243, 9, 0, 0, 231, 9, 0, 0, 171, 6, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 178, 6, 0, 0, 231, 9, 0, 0, + 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 183, 6, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 251, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 2, 10, 0, 0, 9, 10, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 17, 10, 0, 0, 231, 9, 0, 0, 24, 10, 0, 0, 31, 10, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, + 39, 10, 0, 0, 45, 10, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 191, 6, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 199, 6, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 226, 3, 0, 0, 231, 9, 0, 0, 53, 10, 0, 0, 56, 10, 0, 0, 148, 3, 0, 0, + 64, 10, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 71, 10, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 79, 10, 0, 0, 85, 10, 0, 0, 207, 6, 0, 0, 215, 6, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 223, 6, 0, 0, 183, 5, 0, 0, 148, 3, 0, 0, 187, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 231, 9, 0, 0, 198, 6, 0, 0, 201, 3, 0, 0, 148, 3, 0, 0, 231, 6, 0, 0, 239, 6, 0, 0, 148, 3, 0, 0, 247, 6, 0, 0, 255, 6, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 3, 7, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 246, 5, 0, 0, 186, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 231, 9, 0, 0, 231, 9, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 231, 6, 0, 0, 231, 9, 0, 0, 11, 7, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 16, 7, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 21, 7, 0, 0, 29, 7, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 99, 5, 0, 0, 231, 9, 0, 0, 245, 5, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 37, 7, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 45, 7, 0, 0, 52, 7, 0, 0, 148, 3, 0, 0, + 59, 7, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 57, 5, 0, 0, 67, 7, 0, 0, 148, 3, 0, 0, 75, 7, 0, 0, 82, 7, 0, 0, 148, 3, 0, 0, 161, 4, 0, 0, 87, 7, 0, 0, 148, 3, 0, 0, 186, 4, 0, 0, 148, 3, 0, 0, 95, 7, 0, 0, 103, 7, 0, 0, 188, 4, 0, 0, 148, 3, 0, 0, 107, 7, 0, 0, 187, 4, 0, 0, 115, 7, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 251, 5, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 122, 7, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 126, 7, 0, 0, 42, 9, 0, 0, 46, 9, 0, 0, 62, 4, 0, 0, 62, 4, 0, 0, 62, 4, 0, 0, 62, 4, 0, 0, 62, 4, 0, 0, 62, 4, 0, 0, 62, 4, 0, 0, 62, 4, 0, 0, 62, 4, 0, 0, 62, 4, 0, 0, 62, 4, 0, 0, + 62, 4, 0, 0, 62, 4, 0, 0, 62, 4, 0, 0, 93, 10, 0, 0, 101, 10, 0, 0, 62, 4, 0, 0, 62, 4, 0, 0, 62, 4, 0, 0, 106, 10, 0, 0, 110, 10, 0, 0, 118, 10, 0, 0, 179, 9, 0, 0, 183, 9, 0, 0, 155, 9, 0, 0, 62, 4, 0, 0, 62, 4, 0, 0, 62, 4, 0, 0, 246, 10, 0, 0, 115, 9, 0, 0, 134, 7, 0, 0, 142, 7, 0, 0, 150, 7, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 191, 9, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 80, 14, 0, 0, 80, 14, 0, 0, 144, 14, 0, 0, 208, 14, 0, 0, 80, 14, 0, 0, 80, 14, 0, 0, 80, 14, 0, 0, 80, 14, 0, 0, 80, 14, 0, 0, 80, 14, 0, 0, 8, 15, 0, 0, 72, 15, 0, 0, 136, 15, 0, 0, 152, 15, 0, 0, 216, 15, 0, 0, 228, 15, 0, 0, 80, 14, 0, 0, + 80, 14, 0, 0, 36, 16, 0, 0, 80, 14, 0, 0, 80, 14, 0, 0, 80, 14, 0, 0, 92, 16, 0, 0, 156, 16, 0, 0, 220, 16, 0, 0, 20, 17, 0, 0, 72, 17, 0, 0, 116, 17, 0, 0, 176, 17, 0, 0, 232, 17, 0, 0, 4, 18, 0, 0, 68, 18, 0, 0, 32, 10, 0, 0, 192, 12, 0, 0, 96, 10, 0, 0, 159, 10, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, + 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 223, 10, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 31, 11, 0, 0, 160, 1, 0, 0, 69, 11, 0, 0, 128, 11, 0, 0, 192, 11, 0, 0, 0, 12, 0, 0, 253, 12, 0, 0, 64, 12, 0, 0, 61, 13, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, + 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, + 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 128, 12, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, + 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 128, 12, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, + 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 128, 12, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, + 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 128, 12, 0, 0, + 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, + 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 128, 12, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, + 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 128, 12, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, + 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 128, 12, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, + 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, + 160, 1, 0, 0, 160, 1, 0, 0, 128, 12, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, + 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 128, 12, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, + 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 128, 12, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, + 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 128, 12, 0, 0, 160, 1, 0, 0, + 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, + 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 128, 12, 0, 0, 125, 13, 0, 0, 141, 13, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, + 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 128, 12, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, + 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 128, 12, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 158, 7, 0, 0, 148, 3, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 166, 7, 0, 0, 183, 5, 0, 0, 148, 3, 0, 0, 180, 4, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 123, 9, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 174, 7, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 187, 4, 0, 0, 181, 7, 0, 0, 188, 7, 0, 0, 195, 7, 0, 0, 11, 4, 0, 0, 203, 7, 0, 0, 9, 5, 0, 0, 148, 3, 0, 0, 161, 4, 0, 0, 210, 7, 0, 0, 148, 3, 0, 0, 216, 7, 0, 0, 11, 4, 0, 0, 221, 7, 0, 0, 229, 7, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 234, 7, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 199, 6, 0, 0, 242, 7, 0, 0, 11, 4, 0, 0, 59, 5, 0, 0, 30, 5, 0, 0, 249, 7, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 181, 7, 0, 0, 1, 8, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 9, 8, 0, 0, 17, 8, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 21, 8, 0, 0, 29, 8, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 37, 8, 0, 0, 30, 5, 0, 0, 170, 7, 0, 0, 148, 3, 0, 0, 45, 8, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 167, 5, 0, 0, 53, 8, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 58, 8, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 65, 8, 0, 0, 73, 8, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 76, 8, 0, 0, 30, 5, 0, 0, 84, 8, 0, 0, 88, 8, 0, 0, 96, 8, 0, 0, 148, 3, 0, 0, 103, 8, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 110, 8, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 118, 8, 0, 0, 124, 8, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 130, 8, 0, 0, 138, 8, 0, 0, 148, 3, 0, 0, 142, 8, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 61, 5, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 8, 0, 0, 156, 8, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 161, 8, 0, 0, 148, 3, 0, 0, 167, 8, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 217, 7, 0, 0, 148, 3, 0, 0, 173, 8, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 181, 8, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 213, 4, 0, 0, 254, 10, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 226, 3, 0, 0, 35, 11, 0, 0, 189, 8, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 196, 8, 0, 0, 204, 8, 0, 0, 210, 8, 0, 0, 148, 3, 0, 0, 216, 8, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 126, 10, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 240, 9, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 187, 3, 0, 0, 148, 3, 0, 0, 153, 7, 0, 0, 148, 3, 0, 0, 182, 3, 0, 0, 148, 3, 0, 0, 156, 7, 0, 0, 148, 3, 0, 0, 224, 8, 0, 0, 131, 9, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 226, 3, 0, 0, 232, 8, 0, 0, 226, 3, 0, 0, 239, 8, 0, 0, 246, 8, 0, 0, 43, 11, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 51, 11, 0, 0, 59, 11, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 167, 8, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 5, 8, 0, 0, 148, 3, 0, 0, 254, 8, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 231, 9, 0, 0, 142, 10, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 71, 10, 0, 0, 147, 10, 0, 0, 151, 10, 0, 0, 79, 10, 0, 0, 6, 9, 0, 0, 182, 3, 0, 0, 148, 3, 0, 0, + 12, 9, 0, 0, 148, 3, 0, 0, 155, 7, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 156, 6, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, + 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 156, 10, 0, 0, 166, 7, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 71, 10, 0, 0, 231, 9, 0, 0, + 231, 9, 0, 0, 164, 10, 0, 0, 172, 10, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 16, 9, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, + 54, 9, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 62, 9, 0, 0, 66, 9, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 74, 9, 0, 0, 41, 4, 0, 0, 76, 9, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, + 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 62, 4, 0, 0, 215, 9, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 84, 9, 0, 0, 41, 4, 0, 0, 92, 9, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 46, 9, 0, 0, + 137, 4, 0, 0, 50, 9, 0, 0, 100, 9, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 104, 9, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 107, 9, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, + 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 46, 9, 0, 0, 62, 4, 0, 0, 62, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 62, 4, 0, 0, 62, 4, 0, 0, 50, 9, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, + 41, 4, 0, 0, 62, 4, 0, 0, 62, 4, 0, 0, 62, 4, 0, 0, 62, 4, 0, 0, 62, 4, 0, 0, 62, 4, 0, 0, 62, 4, 0, 0, 134, 10, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 41, 4, 0, 0, 142, 10, 0, 0, 231, 9, 0, 0, 180, 10, 0, 0, 231, 9, 0, 0, 188, 10, 0, 0, 193, 10, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 71, 10, 0, 0, 201, 10, 0, 0, 209, 10, 0, 0, 214, 10, 0, 0, 222, 10, 0, 0, 230, 10, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 231, 9, 0, 0, 238, 10, 0, 0, 231, 9, 0, 0, 243, 9, 0, 0, 139, 9, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, + 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 148, 3, 0, 0, 16, 9, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 226, 3, 0, 0, 226, 3, 0, 0, 226, 3, 0, 0, 226, 3, 0, 0, 226, 3, 0, 0, 226, 3, 0, 0, 226, 3, 0, 0, 14, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, + 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, + 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, + 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 6, 11, 0, 0, 115, 3, 1, 0, 115, 3, 1, 0, 115, 3, 1, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 84, 0, 0, 0, 12, 0, + 0, 0, 84, 0, 0, 0, 88, 0, 0, 0, 12, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 12, 0, 0, 0, 12, 0, 0, 0, 12, 0, 0, 0, 84, 0, 0, 0, 88, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 32, 0, + 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 56, 0, 0, 0, 56, 0, 41, 0, 58, 0, 40, 0, 57, 0, 0, 0, 56, 0, 0, 0, 28, 0, 0, 0, 20, 0, 0, 0, 28, 0, 0, 0, 20, 0, 0, 0, 20, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 20, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 0, 58, 0, 0, 0, 56, 0, 91, 0, 57, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 125, 0, 58, 0, 0, 0, 56, 0, 123, 0, 57, 0, 0, 0, 56, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 12, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, + 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 20, 0, 0, 0, 56, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 16, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, + 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, + 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 32, 0, 0, 0, 68, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, + 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, + 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 68, 0, 0, 0, 52, 0, 0, 0, 68, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 68, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 68, 0, 0, 0, 52, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, + 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, + 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 4, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 4, 0, 0, 0, 20, 0, 0, 0, 4, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, + 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, + 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, + 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 52, 0, 0, 0, 4, 0, + 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, + 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, + 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, + 0, 0, 8, 0, 0, 0, 56, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 56, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, + 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 52, 0, 0, 0, 4, 0, + 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, + 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 4, 0, 0, 0, 4, 0, + 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, + 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, + 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, + 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, + 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, + 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 52, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 32, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 59, 15, 58, 0, 58, 15, 57, 0, 61, 15, 58, 0, 60, 15, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, + 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, + 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, + 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 22, 58, 0, 155, 22, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 16, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, + 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, + 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, + 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, + 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, + 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 88, 0, 0, 0, 88, 0, 0, 0, 88, 0, 0, 0, 88, 0, 0, 0, 88, 0, 0, 0, 88, 0, 0, 0, 88, 0, 0, 0, 88, 0, 0, 0, 88, 0, 0, 0, 88, 0, 0, 0, 88, 0, + 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, + 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 44, 0, 0, 0, 76, 0, 0, 0, 36, 0, 0, 0, 64, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 28, 0, 0, 0, 28, 0, 0, 0, 56, 0, + 126, 32, 58, 0, 125, 32, 57, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 28, 0, 0, 0, 28, 0, 0, 0, 56, 0, 142, 32, 58, 0, 141, 32, 57, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 42, 35, 58, 0, 41, 35, 57, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, + 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, + 0, 0, 88, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 48, 58, 0, 8, 48, 57, 0, 11, 48, 58, 0, 10, 48, 57, 0, 13, 48, 58, 0, 12, 48, 57, 0, 15, 48, 58, 0, 14, 48, 57, 0, 17, 48, 58, 0, 16, 48, 57, 0, 0, 0, 56, 0, 0, 0, 56, 0, 21, 48, 58, 0, 20, 48, 57, 0, 23, 48, 58, 0, 22, 48, 57, 0, 25, 48, 58, 0, + 24, 48, 57, 0, 27, 48, 58, 0, 26, 48, 57, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 56, 0, + 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, + 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 68, 0, 0, 0, 52, 0, 0, 0, 68, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61, 255, 58, 0, 0, 0, 56, 0, 59, 255, 57, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 93, 255, 58, 0, 0, 0, 56, 0, 91, 255, 57, 0, 0, 0, 56, 0, 96, 255, 58, 0, 95, 255, 57, 0, 0, 0, 56, 0, 99, 255, 58, 0, 98, 255, 57, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, + 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, + 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, + 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, + 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, + 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, + 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, + 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, + 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, + 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 16, 0, + 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 52, 0, 0, 0, 52, 0, + 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, + 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, + 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, + 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 68, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 68, 0, 0, 0, 52, 0, 0, 0, 52, 0, + 0, 0, 52, 0, 0, 0, 68, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, + 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 28, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, + 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, + 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, + 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 56, 0, 0, 0, 68, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 68, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 68, 0, + 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, + 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 52, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, + 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, + 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 52, 0, 0, 0, 52, 0, + 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, + 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, + 0, 0, 68, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, + 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 56, 0, 0, 0, 56, 0, 9, 255, 58, 0, 8, 255, 57, 0, 0, 0, 56, 0, 0, 0, 28, 0, 0, 0, 20, 0, 0, 0, 28, 0, 0, 0, 20, 0, 0, 0, 20, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, + 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 20, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 52, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, + 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, + 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, 0, 0, 24, 0, + 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 28, 0, 0, 0, 32, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 28, 0, 0, 0, 28, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 32, 0, 0, 0, 32, 0, + 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 88, 0, 0, 0, 12, 0, 0, 0, 40, 0, 0, 0, 72, 0, 0, 0, 60, 0, 0, 0, 48, 0, 0, 0, 80, 0, 0, 0, 20, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 32, 0, + 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, + 0, 0, 52, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 20, 0, 0, 0, 56, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 20, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 90, 254, 58, 0, 89, 254, 57, 0, 92, 254, 58, 0, 91, 254, 57, 0, 94, 254, 58, 0, 93, 254, 57, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 32, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 16, 0, + 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, + 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 8, 0, + 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, + 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, + 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 20, 0, 70, 32, 58, 0, 69, 32, 57, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 88, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 9, 35, 58, 0, 8, 35, 57, 0, 11, 35, 58, 0, 10, 35, 57, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 105, 39, 58, 0, 104, 39, 57, 0, 107, 39, 58, 0, 106, 39, 57, 0, 109, 39, 58, 0, 108, 39, 57, 0, 111, 39, 58, 0, 110, 39, 57, 0, 113, 39, 58, 0, 112, 39, 57, 0, 115, 39, 58, 0, 114, 39, 57, 0, 117, 39, 58, 0, 116, 39, 57, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 198, 39, 58, 0, 197, 39, 57, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 231, 39, 58, 0, 230, 39, 57, 0, 233, 39, 58, 0, 232, 39, 57, 0, 235, 39, 58, 0, 234, 39, 57, 0, 237, 39, 58, 0, 236, 39, 57, 0, 239, 39, 58, 0, 238, 39, 57, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 132, 41, 58, 0, 131, 41, 57, 0, 134, 41, 58, 0, 133, 41, 57, 0, 136, 41, 58, 0, 135, 41, 57, 0, 138, 41, 58, 0, 137, 41, 57, 0, 140, 41, 58, 0, 139, 41, 57, 0, 144, 41, 58, 0, + 143, 41, 57, 0, 142, 41, 58, 0, 141, 41, 57, 0, 146, 41, 58, 0, 145, 41, 57, 0, 148, 41, 58, 0, 147, 41, 57, 0, 150, 41, 58, 0, 149, 41, 57, 0, 152, 41, 58, 0, 151, 41, 57, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 217, 41, 58, 0, 216, 41, 57, 0, 219, 41, 58, 0, 218, 41, 57, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 253, 41, 58, 0, 252, 41, 57, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 35, 46, 58, 0, 34, 46, 57, 0, 37, 46, 58, 0, 36, 46, 57, 0, 39, 46, 58, 0, 38, 46, 57, 0, 41, 46, 58, 0, 40, 46, 57, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 86, 46, 58, 0, 85, 46, 57, 0, 88, 46, 58, 0, 87, 46, 57, 0, 90, 46, 58, 0, 89, 46, 57, 0, 92, 46, 58, 0, 91, 46, 57, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, + 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, + 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 56, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 4, 0, + 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, + 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 52, 0, + 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, + 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 56, 0, + 0, 0, 56, 0, 0, 0, 56, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, + 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, + 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 52, 0, 0, 0, 52, 0, + 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, + 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, + 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, + 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, + 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, + 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, + 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }; } } diff --git a/src/Avalonia.Base/Media/TextFormatting/Unicode/BiDiAlgorithm.cs b/src/Avalonia.Base/Media/TextFormatting/Unicode/BiDiAlgorithm.cs index 2511807d9c..17ec9b1df2 100644 --- a/src/Avalonia.Base/Media/TextFormatting/Unicode/BiDiAlgorithm.cs +++ b/src/Avalonia.Base/Media/TextFormatting/Unicode/BiDiAlgorithm.cs @@ -66,7 +66,7 @@ namespace Avalonia.Media.TextFormatting.Unicode /// The forward mapping maps the start index to the end index. /// The reverse mapping maps the end index to the start index. /// - private readonly Dictionary _isolatePairs = new Dictionary(); + private readonly BidiDictionary _isolatePairs = new BidiDictionary(); /// /// The working BiDi classes @@ -188,12 +188,6 @@ namespace Avalonia.Media.TextFormatting.Unicode { } - /// - /// Gets a per-thread instance that can be re-used as often - /// as necessary. - /// - public static ThreadLocal Instance { get; } = new ThreadLocal(() => new BidiAlgorithm()); - /// /// Gets the resolved levels. /// @@ -1414,35 +1408,37 @@ namespace Avalonia.Media.TextFormatting.Unicode /// Sets the direction of a bracket pair, including setting the direction of /// NSM's inside the brackets and following. /// - /// The paired brackets + /// The paired brackets /// The resolved direction for the bracket pair - private void SetPairedBracketDirection(in BracketPair bracketPair, BidiClass direction) + private void SetPairedBracketDirection(in BracketPair pairedBracket, BidiClass direction) { // Set the direction of the brackets - _runResolvedClasses[bracketPair.OpeningIndex] = direction; - _runResolvedClasses[bracketPair.ClosingIndex] = direction; + _runResolvedClasses[pairedBracket.OpeningIndex] = direction; + _runResolvedClasses[pairedBracket.ClosingIndex] = direction; // Set the directionality of NSM's inside the brackets - for (var i = bracketPair.OpeningIndex + 1; i < bracketPair.ClosingIndex; i++) + // BN characters (such as ZWJ or ZWSP) that appear between the base bracket character + // and the nonspacing mark should be ignored. + for (int i = pairedBracket.OpeningIndex + 1; i < pairedBracket.ClosingIndex; i++) { if (_runOriginalClasses[i] == BidiClass.NonspacingMark) { _runOriginalClasses[i] = direction; } - else + else if (_runOriginalClasses[i] != BidiClass.BoundaryNeutral) { break; } } // Set the directionality of NSM's following the brackets - for (var i = bracketPair.ClosingIndex + 1; i < _runLength; i++) + for (int i = pairedBracket.ClosingIndex + 1; i < _runLength; i++) { if (_runOriginalClasses[i] == BidiClass.NonspacingMark) { - _runResolvedClasses[i] = direction; + _runOriginalClasses[i] = direction; } - else + else if (_runOriginalClasses[i] != BidiClass.BoundaryNeutral) { break; } diff --git a/src/Avalonia.Base/Media/TextFormatting/Unicode/BiDiData.cs b/src/Avalonia.Base/Media/TextFormatting/Unicode/BiDiData.cs index 9d76d56376..65c348e928 100644 --- a/src/Avalonia.Base/Media/TextFormatting/Unicode/BiDiData.cs +++ b/src/Avalonia.Base/Media/TextFormatting/Unicode/BiDiData.cs @@ -18,17 +18,12 @@ namespace Avalonia.Media.TextFormatting.Unicode private ArrayBuilder _savedClasses; private ArrayBuilder _savedPairedBracketTypes; private ArrayBuilder _tempLevelBuffer; - - public BidiData(sbyte paragraphEmbeddingLevel = 0) + + public BidiData(sbyte paragraphEmbeddingLevel) { ParagraphEmbeddingLevel = paragraphEmbeddingLevel; } - public BidiData(ReadOnlySlice text, sbyte paragraphEmbeddingLevel = 0) : this(paragraphEmbeddingLevel) - { - Append(text); - } - public sbyte ParagraphEmbeddingLevel { get; private set; } public bool HasBrackets { get; private set; } @@ -64,13 +59,23 @@ namespace Avalonia.Media.TextFormatting.Unicode /// public ArraySlice PairedBracketValues { get; private set; } + /// + /// Appends text to the bidi data. + /// + /// The text to process. public void Append(ReadOnlySlice text) { _classes.Add(text.Length); _pairedBracketTypes.Add(text.Length); _pairedBracketValues.Add(text.Length); - var i = Length; + // Resolve the BidiCharacterType, paired bracket type and paired + // bracket values for all code points + HasBrackets = false; + HasEmbeddings = false; + HasIsolates = false; + + int i = Length; var codePointEnumerator = new CodepointEnumerator(text); @@ -115,13 +120,13 @@ namespace Avalonia.Media.TextFormatting.Unicode // Opening bracket types can never have a null pairing. codepoint.TryGetPairedBracket(out var paired); - _pairedBracketValues[i] = Codepoint.GetCanonicalType(paired).Value; + _pairedBracketValues[i] = (int)Codepoint.GetCanonicalType(paired).Value; HasBrackets = true; } else if (pbt == BidiPairedBracketType.Close) { - _pairedBracketValues[i] = Codepoint.GetCanonicalType(codepoint).Value; + _pairedBracketValues[i] = (int)Codepoint.GetCanonicalType(codepoint).Value; HasBrackets = true; } diff --git a/src/Avalonia.Base/Media/TextFormatting/Unicode/Codepoint.cs b/src/Avalonia.Base/Media/TextFormatting/Unicode/Codepoint.cs index 39440f6fcf..56a90f31ea 100644 --- a/src/Avalonia.Base/Media/TextFormatting/Unicode/Codepoint.cs +++ b/src/Avalonia.Base/Media/TextFormatting/Unicode/Codepoint.cs @@ -5,50 +5,52 @@ namespace Avalonia.Media.TextFormatting.Unicode { public readonly struct Codepoint { + private readonly uint _value; + /// /// The replacement codepoint that is used for non supported values. /// public static readonly Codepoint ReplacementCodepoint = new Codepoint('\uFFFD'); - public Codepoint(int value) + public Codepoint(uint value) { - Value = value; + _value = value; } /// /// Get the codepoint's value. /// - public int Value { get; } + public uint Value => _value; /// /// Gets the . /// - public GeneralCategory GeneralCategory => UnicodeData.GetGeneralCategory(Value); + public GeneralCategory GeneralCategory => UnicodeData.GetGeneralCategory(_value); /// /// Gets the . /// - public Script Script => UnicodeData.GetScript(Value); + public Script Script => UnicodeData.GetScript(_value); /// /// Gets the . /// - public BidiClass BiDiClass => UnicodeData.GetBiDiClass(Value); + public BidiClass BiDiClass => UnicodeData.GetBiDiClass(_value); /// /// Gets the . /// - public BidiPairedBracketType PairedBracketType => UnicodeData.GetBiDiPairedBracketType(Value); + public BidiPairedBracketType PairedBracketType => UnicodeData.GetBiDiPairedBracketType(_value); /// /// Gets the . /// - public LineBreakClass LineBreakClass => UnicodeData.GetLineBreakClass(Value); + public LineBreakClass LineBreakClass => UnicodeData.GetLineBreakClass(_value); /// /// Gets the . /// - public GraphemeBreakClass GraphemeBreakClass => UnicodeData.GetGraphemeClusterBreak(Value); + public GraphemeBreakClass GraphemeBreakClass => UnicodeData.GetGraphemeClusterBreak(_value); /// /// Determines whether this is a break char. @@ -60,7 +62,7 @@ namespace Avalonia.Media.TextFormatting.Unicode { get { - switch (Value) + switch (_value) { case '\u000A': case '\u000B': @@ -109,12 +111,12 @@ namespace Avalonia.Media.TextFormatting.Unicode [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static Codepoint GetCanonicalType(Codepoint codePoint) { - if (codePoint.Value == 0x3008) + if (codePoint._value == 0x3008) { return new Codepoint(0x2329); } - if (codePoint.Value == 0x3009) + if (codePoint._value == 0x3009) { return new Codepoint(0x232A); } @@ -141,19 +143,19 @@ namespace Avalonia.Media.TextFormatting.Unicode return false; } - codepoint = UnicodeData.GetBiDiPairedBracket(Value); + codepoint = UnicodeData.GetBiDiPairedBracket(_value); return true; } public static implicit operator int(Codepoint codepoint) { - return codepoint.Value; + return (int)codepoint._value; } public static implicit operator uint(Codepoint codepoint) { - return (uint)codepoint.Value; + return codepoint._value; } /// @@ -191,7 +193,7 @@ namespace Avalonia.Media.TextFormatting.Unicode if (0xDC00 <= low && low <= 0xDFFF) { count = 2; - return new Codepoint((hi - 0xD800) * 0x400 + (low - 0xDC00) + 0x10000); + return new Codepoint((uint)((hi - 0xD800) * 0x400 + (low - 0xDC00) + 0x10000)); } return ReplacementCodepoint; @@ -212,7 +214,7 @@ namespace Avalonia.Media.TextFormatting.Unicode if (0xD800 <= hi && hi <= 0xDBFF) { count = 2; - return new Codepoint((hi - 0xD800) * 0x400 + (low - 0xDC00) + 0x10000); + return new Codepoint((uint)((hi - 0xD800) * 0x400 + (low - 0xDC00) + 0x10000)); } return ReplacementCodepoint; @@ -220,5 +222,13 @@ namespace Avalonia.Media.TextFormatting.Unicode return new Codepoint(code); } + + /// + /// Returns if is between + /// and , inclusive. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool IsInRangeInclusive(Codepoint cp, uint lowerBound, uint upperBound) + => (cp._value - lowerBound) <= (upperBound - lowerBound); } } diff --git a/src/Avalonia.Base/Media/TextFormatting/Unicode/GraphemeBreak.cs b/src/Avalonia.Base/Media/TextFormatting/Unicode/GraphemeBreak.cs new file mode 100644 index 0000000000..6986b908a1 --- /dev/null +++ b/src/Avalonia.Base/Media/TextFormatting/Unicode/GraphemeBreak.cs @@ -0,0 +1,7 @@ +namespace Avalonia.Media.TextFormatting.Unicode +{ + internal static class GraphemeBreak + { + public static byte[] Data => new byte[0]; + } +} diff --git a/src/Avalonia.Base/Media/TextFormatting/Unicode/GraphemeBreak.trie.cs b/src/Avalonia.Base/Media/TextFormatting/Unicode/GraphemeBreak.trie.cs index 80158e9d7e..05b7d55ad3 100644 --- a/src/Avalonia.Base/Media/TextFormatting/Unicode/GraphemeBreak.trie.cs +++ b/src/Avalonia.Base/Media/TextFormatting/Unicode/GraphemeBreak.trie.cs @@ -1,31 +1,409 @@ using System; - namespace Avalonia.Media.TextFormatting.Unicode { internal static class GraphemeBreakTrie { public static ReadOnlySpan Data => new byte[] { - 0,14,16,0,0,0,0,0,0,0,133,64,0,245,7,10,248,236,157,127,136,29,87,21,199,103,157,111,246,157,100,211,138,180,69,177,5,241,7,88,91,40,182,150,210,12,138,161,88,27,163,96,241,15,75,161,210,18,44,149,10,193,46,24,80,49,254,163,33,16,136,54,127,84,8,34,18,253,199,68,196,42,136,154,82,21,149,6,218,82,43,72,107,161,54,22,196,173,10,110, - 16,140,210,82,250,125,190,51,228,228,228,206,204,157,121,119,230,109,182,243,133,15,231,220,115,207,156,123,239,121,111,247,253,216,129,189,33,207,178,130,220,66,118,147,61,228,126,19,43,230,180,171,228,139,100,31,217,31,145,127,128,28,174,153,63,66,142,146,99,228,56,249,49,249,5,249,21,57,101,242,158,36,127,36,207,145,23,201,26,89,39,255,34,103,201,43,4,200,178,47, - 147,175,146,131,152,93,91,242,40,217,206,216,55,200,17,114,148,28,35,199,201,9,242,19,114,146,252,134,252,150,60,65,158,54,227,63,145,191,104,254,75,228,140,94,255,63,242,32,89,218,50,91,103,43,237,25,218,55,109,57,87,255,205,244,223,166,227,119,211,190,135,92,110,214,47,152,127,61,99,103,39,51,127,7,253,157,90,175,32,31,162,255,49,29,223,78,123,135,250,119, - 211,222,71,246,146,255,154,243,238,227,120,63,57,64,14,155,58,5,185,82,206,241,46,229,26,242,126,165,48,185,69,13,95,143,204,43,18,243,16,207,243,16,121,158,231,125,94,207,252,45,142,191,87,246,7,231,231,95,193,248,247,93,15,30,118,227,194,240,51,157,251,37,237,99,234,239,37,47,235,252,83,140,253,129,60,71,78,147,53,178,174,121,103,213,190,26,168,143,101,62, - 255,150,47,140,151,172,146,203,107,230,139,72,62,201,243,223,165,61,184,201,196,247,146,7,106,206,93,140,100,125,247,224,42,247,248,158,12,60,7,138,4,252,213,252,12,188,61,193,115,170,24,201,198,30,100,99,15,242,177,7,99,15,178,177,7,249,216,131,177,7,217,216,131,124,236,193,216,131,108,236,65,62,246,96,236,65,150,188,7,87,47,207,190,75,43,199,159,136,248,254, - 226,189,188,230,102,243,153,247,24,191,83,123,133,236,100,108,151,198,111,167,189,131,92,37,179,239,3,239,162,15,250,159,214,249,251,105,87,201,62,29,239,167,253,51,237,129,134,207,210,135,57,127,43,235,124,152,220,70,118,145,143,144,221,228,163,228,214,113,46,27,251,146,141,207,9,25,127,30,198,223,5,89,178,223,5,55,144,29,228,3,164,24,223,139,100,99,15,178,177,7, - 249,216,131,62,122,112,164,231,191,167,236,87,138,0,187,3,177,51,198,191,199,253,237,179,88,0,187,46,153,113,144,172,109,111,230,20,243,158,13,228,190,229,210,243,199,187,56,62,72,78,145,236,141,179,216,141,180,159,33,223,33,143,144,117,178,115,37,203,62,71,94,220,202,191,125,109,203,50,89,154,113,167,241,197,113,98,229,194,88,136,47,153,26,63,162,255,15,94,119,45, - 247,113,47,57,176,61,174,198,72,54,246,96,105,236,193,216,131,108,236,193,210,230,235,193,58,95,23,50,190,46,60,202,247,9,167,249,122,248,146,222,231,177,198,239,174,222,202,215,231,119,232,107,244,223,201,239,152,179,194,207,44,143,47,207,230,127,79,123,141,121,13,127,54,240,94,227,36,57,189,124,238,62,178,53,250,235,21,239,73,254,195,248,171,102,110,153,223,131,93,170, - 247,152,21,1,46,227,220,149,102,254,157,147,115,247,61,77,185,118,114,254,253,95,239,171,169,117,115,205,92,65,174,227,57,111,114,239,87,62,200,107,110,35,31,159,94,11,222,203,164,53,110,113,121,69,4,159,50,235,223,75,255,179,110,63,15,112,188,91,235,126,161,97,175,133,225,43,45,114,139,30,185,175,67,79,138,158,249,46,123,179,99,192,245,246,178,7,39,184,230,195, - 129,199,228,231,27,228,113,42,90,178,71,239,3,91,85,246,56,86,107,248,60,46,204,127,189,81,204,193,209,134,207,118,47,187,241,177,13,120,111,221,113,238,233,135,21,251,186,34,209,253,159,63,104,121,238,159,6,242,207,246,220,135,175,233,207,255,161,13,240,123,224,65,238,225,50,190,206,127,211,236,229,219,9,246,181,74,126,61,153,217,83,180,79,145,103,54,192,121,139,72, - 94,224,94,255,214,176,223,67,29,207,243,207,139,160,15,135,220,30,255,125,17,236,185,232,192,35,27,96,15,215,231,75,255,39,231,219,243,60,130,55,24,127,41,242,154,60,130,81,139,211,216,255,44,217,243,56,239,200,162,31,55,188,206,73,41,212,176,153,133,139,144,114,223,165,197,212,9,248,155,93,147,10,98,133,22,164,254,221,149,90,232,129,20,123,26,66,168,97,210,144, - 227,107,100,53,57,41,53,81,139,148,69,91,10,9,217,204,66,11,46,86,33,130,216,58,214,135,62,215,177,0,36,16,203,52,46,138,31,195,252,108,214,9,117,147,145,18,3,28,226,226,165,38,165,211,81,147,142,215,133,36,166,230,36,148,16,56,87,121,29,166,206,156,130,214,18,199,84,162,216,92,104,12,186,95,49,22,101,226,130,132,10,68,247,8,71,72,147,10,208,1, - 49,126,149,80,193,68,237,144,130,33,239,161,126,174,181,183,168,159,39,170,153,87,144,66,121,75,134,88,175,73,112,207,61,184,121,113,115,80,242,6,144,128,124,78,250,18,28,161,24,166,193,134,49,76,124,40,193,80,55,39,126,114,64,65,215,135,142,197,128,6,36,144,47,74,89,27,21,196,10,202,34,4,119,158,161,215,246,123,128,163,148,40,126,140,50,208,32,52,204,251, - 92,216,64,207,130,243,225,206,58,148,224,122,43,26,67,69,46,2,99,84,212,76,181,63,4,98,177,18,205,135,99,42,40,50,29,168,21,141,165,22,148,190,132,10,134,22,140,133,233,39,12,165,68,241,99,148,129,10,193,16,43,196,38,38,22,2,231,204,76,76,166,3,55,6,137,17,34,115,196,128,152,194,9,5,183,190,152,56,20,63,198,52,80,35,40,139,16,212,138,250, - 18,240,203,60,81,166,18,5,74,157,160,196,8,138,40,139,20,148,210,151,169,19,41,84,196,68,129,193,230,75,13,208,156,121,5,181,162,62,42,136,169,131,26,82,9,145,251,133,201,109,83,27,1,134,18,148,190,215,8,89,43,81,82,158,9,45,145,138,184,173,25,18,90,208,54,31,61,48,175,16,217,55,184,124,113,185,125,74,26,214,66,205,92,91,193,209,69,80,43,234, - 35,34,183,171,208,245,194,134,154,80,250,20,20,49,62,2,72,3,112,62,34,137,221,99,95,130,65,28,8,196,189,68,129,241,197,1,67,159,130,34,10,122,90,71,204,58,168,161,220,147,181,165,143,26,164,2,68,82,10,1,164,156,28,72,168,65,140,21,7,140,191,40,33,130,174,53,165,237,133,9,37,129,115,136,139,139,155,79,45,184,53,196,0,55,7,51,215,86,210,0, - 26,16,151,55,175,96,240,99,68,34,13,243,94,240,129,138,57,209,49,76,204,11,3,81,181,214,60,130,97,72,65,73,85,7,74,40,134,10,188,208,48,174,138,165,148,40,80,36,144,131,158,214,20,183,246,80,66,34,186,174,93,55,135,26,250,16,90,32,74,234,245,69,129,67,92,92,148,170,58,67,10,21,136,130,138,113,151,117,98,114,164,41,169,71,161,167,122,48,216,57, - 148,3,39,40,109,36,230,58,81,234,242,218,74,20,84,248,153,137,45,90,216,228,107,35,64,76,174,29,135,4,71,223,130,33,52,215,70,80,82,74,180,166,164,44,218,81,8,32,21,113,24,250,18,18,215,19,3,34,144,132,107,136,137,137,137,87,9,106,197,128,6,250,16,220,30,196,204,73,197,88,90,212,142,149,40,246,90,84,96,133,0,125,75,12,104,64,2,121,162,182, - 79,33,97,29,81,80,129,4,242,36,48,143,68,123,234,42,232,94,68,125,24,74,137,3,138,24,127,72,65,73,37,49,160,1,49,121,162,182,141,96,174,19,227,35,128,168,109,146,40,112,72,32,134,166,98,29,36,6,68,32,198,79,37,49,192,81,10,138,56,80,38,168,68,237,144,66,36,67,236,35,54,15,1,68,129,97,30,137,171,5,199,84,168,64,212,166,18,58,146,153, - 189,160,2,169,240,83,9,21,248,156,210,98,234,24,27,35,9,80,214,192,212,49,113,24,155,82,80,68,73,89,19,134,148,66,13,41,106,103,166,31,210,129,58,193,209,69,104,153,47,202,34,5,197,250,152,14,84,168,161,47,193,209,103,253,33,133,30,73,181,86,147,208,148,208,49,183,173,16,160,42,142,72,230,21,106,104,154,71,36,165,80,131,157,207,106,114,82,11,142,212, - 245,96,232,83,162,244,85,87,90,176,104,137,50,228,90,178,32,182,110,0,172,182,45,152,149,158,185,196,209,86,219,18,226,181,178,1,240,226,191,181,184,160,103,125,50,244,122,94,175,1,0,0,255,255,0,0,0,255,255,99,102,0,0}; + 0, 16, 14, 0, 0, 0, 0, 0, 144, 155, 0, 0, 89, 3, 0, 0, 97, 3, 0, 0, 105, 3, 0, 0, 113, 3, 0, 0, 137, 3, 0, 0, 145, 3, 0, 0, 97, 3, 0, 0, 105, 3, 0, 0, 97, 3, 0, 0, 105, 3, 0, 0, 97, 3, 0, 0, 105, 3, 0, 0, 97, 3, 0, 0, 105, 3, 0, 0, 97, 3, 0, 0, 105, 3, 0, 0, 97, 3, 0, 0, 105, 3, 0, 0, 97, 3, 0, 0, 105, 3, 0, 0, 97, 3, 0, 0, 105, 3, 0, 0, + 97, 3, 0, 0, 105, 3, 0, 0, 153, 3, 0, 0, 161, 3, 0, 0, 157, 3, 0, 0, 165, 3, 0, 0, 97, 3, 0, 0, 105, 3, 0, 0, 97, 3, 0, 0, 105, 3, 0, 0, 97, 3, 0, 0, 105, 3, 0, 0, 97, 3, 0, 0, 105, 3, 0, 0, 173, 3, 0, 0, 181, 3, 0, 0, 97, 3, 0, 0, 105, 3, 0, 0, 97, 3, 0, 0, 105, 3, 0, 0, 97, 3, 0, 0, 105, 3, 0, 0, 185, 3, 0, 0, 193, 3, 0, 0, 201, 3, 0, 0, + 209, 3, 0, 0, 217, 3, 0, 0, 225, 3, 0, 0, 231, 3, 0, 0, 239, 3, 0, 0, 97, 3, 0, 0, 105, 3, 0, 0, 244, 3, 0, 0, 252, 3, 0, 0, 1, 4, 0, 0, 9, 4, 0, 0, 15, 4, 0, 0, 23, 4, 0, 0, 22, 4, 0, 0, 30, 4, 0, 0, 35, 4, 0, 0, 43, 4, 0, 0, 176, 4, 0, 0, 183, 4, 0, 0, 187, 4, 0, 0, 97, 3, 0, 0, 51, 4, 0, 0, 97, 3, 0, 0, 194, 4, 0, 0, 59, 4, 0, 0, + 202, 4, 0, 0, 204, 4, 0, 0, 212, 4, 0, 0, 220, 4, 0, 0, 228, 4, 0, 0, 229, 4, 0, 0, 237, 4, 0, 0, 245, 4, 0, 0, 253, 4, 0, 0, 254, 4, 0, 0, 6, 5, 0, 0, 11, 5, 0, 0, 253, 4, 0, 0, 254, 4, 0, 0, 19, 5, 0, 0, 27, 5, 0, 0, 228, 4, 0, 0, 35, 5, 0, 0, 43, 5, 0, 0, 220, 4, 0, 0, 51, 5, 0, 0, 203, 4, 0, 0, 59, 5, 0, 0, 97, 3, 0, 0, 67, 5, 0, 0, + 35, 5, 0, 0, 75, 5, 0, 0, 220, 4, 0, 0, 228, 4, 0, 0, 81, 5, 0, 0, 89, 5, 0, 0, 220, 4, 0, 0, 97, 5, 0, 0, 99, 5, 0, 0, 67, 4, 0, 0, 220, 4, 0, 0, 228, 4, 0, 0, 97, 3, 0, 0, 107, 5, 0, 0, 88, 8, 0, 0, 97, 3, 0, 0, 115, 5, 0, 0, 122, 5, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 126, 5, 0, 0, 134, 5, 0, 0, 97, 3, 0, 0, 138, 5, 0, 0, 145, 5, 0, 0, + 97, 3, 0, 0, 153, 5, 0, 0, 161, 5, 0, 0, 168, 5, 0, 0, 50, 5, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 176, 5, 0, 0, 184, 5, 0, 0, 192, 5, 0, 0, 200, 5, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 124, 8, 0, 0, 124, 8, 0, 0, 124, 8, 0, 0, 133, 8, 0, 0, 133, 8, 0, 0, 139, 8, 0, 0, 157, 8, 0, 0, 157, 8, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 182, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 208, 5, 0, 0, 214, 5, 0, 0, 23, 5, 0, 0, 23, 5, 0, 0, 97, 3, 0, 0, 220, 5, 0, 0, 228, 5, 0, 0, 97, 3, 0, 0, 127, 4, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 79, 5, 0, 0, + 233, 5, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 241, 5, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 248, 5, 0, 0, 97, 3, 0, 0, 255, 5, 0, 0, 7, 6, 0, 0, 97, 3, 0, 0, 149, 3, 0, 0, 14, 4, 0, 0, 97, 3, 0, 0, 15, 6, 0, 0, 18, 6, 0, 0, 26, 6, 0, 0, 32, 6, 0, 0, 40, 6, 0, 0, 48, 6, 0, 0, + 97, 3, 0, 0, 55, 6, 0, 0, 97, 3, 0, 0, 62, 6, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 68, 6, 0, 0, 76, 6, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 153, 3, 0, 0, 153, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 133, 4, 0, 0, 139, 4, 0, 0, 94, 6, 0, 0, 93, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 149, 3, 0, 0, 171, 5, 0, 0, 97, 3, 0, 0, 180, 8, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 187, 8, 0, 0, 194, 8, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 197, 8, 0, 0, 204, 8, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 204, 8, 0, 0, 97, 3, 0, 0, 209, 8, 0, 0, 215, 8, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 223, 8, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 229, 8, 0, 0, 237, 8, 0, 0, 239, 8, 0, 0, 247, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 3, 9, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 10, 9, 0, 0, 17, 9, 0, 0, 24, 9, 0, 0, 32, 9, 0, 0, 35, 9, 0, 0, 43, 9, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 51, 9, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 58, 9, 0, 0, 97, 3, 0, 0, 66, 9, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 83, 6, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 226, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 153, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 89, 6, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 6, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 72, 9, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 104, 6, 0, 0, 24, 4, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 140, 5, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 112, 6, 0, 0, 120, 6, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 237, 7, 0, 0, 93, 8, 0, 0, 128, 6, 0, 0, 136, 6, 0, 0, 97, 3, 0, 0, 144, 6, 0, 0, 151, 6, 0, 0, 125, 8, 0, 0, 202, 4, 0, 0, 156, 6, 0, 0, 101, 8, 0, 0, 164, 6, 0, 0, 97, 3, 0, 0, 170, 6, 0, 0, 178, 6, 0, 0, 182, 6, 0, 0, 97, 3, 0, 0, 190, 6, 0, 0, 5, 4, 0, 0, 198, 6, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 206, 6, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, + 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, + 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, + 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, + 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, + 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, + 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, + 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, + 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, + 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, + 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, + 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, + 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, + 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 172, 8, 0, 0, 166, 8, 0, 0, 167, 8, 0, 0, 168, 8, 0, 0, + 169, 8, 0, 0, 170, 8, 0, 0, 171, 8, 0, 0, 147, 8, 0, 0, 154, 8, 0, 0, 158, 8, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 210, 6, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 165, 3, 0, 0, 165, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 113, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 24, 4, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 147, 4, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 228, 13, 0, 0, 228, 13, 0, 0, 36, 14, 0, 0, 132, 13, 0, 0, 132, 13, 0, 0, 132, 13, 0, 0, 132, 13, 0, 0, 132, 13, 0, 0, 132, 13, 0, 0, 132, 13, 0, 0, 132, 13, 0, 0, 132, 13, 0, 0, 100, 14, 0, 0, 116, 14, 0, 0, 132, 13, 0, 0, 132, 13, 0, 0, 132, 13, 0, 0, + 132, 13, 0, 0, 180, 14, 0, 0, 132, 13, 0, 0, 132, 13, 0, 0, 132, 13, 0, 0, 228, 14, 0, 0, 36, 15, 0, 0, 100, 15, 0, 0, 156, 15, 0, 0, 132, 13, 0, 0, 208, 15, 0, 0, 4, 16, 0, 0, 60, 16, 0, 0, 88, 16, 0, 0, 140, 16, 0, 0, 64, 11, 0, 0, 112, 11, 0, 0, 226, 9, 0, 0, 33, 10, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 89, 10, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, + 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 173, 11, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 123, 10, 0, 0, 149, 1, 0, 0, 237, 11, 0, 0, 176, 10, 0, 0, 40, 12, 0, 0, 104, 12, 0, 0, 162, 12, 0, 0, 226, 12, 0, 0, 34, 13, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, + 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, + 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, + 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, + 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, + 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, + 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, + 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, + 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, + 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, + 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, + 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, + 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, + 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, + 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, + 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, + 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 149, 1, 0, 0, 240, 10, 0, 0, 0, 11, 0, 0, 6, 7, 0, 0, 7, 4, 0, 0, 16, 4, 0, 0, 10, 7, 0, 0, 40, 6, 0, 0, 73, 4, 0, 0, 81, 4, 0, 0, 97, 3, 0, 0, 17, 4, 0, 0, 16, 7, 0, 0, 108, 8, 0, 0, 22, 7, 0, 0, 40, 6, 0, 0, 27, 7, 0, 0, 89, 4, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 35, 7, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 226, 3, 0, 0, 43, 7, 0, 0, 97, 5, 0, 0, 99, 5, 0, 0, 51, 7, 0, 0, 59, 7, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 65, 7, 0, 0, 73, 7, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 81, 7, 0, 0, 89, 7, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 94, 7, 0, 0, 102, 7, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 110, 7, 0, 0, 34, 4, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 118, 7, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 182, 3, 0, 0, 126, 7, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 131, 7, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 93, 4, 0, 0, 101, 4, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 138, 7, 0, 0, 146, 7, 0, 0, 154, 7, 0, 0, 105, 4, 0, 0, 161, 7, 0, 0, 97, 3, 0, 0, 113, 4, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 168, 7, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 176, 7, 0, 0, 182, 7, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 188, 7, 0, 0, 121, 4, 0, 0, 97, 3, 0, 0, 196, 7, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 202, 7, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 154, 4, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 238, 7, 0, 0, 96, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 161, 4, 0, 0, 254, 7, 0, 0, 252, 6, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 6, 8, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 137, 3, 0, 0, 153, 3, 0, 0, 153, 3, 0, 0, 153, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 153, 3, 0, 0, 153, 3, 0, 0, 153, 3, 0, 0, 153, 3, 0, 0, 153, 3, 0, 0, 153, 3, 0, 0, 153, 3, 0, 0, 168, 4, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, + 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, + 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, + 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 137, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 218, 6, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 34, 4, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 226, 6, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 234, 6, 0, 0, 238, 6, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 79, 5, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 236, 6, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 246, 6, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 30, 4, 0, 0, 97, 3, 0, 0, 254, 6, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 208, 7, 0, 0, 97, 3, 0, 0, 214, 7, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 220, 7, 0, 0, 116, 8, 0, 0, 226, 7, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 233, 7, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 153, 3, 0, 0, 246, 7, 0, 0, 16, 4, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 153, 3, 0, 0, 14, 8, 0, 0, 153, 3, 0, 0, 21, 8, 0, 0, 28, 8, 0, 0, 36, 8, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 44, 8, 0, 0, 52, 8, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 214, 7, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 214, 6, 0, 0, 97, 3, 0, 0, 57, 8, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 214, 7, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 64, 8, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, + 97, 3, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 79, 9, 0, 0, 209, 8, 0, 0, 97, 3, 0, 0, 84, 9, 0, 0, 92, 9, 0, 0, 99, 9, 0, 0, 252, 8, 0, 0, 80, 8, 0, 0, 107, 9, 0, 0, 114, 9, 0, 0, 122, 9, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, + 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 72, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 253, 8, 0, 0, 130, 9, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, + 252, 8, 0, 0, 134, 9, 0, 0, 97, 3, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 67, 8, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 138, 9, 0, 0, 252, 8, 0, 0, 146, 9, 0, 0, 97, 3, 0, 0, 152, 9, 0, 0, 97, 3, 0, 0, 160, 9, 0, 0, 165, 9, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 69, 8, 0, 0, 169, 9, 0, 0, + 176, 9, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 97, 3, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, + 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, + 252, 8, 0, 0, 252, 8, 0, 0, 252, 8, 0, 0, 253, 8, 0, 0, 88, 3, 1, 0, 88, 3, 1, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 7, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 8, 0, 0, 0, 4, 0, 0, 0, 7, 0, 0, 0, 8, 0, 0, 0, 7, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 7, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 7, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, + 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, + 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, + 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, + 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, + 8, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, + 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, + 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, + 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, + 8, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 8, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, + 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, + 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, + 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, + 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, + 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, + 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, + 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, + 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, + 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, + 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, + 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, + 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 12, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, + 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, + 14, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, + 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, + 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, + 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, + 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, + 14, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, + 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, + 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, + 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, + 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, + 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, + 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }; } } diff --git a/src/Avalonia.Base/Media/TextFormatting/Unicode/LineBreakClass.cs b/src/Avalonia.Base/Media/TextFormatting/Unicode/LineBreakClass.cs index 8b2e3f41e3..bd77c398bd 100644 --- a/src/Avalonia.Base/Media/TextFormatting/Unicode/LineBreakClass.cs +++ b/src/Avalonia.Base/Media/TextFormatting/Unicode/LineBreakClass.cs @@ -35,7 +35,6 @@ namespace Avalonia.Media.TextFormatting.Unicode EModifier, //EM ZWJ, //ZWJ ContingentBreak, //CB - Unknown, //XX Ambiguous, //AI MandatoryBreak, //BK diff --git a/src/Avalonia.Base/Media/TextFormatting/Unicode/LineBreakEnumerator.cs b/src/Avalonia.Base/Media/TextFormatting/Unicode/LineBreakEnumerator.cs index 0f6b81975a..e12a7c06f1 100644 --- a/src/Avalonia.Base/Media/TextFormatting/Unicode/LineBreakEnumerator.cs +++ b/src/Avalonia.Base/Media/TextFormatting/Unicode/LineBreakEnumerator.cs @@ -450,6 +450,20 @@ namespace Avalonia.Media.TextFormatting.Unicode _lb30a = 0; } + // Rule LB30b + if (_nextClass == LineBreakClass.EModifier && _lastPosition > 0) + { + // Mahjong Tiles (Unicode block) are extended pictographics but have a class of ID + // Unassigned codepoints with Line_Break=ID in some blocks are also assigned the Extended_Pictographic property. + // Those blocks are intended for future allocation of emoji characters. + var cp = Codepoint.ReadAt(_text, _lastPosition - 1, out int _); + + if (Codepoint.IsInRangeInclusive(cp, 0x1F000, 0x1F02F)) + { + shouldBreak = false; + } + } + _currentClass = _nextClass; return shouldBreak; diff --git a/src/Avalonia.Base/Media/TextFormatting/Unicode/Script.cs b/src/Avalonia.Base/Media/TextFormatting/Unicode/Script.cs index 2593a77848..bc14c2563c 100644 --- a/src/Avalonia.Base/Media/TextFormatting/Unicode/Script.cs +++ b/src/Avalonia.Base/Media/TextFormatting/Unicode/Script.cs @@ -30,6 +30,7 @@ namespace Avalonia.Media.TextFormatting.Unicode Cherokee, //Cher Chorasmian, //Chrs Coptic, //Copt + CyproMinoan, //Cpmn Cypriot, //Cprt Cyrillic, //Cyrl Devanagari, //Deva @@ -109,6 +110,7 @@ namespace Avalonia.Media.TextFormatting.Unicode Oriya, //Orya Osage, //Osge Osmanya, //Osma + OldUyghur, //Ougr Palmyrene, //Palm PauCinHau, //Pauc OldPermic, //Perm @@ -151,8 +153,11 @@ namespace Avalonia.Media.TextFormatting.Unicode Thai, //Thai Tibetan, //Tibt Tirhuta, //Tirh + Tangsa, //Tnsa + Toto, //Toto Ugaritic, //Ugar Vai, //Vaii + Vithkuqi, //Vith WarangCiti, //Wara Wancho, //Wcho OldPersian, //Xpeo diff --git a/src/Avalonia.Base/Media/TextFormatting/Unicode/UnicodeData.cs b/src/Avalonia.Base/Media/TextFormatting/Unicode/UnicodeData.cs index ff39dc5011..0142a20790 100644 --- a/src/Avalonia.Base/Media/TextFormatting/Unicode/UnicodeData.cs +++ b/src/Avalonia.Base/Media/TextFormatting/Unicode/UnicodeData.cs @@ -36,29 +36,9 @@ namespace Avalonia.Media.TextFormatting.Unicode static UnicodeData() { - unsafe - { - var unicodeData = UnicodeDataTrie.Data; - - fixed (byte* unicodeDataPtr = unicodeData) - { - s_unicodeDataTrie = new UnicodeTrie(new UnmanagedMemoryStream(unicodeDataPtr, unicodeData.Length)); - } - - var graphemeData = GraphemeBreakTrie.Data; - - fixed (byte* graphemeDataPtr = graphemeData) - { - s_graphemeBreakTrie = new UnicodeTrie(new UnmanagedMemoryStream(graphemeDataPtr, graphemeData.Length)); - } - - var bidiData = BiDiTrie.Data; - - fixed (byte* bidiDataPtr = bidiData) - { - s_biDiTrie = new UnicodeTrie(new UnmanagedMemoryStream(bidiDataPtr, bidiData.Length)); - } - } + s_unicodeDataTrie = new UnicodeTrie(UnicodeDataTrie.Data); + s_graphemeBreakTrie = new UnicodeTrie(GraphemeBreakTrie.Data); + s_biDiTrie = new UnicodeTrie(BidiTrie.Data); } /// @@ -67,7 +47,7 @@ namespace Avalonia.Media.TextFormatting.Unicode /// The codepoint in question. /// The code point's general category. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static GeneralCategory GetGeneralCategory(int codepoint) + public static GeneralCategory GetGeneralCategory(uint codepoint) { return (GeneralCategory)(s_unicodeDataTrie.Get(codepoint) & CATEGORY_MASK); } @@ -78,7 +58,7 @@ namespace Avalonia.Media.TextFormatting.Unicode /// The codepoint in question. /// The code point's script. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Script GetScript(int codepoint) + public static Script GetScript(uint codepoint) { return (Script)((s_unicodeDataTrie.Get(codepoint) >> SCRIPT_SHIFT) & SCRIPT_MASK); } @@ -89,7 +69,7 @@ namespace Avalonia.Media.TextFormatting.Unicode /// The codepoint in question. /// The code point's biDi class. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static BidiClass GetBiDiClass(int codepoint) + public static BidiClass GetBiDiClass(uint codepoint) { return (BidiClass)((s_biDiTrie.Get(codepoint) >> BIDICLASS_SHIFT) & BIDICLASS_MASK); } @@ -100,7 +80,7 @@ namespace Avalonia.Media.TextFormatting.Unicode /// The codepoint in question. /// The code point's paired bracket type. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static BidiPairedBracketType GetBiDiPairedBracketType(int codepoint) + public static BidiPairedBracketType GetBiDiPairedBracketType(uint codepoint) { return (BidiPairedBracketType)((s_biDiTrie.Get(codepoint) >> BIDIPAIREDBRACKEDTYPE_SHIFT) & BIDIPAIREDBRACKEDTYPE_MASK); } @@ -111,9 +91,9 @@ namespace Avalonia.Media.TextFormatting.Unicode /// The codepoint in question. /// The code point's paired bracket. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Codepoint GetBiDiPairedBracket(int codepoint) + public static Codepoint GetBiDiPairedBracket(uint codepoint) { - return new Codepoint((int)(s_biDiTrie.Get(codepoint) & BIDIPAIREDBRACKED_MASK)); + return new Codepoint((s_biDiTrie.Get(codepoint) & BIDIPAIREDBRACKED_MASK)); } /// @@ -122,7 +102,7 @@ namespace Avalonia.Media.TextFormatting.Unicode /// The codepoint in question. /// The code point's line break class. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static LineBreakClass GetLineBreakClass(int codepoint) + public static LineBreakClass GetLineBreakClass(uint codepoint) { return (LineBreakClass)((s_unicodeDataTrie.Get(codepoint) >> LINEBREAK_SHIFT) & LINEBREAK_MASK); } @@ -133,7 +113,7 @@ namespace Avalonia.Media.TextFormatting.Unicode /// The codepoint in question. /// The code point's grapheme break type. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static GraphemeBreakClass GetGraphemeClusterBreak(int codepoint) + public static GraphemeBreakClass GetGraphemeClusterBreak(uint codepoint) { return (GraphemeBreakClass)s_graphemeBreakTrie.Get(codepoint); } diff --git a/src/Avalonia.Base/Media/TextFormatting/Unicode/UnicodeData.trie.cs b/src/Avalonia.Base/Media/TextFormatting/Unicode/UnicodeData.trie.cs index dd55fda374..6ef41e3a0b 100644 --- a/src/Avalonia.Base/Media/TextFormatting/Unicode/UnicodeData.trie.cs +++ b/src/Avalonia.Base/Media/TextFormatting/Unicode/UnicodeData.trie.cs @@ -1,122 +1,1086 @@ using System; - namespace Avalonia.Media.TextFormatting.Unicode { - internal static class UnicodeDataTrie + internal static class UnicodeDataTrie { public static ReadOnlySpan Data => new byte[] { - 0,16,0,0,0,0,0,0,0,1,154,144,0,161,43,94,212,236,157,15,148,28,85,157,239,107,230,215,147,204,84,146,78,103,152,252,115,128,16,8,241,224,234,238,193,197,221,163,139,231,117,2,132,158,162,51,52,67,155,63,244,152,233,66,130,202,81,247,225,209,221,167,7,125,13,139,74,202,48,84,134,89,16,199,5,70,81,244,249,111,117,209,93,93,229,5,68,157,41,218, - 177,9,35,168,3,72,16,124,60,149,125,111,87,217,231,62,193,247,190,53,117,59,115,231,166,254,220,234,170,234,10,58,57,231,147,223,253,255,251,221,63,117,235,214,173,59,213,151,100,20,101,47,208,193,91,193,181,224,0,56,4,110,3,147,224,51,224,139,224,31,193,127,7,223,5,223,7,143,130,199,193,51,224,57,240,60,248,13,80,186,20,165,27,228,192,6,112,26,56,19, - 188,10,188,6,188,30,108,7,26,24,2,151,129,125,224,74,240,14,240,87,224,253,224,131,224,58,96,128,155,192,173,224,239,192,39,193,231,193,87,192,55,193,183,193,247,192,15,192,143,193,83,224,25,240,28,120,30,188,8,104,153,162,172,0,39,129,126,112,6,248,35,240,185,94,69,249,83,200,191,0,231,129,29,96,16,148,193,59,215,41,202,217,39,33,30,252,5,184,7,105, - 135,17,126,57,184,202,142,95,166,40,239,5,53,112,3,48,193,71,192,237,224,83,224,11,224,171,224,27,224,1,80,7,179,224,49,240,52,248,5,248,21,248,15,208,177,92,81,122,192,26,176,30,108,2,47,7,127,2,206,131,238,63,135,252,79,224,66,48,8,118,129,125,224,74,112,21,120,231,114,199,246,247,66,94,11,14,48,255,69,200,251,94,212,227,16,252,183,128,219,193, - 39,193,231,89,252,165,136,223,11,116,240,86,112,53,184,100,13,218,22,241,23,160,190,239,129,255,61,140,107,25,31,2,7,24,135,24,223,92,238,200,111,67,78,131,135,152,255,81,38,31,135,124,6,60,7,246,162,252,189,224,121,184,111,67,220,71,99,226,14,240,34,202,188,27,242,110,208,213,173,40,171,192,90,112,10,56,19,124,17,225,95,6,175,130,251,53,224,245,224,235, - 240,127,3,117,189,0,238,251,224,222,217,237,148,119,9,228,94,160,131,183,130,119,128,105,132,255,21,228,53,96,207,6,69,185,30,242,33,132,29,132,28,7,31,3,119,129,207,117,59,237,251,35,196,61,102,143,157,110,232,0,79,195,253,75,240,107,240,0,252,47,64,214,33,103,193,3,176,225,49,200,39,193,179,224,127,131,127,197,245,180,19,225,117,240,6,123,252,245,34,109, - 175,115,93,253,166,219,185,62,121,244,53,139,253,74,15,108,71,88,6,114,37,184,2,121,251,32,79,6,91,192,107,215,43,202,54,48,0,94,9,255,57,160,128,122,157,11,121,62,184,26,121,223,3,174,5,22,198,81,17,97,159,66,218,207,130,47,129,175,129,251,192,52,120,8,252,8,60,9,158,5,207,129,171,193,123,64,21,101,62,15,249,34,200,192,221,3,214,108,112,194, - 47,69,153,21,240,12,202,255,25,120,11,194,222,2,158,227,220,111,7,87,131,247,128,141,96,51,56,11,92,11,14,128,67,224,108,48,6,62,10,62,14,254,27,248,50,211,241,85,91,255,58,69,249,237,58,199,127,45,236,184,1,220,11,247,189,62,60,203,234,242,44,195,100,242,86,112,187,16,247,172,11,85,148,241,90,144,7,111,178,251,162,199,9,107,114,0,237,122,53,194, - 222,13,14,193,125,27,199,251,16,246,54,244,215,7,32,51,125,138,242,97,200,155,193,4,227,58,212,229,173,208,241,24,210,124,162,199,25,111,159,133,252,14,202,253,142,93,247,158,5,183,200,215,17,119,24,60,141,188,191,4,83,112,175,132,142,6,100,31,228,201,224,215,8,255,33,252,143,129,45,240,111,1,71,225,126,37,228,140,221,54,61,24,163,128,96,67,15,120,100,131, - 227,94,3,158,128,251,41,240,115,198,47,55,56,121,68,206,65,89,231,44,161,44,181,129,178,212,6,125,242,109,208,156,63,206,9,145,231,156,37,148,165,54,80,150,218,160,111,169,13,150,218,64,89,106,131,190,165,54,88,106,3,101,169,13,250,254,48,219,224,55,120,118,123,1,207,120,231,194,125,238,9,130,162,226,185,19,235,218,229,144,25,236,141,156,143,176,243,125,88,137, - 52,171,85,103,239,112,18,207,204,159,1,69,132,23,193,122,132,247,33,254,75,108,79,228,171,144,247,130,7,192,38,196,157,14,202,72,247,10,200,97,200,87,67,94,1,249,102,240,58,184,255,18,242,175,193,251,193,118,248,53,240,65,184,13,48,4,247,101,96,12,238,203,33,175,2,39,219,251,80,125,216,23,0,239,132,255,189,224,58,96,128,119,161,157,15,65,94,3,121,13, - 248,20,210,220,6,255,23,32,191,8,254,30,124,9,124,25,252,3,184,7,124,97,41,78,89,106,23,101,105,76,244,45,93,15,75,115,129,18,219,92,48,137,121,247,211,224,179,224,106,220,23,174,78,17,29,123,165,122,138,236,93,66,89,106,3,101,169,13,214,187,183,65,152,245,244,63,168,11,238,127,132,251,94,240,29,48,3,30,81,157,247,212,54,223,64,252,19,156,255,219, - 1,60,128,244,218,50,199,253,83,150,239,127,66,62,7,158,183,215,151,235,240,94,13,178,107,197,226,124,43,224,63,9,212,177,222,189,30,107,206,45,88,159,158,5,250,17,118,6,248,163,21,233,206,61,54,15,176,245,120,6,246,157,223,235,216,105,191,139,125,193,126,46,57,9,235,102,112,15,120,18,156,134,118,168,130,113,48,11,186,215,226,93,37,248,47,224,159,192,111,64, - 55,218,226,92,240,46,112,15,248,53,56,7,122,222,2,198,193,44,88,137,231,139,34,56,104,239,161,171,138,114,39,120,18,156,134,246,168,130,15,131,7,153,124,142,201,15,115,188,106,37,222,215,195,230,14,240,118,184,63,191,114,113,188,205,115,8,91,181,106,193,191,19,238,27,193,247,192,170,44,252,224,70,112,103,71,188,124,143,149,217,181,26,239,179,87,59,238,18,147,119, - 50,62,8,255,167,192,207,184,240,173,57,39,172,157,108,203,29,223,110,75,40,75,109,176,98,169,13,150,218,64,249,131,104,131,107,83,158,3,21,156,151,82,82,226,190,92,186,207,94,39,2,127,138,62,120,29,216,190,194,57,191,83,199,186,166,206,208,16,54,4,222,0,142,96,29,243,3,240,70,184,247,131,17,236,221,190,157,229,217,193,241,238,21,206,218,232,125,144,31,0, - 143,193,125,35,228,223,130,219,192,36,120,26,97,159,97,121,103,177,134,249,49,56,104,159,3,234,195,115,50,194,191,6,190,9,190,5,126,221,231,172,133,94,128,60,226,162,47,131,53,87,38,128,31,35,223,83,224,231,46,249,255,13,97,207,131,23,193,74,164,237,178,215,77,43,157,184,181,144,167,128,51,153,127,7,232,91,235,172,191,94,3,54,98,45,247,122,200,243,65,17, - 156,140,184,45,107,157,116,175,132,44,35,236,28,200,97,200,43,192,219,192,187,192,53,92,121,231,34,254,92,112,61,11,123,202,110,139,149,88,43,162,61,198,33,207,71,220,199,184,244,59,124,184,11,233,138,72,255,57,46,125,25,254,123,224,255,103,46,236,126,184,167,193,67,96,24,241,251,192,143,224,126,18,92,9,247,85,224,89,184,255,5,188,19,238,127,135,252,29,232,196, - 218,241,189,240,191,31,124,16,168,240,247,130,245,171,22,202,222,4,247,203,193,40,226,255,4,242,207,193,235,193,5,171,156,53,168,104,243,45,72,119,27,120,3,226,222,8,38,225,254,36,216,239,146,118,7,248,60,226,222,142,184,119,179,248,175,192,255,53,240,62,248,63,0,238,91,235,172,115,255,150,197,255,29,228,39,61,202,218,1,166,145,254,243,66,252,207,209,7,31,67, - 251,127,5,225,223,4,223,2,15,114,105,30,134,251,81,240,19,240,16,242,255,0,252,15,184,31,135,252,41,248,95,112,255,2,242,255,248,232,221,193,248,127,72,147,193,154,121,37,56,9,108,0,167,102,23,226,183,194,253,10,240,106,240,58,144,7,5,46,126,135,15,37,143,116,187,17,190,25,99,119,4,242,87,176,243,87,109,228,205,130,77,143,99,78,121,156,241,151,62,246, - 252,181,100,157,119,252,30,243,91,180,195,111,99,224,69,38,187,214,121,167,177,159,99,127,235,18,254,95,79,128,126,200,193,182,92,11,172,21,252,31,106,177,46,69,220,139,138,17,185,9,186,111,5,119,112,54,124,2,238,79,131,83,96,219,102,240,247,112,255,19,56,156,80,155,255,27,230,185,187,236,179,183,217,197,225,103,65,247,89,160,129,240,175,67,62,194,197,63,1,247, - 217,8,59,251,15,148,159,181,161,254,175,109,145,127,97,253,244,239,66,127,238,136,153,109,208,181,221,135,223,49,253,203,176,199,178,10,104,8,211,36,89,179,58,126,123,227,102,8,118,14,49,54,194,222,83,193,214,54,218,93,229,206,239,87,5,254,120,181,35,255,140,201,49,216,248,81,112,231,58,199,127,46,194,95,128,124,1,156,239,98,115,145,229,171,130,50,220,195,46,105, - 254,175,189,247,216,139,53,237,106,103,223,244,109,144,239,2,215,128,223,217,123,189,171,177,134,5,227,128,16,191,162,119,33,207,139,108,175,117,37,248,45,220,157,189,78,158,9,164,237,131,251,100,112,6,120,5,88,15,54,129,173,224,85,224,19,72,115,63,234,145,217,24,141,79,163,140,207,174,115,228,151,109,247,106,236,157,175,78,127,92,201,242,207,176,245,91,62,246,94,134, - 58,61,136,248,135,67,214,233,114,228,155,123,9,180,195,85,176,243,42,23,126,202,108,127,13,198,202,235,193,47,218,80,151,95,65,199,89,88,75,255,134,211,165,96,95,161,43,231,157,103,21,226,214,130,83,192,153,224,85,224,53,44,253,185,62,249,118,48,102,236,107,55,183,240,55,44,5,184,75,160,12,246,130,179,237,119,12,27,157,191,91,234,101,82,207,57,239,131,222,2, - 249,159,193,187,192,53,224,122,22,126,47,199,140,240,55,50,47,67,25,167,131,87,128,18,23,254,106,248,95,11,182,129,129,141,11,225,151,192,189,7,236,3,186,173,127,163,19,254,14,200,119,51,247,12,184,6,238,26,243,223,0,121,16,182,140,231,156,185,167,201,199,56,255,93,112,127,14,220,195,194,190,206,228,253,144,223,229,234,97,162,172,143,176,114,191,207,218,233,78,248, - 31,97,238,42,87,246,19,224,103,224,151,224,95,89,25,85,97,78,253,15,166,167,210,227,188,115,225,219,234,222,54,211,179,38,253,115,123,73,177,134,181,237,57,39,128,45,231,36,204,198,53,254,237,144,180,254,115,78,96,54,167,92,255,179,82,190,198,239,61,1,56,39,166,107,249,222,151,32,61,109,28,127,103,191,132,219,233,222,152,218,250,181,224,18,172,89,46,97,236,16, - 214,59,27,216,119,28,54,184,176,109,205,241,233,95,106,236,245,56,251,179,247,15,128,129,53,233,239,233,164,77,41,211,113,140,109,249,46,9,50,202,182,90,143,178,237,112,183,67,30,110,169,124,93,129,236,175,169,74,165,214,161,84,14,99,189,171,144,178,47,223,9,63,128,187,130,176,97,60,222,236,169,57,113,85,59,78,233,84,118,43,153,121,89,57,220,161,12,29,238,148, - 162,98,167,87,58,149,170,93,142,226,48,175,87,33,156,23,107,15,118,93,42,168,195,30,212,103,4,122,119,129,17,48,133,184,169,54,48,12,253,85,244,229,158,60,36,244,110,67,251,255,161,255,219,230,54,46,15,199,55,190,131,216,175,216,99,16,207,174,24,243,251,48,54,246,49,116,244,79,165,214,173,140,0,29,110,235,80,183,114,217,97,167,223,182,163,15,117,54,118,116, - 228,171,34,125,25,233,202,243,233,51,74,129,229,173,176,252,101,96,33,255,94,228,47,51,127,217,142,87,236,179,146,201,141,247,42,116,212,125,226,167,18,166,10,253,83,1,105,234,191,231,114,42,166,52,245,19,88,214,125,234,53,229,147,166,46,184,235,46,121,234,33,242,76,5,164,159,10,136,155,146,212,85,119,73,51,5,44,23,123,44,129,58,120,144,203,255,160,135,123,42, - 130,156,138,177,127,167,124,108,171,199,168,167,126,130,200,41,15,234,62,253,94,119,105,147,122,68,125,83,47,17,172,54,235,155,150,96,0,247,223,129,0,70,4,6,108,106,221,32,195,100,247,98,191,194,165,113,201,63,210,164,230,220,243,143,161,176,176,121,153,113,181,119,196,142,83,22,179,41,227,208,212,53,32,196,143,180,136,137,53,143,185,132,50,223,6,74,135,35,243,33, - 176,243,40,30,132,41,39,239,80,92,65,74,1,20,153,28,176,251,105,197,130,159,176,70,36,48,192,252,5,70,5,207,82,69,46,158,24,35,43,156,126,182,227,42,76,22,25,132,248,34,39,139,172,172,98,12,16,87,102,209,135,66,130,20,5,119,209,69,103,81,82,214,151,97,190,1,245,144,178,224,161,175,234,210,222,5,183,246,95,254,210,166,144,50,197,19,68,234,160,116, - 97,215,60,38,187,214,75,112,95,204,40,158,32,118,22,19,144,197,22,243,22,78,16,251,11,17,36,97,30,92,217,73,109,129,216,156,223,3,119,191,7,221,39,0,253,157,157,202,250,237,153,99,246,110,70,216,102,112,234,246,206,121,127,110,103,215,75,142,245,59,51,243,178,127,21,29,11,235,231,221,55,118,204,75,18,238,207,36,160,238,164,182,65,1,186,251,97,127,255,170, - 227,211,249,113,93,7,29,199,118,196,220,9,121,39,99,226,218,206,121,110,7,21,172,91,38,58,58,149,73,132,79,2,115,27,230,70,73,42,216,47,190,14,146,160,119,226,90,236,219,193,111,160,12,35,69,6,20,249,180,205,251,128,41,195,54,57,198,238,235,148,98,194,238,131,251,24,130,77,70,202,109,104,156,64,76,96,92,25,1,227,114,187,226,63,118,15,32,238,0,23, - 63,233,146,214,96,250,198,208,31,99,18,24,156,141,147,12,195,182,119,115,107,216,215,208,117,144,6,48,117,216,195,220,70,155,49,161,219,140,9,98,115,146,193,235,232,120,105,163,109,57,49,41,93,129,245,172,36,26,210,83,136,123,10,113,28,249,97,167,20,214,6,236,69,165,76,99,79,87,32,211,72,55,13,142,130,185,121,58,149,185,143,116,204,135,17,171,115,3,233,158, - 216,211,57,79,227,141,200,199,49,125,10,244,248,248,27,12,98,101,205,33,126,174,69,8,249,181,62,244,119,194,148,202,24,39,12,98,118,87,16,78,226,181,188,217,31,59,61,165,140,145,192,28,64,33,202,165,16,182,154,146,107,12,147,191,111,17,230,236,243,186,148,81,6,217,182,17,116,251,64,205,182,33,119,127,88,40,32,47,177,120,226,251,133,220,109,178,235,98,192,63, - 202,213,201,20,32,150,118,148,171,51,113,126,147,149,65,1,237,61,202,229,37,151,54,49,56,251,76,65,247,216,183,176,14,144,192,96,249,111,255,27,172,183,193,56,220,227,34,127,131,245,183,157,230,60,39,253,4,211,71,205,249,231,34,204,33,96,6,16,252,22,246,165,44,23,72,168,139,37,132,91,30,249,172,0,40,32,47,9,186,44,15,55,177,186,16,228,12,171,207,12, - 171,91,131,133,19,71,67,8,111,120,164,109,184,228,37,151,118,176,4,187,200,239,62,247,32,238,99,18,52,152,61,22,87,126,3,254,185,128,242,137,191,238,47,194,216,2,163,128,236,113,183,2,99,38,0,18,210,145,100,62,67,162,44,195,39,158,60,210,18,87,23,3,254,81,86,159,81,86,55,83,128,92,234,61,202,165,167,230,245,184,34,218,125,196,206,111,0,83,40,119, - 12,125,55,38,193,4,242,222,126,145,179,47,226,167,195,244,169,103,238,178,46,37,203,32,248,213,151,225,249,222,7,98,229,170,30,126,53,36,20,144,151,4,93,170,143,77,57,212,65,133,63,11,153,99,117,202,9,16,75,155,229,234,76,156,63,199,133,145,11,57,174,108,18,226,84,15,59,115,66,185,189,63,238,148,98,51,203,223,231,1,73,142,179,198,229,152,3,78,103,115, - 11,164,229,2,241,115,210,233,139,195,101,210,18,115,147,16,70,46,233,200,67,15,185,132,91,18,144,80,223,25,212,119,6,52,152,156,1,228,18,63,195,194,103,56,127,131,75,107,185,148,77,92,25,36,217,254,71,158,194,124,44,193,44,244,205,50,142,122,240,196,229,157,243,146,220,230,234,55,97,142,226,48,129,113,6,230,24,31,200,158,35,206,240,246,135,133,34,230,55,88, - 25,212,156,191,206,192,252,197,234,98,10,245,27,5,196,234,109,50,72,240,155,44,140,60,48,185,52,6,116,25,12,114,155,75,207,112,226,248,60,100,207,215,63,197,124,44,1,249,216,49,241,137,140,50,142,178,199,61,152,4,86,14,247,239,18,198,41,99,206,204,204,135,89,62,144,61,142,115,222,254,176,80,136,252,228,145,150,154,243,82,9,243,18,252,51,144,13,48,227,2, - 177,116,51,156,127,134,185,27,12,242,105,215,25,46,31,121,96,9,182,54,132,114,143,52,112,125,74,64,92,25,36,57,55,16,71,110,23,238,19,32,203,80,215,97,254,15,128,144,79,245,241,171,33,200,50,253,57,14,66,121,89,206,38,18,252,57,102,231,102,166,155,56,84,161,236,62,200,62,15,84,142,28,167,155,64,239,35,184,31,74,208,231,83,126,31,99,243,45,157,190, - 109,217,24,193,120,97,144,221,159,155,208,159,49,64,252,120,219,20,79,153,124,217,86,136,116,36,97,7,113,246,54,88,91,16,127,93,141,44,180,147,29,223,96,16,151,126,134,75,51,227,2,121,221,47,127,130,235,73,2,18,108,153,19,236,38,9,140,45,106,170,152,130,219,244,128,4,187,247,225,28,185,225,81,230,129,128,178,76,48,129,125,214,177,167,113,95,146,96,226,138, - 204,60,228,214,126,107,160,19,16,115,19,23,102,112,144,71,184,17,1,10,208,105,184,96,10,110,51,0,131,149,79,62,245,58,192,164,233,81,6,53,215,9,15,161,61,37,32,15,125,22,250,204,242,129,236,107,122,139,127,154,168,144,208,255,13,236,217,55,90,96,6,227,169,225,18,62,199,133,91,46,250,27,33,116,80,4,251,26,49,65,176,225,40,234,116,212,102,11,214,240, - 46,52,144,238,168,71,28,217,249,183,56,238,185,187,50,14,87,48,137,48,29,41,116,142,185,45,29,243,144,203,181,90,239,193,217,51,23,136,197,145,71,30,98,238,41,184,167,34,96,72,64,246,184,239,57,62,204,45,220,16,210,24,156,52,66,230,55,132,114,140,22,243,27,39,120,253,140,16,118,25,109,172,159,17,51,196,116,154,3,120,86,99,76,32,124,98,0,247,50,91, - 246,184,51,30,51,196,223,43,123,162,213,105,82,18,242,88,235,20,113,230,180,152,0,196,202,47,216,103,90,151,29,79,51,126,255,222,140,162,109,196,123,188,54,48,188,81,81,246,236,21,214,42,120,79,105,72,82,201,103,142,113,51,252,55,51,140,0,200,103,173,169,98,190,86,67,66,46,249,114,184,95,228,24,20,102,173,187,18,54,198,128,89,196,245,196,168,176,54,34,9, - 253,106,23,236,143,129,220,5,168,59,160,144,107,125,11,239,125,173,144,144,144,143,236,53,133,142,123,59,160,144,250,179,57,213,149,156,224,206,73,210,95,202,48,58,148,158,166,63,135,115,121,144,167,150,240,156,203,210,17,211,223,139,61,138,94,9,200,195,254,62,148,221,39,1,121,228,159,192,51,246,4,168,216,127,203,93,235,80,38,118,57,99,231,214,91,48,39,219,113,183, - 32,204,102,29,198,24,158,255,77,198,117,235,156,245,204,24,158,241,199,36,32,175,241,191,14,227,55,97,200,239,250,91,23,156,223,174,175,1,73,110,249,187,144,38,1,72,114,252,106,189,152,91,83,130,160,191,52,132,115,31,140,65,129,146,75,56,9,246,15,114,105,7,61,40,113,144,144,95,103,118,16,163,50,134,113,12,134,142,116,74,161,157,174,198,2,53,251,227,116,239, - 56,25,12,164,55,66,64,17,243,27,146,229,18,99,12,239,68,198,36,24,23,202,152,132,127,18,88,25,204,217,9,209,56,31,247,0,48,195,104,0,98,250,231,16,63,7,52,60,179,107,49,51,8,74,156,44,121,64,246,245,178,102,113,250,160,60,37,46,221,160,64,73,18,98,109,80,186,164,75,25,194,94,198,144,4,228,209,255,67,17,243,87,96,79,197,131,1,159,56,98, - 249,205,48,103,176,243,11,220,196,185,41,228,26,129,98,100,116,59,222,145,1,147,201,81,96,116,98,206,247,128,196,235,239,126,92,95,18,76,108,199,253,219,166,19,247,240,166,123,187,195,36,194,38,37,48,153,157,166,15,147,18,229,16,127,191,34,92,131,46,148,112,126,105,16,148,24,131,28,37,33,174,196,197,81,64,123,87,80,118,133,67,197,253,66,229,200,226,158,146,245, - 33,23,64,86,72,71,156,238,254,33,172,253,4,122,113,207,233,149,128,184,114,84,206,222,177,31,161,127,37,48,240,188,101,184,80,224,254,86,171,224,1,249,180,103,29,207,178,245,54,65,46,58,251,177,222,239,247,129,2,198,131,201,205,3,21,132,152,156,223,148,100,48,32,94,67,185,26,135,233,18,166,185,196,13,10,101,80,128,253,102,130,144,135,174,2,206,46,21,124,40, - 6,80,240,128,88,253,138,30,249,136,197,23,2,244,19,43,131,60,100,33,33,251,11,18,118,145,132,253,23,5,80,240,40,187,224,97,255,69,96,132,197,141,112,20,66,230,31,113,201,87,112,169,87,209,165,223,70,124,242,23,36,218,127,132,131,92,218,145,130,236,255,112,230,88,222,237,53,231,239,127,120,200,14,207,35,92,130,178,226,124,243,193,206,67,160,92,235,158,15,43, - 11,84,57,134,145,110,79,94,81,166,15,177,180,118,158,26,135,100,126,130,156,150,252,134,198,52,7,241,115,72,30,247,150,8,152,104,3,179,133,181,215,77,28,166,139,223,12,1,69,88,127,61,140,246,120,152,81,103,223,36,121,88,160,140,62,209,145,90,119,153,131,171,136,171,10,232,46,84,89,223,233,62,80,27,214,155,122,128,13,122,194,246,232,33,244,235,33,108,212,99, - 46,87,119,209,163,75,164,91,169,182,142,173,163,27,178,59,37,200,94,91,45,91,252,253,11,155,163,30,212,133,180,141,29,120,198,102,212,89,24,185,140,129,185,15,226,253,231,14,188,27,101,204,34,221,28,11,155,194,154,110,202,5,66,190,41,143,247,38,83,92,184,101,159,193,59,163,117,220,202,39,198,52,226,231,222,36,183,143,238,70,195,62,235,217,19,237,253,146,204,251, - 52,242,193,8,200,111,36,28,191,155,189,139,24,134,187,194,189,191,169,184,161,176,119,60,77,153,119,190,211,104,83,1,212,202,252,115,16,249,219,0,37,164,139,78,144,250,82,92,247,131,26,202,11,1,185,148,161,173,234,81,180,27,241,204,20,36,111,76,152,48,122,87,5,196,1,98,245,51,217,58,103,36,223,49,207,192,78,7,59,45,185,180,135,122,61,246,6,218,4,217, - 250,14,194,29,3,196,141,135,178,128,30,97,124,144,223,124,184,186,39,18,155,97,247,230,148,32,123,236,31,196,120,105,51,100,183,115,205,65,189,59,60,182,221,196,216,12,255,230,152,32,137,254,86,79,130,13,17,24,123,6,251,105,18,24,103,226,158,119,166,156,77,97,176,176,127,106,185,240,176,36,13,236,209,54,192,28,220,115,216,251,157,19,32,73,59,234,18,223,200,164, - 152,235,78,130,110,139,123,166,157,98,126,75,64,195,30,160,198,24,196,121,128,65,80,98,12,2,29,225,58,71,73,56,51,80,198,255,101,23,116,198,190,154,243,109,105,62,15,241,243,75,63,198,65,140,76,76,96,207,126,158,142,121,40,160,173,6,247,161,158,28,37,6,5,228,171,236,195,122,11,12,61,129,247,55,18,144,215,245,118,10,174,27,15,114,111,196,30,185,36,89, - 6,133,24,39,253,182,158,226,178,182,67,156,13,217,139,187,148,254,213,216,139,118,227,98,188,3,104,178,122,113,156,157,119,0,255,247,126,31,251,255,18,144,88,247,213,78,57,198,122,188,191,21,48,193,1,151,112,195,133,177,71,49,159,73,96,184,228,37,187,255,151,161,15,2,200,225,121,49,231,66,150,145,243,240,147,204,124,191,108,177,30,25,91,178,92,217,189,223,65,251, - 74,64,205,118,95,134,118,199,115,108,63,67,59,3,239,92,129,6,40,161,249,144,24,26,211,51,0,42,12,117,61,234,37,73,118,55,218,149,145,101,244,239,70,61,128,138,248,30,70,150,165,33,73,187,140,128,231,85,35,98,60,181,160,219,144,124,94,157,138,225,27,199,133,21,139,253,246,253,106,4,165,143,184,220,55,10,24,63,133,8,168,66,127,102,133,254,204,9,125,155, - 21,250,178,23,215,114,175,4,228,117,189,173,196,28,200,65,33,199,176,122,16,249,98,130,196,178,235,8,111,51,36,94,163,7,163,173,185,211,88,227,83,138,76,249,92,87,20,114,108,117,99,205,219,45,64,110,99,112,167,243,221,71,217,239,48,158,182,74,46,157,219,247,27,85,159,112,226,226,201,195,173,6,96,68,252,86,209,29,12,138,225,254,100,196,244,237,36,138,80,22, - 37,124,15,54,66,218,115,251,181,206,183,51,197,189,30,179,69,42,74,39,246,73,237,189,85,251,55,158,216,239,52,225,28,111,5,12,179,247,134,149,195,222,237,96,199,15,11,178,130,235,176,2,134,5,127,133,177,139,163,210,140,207,59,229,85,176,95,85,177,169,57,236,230,202,25,246,208,83,1,85,176,155,201,42,131,236,242,106,220,111,90,177,48,10,104,127,138,105,236,25, - 17,199,220,118,188,107,166,249,58,116,28,171,231,62,174,46,21,48,204,181,69,213,14,203,99,207,156,201,10,228,144,36,21,214,238,85,86,78,117,190,252,142,216,246,234,212,22,160,69,247,121,242,77,163,198,24,79,156,222,125,236,119,161,170,104,143,17,182,103,184,15,254,125,246,251,108,197,121,199,215,124,87,91,101,232,12,66,60,73,176,157,59,31,160,43,206,251,223,102,156, - 133,51,91,86,8,168,133,60,86,74,101,19,87,30,69,44,155,90,108,47,43,166,252,86,4,157,196,81,193,59,171,10,131,132,184,50,254,47,39,12,113,250,116,110,44,235,94,172,144,163,204,208,57,72,86,135,178,24,59,31,53,109,92,209,158,115,16,94,232,130,109,122,27,48,185,51,44,26,246,152,181,54,67,92,253,173,46,140,229,136,80,132,246,55,217,153,170,114,155,32, - 65,255,108,150,22,65,18,54,91,72,103,53,81,163,243,176,100,26,114,177,69,195,30,177,150,0,165,10,246,141,5,200,77,255,153,72,159,2,100,207,181,251,177,223,182,21,126,14,18,237,219,186,56,94,164,114,101,70,185,20,242,82,1,146,28,191,198,203,176,230,75,1,98,250,199,126,140,253,88,9,200,195,254,34,202,42,198,8,9,229,23,16,86,104,35,36,232,87,177,175, - 167,250,64,1,253,171,98,61,175,70,128,66,204,133,253,49,60,175,26,88,151,24,9,65,41,234,167,152,234,79,17,219,151,130,198,203,114,244,187,11,196,197,147,79,58,53,38,136,211,65,130,125,196,185,45,140,57,43,1,8,229,207,109,195,89,63,184,103,125,208,54,164,135,109,35,249,80,70,154,114,0,20,113,188,88,43,209,94,49,65,92,121,228,162,107,22,225,179,2,218, - 201,201,80,246,128,56,123,42,195,25,197,192,122,212,104,3,228,210,30,19,118,220,218,100,17,117,142,35,108,156,139,31,143,8,9,229,142,135,196,194,59,227,6,222,89,55,24,132,178,26,156,155,4,26,92,218,6,176,144,223,226,32,123,12,174,246,246,39,5,185,216,71,46,182,207,34,237,108,0,228,115,189,206,225,221,253,156,31,171,253,243,27,125,232,119,1,179,140,189,92, - 238,183,19,168,217,167,125,232,35,129,137,50,206,130,184,49,43,55,23,105,120,7,162,37,0,241,215,245,118,236,127,120,96,97,14,176,18,128,154,115,220,201,232,67,31,44,60,219,88,49,65,110,115,108,63,244,248,160,194,6,53,6,200,167,143,251,17,223,207,65,33,239,73,125,200,211,231,1,69,189,223,109,68,219,5,64,17,117,144,15,7,241,204,126,48,38,168,5,253,55, - 32,223,13,49,65,62,122,198,17,63,238,130,134,51,82,26,71,9,103,172,74,28,20,96,255,208,227,56,255,37,1,121,217,213,1,59,82,130,236,241,183,21,99,76,2,66,218,198,149,184,143,128,71,177,71,64,205,241,187,117,33,190,21,202,167,97,29,228,129,6,40,32,191,138,52,106,12,228,170,56,7,34,73,31,210,247,113,244,187,64,49,93,159,6,206,180,24,17,25,247, - 129,98,158,79,52,236,33,104,9,65,18,250,75,231,227,186,245,160,114,62,238,185,54,25,236,115,9,144,56,46,51,24,131,17,24,122,0,215,189,4,20,161,173,75,168,83,255,37,56,159,6,40,68,190,78,238,236,136,129,177,106,68,132,124,116,141,61,137,253,54,9,200,107,60,117,161,239,61,40,93,128,126,21,24,116,9,43,9,144,61,111,127,27,237,47,65,229,2,140,23, - 14,13,122,7,153,30,13,110,10,104,107,11,207,84,86,76,52,46,197,185,117,200,185,155,177,110,244,120,134,35,23,102,55,97,173,21,35,20,102,62,200,161,175,98,128,90,44,107,176,132,190,98,148,56,6,185,176,65,46,188,82,66,63,219,228,48,47,112,238,18,251,214,190,134,115,133,154,7,196,226,201,37,29,5,228,213,2,160,16,249,43,56,215,72,94,247,147,77,184,102, - 35,48,58,210,117,12,51,0,114,155,15,126,130,235,93,2,242,176,63,119,17,238,193,32,203,32,132,169,120,103,170,250,64,44,175,234,225,87,67,66,1,121,73,208,165,122,164,49,243,78,93,108,127,150,213,39,199,213,45,203,213,145,64,214,195,159,229,194,84,159,247,199,89,46,29,113,168,46,246,101,133,114,115,204,182,156,11,228,210,63,57,143,120,10,96,116,15,198,22,48, - 57,70,153,52,176,191,104,112,76,236,193,115,62,207,6,82,198,126,136,241,35,193,4,203,67,208,57,129,124,166,80,62,133,176,153,98,36,183,31,237,14,114,12,21,239,246,84,208,207,36,5,228,239,125,6,231,147,37,32,175,249,122,19,230,144,22,25,196,53,63,200,40,9,16,43,127,144,75,51,200,197,15,114,238,202,29,152,115,71,24,119,224,28,151,205,38,204,107,77,70, - 184,248,144,104,200,175,113,148,4,251,74,187,160,223,254,230,231,46,128,111,92,106,30,223,185,36,15,134,30,193,186,65,2,242,200,63,97,127,103,244,150,112,120,149,69,45,160,158,142,113,38,73,238,114,140,85,144,99,50,203,220,57,23,178,76,170,62,191,87,69,246,248,125,10,227,83,2,74,232,250,211,58,212,182,65,205,49,215,161,30,99,144,81,18,24,116,9,43,113,101, - 80,115,252,221,135,241,37,65,25,121,203,160,130,119,82,21,134,14,191,218,141,190,13,65,182,128,190,101,228,36,200,114,238,126,228,39,193,254,35,152,155,142,72,48,139,185,112,54,0,10,217,247,22,242,88,246,59,192,229,238,28,75,183,124,177,59,40,143,229,226,182,90,100,230,194,46,87,8,101,207,112,110,2,13,184,27,44,172,1,44,150,223,98,178,1,230,46,196,30,61, - 131,36,218,232,200,119,209,254,18,144,87,27,175,71,61,124,32,201,116,86,4,102,118,163,77,24,13,1,106,182,221,110,199,207,167,157,97,97,22,202,152,187,21,207,96,172,44,74,104,46,34,23,42,47,199,253,239,205,184,94,121,238,6,8,47,189,57,216,22,11,207,235,13,236,97,53,92,152,97,52,56,44,164,183,56,230,238,196,88,169,58,4,233,162,4,80,237,119,6,253, - 201,226,167,223,34,180,67,0,36,153,206,138,200,204,121,232,35,31,200,30,199,231,185,199,53,243,90,40,103,238,60,244,167,0,73,246,199,145,111,225,122,151,96,22,122,102,91,132,56,125,115,227,176,111,188,67,177,240,238,207,138,1,106,94,239,101,180,71,11,144,61,239,150,253,211,240,241,51,66,94,10,192,192,57,71,195,3,226,226,41,32,173,17,1,83,195,243,151,11,196, - 217,105,50,191,201,197,153,30,249,76,96,176,114,41,160,254,99,22,158,215,36,32,143,252,26,244,104,46,16,23,71,62,233,180,152,24,68,93,7,5,8,122,75,144,37,230,30,100,225,37,78,106,30,231,92,137,49,132,186,15,73,64,73,205,199,125,152,51,99,34,135,107,34,7,178,140,126,132,245,3,138,211,222,147,162,149,247,196,199,157,223,182,141,10,181,160,123,238,114,156, - 15,194,187,54,163,13,144,135,13,55,35,238,230,22,33,228,159,192,187,195,9,1,10,209,6,134,164,157,148,16,22,158,89,172,22,33,228,191,191,187,195,7,69,185,191,16,80,127,252,173,173,225,1,181,163,254,157,168,75,194,144,159,254,117,72,147,18,4,253,71,176,119,115,68,2,18,175,221,93,88,183,0,138,216,254,170,253,205,118,138,78,179,188,28,214,128,57,129,254,16, - 235,191,105,140,187,105,142,185,157,25,229,104,136,177,120,228,123,104,47,9,8,105,103,81,238,172,7,100,143,141,85,232,167,152,33,183,49,184,42,217,242,195,208,135,51,139,125,9,209,255,6,188,91,182,89,11,55,32,183,249,232,100,204,61,146,144,144,215,28,198,58,16,225,163,144,163,45,66,62,109,99,34,222,228,56,0,93,7,66,210,243,166,14,165,103,175,243,183,196,3, - 192,204,5,127,115,138,103,176,136,181,28,160,86,175,247,79,224,122,77,16,10,208,111,224,221,167,145,0,20,99,253,41,226,53,68,62,104,73,127,51,243,70,111,252,236,34,89,251,87,57,223,210,228,191,167,73,33,48,132,239,61,82,80,127,221,134,62,105,35,36,218,219,141,241,37,9,185,213,183,91,62,191,95,57,20,178,60,98,233,39,225,54,177,55,110,130,137,66,230,184, - 239,237,83,130,99,157,92,208,241,191,158,0,20,131,126,74,216,70,61,164,173,212,74,251,174,112,254,118,188,132,247,228,37,134,14,63,181,169,127,203,248,191,28,35,116,130,140,47,93,210,150,114,204,245,47,135,108,147,34,254,47,182,64,193,7,66,185,133,128,52,5,70,81,162,188,66,140,20,153,125,69,206,77,204,79,66,155,144,71,27,145,68,187,21,60,218,132,2,218,134, - 66,180,93,161,197,190,43,250,216,89,244,169,35,73,142,25,10,72,67,33,235,88,136,216,223,69,159,250,20,125,236,39,201,235,132,98,168,15,69,188,30,139,45,244,119,53,160,221,10,156,93,67,135,177,143,27,3,147,167,210,34,204,125,93,199,220,19,251,176,31,199,115,106,180,251,144,93,182,41,64,30,225,166,36,20,241,126,151,195,158,122,206,3,10,136,207,73,66,33,117, - 145,71,90,74,224,126,175,102,177,110,14,9,241,237,55,8,219,60,232,65,218,30,15,136,229,239,157,193,249,29,9,200,197,238,205,45,254,141,17,241,229,108,69,157,66,144,187,18,117,227,232,253,25,236,147,128,92,116,159,122,101,167,162,97,31,69,19,160,230,90,100,45,214,11,1,148,222,128,53,162,7,36,81,255,41,252,63,197,209,192,51,69,195,131,105,110,254,33,198,17, - 204,33,71,36,32,33,223,28,131,98,160,140,255,203,45,162,215,112,246,137,243,239,19,252,101,151,58,83,130,246,148,99,66,143,152,159,88,93,140,14,60,143,114,144,75,152,145,32,196,233,35,230,38,206,54,10,97,15,249,212,135,132,178,73,192,112,137,51,60,242,27,45,216,79,18,229,145,75,126,35,68,223,144,100,30,138,169,109,141,22,251,155,92,218,217,8,208,67,9,234, - 167,16,220,137,50,238,140,80,142,206,190,193,168,75,66,2,122,204,80,72,244,24,116,233,17,203,208,219,0,73,183,71,119,11,80,236,223,141,214,149,229,237,225,198,214,199,142,211,94,212,86,168,5,253,36,97,63,197,92,127,106,19,122,30,125,24,166,13,243,225,210,7,234,175,69,235,195,200,249,149,120,9,221,254,74,2,248,212,151,34,182,31,197,140,30,178,110,20,115,251, - 81,76,246,81,139,249,169,77,227,131,132,254,166,86,251,171,150,32,108,110,161,8,101,80,179,156,60,67,244,231,37,137,88,23,242,169,7,121,196,147,11,186,132,14,242,65,143,1,106,177,124,106,1,61,106,125,149,24,175,25,123,125,174,132,207,19,133,33,201,125,92,242,42,163,22,255,28,45,133,226,232,79,227,247,24,181,132,127,31,134,66,180,131,22,241,247,99,180,151,248, - 111,215,104,105,219,169,56,191,63,224,121,125,40,201,98,255,77,191,25,1,138,168,63,147,239,78,5,98,250,235,61,148,42,197,101,233,34,254,6,104,61,38,57,21,64,157,251,173,181,130,15,197,0,10,17,243,235,236,62,88,180,101,205,249,109,208,249,61,14,133,133,177,240,2,243,23,25,5,70,145,15,171,113,249,240,251,36,58,123,103,90,116,65,231,169,177,125,21,46,174, - 200,108,43,50,127,221,110,179,67,221,139,242,23,184,242,234,107,28,105,135,105,2,5,78,87,65,200,87,117,161,200,165,43,112,249,171,92,57,83,107,28,121,220,222,124,173,219,65,241,136,19,220,43,213,116,177,219,109,202,229,55,113,167,2,198,120,221,227,55,116,167,2,174,129,105,70,189,201,50,132,131,122,74,178,184,28,253,11,138,33,165,6,74,23,118,41,23,115,84,88, - 88,73,130,10,210,14,180,160,183,24,81,14,48,74,204,142,17,140,193,17,197,233,11,190,239,234,33,231,185,122,76,114,58,196,220,89,23,198,227,148,132,28,96,245,29,113,169,179,21,115,253,234,30,215,73,221,231,250,169,7,200,10,214,76,245,67,237,193,254,109,175,10,244,237,201,43,243,191,61,181,11,20,113,222,181,152,34,133,132,57,24,227,247,85,15,182,64,253,204,116, - 89,137,51,11,43,83,164,136,235,178,216,6,10,9,81,124,137,219,95,144,168,79,181,77,186,171,41,183,115,245,247,164,94,213,4,251,168,126,130,48,149,22,61,237,163,2,125,211,98,248,26,119,92,159,7,151,47,172,191,227,98,0,229,14,128,105,143,240,1,142,41,15,91,167,124,24,88,238,31,159,36,211,46,20,2,158,183,47,10,160,16,49,255,84,27,199,219,148,27,107, - 218,135,189,70,159,134,156,230,40,224,153,173,144,34,35,88,3,79,97,109,60,213,6,134,177,254,174,178,245,119,181,230,248,163,174,111,45,156,17,183,34,112,67,140,223,255,191,161,5,166,176,70,157,74,145,110,172,81,187,83,196,58,37,25,26,111,196,25,98,142,105,151,176,6,48,48,31,27,192,196,222,129,105,239,99,228,157,223,138,29,251,110,167,20,19,200,123,128,149,97, - 180,194,186,5,14,112,110,163,93,108,76,150,3,30,76,236,205,204,51,45,204,135,211,109,96,128,187,135,79,167,160,127,154,179,227,178,195,138,178,23,12,99,46,220,131,121,113,216,67,86,216,184,172,52,169,117,204,239,253,84,154,126,69,112,11,236,62,156,153,167,194,151,161,144,178,127,222,173,28,251,125,115,29,12,20,59,20,13,242,82,188,35,27,14,176,107,152,73,157,229, - 29,14,72,183,59,223,113,204,189,135,229,187,20,122,46,13,192,20,222,83,101,139,14,246,111,179,15,136,228,187,142,217,115,41,87,198,128,93,175,188,243,219,239,205,120,227,38,14,251,111,204,111,114,145,110,172,14,136,115,137,175,64,247,128,210,163,28,184,184,99,30,3,97,234,221,241,211,243,230,14,249,244,39,37,75,143,7,253,151,102,230,49,112,15,50,66,112,0,76,236, - 199,220,241,201,142,121,105,132,204,111,8,140,224,26,24,73,136,1,9,140,245,106,36,14,248,196,77,114,24,96,20,152,76,26,140,61,236,218,31,62,54,207,40,243,227,212,224,199,241,106,111,236,241,108,120,93,7,55,181,143,129,230,247,81,46,116,238,227,54,163,192,136,114,111,94,222,58,77,253,38,179,97,148,249,71,57,251,76,15,70,5,76,206,109,216,101,231,133,247,246, - 92,94,35,192,46,21,247,124,181,77,228,118,117,205,163,194,157,133,204,2,107,11,41,71,239,202,28,99,206,102,11,57,242,46,219,221,177,224,190,162,233,119,1,225,71,231,243,117,204,203,163,140,198,21,88,215,129,163,92,216,81,14,35,226,245,102,196,200,40,119,77,154,28,163,46,97,166,75,220,168,224,55,192,216,163,88,151,74,48,177,27,115,168,205,122,204,167,28,134,164, - 173,134,128,41,196,141,114,24,46,97,163,30,105,12,151,58,27,45,96,186,216,60,234,129,201,217,55,38,217,126,163,66,254,73,134,90,92,150,46,7,83,166,158,46,6,246,116,140,20,185,245,2,172,73,240,187,76,198,9,196,36,152,136,171,188,83,210,69,205,225,26,75,145,28,35,203,185,115,46,100,25,70,26,207,244,235,22,99,226,190,107,2,67,8,55,146,224,116,212,57, - 69,180,53,233,98,110,71,91,115,140,2,163,19,237,210,38,76,166,211,116,97,148,147,163,140,156,238,144,5,234,102,92,95,41,144,101,54,228,56,178,140,28,231,207,113,168,44,111,239,209,78,41,84,15,221,26,165,139,218,155,46,214,25,233,178,232,155,131,171,122,218,254,141,195,221,246,179,238,106,143,125,31,81,222,148,48,237,210,115,211,2,42,246,197,212,52,185,62,93,194, - 252,189,128,150,0,106,2,251,127,106,8,140,136,251,103,70,68,172,54,124,207,219,242,65,179,239,1,155,113,126,20,247,20,13,82,99,148,4,191,230,17,166,69,196,232,79,151,193,125,93,243,104,120,23,170,165,192,32,211,63,40,137,41,177,127,102,74,96,120,236,143,77,112,24,182,252,16,158,231,184,61,189,161,239,119,74,161,173,70,253,18,164,116,49,206,59,251,80,177,223, - 235,92,156,81,84,251,153,233,148,214,201,161,172,28,35,11,84,232,86,83,34,199,108,200,114,54,229,56,219,178,46,126,21,103,28,212,20,209,206,192,115,65,138,148,56,89,226,252,154,139,95,115,137,83,177,39,168,166,73,29,125,184,18,123,59,237,162,222,94,125,113,124,67,200,0,119,180,136,145,18,123,216,59,39,203,126,6,233,77,17,236,105,89,105,146,77,23,109,107,186, - 68,57,187,101,197,128,138,61,91,53,77,58,210,197,192,53,96,164,136,245,178,228,56,202,152,245,193,178,207,160,173,77,15,213,30,131,167,182,151,62,70,191,237,223,208,126,250,56,140,62,127,38,3,226,141,136,104,246,51,96,103,122,88,56,11,103,165,136,134,53,190,150,34,150,125,15,216,154,30,218,105,237,167,204,49,120,62,158,215,192,32,208,50,136,111,51,37,166,191,228, - 65,238,18,135,44,80,113,102,81,109,51,89,166,59,203,236,200,113,100,133,240,126,164,239,7,157,182,188,4,231,203,64,233,2,212,131,161,97,189,165,181,153,220,8,108,3,89,160,110,66,157,82,36,203,236,200,50,155,114,1,100,61,236,238,31,65,219,218,108,114,220,98,190,126,132,103,153,187,247,39,120,255,34,129,106,151,117,7,246,43,88,153,253,12,3,126,35,37,76,216, - 111,216,247,168,13,233,50,186,7,239,234,24,102,0,42,246,84,213,20,201,238,199,152,97,228,60,200,114,50,43,164,215,208,238,90,154,172,75,151,65,188,167,31,100,148,2,24,228,210,13,50,169,158,142,126,72,147,238,116,209,216,239,208,151,36,208,144,86,75,144,146,135,222,65,166,187,36,132,87,238,206,28,247,123,247,86,74,52,170,56,71,25,146,25,206,61,87,197,217,77, - 134,133,242,230,238,132,27,168,62,191,123,175,182,1,3,107,62,35,69,44,140,81,43,85,148,5,10,28,98,186,130,24,214,76,231,145,62,105,155,11,238,122,189,126,139,216,104,59,138,98,236,4,17,203,177,82,166,177,19,215,175,7,115,59,113,13,55,89,133,107,26,28,21,48,66,252,30,171,145,0,106,194,191,87,170,6,96,36,244,123,165,134,44,55,225,222,211,230,51,52, - 154,15,106,155,127,143,83,21,48,236,57,162,59,61,90,249,189,35,53,78,182,166,139,248,91,67,90,155,49,183,225,185,8,108,87,22,220,237,228,200,211,157,82,204,110,193,126,180,4,71,175,200,28,251,251,150,6,39,31,219,162,40,63,188,66,57,38,103,16,54,3,74,56,179,80,74,17,83,252,91,165,188,28,205,252,149,26,206,232,49,118,49,134,37,255,38,117,24,82,71, - 191,235,2,131,40,127,80,208,167,187,196,15,10,108,15,192,12,64,103,229,155,18,105,244,152,49,19,210,99,70,248,45,61,51,102,38,241,62,99,146,195,140,169,156,73,151,114,39,3,210,76,50,70,35,252,182,252,104,12,12,197,244,187,141,67,45,242,240,161,238,112,172,161,197,28,106,49,31,227,210,21,233,83,22,208,125,184,25,247,204,155,83,164,220,252,222,107,45,29,100, - 127,179,168,156,4,10,250,0,223,98,208,109,89,235,96,208,162,249,110,56,196,189,103,15,39,203,73,181,151,178,216,190,32,202,168,79,89,2,61,33,202,129,253,79,210,54,150,19,178,187,28,129,113,172,57,199,83,100,22,123,176,179,49,115,52,128,39,62,222,121,140,178,61,198,148,20,105,105,206,33,142,238,72,236,199,185,219,253,94,40,29,139,252,219,149,46,229,58,172,197, - 174,59,188,252,216,26,114,55,194,119,35,221,110,91,230,157,111,182,236,70,185,21,27,101,241,247,98,108,247,101,130,191,194,165,173,216,28,230,64,121,111,58,220,173,92,1,182,187,172,95,247,67,111,165,214,233,143,178,96,195,188,158,60,242,216,40,88,155,51,42,28,85,165,147,251,182,68,199,162,244,21,31,170,76,238,106,134,229,133,111,220,52,81,22,194,230,219,52,31,188, - 78,79,146,76,74,191,127,144,97,116,229,213,84,169,216,227,226,240,194,184,60,54,86,14,47,192,135,93,214,116,231,133,126,117,233,231,221,243,82,153,247,239,182,251,93,225,198,34,220,21,137,251,223,176,248,221,34,197,35,109,208,189,181,198,16,194,171,12,221,135,225,32,221,74,235,52,245,87,57,134,153,190,170,71,124,53,1,134,37,215,69,213,20,116,14,135,148,213,20,219, - 173,218,70,221,85,143,177,162,115,99,75,119,113,235,30,227,80,143,145,170,168,191,230,92,159,77,169,39,68,53,44,181,238,5,89,99,110,62,174,198,133,241,110,69,200,139,223,27,169,218,40,46,233,196,176,26,43,183,137,226,82,94,83,214,92,224,211,40,46,122,196,180,138,79,157,130,168,121,212,57,40,157,18,162,124,62,111,205,167,109,252,252,74,68,226,44,191,38,217,102, - 178,241,74,140,117,140,171,44,37,6,14,71,47,35,169,121,68,247,160,154,130,78,157,211,93,141,25,253,4,169,131,222,42,53,129,208,249,187,23,214,142,53,230,118,67,9,81,14,243,87,221,242,213,66,166,19,210,234,110,241,53,9,251,100,237,175,133,40,79,34,93,53,0,157,215,87,19,244,207,187,201,61,141,226,204,103,209,234,76,137,141,231,106,8,244,128,178,244,192,122, - 116,75,247,223,62,172,81,246,121,81,243,137,11,162,22,16,198,220,186,120,189,214,146,99,164,182,252,56,54,227,204,197,230,20,209,35,142,55,61,42,53,151,177,210,78,148,54,216,35,234,80,18,108,15,175,114,20,89,253,2,243,97,221,199,151,173,120,216,125,92,56,45,158,51,107,112,47,10,167,197,191,87,173,180,1,94,183,34,198,177,58,132,237,55,37,110,27,61,218,179, - 221,237,83,147,161,217,183,62,125,220,12,175,137,233,197,48,209,205,245,147,239,245,74,62,215,5,121,216,76,194,248,235,246,73,79,238,99,166,198,16,127,127,93,17,210,37,65,13,182,242,254,195,216,19,20,152,204,224,28,65,138,232,7,83,166,217,63,181,116,216,12,27,54,167,132,30,131,253,147,56,15,58,153,18,122,202,250,39,153,13,186,95,255,222,157,46,126,103,65,244, - 54,48,41,121,142,105,50,33,116,123,14,172,181,0,63,135,214,98,96,209,188,76,194,125,166,59,2,116,60,121,110,189,20,55,10,35,201,121,81,241,209,225,21,158,231,238,173,110,237,144,119,137,143,147,188,139,110,89,106,49,234,143,131,90,192,88,18,211,230,37,235,210,140,207,71,168,115,179,255,21,137,241,224,151,87,137,56,54,221,168,69,196,175,108,37,65,187,101,168,37, - 132,221,79,121,143,49,22,87,249,53,73,157,113,160,180,185,29,91,209,147,247,185,214,69,148,136,227,198,139,195,220,115,8,206,235,232,77,20,159,122,136,246,214,90,28,15,110,117,175,181,216,159,34,121,143,251,143,23,249,22,239,13,126,113,97,202,23,245,200,232,142,10,95,190,232,22,210,138,255,254,63,0,0,0,255,255,0,0,0,255,255,99,102,0,0}; + 0, 0, 16, 0, 0, 0, 0, 0, 0, 164, 1, 0, 108, 4, 0, 0, 116, 4, 0, 0, 124, 4, 0, 0, 132, 4, 0, 0, 156, 4, 0, 0, 164, 4, 0, 0, 172, 4, 0, 0, 180, 4, 0, 0, 188, 4, 0, 0, 196, 4, 0, 0, 202, 4, 0, 0, 210, 4, 0, 0, 218, 4, 0, 0, 226, 4, 0, 0, 234, 4, 0, 0, 242, 4, 0, 0, 248, 4, 0, 0, 0, 5, 0, 0, 8, 5, 0, 0, 16, 5, 0, 0, 19, 5, 0, 0, 27, 5, 0, 0, + 35, 5, 0, 0, 43, 5, 0, 0, 51, 5, 0, 0, 59, 5, 0, 0, 64, 5, 0, 0, 72, 5, 0, 0, 80, 5, 0, 0, 88, 5, 0, 0, 93, 5, 0, 0, 101, 5, 0, 0, 109, 5, 0, 0, 117, 5, 0, 0, 121, 5, 0, 0, 129, 5, 0, 0, 137, 5, 0, 0, 145, 5, 0, 0, 153, 5, 0, 0, 161, 5, 0, 0, 157, 5, 0, 0, 165, 5, 0, 0, 170, 5, 0, 0, 178, 5, 0, 0, 184, 5, 0, 0, 192, 5, 0, 0, 200, 5, 0, 0, + 208, 5, 0, 0, 216, 5, 0, 0, 224, 5, 0, 0, 232, 5, 0, 0, 240, 5, 0, 0, 245, 5, 0, 0, 253, 5, 0, 0, 0, 6, 0, 0, 8, 6, 0, 0, 16, 6, 0, 0, 24, 6, 0, 0, 30, 6, 0, 0, 38, 6, 0, 0, 46, 6, 0, 0, 54, 6, 0, 0, 62, 6, 0, 0, 70, 6, 0, 0, 22, 19, 0, 0, 78, 6, 0, 0, 86, 6, 0, 0, 94, 6, 0, 0, 100, 6, 0, 0, 224, 5, 0, 0, 30, 19, 0, 0, 252, 22, 0, 0, + 163, 19, 0, 0, 165, 19, 0, 0, 173, 19, 0, 0, 38, 19, 0, 0, 108, 6, 0, 0, 114, 6, 0, 0, 122, 6, 0, 0, 130, 6, 0, 0, 138, 6, 0, 0, 144, 6, 0, 0, 152, 6, 0, 0, 160, 6, 0, 0, 168, 6, 0, 0, 174, 6, 0, 0, 182, 6, 0, 0, 190, 6, 0, 0, 198, 6, 0, 0, 204, 6, 0, 0, 212, 6, 0, 0, 220, 6, 0, 0, 228, 6, 0, 0, 236, 6, 0, 0, 244, 6, 0, 0, 251, 6, 0, 0, 3, 7, 0, 0, + 9, 7, 0, 0, 17, 7, 0, 0, 25, 7, 0, 0, 33, 7, 0, 0, 39, 7, 0, 0, 47, 7, 0, 0, 55, 7, 0, 0, 63, 7, 0, 0, 181, 19, 0, 0, 71, 7, 0, 0, 79, 7, 0, 0, 87, 7, 0, 0, 94, 7, 0, 0, 102, 7, 0, 0, 110, 7, 0, 0, 118, 7, 0, 0, 122, 7, 0, 0, 130, 7, 0, 0, 137, 7, 0, 0, 145, 7, 0, 0, 152, 7, 0, 0, 160, 7, 0, 0, 137, 7, 0, 0, 189, 19, 0, 0, 4, 23, 0, 0, + 168, 7, 0, 0, 173, 7, 0, 0, 181, 7, 0, 0, 188, 7, 0, 0, 196, 7, 0, 0, 137, 7, 0, 0, 197, 19, 0, 0, 203, 19, 0, 0, 211, 19, 0, 0, 219, 19, 0, 0, 227, 19, 0, 0, 175, 17, 0, 0, 204, 7, 0, 0, 167, 18, 0, 0, 235, 19, 0, 0, 235, 19, 0, 0, 235, 19, 0, 0, 243, 19, 0, 0, 243, 19, 0, 0, 249, 19, 0, 0, 251, 19, 0, 0, 251, 19, 0, 0, 3, 20, 0, 0, 3, 20, 0, 0, 212, 7, 0, 0, + 3, 20, 0, 0, 220, 7, 0, 0, 224, 7, 0, 0, 232, 7, 0, 0, 3, 20, 0, 0, 238, 7, 0, 0, 3, 20, 0, 0, 244, 7, 0, 0, 252, 7, 0, 0, 4, 8, 0, 0, 183, 17, 0, 0, 183, 17, 0, 0, 12, 8, 0, 0, 11, 20, 0, 0, 12, 20, 0, 0, 12, 20, 0, 0, 12, 20, 0, 0, 12, 20, 0, 0, 12, 20, 0, 0, 12, 20, 0, 0, 12, 20, 0, 0, 12, 20, 0, 0, 12, 20, 0, 0, 12, 20, 0, 0, 12, 20, 0, 0, + 12, 20, 0, 0, 12, 20, 0, 0, 12, 20, 0, 0, 12, 20, 0, 0, 12, 20, 0, 0, 12, 20, 0, 0, 12, 20, 0, 0, 17, 20, 0, 0, 20, 8, 0, 0, 25, 20, 0, 0, 25, 20, 0, 0, 28, 8, 0, 0, 36, 8, 0, 0, 44, 8, 0, 0, 52, 8, 0, 0, 60, 8, 0, 0, 33, 20, 0, 0, 36, 20, 0, 0, 68, 8, 0, 0, 76, 8, 0, 0, 84, 8, 0, 0, 44, 20, 0, 0, 46, 19, 0, 0, 92, 8, 0, 0, 51, 20, 0, 0, + 100, 8, 0, 0, 12, 20, 0, 0, 104, 8, 0, 0, 112, 8, 0, 0, 120, 8, 0, 0, 128, 8, 0, 0, 133, 8, 0, 0, 59, 20, 0, 0, 141, 8, 0, 0, 147, 8, 0, 0, 226, 24, 0, 0, 155, 8, 0, 0, 67, 20, 0, 0, 163, 8, 0, 0, 171, 8, 0, 0, 179, 8, 0, 0, 187, 8, 0, 0, 195, 8, 0, 0, 137, 7, 0, 0, 75, 20, 0, 0, 78, 20, 0, 0, 203, 8, 0, 0, 211, 8, 0, 0, 86, 20, 0, 0, 94, 20, 0, 0, + 102, 20, 0, 0, 219, 8, 0, 0, 110, 20, 0, 0, 227, 8, 0, 0, 235, 8, 0, 0, 54, 19, 0, 0, 243, 8, 0, 0, 247, 8, 0, 0, 255, 8, 0, 0, 7, 9, 0, 0, 12, 5, 0, 0, 175, 18, 0, 0, 62, 19, 0, 0, 183, 18, 0, 0, 190, 18, 0, 0, 70, 19, 0, 0, 51, 5, 0, 0, 51, 5, 0, 0, 188, 4, 0, 0, 188, 4, 0, 0, 188, 4, 0, 0, 188, 4, 0, 0, 191, 17, 0, 0, 188, 4, 0, 0, 188, 4, 0, 0, + 188, 4, 0, 0, 15, 9, 0, 0, 199, 17, 0, 0, 19, 9, 0, 0, 27, 9, 0, 0, 198, 18, 0, 0, 35, 9, 0, 0, 43, 9, 0, 0, 51, 9, 0, 0, 195, 23, 0, 0, 203, 23, 0, 0, 211, 23, 0, 0, 59, 9, 0, 0, 67, 9, 0, 0, 210, 24, 0, 0, 75, 9, 0, 0, 83, 9, 0, 0, 207, 17, 0, 0, 215, 17, 0, 0, 223, 17, 0, 0, 84, 23, 0, 0, 91, 9, 0, 0, 48, 24, 0, 0, 53, 24, 0, 0, 59, 24, 0, 0, + 67, 24, 0, 0, 75, 24, 0, 0, 83, 24, 0, 0, 91, 24, 0, 0, 99, 24, 0, 0, 106, 24, 0, 0, 114, 24, 0, 0, 119, 24, 0, 0, 251, 23, 0, 0, 3, 24, 0, 0, 234, 24, 0, 0, 127, 24, 0, 0, 135, 24, 0, 0, 142, 24, 0, 0, 147, 24, 0, 0, 155, 24, 0, 0, 234, 24, 0, 0, 98, 9, 0, 0, 106, 9, 0, 0, 111, 23, 0, 0, 112, 23, 0, 0, 242, 24, 0, 0, 242, 24, 0, 0, 119, 23, 0, 0, 242, 24, 0, 0, + 242, 24, 0, 0, 247, 24, 0, 0, 251, 24, 0, 0, 3, 25, 0, 0, 163, 24, 0, 0, 171, 24, 0, 0, 179, 24, 0, 0, 11, 25, 0, 0, 19, 25, 0, 0, 27, 25, 0, 0, 187, 24, 0, 0, 28, 25, 0, 0, 36, 25, 0, 0, 44, 25, 0, 0, 52, 25, 0, 0, 60, 25, 0, 0, 234, 24, 0, 0, 64, 25, 0, 0, 127, 23, 0, 0, 133, 23, 0, 0, 234, 24, 0, 0, 11, 24, 0, 0, 18, 24, 0, 0, 72, 25, 0, 0, 72, 25, 0, 0, + 72, 25, 0, 0, 72, 25, 0, 0, 72, 25, 0, 0, 72, 25, 0, 0, 72, 25, 0, 0, 72, 25, 0, 0, 114, 24, 0, 0, 114, 24, 0, 0, 114, 24, 0, 0, 114, 24, 0, 0, 26, 24, 0, 0, 114, 24, 0, 0, 33, 24, 0, 0, 40, 24, 0, 0, 114, 24, 0, 0, 114, 24, 0, 0, 114, 24, 0, 0, 114, 24, 0, 0, 114, 24, 0, 0, 114, 24, 0, 0, 114, 24, 0, 0, 114, 24, 0, 0, 234, 24, 0, 0, 195, 24, 0, 0, 202, 24, 0, 0, + 114, 9, 0, 0, 120, 9, 0, 0, 234, 24, 0, 0, 234, 24, 0, 0, 234, 24, 0, 0, 231, 17, 0, 0, 235, 17, 0, 0, 206, 18, 0, 0, 243, 17, 0, 0, 251, 17, 0, 0, 251, 17, 0, 0, 251, 17, 0, 0, 128, 9, 0, 0, 214, 18, 0, 0, 136, 9, 0, 0, 118, 20, 0, 0, 142, 9, 0, 0, 150, 9, 0, 0, 158, 9, 0, 0, 158, 9, 0, 0, 12, 23, 0, 0, 243, 23, 0, 0, 78, 19, 0, 0, 166, 9, 0, 0, 137, 7, 0, 0, + 174, 9, 0, 0, 80, 25, 0, 0, 80, 25, 0, 0, 181, 9, 0, 0, 80, 25, 0, 0, 80, 25, 0, 0, 80, 25, 0, 0, 80, 25, 0, 0, 80, 25, 0, 0, 80, 25, 0, 0, 189, 9, 0, 0, 195, 9, 0, 0, 86, 19, 0, 0, 94, 19, 0, 0, 203, 9, 0, 0, 126, 20, 0, 0, 211, 9, 0, 0, 134, 20, 0, 0, 142, 20, 0, 0, 102, 19, 0, 0, 219, 9, 0, 0, 223, 9, 0, 0, 150, 20, 0, 0, 150, 20, 0, 0, 228, 9, 0, 0, + 158, 20, 0, 0, 88, 25, 0, 0, 235, 9, 0, 0, 243, 9, 0, 0, 141, 23, 0, 0, 147, 23, 0, 0, 96, 25, 0, 0, 141, 23, 0, 0, 155, 23, 0, 0, 104, 25, 0, 0, 108, 25, 0, 0, 116, 25, 0, 0, 116, 25, 0, 0, 118, 25, 0, 0, 88, 25, 0, 0, 88, 25, 0, 0, 88, 25, 0, 0, 88, 25, 0, 0, 88, 25, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 234, 24, 0, 0, 234, 24, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 110, 19, 0, 0, 174, 20, 0, 0, 174, 20, 0, 0, 174, 20, 0, 0, 174, 20, 0, 0, 174, 20, 0, 0, 174, 20, 0, 0, 174, 20, 0, 0, 174, 20, 0, 0, 174, 20, 0, 0, 174, 20, 0, 0, 174, 20, 0, 0, 174, 20, 0, 0, 174, 20, 0, 0, 174, 20, 0, 0, 174, 20, 0, 0, 174, 20, 0, 0, + 174, 20, 0, 0, 174, 20, 0, 0, 174, 20, 0, 0, 174, 20, 0, 0, 174, 20, 0, 0, 174, 20, 0, 0, 174, 20, 0, 0, 174, 20, 0, 0, 174, 20, 0, 0, 174, 20, 0, 0, 174, 20, 0, 0, 174, 20, 0, 0, 174, 20, 0, 0, 174, 20, 0, 0, 174, 20, 0, 0, 174, 20, 0, 0, 174, 20, 0, 0, 174, 20, 0, 0, 174, 20, 0, 0, 251, 9, 0, 0, 126, 25, 0, 0, 2, 10, 0, 0, 118, 19, 0, 0, 182, 20, 0, 0, 182, 20, 0, 0, + 182, 20, 0, 0, 182, 20, 0, 0, 182, 20, 0, 0, 182, 20, 0, 0, 182, 20, 0, 0, 182, 20, 0, 0, 126, 19, 0, 0, 10, 10, 0, 0, 129, 5, 0, 0, 3, 18, 0, 0, 11, 18, 0, 0, 190, 20, 0, 0, 190, 20, 0, 0, 18, 10, 0, 0, 134, 19, 0, 0, 19, 18, 0, 0, 188, 4, 0, 0, 24, 18, 0, 0, 32, 18, 0, 0, 38, 18, 0, 0, 26, 10, 0, 0, 33, 10, 0, 0, 198, 20, 0, 0, 41, 10, 0, 0, 206, 20, 0, 0, + 49, 10, 0, 0, 214, 20, 0, 0, 217, 20, 0, 0, 57, 10, 0, 0, 225, 20, 0, 0, 233, 20, 0, 0, 240, 20, 0, 0, 65, 10, 0, 0, 73, 10, 0, 0, 248, 20, 0, 0, 252, 20, 0, 0, 81, 10, 0, 0, 89, 10, 0, 0, 4, 21, 0, 0, 97, 10, 0, 0, 105, 10, 0, 0, 142, 19, 0, 0, 12, 21, 0, 0, 16, 21, 0, 0, 113, 10, 0, 0, 121, 10, 0, 0, 129, 10, 0, 0, 137, 10, 0, 0, 222, 18, 0, 0, 144, 10, 0, 0, + 230, 18, 0, 0, 230, 18, 0, 0, 24, 21, 0, 0, 152, 10, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, + 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, + 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, + 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, + 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, + 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, + 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, + 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, + 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, + 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, + 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, + 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, + 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, + 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 38, 21, 0, 0, 32, 21, 0, 0, 33, 21, 0, 0, 34, 21, 0, 0, + 35, 21, 0, 0, 36, 21, 0, 0, 37, 21, 0, 0, 160, 10, 0, 0, 167, 10, 0, 0, 170, 10, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, + 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, + 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, + 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, + 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, + 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, + 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, + 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, + 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, + 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, + 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 178, 10, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 182, 10, 0, 0, 189, 10, 0, 0, 197, 10, 0, 0, 205, 10, 0, 0, 213, 10, 0, 0, 224, 5, 0, 0, 224, 5, 0, 0, 46, 21, 0, 0, 221, 10, 0, 0, 224, 5, 0, 0, 224, 5, 0, 0, 224, 5, 0, 0, 224, 5, 0, 0, 224, 5, 0, 0, 224, 5, 0, 0, 224, 5, 0, 0, + 224, 5, 0, 0, 224, 5, 0, 0, 224, 5, 0, 0, 54, 21, 0, 0, 62, 21, 0, 0, 224, 5, 0, 0, 226, 10, 0, 0, 224, 5, 0, 0, 232, 10, 0, 0, 236, 10, 0, 0, 244, 10, 0, 0, 20, 23, 0, 0, 252, 10, 0, 0, 4, 11, 0, 0, 224, 5, 0, 0, 224, 5, 0, 0, 224, 5, 0, 0, 10, 11, 0, 0, 18, 11, 0, 0, 46, 18, 0, 0, 238, 18, 0, 0, 150, 19, 0, 0, 155, 19, 0, 0, 26, 11, 0, 0, 34, 11, 0, 0, + 42, 11, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, + 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 235, 23, 0, 0, 48, 18, 0, 0, 48, 18, 0, 0, 112, 18, 0, 0, 176, 18, 0, 0, 240, 18, 0, 0, 40, 19, 0, 0, 104, 19, 0, 0, 168, 19, 0, 0, 224, 19, 0, 0, 32, 20, 0, 0, 76, 20, 0, 0, 140, 20, 0, 0, 204, 20, 0, 0, 0, 21, 0, 0, 64, 21, 0, 0, 116, 21, 0, 0, 180, 21, 0, 0, + 228, 21, 0, 0, 36, 22, 0, 0, 100, 22, 0, 0, 116, 22, 0, 0, 168, 22, 0, 0, 224, 22, 0, 0, 32, 23, 0, 0, 96, 23, 0, 0, 160, 23, 0, 0, 212, 23, 0, 0, 0, 24, 0, 0, 64, 24, 0, 0, 120, 24, 0, 0, 184, 24, 0, 0, 248, 24, 0, 0, 96, 10, 0, 0, 160, 10, 0, 0, 224, 10, 0, 0, 32, 11, 0, 0, 96, 11, 0, 0, 139, 11, 0, 0, 203, 11, 0, 0, 237, 11, 0, 0, 13, 12, 0, 0, 237, 11, 0, 0, + 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 77, 12, 0, 0, 112, 17, 0, 0, 112, 17, 0, 0, 141, 12, 0, 0, 205, 12, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 246, 12, 0, 0, 54, 13, 0, 0, 86, 13, 0, 0, 237, 11, 0, 0, 124, 13, 0, 0, 188, 13, 0, 0, 252, 13, 0, 0, 60, 14, 0, 0, 124, 14, 0, 0, 188, 14, 0, 0, 252, 14, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, + 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 60, 15, 0, 0, 160, 1, 0, 0, 116, 15, 0, 0, 180, 15, 0, 0, 160, 1, 0, 0, 191, 15, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, + 160, 1, 0, 0, 245, 15, 0, 0, 21, 16, 0, 0, 85, 16, 0, 0, 160, 1, 0, 0, 160, 1, 0, 0, 149, 16, 0, 0, 21, 16, 0, 0, 21, 16, 0, 0, 21, 16, 0, 0, 21, 16, 0, 0, 21, 16, 0, 0, 21, 16, 0, 0, 21, 16, 0, 0, 21, 16, 0, 0, 21, 16, 0, 0, 21, 16, 0, 0, 21, 16, 0, 0, 21, 16, 0, 0, 21, 16, 0, 0, 21, 16, 0, 0, 21, 16, 0, 0, 21, 16, 0, 0, 21, 16, 0, 0, 21, 16, 0, 0, + 21, 16, 0, 0, 21, 16, 0, 0, 21, 16, 0, 0, 21, 16, 0, 0, 21, 16, 0, 0, 21, 16, 0, 0, 21, 16, 0, 0, 21, 16, 0, 0, 21, 16, 0, 0, 21, 16, 0, 0, 176, 16, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, + 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, + 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, + 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, + 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, + 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, + 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, + 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, + 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, + 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, + 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, + 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, + 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, + 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 240, 16, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, + 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 237, 11, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, + 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 0, 7, 0, 0, 48, 17, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, + 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, + 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, + 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 140, 4, 0, 0, 50, 11, 0, 0, 57, 11, 0, 0, 65, 11, 0, 0, 137, 7, 0, 0, 70, 21, 0, 0, 70, 21, 0, 0, 70, 21, 0, 0, 73, 11, 0, 0, 81, 11, 0, 0, 84, 11, 0, 0, 92, 23, 0, 0, 95, 23, 0, 0, 92, 11, 0, 0, 100, 11, 0, 0, 110, 9, 0, 0, 108, 11, 0, 0, + 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 116, 11, 0, 0, 78, 21, 0, 0, 124, 11, 0, 0, 132, 11, 0, 0, 86, 21, 0, 0, 140, 11, 0, 0, 148, 11, 0, 0, 152, 11, 0, 0, 160, 11, 0, 0, 94, 21, 0, 0, 168, 11, 0, 0, 137, 7, 0, 0, 54, 18, 0, 0, 60, 18, 0, 0, 246, 18, 0, 0, 102, 21, 0, 0, 176, 11, 0, 0, 184, 11, 0, 0, 188, 11, 0, 0, 194, 11, 0, 0, 110, 21, 0, 0, + 202, 11, 0, 0, 118, 21, 0, 0, 209, 11, 0, 0, 213, 11, 0, 0, 221, 11, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 126, 21, 0, 0, 126, 21, 0, 0, 126, 21, 0, 0, 126, 21, 0, 0, 126, 21, 0, 0, 126, 21, 0, 0, 126, 21, 0, 0, 126, 21, 0, 0, 126, 21, 0, 0, 229, 11, 0, 0, 237, 11, 0, 0, 245, 11, 0, 0, 253, 11, 0, 0, 1, 12, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 9, 12, 0, 0, 12, 12, 0, 0, + 20, 12, 0, 0, 134, 21, 0, 0, 28, 12, 0, 0, 36, 12, 0, 0, 137, 7, 0, 0, 44, 12, 0, 0, 52, 12, 0, 0, 60, 12, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 142, 21, 0, 0, 68, 12, 0, 0, 76, 12, 0, 0, 163, 23, 0, 0, 84, 12, 0, 0, 91, 12, 0, 0, 99, 12, 0, 0, 150, 21, 0, 0, 158, 21, 0, 0, 137, 7, 0, 0, 166, 21, 0, 0, 107, 12, 0, 0, 174, 21, 0, 0, 115, 12, 0, 0, 123, 12, 0, 0, + 131, 12, 0, 0, 139, 12, 0, 0, 147, 12, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 182, 21, 0, 0, 182, 21, 0, 0, 155, 12, 0, 0, 137, 7, 0, 0, 68, 18, 0, 0, 163, 12, 0, 0, 254, 18, 0, 0, 171, 12, 0, 0, 190, 21, 0, 0, 179, 12, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 187, 12, 0, 0, + 198, 21, 0, 0, 195, 12, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 206, 21, 0, 0, 203, 12, 0, 0, 210, 12, 0, 0, 217, 12, 0, 0, 225, 12, 0, 0, 229, 12, 0, 0, 236, 12, 0, 0, 244, 12, 0, 0, 214, 21, 0, 0, 216, 21, 0, 0, 252, 12, 0, 0, 3, 13, 0, 0, 224, 21, 0, 0, 228, 21, 0, 0, 11, 13, 0, 0, 17, 13, 0, 0, 236, 21, 0, 0, 25, 13, 0, 0, 33, 13, 0, 0, 37, 13, 0, 0, 244, 21, 0, 0, + 248, 21, 0, 0, 0, 22, 0, 0, 45, 13, 0, 0, 53, 13, 0, 0, 58, 13, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 66, 13, 0, 0, 74, 13, 0, 0, 8, 22, 0, 0, 82, 13, 0, 0, 90, 13, 0, 0, 96, 13, 0, 0, 104, 13, 0, 0, 112, 13, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 16, 22, 0, 0, 19, 22, 0, 0, 120, 13, 0, 0, 128, 13, 0, 0, 27, 22, 0, 0, 31, 22, 0, 0, + 136, 13, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 39, 22, 0, 0, 144, 13, 0, 0, 152, 13, 0, 0, 137, 7, 0, 0, 47, 22, 0, 0, 51, 22, 0, 0, 160, 13, 0, 0, 168, 13, 0, 0, 59, 22, 0, 0, 176, 13, 0, 0, 184, 13, 0, 0, 137, 7, 0, 0, 192, 13, 0, 0, 200, 13, 0, 0, 208, 13, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, + 137, 7, 0, 0, 67, 22, 0, 0, 216, 13, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 76, 18, 0, 0, 6, 19, 0, 0, 224, 13, 0, 0, 232, 13, 0, 0, 238, 13, 0, 0, 246, 13, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 254, 13, 0, 0, 2, 14, 0, 0, 10, 14, 0, 0, 75, 22, 0, 0, 79, 22, 0, 0, 18, 14, 0, 0, 87, 22, 0, 0, 93, 22, 0, 0, 26, 14, 0, 0, 101, 22, 0, 0, 34, 14, 0, 0, + 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 42, 14, 0, 0, 47, 14, 0, 0, 55, 14, 0, 0, 62, 14, 0, 0, 67, 14, 0, 0, 73, 14, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 81, 14, 0, 0, 85, 14, 0, 0, 93, 14, 0, 0, 101, 14, 0, 0, 107, 14, 0, 0, 115, 14, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, + 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 123, 14, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 130, 14, 0, 0, 171, 23, 0, 0, 138, 14, 0, 0, 109, 22, 0, 0, 109, 22, 0, 0, 109, 22, 0, 0, 109, 22, 0, 0, 109, 22, 0, 0, 109, 22, 0, 0, 109, 22, 0, 0, 109, 22, 0, 0, 109, 22, 0, 0, 109, 22, 0, 0, + 109, 22, 0, 0, 109, 22, 0, 0, 109, 22, 0, 0, 109, 22, 0, 0, 109, 22, 0, 0, 109, 22, 0, 0, 109, 22, 0, 0, 109, 22, 0, 0, 109, 22, 0, 0, 109, 22, 0, 0, 109, 22, 0, 0, 109, 22, 0, 0, 109, 22, 0, 0, 109, 22, 0, 0, 109, 22, 0, 0, 109, 22, 0, 0, 109, 22, 0, 0, 109, 22, 0, 0, 146, 14, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 103, 23, 0, 0, 103, 23, 0, 0, 103, 23, 0, 0, + 154, 14, 0, 0, 109, 22, 0, 0, 109, 22, 0, 0, 109, 22, 0, 0, 109, 22, 0, 0, 109, 22, 0, 0, 109, 22, 0, 0, 162, 14, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, + 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, + 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 166, 14, 0, 0, 117, 22, 0, 0, 117, 22, 0, 0, 170, 14, 0, 0, 125, 22, 0, 0, 125, 22, 0, 0, 125, 22, 0, 0, + 125, 22, 0, 0, 125, 22, 0, 0, 125, 22, 0, 0, 125, 22, 0, 0, 125, 22, 0, 0, 125, 22, 0, 0, 125, 22, 0, 0, 125, 22, 0, 0, 125, 22, 0, 0, 125, 22, 0, 0, 125, 22, 0, 0, 125, 22, 0, 0, 125, 22, 0, 0, 125, 22, 0, 0, 125, 22, 0, 0, 127, 22, 0, 0, 125, 22, 0, 0, 135, 22, 0, 0, 125, 22, 0, 0, 125, 22, 0, 0, 125, 22, 0, 0, 125, 22, 0, 0, 125, 22, 0, 0, 125, 22, 0, 0, 138, 22, 0, 0, + 125, 22, 0, 0, 125, 22, 0, 0, 125, 22, 0, 0, 125, 22, 0, 0, 125, 22, 0, 0, 178, 14, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, + 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, + 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 146, 22, 0, 0, 146, 22, 0, 0, 146, 22, 0, 0, 146, 22, 0, 0, 146, 22, 0, 0, + 146, 22, 0, 0, 146, 22, 0, 0, 146, 22, 0, 0, 146, 22, 0, 0, 146, 22, 0, 0, 146, 22, 0, 0, 146, 22, 0, 0, 146, 22, 0, 0, 146, 22, 0, 0, 151, 22, 0, 0, 146, 22, 0, 0, 146, 22, 0, 0, 146, 22, 0, 0, 186, 14, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, + 137, 7, 0, 0, 137, 7, 0, 0, 190, 20, 0, 0, 190, 20, 0, 0, 190, 20, 0, 0, 190, 20, 0, 0, 190, 20, 0, 0, 190, 20, 0, 0, 190, 20, 0, 0, 190, 20, 0, 0, 190, 20, 0, 0, 190, 20, 0, 0, 190, 20, 0, 0, 190, 20, 0, 0, 190, 20, 0, 0, 190, 20, 0, 0, 190, 20, 0, 0, 190, 20, 0, 0, 190, 20, 0, 0, 194, 14, 0, 0, 202, 14, 0, 0, 210, 14, 0, 0, 159, 22, 0, 0, 214, 14, 0, 0, 222, 14, 0, 0, + 227, 14, 0, 0, 167, 22, 0, 0, 171, 22, 0, 0, 235, 14, 0, 0, 243, 14, 0, 0, 251, 14, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, + 137, 7, 0, 0, 137, 7, 0, 0, 84, 18, 0, 0, 14, 19, 0, 0, 3, 15, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 179, 22, 0, 0, 179, 22, 0, 0, 11, 15, 0, 0, 68, 23, 0, 0, 17, 15, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 25, 15, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, + 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, + 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, + 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 33, 15, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, + 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 195, 22, 0, 0, 195, 22, 0, 0, 195, 22, 0, 0, 195, 22, 0, 0, 195, 22, 0, 0, 195, 22, 0, 0, 195, 22, 0, 0, 195, 22, 0, 0, 195, 22, 0, 0, 195, 22, 0, 0, 195, 22, 0, 0, 195, 22, 0, 0, 195, 22, 0, 0, 195, 22, 0, 0, 41, 15, 0, 0, 137, 7, 0, 0, 49, 15, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, + 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, + 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, + 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 53, 15, 0, 0, 203, 22, 0, 0, 204, 22, 0, 0, 204, 22, 0, 0, 204, 22, 0, 0, 204, 22, 0, 0, 204, 22, 0, 0, 204, 22, 0, 0, 204, 22, 0, 0, 204, 22, 0, 0, 61, 15, 0, 0, 65, 15, 0, 0, 72, 15, 0, 0, 212, 22, 0, 0, 212, 22, 0, 0, 212, 22, 0, 0, + 212, 22, 0, 0, 212, 22, 0, 0, 212, 22, 0, 0, 212, 22, 0, 0, 212, 22, 0, 0, 212, 22, 0, 0, 212, 22, 0, 0, 212, 22, 0, 0, 76, 15, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, + 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 220, 22, 0, 0, + 220, 22, 0, 0, 220, 22, 0, 0, 84, 15, 0, 0, 89, 15, 0, 0, 97, 15, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, + 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, + 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 51, 5, 0, 0, 105, 15, 0, 0, 112, 15, 0, 0, 234, 24, 0, 0, 234, 24, 0, 0, 234, 24, 0, 0, 119, 15, 0, 0, 137, 7, 0, 0, 234, 24, 0, 0, 234, 24, 0, 0, 234, 24, 0, 0, 234, 24, 0, 0, 234, 24, 0, 0, 234, 24, 0, 0, + 234, 24, 0, 0, 127, 15, 0, 0, 234, 24, 0, 0, 135, 15, 0, 0, 234, 24, 0, 0, 28, 23, 0, 0, 36, 23, 0, 0, 42, 23, 0, 0, 234, 24, 0, 0, 106, 9, 0, 0, 134, 25, 0, 0, 134, 25, 0, 0, 143, 15, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 151, 15, 0, 0, 234, 24, 0, 0, 234, 24, 0, 0, 159, 15, 0, 0, 167, 15, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, + 137, 7, 0, 0, 92, 18, 0, 0, 99, 18, 0, 0, 175, 15, 0, 0, 102, 18, 0, 0, 183, 15, 0, 0, 191, 15, 0, 0, 199, 15, 0, 0, 96, 18, 0, 0, 207, 15, 0, 0, 215, 15, 0, 0, 223, 15, 0, 0, 101, 18, 0, 0, 109, 18, 0, 0, 92, 18, 0, 0, 99, 18, 0, 0, 95, 18, 0, 0, 102, 18, 0, 0, 110, 18, 0, 0, 93, 18, 0, 0, 100, 18, 0, 0, 96, 18, 0, 0, 230, 15, 0, 0, 118, 18, 0, 0, 126, 18, 0, 0, + 133, 18, 0, 0, 140, 18, 0, 0, 121, 18, 0, 0, 129, 18, 0, 0, 136, 18, 0, 0, 143, 18, 0, 0, 238, 15, 0, 0, 76, 23, 0, 0, 142, 25, 0, 0, 142, 25, 0, 0, 142, 25, 0, 0, 142, 25, 0, 0, 142, 25, 0, 0, 142, 25, 0, 0, 142, 25, 0, 0, 142, 25, 0, 0, 142, 25, 0, 0, 142, 25, 0, 0, 142, 25, 0, 0, 142, 25, 0, 0, 142, 25, 0, 0, 142, 25, 0, 0, 142, 25, 0, 0, 142, 25, 0, 0, 50, 23, 0, 0, + 53, 23, 0, 0, 50, 23, 0, 0, 60, 23, 0, 0, 246, 15, 0, 0, 254, 15, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, + 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 6, 16, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 14, 16, 0, 0, 22, 16, 0, 0, 137, 7, 0, 0, + 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 228, 22, 0, 0, 30, 16, 0, 0, 38, 16, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 42, 16, 0, 0, 47, 16, 0, 0, 236, 22, 0, 0, 55, 16, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, + 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, + 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 63, 16, 0, 0, 244, 22, 0, 0, 244, 22, 0, 0, 244, 22, 0, 0, 244, 22, 0, 0, 244, 22, 0, 0, 244, 22, 0, 0, 71, 16, 0, 0, 137, 7, 0, 0, 151, 18, 0, 0, 159, 18, 0, 0, 79, 16, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, + 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 87, 16, 0, 0, 179, 23, 0, 0, 92, 16, 0, 0, 137, 7, 0, 0, + 137, 7, 0, 0, 100, 16, 0, 0, 105, 16, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 113, 16, 0, 0, 121, 16, 0, 0, 129, 16, 0, 0, 137, 16, 0, 0, 145, 16, 0, 0, 153, 16, 0, 0, 137, 7, 0, 0, 160, 16, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, + 88, 25, 0, 0, 168, 16, 0, 0, 88, 25, 0, 0, 88, 25, 0, 0, 172, 16, 0, 0, 180, 16, 0, 0, 184, 16, 0, 0, 189, 16, 0, 0, 187, 23, 0, 0, 150, 25, 0, 0, 242, 24, 0, 0, 156, 25, 0, 0, 242, 24, 0, 0, 197, 16, 0, 0, 189, 10, 0, 0, 204, 16, 0, 0, 212, 16, 0, 0, 216, 16, 0, 0, 224, 16, 0, 0, 232, 16, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 88, 25, 0, 0, + 88, 25, 0, 0, 88, 25, 0, 0, 88, 25, 0, 0, 164, 25, 0, 0, 172, 25, 0, 0, 180, 25, 0, 0, 218, 24, 0, 0, 88, 25, 0, 0, 88, 25, 0, 0, 188, 25, 0, 0, 195, 25, 0, 0, 203, 25, 0, 0, 211, 25, 0, 0, 88, 25, 0, 0, 88, 25, 0, 0, 219, 25, 0, 0, 226, 25, 0, 0, 232, 25, 0, 0, 235, 25, 0, 0, 242, 25, 0, 0, 88, 25, 0, 0, 248, 25, 0, 0, 255, 25, 0, 0, 88, 25, 0, 0, 88, 25, 0, 0, + 6, 26, 0, 0, 10, 26, 0, 0, 88, 25, 0, 0, 18, 26, 0, 0, 240, 16, 0, 0, 248, 16, 0, 0, 234, 24, 0, 0, 234, 24, 0, 0, 234, 24, 0, 0, 0, 17, 0, 0, 234, 24, 0, 0, 234, 24, 0, 0, 8, 17, 0, 0, 16, 17, 0, 0, 24, 17, 0, 0, 234, 24, 0, 0, 30, 17, 0, 0, 234, 24, 0, 0, 38, 17, 0, 0, 43, 17, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 26, 26, 0, 0, 34, 26, 0, 0, 88, 25, 0, 0, + 42, 26, 0, 0, 88, 25, 0, 0, 48, 26, 0, 0, 55, 26, 0, 0, 88, 25, 0, 0, 234, 24, 0, 0, 234, 24, 0, 0, 0, 17, 0, 0, 51, 17, 0, 0, 59, 17, 0, 0, 64, 17, 0, 0, 72, 17, 0, 0, 80, 17, 0, 0, 234, 24, 0, 0, 234, 24, 0, 0, 234, 24, 0, 0, 234, 24, 0, 0, 88, 17, 0, 0, 234, 24, 0, 0, 106, 9, 0, 0, 96, 17, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, + 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, + 189, 10, 0, 0, 189, 10, 0, 0, 104, 17, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 189, 10, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 112, 17, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 120, 17, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 127, 17, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 135, 17, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, + 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, + 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, + 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 120, 17, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, + 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 104, 17, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, + 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 166, 20, 0, 0, 143, 17, 0, 0, + 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, + 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, + 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 189, 10, 0, 0, 104, 17, 0, 0, 151, 17, 0, 0, 219, 23, 0, 0, 219, 23, 0, 0, 219, 23, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 51, 5, 0, 0, 51, 5, 0, 0, 51, 5, 0, 0, + 51, 5, 0, 0, 51, 5, 0, 0, 51, 5, 0, 0, 51, 5, 0, 0, 159, 17, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, + 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, + 137, 7, 0, 0, 137, 7, 0, 0, 137, 7, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, + 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, + 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 227, 23, 0, 0, 167, 17, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, + 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, + 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, + 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 187, 22, 0, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 4, 0, 65, 128, 9, 0, 65, 192, 8, 0, 65, 192, 8, 0, 65, 64, 9, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, + 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, 101, 128, 10, 0, 91, 128, 1, 0, 91, 192, 0, 0, 91, 0, 3, 0, 94, 64, 2, 0, 91, 128, 2, 0, 91, 0, 3, 0, 91, 192, 0, 0, 92, 0, 0, 0, 88, 128, 0, 0, 91, 0, 3, 0, 96, 64, 2, 0, + 91, 0, 2, 0, 87, 0, 4, 0, 91, 0, 2, 0, 91, 192, 1, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 91, 0, 2, 0, 91, 0, 2, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 91, 128, 1, 0, 91, 0, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, + 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 92, 0, 0, 0, 91, 64, 2, 0, 88, 128, 0, 0, + 95, 0, 3, 0, 86, 0, 3, 0, 95, 0, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, + 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 92, 0, 0, 0, 96, 64, 4, 0, 88, 64, 0, 0, 96, 0, 3, 0, 65, 64, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, 64, 5, 0, 65, 64, 5, 0, + 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 192, 9, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, + 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, 65, 64, 5, 0, 101, 0, 1, 0, 91, 0, 0, 0, 94, 128, 2, 0, 94, 64, 2, 0, 94, 64, 2, 0, 94, 64, 2, 0, 97, 0, 3, 0, 91, 128, 8, 0, 95, 128, 8, 0, 97, 0, 3, 0, 10, 146, 8, 0, 90, 192, 0, 0, 96, 0, 3, 0, 66, 64, 4, 0, 97, 0, 3, 0, 95, 0, 3, 0, 97, 128, 2, 0, 96, 64, 2, 0, 84, 128, 8, 0, 84, 128, 8, 0, + 95, 128, 4, 0, 72, 0, 3, 0, 91, 128, 8, 0, 91, 128, 8, 0, 95, 128, 8, 0, 84, 128, 8, 0, 10, 146, 8, 0, 89, 192, 0, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 91, 0, 0, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, + 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 96, 128, 8, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, + 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 96, 128, 8, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, + 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, + 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, + 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, + 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, + 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, + 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, + 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, + 8, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 10, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 10, 18, 3, 0, 10, 18, 3, 0, 10, 18, 3, 0, 10, 18, 3, 0, 12, 18, 3, 0, 11, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 11, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 11, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, + 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, + 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 11, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, + 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, + 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, + 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, + 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, + 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 10, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, + 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, + 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 73, 0, 3, 0, 73, 0, 3, 0, 73, 0, 3, 0, 73, 0, 3, 0, 73, 0, 3, 0, 73, 0, 3, 0, 73, 0, 3, 0, 73, 0, 3, 0, 73, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 73, 0, 3, 0, 73, 128, 8, 0, 73, 128, 4, 0, 73, 128, 8, 0, 73, 128, 8, 0, 73, 128, 8, 0, + 73, 128, 4, 0, 73, 128, 8, 0, 73, 0, 3, 0, 73, 0, 3, 0, 73, 128, 8, 0, 73, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 95, 128, 8, 0, 95, 128, 8, 0, 95, 128, 8, 0, 95, 128, 8, 0, 95, 0, 3, 0, 95, 128, 8, 0, 95, 0, 3, 0, 95, 128, 4, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, + 95, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 31, 4, 3, 0, 31, 4, 3, 0, 73, 0, 3, 0, 95, 0, 3, 0, 73, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, + 95, 0, 3, 0, 95, 0, 3, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, + 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, + 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 0, 1, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, + 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 0, 1, 0, 144, 0, 1, 0, 144, 0, 1, 0, 144, 0, 1, 0, 144, 0, 1, 0, 144, 0, 1, 0, 144, 0, 1, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, + 144, 64, 5, 0, 144, 64, 5, 0, 140, 11, 3, 0, 136, 11, 3, 0, 140, 11, 3, 0, 136, 11, 3, 0, 73, 0, 3, 0, 159, 11, 3, 0, 140, 11, 3, 0, 136, 11, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 137, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 91, 0, 2, 0, 140, 11, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 159, 11, 3, 0, 95, 0, 3, 0, 140, 11, 3, 0, + 91, 0, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 3, 0, 0, 0, 140, 11, 3, 0, 3, 0, 0, 0, 140, 11, 3, 0, 140, 11, 3, 0, 136, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, + 140, 11, 3, 0, 140, 11, 3, 0, 3, 0, 0, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, + 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 140, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 140, 11, 3, 0, 136, 11, 3, 0, 140, 11, 3, 0, 136, 11, 3, 0, 140, 11, 3, 0, 136, 11, 3, 0, + 140, 11, 3, 0, 136, 11, 3, 0, 140, 11, 3, 0, 136, 11, 3, 0, 204, 6, 3, 0, 200, 6, 3, 0, 204, 6, 3, 0, 200, 6, 3, 0, 204, 6, 3, 0, 200, 6, 3, 0, 204, 6, 3, 0, 200, 6, 3, 0, 204, 6, 3, 0, 200, 6, 3, 0, 204, 6, 3, 0, 200, 6, 3, 0, 204, 6, 3, 0, 200, 6, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 140, 11, 3, 0, 136, 11, 3, 0, 160, 11, 3, 0, + 140, 11, 3, 0, 136, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, + 140, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, + 140, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 136, 7, 3, 0, 136, 7, 3, 0, 136, 7, 3, 0, 136, 7, 3, 0, 136, 7, 3, 0, 136, 7, 3, 0, 136, 7, 3, 0, 136, 7, 3, 0, 136, 7, 3, 0, 136, 7, 3, 0, 136, 7, 3, 0, 136, 7, 3, 0, 136, 7, 3, 0, 136, 7, 3, 0, 136, 7, 3, 0, 136, 7, 3, 0, 136, 7, 3, 0, + 136, 7, 3, 0, 136, 7, 3, 0, 136, 7, 3, 0, 136, 7, 3, 0, 136, 7, 3, 0, 136, 7, 3, 0, 136, 7, 3, 0, 136, 7, 3, 0, 136, 7, 3, 0, 136, 7, 3, 0, 136, 7, 3, 0, 136, 7, 3, 0, 136, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, + 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 161, 7, 3, 0, 144, 71, 5, 0, + 144, 71, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 71, 5, 0, 143, 71, 5, 0, 143, 71, 5, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, + 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, + 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, + 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, + 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 3, 0, 0, 0, + 12, 2, 3, 0, 12, 2, 3, 0, 12, 2, 3, 0, 12, 2, 3, 0, 12, 2, 3, 0, 12, 2, 3, 0, 12, 2, 3, 0, 12, 2, 3, 0, 12, 2, 3, 0, 12, 2, 3, 0, 12, 2, 3, 0, 12, 2, 3, 0, 12, 2, 3, 0, 12, 2, 3, 0, 12, 2, 3, 0, 12, 2, 3, 0, 12, 2, 3, 0, 12, 2, 3, 0, 12, 2, 3, 0, 12, 2, 3, 0, 12, 2, 3, 0, 12, 2, 3, 0, 12, 2, 3, 0, 12, 2, 3, 0, 12, 2, 3, 0, + 12, 2, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 9, 2, 3, 0, 27, 2, 3, 0, 27, 2, 3, 0, 27, 2, 3, 0, 27, 2, 3, 0, 27, 2, 3, 0, 27, 2, 3, 0, 8, 2, 3, 0, 8, 2, 3, 0, 8, 2, 3, 0, 8, 2, 3, 0, 8, 2, 3, 0, 8, 2, 3, 0, 8, 2, 3, 0, 8, 2, 3, 0, 8, 2, 3, 0, 8, 2, 3, 0, 8, 2, 3, 0, 8, 2, 3, 0, 8, 2, 3, 0, 8, 2, 3, 0, 8, 2, 3, 0, + 8, 2, 3, 0, 8, 2, 3, 0, 8, 2, 3, 0, 8, 2, 3, 0, 8, 2, 3, 0, 8, 2, 3, 0, 8, 2, 3, 0, 8, 2, 3, 0, 8, 2, 3, 0, 8, 2, 3, 0, 8, 2, 3, 0, 8, 2, 3, 0, 8, 2, 3, 0, 8, 2, 3, 0, 8, 2, 3, 0, 8, 2, 3, 0, 8, 2, 3, 0, 8, 2, 3, 0, 27, 2, 2, 0, 23, 66, 4, 0, 3, 0, 0, 0, 3, 0, 0, 0, 33, 2, 3, 0, 33, 2, 3, 0, 30, 66, 2, 0, + 3, 0, 0, 0, 80, 77, 5, 0, 80, 77, 5, 0, 80, 77, 5, 0, 80, 77, 5, 0, 80, 77, 5, 0, 80, 77, 5, 0, 80, 77, 5, 0, 80, 77, 5, 0, 80, 77, 5, 0, 80, 77, 5, 0, 80, 77, 5, 0, 80, 77, 5, 0, 80, 77, 5, 0, 80, 77, 5, 0, 80, 77, 5, 0, 80, 77, 5, 0, 80, 77, 5, 0, 80, 77, 5, 0, 80, 77, 5, 0, 80, 77, 5, 0, 80, 77, 5, 0, 80, 77, 5, 0, 80, 77, 5, 0, 80, 77, 5, 0, + 80, 77, 5, 0, 80, 77, 5, 0, 80, 77, 5, 0, 80, 77, 5, 0, 80, 77, 5, 0, 80, 77, 5, 0, 80, 77, 5, 0, 80, 77, 5, 0, 80, 77, 5, 0, 80, 77, 5, 0, 80, 77, 5, 0, 80, 77, 5, 0, 80, 77, 5, 0, 80, 77, 5, 0, 80, 77, 5, 0, 80, 77, 5, 0, 80, 77, 5, 0, 80, 77, 5, 0, 80, 77, 5, 0, 80, 77, 5, 0, 80, 77, 5, 0, 87, 77, 4, 0, 80, 77, 5, 0, 91, 13, 3, 0, 80, 77, 5, 0, + 80, 77, 5, 0, 91, 13, 3, 0, 80, 77, 5, 0, 80, 77, 5, 0, 91, 141, 1, 0, 80, 77, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, + 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 91, 13, 3, 0, + 91, 13, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 130, 1, 3, 0, 130, 1, 3, 0, 130, 1, 3, 0, 130, 1, 3, 0, 130, 1, 3, 0, 66, 0, 3, 0, 160, 1, 3, 0, 160, 1, 3, 0, 160, 1, 3, 0, 155, 129, 2, 0, 155, 129, 2, 0, 158, 129, 2, 0, 91, 0, 2, 0, + 155, 1, 2, 0, 161, 1, 3, 0, 161, 1, 3, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 91, 128, 1, 0, 130, 65, 5, 0, 155, 129, 1, 0, 155, 129, 1, 0, 91, 128, 1, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, + 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, + 138, 1, 3, 0, 73, 0, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, + 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 146, 193, 2, 0, 146, 193, 2, 0, 146, 193, 2, 0, 146, 193, 2, 0, 146, 193, 2, 0, 146, 193, 2, 0, 146, 193, 2, 0, 146, 193, 2, 0, 146, 193, 2, 0, 146, 193, 2, 0, 155, 129, 2, 0, 155, 193, 2, 0, 155, 193, 2, 0, 155, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 144, 64, 5, 0, + 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, + 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, + 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 155, 129, 1, 0, 138, 1, 3, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, + 144, 65, 5, 0, 66, 0, 3, 0, 161, 1, 3, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 137, 1, 3, 0, 137, 1, 3, 0, 144, 65, 5, 0, 144, 65, 5, 0, 161, 1, 3, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 138, 1, 3, 0, 138, 1, 3, 0, 146, 193, 2, 0, 146, 193, 2, 0, 146, 193, 2, 0, 146, 193, 2, 0, 146, 193, 2, 0, + 146, 193, 2, 0, 146, 193, 2, 0, 146, 193, 2, 0, 146, 193, 2, 0, 146, 193, 2, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 161, 1, 3, 0, 161, 1, 3, 0, 138, 1, 3, 0, 27, 34, 3, 0, 27, 34, 3, 0, 27, 34, 3, 0, 27, 34, 3, 0, 27, 34, 3, 0, 27, 34, 3, 0, 27, 34, 3, 0, 27, 34, 3, 0, 27, 34, 3, 0, 27, 34, 3, 0, 27, 34, 3, 0, 27, 34, 3, 0, 27, 34, 3, 0, 27, 34, 3, 0, + 3, 0, 0, 0, 2, 34, 3, 0, 10, 34, 3, 0, 16, 98, 5, 0, 10, 34, 3, 0, 10, 34, 3, 0, 10, 34, 3, 0, 10, 34, 3, 0, 10, 34, 3, 0, 10, 34, 3, 0, 10, 34, 3, 0, 10, 34, 3, 0, 10, 34, 3, 0, 10, 34, 3, 0, 10, 34, 3, 0, 10, 34, 3, 0, 10, 34, 3, 0, 10, 34, 3, 0, 10, 34, 3, 0, 10, 34, 3, 0, 10, 34, 3, 0, 10, 34, 3, 0, 10, 34, 3, 0, 10, 34, 3, 0, 10, 34, 3, 0, + 10, 34, 3, 0, 10, 34, 3, 0, 10, 34, 3, 0, 10, 34, 3, 0, 10, 34, 3, 0, 10, 34, 3, 0, 10, 34, 3, 0, 10, 34, 3, 0, 10, 34, 3, 0, 16, 98, 5, 0, 16, 98, 5, 0, 16, 98, 5, 0, 16, 98, 5, 0, 16, 98, 5, 0, 16, 98, 5, 0, 16, 98, 5, 0, 16, 98, 5, 0, 16, 98, 5, 0, 16, 98, 5, 0, 16, 98, 5, 0, 16, 98, 5, 0, 16, 98, 5, 0, 16, 98, 5, 0, 16, 98, 5, 0, 16, 98, 5, 0, + 16, 98, 5, 0, 16, 98, 5, 0, 16, 98, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 10, 34, 3, 0, 10, 34, 3, 0, 10, 34, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, + 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, + 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 202, 36, 3, 0, 202, 36, 3, 0, 202, 36, 3, 0, 202, 36, 3, 0, 202, 36, 3, 0, 202, 36, 3, 0, 202, 36, 3, 0, 202, 36, 3, 0, 202, 36, 3, 0, 202, 36, 3, 0, 202, 36, 3, 0, 202, 36, 3, 0, 202, 36, 3, 0, 202, 36, 3, 0, 202, 36, 3, 0, 202, 36, 3, 0, 202, 36, 3, 0, 202, 36, 3, 0, 202, 36, 3, 0, + 202, 36, 3, 0, 202, 36, 3, 0, 202, 36, 3, 0, 202, 36, 3, 0, 202, 36, 3, 0, 202, 36, 3, 0, 202, 36, 3, 0, 202, 36, 3, 0, 202, 36, 3, 0, 202, 36, 3, 0, 202, 36, 3, 0, 202, 36, 3, 0, 202, 36, 3, 0, 202, 36, 3, 0, 202, 36, 3, 0, 202, 36, 3, 0, 202, 36, 3, 0, 202, 36, 3, 0, 202, 36, 3, 0, 208, 100, 5, 0, 208, 100, 5, 0, 208, 100, 5, 0, 208, 100, 5, 0, 208, 100, 5, 0, 208, 100, 5, 0, + 208, 100, 5, 0, 208, 100, 5, 0, 208, 100, 5, 0, 208, 100, 5, 0, 208, 100, 5, 0, 202, 36, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 18, 217, 2, 0, 18, 217, 2, 0, 18, 217, 2, 0, 18, 217, 2, 0, 18, 217, 2, 0, + 18, 217, 2, 0, 18, 217, 2, 0, 18, 217, 2, 0, 18, 217, 2, 0, 18, 217, 2, 0, 10, 25, 3, 0, 10, 25, 3, 0, 10, 25, 3, 0, 10, 25, 3, 0, 10, 25, 3, 0, 10, 25, 3, 0, 10, 25, 3, 0, 10, 25, 3, 0, 10, 25, 3, 0, 10, 25, 3, 0, 10, 25, 3, 0, 10, 25, 3, 0, 10, 25, 3, 0, 10, 25, 3, 0, 10, 25, 3, 0, 10, 25, 3, 0, 10, 25, 3, 0, 10, 25, 3, 0, 10, 25, 3, 0, 10, 25, 3, 0, + 10, 25, 3, 0, 10, 25, 3, 0, 10, 25, 3, 0, 10, 25, 3, 0, 10, 25, 3, 0, 10, 25, 3, 0, 10, 25, 3, 0, 10, 25, 3, 0, 10, 25, 3, 0, 10, 25, 3, 0, 10, 25, 3, 0, 10, 25, 3, 0, 10, 25, 3, 0, 16, 89, 5, 0, 16, 89, 5, 0, 16, 89, 5, 0, 16, 89, 5, 0, 16, 89, 5, 0, 16, 89, 5, 0, 16, 89, 5, 0, 16, 89, 5, 0, 16, 89, 5, 0, 9, 25, 3, 0, 9, 25, 3, 0, 33, 25, 3, 0, + 27, 25, 3, 0, 27, 25, 2, 0, 27, 153, 1, 0, 9, 25, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 16, 89, 5, 0, 30, 89, 2, 0, 30, 89, 2, 0, 80, 94, 5, 0, 80, 94, 5, 0, 80, 94, 5, 0, 80, 94, 5, 0, 73, 30, 3, 0, 80, 94, 5, 0, 80, 94, 5, 0, 80, 94, 5, 0, 73, 30, 3, 0, 80, 94, 5, 0, 80, 94, 5, 0, 80, 94, 5, 0, 80, 94, 5, 0, 80, 94, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 91, 30, 3, 0, 91, 30, 3, 0, 91, 30, 3, 0, 91, 30, 3, 0, 91, 30, 3, 0, 91, 30, 3, 0, 91, 30, 3, 0, 91, 30, 3, 0, 91, 30, 3, 0, 91, 30, 3, 0, 91, 30, 3, 0, 91, 30, 3, 0, 91, 30, 3, 0, 91, 30, 3, 0, 91, 30, 3, 0, 3, 0, 0, 0, 138, 20, 3, 0, 138, 20, 3, 0, 138, 20, 3, 0, 138, 20, 3, 0, 138, 20, 3, 0, 138, 20, 3, 0, 138, 20, 3, 0, 138, 20, 3, 0, 138, 20, 3, 0, + 138, 20, 3, 0, 138, 20, 3, 0, 138, 20, 3, 0, 138, 20, 3, 0, 138, 20, 3, 0, 138, 20, 3, 0, 138, 20, 3, 0, 138, 20, 3, 0, 138, 20, 3, 0, 138, 20, 3, 0, 138, 20, 3, 0, 138, 20, 3, 0, 138, 20, 3, 0, 138, 20, 3, 0, 138, 20, 3, 0, 138, 20, 3, 0, 144, 84, 5, 0, 144, 84, 5, 0, 144, 84, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 155, 20, 3, 0, 3, 0, 0, 0, 10, 34, 3, 0, 10, 34, 3, 0, + 10, 34, 3, 0, 10, 34, 3, 0, 10, 34, 3, 0, 10, 34, 3, 0, 10, 34, 3, 0, 10, 34, 3, 0, 10, 34, 3, 0, 10, 34, 3, 0, 10, 34, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, + 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 159, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 3, 0, 0, 0, 130, 1, 3, 0, 130, 1, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, + 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 138, 3, 3, 0, 144, 67, 5, 0, 142, 67, 5, 0, 142, 67, 5, 0, 3, 0, 0, 0, 138, 3, 3, 0, 138, 3, 3, 0, 138, 3, 3, 0, 138, 3, 3, 0, 138, 3, 3, 0, 138, 3, 3, 0, 138, 3, 3, 0, 138, 3, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 138, 3, 3, 0, 138, 3, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 138, 3, 3, 0, 138, 3, 3, 0, + 138, 3, 3, 0, 138, 3, 3, 0, 138, 3, 3, 0, 138, 3, 3, 0, 138, 3, 3, 0, 138, 3, 3, 0, 138, 3, 3, 0, 138, 3, 3, 0, 138, 3, 3, 0, 138, 3, 3, 0, 138, 3, 3, 0, 138, 3, 3, 0, 3, 0, 0, 0, 138, 3, 3, 0, 138, 3, 3, 0, 138, 3, 3, 0, 138, 3, 3, 0, 138, 3, 3, 0, 138, 3, 3, 0, 138, 3, 3, 0, 3, 0, 0, 0, 138, 3, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 138, 3, 3, 0, 138, 3, 3, 0, 138, 3, 3, 0, 138, 3, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 144, 67, 5, 0, 138, 3, 3, 0, 142, 67, 5, 0, 142, 67, 5, 0, 142, 67, 5, 0, 144, 67, 5, 0, 144, 67, 5, 0, 144, 67, 5, 0, 144, 67, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 142, 67, 5, 0, 142, 67, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 142, 67, 5, 0, 142, 67, 5, 0, 144, 67, 5, 0, 138, 3, 3, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 142, 67, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 138, 3, 3, 0, 138, 3, 3, 0, 3, 0, 0, 0, 138, 3, 3, 0, 138, 3, 3, 0, 138, 3, 3, 0, 144, 67, 5, 0, 144, 67, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 146, 195, 2, 0, 146, 195, 2, 0, + 146, 195, 2, 0, 146, 195, 2, 0, 146, 195, 2, 0, 146, 195, 2, 0, 146, 195, 2, 0, 146, 195, 2, 0, 146, 195, 2, 0, 146, 195, 2, 0, 138, 3, 3, 0, 138, 3, 3, 0, 158, 131, 2, 0, 158, 131, 2, 0, 148, 3, 3, 0, 148, 3, 3, 0, 148, 3, 3, 0, 148, 3, 3, 0, 148, 3, 3, 0, 148, 131, 2, 0, 161, 3, 3, 0, 158, 67, 2, 0, 138, 3, 3, 0, 155, 3, 3, 0, 144, 67, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 16, 76, 5, 0, 16, 76, 5, 0, 14, 76, 5, 0, 3, 0, 0, 0, 10, 12, 3, 0, 10, 12, 3, 0, 10, 12, 3, 0, 10, 12, 3, 0, 10, 12, 3, 0, 10, 12, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 10, 12, 3, 0, 10, 12, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 10, 12, 3, 0, 10, 12, 3, 0, 10, 12, 3, 0, 10, 12, 3, 0, 10, 12, 3, 0, 10, 12, 3, 0, 10, 12, 3, 0, + 10, 12, 3, 0, 10, 12, 3, 0, 10, 12, 3, 0, 10, 12, 3, 0, 10, 12, 3, 0, 10, 12, 3, 0, 10, 12, 3, 0, 3, 0, 0, 0, 10, 12, 3, 0, 10, 12, 3, 0, 10, 12, 3, 0, 10, 12, 3, 0, 10, 12, 3, 0, 10, 12, 3, 0, 10, 12, 3, 0, 3, 0, 0, 0, 10, 12, 3, 0, 10, 12, 3, 0, 3, 0, 0, 0, 10, 12, 3, 0, 10, 12, 3, 0, 3, 0, 0, 0, 10, 12, 3, 0, 10, 12, 3, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 16, 76, 5, 0, 3, 0, 0, 0, 14, 76, 5, 0, 14, 76, 5, 0, 14, 76, 5, 0, 16, 76, 5, 0, 16, 76, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 16, 76, 5, 0, 16, 76, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 16, 76, 5, 0, 16, 76, 5, 0, 16, 76, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 16, 76, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 10, 12, 3, 0, 10, 12, 3, 0, 10, 12, 3, 0, 10, 12, 3, 0, 3, 0, 0, 0, 10, 12, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 18, 204, 2, 0, 18, 204, 2, 0, 18, 204, 2, 0, 18, 204, 2, 0, 18, 204, 2, 0, 18, 204, 2, 0, 18, 204, 2, 0, + 18, 204, 2, 0, 18, 204, 2, 0, 18, 204, 2, 0, 16, 76, 5, 0, 16, 76, 5, 0, 10, 12, 3, 0, 10, 12, 3, 0, 10, 12, 3, 0, 16, 76, 5, 0, 27, 12, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 208, 75, 5, 0, 208, 75, 5, 0, 206, 75, 5, 0, 3, 0, 0, 0, 202, 11, 3, 0, + 202, 11, 3, 0, 202, 11, 3, 0, 202, 11, 3, 0, 202, 11, 3, 0, 202, 11, 3, 0, 202, 11, 3, 0, 202, 11, 3, 0, 202, 11, 3, 0, 3, 0, 0, 0, 202, 11, 3, 0, 202, 11, 3, 0, 202, 11, 3, 0, 3, 0, 0, 0, 202, 11, 3, 0, 202, 11, 3, 0, 202, 11, 3, 0, 202, 11, 3, 0, 202, 11, 3, 0, 202, 11, 3, 0, 202, 11, 3, 0, 202, 11, 3, 0, 202, 11, 3, 0, 202, 11, 3, 0, 202, 11, 3, 0, 202, 11, 3, 0, + 202, 11, 3, 0, 202, 11, 3, 0, 3, 0, 0, 0, 202, 11, 3, 0, 202, 11, 3, 0, 202, 11, 3, 0, 202, 11, 3, 0, 202, 11, 3, 0, 202, 11, 3, 0, 202, 11, 3, 0, 3, 0, 0, 0, 202, 11, 3, 0, 202, 11, 3, 0, 3, 0, 0, 0, 202, 11, 3, 0, 202, 11, 3, 0, 202, 11, 3, 0, 202, 11, 3, 0, 202, 11, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 208, 75, 5, 0, 202, 11, 3, 0, 206, 75, 5, 0, 206, 75, 5, 0, + 206, 75, 5, 0, 208, 75, 5, 0, 208, 75, 5, 0, 208, 75, 5, 0, 208, 75, 5, 0, 208, 75, 5, 0, 3, 0, 0, 0, 208, 75, 5, 0, 208, 75, 5, 0, 206, 75, 5, 0, 3, 0, 0, 0, 206, 75, 5, 0, 206, 75, 5, 0, 208, 75, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 202, 11, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 202, 11, 3, 0, 202, 11, 3, 0, 208, 75, 5, 0, 208, 75, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 210, 203, 2, 0, 210, 203, 2, 0, 210, 203, 2, 0, 210, 203, 2, 0, 210, 203, 2, 0, 210, 203, 2, 0, 210, 203, 2, 0, 210, 203, 2, 0, 210, 203, 2, 0, 210, 203, 2, 0, 219, 11, 3, 0, 222, 75, 2, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 202, 11, 3, 0, 208, 75, 5, 0, 208, 75, 5, 0, 208, 75, 5, 0, 208, 75, 5, 0, 208, 75, 5, 0, 208, 75, 5, 0, 3, 0, 0, 0, 80, 90, 5, 0, 78, 90, 5, 0, 78, 90, 5, 0, 3, 0, 0, 0, 74, 26, 3, 0, 74, 26, 3, 0, 74, 26, 3, 0, 74, 26, 3, 0, 74, 26, 3, 0, 74, 26, 3, 0, + 74, 26, 3, 0, 74, 26, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 74, 26, 3, 0, 74, 26, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 74, 26, 3, 0, 74, 26, 3, 0, 74, 26, 3, 0, 74, 26, 3, 0, 74, 26, 3, 0, 74, 26, 3, 0, 74, 26, 3, 0, 74, 26, 3, 0, 74, 26, 3, 0, 74, 26, 3, 0, 74, 26, 3, 0, 74, 26, 3, 0, 74, 26, 3, 0, 74, 26, 3, 0, 3, 0, 0, 0, 74, 26, 3, 0, 74, 26, 3, 0, + 74, 26, 3, 0, 74, 26, 3, 0, 74, 26, 3, 0, 74, 26, 3, 0, 74, 26, 3, 0, 3, 0, 0, 0, 74, 26, 3, 0, 74, 26, 3, 0, 3, 0, 0, 0, 74, 26, 3, 0, 74, 26, 3, 0, 74, 26, 3, 0, 74, 26, 3, 0, 74, 26, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 80, 90, 5, 0, 74, 26, 3, 0, 78, 90, 5, 0, 80, 90, 5, 0, 78, 90, 5, 0, 80, 90, 5, 0, 80, 90, 5, 0, 80, 90, 5, 0, 80, 90, 5, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 78, 90, 5, 0, 78, 90, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 78, 90, 5, 0, 78, 90, 5, 0, 80, 90, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 80, 90, 5, 0, 80, 90, 5, 0, 78, 90, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 74, 26, 3, 0, 74, 26, 3, 0, + 3, 0, 0, 0, 74, 26, 3, 0, 74, 26, 3, 0, 74, 26, 3, 0, 80, 90, 5, 0, 80, 90, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 82, 218, 2, 0, 82, 218, 2, 0, 82, 218, 2, 0, 82, 218, 2, 0, 82, 218, 2, 0, 82, 218, 2, 0, 82, 218, 2, 0, 82, 218, 2, 0, 82, 218, 2, 0, 82, 218, 2, 0, 97, 26, 3, 0, 74, 26, 3, 0, 84, 26, 3, 0, 84, 26, 3, 0, 84, 26, 3, 0, 84, 26, 3, 0, 84, 26, 3, 0, + 84, 26, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 80, 99, 5, 0, 74, 35, 3, 0, 3, 0, 0, 0, 74, 35, 3, 0, 74, 35, 3, 0, 74, 35, 3, 0, 74, 35, 3, 0, 74, 35, 3, 0, 74, 35, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 74, 35, 3, 0, 74, 35, 3, 0, + 74, 35, 3, 0, 3, 0, 0, 0, 74, 35, 3, 0, 74, 35, 3, 0, 74, 35, 3, 0, 74, 35, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 74, 35, 3, 0, 74, 35, 3, 0, 3, 0, 0, 0, 74, 35, 3, 0, 3, 0, 0, 0, 74, 35, 3, 0, 74, 35, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 74, 35, 3, 0, 74, 35, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 74, 35, 3, 0, + 74, 35, 3, 0, 74, 35, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 74, 35, 3, 0, 74, 35, 3, 0, 74, 35, 3, 0, 74, 35, 3, 0, 74, 35, 3, 0, 74, 35, 3, 0, 74, 35, 3, 0, 74, 35, 3, 0, 74, 35, 3, 0, 74, 35, 3, 0, 74, 35, 3, 0, 74, 35, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 78, 99, 5, 0, 78, 99, 5, 0, 80, 99, 5, 0, 78, 99, 5, 0, + 78, 99, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 78, 99, 5, 0, 78, 99, 5, 0, 78, 99, 5, 0, 3, 0, 0, 0, 78, 99, 5, 0, 78, 99, 5, 0, 78, 99, 5, 0, 80, 99, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 74, 35, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 78, 99, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 82, 227, 2, 0, 82, 227, 2, 0, 82, 227, 2, 0, 82, 227, 2, 0, 82, 227, 2, 0, 82, 227, 2, 0, 82, 227, 2, 0, 82, 227, 2, 0, 82, 227, 2, 0, 82, 227, 2, 0, 84, 35, 3, 0, 84, 35, 3, 0, 84, 35, 3, 0, 97, 35, 3, 0, 97, 35, 3, 0, 97, 35, 3, 0, 97, 35, 3, 0, 97, 35, 3, 0, + 97, 35, 3, 0, 94, 99, 2, 0, 97, 35, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 16, 100, 5, 0, 14, 100, 5, 0, 14, 100, 5, 0, 14, 100, 5, 0, 16, 100, 5, 0, 10, 36, 3, 0, 10, 36, 3, 0, 10, 36, 3, 0, 10, 36, 3, 0, 10, 36, 3, 0, 10, 36, 3, 0, 10, 36, 3, 0, 10, 36, 3, 0, 3, 0, 0, 0, 10, 36, 3, 0, 10, 36, 3, 0, 10, 36, 3, 0, + 3, 0, 0, 0, 10, 36, 3, 0, 10, 36, 3, 0, 10, 36, 3, 0, 10, 36, 3, 0, 10, 36, 3, 0, 10, 36, 3, 0, 10, 36, 3, 0, 10, 36, 3, 0, 10, 36, 3, 0, 10, 36, 3, 0, 10, 36, 3, 0, 10, 36, 3, 0, 10, 36, 3, 0, 10, 36, 3, 0, 10, 36, 3, 0, 3, 0, 0, 0, 10, 36, 3, 0, 10, 36, 3, 0, 10, 36, 3, 0, 10, 36, 3, 0, 10, 36, 3, 0, 10, 36, 3, 0, 10, 36, 3, 0, 10, 36, 3, 0, + 10, 36, 3, 0, 10, 36, 3, 0, 10, 36, 3, 0, 10, 36, 3, 0, 10, 36, 3, 0, 10, 36, 3, 0, 10, 36, 3, 0, 10, 36, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 16, 100, 5, 0, 10, 36, 3, 0, 16, 100, 5, 0, 16, 100, 5, 0, 16, 100, 5, 0, 14, 100, 5, 0, 14, 100, 5, 0, 14, 100, 5, 0, 14, 100, 5, 0, 3, 0, 0, 0, 16, 100, 5, 0, 16, 100, 5, 0, 16, 100, 5, 0, 3, 0, 0, 0, 16, 100, 5, 0, + 16, 100, 5, 0, 16, 100, 5, 0, 16, 100, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 16, 100, 5, 0, 16, 100, 5, 0, 3, 0, 0, 0, 10, 36, 3, 0, 10, 36, 3, 0, 10, 36, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 10, 36, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 10, 36, 3, 0, 10, 36, 3, 0, 16, 100, 5, 0, 16, 100, 5, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 18, 228, 2, 0, 18, 228, 2, 0, 18, 228, 2, 0, 18, 228, 2, 0, 18, 228, 2, 0, 18, 228, 2, 0, 18, 228, 2, 0, 18, 228, 2, 0, 18, 228, 2, 0, 18, 228, 2, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 27, 164, 4, 0, 20, 36, 3, 0, 20, 36, 3, 0, 20, 36, 3, 0, 20, 36, 3, 0, 20, 36, 3, 0, + 20, 36, 3, 0, 20, 36, 3, 0, 33, 36, 3, 0, 10, 17, 3, 0, 16, 81, 5, 0, 14, 81, 5, 0, 14, 81, 5, 0, 27, 145, 4, 0, 10, 17, 3, 0, 10, 17, 3, 0, 10, 17, 3, 0, 10, 17, 3, 0, 10, 17, 3, 0, 10, 17, 3, 0, 10, 17, 3, 0, 10, 17, 3, 0, 3, 0, 0, 0, 10, 17, 3, 0, 10, 17, 3, 0, 10, 17, 3, 0, 3, 0, 0, 0, 10, 17, 3, 0, 10, 17, 3, 0, 10, 17, 3, 0, 10, 17, 3, 0, + 10, 17, 3, 0, 10, 17, 3, 0, 10, 17, 3, 0, 10, 17, 3, 0, 10, 17, 3, 0, 10, 17, 3, 0, 10, 17, 3, 0, 10, 17, 3, 0, 10, 17, 3, 0, 10, 17, 3, 0, 10, 17, 3, 0, 3, 0, 0, 0, 10, 17, 3, 0, 10, 17, 3, 0, 10, 17, 3, 0, 10, 17, 3, 0, 10, 17, 3, 0, 10, 17, 3, 0, 10, 17, 3, 0, 10, 17, 3, 0, 10, 17, 3, 0, 10, 17, 3, 0, 3, 0, 0, 0, 10, 17, 3, 0, 10, 17, 3, 0, + 10, 17, 3, 0, 10, 17, 3, 0, 10, 17, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 16, 81, 5, 0, 10, 17, 3, 0, 14, 81, 5, 0, 16, 81, 5, 0, 14, 81, 5, 0, 14, 81, 5, 0, 14, 81, 5, 0, 14, 81, 5, 0, 14, 81, 5, 0, 3, 0, 0, 0, 16, 81, 5, 0, 14, 81, 5, 0, 14, 81, 5, 0, 3, 0, 0, 0, 14, 81, 5, 0, 14, 81, 5, 0, 16, 81, 5, 0, 16, 81, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 14, 81, 5, 0, 14, 81, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 10, 17, 3, 0, 10, 17, 3, 0, 3, 0, 0, 0, 10, 17, 3, 0, 10, 17, 3, 0, 16, 81, 5, 0, 16, 81, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 18, 209, 2, 0, 18, 209, 2, 0, 18, 209, 2, 0, + 18, 209, 2, 0, 18, 209, 2, 0, 18, 209, 2, 0, 18, 209, 2, 0, 18, 209, 2, 0, 18, 209, 2, 0, 18, 209, 2, 0, 3, 0, 0, 0, 10, 17, 3, 0, 10, 17, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 80, 86, 5, 0, 80, 86, 5, 0, + 78, 86, 5, 0, 78, 86, 5, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 3, 0, 0, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 3, 0, 0, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, + 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 78, 86, 5, 0, 80, 86, 5, 0, 80, 86, 5, 0, 80, 86, 5, 0, 80, 86, 5, 0, 3, 0, 0, 0, 78, 86, 5, 0, 78, 86, 5, 0, 78, 86, 5, 0, 3, 0, 0, 0, 78, 86, 5, 0, 78, 86, 5, 0, 78, 86, 5, 0, 80, 86, 5, 0, 74, 22, 3, 0, 97, 22, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 78, 86, 5, 0, 84, 22, 3, 0, 84, 22, 3, 0, 84, 22, 3, 0, 84, 22, 3, 0, 84, 22, 3, 0, 84, 22, 3, 0, 84, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 80, 86, 5, 0, 80, 86, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 82, 214, 2, 0, 82, 214, 2, 0, 82, 214, 2, 0, 82, 214, 2, 0, 82, 214, 2, 0, 82, 214, 2, 0, 82, 214, 2, 0, + 82, 214, 2, 0, 82, 214, 2, 0, 82, 214, 2, 0, 84, 22, 3, 0, 84, 22, 3, 0, 84, 22, 3, 0, 84, 22, 3, 0, 84, 22, 3, 0, 84, 22, 3, 0, 84, 22, 3, 0, 84, 22, 3, 0, 84, 22, 3, 0, 97, 150, 2, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 3, 0, 0, 0, 80, 96, 5, 0, 78, 96, 5, 0, 78, 96, 5, 0, 3, 0, 0, 0, 74, 32, 3, 0, + 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, + 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, 3, 0, 0, 0, 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, + 3, 0, 0, 0, 74, 32, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, 74, 32, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 80, 96, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 78, 96, 5, 0, 78, 96, 5, 0, 78, 96, 5, 0, 80, 96, 5, 0, 80, 96, 5, 0, 80, 96, 5, 0, + 3, 0, 0, 0, 80, 96, 5, 0, 3, 0, 0, 0, 78, 96, 5, 0, 78, 96, 5, 0, 78, 96, 5, 0, 78, 96, 5, 0, 78, 96, 5, 0, 78, 96, 5, 0, 78, 96, 5, 0, 78, 96, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 82, 224, 2, 0, 82, 224, 2, 0, 82, 224, 2, 0, 82, 224, 2, 0, 82, 224, 2, 0, 82, 224, 2, 0, 82, 224, 2, 0, 82, 224, 2, 0, + 82, 224, 2, 0, 82, 224, 2, 0, 3, 0, 0, 0, 3, 0, 0, 0, 78, 96, 5, 0, 78, 96, 5, 0, 91, 32, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 10, 37, 10, 0, 10, 37, 10, 0, 10, 37, 10, 0, 10, 37, 10, 0, 10, 37, 10, 0, 10, 37, 10, 0, + 10, 37, 10, 0, 10, 37, 10, 0, 10, 37, 10, 0, 10, 37, 10, 0, 10, 37, 10, 0, 10, 37, 10, 0, 10, 37, 10, 0, 10, 37, 10, 0, 10, 37, 10, 0, 10, 37, 10, 0, 10, 37, 10, 0, 10, 37, 10, 0, 10, 37, 10, 0, 10, 37, 10, 0, 10, 37, 10, 0, 10, 37, 10, 0, 10, 37, 10, 0, 10, 37, 10, 0, 10, 37, 10, 0, 10, 37, 10, 0, 10, 37, 10, 0, 10, 37, 10, 0, 10, 37, 10, 0, 10, 37, 10, 0, 10, 37, 10, 0, + 10, 37, 10, 0, 16, 37, 10, 0, 10, 37, 10, 0, 10, 37, 10, 0, 16, 37, 10, 0, 16, 37, 10, 0, 16, 37, 10, 0, 16, 37, 10, 0, 16, 37, 10, 0, 16, 37, 10, 0, 16, 37, 10, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 94, 64, 2, 0, 10, 37, 10, 0, 10, 37, 10, 0, 10, 37, 10, 0, 10, 37, 10, 0, 10, 37, 10, 0, 10, 37, 10, 0, 9, 37, 10, 0, 16, 37, 10, 0, 16, 37, 10, 0, + 16, 37, 10, 0, 16, 37, 10, 0, 16, 37, 10, 0, 16, 37, 10, 0, 16, 37, 10, 0, 16, 37, 10, 0, 27, 37, 3, 0, 18, 229, 2, 0, 18, 229, 2, 0, 18, 229, 2, 0, 18, 229, 2, 0, 18, 229, 2, 0, 18, 229, 2, 0, 18, 229, 2, 0, 18, 229, 2, 0, 18, 229, 2, 0, 18, 229, 2, 0, 27, 101, 4, 0, 27, 101, 4, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 202, 17, 10, 0, 202, 17, 10, 0, 3, 0, 0, 0, 202, 17, 10, 0, 3, 0, 0, 0, 202, 17, 10, 0, 202, 17, 10, 0, 202, 17, 10, 0, 202, 17, 10, 0, 202, 17, 10, 0, 3, 0, 0, 0, 202, 17, 10, 0, 202, 17, 10, 0, 202, 17, 10, 0, 202, 17, 10, 0, 202, 17, 10, 0, 202, 17, 10, 0, 202, 17, 10, 0, 202, 17, 10, 0, 202, 17, 10, 0, 202, 17, 10, 0, 202, 17, 10, 0, 202, 17, 10, 0, + 202, 17, 10, 0, 202, 17, 10, 0, 202, 17, 10, 0, 202, 17, 10, 0, 202, 17, 10, 0, 202, 17, 10, 0, 202, 17, 10, 0, 202, 17, 10, 0, 3, 0, 0, 0, 202, 17, 10, 0, 3, 0, 0, 0, 202, 17, 10, 0, 202, 17, 10, 0, 202, 17, 10, 0, 202, 17, 10, 0, 202, 17, 10, 0, 202, 17, 10, 0, 202, 17, 10, 0, 202, 17, 10, 0, 202, 17, 10, 0, 202, 17, 10, 0, 208, 17, 10, 0, 202, 17, 10, 0, 202, 17, 10, 0, 208, 17, 10, 0, + 208, 17, 10, 0, 208, 17, 10, 0, 208, 17, 10, 0, 208, 17, 10, 0, 208, 17, 10, 0, 208, 17, 10, 0, 208, 17, 10, 0, 208, 17, 10, 0, 202, 17, 10, 0, 3, 0, 0, 0, 3, 0, 0, 0, 202, 17, 10, 0, 202, 17, 10, 0, 202, 17, 10, 0, 202, 17, 10, 0, 202, 17, 10, 0, 3, 0, 0, 0, 201, 17, 10, 0, 3, 0, 0, 0, 208, 17, 10, 0, 208, 17, 10, 0, 208, 17, 10, 0, 208, 17, 10, 0, 208, 17, 10, 0, 208, 17, 10, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 210, 209, 2, 0, 210, 209, 2, 0, 210, 209, 2, 0, 210, 209, 2, 0, 210, 209, 2, 0, 210, 209, 2, 0, 210, 209, 2, 0, 210, 209, 2, 0, 210, 209, 2, 0, 210, 209, 2, 0, 3, 0, 0, 0, 3, 0, 0, 0, 202, 17, 10, 0, 202, 17, 10, 0, 202, 17, 10, 0, 202, 17, 10, 0, 74, 37, 3, 0, 74, 37, 3, 0, 74, 37, 3, 0, 74, 37, 3, 0, 74, 37, 3, 0, 74, 37, 3, 0, 74, 37, 3, 0, + 74, 37, 3, 0, 3, 0, 0, 0, 74, 37, 3, 0, 74, 37, 3, 0, 74, 37, 3, 0, 74, 37, 3, 0, 74, 37, 3, 0, 74, 37, 3, 0, 74, 37, 3, 0, 74, 37, 3, 0, 74, 37, 3, 0, 74, 37, 3, 0, 74, 37, 3, 0, 74, 37, 3, 0, 74, 37, 3, 0, 74, 37, 3, 0, 74, 37, 3, 0, 74, 37, 3, 0, 74, 37, 3, 0, 74, 37, 3, 0, 74, 37, 3, 0, 74, 37, 3, 0, 74, 37, 3, 0, 74, 37, 3, 0, 74, 37, 3, 0, + 74, 37, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 78, 101, 4, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, + 91, 101, 4, 0, 80, 101, 5, 0, 80, 101, 5, 0, 74, 37, 3, 0, 74, 37, 3, 0, 74, 37, 3, 0, 74, 37, 3, 0, 74, 37, 3, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 3, 0, 0, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, + 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, 80, 101, 5, 0, + 80, 101, 5, 0, 80, 101, 5, 0, 3, 0, 0, 0, 97, 101, 4, 0, 97, 101, 4, 0, 97, 37, 3, 0, 97, 37, 3, 0, 97, 37, 3, 0, 97, 37, 3, 0, 97, 37, 3, 0, 97, 37, 3, 0, 80, 101, 5, 0, 97, 37, 3, 0, 97, 37, 3, 0, 97, 37, 3, 0, 97, 37, 3, 0, 97, 37, 3, 0, 97, 37, 3, 0, 3, 0, 0, 0, 97, 37, 3, 0, 97, 37, 3, 0, 91, 165, 4, 0, 91, 165, 4, 0, 91, 101, 4, 0, 91, 165, 4, 0, + 91, 37, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 91, 37, 1, 0, 91, 37, 1, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 3, 0, 0, 0, 12, 10, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 12, 10, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, + 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 3, 0, 0, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 3, 0, 0, 0, 202, 9, 3, 0, 3, 0, 0, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 3, 0, 0, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, + 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 3, 0, 0, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 3, 0, 0, 0, 202, 9, 3, 0, + 3, 0, 0, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 3, 0, 0, 0, 202, 9, 3, 0, 202, 9, 3, 0, + 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 3, 0, 0, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, + 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 208, 73, 5, 0, 208, 73, 5, 0, 208, 73, 5, 0, 219, 9, 3, 0, 219, 73, 4, 0, 219, 9, 3, 0, 219, 9, 3, 0, 219, 9, 3, 0, 219, 9, 3, 0, 219, 9, 3, 0, 219, 9, 3, 0, 219, 9, 3, 0, 212, 9, 3, 0, 212, 9, 3, 0, 212, 9, 3, 0, 212, 9, 3, 0, 212, 9, 3, 0, 212, 9, 3, 0, 212, 9, 3, 0, 212, 9, 3, 0, 212, 9, 3, 0, 212, 9, 3, 0, 212, 9, 3, 0, 212, 9, 3, 0, + 212, 9, 3, 0, 212, 9, 3, 0, 212, 9, 3, 0, 212, 9, 3, 0, 212, 9, 3, 0, 212, 9, 3, 0, 212, 9, 3, 0, 212, 9, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, + 202, 9, 3, 0, 202, 9, 3, 0, 225, 9, 3, 0, 225, 9, 3, 0, 225, 9, 3, 0, 225, 9, 3, 0, 225, 9, 3, 0, 225, 9, 3, 0, 225, 9, 3, 0, 225, 9, 3, 0, 225, 9, 3, 0, 225, 9, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, + 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 165, 89, 4, 0, 138, 25, 3, 0, 138, 25, 3, 0, 138, 25, 3, 0, 138, 25, 3, 0, 138, 25, 3, 0, 138, 25, 3, 0, 138, 25, 3, 0, 138, 25, 3, 0, 138, 25, 3, 0, 138, 25, 3, 0, 138, 25, 3, 0, 138, 25, 3, 0, 138, 25, 3, 0, 138, 25, 3, 0, 138, 25, 3, 0, 138, 25, 3, 0, 138, 25, 3, 0, 138, 25, 3, 0, 138, 25, 3, 0, 138, 25, 3, 0, 138, 25, 3, 0, 138, 25, 3, 0, 138, 25, 3, 0, 138, 25, 3, 0, + 138, 25, 3, 0, 138, 25, 3, 0, 156, 25, 0, 0, 152, 89, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 10, 30, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, 91, 64, 4, 0, 91, 64, 4, 0, 91, 64, 4, 0, 19, 30, 3, 0, 19, 30, 3, 0, 19, 30, 3, 0, 10, 30, 3, 0, + 10, 30, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 138, 36, 3, 0, 138, 36, 3, 0, 138, 36, 3, 0, 138, 36, 3, 0, 138, 36, 3, 0, 138, 36, 3, 0, 138, 36, 3, 0, 138, 36, 3, 0, 138, 36, 3, 0, 138, 36, 3, 0, 138, 36, 3, 0, + 138, 36, 3, 0, 138, 36, 3, 0, 138, 36, 3, 0, 138, 36, 3, 0, 138, 36, 3, 0, 138, 36, 3, 0, 138, 36, 3, 0, 144, 100, 5, 0, 144, 100, 5, 0, 144, 100, 5, 0, 142, 100, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 138, 36, 3, 0, 202, 12, 3, 0, 202, 12, 3, 0, 202, 12, 3, 0, 202, 12, 3, 0, + 202, 12, 3, 0, 202, 12, 3, 0, 202, 12, 3, 0, 202, 12, 3, 0, 202, 12, 3, 0, 202, 12, 3, 0, 202, 12, 3, 0, 202, 12, 3, 0, 202, 12, 3, 0, 202, 12, 3, 0, 202, 12, 3, 0, 202, 12, 3, 0, 202, 12, 3, 0, 202, 12, 3, 0, 208, 76, 5, 0, 208, 76, 5, 0, 206, 76, 5, 0, 91, 64, 4, 0, 91, 64, 4, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 10, 5, 3, 0, 10, 5, 3, 0, 10, 5, 3, 0, 10, 5, 3, 0, 10, 5, 3, 0, 10, 5, 3, 0, 10, 5, 3, 0, 10, 5, 3, 0, 10, 5, 3, 0, 10, 5, 3, 0, 10, 5, 3, 0, 10, 5, 3, 0, 10, 5, 3, 0, 10, 5, 3, 0, 10, 5, 3, 0, 10, 5, 3, 0, 10, 5, 3, 0, 10, 5, 3, 0, 16, 69, 5, 0, 16, 69, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 74, 34, 3, 0, 74, 34, 3, 0, 74, 34, 3, 0, 74, 34, 3, 0, 74, 34, 3, 0, 74, 34, 3, 0, 74, 34, 3, 0, 74, 34, 3, 0, 74, 34, 3, 0, 74, 34, 3, 0, 74, 34, 3, 0, 74, 34, 3, 0, 74, 34, 3, 0, 3, 0, 0, 0, 74, 34, 3, 0, + 74, 34, 3, 0, 74, 34, 3, 0, 3, 0, 0, 0, 80, 98, 5, 0, 80, 98, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 78, 16, 10, 0, 78, 16, 10, 0, 78, 16, 10, 0, 78, 16, 10, 0, 78, 16, 10, 0, 78, 16, 10, 0, 80, 16, 10, 0, 78, 16, 10, 0, + 78, 16, 10, 0, 80, 16, 10, 0, 80, 16, 10, 0, 80, 16, 10, 0, 80, 16, 10, 0, 80, 16, 10, 0, 80, 16, 10, 0, 80, 16, 10, 0, 80, 16, 10, 0, 80, 16, 10, 0, 80, 16, 10, 0, 80, 16, 10, 0, 91, 80, 4, 0, 91, 80, 4, 0, 91, 80, 1, 0, 73, 16, 10, 0, 91, 80, 4, 0, 91, 16, 3, 0, 91, 80, 4, 0, 94, 80, 2, 0, 74, 16, 10, 0, 80, 16, 10, 0, 3, 0, 0, 0, 3, 0, 0, 0, 82, 208, 2, 0, + 82, 208, 2, 0, 82, 208, 2, 0, 82, 208, 2, 0, 82, 208, 2, 0, 82, 208, 2, 0, 82, 208, 2, 0, 82, 208, 2, 0, 82, 208, 2, 0, 82, 208, 2, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 84, 16, 3, 0, 84, 16, 3, 0, 84, 16, 3, 0, 84, 16, 3, 0, 84, 16, 3, 0, 84, 16, 3, 0, 84, 16, 3, 0, 84, 16, 3, 0, 84, 16, 3, 0, 84, 16, 3, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 219, 22, 3, 0, 219, 22, 3, 0, 91, 128, 1, 0, 91, 128, 1, 0, 219, 86, 4, 0, 91, 64, 4, 0, 215, 150, 4, 0, 219, 22, 3, 0, 219, 150, 1, 0, 219, 150, 1, 0, 219, 22, 3, 0, 208, 86, 5, 0, 208, 86, 5, 0, 208, 86, 5, 0, 194, 22, 1, 0, 208, 86, 5, 0, 210, 214, 2, 0, 210, 214, 2, 0, 210, 214, 2, 0, + 210, 214, 2, 0, 210, 214, 2, 0, 210, 214, 2, 0, 210, 214, 2, 0, 210, 214, 2, 0, 210, 214, 2, 0, 210, 214, 2, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, + 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, + 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 208, 86, 5, 0, 202, 22, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, + 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 138, 18, 3, 0, 138, 18, 3, 0, 138, 18, 3, 0, 138, 18, 3, 0, 138, 18, 3, 0, 138, 18, 3, 0, 138, 18, 3, 0, + 138, 18, 3, 0, 138, 18, 3, 0, 138, 18, 3, 0, 138, 18, 3, 0, 138, 18, 3, 0, 138, 18, 3, 0, 138, 18, 3, 0, 138, 18, 3, 0, 138, 18, 3, 0, 138, 18, 3, 0, 138, 18, 3, 0, 138, 18, 3, 0, 138, 18, 3, 0, 138, 18, 3, 0, 138, 18, 3, 0, 138, 18, 3, 0, 138, 18, 3, 0, 138, 18, 3, 0, 138, 18, 3, 0, 138, 18, 3, 0, 138, 18, 3, 0, 138, 18, 3, 0, 138, 18, 3, 0, 138, 18, 3, 0, 3, 0, 0, 0, + 144, 82, 5, 0, 144, 82, 5, 0, 144, 82, 5, 0, 142, 82, 5, 0, 142, 82, 5, 0, 142, 82, 5, 0, 142, 82, 5, 0, 144, 82, 5, 0, 144, 82, 5, 0, 142, 82, 5, 0, 142, 82, 5, 0, 142, 82, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 142, 82, 5, 0, 142, 82, 5, 0, 144, 82, 5, 0, 142, 82, 5, 0, 142, 82, 5, 0, 142, 82, 5, 0, 142, 82, 5, 0, 142, 82, 5, 0, 142, 82, 5, 0, + 144, 82, 5, 0, 144, 82, 5, 0, 144, 82, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 161, 18, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 155, 146, 1, 0, 155, 146, 1, 0, 146, 210, 2, 0, 146, 210, 2, 0, 146, 210, 2, 0, 146, 210, 2, 0, 146, 210, 2, 0, 146, 210, 2, 0, 146, 210, 2, 0, 146, 210, 2, 0, 146, 210, 2, 0, 146, 210, 2, 0, 202, 34, 10, 0, 202, 34, 10, 0, + 202, 34, 10, 0, 202, 34, 10, 0, 202, 34, 10, 0, 202, 34, 10, 0, 202, 34, 10, 0, 202, 34, 10, 0, 202, 34, 10, 0, 202, 34, 10, 0, 202, 34, 10, 0, 202, 34, 10, 0, 202, 34, 10, 0, 202, 34, 10, 0, 202, 34, 10, 0, 202, 34, 10, 0, 202, 34, 10, 0, 202, 34, 10, 0, 3, 0, 0, 0, 3, 0, 0, 0, 202, 34, 10, 0, 202, 34, 10, 0, 202, 34, 10, 0, 202, 34, 10, 0, 202, 34, 10, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 18, 227, 2, 0, + 18, 227, 2, 0, 18, 227, 2, 0, 18, 227, 2, 0, 18, 227, 2, 0, 18, 227, 2, 0, 18, 227, 2, 0, 18, 227, 2, 0, 18, 227, 2, 0, 18, 227, 2, 0, 20, 35, 10, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 33, 35, 10, 0, 33, 35, 10, 0, 202, 4, 3, 0, 202, 4, 3, 0, 202, 4, 3, 0, 202, 4, 3, 0, 202, 4, 3, 0, 202, 4, 3, 0, 202, 4, 3, 0, 202, 4, 3, 0, 202, 4, 3, 0, 202, 4, 3, 0, + 202, 4, 3, 0, 202, 4, 3, 0, 202, 4, 3, 0, 202, 4, 3, 0, 202, 4, 3, 0, 202, 4, 3, 0, 202, 4, 3, 0, 202, 4, 3, 0, 202, 4, 3, 0, 202, 4, 3, 0, 202, 4, 3, 0, 202, 4, 3, 0, 202, 4, 3, 0, 208, 68, 5, 0, 208, 68, 5, 0, 206, 68, 5, 0, 206, 68, 5, 0, 208, 68, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 219, 4, 3, 0, 219, 4, 3, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, + 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 142, 17, 10, 0, 144, 17, 10, 0, 142, 17, 10, 0, 144, 17, 10, 0, 144, 17, 10, 0, 144, 17, 10, 0, 144, 17, 10, 0, + 144, 17, 10, 0, 144, 17, 10, 0, 144, 17, 10, 0, 3, 0, 0, 0, 144, 17, 10, 0, 142, 17, 10, 0, 144, 17, 10, 0, 142, 17, 10, 0, 142, 17, 10, 0, 144, 17, 10, 0, 144, 17, 10, 0, 144, 17, 10, 0, 144, 17, 10, 0, 144, 17, 10, 0, 144, 17, 10, 0, 144, 17, 10, 0, 144, 17, 10, 0, 142, 17, 10, 0, 142, 17, 10, 0, 142, 17, 10, 0, 142, 17, 10, 0, 142, 17, 10, 0, 142, 17, 10, 0, 144, 17, 10, 0, 144, 17, 10, 0, + 144, 17, 10, 0, 144, 17, 10, 0, 144, 17, 10, 0, 144, 17, 10, 0, 144, 17, 10, 0, 144, 17, 10, 0, 144, 17, 10, 0, 144, 17, 10, 0, 3, 0, 0, 0, 3, 0, 0, 0, 144, 81, 5, 0, 146, 209, 2, 0, 146, 209, 2, 0, 146, 209, 2, 0, 146, 209, 2, 0, 146, 209, 2, 0, 146, 209, 2, 0, 146, 209, 2, 0, 146, 209, 2, 0, 146, 209, 2, 0, 146, 209, 2, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 146, 209, 2, 0, 146, 209, 2, 0, 146, 209, 2, 0, 146, 209, 2, 0, 146, 209, 2, 0, 146, 209, 2, 0, 146, 209, 2, 0, 146, 209, 2, 0, 146, 209, 2, 0, 146, 209, 2, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 155, 17, 10, 0, 155, 17, 10, 0, 155, 17, 10, 0, 155, 17, 10, 0, 155, 17, 10, 0, 155, 17, 10, 0, 155, 17, 10, 0, + 137, 17, 10, 0, 155, 17, 10, 0, 155, 17, 10, 0, 155, 17, 10, 0, 155, 17, 10, 0, 155, 17, 10, 0, 155, 17, 10, 0, 3, 0, 0, 0, 3, 0, 0, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 143, 64, 5, 0, 144, 64, 5, 0, + 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 142, 66, 5, 0, 142, 66, 5, 0, 144, 66, 5, 0, 142, 66, 5, 0, 142, 66, 5, 0, 138, 2, 3, 0, 138, 2, 3, 0, 138, 2, 3, 0, 138, 2, 3, 0, 138, 2, 3, 0, 138, 2, 3, 0, 138, 2, 3, 0, 138, 2, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 146, 194, 2, 0, 146, 194, 2, 0, + 146, 194, 2, 0, 146, 194, 2, 0, 146, 194, 2, 0, 146, 194, 2, 0, 146, 194, 2, 0, 146, 194, 2, 0, 146, 194, 2, 0, 146, 194, 2, 0, 155, 66, 4, 0, 155, 66, 4, 0, 155, 2, 3, 0, 155, 66, 4, 0, 155, 66, 4, 0, 155, 66, 4, 0, 155, 66, 4, 0, 161, 2, 3, 0, 161, 2, 3, 0, 161, 2, 3, 0, 161, 2, 3, 0, 161, 2, 3, 0, 161, 2, 3, 0, 161, 2, 3, 0, 161, 2, 3, 0, 161, 2, 3, 0, 161, 2, 3, 0, + 144, 66, 5, 0, 144, 66, 5, 0, 144, 66, 5, 0, 144, 66, 5, 0, 144, 66, 5, 0, 144, 66, 5, 0, 144, 66, 5, 0, 144, 66, 5, 0, 144, 66, 5, 0, 161, 2, 3, 0, 161, 2, 3, 0, 161, 2, 3, 0, 161, 2, 3, 0, 161, 2, 3, 0, 161, 2, 3, 0, 161, 2, 3, 0, 161, 2, 3, 0, 161, 2, 3, 0, 155, 66, 4, 0, 155, 66, 4, 0, 3, 0, 0, 0, 74, 3, 3, 0, 74, 3, 3, 0, 74, 3, 3, 0, 74, 3, 3, 0, + 74, 3, 3, 0, 74, 3, 3, 0, 80, 67, 5, 0, 78, 67, 5, 0, 80, 67, 5, 0, 80, 67, 5, 0, 78, 67, 5, 0, 78, 67, 5, 0, 78, 67, 5, 0, 80, 67, 5, 0, 78, 67, 5, 0, 80, 67, 5, 0, 80, 67, 5, 0, 80, 67, 5, 0, 78, 67, 5, 0, 78, 67, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 91, 3, 3, 0, + 91, 3, 3, 0, 91, 3, 3, 0, 91, 3, 3, 0, 74, 18, 3, 0, 74, 18, 3, 0, 74, 18, 3, 0, 74, 18, 3, 0, 78, 82, 5, 0, 78, 82, 5, 0, 78, 82, 5, 0, 78, 82, 5, 0, 78, 82, 5, 0, 78, 82, 5, 0, 78, 82, 5, 0, 78, 82, 5, 0, 80, 82, 5, 0, 80, 82, 5, 0, 80, 82, 5, 0, 80, 82, 5, 0, 80, 82, 5, 0, 80, 82, 5, 0, 80, 82, 5, 0, 80, 82, 5, 0, 78, 82, 5, 0, 78, 82, 5, 0, + 80, 82, 5, 0, 80, 82, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 91, 82, 4, 0, 91, 82, 4, 0, 91, 82, 4, 0, 91, 82, 4, 0, 91, 82, 4, 0, 82, 210, 2, 0, 82, 210, 2, 0, 82, 210, 2, 0, 82, 210, 2, 0, 82, 210, 2, 0, 82, 210, 2, 0, 82, 210, 2, 0, 82, 210, 2, 0, 82, 210, 2, 0, 82, 210, 2, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 74, 18, 3, 0, 74, 18, 3, 0, + 74, 18, 3, 0, 210, 217, 2, 0, 210, 217, 2, 0, 210, 217, 2, 0, 210, 217, 2, 0, 210, 217, 2, 0, 210, 217, 2, 0, 210, 217, 2, 0, 210, 217, 2, 0, 210, 217, 2, 0, 210, 217, 2, 0, 202, 25, 3, 0, 202, 25, 3, 0, 202, 25, 3, 0, 202, 25, 3, 0, 202, 25, 3, 0, 202, 25, 3, 0, 136, 7, 3, 0, 136, 7, 3, 0, 136, 7, 3, 0, 136, 7, 3, 0, 136, 7, 3, 0, 136, 7, 3, 0, 136, 7, 3, 0, 136, 7, 3, 0, + 136, 7, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, + 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 155, 33, 3, 0, 155, 33, 3, 0, 155, 33, 3, 0, 155, 33, 3, 0, 155, 33, 3, 0, 155, 33, 3, 0, 155, 33, 3, 0, 155, 33, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 91, 0, 3, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 78, 64, 5, 0, 144, 64, 5, 0, + 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 74, 0, 3, 0, 74, 0, 3, 0, 74, 0, 3, 0, 74, 0, 3, 0, 144, 64, 5, 0, 74, 0, 3, 0, 74, 0, 3, 0, 74, 0, 3, 0, 74, 0, 3, 0, 74, 0, 3, 0, 74, 0, 3, 0, 144, 64, 5, 0, 74, 0, 3, 0, 74, 0, 3, 0, 78, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 74, 0, 3, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, + 136, 11, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 3, 0, 0, 0, 140, 11, 3, 0, 3, 0, 0, 0, 140, 11, 3, 0, 3, 0, 0, 0, 140, 11, 3, 0, + 3, 0, 0, 0, 140, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, + 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 139, 11, 3, 0, 139, 11, 3, 0, 139, 11, 3, 0, 139, 11, 3, 0, 139, 11, 3, 0, 139, 11, 3, 0, 139, 11, 3, 0, 139, 11, 3, 0, + 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 3, 0, 0, 0, 136, 11, 3, 0, 136, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 139, 11, 3, 0, 159, 11, 3, 0, 136, 11, 3, 0, 159, 11, 3, 0, 159, 11, 3, 0, 159, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 3, 0, 0, 0, 136, 11, 3, 0, 136, 11, 3, 0, 140, 11, 3, 0, + 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 139, 11, 3, 0, 159, 11, 3, 0, 159, 11, 3, 0, 159, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 136, 11, 3, 0, 136, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 3, 0, 0, 0, 159, 11, 3, 0, 159, 11, 3, 0, 159, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, + 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 159, 11, 3, 0, 159, 11, 3, 0, 159, 11, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 3, 0, 0, 0, 136, 11, 3, 0, 136, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, + 140, 11, 3, 0, 139, 11, 3, 0, 159, 139, 4, 0, 159, 11, 3, 0, 3, 0, 0, 0, 66, 128, 5, 0, 66, 0, 3, 0, 66, 0, 3, 0, 66, 0, 3, 0, 66, 0, 3, 0, 3, 0, 0, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 84, 0, 3, 0, 9, 18, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 84, 128, 8, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 92, 0, 0, 0, 88, 64, 0, 0, 9, 146, 8, 0, 84, 0, 3, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, + 92, 0, 0, 0, 88, 64, 0, 0, 3, 0, 0, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 94, 128, 2, 0, 3, 64, 2, 0, 3, 64, 2, 0, 3, 64, 2, 0, 3, 64, 2, 0, 3, 64, 2, 0, + 3, 64, 2, 0, 3, 64, 2, 0, 3, 64, 2, 0, 3, 64, 2, 0, 3, 64, 2, 0, 3, 64, 2, 0, 3, 64, 2, 0, 3, 64, 2, 0, 3, 64, 2, 0, 3, 64, 2, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 143, 64, 5, 0, 143, 64, 5, 0, + 143, 64, 5, 0, 143, 64, 5, 0, 144, 64, 5, 0, 143, 64, 5, 0, 143, 64, 5, 0, 143, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 19, 18, 3, 0, 19, 18, 3, 0, 19, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 19, 18, 3, 0, 19, 18, 3, 0, 19, 18, 3, 0, 19, 18, 3, 0, 84, 128, 8, 0, 97, 0, 3, 0, 97, 0, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 96, 128, 8, 0, + 96, 128, 8, 0, 96, 128, 8, 0, 96, 128, 8, 0, 96, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 96, 0, 3, 0, 96, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, + 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, + 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 3, 0, 0, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, + 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 204, 6, 3, 0, 200, 6, 3, 0, 204, 6, 3, 0, 200, 6, 3, 0, 200, 6, 3, 0, 225, 6, 3, 0, 225, 6, 3, 0, 225, 6, 3, 0, 225, 6, 3, 0, 225, 6, 3, 0, 225, 6, 3, 0, 204, 6, 3, 0, 200, 6, 3, 0, 204, 6, 3, 0, 200, 6, 3, 0, 208, 70, 5, 0, 208, 70, 5, 0, 208, 70, 5, 0, 204, 6, 3, 0, + 200, 6, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 219, 134, 1, 0, 219, 70, 4, 0, 219, 70, 4, 0, 219, 70, 4, 0, 212, 6, 3, 0, 219, 134, 1, 0, 219, 70, 4, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 3, 0, 0, 0, 8, 10, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 8, 10, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 74, 36, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 73, 36, 3, 0, 91, 100, 4, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 80, 100, 5, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, + 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 3, 0, 0, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 3, 0, 0, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 3, 0, 0, 0, + 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 3, 0, 0, 0, 87, 64, 4, 0, 91, 64, 4, 0, 92, 0, 0, 0, 91, 64, 4, 0, 91, 64, 4, 0, 91, 64, 4, 0, 91, 64, 4, 0, 91, 64, 4, 0, 91, 64, 4, 0, 91, 64, 4, 0, 91, 64, 4, 0, 91, 0, 3, 0, 91, 64, 4, 0, 91, 0, 3, 0, 91, 64, 4, 0, 91, 64, 4, 0, 97, 0, 3, 0, + 97, 0, 3, 0, 91, 0, 3, 0, 91, 128, 1, 0, 91, 128, 1, 0, 92, 0, 0, 0, 88, 64, 0, 0, 92, 0, 0, 0, 88, 64, 0, 0, 92, 0, 0, 0, 88, 64, 0, 0, 92, 0, 0, 0, 88, 64, 0, 0, 87, 64, 4, 0, 3, 0, 0, 0, 3, 0, 0, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, + 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 3, 0, 0, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, + 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, + 97, 128, 3, 0, 97, 128, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 138, 13, 9, 0, 138, 141, 3, 0, 138, 13, 9, 0, 138, 141, 3, 0, 138, 13, 9, 0, 138, 141, 3, 0, 138, 13, 9, 0, 138, 141, 3, 0, 138, 13, 9, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, + 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 13, 9, 0, 138, 141, 3, 0, 138, 13, 9, 0, 138, 141, 3, 0, 138, 13, 9, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, + 138, 141, 3, 0, 138, 141, 3, 0, 138, 13, 9, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 13, 9, 0, 138, 13, 9, 0, 3, 0, 0, 0, 3, 0, 0, 0, 144, 64, 5, 0, 144, 64, 5, 0, 95, 64, 1, 0, 95, 64, 1, 0, 137, 77, 1, 0, 137, 77, 1, 0, 138, 141, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, + 10, 132, 3, 0, 10, 132, 3, 0, 3, 0, 0, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 3, 0, 0, 0, 97, 128, 3, 0, 97, 128, 3, 0, 84, 128, 3, 0, + 84, 128, 3, 0, 84, 128, 3, 0, 84, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 202, 15, 9, 0, 202, 15, 9, 0, 202, 15, 9, 0, 202, 15, 9, 0, 202, 15, 9, 0, 202, 15, 9, 0, 202, 15, 9, 0, 202, 15, 9, 0, 202, 15, 9, 0, 202, 15, 9, 0, 202, 15, 9, 0, 202, 15, 9, 0, 202, 15, 9, 0, 202, 15, 9, 0, 202, 15, 9, 0, 202, 15, 9, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, + 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 3, 0, 0, 0, 74, 168, 3, 0, 74, 168, 3, 0, + 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, + 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 74, 19, 3, 0, 74, 19, 3, 0, 74, 19, 3, 0, 74, 19, 3, 0, 74, 19, 3, 0, 74, 19, 3, 0, 74, 19, 3, 0, 74, 19, 3, 0, + 74, 19, 3, 0, 74, 19, 3, 0, 74, 19, 3, 0, 74, 19, 3, 0, 74, 19, 3, 0, 74, 19, 3, 0, 74, 19, 3, 0, 74, 19, 3, 0, 146, 230, 2, 0, 146, 230, 2, 0, 146, 230, 2, 0, 146, 230, 2, 0, 146, 230, 2, 0, 146, 230, 2, 0, 146, 230, 2, 0, 146, 230, 2, 0, 146, 230, 2, 0, 146, 230, 2, 0, 138, 38, 3, 0, 138, 38, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 211, 2, 3, 0, 211, 2, 3, 0, 211, 2, 3, 0, 211, 2, 3, 0, + 211, 2, 3, 0, 211, 2, 3, 0, 211, 2, 3, 0, 211, 2, 3, 0, 211, 2, 3, 0, 211, 2, 3, 0, 208, 66, 5, 0, 208, 66, 5, 0, 219, 2, 3, 0, 219, 66, 4, 0, 219, 66, 4, 0, 219, 66, 4, 0, 219, 66, 4, 0, 219, 66, 4, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, + 8, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 12, 18, 3, 0, 8, 18, 3, 0, 3, 0, 0, 0, 8, 18, 3, 0, 3, 0, 0, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 10, 18, 3, 0, 9, 18, 3, 0, + 9, 18, 3, 0, 8, 18, 3, 0, 10, 18, 3, 0, 10, 18, 3, 0, 10, 18, 3, 0, 10, 18, 3, 0, 10, 18, 3, 0, 202, 33, 3, 0, 202, 33, 3, 0, 202, 33, 3, 0, 206, 97, 5, 0, 206, 97, 5, 0, 208, 97, 5, 0, 208, 97, 5, 0, 206, 97, 5, 0, 225, 33, 3, 0, 225, 33, 3, 0, 225, 33, 3, 0, 225, 33, 3, 0, 208, 97, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 84, 0, 3, 0, 84, 0, 3, 0, + 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 94, 128, 2, 0, 97, 0, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, + 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 27, 156, 4, 0, 27, 156, 4, 0, 27, 156, 1, 0, 27, 156, 1, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 206, 94, 5, 0, 206, 94, 5, 0, 206, 94, 5, 0, 206, 94, 5, 0, + 208, 94, 5, 0, 208, 94, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 219, 94, 4, 0, 219, 94, 4, 0, 210, 222, 2, 0, 210, 222, 2, 0, 210, 222, 2, 0, 210, 222, 2, 0, 210, 222, 2, 0, 210, 222, 2, 0, 210, 222, 2, 0, 210, 222, 2, 0, 210, 222, 2, 0, 210, 222, 2, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 138, 29, 3, 0, 138, 29, 3, 0, 138, 29, 3, 0, 138, 29, 3, 0, 138, 29, 3, 0, 138, 29, 3, 0, 138, 29, 3, 0, 144, 93, 5, 0, 144, 93, 5, 0, 144, 93, 5, 0, 144, 93, 5, 0, 144, 93, 5, 0, 144, 93, 5, 0, 144, 93, 5, 0, 144, 93, 5, 0, 144, 93, 5, 0, 144, 93, 5, 0, 144, 93, 5, 0, 142, 93, 5, 0, 142, 93, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 155, 29, 3, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, + 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 78, 79, 5, 0, 91, 15, 3, 0, 91, 15, 3, 0, 91, 15, 3, 0, 91, 15, 3, 0, 91, 15, 3, 0, 91, 15, 3, 0, 91, 79, 4, 0, + 91, 79, 4, 0, 91, 79, 4, 0, 91, 15, 3, 0, 91, 15, 3, 0, 91, 15, 3, 0, 91, 15, 3, 0, 3, 0, 0, 0, 73, 0, 3, 0, 82, 207, 2, 0, 82, 207, 2, 0, 82, 207, 2, 0, 82, 207, 2, 0, 82, 207, 2, 0, 82, 207, 2, 0, 82, 207, 2, 0, 82, 207, 2, 0, 82, 207, 2, 0, 82, 207, 2, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 91, 15, 3, 0, 91, 15, 3, 0, 202, 23, 10, 0, + 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 208, 23, 10, 0, 201, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 210, 215, 2, 0, 210, 215, 2, 0, 210, 215, 2, 0, 210, 215, 2, 0, 210, 215, 2, 0, 210, 215, 2, 0, 210, 215, 2, 0, 210, 215, 2, 0, 210, 215, 2, 0, 210, 215, 2, 0, + 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 3, 0, 0, 0, 10, 6, 3, 0, 10, 6, 3, 0, 10, 6, 3, 0, 10, 6, 3, 0, 10, 6, 3, 0, 10, 6, 3, 0, 10, 6, 3, 0, 10, 6, 3, 0, 10, 6, 3, 0, 16, 70, 5, 0, 16, 70, 5, 0, 16, 70, 5, 0, 16, 70, 5, 0, 16, 70, 5, 0, 16, 70, 5, 0, 14, 70, 5, 0, 14, 70, 5, 0, 16, 70, 5, 0, 16, 70, 5, 0, + 14, 70, 5, 0, 14, 70, 5, 0, 16, 70, 5, 0, 16, 70, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 10, 6, 3, 0, 10, 6, 3, 0, 10, 6, 3, 0, 16, 70, 5, 0, 10, 6, 3, 0, 10, 6, 3, 0, 10, 6, 3, 0, 10, 6, 3, 0, 10, 6, 3, 0, 10, 6, 3, 0, 10, 6, 3, 0, 10, 6, 3, 0, + 16, 70, 5, 0, 14, 70, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 18, 198, 2, 0, 18, 198, 2, 0, 18, 198, 2, 0, 18, 198, 2, 0, 18, 198, 2, 0, 18, 198, 2, 0, 18, 198, 2, 0, 18, 198, 2, 0, 18, 198, 2, 0, 18, 198, 2, 0, 3, 0, 0, 0, 3, 0, 0, 0, 27, 6, 3, 0, 27, 70, 4, 0, 27, 70, 4, 0, 27, 70, 4, 0, 202, 35, 10, 0, 208, 35, 10, 0, 202, 35, 10, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 202, 35, 10, 0, 202, 35, 10, 0, 201, 35, 10, 0, + 219, 35, 10, 0, 219, 35, 10, 0, 74, 23, 3, 0, 74, 23, 3, 0, 74, 23, 3, 0, 74, 23, 3, 0, 74, 23, 3, 0, 74, 23, 3, 0, 74, 23, 3, 0, 74, 23, 3, 0, 74, 23, 3, 0, 74, 23, 3, 0, 74, 23, 3, 0, 78, 87, 5, 0, 80, 87, 5, 0, 80, 87, 5, 0, 78, 87, 5, 0, 78, 87, 5, 0, 91, 87, 4, 0, 91, 87, 4, 0, 74, 23, 3, 0, 73, 23, 3, 0, 73, 23, 3, 0, 78, 87, 5, 0, 80, 87, 5, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 3, 0, 0, 0, 202, 9, 3, 0, + 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 3, 0, 0, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 136, 11, 3, 0, + 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 9, 18, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, + 72, 6, 3, 0, 74, 23, 3, 0, 74, 23, 3, 0, 74, 23, 3, 0, 78, 87, 5, 0, 78, 87, 5, 0, 80, 87, 5, 0, 78, 87, 5, 0, 78, 87, 5, 0, 80, 87, 5, 0, 78, 87, 5, 0, 78, 87, 5, 0, 91, 87, 4, 0, 78, 87, 5, 0, 80, 87, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 82, 215, 2, 0, 82, 215, 2, 0, 82, 215, 2, 0, 82, 215, 2, 0, 82, 215, 2, 0, 82, 215, 2, 0, 82, 215, 2, 0, 82, 215, 2, 0, + 82, 215, 2, 0, 82, 215, 2, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 74, 140, 6, 0, + 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, + 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, + 74, 204, 6, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, + 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, + 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, + 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 8, 2, 3, 0, 8, 2, 3, 0, 8, 2, 3, 0, 8, 2, 3, 0, 8, 2, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 74, 77, 3, 0, 80, 77, 5, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 96, 13, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, + 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 3, 0, 0, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 3, 0, 0, 0, 74, 77, 3, 0, 3, 0, 0, 0, 74, 77, 3, 0, 74, 77, 3, 0, 3, 0, 0, 0, 74, 77, 3, 0, 74, 77, 3, 0, + 3, 0, 0, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 74, 77, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, + 138, 1, 3, 0, 138, 1, 3, 0, 159, 1, 3, 0, 159, 1, 3, 0, 159, 1, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, + 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, + 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 161, 1, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 158, 129, 2, 0, 161, 1, 3, 0, 161, 1, 3, 0, 161, 1, 3, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, + 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 91, 0, 2, 0, 91, 64, 0, 0, 91, 64, 0, 0, 91, 0, 2, 0, 91, 0, 2, 0, 91, 128, 1, 0, 91, 128, 1, 0, 92, 0, 0, 0, 88, 64, 0, 0, 91, 192, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 88, 64, 0, 0, 92, 0, 0, 0, 88, 64, 0, 0, 92, 0, 0, 0, 88, 64, 0, 0, 91, 128, 3, 0, 91, 128, 3, 0, 92, 0, 0, 0, 88, 64, 0, 0, 91, 128, 3, 0, 91, 128, 3, 0, 91, 128, 3, 0, 91, 128, 3, 0, 86, 128, 3, 0, 86, 128, 3, 0, 86, 128, 3, 0, 91, 64, 0, 0, 91, 128, 3, 0, 91, 64, 0, 0, 3, 0, 0, 0, 91, 64, 1, 0, 91, 64, 1, 0, 91, 128, 1, 0, 91, 128, 1, 0, + 87, 128, 3, 0, 92, 0, 0, 0, 88, 64, 0, 0, 92, 0, 0, 0, 88, 64, 0, 0, 92, 0, 0, 0, 88, 64, 0, 0, 91, 128, 3, 0, 91, 128, 3, 0, 91, 128, 3, 0, 96, 128, 3, 0, 87, 128, 3, 0, 96, 128, 3, 0, 96, 128, 3, 0, 96, 128, 3, 0, 3, 0, 0, 0, 91, 128, 3, 0, 94, 64, 2, 0, 91, 128, 2, 0, 91, 128, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 138, 1, 3, 0, + 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 3, 0, 0, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, + 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 66, 128, 5, 0, 3, 0, 0, 0, 91, 128, 1, 0, 91, 128, 3, 0, 91, 128, 3, 0, 94, 64, 2, 0, 91, 128, 2, 0, 91, 128, 3, 0, 91, 128, 3, 0, 92, 0, 0, 0, 88, 64, 0, 0, 91, 128, 3, 0, + 96, 128, 3, 0, 91, 64, 0, 0, 87, 128, 3, 0, 91, 64, 0, 0, 91, 128, 3, 0, 82, 128, 3, 0, 82, 128, 3, 0, 82, 128, 3, 0, 82, 128, 3, 0, 82, 128, 3, 0, 82, 128, 3, 0, 82, 128, 3, 0, 82, 128, 3, 0, 82, 128, 3, 0, 82, 128, 3, 0, 91, 64, 1, 0, 91, 64, 1, 0, 96, 128, 3, 0, 96, 128, 3, 0, 96, 128, 3, 0, 91, 128, 1, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, + 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, + 74, 140, 3, 0, 74, 140, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, + 74, 140, 3, 0, 74, 140, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 94, 128, 2, 0, 94, 64, 2, 0, 96, 128, 3, 0, 95, 128, 3, 0, 97, 128, 3, 0, 94, 64, 2, 0, 94, 64, 2, 0, 3, 0, 0, 0, 97, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 97, 0, 8, 0, 97, 128, 8, 0, 3, 0, 0, 0, 3, 0, 0, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, + 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 3, 0, 0, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, + 10, 19, 3, 0, 10, 19, 3, 0, 3, 0, 0, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 3, 0, 0, 0, 10, 19, 3, 0, 10, 19, 3, 0, + 3, 0, 0, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, + 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, + 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 91, 64, 4, 0, 91, 64, 4, 0, 91, 64, 4, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 84, 0, 3, 0, 84, 0, 3, 0, + 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 148, 11, 3, 0, 148, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, + 3, 0, 0, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 161, 11, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 97, 0, 3, 0, + 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, + 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 144, 64, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 138, 19, 3, 0, 138, 19, 3, 0, 138, 19, 3, 0, 138, 19, 3, 0, 138, 19, 3, 0, 138, 19, 3, 0, 138, 19, 3, 0, 138, 19, 3, 0, 138, 19, 3, 0, 138, 19, 3, 0, 138, 19, 3, 0, 138, 19, 3, 0, 138, 19, 3, 0, 138, 19, 3, 0, 138, 19, 3, 0, 138, 19, 3, 0, 138, 19, 3, 0, 138, 19, 3, 0, 138, 19, 3, 0, + 138, 19, 3, 0, 138, 19, 3, 0, 138, 19, 3, 0, 138, 19, 3, 0, 138, 19, 3, 0, 138, 19, 3, 0, 138, 19, 3, 0, 138, 19, 3, 0, 138, 19, 3, 0, 138, 19, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 202, 5, 3, 0, 202, 5, 3, 0, 202, 5, 3, 0, 202, 5, 3, 0, 202, 5, 3, 0, 202, 5, 3, 0, 202, 5, 3, 0, 202, 5, 3, 0, 202, 5, 3, 0, 202, 5, 3, 0, 202, 5, 3, 0, 202, 5, 3, 0, + 202, 5, 3, 0, 202, 5, 3, 0, 202, 5, 3, 0, 202, 5, 3, 0, 202, 5, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 144, 64, 5, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, + 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 20, 15, 3, 0, 20, 15, 3, 0, 20, 15, 3, 0, 20, 15, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 10, 15, 3, 0, 10, 15, 3, 0, 10, 15, 3, 0, 10, 11, 3, 0, 10, 11, 3, 0, 10, 11, 3, 0, 10, 11, 3, 0, 10, 11, 3, 0, 10, 11, 3, 0, 10, 11, 3, 0, + 10, 11, 3, 0, 10, 11, 3, 0, 10, 11, 3, 0, 10, 11, 3, 0, 10, 11, 3, 0, 10, 11, 3, 0, 10, 11, 3, 0, 10, 11, 3, 0, 10, 11, 3, 0, 10, 11, 3, 0, 19, 11, 3, 0, 10, 11, 3, 0, 10, 11, 3, 0, 10, 11, 3, 0, 10, 11, 3, 0, 10, 11, 3, 0, 10, 11, 3, 0, 10, 11, 3, 0, 10, 11, 3, 0, 19, 11, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 202, 27, 3, 0, 202, 27, 3, 0, 202, 27, 3, 0, 202, 27, 3, 0, 202, 27, 3, 0, 202, 27, 3, 0, 202, 27, 3, 0, 202, 27, 3, 0, 202, 27, 3, 0, 202, 27, 3, 0, 202, 27, 3, 0, 202, 27, 3, 0, 202, 27, 3, 0, 202, 27, 3, 0, 202, 27, 3, 0, 202, 27, 3, 0, 202, 27, 3, 0, 202, 27, 3, 0, 202, 27, 3, 0, 202, 27, 3, 0, 202, 27, 3, 0, 202, 27, 3, 0, 208, 91, 5, 0, 208, 91, 5, 0, 208, 91, 5, 0, + 208, 91, 5, 0, 208, 91, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 74, 38, 3, 0, 74, 38, 3, 0, 74, 38, 3, 0, 74, 38, 3, 0, 74, 38, 3, 0, 74, 38, 3, 0, 74, 38, 3, 0, 74, 38, 3, 0, 74, 38, 3, 0, 74, 38, 3, 0, 74, 38, 3, 0, 74, 38, 3, 0, 74, 38, 3, 0, 74, 38, 3, 0, 74, 38, 3, 0, 74, 38, 3, 0, 74, 38, 3, 0, 74, 38, 3, 0, + 74, 38, 3, 0, 74, 38, 3, 0, 74, 38, 3, 0, 74, 38, 3, 0, 74, 38, 3, 0, 74, 38, 3, 0, 74, 38, 3, 0, 74, 38, 3, 0, 74, 38, 3, 0, 74, 38, 3, 0, 74, 38, 3, 0, 74, 38, 3, 0, 3, 0, 0, 0, 91, 102, 4, 0, 138, 39, 3, 0, 138, 39, 3, 0, 138, 39, 3, 0, 138, 39, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 138, 39, 3, 0, 138, 39, 3, 0, 138, 39, 3, 0, + 138, 39, 3, 0, 138, 39, 3, 0, 138, 39, 3, 0, 138, 39, 3, 0, 138, 39, 3, 0, 155, 103, 4, 0, 147, 39, 3, 0, 147, 39, 3, 0, 147, 39, 3, 0, 147, 39, 3, 0, 147, 39, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 202, 26, 3, 0, 202, 26, 3, 0, 202, 26, 3, 0, 202, 26, 3, 0, + 202, 26, 3, 0, 202, 26, 3, 0, 202, 26, 3, 0, 202, 26, 3, 0, 202, 26, 3, 0, 202, 26, 3, 0, 202, 26, 3, 0, 202, 26, 3, 0, 202, 26, 3, 0, 202, 26, 3, 0, 202, 26, 3, 0, 202, 26, 3, 0, 202, 26, 3, 0, 202, 26, 3, 0, 202, 26, 3, 0, 202, 26, 3, 0, 202, 26, 3, 0, 202, 26, 3, 0, 202, 26, 3, 0, 202, 26, 3, 0, 202, 26, 3, 0, 202, 26, 3, 0, 202, 26, 3, 0, 202, 26, 3, 0, 202, 26, 3, 0, + 202, 26, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 210, 218, 2, 0, 210, 218, 2, 0, 210, 218, 2, 0, 210, 218, 2, 0, 210, 218, 2, 0, 210, 218, 2, 0, 210, 218, 2, 0, 210, 218, 2, 0, 210, 218, 2, 0, 210, 218, 2, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 140, 26, 3, 0, 140, 26, 3, 0, 140, 26, 3, 0, 140, 26, 3, 0, 140, 26, 3, 0, 140, 26, 3, 0, + 140, 26, 3, 0, 140, 26, 3, 0, 140, 26, 3, 0, 140, 26, 3, 0, 140, 26, 3, 0, 140, 26, 3, 0, 140, 26, 3, 0, 140, 26, 3, 0, 140, 26, 3, 0, 140, 26, 3, 0, 140, 26, 3, 0, 140, 26, 3, 0, 140, 26, 3, 0, 140, 26, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 136, 26, 3, 0, 136, 26, 3, 0, 136, 26, 3, 0, 136, 26, 3, 0, 136, 26, 3, 0, 136, 26, 3, 0, 136, 26, 3, 0, + 136, 26, 3, 0, 136, 26, 3, 0, 136, 26, 3, 0, 136, 26, 3, 0, 136, 26, 3, 0, 136, 26, 3, 0, 136, 26, 3, 0, 136, 26, 3, 0, 136, 26, 3, 0, 136, 26, 3, 0, 136, 26, 3, 0, 136, 26, 3, 0, 136, 26, 3, 0, 136, 26, 3, 0, 136, 26, 3, 0, 136, 26, 3, 0, 136, 26, 3, 0, 136, 26, 3, 0, 136, 26, 3, 0, 136, 26, 3, 0, 136, 26, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 74, 9, 3, 0, 74, 9, 3, 0, 74, 9, 3, 0, 74, 9, 3, 0, 74, 9, 3, 0, 74, 9, 3, 0, 74, 9, 3, 0, 74, 9, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 10, 1, 3, 0, 10, 1, 3, 0, 10, 1, 3, 0, 10, 1, 3, 0, 10, 1, 3, 0, 10, 1, 3, 0, 10, 1, 3, 0, 10, 1, 3, 0, 10, 1, 3, 0, + 10, 1, 3, 0, 10, 1, 3, 0, 10, 1, 3, 0, 10, 1, 3, 0, 10, 1, 3, 0, 10, 1, 3, 0, 10, 1, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 27, 1, 3, 0, 204, 38, 3, 0, 204, 38, 3, 0, 204, 38, 3, 0, 204, 38, 3, 0, 204, 38, 3, 0, 204, 38, 3, 0, + 204, 38, 3, 0, 204, 38, 3, 0, 204, 38, 3, 0, 204, 38, 3, 0, 204, 38, 3, 0, 3, 0, 0, 0, 204, 38, 3, 0, 204, 38, 3, 0, 204, 38, 3, 0, 204, 38, 3, 0, 204, 38, 3, 0, 204, 38, 3, 0, 204, 38, 3, 0, 3, 0, 0, 0, 204, 38, 3, 0, 204, 38, 3, 0, 3, 0, 0, 0, 200, 38, 3, 0, 200, 38, 3, 0, 200, 38, 3, 0, 200, 38, 3, 0, 200, 38, 3, 0, 200, 38, 3, 0, 200, 38, 3, 0, 200, 38, 3, 0, + 200, 38, 3, 0, 200, 38, 3, 0, 200, 38, 3, 0, 3, 0, 0, 0, 200, 38, 3, 0, 200, 38, 3, 0, 200, 38, 3, 0, 200, 38, 3, 0, 200, 38, 3, 0, 200, 38, 3, 0, 200, 38, 3, 0, 200, 38, 3, 0, 200, 38, 3, 0, 200, 38, 3, 0, 200, 38, 3, 0, 200, 38, 3, 0, 200, 38, 3, 0, 200, 38, 3, 0, 200, 38, 3, 0, 3, 0, 0, 0, 200, 38, 3, 0, 200, 38, 3, 0, 200, 38, 3, 0, 200, 38, 3, 0, 200, 38, 3, 0, + 200, 38, 3, 0, 200, 38, 3, 0, 3, 0, 0, 0, 200, 38, 3, 0, 200, 38, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, + 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, + 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, + 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 3, 0, 0, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, + 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 3, 0, 0, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 74, 7, 3, 0, 74, 7, 3, 0, 74, 7, 3, 0, 74, 7, 3, 0, 74, 7, 3, 0, 74, 7, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 74, 7, 3, 0, 3, 0, 0, 0, 74, 7, 3, 0, 74, 7, 3, 0, 74, 7, 3, 0, 74, 7, 3, 0, 74, 7, 3, 0, 74, 7, 3, 0, 74, 7, 3, 0, 74, 7, 3, 0, 74, 7, 3, 0, 74, 7, 3, 0, 74, 7, 3, 0, 74, 7, 3, 0, 74, 7, 3, 0, + 74, 7, 3, 0, 74, 7, 3, 0, 74, 7, 3, 0, 74, 7, 3, 0, 74, 7, 3, 0, 74, 7, 3, 0, 74, 7, 3, 0, 74, 7, 3, 0, 74, 7, 3, 0, 74, 7, 3, 0, 74, 7, 3, 0, 3, 0, 0, 0, 74, 7, 3, 0, 74, 7, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 74, 7, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 74, 7, 3, 0, 202, 1, 3, 0, 202, 1, 3, 0, 202, 1, 3, 0, 202, 1, 3, 0, + 202, 1, 3, 0, 202, 1, 3, 0, 202, 1, 3, 0, 202, 1, 3, 0, 202, 1, 3, 0, 202, 1, 3, 0, 202, 1, 3, 0, 202, 1, 3, 0, 202, 1, 3, 0, 202, 1, 3, 0, 202, 1, 3, 0, 202, 1, 3, 0, 202, 1, 3, 0, 202, 1, 3, 0, 202, 1, 3, 0, 202, 1, 3, 0, 202, 1, 3, 0, 202, 1, 3, 0, 3, 0, 0, 0, 219, 65, 4, 0, 212, 1, 3, 0, 212, 1, 3, 0, 212, 1, 3, 0, 212, 1, 3, 0, 212, 1, 3, 0, + 212, 1, 3, 0, 212, 1, 3, 0, 212, 1, 3, 0, 138, 24, 3, 0, 138, 24, 3, 0, 138, 24, 3, 0, 138, 24, 3, 0, 138, 24, 3, 0, 138, 24, 3, 0, 138, 24, 3, 0, 138, 24, 3, 0, 138, 24, 3, 0, 138, 24, 3, 0, 138, 24, 3, 0, 138, 24, 3, 0, 138, 24, 3, 0, 138, 24, 3, 0, 138, 24, 3, 0, 138, 24, 3, 0, 138, 24, 3, 0, 138, 24, 3, 0, 138, 24, 3, 0, 138, 24, 3, 0, 138, 24, 3, 0, 138, 24, 3, 0, + 138, 24, 3, 0, 138, 24, 3, 0, 138, 24, 3, 0, 138, 24, 3, 0, 138, 24, 3, 0, 138, 24, 3, 0, 138, 24, 3, 0, 138, 24, 3, 0, 138, 24, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 148, 24, 3, 0, 148, 24, 3, 0, 148, 24, 3, 0, 148, 24, 3, 0, 148, 24, 3, 0, 148, 24, 3, 0, 148, 24, 3, 0, 148, 24, 3, 0, + 148, 24, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 10, 13, 3, 0, 10, 13, 3, 0, 10, 13, 3, 0, 10, 13, 3, 0, 10, 13, 3, 0, 10, 13, 3, 0, 10, 13, 3, 0, 10, 13, 3, 0, + 10, 13, 3, 0, 10, 13, 3, 0, 10, 13, 3, 0, 10, 13, 3, 0, 10, 13, 3, 0, 10, 13, 3, 0, 10, 13, 3, 0, 10, 13, 3, 0, 10, 13, 3, 0, 10, 13, 3, 0, 10, 13, 3, 0, 3, 0, 0, 0, 10, 13, 3, 0, 10, 13, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 20, 13, 3, 0, 20, 13, 3, 0, 20, 13, 3, 0, 20, 13, 3, 0, 20, 13, 3, 0, 202, 28, 3, 0, + 202, 28, 3, 0, 202, 28, 3, 0, 202, 28, 3, 0, 202, 28, 3, 0, 202, 28, 3, 0, 202, 28, 3, 0, 202, 28, 3, 0, 202, 28, 3, 0, 202, 28, 3, 0, 202, 28, 3, 0, 202, 28, 3, 0, 202, 28, 3, 0, 202, 28, 3, 0, 202, 28, 3, 0, 202, 28, 3, 0, 202, 28, 3, 0, 202, 28, 3, 0, 202, 28, 3, 0, 202, 28, 3, 0, 202, 28, 3, 0, 202, 28, 3, 0, 212, 28, 3, 0, 212, 28, 3, 0, 212, 28, 3, 0, 212, 28, 3, 0, + 212, 28, 3, 0, 212, 28, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 219, 92, 4, 0, 202, 19, 3, 0, 202, 19, 3, 0, 202, 19, 3, 0, 202, 19, 3, 0, 202, 19, 3, 0, 202, 19, 3, 0, 202, 19, 3, 0, 202, 19, 3, 0, 202, 19, 3, 0, 202, 19, 3, 0, 202, 19, 3, 0, 202, 19, 3, 0, 202, 19, 3, 0, 202, 19, 3, 0, 202, 19, 3, 0, 202, 19, 3, 0, 202, 19, 3, 0, 202, 19, 3, 0, 202, 19, 3, 0, + 202, 19, 3, 0, 202, 19, 3, 0, 202, 19, 3, 0, 202, 19, 3, 0, 202, 19, 3, 0, 202, 19, 3, 0, 202, 19, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 219, 19, 3, 0, 202, 21, 3, 0, 202, 21, 3, 0, 202, 21, 3, 0, 202, 21, 3, 0, 202, 21, 3, 0, 202, 21, 3, 0, 202, 21, 3, 0, 202, 21, 3, 0, 202, 21, 3, 0, 202, 21, 3, 0, 202, 21, 3, 0, 202, 21, 3, 0, + 202, 21, 3, 0, 202, 21, 3, 0, 202, 21, 3, 0, 202, 21, 3, 0, 202, 21, 3, 0, 202, 21, 3, 0, 202, 21, 3, 0, 202, 21, 3, 0, 202, 21, 3, 0, 202, 21, 3, 0, 202, 21, 3, 0, 202, 21, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 212, 21, 3, 0, 212, 21, 3, 0, 202, 21, 3, 0, 202, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, + 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, + 212, 21, 3, 0, 212, 21, 3, 0, 10, 16, 3, 0, 16, 80, 5, 0, 16, 80, 5, 0, 16, 80, 5, 0, 3, 0, 0, 0, 16, 80, 5, 0, 16, 80, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 16, 80, 5, 0, 16, 80, 5, 0, 16, 80, 5, 0, 16, 80, 5, 0, 10, 16, 3, 0, 10, 16, 3, 0, 10, 16, 3, 0, 10, 16, 3, 0, 3, 0, 0, 0, 10, 16, 3, 0, 10, 16, 3, 0, + 10, 16, 3, 0, 3, 0, 0, 0, 10, 16, 3, 0, 10, 16, 3, 0, 10, 16, 3, 0, 10, 16, 3, 0, 10, 16, 3, 0, 10, 16, 3, 0, 10, 16, 3, 0, 10, 16, 3, 0, 10, 16, 3, 0, 10, 16, 3, 0, 10, 16, 3, 0, 10, 16, 3, 0, 10, 16, 3, 0, 10, 16, 3, 0, 10, 16, 3, 0, 10, 16, 3, 0, 10, 16, 3, 0, 10, 16, 3, 0, 10, 16, 3, 0, 10, 16, 3, 0, 10, 16, 3, 0, 10, 16, 3, 0, 10, 16, 3, 0, + 10, 16, 3, 0, 10, 16, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 16, 80, 5, 0, 16, 80, 5, 0, 16, 80, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 16, 80, 5, 0, 20, 16, 3, 0, 20, 16, 3, 0, 20, 16, 3, 0, 20, 16, 3, 0, 20, 16, 3, 0, 20, 16, 3, 0, 20, 16, 3, 0, 20, 16, 3, 0, 20, 16, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 27, 80, 4, 0, 27, 80, 4, 0, 27, 80, 4, 0, 27, 80, 4, 0, 27, 80, 4, 0, 27, 80, 4, 0, 27, 80, 4, 0, 27, 80, 4, 0, 27, 16, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 202, 20, 3, 0, 202, 20, 3, 0, 202, 20, 3, 0, 202, 20, 3, 0, 202, 20, 3, 0, 208, 84, 5, 0, + 208, 84, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 212, 20, 3, 0, 212, 20, 3, 0, 212, 20, 3, 0, 212, 20, 3, 0, 212, 20, 3, 0, 219, 84, 4, 0, 219, 84, 4, 0, 219, 84, 4, 0, 219, 84, 4, 0, 219, 84, 4, 0, 219, 84, 4, 0, 219, 212, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 91, 66, 4, 0, 91, 66, 4, 0, 91, 66, 4, 0, 91, 66, 4, 0, 91, 66, 4, 0, 91, 66, 4, 0, 91, 66, 4, 0, 74, 29, 3, 0, 74, 29, 3, 0, 74, 29, 3, 0, 74, 29, 3, 0, 74, 29, 3, 0, 74, 29, 3, 0, 74, 29, 3, 0, 74, 29, 3, 0, 74, 29, 3, 0, 74, 29, 3, 0, 74, 29, 3, 0, 74, 29, 3, 0, 74, 29, 3, 0, 74, 29, 3, 0, 74, 29, 3, 0, 74, 29, 3, 0, 74, 29, 3, 0, + 74, 29, 3, 0, 74, 29, 3, 0, 74, 29, 3, 0, 74, 29, 3, 0, 74, 29, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 84, 29, 3, 0, 84, 29, 3, 0, 84, 29, 3, 0, 84, 29, 3, 0, 84, 29, 3, 0, 84, 29, 3, 0, 84, 29, 3, 0, 84, 29, 3, 0, 74, 28, 3, 0, 74, 28, 3, 0, 74, 28, 3, 0, 74, 28, 3, 0, 74, 28, 3, 0, 74, 28, 3, 0, 74, 28, 3, 0, 74, 28, 3, 0, 74, 28, 3, 0, 74, 28, 3, 0, + 74, 28, 3, 0, 74, 28, 3, 0, 74, 28, 3, 0, 74, 28, 3, 0, 74, 28, 3, 0, 74, 28, 3, 0, 74, 28, 3, 0, 74, 28, 3, 0, 74, 28, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 84, 28, 3, 0, 84, 28, 3, 0, 84, 28, 3, 0, 84, 28, 3, 0, 84, 28, 3, 0, 84, 28, 3, 0, 84, 28, 3, 0, 84, 28, 3, 0, 138, 28, 3, 0, 138, 28, 3, 0, 138, 28, 3, 0, + 138, 28, 3, 0, 138, 28, 3, 0, 138, 28, 3, 0, 138, 28, 3, 0, 138, 28, 3, 0, 138, 28, 3, 0, 138, 28, 3, 0, 138, 28, 3, 0, 138, 28, 3, 0, 138, 28, 3, 0, 138, 28, 3, 0, 138, 28, 3, 0, 138, 28, 3, 0, 138, 28, 3, 0, 138, 28, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 155, 28, 3, 0, 155, 28, 3, 0, 155, 28, 3, 0, + 155, 28, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 148, 28, 3, 0, 148, 28, 3, 0, 148, 28, 3, 0, 148, 28, 3, 0, 148, 28, 3, 0, 148, 28, 3, 0, 148, 28, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 10, 26, 3, 0, 10, 26, 3, 0, 10, 26, 3, 0, 10, 26, 3, 0, 10, 26, 3, 0, 10, 26, 3, 0, 10, 26, 3, 0, 10, 26, 3, 0, 10, 26, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, + 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 212, 14, 3, 0, 212, 14, 3, 0, 212, 14, 3, 0, 212, 14, 3, 0, 212, 14, 3, 0, 212, 14, 3, 0, 202, 29, 3, 0, 202, 29, 3, 0, 202, 29, 3, 0, 202, 29, 3, 0, 208, 93, 5, 0, 208, 93, 5, 0, 208, 93, 5, 0, 208, 93, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 210, 221, 2, 0, 210, 221, 2, 0, + 210, 221, 2, 0, 210, 221, 2, 0, 210, 221, 2, 0, 210, 221, 2, 0, 210, 221, 2, 0, 210, 221, 2, 0, 210, 221, 2, 0, 210, 221, 2, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 148, 1, 3, 0, 148, 1, 3, 0, 148, 1, 3, 0, 148, 1, 3, 0, 148, 1, 3, 0, 148, 1, 3, 0, 148, 1, 3, 0, 148, 1, 3, 0, 148, 1, 3, 0, 148, 1, 3, 0, 148, 1, 3, 0, + 148, 1, 3, 0, 148, 1, 3, 0, 148, 1, 3, 0, 148, 1, 3, 0, 148, 1, 3, 0, 148, 1, 3, 0, 148, 1, 3, 0, 148, 1, 3, 0, 148, 1, 3, 0, 148, 1, 3, 0, 148, 1, 3, 0, 148, 1, 3, 0, 148, 1, 3, 0, 148, 1, 3, 0, 148, 1, 3, 0, 148, 1, 3, 0, 148, 1, 3, 0, 148, 1, 3, 0, 148, 1, 3, 0, 148, 1, 3, 0, 3, 0, 0, 0, 10, 40, 3, 0, 10, 40, 3, 0, 10, 40, 3, 0, 10, 40, 3, 0, + 10, 40, 3, 0, 10, 40, 3, 0, 10, 40, 3, 0, 10, 40, 3, 0, 10, 40, 3, 0, 10, 40, 3, 0, 3, 0, 0, 0, 16, 104, 5, 0, 16, 104, 5, 0, 23, 104, 4, 0, 3, 0, 0, 0, 3, 0, 0, 0, 10, 40, 3, 0, 10, 40, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 212, 32, 3, 0, 212, 32, 3, 0, 212, 32, 3, 0, 212, 32, 3, 0, 212, 32, 3, 0, 212, 32, 3, 0, 212, 32, 3, 0, 202, 32, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 138, 32, 3, 0, 138, 32, 3, 0, 138, 32, 3, 0, 138, 32, 3, 0, 138, 32, 3, 0, 138, 32, 3, 0, + 138, 32, 3, 0, 138, 32, 3, 0, 138, 32, 3, 0, 138, 32, 3, 0, 138, 32, 3, 0, 138, 32, 3, 0, 138, 32, 3, 0, 138, 32, 3, 0, 138, 32, 3, 0, 138, 32, 3, 0, 138, 32, 3, 0, 138, 32, 3, 0, 144, 96, 5, 0, 144, 96, 5, 0, 144, 96, 5, 0, 144, 96, 5, 0, 144, 96, 5, 0, 144, 96, 5, 0, 144, 96, 5, 0, 144, 96, 5, 0, 144, 96, 5, 0, 144, 96, 5, 0, 144, 96, 5, 0, 148, 32, 3, 0, 148, 32, 3, 0, + 148, 32, 3, 0, 148, 32, 3, 0, 155, 32, 3, 0, 155, 32, 3, 0, 155, 32, 3, 0, 155, 32, 3, 0, 155, 32, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 10, 27, 3, 0, 10, 27, 3, 0, 10, 27, 3, 0, 10, 27, 3, 0, 10, 27, 3, 0, 10, 27, 3, 0, 10, 27, 3, 0, 10, 27, 3, 0, 10, 27, 3, 0, 10, 27, 3, 0, 10, 27, 3, 0, 10, 27, 3, 0, 10, 27, 3, 0, 10, 27, 3, 0, 10, 27, 3, 0, 10, 27, 3, 0, 10, 27, 3, 0, 10, 27, 3, 0, 16, 91, 5, 0, 16, 91, 5, 0, 16, 91, 5, 0, 16, 91, 5, 0, 27, 27, 3, 0, 27, 27, 3, 0, 27, 27, 3, 0, + 27, 27, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 138, 6, 3, 0, 138, 6, 3, 0, + 138, 6, 3, 0, 138, 6, 3, 0, 138, 6, 3, 0, 138, 6, 3, 0, 138, 6, 3, 0, 138, 6, 3, 0, 138, 6, 3, 0, 138, 6, 3, 0, 138, 6, 3, 0, 138, 6, 3, 0, 138, 6, 3, 0, 138, 6, 3, 0, 138, 6, 3, 0, 138, 6, 3, 0, 138, 6, 3, 0, 148, 6, 3, 0, 148, 6, 3, 0, 148, 6, 3, 0, 148, 6, 3, 0, 148, 6, 3, 0, 148, 6, 3, 0, 148, 6, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 138, 9, 3, 0, 138, 9, 3, 0, 138, 9, 3, 0, 138, 9, 3, 0, 138, 9, 3, 0, 138, 9, 3, 0, 138, 9, 3, 0, 138, 9, 3, 0, + 138, 9, 3, 0, 138, 9, 3, 0, 138, 9, 3, 0, 138, 9, 3, 0, 138, 9, 3, 0, 138, 9, 3, 0, 138, 9, 3, 0, 138, 9, 3, 0, 138, 9, 3, 0, 138, 9, 3, 0, 138, 9, 3, 0, 138, 9, 3, 0, 138, 9, 3, 0, 138, 9, 3, 0, 138, 9, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 80, 68, 5, 0, + 80, 68, 5, 0, 80, 68, 5, 0, 80, 68, 5, 0, 80, 68, 5, 0, 80, 68, 5, 0, 80, 68, 5, 0, 91, 68, 4, 0, 91, 68, 4, 0, 91, 4, 3, 0, 91, 4, 3, 0, 91, 4, 3, 0, 91, 4, 3, 0, 91, 4, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 84, 4, 3, 0, 84, 4, 3, 0, 84, 4, 3, 0, 84, 4, 3, 0, 84, 4, 3, 0, 84, 4, 3, 0, 84, 4, 3, 0, 84, 4, 3, 0, + 84, 4, 3, 0, 84, 4, 3, 0, 84, 4, 3, 0, 84, 4, 3, 0, 84, 4, 3, 0, 84, 4, 3, 0, 84, 4, 3, 0, 84, 4, 3, 0, 82, 196, 2, 0, 82, 196, 2, 0, 82, 196, 2, 0, 82, 196, 2, 0, 82, 196, 2, 0, 82, 196, 2, 0, 82, 196, 2, 0, 82, 196, 2, 0, 82, 196, 2, 0, 82, 196, 2, 0, 80, 68, 5, 0, 74, 4, 3, 0, 74, 4, 3, 0, 80, 68, 5, 0, 80, 68, 5, 0, 74, 4, 3, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 80, 68, 5, 0, 91, 81, 4, 0, 91, 81, 4, 0, 80, 81, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 66, 17, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 10, 33, 3, 0, 10, 33, 3, 0, 10, 33, 3, 0, 10, 33, 3, 0, 10, 33, 3, 0, 10, 33, 3, 0, 10, 33, 3, 0, 10, 33, 3, 0, 10, 33, 3, 0, 10, 33, 3, 0, 10, 33, 3, 0, 10, 33, 3, 0, 10, 33, 3, 0, 10, 33, 3, 0, 10, 33, 3, 0, 10, 33, 3, 0, 10, 33, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 18, 225, 2, 0, + 18, 225, 2, 0, 18, 225, 2, 0, 18, 225, 2, 0, 18, 225, 2, 0, 18, 225, 2, 0, 18, 225, 2, 0, 18, 225, 2, 0, 18, 225, 2, 0, 18, 225, 2, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 74, 5, 3, 0, 74, 5, 3, 0, 74, 5, 3, 0, 74, 5, 3, 0, 74, 5, 3, 0, 74, 5, 3, 0, 74, 5, 3, 0, 80, 69, 5, 0, 80, 69, 5, 0, 80, 69, 5, 0, + 80, 69, 5, 0, 80, 69, 5, 0, 78, 69, 5, 0, 80, 69, 5, 0, 80, 69, 5, 0, 80, 69, 5, 0, 80, 69, 5, 0, 80, 69, 5, 0, 80, 69, 5, 0, 80, 69, 5, 0, 80, 69, 5, 0, 3, 0, 0, 0, 82, 197, 2, 0, 82, 197, 2, 0, 82, 197, 2, 0, 82, 197, 2, 0, 82, 197, 2, 0, 82, 197, 2, 0, 82, 197, 2, 0, 82, 197, 2, 0, 82, 197, 2, 0, 82, 197, 2, 0, 91, 69, 4, 0, 91, 69, 4, 0, 91, 69, 4, 0, + 91, 69, 4, 0, 74, 5, 3, 0, 78, 69, 5, 0, 78, 69, 5, 0, 74, 5, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 10, 20, 3, 0, 10, 20, 3, 0, 10, 20, 3, 0, 10, 20, 3, 0, 10, 20, 3, 0, 10, 20, 3, 0, 10, 20, 3, 0, 10, 20, 3, 0, 10, 20, 3, 0, 10, 20, 3, 0, 10, 20, 3, 0, 10, 20, 3, 0, + 10, 20, 3, 0, 10, 20, 3, 0, 10, 20, 3, 0, 10, 20, 3, 0, 10, 20, 3, 0, 10, 20, 3, 0, 10, 20, 3, 0, 16, 84, 5, 0, 27, 20, 3, 0, 27, 148, 4, 0, 10, 20, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 84, 32, 3, 0, 84, 32, 3, 0, 84, 32, 3, 0, 84, 32, 3, 0, + 84, 32, 3, 0, 84, 32, 3, 0, 84, 32, 3, 0, 84, 32, 3, 0, 84, 32, 3, 0, 84, 32, 3, 0, 84, 32, 3, 0, 84, 32, 3, 0, 84, 32, 3, 0, 84, 32, 3, 0, 84, 32, 3, 0, 84, 32, 3, 0, 84, 32, 3, 0, 84, 32, 3, 0, 84, 32, 3, 0, 84, 32, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 138, 16, 3, 0, 138, 16, 3, 0, 138, 16, 3, 0, 138, 16, 3, 0, 138, 16, 3, 0, 138, 16, 3, 0, 138, 16, 3, 0, 138, 16, 3, 0, 138, 16, 3, 0, 138, 16, 3, 0, 138, 16, 3, 0, 138, 16, 3, 0, 138, 16, 3, 0, 138, 16, 3, 0, 138, 16, 3, 0, 138, 16, 3, 0, 138, 16, 3, 0, 138, 16, 3, 0, 3, 0, 0, 0, 138, 16, 3, 0, 138, 16, 3, 0, 138, 16, 3, 0, 138, 16, 3, 0, + 138, 16, 3, 0, 138, 16, 3, 0, 138, 16, 3, 0, 138, 16, 3, 0, 138, 16, 3, 0, 138, 16, 3, 0, 138, 16, 3, 0, 138, 16, 3, 0, 138, 16, 3, 0, 142, 80, 5, 0, 142, 80, 5, 0, 142, 80, 5, 0, 144, 80, 5, 0, 144, 80, 5, 0, 144, 80, 5, 0, 142, 80, 5, 0, 142, 80, 5, 0, 144, 80, 5, 0, 142, 80, 5, 0, 144, 80, 5, 0, 144, 80, 5, 0, 155, 80, 4, 0, 155, 80, 4, 0, 155, 16, 3, 0, 155, 80, 4, 0, + 155, 80, 4, 0, 155, 16, 3, 0, 144, 80, 5, 0, 3, 0, 0, 0, 138, 23, 3, 0, 138, 23, 3, 0, 138, 23, 3, 0, 138, 23, 3, 0, 138, 23, 3, 0, 138, 23, 3, 0, 138, 23, 3, 0, 3, 0, 0, 0, 138, 23, 3, 0, 3, 0, 0, 0, 138, 23, 3, 0, 138, 23, 3, 0, 138, 23, 3, 0, 138, 23, 3, 0, 3, 0, 0, 0, 138, 23, 3, 0, 138, 23, 3, 0, 138, 23, 3, 0, 138, 23, 3, 0, 138, 23, 3, 0, 138, 23, 3, 0, + 138, 23, 3, 0, 138, 23, 3, 0, 138, 23, 3, 0, 138, 23, 3, 0, 138, 23, 3, 0, 138, 23, 3, 0, 138, 23, 3, 0, 138, 23, 3, 0, 138, 23, 3, 0, 3, 0, 0, 0, 138, 23, 3, 0, 138, 23, 3, 0, 138, 23, 3, 0, 138, 23, 3, 0, 138, 23, 3, 0, 138, 23, 3, 0, 138, 23, 3, 0, 138, 23, 3, 0, 138, 23, 3, 0, 138, 23, 3, 0, 155, 87, 4, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 10, 32, 3, 0, 10, 32, 3, 0, 10, 32, 3, 0, 10, 32, 3, 0, 10, 32, 3, 0, 10, 32, 3, 0, 10, 32, 3, 0, 10, 32, 3, 0, 10, 32, 3, 0, 10, 32, 3, 0, 10, 32, 3, 0, 10, 32, 3, 0, 10, 32, 3, 0, 10, 32, 3, 0, 10, 32, 3, 0, 10, 32, 3, 0, 14, 96, 5, 0, 14, 96, 5, 0, 14, 96, 5, 0, 16, 96, 5, 0, 16, 96, 5, 0, 16, 96, 5, 0, 16, 96, 5, 0, + 16, 96, 5, 0, 16, 96, 5, 0, 16, 96, 5, 0, 16, 96, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 18, 224, 2, 0, 18, 224, 2, 0, 18, 224, 2, 0, 18, 224, 2, 0, 18, 224, 2, 0, 18, 224, 2, 0, 18, 224, 2, 0, 18, 224, 2, 0, 18, 224, 2, 0, 18, 224, 2, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 80, 75, 5, 0, 80, 75, 5, 0, 78, 75, 5, 0, 78, 75, 5, 0, 3, 0, 0, 0, 74, 11, 3, 0, 74, 11, 3, 0, 74, 11, 3, 0, 74, 11, 3, 0, 74, 11, 3, 0, 74, 11, 3, 0, 74, 11, 3, 0, 74, 11, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 74, 11, 3, 0, 74, 11, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 74, 11, 3, 0, 74, 11, 3, 0, 74, 11, 3, 0, 74, 11, 3, 0, 74, 11, 3, 0, 74, 11, 3, 0, + 74, 11, 3, 0, 74, 11, 3, 0, 74, 11, 3, 0, 74, 11, 3, 0, 74, 11, 3, 0, 74, 11, 3, 0, 74, 11, 3, 0, 74, 11, 3, 0, 3, 0, 0, 0, 74, 11, 3, 0, 74, 11, 3, 0, 74, 11, 3, 0, 74, 11, 3, 0, 74, 11, 3, 0, 74, 11, 3, 0, 74, 11, 3, 0, 3, 0, 0, 0, 74, 11, 3, 0, 74, 11, 3, 0, 3, 0, 0, 0, 74, 11, 3, 0, 74, 11, 3, 0, 74, 11, 3, 0, 74, 11, 3, 0, 74, 11, 3, 0, + 3, 0, 0, 0, 144, 64, 5, 0, 80, 75, 5, 0, 74, 11, 3, 0, 78, 75, 5, 0, 78, 75, 5, 0, 80, 75, 5, 0, 78, 75, 5, 0, 78, 75, 5, 0, 78, 75, 5, 0, 78, 75, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 78, 75, 5, 0, 78, 75, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 78, 75, 5, 0, 78, 75, 5, 0, 78, 75, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 74, 11, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 78, 75, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 74, 11, 3, 0, 74, 11, 3, 0, 74, 11, 3, 0, 74, 11, 3, 0, 74, 11, 3, 0, 78, 75, 5, 0, 78, 75, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 80, 75, 5, 0, 80, 75, 5, 0, 80, 75, 5, 0, 80, 75, 5, 0, 80, 75, 5, 0, 80, 75, 5, 0, + 80, 75, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 80, 75, 5, 0, 80, 75, 5, 0, 80, 75, 5, 0, 80, 75, 5, 0, 80, 75, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 206, 88, 5, 0, 206, 88, 5, 0, 208, 88, 5, 0, 208, 88, 5, 0, 208, 88, 5, 0, + 206, 88, 5, 0, 208, 88, 5, 0, 202, 24, 3, 0, 202, 24, 3, 0, 202, 24, 3, 0, 202, 24, 3, 0, 219, 88, 4, 0, 219, 88, 4, 0, 219, 88, 4, 0, 219, 88, 4, 0, 219, 24, 3, 0, 210, 216, 2, 0, 210, 216, 2, 0, 210, 216, 2, 0, 210, 216, 2, 0, 210, 216, 2, 0, 210, 216, 2, 0, 210, 216, 2, 0, 210, 216, 2, 0, 210, 216, 2, 0, 210, 216, 2, 0, 219, 88, 4, 0, 219, 88, 4, 0, 3, 0, 0, 0, 219, 24, 3, 0, + 208, 88, 5, 0, 202, 24, 3, 0, 202, 24, 3, 0, 202, 24, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 144, 101, 5, 0, 142, 101, 5, 0, 144, 101, 5, 0, 144, 101, 5, 0, 138, 37, 3, 0, 138, 37, 3, 0, 155, 37, 3, 0, 138, 37, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 146, 229, 2, 0, 146, 229, 2, 0, 146, 229, 2, 0, 146, 229, 2, 0, 146, 229, 2, 0, 146, 229, 2, 0, 146, 229, 2, 0, 146, 229, 2, 0, 146, 229, 2, 0, 146, 229, 2, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 202, 31, 3, 0, 202, 31, 3, 0, 202, 31, 3, 0, 202, 31, 3, 0, 202, 31, 3, 0, 202, 31, 3, 0, 202, 31, 3, 0, 202, 31, 3, 0, 202, 31, 3, 0, + 202, 31, 3, 0, 202, 31, 3, 0, 202, 31, 3, 0, 202, 31, 3, 0, 202, 31, 3, 0, 202, 31, 3, 0, 206, 95, 5, 0, 206, 95, 5, 0, 206, 95, 5, 0, 208, 95, 5, 0, 208, 95, 5, 0, 208, 95, 5, 0, 208, 95, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 206, 95, 5, 0, 206, 95, 5, 0, 206, 95, 5, 0, 206, 95, 5, 0, 208, 95, 5, 0, 208, 95, 5, 0, 206, 95, 5, 0, 208, 95, 5, 0, 208, 95, 5, 0, 219, 159, 4, 0, + 219, 95, 4, 0, 219, 95, 4, 0, 219, 159, 1, 0, 219, 159, 1, 0, 219, 31, 3, 0, 219, 31, 3, 0, 219, 31, 3, 0, 219, 95, 4, 0, 219, 95, 4, 0, 219, 95, 4, 0, 219, 95, 4, 0, 219, 95, 4, 0, 219, 95, 4, 0, 219, 95, 4, 0, 219, 95, 4, 0, 219, 95, 4, 0, 219, 95, 4, 0, 219, 95, 4, 0, 219, 95, 4, 0, 219, 95, 4, 0, 219, 95, 4, 0, 219, 95, 4, 0, 202, 31, 3, 0, 202, 31, 3, 0, 202, 31, 3, 0, + 202, 31, 3, 0, 208, 95, 5, 0, 208, 95, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 144, 86, 5, 0, 155, 86, 4, 0, 155, 86, 4, 0, 155, 22, 3, 0, 138, 22, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 146, 214, 2, 0, 146, 214, 2, 0, 146, 214, 2, 0, 146, 214, 2, 0, + 146, 214, 2, 0, 146, 214, 2, 0, 146, 214, 2, 0, 146, 214, 2, 0, 146, 214, 2, 0, 146, 214, 2, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 219, 150, 4, 0, 219, 150, 4, 0, 219, 150, 4, 0, 219, 150, 4, 0, 219, 150, 4, 0, 219, 150, 4, 0, 219, 150, 4, 0, 219, 150, 4, 0, 219, 150, 4, 0, 219, 150, 4, 0, 219, 150, 4, 0, 219, 150, 4, 0, 219, 150, 4, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 138, 34, 3, 0, 138, 34, 3, 0, 138, 34, 3, 0, 138, 34, 3, 0, 138, 34, 3, 0, 138, 34, 3, 0, + 138, 34, 3, 0, 138, 34, 3, 0, 138, 34, 3, 0, 138, 34, 3, 0, 138, 34, 3, 0, 144, 98, 5, 0, 142, 98, 5, 0, 144, 98, 5, 0, 142, 98, 5, 0, 142, 98, 5, 0, 144, 98, 5, 0, 144, 98, 5, 0, 144, 98, 5, 0, 144, 98, 5, 0, 144, 98, 5, 0, 144, 98, 5, 0, 142, 98, 5, 0, 144, 98, 5, 0, 138, 34, 3, 0, 155, 34, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 146, 226, 2, 0, 146, 226, 2, 0, 146, 226, 2, 0, 146, 226, 2, 0, 146, 226, 2, 0, 146, 226, 2, 0, 146, 226, 2, 0, 146, 226, 2, 0, 146, 226, 2, 0, 146, 226, 2, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 74, 1, 10, 0, 74, 1, 10, 0, 74, 1, 10, 0, 74, 1, 10, 0, 74, 1, 10, 0, 74, 1, 10, 0, 74, 1, 10, 0, 74, 1, 10, 0, 74, 1, 10, 0, 74, 1, 10, 0, 74, 1, 10, 0, 74, 1, 10, 0, 74, 1, 10, 0, 74, 1, 10, 0, 74, 1, 10, 0, 74, 1, 10, 0, 74, 1, 10, 0, + 74, 1, 10, 0, 74, 1, 10, 0, 74, 1, 10, 0, 74, 1, 10, 0, 74, 1, 10, 0, 74, 1, 10, 0, 74, 1, 10, 0, 74, 1, 10, 0, 74, 1, 10, 0, 74, 1, 10, 0, 3, 0, 0, 0, 3, 0, 0, 0, 80, 1, 10, 0, 80, 1, 10, 0, 80, 1, 10, 0, 78, 1, 10, 0, 78, 1, 10, 0, 80, 1, 10, 0, 80, 1, 10, 0, 80, 1, 10, 0, 80, 1, 10, 0, 78, 1, 10, 0, 80, 1, 10, 0, 80, 1, 10, 0, 80, 1, 10, 0, + 80, 1, 10, 0, 80, 1, 10, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 82, 193, 2, 0, 82, 193, 2, 0, 82, 193, 2, 0, 82, 193, 2, 0, 82, 193, 2, 0, 82, 193, 2, 0, 82, 193, 2, 0, 82, 193, 2, 0, 82, 193, 2, 0, 82, 193, 2, 0, 84, 1, 10, 0, 84, 1, 10, 0, 91, 65, 4, 0, 91, 65, 4, 0, 91, 65, 4, 0, 97, 1, 10, 0, 74, 1, 10, 0, 74, 1, 10, 0, 74, 1, 10, 0, + 74, 1, 10, 0, 74, 1, 10, 0, 74, 1, 10, 0, 74, 1, 10, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 74, 8, 3, 0, 74, 8, 3, 0, 74, 8, 3, 0, 74, 8, 3, 0, 74, 8, 3, 0, 74, 8, 3, 0, 74, 8, 3, 0, 74, 8, 3, 0, 74, 8, 3, 0, 74, 8, 3, 0, 74, 8, 3, 0, 74, 8, 3, 0, 78, 72, 5, 0, 78, 72, 5, 0, 78, 72, 5, 0, 80, 72, 5, 0, 80, 72, 5, 0, 80, 72, 5, 0, 80, 72, 5, 0, 80, 72, 5, 0, 80, 72, 5, 0, + 80, 72, 5, 0, 80, 72, 5, 0, 80, 72, 5, 0, 78, 72, 5, 0, 80, 72, 5, 0, 80, 72, 5, 0, 91, 8, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 18, 231, 2, 0, 18, 231, 2, 0, 18, 231, 2, 0, 18, 231, 2, 0, 18, 231, 2, 0, 18, 231, 2, 0, 18, 231, 2, 0, 18, 231, 2, 0, 18, 231, 2, 0, 18, 231, 2, 0, 20, 39, 3, 0, 20, 39, 3, 0, 20, 39, 3, 0, 20, 39, 3, 0, + 20, 39, 3, 0, 20, 39, 3, 0, 20, 39, 3, 0, 20, 39, 3, 0, 20, 39, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 10, 39, 3, 0, 10, 8, 3, 0, 10, 8, 3, 0, 10, 8, 3, 0, 10, 8, 3, 0, 10, 8, 3, 0, 10, 8, 3, 0, 10, 8, 3, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 10, 8, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 10, 8, 3, 0, 10, 8, 3, 0, 10, 8, 3, 0, 10, 8, 3, 0, 10, 8, 3, 0, 10, 8, 3, 0, 10, 8, 3, 0, 10, 8, 3, 0, 3, 0, 0, 0, 10, 8, 3, 0, 10, 8, 3, 0, 3, 0, 0, 0, 10, 8, 3, 0, 10, 8, 3, 0, 10, 8, 3, 0, 10, 8, 3, 0, 10, 8, 3, 0, 10, 8, 3, 0, 10, 8, 3, 0, 10, 8, 3, 0, + 10, 8, 3, 0, 10, 8, 3, 0, 10, 8, 3, 0, 10, 8, 3, 0, 10, 8, 3, 0, 10, 8, 3, 0, 10, 8, 3, 0, 10, 8, 3, 0, 14, 72, 5, 0, 14, 72, 5, 0, 14, 72, 5, 0, 14, 72, 5, 0, 14, 72, 5, 0, 14, 72, 5, 0, 3, 0, 0, 0, 14, 72, 5, 0, 14, 72, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 16, 72, 5, 0, 16, 72, 5, 0, 14, 72, 5, 0, 16, 72, 5, 0, 10, 8, 3, 0, 14, 72, 5, 0, + 10, 8, 3, 0, 14, 72, 5, 0, 16, 72, 5, 0, 27, 72, 4, 0, 27, 72, 4, 0, 27, 72, 4, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 18, 200, 2, 0, 18, 200, 2, 0, 18, 200, 2, 0, 18, 200, 2, 0, 18, 200, 2, 0, 18, 200, 2, 0, 18, 200, 2, 0, 18, 200, 2, 0, 18, 200, 2, 0, 18, 200, 2, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 10, 24, 3, 0, 10, 24, 3, 0, 10, 24, 3, 0, 10, 24, 3, 0, 10, 24, 3, 0, 10, 24, 3, 0, 10, 24, 3, 0, 10, 24, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 10, 24, 3, 0, 10, 24, 3, 0, 10, 24, 3, 0, 10, 24, 3, 0, 10, 24, 3, 0, 10, 24, 3, 0, 10, 24, 3, 0, 10, 24, 3, 0, 10, 24, 3, 0, + 10, 24, 3, 0, 10, 24, 3, 0, 10, 24, 3, 0, 10, 24, 3, 0, 10, 24, 3, 0, 10, 24, 3, 0, 10, 24, 3, 0, 10, 24, 3, 0, 10, 24, 3, 0, 10, 24, 3, 0, 10, 24, 3, 0, 10, 24, 3, 0, 10, 24, 3, 0, 10, 24, 3, 0, 14, 88, 5, 0, 14, 88, 5, 0, 14, 88, 5, 0, 16, 88, 5, 0, 16, 88, 5, 0, 16, 88, 5, 0, 16, 88, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 16, 88, 5, 0, 16, 88, 5, 0, + 14, 88, 5, 0, 14, 88, 5, 0, 14, 88, 5, 0, 14, 88, 5, 0, 16, 88, 5, 0, 10, 24, 3, 0, 27, 152, 4, 0, 10, 24, 3, 0, 14, 88, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 155, 40, 3, 0, 155, 104, 4, 0, 155, 104, 4, 0, 155, 104, 4, 0, 155, 104, 4, 0, 155, 168, 4, 0, 155, 40, 3, 0, 144, 104, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 74, 33, 3, 0, 80, 97, 5, 0, 80, 97, 5, 0, 80, 97, 5, 0, 80, 97, 5, 0, 80, 97, 5, 0, 80, 97, 5, 0, 78, 97, 5, 0, 78, 97, 5, 0, 80, 97, 5, 0, 80, 97, 5, 0, 80, 97, 5, 0, 74, 33, 3, 0, 74, 33, 3, 0, 74, 33, 3, 0, 74, 33, 3, 0, 91, 161, 4, 0, 91, 97, 4, 0, 91, 97, 4, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, + 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 202, 3, 3, 0, 202, 3, 3, 0, 202, 3, 3, 0, 202, 3, 3, 0, 202, 3, 3, 0, 202, 3, 3, 0, 202, 3, 3, 0, 202, 3, 3, 0, 202, 3, 3, 0, 3, 0, 0, 0, 202, 3, 3, 0, 202, 3, 3, 0, 202, 3, 3, 0, 202, 3, 3, 0, 202, 3, 3, 0, 202, 3, 3, 0, 202, 3, 3, 0, 202, 3, 3, 0, + 202, 3, 3, 0, 202, 3, 3, 0, 202, 3, 3, 0, 202, 3, 3, 0, 202, 3, 3, 0, 202, 3, 3, 0, 202, 3, 3, 0, 202, 3, 3, 0, 202, 3, 3, 0, 202, 3, 3, 0, 202, 3, 3, 0, 202, 3, 3, 0, 202, 3, 3, 0, 202, 3, 3, 0, 202, 3, 3, 0, 202, 3, 3, 0, 202, 3, 3, 0, 206, 67, 5, 0, 208, 67, 5, 0, 208, 67, 5, 0, 208, 67, 5, 0, 208, 67, 5, 0, 208, 67, 5, 0, 208, 67, 5, 0, 208, 67, 5, 0, + 3, 0, 0, 0, 208, 67, 5, 0, 208, 67, 5, 0, 208, 67, 5, 0, 208, 67, 5, 0, 208, 67, 5, 0, 208, 67, 5, 0, 206, 67, 5, 0, 208, 67, 5, 0, 202, 3, 3, 0, 219, 67, 4, 0, 219, 67, 4, 0, 219, 67, 4, 0, 219, 67, 4, 0, 219, 67, 4, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 210, 195, 2, 0, 210, 195, 2, 0, 210, 195, 2, 0, 210, 195, 2, 0, 210, 195, 2, 0, 210, 195, 2, 0, 210, 195, 2, 0, 210, 195, 2, 0, 210, 195, 2, 0, 210, 195, 2, 0, 212, 3, 3, 0, 212, 3, 3, 0, 212, 3, 3, 0, 212, 3, 3, 0, 212, 3, 3, 0, 212, 3, 3, 0, 212, 3, 3, 0, 212, 3, 3, 0, 212, 3, 3, 0, 212, 3, 3, 0, 212, 3, 3, 0, 212, 3, 3, 0, 212, 3, 3, 0, 212, 3, 3, 0, 212, 3, 3, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 27, 149, 4, 0, 27, 149, 1, 0, 10, 21, 3, 0, 10, 21, 3, 0, 10, 21, 3, 0, 10, 21, 3, 0, 10, 21, 3, 0, 10, 21, 3, 0, 10, 21, 3, 0, 10, 21, 3, 0, 10, 21, 3, 0, 10, 21, 3, 0, 10, 21, 3, 0, 10, 21, 3, 0, 10, 21, 3, 0, 10, 21, 3, 0, 10, 21, 3, 0, 10, 21, 3, 0, 10, 21, 3, 0, 10, 21, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 16, 85, 5, 0, 16, 85, 5, 0, 16, 85, 5, 0, 16, 85, 5, 0, 16, 85, 5, 0, 16, 85, 5, 0, 16, 85, 5, 0, 16, 85, 5, 0, 16, 85, 5, 0, 16, 85, 5, 0, 16, 85, 5, 0, 16, 85, 5, 0, 16, 85, 5, 0, 16, 85, 5, 0, 3, 0, 0, 0, 14, 85, 5, 0, 16, 85, 5, 0, 16, 85, 5, 0, 16, 85, 5, 0, 16, 85, 5, 0, 16, 85, 5, 0, 16, 85, 5, 0, 16, 85, 5, 0, 14, 85, 5, 0, 16, 85, 5, 0, + 16, 85, 5, 0, 14, 85, 5, 0, 16, 85, 5, 0, 16, 85, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 202, 10, 3, 0, 202, 10, 3, 0, 202, 10, 3, 0, 202, 10, 3, 0, 202, 10, 3, 0, 202, 10, 3, 0, 202, 10, 3, 0, 3, 0, 0, 0, 202, 10, 3, 0, 202, 10, 3, 0, 3, 0, 0, 0, 202, 10, 3, 0, + 202, 10, 3, 0, 202, 10, 3, 0, 202, 10, 3, 0, 202, 10, 3, 0, 202, 10, 3, 0, 202, 10, 3, 0, 202, 10, 3, 0, 202, 10, 3, 0, 202, 10, 3, 0, 202, 10, 3, 0, 202, 10, 3, 0, 202, 10, 3, 0, 202, 10, 3, 0, 202, 10, 3, 0, 202, 10, 3, 0, 202, 10, 3, 0, 202, 10, 3, 0, 202, 10, 3, 0, 202, 10, 3, 0, 202, 10, 3, 0, 202, 10, 3, 0, 208, 74, 5, 0, 208, 74, 5, 0, 208, 74, 5, 0, 208, 74, 5, 0, + 208, 74, 5, 0, 208, 74, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 208, 74, 5, 0, 3, 0, 0, 0, 208, 74, 5, 0, 208, 74, 5, 0, 3, 0, 0, 0, 208, 74, 5, 0, 208, 74, 5, 0, 208, 74, 5, 0, 208, 74, 5, 0, 208, 74, 5, 0, 208, 74, 5, 0, 208, 74, 5, 0, 202, 10, 3, 0, 208, 74, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 210, 202, 2, 0, 210, 202, 2, 0, 210, 202, 2, 0, 210, 202, 2, 0, 210, 202, 2, 0, 210, 202, 2, 0, 210, 202, 2, 0, 210, 202, 2, 0, 210, 202, 2, 0, 210, 202, 2, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 138, 10, 3, 0, 138, 10, 3, 0, 138, 10, 3, 0, 138, 10, 3, 0, 138, 10, 3, 0, 138, 10, 3, 0, 3, 0, 0, 0, + 138, 10, 3, 0, 138, 10, 3, 0, 3, 0, 0, 0, 138, 10, 3, 0, 138, 10, 3, 0, 138, 10, 3, 0, 138, 10, 3, 0, 138, 10, 3, 0, 138, 10, 3, 0, 138, 10, 3, 0, 138, 10, 3, 0, 138, 10, 3, 0, 138, 10, 3, 0, 138, 10, 3, 0, 138, 10, 3, 0, 138, 10, 3, 0, 138, 10, 3, 0, 138, 10, 3, 0, 138, 10, 3, 0, 138, 10, 3, 0, 138, 10, 3, 0, 138, 10, 3, 0, 138, 10, 3, 0, 138, 10, 3, 0, 138, 10, 3, 0, + 138, 10, 3, 0, 138, 10, 3, 0, 142, 74, 5, 0, 142, 74, 5, 0, 142, 74, 5, 0, 142, 74, 5, 0, 142, 74, 5, 0, 3, 0, 0, 0, 144, 74, 5, 0, 144, 74, 5, 0, 3, 0, 0, 0, 142, 74, 5, 0, 142, 74, 5, 0, 144, 74, 5, 0, 142, 74, 5, 0, 144, 74, 5, 0, 138, 10, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 146, 202, 2, 0, + 146, 202, 2, 0, 146, 202, 2, 0, 146, 202, 2, 0, 146, 202, 2, 0, 146, 202, 2, 0, 146, 202, 2, 0, 146, 202, 2, 0, 146, 202, 2, 0, 146, 202, 2, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 74, 20, 3, 0, 74, 20, 3, 0, 74, 20, 3, 0, 74, 20, 3, 0, 74, 20, 3, 0, 74, 20, 3, 0, 74, 20, 3, 0, 74, 20, 3, 0, 74, 20, 3, 0, 74, 20, 3, 0, 74, 20, 3, 0, 74, 20, 3, 0, 74, 20, 3, 0, 74, 20, 3, 0, 74, 20, 3, 0, 74, 20, 3, 0, 74, 20, 3, 0, 74, 20, 3, 0, 74, 20, 3, 0, + 80, 84, 5, 0, 80, 84, 5, 0, 78, 84, 5, 0, 78, 84, 5, 0, 91, 20, 3, 0, 91, 20, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 74, 19, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 94, 163, 2, 0, 97, 35, 3, 0, 97, 35, 3, 0, 97, 35, 3, 0, 97, 35, 3, 0, 97, 35, 3, 0, 97, 35, 3, 0, 97, 35, 3, 0, 97, 35, 3, 0, + 97, 35, 3, 0, 97, 35, 3, 0, 97, 35, 3, 0, 97, 35, 3, 0, 97, 35, 3, 0, 97, 35, 3, 0, 97, 35, 3, 0, 97, 35, 3, 0, 97, 35, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 91, 99, 4, 0, 202, 39, 3, 0, 202, 39, 3, 0, + 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 211, 39, 3, 0, 211, 39, 3, 0, 211, 39, 3, 0, 211, 39, 3, 0, 211, 39, 3, 0, 211, 39, 3, 0, 211, 39, 3, 0, 211, 39, 3, 0, 211, 39, 3, 0, 211, 39, 3, 0, 211, 39, 3, 0, 211, 39, 3, 0, 211, 39, 3, 0, 211, 39, 3, 0, 211, 39, 3, 0, 3, 0, 0, 0, 219, 103, 4, 0, 219, 103, 4, 0, 219, 103, 4, 0, 219, 103, 4, 0, + 219, 103, 4, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 10, 7, 3, 0, 10, 7, 3, 0, 10, 7, 3, 0, 10, 7, 3, 0, 10, 7, 3, 0, 10, 7, 3, 0, + 10, 7, 3, 0, 10, 7, 3, 0, 10, 7, 3, 0, 10, 7, 3, 0, 10, 7, 3, 0, 10, 7, 3, 0, 10, 7, 3, 0, 10, 7, 3, 0, 10, 7, 3, 0, 10, 7, 3, 0, 10, 7, 3, 0, 27, 7, 3, 0, 27, 7, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 3, 0, 0, 0, 2, 9, 1, 0, 2, 9, 1, 0, 2, 9, 1, 0, 2, 9, 1, 0, 2, 9, 1, 0, 2, 9, 1, 0, 2, 9, 1, 0, 2, 9, 0, 0, + 2, 73, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, + 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 10, 23, 3, 0, 10, 23, 3, 0, 10, 23, 3, 0, + 10, 23, 3, 0, 10, 23, 3, 0, 10, 23, 3, 0, 10, 23, 3, 0, 10, 23, 3, 0, 10, 23, 3, 0, 10, 23, 3, 0, 10, 23, 3, 0, 10, 23, 3, 0, 10, 23, 3, 0, 10, 23, 3, 0, 10, 23, 3, 0, 10, 23, 3, 0, 10, 23, 3, 0, 10, 23, 3, 0, 10, 23, 3, 0, 10, 23, 3, 0, 10, 23, 3, 0, 10, 23, 3, 0, 10, 23, 3, 0, 10, 23, 3, 0, 10, 23, 3, 0, 10, 23, 3, 0, 10, 23, 3, 0, 10, 23, 3, 0, + 10, 23, 3, 0, 10, 23, 3, 0, 10, 23, 3, 0, 3, 0, 0, 0, 18, 215, 2, 0, 18, 215, 2, 0, 18, 215, 2, 0, 18, 215, 2, 0, 18, 215, 2, 0, 18, 215, 2, 0, 18, 215, 2, 0, 18, 215, 2, 0, 18, 215, 2, 0, 18, 215, 2, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 27, 87, 4, 0, 27, 87, 4, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, + 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, + 202, 37, 3, 0, 3, 0, 0, 0, 210, 229, 2, 0, 210, 229, 2, 0, 210, 229, 2, 0, 210, 229, 2, 0, 210, 229, 2, 0, 210, 229, 2, 0, 210, 229, 2, 0, 210, 229, 2, 0, 210, 229, 2, 0, 210, 229, 2, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 10, 3, 3, 0, 10, 3, 3, 0, 10, 3, 3, 0, 10, 3, 3, 0, 10, 3, 3, 0, 10, 3, 3, 0, 10, 3, 3, 0, + 10, 3, 3, 0, 10, 3, 3, 0, 10, 3, 3, 0, 10, 3, 3, 0, 10, 3, 3, 0, 10, 3, 3, 0, 10, 3, 3, 0, 10, 3, 3, 0, 10, 3, 3, 0, 10, 3, 3, 0, 10, 3, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 16, 67, 5, 0, 16, 67, 5, 0, 16, 67, 5, 0, 16, 67, 5, 0, 16, 67, 5, 0, 27, 67, 4, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 9, 14, 3, 0, 9, 14, 3, 0, 9, 14, 3, 0, 9, 14, 3, 0, 27, 78, 4, 0, 33, 14, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 18, 206, 2, 0, 18, 206, 2, 0, 18, 206, 2, 0, 18, 206, 2, 0, 18, 206, 2, 0, + 18, 206, 2, 0, 18, 206, 2, 0, 18, 206, 2, 0, 18, 206, 2, 0, 18, 206, 2, 0, 3, 0, 0, 0, 20, 14, 3, 0, 20, 14, 3, 0, 20, 14, 3, 0, 20, 14, 3, 0, 20, 14, 3, 0, 20, 14, 3, 0, 20, 14, 3, 0, 3, 0, 0, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, + 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, + 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 84, 21, 3, 0, 84, 21, 3, 0, 84, 21, 3, 0, 84, 21, 3, 0, 84, 21, 3, 0, 84, 21, 3, 0, 84, 21, 3, 0, 84, 21, 3, 0, 84, 21, 3, 0, 84, 21, 3, 0, 84, 21, 3, 0, 84, 21, 3, 0, 84, 21, 3, 0, 84, 21, 3, 0, 84, 21, 3, 0, 84, 21, 3, 0, 84, 21, 3, 0, 84, 21, 3, 0, 84, 21, 3, 0, 84, 21, 3, 0, 84, 21, 3, 0, 84, 21, 3, 0, 84, 21, 3, 0, 91, 85, 4, 0, 91, 85, 4, 0, + 91, 21, 3, 0, 91, 21, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 10, 29, 3, 0, 10, 29, 3, 0, 10, 29, 3, 0, 10, 29, 3, 0, 10, 29, 3, 0, 10, 29, 3, 0, 10, 29, 3, 0, 10, 29, 3, 0, 10, 29, 3, 0, 10, 29, 3, 0, 10, 29, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 16, 93, 5, 0, 10, 29, 3, 0, 14, 93, 5, 0, + 14, 93, 5, 0, 14, 93, 5, 0, 14, 93, 5, 0, 14, 93, 5, 0, 14, 93, 5, 0, 14, 93, 5, 0, 14, 93, 5, 0, 14, 93, 5, 0, 14, 93, 5, 0, 14, 93, 5, 0, 14, 93, 5, 0, 14, 93, 5, 0, 14, 93, 5, 0, 14, 93, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 16, 93, 5, 0, 16, 93, 5, 0, 16, 93, 5, 0, 16, 93, 5, 0, + 9, 29, 3, 0, 9, 29, 3, 0, 9, 29, 3, 0, 9, 29, 3, 0, 9, 29, 3, 0, 9, 29, 3, 0, 9, 29, 3, 0, 9, 29, 3, 0, 9, 29, 3, 0, 9, 29, 3, 0, 9, 29, 3, 0, 9, 29, 3, 0, 9, 29, 3, 0, 137, 99, 1, 0, 73, 89, 1, 0, 155, 76, 1, 0, 137, 76, 1, 0, 208, 16, 1, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 142, 76, 5, 0, 142, 76, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, + 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 201, 15, 3, 0, 201, 15, 3, 0, 201, 15, 3, 0, 201, 15, 3, 0, 3, 0, 0, 0, 201, 15, 3, 0, 201, 15, 3, 0, 201, 15, 3, 0, 201, 15, 3, 0, + 201, 15, 3, 0, 201, 15, 3, 0, 201, 15, 3, 0, 3, 0, 0, 0, 201, 15, 3, 0, 201, 15, 3, 0, 3, 0, 0, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 138, 13, 9, 0, 138, 13, 9, 0, 138, 13, 9, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 202, 15, 9, 0, 202, 15, 9, 0, 202, 15, 9, 0, 202, 15, 9, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, + 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 202, 8, 3, 0, + 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, + 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 225, 8, 3, 0, 208, 72, 5, 0, 208, 72, 5, 0, + 219, 72, 4, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 144, 64, 5, 0, + 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, + 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, + 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 144, 75, 5, 0, 144, 75, 5, 0, 144, 75, 5, 0, 161, 11, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, + 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 97, 0, 3, 0, + 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, + 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, + 76, 0, 3, 0, 76, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 3, 0, 0, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, + 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 76, 0, 3, 0, 3, 0, 0, 0, + 76, 0, 3, 0, 76, 0, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 76, 0, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 76, 0, 3, 0, 76, 0, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 3, 0, 0, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 72, 0, 3, 0, + 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 3, 0, 0, 0, 72, 0, 3, 0, 3, 0, 0, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 3, 0, 0, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, + 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 3, 0, 0, 0, 76, 0, 3, 0, 76, 0, 3, 0, + 76, 0, 3, 0, 76, 0, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 3, 0, 0, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 3, 0, 0, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, + 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 3, 0, 0, 0, + 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 3, 0, 0, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 3, 0, 0, 0, 76, 0, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 3, 0, 0, 0, 72, 0, 3, 0, 72, 0, 3, 0, + 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, + 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 96, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, + 76, 0, 3, 0, 72, 0, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 33, 31, 3, 0, 33, 31, 3, 0, 33, 31, 3, 0, + 33, 31, 3, 0, 16, 95, 5, 0, 33, 31, 3, 0, 33, 31, 3, 0, 27, 95, 4, 0, 27, 95, 4, 0, 27, 95, 4, 0, 27, 95, 4, 0, 27, 31, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 16, 95, 5, 0, + 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 3, 0, 0, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 10, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, + 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 3, 0, 0, 0, 80, 74, 5, 0, 80, 74, 5, 0, 80, 74, 5, 0, 80, 74, 5, 0, 80, 74, 5, 0, 80, 74, 5, 0, 80, 74, 5, 0, + 3, 0, 0, 0, 80, 74, 5, 0, 80, 74, 5, 0, 80, 74, 5, 0, 80, 74, 5, 0, 80, 74, 5, 0, 80, 74, 5, 0, 80, 74, 5, 0, 80, 74, 5, 0, 80, 74, 5, 0, 80, 74, 5, 0, 80, 74, 5, 0, 80, 74, 5, 0, 80, 74, 5, 0, 80, 74, 5, 0, 80, 74, 5, 0, 80, 74, 5, 0, 80, 74, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 80, 74, 5, 0, 80, 74, 5, 0, 80, 74, 5, 0, 80, 74, 5, 0, 80, 74, 5, 0, + 80, 74, 5, 0, 80, 74, 5, 0, 3, 0, 0, 0, 80, 74, 5, 0, 80, 74, 5, 0, 3, 0, 0, 0, 80, 74, 5, 0, 80, 74, 5, 0, 80, 74, 5, 0, 80, 74, 5, 0, 80, 74, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 74, 14, 3, 0, 74, 14, 3, 0, 74, 14, 3, 0, 74, 14, 3, 0, 74, 14, 3, 0, 74, 14, 3, 0, 74, 14, 3, 0, 74, 14, 3, 0, 74, 14, 3, 0, 74, 14, 3, 0, 74, 14, 3, 0, 74, 14, 3, 0, 74, 14, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 80, 78, 5, 0, 80, 78, 5, 0, + 80, 78, 5, 0, 80, 78, 5, 0, 80, 78, 5, 0, 80, 78, 5, 0, 80, 78, 5, 0, 73, 14, 3, 0, 73, 14, 3, 0, 73, 14, 3, 0, 73, 14, 3, 0, 73, 14, 3, 0, 73, 14, 3, 0, 73, 14, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 82, 206, 2, 0, 82, 206, 2, 0, 82, 206, 2, 0, 82, 206, 2, 0, 82, 206, 2, 0, 82, 206, 2, 0, 82, 206, 2, 0, 82, 206, 2, 0, 82, 206, 2, 0, 82, 206, 2, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 74, 14, 3, 0, 97, 14, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 10, 38, 3, 0, 10, 38, 3, 0, 10, 38, 3, 0, 10, 38, 3, 0, + 10, 38, 3, 0, 10, 38, 3, 0, 10, 38, 3, 0, 10, 38, 3, 0, 10, 38, 3, 0, 10, 38, 3, 0, 10, 38, 3, 0, 10, 38, 3, 0, 10, 38, 3, 0, 10, 38, 3, 0, 10, 38, 3, 0, 10, 38, 3, 0, 10, 38, 3, 0, 10, 38, 3, 0, 16, 102, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 74, 39, 3, 0, 74, 39, 3, 0, 74, 39, 3, 0, 74, 39, 3, 0, 74, 39, 3, 0, 74, 39, 3, 0, 74, 39, 3, 0, 74, 39, 3, 0, 74, 39, 3, 0, 74, 39, 3, 0, 74, 39, 3, 0, 74, 39, 3, 0, 80, 103, 5, 0, 80, 103, 5, 0, 80, 103, 5, 0, 80, 103, 5, 0, 82, 231, 2, 0, 82, 231, 2, 0, + 82, 231, 2, 0, 82, 231, 2, 0, 82, 231, 2, 0, 82, 231, 2, 0, 82, 231, 2, 0, 82, 231, 2, 0, 82, 231, 2, 0, 82, 231, 2, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 94, 103, 2, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 3, 0, 0, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, + 202, 9, 3, 0, 3, 0, 0, 0, 202, 9, 3, 0, 202, 9, 3, 0, 3, 0, 0, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 3, 0, 0, 0, 138, 21, 3, 0, 138, 21, 3, 0, 138, 21, 3, 0, 138, 21, 3, 0, + 138, 21, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 148, 21, 3, 0, 148, 21, 3, 0, 148, 21, 3, 0, 148, 21, 3, 0, 148, 21, 3, 0, 148, 21, 3, 0, 148, 21, 3, 0, 148, 21, 3, 0, 148, 21, 3, 0, 144, 85, 5, 0, 144, 85, 5, 0, 144, 85, 5, 0, 144, 85, 5, 0, 144, 85, 5, 0, 144, 85, 5, 0, 144, 85, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 200, 0, 3, 0, 200, 0, 3, 0, 200, 0, 3, 0, 200, 0, 3, 0, 208, 64, 5, 0, 208, 64, 5, 0, 208, 64, 5, 0, 208, 64, 5, 0, 208, 64, 5, 0, 208, 64, 5, 0, 208, 64, 5, 0, 201, 0, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 210, 192, 2, 0, 210, 192, 2, 0, 210, 192, 2, 0, 210, 192, 2, 0, 210, 192, 2, 0, 210, 192, 2, 0, + 210, 192, 2, 0, 210, 192, 2, 0, 210, 192, 2, 0, 210, 192, 2, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 219, 0, 0, 0, 219, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 97, 128, 2, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 94, 128, 2, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, + 84, 0, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, + 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 97, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, + 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 3, 0, 0, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, + 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 3, 0, 0, 0, 138, 1, 3, 0, 138, 1, 3, 0, 3, 0, 0, 0, + 138, 1, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 138, 1, 3, 0, 3, 0, 0, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 3, 0, 0, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 3, 0, 0, 0, 138, 1, 3, 0, 3, 0, 0, 0, 138, 1, 3, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 138, 1, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 138, 1, 3, 0, 3, 0, 0, 0, 138, 1, 3, 0, 3, 0, 0, 0, 138, 1, 3, 0, 3, 0, 0, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 3, 0, 0, 0, 138, 1, 3, 0, 138, 1, 3, 0, 3, 0, 0, 0, 138, 1, 3, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 138, 1, 3, 0, 3, 0, 0, 0, 138, 1, 3, 0, 3, 0, 0, 0, 138, 1, 3, 0, 3, 0, 0, 0, 138, 1, 3, 0, 3, 0, 0, 0, 138, 1, 3, 0, 3, 0, 0, 0, 138, 1, 3, 0, 138, 1, 3, 0, 3, 0, 0, 0, 138, 1, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 3, 0, 0, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, + 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 3, 0, 0, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 3, 0, 0, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 3, 0, 0, 0, 138, 1, 3, 0, 3, 0, 0, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, + 138, 1, 3, 0, 138, 1, 3, 0, 3, 0, 0, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 3, 0, 0, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 3, 0, 0, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, + 138, 1, 3, 0, 138, 1, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 160, 1, 3, 0, 160, 1, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, + 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, + 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 97, 128, 3, 0, + 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 3, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, + 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, + 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, + 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 97, 0, 7, 0, 97, 0, 7, 0, 97, 0, 7, 0, 97, 0, 7, 0, 97, 0, 7, 0, 97, 0, 7, 0, 97, 0, 7, 0, 97, 0, 7, 0, 97, 0, 7, 0, 97, 0, 7, 0, 97, 0, 7, 0, 97, 0, 7, 0, 97, 0, 7, 0, 97, 0, 7, 0, 97, 0, 7, 0, 97, 0, 7, 0, + 97, 0, 7, 0, 97, 0, 7, 0, 97, 0, 7, 0, 97, 0, 7, 0, 97, 0, 7, 0, 97, 0, 7, 0, 97, 0, 7, 0, 97, 0, 7, 0, 97, 0, 7, 0, 97, 0, 7, 0, 161, 141, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, + 3, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, + 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 97, 128, 3, 0, + 97, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, + 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 97, 64, 7, 0, 97, 128, 3, 0, 97, 128, 3, 0, + 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 64, 7, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, + 3, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, + 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, + 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, + 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, + 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 97, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, + 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, + 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, + 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, + 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 97, 128, 3, 0, + 97, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, + 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, + 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, + 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 97, 128, 3, 0, + 97, 128, 3, 0, 97, 128, 3, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, + 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, + 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, + 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 3, 0, 0, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, + 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 0, 0, 0, 3, 0, 0, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, + 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, + 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, + 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, + 138, 140, 3, 0, 138, 140, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, + 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, + 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 128, 3, 0, 3, 0, 0, 0, 66, 64, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, + 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, + 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, + 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 3, 0, 0, 0, 3, 0, 0, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, + 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 12, 10, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, + 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, 76, 6, 3, 0, + 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, + 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, + 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 140, 11, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 76, 0, 3, 0, 97, 128, 2, 0, 97, 0, 3, 0, 97, 128, 8, 0, 97, 0, 3, 0, 76, 0, 3, 0, 97, 0, 3, 0, 97, 128, 2, 0, 72, 0, 3, 0, + 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 72, 128, 8, 0, 97, 0, 3, 0, 76, 0, 3, 0, 97, 64, 2, 0, 97, 0, 3, 0, 96, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 0, 3, 0, + 76, 0, 3, 0, 97, 0, 3, 0, 140, 11, 3, 0, 97, 0, 3, 0, 76, 0, 3, 0, 97, 0, 3, 0, 12, 18, 3, 0, 12, 146, 8, 0, 76, 0, 3, 0, 76, 0, 3, 0, 97, 0, 3, 0, 72, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 12, 18, 3, 0, 76, 0, 3, 0, 72, 0, 3, 0, 74, 0, 3, 0, 74, 0, 3, 0, 74, 0, 3, 0, 74, 0, 3, 0, 72, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 72, 0, 3, 0, + 72, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 76, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 97, 0, 3, 0, 96, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 8, 18, 3, 0, 97, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 128, 8, 0, 84, 128, 8, 0, + 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 128, 8, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 128, 8, 0, 84, 0, 3, 0, 76, 10, 3, 0, 76, 10, 3, 0, 76, 10, 3, 0, 76, 10, 3, 0, 76, 10, 3, 0, 76, 10, 3, 0, 76, 10, 3, 0, 76, 10, 3, 0, 76, 10, 3, 0, 76, 10, 3, 0, 76, 10, 3, 0, 76, 10, 3, 0, 76, 10, 3, 0, 76, 10, 3, 0, 76, 10, 3, 0, + 76, 10, 3, 0, 76, 10, 3, 0, 76, 10, 3, 0, 76, 10, 3, 0, 76, 10, 3, 0, 76, 10, 3, 0, 76, 10, 3, 0, 76, 10, 3, 0, 76, 10, 3, 0, 76, 10, 3, 0, 76, 10, 3, 0, 76, 10, 3, 0, 76, 10, 3, 0, 76, 10, 3, 0, 76, 10, 3, 0, 76, 10, 3, 0, 76, 10, 3, 0, 72, 10, 3, 0, 72, 10, 3, 0, 72, 10, 3, 0, 72, 10, 3, 0, 72, 10, 3, 0, 72, 10, 3, 0, 72, 10, 3, 0, 72, 10, 3, 0, + 72, 10, 3, 0, 72, 10, 3, 0, 72, 10, 3, 0, 72, 10, 3, 0, 72, 10, 3, 0, 72, 10, 3, 0, 72, 10, 3, 0, 72, 10, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, + 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 204, 6, 3, 0, 200, 6, 3, 0, 204, 6, 3, 0, 200, 6, 3, 0, 204, 6, 3, 0, 200, 6, 3, 0, 204, 6, 3, 0, 200, 6, 3, 0, 204, 6, 3, 0, 200, 6, 3, 0, + 204, 6, 3, 0, 200, 6, 3, 0, 204, 6, 3, 0, 200, 6, 3, 0, 204, 6, 3, 0, 200, 6, 3, 0, 204, 6, 3, 0, 200, 6, 3, 0, 204, 6, 3, 0, 200, 6, 3, 0, 204, 6, 3, 0, 200, 6, 3, 0, 204, 6, 3, 0, 200, 6, 3, 0, 204, 6, 3, 0, 200, 6, 3, 0, 204, 6, 3, 0, 200, 6, 3, 0, 204, 6, 3, 0, 200, 6, 3, 0, 204, 6, 3, 0, 200, 6, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, + 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 138, 7, 3, 0, 144, 71, 5, 0, 143, 71, 5, 0, 143, 71, 5, 0, 143, 71, 5, 0, 155, 7, 3, 0, 144, 71, 5, 0, 144, 71, 5, 0, 144, 71, 5, 0, 144, 71, 5, 0, 144, 71, 5, 0, 144, 71, 5, 0, 144, 71, 5, 0, 144, 71, 5, 0, + 144, 71, 5, 0, 144, 71, 5, 0, 155, 7, 3, 0, 137, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, + 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 140, 7, 3, 0, 136, 7, 3, 0, 137, 7, 3, 0, 137, 7, 3, 0, 144, 71, 5, 0, 144, 71, 5, 0, 95, 0, 3, 0, 95, 0, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, + 12, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 9, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, + 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 73, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 12, 18, 3, 0, + 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 10, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, + 12, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 12, 18, 3, 0, 8, 18, 3, 0, 91, 128, 3, 0, 12, 146, 3, 0, 12, 146, 3, 0, 12, 146, 3, 0, 12, 146, 3, 0, 12, 146, 3, 0, + 12, 146, 3, 0, 12, 146, 3, 0, 12, 146, 3, 0, 12, 146, 3, 0, 12, 146, 3, 0, 12, 146, 3, 0, 12, 146, 3, 0, 12, 146, 3, 0, 12, 146, 3, 0, 12, 146, 3, 0, 12, 146, 3, 0, 12, 146, 3, 0, 12, 146, 3, 0, 12, 146, 3, 0, 12, 146, 3, 0, 12, 146, 3, 0, 12, 146, 3, 0, 12, 146, 3, 0, 12, 146, 3, 0, 12, 146, 3, 0, 12, 146, 3, 0, 92, 0, 0, 0, 91, 128, 3, 0, 88, 64, 0, 0, 95, 128, 3, 0, + 86, 128, 3, 0, 140, 8, 3, 0, 140, 8, 3, 0, 140, 8, 3, 0, 140, 8, 3, 0, 140, 8, 3, 0, 140, 8, 3, 0, 140, 8, 3, 0, 140, 8, 3, 0, 140, 8, 3, 0, 140, 8, 3, 0, 140, 8, 3, 0, 140, 8, 3, 0, 140, 8, 3, 0, 140, 8, 3, 0, 140, 8, 3, 0, 140, 8, 3, 0, 140, 8, 3, 0, 140, 8, 3, 0, 140, 8, 3, 0, 140, 8, 3, 0, 140, 8, 3, 0, 140, 8, 3, 0, 140, 8, 3, 0, 140, 8, 3, 0, + 140, 8, 3, 0, 140, 8, 3, 0, 140, 8, 3, 0, 140, 8, 3, 0, 140, 8, 3, 0, 140, 8, 3, 0, 140, 8, 3, 0, 140, 8, 3, 0, 136, 8, 3, 0, 136, 8, 3, 0, 136, 8, 3, 0, 136, 8, 3, 0, 136, 8, 3, 0, 136, 8, 3, 0, 136, 8, 3, 0, 136, 8, 3, 0, 136, 8, 3, 0, 136, 8, 3, 0, 136, 8, 3, 0, 136, 8, 3, 0, 136, 8, 3, 0, 136, 8, 3, 0, 136, 8, 3, 0, 136, 8, 3, 0, 136, 8, 3, 0, + 136, 8, 3, 0, 136, 8, 3, 0, 136, 8, 3, 0, 136, 8, 3, 0, 136, 8, 3, 0, 136, 8, 3, 0, 136, 8, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, + 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, 204, 14, 3, 0, 12, 39, 3, 0, 12, 39, 3, 0, 12, 39, 3, 0, 12, 39, 3, 0, 12, 39, 3, 0, 12, 39, 3, 0, 12, 39, 3, 0, 12, 39, 3, 0, 12, 39, 3, 0, 12, 39, 3, 0, 12, 39, 3, 0, + 12, 39, 3, 0, 12, 39, 3, 0, 12, 39, 3, 0, 12, 39, 3, 0, 12, 39, 3, 0, 12, 39, 3, 0, 12, 39, 3, 0, 12, 39, 3, 0, 12, 39, 3, 0, 12, 39, 3, 0, 12, 39, 3, 0, 12, 39, 3, 0, 12, 39, 3, 0, 12, 39, 3, 0, 12, 39, 3, 0, 12, 39, 3, 0, 12, 39, 3, 0, 12, 39, 3, 0, 12, 39, 3, 0, 12, 39, 3, 0, 12, 39, 3, 0, 76, 21, 3, 0, 76, 21, 3, 0, 76, 21, 3, 0, 76, 21, 3, 0, + 76, 21, 3, 0, 76, 21, 3, 0, 76, 21, 3, 0, 76, 21, 3, 0, 76, 21, 3, 0, 76, 21, 3, 0, 76, 21, 3, 0, 76, 21, 3, 0, 76, 21, 3, 0, 76, 21, 3, 0, 76, 21, 3, 0, 76, 21, 3, 0, 76, 21, 3, 0, 76, 21, 3, 0, 76, 21, 3, 0, 76, 21, 3, 0, 76, 21, 3, 0, 76, 21, 3, 0, 76, 21, 3, 0, 76, 21, 3, 0, 76, 21, 3, 0, 76, 21, 3, 0, 76, 21, 3, 0, 76, 21, 3, 0, 76, 21, 3, 0, + 76, 21, 3, 0, 76, 21, 3, 0, 76, 21, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, + 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, + 72, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, + 76, 0, 3, 0, 76, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, + 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 96, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, + 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 96, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, + 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 96, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, + 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 96, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, + 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 76, 0, 3, 0, 96, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, + 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 72, 0, 3, 0, 204, 0, 3, 0, 204, 0, 3, 0, 204, 0, 3, 0, 204, 0, 3, 0, 204, 0, 3, 0, 204, 0, 3, 0, 204, 0, 3, 0, 204, 0, 3, 0, 204, 0, 3, 0, 204, 0, 3, 0, 204, 0, 3, 0, + 204, 0, 3, 0, 204, 0, 3, 0, 204, 0, 3, 0, 204, 0, 3, 0, 204, 0, 3, 0, 204, 0, 3, 0, 204, 0, 3, 0, 204, 0, 3, 0, 204, 0, 3, 0, 204, 0, 3, 0, 204, 0, 3, 0, 204, 0, 3, 0, 204, 0, 3, 0, 204, 0, 3, 0, 204, 0, 3, 0, 204, 0, 3, 0, 204, 0, 3, 0, 204, 0, 3, 0, 204, 0, 3, 0, 204, 0, 3, 0, 204, 0, 3, 0, 204, 0, 3, 0, 204, 0, 3, 0, 200, 0, 3, 0, 200, 0, 3, 0, + 200, 0, 3, 0, 200, 0, 3, 0, 200, 0, 3, 0, 200, 0, 3, 0, 200, 0, 3, 0, 200, 0, 3, 0, 200, 0, 3, 0, 200, 0, 3, 0, 200, 0, 3, 0, 200, 0, 3, 0, 200, 0, 3, 0, 200, 0, 3, 0, 200, 0, 3, 0, 200, 0, 3, 0, 200, 0, 3, 0, 200, 0, 3, 0, 200, 0, 3, 0, 200, 0, 3, 0, 200, 0, 3, 0, 200, 0, 3, 0, 200, 0, 3, 0, 200, 0, 3, 0, 200, 0, 3, 0, 200, 0, 3, 0, 200, 0, 3, 0, + 200, 0, 3, 0, 200, 0, 3, 0, 200, 0, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, + 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 91, 0, 3, 0, 9, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 7, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, + 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 137, 11, 3, 0, 137, 11, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 137, 11, 3, 0, 137, 11, 3, 0, + 137, 11, 3, 0, 137, 11, 3, 0, 137, 11, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 137, 7, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, + 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, + 9, 18, 3, 0, 9, 18, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 139, 11, 3, 0, 139, 11, 3, 0, 139, 11, 3, 0, 139, 11, 3, 0, 139, 11, 3, 0, 139, 11, 3, 0, 139, 11, 3, 0, 139, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, 136, 11, 3, 0, + 136, 11, 3, 0, 139, 11, 3, 0, 139, 11, 3, 0, 139, 11, 3, 0, 139, 11, 3, 0, 139, 11, 3, 0, 139, 11, 3, 0, 139, 11, 3, 0, 139, 11, 3, 0, 72, 10, 3, 0, 72, 10, 3, 0, 72, 10, 3, 0, 72, 10, 3, 0, 72, 10, 3, 0, 72, 10, 3, 0, 72, 10, 3, 0, 72, 10, 3, 0, 72, 10, 3, 0, 72, 10, 3, 0, 72, 10, 3, 0, 72, 10, 3, 0, 72, 10, 3, 0, 72, 10, 3, 0, 72, 10, 3, 0, 72, 10, 3, 0, + 72, 10, 3, 0, 72, 10, 3, 0, 72, 10, 3, 0, 72, 10, 3, 0, 72, 10, 3, 0, 72, 10, 3, 0, 72, 10, 3, 0, 72, 10, 3, 0, 72, 10, 3, 0, 72, 10, 3, 0, 72, 10, 3, 0, 72, 10, 3, 0, 72, 10, 3, 0, 72, 10, 3, 0, 72, 10, 3, 0, 72, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, + 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 10, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, + 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, 8, 18, 3, 0, + 95, 0, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, + 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 72, 6, 3, 0, 95, 128, 3, 0, 8, 146, 3, 0, 8, 146, 3, 0, 8, 146, 3, 0, 8, 146, 3, 0, 8, 146, 3, 0, 8, 146, 3, 0, 8, 146, 3, 0, 8, 146, 3, 0, 8, 146, 3, 0, 8, 146, 3, 0, 8, 146, 3, 0, 8, 146, 3, 0, + 8, 146, 3, 0, 8, 146, 3, 0, 8, 146, 3, 0, 8, 146, 3, 0, 8, 146, 3, 0, 8, 146, 3, 0, 8, 146, 3, 0, 8, 146, 3, 0, 8, 146, 3, 0, 8, 146, 3, 0, 8, 146, 3, 0, 8, 146, 3, 0, 8, 146, 3, 0, 8, 146, 3, 0, 92, 0, 0, 0, 96, 128, 3, 0, 88, 64, 0, 0, 96, 128, 3, 0, 92, 0, 0, 0, 136, 8, 3, 0, 136, 8, 3, 0, 136, 8, 3, 0, 136, 8, 3, 0, 136, 8, 3, 0, 136, 8, 3, 0, + 136, 8, 3, 0, 136, 8, 3, 0, 136, 8, 3, 0, 136, 8, 3, 0, 136, 8, 3, 0, 136, 8, 3, 0, 136, 8, 3, 0, 136, 8, 3, 0, 136, 8, 3, 0, 136, 8, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, + 74, 31, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, + 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 200, 14, 3, 0, 8, 39, 3, 0, 8, 39, 3, 0, 8, 39, 3, 0, 8, 39, 3, 0, 8, 39, 3, 0, 8, 39, 3, 0, 8, 39, 3, 0, 8, 39, 3, 0, 8, 39, 3, 0, 8, 39, 3, 0, 8, 39, 3, 0, 8, 39, 3, 0, 8, 39, 3, 0, 8, 39, 3, 0, 8, 39, 3, 0, 8, 39, 3, 0, 8, 39, 3, 0, + 8, 39, 3, 0, 8, 39, 3, 0, 8, 39, 3, 0, 8, 39, 3, 0, 8, 39, 3, 0, 8, 39, 3, 0, 8, 39, 3, 0, 8, 39, 3, 0, 8, 39, 3, 0, 8, 39, 3, 0, 8, 39, 3, 0, 8, 39, 3, 0, 8, 39, 3, 0, 8, 39, 3, 0, 8, 39, 3, 0, 72, 21, 3, 0, 72, 21, 3, 0, 72, 21, 3, 0, 72, 21, 3, 0, 72, 21, 3, 0, 72, 21, 3, 0, 72, 21, 3, 0, 72, 21, 3, 0, 72, 21, 3, 0, 72, 21, 3, 0, + 72, 21, 3, 0, 72, 21, 3, 0, 72, 21, 3, 0, 72, 21, 3, 0, 72, 21, 3, 0, 72, 21, 3, 0, 72, 21, 3, 0, 72, 21, 3, 0, 72, 21, 3, 0, 72, 21, 3, 0, 72, 21, 3, 0, 72, 21, 3, 0, 72, 21, 3, 0, 72, 21, 3, 0, 72, 21, 3, 0, 72, 21, 3, 0, 72, 21, 3, 0, 72, 21, 3, 0, 72, 21, 3, 0, 72, 21, 3, 0, 72, 21, 3, 0, 72, 21, 3, 0, 74, 30, 3, 0, 74, 30, 3, 0, 74, 30, 3, 0, + 74, 30, 3, 0, 74, 30, 3, 0, 74, 30, 3, 0, 74, 30, 3, 0, 74, 30, 3, 0, 74, 30, 3, 0, 74, 30, 3, 0, 74, 30, 3, 0, 74, 30, 3, 0, 74, 30, 3, 0, 74, 30, 3, 0, 74, 30, 3, 0, 74, 30, 3, 0, 74, 30, 3, 0, 74, 30, 3, 0, 74, 30, 3, 0, 74, 30, 3, 0, 74, 30, 3, 0, 74, 30, 3, 0, 80, 94, 5, 0, 80, 94, 5, 0, 80, 94, 5, 0, 80, 94, 5, 0, 73, 30, 3, 0, 80, 94, 5, 0, + 80, 94, 5, 0, 80, 94, 5, 0, 80, 94, 5, 0, 80, 94, 5, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 137, 1, 3, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, + 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 202, 7, 3, 0, 202, 7, 3, 0, 208, 71, 5, 0, 208, 71, 5, 0, 91, 64, 4, 0, 91, 64, 4, 0, 210, 199, 2, 0, 210, 199, 2, 0, 210, 199, 2, 0, 210, 199, 2, 0, 210, 199, 2, 0, 210, 199, 2, 0, 210, 199, 2, 0, 210, 199, 2, 0, + 210, 199, 2, 0, 210, 199, 2, 0, 219, 7, 3, 0, 201, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 201, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, + 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, + 202, 25, 3, 0, 202, 25, 3, 0, 202, 25, 3, 0, 202, 25, 3, 0, 202, 25, 3, 0, 202, 25, 3, 0, 202, 25, 3, 0, 202, 25, 3, 0, 202, 25, 3, 0, 202, 25, 3, 0, 202, 25, 3, 0, 202, 25, 3, 0, 202, 25, 3, 0, 202, 25, 3, 0, 202, 25, 3, 0, 202, 25, 3, 0, 202, 25, 3, 0, 202, 25, 3, 0, 202, 25, 3, 0, 202, 25, 3, 0, 202, 25, 3, 0, 202, 25, 3, 0, 202, 25, 3, 0, 202, 25, 3, 0, 201, 25, 3, 0, + 201, 25, 3, 0, 201, 25, 3, 0, 201, 25, 3, 0, 201, 25, 3, 0, 201, 25, 3, 0, 219, 89, 4, 0, 219, 89, 4, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, + 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 137, 11, 3, 0, 137, 11, 3, 0, 137, 11, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, + 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 9, 18, 3, 0, 137, 11, 3, 0, 90, 192, 0, 0, 89, 192, 0, 0, 92, 0, 0, 0, 88, 64, 0, 0, + 92, 0, 0, 0, 88, 64, 0, 0, 92, 0, 0, 0, 88, 64, 0, 0, 92, 0, 0, 0, 88, 64, 0, 0, 91, 64, 4, 0, 91, 64, 4, 0, 91, 64, 4, 0, 91, 64, 4, 0, 91, 128, 1, 0, 73, 0, 3, 0, 91, 64, 4, 0, 91, 64, 4, 0, 91, 0, 3, 0, 91, 64, 4, 0, 91, 64, 4, 0, 91, 0, 3, 0, 91, 0, 3, 0, 91, 0, 3, 0, 91, 0, 3, 0, 91, 0, 3, 0, 87, 192, 4, 0, 87, 192, 4, 0, 91, 64, 4, 0, + 91, 64, 4, 0, 91, 64, 4, 0, 91, 0, 3, 0, 101, 64, 4, 0, 91, 64, 0, 0, 91, 64, 0, 0, 91, 128, 3, 0, 97, 128, 3, 0, 137, 76, 1, 0, 74, 128, 3, 0, 147, 140, 3, 0, 92, 0, 0, 0, 88, 64, 0, 0, 92, 0, 0, 0, 88, 64, 0, 0, 92, 0, 0, 0, 88, 64, 0, 0, 92, 0, 0, 0, 88, 64, 0, 0, 92, 0, 0, 0, 88, 64, 0, 0, 97, 128, 3, 0, 97, 128, 3, 0, 92, 0, 0, 0, 88, 64, 0, 0, + 92, 0, 0, 0, 88, 64, 0, 0, 92, 0, 0, 0, 88, 64, 0, 0, 92, 0, 0, 0, 88, 64, 0, 0, 87, 64, 1, 0, 92, 0, 0, 0, 88, 64, 0, 0, 88, 64, 0, 0, 97, 128, 3, 0, 147, 140, 3, 0, 147, 140, 3, 0, 147, 140, 3, 0, 147, 140, 3, 0, 147, 140, 3, 0, 147, 140, 3, 0, 147, 140, 3, 0, 147, 140, 3, 0, 147, 140, 3, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 78, 76, 5, 0, + 78, 76, 5, 0, 87, 128, 3, 0, 73, 128, 3, 0, 73, 128, 3, 0, 73, 128, 3, 0, 73, 128, 3, 0, 73, 64, 5, 0, 97, 128, 3, 0, 97, 128, 3, 0, 147, 140, 3, 0, 147, 140, 3, 0, 147, 140, 3, 0, 137, 76, 1, 0, 74, 64, 1, 0, 91, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 15, 9, 0, 202, 143, 3, 0, 202, 15, 9, 0, 202, 143, 3, 0, 202, 15, 9, 0, + 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 15, 9, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 15, 9, 0, 202, 15, 9, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 91, 64, 1, 0, 73, 0, 9, 0, 201, 79, 1, 0, 201, 79, 1, 0, 202, 143, 3, 0, 74, 168, 3, 0, + 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 73, 104, 1, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, + 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 19, 3, 0, 74, 19, 3, 0, 74, 19, 3, 0, 74, 19, 3, 0, 74, 19, 3, 0, 74, 19, 3, 0, 74, 19, 3, 0, 74, 19, 3, 0, 74, 19, 3, 0, 74, 19, 3, 0, 74, 19, 3, 0, 74, 19, 3, 0, 74, 19, 3, 0, 74, 19, 3, 0, 74, 19, 3, 0, 74, 19, 3, 0, 74, 19, 3, 0, 74, 19, 3, 0, 74, 19, 3, 0, + 74, 19, 3, 0, 74, 19, 3, 0, 74, 19, 3, 0, 74, 19, 3, 0, 74, 19, 3, 0, 73, 19, 3, 0, 73, 19, 3, 0, 73, 19, 3, 0, 73, 19, 3, 0, 73, 19, 3, 0, 73, 19, 3, 0, 91, 83, 4, 0, 91, 83, 4, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, + 137, 38, 3, 0, 155, 102, 4, 0, 155, 166, 1, 0, 155, 102, 4, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, + 95, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 95, 0, 3, 0, 73, 0, 3, 0, 73, 0, 3, 0, 73, 0, 3, 0, 73, 0, 3, 0, 73, 0, 3, 0, 73, 0, 3, 0, 73, 0, 3, 0, + 73, 0, 3, 0, 73, 0, 3, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 201, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, + 225, 23, 10, 0, 225, 23, 10, 0, 225, 23, 10, 0, 202, 23, 10, 0, 206, 23, 10, 0, 208, 23, 10, 0, 206, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 88, 64, 0, 0, 91, 64, 0, 0, 92, 0, 0, 0, 88, 64, 0, 0, 91, 64, 0, 0, 91, 64, 1, 0, 202, 143, 3, 0, 202, 15, 9, 0, 202, 15, 9, 0, 202, 15, 9, 0, 202, 15, 9, 0, 202, 15, 9, 0, 202, 15, 9, 0, 202, 15, 9, 0, 202, 15, 9, 0, 202, 15, 9, 0, + 73, 0, 9, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, + 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 73, 64, 1, 0, 73, 64, 1, 0, 208, 71, 5, 0, 208, 71, 5, 0, 208, 71, 5, 0, 206, 71, 5, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, + 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 208, 71, 5, 0, 206, 71, 5, 0, 208, 71, 5, 0, 202, 7, 3, 0, 206, 71, 5, 0, + 206, 71, 5, 0, 206, 71, 5, 0, 208, 71, 5, 0, 208, 71, 5, 0, 208, 71, 5, 0, 208, 71, 5, 0, 208, 71, 5, 0, 208, 71, 5, 0, 208, 71, 5, 0, 208, 71, 5, 0, 206, 71, 5, 0, 206, 71, 5, 0, 206, 71, 5, 0, 206, 71, 5, 0, 208, 71, 5, 0, 206, 71, 5, 0, 206, 71, 5, 0, 202, 7, 3, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 208, 71, 5, 0, 208, 71, 5, 0, 208, 71, 5, 0, + 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, + 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 74, 22, 3, 0, 80, 86, 5, 0, 80, 86, 5, 0, 74, 22, 3, 0, 78, 86, 5, 0, 78, 86, 5, 0, 74, 37, 3, 0, 97, 165, 4, 0, 97, 165, 4, 0, 97, 165, 4, 0, 91, 165, 4, 0, 91, 37, 3, 0, 91, 165, 4, 0, 91, 165, 4, 0, 91, 37, 1, 0, 91, 165, 4, 0, + 91, 165, 4, 0, 91, 101, 4, 0, 91, 37, 1, 0, 91, 165, 1, 0, 91, 165, 1, 0, 91, 165, 1, 0, 91, 165, 1, 0, 91, 165, 1, 0, 91, 37, 1, 0, 97, 37, 3, 0, 91, 165, 1, 0, 97, 37, 3, 0, 97, 37, 3, 0, 97, 37, 3, 0, 80, 101, 5, 0, 80, 101, 5, 0, 97, 37, 3, 0, 97, 37, 3, 0, 97, 37, 3, 0, 97, 37, 3, 0, 97, 37, 3, 0, 97, 37, 3, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, + 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, + 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 206, 23, 10, 0, 206, 23, 10, 0, 208, 23, 10, 0, 208, 23, 10, 0, 208, 23, 10, 0, 208, 23, 10, 0, 206, 23, 10, 0, 208, 23, 10, 0, 208, 23, 10, 0, 208, 23, 10, 0, 208, 23, 10, 0, 208, 23, 10, 0, 208, 23, 10, 0, 206, 23, 10, 0, 208, 23, 10, 0, 208, 23, 10, 0, 206, 23, 10, 0, 206, 23, 10, 0, + 208, 23, 10, 0, 208, 23, 10, 0, 202, 23, 10, 0, 210, 215, 2, 0, 210, 215, 2, 0, 210, 215, 2, 0, 210, 215, 2, 0, 210, 215, 2, 0, 210, 215, 2, 0, 210, 215, 2, 0, 210, 215, 2, 0, 210, 215, 2, 0, 210, 215, 2, 0, 219, 87, 4, 0, 219, 87, 4, 0, 219, 23, 3, 0, 219, 23, 3, 0, 219, 23, 3, 0, 219, 23, 3, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, + 206, 23, 10, 0, 206, 23, 10, 0, 208, 23, 10, 0, 208, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 208, 23, 10, 0, 208, 23, 10, 0, 208, 23, 10, 0, 202, 23, 10, 0, 206, 23, 10, 0, 206, 23, 10, 0, 206, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 206, 23, 10, 0, 206, 23, 10, 0, 206, 23, 10, 0, 206, 23, 10, 0, 206, 23, 10, 0, 206, 23, 10, 0, 206, 23, 10, 0, 202, 23, 10, 0, + 202, 23, 10, 0, 202, 23, 10, 0, 208, 23, 10, 0, 208, 23, 10, 0, 208, 23, 10, 0, 208, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 202, 23, 10, 0, 208, 23, 10, 0, 206, 23, 10, 0, 206, 23, 10, 0, 208, 23, 10, 0, 208, 23, 10, 0, 206, 23, 10, 0, + 206, 23, 10, 0, 206, 23, 10, 0, 206, 23, 10, 0, 206, 23, 10, 0, 206, 23, 10, 0, 208, 23, 10, 0, 202, 23, 10, 0, 206, 23, 10, 0, 210, 215, 2, 0, 210, 215, 2, 0, 210, 215, 2, 0, 210, 215, 2, 0, 210, 215, 2, 0, 210, 215, 2, 0, 210, 215, 2, 0, 210, 215, 2, 0, 210, 215, 2, 0, 210, 215, 2, 0, 206, 23, 10, 0, 206, 23, 10, 0, 206, 23, 10, 0, 208, 23, 10, 0, 225, 23, 10, 0, 225, 23, 10, 0, 74, 76, 6, 0, + 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, + 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 76, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, + 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 140, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, + 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 74, 204, 6, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, + 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, 202, 9, 3, 0, + 202, 9, 3, 0, 202, 9, 3, 0, 151, 69, 4, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, + 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 161, 5, 3, 0, 155, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, + 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 138, 5, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, + 10, 30, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, 10, 30, 3, 0, 74, 16, 10, 0, 74, 16, 10, 0, 74, 16, 10, 0, 74, 16, 10, 0, 74, 16, 10, 0, 74, 16, 10, 0, 74, 16, 10, 0, 74, 16, 10, 0, 74, 16, 10, 0, 74, 16, 10, 0, + 74, 16, 10, 0, 74, 16, 10, 0, 74, 16, 10, 0, 74, 16, 10, 0, 74, 16, 10, 0, 74, 16, 10, 0, 74, 16, 10, 0, 74, 16, 10, 0, 74, 16, 10, 0, 74, 16, 10, 0, 74, 16, 10, 0, 74, 16, 10, 0, 74, 16, 10, 0, 74, 16, 10, 0, 74, 16, 10, 0, 74, 16, 10, 0, 74, 16, 10, 0, 74, 16, 10, 0, 74, 16, 10, 0, 74, 16, 10, 0, 74, 16, 10, 0, 74, 16, 10, 0, 80, 16, 10, 0, 80, 16, 10, 0, 78, 16, 10, 0, + 80, 16, 10, 0, 80, 16, 10, 0, 80, 16, 10, 0, 80, 16, 10, 0, 80, 16, 10, 0, 80, 16, 10, 0, 80, 16, 10, 0, 78, 16, 10, 0, 78, 16, 10, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, + 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 208, 86, 5, 0, 208, 86, 5, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, + 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 202, 22, 3, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, + 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, 10, 35, 10, 0, + 10, 35, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, + 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 138, 17, 10, 0, 144, 66, 5, 0, 144, 66, 5, 0, 144, 66, 5, 0, 144, 66, 5, 0, 142, 66, 5, 0, 138, 2, 3, 0, 138, 2, 3, 0, 138, 2, 3, 0, 138, 2, 3, 0, 138, 2, 3, 0, 138, 2, 3, 0, 138, 2, 3, 0, 138, 2, 3, 0, 138, 2, 3, 0, 138, 2, 3, 0, 138, 2, 3, 0, 138, 2, 3, 0, + 138, 2, 3, 0, 138, 2, 3, 0, 138, 2, 3, 0, 138, 2, 3, 0, 138, 2, 3, 0, 138, 2, 3, 0, 138, 2, 3, 0, 138, 2, 3, 0, 138, 2, 3, 0, 138, 2, 3, 0, 138, 2, 3, 0, 138, 2, 3, 0, 138, 2, 3, 0, 138, 2, 3, 0, 138, 2, 3, 0, 144, 66, 5, 0, 142, 66, 5, 0, 144, 66, 5, 0, 144, 66, 5, 0, 144, 66, 5, 0, 144, 66, 5, 0, 144, 66, 5, 0, 142, 66, 5, 0, 144, 66, 5, 0, 142, 66, 5, 0, + 142, 66, 5, 0, 142, 66, 5, 0, 144, 97, 5, 0, 144, 97, 5, 0, 142, 97, 5, 0, 138, 33, 3, 0, 138, 33, 3, 0, 138, 33, 3, 0, 138, 33, 3, 0, 138, 33, 3, 0, 138, 33, 3, 0, 138, 33, 3, 0, 138, 33, 3, 0, 138, 33, 3, 0, 138, 33, 3, 0, 138, 33, 3, 0, 138, 33, 3, 0, 138, 33, 3, 0, 138, 33, 3, 0, 138, 33, 3, 0, 138, 33, 3, 0, 138, 33, 3, 0, 138, 33, 3, 0, 138, 33, 3, 0, 138, 33, 3, 0, + 138, 33, 3, 0, 138, 33, 3, 0, 138, 33, 3, 0, 138, 33, 3, 0, 138, 33, 3, 0, 138, 33, 3, 0, 138, 33, 3, 0, 138, 33, 3, 0, 138, 33, 3, 0, 138, 33, 3, 0, 142, 97, 5, 0, 144, 97, 5, 0, 144, 97, 5, 0, 144, 97, 5, 0, 144, 97, 5, 0, 142, 97, 5, 0, 142, 97, 5, 0, 144, 97, 5, 0, 144, 97, 5, 0, 142, 97, 5, 0, 144, 97, 5, 0, 144, 97, 5, 0, 144, 97, 5, 0, 138, 33, 3, 0, 138, 33, 3, 0, + 146, 225, 2, 0, 146, 225, 2, 0, 146, 225, 2, 0, 146, 225, 2, 0, 146, 225, 2, 0, 146, 225, 2, 0, 146, 225, 2, 0, 146, 225, 2, 0, 146, 225, 2, 0, 146, 225, 2, 0, 138, 33, 3, 0, 138, 33, 3, 0, 138, 33, 3, 0, 138, 33, 3, 0, 138, 33, 3, 0, 138, 33, 3, 0, 74, 3, 3, 0, 74, 3, 3, 0, 74, 3, 3, 0, 74, 3, 3, 0, 74, 3, 3, 0, 74, 3, 3, 0, 74, 3, 3, 0, 74, 3, 3, 0, 74, 3, 3, 0, + 74, 3, 3, 0, 74, 3, 3, 0, 74, 3, 3, 0, 74, 3, 3, 0, 74, 3, 3, 0, 74, 3, 3, 0, 74, 3, 3, 0, 74, 3, 3, 0, 74, 3, 3, 0, 74, 3, 3, 0, 74, 3, 3, 0, 74, 3, 3, 0, 74, 3, 3, 0, 74, 3, 3, 0, 74, 3, 3, 0, 74, 3, 3, 0, 74, 3, 3, 0, 74, 3, 3, 0, 74, 3, 3, 0, 74, 3, 3, 0, 74, 3, 3, 0, 74, 3, 3, 0, 74, 3, 3, 0, 74, 18, 3, 0, 74, 18, 3, 0, + 74, 18, 3, 0, 74, 18, 3, 0, 74, 18, 3, 0, 74, 18, 3, 0, 74, 18, 3, 0, 74, 18, 3, 0, 74, 18, 3, 0, 74, 18, 3, 0, 74, 18, 3, 0, 74, 18, 3, 0, 74, 18, 3, 0, 74, 18, 3, 0, 74, 18, 3, 0, 74, 18, 3, 0, 74, 18, 3, 0, 74, 18, 3, 0, 74, 18, 3, 0, 74, 18, 3, 0, 74, 18, 3, 0, 74, 18, 3, 0, 74, 18, 3, 0, 74, 18, 3, 0, 74, 18, 3, 0, 74, 18, 3, 0, 74, 18, 3, 0, + 74, 18, 3, 0, 74, 18, 3, 0, 74, 18, 3, 0, 74, 18, 3, 0, 74, 18, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, + 74, 36, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, 74, 36, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 13, 9, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, + 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 87, 64, 1, 0, 202, 15, 9, 0, 202, 143, 3, 0, 202, 15, 9, 0, 202, 143, 3, 0, 202, 15, 9, 0, + 202, 143, 3, 0, 202, 15, 9, 0, 202, 143, 3, 0, 202, 15, 9, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, + 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 15, 9, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, + 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 202, 143, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, + 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 74, 140, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, + 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 10, 132, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, + 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, + 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 138, 140, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, + 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 74, 168, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, + 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 138, 38, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, + 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, 202, 2, 3, 0, + 202, 33, 3, 0, 202, 33, 3, 0, 208, 97, 5, 0, 202, 33, 3, 0, 202, 33, 3, 0, 202, 33, 3, 0, 208, 97, 5, 0, 202, 33, 3, 0, 202, 33, 3, 0, 202, 33, 3, 0, 202, 33, 3, 0, 208, 97, 5, 0, 202, 33, 3, 0, 202, 33, 3, 0, 202, 33, 3, 0, 202, 33, 3, 0, 202, 33, 3, 0, 202, 33, 3, 0, 202, 33, 3, 0, 202, 33, 3, 0, 202, 33, 3, 0, 202, 33, 3, 0, 202, 33, 3, 0, 202, 33, 3, 0, 202, 33, 3, 0, + 202, 33, 3, 0, 202, 33, 3, 0, 202, 33, 3, 0, 202, 33, 3, 0, 202, 33, 3, 0, 202, 33, 3, 0, 202, 33, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, + 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 10, 28, 3, 0, 206, 94, 5, 0, 206, 94, 5, 0, 202, 30, 3, 0, 202, 30, 3, 0, 202, 30, 3, 0, 202, 30, 3, 0, 202, 30, 3, 0, 202, 30, 3, 0, 202, 30, 3, 0, 202, 30, 3, 0, 202, 30, 3, 0, + 202, 30, 3, 0, 202, 30, 3, 0, 202, 30, 3, 0, 202, 30, 3, 0, 202, 30, 3, 0, 202, 30, 3, 0, 202, 30, 3, 0, 202, 30, 3, 0, 202, 30, 3, 0, 202, 30, 3, 0, 202, 30, 3, 0, 202, 30, 3, 0, 202, 30, 3, 0, 202, 30, 3, 0, 202, 30, 3, 0, 202, 30, 3, 0, 202, 30, 3, 0, 202, 30, 3, 0, 202, 30, 3, 0, 202, 30, 3, 0, 202, 30, 3, 0, 206, 94, 5, 0, 206, 94, 5, 0, 206, 94, 5, 0, 206, 94, 5, 0, + 206, 94, 5, 0, 206, 94, 5, 0, 206, 94, 5, 0, 206, 94, 5, 0, 206, 94, 5, 0, 206, 94, 5, 0, 206, 94, 5, 0, 206, 94, 5, 0, 208, 71, 5, 0, 208, 71, 5, 0, 208, 71, 5, 0, 208, 71, 5, 0, 208, 71, 5, 0, 208, 71, 5, 0, 208, 71, 5, 0, 208, 71, 5, 0, 208, 71, 5, 0, 208, 71, 5, 0, 208, 71, 5, 0, 208, 71, 5, 0, 208, 71, 5, 0, 208, 71, 5, 0, 208, 71, 5, 0, 208, 71, 5, 0, 208, 71, 5, 0, + 208, 71, 5, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 202, 7, 3, 0, 219, 7, 3, 0, 219, 7, 3, 0, 219, 7, 3, 0, 202, 7, 3, 0, 219, 135, 4, 0, 202, 7, 3, 0, 202, 7, 3, 0, 208, 71, 5, 0, 146, 207, 2, 0, 146, 207, 2, 0, 146, 207, 2, 0, 146, 207, 2, 0, 146, 207, 2, 0, 146, 207, 2, 0, 146, 207, 2, 0, 146, 207, 2, 0, 146, 207, 2, 0, 146, 207, 2, 0, + 138, 15, 3, 0, 138, 15, 3, 0, 138, 15, 3, 0, 138, 15, 3, 0, 138, 15, 3, 0, 138, 15, 3, 0, 138, 15, 3, 0, 138, 15, 3, 0, 138, 15, 3, 0, 138, 15, 3, 0, 138, 15, 3, 0, 138, 15, 3, 0, 138, 15, 3, 0, 138, 15, 3, 0, 138, 15, 3, 0, 138, 15, 3, 0, 138, 15, 3, 0, 138, 15, 3, 0, 138, 15, 3, 0, 138, 15, 3, 0, 138, 15, 3, 0, 138, 15, 3, 0, 138, 15, 3, 0, 138, 15, 3, 0, 144, 79, 5, 0, + 144, 79, 5, 0, 144, 79, 5, 0, 144, 79, 5, 0, 144, 79, 5, 0, 144, 79, 5, 0, 144, 79, 5, 0, 144, 79, 5, 0, 91, 64, 4, 0, 155, 79, 4, 0, 138, 29, 3, 0, 138, 29, 3, 0, 138, 29, 3, 0, 138, 29, 3, 0, 138, 29, 3, 0, 138, 29, 3, 0, 138, 29, 3, 0, 138, 29, 3, 0, 138, 29, 3, 0, 138, 29, 3, 0, 138, 29, 3, 0, 138, 29, 3, 0, 138, 29, 3, 0, 138, 29, 3, 0, 138, 29, 3, 0, 138, 29, 3, 0, + 80, 79, 5, 0, 80, 79, 5, 0, 80, 79, 5, 0, 78, 79, 5, 0, 74, 15, 3, 0, 74, 15, 3, 0, 74, 15, 3, 0, 74, 15, 3, 0, 74, 15, 3, 0, 74, 15, 3, 0, 74, 15, 3, 0, 74, 15, 3, 0, 74, 15, 3, 0, 74, 15, 3, 0, 74, 15, 3, 0, 74, 15, 3, 0, 74, 15, 3, 0, 74, 15, 3, 0, 74, 15, 3, 0, 74, 15, 3, 0, 74, 15, 3, 0, 74, 15, 3, 0, 74, 15, 3, 0, 74, 15, 3, 0, 74, 15, 3, 0, + 74, 15, 3, 0, 74, 15, 3, 0, 74, 15, 3, 0, 74, 15, 3, 0, 74, 15, 3, 0, 74, 15, 3, 0, 74, 15, 3, 0, 74, 15, 3, 0, 74, 15, 3, 0, 74, 15, 3, 0, 80, 79, 5, 0, 78, 79, 5, 0, 78, 79, 5, 0, 80, 79, 5, 0, 80, 79, 5, 0, 80, 79, 5, 0, 80, 79, 5, 0, 78, 79, 5, 0, 78, 79, 5, 0, 80, 79, 5, 0, 80, 79, 5, 0, 78, 79, 5, 0, 78, 79, 5, 0, 10, 6, 3, 0, 10, 6, 3, 0, + 10, 6, 3, 0, 10, 6, 3, 0, 10, 6, 3, 0, 10, 6, 3, 0, 10, 6, 3, 0, 10, 6, 3, 0, 10, 6, 3, 0, 10, 6, 3, 0, 10, 6, 3, 0, 10, 6, 3, 0, 10, 6, 3, 0, 10, 6, 3, 0, 10, 6, 3, 0, 10, 6, 3, 0, 10, 6, 3, 0, 10, 6, 3, 0, 10, 6, 3, 0, 10, 6, 3, 0, 10, 6, 3, 0, 10, 6, 3, 0, 10, 6, 3, 0, 10, 6, 3, 0, 10, 6, 3, 0, 10, 6, 3, 0, 10, 6, 3, 0, + 10, 6, 3, 0, 10, 6, 3, 0, 10, 6, 3, 0, 10, 6, 3, 0, 10, 6, 3, 0, 202, 35, 10, 0, 202, 35, 10, 0, 202, 35, 10, 0, 202, 35, 10, 0, 202, 35, 10, 0, 202, 35, 10, 0, 202, 35, 10, 0, 202, 35, 10, 0, 202, 35, 10, 0, 202, 35, 10, 0, 202, 35, 10, 0, 202, 35, 10, 0, 202, 35, 10, 0, 202, 35, 10, 0, 202, 35, 10, 0, 202, 35, 10, 0, 202, 35, 10, 0, 202, 35, 10, 0, 202, 35, 10, 0, 202, 35, 10, 0, + 202, 35, 10, 0, 202, 35, 10, 0, 202, 35, 10, 0, 202, 35, 10, 0, 202, 35, 10, 0, 202, 35, 10, 0, 202, 35, 10, 0, 202, 35, 10, 0, 202, 35, 10, 0, 202, 35, 10, 0, 202, 35, 10, 0, 202, 35, 10, 0, 208, 35, 10, 0, 202, 35, 10, 0, 208, 35, 10, 0, 208, 35, 10, 0, 208, 35, 10, 0, 202, 35, 10, 0, 202, 35, 10, 0, 208, 35, 10, 0, 208, 35, 10, 0, 202, 35, 10, 0, 202, 35, 10, 0, 202, 35, 10, 0, 202, 35, 10, 0, + 202, 35, 10, 0, 208, 35, 10, 0, 208, 35, 10, 0, 74, 23, 3, 0, 74, 23, 3, 0, 74, 23, 3, 0, 74, 23, 3, 0, 74, 23, 3, 0, 74, 23, 3, 0, 74, 23, 3, 0, 74, 23, 3, 0, 74, 23, 3, 0, 74, 23, 3, 0, 74, 23, 3, 0, 74, 23, 3, 0, 74, 23, 3, 0, 74, 23, 3, 0, 74, 23, 3, 0, 74, 23, 3, 0, 74, 23, 3, 0, 74, 23, 3, 0, 74, 23, 3, 0, 74, 23, 3, 0, 74, 23, 3, 0, 74, 23, 3, 0, + 74, 23, 3, 0, 74, 23, 3, 0, 74, 23, 3, 0, 74, 23, 3, 0, 74, 23, 3, 0, 74, 23, 3, 0, 74, 23, 3, 0, 74, 23, 3, 0, 74, 23, 3, 0, 74, 23, 3, 0, 74, 204, 5, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, + 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 204, 5, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, + 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 74, 12, 6, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, + 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 159, 1, 3, 0, 159, 1, 3, 0, 159, 1, 3, 0, 159, 1, 3, 0, 159, 1, 3, 0, 159, 1, 3, 0, 159, 1, 3, 0, 159, 1, 3, 0, 159, 1, 3, 0, 159, 1, 3, 0, 159, 1, 3, 0, 159, 1, 3, 0, 159, 1, 3, 0, 159, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, + 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, + 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 88, 64, 0, 0, 92, 0, 0, 0, 161, 1, 3, 0, 161, 1, 3, 0, 161, 1, 3, 0, 161, 1, 3, 0, 161, 1, 3, 0, 161, 1, 3, 0, 161, 1, 3, 0, 161, 1, 3, 0, 161, 1, 3, 0, 161, 1, 3, 0, 161, 1, 3, 0, 161, 1, 3, 0, 161, 1, 3, 0, 161, 1, 3, 0, 161, 1, 3, 0, 161, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, + 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 138, 1, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, + 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 10, 19, 3, 0, 202, 5, 3, 0, 202, 5, 3, 0, 202, 5, 3, 0, 202, 5, 3, 0, 202, 5, 3, 0, 202, 5, 3, 0, + 202, 5, 3, 0, 202, 5, 3, 0, 202, 5, 3, 0, 202, 5, 3, 0, 202, 5, 3, 0, 202, 5, 3, 0, 202, 5, 3, 0, 202, 5, 3, 0, 202, 5, 3, 0, 202, 5, 3, 0, 202, 5, 3, 0, 202, 5, 3, 0, 202, 5, 3, 0, 202, 5, 3, 0, 202, 5, 3, 0, 202, 5, 3, 0, 202, 5, 3, 0, 202, 5, 3, 0, 202, 5, 3, 0, 202, 5, 3, 0, 202, 5, 3, 0, 202, 5, 3, 0, 202, 5, 3, 0, 202, 5, 3, 0, 202, 5, 3, 0, + 202, 5, 3, 0, 10, 15, 3, 0, 10, 15, 3, 0, 10, 15, 3, 0, 10, 15, 3, 0, 10, 15, 3, 0, 10, 15, 3, 0, 10, 15, 3, 0, 10, 15, 3, 0, 10, 15, 3, 0, 10, 15, 3, 0, 10, 15, 3, 0, 10, 15, 3, 0, 10, 15, 3, 0, 10, 15, 3, 0, 10, 15, 3, 0, 10, 15, 3, 0, 10, 15, 3, 0, 10, 15, 3, 0, 10, 15, 3, 0, 10, 15, 3, 0, 10, 15, 3, 0, 10, 15, 3, 0, 10, 15, 3, 0, 10, 15, 3, 0, + 10, 15, 3, 0, 10, 15, 3, 0, 10, 15, 3, 0, 10, 15, 3, 0, 10, 15, 3, 0, 10, 15, 3, 0, 10, 15, 3, 0, 10, 15, 3, 0, 138, 39, 3, 0, 138, 39, 3, 0, 138, 39, 3, 0, 138, 39, 3, 0, 138, 39, 3, 0, 138, 39, 3, 0, 138, 39, 3, 0, 138, 39, 3, 0, 138, 39, 3, 0, 138, 39, 3, 0, 138, 39, 3, 0, 138, 39, 3, 0, 138, 39, 3, 0, 138, 39, 3, 0, 138, 39, 3, 0, 138, 39, 3, 0, 138, 39, 3, 0, + 138, 39, 3, 0, 138, 39, 3, 0, 138, 39, 3, 0, 138, 39, 3, 0, 138, 39, 3, 0, 138, 39, 3, 0, 138, 39, 3, 0, 138, 39, 3, 0, 138, 39, 3, 0, 138, 39, 3, 0, 138, 39, 3, 0, 138, 39, 3, 0, 138, 39, 3, 0, 138, 39, 3, 0, 138, 39, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, + 74, 31, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, 74, 31, 3, 0, 74, 9, 3, 0, 74, 9, 3, 0, 74, 9, 3, 0, + 74, 9, 3, 0, 74, 9, 3, 0, 74, 9, 3, 0, 74, 9, 3, 0, 74, 9, 3, 0, 74, 9, 3, 0, 74, 9, 3, 0, 74, 9, 3, 0, 74, 9, 3, 0, 74, 9, 3, 0, 74, 9, 3, 0, 74, 9, 3, 0, 74, 9, 3, 0, 74, 9, 3, 0, 74, 9, 3, 0, 74, 9, 3, 0, 74, 9, 3, 0, 74, 9, 3, 0, 74, 9, 3, 0, 74, 9, 3, 0, 74, 9, 3, 0, 74, 9, 3, 0, 74, 9, 3, 0, 74, 9, 3, 0, 74, 9, 3, 0, + 74, 9, 3, 0, 74, 9, 3, 0, 74, 9, 3, 0, 74, 9, 3, 0, 10, 1, 3, 0, 10, 1, 3, 0, 10, 1, 3, 0, 10, 1, 3, 0, 10, 1, 3, 0, 10, 1, 3, 0, 10, 1, 3, 0, 10, 1, 3, 0, 10, 1, 3, 0, 10, 1, 3, 0, 10, 1, 3, 0, 10, 1, 3, 0, 10, 1, 3, 0, 10, 1, 3, 0, 10, 1, 3, 0, 10, 1, 3, 0, 10, 1, 3, 0, 10, 1, 3, 0, 10, 1, 3, 0, 10, 1, 3, 0, 10, 1, 3, 0, + 10, 1, 3, 0, 10, 1, 3, 0, 10, 1, 3, 0, 10, 1, 3, 0, 10, 1, 3, 0, 10, 1, 3, 0, 10, 1, 3, 0, 10, 1, 3, 0, 10, 1, 3, 0, 10, 1, 3, 0, 10, 1, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, + 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 202, 18, 3, 0, 74, 27, 3, 0, 74, 27, 3, 0, 74, 27, 3, 0, 74, 27, 3, 0, 74, 27, 3, 0, 74, 27, 3, 0, 74, 27, 3, 0, + 74, 27, 3, 0, 74, 27, 3, 0, 74, 27, 3, 0, 74, 27, 3, 0, 74, 27, 3, 0, 74, 27, 3, 0, 74, 27, 3, 0, 74, 27, 3, 0, 74, 27, 3, 0, 74, 27, 3, 0, 74, 27, 3, 0, 74, 27, 3, 0, 74, 27, 3, 0, 74, 27, 3, 0, 74, 27, 3, 0, 74, 27, 3, 0, 97, 27, 3, 0, 97, 27, 3, 0, 84, 27, 3, 0, 84, 27, 3, 0, 84, 27, 3, 0, 84, 27, 3, 0, 84, 27, 3, 0, 84, 27, 3, 0, 84, 27, 3, 0, + 10, 22, 3, 0, 10, 22, 3, 0, 10, 22, 3, 0, 10, 22, 3, 0, 10, 22, 3, 0, 10, 22, 3, 0, 10, 22, 3, 0, 10, 22, 3, 0, 10, 22, 3, 0, 10, 22, 3, 0, 10, 22, 3, 0, 10, 22, 3, 0, 10, 22, 3, 0, 10, 22, 3, 0, 10, 22, 3, 0, 10, 22, 3, 0, 10, 22, 3, 0, 10, 22, 3, 0, 10, 22, 3, 0, 10, 22, 3, 0, 10, 22, 3, 0, 10, 22, 3, 0, 10, 22, 3, 0, 10, 22, 3, 0, 10, 22, 3, 0, + 10, 22, 3, 0, 10, 22, 3, 0, 10, 22, 3, 0, 10, 22, 3, 0, 10, 22, 3, 0, 10, 22, 3, 0, 10, 22, 3, 0, 138, 30, 3, 0, 138, 30, 3, 0, 138, 30, 3, 0, 138, 30, 3, 0, 138, 30, 3, 0, 138, 30, 3, 0, 138, 30, 3, 0, 138, 30, 3, 0, 138, 30, 3, 0, 138, 30, 3, 0, 138, 30, 3, 0, 138, 30, 3, 0, 138, 30, 3, 0, 138, 30, 3, 0, 138, 30, 3, 0, 138, 30, 3, 0, 138, 30, 3, 0, 138, 30, 3, 0, + 138, 30, 3, 0, 138, 30, 3, 0, 138, 30, 3, 0, 138, 30, 3, 0, 138, 30, 3, 0, 138, 30, 3, 0, 138, 30, 3, 0, 138, 30, 3, 0, 138, 30, 3, 0, 138, 30, 3, 0, 138, 30, 3, 0, 148, 30, 3, 0, 148, 30, 3, 0, 155, 30, 3, 0, 74, 24, 3, 0, 74, 24, 3, 0, 74, 24, 3, 0, 74, 24, 3, 0, 74, 24, 3, 0, 74, 24, 3, 0, 74, 24, 3, 0, 74, 24, 3, 0, 74, 24, 3, 0, 74, 24, 3, 0, 74, 24, 3, 0, + 74, 24, 3, 0, 74, 24, 3, 0, 74, 24, 3, 0, 74, 24, 3, 0, 74, 24, 3, 0, 74, 24, 3, 0, 74, 24, 3, 0, 74, 24, 3, 0, 74, 24, 3, 0, 74, 24, 3, 0, 74, 24, 3, 0, 74, 24, 3, 0, 74, 24, 3, 0, 74, 24, 3, 0, 74, 24, 3, 0, 74, 24, 3, 0, 74, 24, 3, 0, 74, 24, 3, 0, 84, 24, 3, 0, 84, 24, 3, 0, 84, 24, 3, 0, 202, 20, 3, 0, 202, 20, 3, 0, 202, 20, 3, 0, 202, 20, 3, 0, + 202, 20, 3, 0, 202, 20, 3, 0, 202, 20, 3, 0, 202, 20, 3, 0, 225, 20, 3, 0, 202, 20, 3, 0, 202, 20, 3, 0, 202, 20, 3, 0, 202, 20, 3, 0, 202, 20, 3, 0, 202, 20, 3, 0, 202, 20, 3, 0, 202, 20, 3, 0, 202, 20, 3, 0, 202, 20, 3, 0, 202, 20, 3, 0, 202, 20, 3, 0, 202, 20, 3, 0, 202, 20, 3, 0, 202, 20, 3, 0, 202, 20, 3, 0, 202, 20, 3, 0, 202, 20, 3, 0, 202, 20, 3, 0, 202, 20, 3, 0, + 202, 20, 3, 0, 202, 20, 3, 0, 202, 20, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, + 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 74, 2, 3, 0, 10, 26, 3, 0, 10, 26, 3, 0, 10, 26, 3, 0, 10, 26, 3, 0, 10, 26, 3, 0, 10, 26, 3, 0, 10, 26, 3, 0, 10, 26, 3, 0, 10, 26, 3, 0, 10, 26, 3, 0, 10, 26, 3, 0, 10, 26, 3, 0, 10, 26, 3, 0, 10, 26, 3, 0, 10, 26, 3, 0, + 10, 26, 3, 0, 10, 26, 3, 0, 10, 26, 3, 0, 10, 26, 3, 0, 10, 26, 3, 0, 10, 26, 3, 0, 10, 26, 3, 0, 10, 26, 3, 0, 10, 26, 3, 0, 10, 26, 3, 0, 10, 26, 3, 0, 10, 26, 3, 0, 10, 26, 3, 0, 10, 26, 3, 0, 10, 26, 3, 0, 10, 26, 3, 0, 10, 26, 3, 0, 202, 29, 3, 0, 202, 29, 3, 0, 202, 29, 3, 0, 202, 29, 3, 0, 202, 29, 3, 0, 202, 29, 3, 0, 202, 29, 3, 0, 202, 29, 3, 0, + 202, 29, 3, 0, 202, 29, 3, 0, 202, 29, 3, 0, 202, 29, 3, 0, 202, 29, 3, 0, 202, 29, 3, 0, 202, 29, 3, 0, 202, 29, 3, 0, 202, 29, 3, 0, 202, 29, 3, 0, 202, 29, 3, 0, 202, 29, 3, 0, 202, 29, 3, 0, 202, 29, 3, 0, 202, 29, 3, 0, 202, 29, 3, 0, 202, 29, 3, 0, 202, 29, 3, 0, 202, 29, 3, 0, 202, 29, 3, 0, 202, 29, 3, 0, 202, 29, 3, 0, 202, 29, 3, 0, 202, 29, 3, 0, 10, 40, 3, 0, + 10, 40, 3, 0, 10, 40, 3, 0, 10, 40, 3, 0, 10, 40, 3, 0, 10, 40, 3, 0, 10, 40, 3, 0, 10, 40, 3, 0, 10, 40, 3, 0, 10, 40, 3, 0, 10, 40, 3, 0, 10, 40, 3, 0, 10, 40, 3, 0, 10, 40, 3, 0, 10, 40, 3, 0, 10, 40, 3, 0, 10, 40, 3, 0, 10, 40, 3, 0, 10, 40, 3, 0, 10, 40, 3, 0, 10, 40, 3, 0, 10, 40, 3, 0, 10, 40, 3, 0, 10, 40, 3, 0, 10, 40, 3, 0, 10, 40, 3, 0, + 10, 40, 3, 0, 10, 40, 3, 0, 10, 40, 3, 0, 10, 40, 3, 0, 10, 40, 3, 0, 10, 40, 3, 0, 202, 32, 3, 0, 202, 32, 3, 0, 202, 32, 3, 0, 202, 32, 3, 0, 202, 32, 3, 0, 202, 32, 3, 0, 202, 32, 3, 0, 202, 32, 3, 0, 202, 32, 3, 0, 202, 32, 3, 0, 202, 32, 3, 0, 202, 32, 3, 0, 202, 32, 3, 0, 202, 32, 3, 0, 202, 32, 3, 0, 202, 32, 3, 0, 202, 32, 3, 0, 202, 32, 3, 0, 202, 32, 3, 0, + 202, 32, 3, 0, 202, 32, 3, 0, 202, 32, 3, 0, 202, 32, 3, 0, 202, 32, 3, 0, 202, 32, 3, 0, 202, 32, 3, 0, 202, 32, 3, 0, 202, 32, 3, 0, 202, 32, 3, 0, 212, 32, 3, 0, 212, 32, 3, 0, 212, 32, 3, 0, 78, 68, 5, 0, 80, 68, 5, 0, 78, 68, 5, 0, 74, 4, 3, 0, 74, 4, 3, 0, 74, 4, 3, 0, 74, 4, 3, 0, 74, 4, 3, 0, 74, 4, 3, 0, 74, 4, 3, 0, 74, 4, 3, 0, 74, 4, 3, 0, + 74, 4, 3, 0, 74, 4, 3, 0, 74, 4, 3, 0, 74, 4, 3, 0, 74, 4, 3, 0, 74, 4, 3, 0, 74, 4, 3, 0, 74, 4, 3, 0, 74, 4, 3, 0, 74, 4, 3, 0, 74, 4, 3, 0, 74, 4, 3, 0, 74, 4, 3, 0, 74, 4, 3, 0, 74, 4, 3, 0, 74, 4, 3, 0, 74, 4, 3, 0, 74, 4, 3, 0, 74, 4, 3, 0, 74, 4, 3, 0, 80, 68, 5, 0, 80, 68, 5, 0, 80, 68, 5, 0, 80, 68, 5, 0, 80, 68, 5, 0, + 80, 68, 5, 0, 80, 68, 5, 0, 80, 68, 5, 0, 80, 81, 5, 0, 80, 81, 5, 0, 78, 81, 5, 0, 74, 17, 3, 0, 74, 17, 3, 0, 74, 17, 3, 0, 74, 17, 3, 0, 74, 17, 3, 0, 74, 17, 3, 0, 74, 17, 3, 0, 74, 17, 3, 0, 74, 17, 3, 0, 74, 17, 3, 0, 74, 17, 3, 0, 74, 17, 3, 0, 74, 17, 3, 0, 74, 17, 3, 0, 74, 17, 3, 0, 74, 17, 3, 0, 74, 17, 3, 0, 74, 17, 3, 0, 74, 17, 3, 0, + 74, 17, 3, 0, 74, 17, 3, 0, 74, 17, 3, 0, 74, 17, 3, 0, 74, 17, 3, 0, 74, 17, 3, 0, 74, 17, 3, 0, 74, 17, 3, 0, 74, 17, 3, 0, 74, 17, 3, 0, 78, 81, 5, 0, 78, 81, 5, 0, 78, 81, 5, 0, 80, 81, 5, 0, 80, 81, 5, 0, 80, 81, 5, 0, 80, 81, 5, 0, 78, 81, 5, 0, 78, 81, 5, 0, 80, 81, 5, 0, 80, 81, 5, 0, 91, 17, 3, 0, 91, 17, 3, 0, 66, 17, 3, 0, 91, 81, 4, 0, + 91, 81, 4, 0, 80, 69, 5, 0, 80, 69, 5, 0, 80, 69, 5, 0, 74, 5, 3, 0, 74, 5, 3, 0, 74, 5, 3, 0, 74, 5, 3, 0, 74, 5, 3, 0, 74, 5, 3, 0, 74, 5, 3, 0, 74, 5, 3, 0, 74, 5, 3, 0, 74, 5, 3, 0, 74, 5, 3, 0, 74, 5, 3, 0, 74, 5, 3, 0, 74, 5, 3, 0, 74, 5, 3, 0, 74, 5, 3, 0, 74, 5, 3, 0, 74, 5, 3, 0, 74, 5, 3, 0, 74, 5, 3, 0, 74, 5, 3, 0, + 74, 5, 3, 0, 74, 5, 3, 0, 74, 5, 3, 0, 74, 5, 3, 0, 74, 5, 3, 0, 74, 5, 3, 0, 74, 5, 3, 0, 74, 5, 3, 0, 144, 95, 5, 0, 144, 95, 5, 0, 142, 95, 5, 0, 138, 31, 3, 0, 138, 31, 3, 0, 138, 31, 3, 0, 138, 31, 3, 0, 138, 31, 3, 0, 138, 31, 3, 0, 138, 31, 3, 0, 138, 31, 3, 0, 138, 31, 3, 0, 138, 31, 3, 0, 138, 31, 3, 0, 138, 31, 3, 0, 138, 31, 3, 0, 138, 31, 3, 0, + 138, 31, 3, 0, 138, 31, 3, 0, 138, 31, 3, 0, 138, 31, 3, 0, 138, 31, 3, 0, 138, 31, 3, 0, 138, 31, 3, 0, 138, 31, 3, 0, 138, 31, 3, 0, 138, 31, 3, 0, 138, 31, 3, 0, 138, 31, 3, 0, 138, 31, 3, 0, 138, 31, 3, 0, 138, 31, 3, 0, 138, 31, 3, 0, 138, 31, 3, 0, 138, 31, 3, 0, 142, 95, 5, 0, 142, 95, 5, 0, 142, 95, 5, 0, 144, 95, 5, 0, 144, 95, 5, 0, 144, 95, 5, 0, 144, 95, 5, 0, + 144, 95, 5, 0, 144, 95, 5, 0, 144, 95, 5, 0, 144, 95, 5, 0, 144, 95, 5, 0, 142, 95, 5, 0, 142, 95, 5, 0, 138, 31, 3, 0, 138, 31, 3, 0, 138, 31, 3, 0, 138, 31, 3, 0, 155, 95, 4, 0, 155, 95, 4, 0, 155, 31, 3, 0, 155, 95, 4, 0, 144, 95, 5, 0, 144, 95, 5, 0, 144, 95, 5, 0, 144, 95, 5, 0, 155, 31, 3, 0, 142, 95, 5, 0, 144, 95, 5, 0, 146, 223, 2, 0, 146, 223, 2, 0, 146, 223, 2, 0, + 146, 223, 2, 0, 146, 223, 2, 0, 146, 223, 2, 0, 146, 223, 2, 0, 146, 223, 2, 0, 146, 223, 2, 0, 146, 223, 2, 0, 138, 31, 3, 0, 155, 159, 4, 0, 138, 31, 3, 0, 155, 95, 4, 0, 155, 95, 4, 0, 155, 95, 4, 0, 10, 32, 3, 0, 10, 32, 3, 0, 10, 32, 3, 0, 10, 32, 3, 0, 10, 32, 3, 0, 10, 32, 3, 0, 10, 32, 3, 0, 10, 32, 3, 0, 10, 32, 3, 0, 10, 32, 3, 0, 10, 32, 3, 0, 10, 32, 3, 0, + 10, 32, 3, 0, 10, 32, 3, 0, 10, 32, 3, 0, 10, 32, 3, 0, 10, 32, 3, 0, 10, 32, 3, 0, 10, 32, 3, 0, 10, 32, 3, 0, 10, 32, 3, 0, 10, 32, 3, 0, 10, 32, 3, 0, 10, 32, 3, 0, 10, 32, 3, 0, 10, 32, 3, 0, 10, 32, 3, 0, 10, 32, 3, 0, 10, 32, 3, 0, 10, 32, 3, 0, 10, 32, 3, 0, 16, 96, 5, 0, 202, 24, 3, 0, 202, 24, 3, 0, 202, 24, 3, 0, 202, 24, 3, 0, 202, 24, 3, 0, + 202, 24, 3, 0, 202, 24, 3, 0, 202, 24, 3, 0, 202, 24, 3, 0, 202, 24, 3, 0, 202, 24, 3, 0, 202, 24, 3, 0, 202, 24, 3, 0, 202, 24, 3, 0, 202, 24, 3, 0, 202, 24, 3, 0, 202, 24, 3, 0, 202, 24, 3, 0, 202, 24, 3, 0, 202, 24, 3, 0, 202, 24, 3, 0, 202, 24, 3, 0, 202, 24, 3, 0, 202, 24, 3, 0, 202, 24, 3, 0, 202, 24, 3, 0, 202, 24, 3, 0, 202, 24, 3, 0, 202, 24, 3, 0, 202, 24, 3, 0, + 202, 24, 3, 0, 202, 24, 3, 0, 202, 24, 3, 0, 206, 88, 5, 0, 206, 88, 5, 0, 206, 88, 5, 0, 208, 88, 5, 0, 208, 88, 5, 0, 208, 88, 5, 0, 208, 88, 5, 0, 208, 88, 5, 0, 208, 88, 5, 0, 208, 88, 5, 0, 208, 88, 5, 0, 138, 37, 3, 0, 138, 37, 3, 0, 138, 37, 3, 0, 138, 37, 3, 0, 138, 37, 3, 0, 138, 37, 3, 0, 138, 37, 3, 0, 138, 37, 3, 0, 138, 37, 3, 0, 138, 37, 3, 0, 138, 37, 3, 0, + 138, 37, 3, 0, 138, 37, 3, 0, 138, 37, 3, 0, 138, 37, 3, 0, 138, 37, 3, 0, 138, 37, 3, 0, 138, 37, 3, 0, 138, 37, 3, 0, 138, 37, 3, 0, 138, 37, 3, 0, 138, 37, 3, 0, 138, 37, 3, 0, 138, 37, 3, 0, 138, 37, 3, 0, 138, 37, 3, 0, 138, 37, 3, 0, 138, 37, 3, 0, 138, 37, 3, 0, 138, 37, 3, 0, 138, 37, 3, 0, 138, 37, 3, 0, 142, 101, 5, 0, 142, 101, 5, 0, 142, 101, 5, 0, 144, 101, 5, 0, + 144, 101, 5, 0, 144, 101, 5, 0, 144, 101, 5, 0, 144, 101, 5, 0, 144, 101, 5, 0, 142, 101, 5, 0, 144, 101, 5, 0, 142, 101, 5, 0, 142, 101, 5, 0, 142, 101, 5, 0, 142, 101, 5, 0, 144, 101, 5, 0, 202, 31, 3, 0, 202, 31, 3, 0, 202, 31, 3, 0, 202, 31, 3, 0, 202, 31, 3, 0, 202, 31, 3, 0, 202, 31, 3, 0, 202, 31, 3, 0, 202, 31, 3, 0, 202, 31, 3, 0, 202, 31, 3, 0, 202, 31, 3, 0, 202, 31, 3, 0, + 202, 31, 3, 0, 202, 31, 3, 0, 202, 31, 3, 0, 202, 31, 3, 0, 202, 31, 3, 0, 202, 31, 3, 0, 202, 31, 3, 0, 202, 31, 3, 0, 202, 31, 3, 0, 202, 31, 3, 0, 202, 31, 3, 0, 202, 31, 3, 0, 202, 31, 3, 0, 202, 31, 3, 0, 202, 31, 3, 0, 202, 31, 3, 0, 202, 31, 3, 0, 202, 31, 3, 0, 202, 31, 3, 0, 138, 22, 3, 0, 138, 22, 3, 0, 138, 22, 3, 0, 138, 22, 3, 0, 138, 22, 3, 0, 138, 22, 3, 0, + 138, 22, 3, 0, 138, 22, 3, 0, 138, 22, 3, 0, 138, 22, 3, 0, 138, 22, 3, 0, 138, 22, 3, 0, 138, 22, 3, 0, 138, 22, 3, 0, 138, 22, 3, 0, 138, 22, 3, 0, 138, 22, 3, 0, 138, 22, 3, 0, 138, 22, 3, 0, 138, 22, 3, 0, 138, 22, 3, 0, 138, 22, 3, 0, 138, 22, 3, 0, 138, 22, 3, 0, 138, 22, 3, 0, 138, 22, 3, 0, 138, 22, 3, 0, 138, 22, 3, 0, 138, 22, 3, 0, 138, 22, 3, 0, 138, 22, 3, 0, + 138, 22, 3, 0, 142, 86, 5, 0, 142, 86, 5, 0, 142, 86, 5, 0, 144, 86, 5, 0, 144, 86, 5, 0, 144, 86, 5, 0, 144, 86, 5, 0, 144, 86, 5, 0, 144, 86, 5, 0, 144, 86, 5, 0, 144, 86, 5, 0, 142, 86, 5, 0, 142, 86, 5, 0, 144, 86, 5, 0, 142, 86, 5, 0, 144, 86, 5, 0, 138, 34, 3, 0, 138, 34, 3, 0, 138, 34, 3, 0, 138, 34, 3, 0, 138, 34, 3, 0, 138, 34, 3, 0, 138, 34, 3, 0, 138, 34, 3, 0, + 138, 34, 3, 0, 138, 34, 3, 0, 138, 34, 3, 0, 138, 34, 3, 0, 138, 34, 3, 0, 138, 34, 3, 0, 138, 34, 3, 0, 138, 34, 3, 0, 138, 34, 3, 0, 138, 34, 3, 0, 138, 34, 3, 0, 138, 34, 3, 0, 138, 34, 3, 0, 138, 34, 3, 0, 138, 34, 3, 0, 138, 34, 3, 0, 138, 34, 3, 0, 138, 34, 3, 0, 138, 34, 3, 0, 138, 34, 3, 0, 138, 34, 3, 0, 138, 34, 3, 0, 138, 34, 3, 0, 138, 34, 3, 0, 74, 8, 3, 0, + 74, 8, 3, 0, 74, 8, 3, 0, 74, 8, 3, 0, 74, 8, 3, 0, 74, 8, 3, 0, 74, 8, 3, 0, 74, 8, 3, 0, 74, 8, 3, 0, 74, 8, 3, 0, 74, 8, 3, 0, 74, 8, 3, 0, 74, 8, 3, 0, 74, 8, 3, 0, 74, 8, 3, 0, 74, 8, 3, 0, 74, 8, 3, 0, 74, 8, 3, 0, 74, 8, 3, 0, 74, 8, 3, 0, 74, 8, 3, 0, 74, 8, 3, 0, 74, 8, 3, 0, 74, 8, 3, 0, 74, 8, 3, 0, 74, 8, 3, 0, + 74, 8, 3, 0, 74, 8, 3, 0, 74, 8, 3, 0, 74, 8, 3, 0, 74, 8, 3, 0, 74, 8, 3, 0, 138, 40, 3, 0, 144, 104, 5, 0, 144, 104, 5, 0, 144, 104, 5, 0, 144, 104, 5, 0, 144, 104, 5, 0, 144, 104, 5, 0, 144, 104, 5, 0, 144, 104, 5, 0, 144, 104, 5, 0, 144, 104, 5, 0, 138, 40, 3, 0, 138, 40, 3, 0, 138, 40, 3, 0, 138, 40, 3, 0, 138, 40, 3, 0, 138, 40, 3, 0, 138, 40, 3, 0, 138, 40, 3, 0, + 138, 40, 3, 0, 138, 40, 3, 0, 138, 40, 3, 0, 138, 40, 3, 0, 138, 40, 3, 0, 138, 40, 3, 0, 138, 40, 3, 0, 138, 40, 3, 0, 138, 40, 3, 0, 138, 40, 3, 0, 138, 40, 3, 0, 138, 40, 3, 0, 138, 40, 3, 0, 138, 40, 3, 0, 138, 40, 3, 0, 138, 40, 3, 0, 144, 104, 5, 0, 144, 104, 5, 0, 144, 104, 5, 0, 144, 104, 5, 0, 144, 104, 5, 0, 144, 104, 5, 0, 142, 104, 5, 0, 138, 40, 3, 0, 144, 104, 5, 0, + 144, 104, 5, 0, 144, 104, 5, 0, 144, 104, 5, 0, 155, 168, 4, 0, 74, 33, 3, 0, 74, 33, 3, 0, 74, 33, 3, 0, 74, 33, 3, 0, 74, 33, 3, 0, 74, 33, 3, 0, 74, 33, 3, 0, 74, 33, 3, 0, 74, 33, 3, 0, 74, 33, 3, 0, 74, 33, 3, 0, 74, 33, 3, 0, 74, 33, 3, 0, 74, 33, 3, 0, 74, 33, 3, 0, 74, 33, 3, 0, 74, 33, 3, 0, 74, 33, 3, 0, 74, 33, 3, 0, 74, 33, 3, 0, 74, 33, 3, 0, + 74, 33, 3, 0, 74, 33, 3, 0, 74, 33, 3, 0, 74, 33, 3, 0, 74, 33, 3, 0, 74, 33, 3, 0, 74, 33, 3, 0, 74, 33, 3, 0, 74, 33, 3, 0, 74, 33, 3, 0, 74, 33, 3, 0, 74, 33, 3, 0, 74, 33, 3, 0, 80, 97, 5, 0, 80, 97, 5, 0, 80, 97, 5, 0, 80, 97, 5, 0, 80, 97, 5, 0, 80, 97, 5, 0, 80, 97, 5, 0, 80, 97, 5, 0, 80, 97, 5, 0, 80, 97, 5, 0, 80, 97, 5, 0, 80, 97, 5, 0, + 80, 97, 5, 0, 78, 97, 5, 0, 80, 97, 5, 0, 80, 97, 5, 0, 91, 97, 4, 0, 91, 97, 4, 0, 91, 97, 4, 0, 74, 33, 3, 0, 91, 161, 4, 0, 91, 161, 4, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, + 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 138, 27, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, + 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 202, 39, 3, 0, 10, 7, 3, 0, + 10, 7, 3, 0, 10, 7, 3, 0, 10, 7, 3, 0, 10, 7, 3, 0, 10, 7, 3, 0, 10, 7, 3, 0, 10, 7, 3, 0, 10, 7, 3, 0, 10, 7, 3, 0, 10, 7, 3, 0, 10, 7, 3, 0, 10, 7, 3, 0, 10, 7, 3, 0, 10, 7, 3, 0, 10, 7, 3, 0, 10, 7, 3, 0, 10, 7, 3, 0, 10, 7, 3, 0, 10, 7, 3, 0, 10, 7, 3, 0, 10, 7, 3, 0, 10, 7, 3, 0, 10, 7, 3, 0, 10, 7, 3, 0, 10, 7, 3, 0, + 10, 7, 3, 0, 10, 7, 3, 0, 10, 7, 3, 0, 10, 7, 3, 0, 10, 7, 3, 0, 10, 7, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, + 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 0, 0, 10, 9, 0, 0, 10, 9, 0, 0, 10, 73, 0, 0, 10, 73, 0, 0, 10, 73, 0, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 73, 0, 0, 10, 9, 3, 0, + 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 0, 0, 10, 73, 0, 0, 10, 9, 0, 0, 10, 73, 0, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, + 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 0, 0, 10, 73, 0, 0, 10, 73, 0, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 10, 9, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, + 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 0, 0, + 202, 77, 0, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 13, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, + 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 202, 37, 3, 0, 10, 14, 3, 0, + 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, + 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 10, 14, 3, 0, 16, 78, 5, 0, 16, 78, 5, 0, 16, 78, 5, 0, 16, 78, 5, 0, 16, 78, 5, 0, 16, 78, 5, 0, 16, 78, 5, 0, 27, 78, 4, 0, 27, 78, 4, 0, 27, 78, 4, 0, 27, 14, 3, 0, 27, 14, 3, 0, 33, 14, 3, 0, 33, 14, 3, 0, 33, 14, 3, 0, 33, 14, 3, 0, 10, 29, 3, 0, 10, 29, 3, 0, 10, 29, 3, 0, + 10, 29, 3, 0, 10, 29, 3, 0, 10, 29, 3, 0, 10, 29, 3, 0, 10, 29, 3, 0, 10, 29, 3, 0, 10, 29, 3, 0, 10, 29, 3, 0, 10, 29, 3, 0, 10, 29, 3, 0, 10, 29, 3, 0, 10, 29, 3, 0, 10, 29, 3, 0, 10, 29, 3, 0, 10, 29, 3, 0, 10, 29, 3, 0, 10, 29, 3, 0, 10, 29, 3, 0, 10, 29, 3, 0, 10, 29, 3, 0, 10, 29, 3, 0, 10, 29, 3, 0, 10, 29, 3, 0, 10, 29, 3, 0, 10, 29, 3, 0, + 10, 29, 3, 0, 10, 29, 3, 0, 10, 29, 3, 0, 10, 29, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, + 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 138, 163, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, + 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 16, 3, 0, 202, 143, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, + 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, + 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 138, 141, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, + 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 74, 153, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, + 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 202, 8, 3, 0, 74, 14, 3, 0, 74, 14, 3, 0, 74, 14, 3, 0, 74, 14, 3, 0, 74, 14, 3, 0, 74, 14, 3, 0, 74, 14, 3, 0, + 74, 14, 3, 0, 74, 14, 3, 0, 74, 14, 3, 0, 74, 14, 3, 0, 74, 14, 3, 0, 74, 14, 3, 0, 74, 14, 3, 0, 74, 14, 3, 0, 74, 14, 3, 0, 74, 14, 3, 0, 74, 14, 3, 0, 74, 14, 3, 0, 74, 14, 3, 0, 74, 14, 3, 0, 74, 14, 3, 0, 74, 14, 3, 0, 74, 14, 3, 0, 74, 14, 3, 0, 74, 14, 3, 0, 74, 14, 3, 0, 74, 14, 3, 0, 74, 14, 3, 0, 74, 14, 3, 0, 74, 14, 3, 0, 74, 14, 3, 0, + 74, 39, 3, 0, 74, 39, 3, 0, 74, 39, 3, 0, 74, 39, 3, 0, 74, 39, 3, 0, 74, 39, 3, 0, 74, 39, 3, 0, 74, 39, 3, 0, 74, 39, 3, 0, 74, 39, 3, 0, 74, 39, 3, 0, 74, 39, 3, 0, 74, 39, 3, 0, 74, 39, 3, 0, 74, 39, 3, 0, 74, 39, 3, 0, 74, 39, 3, 0, 74, 39, 3, 0, 74, 39, 3, 0, 74, 39, 3, 0, 74, 39, 3, 0, 74, 39, 3, 0, 74, 39, 3, 0, 74, 39, 3, 0, 74, 39, 3, 0, + 74, 39, 3, 0, 74, 39, 3, 0, 74, 39, 3, 0, 74, 39, 3, 0, 74, 39, 3, 0, 74, 39, 3, 0, 74, 39, 3, 0, 138, 21, 3, 0, 138, 21, 3, 0, 138, 21, 3, 0, 138, 21, 3, 0, 138, 21, 3, 0, 138, 21, 3, 0, 138, 21, 3, 0, 138, 21, 3, 0, 138, 21, 3, 0, 138, 21, 3, 0, 138, 21, 3, 0, 138, 21, 3, 0, 138, 21, 3, 0, 138, 21, 3, 0, 138, 21, 3, 0, 138, 21, 3, 0, 138, 21, 3, 0, 138, 21, 3, 0, + 138, 21, 3, 0, 138, 21, 3, 0, 138, 21, 3, 0, 138, 21, 3, 0, 138, 21, 3, 0, 138, 21, 3, 0, 138, 21, 3, 0, 138, 21, 3, 0, 138, 21, 3, 0, 138, 21, 3, 0, 138, 21, 3, 0, 138, 21, 3, 0, 138, 21, 3, 0, 138, 21, 3, 0, 144, 65, 5, 0, 144, 65, 5, 0, 66, 0, 3, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, + 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 144, 65, 5, 0, 82, 229, 2, 0, 82, 229, 2, 0, 82, 229, 2, 0, 82, 229, 2, 0, + 82, 229, 2, 0, 82, 229, 2, 0, 82, 229, 2, 0, 82, 229, 2, 0, 82, 229, 2, 0, 82, 229, 2, 0, 84, 37, 3, 0, 84, 37, 3, 0, 84, 37, 3, 0, 84, 37, 3, 0, 84, 37, 3, 0, 84, 37, 3, 0, 84, 37, 3, 0, 84, 37, 3, 0, 84, 37, 3, 0, 84, 37, 3, 0, 97, 101, 4, 0, 80, 101, 5, 0, 97, 37, 3, 0, 80, 101, 5, 0, 97, 37, 3, 0, 80, 101, 5, 0, 92, 37, 0, 0, 88, 101, 0, 0, 92, 37, 0, 0, + 88, 101, 0, 0, 78, 101, 5, 0, 78, 101, 5, 0, 144, 71, 5, 0, 144, 71, 5, 0, 144, 71, 5, 0, 144, 71, 5, 0, 144, 71, 5, 0, 144, 71, 5, 0, 144, 71, 5, 0, 144, 71, 5, 0, 144, 71, 5, 0, 144, 71, 5, 0, 144, 71, 5, 0, 144, 71, 5, 0, 144, 71, 5, 0, 144, 71, 5, 0, 144, 71, 5, 0, 144, 71, 5, 0, 144, 71, 5, 0, 144, 71, 5, 0, 144, 71, 5, 0, 144, 71, 5, 0, 144, 71, 5, 0, 144, 71, 5, 0, + 144, 71, 5, 0, 144, 71, 5, 0, 144, 71, 5, 0, 144, 71, 5, 0, 144, 71, 5, 0, 144, 71, 5, 0, 144, 71, 5, 0, 144, 71, 5, 0, 144, 71, 5, 0, 144, 71, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 71, 5, 0, + 144, 71, 5, 0, 91, 128, 3, 0, 87, 128, 3, 0, 87, 128, 3, 0, 86, 128, 3, 0, 86, 128, 3, 0, 92, 0, 0, 0, 88, 64, 0, 0, 92, 0, 0, 0, 88, 64, 0, 0, 92, 0, 0, 0, 88, 64, 0, 0, 92, 0, 0, 0, 88, 64, 0, 0, 92, 0, 0, 0, 88, 64, 0, 0, 92, 0, 0, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 78, 64, 5, 0, 78, 64, 5, 0, 144, 64, 5, 0, + 144, 64, 5, 0, 144, 64, 5, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 78, 64, 5, 0, 78, 64, 5, 0, 78, 64, 5, 0, 78, 64, 5, 0, 78, 64, 5, 0, 78, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, + 144, 64, 5, 0, 144, 64, 5, 0, 97, 0, 3, 0, 97, 0, 3, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, + 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 144, 64, 5, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, + 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, + 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 33, 31, 3, 0, 33, 31, 3, 0, 33, 31, 3, 0, 33, 31, 3, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, + 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 16, 95, 5, 0, 33, 31, 3, 0, 33, 31, 3, 0, 33, 31, 3, 0, 33, 31, 3, 0, 33, 31, 3, 0, 33, 31, 3, 0, 33, 31, 3, 0, 33, 31, 3, 0, 16, 95, 5, 0, 33, 31, 3, 0, 33, 31, 3, 0, 33, 31, 3, 0, 33, 31, 3, 0, 33, 31, 3, 0, 33, 31, 3, 0, 33, 31, 3, 0, 33, 31, 3, 0, + 33, 31, 3, 0, 33, 31, 3, 0, 14, 93, 5, 0, 14, 93, 5, 0, 14, 93, 5, 0, 14, 93, 5, 0, 14, 93, 5, 0, 14, 93, 5, 0, 14, 93, 5, 0, 14, 93, 5, 0, 14, 93, 5, 0, 14, 93, 5, 0, 14, 93, 5, 0, 14, 93, 5, 0, 14, 93, 5, 0, 14, 93, 5, 0, 14, 93, 5, 0, 14, 93, 5, 0, 14, 93, 5, 0, 14, 93, 5, 0, 14, 93, 5, 0, 14, 93, 5, 0, 14, 93, 5, 0, 14, 93, 5, 0, 14, 93, 5, 0, + 14, 93, 5, 0, 14, 93, 5, 0, 14, 93, 5, 0, 14, 93, 5, 0, 14, 93, 5, 0, 14, 93, 5, 0, 14, 93, 5, 0, 14, 93, 5, 0, 14, 93, 5, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, + 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 82, 192, 2, 0, 19, 146, 8, 0, 19, 146, 8, 0, 19, 146, 8, 0, 19, 146, 8, 0, 19, 146, 8, 0, 19, 146, 8, 0, 19, 146, 8, 0, 19, 146, 8, 0, 19, 146, 8, 0, + 19, 146, 8, 0, 19, 146, 8, 0, 19, 146, 8, 0, 19, 18, 3, 0, 19, 18, 3, 0, 19, 18, 3, 0, 19, 18, 3, 0, 19, 146, 8, 0, 19, 146, 8, 0, 19, 146, 8, 0, 19, 146, 8, 0, 19, 146, 8, 0, 19, 146, 8, 0, 19, 146, 8, 0, 19, 146, 8, 0, 19, 146, 8, 0, 19, 146, 8, 0, 19, 18, 3, 0, 19, 18, 3, 0, 19, 18, 3, 0, 19, 18, 3, 0, 19, 18, 3, 0, 19, 18, 3, 0, 147, 11, 3, 0, 147, 11, 3, 0, + 147, 11, 3, 0, 147, 11, 3, 0, 147, 11, 3, 0, 147, 11, 3, 0, 147, 11, 3, 0, 147, 11, 3, 0, 147, 11, 3, 0, 147, 11, 3, 0, 147, 11, 3, 0, 147, 11, 3, 0, 147, 11, 3, 0, 147, 11, 3, 0, 147, 11, 3, 0, 147, 11, 3, 0, 147, 11, 3, 0, 147, 11, 3, 0, 147, 11, 3, 0, 147, 11, 3, 0, 147, 11, 3, 0, 147, 11, 3, 0, 147, 11, 3, 0, 147, 11, 3, 0, 147, 11, 3, 0, 147, 11, 3, 0, 147, 11, 3, 0, + 147, 11, 3, 0, 147, 11, 3, 0, 147, 11, 3, 0, 147, 11, 3, 0, 147, 11, 3, 0, 147, 11, 3, 0, 148, 11, 3, 0, 148, 11, 3, 0, 148, 11, 3, 0, 148, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 211, 39, 3, 0, 211, 39, 3, 0, 211, 39, 3, 0, 211, 39, 3, 0, 211, 39, 3, 0, 211, 39, 3, 0, 211, 39, 3, 0, 211, 39, 3, 0, + 211, 39, 3, 0, 211, 39, 3, 0, 211, 39, 3, 0, 211, 39, 3, 0, 211, 39, 3, 0, 211, 39, 3, 0, 211, 39, 3, 0, 211, 39, 3, 0, 211, 39, 3, 0, 211, 39, 3, 0, 211, 39, 3, 0, 211, 39, 3, 0, 211, 39, 3, 0, 211, 39, 3, 0, 211, 39, 3, 0, 211, 39, 3, 0, 211, 39, 3, 0, 211, 39, 3, 0, 211, 39, 3, 0, 211, 39, 3, 0, 211, 39, 3, 0, 211, 39, 3, 0, 211, 39, 3, 0, 211, 39, 3, 0, 84, 128, 8, 0, + 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, + 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, + 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 0, 3, 0, 97, 192, 0, 0, 97, 0, 3, 0, 97, 128, 1, 0, 97, 128, 1, 0, 97, 128, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 92, 0, 0, 0, 88, 64, 0, 0, 92, 0, 0, 0, 88, 64, 0, 0, + 92, 0, 0, 0, 88, 64, 0, 0, 92, 0, 0, 0, 88, 64, 0, 0, 92, 0, 0, 0, 88, 64, 0, 0, 92, 0, 0, 0, 88, 64, 0, 0, 92, 0, 0, 0, 88, 64, 0, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, + 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 84, 128, 3, 0, 84, 128, 3, 0, 84, 128, 3, 0, 84, 128, 3, 0, 84, 128, 3, 0, 84, 128, 3, 0, + 84, 128, 3, 0, 84, 128, 3, 0, 84, 128, 3, 0, 84, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, + 97, 128, 3, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 97, 128, 3, 0, 84, 128, 3, 0, 84, 128, 3, 0, 84, 128, 3, 0, 84, 128, 3, 0, 84, 128, 3, 0, 84, 128, 3, 0, 84, 128, 3, 0, 84, 128, 3, 0, 84, 128, 3, 0, 84, 128, 3, 0, 84, 128, 3, 0, 84, 128, 3, 0, 84, 128, 3, 0, 84, 128, 3, 0, 84, 128, 3, 0, + 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 84, 128, 3, 0, 84, 128, 3, 0, 84, 128, 3, 0, 84, 128, 3, 0, 84, 128, 3, 0, 84, 128, 3, 0, 84, 128, 3, 0, 84, 128, 3, 0, + 84, 128, 3, 0, 84, 128, 3, 0, 84, 128, 3, 0, 84, 128, 3, 0, 84, 128, 3, 0, 84, 128, 3, 0, 84, 128, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, + 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 212, 21, 3, 0, 84, 35, 3, 0, 84, 35, 3, 0, 84, 35, 3, 0, 84, 35, 3, 0, 84, 35, 3, 0, 84, 35, 3, 0, 84, 35, 3, 0, 84, 35, 3, 0, 84, 35, 3, 0, 84, 35, 3, 0, 84, 35, 3, 0, + 84, 35, 3, 0, 84, 35, 3, 0, 84, 35, 3, 0, 84, 35, 3, 0, 84, 35, 3, 0, 84, 35, 3, 0, 84, 35, 3, 0, 84, 35, 3, 0, 84, 35, 3, 0, 84, 35, 3, 0, 97, 35, 3, 0, 97, 35, 3, 0, 97, 35, 3, 0, 97, 35, 3, 0, 97, 35, 3, 0, 97, 35, 3, 0, 97, 35, 3, 0, 97, 35, 3, 0, 94, 163, 2, 0, 94, 163, 2, 0, 94, 163, 2, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, + 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, + 84, 0, 3, 0, 84, 0, 3, 0, 84, 0, 3, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 84, 128, 8, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, + 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 101, 64, 4, 0, 101, 64, 4, 0, 101, 64, 4, 0, 101, 64, 4, 0, 101, 64, 4, 0, 101, 64, 4, 0, 101, 64, 4, 0, 101, 0, 1, 0, 101, 64, 4, 0, 101, 64, 4, 0, 101, 64, 4, 0, 66, 0, 5, 0, 130, 64, 5, 0, 130, 192, 7, 0, 66, 64, 5, 0, + 66, 64, 5, 0, 87, 64, 4, 0, 87, 0, 1, 0, 87, 64, 4, 0, 87, 64, 4, 0, 87, 192, 4, 0, 87, 128, 8, 0, 91, 128, 8, 0, 91, 0, 3, 0, 90, 192, 0, 0, 89, 192, 0, 0, 92, 0, 0, 0, 90, 192, 0, 0, 90, 192, 0, 0, 89, 192, 0, 0, 92, 0, 0, 0, 90, 192, 0, 0, 91, 128, 8, 0, 91, 128, 8, 0, 91, 0, 3, 0, 91, 0, 3, 0, 91, 192, 3, 0, 91, 192, 3, 0, 91, 192, 3, 0, 91, 64, 4, 0, + 99, 192, 8, 0, 100, 192, 8, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 101, 0, 1, 0, 91, 128, 2, 0, 91, 128, 2, 0, 91, 128, 2, 0, 91, 128, 2, 0, 91, 128, 2, 0, 91, 128, 2, 0, 91, 128, 2, 0, 91, 128, 2, 0, 91, 0, 3, 0, 90, 192, 0, 0, 89, 192, 0, 0, 91, 128, 8, 0, 91, 64, 1, 0, 91, 64, 1, 0, 91, 0, 3, 0, 86, 0, 3, 0, 86, 0, 3, 0, + 91, 0, 3, 0, 91, 0, 3, 0, 91, 0, 3, 0, 96, 0, 2, 0, 92, 0, 0, 0, 88, 64, 0, 0, 91, 64, 1, 0, 91, 64, 1, 0, 91, 64, 1, 0, 91, 0, 3, 0, 91, 0, 3, 0, 91, 0, 3, 0, 91, 0, 3, 0, 91, 0, 3, 0, 91, 0, 3, 0, 91, 0, 3, 0, 91, 0, 3, 0, 96, 0, 3, 0, 91, 0, 3, 0, 86, 0, 3, 0, 91, 0, 3, 0, 91, 64, 4, 0, 91, 0, 3, 0, 91, 64, 4, 0, 91, 64, 4, 0, + 91, 64, 4, 0, 91, 64, 4, 0, 91, 0, 3, 0, 91, 64, 4, 0, 91, 64, 4, 0, 101, 64, 4, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, + 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 66, 64, 5, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, + 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 4, 64, 8, 0, 5, 64, 10, 0, 5, 64, 10, 0, 5, 64, 10, 0, 5, 64, 10, 0, 5, 64, 10, 0, + 5, 64, 10, 0, 5, 64, 10, 0, 5, 64, 10, 0, 5, 64, 10, 0, 5, 64, 10, 0, 5, 64, 10, 0, 5, 64, 10, 0, 5, 64, 10, 0, 5, 64, 10, 0, 5, 64, 10, 0, 5, 64, 10, 0, 5, 64, 10, 0, 5, 64, 10, 0, 5, 64, 10, 0, 5, 64, 10, 0, 5, 64, 10, 0, 5, 64, 10, 0, 5, 64, 10, 0, 5, 64, 10, 0, 5, 64, 10, 0, 5, 64, 10, 0, 5, 64, 10, 0, 5, 64, 10, 0, 5, 64, 10, 0, 5, 64, 10, 0, + 5, 64, 10, 0, 5, 64, 10, 0, 91, 192, 0, 0, 91, 192, 0, 0, 90, 192, 0, 0, 89, 192, 0, 0, 90, 192, 0, 0, 89, 192, 0, 0, 91, 192, 0, 0, 91, 192, 0, 0, 91, 192, 0, 0, 90, 192, 0, 0, 89, 192, 0, 0, 91, 192, 0, 0, 90, 192, 0, 0, 89, 192, 0, 0, 91, 64, 4, 0, 91, 64, 4, 0, 91, 64, 4, 0, 91, 64, 4, 0, 91, 64, 4, 0, 91, 64, 4, 0, 91, 64, 4, 0, 91, 64, 4, 0, 91, 0, 3, 0, + 87, 64, 4, 0, 91, 0, 0, 0, 91, 64, 4, 0, 87, 0, 3, 0, 91, 0, 3, 0, 90, 192, 0, 0, 89, 192, 0, 0, 91, 0, 3, 0, 91, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 92, 0, 0, 0, 88, 64, 0, 0, 92, 0, 0, 0, 88, 64, 0, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, + 97, 0, 3, 0, 97, 0, 3, 0, 97, 128, 8, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, + 92, 0, 0, 0, 88, 64, 0, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, + 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 92, 0, 0, 0, 88, 64, 0, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, + 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 92, 0, 0, 0, 88, 64, 0, 0, 92, 0, 0, 0, 88, 64, 0, 0, 92, 0, 0, 0, 88, 64, 0, 0, 92, 0, 0, 0, 88, 64, 0, 0, 92, 0, 0, 0, 88, 64, 0, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, + 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 92, 0, 0, 0, 88, 64, 0, 0, 92, 0, 0, 0, 88, 64, 0, 0, 92, 0, 0, 0, 88, 64, 0, 0, 92, 0, 0, 0, 88, 64, 0, 0, 92, 0, 0, 0, 88, 64, 0, 0, 92, 0, 0, 0, 88, 64, 0, 0, 92, 0, 0, 0, 88, 64, 0, 0, + 92, 0, 0, 0, 88, 64, 0, 0, 92, 0, 0, 0, 88, 64, 0, 0, 92, 0, 0, 0, 88, 64, 0, 0, 92, 0, 0, 0, 88, 64, 0, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, + 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 92, 0, 0, 0, 88, 64, 0, 0, 92, 0, 0, 0, 88, 64, 0, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, + 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 92, 0, 0, 0, 88, 64, 0, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 96, 0, 3, 0, + 97, 0, 3, 0, 97, 0, 3, 0, 96, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 96, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, + 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 96, 128, 8, 0, 97, 0, 3, 0, 96, 128, 8, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, + 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 128, 8, 0, 96, 0, 3, 0, 96, 128, 8, 0, + 96, 128, 8, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 128, 8, 0, 96, 128, 8, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 128, 8, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 128, 8, 0, 96, 0, 3, 0, 96, 128, 8, 0, 96, 64, 2, 0, 96, 64, 2, 0, 96, 0, 3, 0, 96, 128, 8, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 128, 8, 0, 96, 0, 3, 0, + 96, 0, 3, 0, 96, 128, 8, 0, 96, 128, 8, 0, 96, 128, 8, 0, 96, 128, 8, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 128, 8, 0, 96, 0, 3, 0, 96, 128, 8, 0, 96, 0, 3, 0, 96, 128, 8, 0, 96, 128, 8, 0, 96, 128, 8, 0, 96, 128, 8, 0, 96, 128, 8, 0, 96, 128, 8, 0, 96, 0, 3, 0, 96, 128, 8, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 128, 8, 0, + 96, 128, 8, 0, 96, 128, 8, 0, 96, 128, 8, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 128, 8, 0, 96, 128, 8, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 128, 8, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 128, 8, 0, 96, 0, 3, 0, + 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 128, 8, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 128, 8, 0, 96, 128, 8, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 128, 8, 0, 96, 128, 8, 0, 96, 128, 8, 0, + 96, 128, 8, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 128, 8, 0, 96, 128, 8, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 128, 8, 0, 96, 128, 8, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, + 96, 0, 3, 0, 96, 0, 3, 0, 96, 128, 8, 0, 96, 128, 8, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 128, 8, 0, 96, 128, 8, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 128, 8, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, + 96, 128, 8, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 128, 8, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, + 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 128, 8, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, + 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 192, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, + 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, + 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 96, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, + 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, + 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, + 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, + 96, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, + 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 0, 3, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 128, 8, 0, + 97, 128, 8, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 128, 8, 0, 96, 128, 8, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 128, 8, 0, 96, 128, 8, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 128, 8, 0, + 97, 0, 3, 0, 97, 0, 3, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, + 97, 128, 8, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 128, 8, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, + 96, 0, 3, 0, 96, 0, 3, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 0, 3, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 0, 3, 0, 97, 128, 8, 0, 97, 128, 3, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 0, 3, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 0, 3, 0, 96, 128, 8, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, + 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 128, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, + 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, 96, 0, 3, 0, + 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 94, 64, 2, 0, 94, 64, 2, 0, 94, 64, 2, 0, 94, 64, 2, 0, 94, 64, 2, 0, 94, 64, 2, 0, + 94, 64, 2, 0, 94, 128, 2, 0, 94, 64, 2, 0, 94, 64, 2, 0, 94, 64, 2, 0, 94, 64, 2, 0, 94, 64, 2, 0, 94, 64, 2, 0, 94, 64, 2, 0, 94, 64, 2, 0, 94, 64, 2, 0, 94, 64, 2, 0, 94, 64, 2, 0, 94, 64, 2, 0, 94, 64, 2, 0, 94, 64, 2, 0, 94, 128, 2, 0, 94, 64, 2, 0, 94, 64, 2, 0, 94, 64, 2, 0, 94, 64, 2, 0, 94, 128, 2, 0, 94, 64, 2, 0, 94, 64, 2, 0, 94, 128, 2, 0, + 94, 64, 2, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, + 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 95, 128, 7, 0, 95, 128, 7, 0, 95, 128, 7, 0, 95, 128, 7, 0, 95, 128, 7, 0, 97, 16, 3, 0, 97, 16, 3, 0, 97, 16, 3, 0, 97, 16, 3, 0, 97, 16, 3, 0, 97, 16, 3, 0, 97, 16, 3, 0, 97, 16, 3, 0, 97, 16, 3, 0, 97, 16, 3, 0, 97, 16, 3, 0, 97, 16, 3, 0, 97, 16, 3, 0, 97, 16, 3, 0, 97, 16, 3, 0, 97, 16, 3, 0, 97, 16, 3, 0, + 97, 16, 3, 0, 97, 16, 3, 0, 97, 16, 3, 0, 97, 16, 3, 0, 97, 16, 3, 0, 97, 16, 3, 0, 97, 16, 3, 0, 97, 16, 3, 0, 97, 16, 3, 0, 97, 16, 3, 0, 97, 16, 3, 0, 97, 16, 3, 0, 97, 16, 3, 0, 97, 16, 3, 0, 97, 16, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, + 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, + 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, + 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, + 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, + 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, + 97, 128, 3, 0, 97, 0, 3, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 128, 8, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 3, 0, 97, 0, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, + 97, 128, 3, 0, 97, 64, 7, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, + 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 128, 8, 0, 97, 0, 3, 0, 97, 128, 8, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, + 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, + 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, + 97, 0, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 3, 0, 97, 0, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 8, 0, 97, 128, 3, 0, 97, 128, 3, 0, + 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 3, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 0, 3, 0, 97, 128, 8, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 3, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, + 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 8, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 64, 7, 0, 97, 128, 3, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, + 97, 0, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, + 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 128, 8, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 192, 0, 0, 97, 192, 0, 0, 97, 192, 0, 0, 97, 192, 0, 0, 97, 192, 0, 0, 161, 4, 3, 0, 161, 4, 3, 0, 161, 4, 3, 0, 161, 4, 3, 0, 161, 4, 3, 0, 161, 4, 3, 0, 161, 4, 3, 0, 161, 4, 3, 0, 161, 4, 3, 0, + 161, 4, 3, 0, 161, 4, 3, 0, 161, 4, 3, 0, 161, 4, 3, 0, 161, 4, 3, 0, 161, 4, 3, 0, 161, 4, 3, 0, 161, 4, 3, 0, 161, 4, 3, 0, 161, 4, 3, 0, 161, 4, 3, 0, 161, 4, 3, 0, 161, 4, 3, 0, 161, 4, 3, 0, 161, 4, 3, 0, 161, 4, 3, 0, 161, 4, 3, 0, 161, 4, 3, 0, 161, 4, 3, 0, 161, 4, 3, 0, 161, 4, 3, 0, 161, 4, 3, 0, 161, 4, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, + 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, + 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 161, 140, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, + 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, + 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 140, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, + 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, + 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 97, 128, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, + 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 225, 143, 3, 0, 97, 128, 3, 0, + 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, + 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, 97, 168, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, + 161, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 161, 11, 3, 0, 33, 31, 3, 0, 33, 31, 3, 0, 33, 31, 3, 0, 33, 31, 3, 0, + 33, 31, 3, 0, 33, 31, 3, 0, 33, 31, 3, 0, 33, 31, 3, 0, 33, 31, 3, 0, 33, 31, 3, 0, 33, 31, 3, 0, 33, 31, 3, 0, 33, 31, 3, 0, 33, 31, 3, 0, 33, 31, 3, 0, 33, 31, 3, 0, 33, 31, 3, 0, 33, 31, 3, 0, 33, 31, 3, 0, 33, 31, 3, 0, 33, 31, 3, 0, 33, 31, 3, 0, 33, 31, 3, 0, 33, 31, 3, 0, 33, 31, 3, 0, 33, 31, 3, 0, 33, 31, 3, 0, 33, 31, 3, 0, 33, 31, 3, 0, + 33, 31, 3, 0, 33, 31, 3, 0, 33, 31, 3, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, + 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, + 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 8, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 64, 7, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, + 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, + 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 0, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, + 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 64, 7, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, + 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, + 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, + 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 64, 7, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 128, 3, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 128, 3, 0, 97, 128, 3, 0, + 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 64, 7, 0, 97, 128, 3, 0, 97, 64, 7, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 0, 3, 0, 97, 128, 3, 0, 97, 0, 3, 0, + 97, 128, 3, 0, 97, 0, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 64, 7, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 0, 3, 0, 97, 128, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, + 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, + 97, 128, 3, 0, 97, 128, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, + 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, + 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 64, 7, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, + 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 64, 7, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, + 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, + 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 128, 3, 0, + 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, + 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 192, 0, 0, 97, 192, 0, 0, 97, 192, 0, 0, 97, 64, 1, 0, 97, 64, 1, 0, 97, 64, 1, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 128, 3, 0, + 97, 128, 3, 0, 97, 128, 3, 0, 97, 64, 7, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, + 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 0, 3, 0, 97, 64, 7, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 64, 7, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, + 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 64, 7, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, + 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, + 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 64, 7, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, + 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 128, 3, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 128, 3, 0, 97, 64, 7, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, + 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 128, 3, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 128, 3, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, 97, 64, 7, 0, + 97, 64, 7, 0, 97, 64, 7, 0, 97, 128, 3, 0, 97, 128, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }; } } diff --git a/src/Avalonia.Base/Media/TextFormatting/Unicode/UnicodeTrie.cs b/src/Avalonia.Base/Media/TextFormatting/Unicode/UnicodeTrie.cs index 08b019ed33..cf03ed7cd3 100644 --- a/src/Avalonia.Base/Media/TextFormatting/Unicode/UnicodeTrie.cs +++ b/src/Avalonia.Base/Media/TextFormatting/Unicode/UnicodeTrie.cs @@ -15,92 +15,119 @@ // Ported from: https://github.com/foliojs/unicode-trie // Copied from: https://github.com/toptensoftware/RichTextKit +using System; using System.IO; -using System.IO.Compression; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using System.Text; namespace Avalonia.Media.TextFormatting.Unicode { internal class UnicodeTrie { - private readonly int[] _data; + private readonly uint[] _data; private readonly int _highStart; private readonly uint _errorValue; + /// + /// Initializes a new instance of the class. + /// + /// The uncompressed trie data. + public UnicodeTrie(ReadOnlySpan rawData) + { + var header = UnicodeTrieHeader.Parse(rawData); + int length = header.DataLength; + uint[] data = new uint[length / sizeof(uint)]; + + MemoryMarshal.Cast(rawData.Slice(rawData.Length - length)) + .CopyTo(data); + + _highStart = header.HighStart; + _errorValue = header.ErrorValue; + _data = data; + } + + /// + /// Initializes a new instance of the class. + /// + /// The stream containing the data. public UnicodeTrie(Stream stream) { - int dataLength; - using (var bw = new BinaryReader(stream, Encoding.UTF8, true)) + // Read the header info + using (var br = new BinaryReader(stream, Encoding.UTF8, true)) { - _highStart = bw.ReadInt32BE(); - _errorValue = bw.ReadUInt32BE(); - dataLength = bw.ReadInt32BE() / 4; + _highStart = br.ReadInt32(); + _errorValue = br.ReadUInt32(); + _data = new uint[br.ReadInt32() / sizeof(uint)]; } - using (var infl1 = new DeflateStream(stream, CompressionMode.Decompress, true)) - using (var infl2 = new DeflateStream(infl1, CompressionMode.Decompress, true)) - using (var bw = new BinaryReader(infl2, Encoding.UTF8, true)) + // Read the data in compressed format. + using (var br = new BinaryReader(stream, Encoding.UTF8, true)) { - _data = new int[dataLength]; for (int i = 0; i < _data.Length; i++) { - _data[i] = bw.ReadInt32(); + _data[i] = br.ReadUInt32(); } } } - public UnicodeTrie(byte[] buf) : this(new MemoryStream(buf)) - { - } - - internal UnicodeTrie(int[] data, int highStart, uint errorValue) + /// + /// Initializes a new instance of the class. + /// + /// The uncompressed trie data. + /// The start of the last range which ends at U+10ffff. + /// The value for out-of-range code points and illegal UTF-8. + public UnicodeTrie(uint[] data, int highStart, uint errorValue) { _data = data; _highStart = highStart; _errorValue = errorValue; } + /// + /// Saves the to the stream in a compressed format. + /// + /// The output stream. internal void Save(Stream stream) { // Write the header info using (var bw = new BinaryWriter(stream, Encoding.UTF8, true)) { - bw.WriteBE(_highStart); - bw.WriteBE(_errorValue); - bw.WriteBE(_data.Length * 4); + bw.Write(_highStart); + bw.Write(_errorValue); + bw.Write(_data.Length * sizeof(uint)); } - // Double compress the data - using (var def1 = new DeflateStream(stream, CompressionLevel.Optimal, true)) - using (var def2 = new DeflateStream(def1, CompressionLevel.Optimal, true)) - using (var bw = new BinaryWriter(def2, Encoding.UTF8, true)) + // Write the data. + using (var bw = new BinaryWriter(stream, Encoding.UTF8, true)) { - foreach (var v in _data) + for (int i = 0; i < _data.Length; i++) { - bw.Write(v); + bw.Write(_data[i]); } - bw.Flush(); - def2.Flush(); - def1.Flush(); } } - public uint Get(int codePoint) + /// + /// Get the value for a code point as stored in the trie. + /// + /// The code point. + /// The value. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public uint Get(uint codePoint) { - int index; - if ((codePoint < 0) || (codePoint > 0x10ffff)) - { - return _errorValue; - } + uint index; + ref uint dataBase = ref MemoryMarshal.GetReference(_data.AsSpan()); - if ((codePoint < 0xd800) || ((codePoint > 0xdbff) && (codePoint <= 0xffff))) + if (codePoint is < 0x0d800 or (> 0x0dbff and <= 0x0ffff)) { // Ordinary BMP code point, excluding leading surrogates. - // BMP uses a single level lookup. BMP index starts at offset 0 in the index. - // data is stored in the index array itself. - index = (_data[codePoint >> UnicodeTrieBuilder.SHIFT_2] << UnicodeTrieBuilder.INDEX_SHIFT) + (codePoint & UnicodeTrieBuilder.DATA_MASK); - return (uint)_data[index]; + // BMP uses a single level lookup. BMP index starts at offset 0 in the Trie2 index. + // 16 bit data is stored in the index array itself. + index = _data[codePoint >> UnicodeTrieBuilder.SHIFT_2]; + index = (index << UnicodeTrieBuilder.INDEX_SHIFT) + (codePoint & UnicodeTrieBuilder.DATA_MASK); + return Unsafe.Add(ref dataBase, (nint)index); } if (codePoint <= 0xffff) @@ -109,20 +136,57 @@ namespace Avalonia.Media.TextFormatting.Unicode // lead surrogate code units and code points. // The main index has the code unit data. // For this function, we need the code point data. - index = (_data[UnicodeTrieBuilder.LSCP_INDEX_2_OFFSET + ((codePoint - 0xd800) >> UnicodeTrieBuilder.SHIFT_2)] << UnicodeTrieBuilder.INDEX_SHIFT) + (codePoint & UnicodeTrieBuilder.DATA_MASK); - return (uint)_data[index]; + // Note: this expression could be refactored for slightly improved efficiency, but + // surrogate code points will be so rare in practice that it's not worth it. + index = _data[UnicodeTrieBuilder.LSCP_INDEX_2_OFFSET + ((codePoint - 0xd800) >> UnicodeTrieBuilder.SHIFT_2)]; + index = (index << UnicodeTrieBuilder.INDEX_SHIFT) + (codePoint & UnicodeTrieBuilder.DATA_MASK); + return Unsafe.Add(ref dataBase, (nint)index); } if (codePoint < _highStart) { // Supplemental code point, use two-level lookup. - index = _data[(UnicodeTrieBuilder.INDEX_1_OFFSET - UnicodeTrieBuilder.OMITTED_BMP_INDEX_1_LENGTH) + (codePoint >> UnicodeTrieBuilder.SHIFT_1)]; - index = _data[index + ((codePoint >> UnicodeTrieBuilder.SHIFT_2) & UnicodeTrieBuilder.INDEX_2_MASK)]; + index = UnicodeTrieBuilder.INDEX_1_OFFSET - UnicodeTrieBuilder.OMITTED_BMP_INDEX_1_LENGTH + (codePoint >> UnicodeTrieBuilder.SHIFT_1); + index = _data[index]; + index += (codePoint >> UnicodeTrieBuilder.SHIFT_2) & UnicodeTrieBuilder.INDEX_2_MASK; + index = _data[index]; index = (index << UnicodeTrieBuilder.INDEX_SHIFT) + (codePoint & UnicodeTrieBuilder.DATA_MASK); - return (uint)_data[index]; + return Unsafe.Add(ref dataBase, (nint)index); + } + + if (codePoint <= 0x10ffff) + { + return Unsafe.Add(ref dataBase, (nint)(_data.Length - UnicodeTrieBuilder.DATA_GRANULARITY)); + } + + // Fall through. The code point is outside of the legal range of 0..0x10ffff. + return _errorValue; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + private struct UnicodeTrieHeader + { + public int HighStart + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get; + } + + public uint ErrorValue + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get; + } + + public int DataLength + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get; } - return (uint)_data[_data.Length - UnicodeTrieBuilder.DATA_GRANULARITY]; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static UnicodeTrieHeader Parse(ReadOnlySpan data) + => MemoryMarshal.Cast(data)[0]; } } } diff --git a/src/Avalonia.Base/Media/TextFormatting/Unicode/UnicodeTrieBuilder.cs b/src/Avalonia.Base/Media/TextFormatting/Unicode/UnicodeTrieBuilder.cs index a60bac4ce4..87f96984c5 100644 --- a/src/Avalonia.Base/Media/TextFormatting/Unicode/UnicodeTrieBuilder.cs +++ b/src/Avalonia.Base/Media/TextFormatting/Unicode/UnicodeTrieBuilder.cs @@ -368,24 +368,24 @@ namespace Avalonia.Media.TextFormatting.Unicode // calculate the sizes of, and allocate, the index and data arrays var indexLength = allIndexesLength + _dataLength; - var data = new int[indexLength]; + var data = new uint[indexLength]; // write the index-2 array values shifted right by INDEX_SHIFT, after adding dataMove var destIdx = 0; for (i = 0; i < INDEX_2_BMP_LENGTH; i++) { - data[destIdx++] = ((_index2[i] + dataMove) >> INDEX_SHIFT); + data[destIdx++] = (uint)((_index2[i] + dataMove) >> INDEX_SHIFT); } // write UTF-8 2-byte index-2 values, not right-shifted for (i = 0; i < 0xc2 - 0xc0; i++) { // C0..C1 - data[destIdx++] = (dataMove + BAD_UTF8_DATA_OFFSET); + data[destIdx++] = (uint)(dataMove + BAD_UTF8_DATA_OFFSET); } for (; i < 0xe0 - 0xc0; i++) { // C2..DF - data[destIdx++] = (dataMove + _index2[i << (6 - SHIFT_2)]); + data[destIdx++] = (uint)(dataMove + _index2[i << (6 - SHIFT_2)]); } if (_highStart > 0x10000) @@ -396,21 +396,21 @@ namespace Avalonia.Media.TextFormatting.Unicode // write 16-bit index-1 values for supplementary code points for (i = 0; i < index1Length; i++) { - data[destIdx++] = (INDEX_2_OFFSET + _index1[i + OMITTED_BMP_INDEX_1_LENGTH]); + data[destIdx++] = (uint)(INDEX_2_OFFSET + _index1[i + OMITTED_BMP_INDEX_1_LENGTH]); } // write the index-2 array values for supplementary code points, // shifted right by INDEX_SHIFT, after adding dataMove for (i = 0; i < _index2Length - index2Offset; i++) { - data[destIdx++] = ((dataMove + _index2[index2Offset + i]) >> INDEX_SHIFT); + data[destIdx++] = (uint)((dataMove + _index2[index2Offset + i]) >> INDEX_SHIFT); } } // write 16-bit data values for (i = 0; i < _dataLength; i++) { - data[destIdx++] = (int)_data[i]; + data[destIdx++] = _data[i]; } return new UnicodeTrie(data, _highStart, _errorValue); diff --git a/src/Avalonia.Base/Utilities/ArrayBuilder.cs b/src/Avalonia.Base/Utilities/ArrayBuilder.cs index 7048659431..60bf2c7586 100644 --- a/src/Avalonia.Base/Utilities/ArrayBuilder.cs +++ b/src/Avalonia.Base/Utilities/ArrayBuilder.cs @@ -101,7 +101,7 @@ namespace Avalonia.Utilities /// /// The array slice. /// The . - public ArraySlice Add(in ReadOnlySlice value) + public ArraySlice Add(in ArraySlice value) { var position = _size; diff --git a/src/Avalonia.Base/Utilities/ArraySlice.cs b/src/Avalonia.Base/Utilities/ArraySlice.cs index f5a9d3a98d..482f807fe0 100644 --- a/src/Avalonia.Base/Utilities/ArraySlice.cs +++ b/src/Avalonia.Base/Utilities/ArraySlice.cs @@ -116,7 +116,7 @@ namespace Avalonia.Utilities /// public static implicit operator ReadOnlySlice(ArraySlice slice) { - return new ReadOnlySlice(slice._data).AsSlice(slice.Start, slice.Length); + return new ReadOnlySlice(slice._data, 0, slice.Length, slice.Start); } /// diff --git a/src/Avalonia.Base/Utilities/BidiDictionary.cs b/src/Avalonia.Base/Utilities/BidiDictionary.cs new file mode 100644 index 0000000000..654fbc9807 --- /dev/null +++ b/src/Avalonia.Base/Utilities/BidiDictionary.cs @@ -0,0 +1,40 @@ +using System.Collections.Generic; + +namespace Avalonia.Utilities +{ + /// + /// A simple bi-directional dictionary. + /// + /// Key type + /// Value type + internal sealed class BidiDictionary where T1 : notnull where T2 : notnull + { + public Dictionary Forward { get; } = new Dictionary(); + + public Dictionary Reverse { get; } = new Dictionary(); + + public void Clear() + { + Forward.Clear(); + Reverse.Clear(); + } + + public void Add(T1 key, T2 value) + { + Forward.Add(key, value); + Reverse.Add(value, key); + } + +#pragma warning disable CS8601 + public bool TryGetValue(T1 key, out T2 value) => Forward.TryGetValue(key, out value); +#pragma warning restore CS8601 + +#pragma warning disable CS8601 + public bool TryGetKey(T2 value, out T1 key) => Reverse.TryGetValue(value, out key); +#pragma warning restore CS8601 + + public bool ContainsKey(T1 key) => Forward.ContainsKey(key); + + public bool ContainsValue(T2 value) => Reverse.ContainsKey(value); + } +} diff --git a/src/Skia/Avalonia.Skia/TextShaperImpl.cs b/src/Skia/Avalonia.Skia/TextShaperImpl.cs index 777e907617..6b0b7bccbb 100644 --- a/src/Skia/Avalonia.Skia/TextShaperImpl.cs +++ b/src/Skia/Avalonia.Skia/TextShaperImpl.cs @@ -85,7 +85,7 @@ namespace Avalonia.Skia var second = glyphInfos[length - 1]; - if (!new Codepoint((int)second.Codepoint).IsBreakChar) + if (!new Codepoint(second.Codepoint).IsBreakChar) { return; } diff --git a/src/Windows/Avalonia.Direct2D1/Media/TextShaperImpl.cs b/src/Windows/Avalonia.Direct2D1/Media/TextShaperImpl.cs index 6e32d32913..435c7cd89a 100644 --- a/src/Windows/Avalonia.Direct2D1/Media/TextShaperImpl.cs +++ b/src/Windows/Avalonia.Direct2D1/Media/TextShaperImpl.cs @@ -85,7 +85,7 @@ namespace Avalonia.Direct2D1.Media var second = glyphInfos[length - 1]; - if (!new Codepoint((int)second.Codepoint).IsBreakChar) + if (!new Codepoint(second.Codepoint).IsBreakChar) { return; } diff --git a/tests/Avalonia.Base.UnitTests/Media/TextFormatting/BiDiAlgorithmTests.cs b/tests/Avalonia.Base.UnitTests/Media/TextFormatting/BiDiAlgorithmTests.cs index f8a2abc716..5ff2c0e07b 100644 --- a/tests/Avalonia.Base.UnitTests/Media/TextFormatting/BiDiAlgorithmTests.cs +++ b/tests/Avalonia.Base.UnitTests/Media/TextFormatting/BiDiAlgorithmTests.cs @@ -27,7 +27,7 @@ namespace Avalonia.Visuals.UnitTests.Media.TextFormatting private bool Run(BiDiTestData testData) { - var bidi = BidiAlgorithm.Instance.Value; + var bidi = new BidiAlgorithm(); // Run the algorithm... ArraySlice resultLevels; diff --git a/tests/Avalonia.Base.UnitTests/Media/TextFormatting/BiDiClassTests.cs b/tests/Avalonia.Base.UnitTests/Media/TextFormatting/BiDiClassTests.cs index 1ed33e6132..d2cea45ce1 100644 --- a/tests/Avalonia.Base.UnitTests/Media/TextFormatting/BiDiClassTests.cs +++ b/tests/Avalonia.Base.UnitTests/Media/TextFormatting/BiDiClassTests.cs @@ -30,7 +30,7 @@ namespace Avalonia.Visuals.UnitTests.Media.TextFormatting private bool Run(BiDiClassData t) { - var bidi = BidiAlgorithm.Instance.Value; + var bidi = new BidiAlgorithm(); var bidiData = new BidiData(t.ParagraphLevel); var text = Encoding.UTF32.GetString(MemoryMarshal.Cast(t.CodePoints).ToArray()); @@ -39,9 +39,12 @@ namespace Avalonia.Visuals.UnitTests.Media.TextFormatting bidiData.Append(text.AsMemory()); // Act - bidi.Process(bidiData); + for (int i = 0; i < 10; i++) + { + bidi.Process(bidiData); + } - var resultLevels = bidi.ResolvedLevels; + var resultLevels = bidi.ResolvedLevels; var resultParagraphLevel = bidi.ResolvedParagraphEmbeddingLevel; // Assert diff --git a/tests/Avalonia.Base.UnitTests/Media/TextFormatting/BiDiTestDataGenerator.cs b/tests/Avalonia.Base.UnitTests/Media/TextFormatting/BiDiTestDataGenerator.cs index 033e0e2242..3c5a966eb7 100644 --- a/tests/Avalonia.Base.UnitTests/Media/TextFormatting/BiDiTestDataGenerator.cs +++ b/tests/Avalonia.Base.UnitTests/Media/TextFormatting/BiDiTestDataGenerator.cs @@ -129,6 +129,8 @@ namespace Avalonia.Visuals.UnitTests.Media.TextFormatting ParagraphEmbeddingLevel = paragraphEmbeddingLevel, Levels = levels }); + + break; } } } diff --git a/tests/Avalonia.Base.UnitTests/Media/TextFormatting/GraphemeBreakClassTrieGenerator.cs b/tests/Avalonia.Base.UnitTests/Media/TextFormatting/GraphemeBreakClassTrieGenerator.cs index 4d1941f7c5..1a8d41caa4 100644 --- a/tests/Avalonia.Base.UnitTests/Media/TextFormatting/GraphemeBreakClassTrieGenerator.cs +++ b/tests/Avalonia.Base.UnitTests/Media/TextFormatting/GraphemeBreakClassTrieGenerator.cs @@ -19,11 +19,6 @@ namespace Avalonia.Base.UnitTests.Media.TextFormatting var trie = GenerateBreakTypeTrie(); UnicodeDataGenerator.GenerateTrieClass("GraphemeBreak", trie); - - using (var stream = File.Create("Generated\\GraphemeBreak.trie")) - { - trie.Save(stream); - } } private static UnicodeTrie GenerateBreakTypeTrie() @@ -38,9 +33,9 @@ namespace Avalonia.Base.UnitTests.Media.TextFormatting { foreach (var (start, end, graphemeBreakType) in breakData) { - if (!Enum.TryParse(graphemeBreakType, out var value)) + if (!Enum.TryParse(graphemeBreakType.Replace("_", ""), out var value)) { - continue; + continue; } if (start == end) diff --git a/tests/Avalonia.Base.UnitTests/Media/TextFormatting/GraphemeBreakClassTrieGeneratorTests.cs b/tests/Avalonia.Base.UnitTests/Media/TextFormatting/GraphemeBreakClassTrieGeneratorTests.cs index e1e3e14ea7..c9f869cea9 100644 --- a/tests/Avalonia.Base.UnitTests/Media/TextFormatting/GraphemeBreakClassTrieGeneratorTests.cs +++ b/tests/Avalonia.Base.UnitTests/Media/TextFormatting/GraphemeBreakClassTrieGeneratorTests.cs @@ -1,6 +1,10 @@ using System; +using System.Runtime.InteropServices; +using System.Text; using Avalonia.Media.TextFormatting.Unicode; +using Avalonia.Visuals.UnitTests.Media.TextFormatting; using Xunit; +using Xunit.Abstractions; namespace Avalonia.Base.UnitTests.Media.TextFormatting { @@ -10,20 +14,74 @@ namespace Avalonia.Base.UnitTests.Media.TextFormatting /// public class GraphemeBreakClassTrieGeneratorTests { - [Theory(Skip = "Only run when we update the trie.")] - [ClassData(typeof(GraphemeBreakTestDataGenerator))] - public void Should_Enumerate(string text, int expectedLength) + private readonly ITestOutputHelper _outputHelper; + + public GraphemeBreakClassTrieGeneratorTests(ITestOutputHelper outputHelper) { - var textMemory = text.AsMemory(); + _outputHelper = outputHelper; + } - var enumerator = new GraphemeEnumerator(textMemory); + [Fact(/*Skip = "Only run when we update the trie."*/)] + public void Should_Enumerate() + { + var generator = new GraphemeBreakTestDataGenerator(); - Assert.True(enumerator.MoveNext()); + foreach (var testData in generator) + { + Assert.True(Run(testData)); + } + } - Assert.Equal(expectedLength, enumerator.Current.Text.Length); + private bool Run(GraphemeBreakData t) + { + var text = Encoding.UTF32.GetString(MemoryMarshal.Cast(t.Codepoints).ToArray()); + var grapheme = Encoding.UTF32.GetString(MemoryMarshal.Cast(t.Grapheme).ToArray()).AsSpan(); + + var enumerator = new GraphemeEnumerator(text.AsMemory()); + + enumerator.MoveNext(); + + var actual = enumerator.Current.Text.Span; + + var pass = true; + + if(actual.Length != grapheme.Length) + { + pass = false; + } + + if (pass) + { + for (int i = 0; i < grapheme.Length; i++) + { + var a = grapheme[i]; + var b = actual[i]; + + if (a != b) + { + pass = false; + + break; + } + } + } + + if (!pass) + { + _outputHelper.WriteLine($"Failed line {t.LineNumber}"); + _outputHelper.WriteLine($" Text: {text}"); + _outputHelper.WriteLine($" Codepoints: {string.Join(" ", t.Codepoints)}"); + _outputHelper.WriteLine($" Grapheme: {string.Join(" ", t.Grapheme)}"); + _outputHelper.WriteLine($" Line: {t.Line}"); + + return false; + } + + + return true; } - [Fact(Skip = "Only run when we update the trie.")] + [Fact(/*Skip = "Only run when we update the trie."*/)] public void Should_Enumerate_Other() { const string text = "ABCDEFGHIJ"; @@ -44,18 +102,10 @@ namespace Avalonia.Base.UnitTests.Media.TextFormatting Assert.Equal(10, count); } - [Fact(Skip = "Only run when we update the trie.")] + [Fact(/*Skip = "Only run when we update the trie."*/)] public void Should_Generate_Trie() { GraphemeBreakClassTrieGenerator.Execute(); } - - private class GraphemeBreakTestDataGenerator : TestDataGenerator - { - public GraphemeBreakTestDataGenerator() - : base("auxiliary/GraphemeBreakTest.txt") - { - } - } } } diff --git a/tests/Avalonia.Base.UnitTests/Media/TextFormatting/GraphemeBreakTestDataGenerator.cs b/tests/Avalonia.Base.UnitTests/Media/TextFormatting/GraphemeBreakTestDataGenerator.cs new file mode 100644 index 0000000000..f6616d74a2 --- /dev/null +++ b/tests/Avalonia.Base.UnitTests/Media/TextFormatting/GraphemeBreakTestDataGenerator.cs @@ -0,0 +1,108 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.Http; +using Avalonia.Base.UnitTests.Media.TextFormatting; + +namespace Avalonia.Visuals.UnitTests.Media.TextFormatting +{ + internal class GraphemeBreakTestDataGenerator : IEnumerable + { + private readonly List _testData; + + public GraphemeBreakTestDataGenerator() + { + _testData = ReadData(); + } + + public IEnumerator GetEnumerator() + { + return _testData.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + private static List ReadData() + { + var testData = new List(); + + var url = Path.Combine(UnicodeDataGenerator.Ucd, "auxiliary/GraphemeBreakTest.txt"); + + using (var client = new HttpClient()) + using (var result = client.GetAsync(url).GetAwaiter().GetResult()) + { + if (!result.IsSuccessStatusCode) + { + return testData; + } + + using (var stream = result.Content.ReadAsStreamAsync().GetAwaiter().GetResult()) + using (var reader = new StreamReader(stream)) + { + var lineNumber = 0; + + while (!reader.EndOfStream) + { + var line = reader.ReadLine(); + + lineNumber++; + + if (line == null) + { + break; + } + + if (line.StartsWith("#") || string.IsNullOrEmpty(line)) + { + continue; + } + + var elements = line.Split('#'); + + elements = elements[0].Replace("÷\t", "÷").Trim('÷').Split('÷'); + + var graphemeChars = elements[0].Replace(" × ", " ").Split(' '); + + var codepoints = graphemeChars.Where(x => x != "" && x != "×") + .Select(x => Convert.ToInt32(x, 16)).ToList(); + + var grapheme = codepoints.ToArray(); + + if(elements.Length > 1) + { + var remainingChars = elements[1].Replace(" × ", " ").Split(' '); + + var remaining = remainingChars.Where(x => x != "" && x != "×").Select(x => Convert.ToInt32(x, 16)).ToArray(); + + codepoints.AddRange(remaining); + } + + var data = new GraphemeBreakData + { + Line = line, + LineNumber = lineNumber, + Grapheme = grapheme, + Codepoints = codepoints.ToArray() + }; + + testData.Add(data); + } + } + } + return testData; + } + } + + internal struct GraphemeBreakData + { + public string Line { get; set; } + public int LineNumber { get; set; } + public int[] Grapheme { get; set; } + public int[] Codepoints{ get; set; } + } +} diff --git a/tests/Avalonia.Base.UnitTests/Media/TextFormatting/LineBreakEnumuratorTests.cs b/tests/Avalonia.Base.UnitTests/Media/TextFormatting/LineBreakEnumuratorTests.cs index 1dbfbe4d24..15be1200c8 100644 --- a/tests/Avalonia.Base.UnitTests/Media/TextFormatting/LineBreakEnumuratorTests.cs +++ b/tests/Avalonia.Base.UnitTests/Media/TextFormatting/LineBreakEnumuratorTests.cs @@ -134,7 +134,7 @@ namespace Avalonia.Base.UnitTests.Media.TextFormatting _outputHelper.WriteLine($"Expected Breaks: {string.Join(" ", breakPoints)}"); _outputHelper.WriteLine($" Actual Breaks: {string.Join(" ", foundBreaks)}"); _outputHelper.WriteLine($" Text: {text}"); - _outputHelper.WriteLine($" Char Props: {string.Join(" ", codePoints.Select(x => new Codepoint(x).LineBreakClass))}"); + _outputHelper.WriteLine($" Char Props: {string.Join(" ", codePoints.Select(x => new Codepoint((uint)x).LineBreakClass))}"); _outputHelper.WriteLine(""); } diff --git a/tests/Avalonia.Base.UnitTests/Media/TextFormatting/TestDataGenerator.cs b/tests/Avalonia.Base.UnitTests/Media/TextFormatting/TestDataGenerator.cs deleted file mode 100644 index 33b4c8a269..0000000000 --- a/tests/Avalonia.Base.UnitTests/Media/TextFormatting/TestDataGenerator.cs +++ /dev/null @@ -1,85 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net.Http; - -namespace Avalonia.Base.UnitTests.Media.TextFormatting -{ - public abstract class TestDataGenerator : IEnumerable - { - private readonly string _fileName; - private readonly List _testData; - - protected TestDataGenerator(string fileName) - { - _fileName = fileName; - _testData = ReadTestData(); - } - - public IEnumerator GetEnumerator() - { - return _testData.GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - - private List ReadTestData() - { - var testData = new List(); - - using (var client = new HttpClient()) - { - var url = Path.Combine(UnicodeDataGenerator.Ucd, _fileName); - - using (var result = client.GetAsync(url).GetAwaiter().GetResult()) - { - if (!result.IsSuccessStatusCode) - return testData; - - using (var stream = result.Content.ReadAsStreamAsync().GetAwaiter().GetResult()) - using (var reader = new StreamReader(stream)) - { - while (!reader.EndOfStream) - { - var line = reader.ReadLine(); - - if (line == null) - { - break; - } - - if (line.StartsWith("#") || string.IsNullOrEmpty(line)) - { - continue; - } - - var elements = line.Split('#'); - - elements = elements[0].Replace("÷\t", "÷").Trim('÷').Split('÷'); - - var chars = elements[0].Replace(" × ", " ").Split(' '); - - var codepoints = chars.Where(x => x != "" && x != "×") - .Select(x => Convert.ToInt32(x, 16)).ToArray(); - - var text = string.Join(null, codepoints.Select(char.ConvertFromUtf32)); - - var length = codepoints.Select(x => x > ushort.MaxValue ? 2 : 1).Sum(); - - var data = new object[] { text, length }; - - testData.Add(data); - } - } - } - } - - return testData; - } - } -} diff --git a/tests/Avalonia.Base.UnitTests/Media/TextFormatting/UnicodeDataGenerator.cs b/tests/Avalonia.Base.UnitTests/Media/TextFormatting/UnicodeDataGenerator.cs index ab6b06c200..a49c8ffa2a 100644 --- a/tests/Avalonia.Base.UnitTests/Media/TextFormatting/UnicodeDataGenerator.cs +++ b/tests/Avalonia.Base.UnitTests/Media/TextFormatting/UnicodeDataGenerator.cs @@ -10,22 +10,22 @@ namespace Avalonia.Base.UnitTests.Media.TextFormatting { internal static class UnicodeDataGenerator { - public const string Ucd = "https://www.unicode.org/Public/13.0.0/ucd/"; + public const string Ucd = "https://www.unicode.org/Public/14.0.0/ucd/"; - public static UnicodeTrie GenerateBiDiTrie(out BiDiDataEntries biDiDataEntries,out Dictionary biDiData) + public static UnicodeTrie GenerateBiDiTrie(out BiDiDataEntries biDiDataEntries, out Dictionary biDiData) { biDiData = new Dictionary(); - var biDiClassEntries = - UnicodeEnumsGenerator.CreateBiDiClassEnum(); + var bidiClassEntries = + UnicodeEnumsGenerator.CreateBidiClassEnum(); - var biDiClassMappings = CreateTagToIndexMappings(biDiClassEntries); + var bidiClassMappings = CreateTagToIndexMappings(bidiClassEntries); - var biDiClassData = ReadBiDiData(); + var bidiClassData = ReadBiDiData(); - foreach (var (range, name) in biDiClassData) + foreach (var (range, name) in bidiClassData) { - var biDiClass = biDiClassMappings[name]; + var biDiClass = bidiClassMappings[name]; AddBiDiClassRange(biDiData, range, biDiClass); } @@ -56,19 +56,14 @@ namespace Avalonia.Base.UnitTests.Media.TextFormatting biDiDataEntries = new BiDiDataEntries() { - PairedBracketTypes = biDiPairedBracketTypeEntries, BiDiClasses = biDiClassEntries + PairedBracketTypes = biDiPairedBracketTypeEntries, BiDiClasses = bidiClassEntries }; var trie = biDiTrieBuilder.Freeze(); - GenerateTrieClass("BiDi", trie); - - using (var stream = File.Create("Generated\\BiDi.trie")) - { - trie.Save(stream); + GenerateTrieClass("Bidi", trie); - return trie; - } + return trie; } public static void GenerateTrieClass(string name, UnicodeTrie trie) @@ -92,6 +87,8 @@ namespace Avalonia.Base.UnitTests.Media.TextFormatting writer.Write(" "); + long length = stream.Length; + while (true) { var b = stream.ReadByte(); @@ -100,18 +97,22 @@ namespace Avalonia.Base.UnitTests.Media.TextFormatting { break; } - - writer.Write(b.ToString()); - writer.Write(','); + writer.Write(b.ToString()); - if (stream.Position % 100 == 0) + if (stream.Position % 100 > 0 && stream.Position != length) + { + writer.Write(", "); + } + else { + writer.Write(','); writer.Write(Environment.NewLine); - writer.Write(" "); - - continue; + if (stream.Position != length) + { + writer.Write(" "); + } } } @@ -161,12 +162,7 @@ namespace Avalonia.Base.UnitTests.Media.TextFormatting GenerateTrieClass("UnicodeData", trie); - using (var stream = File.Create("Generated\\UnicodeData.trie")) - { - trie.Save(stream); - - return trie; - } + return trie; } private static Dictionary GetUnicodeData(IReadOnlyDictionary generalCategoryMappings, @@ -461,9 +457,7 @@ namespace Avalonia.Base.UnitTests.Media.TextFormatting public int BracketType { get; set; } public int BiDiClass { get; set; } - } - - + } } internal class UnicodeDataEntries diff --git a/tests/Avalonia.Base.UnitTests/Media/TextFormatting/UnicodeDataGeneratorTests.cs b/tests/Avalonia.Base.UnitTests/Media/TextFormatting/UnicodeDataGeneratorTests.cs index f3aea83316..688c711f15 100644 --- a/tests/Avalonia.Base.UnitTests/Media/TextFormatting/UnicodeDataGeneratorTests.cs +++ b/tests/Avalonia.Base.UnitTests/Media/TextFormatting/UnicodeDataGeneratorTests.cs @@ -22,7 +22,7 @@ namespace Avalonia.Base.UnitTests.Media.TextFormatting foreach (var value in unicodeData.Values) { - var data = unicodeDataTrie.Get(value.Codepoint); + var data = unicodeDataTrie.Get((uint)value.Codepoint); Assert.Equal(value.GeneralCategory, GetValue(data, 0, UnicodeData.CATEGORY_MASK)); @@ -35,7 +35,7 @@ namespace Avalonia.Base.UnitTests.Media.TextFormatting foreach (var value in biDiData.Values) { - var data = biDiTrie.Get(value.Codepoint); + var data = biDiTrie.Get((uint)value.Codepoint); Assert.Equal(value.Bracket, GetValue(data, 0, UnicodeData.BIDIPAIREDBRACKED_MASK)); diff --git a/tests/Avalonia.Base.UnitTests/Media/TextFormatting/UnicodeEnumsGenerator.cs b/tests/Avalonia.Base.UnitTests/Media/TextFormatting/UnicodeEnumsGenerator.cs index 10da018eeb..110e57cbd3 100644 --- a/tests/Avalonia.Base.UnitTests/Media/TextFormatting/UnicodeEnumsGenerator.cs +++ b/tests/Avalonia.Base.UnitTests/Media/TextFormatting/UnicodeEnumsGenerator.cs @@ -244,18 +244,18 @@ namespace Avalonia.Base.UnitTests.Media.TextFormatting return orderedLineBreakEntries.Values.ToList(); } - public static List CreateBiDiClassEnum() + public static List CreateBidiClassEnum() { var entries = new List { new DataEntry("Left_To_Right", "L", string.Empty) }; ParseDataEntries("# Bidi_Class (bc)", entries); - using (var stream = File.Create("Generated\\BiDiClass.cs")) + using (var stream = File.Create("Generated\\BidiClass.cs")) using (var writer = new StreamWriter(stream)) { writer.WriteLine("namespace Avalonia.Media.TextFormatting.Unicode"); writer.WriteLine("{"); - writer.WriteLine(" public enum BiDiClass"); + writer.WriteLine(" public enum BidiClass"); writer.WriteLine(" {"); foreach (var entry in entries) @@ -277,12 +277,12 @@ namespace Avalonia.Base.UnitTests.Media.TextFormatting ParseDataEntries("# Bidi_Paired_Bracket_Type (bpt)", entries); - using (var stream = File.Create("Generated\\BiDiPairedBracketType.cs")) + using (var stream = File.Create("Generated\\BidiPairedBracketType.cs")) using (var writer = new StreamWriter(stream)) { writer.WriteLine("namespace Avalonia.Media.TextFormatting.Unicode"); writer.WriteLine("{"); - writer.WriteLine(" public enum BiDiPairedBracketType"); + writer.WriteLine(" public enum BidiPairedBracketType"); writer.WriteLine(" {"); foreach (var entry in entries) diff --git a/tests/Avalonia.UnitTests/HarfBuzzTextShaperImpl.cs b/tests/Avalonia.UnitTests/HarfBuzzTextShaperImpl.cs index 4bc30484e9..459ae3a549 100644 --- a/tests/Avalonia.UnitTests/HarfBuzzTextShaperImpl.cs +++ b/tests/Avalonia.UnitTests/HarfBuzzTextShaperImpl.cs @@ -80,7 +80,7 @@ namespace Avalonia.UnitTests var second = glyphInfos[length - 1]; - if (!new Codepoint((int)second.Codepoint).IsBreakChar) + if (!new Codepoint(second.Codepoint).IsBreakChar) { return; } From cebd5b169de369b47aa6490e9c95c1789d84138a Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Tue, 28 Jun 2022 10:57:29 +0200 Subject: [PATCH 66/78] Added script to run automation tests on macOS. --- .../macos-clean-build-test.sh | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100755 tests/Avalonia.IntegrationTests.Appium/macos-clean-build-test.sh diff --git a/tests/Avalonia.IntegrationTests.Appium/macos-clean-build-test.sh b/tests/Avalonia.IntegrationTests.Appium/macos-clean-build-test.sh new file mode 100755 index 0000000000..30a4a79f4a --- /dev/null +++ b/tests/Avalonia.IntegrationTests.Appium/macos-clean-build-test.sh @@ -0,0 +1,8 @@ +# Cleans, builds, and runs integration tests on macOS. +# Can be used by `git bisect run` to automatically find the commit which introduced a problem. +SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd) +cd "$SCRIPT_DIR"/../.. || exit +git clean -xdf +./build.sh CompileNative +./samples/IntegrationTestApp/bundle.sh +dotnet test tests/Avalonia.IntegrationTests.Appium/ -l "console;verbosity=detailed" From 15c26b9dd55ac83590b79ae61e73db937f580161 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Tue, 28 Jun 2022 12:06:21 +0200 Subject: [PATCH 67/78] Use frame size for CenterOwner startup location. --- src/Avalonia.Controls/Window.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index 92f74530e2..2dd391945b 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -901,10 +901,10 @@ namespace Avalonia.Controls { if (owner != null) { - // TODO: We really need non-client size here. + var ownerSize = owner.FrameSize ?? owner.ClientSize; var ownerRect = new PixelRect( owner.Position, - PixelSize.FromSize(owner.ClientSize, scaling)); + PixelSize.FromSize(ownerSize, scaling)); Position = ownerRect.CenterRect(rect).Position; } } From bf7f50690f6d0b18516daaba971a44bd17570c33 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Tue, 28 Jun 2022 19:06:32 +0200 Subject: [PATCH 68/78] Don't promote layout property values to local values. When DevTools was opened, all layout property values were being promoted to `LocalValue`s because the `_updatingFromControl` flag was not being set during initialization, causing the initial values to be written back out to the control as local values. --- .../ViewModels/ControlLayoutViewModel.cs | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlLayoutViewModel.cs b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlLayoutViewModel.cs index 0c0c005122..a453fef212 100644 --- a/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlLayoutViewModel.cs +++ b/src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlLayoutViewModel.cs @@ -30,20 +30,28 @@ namespace Avalonia.Diagnostics.ViewModels if (control is AvaloniaObject ao) { - MarginThickness = ao.GetValue(Layoutable.MarginProperty); - - if (HasPadding) + try { - PaddingThickness = ao.GetValue(Decorator.PaddingProperty); - } + _updatingFromControl = true; + MarginThickness = ao.GetValue(Layoutable.MarginProperty); + + if (HasPadding) + { + PaddingThickness = ao.GetValue(Decorator.PaddingProperty); + } - if (HasBorder) + if (HasBorder) + { + BorderThickness = ao.GetValue(Border.BorderThicknessProperty); + } + + HorizontalAlignment = ao.GetValue(Layoutable.HorizontalAlignmentProperty); + VerticalAlignment = ao.GetValue(Layoutable.VerticalAlignmentProperty); + } + finally { - BorderThickness = ao.GetValue(Border.BorderThicknessProperty); + _updatingFromControl = false; } - - HorizontalAlignment = ao.GetValue(Layoutable.HorizontalAlignmentProperty); - VerticalAlignment = ao.GetValue(Layoutable.VerticalAlignmentProperty); } UpdateSize(); From 2b1eba8c7cb2253dd5791351c69c579daaafe6b5 Mon Sep 17 00:00:00 2001 From: Tako <53405089+Takoooooo@users.noreply.github.com> Date: Thu, 30 Jun 2022 14:09:28 +0300 Subject: [PATCH 69/78] Fix leak in the InternalSelectionModel --- src/Avalonia.Controls/Selection/InternalSelectionModel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/Selection/InternalSelectionModel.cs b/src/Avalonia.Controls/Selection/InternalSelectionModel.cs index d92ffb0d1a..d0715e402d 100644 --- a/src/Avalonia.Controls/Selection/InternalSelectionModel.cs +++ b/src/Avalonia.Controls/Selection/InternalSelectionModel.cs @@ -168,7 +168,7 @@ namespace Avalonia.Controls.Selection { if (_writableSelectedItems is INotifyCollectionChanged incc) { - incc.CollectionChanged += OnSelectedItemsCollectionChanged; + incc.CollectionChanged -= OnSelectedItemsCollectionChanged; } } From 5c6370aa5600f91ae7077258f503ee5f6ea619bf Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 29 Jun 2022 00:43:45 +0200 Subject: [PATCH 70/78] Don't make ResourceDictionary inherit... ...from `AvaloniaDictionary`. --- .../Controls/ResourceDictionary.cs | 119 ++++++++++++++---- 1 file changed, 98 insertions(+), 21 deletions(-) diff --git a/src/Avalonia.Base/Controls/ResourceDictionary.cs b/src/Avalonia.Base/Controls/ResourceDictionary.cs index 3af14daa83..77863e5101 100644 --- a/src/Avalonia.Base/Controls/ResourceDictionary.cs +++ b/src/Avalonia.Base/Controls/ResourceDictionary.cs @@ -1,38 +1,45 @@ using System; +using System.Collections; using System.Collections.Generic; -using System.Collections.Specialized; +using System.Linq; using Avalonia.Collections; -using Avalonia.Metadata; - -#nullable enable namespace Avalonia.Controls { /// /// An indexed dictionary of resources. /// - public class ResourceDictionary : AvaloniaDictionary, IResourceDictionary + public class ResourceDictionary : IResourceDictionary { + private Dictionary? _inner; private IResourceHost? _owner; private AvaloniaList? _mergedDictionaries; /// /// Initializes a new instance of the class. /// - public ResourceDictionary() - { - CollectionChanged += OnCollectionChanged; - } + public ResourceDictionary() { } /// /// Initializes a new instance of the class. /// - public ResourceDictionary(IResourceHost owner) - : this() + public ResourceDictionary(IResourceHost owner) => Owner = owner; + + public int Count => _inner?.Count ?? 0; + + public object? this[object key] { - Owner = owner; + get => _inner?[key]; + set + { + Inner[key] = value; + Owner?.NotifyHostedResourcesChanged(ResourcesChangedEventArgs.Empty); + } } + public ICollection Keys => (ICollection?)_inner?.Keys ?? Array.Empty(); + public ICollection Values => (ICollection?)_inner?.Values ?? Array.Empty(); + public IResourceHost? Owner { get => _owner; @@ -80,7 +87,7 @@ namespace Avalonia.Controls { get { - if (Count > 0) + if (_inner?.Count > 0) { return true; } @@ -100,11 +107,43 @@ namespace Avalonia.Controls } } + bool ICollection>.IsReadOnly => false; + + private Dictionary Inner => _inner ??= new(); + public event EventHandler? OwnerChanged; + public void Add(object key, object? value) + { + Inner.Add(key, value); + Owner?.NotifyHostedResourcesChanged(ResourcesChangedEventArgs.Empty); + } + + public void Clear() + { + if (_inner?.Count > 0) + { + _inner.Clear(); + Owner?.NotifyHostedResourcesChanged(ResourcesChangedEventArgs.Empty); + } + } + + public bool ContainsKey(object key) => _inner?.ContainsKey(key) ?? false; + + public bool Remove(object key) + { + if (_inner?.Remove(key) == true) + { + Owner?.NotifyHostedResourcesChanged(ResourcesChangedEventArgs.Empty); + return true; + } + + return false; + } + public bool TryGetResource(object key, out object? value) { - if (TryGetValue(key, out value)) + if (_inner is not null && _inner.TryGetValue(key, out value)) { return true; } @@ -120,9 +159,52 @@ namespace Avalonia.Controls } } + value = null; return false; } + public bool TryGetValue(object key, out object? value) + { + if (_inner is not null) + return _inner.TryGetValue(key, out value); + value = null; + return false; + } + + + void ICollection>.Add(KeyValuePair item) + { + Add(item.Key, item.Value); + } + + bool ICollection>.Contains(KeyValuePair item) + { + return (_inner as ICollection>)?.Contains(item) ?? false; + } + + void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) + { + (_inner as ICollection>)?.CopyTo(array, arrayIndex); + } + + bool ICollection>.Remove(KeyValuePair item) + { + if ((_inner as ICollection>)?.Remove(item) == true) + { + Owner?.NotifyHostedResourcesChanged(ResourcesChangedEventArgs.Empty); + return true; + } + + return false; + } + + public IEnumerator> GetEnumerator() + { + return _inner?.GetEnumerator() ?? Enumerable.Empty>().GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + void IResourceProvider.AddOwner(IResourceHost owner) { owner = owner ?? throw new ArgumentNullException(nameof(owner)); @@ -134,7 +216,7 @@ namespace Avalonia.Controls Owner = owner; - var hasResources = Count > 0; + var hasResources = _inner?.Count > 0; if (_mergedDictionaries is object) { @@ -159,7 +241,7 @@ namespace Avalonia.Controls { Owner = null; - var hasResources = Count > 0; + var hasResources = _inner?.Count > 0; if (_mergedDictionaries is object) { @@ -176,10 +258,5 @@ namespace Avalonia.Controls } } } - - private void OnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) - { - Owner?.NotifyHostedResourcesChanged(ResourcesChangedEventArgs.Empty); - } } } From c26173c4fe8e39b03a961666a94ebf74092f63af Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Fri, 1 Jul 2022 16:44:22 +0200 Subject: [PATCH 71/78] Added failing test for #7381. --- .../Rendering/SceneGraph/SceneBuilderTests.cs | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/tests/Avalonia.Base.UnitTests/Rendering/SceneGraph/SceneBuilderTests.cs b/tests/Avalonia.Base.UnitTests/Rendering/SceneGraph/SceneBuilderTests.cs index 879de9fca5..502575702a 100644 --- a/tests/Avalonia.Base.UnitTests/Rendering/SceneGraph/SceneBuilderTests.cs +++ b/tests/Avalonia.Base.UnitTests/Rendering/SceneGraph/SceneBuilderTests.cs @@ -594,6 +594,69 @@ namespace Avalonia.Base.UnitTests.Rendering.SceneGraph } } + [Fact] + public void Should_Update_When_Control_Moved_Causing_Layout_Change() + { + using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface)) + { + Decorator moveFrom; + Decorator moveTo; + Canvas moveMe; + var tree = new TestRoot + { + Width = 100, + Height = 100, + Child = new DockPanel + { + Children = + { + (moveFrom = new Decorator + { + Child = moveMe = new Canvas + { + Width = 100, + Height = 100, + }, + }), + (moveTo = new Decorator()), + } + } + }; + + tree.Measure(Size.Infinity); + tree.Arrange(new Rect(tree.DesiredSize)); + + var scene = new Scene(tree); + var sceneBuilder = new SceneBuilder(); + sceneBuilder.UpdateAll(scene); + + var moveFromNode = (VisualNode)scene.FindNode(moveFrom); + var moveToNode = (VisualNode)scene.FindNode(moveTo); + + Assert.Equal(1, moveFromNode.Children.Count); + Assert.Same(moveMe, moveFromNode.Children[0].Visual); + Assert.Empty(moveToNode.Children); + + moveFrom.Child = null; + moveTo.Child = moveMe; + tree.LayoutManager.ExecuteLayoutPass(); + + scene = scene.CloneScene(); + moveFromNode = (VisualNode)scene.FindNode(moveFrom); + moveToNode = (VisualNode)scene.FindNode(moveTo); + + moveFromNode.SortChildren(scene); + moveToNode.SortChildren(scene); + sceneBuilder.Update(scene, moveFrom); + sceneBuilder.Update(scene, moveTo); + sceneBuilder.Update(scene, moveMe); + + Assert.Empty(moveFromNode.Children); + Assert.Equal(1, moveToNode.Children.Count); + Assert.Same(moveMe, moveToNode.Children[0].Visual); + } + } + [Fact] public void Should_Update_When_Control_Made_Invisible() { From cfe572f30bb40e749ecbb84cacc9477a35aa86e3 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Fri, 1 Jul 2022 16:56:53 +0200 Subject: [PATCH 72/78] Remove node from parent when reparented. When a control was move from one parent container to another, and that move caused the new parent container to be laid out in a different position, a code path was taken which resulted in the `VisualNode` being present under both the old and new containers. Ensure that the node is removed from its old parent in this case. Fixes #7381 Fixes #6103 (probably) --- src/Avalonia.Base/Rendering/SceneGraph/SceneBuilder.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Avalonia.Base/Rendering/SceneGraph/SceneBuilder.cs b/src/Avalonia.Base/Rendering/SceneGraph/SceneBuilder.cs index 5dc426ab06..e4d5a1ca68 100644 --- a/src/Avalonia.Base/Rendering/SceneGraph/SceneBuilder.cs +++ b/src/Avalonia.Base/Rendering/SceneGraph/SceneBuilder.cs @@ -158,6 +158,7 @@ namespace Avalonia.Rendering.SceneGraph if (result != null && result.Parent != parent) { Deindex(scene, result); + ((VisualNode?)result.Parent)?.RemoveChild(result); result = null; } From b4b869a42902431f40766ec0ed276cf2c2db6b18 Mon Sep 17 00:00:00 2001 From: Max Katz Date: Sat, 2 Jul 2022 01:22:14 -0400 Subject: [PATCH 73/78] Fix after event were renamed --- samples/ControlCatalog/Pages/PointersPage.xaml.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/samples/ControlCatalog/Pages/PointersPage.xaml.cs b/samples/ControlCatalog/Pages/PointersPage.xaml.cs index 977cee3d58..b463cf364d 100644 --- a/samples/ControlCatalog/Pages/PointersPage.xaml.cs +++ b/samples/ControlCatalog/Pages/PointersPage.xaml.cs @@ -20,15 +20,15 @@ public class PointersPage : UserControl border1.PointerReleased += Border_PointerReleased; border1.PointerCaptureLost += Border_PointerCaptureLost; border1.PointerMoved += Border_PointerUpdated; - border1.PointerEnter += Border_PointerUpdated; - border1.PointerLeave += Border_PointerUpdated; + border1.PointerEntered += Border_PointerUpdated; + border1.PointerExited += Border_PointerUpdated; border2.PointerPressed += Border_PointerPressed; border2.PointerReleased += Border_PointerReleased; border2.PointerCaptureLost += Border_PointerCaptureLost; border2.PointerMoved += Border_PointerUpdated; - border2.PointerEnter += Border_PointerUpdated; - border2.PointerLeave += Border_PointerUpdated; + border2.PointerEntered += Border_PointerUpdated; + border2.PointerExited += Border_PointerUpdated; } private void Border_PointerUpdated(object sender, PointerEventArgs e) From 17562c16bd25f3b325ff23e4380aecc0c877cc3d Mon Sep 17 00:00:00 2001 From: Max Katz Date: Sat, 2 Jul 2022 03:43:08 -0400 Subject: [PATCH 74/78] Fixes after review --- samples/ControlCatalog/Pages/PointerCanvas.cs | 22 +++++- .../ControlCatalog/Pages/PointersPage.xaml | 1 + .../ControlCatalog/Pages/PointersPage.xaml.cs | 6 +- .../Avalonia.Win32/WindowImpl.AppWndProc.cs | 75 ++++++++++++------- 4 files changed, 72 insertions(+), 32 deletions(-) diff --git a/samples/ControlCatalog/Pages/PointerCanvas.cs b/samples/ControlCatalog/Pages/PointerCanvas.cs index b815a573f2..5843b13a0c 100644 --- a/samples/ControlCatalog/Pages/PointerCanvas.cs +++ b/samples/ControlCatalog/Pages/PointerCanvas.cs @@ -19,6 +19,7 @@ public class PointerCanvas : Control private IDisposable? _statusUpdated; private Dictionary _pointers = new(); private PointerPointProperties? _lastProperties; + private PointerUpdateKind? _lastNonOtherUpdateKind; class PointerPoints { struct CanvasPoint @@ -128,10 +129,11 @@ public class PointerCanvas : Control _statusUpdated = DispatcherTimer.Run(() => { - if (_stopwatch.Elapsed.TotalSeconds > 1) + if (_stopwatch.Elapsed.TotalMilliseconds > 250) { Status = $@"Events per second: {(_events / _stopwatch.Elapsed.TotalSeconds)} PointerUpdateKind: {_lastProperties?.PointerUpdateKind} +Last PointerUpdateKind != Other: {_lastNonOtherUpdateKind} IsLeftButtonPressed: {_lastProperties?.IsLeftButtonPressed} IsRightButtonPressed: {_lastProperties?.IsRightButtonPressed} IsMiddleButtonPressed: {_lastProperties?.IsMiddleButtonPressed} @@ -162,21 +164,27 @@ Twist: {_lastProperties?.Twist}"; void HandleEvent(PointerEventArgs e) { _events++; + if (_threadSleep != 0) { Thread.Sleep(_threadSleep); } InvalidateVisual(); + var lastPointer = e.GetCurrentPoint(this); + _lastProperties = lastPointer.Properties; + + if (_lastProperties.PointerUpdateKind != PointerUpdateKind.Other) + { + _lastNonOtherUpdateKind = _lastProperties.PointerUpdateKind; + } + if (e.RoutedEvent == PointerReleasedEvent && e.Pointer.Type == PointerType.Touch) { _pointers.Remove(e.Pointer.Id); return; } - var lastPointer = e.GetCurrentPoint(this); - _lastProperties = lastPointer.Properties; - if (e.Pointer.Type != PointerType.Pen || lastPointer.Properties.Pressure > 0) { @@ -218,4 +226,10 @@ Twist: {_lastProperties?.Twist}"; HandleEvent(e); base.OnPointerReleased(e); } + + protected override void OnPointerCaptureLost(PointerCaptureLostEventArgs e) + { + _lastProperties = null; + base.OnPointerCaptureLost(e); + } } diff --git a/samples/ControlCatalog/Pages/PointersPage.xaml b/samples/ControlCatalog/Pages/PointersPage.xaml index 1281ec77b6..c39106f29e 100644 --- a/samples/ControlCatalog/Pages/PointersPage.xaml +++ b/samples/ControlCatalog/Pages/PointersPage.xaml @@ -19,6 +19,7 @@ diff --git a/samples/ControlCatalog/Pages/PointersPage.xaml.cs b/samples/ControlCatalog/Pages/PointersPage.xaml.cs index b463cf364d..6fc468e37f 100644 --- a/samples/ControlCatalog/Pages/PointersPage.xaml.cs +++ b/samples/ControlCatalog/Pages/PointersPage.xaml.cs @@ -35,7 +35,8 @@ public class PointersPage : UserControl { var textBlock = (TextBlock)((Border)sender).Child; var position = e.GetPosition((Border)sender); - textBlock.Text = @$"Captured: {e.Pointer.Captured == sender} + textBlock.Text = @$"Type: {e.Pointer.Type} +Captured: {e.Pointer.Captured == sender} PointerId: {e.Pointer.Id} Position: {(int)position.X} {(int)position.Y}"; e.Handled = true; @@ -44,7 +45,8 @@ Position: {(int)position.X} {(int)position.Y}"; private void Border_PointerCaptureLost(object sender, PointerCaptureLostEventArgs e) { var textBlock = (TextBlock)((Border)sender).Child; - textBlock.Text = @$"Captured: {e.Pointer.Captured == sender} + textBlock.Text = @$"Type: {e.Pointer.Type} +Captured: {e.Pointer.Captured == sender} PointerId: {e.Pointer.Id} Position: ??? ???"; e.Handled = true; diff --git a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs index 861110bf9a..2ce4d7d1f0 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs @@ -746,7 +746,6 @@ namespace Avalonia.Win32 { if (GetPointerPenInfoHistory(info.pointerId, ref historyCount, s_historyPenInfos)) { - uint timestamp = 0; for (int i = historyCount - 1; i >= 1; i--) { var historyPenInfo = s_historyPenInfos[i]; @@ -830,7 +829,7 @@ namespace Avalonia.Win32 timestamp = info.dwTime; } - modifiers |= GetInputModifiers(info.dwKeyStates); + modifiers |= GetInputModifiers(info.pointerFlags); } private RawPointerPoint CreateRawPointerPoint(POINTER_INFO pointerInfo) @@ -871,48 +870,40 @@ namespace Avalonia.Win32 private static RawPointerEventType GetEventType(WindowsMessage message, POINTER_INFO info) { - if (message == WindowsMessage.WM_POINTERUPDATE) + var isTouch = info.pointerType == PointerInputType.PT_TOUCH; + if (info.pointerFlags.HasFlag(PointerFlags.POINTER_FLAG_CANCELED)) { - return info.pointerType == PointerInputType.PT_TOUCH - ? RawPointerEventType.TouchUpdate - : RawPointerEventType.Move; + return isTouch ? RawPointerEventType.TouchCancel : RawPointerEventType.LeaveWindow; } - switch (info.pointerType) + + var eventType = ToEventType(info.ButtonChangeType, isTouch); + if (eventType == RawPointerEventType.LeftButtonDown && + message == WindowsMessage.WM_NCPOINTERDOWN) { - case PointerInputType.PT_TOUCH: - if (info.pointerFlags.HasFlag(PointerFlags.POINTER_FLAG_CANCELED)) - { - return RawPointerEventType.TouchCancel; - } - return message == WindowsMessage.WM_POINTERDOWN || message == WindowsMessage.WM_NCPOINTERDOWN - ? RawPointerEventType.TouchBegin - : RawPointerEventType.TouchEnd; - default: - var eventType = ToEventType(info.ButtonChangeType); - if (eventType == RawPointerEventType.LeftButtonDown && - message == WindowsMessage.WM_NCPOINTERDOWN) - { - eventType = RawPointerEventType.NonClientLeftButtonDown; - } - return eventType; + eventType = RawPointerEventType.NonClientLeftButtonDown; } + + return eventType; } - private static RawPointerEventType ToEventType(PointerButtonChangeType type) + private static RawPointerEventType ToEventType(PointerButtonChangeType type, bool isTouch) { return type switch { - PointerButtonChangeType.POINTER_CHANGE_FIRSTBUTTON_DOWN => RawPointerEventType.LeftButtonDown, + PointerButtonChangeType.POINTER_CHANGE_FIRSTBUTTON_DOWN when isTouch => RawPointerEventType.TouchBegin, + PointerButtonChangeType.POINTER_CHANGE_FIRSTBUTTON_DOWN when !isTouch => RawPointerEventType.LeftButtonDown, PointerButtonChangeType.POINTER_CHANGE_SECONDBUTTON_DOWN => RawPointerEventType.RightButtonDown, PointerButtonChangeType.POINTER_CHANGE_THIRDBUTTON_DOWN => RawPointerEventType.MiddleButtonDown, PointerButtonChangeType.POINTER_CHANGE_FOURTHBUTTON_DOWN => RawPointerEventType.XButton1Down, PointerButtonChangeType.POINTER_CHANGE_FIFTHBUTTON_DOWN => RawPointerEventType.XButton2Down, - PointerButtonChangeType.POINTER_CHANGE_FIRSTBUTTON_UP => RawPointerEventType.LeftButtonUp, + PointerButtonChangeType.POINTER_CHANGE_FIRSTBUTTON_UP when isTouch => RawPointerEventType.TouchEnd, + PointerButtonChangeType.POINTER_CHANGE_FIRSTBUTTON_UP when !isTouch => RawPointerEventType.LeftButtonUp, PointerButtonChangeType.POINTER_CHANGE_SECONDBUTTON_UP => RawPointerEventType.RightButtonUp, PointerButtonChangeType.POINTER_CHANGE_THIRDBUTTON_UP => RawPointerEventType.MiddleButtonUp, PointerButtonChangeType.POINTER_CHANGE_FOURTHBUTTON_UP => RawPointerEventType.XButton1Up, PointerButtonChangeType.POINTER_CHANGE_FIFTHBUTTON_UP => RawPointerEventType.XButton2Up, + _ when isTouch => RawPointerEventType.TouchUpdate, _ => RawPointerEventType.Move }; } @@ -1000,5 +991,37 @@ namespace Avalonia.Win32 return modifiers; } + + private static RawInputModifiers GetInputModifiers(PointerFlags flags) + { + var modifiers = WindowsKeyboardDevice.Instance.Modifiers; + + if (flags.HasAllFlags(PointerFlags.POINTER_FLAG_FIRSTBUTTON)) + { + modifiers |= RawInputModifiers.LeftMouseButton; + } + + if (flags.HasAllFlags(PointerFlags.POINTER_FLAG_SECONDBUTTON)) + { + modifiers |= RawInputModifiers.RightMouseButton; + } + + if (flags.HasAllFlags(PointerFlags.POINTER_FLAG_THIRDBUTTON)) + { + modifiers |= RawInputModifiers.MiddleMouseButton; + } + + if (flags.HasAllFlags(PointerFlags.POINTER_FLAG_FOURTHBUTTON)) + { + modifiers |= RawInputModifiers.XButton1MouseButton; + } + + if (flags.HasAllFlags(PointerFlags.POINTER_FLAG_FIFTHBUTTON)) + { + modifiers |= RawInputModifiers.XButton2MouseButton; + } + + return modifiers; + } } } From 1c8b26bcde086be143bb25140e11f3ed97562469 Mon Sep 17 00:00:00 2001 From: Max Katz Date: Sat, 2 Jul 2022 03:46:28 -0400 Subject: [PATCH 75/78] Fix YTilt --- src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs index 2ce4d7d1f0..a2f9b7886a 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs @@ -864,7 +864,7 @@ namespace Avalonia.Win32 Pressure = info.pressure / 1024f, Twist = info.rotation, XTilt = info.tiltX, - YTilt = info.tiltX + YTilt = info.tiltY }; } From 5000a4ffe35699233e1bd7039a9e380718e93994 Mon Sep 17 00:00:00 2001 From: Max Katz Date: Sat, 2 Jul 2022 18:17:35 -0400 Subject: [PATCH 76/78] Do not enable MouseInPointerEnabled automatically and remove EnableWmPointerEvents option --- .editorconfig | 2 +- samples/ControlCatalog.NetCore/Program.cs | 1 - src/Windows/Avalonia.Win32/Win32Platform.cs | 10 +---- .../Avalonia.Win32/WindowImpl.AppWndProc.cs | 42 ++++++++++--------- src/Windows/Avalonia.Win32/WindowImpl.cs | 20 ++++----- 5 files changed, 33 insertions(+), 42 deletions(-) diff --git a/.editorconfig b/.editorconfig index cb589a5ce1..30edee1633 100644 --- a/.editorconfig +++ b/.editorconfig @@ -21,7 +21,7 @@ csharp_new_line_before_finally = true csharp_new_line_before_members_in_object_initializers = true csharp_new_line_before_members_in_anonymous_types = true csharp_new_line_between_query_expression_clauses = true -trim_trailing_whitespace = true +# trim_trailing_whitespace = true # Indentation preferences csharp_indent_block_contents = true diff --git a/samples/ControlCatalog.NetCore/Program.cs b/samples/ControlCatalog.NetCore/Program.cs index d6a297858d..13751b56b5 100644 --- a/samples/ControlCatalog.NetCore/Program.cs +++ b/samples/ControlCatalog.NetCore/Program.cs @@ -115,7 +115,6 @@ namespace ControlCatalog.NetCore }) .With(new Win32PlatformOptions { - EnableWmPointerEvents = true }) .UseSkia() .AfterSetup(builder => diff --git a/src/Windows/Avalonia.Win32/Win32Platform.cs b/src/Windows/Avalonia.Win32/Win32Platform.cs index aa597d6809..8f6993c040 100644 --- a/src/Windows/Avalonia.Win32/Win32Platform.cs +++ b/src/Windows/Avalonia.Win32/Win32Platform.cs @@ -68,17 +68,9 @@ namespace Avalonia /// /// Multitouch allows a surface (a touchpad or touchscreen) to recognize the presence of more than one point of contact with the surface at the same time. /// - [Obsolete("Multitouch is always enabled")] + [Obsolete("Multitouch is always enabled on supported Windows versions")] public bool? EnableMultitouch { get; set; } = true; - /// - /// Enables Win8+ WM_POINTER events support. The default value is false. - /// - /// - /// Required for extended Pen and Touch support. - /// - public bool? EnableWmPointerEvents { get; set; } = false; - /// /// Embeds popups to the window when set to true. The default value is false. /// diff --git a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs index a2f9b7886a..4c7b9a0348 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs @@ -84,7 +84,7 @@ namespace Avalonia.Win32 case WindowsMessage.WM_DESTROY: { UiaCoreProviderApi.UiaReturnRawElementProvider(_hwnd, IntPtr.Zero, IntPtr.Zero, null); - + // We need to release IMM context and state to avoid leaks. if (Imm32InputMethod.Current.HWND == _hwnd) { @@ -110,9 +110,9 @@ namespace Avalonia.Win32 var newDisplayRect = Marshal.PtrToStructure(lParam); _scaling = dpi / 96.0; ScalingChanged?.Invoke(_scaling); - + using (SetResizeReason(PlatformResizeReason.DpiChange)) - { + { SetWindowPos(hWnd, IntPtr.Zero, newDisplayRect.left, @@ -180,7 +180,7 @@ namespace Avalonia.Win32 case WindowsMessage.WM_MBUTTONDOWN: case WindowsMessage.WM_XBUTTONDOWN: { - if (_wmPointerEnabled) + if (IsMouseInPointerEnabled) { break; } @@ -213,7 +213,7 @@ namespace Avalonia.Win32 case WindowsMessage.WM_MBUTTONUP: case WindowsMessage.WM_XBUTTONUP: { - if (_wmPointerEnabled) + if (IsMouseInPointerEnabled) { break; } @@ -241,12 +241,16 @@ namespace Avalonia.Win32 } // Mouse capture is lost case WindowsMessage.WM_CANCELMODE: - _mouseDevice.Capture(null); + if (!IsMouseInPointerEnabled) + { + _mouseDevice.Capture(null); + } + break; case WindowsMessage.WM_MOUSEMOVE: { - if (_wmPointerEnabled) + if (IsMouseInPointerEnabled) { break; } @@ -273,7 +277,7 @@ namespace Avalonia.Win32 timestamp, _owner, RawPointerEventType.Move, - DipFromLParam(lParam), + DipFromLParam(lParam), GetMouseModifiers(wParam)); break; @@ -281,7 +285,7 @@ namespace Avalonia.Win32 case WindowsMessage.WM_MOUSEWHEEL: { - if (_wmPointerEnabled) + if (IsMouseInPointerEnabled) { break; } @@ -290,14 +294,14 @@ namespace Avalonia.Win32 timestamp, _owner, PointToClient(PointFromLParam(lParam)), - new Vector(0, (ToInt32(wParam) >> 16) / wheelDelta), + new Vector(0, (ToInt32(wParam) >> 16) / wheelDelta), GetMouseModifiers(wParam)); break; } case WindowsMessage.WM_MOUSEHWHEEL: { - if (_wmPointerEnabled) + if (IsMouseInPointerEnabled) { break; } @@ -306,14 +310,14 @@ namespace Avalonia.Win32 timestamp, _owner, PointToClient(PointFromLParam(lParam)), - new Vector(-(ToInt32(wParam) >> 16) / wheelDelta, 0), + new Vector(-(ToInt32(wParam) >> 16) / wheelDelta, 0), GetMouseModifiers(wParam)); break; } case WindowsMessage.WM_MOUSELEAVE: { - if (_wmPointerEnabled) + if (IsMouseInPointerEnabled) { break; } @@ -323,7 +327,7 @@ namespace Avalonia.Win32 timestamp, _owner, RawPointerEventType.LeaveWindow, - new Point(-1, -1), + new Point(-1, -1), WindowsKeyboardDevice.Instance.Modifiers); break; } @@ -333,7 +337,7 @@ namespace Avalonia.Win32 case WindowsMessage.WM_NCMBUTTONDOWN: case WindowsMessage.WM_NCXBUTTONDOWN: { - if (_wmPointerEnabled) + if (IsMouseInPointerEnabled) { break; } @@ -598,7 +602,7 @@ namespace Avalonia.Win32 case WindowsMessage.WM_GETMINMAXINFO: { MINMAXINFO mmi = Marshal.PtrToStructure(lParam); - + _maxTrackSize = mmi.ptMaxTrackSize; if (_minSize.Width > 0) @@ -682,7 +686,7 @@ namespace Avalonia.Win32 if (_managedDrag.PreprocessInputEvent(ref e)) return UnmanagedMethods.DefWindowProc(hWnd, msg, wParam, lParam); #endif - + if(shouldTakeFocus) { SetFocus(_hwnd); @@ -915,11 +919,11 @@ namespace Avalonia.Win32 if (langid == _langid && Imm32InputMethod.Current.HWND == Hwnd) { return; - } + } _langid = langid; Imm32InputMethod.Current.SetLanguageAndWindow(this, Hwnd, hkl); - + } private static int ToInt32(IntPtr ptr) diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 95dac19d04..31f30a6e47 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -74,12 +74,12 @@ namespace Avalonia.Win32 private readonly ManagedDeferredRendererLock _rendererLock; private readonly FramebufferManager _framebuffer; private readonly IGlPlatformSurface _gl; + private readonly bool _wmPointerEnabled; private Win32NativeControlHost _nativeControlHost; private WndProc _wndProcDelegate; private string _className; private IntPtr _hwnd; - private bool _wmPointerEnabled; private IInputRoot _owner; private WindowProperties _windowProperties; private bool _trackingMouse;//ToDo - there is something missed. Needs investigation @Steven Kirk @@ -100,10 +100,10 @@ namespace Avalonia.Win32 private bool _ignoreWmChar; private const int MaxPointerHistorySize = 512; - private readonly static PooledList s_intermediatePointsPooledList = new(); - private readonly static POINTER_TOUCH_INFO[] s_historyTouchInfos = new POINTER_TOUCH_INFO[MaxPointerHistorySize]; - private readonly static POINTER_PEN_INFO[] s_historyPenInfos = new POINTER_PEN_INFO[MaxPointerHistorySize]; - private readonly static POINTER_INFO[] s_historyInfos = new POINTER_INFO[MaxPointerHistorySize]; + private static readonly PooledList s_intermediatePointsPooledList = new(); + private static readonly POINTER_TOUCH_INFO[] s_historyTouchInfos = new POINTER_TOUCH_INFO[MaxPointerHistorySize]; + private static readonly POINTER_PEN_INFO[] s_historyPenInfos = new POINTER_PEN_INFO[MaxPointerHistorySize]; + private static readonly POINTER_INFO[] s_historyInfos = new POINTER_INFO[MaxPointerHistorySize]; public WindowImpl() { @@ -138,13 +138,7 @@ namespace Avalonia.Win32 egl.Display is AngleWin32EglDisplay angleDisplay && angleDisplay.PlatformApi == AngleOptions.PlatformApi.DirectX11; - _wmPointerEnabled = Win32Platform.Options.EnableWmPointerEvents - ?? Win32Platform.WindowsVersion >= PlatformConstants.Windows8; - - if (_wmPointerEnabled && !IsMouseInPointerEnabled()) - { - EnableMouseInPointer(true); - } + _wmPointerEnabled = Win32Platform.WindowsVersion >= PlatformConstants.Windows8; CreateWindow(); _framebuffer = new FramebufferManager(_hwnd); @@ -300,6 +294,8 @@ namespace Avalonia.Win32 protected IntPtr Hwnd => _hwnd; + private bool IsMouseInPointerEnabled => _wmPointerEnabled && IsMouseInPointerEnabled(); + public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) { TransparencyLevel = EnableBlur(transparencyLevel); From 6c2b145189115f557e64941d75b571606e76b9ca Mon Sep 17 00:00:00 2001 From: Max Katz Date: Sat, 2 Jul 2022 19:52:39 -0400 Subject: [PATCH 77/78] Remove DottedLineFocusAdorner --- .../Controls/FocusAdorner.xaml | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/Avalonia.Themes.Fluent/Controls/FocusAdorner.xaml b/src/Avalonia.Themes.Fluent/Controls/FocusAdorner.xaml index e6577497da..91bf71ed4d 100644 --- a/src/Avalonia.Themes.Fluent/Controls/FocusAdorner.xaml +++ b/src/Avalonia.Themes.Fluent/Controls/FocusAdorner.xaml @@ -19,16 +19,4 @@ - - - From 1408e521991d0b66cd3d4151da2918a900d058a5 Mon Sep 17 00:00:00 2001 From: Benedikt Stebner Date: Mon, 4 Jul 2022 09:07:44 +0200 Subject: [PATCH 78/78] Add IAddChild support --- .../AvaloniaXamlIlLanguage.cs | 6 ++- .../Avalonia.Markup.Xaml.Loader/xamlil.github | 2 +- .../Avalonia.Markup.Xaml.csproj | 1 + src/Markup/Avalonia.Markup.Xaml/IAddChild.cs | 12 +++++ .../Xaml/BasicTests.cs | 51 +++++++++++++++++++ 5 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 src/Markup/Avalonia.Markup.Xaml/IAddChild.cs diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguage.cs b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguage.cs index 8ed94f6b20..54eac8f59e 100644 --- a/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguage.cs +++ b/src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguage.cs @@ -41,7 +41,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions }, WhitespaceSignificantCollectionAttributes = { - typeSystem.GetType("Avalonia.Metadata.WhitespaceSignificantCollectionAttribute") + typeSystem.GetType("Avalonia.Metadata.WhitespaceSignificantCollectionAttribute") }, TrimSurroundingWhitespaceAttributes = { @@ -56,7 +56,7 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions XmlNamespaceInfoProvider = typeSystem.GetType("Avalonia.Markup.Xaml.XamlIl.Runtime.IAvaloniaXamlIlXmlNamespaceInfoProvider"), - DeferredContentPropertyAttributes = {typeSystem.GetType("Avalonia.Metadata.TemplateContentAttribute")}, + DeferredContentPropertyAttributes = { typeSystem.GetType("Avalonia.Metadata.TemplateContentAttribute") }, DeferredContentExecutorCustomizationDefaultTypeParameter = typeSystem.GetType("Avalonia.Controls.IControl"), DeferredContentExecutorCustomizationTypeParameterDeferredContentAttributePropertyNames = new List { @@ -70,6 +70,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions }, InnerServiceProviderFactoryMethod = runtimeHelpers.FindMethod(m => m.Name == "CreateInnerServiceProviderV1"), + IAddChild = typeSystem.GetType("Avalonia.Markup.Xaml.IAddChild"), + IAddChildOfT = typeSystem.GetType("Avalonia.Markup.Xaml.IAddChild`1") }; rv.CustomAttributeResolver = new AttributeResolver(typeSystem, rv); diff --git a/src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github b/src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github index daaac590e0..a4e6be2d14 160000 --- a/src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github +++ b/src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github @@ -1 +1 @@ -Subproject commit daaac590e078967b78045f74c38ef046d00d8582 +Subproject commit a4e6be2d1407abec4f35fcb208848830ce513ead diff --git a/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj b/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj index 30d321426f..c35cbc35c0 100644 --- a/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj +++ b/src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj @@ -15,6 +15,7 @@ + diff --git a/src/Markup/Avalonia.Markup.Xaml/IAddChild.cs b/src/Markup/Avalonia.Markup.Xaml/IAddChild.cs new file mode 100644 index 0000000000..993eb6142d --- /dev/null +++ b/src/Markup/Avalonia.Markup.Xaml/IAddChild.cs @@ -0,0 +1,12 @@ +namespace Avalonia.Markup.Xaml +{ + public interface IAddChild + { + void AddChild(object child); + } + + public interface IAddChild : IAddChild + { + void AddChild(T child); + } +} diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BasicTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BasicTests.cs index f12785a7ce..bed5f19ecb 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BasicTests.cs +++ b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BasicTests.cs @@ -958,6 +958,29 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml Assert.Equal("Foo", toolTip.Content); } + [Fact] + public void AddChild_Child_Is_Set() + { + var xaml = @"Foo"; + + var target = AvaloniaRuntimeXamlLoader.Parse(xaml); + + Assert.NotNull(target); + Assert.Equal("Foo", target.Child); + } + + [Fact] + public void AddChildOfT_Child_Is_Set() + { + var xaml = @"Foo"; + + var target = AvaloniaRuntimeXamlLoader.Parse(xaml); + + Assert.NotNull(target); + Assert.Null(target.Child); + Assert.Equal("Foo", target.Text); + } + private class SelectedItemsViewModel : INotifyPropertyChanged { public string[] Items { get; set; } @@ -977,6 +1000,34 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml } } } + + public class ObjectWithAddChild : IAddChild + { + public object Child { get; set; } + + void IAddChild.AddChild(object child) + { + Child = child; + } + } + + public class ObjectWithAddChildOfT : IAddChild + { + public string Text { get; set; } + + public object Child { get; set; } + + void IAddChild.AddChild(object child) + { + Child = child; + } + + void IAddChild.AddChild(string child) + { + Text = child; + } + } + public class BasicTestsAttachedPropertyHolder { public static AvaloniaProperty FooProperty =