import java.io.*;
import java.math.*;
import java.util.*;
/*
yash jobanputra
DA-IICT
*/
class mstkp {
private static byte[] buf = new byte[1024];
private static int curChar;
private static int numChars;
private static SpaceCharFilter filter;
private static long mod = 1000000000 + 7;
private static long mod1 = 1000000000 + 9;
private static int MAX=1000001;
private static int block;
private static int count;
private static boolean[] vis;
private static Stack<Integer> st;
private static int times=0;
public static int cc;
public static int pos;
private static void soln(){
int t=ni();
for(int c=0;c<t;c++)
{
int n=ni();
int[][] ecost=new int[n+1][n+1];
for(int i=0;i<=n;i++)
{
tree[i]=new ArrayList<>();
}
for(int i=1;i<n;i++)
{
int a=ni();int b=ni();int cost=ni();
tree[a].add(new Pair(b,i));
tree[b].add(new Pair(a,i));
ecost[a][b]=cost;
ecost[b][a]=cost;
}
hld.initial(n);
hld.dfs(1, 1, tree);
hld.ilca(n);
hld.Hld(1, 0, -1, tree, ecost);
hld.build(1, 1, pos);
while(true)
{
if(s[0].contentEquals("DONE"))
break;
else if(s[0].contentEquals("QUERY"))
pw.
println(hld.
querypath(Integer.
parseInt(s
[1]),
Integer.
parseInt(s
[2]))); else
}
}
}
public static class hld
{
static int[][] p;static int[] dp;static int[] subsize;static int[] endnode;static int chainno;static int[] chainhead,chainind,arrpos,costarr,segtree;
public static void initial(int n)
{
p=new int[n+1][22];
dp=new int[n+1];
subsize=new int[n+1];
endnode=new int[n];
chainhead=new int[n+1];
chainind=new int[n+1];
arrpos=new int[n+1];
costarr=new int[n];
segtree=new int[n*4];
chainno=1;
pos=-1;
}
public static void ilca(int n)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<22;j++)
p[i][j]=-1;
}
for(int j=1;1<<j<=n;j++)
{
for(int i=1;i<=n;i++)
{
if(p[i][j-1]!=-1)
p[i][j]=p[p[i][j-1]][j-1];
}
}
}
public static void dfs(int node,int par,ArrayList<Pair>[] tree)
{
if(par==0) dp[node]=0;
subsize[node]=1;
p[node][0]=par;
for(int i=0;i<tree[node].size();i++)
{
int next=tree[node].get(i).v;
int ind=tree[node].get(i).i;
if(next!=par)
{
endnode[ind]=next;
dfs(next,node,tree);
subsize[node]+=subsize[next];
}
}
}
public static int lca(int u,int v)
{
if(dp[u]<dp[v])
{
int temp=u;
u=v;
v=temp;
}
int log;
for (log = 1; 1 << log <= dp[u]; log++);
log--;
for(int i=log;i>=0;i--)
{
if(dp[u]-(1<<i)>=dp[v])
u=p[u][i];
}
if(u==v)
return u;
for(int i=log;i>=0;i--)
{
if(p[u][i]!=-1 && p[u][i]!=p[v][i])
{u=p[u][i];v=p[v][i];}
}
return p[u][0];
}
public static void Hld(int node,int cost,int par,ArrayList<Pair>[] tree,int[][] ecost)
{
if(chainhead[chainno]==-1) chainhead[chainno]=node;
pos++;
chainind[node]=chainno;
costarr[pos]=cost;
arrpos[node]=pos;
int hn=-1;int hc=0;
for(int i=0;i<tree[node].size();i++)
{
int next=tree[node].get(i).v;
if((next!=par)&&(hn==-1 || subsize[next]>subsize[hn]))
{
hn=next;
hc=ecost[node][next];
}
}
if(hn!=-1)
Hld(hn,hc,node,tree,ecost);
for(int i=0;i<tree[node].size();i++)
{
int next=tree[node].get(i).v;
if(next!=par && next!=hn)
{
chainno++;
Hld(next,ecost[node][next],node,tree,ecost);
}
}
}
public static void build(int node,int l,int r)
{
if(l==r)
{
segtree[node]=costarr[l];
}
else
{
int m=(l+r)/2;
build((2*node),l,m);
build((2*node)+1,m+1,r);
segtree
[node
]=Math.
max(segtree
[2*node
],segtree
[2*node
+1]); }
}
public static void update(int node,int l,int r,int ind,int val)
{
if(l==r)
{
costarr[ind]=val;
segtree[node]=val;
}
else
{
int m=(l+r)/2;
if(l<=ind && ind<=m)
{
update((2*node),l,m,ind,val);
}
else
{
update((2*node+1),m+1,r,ind,val);
}
segtree
[node
]=Math.
max(segtree
[2*node
], segtree
[2*node
+1]); }
}
public static int query(int node,int l,int r,int s,int e)
{
if(e<l || r<s)
return 0;
if(s<=l && e>=r)
return segtree[node];
int m=(l+r)/2;
int p1=query((2*node),l,m,s,e);
int p2=query((2*node+1),m+1,r,s,e);
}
public static int querypath(int u,int v)
{
int lca=lca(u,v);
return Math.
max(queryup
(u,lca
), queryup
(v,lca
)); }
public static int queryup(int u,int v)
{
if(u==v)
return 0;
int lchain;int rchain=chainind[v];
int ans=-1;
while(true)
{
lchain=chainind[u];
if(lchain==rchain)
{
if(u==v)
break;
int cur=query(1,1,pos,arrpos[v]+1,arrpos[u]);
break;
}
int cur=query(1,1,pos,chainhead[lchain],arrpos[u]);
u=chainhead[lchain];
u=p[u][0];
}
return ans;
}
public static void update(int ind,int val)
{
int no=endnode[ind];
update(1,1,pos,arrpos[no],val);
}
}
private static class Pair implements Comparable<Pair>{
int v,i;Pair j;
public Pair(int a,int b){
v=a;
i=b;
}
public Pair(int a,Pair b)
{
v=a;
j=b;
}
@Override
public int compareTo(Pair arg0) {
{
return this.v-arg0.v;
}
}
}
private static long pow(long a, long b, long c) {
if (b == 0)
return 1;
long p = pow(a, b / 2, c);
p = (p * p) % c;
return (b % 2 == 0) ? p : (a * p) % c;
}
private static long gcd(long n, long l) {
if (l == 0)
return n;
return gcd(l, n % l);
}
private static long max(long a, long b) {
if (a > b)
return a;
return b;
}
private static long min(long a, long b) {
if (a < b)
return a;
return b;
}
@Override
public void run() {
/*try {
InputReader(new FileInputStream("C:\\Users\\hardik\\Desktop\\C-small-1-attempt1.in"));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
/*try {
pw=new PrintWriter(new FileOutputStream("C:\\Users\\hardik\\Desktop\\out.txt"));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
soln();
pw.close();
}
},"1",1<<26).start();
}
stream = stream1;
}
private static boolean isWhitespace(int c) {
return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
}
private static boolean isEndOfLine(int c) {
return c == '\n' || c == '\r' || c == -1;
}
private static int read() {
if (numChars == -1)
throw new InputMismatchException();
if (curChar >= numChars) {
curChar = 0;
try {
numChars = stream.read(buf);
throw new InputMismatchException();
}
if (numChars <= 0)
return -1;
}
return buf[curChar++];
}
private static int ni() {
int c = read();
while (isSpaceChar(c))
c = read();
int sgn = 1;
if (c == '-') {
sgn = -1;
c = read();
}
int res = 0;
do {
if (c < '0' || c > '9')
throw new InputMismatchException();
res *= 10;
res += c - '0';
c = read();
} while (!isSpaceChar(c));
return res * sgn;
}
private static long nl() {
int c = read();
while (isSpaceChar(c))
c = read();
int sgn = 1;
if (c == '-') {
sgn = -1;
c = read();
}
long res = 0;
do {
if (c < '0' || c > '9')
throw new InputMismatchException();
res *= 10;
res += c - '0';
c = read();
} while (!isSpaceChar(c));
return res * sgn;
}
private static double nd()
{
double ret = 0, div = 1;
int c = read();
while (c <= ' ')
c = read();
boolean neg = (c == '-');
if (neg)
c = read();
do {
ret = ret * 10 + c - '0';
}
while ((c = read()) >= '0' && c <= '9');
if (c == '.')
{
while ((c = read()) >= '0' && c <= '9')
{
ret += (c - '0') / (div *= 10);
}
}
if (neg)
return -ret;
return ret;
}
private static String nextToken
() { int c = read();
while (isSpaceChar(c))
c = read();
StringBuilder res = new StringBuilder();
do {
res.appendCodePoint(c);
c = read();
} while (!isSpaceChar(c));
return res.toString();
}
int c = read();
while (isSpaceChar(c))
c = read();
StringBuilder res = new StringBuilder();
do {
res.appendCodePoint(c);
c = read();
} while (!isEndOfLine(c));
return res.toString();
}
private static int[] nia(int n) {
int[] arr = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = ni();
}
return arr;
}
private static long[] nla(int n) {
long[] arr = new long[n];
for (int i = 0; i < n; i++) {
arr[i] = nl();
}
return arr;
}
private static void pa(int[] arr) {
for (int i = 0; i < arr.length; i++) {
pw.print(arr[i] + " ");
}
pw.println();
return;
}
private static void pa(long[] arr) {
for (int i = 0; i < arr.length; i++) {
pw.print(arr[i] + " ");
}
return;
}
private static boolean isSpaceChar(int c) {
if (filter != null)
return filter.isSpaceChar(c);
return isWhitespace(c);
}
private static char nc() {
int c = read();
while (isSpaceChar(c))
c = read();
char c1=(char)c;
while(!isSpaceChar(c))
c=read();
return c1;
}
private interface SpaceCharFilter {
public boolean isSpaceChar(int ch);
}
}
aW1wb3J0IGphdmEuaW8uKjsKaW1wb3J0IGphdmEubWF0aC4qOwppbXBvcnQgamF2YS51dGlsLio7Ci8qIAoJCQkJCQkJCQkJCQkJCQkJeWFzaCBqb2JhbnB1dHJhCgkJCQkJCQkJCQkJCQkJCQkJREEtSUlDVAoqLwpjbGFzcyBtc3RrcCB7Cglwcml2YXRlIHN0YXRpYyBJbnB1dFN0cmVhbSBzdHJlYW07Cglwcml2YXRlIHN0YXRpYyBieXRlW10gYnVmID0gbmV3IGJ5dGVbMTAyNF07Cglwcml2YXRlIHN0YXRpYyBpbnQgY3VyQ2hhcjsKCXByaXZhdGUgc3RhdGljIGludCBudW1DaGFyczsKCXByaXZhdGUgc3RhdGljIFNwYWNlQ2hhckZpbHRlciBmaWx0ZXI7Cglwcml2YXRlIHN0YXRpYyBQcmludFdyaXRlciBwdzsKCXByaXZhdGUgc3RhdGljIGxvbmcgbW9kID0gMTAwMDAwMDAwMCArIDc7Cglwcml2YXRlIHN0YXRpYyBsb25nIG1vZDEgPSAxMDAwMDAwMDAwICsgOTsKCXByaXZhdGUgc3RhdGljIGludCBNQVg9MTAwMDAwMTsKCXByaXZhdGUgc3RhdGljIGludCBibG9jazsKCXByaXZhdGUgc3RhdGljIGludCBjb3VudDsKCXByaXZhdGUgc3RhdGljIGJvb2xlYW5bXSB2aXM7Cglwcml2YXRlIHN0YXRpYyBTdGFjazxJbnRlZ2VyPiBzdDsKCXByaXZhdGUgc3RhdGljIGludCB0aW1lcz0wOwoJcHVibGljIHN0YXRpYyBpbnQgY2M7CglwdWJsaWMgc3RhdGljIGludCBwb3M7Cglwcml2YXRlIHN0YXRpYyB2b2lkIHNvbG4oKXsKCQkJaW50IHQ9bmkoKTsKCQkJZm9yKGludCBjPTA7Yzx0O2MrKykKCQkJewoJCQkJaW50IG49bmkoKTsKCQkJCUFycmF5TGlzdDxQYWlyPltdIHRyZWU9bmV3IEFycmF5TGlzdFtuKzFdOwoJCQkJaW50W11bXSBlY29zdD1uZXcgaW50W24rMV1bbisxXTsKCQkJCWZvcihpbnQgaT0wO2k8PW47aSsrKQoJCQkJewoJCQkJCXRyZWVbaV09bmV3IEFycmF5TGlzdDw+KCk7CgkJCQl9CgkJCQlmb3IoaW50IGk9MTtpPG47aSsrKQoJCQkJewoJCQkJCWludCBhPW5pKCk7aW50IGI9bmkoKTtpbnQgY29zdD1uaSgpOwoJCQkJCXRyZWVbYV0uYWRkKG5ldyBQYWlyKGIsaSkpOwoJCQkJCXRyZWVbYl0uYWRkKG5ldyBQYWlyKGEsaSkpOwoJCQkJCWVjb3N0W2FdW2JdPWNvc3Q7CgkJCQkJZWNvc3RbYl1bYV09Y29zdDsKCQkJCX0KCQkJCWhsZC5pbml0aWFsKG4pOwoJCQkJaGxkLmRmcygxLCAxLCB0cmVlKTsKCQkJCWhsZC5pbGNhKG4pOwoJCQkJaGxkLkhsZCgxLCAwLCAtMSwgdHJlZSwgZWNvc3QpOwoJCQkJaGxkLmJ1aWxkKDEsIDEsIHBvcyk7CgkJCQl3aGlsZSh0cnVlKQoJCQkJewoJCQkJCVN0cmluZ1tdIHM9bmxpKCkuc3BsaXQoIiAiKTsKCQkJCQlpZihzWzBdLmNvbnRlbnRFcXVhbHMoIkRPTkUiKSkKCQkJCQkJYnJlYWs7CgkJCQkJZWxzZSBpZihzWzBdLmNvbnRlbnRFcXVhbHMoIlFVRVJZIikpCgkJCQkJCXB3LnByaW50bG4oaGxkLnF1ZXJ5cGF0aChJbnRlZ2VyLnBhcnNlSW50KHNbMV0pLCBJbnRlZ2VyLnBhcnNlSW50KHNbMl0pKSk7CgkJCQkJZWxzZQoJCQkJCQlobGQudXBkYXRlKEludGVnZXIucGFyc2VJbnQoc1sxXSksIEludGVnZXIucGFyc2VJbnQoc1syXSkpOwoJCQkJfQoJCQl9CgkJfQoJcHVibGljIHN0YXRpYyBjbGFzcyBobGQKCXsKCQlzdGF0aWMgaW50W11bXSBwO3N0YXRpYyBpbnRbXSBkcDtzdGF0aWMgaW50W10gc3Vic2l6ZTtzdGF0aWMgaW50W10gZW5kbm9kZTtzdGF0aWMgaW50IGNoYWlubm87c3RhdGljIGludFtdIGNoYWluaGVhZCxjaGFpbmluZCxhcnJwb3MsY29zdGFycixzZWd0cmVlOwoJCXB1YmxpYyBzdGF0aWMgdm9pZCBpbml0aWFsKGludCBuKQoJCXsKCQkJcD1uZXcgaW50W24rMV1bMjJdOwoJCQlkcD1uZXcgaW50W24rMV07CgkJCXN1YnNpemU9bmV3IGludFtuKzFdOwoJCQllbmRub2RlPW5ldyBpbnRbbl07CgkJCWNoYWluaGVhZD1uZXcgaW50W24rMV07CgkJCWNoYWluaW5kPW5ldyBpbnRbbisxXTsKCQkJYXJycG9zPW5ldyBpbnRbbisxXTsKCQkJY29zdGFycj1uZXcgaW50W25dOwoJCQlzZWd0cmVlPW5ldyBpbnRbbio0XTsKCQkJY2hhaW5ubz0xOwoJCQlwb3M9LTE7CgkJCUFycmF5cy5maWxsKGNoYWluaGVhZCwgLTEpOwoJCX0KCQlwdWJsaWMgc3RhdGljIHZvaWQgaWxjYShpbnQgbikKCQl7CgkJCWZvcihpbnQgaT0xO2k8PW47aSsrKQoJCQl7CgkJCQlmb3IoaW50IGo9MTtqPDIyO2orKykKCQkJCQlwW2ldW2pdPS0xOwoJCQl9CgkJCWZvcihpbnQgaj0xOzE8PGo8PW47aisrKQoJCQl7CgkJCQlmb3IoaW50IGk9MTtpPD1uO2krKykKCQkJCXsKCQkJCQlpZihwW2ldW2otMV0hPS0xKQoJCQkJCQlwW2ldW2pdPXBbcFtpXVtqLTFdXVtqLTFdOwoJCQkJfQoJCQl9CgkJfQoJCXB1YmxpYyBzdGF0aWMgdm9pZCBkZnMoaW50IG5vZGUsaW50IHBhcixBcnJheUxpc3Q8UGFpcj5bXSB0cmVlKQoJCXsKCQkJaWYocGFyPT0wKQlkcFtub2RlXT0wOwoJCQlzdWJzaXplW25vZGVdPTE7CgkJCXBbbm9kZV1bMF09cGFyOwoJCQlmb3IoaW50IGk9MDtpPHRyZWVbbm9kZV0uc2l6ZSgpO2krKykKCQkJewoJCQkJaW50IG5leHQ9dHJlZVtub2RlXS5nZXQoaSkudjsKCQkJCWludCBpbmQ9dHJlZVtub2RlXS5nZXQoaSkuaTsKCQkJCWlmKG5leHQhPXBhcikKCQkJCXsKCQkJCQllbmRub2RlW2luZF09bmV4dDsKCQkJCQlkZnMobmV4dCxub2RlLHRyZWUpOwoJCQkJCXN1YnNpemVbbm9kZV0rPXN1YnNpemVbbmV4dF07CgkJCQl9CgkJCX0KCQl9CgkJcHVibGljIHN0YXRpYyBpbnQgbGNhKGludCB1LGludCB2KQoJCXsKCQkJaWYoZHBbdV08ZHBbdl0pCgkJCXsKCQkJCWludCB0ZW1wPXU7CgkJCQl1PXY7CgkJCQl2PXRlbXA7CgkJCX0KCQkJaW50IGxvZzsKCQkJZm9yIChsb2cgPSAxOyAxIDw8IGxvZyA8PSBkcFt1XTsgbG9nKyspOwoJCSAgICAgIGxvZy0tOwoJCSAgICBmb3IoaW50IGk9bG9nO2k+PTA7aS0tKQoJCSAgICB7CgkJICAgIAlpZihkcFt1XS0oMTw8aSk+PWRwW3ZdKQoJCSAgICAJCXU9cFt1XVtpXTsKCQkgICAgfQoJCSAgICBpZih1PT12KQoJCSAgICAJcmV0dXJuIHU7CgkJICAgIGZvcihpbnQgaT1sb2c7aT49MDtpLS0pCgkJICAgIHsKCQkgICAgCWlmKHBbdV1baV0hPS0xICYmIHBbdV1baV0hPXBbdl1baV0pCgkJICAgIAkJe3U9cFt1XVtpXTt2PXBbdl1baV07fQoJCSAgICB9CgkJICAgIHJldHVybiBwW3VdWzBdOwoJCX0KCQlwdWJsaWMgc3RhdGljIHZvaWQgSGxkKGludCBub2RlLGludCBjb3N0LGludCBwYXIsQXJyYXlMaXN0PFBhaXI+W10gdHJlZSxpbnRbXVtdIGVjb3N0KQoJCXsKCQkJaWYoY2hhaW5oZWFkW2NoYWlubm9dPT0tMSkJY2hhaW5oZWFkW2NoYWlubm9dPW5vZGU7CgkJCXBvcysrOwoJCQljaGFpbmluZFtub2RlXT1jaGFpbm5vOwoJCQljb3N0YXJyW3Bvc109Y29zdDsKCQkJYXJycG9zW25vZGVdPXBvczsKCQkJaW50IGhuPS0xO2ludCBoYz0wOwoJCQlmb3IoaW50IGk9MDtpPHRyZWVbbm9kZV0uc2l6ZSgpO2krKykKCQkJewoJCQkJaW50IG5leHQ9dHJlZVtub2RlXS5nZXQoaSkudjsKCQkJCWlmKChuZXh0IT1wYXIpJiYoaG49PS0xIHx8IHN1YnNpemVbbmV4dF0+c3Vic2l6ZVtobl0pKQoJCQkJewoJCQkJCWhuPW5leHQ7CgkJCQkJaGM9ZWNvc3Rbbm9kZV1bbmV4dF07CgkJCQl9CgkJCX0KCQkJaWYoaG4hPS0xKQoJCQkJSGxkKGhuLGhjLG5vZGUsdHJlZSxlY29zdCk7CgkJCWZvcihpbnQgaT0wO2k8dHJlZVtub2RlXS5zaXplKCk7aSsrKQoJCQl7CgkJCQlpbnQgbmV4dD10cmVlW25vZGVdLmdldChpKS52OwoJCQkJaWYobmV4dCE9cGFyICYmIG5leHQhPWhuKQoJCQkJewoJCQkJCWNoYWlubm8rKzsKCQkJCQlIbGQobmV4dCxlY29zdFtub2RlXVtuZXh0XSxub2RlLHRyZWUsZWNvc3QpOwoJCQkJfQoJCQl9CgkJfQoJCXB1YmxpYyBzdGF0aWMgdm9pZCBidWlsZChpbnQgbm9kZSxpbnQgbCxpbnQgcikKCQl7CgkJCWlmKGw9PXIpCgkJCXsKCQkJCXNlZ3RyZWVbbm9kZV09Y29zdGFycltsXTsKCQkJfQoJCQllbHNlCgkJCXsKCQkJCWludCBtPShsK3IpLzI7CgkJCQlidWlsZCgoMipub2RlKSxsLG0pOwoJCQkJYnVpbGQoKDIqbm9kZSkrMSxtKzEscik7CgkJCQlzZWd0cmVlW25vZGVdPU1hdGgubWF4KHNlZ3RyZWVbMipub2RlXSxzZWd0cmVlWzIqbm9kZSsxXSk7CgkJCX0KCQl9CgkJcHVibGljIHN0YXRpYyB2b2lkIHVwZGF0ZShpbnQgbm9kZSxpbnQgbCxpbnQgcixpbnQgaW5kLGludCB2YWwpCgkJewoJCQlpZihsPT1yKQoJCQl7CgkJCQljb3N0YXJyW2luZF09dmFsOwoJCQkJc2VndHJlZVtub2RlXT12YWw7CgkJCX0KCQkJZWxzZQoJCQl7CgkJCQlpbnQgbT0obCtyKS8yOwoJCQkJaWYobDw9aW5kICYmIGluZDw9bSkKCQkJCXsKCQkJCQl1cGRhdGUoKDIqbm9kZSksbCxtLGluZCx2YWwpOwoJCQkJfQoJCQkJZWxzZQoJCQkJewoJCQkJCXVwZGF0ZSgoMipub2RlKzEpLG0rMSxyLGluZCx2YWwpOwoJCQkJfQoJCQkJc2VndHJlZVtub2RlXT1NYXRoLm1heChzZWd0cmVlWzIqbm9kZV0sIHNlZ3RyZWVbMipub2RlKzFdKTsKCQkJfQoJCX0KCQlwdWJsaWMgc3RhdGljIGludCBxdWVyeShpbnQgbm9kZSxpbnQgbCxpbnQgcixpbnQgcyxpbnQgZSkKCQl7CgkJCWlmKGU8bCB8fCByPHMpCgkJCQlyZXR1cm4gMDsKCQkJaWYoczw9bCAmJiBlPj1yKQoJCQkJcmV0dXJuIHNlZ3RyZWVbbm9kZV07CgkJCWludCBtPShsK3IpLzI7CgkJCWludCBwMT1xdWVyeSgoMipub2RlKSxsLG0scyxlKTsKCQkJaW50IHAyPXF1ZXJ5KCgyKm5vZGUrMSksbSsxLHIscyxlKTsKCQkJcmV0dXJuIE1hdGgubWF4KHAxLCBwMik7CgkJfQoJCXB1YmxpYyBzdGF0aWMgaW50IHF1ZXJ5cGF0aChpbnQgdSxpbnQgdikKCQl7CgkJCWludCBsY2E9bGNhKHUsdik7CgkJCXJldHVybiBNYXRoLm1heChxdWVyeXVwKHUsbGNhKSwgcXVlcnl1cCh2LGxjYSkpOwoJCX0KCQlwdWJsaWMgc3RhdGljIGludCBxdWVyeXVwKGludCB1LGludCB2KQoJCXsKCQkJaWYodT09dikKCQkJCXJldHVybiAwOwoJCQlpbnQgbGNoYWluO2ludCByY2hhaW49Y2hhaW5pbmRbdl07CgkJCWludCBhbnM9LTE7CgkJCXdoaWxlKHRydWUpCgkJCXsKCQkJCWxjaGFpbj1jaGFpbmluZFt1XTsKCQkJCWlmKGxjaGFpbj09cmNoYWluKQoJCQkJewoJCQkJCWlmKHU9PXYpCgkJCQkJCWJyZWFrOwoJCQkJCWludCBjdXI9cXVlcnkoMSwxLHBvcyxhcnJwb3Nbdl0rMSxhcnJwb3NbdV0pOwoJCQkJCWFucz1NYXRoLm1heChjdXIsIGFucyk7CgkJCQkJYnJlYWs7CgkJCQl9CgkJCQlpbnQgY3VyPXF1ZXJ5KDEsMSxwb3MsY2hhaW5oZWFkW2xjaGFpbl0sYXJycG9zW3VdKTsKCQkJCWFucz1NYXRoLm1heChjdXIsYW5zKTsKCQkJCXU9Y2hhaW5oZWFkW2xjaGFpbl07CgkJCQl1PXBbdV1bMF07CgkJCX0KCQkJcmV0dXJuIGFuczsKCQl9CgkJcHVibGljIHN0YXRpYyB2b2lkIHVwZGF0ZShpbnQgaW5kLGludCB2YWwpCgkJewoJCQlpbnQgbm89ZW5kbm9kZVtpbmRdOwoJCQl1cGRhdGUoMSwxLHBvcyxhcnJwb3Nbbm9dLHZhbCk7CgkJfQoJfQoJcHJpdmF0ZSBzdGF0aWMgY2xhc3MgUGFpciBpbXBsZW1lbnRzIENvbXBhcmFibGU8UGFpcj57CgkJaW50IHYsaTtQYWlyIGo7CgkJcHVibGljIFBhaXIoaW50IGEsaW50IGIpewoJCQl2PWE7CgkJCWk9YjsKCQl9CgkJcHVibGljIFBhaXIoaW50IGEsUGFpciBiKQoJCXsKCQkJdj1hOwoJCQlqPWI7CgkJfQoJCUBPdmVycmlkZQoJCXB1YmxpYyBpbnQgY29tcGFyZVRvKFBhaXIgYXJnMCkgewoJCQl7CgkJCQlyZXR1cm4gdGhpcy52LWFyZzAudjsKCQkJfQoJCX0KCX0KCQoJcHJpdmF0ZSBzdGF0aWMgbG9uZyBwb3cobG9uZyBhLCBsb25nIGIsIGxvbmcgYykgewoJCWlmIChiID09IDApCgkJCXJldHVybiAxOwoJCWxvbmcgcCA9IHBvdyhhLCBiIC8gMiwgYyk7CgkJcCA9IChwICogcCkgJSBjOwoJCXJldHVybiAoYiAlIDIgPT0gMCkgPyBwIDogKGEgKiBwKSAlIGM7Cgl9Cglwcml2YXRlIHN0YXRpYyBsb25nIGdjZChsb25nIG4sIGxvbmcgbCkgewoJCWlmIChsID09IDApCgkJCXJldHVybiBuOwoJCXJldHVybiBnY2QobCwgbiAlIGwpOwoJfQoKCXByaXZhdGUgc3RhdGljIGxvbmcgbWF4KGxvbmcgYSwgbG9uZyBiKSB7CgkJaWYgKGEgPiBiKQoJCQlyZXR1cm4gYTsKCQlyZXR1cm4gYjsKCX0KCglwcml2YXRlIHN0YXRpYyBsb25nIG1pbihsb25nIGEsIGxvbmcgYikgewoJCWlmIChhIDwgYikKCQkJcmV0dXJuIGE7CgkJcmV0dXJuIGI7Cgl9CgoJcHVibGljIHN0YXRpYyB2b2lkIG1haW4oU3RyaW5nW10gYXJncykgdGhyb3dzIEV4Y2VwdGlvbiB7CgkJbmV3IFRocmVhZChudWxsLG5ldyBSdW5uYWJsZSgpewoJCQlAT3ZlcnJpZGUKCQkJcHVibGljIHZvaWQgcnVuKCkgewoJCQkJLyp0cnkgewoJCQkJCUlucHV0UmVhZGVyKG5ldyBGaWxlSW5wdXRTdHJlYW0oIkM6XFxVc2Vyc1xcaGFyZGlrXFxEZXNrdG9wXFxDLXNtYWxsLTEtYXR0ZW1wdDEuaW4iKSk7CgkJCQl9IGNhdGNoIChGaWxlTm90Rm91bmRFeGNlcHRpb24gZSkgewoJCQkJCS8vIFRPRE8gQXV0by1nZW5lcmF0ZWQgY2F0Y2ggYmxvY2sKCQkJCQllLnByaW50U3RhY2tUcmFjZSgpOwoJCQkJfSovCgkJCQlJbnB1dFJlYWRlcihTeXN0ZW0uaW4pOwoJCQkJcHcgPSBuZXcgUHJpbnRXcml0ZXIoU3lzdGVtLm91dCk7CgkJCQkvKnRyeSB7CgkJCQkJcHc9bmV3IFByaW50V3JpdGVyKG5ldyBGaWxlT3V0cHV0U3RyZWFtKCJDOlxcVXNlcnNcXGhhcmRpa1xcRGVza3RvcFxcb3V0LnR4dCIpKTsKCQkJCX0gY2F0Y2ggKEZpbGVOb3RGb3VuZEV4Y2VwdGlvbiBlKSB7CgkJCQkJLy8gVE9ETyBBdXRvLWdlbmVyYXRlZCBjYXRjaCBibG9jawoJCQkJCWUucHJpbnRTdGFja1RyYWNlKCk7CgkJCQl9Ki8KCQkJCXNvbG4oKTsKCQkJCXB3LmNsb3NlKCk7CgkJCX0KCQl9LCIxIiwxPDwyNikuc3RhcnQoKTsKCX0KCglwdWJsaWMgc3RhdGljIHZvaWQgSW5wdXRSZWFkZXIoSW5wdXRTdHJlYW0gc3RyZWFtMSkgewoJCXN0cmVhbSA9IHN0cmVhbTE7Cgl9CgoJcHJpdmF0ZSBzdGF0aWMgYm9vbGVhbiBpc1doaXRlc3BhY2UoaW50IGMpIHsKCQlyZXR1cm4gYyA9PSAnICcgfHwgYyA9PSAnXG4nIHx8IGMgPT0gJ1xyJyB8fCBjID09ICdcdCcgfHwgYyA9PSAtMTsKCX0KCglwcml2YXRlIHN0YXRpYyBib29sZWFuIGlzRW5kT2ZMaW5lKGludCBjKSB7CgkJcmV0dXJuIGMgPT0gJ1xuJyB8fCBjID09ICdccicgfHwgYyA9PSAtMTsKCX0KCglwcml2YXRlIHN0YXRpYyBpbnQgcmVhZCgpIHsKCQlpZiAobnVtQ2hhcnMgPT0gLTEpCgkJCXRocm93IG5ldyBJbnB1dE1pc21hdGNoRXhjZXB0aW9uKCk7CgkJaWYgKGN1ckNoYXIgPj0gbnVtQ2hhcnMpIHsKCQkJY3VyQ2hhciA9IDA7CgkJCXRyeSB7CgkJCQludW1DaGFycyA9IHN0cmVhbS5yZWFkKGJ1Zik7CgkJCX0gY2F0Y2ggKElPRXhjZXB0aW9uIGUpIHsKCQkJCXRocm93IG5ldyBJbnB1dE1pc21hdGNoRXhjZXB0aW9uKCk7CgkJCX0KCQkJaWYgKG51bUNoYXJzIDw9IDApCgkJCQlyZXR1cm4gLTE7CgkJfQoJCXJldHVybiBidWZbY3VyQ2hhcisrXTsKCX0KCglwcml2YXRlIHN0YXRpYyBpbnQgbmkoKSB7CgkJaW50IGMgPSByZWFkKCk7CgkJd2hpbGUgKGlzU3BhY2VDaGFyKGMpKQoJCQljID0gcmVhZCgpOwoJCWludCBzZ24gPSAxOwoJCWlmIChjID09ICctJykgewoJCQlzZ24gPSAtMTsKCQkJYyA9IHJlYWQoKTsKCQl9CgkJaW50IHJlcyA9IDA7CgkJZG8gewoJCQlpZiAoYyA8ICcwJyB8fCBjID4gJzknKQoJCQkJdGhyb3cgbmV3IElucHV0TWlzbWF0Y2hFeGNlcHRpb24oKTsKCQkJcmVzICo9IDEwOwoJCQlyZXMgKz0gYyAtICcwJzsKCQkJYyA9IHJlYWQoKTsKCQl9IHdoaWxlICghaXNTcGFjZUNoYXIoYykpOwoJCXJldHVybiByZXMgKiBzZ247Cgl9CgoJcHJpdmF0ZSBzdGF0aWMgbG9uZyBubCgpIHsKCQlpbnQgYyA9IHJlYWQoKTsKCQl3aGlsZSAoaXNTcGFjZUNoYXIoYykpCgkJCWMgPSByZWFkKCk7CgkJaW50IHNnbiA9IDE7CgkJaWYgKGMgPT0gJy0nKSB7CgkJCXNnbiA9IC0xOwoJCQljID0gcmVhZCgpOwoJCX0KCQlsb25nIHJlcyA9IDA7CgkJZG8gewoJCQlpZiAoYyA8ICcwJyB8fCBjID4gJzknKQoJCQkJdGhyb3cgbmV3IElucHV0TWlzbWF0Y2hFeGNlcHRpb24oKTsKCQkJcmVzICo9IDEwOwoJCQlyZXMgKz0gYyAtICcwJzsKCQkJYyA9IHJlYWQoKTsKCQl9IHdoaWxlICghaXNTcGFjZUNoYXIoYykpOwoJCXJldHVybiByZXMgKiBzZ247Cgl9Cglwcml2YXRlIHN0YXRpYyBkb3VibGUgbmQoKQogICAgewogICAgICAgIGRvdWJsZSByZXQgPSAwLCBkaXYgPSAxOwogICAgICAgIGludCBjID0gcmVhZCgpOwogICAgICAgIHdoaWxlIChjIDw9ICcgJykKICAgICAgICAgICAgYyA9IHJlYWQoKTsKICAgICAgICBib29sZWFuIG5lZyA9IChjID09ICctJyk7CiAgICAgICAgaWYgKG5lZykKICAgICAgICAgICAgYyA9IHJlYWQoKTsKCiAgICAgICAgZG8gewogICAgICAgICAgICByZXQgPSByZXQgKiAxMCArIGMgLSAnMCc7CiAgICAgICAgfQogICAgICAgIHdoaWxlICgoYyA9IHJlYWQoKSkgPj0gJzAnICYmIGMgPD0gJzknKTsKCiAgICAgICAgaWYgKGMgPT0gJy4nKQogICAgICAgIHsKICAgICAgICAgICAgd2hpbGUgKChjID0gcmVhZCgpKSA+PSAnMCcgJiYgYyA8PSAnOScpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIHJldCArPSAoYyAtICcwJykgLyAoZGl2ICo9IDEwKTsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgaWYgKG5lZykKICAgICAgICAgICAgcmV0dXJuIC1yZXQ7CiAgICAgICAgcmV0dXJuIHJldDsKICAgIH0KCXByaXZhdGUgc3RhdGljIFN0cmluZyBuZXh0VG9rZW4oKSB7CgkJaW50IGMgPSByZWFkKCk7CgkJd2hpbGUgKGlzU3BhY2VDaGFyKGMpKQoJCQljID0gcmVhZCgpOwoJCVN0cmluZ0J1aWxkZXIgcmVzID0gbmV3IFN0cmluZ0J1aWxkZXIoKTsKCQlkbyB7CgkJCXJlcy5hcHBlbmRDb2RlUG9pbnQoYyk7CgkJCWMgPSByZWFkKCk7CgkJfSB3aGlsZSAoIWlzU3BhY2VDaGFyKGMpKTsKCQlyZXR1cm4gcmVzLnRvU3RyaW5nKCk7Cgl9CgoJcHJpdmF0ZSBzdGF0aWMgU3RyaW5nIG5saSgpIHsKCQlpbnQgYyA9IHJlYWQoKTsKCQl3aGlsZSAoaXNTcGFjZUNoYXIoYykpCgkJCWMgPSByZWFkKCk7CgkJU3RyaW5nQnVpbGRlciByZXMgPSBuZXcgU3RyaW5nQnVpbGRlcigpOwoJCWRvIHsKCQkJcmVzLmFwcGVuZENvZGVQb2ludChjKTsKCQkJYyA9IHJlYWQoKTsKCQl9IHdoaWxlICghaXNFbmRPZkxpbmUoYykpOwoJCXJldHVybiByZXMudG9TdHJpbmcoKTsKCX0KCQoJcHJpdmF0ZSBzdGF0aWMgaW50W10gbmlhKGludCBuKSB7CgkJaW50W10gYXJyID0gbmV3IGludFtuXTsKCQlmb3IgKGludCBpID0gMDsgaSA8IG47IGkrKykgewoJCQlhcnJbaV0gPSBuaSgpOwoJCX0KCQlyZXR1cm4gYXJyOwoJfQoKCXByaXZhdGUgc3RhdGljIGxvbmdbXSBubGEoaW50IG4pIHsKCQlsb25nW10gYXJyID0gbmV3IGxvbmdbbl07CgkJZm9yIChpbnQgaSA9IDA7IGkgPCBuOyBpKyspIHsKCQkJYXJyW2ldID0gbmwoKTsKCQl9CgkJcmV0dXJuIGFycjsKCX0KCglwcml2YXRlIHN0YXRpYyB2b2lkIHBhKGludFtdIGFycikgewoJCWZvciAoaW50IGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSB7CgkJCXB3LnByaW50KGFycltpXSArICIgIik7CgkJfQoJCXB3LnByaW50bG4oKTsKCQlyZXR1cm47Cgl9CgoJcHJpdmF0ZSBzdGF0aWMgdm9pZCBwYShsb25nW10gYXJyKSB7CgkJZm9yIChpbnQgaSA9IDA7IGkgPCBhcnIubGVuZ3RoOyBpKyspIHsKCQkJcHcucHJpbnQoYXJyW2ldICsgIiAiKTsKCQl9CgkJU3lzdGVtLm91dC5wcmludGxuKCk7CgkJcmV0dXJuOwoJfQoKCXByaXZhdGUgc3RhdGljIGJvb2xlYW4gaXNTcGFjZUNoYXIoaW50IGMpIHsKCQlpZiAoZmlsdGVyICE9IG51bGwpCgkJCXJldHVybiBmaWx0ZXIuaXNTcGFjZUNoYXIoYyk7CgkJcmV0dXJuIGlzV2hpdGVzcGFjZShjKTsKCX0KCXByaXZhdGUgc3RhdGljIGNoYXIgbmMoKSB7CgkJaW50IGMgPSByZWFkKCk7CgkJd2hpbGUgKGlzU3BhY2VDaGFyKGMpKQoJCQljID0gcmVhZCgpOwoJCWNoYXIgYzE9KGNoYXIpYzsKCQl3aGlsZSghaXNTcGFjZUNoYXIoYykpCgkJCWM9cmVhZCgpOwoJCXJldHVybiBjMTsKCX0KCXByaXZhdGUgaW50ZXJmYWNlIFNwYWNlQ2hhckZpbHRlciB7CgkJcHVibGljIGJvb2xlYW4gaXNTcGFjZUNoYXIoaW50IGNoKTsKCX0KfQ==