import java.util.* ;
import java.io.* ;
import java.text.* ;
public class Main{
//SOLUTION BEGIN
int n = ni( ) , q = ni( ) ;
long [ ] a = new long [ n] , b = new long [ n] ;
for ( int i = 0 ; i< n; i++ ) a[ i] = nl( ) ;
for ( int i = 0 ; i< n; i++ ) b[ i] = nl( ) ;
int B = 200 ;
int C = ( n+ B- 1 ) / B;
Block[ ] bucket = new Block[ C] ; //Square root Decomposition
for ( int i = 0 ; i< C; i++ ) {
bucket[ i] = new Block( B) ;
for ( int j
= i
* B
; j
< Math .
min ( n,
( i
+ 1 ) * B
) ; j
++ ) bucket
[ i
] .
add ( new Line ( b
[ j
] , a
[ j
] , j
) ) ; //Adding lines with slope b[j] and constant a[j] to ith bucket bucket[ i] .build ( ) ; //explained below
}
for ( int qq = 0 ; qq< q; qq++ ) {
int t = ni( ) , l = ni( ) - 1 , r = ni( ) - 1 ;
int sb = l/ B, eb = r/ B;
if ( t== 1 ) {
long ans;
if ( sb== eb) ans = bucket[ sb] .getMax ( l, r) ; //Since l and r are in same block, it is calculated in O(B).
else {
ans
= Math .
max ( bucket
[ sb
] .
getMax ( l, sb
* B
+ B
- 1 ) , bucket
[ eb
] .
getMax ( eb
* B, r
) ) ; //Queried border blocks. for ( int i
= sb
+ 1 ; i
< eb
; i
++ ) ans
= Math .
max ( ans, bucket
[ i
] .
getMax ( ) ) ; //Queried intermediate blocks. }
pn( ans) ;
} else if ( t== 2 ) {
if ( sb== eb) bucket[ sb] .incrementAB ( l,r) ; //Since it affects a part of one block only.
else {
//Updating border blocks
bucket[ sb] .incrementAB ( l,sb* B+ B- 1 ) ;
bucket[ eb] .incrementAB ( eb* B, r) ;
for ( int i = sb+ 1 ; i< eb; i++ ) //Updating intermediate blocks
bucket[ i] .incrementAB ( ) ;
}
} else if ( t== 4 ) {
long x = nl( ) ;
if ( sb== eb) bucket[ sb] .incrementA ( l,r,x) ; //Since it affects a part of one block only.
else {
//Updating border blocks
bucket[ sb] .incrementA ( l,sb* B+ B- 1 ,x) ;
bucket[ eb] .incrementA ( eb* B,r,x) ;
for ( int i = sb+ 1 ; i< eb; i++ ) //Updating intermediate blocks
bucket[ i] .incrementA ( x) ;
}
} else if ( t== 3 ) {
long x = nl( ) ;
if ( sb== eb) bucket[ sb] .incrementB ( l,r,x) ; //Since it affects a part of one block only.
else {
//Updating border blocks
bucket[ sb] .incrementB ( l,sb* B+ B- 1 ,x) ;
bucket[ eb] .incrementB ( eb* B,r,x) ;
for ( int i = sb+ 1 ; i< eb; i++ ) //Updating intermediate blocks
bucket[ i] .incrementB ( x) ;
}
}
}
}
//Class line represent a position p as line with slope b[p] and coefficent a[i]
class Line implements Comparable
< Line
> { long m, c;
int pos;
public Line ( long M,
long C,
int ind
) { m
= M
; c
= C
; pos
= ind
; } long eval( long x) { return m* x+ c; }
public int compareTo
( Line l
) { //Sorting blocks in increasing order of slopes
if ( m
!= l.
m ) return Long .
compare ( m, l.
m ) ; return Long .
compare ( c, l.
c ) ; //If slopes equal, sorted in order of coefficients. }
}
//Calculates intersection point of two lines, rounded to the next integet value.
//This intersection function works only if l1.compareTo(l2) <= 0 as per above method.
if ( l1.m == l2.m && l1.c < l2.c ) return IINF+ 1 ; //Never intersect
if ( l1.c >= l2.c ) return 0 ; //because these lines will never intersect, according to our sorting
long a = l2.c - l1.c , b = l1.m - l2.m ;
return ( a+ b- 1 ) / b; //Rounded up
}
class Block{
//q_cnt - Number of times B was added to A after last updateBlock. cur_max - our index of the line having maximum value at value q_cnt.
int q_cnt, cur_max;
//coefAdd - Sum of all increments by query type 4 to array A, since last update
//slopeAdd - Sum of all increments by query of type 3 to array B, since last update
//slopeEffect, Sum of combined effect of type 2 operation on array A, since last update.
long coefAdd, slopeAdd, slopeEffect;
int lsize = 0 , hsize = 0 , isize = 0 ; //Sizes of following arrays
// ArrayList<Line> lines, hull;
long [ ] intersections;
// ArrayList<Long> intersections;
public Block( int SIZE) {
lines
= new Line [ SIZE
] ; hull
= new Line [ SIZE
] ; intersections = new long [ SIZE] ;
// lines = new ArrayList<>();hull = new ArrayList<>();
// intersections = new ArrayList<>();
q_cnt = cur_max = 0 ;
coefAdd = slopeAdd = slopeEffect = 0 ;
}
//Adds line to block, used during preprocessing only
void add
( Line l
) { lines
[ lsize
++ ] = l
; } //Initialisation function, Sort the lines for hull and create initial convex hull
void build( ) {
convexhull( ) ;
}
//Build can be used, but will add a factor of log(blocksize) to complexity.
//This is called, when slopes of segment [l,r] are increased by X.ie Increment on B is done on [l,r]. It preserves the sorting order of lines, required for Convex hull.
//Since Hull is required to be rebuilt after this sorting, it is always called whenever updateBlockBySlope is called.
void updateBlockBySlope( int l, int r) {
ArrayList< Line> v1 = new ArrayList<> ( ) , v2 = new ArrayList<> ( ) ;
for ( int i = 0 ; i< lsize; i++ ) {
if ( lines[ i] .pos >= l && lines[ i] .pos <= r) v1.add ( lines[ i] ) ;
else v2.add ( lines[ i] ) ;
}
int b = lsize;
lsize = 0 ;
for ( int i1 = 0 , i2 = 0 ; i1+ i2< b; ) {
if ( i1== v1.size ( ) ) lines[ lsize++ ] = v2.get ( i2++ ) ;
else if ( i2== v2.size ( ) ) lines[ lsize++ ] = v1.get ( i1++ ) ;
else {
boolean f = true ;
if ( v1.get ( i1) .m > v2.get ( i2) .m || ( v1.get ( i1) == v2.get ( i2) && v1.get ( i1) .c > v2.get ( i2) .c ) ) f = false ;
if ( f) lines[ lsize++ ] = v1.get ( i1++ ) ;
else lines[ lsize++ ] = v2.get ( i2++ ) ;
}
}
}
//Updates the lines in whole block
void updateBlock( ) {
for ( int i = 0 ; i< lsize; i++ ) {
lines[ i] .c += coefAdd + lines[ i] .m * q_cnt+ slopeEffect; //Added effect of b[i]* number of times operation 2 performed
//plus added combined effect of operation 3 for every increare in array B before every operation 2 since last update
lines[ i] .m += slopeAdd; //Simply added effect of type 3 operation to slope
}
//Resetting
q_cnt = 0 ;
coefAdd = 0 ; slopeAdd = 0 ; slopeEffect = 0 ;
}
//Makes convex hull from lines. Simple variant convex hull is used as lines have slopes sorted.
//Refer Wiki page mentioned in editorial for details.
void convexhull( ) {
isize = 0 ; hsize = 0 ;
cur_max = 0 ; //Current best pointer is reset, since hull is being rebuild.
for ( int i = 0 ; i< lsize; i++ ) {
while ( hsize>= 2 && intersection( lines[ i] , hull[ hsize- 1 ] ) <= intersections[ isize- 1 ] ) {
hsize--;
isize--;
}
boolean add = true ;
if ( hsize> 0 )
if ( intersection( lines[ i] , hull[ hsize- 1 ] ) > IINF)
add = false ;
if ( add) {
if ( hsize> 0 )
intersections[ isize++ ] = intersection( lines[ i] , hull[ hsize- 1 ] ) ;
hull[ hsize++ ] = lines[ i] ;
}
}
}
//Range l to r has been modified. O(B) complexity.
//If slopes are changed, UpdateBlockBySlope is needed.
//else just rebuilding convex hull is sufficient
void update( int l, int r, boolean reorder) {
if ( reorder) updateBlockBySlope( l,r) ; //Ensures sorted order of lines, for convex hull
convexhull( ) ; //Rebuilding convex hull
}
//Returns maximum value in block
long getMax( ) {
//If only one line is always max in whole block.
if ( isize == 0 ) return hull[ 0 ] .eval ( q_cnt) + coefAdd+ slopeEffect;
//Moving our current pointer to best line, the line having maximum value at q_cnt
while ( cur_max< isize && q_cnt>= intersections[ cur_max] )
cur_max++;
return hull[ cur_max] .eval ( q_cnt) + coefAdd+ slopeEffect;
}
//Returns max in range
long getMax( int l, int r) {
long ans = - IINF;
for ( int i = 0 ; i< lsize; i++ )
if ( lines[ i] .pos >= l && lines[ i] .pos <= r)
ans
= Math .
max ( ans, lines
[ i
] .
eval ( q_cnt
) + coefAdd
+ slopeEffect
) ; return ans;
}
void incrementAB( ) {
//The array B is added to array A, so increased query point by 1.
//So, suppose q_cnt was 0. For any line, query(0) would return line.c which is a[i].
//Now, after increasing q_cnt by 1, we make call to query(1), which returns m+c, ie b[i]+a[i], Thus, performing 2nd operation on whole block.
q_cnt++;
//The increase in B made since last update, will be added to A,
//So, we add the increase in B to slopeEffect
slopeEffect+= slopeAdd;
}
//Manual 2nd operation in range [l,r]
void incrementAB( int l, int r) {
updateBlock( ) ; //All lines are updated
for ( int i = 0 ; i< lsize; i++ )
if ( lines[ i] .pos >= l && lines[ i] .pos <= r)
lines[ i] .c += lines[ i] .m ;
update( l, r, false ) ; //Convex hull is required to be built again after change.
}
//Operation 4 on whole block.
void incrementA( long val) {
coefAdd+= val;
}
//OPeration 4 in range [l,r]
void incrementA( int l, int r, long val) {
updateBlock( ) ;
for ( int i = 0 ; i< lsize; i++ )
if ( lines[ i] .pos >= l && lines[ i] .pos <= r)
lines[ i] .c += val;
update( l,r,false ) ;
}
//Operation 3 on whole block
void incrementB( long val) {
slopeAdd+= val;
}
//Operation 3 in range[l,r]
void incrementB( int l, int r, long val) {
updateBlock( ) ;
for ( int i = 0 ; i< lsize; i++ )
if ( lines[ i] .pos >= l && lines[ i] .pos <= r)
lines[ i] .m += val;
update( l,r,true ) ;
}
}
//SOLUTION ENDS
long gcd( long a, long b) { return ( b== 0 ) ? a: gcd( b,a% b) ; }
int gcd( int a, int b) { return ( b== 0 ) ? a: gcd( b,a% b) ; }
int bit( long n) { return ( n== 0 ) ? 0 : ( 1 + bit( n& ( n- 1 ) ) ) ; }
void p
( Object o
) { out.
print ( o
) ; } void pn
( Object o
) { out.
println ( o
) ; } void pni
( Object o
) { out.
println ( o
) ; out.
flush ( ) ; } String nln
( ) { return in.
nextLine ( ) ; } int ni
( ) { return Integer .
parseInt ( in.
next ( ) ) ; } long nl
( ) { return Long .
parseLong ( in.
next ( ) ) ; } double nd
( ) { return Double .
parseDouble ( in.
next ( ) ) ; }
class FastReader{
public FastReader( ) {
}
}
while ( st == null || ! st.hasMoreElements ( ) ) {
try {
e.printStackTrace ( ) ;
}
}
return st.nextToken ( ) ;
}
try {
str = br.readLine ( ) ;
e.printStackTrace ( ) ;
}
return str;
}
}
long mod = ( int ) 1e9+ 7 , IINF = ( long ) 1e18;
final int MAX = ( int ) 1e4+ 1 , INF = ( int ) 1e9, root = 3 ;
double PI = 3.141592653589793238462643383279502884197169399375105820974944 ;
static boolean multipleTC = false , memory = true ;
if ( memory
) new Thread ( null ,
new Runnable ( ) { public void run
( ) { try { new Main
( ) .
run ( ) ; } catch ( Exception e
) { e.
printStackTrace ( ) ; } } } ,
"1" ,
1 << 28 ) .
start ( ) ; else new Main( ) .run ( ) ;
}
in = new FastReader( ) ;
for ( int i = 1 , T= ( multipleTC) ? ni( ) : 1 ; i<= T; i++ ) solve( i) ;
out.flush ( ) ;
out.close ( ) ;
}
}
aW1wb3J0IGphdmEudXRpbC4qOwppbXBvcnQgamF2YS5pby4qOyAKaW1wb3J0IGphdmEudGV4dC4qOwogCnB1YmxpYyBjbGFzcyBNYWluewogICAgLy9TT0xVVElPTiBCRUdJTgogICAgdm9pZCBzb2x2ZShpbnQgVEMpIHRocm93cyBFeGNlcHRpb257CiAgICAgICAgaW50IG4gPSBuaSgpLCBxID0gbmkoKTsKICAgICAgICBsb25nW10gYSA9IG5ldyBsb25nW25dLCBiID0gbmV3IGxvbmdbbl07CiAgICAgICAgZm9yKGludCBpID0gMDsgaTwgbjsgaSsrKWFbaV0gPSBubCgpOwogICAgICAgIGZvcihpbnQgaSA9IDA7IGk8IG47IGkrKyliW2ldID0gbmwoKTsKICAgICAgICBpbnQgQiA9IDIwMDsKICAgICAgICBpbnQgQyA9IChuK0ItMSkvQjsKICAgICAgICBCbG9ja1tdIGJ1Y2tldCA9IG5ldyBCbG9ja1tDXTsvL1NxdWFyZSByb290IERlY29tcG9zaXRpb24KICAgICAgICBmb3IoaW50IGkgPSAwOyBpPCBDOyBpKyspewogICAgICAgICAgICBidWNrZXRbaV0gPSBuZXcgQmxvY2soQik7CiAgICAgICAgICAgIGZvcihpbnQgaiA9IGkqQjsgajwgTWF0aC5taW4obiwgKGkrMSkqQik7IGorKykKICAgICAgICAgICAgICAgIGJ1Y2tldFtpXS5hZGQobmV3IExpbmUoYltqXSwgYVtqXSwgaikpOy8vQWRkaW5nIGxpbmVzIHdpdGggc2xvcGUgYltqXSBhbmQgY29uc3RhbnQgYVtqXSB0byBpdGggYnVja2V0CiAgICAgICAgICAgIGJ1Y2tldFtpXS5idWlsZCgpOy8vZXhwbGFpbmVkIGJlbG93CiAgICAgICAgfQogICAgICAgIGZvcihpbnQgcXEgPSAwOyBxcTxxOyBxcSsrKXsKICAgICAgICAgICAgaW50IHQgPSBuaSgpLCBsID0gbmkoKS0xLCByID0gbmkoKS0xOwogICAgICAgICAgICBpbnQgc2IgPSBsL0IsIGViID0gci9COwogICAgICAgICAgICBpZih0PT0xKXsKICAgICAgICAgICAgICAgIGxvbmcgYW5zOwogICAgICAgICAgICAgICAgaWYoc2I9PWViKWFucyA9IGJ1Y2tldFtzYl0uZ2V0TWF4KGwsIHIpOy8vU2luY2UgbCBhbmQgciBhcmUgaW4gc2FtZSBibG9jaywgaXQgaXMgY2FsY3VsYXRlZCBpbiBPKEIpLgogICAgICAgICAgICAgICAgZWxzZXsKICAgICAgICAgICAgICAgICAgICBhbnMgPSBNYXRoLm1heChidWNrZXRbc2JdLmdldE1heChsLCBzYipCK0ItMSksIGJ1Y2tldFtlYl0uZ2V0TWF4KGViKkIsIHIpKTsvL1F1ZXJpZWQgYm9yZGVyIGJsb2Nrcy4KICAgICAgICAgICAgICAgICAgICBmb3IoaW50IGkgPSBzYisxO2k8ZWI7IGkrKylhbnMgPSBNYXRoLm1heChhbnMsIGJ1Y2tldFtpXS5nZXRNYXgoKSk7Ly9RdWVyaWVkIGludGVybWVkaWF0ZSBibG9ja3MuCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBwbihhbnMpOwogICAgICAgICAgICB9ZWxzZSBpZih0PT0yKXsKICAgICAgICAgICAgICAgIGlmKHNiPT1lYilidWNrZXRbc2JdLmluY3JlbWVudEFCKGwscik7Ly9TaW5jZSBpdCBhZmZlY3RzIGEgcGFydCBvZiBvbmUgYmxvY2sgb25seS4KICAgICAgICAgICAgICAgIGVsc2V7CiAgICAgICAgICAgICAgICAgICAgLy9VcGRhdGluZyBib3JkZXIgYmxvY2tzCiAgICAgICAgICAgICAgICAgICAgYnVja2V0W3NiXS5pbmNyZW1lbnRBQihsLHNiKkIrQi0xKTsKICAgICAgICAgICAgICAgICAgICBidWNrZXRbZWJdLmluY3JlbWVudEFCKGViKkIsIHIpOwogICAgICAgICAgICAgICAgICAgIGZvcihpbnQgaSA9IHNiKzE7IGk8IGViOyBpKyspLy9VcGRhdGluZyBpbnRlcm1lZGlhdGUgYmxvY2tzCiAgICAgICAgICAgICAgICAgICAgICAgIGJ1Y2tldFtpXS5pbmNyZW1lbnRBQigpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9ZWxzZSBpZih0PT00KXsKICAgICAgICAgICAgICAgIGxvbmcgeCA9IG5sKCk7CiAgICAgICAgICAgICAgICBpZihzYj09ZWIpYnVja2V0W3NiXS5pbmNyZW1lbnRBKGwscix4KTsvL1NpbmNlIGl0IGFmZmVjdHMgYSBwYXJ0IG9mIG9uZSBibG9jayBvbmx5LgogICAgICAgICAgICAgICAgZWxzZXsKICAgICAgICAgICAgICAgICAgICAvL1VwZGF0aW5nIGJvcmRlciBibG9ja3MKICAgICAgICAgICAgICAgICAgICBidWNrZXRbc2JdLmluY3JlbWVudEEobCxzYipCK0ItMSx4KTsKICAgICAgICAgICAgICAgICAgICBidWNrZXRbZWJdLmluY3JlbWVudEEoZWIqQixyLHgpOwogICAgICAgICAgICAgICAgICAgIGZvcihpbnQgaSA9IHNiKzE7IGk8IGViOyBpKyspLy9VcGRhdGluZyBpbnRlcm1lZGlhdGUgYmxvY2tzCiAgICAgICAgICAgICAgICAgICAgICAgIGJ1Y2tldFtpXS5pbmNyZW1lbnRBKHgpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9ZWxzZSBpZih0PT0zKXsKICAgICAgICAgICAgICAgIGxvbmcgeCA9IG5sKCk7CiAgICAgICAgICAgICAgICBpZihzYj09ZWIpYnVja2V0W3NiXS5pbmNyZW1lbnRCKGwscix4KTsvL1NpbmNlIGl0IGFmZmVjdHMgYSBwYXJ0IG9mIG9uZSBibG9jayBvbmx5LgogICAgICAgICAgICAgICAgZWxzZXsKICAgICAgICAgICAgICAgICAgICAvL1VwZGF0aW5nIGJvcmRlciBibG9ja3MKICAgICAgICAgICAgICAgICAgICBidWNrZXRbc2JdLmluY3JlbWVudEIobCxzYipCK0ItMSx4KTsKICAgICAgICAgICAgICAgICAgICBidWNrZXRbZWJdLmluY3JlbWVudEIoZWIqQixyLHgpOwogICAgICAgICAgICAgICAgICAgIGZvcihpbnQgaSA9IHNiKzE7IGk8IGViOyBpKyspLy9VcGRhdGluZyBpbnRlcm1lZGlhdGUgYmxvY2tzCiAgICAgICAgICAgICAgICAgICAgICAgIGJ1Y2tldFtpXS5pbmNyZW1lbnRCKHgpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQogICAgLy9DbGFzcyBsaW5lIHJlcHJlc2VudCBhIHBvc2l0aW9uIHAgYXMgbGluZSB3aXRoIHNsb3BlIGJbcF0gYW5kIGNvZWZmaWNlbnQgYVtpXQogICAgY2xhc3MgTGluZSBpbXBsZW1lbnRzIENvbXBhcmFibGU8TGluZT57CiAgICAgICAgbG9uZyBtLCBjOwogICAgICAgIGludCBwb3M7CiAgICAgICAgcHVibGljIExpbmUobG9uZyBNLCBsb25nIEMsIGludCBpbmQpe20gPSBNO2MgPSBDO3BvcyA9IGluZDt9CiAgICAgICAgbG9uZyBldmFsKGxvbmcgeCl7cmV0dXJuIG0qeCtjO30KICAgICAgICBwdWJsaWMgaW50IGNvbXBhcmVUbyhMaW5lIGwpewogICAgICAgICAgICAvL1NvcnRpbmcgYmxvY2tzIGluIGluY3JlYXNpbmcgb3JkZXIgb2Ygc2xvcGVzCiAgICAgICAgICAgIGlmKG0hPWwubSlyZXR1cm4gTG9uZy5jb21wYXJlKG0sIGwubSk7CiAgICAgICAgICAgIHJldHVybiBMb25nLmNvbXBhcmUoYywgbC5jKTsvL0lmIHNsb3BlcyBlcXVhbCwgc29ydGVkIGluIG9yZGVyIG9mIGNvZWZmaWNpZW50cy4KICAgICAgICB9CiAgICB9CiAgICAvL0NhbGN1bGF0ZXMgaW50ZXJzZWN0aW9uIHBvaW50IG9mIHR3byBsaW5lcywgcm91bmRlZCB0byB0aGUgbmV4dCBpbnRlZ2V0IHZhbHVlLgogICAgLy9UaGlzIGludGVyc2VjdGlvbiBmdW5jdGlvbiB3b3JrcyBvbmx5IGlmIGwxLmNvbXBhcmVUbyhsMikgPD0gMCBhcyBwZXIgYWJvdmUgbWV0aG9kLgogICAgbG9uZyBpbnRlcnNlY3Rpb24oTGluZSBsMSwgTGluZSBsMil7CiAgICAgICAgaWYobDEubT09bDIubSAmJiBsMS5jPGwyLmMpcmV0dXJuIElJTkYrMTsvL05ldmVyIGludGVyc2VjdAogICAgICAgIGlmKGwxLmM+PWwyLmMpcmV0dXJuIDA7Ly9iZWNhdXNlIHRoZXNlIGxpbmVzIHdpbGwgbmV2ZXIgaW50ZXJzZWN0LCBhY2NvcmRpbmcgdG8gb3VyIHNvcnRpbmcKICAgICAgICBsb25nIGEgPSBsMi5jLWwxLmMsIGIgPSBsMS5tLWwyLm07CiAgICAgICAgcmV0dXJuIChhK2ItMSkvYjsvL1JvdW5kZWQgdXAKICAgIH0KICAgIAogICAgY2xhc3MgQmxvY2t7CiAgICAgICAgLy9xX2NudCAtIE51bWJlciBvZiB0aW1lcyBCIHdhcyBhZGRlZCB0byBBIGFmdGVyIGxhc3QgdXBkYXRlQmxvY2suIGN1cl9tYXggLSBvdXIgaW5kZXggb2YgdGhlIGxpbmUgaGF2aW5nIG1heGltdW0gdmFsdWUgYXQgdmFsdWUgcV9jbnQuCiAgICAgICAgaW50IHFfY250LCBjdXJfbWF4OwogICAgICAgIC8vY29lZkFkZCAtIFN1bSBvZiBhbGwgaW5jcmVtZW50cyBieSBxdWVyeSB0eXBlIDQgdG8gYXJyYXkgQSwgc2luY2UgbGFzdCB1cGRhdGUKICAgICAgICAvL3Nsb3BlQWRkIC0gU3VtIG9mIGFsbCBpbmNyZW1lbnRzIGJ5IHF1ZXJ5IG9mIHR5cGUgMyB0byBhcnJheSBCLCBzaW5jZSBsYXN0IHVwZGF0ZQogICAgICAgIC8vc2xvcGVFZmZlY3QsIFN1bSBvZiBjb21iaW5lZCBlZmZlY3Qgb2YgdHlwZSAyIG9wZXJhdGlvbiBvbiBhcnJheSBBLCBzaW5jZSBsYXN0IHVwZGF0ZS4KICAgICAgICBsb25nIGNvZWZBZGQsIHNsb3BlQWRkLCBzbG9wZUVmZmVjdDsKICAgICAgICBpbnQgbHNpemUgPSAwLCBoc2l6ZSA9IDAsIGlzaXplID0gMDsvL1NpemVzIG9mIGZvbGxvd2luZyBhcnJheXMKICAgICAgICBMaW5lW10gbGluZXMsIGh1bGw7Ci8vICAgICAgICBBcnJheUxpc3Q8TGluZT4gbGluZXMsIGh1bGw7CiAgICAgICAgbG9uZ1tdIGludGVyc2VjdGlvbnM7Ci8vICAgICAgICBBcnJheUxpc3Q8TG9uZz4gaW50ZXJzZWN0aW9uczsKICAgICAgICBwdWJsaWMgQmxvY2soaW50IFNJWkUpewogICAgICAgICAgICBsaW5lcyA9IG5ldyBMaW5lW1NJWkVdO2h1bGwgPSBuZXcgTGluZVtTSVpFXTsKICAgICAgICAgICAgaW50ZXJzZWN0aW9ucyA9IG5ldyBsb25nW1NJWkVdOwovLyAgICAgICAgICAgIGxpbmVzID0gbmV3IEFycmF5TGlzdDw+KCk7aHVsbCA9IG5ldyBBcnJheUxpc3Q8PigpOwovLyAgICAgICAgICAgIGludGVyc2VjdGlvbnMgPSBuZXcgQXJyYXlMaXN0PD4oKTsKICAgICAgICAgICAgcV9jbnQgPSBjdXJfbWF4ID0gMDsKICAgICAgICAgICAgY29lZkFkZCA9IHNsb3BlQWRkID0gc2xvcGVFZmZlY3QgPSAwOwogICAgICAgIH0KICAgICAgICAvL0FkZHMgbGluZSB0byBibG9jaywgdXNlZCBkdXJpbmcgcHJlcHJvY2Vzc2luZyBvbmx5CiAgICAgICAgdm9pZCBhZGQoTGluZSBsKXtsaW5lc1tsc2l6ZSsrXSA9IGw7fQogICAgICAgIC8vSW5pdGlhbGlzYXRpb24gZnVuY3Rpb24sIFNvcnQgdGhlIGxpbmVzIGZvciBodWxsIGFuZCBjcmVhdGUgaW5pdGlhbCBjb252ZXggaHVsbAogICAgICAgIHZvaWQgYnVpbGQoKXsKICAgICAgICAgICAgQXJyYXlzLnNvcnQobGluZXMsIDAsIGxzaXplKTsKICAgICAgICAgICAgY29udmV4aHVsbCgpOwogICAgICAgIH0KICAgICAgICAvL0J1aWxkIGNhbiBiZSB1c2VkLCBidXQgd2lsbCBhZGQgYSBmYWN0b3Igb2YgbG9nKGJsb2Nrc2l6ZSkgdG8gY29tcGxleGl0eS4KICAgICAgICAvL1RoaXMgaXMgY2FsbGVkLCB3aGVuIHNsb3BlcyBvZiBzZWdtZW50IFtsLHJdIGFyZSBpbmNyZWFzZWQgYnkgWC5pZSBJbmNyZW1lbnQgb24gQiBpcyBkb25lIG9uIFtsLHJdLiBJdCBwcmVzZXJ2ZXMgdGhlIHNvcnRpbmcgb3JkZXIgb2YgbGluZXMsIHJlcXVpcmVkIGZvciBDb252ZXggaHVsbC4KICAgICAgICAvL1NpbmNlIEh1bGwgaXMgcmVxdWlyZWQgdG8gYmUgcmVidWlsdCBhZnRlciB0aGlzIHNvcnRpbmcsIGl0IGlzIGFsd2F5cyBjYWxsZWQgd2hlbmV2ZXIgdXBkYXRlQmxvY2tCeVNsb3BlIGlzIGNhbGxlZC4KICAgICAgICB2b2lkIHVwZGF0ZUJsb2NrQnlTbG9wZShpbnQgbCwgaW50IHIpewogICAgICAgICAgICBBcnJheUxpc3Q8TGluZT4gdjEgPSBuZXcgQXJyYXlMaXN0PD4oKSwgdjIgPSBuZXcgQXJyYXlMaXN0PD4oKTsKICAgICAgICAgICAgZm9yKGludCBpID0gMDsgaTwgbHNpemU7IGkrKyl7CiAgICAgICAgICAgICAgICBpZihsaW5lc1tpXS5wb3M+PWwgJiYgbGluZXNbaV0ucG9zPD1yKXYxLmFkZChsaW5lc1tpXSk7CiAgICAgICAgICAgICAgICBlbHNlIHYyLmFkZChsaW5lc1tpXSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaW50IGIgPSBsc2l6ZTsKICAgICAgICAgICAgbHNpemUgPSAwOwogICAgICAgICAgICBmb3IoaW50IGkxID0gMCwgaTIgPSAwOyBpMStpMjxiOyl7CiAgICAgICAgICAgICAgICBpZihpMT09djEuc2l6ZSgpKWxpbmVzW2xzaXplKytdID0gdjIuZ2V0KGkyKyspOwogICAgICAgICAgICAgICAgZWxzZSBpZihpMj09djIuc2l6ZSgpKWxpbmVzW2xzaXplKytdID0gdjEuZ2V0KGkxKyspOwogICAgICAgICAgICAgICAgZWxzZXsKICAgICAgICAgICAgICAgICAgICBib29sZWFuIGYgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgIGlmKHYxLmdldChpMSkubT52Mi5nZXQoaTIpLm0gfHwgKHYxLmdldChpMSk9PXYyLmdldChpMikgJiYgdjEuZ2V0KGkxKS5jPnYyLmdldChpMikuYykpZiA9IGZhbHNlOwogICAgICAgICAgICAgICAgICAgIGlmKGYpbGluZXNbbHNpemUrK10gPSB2MS5nZXQoaTErKyk7CiAgICAgICAgICAgICAgICAgICAgZWxzZSBsaW5lc1tsc2l6ZSsrXSA9IHYyLmdldChpMisrKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvL1VwZGF0ZXMgdGhlIGxpbmVzIGluIHdob2xlIGJsb2NrCiAgICAgICAgdm9pZCB1cGRhdGVCbG9jaygpewogICAgICAgICAgICBmb3IoaW50IGkgPSAwOyBpPCBsc2l6ZTsgaSsrKXsKICAgICAgICAgICAgICAgIGxpbmVzW2ldLmMgKz0gY29lZkFkZCArIGxpbmVzW2ldLm0qcV9jbnQrc2xvcGVFZmZlY3Q7Ly9BZGRlZCBlZmZlY3Qgb2YgYltpXSogbnVtYmVyIG9mIHRpbWVzIG9wZXJhdGlvbiAyIHBlcmZvcm1lZAogICAgICAgICAgICAgICAgLy9wbHVzIGFkZGVkIGNvbWJpbmVkIGVmZmVjdCBvZiBvcGVyYXRpb24gMyBmb3IgZXZlcnkgaW5jcmVhcmUgaW4gYXJyYXkgQiBiZWZvcmUgZXZlcnkgb3BlcmF0aW9uIDIgc2luY2UgbGFzdCB1cGRhdGUKICAgICAgICAgICAgICAgIGxpbmVzW2ldLm0rPXNsb3BlQWRkOy8vU2ltcGx5IGFkZGVkIGVmZmVjdCBvZiB0eXBlIDMgb3BlcmF0aW9uIHRvIHNsb3BlCiAgICAgICAgICAgIH0KICAgICAgICAgICAgLy9SZXNldHRpbmcKICAgICAgICAgICAgcV9jbnQgPSAwOwogICAgICAgICAgICBjb2VmQWRkID0gMDtzbG9wZUFkZCA9IDA7c2xvcGVFZmZlY3QgPSAwOwogICAgICAgIH0KICAgICAgICAvL01ha2VzIGNvbnZleCBodWxsIGZyb20gbGluZXMuIFNpbXBsZSB2YXJpYW50IGNvbnZleCBodWxsIGlzIHVzZWQgYXMgbGluZXMgaGF2ZSBzbG9wZXMgc29ydGVkLgogICAgICAgIC8vUmVmZXIgV2lraSBwYWdlIG1lbnRpb25lZCBpbiBlZGl0b3JpYWwgZm9yIGRldGFpbHMuCiAgICAgICAgdm9pZCBjb252ZXhodWxsKCl7CiAgICAgICAgICAgIGlzaXplID0gMDtoc2l6ZSA9IDA7CiAgICAgICAgICAgIGN1cl9tYXggPSAwOy8vQ3VycmVudCBiZXN0IHBvaW50ZXIgaXMgcmVzZXQsIHNpbmNlIGh1bGwgaXMgYmVpbmcgcmVidWlsZC4gCiAgICAgICAgICAgIGZvcihpbnQgaSA9IDA7IGk8IGxzaXplOyBpKyspewogICAgICAgICAgICAgICAgd2hpbGUoaHNpemU+PTIgJiYgaW50ZXJzZWN0aW9uKGxpbmVzW2ldLCBodWxsW2hzaXplLTFdKSA8PSBpbnRlcnNlY3Rpb25zW2lzaXplLTFdKXsKICAgICAgICAgICAgICAgICAgICBoc2l6ZS0tOwogICAgICAgICAgICAgICAgICAgIGlzaXplLS07CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBib29sZWFuIGFkZCA9IHRydWU7CiAgICAgICAgICAgICAgICBpZihoc2l6ZT4wKQogICAgICAgICAgICAgICAgICAgIGlmKGludGVyc2VjdGlvbihsaW5lc1tpXSwgaHVsbFtoc2l6ZS0xXSk+SUlORikKICAgICAgICAgICAgICAgICAgICAgICAgYWRkID0gZmFsc2U7CiAgICAgICAgICAgICAgICBpZihhZGQpewogICAgICAgICAgICAgICAgICAgIGlmKGhzaXplPjApCiAgICAgICAgICAgICAgICAgICAgICAgIGludGVyc2VjdGlvbnNbaXNpemUrK10gPSBpbnRlcnNlY3Rpb24obGluZXNbaV0sIGh1bGxbaHNpemUtMV0pOwogICAgICAgICAgICAgICAgICAgIGh1bGxbaHNpemUrK10gPSBsaW5lc1tpXTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAvL1JhbmdlIGwgdG8gciBoYXMgYmVlbiBtb2RpZmllZC4gTyhCKSBjb21wbGV4aXR5LgogICAgICAgIC8vSWYgc2xvcGVzIGFyZSBjaGFuZ2VkLCBVcGRhdGVCbG9ja0J5U2xvcGUgaXMgbmVlZGVkLgogICAgICAgIC8vZWxzZSBqdXN0IHJlYnVpbGRpbmcgY29udmV4IGh1bGwgaXMgc3VmZmljaWVudAogICAgICAgIHZvaWQgdXBkYXRlKGludCBsLCBpbnQgciwgYm9vbGVhbiByZW9yZGVyKXsKICAgICAgICAgICAgaWYocmVvcmRlcil1cGRhdGVCbG9ja0J5U2xvcGUobCxyKTsvL0Vuc3VyZXMgc29ydGVkIG9yZGVyIG9mIGxpbmVzLCBmb3IgY29udmV4IGh1bGwKICAgICAgICAgICAgY29udmV4aHVsbCgpOy8vUmVidWlsZGluZyBjb252ZXggaHVsbAogICAgICAgIH0KICAgICAgICAvL1JldHVybnMgbWF4aW11bSB2YWx1ZSBpbiBibG9jawogICAgICAgIGxvbmcgZ2V0TWF4KCl7CiAgICAgICAgICAgIC8vSWYgb25seSBvbmUgbGluZSBpcyBhbHdheXMgbWF4IGluIHdob2xlIGJsb2NrLgogICAgICAgICAgICBpZihpc2l6ZSA9PSAwKXJldHVybiBodWxsWzBdLmV2YWwocV9jbnQpK2NvZWZBZGQrc2xvcGVFZmZlY3Q7CiAgICAgICAgICAgIC8vTW92aW5nIG91ciBjdXJyZW50IHBvaW50ZXIgdG8gYmVzdCBsaW5lLCB0aGUgbGluZSBoYXZpbmcgbWF4aW11bSB2YWx1ZSBhdCBxX2NudAogICAgICAgICAgICB3aGlsZShjdXJfbWF4PGlzaXplICYmIHFfY250Pj1pbnRlcnNlY3Rpb25zW2N1cl9tYXhdKQogICAgICAgICAgICAgICAgY3VyX21heCsrOwogICAgICAgICAgICByZXR1cm4gaHVsbFtjdXJfbWF4XS5ldmFsKHFfY250KStjb2VmQWRkK3Nsb3BlRWZmZWN0OwogICAgICAgIH0KICAgICAgICAvL1JldHVybnMgbWF4IGluIHJhbmdlCiAgICAgICAgbG9uZyBnZXRNYXgoaW50IGwsIGludCByKXsKICAgICAgICAgICAgbG9uZyBhbnMgPSAtSUlORjsKICAgICAgICAgICAgZm9yKGludCBpID0gMDsgaTwgbHNpemU7IGkrKykKICAgICAgICAgICAgICAgIGlmKGxpbmVzW2ldLnBvcz49bCAmJiBsaW5lc1tpXS5wb3M8PXIpCiAgICAgICAgICAgICAgICAgICAgYW5zID0gTWF0aC5tYXgoYW5zLCBsaW5lc1tpXS5ldmFsKHFfY250KStjb2VmQWRkK3Nsb3BlRWZmZWN0KTsKICAgICAgICAgICAgcmV0dXJuIGFuczsKICAgICAgICB9CiAgICAgICAgdm9pZCBpbmNyZW1lbnRBQigpewogICAgICAgICAgICAvL1RoZSBhcnJheSBCIGlzIGFkZGVkIHRvIGFycmF5IEEsIHNvIGluY3JlYXNlZCBxdWVyeSBwb2ludCBieSAxLgogICAgICAgICAgICAvL1NvLCBzdXBwb3NlIHFfY250IHdhcyAwLiBGb3IgYW55IGxpbmUsIHF1ZXJ5KDApIHdvdWxkIHJldHVybiBsaW5lLmMgd2hpY2ggaXMgYVtpXS4KICAgICAgICAgICAgLy9Ob3csIGFmdGVyIGluY3JlYXNpbmcgcV9jbnQgYnkgMSwgd2UgbWFrZSBjYWxsIHRvIHF1ZXJ5KDEpLCB3aGljaCByZXR1cm5zIG0rYywgaWUgYltpXSthW2ldLCBUaHVzLCBwZXJmb3JtaW5nIDJuZCBvcGVyYXRpb24gb24gd2hvbGUgYmxvY2suCiAgICAgICAgICAgIHFfY250Kys7CiAgICAgICAgICAgIC8vVGhlIGluY3JlYXNlIGluIEIgbWFkZSBzaW5jZSBsYXN0IHVwZGF0ZSwgd2lsbCBiZSBhZGRlZCB0byBBLAogICAgICAgICAgICAvL1NvLCB3ZSBhZGQgdGhlIGluY3JlYXNlIGluIEIgdG8gc2xvcGVFZmZlY3QKICAgICAgICAgICAgc2xvcGVFZmZlY3QrPXNsb3BlQWRkOwogICAgICAgIH0KICAgICAgICAvL01hbnVhbCAybmQgb3BlcmF0aW9uIGluIHJhbmdlIFtsLHJdCiAgICAgICAgdm9pZCBpbmNyZW1lbnRBQihpbnQgbCwgaW50IHIpewogICAgICAgICAgICB1cGRhdGVCbG9jaygpOy8vQWxsIGxpbmVzIGFyZSB1cGRhdGVkCiAgICAgICAgICAgIGZvcihpbnQgaSA9IDA7IGk8IGxzaXplOyBpKyspCiAgICAgICAgICAgICAgICBpZihsaW5lc1tpXS5wb3M+PWwgJiYgbGluZXNbaV0ucG9zPD1yKQogICAgICAgICAgICAgICAgICAgIGxpbmVzW2ldLmMrPWxpbmVzW2ldLm07CiAgICAgICAgICAgIHVwZGF0ZShsLCByLCBmYWxzZSk7Ly9Db252ZXggaHVsbCBpcyByZXF1aXJlZCB0byBiZSBidWlsdCBhZ2FpbiBhZnRlciBjaGFuZ2UuCiAgICAgICAgfQogICAgICAgIC8vT3BlcmF0aW9uIDQgb24gd2hvbGUgYmxvY2suCiAgICAgICAgdm9pZCBpbmNyZW1lbnRBKGxvbmcgdmFsKXsKICAgICAgICAgICAgY29lZkFkZCs9dmFsOwogICAgICAgIH0KICAgICAgICAvL09QZXJhdGlvbiA0IGluIHJhbmdlIFtsLHJdCiAgICAgICAgdm9pZCBpbmNyZW1lbnRBKGludCBsLCBpbnQgciwgbG9uZyB2YWwpewogICAgICAgICAgICB1cGRhdGVCbG9jaygpOwogICAgICAgICAgICBmb3IoaW50IGkgPSAwOyBpPCBsc2l6ZTsgaSsrKQogICAgICAgICAgICAgICAgaWYobGluZXNbaV0ucG9zPj1sICYmIGxpbmVzW2ldLnBvczw9cikKICAgICAgICAgICAgICAgICAgICBsaW5lc1tpXS5jKz12YWw7CiAgICAgICAgICAgIHVwZGF0ZShsLHIsZmFsc2UpOwogICAgICAgIH0KICAgICAgICAvL09wZXJhdGlvbiAzIG9uIHdob2xlIGJsb2NrCiAgICAgICAgdm9pZCBpbmNyZW1lbnRCKGxvbmcgdmFsKXsKICAgICAgICAgICAgc2xvcGVBZGQrPXZhbDsKICAgICAgICB9CiAgICAgICAgLy9PcGVyYXRpb24gMyBpbiByYW5nZVtsLHJdCiAgICAgICAgdm9pZCBpbmNyZW1lbnRCKGludCBsLCBpbnQgciwgbG9uZyB2YWwpewogICAgICAgICAgICB1cGRhdGVCbG9jaygpOwogICAgICAgICAgICBmb3IoaW50IGkgPSAwOyBpPCBsc2l6ZTsgaSsrKQogICAgICAgICAgICAgICAgaWYobGluZXNbaV0ucG9zPj1sICYmIGxpbmVzW2ldLnBvczw9cikKICAgICAgICAgICAgICAgICAgICBsaW5lc1tpXS5tKz12YWw7CiAgICAgICAgICAgIHVwZGF0ZShsLHIsdHJ1ZSk7CiAgICAgICAgfQogICAgfQogICAgLy9TT0xVVElPTiBFTkRTCiAgICBsb25nIGdjZChsb25nIGEsIGxvbmcgYil7cmV0dXJuIChiPT0wKT9hOmdjZChiLGElYik7fQogICAgaW50IGdjZChpbnQgYSwgaW50IGIpe3JldHVybiAoYj09MCk/YTpnY2QoYixhJWIpO30KICAgIGludCBiaXQobG9uZyBuKXtyZXR1cm4gKG49PTApPzA6KDErYml0KG4mKG4tMSkpKTt9CiAgICB2b2lkIHAoT2JqZWN0IG8pe291dC5wcmludChvKTt9CiAgICB2b2lkIHBuKE9iamVjdCBvKXtvdXQucHJpbnRsbihvKTt9CiAgICB2b2lkIHBuaShPYmplY3Qgbyl7b3V0LnByaW50bG4obyk7b3V0LmZsdXNoKCk7fQogICAgU3RyaW5nIG4oKXtyZXR1cm4gaW4ubmV4dCgpO30KICAgIFN0cmluZyBubG4oKXtyZXR1cm4gaW4ubmV4dExpbmUoKTt9CiAgICBpbnQgbmkoKXtyZXR1cm4gSW50ZWdlci5wYXJzZUludChpbi5uZXh0KCkpO30KICAgIGxvbmcgbmwoKXtyZXR1cm4gTG9uZy5wYXJzZUxvbmcoaW4ubmV4dCgpKTt9CiAgICBkb3VibGUgbmQoKXtyZXR1cm4gRG91YmxlLnBhcnNlRG91YmxlKGluLm5leHQoKSk7fQogCiAgICBjbGFzcyBGYXN0UmVhZGVyewogICAgICAgIEJ1ZmZlcmVkUmVhZGVyIGJyOwogICAgICAgIFN0cmluZ1Rva2VuaXplciBzdDsKICAgICAgICBwdWJsaWMgRmFzdFJlYWRlcigpewogICAgICAgICAgICBiciA9IG5ldyBCdWZmZXJlZFJlYWRlcihuZXcgSW5wdXRTdHJlYW1SZWFkZXIoU3lzdGVtLmluKSk7CiAgICAgICAgfQogCiAgICAgICAgcHVibGljIEZhc3RSZWFkZXIoU3RyaW5nIHMpIHRocm93cyBFeGNlcHRpb257CiAgICAgICAgICAgIGJyID0gbmV3IEJ1ZmZlcmVkUmVhZGVyKG5ldyBGaWxlUmVhZGVyKHMpKTsKICAgICAgICB9CiAKICAgICAgICBTdHJpbmcgbmV4dCgpewogICAgICAgICAgICB3aGlsZSAoc3QgPT0gbnVsbCB8fCAhc3QuaGFzTW9yZUVsZW1lbnRzKCkpewogICAgICAgICAgICAgICAgdHJ5ewogICAgICAgICAgICAgICAgICAgIHN0ID0gbmV3IFN0cmluZ1Rva2VuaXplcihici5yZWFkTGluZSgpKTsKICAgICAgICAgICAgICAgIH1jYXRjaCAoSU9FeGNlcHRpb24gIGUpewogICAgICAgICAgICAgICAgICAgIGUucHJpbnRTdGFja1RyYWNlKCk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIHN0Lm5leHRUb2tlbigpOwogICAgICAgIH0KIAogICAgICAgIFN0cmluZyBuZXh0TGluZSgpewogICAgICAgICAgICBTdHJpbmcgc3RyID0gIiI7CiAgICAgICAgICAgIHRyeXsgICAgCiAgICAgICAgICAgICAgICBzdHIgPSBici5yZWFkTGluZSgpOwogICAgICAgICAgICB9Y2F0Y2ggKElPRXhjZXB0aW9uIGUpewogICAgICAgICAgICAgICAgZS5wcmludFN0YWNrVHJhY2UoKTsKICAgICAgICAgICAgfSAgIAogICAgICAgICAgICByZXR1cm4gc3RyOwogICAgICAgIH0KICAgIH0KICAgIGxvbmcgbW9kID0gKGludCkxZTkrNywgSUlORiA9IChsb25nKTFlMTg7CiAgICBmaW5hbCBpbnQgTUFYID0gKGludCkxZTQrMSwgSU5GID0gKGludCkxZTksIHJvb3QgPSAzOwogICAgRGVjaW1hbEZvcm1hdCBkZiA9IG5ldyBEZWNpbWFsRm9ybWF0KCIwLjAwMDAwMDAwIik7CiAgICBkb3VibGUgUEkgPSAzLjE0MTU5MjY1MzU4OTc5MzIzODQ2MjY0MzM4MzI3OTUwMjg4NDE5NzE2OTM5OTM3NTEwNTgyMDk3NDk0NDsKICAgIHN0YXRpYyBib29sZWFuIG11bHRpcGxlVEMgPSBmYWxzZSwgbWVtb3J5ID0gdHJ1ZTsKICAgIEZhc3RSZWFkZXIgaW47UHJpbnRXcml0ZXIgb3V0OwogICAgcHVibGljIHN0YXRpYyB2b2lkIG1haW4oU3RyaW5nW10gYXJncykgdGhyb3dzIEV4Y2VwdGlvbnsKICAgICAgICBpZihtZW1vcnkpbmV3IFRocmVhZChudWxsLCBuZXcgUnVubmFibGUoKSB7cHVibGljIHZvaWQgcnVuKCl7dHJ5e25ldyBNYWluKCkucnVuKCk7fWNhdGNoKEV4Y2VwdGlvbiBlKXtlLnByaW50U3RhY2tUcmFjZSgpO319fSwgIjEiLCAxIDw8IDI4KS5zdGFydCgpOwogICAgICAgIGVsc2UgbmV3IE1haW4oKS5ydW4oKTsKICAgIH0KICAgIHZvaWQgcnVuKCkgdGhyb3dzIEV4Y2VwdGlvbnsKICAgICAgICBpbiA9IG5ldyBGYXN0UmVhZGVyKCk7CiAgICAgICAgb3V0ID0gbmV3IFByaW50V3JpdGVyKFN5c3RlbS5vdXQpOwogICAgICAgIGZvcihpbnQgaSA9IDEsIFQ9IChtdWx0aXBsZVRDKT9uaSgpOjE7IGk8PSBUOyBpKyspc29sdmUoaSk7CiAgICAgICAgb3V0LmZsdXNoKCk7CiAgICAgICAgb3V0LmNsb3NlKCk7CiAgICB9Cn0gICAg