import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.StringTokenizer;
import java.util.Vector;
import java.util.regex.Pattern;
import java.util.Collections;
class Main{
MaterialePerK matPerK[]= new MaterialePerK[16];
int Adiac0 []={1,4,5};
matPerK[0]= new MaterialePerK(new CellaBoggle(0, 0),Adiac0 );
int Adiac1[]={0,4,5,6,2};
matPerK[1]= new MaterialePerK(new CellaBoggle(0, 1),Adiac1 );
int Adiac2[]={1,5,6,3,7};
matPerK[2]= new MaterialePerK(new CellaBoggle(0, 2),Adiac2 );
int Adiac3[]={2,6,7};
matPerK[3]= new MaterialePerK(new CellaBoggle(0, 3),Adiac3 );
int Adiac4[]= {0,1,5,9,8};
matPerK[4]= new MaterialePerK(new CellaBoggle(1, 0),Adiac4);
int Adiac5[]= {4,0,1,2,6,10,9,8};
matPerK[5]= new MaterialePerK(new CellaBoggle(1, 1),Adiac5 );
int Adiac6[]={5,1,2,3,7,11,10,9};
matPerK[6]= new MaterialePerK(new CellaBoggle(1, 2),Adiac6 );
int Adiac7[]={3,2,6,10,11};
matPerK[7]= new MaterialePerK(new CellaBoggle(1, 3),Adiac7 );
int Adiac8[]={4,5,9,13,12};
matPerK[8]= new MaterialePerK(new CellaBoggle(2, 0),Adiac8 );
int Adiac9[]={8,4,5,6,10,14,13,12};
matPerK[9]= new MaterialePerK(new CellaBoggle(2, 1),Adiac9);
int Adiac10[]={9,5,6,7,11,15,14,13};
matPerK[10]= new MaterialePerK(new CellaBoggle(2, 2),Adiac10);
int Adiac11[]={7,6,10,14,15};
matPerK[11]= new MaterialePerK(new CellaBoggle(2, 3),Adiac11);
int Adiac12[]={8,9,13};
matPerK[12]= new MaterialePerK(new CellaBoggle(3, 0),Adiac12);
int Adiac13[]={12,8,9,10,14};
matPerK[13]= new MaterialePerK(new CellaBoggle(3, 1),Adiac13);
int Adiac14[]={13,9,10,11,15};
matPerK[14]= new MaterialePerK(new CellaBoggle(3, 2),Adiac14);
int Adiac15[]={11,10,14};
matPerK[15]= new MaterialePerK(new CellaBoggle(3,3),Adiac15);
ContenitorePigEwu C= new ContenitorePigEwu();
GrafoBoggle Gr= new GrafoBoggle(matPerK,C);
LeggiPreparaM L= new LeggiPreparaM(Gr);
L.LeggiRigheM();
}
static class CellaBoggle {
private int Righe,Col;
public CellaBoggle(int r,int c){
Righe=r; Col=c;
}
int getRiga(){ return Righe; }
int getCol(){ return Col; }
void setRiga(int r){Righe=r; }
void setCol(int c){ Col=c; }
}
static class MaterialePerK {
private int NodiAdiacenti[];
private CellaBoggle C;
public MaterialePerK(CellaBoggle cb,int adiac[]) {
C=cb;
NodiAdiacenti= adiac;
}
CellaBoggle getCellaBoggle(){
return C; }
void setArrayAdiac(int ind,int val){
NodiAdiacenti[ind]=val;
}
int [] getArrayAdiac(){
return NodiAdiacenti;
}
}
static class LeggiPreparaM {
private GrafoBoggle Gr;
private char B1[][];
private char B2[][];
private String pattern
= "([A-Z] ){3}[A-Z]{1}(\t)+([A-Z] ){3}[A-Z]"; private Pattern p = Pattern.compile(pattern);
LeggiPreparaM(GrafoBoggle G) {
Riga=""; B1=new char[4][4]; B2=new char[4][4]; st=null;
}
char[][] getB1() {
return B1;
}
char[][] getB2() {
return B2;
}
int R; boolean cicla=true;
try{
while(true){
R=0;
while(R<4){
Riga=In_Str.readLine();
if(Riga.equals("#") )
return ;
AssegnaRiga(B1,R,0);
AssegnaRiga(B2,R,0);
R++;
}
Gr.TrovaParolePigEwu(getB1(),false);
if(!Gr.TrovaParolePigEwu(getB2(),true)){
System.
out.
println("There are no common words for this pair of boggle boards."); }
Gr.getContenitoreParole().rimuoviVettore();
Gr.getContenitoreParole().allocaVettore();
Gr.getContenitoreParole().setCiSonoComuni(false);
}
return;
}
}
void AssegnaRiga(char B[][],int R,int C1){
while(st.hasMoreTokens() && C1<4){
B[R][C1] = st.nextToken().charAt(0);
C1++;
}
return ;
}
}
static class ContenitorePigEwu {
private boolean ciSonoComuni;
private Vector<ArrayList<String>> parole = new Vector<ArrayList<String>>(26);
private ArrayList<String> paroleComuni ;
ContenitorePigEwu(){
for(int i=0 ; i<26 ;i++){
parole.insertElementAt(new ArrayList<String>(),i);
}
ciSonoComuni=false;
paroleComuni= new ArrayList<String>();
}
public Vector<ArrayList<String>> getParole() {
return parole;
}
public ArrayList<String> getParoleComuni() {
return paroleComuni;
}
boolean ciSonoComuni(){
return ciSonoComuni;
}
void setCiSonoComuni(boolean p){
ciSonoComuni=p;
}
void rimuoviVettore(){
parole.removeAllElements();
paroleComuni.clear();
}
void allocaVettore(){
for(int i=0 ; i<26 ;i++)
parole.insertElementAt(new ArrayList<String>(),i);
paroleComuni= new ArrayList<String>();
}
void inserInOrdineParolaDatoUnaCella
(String parola
){ int indVett= parola.charAt(0)-65;
parole.get(indVett).add(parola);
}
void ordinaVettore(ArrayList<String> arr){
}
void cercaComuni
(String parola2matr
){ int indVett= parola2matr.charAt(0)-65;
if(parole.get(indVett).size()!=0){
int left, right;
left = 0;
right =parole.get(indVett).size();
while (left!=right-1) {
int m = (right+left)/2 ;
String sm
= parole.
get(indVett
).
get(m
);
if(sm.compareTo(parola2matr)<0)
left = m;
else if (sm.compareTo(parola2matr)>0)
right = m;
else {
left = m;
right = m+1;
}
}
if(parola2matr.equals(parole.get(indVett).get(left) )){
paroleComuni.add(parola2matr);
ciSonoComuni=true;
}
}
}
void stampaParoleInComune(){
int k=0 ;
for(; k<paroleComuni.size()-1; k++){
if(! paroleComuni.get(k).equals(paroleComuni.get(k+1) ) )
System.
out.
println(paroleComuni.
get(k
));
}
if(paroleComuni.get(k).equals( paroleComuni.get(k-1) ) )
System.
out.
println(paroleComuni.
get(k
)); else {
System.
out.
println(paroleComuni.
get(k
)); }
}
}
static class GrafoBoggle {
private HashMap
<Integer,MaterialePerK
> GrafoTavola
=new HashMap
<Integer, MaterialePerK
>(16,
16) ; private MaterialePerK matPerK[];
private ContenitorePigEwu contenitoreParole;
private boolean Decr[];
GrafoBoggle(MaterialePerK mater[],ContenitorePigEwu cp){
contenitoreParole=cp;
matPerK=mater;
for(int k=0 ;k<16 ; k++)
GrafoTavola.put(k, matPerK[k]);
Decr= new boolean[4];
}
public ContenitorePigEwu getContenitoreParole() {
return contenitoreParole;
}
boolean TrovaParolePigEwu(char B[][],boolean ConfrontoP){
int contaVoc=0;
int Nodo_K=0;
for(int i=0 ; i<Decr.length ;i++)
Decr[i]=false;
while(Nodo_K<16){
if(CeVocaleAlNodo(Nodo_K,B) ){
contaVoc++;
Decr[0]=true;
}
for(int i=0; i<GrafoTavola.get(Nodo_K).getArrayAdiac().length;i++) {
int Nodo_K2=GrafoTavola.get(Nodo_K).getArrayAdiac()[i];
if(Nodo_K!=Nodo_K2){
if(CeVocaleAlNodo(Nodo_K2,B)){
contaVoc++;
Decr[1]=true;
}
for(int u=0; u< GrafoTavola.get(Nodo_K2).getArrayAdiac().length;u++) {
int Nodo_K3 = GrafoTavola.get(Nodo_K2).getArrayAdiac()[u];
if(CeVocaleAlNodo(Nodo_K3,B)){
contaVoc++;
Decr[2]=true;
}
if(contaVoc<3 && Nodo_K3!=Nodo_K && Nodo_K3!= Nodo_K2 ){
for(int y=0 ; y< GrafoTavola.get(Nodo_K3).getArrayAdiac().length; y++){
int Nodo_K4= GrafoTavola.get(Nodo_K3).getArrayAdiac()[y];
if(CeVocaleAlNodo(Nodo_K4,B)) {
contaVoc++;
Decr[3]=true;
}
if(contaVoc==2 && Nodo_K4!=Nodo_K2 && Nodo_K4!=Nodo_K && Nodo_K4!=Nodo_K3){
String s
= new StringBuilder
().
append(ConvertiNodoLettera
(Nodo_K, B
)).
append(ConvertiNodoLettera
(Nodo_K2, B
)).
append(ConvertiNodoLettera(Nodo_K3, B)).append(ConvertiNodoLettera(Nodo_K4, B)).toString();
if(!ConfrontoP)
contenitoreParole.inserInOrdineParolaDatoUnaCella(s);
else
contenitoreParole.cercaComuni(s);
}
if(Decr[3]){
contaVoc--;
Decr[3]=false;
}
}
}
if(Decr[2]){
contaVoc--;
Decr[2]=false;
}
}
if(Decr[1]){
contaVoc--;
Decr[1]=false;
}
}
}
if(Decr[0]){
contaVoc--;
Decr[0]=false;
}
if(!ConfrontoP){
int ind = ConvertiNodoLettera(Nodo_K, B)-65;
contenitoreParole.ordinaVettore(contenitoreParole.getParole().get(ind));
}
Nodo_K++;
}
if(ConfrontoP){
if(contenitoreParole.ciSonoComuni()) {
contenitoreParole.ordinaVettore(contenitoreParole.getParoleComuni() );
contenitoreParole.stampaParoleInComune();
return true;
}
}
return false;
}
char ConvertiNodoLettera(int kN,char B[][]){
CellaBoggle Cb= GrafoTavola.get(kN).getCellaBoggle();
int R=Cb.getRiga(); int C=Cb.getCol();
return B[R][C];
}
boolean CeVocaleAlNodo(int Nodo_K,char B[][]){
CellaBoggle Cb= GrafoTavola.get(Nodo_K).getCellaBoggle();
int R=Cb.getRiga(); int C=Cb.getCol();
switch( B[R][C] ){
case 'A': return true ;
case 'Y': return true;
case 'E': return true;
case 'O': return true;
case 'I': return true;
case 'U': return true;
};
return false;
}
}
}
aW1wb3J0IGphdmEuaW8uQnVmZmVyZWRSZWFkZXI7CmltcG9ydCBqYXZhLmlvLklPRXhjZXB0aW9uOwppbXBvcnQgamF2YS5pby5JbnB1dFN0cmVhbVJlYWRlcjsKaW1wb3J0IGphdmEudXRpbC5BcnJheUxpc3Q7CmltcG9ydCBqYXZhLnV0aWwuSGFzaE1hcDsKaW1wb3J0IGphdmEudXRpbC5MaW5rZWRMaXN0OwppbXBvcnQgamF2YS51dGlsLlN0cmluZ1Rva2VuaXplcjsKaW1wb3J0IGphdmEudXRpbC5WZWN0b3I7CmltcG9ydCBqYXZhLnV0aWwucmVnZXguUGF0dGVybjsKaW1wb3J0IGphdmEudXRpbC5Db2xsZWN0aW9uczsKCmNsYXNzIE1haW57CiAgIAogICBwdWJsaWMgc3RhdGljIHZvaWQgbWFpbihTdHJpbmcgYXJnc1tdKSB0aHJvd3MgSU9FeGNlcHRpb257CiAgICAgICBNYXRlcmlhbGVQZXJLIG1hdFBlcktbXT0gbmV3IE1hdGVyaWFsZVBlcktbMTZdOwogICAgICAgICAgCiAgICAgICAgICAgaW50IEFkaWFjMCBbXT17MSw0LDV9OwogICAgICAgICAgIG1hdFBlcktbMF09IG5ldyBNYXRlcmlhbGVQZXJLKG5ldyBDZWxsYUJvZ2dsZSgwLCAwKSxBZGlhYzAgKTsKICAgICAgICAgIGludCBBZGlhYzFbXT17MCw0LDUsNiwyfTsKICAgICAgICAgIG1hdFBlcktbMV09IG5ldyBNYXRlcmlhbGVQZXJLKG5ldyBDZWxsYUJvZ2dsZSgwLCAxKSxBZGlhYzEgKTsKICAgICAgICAgIGludCBBZGlhYzJbXT17MSw1LDYsMyw3fTsgICAKICAgICAgICAgIG1hdFBlcktbMl09IG5ldyBNYXRlcmlhbGVQZXJLKG5ldyBDZWxsYUJvZ2dsZSgwLCAyKSxBZGlhYzIgKTsKICAgICAgICAgIGludCBBZGlhYzNbXT17Miw2LDd9OwogICAgICAgICAgIG1hdFBlcktbM109IG5ldyBNYXRlcmlhbGVQZXJLKG5ldyBDZWxsYUJvZ2dsZSgwLCAzKSxBZGlhYzMgKTsKICAgICAgCiAgICAgICAgICAKICAgICAgICAgIGludCBBZGlhYzRbXT0gezAsMSw1LDksOH07CiAgICAgICAgICAgIG1hdFBlcktbNF09IG5ldyBNYXRlcmlhbGVQZXJLKG5ldyBDZWxsYUJvZ2dsZSgxLCAwKSxBZGlhYzQpOwogICAgICAgICAgaW50IEFkaWFjNVtdPSB7NCwwLDEsMiw2LDEwLDksOH07CiAgICAgICAgICBtYXRQZXJLWzVdPSBuZXcgTWF0ZXJpYWxlUGVySyhuZXcgQ2VsbGFCb2dnbGUoMSwgMSksQWRpYWM1ICk7ICAgCiAgICAgICAgICBpbnQgQWRpYWM2W109ezUsMSwyLDMsNywxMSwxMCw5fTsKICAgICAgICAgIG1hdFBlcktbNl09IG5ldyBNYXRlcmlhbGVQZXJLKG5ldyBDZWxsYUJvZ2dsZSgxLCAyKSxBZGlhYzYgKTsgICAKICAgICAgICAgICBpbnQgQWRpYWM3W109ezMsMiw2LDEwLDExfTsKICAgICAgICAgIG1hdFBlcktbN109IG5ldyBNYXRlcmlhbGVQZXJLKG5ldyBDZWxsYUJvZ2dsZSgxLCAzKSxBZGlhYzcgKTsgICAKICAgICAgICAgCiAgICAgICAgICBpbnQgQWRpYWM4W109ezQsNSw5LDEzLDEyfTsgICAgICAKICAgICAgICAgIG1hdFBlcktbOF09IG5ldyBNYXRlcmlhbGVQZXJLKG5ldyBDZWxsYUJvZ2dsZSgyLCAwKSxBZGlhYzggKTsgICAKICAgICAgICAgIGludCBBZGlhYzlbXT17OCw0LDUsNiwxMCwxNCwxMywxMn07ICAgICAgCiAgICAgICAgICBtYXRQZXJLWzldPSBuZXcgTWF0ZXJpYWxlUGVySyhuZXcgQ2VsbGFCb2dnbGUoMiwgMSksQWRpYWM5KTsgICAKICAgICAgICAgIGludCBBZGlhYzEwW109ezksNSw2LDcsMTEsMTUsMTQsMTN9OwogICAgICAgICAgbWF0UGVyS1sxMF09IG5ldyBNYXRlcmlhbGVQZXJLKG5ldyBDZWxsYUJvZ2dsZSgyLCAyKSxBZGlhYzEwKTsKICAgICAgICAgIGludCBBZGlhYzExW109ezcsNiwxMCwxNCwxNX07CiAgICAgICAgICBtYXRQZXJLWzExXT0gbmV3IE1hdGVyaWFsZVBlcksobmV3IENlbGxhQm9nZ2xlKDIsIDMpLEFkaWFjMTEpOwogICAgICAgICAKICAgICAgICAgICAgaW50IEFkaWFjMTJbXT17OCw5LDEzfTsgICAgICAKICAgICAgICAgICAgbWF0UGVyS1sxMl09IG5ldyBNYXRlcmlhbGVQZXJLKG5ldyBDZWxsYUJvZ2dsZSgzLCAwKSxBZGlhYzEyKTsKICAgICAgICAgICAgaW50IEFkaWFjMTNbXT17MTIsOCw5LDEwLDE0fTsgICAKICAgICAgICAgICAgbWF0UGVyS1sxM109IG5ldyBNYXRlcmlhbGVQZXJLKG5ldyBDZWxsYUJvZ2dsZSgzLCAxKSxBZGlhYzEzKTsKICAgICAgICAgICAgaW50IEFkaWFjMTRbXT17MTMsOSwxMCwxMSwxNX07ICAgCiAgICAgICAgICAgIG1hdFBlcktbMTRdPSBuZXcgTWF0ZXJpYWxlUGVySyhuZXcgQ2VsbGFCb2dnbGUoMywgMiksQWRpYWMxNCk7CiAgICAgICAgICAgIGludCBBZGlhYzE1W109ezExLDEwLDE0fTsKICAgICAgICAgICAgbWF0UGVyS1sxNV09IG5ldyBNYXRlcmlhbGVQZXJLKG5ldyBDZWxsYUJvZ2dsZSgzLDMpLEFkaWFjMTUpOwogICAgICAgICAgIAogICAgICAgICAgICBDb250ZW5pdG9yZVBpZ0V3dSBDPSBuZXcgQ29udGVuaXRvcmVQaWdFd3UoKTsKICAgICAgICAgICAgR3JhZm9Cb2dnbGUgR3I9IG5ldyBHcmFmb0JvZ2dsZShtYXRQZXJLLEMpOwogICAgICAgICAgICBMZWdnaVByZXBhcmFNIEw9IG5ldyBMZWdnaVByZXBhcmFNKEdyKTsKICAgICAgICAgICAgIEwuTGVnZ2lSaWdoZU0oKTsKfSAgIAoKIHN0YXRpYyBjbGFzcyBDZWxsYUJvZ2dsZSB7CiAgICBwcml2YXRlIGludCBSaWdoZSxDb2w7CiAgIAogICBwdWJsaWMgQ2VsbGFCb2dnbGUoaW50IHIsaW50IGMpewogICAgICAgUmlnaGU9cjsgIENvbD1jOyAgICAgIAogICB9CiAgIGludCBnZXRSaWdhKCl7IHJldHVybiBSaWdoZTsgIH0KICAgaW50IGdldENvbCgpeyAgcmV0dXJuIENvbDsgICAgfQogICAKICAgdm9pZCBzZXRSaWdhKGludCByKXtSaWdoZT1yOyAgfQogICB2b2lkIHNldENvbChpbnQgYyl7IENvbD1jOyAgICB9CiB9Cgogc3RhdGljIGNsYXNzIE1hdGVyaWFsZVBlcksgewogICAgICAgcHJpdmF0ZSBpbnQgTm9kaUFkaWFjZW50aVtdOwogICAgICBwcml2YXRlIENlbGxhQm9nZ2xlIEM7CiAgICAgIAogICAgICBwdWJsaWMgTWF0ZXJpYWxlUGVySyhDZWxsYUJvZ2dsZSBjYixpbnQgYWRpYWNbXSkgewogICAgICAgICBDPWNiOwogICAgICAgICBOb2RpQWRpYWNlbnRpPSBhZGlhYzsKICAgICAgfQogICAgICAKICAgICAgQ2VsbGFCb2dnbGUgZ2V0Q2VsbGFCb2dnbGUoKXsKICAgICAgICAgcmV0dXJuIEM7IH0KICAgICAgCgogICAgICB2b2lkIHNldEFycmF5QWRpYWMoaW50IGluZCxpbnQgdmFsKXsKICAgICAgICAgTm9kaUFkaWFjZW50aVtpbmRdPXZhbDsKICAgICAgfQoKICAgICAgIGludCBbXSBnZXRBcnJheUFkaWFjKCl7CiAgICAgICAgICByZXR1cm4gTm9kaUFkaWFjZW50aTsKICAgICAgIH0KCiAgIH0KCgogc3RhdGljIGNsYXNzIExlZ2dpUHJlcGFyYU0gewogICAgcHJpdmF0ZSBHcmFmb0JvZ2dsZSBHcjsKICAgIHByaXZhdGUgU3RyaW5nIFJpZ2E7ICAgCiAgICAgcHJpdmF0ZSBjaGFyIEIxW11bXTsKICAgICBwcml2YXRlIGNoYXIgQjJbXVtdOwogICAgIHByaXZhdGUgU3RyaW5nVG9rZW5pemVyIHN0OwogICAgIHByaXZhdGUgQnVmZmVyZWRSZWFkZXIgSW5fU3RyOwogICAgIHByaXZhdGUgU3RyaW5nIHBhdHRlcm4gPSAiKFtBLVpdICl7M31bQS1aXXsxfShcdCkrKFtBLVpdICl7M31bQS1aXSI7CiAgICAgcHJpdmF0ZSBQYXR0ZXJuIHAgPSBQYXR0ZXJuLmNvbXBpbGUocGF0dGVybik7CiAgICAgCiAgICBMZWdnaVByZXBhcmFNKEdyYWZvQm9nZ2xlIEcpIHsKICAgICBSaWdhPSIiOyAgICBCMT1uZXcgY2hhcls0XVs0XTsgICAgQjI9bmV3IGNoYXJbNF1bNF07ICAgc3Q9bnVsbDsgICAKICAgICBJbl9TdHIgPSBuZXcgQnVmZmVyZWRSZWFkZXIobmV3IElucHV0U3RyZWFtUmVhZGVyKFN5c3RlbS5pbikpOyAgR3I9RzsKICAgIH0KCiAgICAgY2hhcltdW10gZ2V0QjEoKSB7CiAgICAgICByZXR1cm4gQjE7CiAgICB9CiAgICAKICAgICBjaGFyW11bXSBnZXRCMigpIHsKICAgICAgIHJldHVybiBCMjsKICAgIH0KICAgIAogICAgIHZvaWQgTGVnZ2lSaWdoZU0oKXRocm93cyBJT0V4Y2VwdGlvbnsKICAgICAgIGludCBSOyAgIGJvb2xlYW4gY2ljbGE9dHJ1ZTsKICAgICAgIHRyeXsKICAgICAgIHdoaWxlKHRydWUpeyAgIAogICAgICAgICAgICAgIFI9MDsKICAgICAgICAgICAgICB3aGlsZShSPDQpewogICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICBSaWdhPUluX1N0ci5yZWFkTGluZSgpOwogICAgICAgICAgICAgICAgICAgIGlmKFJpZ2EuZXF1YWxzKCIjIikgKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIDsgICAKICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKCk7CiAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3Q9IG5ldyBTdHJpbmdUb2tlbml6ZXIoUmlnYSwiICAgICIpOwogICAgICAgICAgICAgICAgICAgICAgICAgQXNzZWduYVJpZ2EoQjEsUiwwKTsKICAgICAgICAgICAgICAgICAgICAgICAgIEFzc2VnbmFSaWdhKEIyLFIsMCk7CiAgICAgICAgICAgICAgUisrOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgIEdyLlRyb3ZhUGFyb2xlUGlnRXd1KGdldEIxKCksZmFsc2UpOwogICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgaWYoIUdyLlRyb3ZhUGFyb2xlUGlnRXd1KGdldEIyKCksdHJ1ZSkpewogICAgICAgICAgICAgICAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKCJUaGVyZSBhcmUgbm8gY29tbW9uIHdvcmRzIGZvciB0aGlzIHBhaXIgb2YgYm9nZ2xlIGJvYXJkcy4iKTsKICAgICAgICAgICAgICAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKCk7CiAgICAgICAgICAgICAgICAgICAgICB9IAoKICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgIEdyLmdldENvbnRlbml0b3JlUGFyb2xlKCkucmltdW92aVZldHRvcmUoKTsgICAKICAgICAgICAgICAgICAgIEdyLmdldENvbnRlbml0b3JlUGFyb2xlKCkuYWxsb2NhVmV0dG9yZSgpOwogICAgICAgICAgICAgICAgR3IuZ2V0Q29udGVuaXRvcmVQYXJvbGUoKS5zZXRDaVNvbm9Db211bmkoZmFsc2UpOyAKICAgIAogICAgICB9ICAgCgogICAgIH1jYXRjaCAoSU9FeGNlcHRpb24gZSkgewogICAgICAgIHJldHVybjsKICAgICB9CiB9CgogICAgICAgICB2b2lkIEFzc2VnbmFSaWdhKGNoYXIgQltdW10saW50IFIsaW50IEMxKXsKICAgICAgICAgIHdoaWxlKHN0Lmhhc01vcmVUb2tlbnMoKSAmJiBDMTw0KXsKICAgICAgICAgICAgICBCW1JdW0MxXSA9IHN0Lm5leHRUb2tlbigpLmNoYXJBdCgwKTsKICAgICAgICAgICAgQzErKzsKICAgICAgICAgICAgfQogICAgICAgICAgICAgcmV0dXJuIDsKICAgIH0KICAgIAogfQoKICBzdGF0aWMgY2xhc3MgQ29udGVuaXRvcmVQaWdFd3UgewogICAgCiAgIHByaXZhdGUgYm9vbGVhbiBjaVNvbm9Db211bmk7ICAgICAKICAgICBwcml2YXRlIFZlY3RvcjxBcnJheUxpc3Q8U3RyaW5nPj4gIHBhcm9sZSA9IG5ldyBWZWN0b3I8QXJyYXlMaXN0PFN0cmluZz4+KDI2KTsKICAgICBwcml2YXRlIEFycmF5TGlzdDxTdHJpbmc+ICBwYXJvbGVDb211bmkgOwogCiAgICAgCiAgICAgIENvbnRlbml0b3JlUGlnRXd1KCl7CiAgICAgICAgZm9yKGludCBpPTAgOyBpPDI2IDtpKyspewogICAgICAgICAgICBwYXJvbGUuaW5zZXJ0RWxlbWVudEF0KG5ldyBBcnJheUxpc3Q8U3RyaW5nPigpLGkpOwogICAgICAgIH0gCiAgICAgICAgY2lTb25vQ29tdW5pPWZhbHNlOwogICAgICBwYXJvbGVDb211bmk9IG5ldyBBcnJheUxpc3Q8U3RyaW5nPigpOwogICAgICB9CiAgICAgCiAgICAgIHB1YmxpYyBWZWN0b3I8QXJyYXlMaXN0PFN0cmluZz4+IGdldFBhcm9sZSgpIHsKICAgICAgcmV0dXJuIHBhcm9sZTsKICAgfQogICAgIAogICAgICBwdWJsaWMgQXJyYXlMaXN0PFN0cmluZz4gZ2V0UGFyb2xlQ29tdW5pKCkgewogICAgICByZXR1cm4gcGFyb2xlQ29tdW5pOwogICB9CiAgICAgCiAgICAgIGJvb2xlYW4gY2lTb25vQ29tdW5pKCl7CiAgICAgICAgIHJldHVybiBjaVNvbm9Db211bmk7CiAgICAgIH0KICAgICAKICAgICAgdm9pZCBzZXRDaVNvbm9Db211bmkoYm9vbGVhbiBwKXsKICAgICAgICAgICAgICBjaVNvbm9Db211bmk9cDsKICAgICAgfQoKICAgICAgdm9pZCByaW11b3ZpVmV0dG9yZSgpewogICAgICAgICAgICAgcGFyb2xlLnJlbW92ZUFsbEVsZW1lbnRzKCk7CiAgICAgICAgICBwYXJvbGVDb211bmkuY2xlYXIoKTsKICAgICAgfQoKICAgICB2b2lkIGFsbG9jYVZldHRvcmUoKXsKICAgICAgZm9yKGludCBpPTAgOyBpPDI2IDtpKyspCiAgICAgICAgICAgcGFyb2xlLmluc2VydEVsZW1lbnRBdChuZXcgQXJyYXlMaXN0PFN0cmluZz4oKSxpKTsKICAgICAgICAgcGFyb2xlQ29tdW5pPSBuZXcgQXJyYXlMaXN0PFN0cmluZz4oKTsKICAgICB9CiAgIAogICAgIHZvaWQgaW5zZXJJbk9yZGluZVBhcm9sYURhdG9VbmFDZWxsYShTdHJpbmcgcGFyb2xhKXsKICAgICAgICAgaW50IGluZFZldHQ9IHBhcm9sYS5jaGFyQXQoMCktNjU7CiAgICAgICAgIHBhcm9sZS5nZXQoaW5kVmV0dCkuYWRkKHBhcm9sYSk7CiAgICAgfQoKICAgICB2b2lkIG9yZGluYVZldHRvcmUoQXJyYXlMaXN0PFN0cmluZz4gIGFycil7CiAgICAgICAgICBDb2xsZWN0aW9ucy5zb3J0KGFycik7CiAgICAgfQogICAgIAogIHZvaWQgY2VyY2FDb211bmkoU3RyaW5nIHBhcm9sYTJtYXRyKXsKICAgICBpbnQgaW5kVmV0dD0gcGFyb2xhMm1hdHIuY2hhckF0KDApLTY1OwogICAgICAgaWYocGFyb2xlLmdldChpbmRWZXR0KS5zaXplKCkhPTApewogICAgICAgIGludCBsZWZ0LCByaWdodDsKICAgICAgICAgICAgbGVmdCA9IDA7CiAgICAgICAgICAgICByaWdodCA9cGFyb2xlLmdldChpbmRWZXR0KS5zaXplKCk7CiAgICAgICAgICAgIAogICAgICAgICAgICAgd2hpbGUgKGxlZnQhPXJpZ2h0LTEpIHsKICAgICAgICAgICAgICAgIGludCBtID0gKHJpZ2h0K2xlZnQpLzIgIDsKICAgICAgICAgCiAgICAgICAgICAgICAgICBTdHJpbmcgc20gPSBwYXJvbGUuZ2V0KGluZFZldHQpLmdldChtKTsKICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgIGlmKHNtLmNvbXBhcmVUbyhwYXJvbGEybWF0cik8MCkKICAgICAgICAgICAgICAgICAgICAgbGVmdCA9IG07CiAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICBlbHNlIGlmIChzbS5jb21wYXJlVG8ocGFyb2xhMm1hdHIpPjApCiAgICAgICAgICAgICAgICAgIHJpZ2h0ID0gbTsKICAgICAgICAgICAgICAgICBlbHNlIHsKICAgICAgICAgICAgICAgICAgbGVmdCA9IG07IAogICAgICAgICAgICAgICAgICByaWdodCA9IG0rMTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgCiAgICAgICAgICAgICBpZihwYXJvbGEybWF0ci5lcXVhbHMocGFyb2xlLmdldChpbmRWZXR0KS5nZXQobGVmdCkgKSl7CiAgICAgICAgICAgICAgICAgICAgcGFyb2xlQ29tdW5pLmFkZChwYXJvbGEybWF0cik7CiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNpU29ub0NvbXVuaT10cnVlOwogICAgICAgICAgICAgIH0KICAgICAgfQogICAgICAgICAKICB9CgogICAgdm9pZCBzdGFtcGFQYXJvbGVJbkNvbXVuZSgpewogICAgICAgaW50IGs9MCA7CiAgICAgICBmb3IoOyBrPHBhcm9sZUNvbXVuaS5zaXplKCktMTsgaysrKXsKICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICBpZighIHBhcm9sZUNvbXVuaS5nZXQoaykuZXF1YWxzKHBhcm9sZUNvbXVuaS5nZXQoaysxKSAgICkgICApCiAgICAgICAgICAgICAgICAgICAgIFN5c3RlbS5vdXQucHJpbnRsbihwYXJvbGVDb211bmkuZ2V0KGspKTsKICAgICAgICAgICAgICAgICAKICAgICAgIH0KCiAgICAgICAgICAgICAgICAgaWYocGFyb2xlQ29tdW5pLmdldChrKS5lcXVhbHMoICBwYXJvbGVDb211bmkuZ2V0KGstMSkgICkgICAgICkKICAgICAgICAgICAgICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4ocGFyb2xlQ29tdW5pLmdldChrKSk7CiAgICAgICAgICAgICAgICAgZWxzZSB7CiAgICAgICAgICAgICAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKHBhcm9sZUNvbXVuaS5nZXQoaykpOwogICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKCk7CiAgICAgICAgICAgICAgICAgIAogICAgfSAgIAogICAKfQogICAgc3RhdGljIGNsYXNzIEdyYWZvQm9nZ2xlIHsKCiAgICAgcHJpdmF0ZSAgIEhhc2hNYXA8SW50ZWdlcixNYXRlcmlhbGVQZXJLPiBHcmFmb1Rhdm9sYSA9bmV3IEhhc2hNYXA8SW50ZWdlciwgTWF0ZXJpYWxlUGVySz4oMTYsIDE2KSA7CiAgICAgcHJpdmF0ZSBNYXRlcmlhbGVQZXJLIG1hdFBlcktbXTsKICAgICBwcml2YXRlICBDb250ZW5pdG9yZVBpZ0V3dSBjb250ZW5pdG9yZVBhcm9sZTsKICAgICBwcml2YXRlIGJvb2xlYW4gRGVjcltdOwogICAgIAogICAgR3JhZm9Cb2dnbGUoTWF0ZXJpYWxlUGVySyBtYXRlcltdLENvbnRlbml0b3JlUGlnRXd1IGNwKXsKICAgICAgIGNvbnRlbml0b3JlUGFyb2xlPWNwOwogICAgICAgICAgbWF0UGVySz1tYXRlcjsKICAgICAgICAgICBmb3IoaW50IGs9MCA7azwxNiA7IGsrKykKICAgICAgICAgICBHcmFmb1Rhdm9sYS5wdXQoaywgbWF0UGVyS1trXSk7ICAgICAKICAgICAgICAgICAgICBEZWNyPSBuZXcgYm9vbGVhbls0XTsKICAgIH0KICAgCiAgICBwdWJsaWMgQ29udGVuaXRvcmVQaWdFd3UgZ2V0Q29udGVuaXRvcmVQYXJvbGUoKSB7CiAgICAgIHJldHVybiBjb250ZW5pdG9yZVBhcm9sZTsKICAgfQoKICAgIGJvb2xlYW4gVHJvdmFQYXJvbGVQaWdFd3UoY2hhciBCW11bXSxib29sZWFuIENvbmZyb250b1ApewogICAgICAgIGludCBjb250YVZvYz0wOwogICAgICAgIGludCBOb2RvX0s9MDsKICAgICAgICBmb3IoaW50IGk9MCA7IGk8RGVjci5sZW5ndGggO2krKykKICAgICAgICAgICAgRGVjcltpXT1mYWxzZTsgICAKICAgICAgICAgICAgCiB3aGlsZShOb2RvX0s8MTYpewogICAgICAgICAgICAgICAKICAgICAgIGlmKENlVm9jYWxlQWxOb2RvKE5vZG9fSyxCKSApewogICAgICAgICAgY29udGFWb2MrKzsKICAgICAgICAgIERlY3JbMF09dHJ1ZTsKICAgICAgIH0KICAgICAgICAgICAgCiAgICAgICAgICBmb3IoaW50IGk9MDsgaTxHcmFmb1Rhdm9sYS5nZXQoTm9kb19LKS5nZXRBcnJheUFkaWFjKCkubGVuZ3RoO2krKykgeyAKICAgICAgICAgICAgICAgICAgaW50IE5vZG9fSzI9R3JhZm9UYXZvbGEuZ2V0KE5vZG9fSykuZ2V0QXJyYXlBZGlhYygpW2ldOwogICAgICAgICAgIAogICAgICAgaWYoTm9kb19LIT1Ob2RvX0syKXsgICAgICAKICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgaWYoQ2VWb2NhbGVBbE5vZG8oTm9kb19LMixCKSl7CiAgICAgICAgICAgICAgICAgICAgICAgICBjb250YVZvYysrOwogICAgICAgICAgICAgICAgICAgICAgICAgRGVjclsxXT10cnVlOwogICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICBmb3IoaW50IHU9MDsgdTwgR3JhZm9UYXZvbGEuZ2V0KE5vZG9fSzIpLmdldEFycmF5QWRpYWMoKS5sZW5ndGg7dSsrKSB7CiAgICAgICAgICAgICAgICAgICAgaW50IE5vZG9fSzMgPSBHcmFmb1Rhdm9sYS5nZXQoTm9kb19LMikuZ2V0QXJyYXlBZGlhYygpW3VdOyAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgaWYoQ2VWb2NhbGVBbE5vZG8oTm9kb19LMyxCKSl7CiAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGFWb2MrKzsKICAgICAgICAgICAgICAgICAgICAgICAgICBEZWNyWzJdPXRydWU7CiAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgIGlmKGNvbnRhVm9jPDMgICYmIE5vZG9fSzMhPU5vZG9fSyAmJiBOb2RvX0szIT0gTm9kb19LMiApeyAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvcihpbnQgeT0wIDsgeTwgR3JhZm9UYXZvbGEuZ2V0KE5vZG9fSzMpLmdldEFycmF5QWRpYWMoKS5sZW5ndGg7ICB5KyspewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludCBOb2RvX0s0PSBHcmFmb1Rhdm9sYS5nZXQoTm9kb19LMykuZ2V0QXJyYXlBZGlhYygpW3ldOyAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYoQ2VWb2NhbGVBbE5vZG8oTm9kb19LNCxCKSkgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRhVm9jKys7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRGVjclszXT10cnVlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmKGNvbnRhVm9jPT0yICAmJiAgTm9kb19LNCE9Tm9kb19LMiAmJiBOb2RvX0s0IT1Ob2RvX0sgJiYgTm9kb19LNCE9Tm9kb19LMyl7CiAgICAgICAgICAgICAgICBTdHJpbmcgcyA9IG5ldyBTdHJpbmdCdWlsZGVyKCkuYXBwZW5kKENvbnZlcnRpTm9kb0xldHRlcmEoTm9kb19LLCBCKSkuYXBwZW5kKENvbnZlcnRpTm9kb0xldHRlcmEoTm9kb19LMiwgQikpLgogICAgICAgICAgICAgICAgIGFwcGVuZChDb252ZXJ0aU5vZG9MZXR0ZXJhKE5vZG9fSzMsIEIpKS5hcHBlbmQoQ29udmVydGlOb2RvTGV0dGVyYShOb2RvX0s0LCBCKSkudG9TdHJpbmcoKTsgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmKCFDb25mcm9udG9QKSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGVuaXRvcmVQYXJvbGUuaW5zZXJJbk9yZGluZVBhcm9sYURhdG9VbmFDZWxsYShzKTsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGVuaXRvcmVQYXJvbGUuY2VyY2FDb211bmkocyk7ICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZihEZWNyWzNdKXsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRhVm9jLS07CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBEZWNyWzNdPWZhbHNlOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgaWYoRGVjclsyXSl7CiAgICAgICAgICAgICAgICAgICAgICAgY29udGFWb2MtLTsgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgIERlY3JbMl09ZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICBpZihEZWNyWzFdKXsKICAgICAgICAgICAgICAgICAgICAgICAgY29udGFWb2MtLTsgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICBEZWNyWzFdPWZhbHNlOwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgfSAgIAogICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICB9CiAgICAgICAgICAKICAgICAgICAgIGlmKERlY3JbMF0pewogICAgICAgICAgY29udGFWb2MtLTsgICAKICAgICAgICAgICAgIERlY3JbMF09ZmFsc2U7CiAgICAgICAgICB9CiAgICAgICAgICAgICAKICAgICAgICAgIGlmKCFDb25mcm9udG9QKXsKICAgICAgICAgICAgaW50IGluZCA9IENvbnZlcnRpTm9kb0xldHRlcmEoTm9kb19LLCBCKS02NTsKICAgICAgICAgICAgICBjb250ZW5pdG9yZVBhcm9sZS5vcmRpbmFWZXR0b3JlKGNvbnRlbml0b3JlUGFyb2xlLmdldFBhcm9sZSgpLmdldChpbmQpKTsgICAgICAgICAgICAgCiAgICAgICAgICB9ICAgICAgICAgIAogIE5vZG9fSysrOyAgICAgICAgIAogIH0gICAgICAgICAgCgogICAgIGlmKENvbmZyb250b1ApewogICAgICAgIGlmKGNvbnRlbml0b3JlUGFyb2xlLmNpU29ub0NvbXVuaSgpKSB7CiAgICAgICAgY29udGVuaXRvcmVQYXJvbGUub3JkaW5hVmV0dG9yZShjb250ZW5pdG9yZVBhcm9sZS5nZXRQYXJvbGVDb211bmkoKSApOwogICAgICAgICAgY29udGVuaXRvcmVQYXJvbGUuc3RhbXBhUGFyb2xlSW5Db211bmUoKTsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CiAgICAgICAgIAogICAgIH0gICAgIAogICAgICAgICAgIAogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgICAgCiAgICB9ICAgCgogICAgICAgICBjaGFyIENvbnZlcnRpTm9kb0xldHRlcmEoaW50IGtOLGNoYXIgQltdW10pewogICAgICAgICAgIENlbGxhQm9nZ2xlIENiPSBHcmFmb1Rhdm9sYS5nZXQoa04pLmdldENlbGxhQm9nZ2xlKCk7CiAgICAgICAgICAgICBpbnQgUj1DYi5nZXRSaWdhKCk7ICBpbnQgQz1DYi5nZXRDb2woKTsKICAgICAgICAgICAgICByZXR1cm4gQltSXVtDXTsKICAgICAgICAgIH0KCiAgICBib29sZWFuIENlVm9jYWxlQWxOb2RvKGludCBOb2RvX0ssY2hhciBCW11bXSl7CiAgICAgICBDZWxsYUJvZ2dsZSBDYj0gICBHcmFmb1Rhdm9sYS5nZXQoTm9kb19LKS5nZXRDZWxsYUJvZ2dsZSgpOwogICAgICAgICBpbnQgUj1DYi5nZXRSaWdhKCk7ICBpbnQgQz1DYi5nZXRDb2woKTsKICAgICAgICAgCiAgICAgICAgIHN3aXRjaCggQltSXVtDXSApewogICAgICAgICAgICAgICAgICAgICBjYXNlICdBJzogcmV0dXJuIHRydWUgOwogICAgICAgICAgICAgICAgICAgICBjYXNlICdZJzogcmV0dXJuIHRydWU7CiAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ0UnOiByZXR1cm4gdHJ1ZTsKICAgICAgICAgICAgICAgICAgICAgY2FzZSAnTyc6IHJldHVybiB0cnVlOwogICAgICAgICAgICAgICAgICAgICBjYXNlICdJJzogcmV0dXJuIHRydWU7CiAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ1UnOiByZXR1cm4gdHJ1ZTsKICAgICAgICAgfTsKICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogCgogfQogICAgICAKfQ==