trying to create a 3D animated or interactive Dash-style visualization that clearly shows MQPA works—from raw molecular/environmental data, through classical prep, quantum processing, and final visualization.

MQPA: A Hybrid Quantum-Classical Workflow Visualization

MQPA (Molecular Quantum Particle Algorithm) integrates classical computing and quantum simulation to process molecular and environmental data. The following is a plan for a single 3D-rendered animation (or interactive visualization) demonstrating how MQPA works, suitable for a live presentation. This visual pipeline flows from data inputclassical preparationquantum circuit simulationresults, highlighting the hybrid nature of MQPA. Key quantum concepts like superposition and entanglement are illustrated with intuitive metaphors (e.g. a spinning coin and linked particles) to keep it accessible for a general audience.

Visualization Flow: From Data to Results

  1. Molecular/Environmental Data Input: The animation begins on the left with numerous small particles (points) representing raw input data – for example, molecule structures or environmental sensor readings. These data-points are animated in a cluster, moving from left to right. This movement introduces the pipeline flow, showing data streaming into the system. At this stage, the points might be colored uniformly (e.g. blue) to indicate unprocessed, raw data. The audience sees a cloud of “data particles” entering the pipeline, establishing the context of incoming information.

  2. Classical Data Preparation: As the data particles reach the next section (classical processing), they change in appearance – for instance, converging closer together or changing color (e.g. to orange) – to signify transformation by classical computing steps. This classical phase could involve data cleaning, feature scaling, or encoding that prepares the information for quantum processing. Visually, you might show the particles becoming more organized (e.g. tighter cluster or aligned), indicating that a conventional computer has structured the data. This highlights the classical part of the hybrid system (performed on a normal computer), which precedes any quantum action. The separation of this stage underscores that MQPA leverages classical computing where appropriate before invoking quantum resources.

  3. Quantum Circuit Simulation: Next, the data enters the quantum simulation stage (center of the visual). Here the animation emphasizes uniquely quantum phenomena:

    • Superposition: Some particles enter a special state where they seem to exist in two states at once. For example, one of the data particles is surrounded by a faint, spinning transparent sphere – akin to a qubit’s Bloch sphere – conveying that it’s now in a superposition of 0 and 1. In the analogy, this is like a coin flipped in the air, representing both heads and tails simultaneously until measured (quantum gate - What are classical analogies for the notions of superposition, entanglement, and interference? - Quantum Computing Stack Exchange). All the data-points at this quantum stage might spread out more widely (e.g. the cluster expands), illustrating that the quantum algorithm is exploring many possibilities in parallel. We optionally overlay a simple formula like |ψ⟩ = α|0⟩ + β|1⟩ near the particle in superposition, reinforcing that a qubit’s state is a combination of 0 and 1 states.
    • Entanglement: To demonstrate entanglement, a few pairs of particles are visually linked by glowing lines. These indicate that certain qubit-pairs have become correlated – changing one would instantaneously affect the other, as if the two were connected by an invisible thread. This is analogous to two coins tossed in sync such that knowing the outcome of one tells you the outcome of the other, no matter how far apart they are (quantum gate - What are classical analogies for the notions of superposition, entanglement, and interference? - Quantum Computing Stack Exchange). The animation might highlight two such entangled pairs (perhaps with a different color connection or a slight halo on those particles) to show the concept clearly without overwhelming the viewer.
    • Quantum Processing: The quantum circuit itself can be suggested with subtle imagery. For instance, the background could show a faint circuit diagram or quantum gate icons, and the data particles passing through this region could trigger small flashes or changes, implying quantum operations are being applied. The goal is to convey that in this stage, a quantum computer handles the data, leveraging superposition and entanglement to perform computations that explore combinations of molecular interactions in ways a classical computer can’t. In essence, the qubits (represented by our particles) utilize quantum effects to evaluate many potential outcomes simultaneously, capturing complex molecular behaviors (like electron-electron interactions) that classical simulations would need heavy approximations for (How quantum computers simulate at the atomic level). Despite using such advanced concepts, the visual remains understandable: the spinning coin (superposition) and connected pairs (entanglement) serve as intuitive metaphors for non-technical viewers.
  4. Results Visualization: Finally, the processed data emerges on the right side as output results. The particles (now colored, say, green) flow into this output stage and might reconverge or arrange into a meaningful pattern (for example, forming a bar chart, map overlay, or simply clustering to indicate a result set). At this point, all quantum-specific imagery (the superposition sphere, entanglement links) fades away – signifying that the quantum calculation is complete and we’re back in the classical realm with tangible results. This could be depicted by the particles slowing down and settling, or an overlay of a simple graph or map that these results inform. The visual message is that the insights have been extracted from the data: after the hybrid quantum-classical processing, we have a result that can be interpreted in classical terms (for instance, a predicted molecular structure, a risk map of an environmental factor, etc.). This brings the focus back to the real-world context, completing the left-to-right narrative from raw data to actionable insight.

Throughout this flow, labels or color shifts differentiate the classical vs. quantum sections, reinforcing the hybrid nature. The x-axis of the 3D scene can be labeled with the stages “Input”, “Classical Prep”, “Quantum Sim”, and “Results” to orient the audience. By the end of the animation, the audience has seen data enter, get refined, undergo quantum magic, and come out as a useful outcome.

Key Visual Elements and Metaphors

  • Hybrid Pipeline (Classical + Quantum): The visualization distinctly separates the classical processing phase and the quantum simulation phase. For example, the background or particle color changes when moving from classical to quantum, and text labels (“Classical Computer” vs “Quantum Computer”) might appear at the top of each region. This makes it clear that MQPA is a hybrid algorithm leveraging both classical and quantum computing in tandem (How quantum computers simulate at the atomic level). The classical part is depicted with more orderly, conventional visuals (regular clustering of data, perhaps a CPU icon), whereas the quantum part introduces flashy, futuristic elements (glowing connections, a swirling sphere) to suggest the more exotic quantum operations.

  • Animated Data Flow: The data is shown as flowing left-to-right in a continuous animation. This directional movement provides a visual narrative – akin to an assembly line – that the audience can follow. It starts with scattered input particles that gradually move through each stage. Arrows or motion lines can be added to reinforce movement direction. By animating the transition between stages (rather than just showing static steps), we keep viewers engaged and intuitively communicate the progression of time and processing in the pipeline.

  • Superposition (Spinning Coin / Sphere): Superposition is illustrated by showing a qubit in a mixed state. In the visual, this is done by taking one of the quantum-stage particles and giving it a dual representation: for instance, it might rapidly oscillate or split into a faint duplicate, indicating it’s “both states at once.” We use the spinning coin analogy – a coin mid-flip represents heads and tails simultaneously (quantum gate - What are classical analogies for the notions of superposition, entanglement, and interference? - Quantum Computing Stack Exchange). In practice, the animation uses a transparent sphere around a qubit (a Bloch sphere representation) that rotates or shimmers. The sphere conveys that the qubit’s state is spread out (not just a single point) until measurement. This element clearly distinguishes quantum behavior from the binary on/off states in a classical computer. It’s an optional flourish, but it powerfully conveys the idea that during the quantum circuit simulation, data isn’t just 0 or 1, but a combination of possibilities.

  • Entanglement (Connected Particles): Entanglement is depicted by drawing connections (glowing lines or springs) between certain particle pairs in the quantum section. When the particles are entangled, their connection line appears, perhaps pulsing to signify a linkage. If one particle’s state were to collapse, the connected partner would immediately collapse correspondingly – an effect we might hint at by a brief synchronized flash of those particles. The coin analogy for entanglement is two coins tossed such that one landing heads forces the other to land tails (they are linked in outcome) (quantum gate - What are classical analogies for the notions of superposition, entanglement, and interference? - Quantum Computing Stack Exchange). By showing at least one pair of entangled particles, the visualization communicates that MQPA’s quantum step leverages multi-particle correlations. These connections disappear before and after the quantum stage, indicating this phenomenon is unique to the quantum processor’s inner workings.

  • Data Transformation Cues: At each transition, the visualization uses color and position changes to indicate that the data is being transformed. For example, raw data (blue) -> processed data (orange) -> quantum-encoded data (purple) -> output result (green). Similarly, the spatial distribution of the particles changes: they might start dispersed, then cluster (classical cleaned), then spread out (quantum exploring state space), then cluster again or form a pattern (final results). These transformations make it easy to see that something happens to the data at every stage. Even without understanding the technical details, the audience sees “the data looks different now” after each step, reinforcing that each phase adds value (e.g., noise removed in classical prep, new patterns discovered in quantum phase, etc.).

  • Formula and Notation Overlays: To lightly introduce quantum notation without overwhelming the viewer, the visualization can overlay a simple formula during the quantum stage. For instance, when the superposition sphere appears, the text “|ψ⟩ = α|0⟩ + β|1⟩” fades in next to it. This is the standard notation for a qubit state – indicating the qubit is in a combination of the |0⟩ state and |1⟩ state. We keep this text non-intrusive (perhaps semi-transparent and on-screen for only a moment) so that non-technical viewers are not lost. Its purpose is to connect the visual to the concept: those who know basic quantum mechanics will recognize the superposition formula, while others will simply take it as a hint of “some math happening in the quantum part.” We might also display brief labels like “Superposition” and “Entanglement” near the coin and linked particles respectively, just to drive the terminology home in a friendly way.

By combining these elements – moving particles, color changes, a spinning coin/sphere, connecting lines, and a touch of notation – the visualization paints a clear picture of MQPA’s hybrid workflow. It avoids dense mathematics or code on screen, opting instead for an engaging, story-like animation that can be narrated live.

Implementation: Interactive 3D Animation (Python Plotly)

To create this visualization, we can use Python with Plotly for an interactive 3D animation. Plotly allows us to script the positions of particles in 3D space for each stage and animate transitions between stages. Below is a Python code snippet that generates an interactive 3D plot following the described flow. The output can be saved as an HTML file (for viewing in a web browser) or recorded as an MP4 video for embedding into PowerPoint.

import plotly.graph_objects as go
import numpy as np

# Define number of data particles
num_points = 8
np.random.seed(0)  # for reproducibility

# 1. Generate positions for each stage of the pipeline
# Input stage (x ~ 0): scattered points
x_input = np.zeros(num_points)  # around x=0
y_input = np.random.uniform(-1, 1, num_points)    # random spread in y
z_input = np.random.uniform(-1, 1, num_points)    # random spread in z

# Classical stage (x ~ 1): points clustered more tightly (data cleaned/organized)
x_classical = np.ones(num_points) * 1.0           # at x=1
y_classical = y_input * 0.3                       # reduced spread in y (clustered)
z_classical = z_input * 0.3                       # reduced spread in z

# Quantum stage (x ~ 2): points spread out (exploring many states in parallel)
x_quantum = np.ones(num_points) * 2.0             # at x=2
y_quantum = y_input * 2.0                         # increased spread in y
z_quantum = z_input * 2.0                         # increased spread in z

# Output stage (x ~ 3): points possibly re-clustered for results
x_output = np.ones(num_points) * 3.0              # at x=3
y_output = y_input * 0.5 + 0.5                    # moderate spread, shifted upward a bit
z_output = z_input * 0.5                          # moderate spread in z

# 2. Define which points to show as entangled (we'll connect two pairs of points)
entangled_pairs = [(0, 1), (2, 3)]
# Prepare coordinates for line segments between entangled points (at quantum stage positions)
line_x = []; line_y = []; line_z = []
for i, j in entangled_pairs:
    line_x += [x_quantum[i], x_quantum[j], None]   # None as a break in the line
    line_y += [y_quantum[i], y_quantum[j], None]
    line_z += [z_quantum[i], z_quantum[j], None]

# 3. Create a Bloch sphere representation for superposition around one particle (e.g., particle 0)
center_idx = 0  # index of the particle to highlight with a sphere
cx, cy, cz = x_quantum[center_idx], y_quantum[center_idx], z_quantum[center_idx]
sphere_r = 0.5  # radius of the sphere
# Generate points on a sphere (for visual effect of a transparent globe)
phi = np.linspace(0, np.pi, 20)
theta = np.linspace(0, 2*np.pi, 40)
sphere_x = []; sphere_y = []; sphere_z = []
for p in phi:
    for t in theta:
        sphere_x.append(cx + sphere_r * np.sin(p) * np.cos(t))
        sphere_y.append(cy + sphere_r * np.sin(p) * np.sin(t))
        sphere_z.append(cz + sphere_r * np.cos(p))

# 4. Prepare a text label for the superposition formula, positioned just above the sphere
text_label = "|ψ⟩ = α|0⟩ + β|1⟩"
text_x = [cx]                          # same x as the highlighted qubit
text_y = [cy + sphere_r * 2.0]         # a bit above the sphere
text_z = [cz]                          # same z as the highlighted qubit

# 5. Create scatter traces for:
#    - Data particles (will update positions per frame)
#    - Entanglement lines (appear in quantum stage)
#    - Sphere points (appear in quantum stage)
#    - Text label (appears in quantum stage)
data_trace = go.Scatter3d(x=x_input, y=y_input, z=z_input, mode='markers',
                          marker=dict(size=8, color='blue'), name="Data")
entanglement_trace = go.Scatter3d(x=[], y=[], z=[], mode='lines',
                                  line=dict(color='red', width=4),
                                  name="Entanglement", visible=False)
sphere_trace = go.Scatter3d(x=[], y=[], z=[], mode='markers',
                             marker=dict(size=2, color='rgba(100,150,255,0.3)'),
                             name="Bloch Sphere", visible=False)
text_trace = go.Scatter3d(x=[], y=[], z=[], mode='text',
                          text=[], textfont=dict(color='black', size=16),
                          name="Superposition Formula", visible=False)

# 6. Initialize figure with all traces
fig = go.Figure(data=[data_trace, entanglement_trace, sphere_trace, text_trace])

