This short paper proposes a slope factor method to be used in routing
algorithms for cycling, suited for hilly cities.
Cost for bicycle
routing models
Bicycle routing models add to car routing modeling a greater
complexity that results essentially from the greater number of degrees
of freedom associated with cycling (i.e., a smaller, lighter and more
versatile vehicle in terms of maneuvering) and the fact that it is human
powered and therefore depending on a limited energy, thus depending on
the effort that is transmitted by the cyclist himself. This results in a
series of specific peculiarities in its riding, namely: a greater number
of variables relevant to the routing cost function, and the existence of
more subjective variables.
A complexity involved in modeling route choice for cyclists
represents a challenge. Even if we understand which variables are
determinant for route choice, models become more accurate if it
incorporates the versatility of the bicycle in urban context, and its
ability to circulate in non-road spaces.
GIS allows modeling a road network in the form of a topological
graph, to which a series of functions and algorithms, including the
least cost path (Dijkstra 1959). The application of
the least cost path algorithm assumes the existence of a graph formed by
a set of set of edges and nodes. The edges can be oriented or not and,
to these, a travel cost is associated, with one or more parameters,
never less than zero. Associating a travel cost to each arc in the
network, the route cost is defined as the sum of the costs of the arcs
that compose it.
Speed
For a constant urban cycling speed travel
(factor = 1), let’s say 15 km/h, we assume that the speed is
linear to the edge extension, and its cost is its travel time.
\[ c_{speed} =
\frac{length_{[m]}}{speed_{[m/s]}} = time_{[s]}\tag{Eq.1}\]
Many factors may be determinant for cycling speed,
such the surface conditions, traffic, weather, mass, type of bicycle,
directness, confidence, etc (Hochmair 2007; Félix 2012; Broach,
Dill, and Gliebe 2012; Broach
2016). Here we will look only to speed related with
gradient, from the perspective of a common urban cyclist.
Slope or
gradient
When comes to cycling, the route gradient can be a determinant
variable to chose a route instead of an alternative. It is commonly
known that cyclists are averse to roads with an ascending gradient, and
that cyclists prefer roads with a descending gradient. The
direction of the gradient is determinant.
It is also known, by the gravity laws, that an object traveling at a
constant speed, its speed becomes faster when going down the hill, and
slower when going uphill. Buy how does it applies to a human behavior?
How does it varies when effort, fear, stamina, and reward plays a role?
When does a cyclist use the break levers? When does a cyclist slows her
pace?
The slope enters the cost function as a proxy for cyclist effort -
the amount of energy a cyclist must expend to travel on a street with a
given slope - causing the traversing time to increase for uphill routes.
On downhill routes, the effort is reduced and the theoretical speed is
increased, reducing their traversing time.
Scott (2020) designed an experiment for
hiking, and applied a rule saying “A 10% grade incline cuts your
speed in half”. In their results, they suggested
an equation to calculate uphill speed (for hiking):
\[
speed = speed_{flat} * e^{(-0.04*slope)}\tag{Eq.2}
\]
Which results that with a grade of 20%, one can walk at a speed of
1.78 km/h it her horizontal speed was 4 km/h. When applying to cycling,
for a flat speed of 15km/h, the same incline would be ride at a 6.74
km/h speed, which is not reliable for a standard cyclist.
Also, the extension of the road segment enters in the cost function:
for longer segments at a given gradient, the effort of the cyclist is
higher than for a shorter segment with the same gradient.
Figure 1 shows the maximum lengths of uphill gradient acceptable to
cyclists (Austroads
2009). It considers that over a 3% slope, the length should
be taken into account.
Fig. 1 - Desirable uphill gradients for ease of
cycling (Austroads 2009)
Sometimes it is more efficient to travel a longer distance with less
steep gradients rather than a shorter distance on a steep gradient.
Other times the extra distance to ride to overcome the gradient is not
so worthwhile and the cyclist chooses to ride up the steeper gradient by
hand. The maximum crossing cost penalty was considered to be 10 times
for this situation, i.e. for edges with a gradient greater than 20%.
Very steep roads are a problem not only for uphill riding, but also
for downhill riding, because a mechanical failure in the brakes can lead
to a dangerous situation for the rider, who also has to expend some
effort and skill to keep the bike balanced and control the additional
risk.
Fig. 2 - World’s steepest street, with a 35%
incline for over 161 meters. Baldwin Street, Dunedin, New Zealand
(Photo: Wikipedia)
Downhill edges mostly result in benefit to the cyclist, increasing
its speed. However, this is not linear, decreasing from slope values
above 13%, and may even slow down the speed (relative to the average
flat speed) it too steep.
Speed-Slope Factor
After an iterative process, which considered the cyclist effort as a
function of slope abacuses suggested by AASHTO
(1999) and Austroads (2009) (p. 41), and also a cost
formula developed by Price and Entrada/San Juan
Inc. (2008), Eq. 3 presets a
function that models the slope factor based on the slope [%] and length
[m] of each road segment. This function, which is non-symmetric and
non-monotonic, reproduces the essential characteristics of the
slope/effort relationship.
In addition to this function, a second set of criteria is applied
(g), which increases the slope factor when road
segments have a given length [m] and slope [%], with intervals as
suggested by CEAP - Centro de Estudos de
Arquitectura Paisagista (n.d.)
. Eq. 4 shows that edges with gradient between 0 and 20 in the upward
direction are thus penalized by accumulation of effort.
\[slope factor_{(slope,length)} =
\begin{cases} 1.5 &\Leftarrow \quad slope <-30 \\
1+ 2\frac{0.7}{13} * slope +\frac{0.7}{13^2}*slope^2 &\Leftarrow -30
\leq slope <0 \\
1+ (\frac{slope}{g_{(slope, length)}})^2 &\Leftarrow 0 \leq slope
\leq20 \\
10 &\Leftarrow 20 <slope
\end{cases}\tag{Eq.3} \]
With,
\[g_{(slope,length)} = \begin{cases} 4
&\Leftarrow 10<slope \leq 13 \quad\wedge\quad length > 15\\
4.5 &\Leftarrow 8 <slope \leq 10 \quad\wedge\quad length > 30
\\
5 &\Leftarrow 5 <slope \leq 8 \quad\wedge\quad length > 60 \\
6 &\Leftarrow 3 <slope \leq 5 \quad\wedge\quad length > 120
\\
7 &\Leftarrow otherwise
\end{cases}\tag{Eq.4} \]
As the max penalization going uphill should not be 10 times more than
the flat speed, we add another condition to maximize the slope
factor, as follows:
\[slope factor_{(slope,length)}adjst =
\begin{cases}
10 &\Leftarrow slope >13 \quad\wedge\quad length >15 \\
10 &\Leftarrow slope >10 \quad\wedge\quad length >30 \\
10 &\Leftarrow slope >8 \quad\wedge\quad length >60 \\
10 &\Leftarrow slope >5 \quad\wedge\quad length >120 \\
\end{cases}\tag{Eq.5} \]
This functions result in a speed factor (in log scale) that
varies as this:

