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