# Customize 3D axes: label the stages on the x-axis, hide y/z tick labels for clarity
fig.update_layout(
    scene=dict(
        xaxis=dict(title="", tickmode='array',
                   tickvals=[0, 1, 2, 3],
                   ticktext=["Input Data", "Classical Prep", "Quantum Sim", "Results"]),
        yaxis=dict(title="", showticklabels=False),
        zaxis=dict(title="", showticklabels=False),
    ),
    margin=dict(l=0, r=0, b=0, t=0)  # tight layout
)

# 7. Define animation frames for each stage of the pipeline
fig.frames = [
    # Frame 0: Input stage
    go.Frame(name="Input", data=[
        go.Scatter3d(x=x_input, y=y_input, z=z_input,
                     marker=dict(color='blue')),               # data points blue at input
        go.Scatter3d(x=[], y=[], z=[]),                        # entanglement (hidden)
        go.Scatter3d(x=[], y=[], z=[]),                        # sphere (hidden)
        go.Scatter3d(x=[], y=[], z=[], text=[])                # text (hidden)
    ]),
    # Frame 1: Classical stage
    go.Frame(name="Classical", data=[
        go.Scatter3d(x=x_classical, y=y_classical, z=z_classical,
                     marker=dict(color='orange')),             # data points turn orange
        go.Scatter3d(x=[], y=[], z=[]),                        # entanglement hidden
        go.Scatter3d(x=[], y=[], z=[]),                        # sphere hidden
        go.Scatter3d(x=[], y=[], z=[], text=[])                # text hidden
    ]),
    # Frame 2: Quantum stage
    go.Frame(name="Quantum", data=[
        go.Scatter3d(x=x_quantum, y=y_quantum, z=z_quantum,
                     marker=dict(color='purple')),             # data points turn purple
        go.Scatter3d(x=line_x, y=line_y, z=line_z),             # entanglement lines visible
        go.Scatter3d(x=sphere_x, y=sphere_y, z=sphere_z),       # sphere points visible
        go.Scatter3d(x=text_x, y=text_y, z=text_z, text=[text_label])  # formula text visible
    ]),
    # Frame 3: Results stage
    go.Frame(name="Results", data=[
        go.Scatter3d(x=x_output, y=y_output, z=z_output,
                     marker=dict(color='green')),              # data points turn green for output
        go.Scatter3d(x=[], y=[], z=[]),                        # entanglement off
        go.Scatter3d(x=[], y=[], z=[]),                        # sphere off
        go.Scatter3d(x=[], y=[], z=[], text=[])                # text off
    ])
]

# 8. Add play button and slider for interactivity
fig.update_layout(
    updatemenus=[dict(type="buttons",
                      buttons=[dict(label="Play", method="animate",
                                    args=[None, {"frame": {"duration": 1000, "redraw": True},
                                                 "transition": {"duration": 500},
                                                 "fromcurrent": True, "mode": "immediate"}])],
                      x=0.1, y=-0.1, showactive=False)],
    sliders=[dict(steps=[dict(method="animate", label=frame.name,
                              args=[[frame.name], {"frame": {"duration": 1000, "redraw": True},
                                                   "transition": {"duration": 500},
                                                   "mode": "immediate"}])
                         for frame in fig.frames],
                 x=0.1, y=-0.07, xanchor="left", yanchor="top", pad=dict(t=30))]
)

# The figure can be shown in a Jupyter environment or exported to HTML:
# fig.show()  # to display in an interactive environment
fig.write_html("mqpa_visualization.html", auto_play=False, include_plotlyjs=True)
print("Animation ready: open 'mqpa_visualization.html' in a web browser to view.")

How it works: The code above creates an interactive 3D scene with Plotly. It defines four key frames corresponding to the stages of MQPA (Input, Classical, Quantum, Results). In each frame, the positions and colors of the data-point markers are updated: - Initially, points are at x=0 (input side) and colored blue. - After classical prep, points move to x=1 and turn orange (indicating a classical transformation). - In the quantum frame, points shift to x=2 (quantum processor side) and turn purple. The entanglement lines (red connecting lines) and the sphere + formula text appear in this frame only. - In the results frame, points move to x=3 and turn green, while the sphere, links, and text are hidden (since those were only part of the quantum process).

We added a slider and play button so the presenter can either let the animation play or manually step through each stage. The 3D plot is interactive – one can click and drag to rotate the view, which is useful if the presenter wants to show the audience different angles of the 3D scene. By default, the axes are labeled with the stage names (“Input Data”, “Classical Prep”, etc.) along the x-axis, and we hid the y/z tick labels to reduce clutter (since the y,z coordinates aren’t conceptually important beyond showing relative positioning).

Output: Running this script will generate an HTML file named mqpa_visualization.html. You can open that file in any modern web browser to view the interactive animation. In the browser, you’ll see the data particles and can use the play button or slider to navigate the pipeline from left (Input) to right (Results). The entire sequence can also be paused at each step, which is ideal during a live talk — you can stop, rotate the view, and discuss what’s happening (for example, pausing at the Quantum stage to explain superposition and entanglement with the visual aids).

Using the Visualization in a Presentation

This visualization is designed to be presentation-friendly. Here are a few tips on using it: - In PowerPoint: If you prefer a static video, you can record the animation (e.g., using Plotly’s built-in video export or a screen recording) to get an MP4 file. Embed the video in your slide so it auto-plays, or click through frame-by-frame using the slider for a guided explanation. - Live Demo Mode: Because the output is an HTML file, you can present it live by opening it in a web browser during your talk. This allows you to interact (rotate the 3D view, replay the animation, etc.) in real-time. It can make the demo more engaging, as you can respond to audience requests like “what happens if we look from this angle?”. - Narration Cues: The visualization aligns with typical MQPA narration. For example, as the blue points appear and move, you might say “Here our raw molecular and environmental data comes in.” When the points turn orange at x=1, you’d explain “a classical computer cleans and prepares the data (orange)…”. At the quantum stage, point out the superposition (spinning sphere around a qubit) and entanglement (red linking lines) – this is a perfect time to use the coin analogies (flipping coin for superposition, linked coins for entanglement) to reinforce understanding (quantum gate - What are classical analogies for the notions of superposition, entanglement, and interference? - Quantum Computing Stack Exchange) (quantum gate - What are classical analogies for the notions of superposition, entanglement, and interference? - Quantum Computing Stack Exchange). Finally, as the points turn green and settle at the output, you conclude with how the results are obtained and can be visualized classically.