And, finally, we divide the constant flat speed by the slope
factor as :
\[
speed = \frac{speed_{flat}}{slope factor}\tag{Eq.5}
\]
What does it means
uphill?
When going uphill, speed will reduce, and longer the
road segments, higher the denominator, and slower the cyclist speed.
For instance, if assuming a constant flat speed of 15 km/h and a road
with 80 m and 3% uphill, a cyclist will reduce to 12.67 km/h
speedflat = 15
slope = 3
length = 50
speedflat / speedfactor(slope, length, g = g(slope, length))
## [1] 12.67241
If it is slightly steeper, with 4% uphill, a cyclist
will reduce to 11.31 km/h
slope = 4
length = 50
speedflat / speedfactor(slope, length, g = g(slope, length))
## [1] 11.30769
If that same segment is longer, a cyclist will
reduce to 10.38 km/h
slope = 4
length = 150
speedflat / speedfactor(slope, length, g = g(slope, length))
## [1] 10.38462
For higher gradients, the speed decreases with more
sensitivity regarding the segment length.
slope = 6
length = 60
speedflat / speedfactor(slope, length, g = g(slope, length))
## [1] 8.647059
slope = 6
length = 80
speedflat / speedfactor(slope, length, g = g(slope, length))
## [1] 6.147541
And for very steep streets, cycling speed may reduce
to walking speed.
slope = 9
length = 40
speedflat / speedfactor(slope, length, g = g(slope, length))
## [1] 3
And downhill?
In another hand, when going downhill, speeds will
increase until it gets 3.33x faster, when the gradient is 13%. For
steeper gradients, the cyclist will tend to break, and the speed will be
lower.
Until the moment when it gets so scary to ride it (again, for a
regular urban cyclist with mild experience), that it will take more time
to travel that road than if it was flat.
length = 100
slope = -8
speedflat / speedfactor(slope, length, g = g(slope, length))
## [1] 37.17009
slope = -13
speedflat / speedfactor(slope, length, g = g(slope, length))
## [1] 50
slope = -20
speedflat / speedfactor(slope, length, g = g(slope, length))
## [1] 29.82353
slope = -25
speedflat / speedfactor(slope, length, g = g(slope, length))
## [1] 16.73267
slope = -30
speedflat / speedfactor(slope, length, g = g(slope, length))
## [1] 10.01976
Case Study
Here we will use a small road network from downtown Lisbon
(Portugal), retrieved from slopes()
package, to test the
speed-slope factor.
This area is known for a flat and orthogonal set of streets,
surrounded by organic and steep streets, ranging from 0 to 21%.
For the purpose of the example, we will assign a direction of the
gradient, once that it was not defined.
And now compute the length, slope, and the speed-slope factor for
each segment. We can observe, in a logarithmic y-scale, that there are a
lot of flat or almost flat segments (factor around 1), some uphill
segments that reach factor 10, and some downhill segments that reach
factor 0.3.
#length and slope
DATA$length = st_length(DATA) |> units::drop_units() #in meters
DATA$slope[DATA$direction == "TF"] = -(DATA$slope[DATA$direction == "TF"])
slope = DATA$slope
length = DATA$length
#speed-slope factor
g = g(slope, length)
spf = speedfactor(slope, length, g)

