#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <math.h>
#include <time.h>
HANDLE hOut;
time_t start, endet;
int width = 55 , height = 36 , modifikator = 0 , siegPunkte = 5 , spielmodus = 0 ;;
int cScore = 0 , yScore = 0 , y2Score = 0 , mainLoop = 0 ;;
int links = 65 , rechts = 68 , beenden = 81 ;
int links2 = 37 , rechts2 = 39 , beenden2 = 38 ;
char name[ 40 ] = "" ;
char pfad[ 60 ] = "C:\\ Machbar.txt" ;
char modus [ 30 ] = "Mensch vs Computer" ;
char schwierigkeit[ 20 ] = "Machbar" ;
char spielergebnis[ 20 ] = "" ;
double dif = 0.0f ;
float maxSpeed = 3.2f , kiReaktion = 8.0f ;
typedef struct
{
float x, y; // x und y Position des Pads
int size; // Größe des Pads
float ox, oy; // Anfangstellung der Pads
float vx; // KI Geschwindigkeit
} spieler;
// Methode, um Werte für ein Objekt der spieler struct zu setzen
void spieler_( spieler * this, int _x, int _y, int _size)
{
this-> x = ( float ) ( _x) ;
this-> y = ( float ) ( _y) ;
this-> size = _size;
this-> ox = ( float ) ( _x) ;
this-> oy = ( float ) ( _y) ;
}
// Pads zeichnen
void draw( spieler * this)
{
int i;
COORD p;
p.X = ( int ) ( this-> ox) - this-> size ;
p.Y = ( int ) ( this-> oy) ;
SetConsoleCursorPosition( hOut, p) ;
for ( i = - this-> size; i < this-> size + modifikator; i++ )
{
}
p.X = ( int ) ( this-> x) - this-> size; // Pads zeichnen
p.Y = ( int ) ( this-> y) ;
SetConsoleCursorPosition( hOut, p) ;
SetConsoleTextAttribute( hOut, 10 ) ;
for ( i = - this-> size; i < this-> size + modifikator; i++ )
{
}
SetConsoleTextAttribute( hOut, 15 ) ;
this-> ox = this-> x;
this-> oy = this-> y;
}
typedef struct ball
{
float x, y, ox, oy; // aktuelle und Anfangsstellung des Balls
float vx, vy; // Geschwindigkeit x, y des Balls
} ball;
// Methode, um Werte für ein Objekt der ball struct zu setzen
void ball_( ball * this, int _x, int _y)
{
this-> x = ( float ) ( _x) ;
this-> y = ( float ) ( _y) ;
this-> ox = ( float ) ( this-> x) ;
this-> oy = ( float ) ( this-> y) ;
this-> vx = this-> vy = 0 ;
}
// Ball zeichnen
void drawball( ball * this)
{
COORD p;
p.X = ( int ) ( this-> ox) ;
p.Y = ( int ) ( this-> oy) ;
SetConsoleCursorPosition( hOut, p) ;
p.X = ( int ) ( this-> x) ;
p.Y = ( int ) ( this-> y) ;
SetConsoleCursorPosition( hOut, p) ;
SetConsoleTextAttribute( hOut, 12 ) ;
SetConsoleTextAttribute( hOut, 15 ) ;
this-> ox = this-> x;
this-> oy = this-> y;
}
// Alles zur�¼cksetzen
void reset( spieler * you, spieler * you2, spieler * comp, ball * b, int you_score , int you2_score, int comp_score)
{
b-> x = ( float ) ( width / 2 - 1 ) ;
b-> y = ( float ) ( height / 2 ) ; // Koordinaten zum zeichnen auf Anfangswerte setzen
you-> x = comp-> x = ( float ) ( width / 2 ) ;
comp-> vx = 0.0f ; // Geschwindigkeiten auf 0 standart zurücksetzen
b
-> vx
= ( float ) ( rand ( ) % 3 ) - 1.5f ; b-> vy = 1 ;
COORD p;
p.X = 0 ;
p.Y = height;
SetConsoleCursorPosition( hOut, p) ;
if ( spielmodus
== 0 ) printf ( "\n | Your score: %i | Computer score: %i ||| Speed: 0 |\n " , you_score
, comp_score
) ; // Spielstand aktualisieren bei Spielmodus = Mensch vs Computer if ( spielmodus
== 1 ) printf ( "\n | Spi. 1 score: %i | Spi. 2 score: %i ||| Speed: 0 |\n " , you_score
, you2_score
) ; // Spielstand aktualisieren bei Spielmodus = Mensch vs Mensch }
// Größe der Konsole festlegen
void setWindowSize( int x, int y)
{
SMALL_RECT sr_window = { 0 , 0 , x - 1 , y - 1 } ;
COORD extension;
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo( GetStdHandle( STD_OUTPUT_HANDLE) , & csbi) ; // Akutelle Fensterpuffer Größe ermitteln
extension.X = max( x, csbi.dwMaximumWindowSize .X ) ;
extension.Y = max( y, csbi.dwMaximumWindowSize .Y ) ;
SetConsoleScreenBufferSize( GetStdHandle( STD_OUTPUT_HANDLE) , extension) ; // Puffer auf max Werte setzen
SetConsoleWindowInfo( GetStdHandle( STD_OUTPUT_HANDLE) , TRUE, & sr_window) ; // Fenster auf max Werte setzen
extension.X = x;
extension.Y = y;
SetConsoleScreenBufferSize( GetStdHandle( STD_OUTPUT_HANDLE) , extension) ; // Puffer auf Fenstergröße setzen
}
// Highscore anzeigen
void highscoreAusgeben( )
{
char * ausgabe; // Zeiger auf bestimmte Stellen im später eingelesenen String
char zwischenPfad[ 60 ] = "" ; // char array, um einen Dateipfad zwischenzuspeichern
strcat ( zwischenPfad
, pfad
) ; // Pfad in zwischenPfad zwischenspeichern char einlesen[ 69 ] ; // Array um Inhalt der txt zwischen zu speichern
system ( "cls" ) ; // Konsole leeren printf ( "Welche Highscores wollen sie anschauen?\n \n " ) ; printf ( "<3> Veteran\n " ) ; // Highscore Auswahlmenü darstellen printf ( "<4> Nervt\224 tend\n " ) ;
int auswahl = _getch( ) ; // "Hihscorelistenauswahl" in auswahl speichern
system ( "cls" ) ; // Konsole leeren
if ( auswahl == 49 ) // falls "1" gedrückt wurde, Amateur.txt ausgeben
{
FILE* FDatei; // Zeiger auf Highscore txt erstellen
strcpy ( pfad
, "C:\\ Amateur.txt" ) ; // Pfad für die Amatuer.txt in das char Array pfad kopieren FDatei
= fopen ( pfad
, "r" ) ; // Amateur.txt öffnen und lesen int i = 1 ; // Startwert für Vorzeichen (1. , 2. , 3....) für Ausgabe erhöhen
if ( ! FDatei) // gibt es die Amateur.txt noch nicht?
{
FDatei
= fopen ( pfad
, "w" ) ; // falls Amateur.txt noch nicht vorhanden, erstelle diese printf ( "\n Leider hat noch niemand einen Highscore aufgestellt!\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <1> Zur\201 ck zum Hauptmen\201 " ) ;
int auswahl = _getch( ) ; // zurück zum Menü Abfrage (falls 1 gedrückt wird zurück zum mNeü)
if ( auswahl == 49 )
{
return ;
}
}
else if ( fgets ( einlesen
, 50 , FDatei
) == NULL
) // steht etwas in der Amateur.txt? {
printf ( "\n Leider hat noch niemand einen Highscore aufgestellt!\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <1> Zur\201 ck zum Hauptmen\201 " ) ; // falls nein, dies ausgeben int auswahl = _getch( ) ; // zurück zum Menü Abfrage (falls 1 gedrückt wird)
if ( auswahl == 49 )
{
return ;
}
fclose ( FDatei
) ; // Datei schliessen }
else
{
FDatei
= fopen ( pfad
, "r" ) ; // noch einmal schließen und öffnen, um wieder am Anfang der Datei zu beginnen while ( fgets ( einlesen
, 50 , FDatei
) ) // ansonsten Highscore ausgeben & lese bis Dateiende {
ausgabe
= strchr ( einlesen
, '.' ) ; // Punkt im eingelesenen String suchen ausgabe += 1 ; // Zeiger um 1 nach rechts verschieben, um den Punkt nicht mit auszugeben
printf ( "%i. %s" , i
, ausgabe
) ; // bearbeiteten String ausgeben i++; // Vorzeichen (1. , 2. , 3....) für Ausgabe erhöhen
}
fclose ( FDatei
) ; // Datei schliessen printf ( "\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <1> Zur\201 ck zum Hauptmen\201 " ) ; // falls Highscore Datei noch nicht vorhanden, erstelle diese
int auswahl = _getch( ) ; // zurück zum Menü Abfrage (falls 1 gedrückt wird)
if ( auswahl == 49 )
{
return ;
}
}
}
if ( auswahl == 50 ) // falls "1" gedrückt wurde, Machbar.txt ausgeben
{
FILE* FDatei; // Zeiger auf Machbar txt erstellen
strcpy ( pfad
, "C:\\ Machbar.txt" ) ; // Pfad für die Machbar.txt in das char Array pfad kopieren FDatei
= fopen ( pfad
, "r" ) ; // Machbar.txt öffnen und lesen int i = 1 ; // Startwert für Vorzeichen (1. , 2. , 3....) für Ausgabe erhöhen
if ( ! FDatei) // gibt es die Machbar.txt noch nicht?
{
FDatei
= fopen ( pfad
, "w" ) ; // falls Amateur.txt noch nicht vorhanden, erstelle diese printf ( "\n Leider hat noch niemand einen Highscore aufgestellt!\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <1> Zur\201 ck zum Hauptmen\201 " ) ;
int auswahl = _getch( ) ; // zurück zum Menü Abfrage (falls 1 gedrückt wird zurück zum mNeü)
if ( auswahl == 49 )
{
return ;
}
}
else if ( fgets ( einlesen
, 50 , FDatei
) == NULL
) // steht etwas in der Machbar.txt? {
printf ( "\n Leider hat noch niemand einen Highscore aufgestellt!\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <1> Zur\201 ck zum Hauptmen\201 " ) ; // falls nein, dies ausgeben int auswahl = _getch( ) ; // zurück zum Menü Abfrage (falls 1 gedrückt wird)
if ( auswahl == 49 )
{
return ;
}
fclose ( FDatei
) ; // Datei schliessen }
else
{
FDatei
= fopen ( pfad
, "r" ) ; // noch einmal schließen und öffnen, um wieder am Anfang der Datei zu beginnen while ( fgets ( einlesen
, 50 , FDatei
) ) // ansonsten Highscore ausgeben & lese bis Dateiende {
ausgabe
= strchr ( einlesen
, '.' ) ; // Punkt im eingelesenen String suchen ausgabe += 1 ; // Zeiger um 1 nach rechts verschieben, um den Punkt nicht mit auszugeben
printf ( "%i. %s" , i
, ausgabe
) ; // bearbeiteten String ausgeben i++; // Vorzeichen (1. , 2. , 3....) für Ausgabe erhöhen
}
fclose ( FDatei
) ; // Datei schliessen printf ( "\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <1> Zur\201 ck zum Hauptmen\201 " ) ; // falls Highscore Datei noch nicht vorhanden, erstelle diese
int auswahl = _getch( ) ; // zurück zum Menü Abfrage (falls 1 gedrückt wird)
if ( auswahl == 49 )
{
return ;
}
}
}
if ( auswahl == 51 ) // falls "1" gedrückt wurde, Veteran.txt ausgeben
{
FILE* FDatei; // Zeiger auf Veteran txt erstellen
strcpy ( pfad
, "C:\\ Veteran.txt" ) ; // Pfad für die Veteran.txt in das char Array pfad kopieren FDatei
= fopen ( pfad
, "r" ) ; // Veteran.txt öffnen und lesen int i = 1 ; // Startwert für Vorzeichen (1. , 2. , 3....) für Ausgabe erhöhen
if ( ! FDatei) // gibt es die Veteran.txt noch nicht?
{
FDatei
= fopen ( pfad
, "w" ) ; // falls Veteran.txt noch nicht vorhanden, erstelle diese printf ( "\n Leider hat noch niemand einen Highscore aufgestellt!\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <1> Zur\201 ck zum Hauptmen\201 " ) ;
int auswahl = _getch( ) ; // zurück zum Menü Abfrage (falls 1 gedrückt wird zurück zum mNeü)
if ( auswahl == 49 )
{
return ;
}
}
else if ( fgets ( einlesen
, 50 , FDatei
) == NULL
) // steht etwas in der Veteran.txt? {
printf ( "\n Leider hat noch niemand einen Highscore aufgestellt!\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <1> Zur\201 ck zum Hauptmen\201 " ) ; // falls nein, dies ausgeben int auswahl = _getch( ) ; // zurück zum Menü Abfrage (falls 1 gedrückt wird)
if ( auswahl == 49 )
{
return ;
}
fclose ( FDatei
) ; // Datei schliessen }
else
{
FDatei
= fopen ( pfad
, "r" ) ; // noch einmal schließen und öffnen, um wieder am Anfang der Datei zu beginnen while ( fgets ( einlesen
, 50 , FDatei
) ) // ansonsten Highscore ausgeben & lese bis Dateiende {
ausgabe
= strchr ( einlesen
, '.' ) ; // Punkt im eingelesenen String suchen ausgabe += 1 ; // Zeiger um 1 nach rechts verschieben, um den Punkt nicht mit auszugeben
printf ( "%i. %s" , i
, ausgabe
) ; // bearbeiteten String ausgeben i++; // Vorzeichen (1. , 2. , 3....) für Ausgabe erhöhen
}
fclose ( FDatei
) ; // Datei schliessen printf ( "\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <1> Zur\201 ck zum Hauptmen\201 " ) ; // falls Highscore Datei noch nicht vorhanden, erstelle diese
int auswahl = _getch( ) ; // zurück zum Menü Abfrage (falls 1 gedrückt wird)
if ( auswahl == 49 )
{
return ;
}
}
}
if ( auswahl == 52 ) // falls "1" gedrückt wurde, Nervt\224tend.txt ausgeben
{
FILE* FDatei; // Zeiger auf Nervt\224tend txt erstellen
strcpy ( pfad
, "C:\\ Nervt\224 tend.txt" ) ; // Pfad für die Nervt\224tend.txt in das char Array pfad kopieren FDatei
= fopen ( pfad
, "r" ) ; // Nervt\224tend.txt öffnen und lesen int i = 1 ; // Startwert für Vorzeichen (1. , 2. , 3....) für Ausgabe erhöhen
if ( ! FDatei) // gibt es die Nervt\224tend.txt noch nicht?
{
FDatei
= fopen ( pfad
, "w" ) ; // falls Nervt\224tend.txt noch nicht vorhanden, erstelle diese printf ( "\n Leider hat noch niemand einen Highscore aufgestellt!\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <1> Zur\201 ck zum Hauptmen\201 " ) ;
int auswahl = _getch( ) ; // zurück zum Menü Abfrage (falls 1 gedrückt wird zurück zum mNeü)
if ( auswahl == 49 )
{
return ;
}
}
else if ( fgets ( einlesen
, 50 , FDatei
) == NULL
) // steht etwas in der Nervt\224tend.txt? {
printf ( "\n Leider hat noch niemand einen Highscore aufgestellt!\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <1> Zur\201 ck zum Hauptmen\201 " ) ; // falls nein, dies ausgeben int auswahl = _getch( ) ; // zurück zum Menü Abfrage (falls 1 gedrückt wird)
if ( auswahl == 49 )
{
return ;
}
fclose ( FDatei
) ; // Datei schliessen }
else
{
FDatei
= fopen ( pfad
, "r" ) ; // noch einmal schließen und öffnen, um wieder am Anfang der Datei zu beginnen while ( fgets ( einlesen
, 50 , FDatei
) ) // ansonsten Highscore ausgeben & lese bis Dateiende {
ausgabe
= strchr ( einlesen
, '.' ) ; // Punkt im eingelesenen String suchen ausgabe += 1 ; // Zeiger um 1 nach rechts verschieben, um den Punkt nicht mit auszugeben
printf ( "%i. %s" , i
, ausgabe
) ; // bearbeiteten String ausgeben i++; // Vorzeichen (1. , 2. , 3....) für Ausgabe erhöhen
}
fclose ( FDatei
) ; // Datei schliessen printf ( "\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <1> Zur\201 ck zum Hauptmen\201 " ) ; // falls Highscore Datei noch nicht vorhanden, erstelle diese
int auswahl = _getch( ) ; // zurück zum Menü Abfrage (falls 1 gedrückt wird)
if ( auswahl == 49 )
{
return ;
}
}
}
if ( auswahl == 53 ) // falls "1" gedrückt wurde, Mehrspieler.txt ausgeben
{
FILE* FDatei; // Zeiger auf Highscore txt erstellen
strcpy ( pfad
, "C:\\ Mehrspieler.txt" ) ; // Pfad für die Mehrspieler.txt in das char Array pfad kopieren FDatei
= fopen ( pfad
, "r" ) ; // Mehrspieler.txt öffnen und lesen int i = 1 ; // Startwert für Vorzeichen (1. , 2. , 3....) für Ausgabe erhöhen
if ( ! FDatei) // gibt es die Amateur.txt noch nicht?
{
FDatei
= fopen ( pfad
, "w" ) ; // falls Mehrspieler.txt noch nicht vorhanden, erstelle diese printf ( "\n Leider hat noch niemand einen Highscore aufgestellt!\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <1> Zur\201 ck zum Hauptmen\201 " ) ;
int auswahl = _getch( ) ; // zurück zum Menü Abfrage (falls 1 gedrückt wird zurück zum mNeü)
if ( auswahl == 49 )
{
return ;
}
}
else if ( fgets ( einlesen
, 50 , FDatei
) == NULL
) // steht etwas in der Mehrspieler.txt? {
printf ( "\n Leider hat noch niemand einen Highscore aufgestellt!\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <1> Zur\201 ck zum Hauptmen\201 " ) ; // falls nein, dies ausgeben int auswahl = _getch( ) ; // zurück zum Menü Abfrage (falls 1 gedrückt wird)
if ( auswahl == 49 )
{
return ;
}
fclose ( FDatei
) ; // Datei schliessen }
else
{
FDatei
= fopen ( pfad
, "r" ) ; // noch einmal schließen und öffnen, um wieder am Anfang der Datei zu beginnen while ( fgets ( einlesen
, 50 , FDatei
) ) // ansonsten Highscore ausgeben & lese bis Dateiende {
ausgabe
= strchr ( einlesen
, '.' ) ; // Punkt im eingelesenen String suchen ausgabe += 1 ; // Zeiger um 1 nach rechts verschieben, um den Punkt nicht mit auszugeben
printf ( "%i. %s" , i
, ausgabe
) ; // bearbeiteten String ausgeben i++; // Vorzeichen (1. , 2. , 3....) für Ausgabe erhöhen
}
fclose ( FDatei
) ; // Datei schliessen printf ( "\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n <1> Zur\201 ck zum Hauptmen\201 " ) ; // falls Highscore Datei noch nicht vorhanden, erstelle diese
int auswahl = _getch( ) ; // zurück zum Menü Abfrage (falls 1 gedrückt wird)
if ( auswahl == 49 )
{
return ;
}
}
}
else
{
printf ( "\n \n Ung\201 ltige Eingabe!\n \n " ) ; Sleep( 2000 ) ; // falls eine Taste, die nicht zur Auswahl steht gedrückt wurde, Ungültige Eingabe anzeigen
highscoreAusgeben( ) ; // und highscoreAusgeben() Methode neu aufrufen
}
strcpy ( pfad
, zwischenPfad
) ; // ursprünglichen Pfad -> strcpy ( zwischenPfad
, "" ) ; // -> wiederherstellen }
// Highscore in Datei schreiben
void highscoreEinlesen( )
{
double high[ 20 ] ; // Array anlegen, um dort die ausgelesenen Highscores zwischenzuspeichern
high[ 0 ] = dif, high[ 1 ] = dif, high[ 2 ] = dif, high[ 3 ] = dif; // alle Highscores auf 1000 setzen, da sonst ein erster Vergleich nicht möglich wäre (high[i] = 0, dif = 20 -> high[i] < dif)
FILE* FDatei; // Zeiger auf Datei erstellen
FDatei
= fopen ( pfad
, "r" ) ; // Zeiger auf die Datei mit dem Pfad der in "pfad" gespeichert ist richten und diese zum lesen öffnen //-------------------------------------------------------- Zahlen einlesen --------------------------------------------------------------------------------------
char score[ 60 ] ;
char * sc; // char arrays, um eingelesene Highscores zwischenzuspeichern
int i = 0 ; // Zählvariable, um Array durchzulaufen
while ( fgets ( score
, 40 , FDatei
) != NULL
) // erste Zeile der Datei einlesen un solange fortfahren, bis das Dateiende erreicht ist {
sc
= strchr ( score
, ':' ) ; // nach Doppelpunkt in der jeweiligen Zeile suchen und Zeiger auf diesen setzen high
[ i
] = strtod ( sc
+ 1 , NULL
) ; // ab dem Doppelpunkt + 1 Zeichen dahinter alles einlesen und in double konvertieren. Endergebnis in double array sp. i++; // Zählvariable erhöhen
}
fclose ( FDatei
) ; // Datei schließen
//-------------------------------------------------------- Namen einlesen --------------------------------------------------------------------------------------
char * st1 = 0 ;
char * st2 = 0 ;
char * st3 = 0 ;
char * st4 = 0 ; // Zeiger erstellen für spätere Verarbeitung der eingelesenen Strings
char * st5 = 0 ;
char * st6 = 0 ;
char * st7 = 0 ;
char * st8 = 0 ;
char * st9 = 0 ;
char * ptr = ":" ; // Suchkriterium für strtok festlegen
FDatei
= fopen ( pfad
, "r" ) ; // Datei erneut öffnen und lesen
if ( fgets ( score
, 60 , FDatei
) != NULL
) // erste Zeile der Datei einlesen und fortfahren, falls in dieser etwas steht {
fclose ( FDatei
) ; // Datei schließen FDatei
= fopen ( pfad
, "r" ) ; // Datei erneut öffnen und lesen um wieder am Dateianfang zu starten
char platz1[ 60 ] = "" ; // char array zum zwischenspeichern des eingelesenen String
if ( fgets ( platz1
, 60 , FDatei
) != NULL
) // erste Zeile der Datei einlesen und fortfahren, falls in dieser etwas steht {
st1
= strchr ( platz1
, '.' ) ; // in dem eingelesenen String einen "." suchen. Highscores werden im folgenden Format abgespeichert: .Marcel's Zeit: 2s st1 += 1 ; // Zeiger um 1 nach rechts verschieben, um den Punkt nicht mit auszugeben
strtok ( st1
, ptr
) ; // Den Zeiger soweit verschieben, bis ein ":" gefunden wurde und diesen sowie alles dahinter vom String abtrennen }
char platz2[ 60 ] = "" ;
if ( fgets ( platz2
, 60 , FDatei
) != NULL
) // Dieses Verfahren wird auch für die folgenden Werte verwendet. Es sind maximal 10 Werte speicherbar. {
st2 += 1 ;
}
char platz3[ 60 ] = "" ;
if ( fgets ( platz3
, 60 , FDatei
) != NULL
) {
st3 += 1 ;
}
char platz4[ 60 ] = "" ;
if ( fgets ( platz4
, 60 , FDatei
) != NULL
) {
st4 += 1 ;
}
char platz5[ 60 ] = "" ;
if ( fgets ( platz5
, 60 , FDatei
) != NULL
) {
st5 += 1 ;
}
char platz6[ 60 ] = "" ;
if ( fgets ( platz6
, 60 , FDatei
) != NULL
) {
st6 += 1 ;
}
char platz7[ 60 ] = "" ;
if ( fgets ( platz7
, 60 , FDatei
) != NULL
) {
st7 += 1 ;
}
char platz8[ 60 ] = "" ;
if ( fgets ( platz8
, 60 , FDatei
) != NULL
) {
st8 += 1 ;
}
char platz9[ 60 ] = "" ;
if ( fgets ( platz9
, 60 , FDatei
) != NULL
) {
st9 += 1 ;
}
fclose ( FDatei
) ; // Datei schließen
FDatei
= fopen ( pfad
, "w+" ) ; // Datei öffnen und bearbeiten
if ( dif <= high[ 0 ] ) // falls dif (neue Highscore Zeit) besser als der aktuelle Platz 1 gespeichert in high[0] ist....
{
high[ 9 ] = high[ 8 ] ;
high[ 8 ] = high[ 7 ] ;
high[ 7 ] = high[ 6 ] ; // Dann verschiebe alle Highscores um einen Platz nach unten
high[ 6 ] = high[ 5 ] ;
high[ 5 ] = high[ 4 ] ;
high[ 4 ] = high[ 3 ] ;
high[ 3 ] = high[ 2 ] ;
high[ 2 ] = high[ 1 ] ;
high[ 1 ] = high[ 0 ] ;
high[ 0 ] = dif; // und setze den neuen Bestwert(dif) auf den Platz1
if ( name
!= NULL
) fprintf ( FDatei
, ".%s's Zeit: %.2fs\n " , name
, high
[ 0 ] ) ; // wenn ein Name(in der Methode spielen) eingegeben wurde, so wird dieser nun mit dem neuen Bestwert im Format if ( st1
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st1
, high
[ 1 ] ) ; // .Jemand's Zeit: 20.00s abgespeichert if ( st2
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st2
, high
[ 2 ] ) ; if ( st3
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st3
, high
[ 3 ] ) ; // nun alle anderen Werte in die Datei schreiben, solange diese ungleich Null sind. Wird der Wert Null erreicht, so if ( st4
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st4
, high
[ 4 ] ) ; // werden alle restlichen Schreibvorgänge übersprungen, da keine weiteren Highscores bisher aufgestellt wurden if ( st5
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st5
, high
[ 5 ] ) ; if ( st6
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st6
, high
[ 6 ] ) ; if ( st7
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st7
, high
[ 7 ] ) ; if ( st8
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st8
, high
[ 8 ] ) ; if ( st9
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs" , st9
, high
[ 9 ] ) ; }
else if ( dif > high[ 0 ] && dif <= high[ 1 ] )
{
high[ 9 ] = high[ 8 ] ;
high[ 8 ] = high[ 7 ] ;
high[ 7 ] = high[ 6 ] ;
high[ 6 ] = high[ 5 ] ;
high[ 5 ] = high[ 4 ] ;
high[ 4 ] = high[ 3 ] ;
high[ 3 ] = high[ 2 ] ;
high[ 2 ] = high[ 1 ] ;
high[ 1 ] = dif;
if ( st1
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st1
, high
[ 0 ] ) ; // Die folgenden Blöcke basieren auf dem selben Prinzip mit jedoch angepassten Bedingungen if ( name
!= NULL
) fprintf ( FDatei
, ".%s's Zeit: %.2fs\n " , name
, high
[ 1 ] ) ; if ( st2
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st2
, high
[ 2 ] ) ; if ( st3
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st3
, high
[ 3 ] ) ; if ( st4
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st4
, high
[ 4 ] ) ; if ( st5
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st5
, high
[ 5 ] ) ; if ( st6
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st6
, high
[ 6 ] ) ; if ( st7
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st7
, high
[ 7 ] ) ; if ( st8
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st8
, high
[ 8 ] ) ; if ( st9
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs" , st9
, high
[ 9 ] ) ; }
else if ( dif > high[ 0 ] && dif > high[ 1 ] && dif <= high[ 2 ] )
{
high[ 9 ] = high[ 8 ] ;
high[ 8 ] = high[ 7 ] ;
high[ 7 ] = high[ 6 ] ;
high[ 6 ] = high[ 5 ] ;
high[ 5 ] = high[ 4 ] ;
high[ 4 ] = high[ 3 ] ;
high[ 3 ] = high[ 2 ] ;
high[ 2 ] = dif;
if ( st1
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st1
, high
[ 0 ] ) ; if ( st2
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st2
, high
[ 1 ] ) ; if ( name
!= NULL
) fprintf ( FDatei
, ".%s's Zeit: %.2fs\n " , name
, high
[ 2 ] ) ; if ( st3
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st3
, high
[ 3 ] ) ; if ( st4
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st4
, high
[ 4 ] ) ; if ( st5
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st5
, high
[ 5 ] ) ; if ( st6
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st6
, high
[ 6 ] ) ; if ( st7
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st7
, high
[ 7 ] ) ; if ( st8
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st8
, high
[ 8 ] ) ; if ( st9
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs" , st9
, high
[ 9 ] ) ; }
else if ( dif > high[ 0 ] && dif >= high[ 1 ] && dif > high[ 2 ] && dif <= high[ 3 ] )
{
high[ 9 ] = high[ 8 ] ;
high[ 8 ] = high[ 7 ] ;
high[ 7 ] = high[ 6 ] ;
high[ 6 ] = high[ 5 ] ;
high[ 5 ] = high[ 4 ] ;
high[ 4 ] = high[ 3 ] ;
high[ 3 ] = dif;
if ( st1
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st1
, high
[ 0 ] ) ; if ( st2
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st2
, high
[ 1 ] ) ; if ( st3
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st3
, high
[ 2 ] ) ; if ( name
!= NULL
) fprintf ( FDatei
, ".%s's Zeit: %.2fs\n " , name
, high
[ 3 ] ) ; if ( st4
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st4
, high
[ 4 ] ) ; if ( st5
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st5
, high
[ 5 ] ) ; if ( st6
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st6
, high
[ 6 ] ) ; if ( st7
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st7
, high
[ 7 ] ) ; if ( st8
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st8
, high
[ 8 ] ) ; if ( st9
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs" , st9
, high
[ 9 ] ) ; }
else if ( dif > high[ 3 ] && dif <= high[ 4 ] )
{
high[ 9 ] = high[ 8 ] ;
high[ 8 ] = high[ 7 ] ;
high[ 7 ] = high[ 6 ] ;
high[ 6 ] = high[ 5 ] ;
high[ 5 ] = high[ 4 ] ;
high[ 4 ] = dif;
if ( st1
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st1
, high
[ 0 ] ) ; if ( st2
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st2
, high
[ 1 ] ) ; if ( st3
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st3
, high
[ 2 ] ) ; if ( st4
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st4
, high
[ 3 ] ) ; if ( name
!= NULL
) fprintf ( FDatei
, ".%s's Zeit: %.2fs\n " , name
, high
[ 4 ] ) ; if ( st5
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st5
, high
[ 5 ] ) ; if ( st6
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st6
, high
[ 6 ] ) ; if ( st7
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st7
, high
[ 7 ] ) ; if ( st8
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st8
, high
[ 8 ] ) ; if ( st9
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs" , st9
, high
[ 9 ] ) ;
}
else if ( dif > high[ 4 ] && dif <= high[ 5 ] )
{
high[ 9 ] = high[ 8 ] ;
high[ 8 ] = high[ 7 ] ;
high[ 7 ] = high[ 6 ] ;
high[ 6 ] = high[ 5 ] ;
high[ 5 ] = dif;
if ( st1
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st1
, high
[ 0 ] ) ; if ( st2
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st2
, high
[ 1 ] ) ; if ( st3
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st3
, high
[ 2 ] ) ; if ( st4
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st4
, high
[ 3 ] ) ; if ( st5
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st5
, high
[ 4 ] ) ; if ( name
!= NULL
) fprintf ( FDatei
, ".%s's Zeit: %.2fs\n " , name
, high
[ 5 ] ) ; if ( st6
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st6
, high
[ 6 ] ) ; if ( st7
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st7
, high
[ 7 ] ) ; if ( st8
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st8
, high
[ 8 ] ) ; if ( st9
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs" , st9
, high
[ 9 ] ) ; }
else if ( dif > high[ 5 ] && dif <= high[ 6 ] )
{
high[ 9 ] = high[ 8 ] ;
high[ 8 ] = high[ 7 ] ;
high[ 7 ] = high[ 6 ] ;
high[ 6 ] = dif;
if ( st1
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st1
, high
[ 0 ] ) ; if ( st2
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st2
, high
[ 1 ] ) ; if ( st3
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st3
, high
[ 2 ] ) ; if ( st4
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st4
, high
[ 3 ] ) ; if ( st5
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st5
, high
[ 4 ] ) ; if ( st6
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st6
, high
[ 5 ] ) ; if ( name
!= NULL
) fprintf ( FDatei
, ".%s's Zeit: %.2fs\n " , name
, high
[ 6 ] ) ; if ( st7
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st7
, high
[ 7 ] ) ; if ( st8
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st8
, high
[ 8 ] ) ; if ( st9
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs" , st9
, high
[ 9 ] ) ; }
else if ( dif > high[ 6 ] && dif <= high[ 7 ] )
{
high[ 9 ] = high[ 8 ] ;
high[ 8 ] = high[ 7 ] ;
high[ 7 ] = dif;
if ( st1
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st1
, high
[ 0 ] ) ; if ( st2
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st2
, high
[ 1 ] ) ; if ( st3
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st3
, high
[ 2 ] ) ; if ( st4
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st4
, high
[ 3 ] ) ; if ( st5
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st5
, high
[ 4 ] ) ; if ( st6
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st6
, high
[ 5 ] ) ; if ( st7
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st7
, high
[ 6 ] ) ; if ( name
!= NULL
) fprintf ( FDatei
, ".%s's Zeit: %.2fs\n " , name
, high
[ 7 ] ) ; if ( st8
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st8
, high
[ 8 ] ) ; if ( st9
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs" , st9
, high
[ 9 ] ) ; }
else if ( dif > high[ 7 ] && dif <= high[ 8 ] )
{
high[ 9 ] = high[ 8 ] ;
high[ 8 ] = dif;
if ( st1
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st1
, high
[ 0 ] ) ; if ( st2
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st2
, high
[ 1 ] ) ; if ( st3
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st3
, high
[ 2 ] ) ; if ( st4
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st4
, high
[ 3 ] ) ; if ( st5
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st5
, high
[ 4 ] ) ; if ( st6
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st6
, high
[ 5 ] ) ; if ( st7
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st7
, high
[ 6 ] ) ; if ( st8
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st8
, high
[ 7 ] ) ; if ( name
!= NULL
) fprintf ( FDatei
, ".%s's Zeit: %.2fs\n " , name
, high
[ 8 ] ) ; if ( st9
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs" , st9
, high
[ 9 ] ) ; }
else if ( dif > high[ 8 ] && dif <= high[ 9 ] )
{
high[ 9 ] = dif;
if ( st1
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st1
, high
[ 0 ] ) ; if ( st2
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st2
, high
[ 1 ] ) ; if ( st3
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st3
, high
[ 2 ] ) ; if ( st4
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st4
, high
[ 3 ] ) ; if ( st5
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st5
, high
[ 4 ] ) ; if ( st6
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st6
, high
[ 5 ] ) ; if ( st7
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st7
, high
[ 6 ] ) ; if ( st8
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st8
, high
[ 7 ] ) ; if ( st9
!= NULL
) fprintf ( FDatei
, ".%s: %.2fs\n " , st9
, high
[ 8 ] ) ; if ( name
!= NULL
) fprintf ( FDatei
, ".%s's Zeit: %.2fs" , name
, high
[ 9 ] ) ; }
fclose ( FDatei
) ; // Datei schließen }
// Vorgehen nach Spielende abfragen
void spielende( )
{
printf ( "------------------------------------\n " ) ; printf ( "| %s \t \t |\n |----------------------------------|" , spielergebnis
, dif
) ; // Tabelle mit Spielergebnissen anzeigen printf ( "\n | Endstand: Du <%i> Computer <%i> |\n " , yScore
, cScore
) ; printf ( "------------------------------------\n \n " ) ; printf ( "W\204 hlen sie eine M\224 glichkeit!\n \n " ) ; printf ( "<1> Zur\201 ck zum Hauptmen\201 \n " ) ; // Menü nach Spielende darstellen printf ( "<2> Highscore anzeigen\n " ) ; COORD p;
p.X = ( int ) ( 20 ) ;
p.Y = ( int ) ( 1 ) ;
SetConsoleCursorPosition( hOut, p) ;
int auswahl = _getch( ) ;
if ( auswahl == 49 ) // falls 1 gedrückt wird, zurück zum Hauptmenü
{
mainLoop = 0 ;
return ;
}
else if ( auswahl == 50 ) // falls 2 gedrückt wird, highscoreAusgeben() Methode aufrufen
{
highscoreAusgeben( ) ;
}
else
{
printf ( "\n \n Ung\201 ltige Eingabe!\n \n " ) ; Sleep( 2000 ) ; // falls eine Taste, die nicht zur Auswahl steht gedrückt wurde, Ungültige Eingabe anzeigen
system ( "cls" ) ; // und zurück zum Hautpmenü spielende( ) ;
}
}
// Spiel ausführen
void spielen( )
{
setWindowSize( 55 , 39 ) ; // Konsolenfenster auf passende Größe für das Spiel setzen
// Oberfläche zeichnen
SetConsoleTextAttribute( hOut, 15 ) ; // Schriftfarbe auf weiß setzen
for ( int i = 0 ; i < width - 1 ; ++ i)
{
printf ( "-" ) ; // obere Spielfeldbegrenzung zeichnen }
for ( int i = 0 ; i < height - 1 ; ++ i)
{
printf ( "\n |" ) ; // seitlich rechte Spielfeldbegrenzung zeichnen
for ( int i = 0 ; i < width - 3 ; ++ i)
printf ( "|" ) ; // linke seitliche Spielfeldbegrenzung zeichnen }
for ( int i = 0 ; i < width - 1 ; ++ i)
{
printf ( "-" ) ; // untere Spielfeldbegrenzung zeichnen }
if ( spielmodus
== 0 ) printf ( "\n | Your score: 0 | Computer score: 0 ||| Speed: 0 |\n " ) ; // Statistik unter der unteren Spielfeldbegrenzung zeichnen if ( spielmodus
== 1 ) printf ( "\n | Spi. 1 score: 0 | Spi. 2 score: 0 ||| Speed: 0 |\n " ) ;
for ( int i = 0 ; i < width - 1 ; ++ i)
{
printf ( "-" ) ; // unter der Statistik noch eine Linie zeichnen }
// Ende Oberfläche zeichnen
// Spieler und Ball erstellen
spieler you, you2, comp; ball b; // Objekte Spieler, Spieler 2, Computer und Ball der Anfangs definierten struct erstellen
spieler_( & you, width / 2 , height - 2 , 4 ) ; // Anfangswerte für Spieler an die spieler_() Methode übergeben
spieler_( & you2, width / 2 , 2 , 4 ) ; // Anfangswerte für Spieler2 an die spieler_() Methode übergeben
spieler_( & comp, width / 2 , 2 , 4 ) ; // Anfangswerte für den Computer an die spieler_() Methode übergeben
ball_( & b, width / 2 - 1 , height / 2 ) ; // Anfangswerte für den Ball an die ball_() Methode übergeben
b.
vx = ( float ) ( rand ( ) % 3 ) - 1.5f ; // Ball in zufällige Richtung zum Spieler schicken b.vy = 1 ;
comp.vx = 0 ;
// Benötigte Variablen initialisieren
int gestartet = 0 ; // gestartet auf "nein" setzen (0 = nein, 1 = ja)
int you_score = 0 , comp_score = 0 , you2_score = 0 ; // Statistik (Punkte) auf Standard setzen
const int delay = 50 ; // Konstanten Wert für die Spielverzögerung setzen
float speed = 0.0f ; // Statistik der Ballgeschwindigkeit auf Standart setzen
char schwierigkeit1[ 20 ] = "Amateur" ;
char schwierigkeit2[ 20 ] = "Machbar" ;
char schwierigkeit3[ 20 ] = "Veteran" ; // Strings zum Vergleich der Schwierigkeiten initialisieren
char schwierigkeit4[ 20 ] = "Nervt\224 tend" ;
time ( & start
) ; // Stoppuhr für Highscore starten
while ( 1 )
{
if ( gestartet == 1 ) // Spiel gestartet?
{
if ( GetAsyncKeyState( links) ) // falls ja, fragen ob die Taste die in "links" gespeichert ist, gedrückt wurde
{
if ( strcmp ( schwierigkeit
, schwierigkeit1
) == 0 ) // falls ja, schwierigkeitsgrad vergleichen, um die passende Bewegungsgeschwindigkeit der Pads zu wählen {
you.x -= 2 , 5 ;
}
else if ( strcmp ( schwierigkeit
, schwierigkeit2
) == 0 ) // dies für alle Schwierigkeitsgrade durchspielen {
you.x -= 2 ;
}
else if ( strcmp ( schwierigkeit
, schwierigkeit3
) == 0 ) {
you.x -= 2 ;
}
else if ( strcmp ( schwierigkeit
, schwierigkeit4
) == 0 ) {
you.x -= 2 , 5 ;
}
}
else if ( GetAsyncKeyState( rechts) ) // falls ja, fragen ob die Taste die in "rechts" gespeichert ist, gedrückt wurde
{
if ( strcmp ( schwierigkeit
, schwierigkeit1
) == 0 ) // falls ja, schwierigkeitsgrad vergleichen, um die passende Bewegungsgeschwindigkeit der Pads zu wählen {
you.x += 2 , 5 ;
}
else if ( strcmp ( schwierigkeit
, schwierigkeit2
) == 0 ) {
you.x += 2 ;
}
else if ( strcmp ( schwierigkeit
, schwierigkeit3
) == 0 ) // dies für alle Schwierigkeitsgrade durchspielen {
you.x += 2 ;
}
else if ( strcmp ( schwierigkeit
, schwierigkeit4
) == 0 ) {
you.x += 5 ;
}
}
else if ( GetAsyncKeyState( beenden) ) // falls ja, fragen ob die Taste die in "beenden" gespeichert ist, gedrückt wurde
{
COORD p;
p.X = ( int ) ( width / 2 - 16 ) ;
p.Y = ( int ) ( height / 1.8f ) ;
SetConsoleCursorPosition( hOut, p) ;
printf ( "Spiel wirklich beenden?" ) ; p.X = ( int ) ( width / 2 - 16 ) ;
p.Y = ( int ) ( height / 1.6f ) ;
SetConsoleCursorPosition( hOut, p) ; // Abfrage, ob Spiel fortsetzen oder Beenden
printf ( "<1> Weiterspielen\n " ) ; // wird druch das drücken der q Taste p.X = ( int ) ( width / 2 - 16 ) ; // in die Konsole geschrieben
p.Y = ( int ) ( height / 1.55f ) ;
SetConsoleCursorPosition( hOut, p) ;
printf ( "<2> Spiel beenden\n \n " ) ; p.X = ( int ) ( width / 2 - 17 ) ;
p.Y = ( int ) ( height / 1.35f ) ;
SetConsoleCursorPosition( hOut, p) ;
char c;
while ( ( c = _getch( ) ) != EOF && c != 'q' ) ; // Puffer automatisch im Hintergrund leeren (Zeiger im Puffer bis zum ersten Auftreten eines "q" verschieben)
int auswahl = _getch( ) ; // einlesen, ob fortsetzen oder beenden ausgewählt wurde und solange Spiel anhalten, bis Eingabe getätigt wurde
if ( auswahl == 49 ) // falls fortsetzen ausgewählt ->
{
p.X = ( int ) ( width / 2 - 16 ) ;
p.Y = ( int ) ( height / 1.8f ) ;
SetConsoleCursorPosition( hOut, p) ;
p.X = ( int ) ( width / 2 - 16 ) ;
p.Y = ( int ) ( height / 1.6f ) ;
SetConsoleCursorPosition( hOut, p) ; // -> zu passenden Positionen springen und den Dialog wieder entfernen -> Spiel wird fortgesetzt
p.X = ( int ) ( width / 2 - 16 ) ;
p.Y = ( int ) ( height / 1.55f ) ;
SetConsoleCursorPosition( hOut, p) ;
}
else // falls beenden ausgewählt, aus der Spielschleife springen
{
time ( & endet
) ; // Stoppuhr stoppen um verfälschung der Zeit zu umgehen break ;
}
}
if ( GetAsyncKeyState( links2) ) // falls Spielmodus = Mensch vs Mensch, ist das gegnerische Pad bewegbar. Abfrage ob Taste die in "links2"
{ // gespeichert ist gedrückt wurde
if ( strcmp ( schwierigkeit
, schwierigkeit1
) == 0 ) {
you2.x -= 2 , 5 ;
}
else if ( strcmp ( schwierigkeit
, schwierigkeit2
) == 0 ) // falls ja, schwierigkeitsgrad vergleichen, um die passende Bewegungsgeschwindigkeit der Pads zu wählen {
you2.x -= 2 ;
}
else if ( strcmp ( schwierigkeit
, schwierigkeit3
) == 0 ) // dies für alle Schwierigkeitsgrade durchspielen {
you2.x -= 2 ;
}
else if ( strcmp ( schwierigkeit
, schwierigkeit4
) == 0 ) {
you2.x -= 2 , 5 ;
}
}
else if ( GetAsyncKeyState( rechts2) ) // fragen ob die Taste die in "rechts2" gespeichert ist, gedrückt wurde (Mensch vs Mensch)
{
if ( strcmp ( schwierigkeit
, schwierigkeit1
) == 0 ) // falls ja, schwierigkeitsgrad vergleichen, um die passende Bewegungsgeschwindigkeit der Pads zu wählen {
you2.x += 2 , 5 ;
}
else if ( strcmp ( schwierigkeit
, schwierigkeit2
) == 0 ) {
you2.x += 2 ;
}
else if ( strcmp ( schwierigkeit
, schwierigkeit3
) == 0 ) // dies für alle Schwierigkeitsgrade durchspielen {
you2.x += 2 ;
}
else if ( strcmp ( schwierigkeit
, schwierigkeit4
) == 0 ) {
you2.x += 5 ;
}
}
// Ballgeschwindigkeit für Statistik berechnen
float x
= pow ( b.
vx , 2 ) ; // y - Geschwindigkeit des Balles quadrieren float y
= pow ( b.
vy , 2 ) ; // x - Geschwindikeit des Balles quadrieren (Satz des Pythagoras) speed = x + y; // beide Werte addieren
speed
= sqrt ( speed
) ; // Wurzel aus dem neuen in "speed" gespeicherten Wert ziehen COORD p;
p.X = ( int ) ( 47 ) ; // Koordinaten für die Geschwindigkeitsanzeige des Balls rechts unten in der Konsole setzen
p.Y = ( int ) ( 37 ) ;
SetConsoleCursorPosition( hOut, p) ; // Cursor dorthin bewegen
printf ( "%.2f" , speed
) ; // Aktuelle Ballgeschwindigkeit (in speed gespeichert) dort mit zwei Nachkommastellen ausgeben
// KI zum Ball führen
if ( spielmodus == 0 ) // falls Spielmodus = Mensch vs Computer
{
comp.vx -= ( float ) ( comp.x - b.x ) / kiReaktion; // Computer x - Position - Ball x - Position, um zu errechnen, wo der Computer sich hinbewegen muss geteilt durch einen Modifikator,
comp.vx *= 0.83f ; // der die KI als weitere Schwierigkeit langsamer oder schneller reagieren lassen kann ||| Computer x - Geschwindigkeit reduzieren
}
// KI Geschwindigeit in Abhängigkeit der Ballgeschwindigkeit anpassen
comp.x += comp.vx ;
// Bewegungsgrenzen setzen Spieler 1
if ( you.x < you.size + 1 ) // falls Spieler1 x-Position kleiner als Padgröße + 1 (linke Außenseite erreicht)
{
you.x = ( float ) ( you.size + 1 ) ; // dann Spieler auf dieser x - Position halten und nicht überqueren lassen (linke Seite)
}
else if ( you.x > width - you.size - 2 - modifikator) // falls Spieler1 x - Position größer als Konsolenbreite - Padgröße - 2(wegen Spielbegrenzungen) - modifikator, der die
{ // Padgröße den Grenzen anpasst
you.x = ( float ) ( width - you.size - 2 - modifikator) ; // dann Spieler auf dieser x - Position halten und nicht überqueren lassen (rechte Seite)
}
// Bewegungsgrenzen setzen Spieler 2
if ( you2.x < you2.size + 1 ) // falls Spieler1 x-Position kleiner als Padgröße + 1 (linke Außenseite erreicht)
{
you2.x = ( float ) ( you2.size + 1 ) ; // dann Spieler2 auf dieser x - Position halten und nicht überqueren lassen (linke Seite)
}
else if ( you2.x > width - you2.size - 2 - modifikator) // falls Spieler2 x - Position größer als Konsolenbreite - Padgröße - 2(wegen Spielbegrenzungen) - modifikator, der die
{ // Padgröße den Grenzen anpasst
you2.x = ( float ) ( width - you2.size - 2 - modifikator) ; // dann Spieler2 auf dieser x - Position halten und nicht überqueren lassen (rechte Seite)
}
// KI Bewegungsgrenze setzen
if ( comp.x < comp.size + 1 ) // falls Spieler1 x-Position kleiner als Padgröße + 1 (linke Außenseite erreicht)
{
comp.x = ( float ) ( comp.size + 1 ) ; // dann Computer auf dieser x - Position halten und nicht überqueren lassen (linke Seite)
}
else if ( comp.x > width - comp.size - 2 - modifikator) // falls Computer x - Position größer als Konsolenbreite - Padgröße - 2(wegen Spielbegrenzungen) - modifikator, der die
{ // Padgröße den Grenzen anpasst
comp.x = ( float ) ( width - comp.size - 2 - modifikator) ; // dann Computer auf dieser x - Position halten und nicht überqueren lassen (rechte Seite)
}
// Ball Höchstgeschwindigkeit einhalten
if ( b.vx < - maxSpeed) // falls Ball x - Geschwindigkeit in diesem Fall "unter" der maximal erlaubten Geschwindigkeit liegt
{
b.vx = - maxSpeed; // Ball x - Geschwindigkeit wieder auf "minimal" erlaubten Wert zurücksetzen
}
else if ( b.vx > maxSpeed) // falls Ball x - Geschwindigkeit über der maximal erlaubten Geschwindigkeit liegt
{
b.vx = maxSpeed; // Ball x - Geschwindigkeit wieder auf maximal erlaubten Wert zurücksetzen
}
// Dem Ball an der aktuellen Position Geschwindigkeit zuführen
b.x += b.vx ; // die aktuelle x - Position des Balles um den aktuellen Wert der x - Ballgeschwindigkeit verschieben
b.y += b.vy ; // die aktuelle y - Position des Balles um den aktuellen Wert der y - Ballgeschwindigkeit verschieben
// Hat der Ball den Spieler getroffen?
if ( b.y >= you.y - 1 && b.y <= you.y + 1 ) // ist die y - Position des Balls 1 über dem Pad und ist die y - Position des Balls nicht 1 unter dem Pad (da sonst Punkt geben würde)
{
if ( b.x > you.x - you.size && b.x < you.x + you.size ) // ist die x - Position des Balls kleiner bzw. größer als die x - Position des Pads - und + die Padgröße, ist das Pad getroffen
{
b.vy *= - 1 ; // Ball y-Richtung umkehren
b.vx += ( float ) ( b.x - you.x ) / 3 ; // Ball x - Geschwindigkeit bei auftreffen auf das Pad - die Pad x - Position rechnen, um eine resultierende Richtung zu erhalten
b.y = you.y - 1 ; // Ball auf Position direkt über dem Pad setzen, um ein hindurchfallen durch das Pad zu verhindern
}
}
// Hat der Ball den Spieler2 getroffen?
if ( b.y <= you2.y + 1 && b.y >= you2.y - 1 ) // ist die y - Position des Balls 1 unter dem Pad und ist die y - Position des Balls nicht 1 über dem Pad (da sonst Punkt geben würde)
{
if ( b.x > you2.x - you2.size && b.x < you2.x + you2.size ) // ist die x - Position des Balls kleiner bzw. größer als die x - Position des Pads - und + die Padgröße, ist das Pad getroffen
{
b.vy *= - 1 ; // Ball y-Richtung umkehren
b.vx += ( float ) ( b.x - you2.x ) / 3 ; // Ball x - Geschwindigkeit bei auftreffen auf das Pad - die Pad x - Position rechnen, um eine resultierende Richtung zu erhalten
b.y = you2.y + 1 ; // Ball auf Position direkt unter dem Pad setzen, um ein hindurchfallen durch das Pad zu verhindern
}
}
// Hat der Ball die KI getroffen?
if ( b.y <= comp.y + 1 && b.y >= comp.y - 1 ) // ist die y - Position des Balls 1 unter dem Pad und ist die y - Position des Balls nicht 1 über dem Pad (da sonst Punkt geben würde)
{
if ( b.x > comp.x - comp.size && b.x < comp.x + comp.size ) // ist die x - Position des Balls kleiner bzw. größer als die x - Position des Pads - und + die Padgröße, ist das Pad getroffen
{
b.vy *= - 1 ; // Ball y-Richtung umkehren
b.vx += ( float ) ( b.x - comp.x ) / 3 ; // Ball x - Geschwindigkeit bei auftreffen auf das Pad - die Pad x - Position rechnen, um eine resultierende Richtung zu erhalten
b.y = comp.y + 1 ; // Ball auf Position direkt unter dem Pad setzen, um ein hindurchfallen durch das Pad zu verhindern
}
}
// Hat der Ball die Grenzen überschritten?(Punkt bekommen)
if ( b.y >= height && spielmodus == 0 ) // falls y-Wert 55 vom Ball überschritten und Spielmodus = Mensch vs Computer
{
gestartet = 0 ; // Spiel gestartet? auf "nein" setzen, um auf Leertaste gedrückt? zu warten
comp_score++; // Computer score um 1 erhöhen
cScore = comp_score; // Computer score in glabaer Variable cScore für weitere Verarbeitung speichern
reset( & you, & you2, & comp, & b, you_score, you2_score, comp_score ) ;
}
else if ( b.y >= height && spielmodus == 1 ) // falls y-Wert 55 vom Ball überschritten und Spielmodus = Mensch vs Mensch
{
gestartet = 0 ; // Spiel gestartet? auf "nein" setzen, um auf Leertaste gedrückt? zu warten
you2_score++; // Spieler 2 score um 1 erhöhen
y2Score = you2_score; // Spieler 2 score in glabaer Variable y2Score für weitere Verarbeitung speichern
reset( & you, & you2, & comp, & b, you_score, you2_score, comp_score ) ;
}
else if ( b.y <= 0 ) // falls y-Wert 0 vom Ball überschritten
{
gestartet = 0 ; // Spiel gestartet? auf "nein" setzen, um auf Leertaste gedrückt? zu warten
you_score++; // Spieler 1 score um 1 erhöhen
yScore = you_score; // Spieler 1 score in glabaer Variable yScore für weitere Verarbeitung speichern
reset( & you, & you2, & comp, & b, you_score, you2_score, comp_score ) ;
}
if ( b.x <= 1 ) // falls der Ball die linke Außenwand trifft
{
b.vx *= - 1 ; // x - Richtung/Geschwindigkeit des Ball invertieren
b.x = 1.0f ; // x - Position des Balls zurück auf 1 setzen, damit er nicht die Grenzen überquert
}
else if ( b.x >= width - 3 ) // falls der Ball die rechte Außenwand trifft
{
b.vx *= - 1 ; // x - Richtung/Geschwindigkeit des Ball invertieren
b.x = ( float ) ( width - 3 ) ; // x - Position des Balls zurück auf die Konsolenbreite - 3 setzen, damit er nicht die Grenzen überquert
}
}
else if ( you_score == siegPunkte || you2_score == siegPunkte)
{
dif = 1000 ;
system ( "cls" ) ; // Konsole leeren time ( & endet
) ; // Stoppuhr stoppen dif
= difftime ( endet
, start
) ; // Highscore Zeit berechnen (ende - anfang) strcpy ( spielergebnis
, "" ) ; // spielergebnis string leeren strcat ( spielergebnis
, "Gewonnen!!!" ) ; // Endergebnis speichern für spätere Ausgabe printf ( "\n \n \n \n \n \n \n \n \t \t Gewonnen!!! :)" ) ; // Siegmeldung ausgeben printf ( "\n \n \n \n ...um fortzufahren bitte Enter dr\201 cken..." ) ; char c;
while ( ( c = _getch( ) ) != EOF && c != 13 ) ; // Puffer automatisch im Hintergrund leeren
//-------------------------------------------------------- Namen einlesen -------------------------------------------------------------------------------------------
printf ( "Bitte geben sie ihren Namen ein: " ) ; // Benutzer zur Namenseingabe aufforden und diesen in "name" abspeichern
//-------------------------------------------------------- Highscores einlesen --------------------------------------------------------------------------------------
FILE * FDatei; // Zeiger auf eine Datei erstellen
FDatei
= fopen ( pfad
, "r" ) ; // Zeiger auf die Datei, die in "pfad" angegeben ist und diese zum lesen öffnen if ( ! FDatei) // falls die Datei noch nicht existiert ->
{
FDatei
= fopen ( pfad
, "w" ) ; // -> diese erstellen fclose ( FDatei
) ; // Datei schließen }
highscoreEinlesen( ) ; // in die Methode highscoreEinlesen() springen, um den neuen Highscore abzuspeichern
mainLoop = 1 ; // über main Funktion zu spielende() springen
break ;
}
else if ( comp_score == siegPunkte)
{
system ( "cls" ) ; // Konsole leeren time ( & endet
) ; // Stoppuhr stoppen dif
= difftime ( endet
, start
) ; // Highscore Zeit berechnen (ende - anfang) strcpy ( spielergebnis
, "" ) ; // spielergebnis string leeren strcat ( spielergebnis
, "Verloren!!!" ) ; // Endergebnis speichern für spätere Ausgabe printf ( "\n \n \n \n \n \n \n \n \t \t Verloren!!! :(" ) ; // Niederlage Meldung ausgeben printf ( "\n \n \n \n ...um fortzufahren bitte Enter dr\201 cken..." ) ; char c;
while ( ( c = _getch( ) ) != EOF && c != 13 ) ; // Puffer automatisch im Hintergrund leeren und warten bis Enter gedrückt wurde
mainLoop = 1 ; // über main Funktion zu spielende() springen
break ;
}
else
{
// Startbedingungüberprüfen (Leertaste gedrückt? bzw. Spiel gestartet?)
COORD p;
p.X = ( int ) ( width / 2 - 16 ) ;
p.Y = ( int ) ( height / 1.5f ) ;
SetConsoleCursorPosition( hOut, p) ;
printf ( "Press the space bar to start..." ) ; // Cursor in die Mitte des Bildschirms setzen und jene Meldung zeigen
if ( GetAsyncKeyState( VK_SPACE) ) // Leertaste gedrückt?
{
COORD p;
p.X = ( int ) ( width / 2 - 16 ) ;
p.Y = ( int ) ( height / 1.5f ) ;
SetConsoleCursorPosition( hOut, p) ; // falls ja, entferne Meldung wieder
gestartet = 1 ; // Status auf Spiel "gestartet" setzen, um in anderen Verlauf der while Schleife zu gelangen
}
}
// Alles zeichnen
draw( & you) ; // Spieler 1 mit aktuellen Werten zeichnen
if ( spielmodus == 1 ) draw( & you2) ; // falls Spielmodus = Mensch vs Mensch, Spieler 2 mit aktuellen Werten zeichnen
if ( spielmodus == 0 ) draw( & comp) ; // falls Spielmodus = Mensch vs Computer, Computer mit aktuellen Werten zeichnen
drawball( & b) ; // Ball mit aktuellen Werten zeichnen
// Verzögern
Sleep( delay) ; // nach jedem Durchgang 50ms warten, um übermäßiges flackern zu verhindern und das Spiel in einer benutzerfreundlichen
} // Geschwindigkeit ablaufen zu lassen
}
// Konfiguration der Tastenbelegung
void steuerung( )
{
printf ( "===========================================================================\n " ) ; printf ( "== Bitte w\204 hlen sie die Taste die sie ver\204 ndern m\224 chten und dr\201 cken sie ==\n " ) ; printf ( "== anschlie\341 end die Taste die sie zuweisen wollen! ==\n " ) ; // Menü darstellen printf ( "===========================================================================\n \n " ) ;
printf ( "Beachte: Kleinbuchstaben m\201 ssen als Gro\341 buchstaben angegeben werden!\n " ) ; printf ( "\t Die Tasten von Spieler 2 k\224 nnen nicht ver\204 ndert werden!\n \n \n " ) ;
printf ( "<1> Links\t \t \t Aktuelle Taste: %c\n " , links
) ; printf ( "<2> Rechts\t \t \t Aktuelle Taste: %c\n " , rechts
) ; // aktuelle Tastenbelegung für Spieler1 anzeigen printf ( "<3> Beenden\t \t \t Aktuelle Taste: %c\n \n " , beenden
) ;
printf ( "--> Links\t \t \t Aktuelle Taste: Pfeiltaste links\n " ) ; printf ( "--> Rechts\t \t \t Aktuelle Taste: Pfeiltaste rechts\n \n \n " ) ; // aktuelle Tastenbelegung für Spieler2 anzeigen
printf ( "<4> Zur\201 ck zum Hauptmen\201 " ) ;
int auswahl = _getch( ) ; // Menüauswahl einlesen und in "auswahl" speichern
if ( auswahl == 49 ) // falls 1 gedrückt...
{
links = _getch( ) ;
system ( "cls" ) ; // dann auf erneute Eingabe warten und diesen als neuen Wert für die Taste links setzen steuerung( ) ; // Konsole leeren und steuerung() erneut aufrufen, um das Menü zu aktualisieren
}
else if ( auswahl == 50 ) // falls 2 gedrückt...
{
rechts = _getch( ) ; // dann auf erneute Eingabe warten und diesen als neuen Wert für die Taste rechts setzen
system ( "cls" ) ; // Konsole leeren und steuerung() erneut aufrufen, um das Menü zu aktualisieren steuerung( ) ;
}
else if ( auswahl == 51 ) // falls 3 gedrückt...
{
beenden = _getch( ) ; // dann auf erneute Eingabe warten und diesen als neuen Wert für die Taste beenden setzen
system ( "cls" ) ; // Konsole leeren und steuerung() erneut aufrufen, um das Menü zu aktualisieren steuerung( ) ;
}
else if ( auswahl == 52 ) // falls 4 gedrückt...
{
system ( "cls" ) ; // ...zurück zum Hauptmenü return ;
}
else
{
printf ( "\n \n Ung\201 ltige Eingabe!\n \n " ) ; Sleep( 2000 ) ; // falls eine Taste, die nicht zur Auswahl steht gedrückt wurde, Ungültige Eingabe anzeigen
system ( "cls" ) ; // und zurück zum Hautpmenü steuerung( ) ;
}
}
// Schwierigkeitsgrad, Ballgeschwindigkeit
// einstellen, alles zurücksetzen
void einstellungen( )
{
printf ( "Bitte w\204 hlen sie eine Einstellung die sie ver\204 ndern m\224 chten!\n \n " ) ; printf ( "<1> Spielmodus / Spieleranzahl\t \t Aktueller Modus: %s\n " , modus
) ; printf ( "<2> Schwieriegkeitsgrad \204 ndern\t \t Aktuelle Schwierigkeit: %s\n " , schwierigkeit
) ; // Menü mit aktuellen Einstellungen anzeigen printf ( "<3> Maximale Ballgeschwindigkeit\t Aktuelle Geschwindigkeit: %.2f\n " , maxSpeed
) ; printf ( "<4> Anzahl der Punkte bis zum Sieg\t Aktuelle Siegpunkte: %i\n " , siegPunkte
) ; printf ( "<5> Alle Einstellungen zur\201 cksetzen\n " ) ; printf ( "<6> Highscore zur\201 cksetzten\n " ) ; printf ( "<7> Zur\201 ck zum Hauptmen\201 \n \n " ) ;
int auswahl = _getch( ) ; // Menüauswahl einlesen und in "auswahl" speichern
if ( auswahl == 49 ) // Eingabe auswerten (falls 1 gedrückt)
{
printf ( "W\204 hlen sie ihren bevorzugten Spielmodus!\n \n " ) ; printf ( "<1> Mensch vs Computer\n " ) ; // dann Spielmodus Menü darstellen printf ( "<2> Mensch vs Mensch\n " ) ;
char zwischensp[ 60 ] ; // char array, um pfad für Highscore.txt während Mehrspieler zwischenzuspeichern
int auswahl = _getch( ) ; // Menüauswahl einlesen und in "auswahl" speichern
strcpy ( modus
, "" ) ; // char array "modus" leeren
if ( auswahl == 49 )
{
spielmodus = 0 ;
strcat ( modus
, "Mensch vs Computer" ) ; // Anzeige im Einstellungsmenü aktualisieren (alter String wird gelöscht und neuer angehängt) strcpy ( pfad
, zwischensp
) ; // Pfad für Highscoredatei aktualisieren return ; // zwischengespeicherten Pfad (in "zwischensp") wieder in "pfad" kopieren
}
else if ( auswahl == 50 )
{
spielmodus = 1 ;
strcat ( modus
, "Mensch vs Mensch" ) ; // Anzeige im Einstellungsmenü aktualisieren (alter String wird gelöscht und neuer angehängt) strcpy ( pfad
, "C:\\ Mehrspieler.txt" ) ; // Pfad für Highscoredatei aktualisieren return ;
}
}
else if ( auswahl == 50 ) // Eingabe auswerten
{
printf ( "W\204 hlen sie ihren bevorzugten Schwierigkeitsgrad!\n \n " ) ; printf ( "<1> Amateur\n " ) ; // Schwierigkeitsgrad Menü öffnen printf ( "<4> Nervt\224 tend\n " ) ;
int auswahl = _getch( ) ; // Menüauswahl einlesen
if ( auswahl == 49 ) // falls 1 gedrückt dann...
{
modifikator = 0 ;
modifikator += 2 ; // Padlänge anpassen
maxSpeed = 1.8f ; // Ballgeschwindigkeit je nach Auswahl anpassen
strcat ( schwierigkeit
, "Amateur" ) ; // Schwierigkeitsgradanzeige im Einstellungsmenü aktualisieren strcpy ( pfad
, "C:\\ Amateur.txt" ) ; // Pfad für Highscoredatei aktualisieren kiReaktion = 10.0f ; // Computer Schnelligkeit setzen
return ; // (alter String wird gelöscht und neuer angehängt)
}
else if ( auswahl == 50 )
{
modifikator = 0 ;
strcat ( schwierigkeit
, "Machbar" ) ; // das selbe für alle andern Schwierigkeitsgrade strcpy ( pfad
, "C:\\ Machbar.txt" ) ; kiReaktion = 8.0f ;
maxSpeed = 3.2f ;
return ;
}
else if ( auswahl == 51 )
{
modifikator = 0 ;
modifikator -= 2 ;
strcat ( schwierigkeit
, "Veteran" ) ; strcpy ( pfad
, "C:\\ Veteran.txt" ) ; kiReaktion = 6.0f ;
maxSpeed = 4.5f ;
return ;
}
else if ( auswahl == 52 )
{
modifikator = 0 ;
modifikator -= 4 ;
strcat ( schwierigkeit
, "Nervt\224 tend" ) ; strcpy ( pfad
, "C:\\ Nervt\224 tend.txt" ) ; kiReaktion = 3.7f ;
maxSpeed = 6.0f ;
return ;
}
else
{
printf ( "\n \n Ung\201 ltige Eingabe!\n \n " ) ; // falls eine Taste, die nicht zur Auswahl steht gedrückt wurde, Ungültige Eingabe anzeigen Sleep( 2000 ) ; // und zurück zum Hautpmenü
return ;
}
}
else if ( auswahl == 51 )
{
printf ( "Neue Ballgeschwindigkeit eingeben!\n \n " ) ; // Abfrage nach neuer Ballgeschwindigkeit
if ( maxSpeed != 1.8f && maxSpeed != 2.8f && maxSpeed != 3.5f && maxSpeed != 5 ) // Falls Ballgeschwindigkeit ungleich den Voreinstellungen, so
{
strcpy ( schwierigkeit
, "" ) ; // wird die Schwierigkeitsanzeige auf "Persönlich" gesetzt strcat ( schwierigkeit
, "Pers\224 nlich" ) ; }
einstellungen( ) ; // zurück zum Einstellungsmenü
}
else if ( auswahl == 52 )
{
printf ( "Neue Anzahl der ben\224 tigten Siegpunkte eingeben!\n \n " ) ; // Abfrage nach neuer Ballgeschwindigkeit return ;
}
else if ( auswahl == 53 )
{
printf ( "Sind sie sich sicher, dass sie alle Einstellungen zur\201 cksetzen m\224 chten?\n \n " ) ; // Fragen, ob der Benutzer sicher ist, dass er die Einstellungen zurücksetzen möchte printf ( "<1> Ja, alle l\224 schen\n " ) ; printf ( "<2> Nein, zur\201 ck zu Einstellungen" ) ;
int auswahl = _getch( ) ; // Benutzereingabe einlesen
if ( auswahl == 49 )
{
strcat ( schwierigkeit
, "Machbar" ) ; // Alle Werte auf Standard setzen maxSpeed = 3.2f ;
links = 65 , rechts = 68 , beenden = 81 ;
printf ( "\n Einstellungen erfolgreich zur\201 ckgesetzt!" ) ; Sleep( 2500 ) ;
return ;
}
else if ( auswahl == 50 )
{
einstellungen( ) ; // falls nein, zurück zum Einstellungsmenü
}
else
{
printf ( "\n \n Ung\201 ltige Eingabe!\n \n " ) ; Sleep( 2000 ) ; // falls eine Taste, die nicht zur Auswahl stand gedrückt wurde, Ungültige Eingabe anzeigen
system ( "cls" ) ; // und zurück zum Hautpmenü einstellungen( ) ;
}
}
else if ( auswahl == 54 )
{
printf ( "Sind sie sich sicher, dass sie alle Highscores l\224 schen m\224 chten?\n \n " ) ; // Fragen, ob der Benutzer sicher ist, dass er die Highscores löschen möchte printf ( "<1> Ja, alle l\224 schen\n " ) ; printf ( "<2> Nein, zur\201 ck zu Einstellungen" ) ;
int auswahl = _getch( ) ; // Benutzereingabe einlesen
if ( auswahl == 49 )
{
FILE * FDatei;
FDatei
= fopen ( "C:\\ Amateur" , "w" ) ; // Alte Highscore Textdatei löschen und neue leere Datei erstellen FDatei
= fopen ( "C:\\ Machbar.txt" , "w" ) ; // Alte Highscore Textdatei löschen und neue leere Datei erstellen FDatei
= fopen ( "C:\\ Veteran.txt" , "w" ) ; // Alte Highscore Textdatei löschen und neue leere Datei erstellen FDatei
= fopen ( "C:\\ Nervt\224 tend.txt" , "w" ) ; // Alte Highscore Textdatei löschen und neue leere Datei erstellen FDatei
= fopen ( "C:\\ Mehrspieler.txt" , "w" ) ; // Alte Highscore Textdatei löschen und neue leere Datei erstellen printf ( "Highscores erfolgreich zur\201 ckgesetzt!" ) ; Sleep( 2000 ) ; // "Erfolgreich" Meldung ausgeben und 2 sekunden warten
return ;
}
else if ( auswahl == 50 )
{
einstellungen( ) ; // ansonsten zurück in das Einstellungsmenü
}
else
{
printf ( "\n \n Ung\201 ltige Eingabe!\n \n " ) ; Sleep( 2000 ) ; // falls eine Taste, die nicht zur Auswahl steht gedrückt wurde, Ungültige Eingabe anzeigen
system ( "cls" ) ; // und zurück zum Hautpmenü einstellungen( ) ;
}
}
else if ( auswahl == 55 ) // falls im Einstellungenmenü 7 gedrückt wurde dann...
{
system ( "cls" ) ; // ...zurück zum Hauptmenü return ;
}
else
{
printf ( "\n \n Ung\201 ltige Eingabe!\n \n " ) ; Sleep( 2000 ) ; // falls eine Taste, die nicht zur Auswahl steht gedrückt wurde, Ungültige Eingabe anzeigen
system ( "cls" ) ; // und zurück zum Hautpmenü einstellungen( ) ;
}
}
// Hauptmenü anzeigen und Auswahl auswerten
void menu( )
{
setWindowSize( 80 , 25 ) ; // setWindowSize() Methode aufrufen, um die Standartgröße der Konsole (80,25) nach dem Spiel wiederherzustellen
system ( "cls" ) ; // Konsole leeren printf ( "W\204 hlen sie eine M\224 glichkeit!\n \n " ) ; printf ( "<2> Steuerung\n " ) ; // Menü darstellen printf ( "<4> Einstellungen\n " ) ; printf ( "<5> Spiel beenden\n \n " ) ; int auswahl = _getch( ) ;
// Auf Benutzereingabe warten und diese in "auswahl" speichern
system ( "cls" ) ; // Konsole erneut leeren
if ( auswahl == 49 )
{
spielen( ) ;
}
else if ( auswahl == 50 ) // je nach Auswahl, das enstprechende Untermenü öffnen
{
steuerung( ) ;
}
else if ( auswahl == 51 )
{
highscoreAusgeben( ) ;
}
else if ( auswahl == 52 )
{
einstellungen( ) ;
}
else if ( auswahl == 53 ) // falls 5 gedrückt...
{
mainLoop = 2 ; // ...Main Schleife unterbrechen und Programm beenden
}
else
{
printf ( "\n \n Ung\201 ltige Eingabe!\n \n " ) ; Sleep( 2000 ) ; // falls eine Taste, die nicht zur Auswahl steht gedrückt wurde, Ungültige Eingabe anzeigen
menu( ) ; // und zurück zum Hautpmenü
}
}
// Beginn des Programms direkter Verweis nach Menü
int main( )
{
// Cursor verstecken
CONSOLE_CURSOR_INFO ConCurInf;
hOut = GetStdHandle( STD_OUTPUT_HANDLE) ;
ConCurInf.dwSize = 10 ;
//ConCurInf.bVisible = false;
SetConsoleCursorInfo( hOut, & ConCurInf) ;
while ( mainLoop <= 1 )
{
if ( mainLoop == 0 )
{
menu( ) ; // verhindern, dass das Programm frühzeitig beendet wird
}
else if ( mainLoop == 1 )
{
spielende( ) ; // spielende() aufrufen, sobald das Spiel beendet wurde bzw. mainLoop zu 1 gesetzt wurde
}
}
}
I2luY2x1ZGUgPHdpbmRvd3MuaD4KI2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxjb25pby5oPgojaW5jbHVkZSA8bWF0aC5oPgojaW5jbHVkZSA8dGltZS5oPgoKSEFORExFIGhPdXQ7CnRpbWVfdCBzdGFydCxlbmRldDsKaW50IHdpZHRoID0gNTUsIGhlaWdodCA9IDM2LCBtb2RpZmlrYXRvciA9IDAsIHNpZWdQdW5rdGUgPSA1LCBzcGllbG1vZHVzID0gMDs7CmludCBjU2NvcmUgPSAwLCB5U2NvcmUgPSAwLCB5MlNjb3JlID0gMCwgbWFpbkxvb3AgPSAwOzsKaW50IGxpbmtzID0gNjUsIHJlY2h0cyA9IDY4LCBiZWVuZGVuID0gODE7CmludCBsaW5rczIgPSAzNywgcmVjaHRzMiA9IDM5LCBiZWVuZGVuMiA9IDM4OwpjaGFyIG5hbWVbNDBdID0gIiI7CmNoYXIgcGZhZFs2MF0gPSAiQzpcXE1hY2hiYXIudHh0IjsKY2hhciBtb2R1cyBbMzBdID0gIk1lbnNjaCB2cyBDb21wdXRlciI7CmNoYXIgc2Nod2llcmlna2VpdFsyMF0gPSAiTWFjaGJhciI7CmNoYXIgc3BpZWxlcmdlYm5pc1syMF0gPSAiIjsKZG91YmxlIGRpZiA9IDAuMGY7CmZsb2F0IG1heFNwZWVkID0gMy4yZiwga2lSZWFrdGlvbiA9IDguMGY7IAoKICAgIAoJdHlwZWRlZiBzdHJ1Y3QKCXsKCQlmbG9hdCB4LCB5OwkJCQkJCS8vIHggdW5kIHkgUG9zaXRpb24gZGVzIFBhZHMKCQlpbnQgc2l6ZTsJCQkJCQkvLyBHcsO2w59lIGRlcyBQYWRzCgkJZmxvYXQgb3gsIG95OwkJCQkJLy8gQW5mYW5nc3RlbGx1bmcgZGVyIFBhZHMKCQlmbG9hdCB2eDsJCQkJCQkvLyBLSSBHZXNjaHdpbmRpZ2tlaXQgCgoJfSBzcGllbGVyOwoJCgkvLyBNZXRob2RlLCB1bSBXZXJ0ZSBmw7xyIGVpbiBPYmpla3QgZGVyIHNwaWVsZXIgc3RydWN0IHp1IHNldHplbgoJdm9pZCBzcGllbGVyXyhzcGllbGVyICp0aGlzLGludCBfeCwgaW50IF95LCBpbnQgX3NpemUpCgl7CgkJdGhpcy0+eCA9IChmbG9hdCkoX3gpOwoJCXRoaXMtPnkgPSAoZmxvYXQpKF95KTsKCQl0aGlzLT5zaXplID0gX3NpemU7CgkJdGhpcy0+b3ggPSAoZmxvYXQpKF94KTsKCQl0aGlzLT5veSA9IChmbG9hdCkoX3kpOwoJfQoKCS8vIFBhZHMgemVpY2huZW4KCXZvaWQgZHJhdyhzcGllbGVyICp0aGlzKQoJewoJICBpbnQgaTsKCQlDT09SRCBwOwoJCXAuWCA9IChpbnQpKHRoaXMtPm94KSAtIHRoaXMtPnNpemUgOwoJCXAuWSA9IChpbnQpKHRoaXMtPm95KTsKCQlTZXRDb25zb2xlQ3Vyc29yUG9zaXRpb24oaE91dCwgcCk7CgoJCWZvciAoaSA9IC10aGlzLT5zaXplOyBpIDwgdGhpcy0+c2l6ZSArIG1vZGlmaWthdG9yOyBpKyspCgkJewoJCQlwcmludGYoIiAiKTsKCQl9CgoJCXAuWCA9IChpbnQpKHRoaXMtPngpIC0gdGhpcy0+c2l6ZTsJCQkJCS8vIFBhZHMgemVpY2huZW4KCQlwLlkgPSAoaW50KSh0aGlzLT55KTsKCQlTZXRDb25zb2xlQ3Vyc29yUG9zaXRpb24oaE91dCwgcCk7CgkJU2V0Q29uc29sZVRleHRBdHRyaWJ1dGUoaE91dCwgMTApOwoKCQlmb3IgKGkgPSAtdGhpcy0+c2l6ZTsgaSA8IHRoaXMtPnNpemUgKyBtb2RpZmlrYXRvcjsgaSsrKQoJCXsKCQkJcHJpbnRmKCI9Iik7CgkJfQoKCQlTZXRDb25zb2xlVGV4dEF0dHJpYnV0ZShoT3V0LCAxNSk7CgkJdGhpcy0+b3ggPSB0aGlzLT54OwoJCXRoaXMtPm95ID0gdGhpcy0+eTsKCX0KCQoJdHlwZWRlZiBzdHJ1Y3QgYmFsbAoJewoJCWZsb2F0IHgsIHksIG94LCBveTsJCQkJLy8gYWt0dWVsbGUgdW5kIEFuZmFuZ3NzdGVsbHVuZyBkZXMgQmFsbHMKCQlmbG9hdCB2eCwgdnk7CQkJCQkvLyBHZXNjaHdpbmRpZ2tlaXQgeCwgeSBkZXMgQmFsbHMKCX0gYmFsbDsKCQoJLy8gTWV0aG9kZSwgdW0gV2VydGUgZsO8ciBlaW4gT2JqZWt0IGRlciBiYWxsIHN0cnVjdCB6dSBzZXR6ZW4KCXZvaWQgYmFsbF8oYmFsbCAqdGhpcyxpbnQgX3gsIGludCBfeSkgCgl7CgkJdGhpcy0+eCA9IChmbG9hdCkoX3gpOwoJCXRoaXMtPnkgPSAoZmxvYXQpKF95KTsKCQl0aGlzLT5veCA9IChmbG9hdCkodGhpcy0+eCk7CgkJdGhpcy0+b3kgPSAoZmxvYXQpKHRoaXMtPnkpOwoJCXRoaXMtPnZ4ID0gdGhpcy0+dnkgPSAwOwoJfQoKCS8vIEJhbGwgemVpY2huZW4KCXZvaWQgZHJhd2JhbGwoYmFsbCAqdGhpcykKCXsKCQlDT09SRCBwOwogCQlwLlggPSAoaW50KSh0aGlzLT5veCk7CgkJcC5ZID0gKGludCkodGhpcy0+b3kpOwoJCVNldENvbnNvbGVDdXJzb3JQb3NpdGlvbihoT3V0LCBwKTsKCQlwcmludGYoIiAiKTsKCQlwLlggPSAoaW50KSh0aGlzLT54KTsKCQlwLlkgPSAoaW50KSh0aGlzLT55KTsKCQlTZXRDb25zb2xlQ3Vyc29yUG9zaXRpb24oaE91dCwgcCk7CgkJU2V0Q29uc29sZVRleHRBdHRyaWJ1dGUoaE91dCwgMTIpOwoJCXByaW50ZigiMCIpOwoJCVNldENvbnNvbGVUZXh0QXR0cmlidXRlKGhPdXQsIDE1KTsKCQl0aGlzLT5veCA9IHRoaXMtPng7CgkJdGhpcy0+b3kgPSB0aGlzLT55OwoJfQoKCS8vIEFsbGVzIHp1csODP8OCwrxja3NldHplbgoJdm9pZCByZXNldChzcGllbGVyICp5b3UsIHNwaWVsZXIgKnlvdTIsIHNwaWVsZXIgKmNvbXAsIGJhbGwgKmIsIGludCB5b3Vfc2NvcmUgLCBpbnQgeW91Ml9zY29yZSwgaW50IGNvbXBfc2NvcmUpCgl7CgkJYi0+eCA9IChmbG9hdCkod2lkdGggLyAyIC0gMSk7CgkJYi0+eSA9IChmbG9hdCkoaGVpZ2h0IC8gMik7CQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJLy8gS29vcmRpbmF0ZW4genVtIHplaWNobmVuIGF1ZiBBbmZhbmdzd2VydGUgc2V0emVuCgkJeW91LT54ID0gY29tcC0+eCA9IChmbG9hdCkod2lkdGggLyAyKTsKCQljb21wLT52eCA9IDAuMGY7CQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkvLyBHZXNjaHdpbmRpZ2tlaXRlbiBhdWYgMCBzdGFuZGFydCB6dXLDvGNrc2V0emVuCgkJYi0+dnggPSAoZmxvYXQpKHJhbmQoKSAlIDMpIC0gMS41ZjsKCQliLT52eSA9IDE7CQoJCUNPT1JEIHA7CgkJcC5YID0gMDsKIAkJcC5ZID0gaGVpZ2h0OwoJCVNldENvbnNvbGVDdXJzb3JQb3NpdGlvbihoT3V0LCBwKTsKCQlpZihzcGllbG1vZHVzID09IDApcHJpbnRmKCJcbnwgWW91ciBzY29yZTogJWkgfCBDb21wdXRlciBzY29yZTogJWkgfHx8IFNwZWVkOiAgIDAgICB8XG4iLCB5b3Vfc2NvcmUsIGNvbXBfc2NvcmUpOwkJLy8gU3BpZWxzdGFuZCBha3R1YWxpc2llcmVuIGJlaSBTcGllbG1vZHVzID0gTWVuc2NoIHZzIENvbXB1dGVyCgkJaWYoc3BpZWxtb2R1cyA9PSAxKXByaW50ZigiXG58IFNwaS4gMSBzY29yZTogJWkgfCBTcGkuIDIgc2NvcmU6ICVpIHx8fCBTcGVlZDogICAwICAgfFxuIiwgeW91X3Njb3JlLCB5b3UyX3Njb3JlKTsJCS8vIFNwaWVsc3RhbmQgYWt0dWFsaXNpZXJlbiBiZWkgU3BpZWxtb2R1cyA9IE1lbnNjaCB2cyBNZW5zY2gKCX0KCgkvLyBHcsO2w59lIGRlciBLb25zb2xlIGZlc3RsZWdlbgoJdm9pZCBzZXRXaW5kb3dTaXplKGludCB4LCBpbnQgeSkgCgl7IAoJCVNNQUxMX1JFQ1Qgc3Jfd2luZG93ID0gezAsIDAsIHggLSAxLCB5IC0gMX07IAoJCUNPT1JEIGV4dGVuc2lvbjsgCgkJQ09OU09MRV9TQ1JFRU5fQlVGRkVSX0lORk8gY3NiaTsgCiAgICAKCQlHZXRDb25zb2xlU2NyZWVuQnVmZmVySW5mbyhHZXRTdGRIYW5kbGUoU1REX09VVFBVVF9IQU5ETEUpLCAmY3NiaSk7CQkJCS8vIEFrdXRlbGxlIEZlbnN0ZXJwdWZmZXIgR3LDtsOfZSBlcm1pdHRlbG4KICAKCQlleHRlbnNpb24uWCA9IG1heCh4LCBjc2JpLmR3TWF4aW11bVdpbmRvd1NpemUuWCk7IAoJCWV4dGVuc2lvbi5ZID0gbWF4KHksIGNzYmkuZHdNYXhpbXVtV2luZG93U2l6ZS5ZKTsgCiAgCgkJU2V0Q29uc29sZVNjcmVlbkJ1ZmZlclNpemUoR2V0U3RkSGFuZGxlKFNURF9PVVRQVVRfSEFORExFKSwgZXh0ZW5zaW9uKTsJCQkvLyBQdWZmZXIgYXVmIG1heCBXZXJ0ZSBzZXR6ZW4KCQlTZXRDb25zb2xlV2luZG93SW5mbyhHZXRTdGRIYW5kbGUoU1REX09VVFBVVF9IQU5ETEUpLCBUUlVFLCAmc3Jfd2luZG93KTsJCS8vIEZlbnN0ZXIgYXVmIG1heCBXZXJ0ZSBzZXR6ZW4KICAgIAoJCWV4dGVuc2lvbi5YID0geDsgCgkJZXh0ZW5zaW9uLlkgPSB5OyAKCQlTZXRDb25zb2xlU2NyZWVuQnVmZmVyU2l6ZShHZXRTdGRIYW5kbGUoU1REX09VVFBVVF9IQU5ETEUpLCBleHRlbnNpb24pOwkJCS8vIFB1ZmZlciBhdWYgRmVuc3Rlcmdyw7bDn2Ugc2V0emVuCgl9CgoJLy8gSGlnaHNjb3JlIGFuemVpZ2VuCgl2b2lkIGhpZ2hzY29yZUF1c2dlYmVuKCkKCXsgCgkJCWNoYXIqIGF1c2dhYmU7CQkJCQkJCQkJCS8vIFplaWdlciBhdWYgYmVzdGltbXRlIFN0ZWxsZW4gaW0gc3DDpHRlciBlaW5nZWxlc2VuZW4gU3RyaW5nCQkJCQkKCQkJY2hhciB6d2lzY2hlblBmYWRbNjBdID0gIiI7CQkJCQkJCS8vIGNoYXIgYXJyYXksIHVtIGVpbmVuIERhdGVpcGZhZCB6d2lzY2hlbnp1c3BlaWNoZXJuCgkJCXN0cmNhdCh6d2lzY2hlblBmYWQscGZhZCk7CQkJCQkJCS8vIFBmYWQgaW4gendpc2NoZW5QZmFkIHp3aXNjaGVuc3BlaWNoZXJuCgkJCWNoYXIgZWlubGVzZW5bNjldOwkJCQkJCQkJCS8vIEFycmF5IHVtIEluaGFsdCBkZXIgdHh0IHp3aXNjaGVuIHp1IHNwZWljaGVybgoJCQkKCQkJc3lzdGVtKCJjbHMiKTsJCQkJCQkJCQkJLy8gS29uc29sZSBsZWVyZW4KCQkJcHJpbnRmKCJXZWxjaGUgSGlnaHNjb3JlcyB3b2xsZW4gc2llIGFuc2NoYXVlbj9cblxuIik7CgkJCXByaW50ZigiPDE+IEFtYXRldXJcbiIpOwoJCQlwcmludGYoIjwyPiBNYWNoYmFyXG4iKTsKCQkJcHJpbnRmKCI8Mz4gVmV0ZXJhblxuIik7CQkJCQkJCS8vIEhpZ2hzY29yZSBBdXN3YWhsbWVuw7wgZGFyc3RlbGxlbgoJCQlwcmludGYoIjw0PiBOZXJ2dFwyMjR0ZW5kXG4iKTsKCQkJcHJpbnRmKCI8NT4gTWVocnNwaWVsZXIiKTsKCgkJCWludCBhdXN3YWhsID0gX2dldGNoKCk7CQkJCQkJCQkvLyAiSGloc2NvcmVsaXN0ZW5hdXN3YWhsIiBpbiBhdXN3YWhsIHNwZWljaGVybgoJCQlzeXN0ZW0oImNscyIpOwkJCQkJCQkJCQkvLyBLb25zb2xlIGxlZXJlbgoKCQkJaWYoYXVzd2FobCA9PSA0OSkJCQkJCQkJCQkvLyBmYWxscyAiMSIgZ2VkcsO8Y2t0IHd1cmRlLCBBbWF0ZXVyLnR4dCBhdXNnZWJlbgoJCQl7CgkJCQlGSUxFKiBGRGF0ZWk7CQkJCQkJCQkJLy8gWmVpZ2VyIGF1ZiBIaWdoc2NvcmUgdHh0IGVyc3RlbGxlbgoJCQkJc3RyY3B5KHBmYWQsICJDOlxcQW1hdGV1ci50eHQiKTsJCQkJLy8gUGZhZCBmw7xyIGRpZSBBbWF0dWVyLnR4dCBpbiBkYXMgY2hhciBBcnJheSBwZmFkIGtvcGllcmVuCgkJCQlGRGF0ZWkgPSBmb3BlbihwZmFkLCAiciIpOwkJCQkJCS8vIEFtYXRldXIudHh0IMO2ZmZuZW4gdW5kIGxlc2VuCgkJCQlpbnQgaSA9IDE7CQkJCQkJCQkJCS8vIFN0YXJ0d2VydCBmw7xyIFZvcnplaWNoZW4gKDEuICwgMi4gLCAzLi4uLikgZsO8ciBBdXNnYWJlIGVyaMO2aGVuCgoJCQkJaWYoIUZEYXRlaSkJCQkJCQkJCQkJLy8gZ2lidCBlcyBkaWUgQW1hdGV1ci50eHQgbm9jaCBuaWNodD8KCQkJCXsKCQkJCQlGRGF0ZWkgPSBmb3BlbihwZmFkLCAidyIpOwkJCQkJLy8gZmFsbHMgQW1hdGV1ci50eHQgbm9jaCBuaWNodCB2b3JoYW5kZW4sIGVyc3RlbGxlIGRpZXNlCgkJCQkJZmNsb3NlKEZEYXRlaSk7CgkJCQkJcHJpbnRmKCJcbkxlaWRlciBoYXQgbm9jaCBuaWVtYW5kIGVpbmVuIEhpZ2hzY29yZSBhdWZnZXN0ZWxsdCFcblxuXG5cblxuXG5cblxuXG5cblxuXG5cblxuXG48MT4gWnVyXDIwMWNrIHp1bSBIYXVwdG1lblwyMDEiKTsJCgkJCQoJCQkJCWludCBhdXN3YWhsID0gX2dldGNoKCk7CQkJCQkJLy8genVyw7xjayB6dW0gTWVuw7wgQWJmcmFnZSAoZmFsbHMgMSBnZWRyw7xja3Qgd2lyZCB6dXLDvGNrIHp1bSBtTmXDvCkKCQkJCQlpZihhdXN3YWhsID09IDQ5KQkJCQkJCgkJCQkJewoJCQkJCQlyZXR1cm47CgkJCQkJfQoJCQkJfQoJCQkJZWxzZSBpZihmZ2V0cyhlaW5sZXNlbiw1MCxGRGF0ZWkpID09IE5VTEwpCQkvLyBzdGVodCBldHdhcyBpbiBkZXIgQW1hdGV1ci50eHQ/CgkJCQl7CgkJCQkJcHJpbnRmKCJcbkxlaWRlciBoYXQgbm9jaCBuaWVtYW5kIGVpbmVuIEhpZ2hzY29yZSBhdWZnZXN0ZWxsdCFcblxuXG5cblxuXG5cblxuXG5cblxuXG5cblxuXG48MT4gWnVyXDIwMWNrIHp1bSBIYXVwdG1lblwyMDEiKTsgLy8gZmFsbHMgbmVpbiwgZGllcyBhdXNnZWJlbgoJCQkJCWludCBhdXN3YWhsID0gX2dldGNoKCk7CQkJCQkJLy8genVyw7xjayB6dW0gTWVuw7wgQWJmcmFnZSAoZmFsbHMgMSBnZWRyw7xja3Qgd2lyZCkKCQkJCQlpZihhdXN3YWhsID09IDQ5KQoJCQkJCXsKCQkJCQkJcmV0dXJuOwoJCQkJCX0KCQkJCQlmY2xvc2UoRkRhdGVpKTsJCQkJCQkJCS8vIERhdGVpIHNjaGxpZXNzZW4KCQkJCX0KCQkJCWVsc2UKCQkJCXsKCQkJCQlmY2xvc2UoRkRhdGVpKTsJCQkJCQkJCgkJCQkJRkRhdGVpID0gZm9wZW4ocGZhZCwgInIiKTsJCQkJCS8vIG5vY2ggZWlubWFsIHNjaGxpZcOfZW4gdW5kIMO2ZmZuZW4sIHVtIHdpZWRlciBhbSBBbmZhbmcgZGVyIERhdGVpIHp1IGJlZ2lubmVuCgkJCQkJd2hpbGUgKGZnZXRzKGVpbmxlc2VuLDUwLEZEYXRlaSkpCQkJLy8gYW5zb25zdGVuIEhpZ2hzY29yZSBhdXNnZWJlbiAmIGxlc2UgYmlzIERhdGVpZW5kZQoJCQkJCXsJCgkJCQkJCWF1c2dhYmUgPSBzdHJjaHIgKGVpbmxlc2VuLCAnLicpOwkJLy8gUHVua3QgaW0gZWluZ2VsZXNlbmVuIFN0cmluZyBzdWNoZW4KCQkJCQkJYXVzZ2FiZSArPSAxOwkJCQkJCQkvLyBaZWlnZXIgdW0gMSBuYWNoIHJlY2h0cyB2ZXJzY2hpZWJlbiwgdW0gZGVuIFB1bmt0IG5pY2h0IG1pdCBhdXN6dWdlYmVuCgkJCQkJCXByaW50ZigiJWkuICVzIiwgaSwgYXVzZ2FiZSk7CQkJLy8gYmVhcmJlaXRldGVuIFN0cmluZyBhdXNnZWJlbgoJCQkJCQlpKys7CQkJCQkJCQkJLy8gVm9yemVpY2hlbiAoMS4gLCAyLiAsIDMuLi4uKSBmw7xyIEF1c2dhYmUgZXJow7ZoZW4KCQkJCQl9CQoJCQkJCWZjbG9zZShGRGF0ZWkpOwkJCQkJCQkJLy8gRGF0ZWkgc2NobGllc3NlbgoJCQkJCXByaW50ZigiXG5cblxuXG5cblxuXG5cblxuXG5cblxuXG5cblxuXG48MT4gWnVyXDIwMWNrIHp1bSBIYXVwdG1lblwyMDEiKTsJLy8gZmFsbHMgSGlnaHNjb3JlIERhdGVpIG5vY2ggbmljaHQgdm9yaGFuZGVuLCBlcnN0ZWxsZSBkaWVzZQoKCQkJCQlpbnQgYXVzd2FobCA9IF9nZXRjaCgpOwkJCQkJCS8vIHp1csO8Y2sgenVtIE1lbsO8IEFiZnJhZ2UgKGZhbGxzIDEgZ2VkcsO8Y2t0IHdpcmQpCgkJCQkJaWYoYXVzd2FobCA9PSA0OSkKCQkJCQl7CgkJCQkJCXJldHVybjsKCQkJCQl9CgkJCQl9CgkJCX0KCQkJaWYoYXVzd2FobCA9PSA1MCkJCQkJCQkJCQkvLyBmYWxscyAiMSIgZ2VkcsO8Y2t0IHd1cmRlLCBNYWNoYmFyLnR4dCBhdXNnZWJlbgoJCQl7CgkJCQlGSUxFKiBGRGF0ZWk7CQkJCQkJCQkJLy8gWmVpZ2VyIGF1ZiBNYWNoYmFyIHR4dCBlcnN0ZWxsZW4KCQkJCXN0cmNweShwZmFkLCAiQzpcXE1hY2hiYXIudHh0Iik7CQkJCS8vIFBmYWQgZsO8ciBkaWUgTWFjaGJhci50eHQgaW4gZGFzIGNoYXIgQXJyYXkgcGZhZCBrb3BpZXJlbgoJCQkJRkRhdGVpID0gZm9wZW4ocGZhZCwgInIiKTsJCQkJCQkvLyBNYWNoYmFyLnR4dCDDtmZmbmVuIHVuZCBsZXNlbgoJCQkJaW50IGkgPSAxOwkJCQkJCQkJCQkvLyBTdGFydHdlcnQgZsO8ciBWb3J6ZWljaGVuICgxLiAsIDIuICwgMy4uLi4pIGbDvHIgQXVzZ2FiZSBlcmjDtmhlbgoKCQkJCWlmKCFGRGF0ZWkpCQkJCQkJCQkJCS8vIGdpYnQgZXMgZGllIE1hY2hiYXIudHh0IG5vY2ggbmljaHQ/CgkJCQl7CgkJCQkJRkRhdGVpID0gZm9wZW4ocGZhZCwgInciKTsJCQkJCS8vIGZhbGxzIEFtYXRldXIudHh0IG5vY2ggbmljaHQgdm9yaGFuZGVuLCBlcnN0ZWxsZSBkaWVzZQoJCQkJCWZjbG9zZShGRGF0ZWkpOwoJCQkJCXByaW50ZigiXG5MZWlkZXIgaGF0IG5vY2ggbmllbWFuZCBlaW5lbiBIaWdoc2NvcmUgYXVmZ2VzdGVsbHQhXG5cblxuXG5cblxuXG5cblxuXG5cblxuXG5cblxuPDE+IFp1clwyMDFjayB6dW0gSGF1cHRtZW5cMjAxIik7CQoJCQkKCQkJCQlpbnQgYXVzd2FobCA9IF9nZXRjaCgpOwkJCQkJCS8vIHp1csO8Y2sgenVtIE1lbsO8IEFiZnJhZ2UgKGZhbGxzIDEgZ2VkcsO8Y2t0IHdpcmQgenVyw7xjayB6dW0gbU5lw7wpCgkJCQkJaWYoYXVzd2FobCA9PSA0OSkJCQkJCQoJCQkJCXsKCQkJCQkJcmV0dXJuOwoJCQkJCX0KCQkJCX0KCQkJCWVsc2UgaWYoZmdldHMoZWlubGVzZW4sNTAsRkRhdGVpKSA9PSBOVUxMKQkJLy8gc3RlaHQgZXR3YXMgaW4gZGVyIE1hY2hiYXIudHh0PwoJCQkJewoJCQkJCXByaW50ZigiXG5MZWlkZXIgaGF0IG5vY2ggbmllbWFuZCBlaW5lbiBIaWdoc2NvcmUgYXVmZ2VzdGVsbHQhXG5cblxuXG5cblxuXG5cblxuXG5cblxuXG5cblxuPDE+IFp1clwyMDFjayB6dW0gSGF1cHRtZW5cMjAxIik7IC8vIGZhbGxzIG5laW4sIGRpZXMgYXVzZ2ViZW4KCQkJCQlpbnQgYXVzd2FobCA9IF9nZXRjaCgpOwkJCQkJCS8vIHp1csO8Y2sgenVtIE1lbsO8IEFiZnJhZ2UgKGZhbGxzIDEgZ2VkcsO8Y2t0IHdpcmQpCgkJCQkJaWYoYXVzd2FobCA9PSA0OSkKCQkJCQl7CgkJCQkJCXJldHVybjsKCQkJCQl9CgkJCQkJZmNsb3NlKEZEYXRlaSk7CQkJCQkJCQkvLyBEYXRlaSBzY2hsaWVzc2VuCgkJCQl9CgkJCQllbHNlCgkJCQl7CgkJCQkJZmNsb3NlKEZEYXRlaSk7CQkJCQkJCQoJCQkJCUZEYXRlaSA9IGZvcGVuKHBmYWQsICJyIik7CQkJCQkvLyBub2NoIGVpbm1hbCBzY2hsaWXDn2VuIHVuZCDDtmZmbmVuLCB1bSB3aWVkZXIgYW0gQW5mYW5nIGRlciBEYXRlaSB6dSBiZWdpbm5lbgoJCQkJCXdoaWxlIChmZ2V0cyhlaW5sZXNlbiw1MCxGRGF0ZWkpKQkJCS8vIGFuc29uc3RlbiBIaWdoc2NvcmUgYXVzZ2ViZW4gJiBsZXNlIGJpcyBEYXRlaWVuZGUKCQkJCQl7CQoJCQkJCQlhdXNnYWJlID0gc3RyY2hyIChlaW5sZXNlbiwgJy4nKTsJCS8vIFB1bmt0IGltIGVpbmdlbGVzZW5lbiBTdHJpbmcgc3VjaGVuCgkJCQkJCWF1c2dhYmUgKz0gMTsJCQkJCQkJLy8gWmVpZ2VyIHVtIDEgbmFjaCByZWNodHMgdmVyc2NoaWViZW4sIHVtIGRlbiBQdW5rdCBuaWNodCBtaXQgYXVzenVnZWJlbgoJCQkJCQlwcmludGYoIiVpLiAlcyIsIGksIGF1c2dhYmUpOwkJCS8vIGJlYXJiZWl0ZXRlbiBTdHJpbmcgYXVzZ2ViZW4KCQkJCQkJaSsrOwkJCQkJCQkJCS8vIFZvcnplaWNoZW4gKDEuICwgMi4gLCAzLi4uLikgZsO8ciBBdXNnYWJlIGVyaMO2aGVuCgkJCQkJfQkKCQkJCQlmY2xvc2UoRkRhdGVpKTsJCQkJCQkJCS8vIERhdGVpIHNjaGxpZXNzZW4KCQkJCQlwcmludGYoIlxuXG5cblxuXG5cblxuXG5cblxuXG5cblxuXG5cblxuPDE+IFp1clwyMDFjayB6dW0gSGF1cHRtZW5cMjAxIik7CS8vIGZhbGxzIEhpZ2hzY29yZSBEYXRlaSBub2NoIG5pY2h0IHZvcmhhbmRlbiwgZXJzdGVsbGUgZGllc2UKCgkJCQkJaW50IGF1c3dhaGwgPSBfZ2V0Y2goKTsJCQkJCQkvLyB6dXLDvGNrIHp1bSBNZW7DvCBBYmZyYWdlIChmYWxscyAxIGdlZHLDvGNrdCB3aXJkKQoJCQkJCWlmKGF1c3dhaGwgPT0gNDkpCgkJCQkJewoJCQkJCQlyZXR1cm47CgkJCQkJfQoJCQkJfQoJCQl9CgkJCWlmKGF1c3dhaGwgPT0gNTEpCQkJCQkJCQkJLy8gZmFsbHMgIjEiIGdlZHLDvGNrdCB3dXJkZSwgVmV0ZXJhbi50eHQgYXVzZ2ViZW4KCQkJewoJCQkJRklMRSogRkRhdGVpOwkJCQkJCQkJCS8vIFplaWdlciBhdWYgVmV0ZXJhbiB0eHQgZXJzdGVsbGVuCgkJCQlzdHJjcHkocGZhZCwgIkM6XFxWZXRlcmFuLnR4dCIpOwkJCQkvLyBQZmFkIGbDvHIgZGllIFZldGVyYW4udHh0IGluIGRhcyBjaGFyIEFycmF5IHBmYWQga29waWVyZW4KCQkJCUZEYXRlaSA9IGZvcGVuKHBmYWQsICJyIik7CQkJCQkJLy8gVmV0ZXJhbi50eHQgw7ZmZm5lbiB1bmQgbGVzZW4KCQkJCWludCBpID0gMTsJCQkJCQkJCQkJLy8gU3RhcnR3ZXJ0IGbDvHIgVm9yemVpY2hlbiAoMS4gLCAyLiAsIDMuLi4uKSBmw7xyIEF1c2dhYmUgZXJow7ZoZW4KCgkJCQlpZighRkRhdGVpKQkJCQkJCQkJCQkvLyBnaWJ0IGVzIGRpZSBWZXRlcmFuLnR4dCBub2NoIG5pY2h0PwoJCQkJewoJCQkJCUZEYXRlaSA9IGZvcGVuKHBmYWQsICJ3Iik7CQkJCQkvLyBmYWxscyBWZXRlcmFuLnR4dCBub2NoIG5pY2h0IHZvcmhhbmRlbiwgZXJzdGVsbGUgZGllc2UKCQkJCQlmY2xvc2UoRkRhdGVpKTsKCQkJCQlwcmludGYoIlxuTGVpZGVyIGhhdCBub2NoIG5pZW1hbmQgZWluZW4gSGlnaHNjb3JlIGF1Zmdlc3RlbGx0IVxuXG5cblxuXG5cblxuXG5cblxuXG5cblxuXG5cbjwxPiBadXJcMjAxY2sgenVtIEhhdXB0bWVuXDIwMSIpOwkKCQkJCgkJCQkJaW50IGF1c3dhaGwgPSBfZ2V0Y2goKTsJCQkJCQkvLyB6dXLDvGNrIHp1bSBNZW7DvCBBYmZyYWdlIChmYWxscyAxIGdlZHLDvGNrdCB3aXJkIHp1csO8Y2sgenVtIG1OZcO8KQoJCQkJCWlmKGF1c3dhaGwgPT0gNDkpCQkJCQkKCQkJCQl7CgkJCQkJCXJldHVybjsKCQkJCQl9CgkJCQl9CgkJCQllbHNlIGlmKGZnZXRzKGVpbmxlc2VuLDUwLEZEYXRlaSkgPT0gTlVMTCkJCS8vIHN0ZWh0IGV0d2FzIGluIGRlciBWZXRlcmFuLnR4dD8KCQkJCXsKCQkJCQlwcmludGYoIlxuTGVpZGVyIGhhdCBub2NoIG5pZW1hbmQgZWluZW4gSGlnaHNjb3JlIGF1Zmdlc3RlbGx0IVxuXG5cblxuXG5cblxuXG5cblxuXG5cblxuXG5cbjwxPiBadXJcMjAxY2sgenVtIEhhdXB0bWVuXDIwMSIpOyAvLyBmYWxscyBuZWluLCBkaWVzIGF1c2dlYmVuCgkJCQkJaW50IGF1c3dhaGwgPSBfZ2V0Y2goKTsJCQkJCQkvLyB6dXLDvGNrIHp1bSBNZW7DvCBBYmZyYWdlIChmYWxscyAxIGdlZHLDvGNrdCB3aXJkKQoJCQkJCWlmKGF1c3dhaGwgPT0gNDkpCgkJCQkJewoJCQkJCQlyZXR1cm47CgkJCQkJfQoJCQkJCWZjbG9zZShGRGF0ZWkpOwkJCQkJCQkJLy8gRGF0ZWkgc2NobGllc3NlbgoJCQkJfQoJCQkJZWxzZQoJCQkJewoJCQkJCWZjbG9zZShGRGF0ZWkpOwkJCQkJCQkKCQkJCQlGRGF0ZWkgPSBmb3BlbihwZmFkLCAiciIpOwkJCQkJLy8gbm9jaCBlaW5tYWwgc2NobGllw59lbiB1bmQgw7ZmZm5lbiwgdW0gd2llZGVyIGFtIEFuZmFuZyBkZXIgRGF0ZWkgenUgYmVnaW5uZW4KCQkJCQl3aGlsZSAoZmdldHMoZWlubGVzZW4sNTAsRkRhdGVpKSkJCQkvLyBhbnNvbnN0ZW4gSGlnaHNjb3JlIGF1c2dlYmVuICYgbGVzZSBiaXMgRGF0ZWllbmRlCgkJCQkJewkKCQkJCQkJYXVzZ2FiZSA9IHN0cmNociAoZWlubGVzZW4sICcuJyk7CQkvLyBQdW5rdCBpbSBlaW5nZWxlc2VuZW4gU3RyaW5nIHN1Y2hlbgoJCQkJCQlhdXNnYWJlICs9IDE7CQkJCQkJCS8vIFplaWdlciB1bSAxIG5hY2ggcmVjaHRzIHZlcnNjaGllYmVuLCB1bSBkZW4gUHVua3QgbmljaHQgbWl0IGF1c3p1Z2ViZW4KCQkJCQkJcHJpbnRmKCIlaS4gJXMiLCBpLCBhdXNnYWJlKTsJCQkvLyBiZWFyYmVpdGV0ZW4gU3RyaW5nIGF1c2dlYmVuCgkJCQkJCWkrKzsJCQkJCQkJCQkvLyBWb3J6ZWljaGVuICgxLiAsIDIuICwgMy4uLi4pIGbDvHIgQXVzZ2FiZSBlcmjDtmhlbgoJCQkJCX0JCgkJCQkJZmNsb3NlKEZEYXRlaSk7CQkJCQkJCQkvLyBEYXRlaSBzY2hsaWVzc2VuCgkJCQkJcHJpbnRmKCJcblxuXG5cblxuXG5cblxuXG5cblxuXG5cblxuXG5cbjwxPiBadXJcMjAxY2sgenVtIEhhdXB0bWVuXDIwMSIpOwkvLyBmYWxscyBIaWdoc2NvcmUgRGF0ZWkgbm9jaCBuaWNodCB2b3JoYW5kZW4sIGVyc3RlbGxlIGRpZXNlCgoJCQkJCWludCBhdXN3YWhsID0gX2dldGNoKCk7CQkJCQkJLy8genVyw7xjayB6dW0gTWVuw7wgQWJmcmFnZSAoZmFsbHMgMSBnZWRyw7xja3Qgd2lyZCkKCQkJCQlpZihhdXN3YWhsID09IDQ5KQoJCQkJCXsKCQkJCQkJcmV0dXJuOwoJCQkJCX0KCQkJCX0KCQkJfQoJCQlpZihhdXN3YWhsID09IDUyKQkJCQkJCQkJCS8vIGZhbGxzICIxIiBnZWRyw7xja3Qgd3VyZGUsIE5lcnZ0XDIyNHRlbmQudHh0IGF1c2dlYmVuCgkJCXsKCQkJCUZJTEUqIEZEYXRlaTsJCQkJCQkJCQkvLyBaZWlnZXIgYXVmIE5lcnZ0XDIyNHRlbmQgdHh0IGVyc3RlbGxlbgoJCQkJc3RyY3B5KHBmYWQsICJDOlxcTmVydnRcMjI0dGVuZC50eHQiKTsJCQkvLyBQZmFkIGbDvHIgZGllIE5lcnZ0XDIyNHRlbmQudHh0IGluIGRhcyBjaGFyIEFycmF5IHBmYWQga29waWVyZW4KCQkJCUZEYXRlaSA9IGZvcGVuKHBmYWQsICJyIik7CQkJCQkJLy8gTmVydnRcMjI0dGVuZC50eHQgw7ZmZm5lbiB1bmQgbGVzZW4KCQkJCWludCBpID0gMTsJCQkJCQkJCQkJLy8gU3RhcnR3ZXJ0IGbDvHIgVm9yemVpY2hlbiAoMS4gLCAyLiAsIDMuLi4uKSBmw7xyIEF1c2dhYmUgZXJow7ZoZW4KCgkJCQlpZighRkRhdGVpKQkJCQkJCQkJCQkvLyBnaWJ0IGVzIGRpZSBOZXJ2dFwyMjR0ZW5kLnR4dCBub2NoIG5pY2h0PwoJCQkJewoJCQkJCUZEYXRlaSA9IGZvcGVuKHBmYWQsICJ3Iik7CQkJCQkvLyBmYWxscyBOZXJ2dFwyMjR0ZW5kLnR4dCBub2NoIG5pY2h0IHZvcmhhbmRlbiwgZXJzdGVsbGUgZGllc2UKCQkJCQlmY2xvc2UoRkRhdGVpKTsKCQkJCQlwcmludGYoIlxuTGVpZGVyIGhhdCBub2NoIG5pZW1hbmQgZWluZW4gSGlnaHNjb3JlIGF1Zmdlc3RlbGx0IVxuXG5cblxuXG5cblxuXG5cblxuXG5cblxuXG5cbjwxPiBadXJcMjAxY2sgenVtIEhhdXB0bWVuXDIwMSIpOwkKCQkJCgkJCQkJaW50IGF1c3dhaGwgPSBfZ2V0Y2goKTsJCQkJCQkvLyB6dXLDvGNrIHp1bSBNZW7DvCBBYmZyYWdlIChmYWxscyAxIGdlZHLDvGNrdCB3aXJkIHp1csO8Y2sgenVtIG1OZcO8KQoJCQkJCWlmKGF1c3dhaGwgPT0gNDkpCQkJCQkKCQkJCQl7CgkJCQkJCXJldHVybjsKCQkJCQl9CgkJCQl9CgkJCQllbHNlIGlmKGZnZXRzKGVpbmxlc2VuLDUwLEZEYXRlaSkgPT0gTlVMTCkJCS8vIHN0ZWh0IGV0d2FzIGluIGRlciBOZXJ2dFwyMjR0ZW5kLnR4dD8KCQkJCXsKCQkJCQlwcmludGYoIlxuTGVpZGVyIGhhdCBub2NoIG5pZW1hbmQgZWluZW4gSGlnaHNjb3JlIGF1Zmdlc3RlbGx0IVxuXG5cblxuXG5cblxuXG5cblxuXG5cblxuXG5cbjwxPiBadXJcMjAxY2sgenVtIEhhdXB0bWVuXDIwMSIpOyAvLyBmYWxscyBuZWluLCBkaWVzIGF1c2dlYmVuCgkJCQkJaW50IGF1c3dhaGwgPSBfZ2V0Y2goKTsJCQkJCQkvLyB6dXLDvGNrIHp1bSBNZW7DvCBBYmZyYWdlIChmYWxscyAxIGdlZHLDvGNrdCB3aXJkKQoJCQkJCWlmKGF1c3dhaGwgPT0gNDkpCgkJCQkJewoJCQkJCQlyZXR1cm47CgkJCQkJfQoJCQkJCWZjbG9zZShGRGF0ZWkpOwkJCQkJCQkJLy8gRGF0ZWkgc2NobGllc3NlbgoJCQkJfQoJCQkJZWxzZQoJCQkJewoJCQkJCWZjbG9zZShGRGF0ZWkpOwkJCQkJCQkKCQkJCQlGRGF0ZWkgPSBmb3BlbihwZmFkLCAiciIpOwkJCQkJLy8gbm9jaCBlaW5tYWwgc2NobGllw59lbiB1bmQgw7ZmZm5lbiwgdW0gd2llZGVyIGFtIEFuZmFuZyBkZXIgRGF0ZWkgenUgYmVnaW5uZW4KCQkJCQl3aGlsZSAoZmdldHMoZWlubGVzZW4sNTAsRkRhdGVpKSkJCQkvLyBhbnNvbnN0ZW4gSGlnaHNjb3JlIGF1c2dlYmVuICYgbGVzZSBiaXMgRGF0ZWllbmRlCgkJCQkJewkKCQkJCQkJYXVzZ2FiZSA9IHN0cmNociAoZWlubGVzZW4sICcuJyk7CQkvLyBQdW5rdCBpbSBlaW5nZWxlc2VuZW4gU3RyaW5nIHN1Y2hlbgoJCQkJCQlhdXNnYWJlICs9IDE7CQkJCQkJCS8vIFplaWdlciB1bSAxIG5hY2ggcmVjaHRzIHZlcnNjaGllYmVuLCB1bSBkZW4gUHVua3QgbmljaHQgbWl0IGF1c3p1Z2ViZW4KCQkJCQkJcHJpbnRmKCIlaS4gJXMiLCBpLCBhdXNnYWJlKTsJCQkvLyBiZWFyYmVpdGV0ZW4gU3RyaW5nIGF1c2dlYmVuCgkJCQkJCWkrKzsJCQkJCQkJCQkvLyBWb3J6ZWljaGVuICgxLiAsIDIuICwgMy4uLi4pIGbDvHIgQXVzZ2FiZSBlcmjDtmhlbgoJCQkJCX0JCgkJCQkJZmNsb3NlKEZEYXRlaSk7CQkJCQkJCQkvLyBEYXRlaSBzY2hsaWVzc2VuCgkJCQkJcHJpbnRmKCJcblxuXG5cblxuXG5cblxuXG5cblxuXG5cblxuXG5cbjwxPiBadXJcMjAxY2sgenVtIEhhdXB0bWVuXDIwMSIpOwkvLyBmYWxscyBIaWdoc2NvcmUgRGF0ZWkgbm9jaCBuaWNodCB2b3JoYW5kZW4sIGVyc3RlbGxlIGRpZXNlCgoJCQkJCWludCBhdXN3YWhsID0gX2dldGNoKCk7CQkJCQkJLy8genVyw7xjayB6dW0gTWVuw7wgQWJmcmFnZSAoZmFsbHMgMSBnZWRyw7xja3Qgd2lyZCkKCQkJCQlpZihhdXN3YWhsID09IDQ5KQoJCQkJCXsKCQkJCQkJcmV0dXJuOwoJCQkJCX0KCQkJCX0KCQkJfQoJCQlpZihhdXN3YWhsID09IDUzKQkJCQkJCQkJCS8vIGZhbGxzICIxIiBnZWRyw7xja3Qgd3VyZGUsIE1laHJzcGllbGVyLnR4dCBhdXNnZWJlbgoJCQl7CgkJCQlGSUxFKiBGRGF0ZWk7CQkJCQkJCQkJLy8gWmVpZ2VyIGF1ZiBIaWdoc2NvcmUgdHh0IGVyc3RlbGxlbgoJCQkJc3RyY3B5KHBmYWQsICJDOlxcTWVocnNwaWVsZXIudHh0Iik7CQkJLy8gUGZhZCBmw7xyIGRpZSBNZWhyc3BpZWxlci50eHQgaW4gZGFzIGNoYXIgQXJyYXkgcGZhZCBrb3BpZXJlbgoJCQkJRkRhdGVpID0gZm9wZW4ocGZhZCwgInIiKTsJCQkJCQkvLyBNZWhyc3BpZWxlci50eHQgw7ZmZm5lbiB1bmQgbGVzZW4KCQkJCWludCBpID0gMTsJCQkJCQkJCQkJLy8gU3RhcnR3ZXJ0IGbDvHIgVm9yemVpY2hlbiAoMS4gLCAyLiAsIDMuLi4uKSBmw7xyIEF1c2dhYmUgZXJow7ZoZW4KCgkJCQlpZighRkRhdGVpKQkJCQkJCQkJCQkvLyBnaWJ0IGVzIGRpZSBBbWF0ZXVyLnR4dCBub2NoIG5pY2h0PwoJCQkJewoJCQkJCUZEYXRlaSA9IGZvcGVuKHBmYWQsICJ3Iik7CQkJCQkvLyBmYWxscyBNZWhyc3BpZWxlci50eHQgbm9jaCBuaWNodCB2b3JoYW5kZW4sIGVyc3RlbGxlIGRpZXNlCgkJCQkJZmNsb3NlKEZEYXRlaSk7CgkJCQkJcHJpbnRmKCJcbkxlaWRlciBoYXQgbm9jaCBuaWVtYW5kIGVpbmVuIEhpZ2hzY29yZSBhdWZnZXN0ZWxsdCFcblxuXG5cblxuXG5cblxuXG5cblxuXG5cblxuXG48MT4gWnVyXDIwMWNrIHp1bSBIYXVwdG1lblwyMDEiKTsJCgkJCQoJCQkJCWludCBhdXN3YWhsID0gX2dldGNoKCk7CQkJCQkJLy8genVyw7xjayB6dW0gTWVuw7wgQWJmcmFnZSAoZmFsbHMgMSBnZWRyw7xja3Qgd2lyZCB6dXLDvGNrIHp1bSBtTmXDvCkKCQkJCQlpZihhdXN3YWhsID09IDQ5KQkJCQkJCgkJCQkJewoJCQkJCQlyZXR1cm47CgkJCQkJfQoJCQkJfQoJCQkJZWxzZSBpZihmZ2V0cyhlaW5sZXNlbiw1MCxGRGF0ZWkpID09IE5VTEwpCQkvLyBzdGVodCBldHdhcyBpbiBkZXIgTWVocnNwaWVsZXIudHh0PwoJCQkJewoJCQkJCXByaW50ZigiXG5MZWlkZXIgaGF0IG5vY2ggbmllbWFuZCBlaW5lbiBIaWdoc2NvcmUgYXVmZ2VzdGVsbHQhXG5cblxuXG5cblxuXG5cblxuXG5cblxuXG5cblxuPDE+IFp1clwyMDFjayB6dW0gSGF1cHRtZW5cMjAxIik7IC8vIGZhbGxzIG5laW4sIGRpZXMgYXVzZ2ViZW4KCQkJCQlpbnQgYXVzd2FobCA9IF9nZXRjaCgpOwkJCQkJCS8vIHp1csO8Y2sgenVtIE1lbsO8IEFiZnJhZ2UgKGZhbGxzIDEgZ2VkcsO8Y2t0IHdpcmQpCgkJCQkJaWYoYXVzd2FobCA9PSA0OSkKCQkJCQl7CgkJCQkJCXJldHVybjsKCQkJCQl9CgkJCQkJZmNsb3NlKEZEYXRlaSk7CQkJCQkJCQkvLyBEYXRlaSBzY2hsaWVzc2VuCgkJCQl9CgkJCQllbHNlCgkJCQl7CgkJCQkJZmNsb3NlKEZEYXRlaSk7CQkJCQkJCQoJCQkJCUZEYXRlaSA9IGZvcGVuKHBmYWQsICJyIik7CQkJCQkvLyBub2NoIGVpbm1hbCBzY2hsaWXDn2VuIHVuZCDDtmZmbmVuLCB1bSB3aWVkZXIgYW0gQW5mYW5nIGRlciBEYXRlaSB6dSBiZWdpbm5lbgoJCQkJCXdoaWxlIChmZ2V0cyhlaW5sZXNlbiw1MCxGRGF0ZWkpKQkJCS8vIGFuc29uc3RlbiBIaWdoc2NvcmUgYXVzZ2ViZW4gJiBsZXNlIGJpcyBEYXRlaWVuZGUKCQkJCQl7CQoJCQkJCQlhdXNnYWJlID0gc3RyY2hyIChlaW5sZXNlbiwgJy4nKTsJCS8vIFB1bmt0IGltIGVpbmdlbGVzZW5lbiBTdHJpbmcgc3VjaGVuCgkJCQkJCWF1c2dhYmUgKz0gMTsJCQkJCQkJLy8gWmVpZ2VyIHVtIDEgbmFjaCByZWNodHMgdmVyc2NoaWViZW4sIHVtIGRlbiBQdW5rdCBuaWNodCBtaXQgYXVzenVnZWJlbgoJCQkJCQlwcmludGYoIiVpLiAlcyIsIGksIGF1c2dhYmUpOwkJCS8vIGJlYXJiZWl0ZXRlbiBTdHJpbmcgYXVzZ2ViZW4KCQkJCQkJaSsrOwkJCQkJCQkJCS8vIFZvcnplaWNoZW4gKDEuICwgMi4gLCAzLi4uLikgZsO8ciBBdXNnYWJlIGVyaMO2aGVuCgkJCQkJfQkKCQkJCQlmY2xvc2UoRkRhdGVpKTsJCQkJCQkJCS8vIERhdGVpIHNjaGxpZXNzZW4KCQkJCQlwcmludGYoIlxuXG5cblxuXG5cblxuXG5cblxuXG5cblxuXG5cblxuPDE+IFp1clwyMDFjayB6dW0gSGF1cHRtZW5cMjAxIik7CS8vIGZhbGxzIEhpZ2hzY29yZSBEYXRlaSBub2NoIG5pY2h0IHZvcmhhbmRlbiwgZXJzdGVsbGUgZGllc2UKCgkJCQkJaW50IGF1c3dhaGwgPSBfZ2V0Y2goKTsJCQkJCQkvLyB6dXLDvGNrIHp1bSBNZW7DvCBBYmZyYWdlIChmYWxscyAxIGdlZHLDvGNrdCB3aXJkKQoJCQkJCWlmKGF1c3dhaGwgPT0gNDkpCgkJCQkJewoJCQkJCQlyZXR1cm47CgkJCQkJfQoJCQkJfQoJCQl9CgkJCWVsc2UKCQkJewoJCQkJcHJpbnRmKCJcblxuVW5nXDIwMWx0aWdlIEVpbmdhYmUhXG5cbiIpOwoJCQkJU2xlZXAoMjAwMCk7CQkJCQkJCQkJLy8gZmFsbHMgZWluZSBUYXN0ZSwgZGllIG5pY2h0IHp1ciBBdXN3YWhsIHN0ZWh0IGdlZHLDvGNrdCB3dXJkZSwgVW5nw7xsdGlnZSBFaW5nYWJlIGFuemVpZ2VuCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkKCQkJCWhpZ2hzY29yZUF1c2dlYmVuKCk7CQkJCQkJCS8vIHVuZCBoaWdoc2NvcmVBdXNnZWJlbigpIE1ldGhvZGUgbmV1IGF1ZnJ1ZmVuCgkJCX0KCgkJCXN0cmNweShwZmFkLCB6d2lzY2hlblBmYWQpOwkJCQkJCQkvLyB1cnNwcsO8bmdsaWNoZW4gUGZhZCAtPgoJCQlzdHJjcHkoendpc2NoZW5QZmFkLCAiIik7CQkJCQkJCS8vIC0+IHdpZWRlcmhlcnN0ZWxsZW4KCX0KCgkvLyBIaWdoc2NvcmUgaW4gRGF0ZWkgc2NocmVpYmVuCgl2b2lkIGhpZ2hzY29yZUVpbmxlc2VuKCkKCXsKCQkJZG91YmxlIGhpZ2hbMjBdOwkJCQkJCQkJCQkJCQkJCS8vIEFycmF5IGFubGVnZW4sIHVtIGRvcnQgZGllIGF1c2dlbGVzZW5lbiBIaWdoc2NvcmVzIHp3aXNjaGVuenVzcGVpY2hlcm4KCQkJaGlnaFswXSA9IGRpZiwgaGlnaFsxXSA9IGRpZiwgaGlnaFsyXSA9IGRpZiwgaGlnaFszXSA9IGRpZjsJCQkJCS8vIGFsbGUgSGlnaHNjb3JlcyBhdWYgMTAwMCBzZXR6ZW4sIGRhIHNvbnN0IGVpbiBlcnN0ZXIgVmVyZ2xlaWNoIG5pY2h0IG3DtmdsaWNoIHfDpHJlIChoaWdoW2ldID0gMCwgZGlmID0gMjAgLT4gaGlnaFtpXSA8IGRpZikKCQkJRklMRSogRkRhdGVpOwkJCQkJCQkJCQkJCQkJCQkvLyBaZWlnZXIgYXVmIERhdGVpIGVyc3RlbGxlbgoJCQlGRGF0ZWkgPSBmb3BlbihwZmFkLCAiciIpOwkJCQkJCQkJCQkJCQkvLyBaZWlnZXIgYXVmIGRpZSBEYXRlaSBtaXQgZGVtIFBmYWQgZGVyIGluICJwZmFkIiBnZXNwZWljaGVydCBpc3QgcmljaHRlbiB1bmQgZGllc2UgenVtIGxlc2VuIMO2ZmZuZW4KLy8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBaYWhsZW4gZWlubGVzZW4gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCQkJY2hhciBzY29yZVs2MF07CgkJCWNoYXIqIHNjOwkJCQkJCQkJCQkJCQkJCQkJLy8gY2hhciBhcnJheXMsIHVtIGVpbmdlbGVzZW5lIEhpZ2hzY29yZXMgendpc2NoZW56dXNwZWljaGVybgoJCQlpbnQgaSA9IDA7CQkJCQkJCQkJCQkJCQkJCQkvLyBaw6RobHZhcmlhYmxlLCB1bSBBcnJheSBkdXJjaHp1bGF1ZmVuCgkJCXdoaWxlKGZnZXRzKHNjb3JlLDQwLEZEYXRlaSkgIT0gTlVMTCkJCQkJCQkJCQkJLy8gZXJzdGUgWmVpbGUgZGVyIERhdGVpIGVpbmxlc2VuIHVuIHNvbGFuZ2UgZm9ydGZhaHJlbiwgYmlzIGRhcyBEYXRlaWVuZGUgZXJyZWljaHQgaXN0CQkJCgkJCXsJCQkJCQkJCgkJCQlzYyA9IHN0cmNocihzY29yZSwgJzonKTsJCQkJCQkJCQkJCQkvLyBuYWNoIERvcHBlbHB1bmt0IGluIGRlciBqZXdlaWxpZ2VuIFplaWxlIHN1Y2hlbiB1bmQgWmVpZ2VyIGF1ZiBkaWVzZW4gc2V0emVuCgkJCQloaWdoW2ldID0gc3RydG9kKHNjKzEsTlVMTCk7CQkJCQkJCQkJCQkvLyBhYiBkZW0gRG9wcGVscHVua3QgKyAxIFplaWNoZW4gZGFoaW50ZXIgYWxsZXMgZWlubGVzZW4gdW5kIGluIGRvdWJsZSBrb252ZXJ0aWVyZW4uIEVuZGVyZ2VibmlzIGluIGRvdWJsZSBhcnJheSBzcC4KCQkJCWkrKzsJCQkJCQkJCQkJCQkJCQkJCS8vIFrDpGhsdmFyaWFibGUgZXJow7ZoZW4KCQkJfQoJCQlmY2xvc2UoRkRhdGVpKTsJCQkJCQkJCQkJCQkJCQkJLy8gRGF0ZWkgc2NobGllw59lbgoKLy8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBOYW1lbiBlaW5sZXNlbiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoJCQkKCQkJY2hhciogc3QxID0gMDsKCQkJY2hhciogc3QyID0gMDsKCQkJY2hhciogc3QzID0gMDsKCQkJY2hhciogc3Q0ID0gMDsJCQkJCQkJCQkJCQkJCQkJLy8gWmVpZ2VyIGVyc3RlbGxlbiBmw7xyIHNww6R0ZXJlIFZlcmFyYmVpdHVuZyBkZXIgZWluZ2VsZXNlbmVuIFN0cmluZ3MKCQkJY2hhciogc3Q1ID0gMDsKCQkJY2hhciogc3Q2ID0gMDsKCQkJY2hhciogc3Q3ID0gMDsKCQkJY2hhciogc3Q4ID0gMDsKCQkJY2hhciogc3Q5ID0gMDsKCQkJY2hhciogcHRyID0gIjoiOwkJCQkJCQkJCQkJCQkJCS8vIFN1Y2hrcml0ZXJpdW0gZsO8ciBzdHJ0b2sgZmVzdGxlZ2VuCgkJCUZEYXRlaSA9IGZvcGVuKHBmYWQsICJyIik7CQkJCQkJCQkJCQkJCS8vIERhdGVpIGVybmV1dCDDtmZmbmVuIHVuZCBsZXNlbgoJCQkKCQkJaWYoZmdldHMoc2NvcmUsNjAsRkRhdGVpKSAhPSBOVUxMKQkJCQkJCQkJCQkJLy8gZXJzdGUgWmVpbGUgZGVyIERhdGVpIGVpbmxlc2VuIHVuZCBmb3J0ZmFocmVuLCBmYWxscyBpbiBkaWVzZXIgZXR3YXMgc3RlaHQJCgkJCXsKCQkJCWZjbG9zZShGRGF0ZWkpOwkJCQkJCQkJCQkJCQkJCS8vIERhdGVpIHNjaGxpZcOfZW4KCQkJCUZEYXRlaSA9IGZvcGVuKHBmYWQsICJyIik7CQkJCQkJCQkJCQkJLy8gRGF0ZWkgZXJuZXV0IMO2ZmZuZW4gdW5kIGxlc2VuIHVtIHdpZWRlciBhbSBEYXRlaWFuZmFuZyB6dSBzdGFydGVuCgkJCQkKCQkJCWNoYXIgcGxhdHoxWzYwXSA9ICIiOwkJCQkJCQkJCQkJCQkvLyBjaGFyIGFycmF5IHp1bSB6d2lzY2hlbnNwZWljaGVybiBkZXMgZWluZ2VsZXNlbmVuIFN0cmluZwoJCQkJaWYoZmdldHMocGxhdHoxLDYwLEZEYXRlaSkgIT0gTlVMTCkJCQkJCQkJCQkJLy8gZXJzdGUgWmVpbGUgZGVyIERhdGVpIGVpbmxlc2VuIHVuZCBmb3J0ZmFocmVuLCBmYWxscyBpbiBkaWVzZXIgZXR3YXMgc3RlaHQJCgkJCQl7CgkJCQkJc3QxID0gc3RyY2hyIChwbGF0ejEsICcuJyk7CQkJCQkJCQkJCQkvLyBpbiBkZW0gZWluZ2VsZXNlbmVuIFN0cmluZyBlaW5lbiAiLiIgc3VjaGVuLiBIaWdoc2NvcmVzIHdlcmRlbiBpbSBmb2xnZW5kZW4gRm9ybWF0IGFiZ2VzcGVpY2hlcnQ6IC5NYXJjZWwncyBaZWl0OiAycwoJCQkJCXN0MSArPSAxOwkJCQkJCQkJCQkJCQkJCS8vIFplaWdlciB1bSAxIG5hY2ggcmVjaHRzIHZlcnNjaGllYmVuLCB1bSBkZW4gUHVua3QgbmljaHQgbWl0IGF1c3p1Z2ViZW4KCQkJCQlzdHJ0b2soc3QxLHB0cik7CQkJCQkJCQkJCQkJCS8vIERlbiBaZWlnZXIgc293ZWl0IHZlcnNjaGllYmVuLCBiaXMgZWluICI6IiBnZWZ1bmRlbiB3dXJkZSB1bmQgZGllc2VuIHNvd2llIGFsbGVzIGRhaGludGVyIHZvbSBTdHJpbmcgYWJ0cmVubmVuCgkJCQl9CgoJCQkJY2hhciBwbGF0ejJbNjBdID0gIiI7CgkJCQlpZihmZ2V0cyhwbGF0ejIsNjAsRkRhdGVpKSAhPSBOVUxMKQkJCQkJCQkJCQkvLyBEaWVzZXMgVmVyZmFocmVuIHdpcmQgYXVjaCBmw7xyIGRpZSBmb2xnZW5kZW4gV2VydGUgdmVyd2VuZGV0LiBFcyBzaW5kIG1heGltYWwgMTAgV2VydGUgc3BlaWNoZXJiYXIuCgkJCQl7CgkJCQkJc3QyID0gc3RyY2hyIChwbGF0ejIsICcuJyk7CgkJCQkJc3QyICs9IDE7CgkJCQkJc3RydG9rKHN0MixwdHIpOwoJCQkJfQoJCQkJCgkJCQljaGFyIHBsYXR6M1s2MF0gPSAiIjsKCQkJCWlmKGZnZXRzKHBsYXR6Myw2MCxGRGF0ZWkpICE9IE5VTEwpIAoJCQkJewoJCQkJCXN0MyA9IHN0cmNociAocGxhdHozLCAnLicpOwoJCQkJCXN0MyArPSAxOwoJCQkJCXN0cnRvayhzdDMscHRyKTt9CgkJCQl9CgkJCQkKCQkJCWNoYXIgcGxhdHo0WzYwXSA9ICIiOwoJCQkJaWYoZmdldHMocGxhdHo0LDYwLEZEYXRlaSkgIT0gTlVMTCkgCgkJCQl7CgkJCQkJc3Q0ID0gc3RyY2hyIChwbGF0ejQsICcuJyk7CgkJCQkJc3Q0ICs9IDE7CgkJCQkJc3RydG9rKHN0NCxwdHIpOwoJCQkJfQoKCQkJCWNoYXIgcGxhdHo1WzYwXSA9ICIiOwoJCQkJaWYoZmdldHMocGxhdHo1LDYwLEZEYXRlaSkgIT0gTlVMTCkgCgkJCQl7CgkJCQkJc3Q1ID0gc3RyY2hyIChwbGF0ejUsICcuJyk7CgkJCQkJc3Q1ICs9IDE7CgkJCQkJc3RydG9rKHN0NSxwdHIpOwoJCQkJfQoKCQkJCWNoYXIgcGxhdHo2WzYwXSA9ICIiOwoJCQkJaWYoZmdldHMocGxhdHo2LDYwLEZEYXRlaSkgIT0gTlVMTCkgCgkJCQl7CgkJCQkJc3Q2ID0gc3RyY2hyIChwbGF0ejYsICcuJyk7CgkJCQkJc3Q2ICs9IDE7CgkJCQkJc3RydG9rKHN0NixwdHIpOwoJCQkJfQoKCQkJCWNoYXIgcGxhdHo3WzYwXSA9ICIiOwoJCQkJaWYoZmdldHMocGxhdHo3LDYwLEZEYXRlaSkgIT0gTlVMTCkgCgkJCQl7CgkJCQkJc3Q3ID0gc3RyY2hyIChwbGF0ejcsICcuJyk7CgkJCQkJc3Q3ICs9IDE7CgkJCQkJc3RydG9rKHN0NyxwdHIpOwoJCQkJfQoKCQkJCWNoYXIgcGxhdHo4WzYwXSA9ICIiOwoJCQkJaWYoZmdldHMocGxhdHo4LDYwLEZEYXRlaSkgIT0gTlVMTCkgCgkJCQl7CgkJCQkJc3Q4ID0gc3RyY2hyIChwbGF0ejgsICcuJyk7CgkJCQkJc3Q4ICs9IDE7CgkJCQkJc3RydG9rKHN0OCxwdHIpOwoJCQkJfQoKCQkJCWNoYXIgcGxhdHo5WzYwXSA9ICIiOwoJCQkJaWYoZmdldHMocGxhdHo5LDYwLEZEYXRlaSkgIT0gTlVMTCkgCgkJCQl7CgkJCQkJc3Q5ID0gc3RyY2hyIChwbGF0ejksICcuJyk7CgkJCQkJc3Q5ICs9IDE7CgkJCQkJc3RydG9rKHN0OSxwdHIpOwoJCQkJfQoJCQkJZmNsb3NlKEZEYXRlaSk7CQkJCQkJCQkJCQkJCQkJLy8gRGF0ZWkgc2NobGllw59lbgoKCQkJCUZEYXRlaSA9IGZvcGVuKHBmYWQsIncrIik7CQkJCQkJCQkJCQkJLy8gRGF0ZWkgw7ZmZm5lbiB1bmQgYmVhcmJlaXRlbgoJCQoJCWlmKGRpZiA8PSBoaWdoWzBdKQkJCQkJCQkJCQkJCQkJCQkvLyBmYWxscyBkaWYgKG5ldWUgSGlnaHNjb3JlIFplaXQpIGJlc3NlciBhbHMgZGVyIGFrdHVlbGxlIFBsYXR6IDEgZ2VzcGVpY2hlcnQgaW4gaGlnaFswXSBpc3QuLi4uCgkJewoJCQloaWdoWzldID0gaGlnaFs4XTsKCQkJaGlnaFs4XSA9IGhpZ2hbN107CgkJCWhpZ2hbN10gPSBoaWdoWzZdOwkJCQkJCQkJCQkJCQkJCS8vIERhbm4gdmVyc2NoaWViZSBhbGxlIEhpZ2hzY29yZXMgdW0gZWluZW4gUGxhdHogbmFjaCB1bnRlbgoJCQloaWdoWzZdID0gaGlnaFs1XTsKCQkJaGlnaFs1XSA9IGhpZ2hbNF07CgkJCWhpZ2hbNF0gPSBoaWdoWzNdOwoJCQloaWdoWzNdID0gaGlnaFsyXTsKCQkJaGlnaFsyXSA9IGhpZ2hbMV07CgkJCWhpZ2hbMV0gPSBoaWdoWzBdOwoJCQloaWdoWzBdID0gZGlmOwkJCQkJCQkJCQkJCQkJCQkvLyB1bmQgc2V0emUgZGVuIG5ldWVuIEJlc3R3ZXJ0KGRpZikgYXVmIGRlbiBQbGF0ejEKCQkJaWYobmFtZSAhPSBOVUxMKWZwcmludGYoRkRhdGVpLCAiLiVzJ3MgWmVpdDogJS4yZnNcbiIsbmFtZSxoaWdoWzBdKTsJCS8vIHdlbm4gZWluIE5hbWUoaW4gZGVyIE1ldGhvZGUgc3BpZWxlbikgZWluZ2VnZWJlbiB3dXJkZSwgc28gd2lyZCBkaWVzZXIgbnVuIG1pdCBkZW0gbmV1ZW4gQmVzdHdlcnQgaW0gRm9ybWF0CgkJCWlmKHN0MSAhPSBOVUxMKWZwcmludGYoRkRhdGVpLCAiLiVzOiAlLjJmc1xuIixzdDEsaGlnaFsxXSk7CQkJCQkvLyAuSmVtYW5kJ3MgWmVpdDogMjAuMDBzIGFiZ2VzcGVpY2hlcnQKCQkJaWYoc3QyICE9IE5VTEwpZnByaW50ZihGRGF0ZWksICIuJXM6ICUuMmZzXG4iLHN0MixoaWdoWzJdKTsKCQkJaWYoc3QzICE9IE5VTEwpZnByaW50ZihGRGF0ZWksICIuJXM6ICUuMmZzXG4iLHN0MyxoaWdoWzNdKTsJCQkJCS8vIG51biBhbGxlIGFuZGVyZW4gV2VydGUgaW4gZGllIERhdGVpIHNjaHJlaWJlbiwgc29sYW5nZSBkaWVzZSB1bmdsZWljaCBOdWxsIHNpbmQuIFdpcmQgZGVyIFdlcnQgTnVsbCBlcnJlaWNodCwgc28KCQkJaWYoc3Q0ICE9IE5VTEwpZnByaW50ZihGRGF0ZWksICIuJXM6ICUuMmZzXG4iLHN0NCxoaWdoWzRdKTsJCQkJCS8vIHdlcmRlbiBhbGxlIHJlc3RsaWNoZW4gU2NocmVpYnZvcmfDpG5nZSDDvGJlcnNwcnVuZ2VuLCBkYSBrZWluZSB3ZWl0ZXJlbiBIaWdoc2NvcmVzIGJpc2hlciBhdWZnZXN0ZWxsdCB3dXJkZW4KCQkJaWYoc3Q1ICE9IE5VTEwpZnByaW50ZihGRGF0ZWksICIuJXM6ICUuMmZzXG4iLHN0NSxoaWdoWzVdKTsJCQoJCQlpZihzdDYgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3Q2LGhpZ2hbNl0pOwoJCQlpZihzdDcgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3Q3LGhpZ2hbN10pOwoJCQlpZihzdDggIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3Q4LGhpZ2hbOF0pOwoJCQlpZihzdDkgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnMiLHN0OSxoaWdoWzldKTsKCQl9CgkJZWxzZSBpZihkaWYgPiBoaWdoWzBdICYmIGRpZiA8PSBoaWdoWzFdKQoJCXsKCQkJaGlnaFs5XSA9IGhpZ2hbOF07CgkJCWhpZ2hbOF0gPSBoaWdoWzddOwoJCQloaWdoWzddID0gaGlnaFs2XTsKCQkJaGlnaFs2XSA9IGhpZ2hbNV07CgkJCWhpZ2hbNV0gPSBoaWdoWzRdOwoJCQloaWdoWzRdID0gaGlnaFszXTsKCQkJaGlnaFszXSA9IGhpZ2hbMl07CgkJCWhpZ2hbMl0gPSBoaWdoWzFdOwoJCQloaWdoWzFdID0gZGlmOwoJCQlpZihzdDEgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3QxLGhpZ2hbMF0pOwkJCQkJLy8gRGllIGZvbGdlbmRlbiBCbMO2Y2tlIGJhc2llcmVuIGF1ZiBkZW0gc2VsYmVuIFByaW56aXAgbWl0IGplZG9jaCBhbmdlcGFzc3RlbiBCZWRpbmd1bmdlbgoJCQlpZihuYW1lICE9IE5VTEwpZnByaW50ZihGRGF0ZWksICIuJXMncyBaZWl0OiAlLjJmc1xuIixuYW1lLGhpZ2hbMV0pOwoJCQlpZihzdDIgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3QyLGhpZ2hbMl0pOwoJCQlpZihzdDMgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3QzLGhpZ2hbM10pOwoJCQlpZihzdDQgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3Q0LGhpZ2hbNF0pOwoJCQlpZihzdDUgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3Q1LGhpZ2hbNV0pOwoJCQlpZihzdDYgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3Q2LGhpZ2hbNl0pOwoJCQlpZihzdDcgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3Q3LGhpZ2hbN10pOwoJCQlpZihzdDggIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3Q4LGhpZ2hbOF0pOwoJCQlpZihzdDkgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnMiLHN0OSxoaWdoWzldKTsKCQl9CgkJZWxzZSBpZihkaWYgPiBoaWdoWzBdICYmIGRpZiA+IGhpZ2hbMV0gJiYgZGlmIDw9IGhpZ2hbMl0pCgkJewoJCQloaWdoWzldID0gaGlnaFs4XTsKCQkJaGlnaFs4XSA9IGhpZ2hbN107CgkJCWhpZ2hbN10gPSBoaWdoWzZdOwoJCQloaWdoWzZdID0gaGlnaFs1XTsKCQkJaGlnaFs1XSA9IGhpZ2hbNF07CgkJCWhpZ2hbNF0gPSBoaWdoWzNdOwoJCQloaWdoWzNdID0gaGlnaFsyXTsKCQkJaGlnaFsyXSA9IGRpZjsKCQkJaWYoc3QxICE9IE5VTEwpZnByaW50ZihGRGF0ZWksICIuJXM6ICUuMmZzXG4iLHN0MSxoaWdoWzBdKTsKCQkJaWYoc3QyICE9IE5VTEwpZnByaW50ZihGRGF0ZWksICIuJXM6ICUuMmZzXG4iLHN0MixoaWdoWzFdKTsKCQkJaWYobmFtZSAhPSBOVUxMKWZwcmludGYoRkRhdGVpLCAiLiVzJ3MgWmVpdDogJS4yZnNcbiIsbmFtZSxoaWdoWzJdKTsKCQkJaWYoc3QzICE9IE5VTEwpZnByaW50ZihGRGF0ZWksICIuJXM6ICUuMmZzXG4iLHN0MyxoaWdoWzNdKTsKCQkJaWYoc3Q0ICE9IE5VTEwpZnByaW50ZihGRGF0ZWksICIuJXM6ICUuMmZzXG4iLHN0NCxoaWdoWzRdKTsKCQkJaWYoc3Q1ICE9IE5VTEwpZnByaW50ZihGRGF0ZWksICIuJXM6ICUuMmZzXG4iLHN0NSxoaWdoWzVdKTsKCQkJaWYoc3Q2ICE9IE5VTEwpZnByaW50ZihGRGF0ZWksICIuJXM6ICUuMmZzXG4iLHN0NixoaWdoWzZdKTsKCQkJaWYoc3Q3ICE9IE5VTEwpZnByaW50ZihGRGF0ZWksICIuJXM6ICUuMmZzXG4iLHN0NyxoaWdoWzddKTsKCQkJaWYoc3Q4ICE9IE5VTEwpZnByaW50ZihGRGF0ZWksICIuJXM6ICUuMmZzXG4iLHN0OCxoaWdoWzhdKTsKCQkJaWYoc3Q5ICE9IE5VTEwpZnByaW50ZihGRGF0ZWksICIuJXM6ICUuMmZzIixzdDksaGlnaFs5XSk7CgkJfQoJCWVsc2UgaWYoZGlmID4gaGlnaFswXSAmJiBkaWYgPj0gaGlnaFsxXSAmJiBkaWYgPiBoaWdoWzJdICYmIGRpZiA8PSBoaWdoWzNdKQoJCXsKCgkJCWhpZ2hbOV0gPSBoaWdoWzhdOwoJCQloaWdoWzhdID0gaGlnaFs3XTsKCQkJaGlnaFs3XSA9IGhpZ2hbNl07CgkJCWhpZ2hbNl0gPSBoaWdoWzVdOwoJCQloaWdoWzVdID0gaGlnaFs0XTsKCQkJaGlnaFs0XSA9IGhpZ2hbM107CgkJCWhpZ2hbM10gPSBkaWY7CgkJCWlmKHN0MSAhPSBOVUxMKWZwcmludGYoRkRhdGVpLCAiLiVzOiAlLjJmc1xuIixzdDEsaGlnaFswXSk7CgkJCWlmKHN0MiAhPSBOVUxMKWZwcmludGYoRkRhdGVpLCAiLiVzOiAlLjJmc1xuIixzdDIsaGlnaFsxXSk7CgkJCWlmKHN0MyAhPSBOVUxMKWZwcmludGYoRkRhdGVpLCAiLiVzOiAlLjJmc1xuIixzdDMsaGlnaFsyXSk7CgkJCWlmKG5hbWUgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lcydzIFplaXQ6ICUuMmZzXG4iLG5hbWUsaGlnaFszXSk7CgkJCWlmKHN0NCAhPSBOVUxMKWZwcmludGYoRkRhdGVpLCAiLiVzOiAlLjJmc1xuIixzdDQsaGlnaFs0XSk7CgkJCWlmKHN0NSAhPSBOVUxMKWZwcmludGYoRkRhdGVpLCAiLiVzOiAlLjJmc1xuIixzdDUsaGlnaFs1XSk7CgkJCWlmKHN0NiAhPSBOVUxMKWZwcmludGYoRkRhdGVpLCAiLiVzOiAlLjJmc1xuIixzdDYsaGlnaFs2XSk7CgkJCWlmKHN0NyAhPSBOVUxMKWZwcmludGYoRkRhdGVpLCAiLiVzOiAlLjJmc1xuIixzdDcsaGlnaFs3XSk7CgkJCWlmKHN0OCAhPSBOVUxMKWZwcmludGYoRkRhdGVpLCAiLiVzOiAlLjJmc1xuIixzdDgsaGlnaFs4XSk7CgkJCWlmKHN0OSAhPSBOVUxMKWZwcmludGYoRkRhdGVpLCAiLiVzOiAlLjJmcyIsc3Q5LGhpZ2hbOV0pOwoJCX0KCQllbHNlIGlmKGRpZiA+IGhpZ2hbM10gJiYgZGlmIDw9IGhpZ2hbNF0pCgkJewoKCQkJaGlnaFs5XSA9IGhpZ2hbOF07CgkJCWhpZ2hbOF0gPSBoaWdoWzddOwoJCQloaWdoWzddID0gaGlnaFs2XTsKCQkJaGlnaFs2XSA9IGhpZ2hbNV07CgkJCWhpZ2hbNV0gPSBoaWdoWzRdOwoJCQloaWdoWzRdID0gZGlmOwoJCQlpZihzdDEgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3QxLGhpZ2hbMF0pOwoJCQlpZihzdDIgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3QyLGhpZ2hbMV0pOwoJCQlpZihzdDMgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3QzLGhpZ2hbMl0pOwoJCQlpZihzdDQgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3Q0LGhpZ2hbM10pOwoJCQlpZihuYW1lICE9IE5VTEwpZnByaW50ZihGRGF0ZWksICIuJXMncyBaZWl0OiAlLjJmc1xuIixuYW1lLGhpZ2hbNF0pOwoJCQlpZihzdDUgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3Q1LGhpZ2hbNV0pOwoJCQlpZihzdDYgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3Q2LGhpZ2hbNl0pOwoJCQlpZihzdDcgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3Q3LGhpZ2hbN10pOwoJCQlpZihzdDggIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3Q4LGhpZ2hbOF0pOwoJCQlpZihzdDkgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnMiLHN0OSxoaWdoWzldKTsKCQkKCQl9CgkJZWxzZSBpZihkaWYgPiBoaWdoWzRdICYmIGRpZiA8PSBoaWdoWzVdKQoJCXsKCQkJaGlnaFs5XSA9IGhpZ2hbOF07CgkJCWhpZ2hbOF0gPSBoaWdoWzddOwoJCQloaWdoWzddID0gaGlnaFs2XTsKCQkJaGlnaFs2XSA9IGhpZ2hbNV07CgkJCWhpZ2hbNV0gPSBkaWY7CgkJCWlmKHN0MSAhPSBOVUxMKWZwcmludGYoRkRhdGVpLCAiLiVzOiAlLjJmc1xuIixzdDEsaGlnaFswXSk7CgkJCWlmKHN0MiAhPSBOVUxMKWZwcmludGYoRkRhdGVpLCAiLiVzOiAlLjJmc1xuIixzdDIsaGlnaFsxXSk7CgkJCWlmKHN0MyAhPSBOVUxMKWZwcmludGYoRkRhdGVpLCAiLiVzOiAlLjJmc1xuIixzdDMsaGlnaFsyXSk7CgkJCWlmKHN0NCAhPSBOVUxMKWZwcmludGYoRkRhdGVpLCAiLiVzOiAlLjJmc1xuIixzdDQsaGlnaFszXSk7CgkJCWlmKHN0NSAhPSBOVUxMKWZwcmludGYoRkRhdGVpLCAiLiVzOiAlLjJmc1xuIixzdDUsaGlnaFs0XSk7CgkJCWlmKG5hbWUgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lcydzIFplaXQ6ICUuMmZzXG4iLG5hbWUsaGlnaFs1XSk7CgkJCWlmKHN0NiAhPSBOVUxMKWZwcmludGYoRkRhdGVpLCAiLiVzOiAlLjJmc1xuIixzdDYsaGlnaFs2XSk7CgkJCWlmKHN0NyAhPSBOVUxMKWZwcmludGYoRkRhdGVpLCAiLiVzOiAlLjJmc1xuIixzdDcsaGlnaFs3XSk7CgkJCWlmKHN0OCAhPSBOVUxMKWZwcmludGYoRkRhdGVpLCAiLiVzOiAlLjJmc1xuIixzdDgsaGlnaFs4XSk7CgkJCWlmKHN0OSAhPSBOVUxMKWZwcmludGYoRkRhdGVpLCAiLiVzOiAlLjJmcyIsc3Q5LGhpZ2hbOV0pOwoJCX0KCQllbHNlIGlmKGRpZiA+IGhpZ2hbNV0gJiYgZGlmIDw9IGhpZ2hbNl0pCgkJewoJCQloaWdoWzldID0gaGlnaFs4XTsKCQkJaGlnaFs4XSA9IGhpZ2hbN107CgkJCWhpZ2hbN10gPSBoaWdoWzZdOwoJCQloaWdoWzZdID0gZGlmOwoJCQlpZihzdDEgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3QxLGhpZ2hbMF0pOwoJCQlpZihzdDIgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3QyLGhpZ2hbMV0pOwoJCQlpZihzdDMgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3QzLGhpZ2hbMl0pOwoJCQlpZihzdDQgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3Q0LGhpZ2hbM10pOwoJCQlpZihzdDUgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3Q1LGhpZ2hbNF0pOwoJCQlpZihzdDYgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3Q2LGhpZ2hbNV0pOwoJCQlpZihuYW1lICE9IE5VTEwpZnByaW50ZihGRGF0ZWksICIuJXMncyBaZWl0OiAlLjJmc1xuIixuYW1lLGhpZ2hbNl0pOwoJCQlpZihzdDcgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3Q3LGhpZ2hbN10pOwoJCQlpZihzdDggIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3Q4LGhpZ2hbOF0pOwoJCQlpZihzdDkgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnMiLHN0OSxoaWdoWzldKTsKCQl9CgkJZWxzZSBpZihkaWYgPiBoaWdoWzZdICYmIGRpZiA8PSBoaWdoWzddKQoJCXsKCQkJaGlnaFs5XSA9IGhpZ2hbOF07CgkJCWhpZ2hbOF0gPSBoaWdoWzddOwoJCQloaWdoWzddID0gZGlmOwoJCQlpZihzdDEgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3QxLGhpZ2hbMF0pOwoJCQlpZihzdDIgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3QyLGhpZ2hbMV0pOwoJCQlpZihzdDMgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3QzLGhpZ2hbMl0pOwoJCQlpZihzdDQgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3Q0LGhpZ2hbM10pOwoJCQlpZihzdDUgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3Q1LGhpZ2hbNF0pOwoJCQlpZihzdDYgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3Q2LGhpZ2hbNV0pOwoJCQlpZihzdDcgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3Q3LGhpZ2hbNl0pOwoJCQlpZihuYW1lICE9IE5VTEwpZnByaW50ZihGRGF0ZWksICIuJXMncyBaZWl0OiAlLjJmc1xuIixuYW1lLGhpZ2hbN10pOwoJCQlpZihzdDggIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3Q4LGhpZ2hbOF0pOwoJCQlpZihzdDkgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnMiLHN0OSxoaWdoWzldKTsKCQl9CgkJZWxzZSBpZihkaWYgPiBoaWdoWzddICYmIGRpZiA8PSBoaWdoWzhdKQoJCXsKCQkJaGlnaFs5XSA9IGhpZ2hbOF07CgkJCWhpZ2hbOF0gPSBkaWY7CgkJCWlmKHN0MSAhPSBOVUxMKWZwcmludGYoRkRhdGVpLCAiLiVzOiAlLjJmc1xuIixzdDEsaGlnaFswXSk7CgkJCWlmKHN0MiAhPSBOVUxMKWZwcmludGYoRkRhdGVpLCAiLiVzOiAlLjJmc1xuIixzdDIsaGlnaFsxXSk7CgkJCWlmKHN0MyAhPSBOVUxMKWZwcmludGYoRkRhdGVpLCAiLiVzOiAlLjJmc1xuIixzdDMsaGlnaFsyXSk7CgkJCWlmKHN0NCAhPSBOVUxMKWZwcmludGYoRkRhdGVpLCAiLiVzOiAlLjJmc1xuIixzdDQsaGlnaFszXSk7CgkJCWlmKHN0NSAhPSBOVUxMKWZwcmludGYoRkRhdGVpLCAiLiVzOiAlLjJmc1xuIixzdDUsaGlnaFs0XSk7CgkJCWlmKHN0NiAhPSBOVUxMKWZwcmludGYoRkRhdGVpLCAiLiVzOiAlLjJmc1xuIixzdDYsaGlnaFs1XSk7CgkJCWlmKHN0NyAhPSBOVUxMKWZwcmludGYoRkRhdGVpLCAiLiVzOiAlLjJmc1xuIixzdDcsaGlnaFs2XSk7CgkJCWlmKHN0OCAhPSBOVUxMKWZwcmludGYoRkRhdGVpLCAiLiVzOiAlLjJmc1xuIixzdDgsaGlnaFs3XSk7CgkJCWlmKG5hbWUgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lcydzIFplaXQ6ICUuMmZzXG4iLG5hbWUsaGlnaFs4XSk7CgkJCWlmKHN0OSAhPSBOVUxMKWZwcmludGYoRkRhdGVpLCAiLiVzOiAlLjJmcyIsc3Q5LGhpZ2hbOV0pOwoJCX0KCQllbHNlIGlmKGRpZiA+IGhpZ2hbOF0gJiYgZGlmIDw9IGhpZ2hbOV0pCgkJewoJCQloaWdoWzldID0gZGlmOwoJCQlpZihzdDEgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3QxLGhpZ2hbMF0pOwoJCQlpZihzdDIgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3QyLGhpZ2hbMV0pOwoJCQlpZihzdDMgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3QzLGhpZ2hbMl0pOwoJCQlpZihzdDQgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3Q0LGhpZ2hbM10pOwoJCQlpZihzdDUgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3Q1LGhpZ2hbNF0pOwoJCQlpZihzdDYgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3Q2LGhpZ2hbNV0pOwoJCQlpZihzdDcgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3Q3LGhpZ2hbNl0pOwoJCQlpZihzdDggIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3Q4LGhpZ2hbN10pOwoJCQlpZihzdDkgIT0gTlVMTClmcHJpbnRmKEZEYXRlaSwgIi4lczogJS4yZnNcbiIsc3Q5LGhpZ2hbOF0pOwoJCQlpZihuYW1lICE9IE5VTEwpZnByaW50ZihGRGF0ZWksICIuJXMncyBaZWl0OiAlLjJmcyIsbmFtZSxoaWdoWzldKTsKCQl9CgkJZmNsb3NlKEZEYXRlaSk7CQkJCQkJCQkJCQkJCQkJCQkvLyBEYXRlaSBzY2hsaWXDn2VuCgl9CgoJLy8gVm9yZ2VoZW4gbmFjaCBTcGllbGVuZGUgYWJmcmFnZW4KCXZvaWQgc3BpZWxlbmRlKCkKCXsKCQlzeXN0ZW0oImNscyIpOwoJCXByaW50ZigiLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4iKTsKCQlwcmludGYoInwgJXMgXHRcdCAgICAgICAgICAgfFxufC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS18Iiwgc3BpZWxlcmdlYm5pcywgZGlmKTsJCQkvLyBUYWJlbGxlIG1pdCBTcGllbGVyZ2Vibmlzc2VuIGFuemVpZ2VuCgkJcHJpbnRmKCJcbnwgRW5kc3RhbmQ6IER1IDwlaT4gIENvbXB1dGVyIDwlaT4gICB8XG4iLHlTY29yZSwgY1Njb3JlKTsKCQlwcmludGYoIi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4iKTsKCQlwcmludGYoIldcMjA0aGxlbiBzaWUgZWluZSBNXDIyNGdsaWNoa2VpdCFcblxuIik7CgkJcHJpbnRmKCI8MT4gWnVyXDIwMWNrIHp1bSBIYXVwdG1lblwyMDFcbiIpOwkJCQkJCQkJCQkJCQkJCS8vIE1lbsO8IG5hY2ggU3BpZWxlbmRlIGRhcnN0ZWxsZW4KCQlwcmludGYoIjwyPiBIaWdoc2NvcmUgYW56ZWlnZW5cbiIpOwoJCUNPT1JEIHA7CgkJcC5YID0gKGludCkgKDIwKTsKCQlwLlkgPSAoaW50KSAoMSk7CgkJU2V0Q29uc29sZUN1cnNvclBvc2l0aW9uKGhPdXQsIHApOwoJCXByaW50ZigiWmVpdDogJS4yZnMiLCBkaWYpOwoJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkKCQlpbnQgYXVzd2FobCA9IF9nZXRjaCgpOwoKCQlpZihhdXN3YWhsID09IDQ5KQkJCQkJCQkJCQkJCQkJCQkJCQkJCS8vIGZhbGxzIDEgZ2VkcsO8Y2t0IHdpcmQsIHp1csO8Y2sgenVtIEhhdXB0bWVuw7wKCQl7CgkJCW1haW5Mb29wID0gMDsKCQkJcmV0dXJuOwoJCX0KCQllbHNlIGlmKGF1c3dhaGwgPT0gNTApCQkJCQkJCQkJCQkJCQkJCQkJCQkvLyBmYWxscyAyIGdlZHLDvGNrdCB3aXJkLCBoaWdoc2NvcmVBdXNnZWJlbigpIE1ldGhvZGUgYXVmcnVmZW4KCQl7CgkJCWhpZ2hzY29yZUF1c2dlYmVuKCk7CgkJfQoJCWVsc2UKCQl7CgkJIHByaW50ZigiXG5cblVuZ1wyMDFsdGlnZSBFaW5nYWJlIVxuXG4iKTsKCQkgU2xlZXAoMjAwMCk7CQkJCQkJCQkJCQkJCQkJCQkJCQkJCS8vIGZhbGxzIGVpbmUgVGFzdGUsIGRpZSBuaWNodCB6dXIgQXVzd2FobCBzdGVodCBnZWRyw7xja3Qgd3VyZGUsIFVuZ8O8bHRpZ2UgRWluZ2FiZSBhbnplaWdlbgoJCSBzeXN0ZW0oImNscyIpOwkJCQkJCQkJCQkJCQkJCQkJCQkJCQkvLyB1bmQgenVyw7xjayB6dW0gSGF1dHBtZW7DvAoJCSBzcGllbGVuZGUoKTsKCQl9CiAJfQoKCS8vIFNwaWVsIGF1c2bDvGhyZW4KCXZvaWQgc3BpZWxlbigpCgl7CgoJCXNldFdpbmRvd1NpemUoNTUsMzkpOwkJCQkJCQkJCQkvLyBLb25zb2xlbmZlbnN0ZXIgYXVmIHBhc3NlbmRlIEdyw7bDn2UgZsO8ciBkYXMgU3BpZWwgc2V0emVuCgoJCS8vIE9iZXJmbMOkY2hlIHplaWNobmVuCiAJCVNldENvbnNvbGVUZXh0QXR0cmlidXRlKCBoT3V0LCAxNSApOwkJCQkJCS8vIFNjaHJpZnRmYXJiZSBhdWYgd2Vpw58gc2V0emVuCgoJCWZvciAoaW50IGkgPSAwOyBpIDwgd2lkdGggLSAxOyArK2kpCgkJewoJCQlwcmludGYoIi0iKTsJCQkJCQkJCQkJCS8vIG9iZXJlIFNwaWVsZmVsZGJlZ3Jlbnp1bmcgemVpY2huZW4KCQl9CgkJZm9yIChpbnQgaSA9IDA7IGkgPCBoZWlnaHQgLSAxOyArK2kpCQkJCQkJCgkJewoJCQlwcmludGYoIlxufCIpOwkJCQkJCQkJCQkJLy8gc2VpdGxpY2ggcmVjaHRlIFNwaWVsZmVsZGJlZ3Jlbnp1bmcgemVpY2huZW4KCgkJZm9yIChpbnQgaSA9IDA7IGkgPCB3aWR0aCAtIDM7ICsraSkKCQkJcHJpbnRmKCIgIik7CQkJCQkJCQoJCQlwcmludGYoInwiKTsJCQkJCQkJCQkJCS8vIGxpbmtlIHNlaXRsaWNoZSBTcGllbGZlbGRiZWdyZW56dW5nIHplaWNobmVuCgkJfQoJCXByaW50ZigiXG4iKTsKCQlmb3IgKGludCBpID0gMDsgaSA8IHdpZHRoIC0gMTsgKytpKQoJCXsKCQkJcHJpbnRmKCItIik7CQkJCQkJCQkJCQkJCQkJCQkJCQkJCS8vIHVudGVyZSBTcGllbGZlbGRiZWdyZW56dW5nIHplaWNobmVuCgkJfQoJCWlmKHNwaWVsbW9kdXMgPT0gMClwcmludGYoIlxufCBZb3VyIHNjb3JlOiAwIHwgQ29tcHV0ZXIgc2NvcmU6IDAgfHx8IFNwZWVkOiAgIDAgICB8XG4iKTsJCQkJLy8gU3RhdGlzdGlrIHVudGVyIGRlciB1bnRlcmVuIFNwaWVsZmVsZGJlZ3Jlbnp1bmcgemVpY2huZW4KCQlpZihzcGllbG1vZHVzID09IDEpcHJpbnRmKCJcbnwgU3BpLiAxIHNjb3JlOiAwIHwgU3BpLiAyIHNjb3JlOiAwIHx8fCBTcGVlZDogICAwICAgfFxuIik7CgkJCgkJZm9yIChpbnQgaSA9IDA7IGkgPCB3aWR0aCAtIDE7ICsraSkKCQl7CgkJCXByaW50ZigiLSIpOwkJCQkJCQkJCQkJCQkJCQkJCQkJCQkvLyB1bnRlciBkZXIgU3RhdGlzdGlrIG5vY2ggZWluZSBMaW5pZSB6ZWljaG5lbgkJCgkJfQkJCQkKCQkvLyBFbmRlIE9iZXJmbMOkY2hlIHplaWNobmVuCgkKCQkvLyBTcGllbGVyIHVuZCBCYWxsIGVyc3RlbGxlbgoJCXNwaWVsZXIgeW91LCB5b3UyLCBjb21wOyBiYWxsIGI7CQkJCQkJCS8vIE9iamVrdGUgU3BpZWxlciwgU3BpZWxlciAyLCBDb21wdXRlciB1bmQgQmFsbCBkZXIgQW5mYW5ncyBkZWZpbmllcnRlbiBzdHJ1Y3QgZXJzdGVsbGVuCgkJc3BpZWxlcl8oJnlvdSwgd2lkdGggLyAyLCBoZWlnaHQgLSAyLCA0KTsJCQkJCS8vIEFuZmFuZ3N3ZXJ0ZSBmw7xyIFNwaWVsZXIgYW4gZGllIHNwaWVsZXJfKCkgTWV0aG9kZSDDvGJlcmdlYmVuCQkJCQkKCQlzcGllbGVyXygmeW91Miwgd2lkdGggLyAyLDIsIDQpOwkJCQkJCQkvLyBBbmZhbmdzd2VydGUgZsO8ciBTcGllbGVyMiBhbiBkaWUgc3BpZWxlcl8oKSBNZXRob2RlIMO8YmVyZ2ViZW4KCQlzcGllbGVyXygmY29tcCwgd2lkdGggLyAyLCAyLCA0KTsJCQkJCQkJLy8gQW5mYW5nc3dlcnRlIGbDvHIgZGVuIENvbXB1dGVyIGFuIGRpZSBzcGllbGVyXygpIE1ldGhvZGUgw7xiZXJnZWJlbgoJCWJhbGxfKCZiLCB3aWR0aCAvIDIgLSAxLCBoZWlnaHQgLyAyKTsJCQkJCQkvLyBBbmZhbmdzd2VydGUgZsO8ciBkZW4gQmFsbCBhbiBkaWUgYmFsbF8oKSBNZXRob2RlIMO8YmVyZ2ViZW4KCQliLnZ4ID0gKGZsb2F0KShyYW5kKCkgJSAzKSAtIDEuNWY7CQkJCQkJCS8vIEJhbGwgaW4genVmw6RsbGlnZSBSaWNodHVuZyB6dW0gU3BpZWxlciBzY2hpY2tlbgoJCWIudnkgPSAxOwoJCWNvbXAudnggPSAwOwoJCQoJCS8vIEJlbsO2dGlndGUgVmFyaWFibGVuIGluaXRpYWxpc2llcmVuCgkJaW50IGdlc3RhcnRldCAgPSAwOwkJCQkJCQkJCQkJLy8gZ2VzdGFydGV0IGF1ZiAibmVpbiIgc2V0emVuICgwID0gbmVpbiwgMSA9IGphKQoJCWludCB5b3Vfc2NvcmUgPSAwLCBjb21wX3Njb3JlID0gMCwgeW91Ml9zY29yZSA9IDA7CQkJLy8gU3RhdGlzdGlrIChQdW5rdGUpIGF1ZiBTdGFuZGFyZCBzZXR6ZW4KCQljb25zdCBpbnQgZGVsYXkgPSA1MDsJCQkJCQkJCQkJLy8gS29uc3RhbnRlbiBXZXJ0IGbDvHIgZGllIFNwaWVsdmVyesO2Z2VydW5nIHNldHplbgoJCWZsb2F0IHNwZWVkID0gMC4wZjsJCQkJCQkJCQkJCS8vIFN0YXRpc3RpayBkZXIgQmFsbGdlc2Nod2luZGlna2VpdCBhdWYgU3RhbmRhcnQgc2V0emVuCgkJY2hhciBzY2h3aWVyaWdrZWl0MVsyMF0gPSAiQW1hdGV1ciI7CQkJCQkJCgkJY2hhciBzY2h3aWVyaWdrZWl0MlsyMF0gPSAiTWFjaGJhciI7CgkJY2hhciBzY2h3aWVyaWdrZWl0M1syMF0gPSAiVmV0ZXJhbiI7CQkJCQkJLy8gU3RyaW5ncyB6dW0gVmVyZ2xlaWNoIGRlciBTY2h3aWVyaWdrZWl0ZW4gaW5pdGlhbGlzaWVyZW4KCQljaGFyIHNjaHdpZXJpZ2tlaXQ0WzIwXSA9ICJOZXJ2dFwyMjR0ZW5kIjsKCQkKCQl0aW1lKCZzdGFydCk7CQkJCQkJCQkJCQkJLy8gU3RvcHB1aHIgZsO8ciBIaWdoc2NvcmUgc3RhcnRlbgoJCQp3aGlsZSAoMSkgCnsKICAgIGlmIChnZXN0YXJ0ZXQgPT0gMSkJCQkJCQkJCQkJCQkvLyBTcGllbCBnZXN0YXJ0ZXQ/Cgl7CgoJCWlmIChHZXRBc3luY0tleVN0YXRlKGxpbmtzKSkJCQkJCQkJCS8vIGZhbGxzIGphLCBmcmFnZW4gb2IgZGllIFRhc3RlIGRpZSBpbiAibGlua3MiIGdlc3BlaWNoZXJ0IGlzdCwgZ2VkcsO8Y2t0IHd1cmRlCgkJewoJCQlpZihzdHJjbXAoc2Nod2llcmlna2VpdCxzY2h3aWVyaWdrZWl0MSkgPT0gMCkJCQkvLyBmYWxscyBqYSwgc2Nod2llcmlna2VpdHNncmFkIHZlcmdsZWljaGVuLCB1bSBkaWUgcGFzc2VuZGUgQmV3ZWd1bmdzZ2VzY2h3aW5kaWdrZWl0IGRlciBQYWRzIHp1IHfDpGhsZW4KCQkJewoJCQkJeW91LnggLT0gMiw1OwoJCQl9CgkJCWVsc2UgaWYoc3RyY21wKHNjaHdpZXJpZ2tlaXQsc2Nod2llcmlna2VpdDIpID09IDApCQkvLyBkaWVzIGbDvHIgYWxsZSBTY2h3aWVyaWdrZWl0c2dyYWRlIGR1cmNoc3BpZWxlbgoJCQl7CgkJCQl5b3UueCAtPSAyOwoJCQl9CgkJCWVsc2UgaWYoc3RyY21wKHNjaHdpZXJpZ2tlaXQsc2Nod2llcmlna2VpdDMpID09IDApCgkJCXsKCQkJCXlvdS54IC09IDI7CgkJCX0KCQkJZWxzZSBpZihzdHJjbXAoc2Nod2llcmlna2VpdCxzY2h3aWVyaWdrZWl0NCkgPT0gMCkKCQkJewoJCQkJeW91LnggLT0gMiw1OwoJCQl9CgkJfSAKCQllbHNlIGlmIChHZXRBc3luY0tleVN0YXRlKHJlY2h0cykpCQkJCQkJCS8vIGZhbGxzIGphLCBmcmFnZW4gb2IgZGllIFRhc3RlIGRpZSBpbiAicmVjaHRzIiBnZXNwZWljaGVydCBpc3QsIGdlZHLDvGNrdCB3dXJkZQoJCXsKCQkJaWYoc3RyY21wKHNjaHdpZXJpZ2tlaXQsc2Nod2llcmlna2VpdDEpID09IDApCQkJLy8gZmFsbHMgamEsIHNjaHdpZXJpZ2tlaXRzZ3JhZCB2ZXJnbGVpY2hlbiwgdW0gZGllIHBhc3NlbmRlIEJld2VndW5nc2dlc2Nod2luZGlna2VpdCBkZXIgUGFkcyB6dSB3w6RobGVuCgkJCXsKCQkJCXlvdS54ICs9IDIsNTsKCQkJfQoJCQllbHNlIGlmKHN0cmNtcChzY2h3aWVyaWdrZWl0LHNjaHdpZXJpZ2tlaXQyKSA9PSAwKQoJCQl7CgkJCQl5b3UueCArPSAyOwoJCQl9CgkJCWVsc2UgaWYoc3RyY21wKHNjaHdpZXJpZ2tlaXQsc2Nod2llcmlna2VpdDMpID09IDApCQkvLyBkaWVzIGbDvHIgYWxsZSBTY2h3aWVyaWdrZWl0c2dyYWRlIGR1cmNoc3BpZWxlbgoJCQl7CgkJCQl5b3UueCArPSAyOwoJCQl9CgkJCWVsc2UgaWYoc3RyY21wKHNjaHdpZXJpZ2tlaXQsc2Nod2llcmlna2VpdDQpID09IDApCgkJCXsKCQkJCXlvdS54ICs9IDU7CgkJCX0KCQl9CgkJZWxzZSBpZiAoR2V0QXN5bmNLZXlTdGF0ZShiZWVuZGVuKSkJCQkJCQkJLy8gZmFsbHMgamEsIGZyYWdlbiBvYiBkaWUgVGFzdGUgZGllIGluICJiZWVuZGVuIiBnZXNwZWljaGVydCBpc3QsIGdlZHLDvGNrdCB3dXJkZQoJCXsKCQkJQ09PUkQgcDsKCQkJcC5YID0gKGludCkgKHdpZHRoIC8gMiAtIDE2KTsKCQkJcC5ZID0gKGludCkgKGhlaWdodCAvIDEuOGYpOwoJCQlTZXRDb25zb2xlQ3Vyc29yUG9zaXRpb24oaE91dCwgcCk7CgkJCXByaW50ZigiU3BpZWwgd2lya2xpY2ggYmVlbmRlbj8iKTsKCQkJcC5YID0gKGludCkgKHdpZHRoIC8gMiAtIDE2KTsKCQkJcC5ZID0gKGludCkgKGhlaWdodCAvIDEuNmYpOwoJCQlTZXRDb25zb2xlQ3Vyc29yUG9zaXRpb24oaE91dCwgcCk7CQkJCQkJLy8gQWJmcmFnZSwgb2IgU3BpZWwgZm9ydHNldHplbiBvZGVyIEJlZW5kZW4KCQkJcHJpbnRmKCI8MT4gV2VpdGVyc3BpZWxlblxuIik7CQkJCQkJCS8vIHdpcmQgZHJ1Y2ggZGFzIGRyw7xja2VuIGRlciBxIFRhc3RlCgkJCXAuWCA9IChpbnQpICh3aWR0aCAvIDIgLSAxNik7CQkJCQkJCS8vIGluIGRpZSBLb25zb2xlIGdlc2NocmllYmVuCgkJCXAuWSA9IChpbnQpIChoZWlnaHQgLyAxLjU1Zik7CQkJCQkJCQoJCQlTZXRDb25zb2xlQ3Vyc29yUG9zaXRpb24oaE91dCwgcCk7CgkJCXByaW50ZigiPDI+IFNwaWVsIGJlZW5kZW5cblxuIik7CgkJCXAuWCA9IChpbnQpICh3aWR0aCAvIDIgLSAxNyk7CgkJCXAuWSA9IChpbnQpIChoZWlnaHQgLyAxLjM1Zik7CgkJCVNldENvbnNvbGVDdXJzb3JQb3NpdGlvbihoT3V0LCBwKTsKCQkJY2hhciBjOwoJCQl3aGlsZSAoKGMgPSBfZ2V0Y2goKSkgIT0gRU9GICYmIGMgIT0gJ3EnKTsJCQkJLy8gUHVmZmVyIGF1dG9tYXRpc2NoIGltIEhpbnRlcmdydW5kIGxlZXJlbiAoWmVpZ2VyIGltIFB1ZmZlciBiaXMgenVtIGVyc3RlbiBBdWZ0cmV0ZW4gZWluZXMgInEiIHZlcnNjaGllYmVuKQoJCQlpbnQgYXVzd2FobCA9IF9nZXRjaCgpOwkJCQkJCQkJCS8vIGVpbmxlc2VuLCBvYiBmb3J0c2V0emVuIG9kZXIgYmVlbmRlbiBhdXNnZXfDpGhsdCB3dXJkZSB1bmQgc29sYW5nZSBTcGllbCBhbmhhbHRlbiwgYmlzIEVpbmdhYmUgZ2V0w6R0aWd0IHd1cmRlCgoJCQlpZihhdXN3YWhsID09IDQ5KQkJCQkJCQkJCQkvLyBmYWxscyBmb3J0c2V0emVuIGF1c2dld8OkaGx0IC0+CgkJCXsKCQkJCXAuWCA9IChpbnQpICh3aWR0aCAvIDIgLSAxNik7CgkJCQlwLlkgPSAoaW50KSAoaGVpZ2h0IC8gMS44Zik7CgkJCQlTZXRDb25zb2xlQ3Vyc29yUG9zaXRpb24oaE91dCwgcCk7CgkJCQlwcmludGYoIiAgICAgICAgICAgICAgICAgICAgICAgICAgIik7CgkJCQlwLlggPSAoaW50KSAod2lkdGggLyAyIC0gMTYpOwoJCQkJcC5ZID0gKGludCkgKGhlaWdodCAvIDEuNmYpOwoJCQkJU2V0Q29uc29sZUN1cnNvclBvc2l0aW9uKGhPdXQsIHApOwkJCQkJLy8gLT4genUgcGFzc2VuZGVuIFBvc2l0aW9uZW4gc3ByaW5nZW4gdW5kIGRlbiBEaWFsb2cgd2llZGVyIGVudGZlcm5lbiAtPiBTcGllbCB3aXJkIGZvcnRnZXNldHp0CgkJCQlwcmludGYoIiAgICAgICAgICAgICAgICAgICAgICAgICAgIik7CgkJCQlwLlggPSAoaW50KSAod2lkdGggLyAyIC0gMTYpOwoJCQkJcC5ZID0gKGludCkgKGhlaWdodCAvIDEuNTVmKTsKCQkJCVNldENvbnNvbGVDdXJzb3JQb3NpdGlvbihoT3V0LCBwKTsKCQkJCXByaW50ZigiICAgICAgICAgICAgICAgICAgICAgICAgICAiKTsKCQkJfQkKCQkJZWxzZSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBmYWxscyBiZWVuZGVuIGF1c2dld8OkaGx0LCBhdXMgZGVyIFNwaWVsc2NobGVpZmUgc3ByaW5nZW4KCQkJewoJCQkJdGltZSgmZW5kZXQpOwkJCQkJCQkJCQkvLyBTdG9wcHVociBzdG9wcGVuIHVtIHZlcmbDpGxzY2h1bmcgZGVyIFplaXQgenUgdW1nZWhlbgoJCQkJYnJlYWs7CgkJCX0KCQl9CgkJaWYgKEdldEFzeW5jS2V5U3RhdGUobGlua3MyKSkJCQkJCQkJCS8vIGZhbGxzIFNwaWVsbW9kdXMgPSBNZW5zY2ggdnMgTWVuc2NoLCBpc3QgZGFzIGdlZ25lcmlzY2hlIFBhZCBiZXdlZ2Jhci4gQWJmcmFnZSBvYiBUYXN0ZSBkaWUgaW4gImxpbmtzMiIgCgkJeyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gZ2VzcGVpY2hlcnQgaXN0IGdlZHLDvGNrdCB3dXJkZQoJCQlpZihzdHJjbXAoc2Nod2llcmlna2VpdCxzY2h3aWVyaWdrZWl0MSkgPT0gMCkKCQkJewoJCQkJeW91Mi54IC09IDIsNTsKCQkJfQoJCQllbHNlIGlmKHN0cmNtcChzY2h3aWVyaWdrZWl0LHNjaHdpZXJpZ2tlaXQyKSA9PSAwKQkJLy8gZmFsbHMgamEsIHNjaHdpZXJpZ2tlaXRzZ3JhZCB2ZXJnbGVpY2hlbiwgdW0gZGllIHBhc3NlbmRlIEJld2VndW5nc2dlc2Nod2luZGlna2VpdCBkZXIgUGFkcyB6dSB3w6RobGVuCgkJCXsKCQkJCXlvdTIueCAtPSAyOwoJCQl9CgkJCWVsc2UgaWYoc3RyY21wKHNjaHdpZXJpZ2tlaXQsc2Nod2llcmlna2VpdDMpID09IDApCQkvLyBkaWVzIGbDvHIgYWxsZSBTY2h3aWVyaWdrZWl0c2dyYWRlIGR1cmNoc3BpZWxlbgoJCQl7CgkJCQl5b3UyLnggLT0gMjsKCQkJfQoJCQllbHNlIGlmKHN0cmNtcChzY2h3aWVyaWdrZWl0LHNjaHdpZXJpZ2tlaXQ0KSA9PSAwKQoJCQl7CgkJCQl5b3UyLnggLT0gMiw1OwoJCQl9CgkJfSAKCQllbHNlIGlmIChHZXRBc3luY0tleVN0YXRlKHJlY2h0czIpKQkJCQkJCQkvLyBmcmFnZW4gb2IgZGllIFRhc3RlIGRpZSBpbiAicmVjaHRzMiIgZ2VzcGVpY2hlcnQgaXN0LCBnZWRyw7xja3Qgd3VyZGUgKE1lbnNjaCB2cyBNZW5zY2gpCgkJewoJCQlpZihzdHJjbXAoc2Nod2llcmlna2VpdCxzY2h3aWVyaWdrZWl0MSkgPT0gMCkJCQkvLyBmYWxscyBqYSwgc2Nod2llcmlna2VpdHNncmFkIHZlcmdsZWljaGVuLCB1bSBkaWUgcGFzc2VuZGUgQmV3ZWd1bmdzZ2VzY2h3aW5kaWdrZWl0IGRlciBQYWRzIHp1IHfDpGhsZW4KCQkJewoJCQkJeW91Mi54ICs9IDIsNTsKCQkJfQoJCQllbHNlIGlmKHN0cmNtcChzY2h3aWVyaWdrZWl0LHNjaHdpZXJpZ2tlaXQyKSA9PSAwKQoJCQl7CgkJCQl5b3UyLnggKz0gMjsKCQkJfQoJCQllbHNlIGlmKHN0cmNtcChzY2h3aWVyaWdrZWl0LHNjaHdpZXJpZ2tlaXQzKSA9PSAwKQkJLy8gZGllcyBmw7xyIGFsbGUgU2Nod2llcmlna2VpdHNncmFkZSBkdXJjaHNwaWVsZW4KCQkJewoJCQkJeW91Mi54ICs9IDI7CgkJCX0KCQkJZWxzZSBpZihzdHJjbXAoc2Nod2llcmlna2VpdCxzY2h3aWVyaWdrZWl0NCkgPT0gMCkKCQkJewoJCQkJeW91Mi54ICs9IDU7CgkJCX0KCQl9CgoJICAvLyBCYWxsZ2VzY2h3aW5kaWdrZWl0IGbDvHIgU3RhdGlzdGlrIGJlcmVjaG5lbgoJICBmbG9hdCB4ID0gcG93KGIudngsIDIpOwkJCQkJCQkJCQkvLyB5IC0gR2VzY2h3aW5kaWdrZWl0IGRlcyBCYWxsZXMgcXVhZHJpZXJlbgoJICBmbG9hdCB5ID0gcG93KGIudnksIDIpOwkJCQkJCQkJCQkvLyB4IC0gR2VzY2h3aW5kaWtlaXQgZGVzIEJhbGxlcyBxdWFkcmllcmVuCQkoU2F0eiBkZXMgUHl0aGFnb3JhcykKCSAgc3BlZWQgPSB4ICsgeTsJCQkJCQkJCQkJCQkvLyBiZWlkZSBXZXJ0ZSBhZGRpZXJlbgkJCQkJCQkJCQkJCgkgIHNwZWVkID0gc3FydChzcGVlZCk7CQkJCQkJCQkJCQkvLyBXdXJ6ZWwgYXVzIGRlbSBuZXVlbiBpbiAic3BlZWQiIGdlc3BlaWNoZXJ0ZW4gV2VydCB6aWVoZW4gCgkgIENPT1JEIHA7CiAgICAgIHAuWCA9IChpbnQpICg0Nyk7CQkJCQkJCQkJCQkJLy8gS29vcmRpbmF0ZW4gZsO8ciBkaWUgR2VzY2h3aW5kaWdrZWl0c2FuemVpZ2UgZGVzIEJhbGxzIHJlY2h0cyB1bnRlbiBpbiBkZXIgS29uc29sZSBzZXR6ZW4KICAgICAgcC5ZID0gKGludCkgKDM3KTsKICAgICAgU2V0Q29uc29sZUN1cnNvclBvc2l0aW9uKGhPdXQsIHApOwkJCQkJCQkvLyBDdXJzb3IgZG9ydGhpbiBiZXdlZ2VuCgkgIHByaW50ZigiJS4yZiIsIHNwZWVkKTsJCQkJCQkJCQkJLy8gQWt0dWVsbGUgQmFsbGdlc2Nod2luZGlna2VpdCAoaW4gc3BlZWQgZ2VzcGVpY2hlcnQpIGRvcnQgbWl0IHp3ZWkgTmFjaGtvbW1hc3RlbGxlbiBhdXNnZWJlbgoJCQoKICAgICAgLy8gS0kgenVtIEJhbGwgZsO8aHJlbgoJICBpZihzcGllbG1vZHVzID09IDApCQkJCQkJCQkJCQkvLyBmYWxscyBTcGllbG1vZHVzID0gTWVuc2NoIHZzIENvbXB1dGVyCiAgICAgIHsKCQljb21wLnZ4IC09IChmbG9hdCkgKGNvbXAueCAtIGIueCkgLyBraVJlYWt0aW9uOwkJCQkvLyBDb21wdXRlciB4IC0gUG9zaXRpb24gLSBCYWxsIHggLSBQb3NpdGlvbiwgdW0genUgZXJyZWNobmVuLCB3byBkZXIgQ29tcHV0ZXIgc2ljaCBoaW5iZXdlZ2VuIG11c3MgZ2V0ZWlsdCBkdXJjaCBlaW5lbiBNb2RpZmlrYXRvciwgCQoJICAJY29tcC52eCAqPSAwLjgzZjsJCQkJCQkJCQkJCS8vIGRlciBkaWUgS0kgYWxzIHdlaXRlcmUgU2Nod2llcmlna2VpdCBsYW5nc2FtZXIgb2RlciBzY2huZWxsZXIgcmVhZ2llcmVuIGxhc3NlbiBrYW5uIHx8fCBDb21wdXRlciB4IC0gR2VzY2h3aW5kaWdrZWl0IHJlZHV6aWVyZW4KCSAgfQoKICAgICAgLy8gS0kgR2VzY2h3aW5kaWdlaXQgaW4gQWJow6RuZ2lna2VpdCBkZXIgQmFsbGdlc2Nod2luZGlna2VpdCBhbnBhc3NlbgogICAgICBjb21wLnggKz0gY29tcC52eDsKCiAgICAgIC8vIEJld2VndW5nc2dyZW56ZW4gc2V0emVuIFNwaWVsZXIgMQogICAgICBpZiAoeW91LnggPCB5b3Uuc2l6ZSArIDEpCQkJCQkJCQkJCS8vIGZhbGxzIFNwaWVsZXIxIHgtUG9zaXRpb24ga2xlaW5lciBhbHMgUGFkZ3LDtsOfZSArIDEgKGxpbmtlIEF1w59lbnNlaXRlIGVycmVpY2h0KQoJICB7CiAgICAgICAgeW91LnggPSAoZmxvYXQpICh5b3Uuc2l6ZSArIDEpOwkJCQkJCQkJLy8gZGFubiBTcGllbGVyIGF1ZiBkaWVzZXIgeCAtIFBvc2l0aW9uIGhhbHRlbiB1bmQgbmljaHQgw7xiZXJxdWVyZW4gbGFzc2VuIChsaW5rZSBTZWl0ZSkKICAgICAgfSAKCSAgZWxzZSBpZiAoeW91LnggPiB3aWR0aCAtIHlvdS5zaXplIC0gMiAtIG1vZGlmaWthdG9yKQkJCS8vIGZhbGxzIFNwaWVsZXIxIHggLSBQb3NpdGlvbiBncsO2w59lciBhbHMgS29uc29sZW5icmVpdGUgLSBQYWRncsO2w59lIC0gMih3ZWdlbiBTcGllbGJlZ3Jlbnp1bmdlbikgLSBtb2RpZmlrYXRvciwgZGVyIGRpZSAKCSAgeyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBQYWRncsO2w59lIGRlbiBHcmVuemVuIGFucGFzc3QKICAgICAgICB5b3UueCA9IChmbG9hdCkgKHdpZHRoIC0geW91LnNpemUgLSAyIC0gbW9kaWZpa2F0b3IpOwkJLy8gZGFubiBTcGllbGVyIGF1ZiBkaWVzZXIgeCAtIFBvc2l0aW9uIGhhbHRlbiB1bmQgbmljaHQgw7xiZXJxdWVyZW4gbGFzc2VuIChyZWNodGUgU2VpdGUpCiAgICAgIH0KCgkgIC8vIEJld2VndW5nc2dyZW56ZW4gc2V0emVuIFNwaWVsZXIgMgogICAgICBpZiAoeW91Mi54IDwgeW91Mi5zaXplICsgMSkJCQkJCQkJCQkvLyBmYWxscyBTcGllbGVyMSB4LVBvc2l0aW9uIGtsZWluZXIgYWxzIFBhZGdyw7bDn2UgKyAxIChsaW5rZSBBdcOfZW5zZWl0ZSBlcnJlaWNodCkKCSAgewogICAgICAgIHlvdTIueCA9IChmbG9hdCkgKHlvdTIuc2l6ZSArIDEpOwkJCQkJCQkvLyBkYW5uIFNwaWVsZXIyIGF1ZiBkaWVzZXIgeCAtIFBvc2l0aW9uIGhhbHRlbiB1bmQgbmljaHQgw7xiZXJxdWVyZW4gbGFzc2VuCShsaW5rZSBTZWl0ZSkKICAgICAgfSAKCSAgZWxzZSBpZiAoeW91Mi54ID4gd2lkdGggLSB5b3UyLnNpemUgLSAyIC0gbW9kaWZpa2F0b3IpCQkvLyBmYWxscyBTcGllbGVyMiB4IC0gUG9zaXRpb24gZ3LDtsOfZXIgYWxzIEtvbnNvbGVuYnJlaXRlIC0gUGFkZ3LDtsOfZSAtIDIod2VnZW4gU3BpZWxiZWdyZW56dW5nZW4pIC0gbW9kaWZpa2F0b3IsIGRlciBkaWUgCgkgIHsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUGFkZ3LDtsOfZSBkZW4gR3JlbnplbiBhbnBhc3N0CiAgICAgICAgeW91Mi54ID0gKGZsb2F0KSAod2lkdGggLSB5b3UyLnNpemUgLSAyIC0gbW9kaWZpa2F0b3IpOwkJLy8gZGFubiBTcGllbGVyMiBhdWYgZGllc2VyIHggLSBQb3NpdGlvbiBoYWx0ZW4gdW5kIG5pY2h0IMO8YmVycXVlcmVuIGxhc3NlbiAocmVjaHRlIFNlaXRlKQogICAgICB9CgogICAgICAvLyBLSSBCZXdlZ3VuZ3NncmVuemUgc2V0emVuCiAgICAgIGlmIChjb21wLnggPCBjb21wLnNpemUgKyAxKQkJCQkJCQkJCS8vIGZhbGxzIFNwaWVsZXIxIHgtUG9zaXRpb24ga2xlaW5lciBhbHMgUGFkZ3LDtsOfZSArIDEgKGxpbmtlIEF1w59lbnNlaXRlIGVycmVpY2h0KQoJICB7CiAgICAgICAgY29tcC54ID0gKGZsb2F0KSAoY29tcC5zaXplICsgMSk7CQkJCQkJCS8vIGRhbm4gQ29tcHV0ZXIgYXVmIGRpZXNlciB4IC0gUG9zaXRpb24gaGFsdGVuIHVuZCBuaWNodCDDvGJlcnF1ZXJlbiBsYXNzZW4gKGxpbmtlIFNlaXRlKQogICAgICB9IAoJICBlbHNlIGlmIChjb21wLnggPiB3aWR0aCAtIGNvbXAuc2l6ZSAtIDIgLSBtb2RpZmlrYXRvcikJCS8vIGZhbGxzIENvbXB1dGVyIHggLSBQb3NpdGlvbiBncsO2w59lciBhbHMgS29uc29sZW5icmVpdGUgLSBQYWRncsO2w59lIC0gMih3ZWdlbiBTcGllbGJlZ3Jlbnp1bmdlbikgLSBtb2RpZmlrYXRvciwgZGVyIGRpZSAKCSAgeyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBQYWRncsO2w59lIGRlbiBHcmVuemVuIGFucGFzc3QKICAgICAgICBjb21wLnggPSAoZmxvYXQpICh3aWR0aCAtIGNvbXAuc2l6ZSAtIDIgLSBtb2RpZmlrYXRvcik7CQkvLyBkYW5uIENvbXB1dGVyIGF1ZiBkaWVzZXIgeCAtIFBvc2l0aW9uIGhhbHRlbiB1bmQgbmljaHQgw7xiZXJxdWVyZW4gbGFzc2VuIChyZWNodGUgU2VpdGUpCiAgICAgIH0KCiAgICAgIC8vIEJhbGwgSMO2Y2hzdGdlc2Nod2luZGlna2VpdCBlaW5oYWx0ZW4KICAgICAgaWYgIChiLnZ4IDwgLW1heFNwZWVkKQkJCQkJCQkJCQkvLyBmYWxscyBCYWxsIHggLSBHZXNjaHdpbmRpZ2tlaXQgaW4gZGllc2VtIEZhbGwgInVudGVyIiBkZXIgbWF4aW1hbCBlcmxhdWJ0ZW4gR2VzY2h3aW5kaWdrZWl0IGxpZWd0CgkgIHsKICAgICAgICBiLnZ4ID0gLW1heFNwZWVkOwkJCQkJCQkJCQkJLy8gQmFsbCB4IC0gR2VzY2h3aW5kaWdrZWl0IHdpZWRlciBhdWYgIm1pbmltYWwiIGVybGF1YnRlbiBXZXJ0IHp1csO8Y2tzZXR6ZW4KICAgICAgfQkJCgkgIGVsc2UgaWYgKGIudnggPiBtYXhTcGVlZCkJCQkJCQkJCQkJLy8gZmFsbHMgQmFsbCB4IC0gR2VzY2h3aW5kaWdrZWl0IMO8YmVyIGRlciBtYXhpbWFsIGVybGF1YnRlbiBHZXNjaHdpbmRpZ2tlaXQgbGllZ3QKCSAgewogICAgICAgIGIudnggPSBtYXhTcGVlZDsJCQkJCQkJCQkJCS8vIEJhbGwgeCAtIEdlc2Nod2luZGlna2VpdCB3aWVkZXIgYXVmIG1heGltYWwgZXJsYXVidGVuIFdlcnQgenVyw7xja3NldHplbgogICAgICB9CgogICAgICAvLyBEZW0gQmFsbCBhbiBkZXIgYWt0dWVsbGVuIFBvc2l0aW9uIEdlc2Nod2luZGlna2VpdCB6dWbDvGhyZW4KICAgICAgYi54ICs9IGIudng7CQkJCQkJCQkJCQkJCS8vIGRpZSBha3R1ZWxsZSB4IC0gUG9zaXRpb24gZGVzIEJhbGxlcyB1bSBkZW4gYWt0dWVsbGVuIFdlcnQgZGVyIHggLSBCYWxsZ2VzY2h3aW5kaWdrZWl0IHZlcnNjaGllYmVuCiAgICAgIGIueSArPSBiLnZ5OwkJCQkJCQkJCQkJCQkvLyBkaWUgYWt0dWVsbGUgeSAtIFBvc2l0aW9uIGRlcyBCYWxsZXMgdW0gZGVuIGFrdHVlbGxlbiBXZXJ0IGRlciB5IC0gQmFsbGdlc2Nod2luZGlna2VpdCB2ZXJzY2hpZWJlbgoKICAgICAgLy8gSGF0IGRlciBCYWxsIGRlbiBTcGllbGVyIGdldHJvZmZlbj8KICAgICAgaWYgKGIueSA+PSB5b3UueSAtIDEgJiYgYi55IDw9IHlvdS55ICsgMSkJCQkJCQkvLyBpc3QgZGllIHkgLSBQb3NpdGlvbiBkZXMgQmFsbHMgMSDDvGJlciBkZW0gUGFkIHVuZCBpc3QgZGllIHkgLSBQb3NpdGlvbiBkZXMgQmFsbHMgbmljaHQgMSB1bnRlciBkZW0gUGFkIChkYSBzb25zdCBQdW5rdCBnZWJlbiB3w7xyZGUpCgkgIHsKICAgICAgICBpZiAoYi54ID4geW91LnggLSB5b3Uuc2l6ZSAmJiBiLnggPCB5b3UueCArIHlvdS5zaXplKQkJLy8gaXN0IGRpZSB4IC0gUG9zaXRpb24gZGVzIEJhbGxzIGtsZWluZXIgYnp3LiBncsO2w59lciBhbHMgZGllIHggLSBQb3NpdGlvbiBkZXMgUGFkcyAtIHVuZCArIGRpZSBQYWRncsO2w59lLCBpc3QgZGFzIFBhZCBnZXRyb2ZmZW4KCQl7CiAgICAgICAgICBiLnZ5ICo9IC0xOwkJCQkJCQkJCQkJCS8vIEJhbGwgeS1SaWNodHVuZyB1bWtlaHJlbgogICAgICAgICAgYi52eCArPSAoZmxvYXQpKGIueCAtIHlvdS54KSAvIDM7CQkJCQkJCS8vIEJhbGwgeCAtIEdlc2Nod2luZGlna2VpdCBiZWkgYXVmdHJlZmZlbiBhdWYgZGFzIFBhZCAtIGRpZSBQYWQgeCAtIFBvc2l0aW9uIHJlY2huZW4sIHVtIGVpbmUgcmVzdWx0aWVyZW5kZSBSaWNodHVuZyB6dSBlcmhhbHRlbgogICAgICAgICAgYi55ID0geW91LnkgLSAxOwkJCQkJCQkJCQkJLy8gQmFsbCBhdWYgUG9zaXRpb24gZGlyZWt0IMO8YmVyIGRlbSBQYWQgc2V0emVuLCB1bSBlaW4gaGluZHVyY2hmYWxsZW4gZHVyY2ggZGFzIFBhZCB6dSB2ZXJoaW5kZXJuCiAgICAgICAgfQogICAgICB9CgoJICAgLy8gSGF0IGRlciBCYWxsIGRlbiBTcGllbGVyMiBnZXRyb2ZmZW4/CiAgICAgIGlmIChiLnkgPD0geW91Mi55ICsgMSAmJiBiLnkgPj0geW91Mi55IC0gMSkJCQkJCS8vIGlzdCBkaWUgeSAtIFBvc2l0aW9uIGRlcyBCYWxscyAxIHVudGVyIGRlbSBQYWQgdW5kIGlzdCBkaWUgeSAtIFBvc2l0aW9uIGRlcyBCYWxscyBuaWNodCAxIMO8YmVyIGRlbSBQYWQgKGRhIHNvbnN0IFB1bmt0IGdlYmVuIHfDvHJkZSkKCSAgewogICAgICAgIGlmIChiLnggPiB5b3UyLnggLSB5b3UyLnNpemUgJiYgYi54IDwgeW91Mi54ICsgeW91Mi5zaXplKQkvLyBpc3QgZGllIHggLSBQb3NpdGlvbiBkZXMgQmFsbHMga2xlaW5lciBiencuIGdyw7bDn2VyIGFscyBkaWUgeCAtIFBvc2l0aW9uIGRlcyBQYWRzIC0gdW5kICsgZGllIFBhZGdyw7bDn2UsIGlzdCBkYXMgUGFkIGdldHJvZmZlbgoJCXsKICAgICAgICAgIGIudnkgKj0gLTE7CQkJCQkJCQkJCQkJLy8gQmFsbCB5LVJpY2h0dW5nIHVta2VocmVuCiAgICAgICAgICBiLnZ4ICs9IChmbG9hdCkoYi54IC0geW91Mi54KSAvIDM7CQkJCQkJLy8gQmFsbCB4IC0gR2VzY2h3aW5kaWdrZWl0IGJlaSBhdWZ0cmVmZmVuIGF1ZiBkYXMgUGFkIC0gZGllIFBhZCB4IC0gUG9zaXRpb24gcmVjaG5lbiwgdW0gZWluZSByZXN1bHRpZXJlbmRlIFJpY2h0dW5nIHp1IGVyaGFsdGVuIAogICAgICAgICAgYi55ID0geW91Mi55ICsgMTsJCQkJCQkJCQkJCS8vIEJhbGwgYXVmIFBvc2l0aW9uIGRpcmVrdCB1bnRlciBkZW0gUGFkIHNldHplbiwgdW0gZWluIGhpbmR1cmNoZmFsbGVuIGR1cmNoIGRhcyBQYWQgenUgdmVyaGluZGVybgogICAgICAgIH0KICAgICAgfQoKICAgICAgLy8gSGF0IGRlciBCYWxsIGRpZSBLSSBnZXRyb2ZmZW4/CiAgICAgIGlmIChiLnkgPD0gY29tcC55ICsgMSAmJiBiLnkgPj0gY29tcC55IC0gMSkJCQkJCS8vIGlzdCBkaWUgeSAtIFBvc2l0aW9uIGRlcyBCYWxscyAxIHVudGVyIGRlbSBQYWQgdW5kIGlzdCBkaWUgeSAtIFBvc2l0aW9uIGRlcyBCYWxscyBuaWNodCAxIMO8YmVyIGRlbSBQYWQgKGRhIHNvbnN0IFB1bmt0IGdlYmVuIHfDvHJkZSkKCSAgewogICAgICAgIGlmIChiLnggPiBjb21wLnggLSBjb21wLnNpemUgJiYgYi54IDwgY29tcC54ICsgY29tcC5zaXplKQkvLyBpc3QgZGllIHggLSBQb3NpdGlvbiBkZXMgQmFsbHMga2xlaW5lciBiencuIGdyw7bDn2VyIGFscyBkaWUgeCAtIFBvc2l0aW9uIGRlcyBQYWRzIC0gdW5kICsgZGllIFBhZGdyw7bDn2UsIGlzdCBkYXMgUGFkIGdldHJvZmZlbgoJCXsKICAgICAgICAgIGIudnkgKj0gLTE7CQkJCQkJCQkJCQkJLy8gQmFsbCB5LVJpY2h0dW5nIHVta2VocmVuCiAgICAgICAgICBiLnZ4ICs9IChmbG9hdCkoYi54IC0gY29tcC54KSAvIDM7CQkJCQkJLy8gQmFsbCB4IC0gR2VzY2h3aW5kaWdrZWl0IGJlaSBhdWZ0cmVmZmVuIGF1ZiBkYXMgUGFkIC0gZGllIFBhZCB4IC0gUG9zaXRpb24gcmVjaG5lbiwgdW0gZWluZSByZXN1bHRpZXJlbmRlIFJpY2h0dW5nIHp1IGVyaGFsdGVuCiAgICAgICAgICBiLnkgPSBjb21wLnkgKyAxOwkJCQkJCQkJCQkJLy8gQmFsbCBhdWYgUG9zaXRpb24gZGlyZWt0IHVudGVyIGRlbSBQYWQgc2V0emVuLCB1bSBlaW4gaGluZHVyY2hmYWxsZW4gZHVyY2ggZGFzIFBhZCB6dSB2ZXJoaW5kZXJuCiAgICAgICAgfQkKICAgICAgfQoKICAgICAgLy8gSGF0IGRlciBCYWxsIGRpZSBHcmVuemVuIMO8YmVyc2Nocml0dGVuPyhQdW5rdCBiZWtvbW1lbikKCSAgaWYgKGIueSA+PSBoZWlnaHQgJiYgc3BpZWxtb2R1cyA9PSAwKQkJCQkJCQkvLyBmYWxscyB5LVdlcnQgNTUgdm9tIEJhbGwgw7xiZXJzY2hyaXR0ZW4gdW5kIFNwaWVsbW9kdXMgPSBNZW5zY2ggdnMgQ29tcHV0ZXIKCSAgewoJCWdlc3RhcnRldCA9IDA7CQkJCQkJCQkJCQkJLy8gU3BpZWwgZ2VzdGFydGV0PyBhdWYgIm5laW4iIHNldHplbiwgdW0gYXVmIExlZXJ0YXN0ZSBnZWRyw7xja3Q/IHp1IHdhcnRlbgogICAgICAgIGNvbXBfc2NvcmUrKzsJCQkJCQkJCQkJCQkvLyBDb21wdXRlciBzY29yZSB1bSAxIGVyaMO2aGVuCgkJY1Njb3JlID0gY29tcF9zY29yZTsJCQkJCQkJCQkJLy8gQ29tcHV0ZXIgc2NvcmUgaW4gZ2xhYmFlciBWYXJpYWJsZSBjU2NvcmUgZsO8ciB3ZWl0ZXJlIFZlcmFyYmVpdHVuZyBzcGVpY2hlcm4KICAgICAgICByZXNldCgmeW91LCAmeW91MiwgJmNvbXAsICZiLCB5b3Vfc2NvcmUsIHlvdTJfc2NvcmUsIGNvbXBfc2NvcmUgKTsKICAgICAgfQoJICBlbHNlIGlmIChiLnkgPj0gaGVpZ2h0ICYmIHNwaWVsbW9kdXMgPT0gMSkJCQkJCS8vIGZhbGxzIHktV2VydCA1NSB2b20gQmFsbCDDvGJlcnNjaHJpdHRlbiB1bmQgU3BpZWxtb2R1cyA9IE1lbnNjaCB2cyBNZW5zY2gKCSAgewoJCWdlc3RhcnRldCA9IDA7CQkJCQkJCQkJCQkJLy8gU3BpZWwgZ2VzdGFydGV0PyBhdWYgIm5laW4iIHNldHplbiwgdW0gYXVmIExlZXJ0YXN0ZSBnZWRyw7xja3Q/IHp1IHdhcnRlbgogICAgICAgIHlvdTJfc2NvcmUrKzsJCQkJCQkJCQkJCQkvLyBTcGllbGVyIDIgc2NvcmUgdW0gMSBlcmjDtmhlbgoJCXkyU2NvcmUgPSB5b3UyX3Njb3JlOwkJCQkJCQkJCQkvLyBTcGllbGVyIDIgc2NvcmUgaW4gZ2xhYmFlciBWYXJpYWJsZSB5MlNjb3JlIGbDvHIgd2VpdGVyZSBWZXJhcmJlaXR1bmcgc3BlaWNoZXJuCiAgICAgICAgcmVzZXQoJnlvdSwgJnlvdTIsICZjb21wLCAmYiwgeW91X3Njb3JlLCB5b3UyX3Njb3JlLCBjb21wX3Njb3JlICk7CiAgICAgIH0KCSAgZWxzZSBpZiAoYi55IDw9IDApCQkJCQkJCQkJCQkvLyBmYWxscyB5LVdlcnQgMCB2b20gQmFsbCDDvGJlcnNjaHJpdHRlbgoJICB7CgkJZ2VzdGFydGV0ID0gMDsJCQkJCQkJCQkJCQkvLyBTcGllbCBnZXN0YXJ0ZXQ/IGF1ZiAibmVpbiIgc2V0emVuLCB1bSBhdWYgTGVlcnRhc3RlIGdlZHLDvGNrdD8genUgd2FydGVuCiAgICAgICAgeW91X3Njb3JlKys7CQkJCQkJCQkJCQkJLy8gU3BpZWxlciAxIHNjb3JlIHVtIDEgZXJow7ZoZW4KCQl5U2NvcmUgPSB5b3Vfc2NvcmU7CQkJCQkJCQkJCQkvLyBTcGllbGVyIDEgc2NvcmUgaW4gZ2xhYmFlciBWYXJpYWJsZSB5U2NvcmUgZsO8ciB3ZWl0ZXJlIFZlcmFyYmVpdHVuZyBzcGVpY2hlcm4KICAgICAgICByZXNldCgmeW91LCAmeW91MiwgJmNvbXAsICZiLCB5b3Vfc2NvcmUsIHlvdTJfc2NvcmUsIGNvbXBfc2NvcmUgKTsKICAgICAgfQogICAgICBpZiAoYi54IDw9IDEpCQkJCQkJCQkJCQkJCS8vIGZhbGxzIGRlciBCYWxsIGRpZSBsaW5rZSBBdcOfZW53YW5kIHRyaWZmdAoJICB7CiAgICAgICAgYi52eCAqPSAtMTsJCQkJCQkJCQkJCQkJLy8geCAtIFJpY2h0dW5nL0dlc2Nod2luZGlna2VpdCBkZXMgQmFsbCBpbnZlcnRpZXJlbgogICAgICAgIGIueCA9IDEuMGY7CQkJCQkJCQkJCQkJCS8vIHggLSBQb3NpdGlvbiBkZXMgQmFsbHMgenVyw7xjayBhdWYgMSBzZXR6ZW4sIGRhbWl0IGVyIG5pY2h0IGRpZSBHcmVuemVuIMO8YmVycXVlcnQKICAgICAgfSAKCSAgZWxzZSBpZiAoYi54ID49IHdpZHRoIC0gMykJCQkJCQkJCQkvLyBmYWxscyBkZXIgQmFsbCBkaWUgcmVjaHRlIEF1w59lbndhbmQgdHJpZmZ0CgkgIHsKICAgICAgICBiLnZ4ICo9IC0xOwkJCQkJCQkJCQkJCQkvLyB4IC0gUmljaHR1bmcvR2VzY2h3aW5kaWdrZWl0IGRlcyBCYWxsIGludmVydGllcmVuCiAgICAgICAgYi54ID0gKGZsb2F0KSh3aWR0aCAtIDMpOwkJCQkJCQkJCQkvLyB4IC0gUG9zaXRpb24gZGVzIEJhbGxzIHp1csO8Y2sgYXVmIGRpZSBLb25zb2xlbmJyZWl0ZSAtIDMgc2V0emVuLCBkYW1pdCBlciBuaWNodCBkaWUgR3JlbnplbiDDvGJlcnF1ZXJ0CiAgICAgIH0gIAoJfQoJZWxzZSBpZih5b3Vfc2NvcmUgPT0gc2llZ1B1bmt0ZSB8fCB5b3UyX3Njb3JlID09IHNpZWdQdW5rdGUpCgl7CgkJZGlmID0gMTAwMDsKCQlzeXN0ZW0oImNscyIpOwkJCQkJCQkJCQkJCS8vIEtvbnNvbGUgbGVlcmVuCgkJdGltZSgmZW5kZXQpOwkJCQkJCQkJCQkJCS8vIFN0b3BwdWhyIHN0b3BwZW4KCQlkaWYgPSBkaWZmdGltZShlbmRldCxzdGFydCk7CQkJCQkJCQkvLyBIaWdoc2NvcmUgWmVpdCBiZXJlY2huZW4gKGVuZGUgLSBhbmZhbmcpCgkJc3RyY3B5KHNwaWVsZXJnZWJuaXMsICIiKTsJCQkJCQkJCQkvLyBzcGllbGVyZ2VibmlzIHN0cmluZyBsZWVyZW4KCQlzdHJjYXQoc3BpZWxlcmdlYm5pcywgIkdld29ubmVuISEhIik7CQkJCQkJLy8gRW5kZXJnZWJuaXMgc3BlaWNoZXJuIGbDvHIgc3DDpHRlcmUgQXVzZ2FiZQoJCXByaW50ZigiXG5cblxuXG5cblxuXG5cblx0XHQgICBHZXdvbm5lbiEhISA6KSIpOwkJCS8vIFNpZWdtZWxkdW5nIGF1c2dlYmVuCgkJcHJpbnRmKCJcblxuXG5cbiAgICAgLi4udW0gZm9ydHp1ZmFocmVuIGJpdHRlIEVudGVyIGRyXDIwMWNrZW4uLi4iKTsKCQljaGFyIGM7CQoJCXdoaWxlICgoYyA9IF9nZXRjaCgpKSAhPSBFT0YgJiYgYyAhPSAxMyk7CQkJCQkvLyBQdWZmZXIgYXV0b21hdGlzY2ggaW0gSGludGVyZ3J1bmQgbGVlcmVuCgkJc3lzdGVtKCJjbHMiKTsKCi8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gTmFtZW4gZWlubGVzZW4gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKCQlwcmludGYoIkJpdHRlIGdlYmVuIHNpZSBpaHJlbiBOYW1lbiBlaW46ICIpOwkJCQkvLyBCZW51dHplciB6dXIgTmFtZW5zZWluZ2FiZSBhdWZmb3JkZW4gdW5kIGRpZXNlbiBpbiAibmFtZSIgYWJzcGVpY2hlcm4KCQlzY2FuZigiJXMiLCBuYW1lKTsJCQoJCQovLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIEhpZ2hzY29yZXMgZWlubGVzZW4gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCgkJRklMRSAqRkRhdGVpOwkJCQkJCQkJCQkJCS8vIFplaWdlciBhdWYgZWluZSBEYXRlaSBlcnN0ZWxsZW4KCQkJCgkJRkRhdGVpID0gZm9wZW4ocGZhZCwgInIiKTsJCQkJCQkJCQkvLyBaZWlnZXIgYXVmIGRpZSBEYXRlaSwgZGllIGluICJwZmFkIiBhbmdlZ2ViZW4gaXN0IHVuZCBkaWVzZSB6dW0gbGVzZW4gw7ZmZm5lbgoJCWlmKCFGRGF0ZWkpCQkJCQkJCQkJCQkJCS8vIGZhbGxzIGRpZSBEYXRlaSBub2NoIG5pY2h0IGV4aXN0aWVydCAtPgoJCXsKCQkJRkRhdGVpID0gZm9wZW4ocGZhZCwgInciKTsJCQkJCQkJCS8vIC0+IGRpZXNlIGVyc3RlbGxlbgoJCQlmY2xvc2UoRkRhdGVpKTsJCQkJCQkJCQkJCS8vIERhdGVpIHNjaGxpZcOfZW4KCQl9CgkJaGlnaHNjb3JlRWlubGVzZW4oKTsJCQkJCQkJCQkJLy8gaW4gZGllIE1ldGhvZGUgaGlnaHNjb3JlRWlubGVzZW4oKSBzcHJpbmdlbiwgdW0gZGVuIG5ldWVuIEhpZ2hzY29yZSBhYnp1c3BlaWNoZXJuCgkJbWFpbkxvb3AgPSAxOwkJCQkJCQkJCQkJCS8vIMO8YmVyIG1haW4gRnVua3Rpb24genUgc3BpZWxlbmRlKCkgc3ByaW5nZW4gCgkJYnJlYWs7CgkgIH0KCQllbHNlIGlmKGNvbXBfc2NvcmUgPT0gc2llZ1B1bmt0ZSkKCSAgewoJCXN5c3RlbSgiY2xzIik7CQkJCQkJCQkJCQkJLy8gS29uc29sZSBsZWVyZW4KCQl0aW1lKCZlbmRldCk7CQkJCQkJCQkJCQkJLy8gU3RvcHB1aHIgc3RvcHBlbgoJCWRpZiA9IGRpZmZ0aW1lKGVuZGV0LHN0YXJ0KTsJCQkJCQkJCS8vIEhpZ2hzY29yZSBaZWl0IGJlcmVjaG5lbiAoZW5kZSAtIGFuZmFuZykKCQlzdHJjcHkoc3BpZWxlcmdlYm5pcywgIiIpOwkJCQkJCQkJCS8vIHNwaWVsZXJnZWJuaXMgc3RyaW5nIGxlZXJlbgoJCXN0cmNhdChzcGllbGVyZ2VibmlzLCAiVmVybG9yZW4hISEiKTsJCQkJCQkvLyBFbmRlcmdlYm5pcyBzcGVpY2hlcm4gZsO8ciBzcMOkdGVyZSBBdXNnYWJlCgkJcHJpbnRmKCJcblxuXG5cblxuXG5cblxuXHRcdCAgIFZlcmxvcmVuISEhIDooIik7CQkJLy8gTmllZGVybGFnZSBNZWxkdW5nIGF1c2dlYmVuCgkJcHJpbnRmKCJcblxuXG5cbiAgICAgLi4udW0gZm9ydHp1ZmFocmVuIGJpdHRlIEVudGVyIGRyXDIwMWNrZW4uLi4iKTsKCQljaGFyIGM7CQoJCXdoaWxlICgoYyA9IF9nZXRjaCgpKSAhPSBFT0YgJiYgYyAhPSAxMyk7CQkJCQkvLyBQdWZmZXIgYXV0b21hdGlzY2ggaW0gSGludGVyZ3J1bmQgbGVlcmVuIHVuZCB3YXJ0ZW4gYmlzIEVudGVyIGdlZHLDvGNrdCB3dXJkZQoJCW1haW5Mb29wID0gMTsJCQkJCQkJCQkJCQkvLyDDvGJlciBtYWluIEZ1bmt0aW9uIHp1IHNwaWVsZW5kZSgpIHNwcmluZ2VuIAoJCWJyZWFrOwoJICB9CgllbHNlIAoJewogICAgICAvLyBTdGFydGJlZGluZ3VuZ8O8YmVycHLDvGZlbiAoTGVlcnRhc3RlIGdlZHLDvGNrdD8gYnp3LiBTcGllbCBnZXN0YXJ0ZXQ/KQogICAgICBDT09SRCBwOwogICAgICBwLlggPSAoaW50KSAod2lkdGggLyAyIC0gMTYpOwogICAgICBwLlkgPSAoaW50KSAoaGVpZ2h0IC8gMS41Zik7CQogICAgICBTZXRDb25zb2xlQ3Vyc29yUG9zaXRpb24oaE91dCwgcCk7CiAgICAgIHByaW50ZigiUHJlc3MgdGhlIHNwYWNlIGJhciB0byBzdGFydC4uLiIpOwkJCQkJLy8gQ3Vyc29yIGluIGRpZSBNaXR0ZSBkZXMgQmlsZHNjaGlybXMgc2V0emVuIHVuZCBqZW5lIE1lbGR1bmcgemVpZ2VuCgogICAgICBpZiAoR2V0QXN5bmNLZXlTdGF0ZShWS19TUEFDRSkpCQkJCQkJCQkvLyBMZWVydGFzdGUgZ2VkcsO8Y2t0PwoJICB7CiAgICAgICAgQ09PUkQgcDsKICAgICAgICBwLlggPSAoaW50KSAod2lkdGggLyAyIC0gMTYpOwogICAgICAgIHAuWSA9IChpbnQpIChoZWlnaHQgLyAxLjVmKTsKICAgICAgICBTZXRDb25zb2xlQ3Vyc29yUG9zaXRpb24oaE91dCwgcCk7CQkJCQkJCS8vIGZhbGxzIGphLCBlbnRmZXJuZSBNZWxkdW5nIHdpZWRlcgogICAgICAgIHByaW50ZigiICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiKTsKICAgICAgICBnZXN0YXJ0ZXQgPSAxOwkJCQkJCQkJCQkJCS8vIFN0YXR1cyBhdWYgU3BpZWwgImdlc3RhcnRldCIgc2V0emVuLCB1bSBpbiBhbmRlcmVuIFZlcmxhdWYgZGVyIHdoaWxlIFNjaGxlaWZlIHp1IGdlbGFuZ2VuCiAgICAgIH0KICAgIH0KCiAgICAvLyBBbGxlcyB6ZWljaG5lbgogICAgZHJhdygmeW91KTsJCQkJCQkJCQkJCQkJCS8vIFNwaWVsZXIgMSBtaXQgYWt0dWVsbGVuIFdlcnRlbiB6ZWljaG5lbgoJaWYoc3BpZWxtb2R1cyA9PSAxKWRyYXcoJnlvdTIpOwkJCQkJCQkJCS8vIGZhbGxzIFNwaWVsbW9kdXMgPSBNZW5zY2ggdnMgTWVuc2NoLCBTcGllbGVyIDIgbWl0IGFrdHVlbGxlbiBXZXJ0ZW4gemVpY2huZW4KICAgIGlmKHNwaWVsbW9kdXMgPT0gMClkcmF3KCZjb21wKTsJCQkJCQkJCQkvLyBmYWxscyBTcGllbG1vZHVzID0gTWVuc2NoIHZzIENvbXB1dGVyLCBDb21wdXRlciBtaXQgYWt0dWVsbGVuIFdlcnRlbiB6ZWljaG5lbgogICAgZHJhd2JhbGwoJmIpOwkJCQkJCQkJCQkJCQkvLyBCYWxsIG1pdCBha3R1ZWxsZW4gV2VydGVuIHplaWNobmVuCiAgICAKCS8vIFZlcnrDtmdlcm4KICAgIFNsZWVwKGRlbGF5KTsJCQkJCQkJCQkJCQkJLy8gbmFjaCBqZWRlbSBEdXJjaGdhbmcgNTBtcyB3YXJ0ZW4sIHVtIMO8YmVybcOkw59pZ2VzIGZsYWNrZXJuIHp1IHZlcmhpbmRlcm4gdW5kIGRhcyBTcGllbCBpbiBlaW5lciBiZW51dHplcmZyZXVuZGxpY2hlbiAKICB9CQkJCQkJCQkJCQkJCQkJCQkvLyBHZXNjaHdpbmRpZ2tlaXQgYWJsYXVmZW4genUgbGFzc2VuCiAJfQoKCS8vIEtvbmZpZ3VyYXRpb24gZGVyIFRhc3RlbmJlbGVndW5nCgl2b2lkIHN0ZXVlcnVuZygpCgl7Cgkgc3lzdGVtKCJjbHMiKTsKCSBwcmludGYoIj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuIik7CgkgcHJpbnRmKCI9PSAgQml0dGUgd1wyMDRobGVuIHNpZSBkaWUgVGFzdGUgZGllIHNpZSB2ZXJcMjA0bmRlcm4gbVwyMjRjaHRlbiB1bmQgZHJcMjAxY2tlbiBzaWUgPT1cbiIpOwoJIHByaW50ZigiPT0gIGFuc2NobGllXDM0MWVuZCBkaWUgVGFzdGUgZGllIHNpZSB6dXdlaXNlbiB3b2xsZW4hICAgICAgICAgICAgICAgICAgICAgID09XG4iKTsJCQkJLy8gTWVuw7wgZGFyc3RlbGxlbgoJIHByaW50ZigiPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiIpOwoJIAoJIHByaW50ZigiQmVhY2h0ZTogS2xlaW5idWNoc3RhYmVuIG1cMjAxc3NlbiBhbHMgR3JvXDM0MWJ1Y2hzdGFiZW4gYW5nZWdlYmVuIHdlcmRlbiFcbiIpOwoJIHByaW50ZigiXHQgRGllIFRhc3RlbiB2b24gU3BpZWxlciAyIGtcMjI0bm5lbiBuaWNodCB2ZXJcMjA0bmRlcnQgd2VyZGVuIVxuXG5cbiIpOwoKCSBwcmludGYoIlNwaWVsZXIgMTpcbiIsbGlua3MpOwoJIHByaW50ZigiLS0tLS0tLS0tLVxuIixsaW5rcyk7CgkgcHJpbnRmKCI8MT4gTGlua3NcdFx0XHRBa3R1ZWxsZSBUYXN0ZTogJWNcbiIsbGlua3MpOwoJIHByaW50ZigiPDI+IFJlY2h0c1x0XHRcdEFrdHVlbGxlIFRhc3RlOiAlY1xuIixyZWNodHMpOwkJCQkJCQkJCQkJCQkJLy8gYWt0dWVsbGUgVGFzdGVuYmVsZWd1bmcgZsO8ciBTcGllbGVyMSBhbnplaWdlbgoJIHByaW50ZiAoIjwzPiBCZWVuZGVuXHRcdFx0QWt0dWVsbGUgVGFzdGU6ICVjXG5cbiIsYmVlbmRlbik7CgoJIHByaW50ZigiU3BpZWxlciAyOlxuIixsaW5rcyk7CgkgcHJpbnRmKCItLS0tLS0tLS0tXG4iLGxpbmtzKTsKCSBwcmludGYoIi0tPiBMaW5rc1x0XHRcdEFrdHVlbGxlIFRhc3RlOiBQZmVpbHRhc3RlIGxpbmtzXG4iKTsKCSBwcmludGYoIi0tPiBSZWNodHNcdFx0XHRBa3R1ZWxsZSBUYXN0ZTogUGZlaWx0YXN0ZSByZWNodHNcblxuXG4iKTsJCQkJCQkJCQkJCS8vIGFrdHVlbGxlIFRhc3RlbmJlbGVndW5nIGbDvHIgU3BpZWxlcjIgYW56ZWlnZW4KCgkgcHJpbnRmKCI8ND4gWnVyXDIwMWNrIHp1bSBIYXVwdG1lblwyMDEiKTsKCSAKCSBpbnQgYXVzd2FobCA9IF9nZXRjaCgpOwkJCQkJCQkJCQkJCQkJCQkJCQkJCS8vIE1lbsO8YXVzd2FobCBlaW5sZXNlbiB1bmQgaW4gImF1c3dhaGwiIHNwZWljaGVybgoKCSBpZihhdXN3YWhsID09IDQ5KQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJLy8gZmFsbHMgMSBnZWRyw7xja3QuLi4KCSB7CgkJIGxpbmtzID0gX2dldGNoKCk7CQkJCQkJCQkJCQkJCQkJCQkJCQkJCQoJCSBzeXN0ZW0oImNscyIpOwkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJLy8gZGFubiBhdWYgZXJuZXV0ZSBFaW5nYWJlIHdhcnRlbiB1bmQgZGllc2VuIGFscyBuZXVlbiBXZXJ0IGbDvHIgZGllIFRhc3RlIGxpbmtzIHNldHplbgoJCSBzdGV1ZXJ1bmcoKTsJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCS8vIEtvbnNvbGUgbGVlcmVuIHVuZCBzdGV1ZXJ1bmcoKSBlcm5ldXQgYXVmcnVmZW4sIHVtIGRhcyBNZW7DvCB6dSBha3R1YWxpc2llcmVuCgkgfQoJIGVsc2UgaWYoYXVzd2FobCA9PSA1MCkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJLy8gZmFsbHMgMiBnZWRyw7xja3QuLi4KCSB7CgkJIHJlY2h0cyA9IF9nZXRjaCgpOwkJCQkJCQkJCQkJCQkJCQkJCQkJCQkvLyBkYW5uIGF1ZiBlcm5ldXRlIEVpbmdhYmUgd2FydGVuIHVuZCBkaWVzZW4gYWxzIG5ldWVuIFdlcnQgZsO8ciBkaWUgVGFzdGUgcmVjaHRzIHNldHplbgoJCSBzeXN0ZW0oImNscyIpOwkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJLy8gS29uc29sZSBsZWVyZW4gdW5kIHN0ZXVlcnVuZygpIGVybmV1dCBhdWZydWZlbiwgdW0gZGFzIE1lbsO8IHp1IGFrdHVhbGlzaWVyZW4KCQkgc3RldWVydW5nKCk7CgkgfQoJIGVsc2UgaWYoYXVzd2FobCA9PSA1MSkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJLy8gZmFsbHMgMyBnZWRyw7xja3QuLi4KCSB7CgkJIGJlZW5kZW4gPSBfZ2V0Y2goKTsJCQkJCQkJCQkJCQkJCQkJCQkJCQkvLyBkYW5uIGF1ZiBlcm5ldXRlIEVpbmdhYmUgd2FydGVuIHVuZCBkaWVzZW4gYWxzIG5ldWVuIFdlcnQgZsO8ciBkaWUgVGFzdGUgYmVlbmRlbiBzZXR6ZW4JCQkJCQkJCQkJCQkJCgkJIHN5c3RlbSgiY2xzIik7CQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkvLyBLb25zb2xlIGxlZXJlbiB1bmQgc3RldWVydW5nKCkgZXJuZXV0IGF1ZnJ1ZmVuLCB1bSBkYXMgTWVuw7wgenUgYWt0dWFsaXNpZXJlbgoJCSBzdGV1ZXJ1bmcoKTsKCSB9CgkgZWxzZSBpZihhdXN3YWhsID09IDUyKQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkvLyBmYWxscyA0IGdlZHLDvGNrdC4uLgoJIHsKCQkgc3lzdGVtKCJjbHMiKTsJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCS8vIC4uLnp1csO8Y2sgenVtIEhhdXB0bWVuw7wKCQkgcmV0dXJuOwoJIH0KCSBlbHNlCgkgewoJCSBwcmludGYoIlxuXG5VbmdcMjAxbHRpZ2UgRWluZ2FiZSFcblxuIik7CgkJIFNsZWVwKDIwMDApOwkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJLy8gZmFsbHMgZWluZSBUYXN0ZSwgZGllIG5pY2h0IHp1ciBBdXN3YWhsIHN0ZWh0IGdlZHLDvGNrdCB3dXJkZSwgVW5nw7xsdGlnZSBFaW5nYWJlIGFuemVpZ2VuCgkJIHN5c3RlbSgiY2xzIik7CQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkvLyB1bmQgenVyw7xjayB6dW0gSGF1dHBtZW7DvAoJCSBzdGV1ZXJ1bmcoKTsKCSB9CiAJfQoKCS8vIFNjaHdpZXJpZ2tlaXRzZ3JhZCwgQmFsbGdlc2Nod2luZGlna2VpdAoJLy8gZWluc3RlbGxlbiwgYWxsZXMgenVyw7xja3NldHplbgoJdm9pZCBlaW5zdGVsbHVuZ2VuKCkKIAl7Cgkgc3lzdGVtKCJjbHMiKTsKCSBwcmludGYoIkJpdHRlIHdcMjA0aGxlbiBzaWUgZWluZSBFaW5zdGVsbHVuZyBkaWUgc2llIHZlclwyMDRuZGVybiBtXDIyNGNodGVuIVxuXG4iKTsKCSBwcmludGYoIjwxPiBTcGllbG1vZHVzIC8gU3BpZWxlcmFuemFobFx0XHRBa3R1ZWxsZXIgTW9kdXM6ICVzXG4iLG1vZHVzKTsKCSBwcmludGYoIjwyPiBTY2h3aWVyaWVna2VpdHNncmFkIFwyMDRuZGVyblx0XHRBa3R1ZWxsZSBTY2h3aWVyaWdrZWl0OiAlc1xuIixzY2h3aWVyaWdrZWl0KTsJCQkvLyBNZW7DvCBtaXQgYWt0dWVsbGVuIEVpbnN0ZWxsdW5nZW4gYW56ZWlnZW4KCSBwcmludGYoIjwzPiBNYXhpbWFsZSBCYWxsZ2VzY2h3aW5kaWdrZWl0XHRBa3R1ZWxsZSBHZXNjaHdpbmRpZ2tlaXQ6ICUuMmZcbiIsbWF4U3BlZWQpOwoJIHByaW50ZigiPDQ+IEFuemFobCBkZXIgUHVua3RlIGJpcyB6dW0gU2llZ1x0QWt0dWVsbGUgU2llZ3B1bmt0ZTogJWlcbiIsc2llZ1B1bmt0ZSk7CgkgcHJpbnRmKCI8NT4gQWxsZSBFaW5zdGVsbHVuZ2VuIHp1clwyMDFja3NldHplblxuIik7CgkgcHJpbnRmKCI8Nj4gSGlnaHNjb3JlIHp1clwyMDFja3NldHp0ZW5cbiIpOwoJIHByaW50ZigiPDc+IFp1clwyMDFjayB6dW0gSGF1cHRtZW5cMjAxXG5cbiIpOwoKCSBpbnQgYXVzd2FobCA9IF9nZXRjaCgpOwkJCQkJCQkJCQkJCQkJCQkJCQkvLyBNZW7DvGF1c3dhaGwgZWlubGVzZW4gdW5kIGluICJhdXN3YWhsIiBzcGVpY2hlcm4KCgkgaWYoYXVzd2FobCA9PSA0OSkJCQkJCQkJCQkJCQkJCQkJCQkJCQkvLyBFaW5nYWJlIGF1c3dlcnRlbiAoZmFsbHMgMSBnZWRyw7xja3QpCgkgewoJCSBzeXN0ZW0oImNscyIpOwoJCSBwcmludGYoIldcMjA0aGxlbiBzaWUgaWhyZW4gYmV2b3J6dWd0ZW4gU3BpZWxtb2R1cyFcblxuIik7CgkJIHByaW50ZigiPDE+IE1lbnNjaCB2cyBDb21wdXRlclxuIik7CQkJCQkJCQkJCQkJCQkJLy8gZGFubiBTcGllbG1vZHVzIE1lbsO8IGRhcnN0ZWxsZW4KCQkgcHJpbnRmKCI8Mj4gTWVuc2NoIHZzIE1lbnNjaFxuIik7CgoJCSBjaGFyIHp3aXNjaGVuc3BbNjBdOwkJCQkJCQkJCQkJCQkJCQkJCQkvLyBjaGFyIGFycmF5LCB1bSBwZmFkIGbDvHIgSGlnaHNjb3JlLnR4dCB3w6RocmVuZCBNZWhyc3BpZWxlciB6d2lzY2hlbnp1c3BlaWNoZXJuCgkJIGludCBhdXN3YWhsID0gX2dldGNoKCk7CQkJCQkJCQkJCQkJCQkJCQkJLy8gTWVuw7xhdXN3YWhsIGVpbmxlc2VuIHVuZCBpbiAiYXVzd2FobCIgc3BlaWNoZXJuCgkJIHN0cmNweShtb2R1cywgIiIpOwkJCQkJCQkJCQkJCQkJCQkJCQkJLy8gY2hhciBhcnJheSAibW9kdXMiIGxlZXJlbgoKCQkgaWYoYXVzd2FobCA9PSA0OSkKCQkgewoJCQkgc3BpZWxtb2R1cyA9IDA7CgkJCSBzdHJjYXQobW9kdXMsICJNZW5zY2ggdnMgQ29tcHV0ZXIiKTsJCQkJCQkJCQkJCQkJCS8vIEFuemVpZ2UgaW0gRWluc3RlbGx1bmdzbWVuw7wgYWt0dWFsaXNpZXJlbiAoYWx0ZXIgU3RyaW5nIHdpcmQgZ2Vsw7ZzY2h0IHVuZCBuZXVlciBhbmdlaMOkbmd0KQkJCgkJCSBzdHJjcHkocGZhZCwgendpc2NoZW5zcCk7CQkJCQkJCQkJCQkJCQkJCQkvLyBQZmFkIGbDvHIgSGlnaHNjb3JlZGF0ZWkgYWt0dWFsaXNpZXJlbgoJCQkgcmV0dXJuOwkJCQkJCQkJCQkJCQkJCQkJCQkJCS8vIHp3aXNjaGVuZ2VzcGVpY2hlcnRlbiBQZmFkIChpbiAiendpc2NoZW5zcCIpIHdpZWRlciBpbiAicGZhZCIga29waWVyZW4KCQkgfQoJCSBlbHNlIGlmKGF1c3dhaGwgPT0gNTApCgkJIHsKCQkJIHN0cmNweSh6d2lzY2hlbnNwLHBmYWQpOwoJCQkgc3BpZWxtb2R1cyA9IDE7CgkJCSBzdHJjYXQobW9kdXMsICJNZW5zY2ggdnMgTWVuc2NoIik7CQkJCQkJCQkJCQkJCQkJLy8gQW56ZWlnZSBpbSBFaW5zdGVsbHVuZ3NtZW7DvCBha3R1YWxpc2llcmVuIChhbHRlciBTdHJpbmcgd2lyZCBnZWzDtnNjaHQgdW5kIG5ldWVyIGFuZ2Vow6RuZ3QpCQoJCQkgc3RyY3B5KHBmYWQsICJDOlxcTWVocnNwaWVsZXIudHh0Iik7CQkJCQkJCQkJCQkJCQkvLyBQZmFkIGbDvHIgSGlnaHNjb3JlZGF0ZWkgYWt0dWFsaXNpZXJlbgoJCQkgcmV0dXJuOwkKCQkgfQoJIH0KCSBlbHNlIGlmKGF1c3dhaGwgPT0gNTApCQkJCQkJCQkJCQkJCQkJCQkJCQkvLyBFaW5nYWJlIGF1c3dlcnRlbgoJIHsKCQkgc3lzdGVtKCJjbHMiKTsKCQkgcHJpbnRmKCJXXDIwNGhsZW4gc2llIGlocmVuIGJldm9yenVndGVuIFNjaHdpZXJpZ2tlaXRzZ3JhZCFcblxuIik7CgkJIHByaW50ZigiPDE+IEFtYXRldXJcbiIpOwkJCQkJCQkJCQkJCQkJCQkJCS8vIFNjaHdpZXJpZ2tlaXRzZ3JhZCBNZW7DvCDDtmZmbmVuCgkJIHByaW50ZigiPDI+IE1hY2hiYXJcbiIpOwoJCSBwcmludGYoIjwzPiBWZXRlcmFuXG4iKTsKCQkgcHJpbnRmKCI8ND4gTmVydnRcMjI0dGVuZFxuIik7CgoJCSBpbnQgYXVzd2FobCA9IF9nZXRjaCgpOwkJCQkJCQkJCQkJCQkJCQkJCS8vIE1lbsO8YXVzd2FobCBlaW5sZXNlbgoJCSBzdHJjcHkoc2Nod2llcmlna2VpdCwgIiIpOwoKCQkgaWYoYXVzd2FobCA9PSA0OSkJCQkJCQkJCQkJCQkJCQkJCQkJCS8vIGZhbGxzIDEgZ2VkcsO8Y2t0IGRhbm4uLi4KCQkgewoJCQkgbW9kaWZpa2F0b3IgPSAwOwoJCQkgbW9kaWZpa2F0b3IgKz0gMjsJCQkJCQkJCQkJCQkJCQkJCQkJLy8gUGFkbMOkbmdlIGFucGFzc2VuCgkJCSBtYXhTcGVlZCA9IDEuOGY7CQkJCQkJCQkJCQkJCQkJCQkJCS8vIEJhbGxnZXNjaHdpbmRpZ2tlaXQgamUgbmFjaCBBdXN3YWhsIGFucGFzc2VuCgkJCSBzdHJjYXQoc2Nod2llcmlna2VpdCwgIkFtYXRldXIiKTsJCQkJCQkJCQkJCQkJCQkvLyBTY2h3aWVyaWdrZWl0c2dyYWRhbnplaWdlIGltIEVpbnN0ZWxsdW5nc21lbsO8IGFrdHVhbGlzaWVyZW4KCQkJIHN0cmNweShwZmFkLCAiQzpcXEFtYXRldXIudHh0Iik7CQkJCQkJCQkJCQkJCQkJLy8gUGZhZCBmw7xyIEhpZ2hzY29yZWRhdGVpIGFrdHVhbGlzaWVyZW4KCQkJIGtpUmVha3Rpb24gPSAxMC4wZjsJCQkJCQkJCQkJCQkJCQkJCQkvLyBDb21wdXRlciBTY2huZWxsaWdrZWl0IHNldHplbgoJCQkgcmV0dXJuOwkJCQkJCQkJCQkJCQkJCQkJCQkJCS8vIChhbHRlciBTdHJpbmcgd2lyZCBnZWzDtnNjaHQgdW5kIG5ldWVyIGFuZ2Vow6RuZ3QpCgkJIH0KCQkgZWxzZSBpZihhdXN3YWhsID09IDUwKQoJCSB7CgkJCSBtb2RpZmlrYXRvciA9IDA7CgkJCSBzdHJjYXQoc2Nod2llcmlna2VpdCwgIk1hY2hiYXIiKTsJCQkJCQkJCQkJCQkJCQkvLyBkYXMgc2VsYmUgZsO8ciBhbGxlIGFuZGVybiBTY2h3aWVyaWdrZWl0c2dyYWRlCgkJCSBzdHJjcHkocGZhZCwgIkM6XFxNYWNoYmFyLnR4dCIpOwoJCQkga2lSZWFrdGlvbiA9IDguMGY7CgkJCSBtYXhTcGVlZCA9IDMuMmY7CgkJCSByZXR1cm47CgkJIH0KCQkgZWxzZSBpZihhdXN3YWhsID09IDUxKQoJCSB7CgkJCSBtb2RpZmlrYXRvciA9IDA7CgkJCSBtb2RpZmlrYXRvciAtPSAyOwoJCQkgc3RyY2F0KHNjaHdpZXJpZ2tlaXQsICJWZXRlcmFuIik7CgkJCSBzdHJjcHkocGZhZCwgIkM6XFxWZXRlcmFuLnR4dCIpOwoJCQkga2lSZWFrdGlvbiA9IDYuMGY7CgkJCSBtYXhTcGVlZCA9IDQuNWY7CgkJCSByZXR1cm47CgkJIH0KCQkgZWxzZSBpZihhdXN3YWhsID09IDUyKQoJCSB7CgkJCSBtb2RpZmlrYXRvciA9IDA7CgkJCSBtb2RpZmlrYXRvciAtPSA0OwoJCQkgc3RyY2F0KHNjaHdpZXJpZ2tlaXQsICJOZXJ2dFwyMjR0ZW5kIik7CgkJCSBzdHJjcHkocGZhZCwgIkM6XFxOZXJ2dFwyMjR0ZW5kLnR4dCIpOwoJCQkga2lSZWFrdGlvbiA9IDMuN2Y7CgkJCSBtYXhTcGVlZCA9IDYuMGY7CgkJCSByZXR1cm47CgkJIH0KCQkgZWxzZQoJCSB7CgkJCXByaW50ZigiXG5cblVuZ1wyMDFsdGlnZSBFaW5nYWJlIVxuXG4iKTsJCQkJCQkJCQkJCQkJLy8gZmFsbHMgZWluZSBUYXN0ZSwgZGllIG5pY2h0IHp1ciBBdXN3YWhsIHN0ZWh0IGdlZHLDvGNrdCB3dXJkZSwgVW5nw7xsdGlnZSBFaW5nYWJlIGFuemVpZ2VuCgkJCVNsZWVwKDIwMDApOwkJCQkJCQkJCQkJCQkJCQkJCQkJLy8gdW5kIHp1csO8Y2sgenVtIEhhdXRwbWVuw7wKCQkJcmV0dXJuOwoJCSB9CgkgfQoJIGVsc2UgaWYoYXVzd2FobCA9PSA1MSkKCSB7CgkJIHByaW50ZigiTmV1ZSBCYWxsZ2VzY2h3aW5kaWdrZWl0IGVpbmdlYmVuIVxuXG4iKTsJCQkJCQkJCQkJCQkvLyBBYmZyYWdlIG5hY2ggbmV1ZXIgQmFsbGdlc2Nod2luZGlna2VpdAoJCSBzY2FuZigiJWYiLCZtYXhTcGVlZCk7CQoKCQkgaWYobWF4U3BlZWQgIT0gMS44ZiAmJiBtYXhTcGVlZCAhPSAyLjhmICYmIG1heFNwZWVkICE9IDMuNWYgJiYgbWF4U3BlZWQgIT0gNSkJCQkJCS8vIEZhbGxzIEJhbGxnZXNjaHdpbmRpZ2tlaXQgdW5nbGVpY2ggZGVuIFZvcmVpbnN0ZWxsdW5nZW4sIHNvCgkJIHsKCQkJc3RyY3B5KHNjaHdpZXJpZ2tlaXQsIiIpOwkJCQkJCQkJCQkJCQkJCQkJLy8gd2lyZCBkaWUgU2Nod2llcmlna2VpdHNhbnplaWdlIGF1ZiAiUGVyc8O2bmxpY2giIGdlc2V0enQKCQkJc3RyY2F0KHNjaHdpZXJpZ2tlaXQsICJQZXJzXDIyNG5saWNoIik7CgkJCXN5c3RlbSgiY2xzIik7CgkJIH0KCQkgZWluc3RlbGx1bmdlbigpOwkJCQkJCQkJCQkJCQkJCQkJCQkJLy8genVyw7xjayB6dW0gRWluc3RlbGx1bmdzbWVuw7wKCSB9CgkgZWxzZSBpZihhdXN3YWhsID09IDUyKQoJIHsKCQkgcHJpbnRmKCJOZXVlIEFuemFobCBkZXIgYmVuXDIyNHRpZ3RlbiBTaWVncHVua3RlIGVpbmdlYmVuIVxuXG4iKTsJCQkJCQkJCS8vIEFiZnJhZ2UgbmFjaCBuZXVlciBCYWxsZ2VzY2h3aW5kaWdrZWl0CgkJIHNjYW5mKCIlaSIsJnNpZWdQdW5rdGUpOwoJCSBzeXN0ZW0oImNscyIpOwoJCSByZXR1cm47CgkgfQoJIGVsc2UgaWYoYXVzd2FobCA9PSA1MykKCSB7CgkJIHN5c3RlbSgiY2xzIik7CgkJIHByaW50ZigiU2luZCBzaWUgc2ljaCBzaWNoZXIsIGRhc3Mgc2llIGFsbGUgRWluc3RlbGx1bmdlbiB6dXJcMjAxY2tzZXR6ZW4gbVwyMjRjaHRlbj9cblxuIik7CS8vIEZyYWdlbiwgb2IgZGVyIEJlbnV0emVyIHNpY2hlciBpc3QsIGRhc3MgZXIgZGllIEVpbnN0ZWxsdW5nZW4genVyw7xja3NldHplbiBtw7ZjaHRlCgkJIHByaW50ZigiPDE+IEphLCBhbGxlIGxcMjI0c2NoZW5cbiIpOwoJCSBwcmludGYoIjwyPiBOZWluLCB6dXJcMjAxY2sgenUgRWluc3RlbGx1bmdlbiIpOwoKCQkgaW50IGF1c3dhaGwgPSBfZ2V0Y2goKTsJCQkJCQkJCQkJCQkJCQkJCQkvLyBCZW51dHplcmVpbmdhYmUgZWlubGVzZW4KCQkgCgkJIGlmKGF1c3dhaGwgPT0gNDkpCgkJIHsKCQkJc3lzdGVtKCJjbHMiKTsKCQkJc3RyY3B5KHNjaHdpZXJpZ2tlaXQsIiIpOwoJCQlzdHJjYXQoc2Nod2llcmlna2VpdCwgIk1hY2hiYXIiKTsJCQkJCQkJCQkJCQkJCQkvLyBBbGxlIFdlcnRlIGF1ZiBTdGFuZGFyZCBzZXR6ZW4KCQkJbWF4U3BlZWQgPSAzLjJmOwoJCQlsaW5rcyA9IDY1LCByZWNodHMgPSA2OCwgYmVlbmRlbiA9IDgxOyAKCQkJcHJpbnRmKCJcbiBFaW5zdGVsbHVuZ2VuIGVyZm9sZ3JlaWNoIHp1clwyMDFja2dlc2V0enQhIik7CgkJCVNsZWVwKDI1MDApOwoJCQlzeXN0ZW0oImNscyIpOwoJCQlyZXR1cm47CgkJICB9CgkJICBlbHNlIGlmKGF1c3dhaGwgPT0gNTApCgkJICB7CgkJCWVpbnN0ZWxsdW5nZW4oKTsJCQkJCQkJCQkJCQkJCQkJCQkJLy8gZmFsbHMgbmVpbiwgenVyw7xjayB6dW0gRWluc3RlbGx1bmdzbWVuw7wKCQkgIH0KCQkgIGVsc2UKCQkgIHsKCQkJcHJpbnRmKCJcblxuVW5nXDIwMWx0aWdlIEVpbmdhYmUhXG5cbiIpOwoJCQlTbGVlcCgyMDAwKTsJCQkJCQkJCQkJCQkJCQkJCQkJCS8vIGZhbGxzIGVpbmUgVGFzdGUsIGRpZSBuaWNodCB6dXIgQXVzd2FobCBzdGFuZCBnZWRyw7xja3Qgd3VyZGUsIFVuZ8O8bHRpZ2UgRWluZ2FiZSBhbnplaWdlbgoJCQlzeXN0ZW0oImNscyIpOwkJCQkJCQkJCQkJCQkJCQkJCQkJLy8gdW5kIHp1csO8Y2sgenVtIEhhdXRwbWVuw7wKCQkJZWluc3RlbGx1bmdlbigpOwoJCSAgfQoJIH0KCSBlbHNlIGlmKGF1c3dhaGwgPT0gNTQpCgkgewoJCSBzeXN0ZW0oImNscyIpOwkKCQkgcHJpbnRmKCJTaW5kIHNpZSBzaWNoIHNpY2hlciwgZGFzcyBzaWUgYWxsZSBIaWdoc2NvcmVzIGxcMjI0c2NoZW4gbVwyMjRjaHRlbj9cblxuIik7CQkJLy8gRnJhZ2VuLCBvYiBkZXIgQmVudXR6ZXIgc2ljaGVyIGlzdCwgZGFzcyBlciBkaWUgSGlnaHNjb3JlcyBsw7ZzY2hlbiBtw7ZjaHRlCgkJIHByaW50ZigiPDE+IEphLCBhbGxlIGxcMjI0c2NoZW5cbiIpOwoJCSBwcmludGYoIjwyPiBOZWluLCB6dXJcMjAxY2sgenUgRWluc3RlbGx1bmdlbiIpOwoKCQkgaW50IGF1c3dhaGwgPSBfZ2V0Y2goKTsJCQkJCQkJCQkJCQkJCQkJCQkvLyBCZW51dHplcmVpbmdhYmUgZWlubGVzZW4KCgkJIGlmKGF1c3dhaGwgPT0gNDkpCgkJIHsKCQkJRklMRSAqRkRhdGVpOwoJCQlGRGF0ZWkgPSBmb3BlbigiQzpcXEFtYXRldXIiLCJ3Iik7CQkJCQkJCQkJCQkJCQkJLy8gQWx0ZSBIaWdoc2NvcmUgVGV4dGRhdGVpIGzDtnNjaGVuIHVuZCBuZXVlIGxlZXJlIERhdGVpIGVyc3RlbGxlbgoJCQlmY2xvc2UoRkRhdGVpKTsKCQkJRkRhdGVpID0gZm9wZW4oIkM6XFxNYWNoYmFyLnR4dCIsInciKTsJCQkJCQkJCQkJCQkJCS8vIEFsdGUgSGlnaHNjb3JlIFRleHRkYXRlaSBsw7ZzY2hlbiB1bmQgbmV1ZSBsZWVyZSBEYXRlaSBlcnN0ZWxsZW4KCQkJZmNsb3NlKEZEYXRlaSk7CQoJCQlGRGF0ZWkgPSBmb3BlbigiQzpcXFZldGVyYW4udHh0IiwidyIpOwkJCQkJCQkJCQkJCQkJLy8gQWx0ZSBIaWdoc2NvcmUgVGV4dGRhdGVpIGzDtnNjaGVuIHVuZCBuZXVlIGxlZXJlIERhdGVpIGVyc3RlbGxlbgoJCQlmY2xvc2UoRkRhdGVpKTsJCgkJCUZEYXRlaSA9IGZvcGVuKCJDOlxcTmVydnRcMjI0dGVuZC50eHQiLCJ3Iik7CQkJCQkJCQkJCQkJLy8gQWx0ZSBIaWdoc2NvcmUgVGV4dGRhdGVpIGzDtnNjaGVuIHVuZCBuZXVlIGxlZXJlIERhdGVpIGVyc3RlbGxlbgoJCQlmY2xvc2UoRkRhdGVpKTsKCQkJRkRhdGVpID0gZm9wZW4oIkM6XFxNZWhyc3BpZWxlci50eHQiLCJ3Iik7CQkJCQkJCQkJCQkJCS8vIEFsdGUgSGlnaHNjb3JlIFRleHRkYXRlaSBsw7ZzY2hlbiB1bmQgbmV1ZSBsZWVyZSBEYXRlaSBlcnN0ZWxsZW4KCQkJZmNsb3NlKEZEYXRlaSk7CQoJCQlzeXN0ZW0oImNscyIpOwoJCQlwcmludGYoIkhpZ2hzY29yZXMgZXJmb2xncmVpY2ggenVyXDIwMWNrZ2VzZXR6dCEiKTsKCQkJU2xlZXAoMjAwMCk7CQkJCQkJCQkJCQkJCQkJCQkJCQkvLyAiRXJmb2xncmVpY2giIE1lbGR1bmcgYXVzZ2ViZW4gdW5kIDIgc2VrdW5kZW4gd2FydGVuCgkJCXJldHVybjsKCQkgfQoJCSBlbHNlIGlmKGF1c3dhaGwgPT0gNTApCgkJIHsKCQkJZWluc3RlbGx1bmdlbigpOwkJCQkJCQkJCQkJCQkJCQkJCQkvLyBhbnNvbnN0ZW4genVyw7xjayBpbiBkYXMgRWluc3RlbGx1bmdzbWVuw7wKCQkgfQoJCSBlbHNlCgkJIHsKCQkJcHJpbnRmKCJcblxuVW5nXDIwMWx0aWdlIEVpbmdhYmUhXG5cbiIpOwoJCQlTbGVlcCgyMDAwKTsJCQkJCQkJCQkJCQkJCQkJCQkJCS8vIGZhbGxzIGVpbmUgVGFzdGUsIGRpZSBuaWNodCB6dXIgQXVzd2FobCBzdGVodCBnZWRyw7xja3Qgd3VyZGUsIFVuZ8O8bHRpZ2UgRWluZ2FiZSBhbnplaWdlbgoJCQlzeXN0ZW0oImNscyIpOwkJCQkJCQkJCQkJCQkJCQkJCQkJLy8gdW5kIHp1csO8Y2sgenVtIEhhdXRwbWVuw7wKCQkJZWluc3RlbGx1bmdlbigpOwoJCSB9CgkgfQoJIGVsc2UgaWYoYXVzd2FobCA9PSA1NSkJCQkJCQkJCQkJCQkJCQkJCQkJCS8vIGZhbGxzIGltIEVpbnN0ZWxsdW5nZW5tZW7DvCA3IGdlZHLDvGNrdCB3dXJkZSBkYW5uLi4uCgkgewoJCSBzeXN0ZW0oImNscyIpOwkJCQkJCQkJCQkJCQkJCQkJCQkJCS8vIC4uLnp1csO8Y2sgenVtIEhhdXB0bWVuw7wKCQkgcmV0dXJuOwoJIH0KCSBlbHNlCgkgewoJCSBwcmludGYoIlxuXG5VbmdcMjAxbHRpZ2UgRWluZ2FiZSFcblxuIik7CgkJIFNsZWVwKDIwMDApOwkJCQkJCQkJCQkJCQkJCQkJCQkJCS8vIGZhbGxzIGVpbmUgVGFzdGUsIGRpZSBuaWNodCB6dXIgQXVzd2FobCBzdGVodCBnZWRyw7xja3Qgd3VyZGUsIFVuZ8O8bHRpZ2UgRWluZ2FiZSBhbnplaWdlbgoJCSBzeXN0ZW0oImNscyIpOwkJCQkJCQkJCQkJCQkJCQkJCQkJCS8vIHVuZCB6dXLDvGNrIHp1bSBIYXV0cG1lbsO8CgkJIGVpbnN0ZWxsdW5nZW4oKTsKCSB9CgoJIAoJIAogCX0KCgkvLyBIYXVwdG1lbsO8IGFuemVpZ2VuIHVuZCBBdXN3YWhsIGF1c3dlcnRlbgoJdm9pZCBtZW51KCkKIAl7CgoJc2V0V2luZG93U2l6ZSg4MCwyNSk7CQkJCQkJCQkJCQkJCQkJCQkvLyBzZXRXaW5kb3dTaXplKCkgTWV0aG9kZSBhdWZydWZlbiwgdW0gZGllIFN0YW5kYXJ0Z3LDtsOfZSBkZXIgS29uc29sZSAoODAsMjUpIG5hY2ggZGVtIFNwaWVsIHdpZWRlcmhlcnp1c3RlbGxlbgoKCXN5c3RlbSgiY2xzIik7CQkJCQkJCQkJCQkJCQkJCQkJCS8vIEtvbnNvbGUgbGVlcmVuCglwcmludGYoIldcMjA0aGxlbiBzaWUgZWluZSBNXDIyNGdsaWNoa2VpdCFcblxuIik7CglwcmludGYoIjwxPiBQb25nIHNwaWVsZW5cbiIpOwoJcHJpbnRmKCI8Mj4gU3RldWVydW5nXG4iKTsJCQkJCQkJCQkJCQkJCQkJLy8gTWVuw7wgZGFyc3RlbGxlbgoJcHJpbnRmKCI8Mz4gSGlnaHNjb3JlXG4iKTsKCXByaW50ZigiPDQ+IEVpbnN0ZWxsdW5nZW5cbiIpOwoJcHJpbnRmKCI8NT4gU3BpZWwgYmVlbmRlblxuXG4iKTsKCWludCBhdXN3YWhsID0gX2dldGNoKCk7CQoJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCS8vIEF1ZiBCZW51dHplcmVpbmdhYmUgd2FydGVuIHVuZCBkaWVzZSBpbiAiYXVzd2FobCIgc3BlaWNoZXJuCglzeXN0ZW0oImNscyIpOwkJCQkJCQkJCQkJCQkJCQkJCQkvLyBLb25zb2xlIGVybmV1dCBsZWVyZW4KCglpZihhdXN3YWhsID09IDQ5KQkJCQkJCQkJCQkJCQkJCQkJCQkKCXsKCQlzcGllbGVuKCk7CQkJCQkJCQkJCQkJCQkJCQkJCQoJfQoJZWxzZSBpZihhdXN3YWhsID09IDUwKQkJCQkJCQkJCQkJCQkJCQkJLy8gamUgbmFjaCBBdXN3YWhsLCBkYXMgZW5zdHByZWNoZW5kZSBVbnRlcm1lbsO8IMO2ZmZuZW4KCXsKCQlzdGV1ZXJ1bmcoKTsKCX0KCWVsc2UgaWYoYXVzd2FobCA9PSA1MSkKCXsKCQloaWdoc2NvcmVBdXNnZWJlbigpOwoJfQoJZWxzZSBpZihhdXN3YWhsID09IDUyKQoJewoJCWVpbnN0ZWxsdW5nZW4oKTsKCX0KCWVsc2UgaWYoYXVzd2FobCA9PSA1MykJCQkJCQkJCQkJCQkJCQkJCS8vIGZhbGxzIDUgZ2VkcsO8Y2t0Li4uCgl7CgkJbWFpbkxvb3AgPSAyOwkJCQkJCQkJCQkJCQkJCQkJCS8vIC4uLk1haW4gU2NobGVpZmUgdW50ZXJicmVjaGVuIHVuZCBQcm9ncmFtbSBiZWVuZGVuCgl9CgllbHNlCgl7CgkJIHByaW50ZigiXG5cblVuZ1wyMDFsdGlnZSBFaW5nYWJlIVxuXG4iKTsKCQkgU2xlZXAoMjAwMCk7CQkJCQkJCQkJCQkJCQkJCQkJLy8gZmFsbHMgZWluZSBUYXN0ZSwgZGllIG5pY2h0IHp1ciBBdXN3YWhsIHN0ZWh0IGdlZHLDvGNrdCB3dXJkZSwgVW5nw7xsdGlnZSBFaW5nYWJlIGFuemVpZ2VuCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkKCQkgbWVudSgpOwkJCQkJCQkJCQkJCQkJCQkJCQkvLyB1bmQgenVyw7xjayB6dW0gSGF1dHBtZW7DvAoJfQogCX0KCQoJLy8gQmVnaW5uIGRlcyBQcm9ncmFtbXMgZGlyZWt0ZXIgVmVyd2VpcyBuYWNoIE1lbsO8CglpbnQgbWFpbigpCgl7CQoKCQkvLyBDdXJzb3IgdmVyc3RlY2tlbgoJCUNPTlNPTEVfQ1VSU09SX0lORk8gQ29uQ3VySW5mOwoJCWhPdXQgPSBHZXRTdGRIYW5kbGUoU1REX09VVFBVVF9IQU5ETEUpOwoJCUNvbkN1ckluZi5kd1NpemUgPSAxMDsKCQkvL0NvbkN1ckluZi5iVmlzaWJsZSA9IGZhbHNlOwoJCVNldENvbnNvbGVDdXJzb3JJbmZvKGhPdXQsICZDb25DdXJJbmYpOwoKCQl3aGlsZShtYWluTG9vcCA8PSAxKQoJCXsKCQkJaWYobWFpbkxvb3AgPT0gMCkKCQkJewoJCQkJbWVudSgpOwkJCQkJCQkJCQkJCQkJCQkJCQkJCS8vIHZlcmhpbmRlcm4sIGRhc3MgZGFzIFByb2dyYW1tIGZyw7xoemVpdGlnIGJlZW5kZXQgd2lyZAoJCQl9CgkJCWVsc2UgaWYobWFpbkxvb3AgPT0gMSkKCQkJewoJCQkJc3BpZWxlbmRlKCk7CQkJCQkJCQkJCQkJCQkJCQkJCS8vIHNwaWVsZW5kZSgpIGF1ZnJ1ZmVuLCBzb2JhbGQgZGFzIFNwaWVsIGJlZW5kZXQgd3VyZGUgYnp3LiBtYWluTG9vcCB6dSAxIGdlc2V0enQgd3VyZGUKCQkJfQoJCQkKCQl9CQoKCX0=