By following this flow and utilizing the provided code, you will have a compelling 3D animation that clearly demonstrates how MQPA works. It visually encapsulates the essence of a hybrid quantum-classical algorithm turning raw environmental/molecular data into meaningful results, in a way that is both educational and engaging for a general audience. With this in your presentation, abstract concepts like superposition and entanglement become concrete, and the power of combining classical and quantum computing in environmental modeling is made vividly clear. Enjoy your presentation, and best of luck illustrating the future of computing! (How quantum computers simulate at the atomic level)

  1. Access my Original Space:
    • Visit the Quantum Particle Simulator Space: citeturn0search0
  2. ** Space:**
    • On the Space page, click the “Duplicate this Space” button. This will create a copy under your Hugging Face account, allowing you to modify and run it independently.
  3. Review the Source Code:
    • Navigate to the “Files” section of duplicated Space to examine the source code. This will help you understand the structure and functionality of the application.
  4. Set Up new Environment:
    • Ensure you have Python installed on your local machine.

    • Install necessary libraries. The application likely uses libraries such as numpy, matplotlib, and plotly. Install them using pip:

      pip install numpy matplotlib plotly
  5. Run the Application Locally:
    • Clone my duplicated Space repository to your local machine:

      git clone https://huggingface.co/spaces/texaschikkita/Quantum
    • Navigate to the project directory:

      cd Quantum
    • Run the application script. If the main script is named app.py, execute:

      python app.py
    • This should launch the application locally, allowing you to interact with the Quantum Particle Simulator on your machine.

  6. Modify and Customize:
    • With the application running locally, I can edit the source code to customize features, appearance, or functionality according to model etc needs. Use an IDE or text editor to make changes to the Python scripts.
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQp0cnlpbmcgdG8gY3JlYXRlIGEgM0QgYW5pbWF0ZWQgb3IgaW50ZXJhY3RpdmUgRGFzaC1zdHlsZSB2aXN1YWxpemF0aW9uIHRoYXQgY2xlYXJseSBzaG93cyAgTVFQQSB3b3Jrc+KAlGZyb20gcmF3IG1vbGVjdWxhci9lbnZpcm9ubWVudGFsIGRhdGEsIHRocm91Z2ggY2xhc3NpY2FsIHByZXAsIHF1YW50dW0gcHJvY2Vzc2luZywgYW5kIGZpbmFsIHZpc3VhbGl6YXRpb24uDQoNCg0KDQojIE1RUEE6IEEgSHlicmlkIFF1YW50dW0tQ2xhc3NpY2FsIFdvcmtmbG93IFZpc3VhbGl6YXRpb24NCg0KKipNUVBBIChNb2xlY3VsYXIgUXVhbnR1bSBQYXJ0aWNsZSBBbGdvcml0aG0pKiogaW50ZWdyYXRlcyBjbGFzc2ljYWwgY29tcHV0aW5nIGFuZCBxdWFudHVtIHNpbXVsYXRpb24gdG8gcHJvY2VzcyBtb2xlY3VsYXIgYW5kIGVudmlyb25tZW50YWwgZGF0YS4gVGhlIGZvbGxvd2luZyBpcyBhIHBsYW4gZm9yIGEgc2luZ2xlIDNELXJlbmRlcmVkIGFuaW1hdGlvbiAob3IgaW50ZXJhY3RpdmUgdmlzdWFsaXphdGlvbikgZGVtb25zdHJhdGluZyAqKmhvdyBNUVBBIHdvcmtzKiosIHN1aXRhYmxlIGZvciBhIGxpdmUgcHJlc2VudGF0aW9uLiBUaGlzIHZpc3VhbCBwaXBlbGluZSBmbG93cyBmcm9tICoqZGF0YSBpbnB1dCoqIOKGkiAqKmNsYXNzaWNhbCBwcmVwYXJhdGlvbioqIOKGkiAqKnF1YW50dW0gY2lyY3VpdCBzaW11bGF0aW9uKiog4oaSICoqcmVzdWx0cyoqLCBoaWdobGlnaHRpbmcgdGhlIGh5YnJpZCBuYXR1cmUgb2YgTVFQQS4gS2V5IHF1YW50dW0gY29uY2VwdHMgbGlrZSAqc3VwZXJwb3NpdGlvbiogYW5kICplbnRhbmdsZW1lbnQqIGFyZSBpbGx1c3RyYXRlZCB3aXRoIGludHVpdGl2ZSBtZXRhcGhvcnMgKGUuZy4gYSBzcGlubmluZyBjb2luIGFuZCBsaW5rZWQgcGFydGljbGVzKSB0byBrZWVwIGl0IGFjY2Vzc2libGUgZm9yIGEgZ2VuZXJhbCBhdWRpZW5jZS4NCg0KIyMgVmlzdWFsaXphdGlvbiBGbG93OiBGcm9tIERhdGEgdG8gUmVzdWx0cw0KDQoxLiAqKk1vbGVjdWxhci9FbnZpcm9ubWVudGFsIERhdGEgSW5wdXQ6KiogVGhlIGFuaW1hdGlvbiBiZWdpbnMgb24gdGhlIGxlZnQgd2l0aCBudW1lcm91cyBzbWFsbCBwYXJ0aWNsZXMgKHBvaW50cykgcmVwcmVzZW50aW5nIHJhdyBpbnB1dCBkYXRhIOKAkyBmb3IgZXhhbXBsZSwgbW9sZWN1bGUgc3RydWN0dXJlcyBvciBlbnZpcm9ubWVudGFsIHNlbnNvciByZWFkaW5ncy4gVGhlc2UgZGF0YS1wb2ludHMgYXJlIGFuaW1hdGVkIGluIGEgY2x1c3RlciwgbW92aW5nIGZyb20gbGVmdCB0byByaWdodC4gVGhpcyBtb3ZlbWVudCBpbnRyb2R1Y2VzIHRoZSBwaXBlbGluZSBmbG93LCBzaG93aW5nIGRhdGEgc3RyZWFtaW5nIGludG8gdGhlIHN5c3RlbS4gQXQgdGhpcyBzdGFnZSwgdGhlIHBvaW50cyBtaWdodCBiZSBjb2xvcmVkIHVuaWZvcm1seSAoZS5nLiBibHVlKSB0byBpbmRpY2F0ZSB1bnByb2Nlc3NlZCwgcmF3IGRhdGEuIFRoZSBhdWRpZW5jZSBzZWVzIGEgY2xvdWQgb2Yg4oCcZGF0YSBwYXJ0aWNsZXPigJ0gZW50ZXJpbmcgdGhlIHBpcGVsaW5lLCBlc3RhYmxpc2hpbmcgdGhlIGNvbnRleHQgb2YgKmluY29taW5nIGluZm9ybWF0aW9uKi4gDQoNCjIuICoqQ2xhc3NpY2FsIERhdGEgUHJlcGFyYXRpb246KiogQXMgdGhlIGRhdGEgcGFydGljbGVzIHJlYWNoIHRoZSBuZXh0IHNlY3Rpb24gKGNsYXNzaWNhbCBwcm9jZXNzaW5nKSwgdGhleSBjaGFuZ2UgaW4gYXBwZWFyYW5jZSDigJMgZm9yIGluc3RhbmNlLCBjb252ZXJnaW5nIGNsb3NlciB0b2dldGhlciBvciBjaGFuZ2luZyBjb2xvciAoZS5nLiB0byBvcmFuZ2UpIOKAkyB0byBzaWduaWZ5IHRyYW5zZm9ybWF0aW9uIGJ5IGNsYXNzaWNhbCBjb21wdXRpbmcgc3RlcHMuIFRoaXMgY2xhc3NpY2FsIHBoYXNlIGNvdWxkIGludm9sdmUgZGF0YSBjbGVhbmluZywgZmVhdHVyZSBzY2FsaW5nLCBvciBlbmNvZGluZyB0aGF0IHByZXBhcmVzIHRoZSBpbmZvcm1hdGlvbiBmb3IgcXVhbnR1bSBwcm9jZXNzaW5nLiBWaXN1YWxseSwgeW91IG1pZ2h0IHNob3cgdGhlIHBhcnRpY2xlcyBiZWNvbWluZyBtb3JlIG9yZ2FuaXplZCAoZS5nLiB0aWdodGVyIGNsdXN0ZXIgb3IgYWxpZ25lZCksIGluZGljYXRpbmcgdGhhdCBhIGNvbnZlbnRpb25hbCBjb21wdXRlciBoYXMgc3RydWN0dXJlZCB0aGUgZGF0YS4gVGhpcyBoaWdobGlnaHRzIHRoZSAqY2xhc3NpY2FsKiBwYXJ0IG9mIHRoZSBoeWJyaWQgc3lzdGVtIChwZXJmb3JtZWQgb24gYSBub3JtYWwgY29tcHV0ZXIpLCB3aGljaCBwcmVjZWRlcyBhbnkgcXVhbnR1bSBhY3Rpb24uIFRoZSBzZXBhcmF0aW9uIG9mIHRoaXMgc3RhZ2UgdW5kZXJzY29yZXMgdGhhdCBNUVBBIGxldmVyYWdlcyBjbGFzc2ljYWwgY29tcHV0aW5nIHdoZXJlIGFwcHJvcHJpYXRlIGJlZm9yZSBpbnZva2luZyBxdWFudHVtIHJlc291cmNlcy4NCg0KMy4gKipRdWFudHVtIENpcmN1aXQgU2ltdWxhdGlvbjoqKiBOZXh0LCB0aGUgZGF0YSBlbnRlcnMgdGhlIHF1YW50dW0gc2ltdWxhdGlvbiBzdGFnZSAoY2VudGVyIG9mIHRoZSB2aXN1YWwpLiBIZXJlIHRoZSBhbmltYXRpb24gZW1waGFzaXplcyB1bmlxdWVseSBxdWFudHVtIHBoZW5vbWVuYToNCiAgIC0gKipTdXBlcnBvc2l0aW9uOioqIFNvbWUgcGFydGljbGVzIGVudGVyIGEgc3BlY2lhbCBzdGF0ZSB3aGVyZSB0aGV5IHNlZW0gdG8gZXhpc3QgaW4gdHdvIHN0YXRlcyBhdCBvbmNlLiBGb3IgZXhhbXBsZSwgb25lIG9mIHRoZSBkYXRhIHBhcnRpY2xlcyBpcyBzdXJyb3VuZGVkIGJ5IGEgZmFpbnQsIHNwaW5uaW5nIHRyYW5zcGFyZW50IHNwaGVyZSDigJMgYWtpbiB0byBhIHF1Yml04oCZcyBCbG9jaCBzcGhlcmUg4oCTIGNvbnZleWluZyB0aGF0IGl04oCZcyBub3cgaW4gYSBzdXBlcnBvc2l0aW9uIG9mIDAgYW5kIDEuIEluIHRoZSBhbmFsb2d5LCB0aGlzIGlzIGxpa2UgYSBjb2luIGZsaXBwZWQgaW4gdGhlIGFpciwgcmVwcmVzZW50aW5nIGJvdGggaGVhZHMgKmFuZCogdGFpbHMgc2ltdWx0YW5lb3VzbHkgdW50aWwgbWVhc3VyZWQgKFtxdWFudHVtIGdhdGUgLSBXaGF0IGFyZSBjbGFzc2ljYWwgYW5hbG9naWVzIGZvciB0aGUgbm90aW9ucyBvZiBzdXBlcnBvc2l0aW9uLCBlbnRhbmdsZW1lbnQsIGFuZCBpbnRlcmZlcmVuY2U/IC0gUXVhbnR1bSBDb21wdXRpbmcgU3RhY2sgRXhjaGFuZ2VdKGh0dHBzOi8vcXVhbnR1bWNvbXB1dGluZy5zdGFja2V4Y2hhbmdlLmNvbS9xdWVzdGlvbnMvMzc5Nzcvd2hhdC1hcmUtY2xhc3NpY2FsLWFuYWxvZ2llcy1mb3ItdGhlLW5vdGlvbnMtb2Ytc3VwZXJwb3NpdGlvbi1lbnRhbmdsZW1lbnQtYW5kIzp+OnRleHQ9U3VwZXJwb3NpdGlvbiUzQSUyMEltYWdpbmUlMjBhJTIwY29pbiUyMGZsaXBwZWQsY29sbGFwc2VzJTIwdG8lMjBhJTIwc2luZ2xlJTIwb3V0Y29tZSkpLiBBbGwgdGhlIGRhdGEtcG9pbnRzIGF0IHRoaXMgcXVhbnR1bSBzdGFnZSBtaWdodCBzcHJlYWQgb3V0IG1vcmUgd2lkZWx5IChlLmcuIHRoZSBjbHVzdGVyIGV4cGFuZHMpLCBpbGx1c3RyYXRpbmcgdGhhdCB0aGUgcXVhbnR1bSBhbGdvcml0aG0gaXMgZXhwbG9yaW5nIG1hbnkgcG9zc2liaWxpdGllcyBpbiBwYXJhbGxlbC4gV2Ugb3B0aW9uYWxseSBvdmVybGF5IGEgc2ltcGxlIGZvcm11bGEgbGlrZSAqKnzPiOKfqSA9IM6xfDDin6kgKyDOsnwx4p+pKiogbmVhciB0aGUgcGFydGljbGUgaW4gc3VwZXJwb3NpdGlvbiwgcmVpbmZvcmNpbmcgdGhhdCBhIHF1Yml04oCZcyBzdGF0ZSBpcyBhIGNvbWJpbmF0aW9uIG9mIDAgYW5kIDEgc3RhdGVzLg0KICAgLSAqKkVudGFuZ2xlbWVudDoqKiBUbyBkZW1vbnN0cmF0ZSBlbnRhbmdsZW1lbnQsIGEgZmV3IHBhaXJzIG9mIHBhcnRpY2xlcyBhcmUgdmlzdWFsbHkgbGlua2VkIGJ5IGdsb3dpbmcgbGluZXMuIFRoZXNlIGluZGljYXRlIHRoYXQgY2VydGFpbiBxdWJpdC1wYWlycyBoYXZlIGJlY29tZSBjb3JyZWxhdGVkIOKAkyBjaGFuZ2luZyBvbmUgd291bGQgaW5zdGFudGFuZW91c2x5IGFmZmVjdCB0aGUgb3RoZXIsIGFzIGlmIHRoZSB0d28gd2VyZSBjb25uZWN0ZWQgYnkgYW4gaW52aXNpYmxlIHRocmVhZC4gVGhpcyBpcyBhbmFsb2dvdXMgdG8gdHdvIGNvaW5zIHRvc3NlZCBpbiBzeW5jIHN1Y2ggdGhhdCBrbm93aW5nIHRoZSBvdXRjb21lIG9mIG9uZSB0ZWxscyB5b3UgdGhlIG91dGNvbWUgb2YgdGhlIG90aGVyLCBubyBtYXR0ZXIgaG93IGZhciBhcGFydCB0aGV5IGFyZSAoW3F1YW50dW0gZ2F0ZSAtIFdoYXQgYXJlIGNsYXNzaWNhbCBhbmFsb2dpZXMgZm9yIHRoZSBub3Rpb25zIG9mIHN1cGVycG9zaXRpb24sIGVudGFuZ2xlbWVudCwgYW5kIGludGVyZmVyZW5jZT8gLSBRdWFudHVtIENvbXB1dGluZyBTdGFjayBFeGNoYW5nZV0oaHR0cHM6Ly9xdWFudHVtY29tcHV0aW5nLnN0YWNrZXhjaGFuZ2UuY29tL3F1ZXN0aW9ucy8zNzk3Ny93aGF0LWFyZS1jbGFzc2ljYWwtYW5hbG9naWVzLWZvci10aGUtbm90aW9ucy1vZi1zdXBlcnBvc2l0aW9uLWVudGFuZ2xlbWVudC1hbmQjOn46dGV4dD1FbnRhbmdsZW1lbnQlM0ElMjBDb25zaWRlciUyMHR3byUyMGNvaW5zJTIwdG9zc2VkLGNvcnJlbGF0aW9uJTIwd2l0aG91dCUyMGRpcmVjdCUyMGNhdXNhbCUyMGluZmx1ZW5jZSkpLiBUaGUgYW5pbWF0aW9uIG1pZ2h0IGhpZ2hsaWdodCB0d28gc3VjaCBlbnRhbmdsZWQgcGFpcnMgKHBlcmhhcHMgd2l0aCBhIGRpZmZlcmVudCBjb2xvciBjb25uZWN0aW9uIG9yIGEgc2xpZ2h0IGhhbG8gb24gdGhvc2UgcGFydGljbGVzKSB0byBzaG93IHRoZSBjb25jZXB0IGNsZWFybHkgd2l0aG91dCBvdmVyd2hlbG1pbmcgdGhlIHZpZXdlci4NCiAgIC0gKipRdWFudHVtIFByb2Nlc3Npbmc6KiogVGhlIHF1YW50dW0gY2lyY3VpdCBpdHNlbGYgY2FuIGJlIHN1Z2dlc3RlZCB3aXRoIHN1YnRsZSBpbWFnZXJ5LiBGb3IgaW5zdGFuY2UsIHRoZSBiYWNrZ3JvdW5kIGNvdWxkIHNob3cgYSBmYWludCBjaXJjdWl0IGRpYWdyYW0gb3IgcXVhbnR1bSBnYXRlIGljb25zLCBhbmQgdGhlIGRhdGEgcGFydGljbGVzIHBhc3NpbmcgdGhyb3VnaCB0aGlzIHJlZ2lvbiBjb3VsZCB0cmlnZ2VyIHNtYWxsIGZsYXNoZXMgb3IgY2hhbmdlcywgaW1wbHlpbmcgcXVhbnR1bSBvcGVyYXRpb25zIGFyZSBiZWluZyBhcHBsaWVkLiBUaGUgZ29hbCBpcyB0byBjb252ZXkgdGhhdCBpbiB0aGlzIHN0YWdlLCBhICoqcXVhbnR1bSBjb21wdXRlcioqIGhhbmRsZXMgdGhlIGRhdGEsIGxldmVyYWdpbmcgc3VwZXJwb3NpdGlvbiBhbmQgZW50YW5nbGVtZW50IHRvIHBlcmZvcm0gY29tcHV0YXRpb25zIHRoYXQgZXhwbG9yZSBjb21iaW5hdGlvbnMgb2YgbW9sZWN1bGFyIGludGVyYWN0aW9ucyBpbiB3YXlzIGEgY2xhc3NpY2FsIGNvbXB1dGVyIGNhbuKAmXQuIEluIGVzc2VuY2UsIHRoZSBxdWJpdHMgKHJlcHJlc2VudGVkIGJ5IG91ciBwYXJ0aWNsZXMpIHV0aWxpemUgcXVhbnR1bSBlZmZlY3RzIHRvIGV2YWx1YXRlIG1hbnkgcG90ZW50aWFsIG91dGNvbWVzIHNpbXVsdGFuZW91c2x5LCBjYXB0dXJpbmcgY29tcGxleCBtb2xlY3VsYXIgYmVoYXZpb3JzIChsaWtlIGVsZWN0cm9uLWVsZWN0cm9uIGludGVyYWN0aW9ucykgdGhhdCBjbGFzc2ljYWwgc2ltdWxhdGlvbnMgd291bGQgbmVlZCBoZWF2eSBhcHByb3hpbWF0aW9ucyBmb3IgKFtIb3cgcXVhbnR1bSBjb21wdXRlcnMgc2ltdWxhdGUgYXQgdGhlIGF0b21pYyBsZXZlbF0oaHR0cHM6Ly93d3cucml2ZXJsYW5lLmNvbS9ibG9nL21vZGVsbGluZy1tb2xlY3VsZXMtaG93LXF1YW50dW0tY29tcHV0ZXJzLXNpbXVsYXRlLWF0LXRoZS1hdG9taWMtbGV2ZWwjOn46dGV4dD1UaGUlMjBiaWclMjBhZHZhbnRhZ2UlMjBvZiUyMHF1YW50dW0scXViaXRzJTI5JTIwdG8lMjByZXByZXNlbnQlMjB0aGVtKSkuIERlc3BpdGUgdXNpbmcgc3VjaCBhZHZhbmNlZCBjb25jZXB0cywgdGhlIHZpc3VhbCByZW1haW5zICoqdW5kZXJzdGFuZGFibGUqKjogdGhlIHNwaW5uaW5nIGNvaW4gKHN1cGVycG9zaXRpb24pIGFuZCBjb25uZWN0ZWQgcGFpcnMgKGVudGFuZ2xlbWVudCkgc2VydmUgYXMgaW50dWl0aXZlIG1ldGFwaG9ycyBmb3Igbm9uLXRlY2huaWNhbCB2aWV3ZXJzLg0KDQo0LiAqKlJlc3VsdHMgVmlzdWFsaXphdGlvbjoqKiBGaW5hbGx5LCB0aGUgcHJvY2Vzc2VkIGRhdGEgZW1lcmdlcyBvbiB0aGUgcmlnaHQgc2lkZSBhcyAqKm91dHB1dCByZXN1bHRzKiouIFRoZSBwYXJ0aWNsZXMgKG5vdyBjb2xvcmVkLCBzYXksIGdyZWVuKSBmbG93IGludG8gdGhpcyBvdXRwdXQgc3RhZ2UgYW5kIG1pZ2h0IHJlY29udmVyZ2Ugb3IgYXJyYW5nZSBpbnRvIGEgbWVhbmluZ2Z1bCBwYXR0ZXJuIChmb3IgZXhhbXBsZSwgZm9ybWluZyBhIGJhciBjaGFydCwgbWFwIG92ZXJsYXksIG9yIHNpbXBseSBjbHVzdGVyaW5nIHRvIGluZGljYXRlIGEgcmVzdWx0IHNldCkuIEF0IHRoaXMgcG9pbnQsIGFsbCBxdWFudHVtLXNwZWNpZmljIGltYWdlcnkgKHRoZSBzdXBlcnBvc2l0aW9uIHNwaGVyZSwgZW50YW5nbGVtZW50IGxpbmtzKSBmYWRlcyBhd2F5IOKAkyBzaWduaWZ5aW5nIHRoYXQgdGhlIHF1YW50dW0gY2FsY3VsYXRpb24gaXMgY29tcGxldGUgYW5kIHdl4oCZcmUgYmFjayBpbiB0aGUgY2xhc3NpY2FsIHJlYWxtIHdpdGggdGFuZ2libGUgcmVzdWx0cy4gVGhpcyBjb3VsZCBiZSBkZXBpY3RlZCBieSB0aGUgcGFydGljbGVzIHNsb3dpbmcgZG93biBhbmQgc2V0dGxpbmcsIG9yIGFuIG92ZXJsYXkgb2YgYSBzaW1wbGUgZ3JhcGggb3IgbWFwIHRoYXQgdGhlc2UgcmVzdWx0cyBpbmZvcm0uIFRoZSB2aXN1YWwgbWVzc2FnZSBpcyB0aGF0IHRoZSAqaW5zaWdodHMqIGhhdmUgYmVlbiBleHRyYWN0ZWQgZnJvbSB0aGUgZGF0YTogYWZ0ZXIgdGhlIGh5YnJpZCBxdWFudHVtLWNsYXNzaWNhbCBwcm9jZXNzaW5nLCB3ZSBoYXZlIGEgcmVzdWx0IHRoYXQgY2FuIGJlIGludGVycHJldGVkIGluIGNsYXNzaWNhbCB0ZXJtcyAoZm9yIGluc3RhbmNlLCBhIHByZWRpY3RlZCBtb2xlY3VsYXIgc3RydWN0dXJlLCBhIHJpc2sgbWFwIG9mIGFuIGVudmlyb25tZW50YWwgZmFjdG9yLCBldGMuKS4gVGhpcyBicmluZ3MgdGhlIGZvY3VzIGJhY2sgdG8gdGhlIHJlYWwtd29ybGQgY29udGV4dCwgY29tcGxldGluZyB0aGUgbGVmdC10by1yaWdodCBuYXJyYXRpdmUgZnJvbSByYXcgZGF0YSB0byBhY3Rpb25hYmxlIGluc2lnaHQuDQoNClRocm91Z2hvdXQgdGhpcyBmbG93LCAqKmxhYmVscyBvciBjb2xvciBzaGlmdHMqKiBkaWZmZXJlbnRpYXRlIHRoZSAqKmNsYXNzaWNhbCB2cy4gcXVhbnR1bSoqIHNlY3Rpb25zLCByZWluZm9yY2luZyB0aGUgaHlicmlkIG5hdHVyZS4gVGhlIHgtYXhpcyBvZiB0aGUgM0Qgc2NlbmUgY2FuIGJlIGxhYmVsZWQgd2l0aCB0aGUgc3RhZ2VzIOKAnElucHV04oCdLCDigJxDbGFzc2ljYWwgUHJlcOKAnSwg4oCcUXVhbnR1bSBTaW3igJ0sIGFuZCDigJxSZXN1bHRz4oCdIHRvIG9yaWVudCB0aGUgYXVkaWVuY2UuIEJ5IHRoZSBlbmQgb2YgdGhlIGFuaW1hdGlvbiwgdGhlIGF1ZGllbmNlIGhhcyBzZWVuIGRhdGEgZW50ZXIsIGdldCByZWZpbmVkLCB1bmRlcmdvIHF1YW50dW0gbWFnaWMsIGFuZCBjb21lIG91dCBhcyBhIHVzZWZ1bCBvdXRjb21lLg0KDQojIyBLZXkgVmlzdWFsIEVsZW1lbnRzIGFuZCBNZXRhcGhvcnMNCg0KLSAqKkh5YnJpZCBQaXBlbGluZSAoQ2xhc3NpY2FsICsgUXVhbnR1bSk6KiogVGhlIHZpc3VhbGl6YXRpb24gZGlzdGluY3RseSBzZXBhcmF0ZXMgdGhlIGNsYXNzaWNhbCBwcm9jZXNzaW5nIHBoYXNlIGFuZCB0aGUgcXVhbnR1bSBzaW11bGF0aW9uIHBoYXNlLiBGb3IgZXhhbXBsZSwgdGhlIGJhY2tncm91bmQgb3IgcGFydGljbGUgY29sb3IgY2hhbmdlcyB3aGVuIG1vdmluZyBmcm9tIGNsYXNzaWNhbCB0byBxdWFudHVtLCBhbmQgdGV4dCBsYWJlbHMgKOKAnENsYXNzaWNhbCBDb21wdXRlcuKAnSB2cyDigJxRdWFudHVtIENvbXB1dGVy4oCdKSBtaWdodCBhcHBlYXIgYXQgdGhlIHRvcCBvZiBlYWNoIHJlZ2lvbi4gVGhpcyBtYWtlcyBpdCBjbGVhciB0aGF0IE1RUEEgaXMgYSAqaHlicmlkKiBhbGdvcml0aG0gbGV2ZXJhZ2luZyBib3RoIGNsYXNzaWNhbCBhbmQgcXVhbnR1bSBjb21wdXRpbmcgaW4gdGFuZGVtIChbSG93IHF1YW50dW0gY29tcHV0ZXJzIHNpbXVsYXRlIGF0IHRoZSBhdG9taWMgbGV2ZWxdKGh0dHBzOi8vd3d3LnJpdmVybGFuZS5jb20vYmxvZy9tb2RlbGxpbmctbW9sZWN1bGVzLWhvdy1xdWFudHVtLWNvbXB1dGVycy1zaW11bGF0ZS1hdC10aGUtYXRvbWljLWxldmVsIzp+OnRleHQ9VGhlJTIwYmlnJTIwYWR2YW50YWdlJTIwb2YlMjBxdWFudHVtLHF1Yml0cyUyOSUyMHRvJTIwcmVwcmVzZW50JTIwdGhlbSkpLiBUaGUgY2xhc3NpY2FsIHBhcnQgaXMgZGVwaWN0ZWQgd2l0aCBtb3JlIG9yZGVybHksIGNvbnZlbnRpb25hbCB2aXN1YWxzIChyZWd1bGFyIGNsdXN0ZXJpbmcgb2YgZGF0YSwgcGVyaGFwcyBhIENQVSBpY29uKSwgd2hlcmVhcyB0aGUgcXVhbnR1bSBwYXJ0IGludHJvZHVjZXMgZmxhc2h5LCBmdXR1cmlzdGljIGVsZW1lbnRzIChnbG93aW5nIGNvbm5lY3Rpb25zLCBhIHN3aXJsaW5nIHNwaGVyZSkgdG8gc3VnZ2VzdCB0aGUgbW9yZSBleG90aWMgcXVhbnR1bSBvcGVyYXRpb25zLg0KDQotICoqQW5pbWF0ZWQgRGF0YSBGbG93OioqIFRoZSBkYXRhIGlzIHNob3duIGFzIGZsb3dpbmcgKipsZWZ0LXRvLXJpZ2h0KiogaW4gYSBjb250aW51b3VzIGFuaW1hdGlvbi4gVGhpcyBkaXJlY3Rpb25hbCBtb3ZlbWVudCBwcm92aWRlcyBhIHZpc3VhbCBuYXJyYXRpdmUg4oCTIGFraW4gdG8gYW4gYXNzZW1ibHkgbGluZSDigJMgdGhhdCB0aGUgYXVkaWVuY2UgY2FuIGZvbGxvdy4gSXQgc3RhcnRzIHdpdGggc2NhdHRlcmVkIGlucHV0IHBhcnRpY2xlcyB0aGF0IGdyYWR1YWxseSBtb3ZlIHRocm91Z2ggZWFjaCBzdGFnZS4gQXJyb3dzIG9yIG1vdGlvbiBsaW5lcyBjYW4gYmUgYWRkZWQgdG8gcmVpbmZvcmNlIG1vdmVtZW50IGRpcmVjdGlvbi4gQnkgYW5pbWF0aW5nIHRoZSB0cmFuc2l0aW9uIGJldHdlZW4gc3RhZ2VzIChyYXRoZXIgdGhhbiBqdXN0IHNob3dpbmcgc3RhdGljIHN0ZXBzKSwgd2Uga2VlcCB2aWV3ZXJzIGVuZ2FnZWQgYW5kIGludHVpdGl2ZWx5IGNvbW11bmljYXRlIHRoZSBwcm9ncmVzc2lvbiBvZiB0aW1lIGFuZCBwcm9jZXNzaW5nIGluIHRoZSBwaXBlbGluZS4NCg0KLSAqKlN1cGVycG9zaXRpb24gKFNwaW5uaW5nIENvaW4gLyBTcGhlcmUpOioqIFN1cGVycG9zaXRpb24gaXMgaWxsdXN0cmF0ZWQgYnkgc2hvd2luZyBhIHF1Yml0IGluIGEgbWl4ZWQgc3RhdGUuIEluIHRoZSB2aXN1YWwsIHRoaXMgaXMgZG9uZSBieSB0YWtpbmcgb25lIG9mIHRoZSBxdWFudHVtLXN0YWdlIHBhcnRpY2xlcyBhbmQgZ2l2aW5nIGl0IGEgZHVhbCByZXByZXNlbnRhdGlvbjogZm9yIGluc3RhbmNlLCBpdCBtaWdodCByYXBpZGx5IG9zY2lsbGF0ZSBvciBzcGxpdCBpbnRvIGEgZmFpbnQgZHVwbGljYXRlLCBpbmRpY2F0aW5nIGl04oCZcyDigJxib3RoIHN0YXRlcyBhdCBvbmNlLuKAnSBXZSB1c2UgdGhlICoqc3Bpbm5pbmcgY29pbioqIGFuYWxvZ3kg4oCTIGEgY29pbiBtaWQtZmxpcCByZXByZXNlbnRzIGhlYWRzIGFuZCB0YWlscyBzaW11bHRhbmVvdXNseSAoW3F1YW50dW0gZ2F0ZSAtIFdoYXQgYXJlIGNsYXNzaWNhbCBhbmFsb2dpZXMgZm9yIHRoZSBub3Rpb25zIG9mIHN1cGVycG9zaXRpb24sIGVudGFuZ2xlbWVudCwgYW5kIGludGVyZmVyZW5jZT8gLSBRdWFudHVtIENvbXB1dGluZyBTdGFjayBFeGNoYW5nZV0oaHR0cHM6Ly9xdWFudHVtY29tcHV0aW5nLnN0YWNrZXhjaGFuZ2UuY29tL3F1ZXN0aW9ucy8zNzk3Ny93aGF0LWFyZS1jbGFzc2ljYWwtYW5hbG9naWVzLWZvci10aGUtbm90aW9ucy1vZi1zdXBlcnBvc2l0aW9uLWVudGFuZ2xlbWVudC1hbmQjOn46dGV4dD1TdXBlcnBvc2l0aW9uJTNBJTIwSW1hZ2luZSUyMGElMjBjb2luJTIwZmxpcHBlZCxjb2xsYXBzZXMlMjB0byUyMGElMjBzaW5nbGUlMjBvdXRjb21lKSkuIEluIHByYWN0aWNlLCB0aGUgYW5pbWF0aW9uIHVzZXMgYSB0cmFuc3BhcmVudCBzcGhlcmUgYXJvdW5kIGEgcXViaXQgKGEgQmxvY2ggc3BoZXJlIHJlcHJlc2VudGF0aW9uKSB0aGF0IHJvdGF0ZXMgb3Igc2hpbW1lcnMuIFRoZSBzcGhlcmUgY29udmV5cyB0aGF0IHRoZSBxdWJpdOKAmXMgc3RhdGUgaXMgc3ByZWFkIG91dCAobm90IGp1c3QgYSBzaW5nbGUgcG9pbnQpIHVudGlsIG1lYXN1cmVtZW50LiBUaGlzIGVsZW1lbnQgY2xlYXJseSBkaXN0aW5ndWlzaGVzIHF1YW50dW0gYmVoYXZpb3IgZnJvbSB0aGUgYmluYXJ5IG9uL29mZiBzdGF0ZXMgaW4gYSBjbGFzc2ljYWwgY29tcHV0ZXIuIEl04oCZcyBhbiBvcHRpb25hbCBmbG91cmlzaCwgYnV0IGl0IHBvd2VyZnVsbHkgY29udmV5cyB0aGUgaWRlYSB0aGF0IGR1cmluZyB0aGUgcXVhbnR1bSBjaXJjdWl0IHNpbXVsYXRpb24sIGRhdGEgaXNu4oCZdCBqdXN0IDAgb3IgMSwgYnV0IGEgY29tYmluYXRpb24gb2YgcG9zc2liaWxpdGllcy4NCg0KLSAqKkVudGFuZ2xlbWVudCAoQ29ubmVjdGVkIFBhcnRpY2xlcyk6KiogRW50YW5nbGVtZW50IGlzIGRlcGljdGVkIGJ5IGRyYXdpbmcgY29ubmVjdGlvbnMgKGdsb3dpbmcgbGluZXMgb3Igc3ByaW5ncykgYmV0d2VlbiBjZXJ0YWluIHBhcnRpY2xlIHBhaXJzIGluIHRoZSBxdWFudHVtIHNlY3Rpb24uIFdoZW4gdGhlIHBhcnRpY2xlcyBhcmUgZW50YW5nbGVkLCB0aGVpciBjb25uZWN0aW9uIGxpbmUgYXBwZWFycywgcGVyaGFwcyBwdWxzaW5nIHRvIHNpZ25pZnkgYSBsaW5rYWdlLiBJZiBvbmUgcGFydGljbGXigJlzIHN0YXRlIHdlcmUgdG8gY29sbGFwc2UsIHRoZSBjb25uZWN0ZWQgcGFydG5lciB3b3VsZCBpbW1lZGlhdGVseSBjb2xsYXBzZSBjb3JyZXNwb25kaW5nbHkg4oCTIGFuIGVmZmVjdCB3ZSBtaWdodCBoaW50IGF0IGJ5IGEgYnJpZWYgc3luY2hyb25pemVkIGZsYXNoIG9mIHRob3NlIHBhcnRpY2xlcy4gVGhlIGNvaW4gYW5hbG9neSBmb3IgZW50YW5nbGVtZW50IGlzIHR3byBjb2lucyB0b3NzZWQgc3VjaCB0aGF0IG9uZSBsYW5kaW5nIGhlYWRzIGZvcmNlcyB0aGUgb3RoZXIgdG8gbGFuZCB0YWlscyAodGhleSBhcmUgbGlua2VkIGluIG91dGNvbWUpIChbcXVhbnR1bSBnYXRlIC0gV2hhdCBhcmUgY2xhc3NpY2FsIGFuYWxvZ2llcyBmb3IgdGhlIG5vdGlvbnMgb2Ygc3VwZXJwb3NpdGlvbiwgZW50YW5nbGVtZW50LCBhbmQgaW50ZXJmZXJlbmNlPyAtIFF1YW50dW0gQ29tcHV0aW5nIFN0YWNrIEV4Y2hhbmdlXShodHRwczovL3F1YW50dW1jb21wdXRpbmcuc3RhY2tleGNoYW5nZS5jb20vcXVlc3Rpb25zLzM3OTc3L3doYXQtYXJlLWNsYXNzaWNhbC1hbmFsb2dpZXMtZm9yLXRoZS1ub3Rpb25zLW9mLXN1cGVycG9zaXRpb24tZW50YW5nbGVtZW50LWFuZCM6fjp0ZXh0PUVudGFuZ2xlbWVudCUzQSUyMENvbnNpZGVyJTIwdHdvJTIwY29pbnMlMjB0b3NzZWQsY29ycmVsYXRpb24lMjB3aXRob3V0JTIwZGlyZWN0JTIwY2F1c2FsJTIwaW5mbHVlbmNlKSkuIEJ5IHNob3dpbmcgYXQgbGVhc3Qgb25lIHBhaXIgb2YgZW50YW5nbGVkIHBhcnRpY2xlcywgdGhlIHZpc3VhbGl6YXRpb24gY29tbXVuaWNhdGVzIHRoYXQgTVFQQeKAmXMgcXVhbnR1bSBzdGVwIGxldmVyYWdlcyBtdWx0aS1wYXJ0aWNsZSBjb3JyZWxhdGlvbnMuIFRoZXNlIGNvbm5lY3Rpb25zIGRpc2FwcGVhciBiZWZvcmUgYW5kIGFmdGVyIHRoZSBxdWFudHVtIHN0YWdlLCBpbmRpY2F0aW5nIHRoaXMgcGhlbm9tZW5vbiBpcyB1bmlxdWUgdG8gdGhlIHF1YW50dW0gcHJvY2Vzc29y4oCZcyBpbm5lciB3b3JraW5ncy4NCg0KLSAqKkRhdGEgVHJhbnNmb3JtYXRpb24gQ3VlczoqKiBBdCBlYWNoIHRyYW5zaXRpb24sIHRoZSB2aXN1YWxpemF0aW9uIHVzZXMgKipjb2xvciBhbmQgcG9zaXRpb24gY2hhbmdlcyoqIHRvIGluZGljYXRlIHRoYXQgdGhlIGRhdGEgaXMgYmVpbmcgdHJhbnNmb3JtZWQuIEZvciBleGFtcGxlLCByYXcgZGF0YSAoYmx1ZSkgLT4gcHJvY2Vzc2VkIGRhdGEgKG9yYW5nZSkgLT4gcXVhbnR1bS1lbmNvZGVkIGRhdGEgKHB1cnBsZSkgLT4gb3V0cHV0IHJlc3VsdCAoZ3JlZW4pLiBTaW1pbGFybHksIHRoZSBzcGF0aWFsIGRpc3RyaWJ1dGlvbiBvZiB0aGUgcGFydGljbGVzIGNoYW5nZXM6IHRoZXkgbWlnaHQgc3RhcnQgZGlzcGVyc2VkLCB0aGVuIGNsdXN0ZXIgKGNsYXNzaWNhbCBjbGVhbmVkKSwgdGhlbiBzcHJlYWQgb3V0IChxdWFudHVtIGV4cGxvcmluZyBzdGF0ZSBzcGFjZSksIHRoZW4gY2x1c3RlciBhZ2FpbiBvciBmb3JtIGEgcGF0dGVybiAoZmluYWwgcmVzdWx0cykuIFRoZXNlIHRyYW5zZm9ybWF0aW9ucyBtYWtlIGl0IGVhc3kgdG8gc2VlIHRoYXQgc29tZXRoaW5nICpoYXBwZW5zKiB0byB0aGUgZGF0YSBhdCBldmVyeSBzdGFnZS4gRXZlbiB3aXRob3V0IHVuZGVyc3RhbmRpbmcgdGhlIHRlY2huaWNhbCBkZXRhaWxzLCB0aGUgYXVkaWVuY2Ugc2VlcyDigJx0aGUgZGF0YSBsb29rcyBkaWZmZXJlbnQgbm934oCdIGFmdGVyIGVhY2ggc3RlcCwgcmVpbmZvcmNpbmcgdGhhdCBlYWNoIHBoYXNlIGFkZHMgdmFsdWUgKGUuZy4sIG5vaXNlIHJlbW92ZWQgaW4gY2xhc3NpY2FsIHByZXAsIG5ldyBwYXR0ZXJucyBkaXNjb3ZlcmVkIGluIHF1YW50dW0gcGhhc2UsIGV0Yy4pLg0KDQotICoqRm9ybXVsYSBhbmQgTm90YXRpb24gT3ZlcmxheXM6KiogVG8gbGlnaHRseSBpbnRyb2R1Y2UgcXVhbnR1bSBub3RhdGlvbiB3aXRob3V0IG92ZXJ3aGVsbWluZyB0aGUgdmlld2VyLCB0aGUgdmlzdWFsaXphdGlvbiBjYW4gb3ZlcmxheSBhIHNpbXBsZSBmb3JtdWxhIGR1cmluZyB0aGUgcXVhbnR1bSBzdGFnZS4gRm9yIGluc3RhbmNlLCB3aGVuIHRoZSBzdXBlcnBvc2l0aW9uIHNwaGVyZSBhcHBlYXJzLCB0aGUgdGV4dCDigJx8z4jin6kgPSDOsXww4p+pICsgzrJ8MeKfqeKAnSBmYWRlcyBpbiBuZXh0IHRvIGl0LiBUaGlzIGlzIHRoZSBzdGFuZGFyZCBub3RhdGlvbiBmb3IgYSBxdWJpdCBzdGF0ZSDigJMgaW5kaWNhdGluZyB0aGUgcXViaXQgaXMgaW4gYSBjb21iaW5hdGlvbiBvZiB0aGUgYHww4p+pYCBzdGF0ZSBhbmQgYHwx4p+pYCBzdGF0ZS4gV2Uga2VlcCB0aGlzIHRleHQgbm9uLWludHJ1c2l2ZSAocGVyaGFwcyBzZW1pLXRyYW5zcGFyZW50IGFuZCBvbi1zY3JlZW4gZm9yIG9ubHkgYSBtb21lbnQpIHNvIHRoYXQgbm9uLXRlY2huaWNhbCB2aWV3ZXJzIGFyZSBub3QgbG9zdC4gSXRzIHB1cnBvc2UgaXMgdG8gKipjb25uZWN0IHRoZSB2aXN1YWwgdG8gdGhlIGNvbmNlcHQqKjogdGhvc2Ugd2hvIGtub3cgYmFzaWMgcXVhbnR1bSBtZWNoYW5pY3Mgd2lsbCByZWNvZ25pemUgdGhlIHN1cGVycG9zaXRpb24gZm9ybXVsYSwgd2hpbGUgb3RoZXJzIHdpbGwgc2ltcGx5IHRha2UgaXQgYXMgYSBoaW50IG9mIOKAnHNvbWUgbWF0aCBoYXBwZW5pbmcgaW4gdGhlIHF1YW50dW0gcGFydC7igJ0gV2UgbWlnaHQgYWxzbyBkaXNwbGF5IGJyaWVmIGxhYmVscyBsaWtlIOKAnFN1cGVycG9zaXRpb27igJ0gYW5kIOKAnEVudGFuZ2xlbWVudOKAnSBuZWFyIHRoZSBjb2luIGFuZCBsaW5rZWQgcGFydGljbGVzIHJlc3BlY3RpdmVseSwganVzdCB0byBkcml2ZSB0aGUgdGVybWlub2xvZ3kgaG9tZSBpbiBhIGZyaWVuZGx5IHdheS4NCg0KQnkgY29tYmluaW5nIHRoZXNlIGVsZW1lbnRzIOKAkyBtb3ZpbmcgcGFydGljbGVzLCBjb2xvciBjaGFuZ2VzLCBhIHNwaW5uaW5nIGNvaW4vc3BoZXJlLCBjb25uZWN0aW5nIGxpbmVzLCBhbmQgYSB0b3VjaCBvZiBub3RhdGlvbiDigJMgdGhlIHZpc3VhbGl6YXRpb24gcGFpbnRzIGEgY2xlYXIgcGljdHVyZSBvZiBNUVBB4oCZcyBoeWJyaWQgd29ya2Zsb3cuIEl0IGF2b2lkcyBkZW5zZSBtYXRoZW1hdGljcyBvciBjb2RlIG9uIHNjcmVlbiwgb3B0aW5nIGluc3RlYWQgZm9yIGFuICoqZW5nYWdpbmcsIHN0b3J5LWxpa2UgYW5pbWF0aW9uKiogdGhhdCBjYW4gYmUgbmFycmF0ZWQgbGl2ZS4NCg0KIyMgSW1wbGVtZW50YXRpb246IEludGVyYWN0aXZlIDNEIEFuaW1hdGlvbiAoUHl0aG9uIFBsb3RseSkNCg0KVG8gY3JlYXRlIHRoaXMgdmlzdWFsaXphdGlvbiwgd2UgY2FuIHVzZSBQeXRob24gd2l0aCBQbG90bHkgZm9yIGFuIGludGVyYWN0aXZlIDNEIGFuaW1hdGlvbi4gUGxvdGx5IGFsbG93cyB1cyB0byBzY3JpcHQgdGhlIHBvc2l0aW9ucyBvZiBwYXJ0aWNsZXMgaW4gM0Qgc3BhY2UgZm9yIGVhY2ggc3RhZ2UgYW5kIGFuaW1hdGUgdHJhbnNpdGlvbnMgYmV0d2VlbiBzdGFnZXMuIEJlbG93IGlzIGEgUHl0aG9uIGNvZGUgc25pcHBldCB0aGF0IGdlbmVyYXRlcyBhbiBpbnRlcmFjdGl2ZSAzRCBwbG90IGZvbGxvd2luZyB0aGUgZGVzY3JpYmVkIGZsb3cuIFRoZSBvdXRwdXQgY2FuIGJlIHNhdmVkIGFzIGFuIEhUTUwgZmlsZSAoZm9yIHZpZXdpbmcgaW4gYSB3ZWIgYnJvd3Nlcikgb3IgcmVjb3JkZWQgYXMgYW4gTVA0IHZpZGVvIGZvciBlbWJlZGRpbmcgaW50byBQb3dlclBvaW50Lg0KDQpgYGBweXRob24NCmltcG9ydCBwbG90bHkuZ3JhcGhfb2JqZWN0cyBhcyBnbw0KaW1wb3J0IG51bXB5IGFzIG5wDQoNCiMgRGVmaW5lIG51bWJlciBvZiBkYXRhIHBhcnRpY2xlcw0KbnVtX3BvaW50cyA9IDgNCm5wLnJhbmRvbS5zZWVkKDApICAjIGZvciByZXByb2R1Y2liaWxpdHkNCg0KIyAxLiBHZW5lcmF0ZSBwb3NpdGlvbnMgZm9yIGVhY2ggc3RhZ2Ugb2YgdGhlIHBpcGVsaW5lDQojIElucHV0IHN0YWdlICh4IH4gMCk6IHNjYXR0ZXJlZCBwb2ludHMNCnhfaW5wdXQgPSBucC56ZXJvcyhudW1fcG9pbnRzKSAgIyBhcm91bmQgeD0wDQp5X2lucHV0ID0gbnAucmFuZG9tLnVuaWZvcm0oLTEsIDEsIG51bV9wb2ludHMpICAgICMgcmFuZG9tIHNwcmVhZCBpbiB5DQp6X2lucHV0ID0gbnAucmFuZG9tLnVuaWZvcm0oLTEsIDEsIG51bV9wb2ludHMpICAgICMgcmFuZG9tIHNwcmVhZCBpbiB6DQoNCiMgQ2xhc3NpY2FsIHN0YWdlICh4IH4gMSk6IHBvaW50cyBjbHVzdGVyZWQgbW9yZSB0aWdodGx5IChkYXRhIGNsZWFuZWQvb3JnYW5pemVkKQ0KeF9jbGFzc2ljYWwgPSBucC5vbmVzKG51bV9wb2ludHMpICogMS4wICAgICAgICAgICAjIGF0IHg9MQ0KeV9jbGFzc2ljYWwgPSB5X2lucHV0ICogMC4zICAgICAgICAgICAgICAgICAgICAgICAjIHJlZHVjZWQgc3ByZWFkIGluIHkgKGNsdXN0ZXJlZCkNCnpfY2xhc3NpY2FsID0gel9pbnB1dCAqIDAuMyAgICAgICAgICAgICAgICAgICAgICAgIyByZWR1Y2VkIHNwcmVhZCBpbiB6DQoNCiMgUXVhbnR1bSBzdGFnZSAoeCB+IDIpOiBwb2ludHMgc3ByZWFkIG91dCAoZXhwbG9yaW5nIG1hbnkgc3RhdGVzIGluIHBhcmFsbGVsKQ0KeF9xdWFudHVtID0gbnAub25lcyhudW1fcG9pbnRzKSAqIDIuMCAgICAgICAgICAgICAjIGF0IHg9Mg0KeV9xdWFudHVtID0geV9pbnB1dCAqIDIuMCAgICAgICAgICAgICAgICAgICAgICAgICAjIGluY3JlYXNlZCBzcHJlYWQgaW4geQ0Kel9xdWFudHVtID0gel9pbnB1dCAqIDIuMCAgICAgICAgICAgICAgICAgICAgICAgICAjIGluY3JlYXNlZCBzcHJlYWQgaW4geg0KDQojIE91dHB1dCBzdGFnZSAoeCB+IDMpOiBwb2ludHMgcG9zc2libHkgcmUtY2x1c3RlcmVkIGZvciByZXN1bHRzDQp4X291dHB1dCA9IG5wLm9uZXMobnVtX3BvaW50cykgKiAzLjAgICAgICAgICAgICAgICMgYXQgeD0zDQp5X291dHB1dCA9IHlfaW5wdXQgKiAwLjUgKyAwLjUgICAgICAgICAgICAgICAgICAgICMgbW9kZXJhdGUgc3ByZWFkLCBzaGlmdGVkIHVwd2FyZCBhIGJpdA0Kel9vdXRwdXQgPSB6X2lucHV0ICogMC41ICAgICAgICAgICAgICAgICAgICAgICAgICAjIG1vZGVyYXRlIHNwcmVhZCBpbiB6DQoNCiMgMi4gRGVmaW5lIHdoaWNoIHBvaW50cyB0byBzaG93IGFzIGVudGFuZ2xlZCAod2UnbGwgY29ubmVjdCB0d28gcGFpcnMgb2YgcG9pbnRzKQ0KZW50YW5nbGVkX3BhaXJzID0gWygwLCAxKSwgKDIsIDMpXQ0KIyBQcmVwYXJlIGNvb3JkaW5hdGVzIGZvciBsaW5lIHNlZ21lbnRzIGJldHdlZW4gZW50YW5nbGVkIHBvaW50cyAoYXQgcXVhbnR1bSBzdGFnZSBwb3NpdGlvbnMpDQpsaW5lX3ggPSBbXTsgbGluZV95ID0gW107IGxpbmVfeiA9IFtdDQpmb3IgaSwgaiBpbiBlbnRhbmdsZWRfcGFpcnM6DQogICAgbGluZV94ICs9IFt4X3F1YW50dW1baV0sIHhfcXVhbnR1bVtqXSwgTm9uZV0gICAjIE5vbmUgYXMgYSBicmVhayBpbiB0aGUgbGluZQ0KICAgIGxpbmVfeSArPSBbeV9xdWFudHVtW2ldLCB5X3F1YW50dW1bal0sIE5vbmVdDQogICAgbGluZV96ICs9IFt6X3F1YW50dW1baV0sIHpfcXVhbnR1bVtqXSwgTm9uZV0NCg0KIyAzLiBDcmVhdGUgYSBCbG9jaCBzcGhlcmUgcmVwcmVzZW50YXRpb24gZm9yIHN1cGVycG9zaXRpb24gYXJvdW5kIG9uZSBwYXJ0aWNsZSAoZS5nLiwgcGFydGljbGUgMCkNCmNlbnRlcl9pZHggPSAwICAjIGluZGV4IG9mIHRoZSBwYXJ0aWNsZSB0byBoaWdobGlnaHQgd2l0aCBhIHNwaGVyZQ0KY3gsIGN5LCBjeiA9IHhfcXVhbnR1bVtjZW50ZXJfaWR4XSwgeV9xdWFudHVtW2NlbnRlcl9pZHhdLCB6X3F1YW50dW1bY2VudGVyX2lkeF0NCnNwaGVyZV9yID0gMC41ICAjIHJhZGl1cyBvZiB0aGUgc3BoZXJlDQojIEdlbmVyYXRlIHBvaW50cyBvbiBhIHNwaGVyZSAoZm9yIHZpc3VhbCBlZmZlY3Qgb2YgYSB0cmFuc3BhcmVudCBnbG9iZSkNCnBoaSA9IG5wLmxpbnNwYWNlKDAsIG5wLnBpLCAyMCkNCnRoZXRhID0gbnAubGluc3BhY2UoMCwgMipucC5waSwgNDApDQpzcGhlcmVfeCA9IFtdOyBzcGhlcmVfeSA9IFtdOyBzcGhlcmVfeiA9IFtdDQpmb3IgcCBpbiBwaGk6DQogICAgZm9yIHQgaW4gdGhldGE6DQogICAgICAgIHNwaGVyZV94LmFwcGVuZChjeCArIHNwaGVyZV9yICogbnAuc2luKHApICogbnAuY29zKHQpKQ0KICAgICAgICBzcGhlcmVfeS5hcHBlbmQoY3kgKyBzcGhlcmVfciAqIG5wLnNpbihwKSAqIG5wLnNpbih0KSkNCiAgICAgICAgc3BoZXJlX3ouYXBwZW5kKGN6ICsgc3BoZXJlX3IgKiBucC5jb3MocCkpDQoNCiMgNC4gUHJlcGFyZSBhIHRleHQgbGFiZWwgZm9yIHRoZSBzdXBlcnBvc2l0aW9uIGZvcm11bGEsIHBvc2l0aW9uZWQganVzdCBhYm92ZSB0aGUgc3BoZXJlDQp0ZXh0X2xhYmVsID0gInzPiOKfqSA9IM6xfDDin6kgKyDOsnwx4p+pIg0KdGV4dF94ID0gW2N4XSAgICAgICAgICAgICAgICAgICAgICAgICAgIyBzYW1lIHggYXMgdGhlIGhpZ2hsaWdodGVkIHF1Yml0DQp0ZXh0X3kgPSBbY3kgKyBzcGhlcmVfciAqIDIuMF0gICAgICAgICAjIGEgYml0IGFib3ZlIHRoZSBzcGhlcmUNCnRleHRfeiA9IFtjel0gICAgICAgICAgICAgICAgICAgICAgICAgICMgc2FtZSB6IGFzIHRoZSBoaWdobGlnaHRlZCBxdWJpdA0KDQojIDUuIENyZWF0ZSBzY2F0dGVyIHRyYWNlcyBmb3I6DQojICAgIC0gRGF0YSBwYXJ0aWNsZXMgKHdpbGwgdXBkYXRlIHBvc2l0aW9ucyBwZXIgZnJhbWUpDQojICAgIC0gRW50YW5nbGVtZW50IGxpbmVzIChhcHBlYXIgaW4gcXVhbnR1bSBzdGFnZSkNCiMgICAgLSBTcGhlcmUgcG9pbnRzIChhcHBlYXIgaW4gcXVhbnR1bSBzdGFnZSkNCiMgICAgLSBUZXh0IGxhYmVsIChhcHBlYXJzIGluIHF1YW50dW0gc3RhZ2UpDQpkYXRhX3RyYWNlID0gZ28uU2NhdHRlcjNkKHg9eF9pbnB1dCwgeT15X2lucHV0LCB6PXpfaW5wdXQsIG1vZGU9J21hcmtlcnMnLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBtYXJrZXI9ZGljdChzaXplPTgsIGNvbG9yPSdibHVlJyksIG5hbWU9IkRhdGEiKQ0KZW50YW5nbGVtZW50X3RyYWNlID0gZ28uU2NhdHRlcjNkKHg9W10sIHk9W10sIHo9W10sIG1vZGU9J2xpbmVzJywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5lPWRpY3QoY29sb3I9J3JlZCcsIHdpZHRoPTQpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWU9IkVudGFuZ2xlbWVudCIsIHZpc2libGU9RmFsc2UpDQpzcGhlcmVfdHJhY2UgPSBnby5TY2F0dGVyM2QoeD1bXSwgeT1bXSwgej1bXSwgbW9kZT0nbWFya2VycycsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmtlcj1kaWN0KHNpemU9MiwgY29sb3I9J3JnYmEoMTAwLDE1MCwyNTUsMC4zKScpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lPSJCbG9jaCBTcGhlcmUiLCB2aXNpYmxlPUZhbHNlKQ0KdGV4dF90cmFjZSA9IGdvLlNjYXR0ZXIzZCh4PVtdLCB5PVtdLCB6PVtdLCBtb2RlPSd0ZXh0JywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgdGV4dD1bXSwgdGV4dGZvbnQ9ZGljdChjb2xvcj0nYmxhY2snLCBzaXplPTE2KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZT0iU3VwZXJwb3NpdGlvbiBGb3JtdWxhIiwgdmlzaWJsZT1GYWxzZSkNCg0KIyA2LiBJbml0aWFsaXplIGZpZ3VyZSB3aXRoIGFsbCB0cmFjZXMNCmZpZyA9IGdvLkZpZ3VyZShkYXRhPVtkYXRhX3RyYWNlLCBlbnRhbmdsZW1lbnRfdHJhY2UsIHNwaGVyZV90cmFjZSwgdGV4dF90cmFjZV0pDQoNCiMgQ3VzdG9taXplIDNEIGF4ZXM6IGxhYmVsIHRoZSBzdGFnZXMgb24gdGhlIHgtYXhpcywgaGlkZSB5L3ogdGljayBsYWJlbHMgZm9yIGNsYXJpdHkNCmZpZy51cGRhdGVfbGF5b3V0KA0KICAgIHNjZW5lPWRpY3QoDQogICAgICAgIHhheGlzPWRpY3QodGl0bGU9IiIsIHRpY2ttb2RlPSdhcnJheScsDQogICAgICAgICAgICAgICAgICAgdGlja3ZhbHM9WzAsIDEsIDIsIDNdLA0KICAgICAgICAgICAgICAgICAgIHRpY2t0ZXh0PVsiSW5wdXQgRGF0YSIsICJDbGFzc2ljYWwgUHJlcCIsICJRdWFudHVtIFNpbSIsICJSZXN1bHRzIl0pLA0KICAgICAgICB5YXhpcz1kaWN0KHRpdGxlPSIiLCBzaG93dGlja2xhYmVscz1GYWxzZSksDQogICAgICAgIHpheGlzPWRpY3QodGl0bGU9IiIsIHNob3d0aWNrbGFiZWxzPUZhbHNlKSwNCiAgICApLA0KICAgIG1hcmdpbj1kaWN0KGw9MCwgcj0wLCBiPTAsIHQ9MCkgICMgdGlnaHQgbGF5b3V0DQopDQoNCiMgNy4gRGVmaW5lIGFuaW1hdGlvbiBmcmFtZXMgZm9yIGVhY2ggc3RhZ2Ugb2YgdGhlIHBpcGVsaW5lDQpmaWcuZnJhbWVzID0gWw0KICAgICMgRnJhbWUgMDogSW5wdXQgc3RhZ2UNCiAgICBnby5GcmFtZShuYW1lPSJJbnB1dCIsIGRhdGE9Ww0KICAgICAgICBnby5TY2F0dGVyM2QoeD14X2lucHV0LCB5PXlfaW5wdXQsIHo9el9pbnB1dCwNCiAgICAgICAgICAgICAgICAgICAgIG1hcmtlcj1kaWN0KGNvbG9yPSdibHVlJykpLCAgICAgICAgICAgICAgICMgZGF0YSBwb2ludHMgYmx1ZSBhdCBpbnB1dA0KICAgICAgICBnby5TY2F0dGVyM2QoeD1bXSwgeT1bXSwgej1bXSksICAgICAgICAgICAgICAgICAgICAgICAgIyBlbnRhbmdsZW1lbnQgKGhpZGRlbikNCiAgICAgICAgZ28uU2NhdHRlcjNkKHg9W10sIHk9W10sIHo9W10pLCAgICAgICAgICAgICAgICAgICAgICAgICMgc3BoZXJlIChoaWRkZW4pDQogICAgICAgIGdvLlNjYXR0ZXIzZCh4PVtdLCB5PVtdLCB6PVtdLCB0ZXh0PVtdKSAgICAgICAgICAgICAgICAjIHRleHQgKGhpZGRlbikNCiAgICBdKSwNCiAgICAjIEZyYW1lIDE6IENsYXNzaWNhbCBzdGFnZQ0KICAgIGdvLkZyYW1lKG5hbWU9IkNsYXNzaWNhbCIsIGRhdGE9Ww0KICAgICAgICBnby5TY2F0dGVyM2QoeD14X2NsYXNzaWNhbCwgeT15X2NsYXNzaWNhbCwgej16X2NsYXNzaWNhbCwNCiAgICAgICAgICAgICAgICAgICAgIG1hcmtlcj1kaWN0KGNvbG9yPSdvcmFuZ2UnKSksICAgICAgICAgICAgICMgZGF0YSBwb2ludHMgdHVybiBvcmFuZ2UNCiAgICAgICAgZ28uU2NhdHRlcjNkKHg9W10sIHk9W10sIHo9W10pLCAgICAgICAgICAgICAgICAgICAgICAgICMgZW50YW5nbGVtZW50IGhpZGRlbg0KICAgICAgICBnby5TY2F0dGVyM2QoeD1bXSwgeT1bXSwgej1bXSksICAgICAgICAgICAgICAgICAgICAgICAgIyBzcGhlcmUgaGlkZGVuDQogICAgICAgIGdvLlNjYXR0ZXIzZCh4PVtdLCB5PVtdLCB6PVtdLCB0ZXh0PVtdKSAgICAgICAgICAgICAgICAjIHRleHQgaGlkZGVuDQogICAgXSksDQogICAgIyBGcmFtZSAyOiBRdWFudHVtIHN0YWdlDQogICAgZ28uRnJhbWUobmFtZT0iUXVhbnR1bSIsIGRhdGE9Ww0KICAgICAgICBnby5TY2F0dGVyM2QoeD14X3F1YW50dW0sIHk9eV9xdWFudHVtLCB6PXpfcXVhbnR1bSwNCiAgICAgICAgICAgICAgICAgICAgIG1hcmtlcj1kaWN0KGNvbG9yPSdwdXJwbGUnKSksICAgICAgICAgICAgICMgZGF0YSBwb2ludHMgdHVybiBwdXJwbGUNCiAgICAgICAgZ28uU2NhdHRlcjNkKHg9bGluZV94LCB5PWxpbmVfeSwgej1saW5lX3opLCAgICAgICAgICAgICAjIGVudGFuZ2xlbWVudCBsaW5lcyB2aXNpYmxlDQogICAgICAgIGdvLlNjYXR0ZXIzZCh4PXNwaGVyZV94LCB5PXNwaGVyZV95LCB6PXNwaGVyZV96KSwgICAgICAgIyBzcGhlcmUgcG9pbnRzIHZpc2libGUNCiAgICAgICAgZ28uU2NhdHRlcjNkKHg9dGV4dF94LCB5PXRleHRfeSwgej10ZXh0X3osIHRleHQ9W3RleHRfbGFiZWxdKSAgIyBmb3JtdWxhIHRleHQgdmlzaWJsZQ0KICAgIF0pLA0KICAgICMgRnJhbWUgMzogUmVzdWx0cyBzdGFnZQ0KICAgIGdvLkZyYW1lKG5hbWU9IlJlc3VsdHMiLCBkYXRhPVsNCiAgICAgICAgZ28uU2NhdHRlcjNkKHg9eF9vdXRwdXQsIHk9eV9vdXRwdXQsIHo9el9vdXRwdXQsDQogICAgICAgICAgICAgICAgICAgICBtYXJrZXI9ZGljdChjb2xvcj0nZ3JlZW4nKSksICAgICAgICAgICAgICAjIGRhdGEgcG9pbnRzIHR1cm4gZ3JlZW4gZm9yIG91dHB1dA0KICAgICAgICBnby5TY2F0dGVyM2QoeD1bXSwgeT1bXSwgej1bXSksICAgICAgICAgICAgICAgICAgICAgICAgIyBlbnRhbmdsZW1lbnQgb2ZmDQogICAgICAgIGdvLlNjYXR0ZXIzZCh4PVtdLCB5PVtdLCB6PVtdKSwgICAgICAgICAgICAgICAgICAgICAgICAjIHNwaGVyZSBvZmYNCiAgICAgICAgZ28uU2NhdHRlcjNkKHg9W10sIHk9W10sIHo9W10sIHRleHQ9W10pICAgICAgICAgICAgICAgICMgdGV4dCBvZmYNCiAgICBdKQ0KXQ0KDQojIDguIEFkZCBwbGF5IGJ1dHRvbiBhbmQgc2xpZGVyIGZvciBpbnRlcmFjdGl2aXR5DQpmaWcudXBkYXRlX2xheW91dCgNCiAgICB1cGRhdGVtZW51cz1bZGljdCh0eXBlPSJidXR0b25zIiwNCiAgICAgICAgICAgICAgICAgICAgICBidXR0b25zPVtkaWN0KGxhYmVsPSJQbGF5IiwgbWV0aG9kPSJhbmltYXRlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFyZ3M9W05vbmUsIHsiZnJhbWUiOiB7ImR1cmF0aW9uIjogMTAwMCwgInJlZHJhdyI6IFRydWV9LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJ0cmFuc2l0aW9uIjogeyJkdXJhdGlvbiI6IDUwMH0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImZyb21jdXJyZW50IjogVHJ1ZSwgIm1vZGUiOiAiaW1tZWRpYXRlIn1dKV0sDQogICAgICAgICAgICAgICAgICAgICAgeD0wLjEsIHk9LTAuMSwgc2hvd2FjdGl2ZT1GYWxzZSldLA0KICAgIHNsaWRlcnM9W2RpY3Qoc3RlcHM9W2RpY3QobWV0aG9kPSJhbmltYXRlIiwgbGFiZWw9ZnJhbWUubmFtZSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFyZ3M9W1tmcmFtZS5uYW1lXSwgeyJmcmFtZSI6IHsiZHVyYXRpb24iOiAxMDAwLCAicmVkcmF3IjogVHJ1ZX0sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAidHJhbnNpdGlvbiI6IHsiZHVyYXRpb24iOiA1MDB9LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIm1vZGUiOiAiaW1tZWRpYXRlIn1dKQ0KICAgICAgICAgICAgICAgICAgICAgICAgIGZvciBmcmFtZSBpbiBmaWcuZnJhbWVzXSwNCiAgICAgICAgICAgICAgICAgeD0wLjEsIHk9LTAuMDcsIHhhbmNob3I9ImxlZnQiLCB5YW5jaG9yPSJ0b3AiLCBwYWQ9ZGljdCh0PTMwKSldDQopDQoNCiMgVGhlIGZpZ3VyZSBjYW4gYmUgc2hvd24gaW4gYSBKdXB5dGVyIGVudmlyb25tZW50IG9yIGV4cG9ydGVkIHRvIEhUTUw6DQojIGZpZy5zaG93KCkgICMgdG8gZGlzcGxheSBpbiBhbiBpbnRlcmFjdGl2ZSBlbnZpcm9ubWVudA0KZmlnLndyaXRlX2h0bWwoIm1xcGFfdmlzdWFsaXphdGlvbi5odG1sIiwgYXV0b19wbGF5PUZhbHNlLCBpbmNsdWRlX3Bsb3RseWpzPVRydWUpDQpwcmludCgiQW5pbWF0aW9uIHJlYWR5OiBvcGVuICdtcXBhX3Zpc3VhbGl6YXRpb24uaHRtbCcgaW4gYSB3ZWIgYnJvd3NlciB0byB2aWV3LiIpDQpgYGAgDQoNCioqSG93IGl0IHdvcmtzOioqIFRoZSBjb2RlIGFib3ZlIGNyZWF0ZXMgYW4gaW50ZXJhY3RpdmUgM0Qgc2NlbmUgd2l0aCBQbG90bHkuIEl0IGRlZmluZXMgZm91ciBrZXkgKipmcmFtZXMqKiBjb3JyZXNwb25kaW5nIHRvIHRoZSBzdGFnZXMgb2YgTVFQQSAoSW5wdXQsIENsYXNzaWNhbCwgUXVhbnR1bSwgUmVzdWx0cykuIEluIGVhY2ggZnJhbWUsIHRoZSBwb3NpdGlvbnMgYW5kIGNvbG9ycyBvZiB0aGUgZGF0YS1wb2ludCBtYXJrZXJzIGFyZSB1cGRhdGVkOg0KLSBJbml0aWFsbHksIHBvaW50cyBhcmUgYXQgKip4PTAqKiAoaW5wdXQgc2lkZSkgYW5kIGNvbG9yZWQgYmx1ZS4NCi0gQWZ0ZXIgY2xhc3NpY2FsIHByZXAsIHBvaW50cyBtb3ZlIHRvICoqeD0xKiogYW5kIHR1cm4gb3JhbmdlIChpbmRpY2F0aW5nIGEgY2xhc3NpY2FsIHRyYW5zZm9ybWF0aW9uKS4NCi0gSW4gdGhlIHF1YW50dW0gZnJhbWUsIHBvaW50cyBzaGlmdCB0byAqKng9MioqIChxdWFudHVtIHByb2Nlc3NvciBzaWRlKSBhbmQgdHVybiBwdXJwbGUuIFRoZSBlbnRhbmdsZW1lbnQgbGluZXMgKGByZWRgIGNvbm5lY3RpbmcgbGluZXMpIGFuZCB0aGUgc3BoZXJlICsgZm9ybXVsYSB0ZXh0IGFwcGVhciBpbiB0aGlzIGZyYW1lIG9ubHkuDQotIEluIHRoZSByZXN1bHRzIGZyYW1lLCBwb2ludHMgbW92ZSB0byAqKng9MyoqIGFuZCB0dXJuIGdyZWVuLCB3aGlsZSB0aGUgc3BoZXJlLCBsaW5rcywgYW5kIHRleHQgYXJlIGhpZGRlbiAoc2luY2UgdGhvc2Ugd2VyZSBvbmx5IHBhcnQgb2YgdGhlIHF1YW50dW0gcHJvY2VzcykuDQoNCldlIGFkZGVkIGEgKipzbGlkZXIgYW5kIHBsYXkgYnV0dG9uKiogc28gdGhlIHByZXNlbnRlciBjYW4gZWl0aGVyIGxldCB0aGUgYW5pbWF0aW9uIHBsYXkgb3IgbWFudWFsbHkgc3RlcCB0aHJvdWdoIGVhY2ggc3RhZ2UuIFRoZSAzRCBwbG90IGlzIGludGVyYWN0aXZlIOKAkyBvbmUgY2FuIGNsaWNrIGFuZCBkcmFnIHRvIHJvdGF0ZSB0aGUgdmlldywgd2hpY2ggaXMgdXNlZnVsIGlmIHRoZSBwcmVzZW50ZXIgd2FudHMgdG8gc2hvdyB0aGUgYXVkaWVuY2UgZGlmZmVyZW50IGFuZ2xlcyBvZiB0aGUgM0Qgc2NlbmUuIEJ5IGRlZmF1bHQsIHRoZSBheGVzIGFyZSBsYWJlbGVkIHdpdGggdGhlIHN0YWdlIG5hbWVzICjigJxJbnB1dCBEYXRh4oCdLCDigJxDbGFzc2ljYWwgUHJlcOKAnSwgZXRjLikgYWxvbmcgdGhlIHgtYXhpcywgYW5kIHdlIGhpZCB0aGUgeS96IHRpY2sgbGFiZWxzIHRvIHJlZHVjZSBjbHV0dGVyIChzaW5jZSB0aGUgeSx6IGNvb3JkaW5hdGVzIGFyZW7igJl0IGNvbmNlcHR1YWxseSBpbXBvcnRhbnQgYmV5b25kIHNob3dpbmcgcmVsYXRpdmUgcG9zaXRpb25pbmcpLg0KDQoqKk91dHB1dDoqKiBSdW5uaW5nIHRoaXMgc2NyaXB0IHdpbGwgZ2VuZXJhdGUgYW4gSFRNTCBmaWxlIG5hbWVkIGBtcXBhX3Zpc3VhbGl6YXRpb24uaHRtbGAuIFlvdSBjYW4gb3BlbiB0aGF0IGZpbGUgaW4gYW55IG1vZGVybiB3ZWIgYnJvd3NlciB0byB2aWV3IHRoZSBpbnRlcmFjdGl2ZSBhbmltYXRpb24uIEluIHRoZSBicm93c2VyLCB5b3XigJlsbCBzZWUgdGhlIGRhdGEgcGFydGljbGVzIGFuZCBjYW4gdXNlIHRoZSBwbGF5IGJ1dHRvbiBvciBzbGlkZXIgdG8gbmF2aWdhdGUgdGhlIHBpcGVsaW5lIGZyb20gbGVmdCAoSW5wdXQpIHRvIHJpZ2h0IChSZXN1bHRzKS4gVGhlIGVudGlyZSBzZXF1ZW5jZSBjYW4gYWxzbyBiZSBwYXVzZWQgYXQgZWFjaCBzdGVwLCB3aGljaCBpcyBpZGVhbCBkdXJpbmcgYSBsaXZlIHRhbGsg4oCUIHlvdSBjYW4gc3RvcCwgcm90YXRlIHRoZSB2aWV3LCBhbmQgZGlzY3VzcyB3aGF04oCZcyBoYXBwZW5pbmcgKGZvciBleGFtcGxlLCBwYXVzaW5nIGF0IHRoZSBRdWFudHVtIHN0YWdlIHRvIGV4cGxhaW4gc3VwZXJwb3NpdGlvbiBhbmQgZW50YW5nbGVtZW50IHdpdGggdGhlIHZpc3VhbCBhaWRzKS4NCg0KIyMgVXNpbmcgdGhlIFZpc3VhbGl6YXRpb24gaW4gYSBQcmVzZW50YXRpb24NCg0KVGhpcyB2aXN1YWxpemF0aW9uIGlzIGRlc2lnbmVkIHRvIGJlIHByZXNlbnRhdGlvbi1mcmllbmRseS4gSGVyZSBhcmUgYSBmZXcgdGlwcyBvbiB1c2luZyBpdDoNCi0gKipJbiBQb3dlclBvaW50OioqIElmIHlvdSBwcmVmZXIgYSBzdGF0aWMgdmlkZW8sIHlvdSBjYW4gcmVjb3JkIHRoZSBhbmltYXRpb24gKGUuZy4sIHVzaW5nIFBsb3RseeKAmXMgYnVpbHQtaW4gdmlkZW8gZXhwb3J0IG9yIGEgc2NyZWVuIHJlY29yZGluZykgdG8gZ2V0IGFuIE1QNCBmaWxlLiBFbWJlZCB0aGUgdmlkZW8gaW4geW91ciBzbGlkZSBzbyBpdCBhdXRvLXBsYXlzLCBvciBjbGljayB0aHJvdWdoIGZyYW1lLWJ5LWZyYW1lIHVzaW5nIHRoZSBzbGlkZXIgZm9yIGEgZ3VpZGVkIGV4cGxhbmF0aW9uLg0KLSAqKkxpdmUgRGVtbyBNb2RlOioqIEJlY2F1c2UgdGhlIG91dHB1dCBpcyBhbiBIVE1MIGZpbGUsIHlvdSBjYW4gcHJlc2VudCBpdCBsaXZlIGJ5IG9wZW5pbmcgaXQgaW4gYSB3ZWIgYnJvd3NlciBkdXJpbmcgeW91ciB0YWxrLiBUaGlzIGFsbG93cyB5b3UgdG8gaW50ZXJhY3QgKHJvdGF0ZSB0aGUgM0QgdmlldywgcmVwbGF5IHRoZSBhbmltYXRpb24sIGV0Yy4pIGluIHJlYWwtdGltZS4gSXQgY2FuIG1ha2UgdGhlIGRlbW8gbW9yZSBlbmdhZ2luZywgYXMgeW91IGNhbiByZXNwb25kIHRvIGF1ZGllbmNlIHJlcXVlc3RzIGxpa2Ug4oCcd2hhdCBoYXBwZW5zIGlmIHdlIGxvb2sgZnJvbSB0aGlzIGFuZ2xlP+KAnS4NCi0gKipOYXJyYXRpb24gQ3VlczoqKiBUaGUgdmlzdWFsaXphdGlvbiBhbGlnbnMgd2l0aCB0eXBpY2FsIE1RUEEgbmFycmF0aW9uLiBGb3IgZXhhbXBsZSwgYXMgdGhlIGJsdWUgcG9pbnRzIGFwcGVhciBhbmQgbW92ZSwgeW91IG1pZ2h0IHNheSDigJxIZXJlIG91ciByYXcgbW9sZWN1bGFyIGFuZCBlbnZpcm9ubWVudGFsIGRhdGEgY29tZXMgaW4u4oCdIFdoZW4gdGhlIHBvaW50cyB0dXJuIG9yYW5nZSBhdCB4PTEsIHlvdeKAmWQgZXhwbGFpbiDigJxhIGNsYXNzaWNhbCBjb21wdXRlciBjbGVhbnMgYW5kIHByZXBhcmVzIHRoZSBkYXRhIChvcmFuZ2Up4oCm4oCdLiBBdCB0aGUgcXVhbnR1bSBzdGFnZSwgcG9pbnQgb3V0IHRoZSBzdXBlcnBvc2l0aW9uIChzcGlubmluZyBzcGhlcmUgYXJvdW5kIGEgcXViaXQpIGFuZCBlbnRhbmdsZW1lbnQgKHJlZCBsaW5raW5nIGxpbmVzKSDigJMgdGhpcyBpcyBhIHBlcmZlY3QgdGltZSB0byB1c2UgdGhlIGNvaW4gYW5hbG9naWVzIChmbGlwcGluZyBjb2luIGZvciBzdXBlcnBvc2l0aW9uLCBsaW5rZWQgY29pbnMgZm9yIGVudGFuZ2xlbWVudCkgdG8gcmVpbmZvcmNlIHVuZGVyc3RhbmRpbmcgKFtxdWFudHVtIGdhdGUgLSBXaGF0IGFyZSBjbGFzc2ljYWwgYW5hbG9naWVzIGZvciB0aGUgbm90aW9ucyBvZiBzdXBlcnBvc2l0aW9uLCBlbnRhbmdsZW1lbnQsIGFuZCBpbnRlcmZlcmVuY2U/IC0gUXVhbnR1bSBDb21wdXRpbmcgU3RhY2sgRXhjaGFuZ2VdKGh0dHBzOi8vcXVhbnR1bWNvbXB1dGluZy5zdGFja2V4Y2hhbmdlLmNvbS9xdWVzdGlvbnMvMzc5Nzcvd2hhdC1hcmUtY2xhc3NpY2FsLWFuYWxvZ2llcy1mb3ItdGhlLW5vdGlvbnMtb2Ytc3VwZXJwb3NpdGlvbi1lbnRhbmdsZW1lbnQtYW5kIzp+OnRleHQ9U3VwZXJwb3NpdGlvbiUzQSUyMEltYWdpbmUlMjBhJTIwY29pbiUyMGZsaXBwZWQsY29sbGFwc2VzJTIwdG8lMjBhJTIwc2luZ2xlJTIwb3V0Y29tZSkpIChbcXVhbnR1bSBnYXRlIC0gV2hhdCBhcmUgY2xhc3NpY2FsIGFuYWxvZ2llcyBmb3IgdGhlIG5vdGlvbnMgb2Ygc3VwZXJwb3NpdGlvbiwgZW50YW5nbGVtZW50LCBhbmQgaW50ZXJmZXJlbmNlPyAtIFF1YW50dW0gQ29tcHV0aW5nIFN0YWNrIEV4Y2hhbmdlXShodHRwczovL3F1YW50dW1jb21wdXRpbmcuc3RhY2tleGNoYW5nZS5jb20vcXVlc3Rpb25zLzM3OTc3L3doYXQtYXJlLWNsYXNzaWNhbC1hbmFsb2dpZXMtZm9yLXRoZS1ub3Rpb25zLW9mLXN1cGVycG9zaXRpb24tZW50YW5nbGVtZW50LWFuZCM6fjp0ZXh0PUVudGFuZ2xlbWVudCUzQSUyMENvbnNpZGVyJTIwdHdvJTIwY29pbnMlMjB0b3NzZWQsY29ycmVsYXRpb24lMjB3aXRob3V0JTIwZGlyZWN0JTIwY2F1c2FsJTIwaW5mbHVlbmNlKSkuIEZpbmFsbHksIGFzIHRoZSBwb2ludHMgdHVybiBncmVlbiBhbmQgc2V0dGxlIGF0IHRoZSBvdXRwdXQsIHlvdSBjb25jbHVkZSB3aXRoIGhvdyB0aGUgcmVzdWx0cyBhcmUgb2J0YWluZWQgYW5kIGNhbiBiZSB2aXN1YWxpemVkIGNsYXNzaWNhbGx5Lg0KDQpCeSBmb2xsb3dpbmcgdGhpcyBmbG93IGFuZCB1dGlsaXppbmcgdGhlIHByb3ZpZGVkIGNvZGUsIHlvdSB3aWxsIGhhdmUgYSAqKmNvbXBlbGxpbmcgM0QgYW5pbWF0aW9uKiogdGhhdCBjbGVhcmx5IGRlbW9uc3RyYXRlcyBob3cgTVFQQSB3b3Jrcy4gSXQgdmlzdWFsbHkgZW5jYXBzdWxhdGVzIHRoZSBlc3NlbmNlIG9mIGEgaHlicmlkIHF1YW50dW0tY2xhc3NpY2FsIGFsZ29yaXRobSB0dXJuaW5nIHJhdyBlbnZpcm9ubWVudGFsL21vbGVjdWxhciBkYXRhIGludG8gbWVhbmluZ2Z1bCByZXN1bHRzLCBpbiBhIHdheSB0aGF0IGlzIGJvdGggZWR1Y2F0aW9uYWwgYW5kIGVuZ2FnaW5nIGZvciBhIGdlbmVyYWwgYXVkaWVuY2UuIFdpdGggdGhpcyBpbiB5b3VyIHByZXNlbnRhdGlvbiwgYWJzdHJhY3QgY29uY2VwdHMgbGlrZSBzdXBlcnBvc2l0aW9uIGFuZCBlbnRhbmdsZW1lbnQgYmVjb21lIGNvbmNyZXRlLCBhbmQgdGhlIHBvd2VyIG9mIGNvbWJpbmluZyBjbGFzc2ljYWwgYW5kIHF1YW50dW0gY29tcHV0aW5nIGluIGVudmlyb25tZW50YWwgbW9kZWxpbmcgaXMgbWFkZSB2aXZpZGx5IGNsZWFyLiBFbmpveSB5b3VyIHByZXNlbnRhdGlvbiwgYW5kIGJlc3Qgb2YgbHVjayBpbGx1c3RyYXRpbmcgdGhlIGZ1dHVyZSBvZiBjb21wdXRpbmchICAoW0hvdyBxdWFudHVtIGNvbXB1dGVycyBzaW11bGF0ZSBhdCB0aGUgYXRvbWljIGxldmVsXShodHRwczovL3d3dy5yaXZlcmxhbmUuY29tL2Jsb2cvbW9kZWxsaW5nLW1vbGVjdWxlcy1ob3ctcXVhbnR1bS1jb21wdXRlcnMtc2ltdWxhdGUtYXQtdGhlLWF0b21pYy1sZXZlbCM6fjp0ZXh0PVRoZSUyMGJpZyUyMGFkdmFudGFnZSUyMG9mJTIwcXVhbnR1bSxxdWJpdHMlMjklMjB0byUyMHJlcHJlc2VudCUyMHRoZW0pKQ0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoxLiAqKkFjY2VzcyBteSAgT3JpZ2luYWwgU3BhY2U6KioNCiAgIC0gVmlzaXQgdGhlIFF1YW50dW0gUGFydGljbGUgU2ltdWxhdG9yIFNwYWNlOiDuiIBjaXRl7oiCdHVybjBzZWFyY2gw7oiBDQoNCjIuICoqIFNwYWNlOioqDQogICAtIE9uIHRoZSBTcGFjZSBwYWdlLCBjbGljayB0aGUgIkR1cGxpY2F0ZSB0aGlzIFNwYWNlIiBidXR0b24uIFRoaXMgd2lsbCBjcmVhdGUgYSBjb3B5IHVuZGVyIHlvdXIgSHVnZ2luZyBGYWNlIGFjY291bnQsIGFsbG93aW5nIHlvdSB0byBtb2RpZnkgYW5kIHJ1biBpdCBpbmRlcGVuZGVudGx5Lg0KDQozLiAqKlJldmlldyB0aGUgU291cmNlIENvZGU6KioNCiAgIC0gTmF2aWdhdGUgdG8gdGhlICJGaWxlcyIgc2VjdGlvbiBvZiAgZHVwbGljYXRlZCBTcGFjZSB0byBleGFtaW5lIHRoZSBzb3VyY2UgY29kZS4gVGhpcyB3aWxsIGhlbHAgeW91IHVuZGVyc3RhbmQgdGhlIHN0cnVjdHVyZSBhbmQgZnVuY3Rpb25hbGl0eSBvZiB0aGUgYXBwbGljYXRpb24uDQoNCjQuICoqU2V0IFVwIG5ldyAgRW52aXJvbm1lbnQ6KioNCiAgIC0gRW5zdXJlIHlvdSBoYXZlIFB5dGhvbiBpbnN0YWxsZWQgb24geW91ciBsb2NhbCBtYWNoaW5lLg0KICAgLSBJbnN0YWxsIG5lY2Vzc2FyeSBsaWJyYXJpZXMuIFRoZSBhcHBsaWNhdGlvbiBsaWtlbHkgdXNlcyBsaWJyYXJpZXMgc3VjaCBhcyBgbnVtcHlgLCBgbWF0cGxvdGxpYmAsIGFuZCBgcGxvdGx5YC4gSW5zdGFsbCB0aGVtIHVzaW5nIHBpcDoNCiAgICAgYGBgYmFzaA0KICAgICBwaXAgaW5zdGFsbCBudW1weSBtYXRwbG90bGliIHBsb3RseQ0KICAgICBgYGANCg0KNS4gKipSdW4gdGhlIEFwcGxpY2F0aW9uIExvY2FsbHk6KioNCiAgIC0gQ2xvbmUgbXkgIGR1cGxpY2F0ZWQgU3BhY2UgcmVwb3NpdG9yeSB0byB5b3VyIGxvY2FsIG1hY2hpbmU6DQogICAgIGBgYGJhc2gNCiAgICAgZ2l0IGNsb25lIGh0dHBzOi8vaHVnZ2luZ2ZhY2UuY28vc3BhY2VzL3RleGFzY2hpa2tpdGEvUXVhbnR1bQ0KICAgICBgYGANCiAgIC0gTmF2aWdhdGUgdG8gdGhlIHByb2plY3QgZGlyZWN0b3J5Og0KICAgICBgYGBiYXNoDQogICAgIGNkIFF1YW50dW0NCiAgICAgYGBgDQogICAtIFJ1biB0aGUgYXBwbGljYXRpb24gc2NyaXB0LiBJZiB0aGUgbWFpbiBzY3JpcHQgaXMgbmFtZWQgYGFwcC5weWAsIGV4ZWN1dGU6DQogICAgIGBgYGJhc2gNCiAgICAgcHl0aG9uIGFwcC5weQ0KICAgICBgYGANCiAgIC0gVGhpcyBzaG91bGQgbGF1bmNoIHRoZSBhcHBsaWNhdGlvbiBsb2NhbGx5LCBhbGxvd2luZyB5b3UgdG8gaW50ZXJhY3Qgd2l0aCB0aGUgUXVhbnR1bSBQYXJ0aWNsZSBTaW11bGF0b3Igb24geW91ciBtYWNoaW5lLg0KDQo2LiAqKk1vZGlmeSBhbmQgQ3VzdG9taXplOioqDQogICAtIFdpdGggdGhlIGFwcGxpY2F0aW9uIHJ1bm5pbmcgbG9jYWxseSwgSSBjYW4gZWRpdCB0aGUgc291cmNlIGNvZGUgdG8gY3VzdG9taXplIGZlYXR1cmVzLCBhcHBlYXJhbmNlLCBvciBmdW5jdGlvbmFsaXR5IGFjY29yZGluZyB0byBtb2RlbCBldGMgIG5lZWRzLiBVc2UgYW4gSURFIG9yIHRleHQgZWRpdG9yIHRvIG1ha2UgY2hhbmdlcyB0byB0aGUgUHl0aG9uIHNjcmlwdHMuDQoNCg0K