By defining a flat speed of 16 km/h
, it results in
segments that are cycled up to 6 minutes uphill, and at a maximum speed
of 53 km/h.
#set speed
speedflat = 16 #set here in km/h (convert to m/s: speed/3.6)
DATA$speedfactor = spf
DATA$speed = speedflat / DATA$speedfactor
DATA$time = length / DATA$speed*3.6
mapview::mapview(DATA, zcol = "speed")
summary(DATA$speed)
## Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
## 1.60 12.58 16.00 19.71 23.90 53.31 5
mapview::mapview(DATA, zcol = "time")
summary(DATA$time)
## Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
## 0.1801 6.1184 13.7522 37.9580 35.7793 418.3530 5
This is a work in progress. Suggestions and comments are
welcome! :) github.com/U-Shift/Declives-RedeViaria/tree/main/SpeedSlopeFactor
Conclusion
For a hilly city, the slope factor is a good approach to model the
cost of the cyclist effort in a routing algorithm. It is a non-linear
and non-monotonic function that reproduces the essential characteristics
of the slope/effort relationship, and it is a good proxy for cyclist
effort. It is also a good approach to model the cyclist speed in a road
network.
Further research is needed to validate this approach, and to understand
how it can be applied to different types of cyclists, and to different
types of bicycles, as this method does not consider the effort on an
e-bike.
Plausible? Let’s discuss it!
References
AASHTO. 1999.
Guide for the Development of Bicycle Facilities.
Washington, DC: American Association of State Highway; Transportation
Officials.
http://safety.fhwa.dot.gov/ped_bike/docs/b_aashtobik.pdf.
Austroads. 2009. “Part 6A: Pedestrian and Cyclist Paths.”
In. Austroads.
Broach, Joseph. 2016. “Travel Mode Choice Framework Incorporating
Realistic Bike and Walk Routes.” PhD thesis.
Broach, Joseph, Jennifer Dill, and John Gliebe. 2012.
“Where Do
Cyclists Ride? A Route Choice Model Developed with Revealed Preference
GPS Data.” Transportation Research Part A: Policy and
Practice 46 (10): 1730–40.
https://doi.org/10.1016/j.tra.2012.07.005.
CEAP - Centro de Estudos de Arquitectura Paisagista. n.d.
“Contributos Para o Regulamento de Percursos Cicláveis Em
Portugal.”
Dijkstra, E. W. 1959.
“A Note on Two Problems in Connexion with
Graphs.” Numerische Mathematik 1 (1): 269–71.
https://doi.org/10.1007/bf01386390.
Félix, Rosa. 2012.
“Gestão Da Mobilidade Em Bicicleta:
Necessidades, Factores de Preferência e Ferramentas de Suporte Ao
Planeamento e Gestão de Redes. O Caso de Lisboa.” Master’s
thesis, Instituto Superior Técnico; University of Lisbon.
https://fenix.tecnico.ulisboa.pt/downloadFile/395144993029/GestaoMobilidadeBicicleta_RosaFelix_IST2012.pdf.
Hochmair, Hartwig. 2007. “Optimal Route Selection with Route
Planners: Results of a Desktop Usability Study.” In, 5–8.
Seattle, Washington: ACM GIS.
Price, Mike, and Entrada/San Juan Inc. 2008. “Slopes , Sharp Turns
, and Speed: Refining Emergency Response Networks to Accommodate Steep
Slopes and Turn Rules.” Hands On - ArcUser Spring 2008
11 (2): 50–57.
LS0tCnRpdGxlOiAiU3BlZWQtU2xvcGUgZmFjdG9yIgphdXRob3I6ICJSb3NhIEbDqWxpeCIKIyBkYXRlOiAiYHIgZm9ybWF0KFN5cy50aW1lKCksICclZCAlQiwgJVknKWAiCmRhdGU6ICIxNSBhcHJpbCwgMjAyMSIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICBmaWdfY2FwdGlvbjogeWVzCiAgICBrZWVwX3RleDogeWVzCiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKICAgIHRvY19kZXB0aDogMwogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiMgb3V0cHV0OgojICAgZ2l0aHViX2RvY3VtZW50OgojICAgICBwYW5kb2NfYXJnczogIi0td2VidGV4IgpiaWJsaW9ncmFwaHk6IHJlZnMuYmliCmxpbmstY2l0YXRpb25zOiB5ZXMKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQpgYGAKCmBgYHtyIGluY2x1ZGU9RkFMU0V9CiNpbXBvcnQgbGlicmFyaWVzCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHNmKQpsaWJyYXJ5KHNsb3BlcykKbGlicmFyeSh0bWFwKQpsaWJyYXJ5KG1hcHZpZXcpCm1hcHZpZXdPcHRpb25zKGZnYiA9IEZBTFNFKQpgYGAKClRoaXMgc2hvcnQgcGFwZXIgcHJvcG9zZXMgYSBzbG9wZSBmYWN0b3IgbWV0aG9kIHRvIGJlIHVzZWQgaW4gcm91dGluZyBhbGdvcml0aG1zIGZvciBjeWNsaW5nLCBzdWl0ZWQgZm9yIGhpbGx5IGNpdGllcy4KCiMgQ29zdCBmb3IgYmljeWNsZSByb3V0aW5nIG1vZGVscwoKQmljeWNsZSByb3V0aW5nIG1vZGVscyBhZGQgdG8gY2FyIHJvdXRpbmcgbW9kZWxpbmcgYSBncmVhdGVyIGNvbXBsZXhpdHkgdGhhdCByZXN1bHRzIGVzc2VudGlhbGx5IGZyb20gdGhlIGdyZWF0ZXIgbnVtYmVyIG9mIGRlZ3JlZXMgb2YgZnJlZWRvbSBhc3NvY2lhdGVkIHdpdGggY3ljbGluZyAoaS5lLiwgYSBzbWFsbGVyLCBsaWdodGVyIGFuZCBtb3JlIHZlcnNhdGlsZSB2ZWhpY2xlIGluIHRlcm1zIG9mIG1hbmV1dmVyaW5nKSBhbmQgdGhlIGZhY3QgdGhhdCBpdCBpcyBodW1hbiBwb3dlcmVkIGFuZCB0aGVyZWZvcmUgZGVwZW5kaW5nIG9uIGEgbGltaXRlZCBlbmVyZ3ksIHRodXMgZGVwZW5kaW5nIG9uIHRoZSBlZmZvcnQgdGhhdCBpcyB0cmFuc21pdHRlZCBieSB0aGUgY3ljbGlzdCBoaW1zZWxmLiBUaGlzIHJlc3VsdHMgaW4gYSBzZXJpZXMgb2Ygc3BlY2lmaWMgcGVjdWxpYXJpdGllcyBpbiBpdHMgcmlkaW5nLCBuYW1lbHk6IGEgZ3JlYXRlciBudW1iZXIgb2YgdmFyaWFibGVzIHJlbGV2YW50IHRvIHRoZSByb3V0aW5nIGNvc3QgZnVuY3Rpb24sIGFuZCB0aGUgZXhpc3RlbmNlIG9mIG1vcmUgc3ViamVjdGl2ZSB2YXJpYWJsZXMuCgpBIGNvbXBsZXhpdHkgaW52b2x2ZWQgaW4gbW9kZWxpbmcgcm91dGUgY2hvaWNlIGZvciBjeWNsaXN0cyByZXByZXNlbnRzIGEgY2hhbGxlbmdlLiBFdmVuIGlmIHdlIHVuZGVyc3RhbmQgd2hpY2ggdmFyaWFibGVzIGFyZSBkZXRlcm1pbmFudCBmb3Igcm91dGUgY2hvaWNlLCBtb2RlbHMgYmVjb21lIG1vcmUgYWNjdXJhdGUgaWYgaXQgaW5jb3Jwb3JhdGVzIHRoZSB2ZXJzYXRpbGl0eSBvZiB0aGUgYmljeWNsZSBpbiB1cmJhbiBjb250ZXh0LCBhbmQgaXRzIGFiaWxpdHkgdG8gY2lyY3VsYXRlIGluIG5vbi1yb2FkIHNwYWNlcy4KCkdJUyBhbGxvd3MgbW9kZWxpbmcgYSByb2FkIG5ldHdvcmsgaW4gdGhlIGZvcm0gb2YgYSB0b3BvbG9naWNhbCBncmFwaCwgdG8gd2hpY2ggYSBzZXJpZXMgb2YgZnVuY3Rpb25zIGFuZCBhbGdvcml0aG1zLCBpbmNsdWRpbmcgdGhlIGxlYXN0IGNvc3QgcGF0aCBbQGRpamtzdHJhMTk1OV0uIFRoZSBhcHBsaWNhdGlvbiBvZiB0aGUgbGVhc3QgY29zdCBwYXRoIGFsZ29yaXRobSBhc3N1bWVzIHRoZSBleGlzdGVuY2Ugb2YgYSBncmFwaCBmb3JtZWQgYnkgYSBzZXQgb2Ygc2V0IG9mIGVkZ2VzIGFuZCBub2Rlcy4gVGhlIGVkZ2VzIGNhbiBiZSBvcmllbnRlZCBvciBub3QgYW5kLCB0byB0aGVzZSwgYSB0cmF2ZWwgY29zdCBpcyBhc3NvY2lhdGVkLCB3aXRoIG9uZSBvciBtb3JlIHBhcmFtZXRlcnMsIG5ldmVyIGxlc3MgdGhhbiB6ZXJvLiBBc3NvY2lhdGluZyBhIHRyYXZlbCBjb3N0IHRvIGVhY2ggYXJjIGluIHRoZSBuZXR3b3JrLCB0aGUgcm91dGUgY29zdCBpcyBkZWZpbmVkIGFzIHRoZSBzdW0gb2YgdGhlIGNvc3RzIG9mIHRoZSBhcmNzIHRoYXQgY29tcG9zZSBpdC4KCiMjIFNwZWVkCgpGb3IgYSAqKmNvbnN0YW50KiogdXJiYW4gY3ljbGluZyBzcGVlZCB0cmF2ZWwgKCpmYWN0b3IgPSAxKiksIGxldCdzIHNheSAxNSBrbS9oLCB3ZSBhc3N1bWUgdGhhdCB0aGUgc3BlZWQgaXMgbGluZWFyIHRvIHRoZSBlZGdlIGV4dGVuc2lvbiwgYW5kIGl0cyBjb3N0IGlzIGl0cyB0cmF2ZWwgdGltZS4KCiQkIGNfe3NwZWVkfSA9IFxmcmFje2xlbmd0aF97W21dfX17c3BlZWRfe1ttL3NdfX0gPSB0aW1lX3tbc119XHRhZ3tFcS4xfSQkCgpNYW55IGZhY3RvcnMgbWF5IGJlIGRldGVybWluYW50IGZvciAqKmN5Y2xpbmcgc3BlZWQqKiwgc3VjaCB0aGUgc3VyZmFjZSBjb25kaXRpb25zLCB0cmFmZmljLCB3ZWF0aGVyLCBtYXNzLCB0eXBlIG9mIGJpY3ljbGUsIGRpcmVjdG5lc3MsIGNvbmZpZGVuY2UsIGV0YyBbQGhvY2htYWlyMjAwNzsgQEZlbGl4MjAxMjsgQGJyb2FjaDIwMTI7IEBicm9hY2gyMDE2XS4gSGVyZSB3ZSB3aWxsIGxvb2sgb25seSB0byAqKnNwZWVkIHJlbGF0ZWQgd2l0aCBncmFkaWVudCoqLCBmcm9tIHRoZSBwZXJzcGVjdGl2ZSBvZiBhIGNvbW1vbiB1cmJhbiBjeWNsaXN0LgoKIyMgU2xvcGUgb3IgZ3JhZGllbnQKCldoZW4gY29tZXMgdG8gY3ljbGluZywgdGhlIHJvdXRlIGdyYWRpZW50IGNhbiBiZSBhIGRldGVybWluYW50IHZhcmlhYmxlIHRvIGNob3NlIGEgcm91dGUgaW5zdGVhZCBvZiBhbiBhbHRlcm5hdGl2ZS4gSXQgaXMgY29tbW9ubHkga25vd24gdGhhdCBjeWNsaXN0cyBhcmUgYXZlcnNlIHRvIHJvYWRzIHdpdGggYW4gYXNjZW5kaW5nIGdyYWRpZW50LCBhbmQgdGhhdCBjeWNsaXN0cyBwcmVmZXIgcm9hZHMgd2l0aCBhIGRlc2NlbmRpbmcgZ3JhZGllbnQuIFRoZSAqKmRpcmVjdGlvbioqIG9mIHRoZSBncmFkaWVudCBpcyBkZXRlcm1pbmFudC4KCkl0IGlzIGFsc28ga25vd24sIGJ5IHRoZSBncmF2aXR5IGxhd3MsIHRoYXQgYW4gb2JqZWN0IHRyYXZlbGluZyBhdCBhIGNvbnN0YW50IHNwZWVkLCBpdHMgc3BlZWQgYmVjb21lcyBmYXN0ZXIgd2hlbiBnb2luZyBkb3duIHRoZSBoaWxsLCBhbmQgc2xvd2VyIHdoZW4gZ29pbmcgdXBoaWxsLiBCdXkgaG93IGRvZXMgaXQgYXBwbGllcyB0byBhIGh1bWFuIGJlaGF2aW9yPyBIb3cgZG9lcyBpdCB2YXJpZXMgd2hlbiBlZmZvcnQsIGZlYXIsIHN0YW1pbmEsIGFuZCByZXdhcmQgcGxheXMgYSByb2xlPyBXaGVuIGRvZXMgYSBjeWNsaXN0IHVzZSB0aGUgYnJlYWsgbGV2ZXJzPyBXaGVuIGRvZXMgYSBjeWNsaXN0IHNsb3dzIGhlciBwYWNlPwoKVGhlIHNsb3BlIGVudGVycyB0aGUgY29zdCBmdW5jdGlvbiBhcyBhIHByb3h5IGZvciBjeWNsaXN0IGVmZm9ydCAtIHRoZSBhbW91bnQgb2YgZW5lcmd5IGEgY3ljbGlzdCBtdXN0IGV4cGVuZCB0byB0cmF2ZWwgb24gYSBzdHJlZXQgd2l0aCBhIGdpdmVuIHNsb3BlIC0gY2F1c2luZyB0aGUgdHJhdmVyc2luZyB0aW1lIHRvIGluY3JlYXNlIGZvciB1cGhpbGwgcm91dGVzLiBPbiBkb3duaGlsbCByb3V0ZXMsIHRoZSBlZmZvcnQgaXMgcmVkdWNlZCBhbmQgdGhlIHRoZW9yZXRpY2FsIHNwZWVkIGlzIGluY3JlYXNlZCwgcmVkdWNpbmcgdGhlaXIgdHJhdmVyc2luZyB0aW1lLgoKQHNjb3R0MjAyMCBkZXNpZ25lZCBhbiBleHBlcmltZW50IGZvciBoaWtpbmcsIGFuZCBhcHBsaWVkIGEgcnVsZSBzYXlpbmcgIipBIDEwJSBncmFkZSBpbmNsaW5lIGN1dHMgeW91ciBzcGVlZCBpbiBoYWxmIioqLioqKiBJbiB0aGVpciByZXN1bHRzLCB0aGV5IHN1Z2dlc3RlZCBhbiBlcXVhdGlvbiB0byBjYWxjdWxhdGUgdXBoaWxsIHNwZWVkIChmb3IgaGlraW5nKToKCiQkCnNwZWVkID0gc3BlZWRfe2ZsYXR9ICogZV57KC0wLjA0KnNsb3BlKX1cdGFne0VxLjJ9CiQkCgpXaGljaCByZXN1bHRzIHRoYXQgd2l0aCBhIGdyYWRlIG9mIDIwJSwgb25lIGNhbiB3YWxrIGF0IGEgc3BlZWQgb2YgMS43OCBrbS9oIGl0IGhlciBob3Jpem9udGFsIHNwZWVkIHdhcyA0IGttL2guIFdoZW4gYXBwbHlpbmcgdG8gY3ljbGluZywgZm9yIGEgZmxhdCBzcGVlZCBvZiAxNWttL2gsIHRoZSBzYW1lIGluY2xpbmUgd291bGQgYmUgcmlkZSBhdCBhIDYuNzQga20vaCBzcGVlZCwgd2hpY2ggaXMgbm90IHJlbGlhYmxlIGZvciBhIHN0YW5kYXJkIGN5Y2xpc3QuCgpBbHNvLCB0aGUgZXh0ZW5zaW9uIG9mIHRoZSByb2FkIHNlZ21lbnQgZW50ZXJzIGluIHRoZSBjb3N0IGZ1bmN0aW9uOiBmb3IgbG9uZ2VyIHNlZ21lbnRzIGF0IGEgZ2l2ZW4gZ3JhZGllbnQsIHRoZSBlZmZvcnQgb2YgdGhlIGN5Y2xpc3QgaXMgaGlnaGVyIHRoYW4gZm9yIGEgc2hvcnRlciBzZWdtZW50IHdpdGggdGhlIHNhbWUgZ3JhZGllbnQuCgpGaWd1cmUgMSBzaG93cyB0aGUgbWF4aW11bSBsZW5ndGhzIG9mIHVwaGlsbCBncmFkaWVudCBhY2NlcHRhYmxlIHRvIGN5Y2xpc3RzIFtAYXVzdHJvYWRzMjAwOV0uIEl0IGNvbnNpZGVycyB0aGF0IG92ZXIgYSAzJSBzbG9wZSwgdGhlIGxlbmd0aCBzaG91bGQgYmUgdGFrZW4gaW50byBhY2NvdW50LgoKIVtGaWcuIDEgLSBEZXNpcmFibGUgdXBoaWxsIGdyYWRpZW50cyBmb3IgZWFzZSBvZiBjeWNsaW5nIChBdXN0cm9hZHMgMjAwOSldKFNwZWVkU2xvcGVGYWN0b3JfZmlsZXMvYXVzdHJvYWRzMjAwOV9ncmFkaWVudC5QTkcpCgpTb21ldGltZXMgaXQgaXMgbW9yZSBlZmZpY2llbnQgdG8gdHJhdmVsIGEgbG9uZ2VyIGRpc3RhbmNlIHdpdGggbGVzcyBzdGVlcCBncmFkaWVudHMgcmF0aGVyIHRoYW4gYSBzaG9ydGVyIGRpc3RhbmNlIG9uIGEgc3RlZXAgZ3JhZGllbnQuIE90aGVyIHRpbWVzIHRoZSBleHRyYSBkaXN0YW5jZSB0byByaWRlIHRvIG92ZXJjb21lIHRoZSBncmFkaWVudCBpcyBub3Qgc28gd29ydGh3aGlsZSBhbmQgdGhlIGN5Y2xpc3QgY2hvb3NlcyB0byByaWRlIHVwIHRoZSBzdGVlcGVyIGdyYWRpZW50IGJ5IGhhbmQuIFRoZSBtYXhpbXVtIGNyb3NzaW5nIGNvc3QgcGVuYWx0eSB3YXMgY29uc2lkZXJlZCB0byBiZSAxMCB0aW1lcyBmb3IgdGhpcyBzaXR1YXRpb24sIGkuZS4gZm9yIGVkZ2VzIHdpdGggYSBncmFkaWVudCBncmVhdGVyIHRoYW4gMjAlLgoKVmVyeSBzdGVlcCByb2FkcyBhcmUgYSBwcm9ibGVtIG5vdCBvbmx5IGZvciB1cGhpbGwgcmlkaW5nLCBidXQgYWxzbyBmb3IgZG93bmhpbGwgcmlkaW5nLCBiZWNhdXNlIGEgbWVjaGFuaWNhbCBmYWlsdXJlIGluIHRoZSBicmFrZXMgY2FuIGxlYWQgdG8gYSBkYW5nZXJvdXMgc2l0dWF0aW9uIGZvciB0aGUgcmlkZXIsIHdobyBhbHNvIGhhcyB0byBleHBlbmQgc29tZSBlZmZvcnQgYW5kIHNraWxsIHRvIGtlZXAgdGhlIGJpa2UgYmFsYW5jZWQgYW5kIGNvbnRyb2wgdGhlIGFkZGl0aW9uYWwgcmlzay4KCiFbRmlnLiAyIC0gV29ybGQncyBzdGVlcGVzdCBzdHJlZXQsIHdpdGggYSAzNSUgaW5jbGluZSBmb3Igb3ZlciAxNjEgbWV0ZXJzLiBCYWxkd2luIFN0cmVldCwgRHVuZWRpbiwgTmV3IFplYWxhbmQgKFBob3RvOiBXaWtpcGVkaWEpXShodHRwczovL3VwbG9hZC53aWtpbWVkaWEub3JnL3dpa2lwZWRpYS9jb21tb25zL2IvYjgvRHVuZWRpbkJhbGR3aW5TdHJlZXRfUGFya2VkX0Nhci5qcGcpe3dpZHRoPSI1MDAiIGFsaWduPSJcImNlbnRlciJ9CgpEb3duaGlsbCBlZGdlcyBtb3N0bHkgcmVzdWx0IGluIGJlbmVmaXQgdG8gdGhlIGN5Y2xpc3QsIGluY3JlYXNpbmcgaXRzIHNwZWVkLiBIb3dldmVyLCB0aGlzIGlzIG5vdCBsaW5lYXIsIGRlY3JlYXNpbmcgZnJvbSBzbG9wZSB2YWx1ZXMgYWJvdmUgMTMlLCBhbmQgbWF5IGV2ZW4gc2xvdyBkb3duIHRoZSBzcGVlZCAocmVsYXRpdmUgdG8gdGhlIGF2ZXJhZ2UgZmxhdCBzcGVlZCkgaXQgdG9vIHN0ZWVwLgoKIyBTcGVlZC1TbG9wZSBGYWN0b3IKCkFmdGVyIGFuIGl0ZXJhdGl2ZSBwcm9jZXNzLCB3aGljaCBjb25zaWRlcmVkIHRoZSBjeWNsaXN0IGVmZm9ydCBhcyBhIGZ1bmN0aW9uIG9mIHNsb3BlIGFiYWN1c2VzIHN1Z2dlc3RlZCBieSBAYWFzaHRvMTk5OSBhbmQgQGF1c3Ryb2FkczIwMDkgKHAuIDQxKSwgYW5kIGFsc28gYSBjb3N0IGZvcm11bGEgZGV2ZWxvcGVkIGJ5IEBwcmljZTIwMDgsIEVxLiAzIHByZXNldHMgYSBmdW5jdGlvbiB0aGF0IG1vZGVscyB0aGUgc2xvcGUgZmFjdG9yIGJhc2VkIG9uIHRoZSBzbG9wZSBbJV0gYW5kIGxlbmd0aCBbbV0gb2YgZWFjaCByb2FkIHNlZ21lbnQuIFRoaXMgZnVuY3Rpb24sIHdoaWNoIGlzIG5vbi1zeW1tZXRyaWMgYW5kIG5vbi1tb25vdG9uaWMsIHJlcHJvZHVjZXMgdGhlIGVzc2VudGlhbCBjaGFyYWN0ZXJpc3RpY3Mgb2YgdGhlIHNsb3BlL2VmZm9ydCByZWxhdGlvbnNoaXAuCgpJbiBhZGRpdGlvbiB0byB0aGlzIGZ1bmN0aW9uLCBhIHNlY29uZCBzZXQgb2YgY3JpdGVyaWEgaXMgYXBwbGllZCAoKmcqKSwgd2hpY2ggaW5jcmVhc2VzIHRoZSAqc2xvcGUgZmFjdG9yKiB3aGVuIHJvYWQgc2VnbWVudHMgaGF2ZSBhIGdpdmVuIGxlbmd0aCBbbV0gYW5kIHNsb3BlIFslXSwgd2l0aCBpbnRlcnZhbHMgYXMgc3VnZ2VzdGVkIGJ5IEBjZWFwLWNlbnRyb2RlZXN0dWRvc2RlYXJxdWl0ZWN0dXJhcGFpc2FnaXN0YSAuIEVxLiA0IHNob3dzIHRoYXQgZWRnZXMgd2l0aCBncmFkaWVudCBiZXR3ZWVuIDAgYW5kIDIwIGluIHRoZSB1cHdhcmQgZGlyZWN0aW9uIGFyZSB0aHVzIHBlbmFsaXplZCBieSBhY2N1bXVsYXRpb24gb2YgZWZmb3J0LgoKJCRzbG9wZSBmYWN0b3JfeyhzbG9wZSxsZW5ndGgpfSA9IFxiZWdpbntjYXNlc30gMS41ICZcTGVmdGFycm93IFxxdWFkIHNsb3BlIDwtMzAgXFwKMSsgMlxmcmFjezAuN317MTN9ICogc2xvcGUgK1xmcmFjezAuN317MTNeMn0qc2xvcGVeMiAmXExlZnRhcnJvdyAtMzAgXGxlcSBzbG9wZSA8MCBcXAoxKyAoXGZyYWN7c2xvcGV9e2dfeyhzbG9wZSwgbGVuZ3RoKX19KV4yICZcTGVmdGFycm93IDAgXGxlcSBzbG9wZSBcbGVxMjAgXFwKMTAgJlxMZWZ0YXJyb3cgMjAgPHNsb3BlIApcZW5ke2Nhc2VzfVx0YWd7RXEuM30gJCQKCldpdGgsCgokJGdfeyhzbG9wZSxsZW5ndGgpfSA9IFxiZWdpbntjYXNlc30gNCAmXExlZnRhcnJvdyAxMDxzbG9wZSBcbGVxIDEzIFxxdWFkXHdlZGdlXHF1YWQgIGxlbmd0aCA+IDE1XFwKNC41ICZcTGVmdGFycm93IDggPHNsb3BlIFxsZXEgMTAgXHF1YWRcd2VkZ2VccXVhZCAgbGVuZ3RoID4gMzAgXFwKNSAmXExlZnRhcnJvdyA1IDxzbG9wZSBcbGVxIDggXHF1YWRcd2VkZ2VccXVhZCAgbGVuZ3RoID4gNjAgXFwKNiAmXExlZnRhcnJvdyAzIDxzbG9wZSBcbGVxIDUgXHF1YWRcd2VkZ2VccXVhZCAgbGVuZ3RoID4gMTIwIFxcCjcgJlxMZWZ0YXJyb3cgb3RoZXJ3aXNlIApcZW5ke2Nhc2VzfVx0YWd7RXEuNH0gJCQKCkFzIHRoZSBtYXggcGVuYWxpemF0aW9uIGdvaW5nIHVwaGlsbCBzaG91bGQgbm90IGJlIDEwIHRpbWVzIG1vcmUgdGhhbiB0aGUgZmxhdCBzcGVlZCwgd2UgYWRkIGFub3RoZXIgY29uZGl0aW9uIHRvIG1heGltaXplIHRoZSAqKnNsb3BlIGZhY3RvcioqLCBhcyBmb2xsb3dzOgoKJCRzbG9wZSBmYWN0b3JfeyhzbG9wZSxsZW5ndGgpfWFkanN0ID0gXGJlZ2lue2Nhc2VzfSAKMTAgJlxMZWZ0YXJyb3cgc2xvcGUgPjEzIFxxdWFkXHdlZGdlXHF1YWQgIGxlbmd0aCA+MTUgXFwKMTAgJlxMZWZ0YXJyb3cgc2xvcGUgPjEwIFxxdWFkXHdlZGdlXHF1YWQgIGxlbmd0aCA+MzAgXFwKMTAgJlxMZWZ0YXJyb3cgc2xvcGUgPjggXHF1YWRcd2VkZ2VccXVhZCAgbGVuZ3RoID42MCBcXAoxMCAmXExlZnRhcnJvdyBzbG9wZSA+NSBccXVhZFx3ZWRnZVxxdWFkICBsZW5ndGggPjEyMCBcXApcZW5ke2Nhc2VzfVx0YWd7RXEuNX0gJCQKCjwhLS0gJCRzbG9wZWZhY3Rvcl97KHNsb3BlLGxlbmd0aCl9ID4gMTAgXFJpZ2h0YXJyb3cgc2xvcGUgZmFjdG9yX3soc2xvcGUsbGVuZ3RoKX1hZGpzdCA9IDEwIFx0YWd7RXEuNH0gJCQtLT4KCmBgYHtyIGluY2x1ZGU9RkFMU0V9CiNnIGZ1bmN0aW9uCmcgPSBmdW5jdGlvbihzbG9wZSwgbGVuZ3RoKXsKICBpZmVsc2UoKHNsb3BlID4gMTAgJiBzbG9wZSA8PSAxMyAmIGxlbmd0aCA+IDE1KSwgNCwgCiAgICBpZmVsc2UoKHNsb3BlID4gOCAmIHNsb3BlIDw9IDEwICYgbGVuZ3RoID4gMzApLCA0LjUsCiAgICAgIGlmZWxzZSgoc2xvcGUgPiA1ICYgc2xvcGUgPD0gOCAmIGxlbmd0aCA+IDYwKSwgNSwgCiAgICAgICAgaWZlbHNlKChzbG9wZSA+IDMgJiBzbG9wZSA8PSA1ICYgbGVuZ3RoID4gMTIwKSwgNiwgCiAgICAgICAgICAgICAgIDcpKSkpCn0KCiNzbG9wZS1mYWN0b3IgZnVuY3Rpb24Kc3BlZWRmYWN0b3IgPSBmdW5jdGlvbihzbG9wZSwgbGVuZ3RoLCBnKSB7CiAgaWZlbHNlKGlmZWxzZSgoc2xvcGUgPCAtMzApLDEuNSwKICAgICAgICBpZmVsc2Uoc2xvcGUgPCAwLCAxICsgKDAuNyAvIDEzKSAqIDIgKiBzbG9wZSArIDAuNyAvICgxMyBeIDIpICogc2xvcGUgXiAyLAogICAgICAgICAgIGlmZWxzZSgoc2xvcGUgPiAyMCksIDEwLAogICAgICAgICAgICAgIGlmZWxzZSgoc2xvcGUgPj0gMCAmIHNsb3BlIDw9IDIwKSwgMSArIChzbG9wZSAvIGcpIF4gMiwKICAgICAgICAgICAgICAgICAgTkEpKSkpID4xMCwgMTAsCiAgICAgIGlmZWxzZSgoc2xvcGUgPCAtMzApLDEuNSwKICAgICAgICBpZmVsc2Uoc2xvcGUgPCAwLCAxICsgKDAuNyAvIDEzKSAqIDIgKiBzbG9wZSArIDAuNyAvICgxMyBeIDIpICogc2xvcGUgXiAyLAogICAgICAgICAgIGlmZWxzZSgoc2xvcGUgPiAyMCksIDEwLAogICAgICAgICAgICAgIGlmZWxzZSgoc2xvcGUgPj0gMCAmIHNsb3BlIDw9IDIwKSwgMSArIChzbG9wZSAvIGcpIF4gMiwKICAgICAgICAgICAgICAgICAgTkEpKSkpKQp9CiNUaGVyZSBpcyBwcm9iYWJseSBhIHdheSB0byB3cml0ZSB0aGlzIGNvZGUgY2xlYW5lci4uLgpgYGAKClRoaXMgZnVuY3Rpb25zIHJlc3VsdCBpbiBhIHNwZWVkIGZhY3RvciAoaW4gKmxvZyogc2NhbGUpIHRoYXQgdmFyaWVzIGFzIHRoaXM6CgpgYGB7ciBlY2hvPUZBTFNFfQpjdXJ2ZSgKICBleHByID0gc3BlZWRmYWN0b3Ioc2xvcGUgPSB4LCBnID0gNywgbGVuZ3RoID0gMTIwKSwKICBmcm9tID0gLTM1LCB0byA9IDI1LCBjb2wgPSAiYmx1ZSIsIGx3ZCA9IDMsIGxvZyA9ICJ5IiwKICB4bGFiID0gInNsb3BlIFslXSIsIHlsYWIgPSAic2xvcGUgZmFjdG9yIikKY3VydmUoCiAgZXhwciA9IHNwZWVkZmFjdG9yKHNsb3BlID0geCwgZyA9IDQsIGxlbmd0aCA9IDEyMCksCiAgZnJvbSA9IDEwLCB0byA9IDI1LCBjb2wgPSAicHVycGxlIiwgbHdkID0gMiwgbHR5ID0gNSwgbG9nID0gInkiLCBhZGQgPSBUKQpjdXJ2ZSgKICBleHByID0gc3BlZWRmYWN0b3Ioc2xvcGUgPSB4LCBnID0gNC41LCBsZW5ndGggPSAxMjApLAogIGZyb20gPSA4LCB0byA9IDI1LCBjb2wgPSAiZ3JleSIsIGx3ZCA9IDIsIGx0eSA9IDQsIGxvZyA9ICJ5IiwgYWRkID0gVCkKY3VydmUoCiAgZXhwciA9IHNwZWVkZmFjdG9yKHNsb3BlID0geCwgZyA9IDUsIGxlbmd0aCA9IDEyMCksCiAgZnJvbSA9IDUsIHRvID0gMjUsIGNvbCA9ICJvcmFuZ2UiLCBsd2QgPSAyLCBsdHkgPSAzLCBsb2cgPSAieSIsIGFkZCA9IFQpCmN1cnZlKAogIGV4cHIgPSBzcGVlZGZhY3RvcihzbG9wZSA9IHgsIGcgPSA2LCBsZW5ndGggPSAxMjApLAogIGZyb20gPSAzLCB0byA9IDI1LCBjb2wgPSAicmVkIiwgbHdkID0gMiwgbHR5ID0gMiwgbG9nID0gInkiLCBhZGQgPSBUKQpjdXJ2ZSgKICBleHByID0gc3BlZWRmYWN0b3Ioc2xvcGUgPSB4LCBnID0gNywgbGVuZ3RoID0gMTIwKSwKICBmcm9tID0gLTM1LCB0byA9IDI1LCBjb2wgPSAiYmx1ZSIsIGx3ZCA9IDIsIGxvZyA9ICJ5IiwgYWRkID0gVCkKYWJsaW5lKGggPSAxLCB2ID0gMCwgbHR5ID0gMykKdGl0bGUobWFpbiA9ICJTbG9wZS1TcGVlZCBmdW5jdGlvbiIpCmxlZ2VuZCgtMzAsIDksCiAgbGVnZW5kID0gYygKICAgICJzcGVlZCBmYWN0b3IgKGJhc2UpIiwKICAgICJzbG9wZSA+MyUsIGxlbmd0aCA+MTIwIG0iLAogICAgInNsb3BlID41JSwgbGVuZ3RoID42MCBtIiwKICAgICJzbG9wZSA+OCUsIGxlbmd0aCA+MzAgbSIsCiAgICAic2xvcGUgPjEwJSwgbGVuZ3RoID4xNSBtIiksCiAgY29sID0gYygiYmx1ZSIsICJyZWQiLCAib3JhbmdlIiwgImdyZXkiLCAicHVycGxlIiksCiAgbHR5ID0gMTo1LCBjZXggPSAwLjksIGx3ZCA9IGMoMywgMiwgMiwgMiwgMiksIGJveC5sdHkgPSAwKQpgYGAKCkFuZCwgZmluYWxseSwgd2UgZGl2aWRlIHRoZSBjb25zdGFudCBmbGF0IHNwZWVkIGJ5IHRoZSAqc2xvcGUgZmFjdG9yKiBhcyA6CgokJApzcGVlZCA9IFxmcmFje3NwZWVkX3tmbGF0fX17c2xvcGUgZmFjdG9yfVx0YWd7RXEuNX0KJCQKCmBgYHtyIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CnNwZWVkID0gc3BlZWRmbGF0IC8gc3BlZWRmYWN0b3Ioc2xvcGUsIGxlbmd0aCwgZyA9IGcoc2xvcGUsIGxlbmd0aCkpCmBgYAoKIyMgV2hhdCBkb2VzIGl0IG1lYW5zIHVwaGlsbD8KCldoZW4gZ29pbmcgKip1cGhpbGwqKiwgc3BlZWQgd2lsbCByZWR1Y2UsIGFuZCBsb25nZXIgdGhlIHJvYWQgc2VnbWVudHMsIGhpZ2hlciB0aGUgZGVub21pbmF0b3IsIGFuZCBzbG93ZXIgdGhlIGN5Y2xpc3Qgc3BlZWQuCgpGb3IgaW5zdGFuY2UsIGlmIGFzc3VtaW5nIGEgY29uc3RhbnQgZmxhdCBzcGVlZCBvZiAxNSBrbS9oIGFuZCBhIHJvYWQgd2l0aCA4MCBtIGFuZCAzJSB1cGhpbGwsIGEgY3ljbGlzdCB3aWxsIHJlZHVjZSB0byAxMi42NyBrbS9oCgpgYGB7cn0Kc3BlZWRmbGF0ID0gMTUKc2xvcGUgPSAzCmxlbmd0aCA9IDUwCnNwZWVkZmxhdCAvIHNwZWVkZmFjdG9yKHNsb3BlLCBsZW5ndGgsIGcgPSBnKHNsb3BlLCBsZW5ndGgpKQpgYGAKCklmIGl0IGlzIHNsaWdodGx5ICoqc3RlZXBlcioqLCB3aXRoIDQlIHVwaGlsbCwgYSBjeWNsaXN0IHdpbGwgcmVkdWNlIHRvIDExLjMxIGttL2gKCmBgYHtyfQpzbG9wZSA9IDQKbGVuZ3RoID0gNTAKc3BlZWRmbGF0IC8gc3BlZWRmYWN0b3Ioc2xvcGUsIGxlbmd0aCwgZyA9IGcoc2xvcGUsIGxlbmd0aCkpCmBgYAoKSWYgdGhhdCBzYW1lIHNlZ21lbnQgaXMgKipsb25nZXIqKiwgYSBjeWNsaXN0IHdpbGwgcmVkdWNlIHRvIDEwLjM4IGttL2gKCmBgYHtyfQpzbG9wZSA9IDQKbGVuZ3RoID0gMTUwCnNwZWVkZmxhdCAvIHNwZWVkZmFjdG9yKHNsb3BlLCBsZW5ndGgsIGcgPSBnKHNsb3BlLCBsZW5ndGgpKQpgYGAKCkZvciAqKmhpZ2hlciBncmFkaWVudHMqKiwgdGhlIHNwZWVkIGRlY3JlYXNlcyB3aXRoIG1vcmUgc2Vuc2l0aXZpdHkgcmVnYXJkaW5nIHRoZSAqKnNlZ21lbnQgbGVuZ3RoKiouCgpgYGB7cn0Kc2xvcGUgPSA2Cmxlbmd0aCA9IDYwCnNwZWVkZmxhdCAvIHNwZWVkZmFjdG9yKHNsb3BlLCBsZW5ndGgsIGcgPSBnKHNsb3BlLCBsZW5ndGgpKQpgYGAKCmBgYHtyfQpzbG9wZSA9IDYKbGVuZ3RoID0gODAKc3BlZWRmbGF0IC8gc3BlZWRmYWN0b3Ioc2xvcGUsIGxlbmd0aCwgZyA9IGcoc2xvcGUsIGxlbmd0aCkpCmBgYAoKQW5kIGZvciAqKnZlcnkgc3RlZXAgc3RyZWV0cyoqLCBjeWNsaW5nIHNwZWVkIG1heSByZWR1Y2UgdG8gd2Fsa2luZyBzcGVlZC4KCmBgYHtyfQpzbG9wZSA9IDkKbGVuZ3RoID0gNDAKc3BlZWRmbGF0IC8gc3BlZWRmYWN0b3Ioc2xvcGUsIGxlbmd0aCwgZyA9IGcoc2xvcGUsIGxlbmd0aCkpCmBgYAoKIyMgQW5kIGRvd25oaWxsPwoKSW4gYW5vdGhlciBoYW5kLCB3aGVuIGdvaW5nICoqZG93bmhpbGwqKiwgc3BlZWRzIHdpbGwgaW5jcmVhc2UgdW50aWwgaXQgZ2V0cyAzLjMzeCBmYXN0ZXIsIHdoZW4gdGhlIGdyYWRpZW50IGlzIDEzJS4gRm9yIHN0ZWVwZXIgZ3JhZGllbnRzLCB0aGUgY3ljbGlzdCB3aWxsIHRlbmQgdG8gYnJlYWssIGFuZCB0aGUgc3BlZWQgd2lsbCBiZSBsb3dlci4KClVudGlsIHRoZSBtb21lbnQgd2hlbiBpdCBnZXRzIHNvIHNjYXJ5IHRvIHJpZGUgaXQgKGFnYWluLCBmb3IgYSByZWd1bGFyIHVyYmFuIGN5Y2xpc3Qgd2l0aCBtaWxkIGV4cGVyaWVuY2UpLCB0aGF0IGl0IHdpbGwgdGFrZSBtb3JlIHRpbWUgdG8gdHJhdmVsIHRoYXQgcm9hZCB0aGFuIGlmIGl0IHdhcyBmbGF0LgoKYGBge3J9Cmxlbmd0aCA9IDEwMApzbG9wZSA9IC04CnNwZWVkZmxhdCAvIHNwZWVkZmFjdG9yKHNsb3BlLCBsZW5ndGgsIGcgPSBnKHNsb3BlLCBsZW5ndGgpKQpzbG9wZSA9IC0xMwpzcGVlZGZsYXQgLyBzcGVlZGZhY3RvcihzbG9wZSwgbGVuZ3RoLCBnID0gZyhzbG9wZSwgbGVuZ3RoKSkKc2xvcGUgPSAtMjAKc3BlZWRmbGF0IC8gc3BlZWRmYWN0b3Ioc2xvcGUsIGxlbmd0aCwgZyA9IGcoc2xvcGUsIGxlbmd0aCkpCnNsb3BlID0gLTI1CnNwZWVkZmxhdCAvIHNwZWVkZmFjdG9yKHNsb3BlLCBsZW5ndGgsIGcgPSBnKHNsb3BlLCBsZW5ndGgpKQpzbG9wZSA9IC0zMApzcGVlZGZsYXQgLyBzcGVlZGZhY3RvcihzbG9wZSwgbGVuZ3RoLCBnID0gZyhzbG9wZSwgbGVuZ3RoKSkKYGBgCgojIENhc2UgU3R1ZHkKCkhlcmUgd2Ugd2lsbCB1c2UgYSBzbWFsbCByb2FkIG5ldHdvcmsgZnJvbSBkb3dudG93biBMaXNib24gKFBvcnR1Z2FsKSwgcmV0cmlldmVkIGZyb20gYHNsb3BlcygpYCBwYWNrYWdlLCB0byB0ZXN0IHRoZSBzcGVlZC1zbG9wZSBmYWN0b3IuCgpUaGlzIGFyZWEgaXMga25vd24gZm9yIGEgZmxhdCBhbmQgb3J0aG9nb25hbCBzZXQgb2Ygc3RyZWV0cywgc3Vycm91bmRlZCBieSBvcmdhbmljIGFuZCBzdGVlcCBzdHJlZXRzLCByYW5naW5nIGZyb20gMCB0byAyMSUuCgpgYGB7ciBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQojdXNlIGV4YW1wbGUgZnJvbSBzbG9wZXMoKQpEQVRBID0gc2xvcGVzOjpsaXNib25fcm9hZF9uZXR3b3JrCkRBVEEkc2xvcGVfZGlyZWN0ZWQgPSBzbG9wZV9yYXN0ZXIoREFUQSwgZGVtID0gZGVtX2xpc2Jvbl9yYXN0ZXIsIGRpcmVjdGVkID0gVFJVRSkgIyBuZWdhdGl2ZSBpcyBkb3duaGlsbApEQVRBJHNsb3BlID0gMTAwKmFicyhEQVRBJHNsb3BlX2RpcmVjdGVkKQpEQVRBJHNsb3BlX2NsYXNzID0gREFUQSRzbG9wZSAlPiUgCiAgY3V0KAogICAgYnJlYWtzID0gYygwLCAzLCA1LCA4LCAxMCwgMjAsIEluZiksCiAgICBsYWJlbHMgPSBjKCIwLTM6IGZsYXQiLCAiMy01OiBtaWxkIiwgIjUtODogbWVkaXVtIiwgIjgtMTA6IGhhcmQiLCAiMTAtMjA6IGV4dHJlbWUiLCAiPjIwOiBpbXBvc3NpYmxlIiksCiAgICByaWdodCA9IEYKICApCnBhbHJlZGdyZWVuID0gYygiIzI2NzMwMCIsICIjNzBBODAwIiwgIiNGRkFBMDAiLCAiI0U2MDAwMCIsICIjQTgwMDAwIiwgIiM3MzAwMDAiKQp0bWFwX21vZGUoInZpZXciKQp0bV9zaGFwZShEQVRBKSArCiAgdG1fbGluZXMoCiAgICBjb2wgPSAic2xvcGVfY2xhc3MiLAogICAgcGFsZXR0ZSA9IHBhbHJlZGdyZWVuLAogICAgbHdkID0gMiwKICAgIGlkID0gInNsb3BlIikKYGBgCgpGb3IgdGhlIHB1cnBvc2Ugb2YgdGhlIGV4YW1wbGUsIHdlIHdpbGwgYXNzaWduIGEgZGlyZWN0aW9uIG9mIHRoZSBncmFkaWVudCwgb25jZSB0aGF0IGl0IHdhcyBub3QgZGVmaW5lZC4KCmBgYHtyIGVjaG89RkFMU0UsIHdhcm5pbmc9RkFMU0V9CiNhc3NpZ24gYSBkaXJlY3Rpb24gb2Ygc2xvcGUsIGZvciB0aGUgcHVycG9zZSBvZiB0aGUgZXhhbXBsZQpEQVRBJGRpcmVjdGlvbiA9ICJGVCIgI0Zyb20tVG8KREFUQSRkaXJlY3Rpb25bREFUQSRzbG9wZV9kaXJlY3RlZCA8IDBdID0gIlRGIiAjVG8tRnJvbQoKbWFwdmlldzo6bWFwdmlldyhEQVRBWyJkaXJlY3Rpb24iXSwgIHNlbGZjb250YWluZWQ9VFJVRSkKYGBgCgpBbmQgbm93IGNvbXB1dGUgdGhlIGxlbmd0aCwgc2xvcGUsIGFuZCB0aGUgc3BlZWQtc2xvcGUgZmFjdG9yIGZvciBlYWNoIHNlZ21lbnQuIFdlIGNhbiBvYnNlcnZlLCBpbiBhIGxvZ2FyaXRobWljIHktc2NhbGUsIHRoYXQgdGhlcmUgYXJlIGEgbG90IG9mIGZsYXQgb3IgYWxtb3N0IGZsYXQgc2VnbWVudHMgKGZhY3RvciBhcm91bmQgMSksIHNvbWUgdXBoaWxsIHNlZ21lbnRzIHRoYXQgcmVhY2ggZmFjdG9yIDEwLCBhbmQgc29tZSBkb3duaGlsbCBzZWdtZW50cyB0aGF0IHJlYWNoIGZhY3RvciAwLjMuCgpgYGB7cn0KI2xlbmd0aCBhbmQgc2xvcGUKREFUQSRsZW5ndGggPSBzdF9sZW5ndGgoREFUQSkgfD4gdW5pdHM6OmRyb3BfdW5pdHMoKSAjaW4gbWV0ZXJzCkRBVEEkc2xvcGVbREFUQSRkaXJlY3Rpb24gPT0gIlRGIl0gPSAtKERBVEEkc2xvcGVbREFUQSRkaXJlY3Rpb24gPT0gIlRGIl0pCnNsb3BlID0gREFUQSRzbG9wZQpsZW5ndGggPSBEQVRBJGxlbmd0aAoKI3NwZWVkLXNsb3BlIGZhY3RvcgpnID0gZyhzbG9wZSwgbGVuZ3RoKQpzcGYgPSBzcGVlZGZhY3RvcihzbG9wZSwgbGVuZ3RoLCBnKQpgYGAKCmBgYHtyIGVjaG89RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmN1cnZlKAogIGV4cHIgPSBzcGVlZGZhY3RvcihzbG9wZSA9IHgsIGcgPSA3LCBsZW5ndGggPSAxMjApLAogIGZyb20gPSAtMzUsIHRvID0gMzAsIGNvbCA9ICJibHVlIiwgbHdkID0gMSwgbG9nID0gInkiLAogIHhsYWIgPSAic2xvcGUgWyVdIiwgeWxhYiA9ICJzbG9wZSBmYWN0b3IiKQpjdXJ2ZSgKICBleHByID0gc3BlZWRmYWN0b3Ioc2xvcGUgPSB4LCBnID0gNCwgbGVuZ3RoID0gMTIwKSwKICBmcm9tID0gMTAsIHRvID0gMzAsIGNvbCA9ICJwdXJwbGUiLCBsd2QgPSAxLCBsdHkgPSA1LCBsb2cgPSAieSIsIGFkZCA9IFQpCmN1cnZlKAogIGV4cHIgPSBzcGVlZGZhY3RvcihzbG9wZSA9IHgsIGcgPSA0LjUsIGxlbmd0aCA9IDEyMCksCiAgZnJvbSA9IDgsIHRvID0gMzAsIGNvbCA9ICJncmV5IiwgbHdkID0gMSwgbHR5ID0gNCwgbG9nID0gInkiLCBhZGQgPSBUKQpjdXJ2ZSgKICBleHByID0gc3BlZWRmYWN0b3Ioc2xvcGUgPSB4LCBnID0gNSwgbGVuZ3RoID0gMTIwKSwKICBmcm9tID0gNSwgdG8gPSAzMCwgY29sID0gIm9yYW5nZSIsIGx3ZCA9IDEsIGx0eSA9IDMsIGxvZyA9ICJ5IiwgYWRkID0gVCkKY3VydmUoCiAgZXhwciA9IHNwZWVkZmFjdG9yKHNsb3BlID0geCwgZyA9IDYsIGxlbmd0aCA9IDEyMCksCiAgZnJvbSA9IDMsIHRvID0gMzAsIGNvbCA9ICJyZWQiLCBsd2QgPSAxLCBsdHkgPSAyLCBsb2cgPSAieSIsIGFkZCA9IFQpCmN1cnZlKAogIGV4cHIgPSBzcGVlZGZhY3RvcihzbG9wZSA9IHgsIGcgPSA3LCBsZW5ndGggPSAxMjApLAogIGZyb20gPSAtMzUsIHRvID0gMzAsIGNvbCA9ICJibHVlIiwgbHdkID0gMSwgbG9nID0gInkiLCBhZGQgPSBUKQphYmxpbmUoaCA9IDEsIHYgPSAwLCBsdHkgPSAzKQpwb2ludHMoc2xvcGUsIHNwZiwgbG9nPSJ5IiwgYWRkID0gVCkgI2Zyb20gdGhlIHJlc3VsdHMKYGBgCgpCeSBkZWZpbmluZyBhIGZsYXQgc3BlZWQgb2YgYDE2IGttL2hgLCBpdCByZXN1bHRzIGluIHNlZ21lbnRzIHRoYXQgYXJlIGN5Y2xlZCB1cCB0byA2IG1pbnV0ZXMgdXBoaWxsLCBhbmQgYXQgYSBtYXhpbXVtIHNwZWVkIG9mIDUzIGttL2guCgpgYGB7cn0KI3NldCBzcGVlZApzcGVlZGZsYXQgPSAxNiAjc2V0IGhlcmUgaW4ga20vaCAoY29udmVydCB0byBtL3M6IHNwZWVkLzMuNikKCkRBVEEkc3BlZWRmYWN0b3IgPSBzcGYKREFUQSRzcGVlZCA9IHNwZWVkZmxhdCAvIERBVEEkc3BlZWRmYWN0b3IKREFUQSR0aW1lID0gbGVuZ3RoIC8gREFUQSRzcGVlZCozLjYKCm1hcHZpZXc6Om1hcHZpZXcoREFUQSwgemNvbCA9ICJzcGVlZCIpCnN1bW1hcnkoREFUQSRzcGVlZCkKbWFwdmlldzo6bWFwdmlldyhEQVRBLCB6Y29sID0gInRpbWUiKQpzdW1tYXJ5KERBVEEkdGltZSkKYGBgCgpUaGlzIGlzIGEgd29yayBpbiBwcm9ncmVzcy4gKipTdWdnZXN0aW9ucyBhbmQgY29tbWVudHMgYXJlIHdlbGNvbWUqKiEgOikKW2dpdGh1Yi5jb20vVS1TaGlmdC9EZWNsaXZlcy1SZWRlVmlhcmlhL3RyZWUvbWFpbi9TcGVlZFNsb3BlRmFjdG9yXShodHRwczovL2dpdGh1Yi5jb20vVS1TaGlmdC9EZWNsaXZlcy1SZWRlVmlhcmlhL3RyZWUvbWFpbi9TcGVlZFNsb3BlRmFjdG9yKQoKIyBDb25jbHVzaW9uCgpGb3IgYSBoaWxseSBjaXR5LCB0aGUgc2xvcGUgZmFjdG9yIGlzIGEgZ29vZCBhcHByb2FjaCB0byBtb2RlbCB0aGUgY29zdCBvZiB0aGUgY3ljbGlzdCBlZmZvcnQgaW4gYSByb3V0aW5nIGFsZ29yaXRobS4gSXQgaXMgYSBub24tbGluZWFyIGFuZCBub24tbW9ub3RvbmljIGZ1bmN0aW9uIHRoYXQgcmVwcm9kdWNlcyB0aGUgZXNzZW50aWFsIGNoYXJhY3RlcmlzdGljcyBvZiB0aGUgc2xvcGUvZWZmb3J0IHJlbGF0aW9uc2hpcCwgYW5kIGl0IGlzIGEgZ29vZCBwcm94eSBmb3IgY3ljbGlzdCBlZmZvcnQuIEl0IGlzIGFsc28gYSBnb29kIGFwcHJvYWNoIHRvIG1vZGVsIHRoZSBjeWNsaXN0IHNwZWVkIGluIGEgcm9hZCBuZXR3b3JrLiAgCkZ1cnRoZXIgcmVzZWFyY2ggaXMgbmVlZGVkIHRvIHZhbGlkYXRlIHRoaXMgYXBwcm9hY2gsIGFuZCB0byB1bmRlcnN0YW5kIGhvdyBpdCBjYW4gYmUgYXBwbGllZCB0byBkaWZmZXJlbnQgdHlwZXMgb2YgY3ljbGlzdHMsIGFuZCB0byBkaWZmZXJlbnQgdHlwZXMgb2YgYmljeWNsZXMsIGFzIHRoaXMgbWV0aG9kIGRvZXMgbm90IGNvbnNpZGVyIHRoZSBlZmZvcnQgb24gYW4gZS1iaWtlLiAKClBsYXVzaWJsZT8gTGV0J3MgZGlzY3VzcyBpdCEKCiMgUmVmZXJlbmNlcwo=