//Пункты меню, можно добавить до 10
String menuItems[ ] = { "Meteo" , "Meteo+" , "Set alarm" , "About" } ;
//Переменная для кнопок навигации
int readKey;
//Переменные для меню
int menuPage = 0 ;
int maxMenuPages = round( ( ( sizeof ( menuItems) / sizeof ( String) ) / 2 ) + .5 ) ;
int cursorPosition = 0 ;
//Дополнительные симводы
byte downArrow[ 8 ] = {
0b00100 , // *
0b00100 , // *
0b00100 , // *
0b00100 , // *
0b00100 , // *
0b10101 , // * * *
0b01110 , // ***
0b00100 // *
} ;
byte upArrow[ 8 ] = {
0b00100 , // *
0b01110 , // ***
0b10101 , // * * *
0b00100 , // *
0b00100 , // *
0b00100 , // *
0b00100 , // *
0b00100 // *
} ;
byte menuCursor[ 8 ] = {
B01000, // *
B00100, // *
B00010, // *
B00001, // *
B00010, // *
B00100, // *
B01000, // *
B00000 //
} ;
byte termometru[ 8 ] = //Температура
{
B00100,
B01010,
B01010,
B01110,
B01110,
B11111,
B11111,
B01110
} ;
byte picatura[ 8 ] = //Влажность
{
B00100,
B00100,
B01010,
B01010,
B10001,
B10001,
B10001,
B01110,
} ;
byte ring[ 8 ] = //Будильник
{
B00000,
B00100,
B01110,
B01110,
B01110,
B11111,
B00100,
B00000
} ;
//Подключение необходимых библиотек
#include <Wire.h>
#include <LiquidCrystal.h>
#include <DS3231.h> //ЧАСЫ
#include "DHT.h" //DHT
#include <BMP085.h> //BMP
#include <EEPROM.h>
//Инициализация LCD Keypad shield
LiquidCrystal lcd( 8 , 9 , 4 , 5 , 6 , 7 ) ;
DS3231 rtc( SDA, SCL) ; //ЧАСЫ
Time t; //ЧАСЫ
BMP085 dps = BMP085( ) ; //BMP
#define DHTPIN 1 //DHT ПИН
#define DHTTYPE DHT22 //Тип DHT
DHT dht( DHTPIN, DHTTYPE) ; //DHT
long Temperature = 0 , Pressure = 0 , Altitude = 0 ; //BMP
#define tonePin 11 //Пин пьезоэлемента
void setup( ) {
//Serial.begin(9600);
rtc.begin ( ) ; //ЧАСЫ
dht.begin ( ) ; //DHT
Wire.begin ( ) ; //Для BMP
dps.init ( MODE_ULTRA_HIGHRES, 14000 , true ) ; //BMP, 130 Метров над уровнем моря
//Инициализация LCD экрана
lcd.begin ( 16 , 2 ) ;
lcd.clear ( ) ;
//Создание дополнительных символов
lcd.createChar ( 0 , menuCursor) ;
lcd.createChar ( 1 , upArrow) ;
lcd.createChar ( 2 , downArrow) ;
lcd.createChar ( 3 , termometru) ;
lcd.createChar ( 4 , picatura) ;
lcd.createChar ( 5 , ring) ;
analogWrite( 10 , 155 ) ; //Яркость (до 255)
//Нужно для того, что бы при перезагрузке перекидывало на то меню в котором мы были последний раз
if ( EEPROM.read ( 0 ) == 1 ) {
menuItem1( ) ;
} else if ( EEPROM.read ( 0 ) == 2 ) {
menuItem2( ) ;
} else if ( EEPROM.read ( 0 ) == 3 ) {
menuItem3( ) ;
} else if ( EEPROM.read ( 0 ) == 4 ) {
menuItem4( ) ;
} else if ( EEPROM.read ( 0 ) == 5 ) {
menuItem5( ) ;
} else if ( EEPROM.read ( 0 ) == 0 ) { }
}
void loop( ) {
mainMenuDraw( ) ;
drawCursor( ) ;
operateMainMenu( ) ;
}
//Функция будильника, в данном случае пищать зуммером
void ton( ) {
lcd.clear ( ) ;
delay( 250 ) ;
lcd.setCursor ( 0 , 0 ) ;
lcd.print ( "WAKE UP" ) ;
lcd.setCursor ( 13 , 1 ) ;
lcd.print ( "NEO..." ) ;
tone( tonePin, 440 , 250 ) ;
delay( 250 ) ;
tone( tonePin, 165 , 250 ) ;
delay( 250 ) ;
tone( tonePin, 440 , 250 ) ;
delay( 250 ) ;
delay( 250 ) ;
tone( tonePin, 440 , 250 ) ;
delay( 250 ) ;
tone( tonePin, 165 , 250 ) ;
delay( 250 ) ;
tone( tonePin, 440 , 250 ) ;
delay( 250 ) ;
delay( 250 ) ;
tone( tonePin, 330 , 125 ) ;
delay( 125 ) ;
tone( tonePin, 294 , 125 ) ;
delay( 125 ) ;
tone( tonePin, 262 , 125 ) ;
delay( 124 ) ;
tone( tonePin, 494 , 125 ) ;
delay( 125 ) ;
tone( tonePin, 440 , 125 ) ;
delay( 125 ) ;
tone( tonePin, 494 , 125 ) ;
delay( 125 ) ;
tone( tonePin, 262 , 125 ) ;
delay( 125 ) ;
tone( tonePin, 294 , 125 ) ;
delay( 125 ) ;
tone( tonePin, 330 , 250 ) ;
delay( 250 ) ;
tone( tonePin, 165 , 250 ) ;
delay( 250 ) ;
tone( tonePin, 440 , 250 ) ;
delay( 250 ) ;
lcd.clear ( ) ;
}
//Функция выводящая на экран два пункта меню, они будут менятся при прокрутке
void mainMenuDraw( ) {
Serial.print ( menuPage) ;
lcd.clear ( ) ;
lcd.setCursor ( 1 , 0 ) ;
lcd.print ( menuItems[ menuPage] ) ;
lcd.setCursor ( 1 , 1 ) ;
lcd.print ( menuItems[ menuPage + 1 ] ) ;
if ( menuPage == 0 ) {
lcd.setCursor ( 15 , 1 ) ;
lcd.write ( byte( 2 ) ) ;
} else if ( menuPage > 0 and menuPage < maxMenuPages) {
lcd.setCursor ( 15 , 1 ) ;
lcd.write ( byte( 2 ) ) ;
lcd.setCursor ( 15 , 0 ) ;
lcd.write ( byte( 1 ) ) ;
} else if ( menuPage == maxMenuPages) {
lcd.setCursor ( 15 , 0 ) ;
lcd.write ( byte( 1 ) ) ;
}
}
//Функция рисуящая курсор в соответствии с выбранным пунктом меню
void drawCursor( ) {
for ( int x = 0 ; x < 2 ; x++ ) {
lcd.setCursor ( 0 , x) ;
lcd.print ( " " ) ;
}
// The menu is set up to be progressive (menuPage 0 = Item 1 & Item 2, menuPage 1 = Item 2 & Item 3, menuPage 2 = Item 3 & Item 4), so
// in order to determine where the cursor should be you need to see if you are at an odd or even menu page and an odd or even cursor position.
if ( menuPage % 2 == 0 ) {
if ( cursorPosition % 2 == 0 ) { // If the menu page is even and the cursor position is even that means the cursor should be on line 1
lcd.setCursor ( 0 , 0 ) ;
lcd.write ( byte( 0 ) ) ;
}
if ( cursorPosition % 2 != 0 ) { // If the menu page is even and the cursor position is odd that means the cursor should be on line 2
lcd.setCursor ( 0 , 1 ) ;
lcd.write ( byte( 0 ) ) ;
}
}
if ( menuPage % 2 != 0 ) {
if ( cursorPosition % 2 == 0 ) { // If the menu page is odd and the cursor position is even that means the cursor should be on line 2
lcd.setCursor ( 0 , 1 ) ;
lcd.write ( byte( 0 ) ) ;
}
if ( cursorPosition % 2 != 0 ) { // If the menu page is odd and the cursor position is odd that means the cursor should be on line 1
lcd.setCursor ( 0 , 0 ) ;
lcd.write ( byte( 0 ) ) ;
}
}
}
void operateMainMenu( ) {
int activeButton = 0 ;
while ( activeButton == 0 ) {
int button;
readKey = analogRead( 0 ) ;
if ( readKey < 790 ) {
delay( 100 ) ;
readKey = analogRead( 0 ) ;
}
button = evaluateButton( readKey) ;
switch ( button) {
case 0 : //Если ничего не нажато
break ;
case 1 : //Выполнять действие если нажата "назад"
button = 0 ;
switch ( cursorPosition) { //Переходить в то меню, на котором стоит курсор
case 0 :
menuItem1( ) ;
break ;
case 1 :
menuItem2( ) ;
break ;
case 2 :
menuItem3( ) ;
break ;
case 3 :
menuItem4( ) ;
break ;
case 4 :
menuItem5( ) ;
break ;
case 5 :
menuItem6( ) ;
break ;
case 6 :
menuItem7( ) ;
break ;
case 7 :
menuItem8( ) ;
break ;
case 8 :
menuItem9( ) ;
break ;
case 9 :
menuItem10( ) ;
break ;
}
activeButton = 1 ;
mainMenuDraw( ) ;
drawCursor( ) ;
break ;
case 2 :
button = 0 ;
if ( menuPage == 0 ) {
cursorPosition = cursorPosition - 1 ;
cursorPosition = constrain( cursorPosition, 0 , ( ( sizeof ( menuItems) / sizeof ( String) ) - 1 ) ) ;
}
if ( menuPage % 2 == 0 and cursorPosition % 2 == 0 ) {
menuPage = menuPage - 1 ;
menuPage = constrain( menuPage, 0 , maxMenuPages) ;
}
if ( menuPage % 2 != 0 and cursorPosition % 2 != 0 ) {
menuPage = menuPage - 1 ;
menuPage = constrain( menuPage, 0 , maxMenuPages) ;
}
cursorPosition = cursorPosition - 1 ;
cursorPosition = constrain( cursorPosition, 0 , ( ( sizeof ( menuItems) / sizeof ( String) ) - 1 ) ) ;
mainMenuDraw( ) ;
drawCursor( ) ;
activeButton = 1 ;
break ;
case 3 :
button = 0 ;
if ( menuPage % 2 == 0 and cursorPosition % 2 != 0 ) {
menuPage = menuPage + 1 ;
menuPage = constrain( menuPage, 0 , maxMenuPages) ;
}
if ( menuPage % 2 != 0 and cursorPosition % 2 == 0 ) {
menuPage = menuPage + 1 ;
menuPage = constrain( menuPage, 0 , maxMenuPages) ;
}
cursorPosition = cursorPosition + 1 ;
cursorPosition = constrain( cursorPosition, 0 , ( ( sizeof ( menuItems) / sizeof ( String) ) - 1 ) ) ;
mainMenuDraw( ) ;
drawCursor( ) ;
activeButton = 1 ;
break ;
}
}
}
//Эта функция вызывается когда нажата какая-либо кнопка и путем считывания напряжения на A0, определить какая именно кнопка нажата
int evaluateButton( int x) {
int result = 0 ;
if ( x < 50 ) {
result = 1 ; // Right
} else if ( x < 195 ) {
result = 2 ; // Up
} else if ( x < 380 ) {
result = 3 ; // Down
} else if ( x < 500 ) {
result = 4 ; // Left
} else if ( x < 790 ) {
result = 5 ; // Set
}
return result;
}
//Функции, рисующие стрелки в настройках
//Установка курсора на минуты
void drawInstructions( ) {
lcd.setCursor ( 5 , 2 ) ;
lcd.print ( " " ) ;
lcd.setCursor ( 10 , 1 ) ;
lcd.print ( "\1 " ) ; // Up arrow
}
//Установка курсора на часы
void drawInstruction2( ) {
lcd.setCursor ( 5 , 2 ) ;
lcd.print ( " " ) ;
lcd.setCursor ( 7 , 1 ) ;
lcd.print ( "\1 " ) ;
}
//Установка курсора на будильник
void drawInstruction3( ) {
lcd.setCursor ( 5 , 2 ) ;
lcd.print ( " " ) ;
lcd.setCursor ( 13 , 1 ) ;
lcd.print ( "\1 " ) ;
}
//Для выхода из меню нужно немного удерживать соответствующие кнопки
void menuItem1( ) { // Первое меню: вывод только времени с температурой и влажностью
int activeButton = 0 ;
int i= 0 ;
lcd.clear ( ) ;
EEPROM.write ( 0 , 1 ) ; //Запись в EEPROM что мы находимся в первом меню
while ( activeButton == 0 ) {
int button;
readKey = analogRead( 0 ) ;
if ( readKey < 790 ) {
delay( 100 ) ;
readKey = analogRead( 0 ) ;
}
button = evaluateButton( readKey) ;
switch ( button) {
case 4 : // Если нажата кнопка "left"
button = 0 ;
activeButton = 1 ;
EEPROM.write ( 0 , 0 ) ; //Запись в EEPROM что мы вышли в главное меню
break ;
case 5 : // Если нажата кнопка "set"
button = 0 ;
activeButton = 1 ;
EEPROM.write ( 0 , 0 ) ; //Запись в EEPROM что мы вышли в главное меню
break ;
default :
t = rtc.getTime ( ) ; //ПЕРЕМЕННАЯ ДЛЯ ВРЕМЕНИ
if ( t.hour >= 0 && t.hour < 10 ) { lcd.setCursor ( 6 , 0 ) ; lcd.print ( "0" ) ; lcd.print ( t.hour ) ; } //Часы
else { lcd.setCursor ( 6 , 0 ) ; lcd.print ( t.hour ) ; }
lcd.print ( ":" ) ;
if ( t.min >= 0 && t.min < 10 ) { lcd.setCursor ( 9 , 0 ) ; lcd.print ( "0" ) ; lcd.print ( t.min ) ; } //Минуты
else { lcd.setCursor ( 9 , 0 ) ; lcd.print ( t.min ) ; }
//lcd.print(":");
//Отображение секунд пришлось отключить, т.к. на санятие данных с DHT происходит не мнгновенно
//и из-за этого секунды так сказать проскакивают
//if (t.sec >= 0 && t.sec < 10) { lcd.setCursor(10, 0); lcd.print("0"); lcd.print(t.sec);} //Секунды
//else { lcd.setCursor(10, 0); lcd.print(t.sec);}
float temp = dht.readTemperature ( ) ; //ПЕРЕМЕННЫЕ ДЛЯ DHT
float h = dht.readHumidity ( ) ;
lcd.setCursor ( 1 , 1 ) ; //Температура
lcd.print ( "\3 " ) ;
lcd.setCursor ( 3 , 1 ) ;
lcd.print ( temp, 0 ) ;
lcd.print ( ( char ) 223 ) ; //Значек грудуса
lcd.print ( "C" ) ;
lcd.setCursor ( 10 , 1 ) ; //Влажность
lcd.print ( "\4 " ) ;
lcd.setCursor ( 12 , 1 ) ;
lcd.print ( h, 0 ) ;
lcd.print ( "%" ) ;
lcd.setCursor ( 0 , 0 ) ;
if ( EEPROM.read ( 3 ) == 1 ) { lcd.print ( "\5 " ) ; } //Отображение статуса будильника
else if ( EEPROM.read ( 3 ) == 0 ) { lcd.print ( " " ) ; }
if ( EEPROM.read ( 1 ) == t.hour && EEPROM.read ( 2 ) == t.min && t.sec == 0 && EEPROM.read ( 3 ) == 1 ) { //Сам будильник
ton( ) ;
}
}
}
}
void menuItem2( ) { //Второе меню: вывод полной даты и всех данных с датчиков
int activeButton = 0 ;
lcd.clear ( ) ;
EEPROM.write ( 0 , 2 ) ;
while ( activeButton == 0 ) {
int button;
readKey = analogRead( 0 ) ;
if ( readKey < 790 ) {
delay( 100 ) ;
readKey = analogRead( 0 ) ;
}
button = evaluateButton( readKey) ;
switch ( button) {
case 4 : // Если нажата кнопка "left"
button = 0 ;
activeButton = 1 ;
EEPROM.write ( 0 , 0 ) ;
break ;
case 5 : // Если нажата кнопка "set"
button = 0 ;
activeButton = 1 ;
EEPROM.write ( 0 , 0 ) ;
break ;
default :
t = rtc.getTime ( ) ; //ПЕРЕМЕННАЯ ДЛЯ ВРЕМЕНИ
if ( t.hour >= 0 && t.hour < 10 ) { lcd.setCursor ( 0 , 0 ) ; lcd.print ( "0" ) ; lcd.print ( t.hour ) ; } //Часы
else { lcd.setCursor ( 0 , 0 ) ; lcd.print ( t.hour ) ; }
lcd.print ( ":" ) ;
if ( t.min >= 0 && t.min < 10 ) { lcd.setCursor ( 3 , 0 ) ; lcd.print ( "0" ) ; lcd.print ( t.min ) ; } //Минуты
else { lcd.setCursor ( 3 , 0 ) ; lcd.print ( t.min ) ; }
if ( t.dow >= 0 && t.dow < 10 ) { lcd.setCursor ( 8 , 0 ) ; lcd.print ( "0" ) ; lcd.print ( t.dow ) ; } //День
else { lcd.setCursor ( 8 , 0 ) ; lcd.print ( t.dow ) ; }
lcd.print ( "/" ) ;
if ( t.mon >= 0 && t.mon < 10 ) { lcd.setCursor ( 11 , 0 ) ; lcd.print ( "0" ) ; lcd.print ( t.mon ) ; } //Месяц
else { lcd.setCursor ( 11 , 0 ) ; lcd.print ( t.mon ) ; }
lcd.print ( "/" ) ;
if ( t.year >= 0 && t.year < 10 ) { lcd.setCursor ( 14 , 0 ) ; lcd.print ( "0" ) ; lcd.print ( t.year - 2000 ) ; } //Год
else { lcd.setCursor ( 14 , 0 ) ; lcd.print ( t.year - 2000 ) ; }
float temp = dht.readTemperature ( ) ; //ПЕРЕМЕННЫЕ ДЛЯ DHT
float h = dht.readHumidity ( ) ;
dps.getPressure ( & Pressure) ; //ПЕРЕМЕННЫЕ ДЛЯ BMP
dps.getAltitude ( & Altitude) ;
lcd.setCursor ( 0 , 1 ) ; //Температура
lcd.print ( "\3 " ) ;
lcd.setCursor ( 1 , 1 ) ;
lcd.print ( temp, 0 ) ;
lcd.print ( ( char ) 223 ) ; //degree sign
lcd.print ( "C" ) ;
lcd.setCursor ( 6 , 1 ) ; //Давление
lcd.print ( Pressure/ 133.3 , 0 ) ;
lcd.print ( "mm" ) ;
lcd.setCursor ( 12 , 1 ) ; //Влажность
lcd.print ( "\4 " ) ;
lcd.setCursor ( 13 , 1 ) ;
lcd.print ( h, 0 ) ;
lcd.print ( "%" ) ;
lcd.setCursor ( 6 , 0 ) ;
if ( EEPROM.read ( 3 ) == 1 ) { lcd.print ( "\5 " ) ; } //Отображение статуса будильника
else if ( EEPROM.read ( 3 ) == 0 ) { lcd.print ( " " ) ; }
if ( EEPROM.read ( 1 ) == t.hour && EEPROM.read ( 2 ) == t.min && t.sec == 0 && EEPROM.read ( 3 ) == 1 ) { //Сам будильник
ton( ) ;
}
}
}
}
void menuItem3( ) { //Третье меню
int activeButton = 0 ;
int alarmHour = EEPROM.read ( 1 ) ; //В первой ячейке хранится часы будильника
int alarmMinute = EEPROM.read ( 2 ) ; //Во второй минуты
int alarmStat = EEPROM.read ( 3 ) ; //В третей статус, включен будильник (1) или нет (0)
int alarmPos = 1 ; //Позиция курсора, т.е.что менять: 1-Минуты, 0-Часы, 2-ВКЛ или ВЫКЛ будильника
lcd.clear ( ) ;
EEPROM.write ( 0 , 3 ) ;
lcd.setCursor ( 0 , 1 ) ;
drawInstructions( ) ;
lcd.setCursor ( 0 , 0 ) ;
lcd.print ( "ALARM: " ) ;
if ( alarmHour >= 0 && alarmHour < 10 ) { lcd.print ( "0" ) ; lcd.print ( alarmHour) ; }
else lcd.print ( alarmHour) ;
lcd.setCursor ( 9 , 0 ) ;
lcd.print ( ":" ) ;
if ( alarmMinute >= 0 && alarmMinute < 10 ) { lcd.print ( "0" ) ; lcd.print ( alarmMinute) ; }
else lcd.print ( alarmMinute) ;
lcd.setCursor ( 13 , 0 ) ;
if ( alarmStat== 1 ) lcd.print ( "ON" ) ;
else if ( alarmStat== 0 ) lcd.print ( "OFF" ) ;
while ( activeButton == 0 ) {
int button;
readKey = analogRead( 0 ) ;
if ( readKey < 790 ) {
delay( 100 ) ;
readKey = analogRead( 0 ) ;
}
button = evaluateButton( readKey) ;
switch ( button) {
case 2 : //Прибавляем значения минут, часов или ВКЛ будильника, в соответствии где стоит курсор
if ( alarmPos== 1 ) {
button = 0 ;
if ( alarmMinute== 59 ) alarmMinute= 0 ;
else alarmMinute = alarmMinute + 1 ;
alarmMinute = constrain( alarmMinute, 0 , 60 ) ;
lcd.setCursor ( 10 , 0 ) ;
lcd.print ( " " ) ;
lcd.setCursor ( 10 , 0 ) ;
if ( alarmMinute >= 0 && alarmMinute < 10 ) { lcd.print ( "0" ) ; lcd.print ( alarmMinute) ; }
else lcd.print ( alarmMinute) ;
break ;
} else if ( alarmPos== 0 ) {
button = 0 ;
if ( alarmHour== 23 ) alarmHour= 0 ;
else alarmHour = alarmHour + 1 ;
alarmHour = constrain( alarmHour, 0 , 24 ) ;
lcd.setCursor ( 7 , 0 ) ;
lcd.print ( " " ) ;
lcd.setCursor ( 7 , 0 ) ;
if ( alarmHour >= 0 && alarmHour < 10 ) { lcd.print ( "0" ) ; lcd.print ( alarmHour) ; }
else lcd.print ( alarmHour) ;
break ;
} else if ( alarmPos== 2 ) {
button = 0 ;
lcd.setCursor ( 13 , 0 ) ;
lcd.print ( "ON " ) ;
alarmStat= 1 ;
break ;
}
case 3 : //Убавляем значения минут, часов или ВЫКЛ будильника, в соответствии где стоит курсор
if ( alarmPos== 1 ) {
button = 0 ;
if ( alarmMinute== 0 ) alarmMinute= 59 ;
else alarmMinute = alarmMinute - 1 ;
alarmMinute = constrain( alarmMinute, 0 , 60 ) ;
lcd.setCursor ( 10 , 0 ) ;
lcd.print ( " " ) ;
lcd.setCursor ( 10 , 0 ) ;
if ( alarmMinute >= 0 && alarmMinute < 10 ) { lcd.print ( "0" ) ; lcd.print ( alarmMinute) ; }
else lcd.print ( alarmMinute) ;
break ;
} else if ( alarmPos== 0 ) {
button = 0 ;
if ( alarmHour== 0 ) alarmHour= 23 ;
else alarmHour = alarmHour - 1 ;
alarmHour = constrain( alarmHour, 0 , 24 ) ;
lcd.setCursor ( 7 , 0 ) ;
lcd.print ( " " ) ;
lcd.setCursor ( 7 , 0 ) ;
if ( alarmHour >= 0 && alarmHour < 10 ) { lcd.print ( "0" ) ; lcd.print ( alarmHour) ; }
else lcd.print ( alarmHour) ;
break ;
} else if ( alarmPos== 2 ) {
button = 0 ;
lcd.setCursor ( 13 , 0 ) ;
lcd.print ( "OFF" ) ;
alarmStat= 0 ;
break ;
}
case 4 : // Если нажата кнопка влево, смотрим где стоит курсор в данный момент и переставляем левее
if ( alarmPos== 2 ) {
drawInstructions( ) ;
alarmPos= 1 ;
} else if ( alarmPos== 1 ) {
drawInstruction2( ) ;
alarmPos= 0 ;
}
break ;
case 1 : // Если нажата кнопка вправо, смотрим где стоит курсор в данный момент и переставляем правее
if ( alarmPos== 0 ) {
drawInstructions( ) ;
alarmPos= 1 ;
} else if ( alarmPos== 1 ) {
drawInstruction3( ) ;
alarmPos= 2 ;
}
break ;
case 5 : // Сохранение времни будильника в его статус (вкл или выкл) в EEPROM
button = 0 ;
lcd.clear ( ) ;
lcd.noBlink ( ) ;
EEPROM.write ( 0 , 0 ) ;
lcd.setCursor ( 2 , 0 ) ;
lcd.print ( "-- ALARM --" ) ;
lcd.setCursor ( 2 , 1 ) ;
lcd.print ( "-- SAVED --" ) ;
EEPROM.write ( 1 , alarmHour) ;
EEPROM.write ( 2 , alarmMinute) ;
EEPROM.write ( 3 , alarmStat) ;
delay( 1500 ) ;
activeButton = 1 ;
break ;
}
}
}
void menuItem4( ) { // Четвертое меню
int activeButton = 0 ;
lcd.clear ( ) ;
EEPROM.write ( 0 , 5 ) ;
lcd.setCursor ( 1 , 0 ) ;
lcd.print ( "PIKABU" ) ;
lcd.setCursor ( 11 , 1 ) ;
lcd.print ( "2017" ) ;
while ( activeButton == 0 ) {
int button;
readKey = analogRead( 0 ) ;
if ( readKey < 790 ) {
delay( 100 ) ;
readKey = analogRead( 0 ) ;
}
button = evaluateButton( readKey) ;
switch ( button) {
case 4 : // Если нажата кнопка "left"
button = 0 ;
activeButton = 1 ;
EEPROM.write ( 0 , 0 ) ;
break ;
case 5 : // Если нажата кнопка "set"
button = 0 ;
activeButton = 1 ;
EEPROM.write ( 0 , 0 ) ;
break ;
}
}
}
void menuItem5( ) { // Пятое меню (Для активации добавить название меню в самом начале)
int activeButton = 0 ;
lcd.clear ( ) ;
EEPROM.write ( 0 , 4 ) ;
lcd.setCursor ( 3 , 0 ) ;
lcd.print ( "Hello, World!" ) ;
while ( activeButton == 0 ) {
int button;
readKey = analogRead( 0 ) ;
if ( readKey < 790 ) {
delay( 100 ) ;
readKey = analogRead( 0 ) ;
}
button = evaluateButton( readKey) ;
switch ( button) {
case 4 :
button = 0 ;
activeButton = 1 ;
EEPROM.write ( 0 , 0 ) ;
break ;
}
}
}
void menuItem6( ) { // Шестое меню
int activeButton = 0 ;
lcd.clear ( ) ;
lcd.setCursor ( 3 , 0 ) ;
lcd.print ( "Sub Menu 6" ) ;
while ( activeButton == 0 ) {
int button;
readKey = analogRead( 0 ) ;
if ( readKey < 790 ) {
delay( 100 ) ;
readKey = analogRead( 0 ) ;
}
button = evaluateButton( readKey) ;
switch ( button) {
case 4 : // Если нажата кнопка "left"
button = 0 ;
activeButton = 1 ;
break ;
}
}
}
void menuItem7( ) { // Седьмое меню
int activeButton = 0 ;
lcd.clear ( ) ;
lcd.setCursor ( 3 , 0 ) ;
lcd.print ( "Sub Menu 7" ) ;
while ( activeButton == 0 ) {
int button;
readKey = analogRead( 0 ) ;
if ( readKey < 790 ) {
delay( 100 ) ;
readKey = analogRead( 0 ) ;
}
button = evaluateButton( readKey) ;
switch ( button) {
case 4 : // Если нажата кнопка "left"
button = 0 ;
activeButton = 1 ;
break ;
}
}
}
void menuItem8( ) { // Восьмое меню
int activeButton = 0 ;
lcd.clear ( ) ;
lcd.setCursor ( 3 , 0 ) ;
lcd.print ( "Sub Menu 8" ) ;
while ( activeButton == 0 ) {
int button;
readKey = analogRead( 0 ) ;
if ( readKey < 790 ) {
delay( 100 ) ;
readKey = analogRead( 0 ) ;
}
button = evaluateButton( readKey) ;
switch ( button) {
case 4 : // Если нажата кнопка "left"
button = 0 ;
activeButton = 1 ;
break ;
}
}
}
void menuItem9( ) { // Девятое меню
int activeButton = 0 ;
lcd.clear ( ) ;
lcd.setCursor ( 3 , 0 ) ;
lcd.print ( "Sub Menu 9" ) ;
while ( activeButton == 0 ) {
int button;
readKey = analogRead( 0 ) ;
if ( readKey < 790 ) {
delay( 100 ) ;
readKey = analogRead( 0 ) ;
}
button = evaluateButton( readKey) ;
switch ( button) {
case 4 : // Если нажата кнопка "left"
button = 0 ;
activeButton = 1 ;
break ;
}
}
}
void menuItem10( ) { // Десятое меню
int activeButton = 0 ;
lcd.clear ( ) ;
lcd.setCursor ( 3 , 0 ) ;
lcd.print ( "Sub Menu 10" ) ;
while ( activeButton == 0 ) {
int button;
readKey = analogRead( 0 ) ;
if ( readKey < 790 ) {
delay( 100 ) ;
readKey = analogRead( 0 ) ;
}
button = evaluateButton( readKey) ;
switch ( button) {
case 4 : // Если нажата кнопка "left"
button = 0 ;
activeButton = 1 ;
break ;
}
}
}
Ly/Qn9GD0L3QutGC0Ysg0LzQtdC90Y4sINC80L7QttC90L4g0LTQvtCx0LDQstC40YLRjCDQtNC+IDEwClN0cmluZyBtZW51SXRlbXNbXSA9IHsiTWV0ZW8iLCAiTWV0ZW8rIiwgIlNldCBhbGFybSIsICJBYm91dCJ9OwoKLy/Qn9C10YDQtdC80LXQvdC90LDRjyDQtNC70Y8g0LrQvdC+0L/QvtC6INC90LDQstC40LPQsNGG0LjQuAppbnQgcmVhZEtleTsKCi8v0J/QtdGA0LXQvNC10L3QvdGL0LUg0LTQu9GPINC80LXQvdGOCmludCBtZW51UGFnZSA9IDA7CmludCBtYXhNZW51UGFnZXMgPSByb3VuZCgoKHNpemVvZihtZW51SXRlbXMpIC8gc2l6ZW9mKFN0cmluZykpIC8gMikgKyAuNSk7CmludCBjdXJzb3JQb3NpdGlvbiA9IDA7CgovL9CU0L7Qv9C+0LvQvdC40YLQtdC70YzQvdGL0LUg0YHQuNC80LLQvtC00YsKYnl0ZSBkb3duQXJyb3dbOF0gPSB7CiAgMGIwMDEwMCwgLy8gICAqCiAgMGIwMDEwMCwgLy8gICAqCiAgMGIwMDEwMCwgLy8gICAqCiAgMGIwMDEwMCwgLy8gICAqCiAgMGIwMDEwMCwgLy8gICAqCiAgMGIxMDEwMSwgLy8gKiAqICoKICAwYjAxMTEwLCAvLyAgKioqCiAgMGIwMDEwMCAgLy8gICAqCn07CgpieXRlIHVwQXJyb3dbOF0gPSB7CiAgMGIwMDEwMCwgLy8gICAqCiAgMGIwMTExMCwgLy8gICoqKgogIDBiMTAxMDEsIC8vICogKiAqCiAgMGIwMDEwMCwgLy8gICAqCiAgMGIwMDEwMCwgLy8gICAqCiAgMGIwMDEwMCwgLy8gICAqCiAgMGIwMDEwMCwgLy8gICAqCiAgMGIwMDEwMCAgLy8gICAqCn07CgpieXRlIG1lbnVDdXJzb3JbOF0gPSB7CiAgQjAxMDAwLCAvLyAgKgogIEIwMDEwMCwgLy8gICAqCiAgQjAwMDEwLCAvLyAgICAqCiAgQjAwMDAxLCAvLyAgICAgKgogIEIwMDAxMCwgLy8gICAgKgogIEIwMDEwMCwgLy8gICAqCiAgQjAxMDAwLCAvLyAgKgogIEIwMDAwMCAgLy8KfTsKCmJ5dGUgdGVybW9tZXRydVs4XSA9IC8v0KLQtdC80L/QtdGA0LDRgtGD0YDQsAp7CiAgICBCMDAxMDAsCiAgICBCMDEwMTAsCiAgICBCMDEwMTAsCiAgICBCMDExMTAsCiAgICBCMDExMTAsCiAgICBCMTExMTEsCiAgICBCMTExMTEsCiAgICBCMDExMTAKfTsKCmJ5dGUgcGljYXR1cmFbOF0gPSAvL9CS0LvQsNC20L3QvtGB0YLRjAp7CiAgICBCMDAxMDAsCiAgICBCMDAxMDAsCiAgICBCMDEwMTAsCiAgICBCMDEwMTAsCiAgICBCMTAwMDEsCiAgICBCMTAwMDEsCiAgICBCMTAwMDEsCiAgICBCMDExMTAsCn07CgpieXRlIHJpbmdbOF0gPSAvL9CR0YPQtNC40LvRjNC90LjQugp7CiAgICBCMDAwMDAsCiAgICBCMDAxMDAsCiAgICBCMDExMTAsCiAgICBCMDExMTAsCiAgICBCMDExMTAsCiAgICBCMTExMTEsCiAgICBCMDAxMDAsCiAgICBCMDAwMDAKfTsKCi8v0J/QvtC00LrQu9GO0YfQtdC90LjQtSDQvdC10L7QsdGF0L7QtNC40LzRi9GFINCx0LjQsdC70LjQvtGC0LXQugojaW5jbHVkZSA8V2lyZS5oPgojaW5jbHVkZSA8TGlxdWlkQ3J5c3RhbC5oPgojaW5jbHVkZSA8RFMzMjMxLmg+IC8v0KfQkNCh0KsKI2luY2x1ZGUgIkRIVC5oIiAvL0RIVAojaW5jbHVkZSA8Qk1QMDg1Lmg+IC8vQk1QCiNpbmNsdWRlIDxFRVBST00uaD4KCi8v0JjQvdC40YbQuNCw0LvQuNC30LDRhtC40Y8gTENEIEtleXBhZCBzaGllbGQKTGlxdWlkQ3J5c3RhbCBsY2QoOCwgOSwgNCwgNSwgNiwgNyk7CgpEUzMyMzEgIHJ0YyhTREEsIFNDTCk7IC8v0KfQkNCh0KsKVGltZSAgdDsgLy/Qp9CQ0KHQqwpCTVAwODUgZHBzID0gQk1QMDg1KCk7IC8vQk1QCgojZGVmaW5lIERIVFBJTiAxIC8vREhUINCf0JjQnQojZGVmaW5lIERIVFRZUEUgREhUMjIgLy/QotC40L8gREhUCkRIVCBkaHQoREhUUElOLCBESFRUWVBFKTsgLy9ESFQKCmxvbmcgVGVtcGVyYXR1cmUgPSAwLCBQcmVzc3VyZSA9IDAsIEFsdGl0dWRlID0gMDsgLy9CTVAKCiNkZWZpbmUgdG9uZVBpbiAxMSAvL9Cf0LjQvSDQv9GM0LXQt9C+0Y3Qu9C10LzQtdC90YLQsAoKdm9pZCBzZXR1cCgpIHsKICAvL1NlcmlhbC5iZWdpbig5NjAwKTsKICBydGMuYmVnaW4oKTsgLy/Qp9CQ0KHQqwogIGRodC5iZWdpbigpOyAvL0RIVAogIFdpcmUuYmVnaW4oKTsgLy/QlNC70Y8gQk1QCiAgZHBzLmluaXQoTU9ERV9VTFRSQV9ISUdIUkVTLCAxNDAwMCwgdHJ1ZSk7IC8vQk1QLCAxMzAg0JzQtdGC0YDQvtCyINC90LDQtCDRg9GA0L7QstC90LXQvCDQvNC+0YDRjwoKICAvL9CY0L3QuNGG0LjQsNC70LjQt9Cw0YbQuNGPIExDRCDRjdC60YDQsNC90LAKICBsY2QuYmVnaW4oMTYsIDIpOwogIGxjZC5jbGVhcigpOwoKICAvL9Ch0L7Qt9C00LDQvdC40LUg0LTQvtC/0L7Qu9C90LjRgtC10LvRjNC90YvRhSDRgdC40LzQstC+0LvQvtCyCiAgbGNkLmNyZWF0ZUNoYXIoMCwgbWVudUN1cnNvcik7CiAgbGNkLmNyZWF0ZUNoYXIoMSwgdXBBcnJvdyk7CiAgbGNkLmNyZWF0ZUNoYXIoMiwgZG93bkFycm93KTsKCiAgbGNkLmNyZWF0ZUNoYXIoMywgdGVybW9tZXRydSk7CiAgbGNkLmNyZWF0ZUNoYXIoNCwgcGljYXR1cmEpOwogIGxjZC5jcmVhdGVDaGFyKDUsIHJpbmcpOwoKICBhbmFsb2dXcml0ZSgxMCwgMTU1KTsgLy/Qr9GA0LrQvtGB0YLRjCAo0LTQviAyNTUpCgogIC8v0J3Rg9C20L3QviDQtNC70Y8g0YLQvtCz0L4sINGH0YLQviDQsdGLINC/0YDQuCDQv9C10YDQtdC30LDQs9GA0YPQt9C60LUg0L/QtdGA0LXQutC40LTRi9Cy0LDQu9C+INC90LAg0YLQviDQvNC10L3RjiDQsiDQutC+0YLQvtGA0L7QvCDQvNGLINCx0YvQu9C4INC/0L7RgdC70LXQtNC90LjQuSDRgNCw0LcKICBpZiAoRUVQUk9NLnJlYWQoMCkgPT0gMSl7CiAgICBtZW51SXRlbTEoKTsKICB9IGVsc2UgaWYgKEVFUFJPTS5yZWFkKDApPT0yKXsKICAgIG1lbnVJdGVtMigpOwogIH0gZWxzZSBpZiAoRUVQUk9NLnJlYWQoMCk9PTMpewogICAgbWVudUl0ZW0zKCk7CiAgfSBlbHNlIGlmIChFRVBST00ucmVhZCgwKT09NCl7CiAgICBtZW51SXRlbTQoKTsKICB9IGVsc2UgaWYgKEVFUFJPTS5yZWFkKDApPT01KXsKICAgIG1lbnVJdGVtNSgpOwogIH0gZWxzZSBpZiAoRUVQUk9NLnJlYWQoMCk9PTApeyB9Cn0KCnZvaWQgbG9vcCgpIHsKICBtYWluTWVudURyYXcoKTsKICBkcmF3Q3Vyc29yKCk7CiAgb3BlcmF0ZU1haW5NZW51KCk7Cn0KCiAgLy/QpNGD0L3QutGG0LjRjyDQsdGD0LTQuNC70YzQvdC40LrQsCwg0LIg0LTQsNC90L3QvtC8INGB0LvRg9GH0LDQtSDQv9C40YnQsNGC0Ywg0LfRg9C80LzQtdGA0L7QvAp2b2lkIHRvbigpIHsKICBsY2QuY2xlYXIoKTsKICBkZWxheSgyNTApOwogIGxjZC5zZXRDdXJzb3IoMCwgMCk7CiAgbGNkLnByaW50KCJXQUtFIFVQIik7CiAgbGNkLnNldEN1cnNvcigxMywgMSk7CiAgbGNkLnByaW50KCJORU8uLi4iKTsKCiAgdG9uZSh0b25lUGluLCA0NDAsIDI1MCk7CiAgZGVsYXkoMjUwKTsKICB0b25lKHRvbmVQaW4sIDE2NSwgMjUwKTsKICBkZWxheSgyNTApOwogIHRvbmUodG9uZVBpbiwgNDQwLCAyNTApOwogIGRlbGF5KDI1MCk7CiAgZGVsYXkoMjUwKTsKICAKICB0b25lKHRvbmVQaW4sIDQ0MCwgMjUwKTsKICBkZWxheSgyNTApOwogIHRvbmUodG9uZVBpbiwgMTY1LCAyNTApOwogIGRlbGF5KDI1MCk7CiAgdG9uZSh0b25lUGluLCA0NDAsIDI1MCk7CiAgZGVsYXkoMjUwKTsKICBkZWxheSgyNTApOwogIAogIHRvbmUodG9uZVBpbiwgMzMwLCAxMjUpOwogIGRlbGF5KDEyNSk7CiAgdG9uZSh0b25lUGluLCAyOTQsIDEyNSk7CiAgZGVsYXkoMTI1KTsKICB0b25lKHRvbmVQaW4sIDI2MiwgMTI1KTsKICBkZWxheSgxMjQpOwogIHRvbmUodG9uZVBpbiwgNDk0LCAxMjUpOwogIGRlbGF5KDEyNSk7CiAgdG9uZSh0b25lUGluLCA0NDAsIDEyNSk7CiAgZGVsYXkoMTI1KTsKICB0b25lKHRvbmVQaW4sIDQ5NCwgMTI1KTsKICBkZWxheSgxMjUpOwogIHRvbmUodG9uZVBpbiwgMjYyLCAxMjUpOwogIGRlbGF5KDEyNSk7CiAgdG9uZSh0b25lUGluLCAyOTQsIDEyNSk7CiAgZGVsYXkoMTI1KTsKICAKICB0b25lKHRvbmVQaW4sIDMzMCwgMjUwKTsKICBkZWxheSgyNTApOwogIHRvbmUodG9uZVBpbiwgMTY1LCAyNTApOwogIGRlbGF5KDI1MCk7CiAgdG9uZSh0b25lUGluLCA0NDAsIDI1MCk7CiAgZGVsYXkoMjUwKTsKICAKICBsY2QuY2xlYXIoKTsKfQoKICAvL9Ck0YPQvdC60YbQuNGPINCy0YvQstC+0LTRj9GJ0LDRjyDQvdCwINGN0LrRgNCw0L0g0LTQstCwINC/0YPQvdC60YLQsCDQvNC10L3Rjiwg0L7QvdC4INCx0YPQtNGD0YIg0LzQtdC90Y/RgtGB0Y8g0L/RgNC4INC/0YDQvtC60YDRg9GC0LrQtQp2b2lkIG1haW5NZW51RHJhdygpIHsKICBTZXJpYWwucHJpbnQobWVudVBhZ2UpOwogIGxjZC5jbGVhcigpOwogIGxjZC5zZXRDdXJzb3IoMSwgMCk7CiAgbGNkLnByaW50KG1lbnVJdGVtc1ttZW51UGFnZV0pOwogIGxjZC5zZXRDdXJzb3IoMSwgMSk7CiAgbGNkLnByaW50KG1lbnVJdGVtc1ttZW51UGFnZSArIDFdKTsKICBpZiAobWVudVBhZ2UgPT0gMCkgewogICAgbGNkLnNldEN1cnNvcigxNSwgMSk7CiAgICBsY2Qud3JpdGUoYnl0ZSgyKSk7CiAgfSBlbHNlIGlmIChtZW51UGFnZSA+IDAgYW5kIG1lbnVQYWdlIDwgbWF4TWVudVBhZ2VzKSB7CiAgICBsY2Quc2V0Q3Vyc29yKDE1LCAxKTsKICAgIGxjZC53cml0ZShieXRlKDIpKTsKICAgIGxjZC5zZXRDdXJzb3IoMTUsIDApOwogICAgbGNkLndyaXRlKGJ5dGUoMSkpOwogIH0gZWxzZSBpZiAobWVudVBhZ2UgPT0gbWF4TWVudVBhZ2VzKSB7CiAgICBsY2Quc2V0Q3Vyc29yKDE1LCAwKTsKICAgIGxjZC53cml0ZShieXRlKDEpKTsKICB9Cn0KCiAgLy/QpNGD0L3QutGG0LjRjyDRgNC40YHRg9GP0YnQsNGPINC60YPRgNGB0L7RgCDQsiDRgdC+0L7RgtCy0LXRgtGB0YLQstC40Lgg0YEg0LLRi9Cx0YDQsNC90L3Ri9C8INC/0YPQvdC60YLQvtC8INC80LXQvdGOCnZvaWQgZHJhd0N1cnNvcigpIHsKICBmb3IgKGludCB4ID0gMDsgeCA8IDI7IHgrKykgewogICAgbGNkLnNldEN1cnNvcigwLCB4KTsKICAgIGxjZC5wcmludCgiICIpOwogIH0KCiAgLy8gVGhlIG1lbnUgaXMgc2V0IHVwIHRvIGJlIHByb2dyZXNzaXZlIChtZW51UGFnZSAwID0gSXRlbSAxICYgSXRlbSAyLCBtZW51UGFnZSAxID0gSXRlbSAyICYgSXRlbSAzLCBtZW51UGFnZSAyID0gSXRlbSAzICYgSXRlbSA0KSwgc28KICAvLyBpbiBvcmRlciB0byBkZXRlcm1pbmUgd2hlcmUgdGhlIGN1cnNvciBzaG91bGQgYmUgeW91IG5lZWQgdG8gc2VlIGlmIHlvdSBhcmUgYXQgYW4gb2RkIG9yIGV2ZW4gbWVudSBwYWdlIGFuZCBhbiBvZGQgb3IgZXZlbiBjdXJzb3IgcG9zaXRpb24uCiAgaWYgKG1lbnVQYWdlICUgMiA9PSAwKSB7CiAgICBpZiAoY3Vyc29yUG9zaXRpb24gJSAyID09IDApIHsgIC8vIElmIHRoZSBtZW51IHBhZ2UgaXMgZXZlbiBhbmQgdGhlIGN1cnNvciBwb3NpdGlvbiBpcyBldmVuIHRoYXQgbWVhbnMgdGhlIGN1cnNvciBzaG91bGQgYmUgb24gbGluZSAxCiAgICAgIGxjZC5zZXRDdXJzb3IoMCwgMCk7CiAgICAgIGxjZC53cml0ZShieXRlKDApKTsKICAgIH0KICAgIGlmIChjdXJzb3JQb3NpdGlvbiAlIDIgIT0gMCkgeyAgLy8gSWYgdGhlIG1lbnUgcGFnZSBpcyBldmVuIGFuZCB0aGUgY3Vyc29yIHBvc2l0aW9uIGlzIG9kZCB0aGF0IG1lYW5zIHRoZSBjdXJzb3Igc2hvdWxkIGJlIG9uIGxpbmUgMgogICAgICBsY2Quc2V0Q3Vyc29yKDAsIDEpOwogICAgICBsY2Qud3JpdGUoYnl0ZSgwKSk7CiAgICB9CiAgfQogIGlmIChtZW51UGFnZSAlIDIgIT0gMCkgewogICAgaWYgKGN1cnNvclBvc2l0aW9uICUgMiA9PSAwKSB7ICAvLyBJZiB0aGUgbWVudSBwYWdlIGlzIG9kZCBhbmQgdGhlIGN1cnNvciBwb3NpdGlvbiBpcyBldmVuIHRoYXQgbWVhbnMgdGhlIGN1cnNvciBzaG91bGQgYmUgb24gbGluZSAyCiAgICAgIGxjZC5zZXRDdXJzb3IoMCwgMSk7CiAgICAgIGxjZC53cml0ZShieXRlKDApKTsKICAgIH0KICAgIGlmIChjdXJzb3JQb3NpdGlvbiAlIDIgIT0gMCkgeyAgLy8gSWYgdGhlIG1lbnUgcGFnZSBpcyBvZGQgYW5kIHRoZSBjdXJzb3IgcG9zaXRpb24gaXMgb2RkIHRoYXQgbWVhbnMgdGhlIGN1cnNvciBzaG91bGQgYmUgb24gbGluZSAxCiAgICAgIGxjZC5zZXRDdXJzb3IoMCwgMCk7CiAgICAgIGxjZC53cml0ZShieXRlKDApKTsKICAgIH0KICB9Cn0KCnZvaWQgb3BlcmF0ZU1haW5NZW51KCkgewogIGludCBhY3RpdmVCdXR0b24gPSAwOwogIHdoaWxlIChhY3RpdmVCdXR0b24gPT0gMCkgewogICAgaW50IGJ1dHRvbjsKICAgIHJlYWRLZXkgPSBhbmFsb2dSZWFkKDApOwogICAgaWYgKHJlYWRLZXkgPCA3OTApIHsKICAgICAgZGVsYXkoMTAwKTsKICAgICAgcmVhZEtleSA9IGFuYWxvZ1JlYWQoMCk7CiAgICB9CiAgICBidXR0b24gPSBldmFsdWF0ZUJ1dHRvbihyZWFkS2V5KTsKICAgIHN3aXRjaCAoYnV0dG9uKSB7CiAgICAgIGNhc2UgMDogLy/QldGB0LvQuCDQvdC40YfQtdCz0L4g0L3QtSDQvdCw0LbQsNGC0L4KICAgICAgICBicmVhazsKICAgICAgY2FzZSAxOiAgLy/QktGL0L/QvtC70L3Rj9GC0Ywg0LTQtdC50YHRgtCy0LjQtSDQtdGB0LvQuCDQvdCw0LbQsNGC0LAgItC90LDQt9Cw0LQiCiAgICAgICAgYnV0dG9uID0gMDsKICAgICAgICBzd2l0Y2ggKGN1cnNvclBvc2l0aW9uKSB7IC8v0J/QtdGA0LXRhdC+0LTQuNGC0Ywg0LIg0YLQviDQvNC10L3Rjiwg0L3QsCDQutC+0YLQvtGA0L7QvCDRgdGC0L7QuNGCINC60YPRgNGB0L7RgAogICAgICAgICAgY2FzZSAwOgogICAgICAgICAgICBtZW51SXRlbTEoKTsgCiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAxOgogICAgICAgICAgICBtZW51SXRlbTIoKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIDI6CiAgICAgICAgICAgIG1lbnVJdGVtMygpOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgMzoKICAgICAgICAgICAgbWVudUl0ZW00KCk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSA0OgogICAgICAgICAgICBtZW51SXRlbTUoKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIDU6CiAgICAgICAgICAgIG1lbnVJdGVtNigpOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgNjoKICAgICAgICAgICAgbWVudUl0ZW03KCk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSA3OgogICAgICAgICAgICBtZW51SXRlbTgoKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIDg6CiAgICAgICAgICAgIG1lbnVJdGVtOSgpOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgOToKICAgICAgICAgICAgbWVudUl0ZW0xMCgpOwogICAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgYWN0aXZlQnV0dG9uID0gMTsKICAgICAgICBtYWluTWVudURyYXcoKTsKICAgICAgICBkcmF3Q3Vyc29yKCk7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgMjoKICAgICAgICBidXR0b24gPSAwOwogICAgICAgIGlmIChtZW51UGFnZSA9PSAwKSB7CiAgICAgICAgICBjdXJzb3JQb3NpdGlvbiA9IGN1cnNvclBvc2l0aW9uIC0gMTsKICAgICAgICAgIGN1cnNvclBvc2l0aW9uID0gY29uc3RyYWluKGN1cnNvclBvc2l0aW9uLCAwLCAoKHNpemVvZihtZW51SXRlbXMpIC8gc2l6ZW9mKFN0cmluZykpIC0gMSkpOwogICAgICAgIH0KICAgICAgICBpZiAobWVudVBhZ2UgJSAyID09IDAgYW5kIGN1cnNvclBvc2l0aW9uICUgMiA9PSAwKSB7CiAgICAgICAgICBtZW51UGFnZSA9IG1lbnVQYWdlIC0gMTsKICAgICAgICAgIG1lbnVQYWdlID0gY29uc3RyYWluKG1lbnVQYWdlLCAwLCBtYXhNZW51UGFnZXMpOwogICAgICAgIH0KCiAgICAgICAgaWYgKG1lbnVQYWdlICUgMiAhPSAwIGFuZCBjdXJzb3JQb3NpdGlvbiAlIDIgIT0gMCkgewogICAgICAgICAgbWVudVBhZ2UgPSBtZW51UGFnZSAtIDE7CiAgICAgICAgICBtZW51UGFnZSA9IGNvbnN0cmFpbihtZW51UGFnZSwgMCwgbWF4TWVudVBhZ2VzKTsKICAgICAgICB9CgogICAgICAgIGN1cnNvclBvc2l0aW9uID0gY3Vyc29yUG9zaXRpb24gLSAxOwogICAgICAgIGN1cnNvclBvc2l0aW9uID0gY29uc3RyYWluKGN1cnNvclBvc2l0aW9uLCAwLCAoKHNpemVvZihtZW51SXRlbXMpIC8gc2l6ZW9mKFN0cmluZykpIC0gMSkpOwoKICAgICAgICBtYWluTWVudURyYXcoKTsKICAgICAgICBkcmF3Q3Vyc29yKCk7CiAgICAgICAgYWN0aXZlQnV0dG9uID0gMTsKICAgICAgICBicmVhazsKICAgICAgY2FzZSAzOgogICAgICAgIGJ1dHRvbiA9IDA7CiAgICAgICAgaWYgKG1lbnVQYWdlICUgMiA9PSAwIGFuZCBjdXJzb3JQb3NpdGlvbiAlIDIgIT0gMCkgewogICAgICAgICAgbWVudVBhZ2UgPSBtZW51UGFnZSArIDE7CiAgICAgICAgICBtZW51UGFnZSA9IGNvbnN0cmFpbihtZW51UGFnZSwgMCwgbWF4TWVudVBhZ2VzKTsKICAgICAgICB9CgogICAgICAgIGlmIChtZW51UGFnZSAlIDIgIT0gMCBhbmQgY3Vyc29yUG9zaXRpb24gJSAyID09IDApIHsKICAgICAgICAgIG1lbnVQYWdlID0gbWVudVBhZ2UgKyAxOwogICAgICAgICAgbWVudVBhZ2UgPSBjb25zdHJhaW4obWVudVBhZ2UsIDAsIG1heE1lbnVQYWdlcyk7CiAgICAgICAgfQoKICAgICAgICBjdXJzb3JQb3NpdGlvbiA9IGN1cnNvclBvc2l0aW9uICsgMTsKICAgICAgICBjdXJzb3JQb3NpdGlvbiA9IGNvbnN0cmFpbihjdXJzb3JQb3NpdGlvbiwgMCwgKChzaXplb2YobWVudUl0ZW1zKSAvIHNpemVvZihTdHJpbmcpKSAtIDEpKTsKICAgICAgICBtYWluTWVudURyYXcoKTsKICAgICAgICBkcmF3Q3Vyc29yKCk7CiAgICAgICAgYWN0aXZlQnV0dG9uID0gMTsKICAgICAgICBicmVhazsKICAgIH0KICB9Cn0KCiAgLy/QrdGC0LAg0YTRg9C90LrRhtC40Y8g0LLRi9C30YvQstCw0LXRgtGB0Y8g0LrQvtCz0LTQsCDQvdCw0LbQsNGC0LAg0LrQsNC60LDRjy3Qu9C40LHQviDQutC90L7Qv9C60LAg0Lgg0L/Rg9GC0LXQvCDRgdGH0LjRgtGL0LLQsNC90LjRjyDQvdCw0L/RgNGP0LbQtdC90LjRjyDQvdCwIEEwLCDQvtC/0YDQtdC00LXQu9C40YLRjCDQutCw0LrQsNGPINC40LzQtdC90L3QviDQutC90L7Qv9C60LAg0L3QsNC20LDRgtCwCmludCBldmFsdWF0ZUJ1dHRvbihpbnQgeCkgewogIGludCByZXN1bHQgPSAwOwogIGlmICh4IDwgNTApIHsKICAgIHJlc3VsdCA9IDE7IC8vIFJpZ2h0CiAgfSBlbHNlIGlmICh4IDwgMTk1KSB7CiAgICByZXN1bHQgPSAyOyAvLyBVcAogIH0gZWxzZSBpZiAoeCA8IDM4MCkgewogICAgcmVzdWx0ID0gMzsgLy8gRG93bgogIH0gZWxzZSBpZiAoeCA8IDUwMCl7CiAgICByZXN1bHQgPSA0OyAvLyBMZWZ0CiAgfSBlbHNlIGlmICh4IDwgNzkwKSB7CiAgICByZXN1bHQgPSA1OyAvLyBTZXQKICB9CiAgcmV0dXJuIHJlc3VsdDsKfQoKICAvL9Ck0YPQvdC60YbQuNC4LCDRgNC40YHRg9GO0YnQuNC1INGB0YLRgNC10LvQutC4INCyINC90LDRgdGC0YDQvtC50LrQsNGFCi8v0KPRgdGC0LDQvdC+0LLQutCwINC60YPRgNGB0L7RgNCwINC90LAg0LzQuNC90YPRgtGLCnZvaWQgZHJhd0luc3RydWN0aW9ucygpIHsKICBsY2Quc2V0Q3Vyc29yKDUsIDIpOwogIGxjZC5wcmludCgiICAgICAgICAgICAiKTsKICBsY2Quc2V0Q3Vyc29yKDEwLCAxKTsKICBsY2QucHJpbnQoIlwxIik7IC8vIFVwIGFycm93Cn0KCi8v0KPRgdGC0LDQvdC+0LLQutCwINC60YPRgNGB0L7RgNCwINC90LAg0YfQsNGB0YsKdm9pZCBkcmF3SW5zdHJ1Y3Rpb24yKCkgewogIGxjZC5zZXRDdXJzb3IoNSwgMik7CiAgbGNkLnByaW50KCIgICAgICAgICAgICIpOwogIGxjZC5zZXRDdXJzb3IoNywgMSk7CiAgbGNkLnByaW50KCJcMSIpOwp9CgovL9Cj0YHRgtCw0L3QvtCy0LrQsCDQutGD0YDRgdC+0YDQsCDQvdCwINCx0YPQtNC40LvRjNC90LjQugp2b2lkIGRyYXdJbnN0cnVjdGlvbjMoKSB7CiAgbGNkLnNldEN1cnNvcig1LCAyKTsKICBsY2QucHJpbnQoIiAgICAgICAgICAgIik7CiAgbGNkLnNldEN1cnNvcigxMywgMSk7CiAgbGNkLnByaW50KCJcMSIpOwp9CgoKLy/QlNC70Y8g0LLRi9GF0L7QtNCwINC40Lcg0LzQtdC90Y4g0L3Rg9C20L3QviDQvdC10LzQvdC+0LPQviDRg9C00LXRgNC20LjQstCw0YLRjCDRgdC+0L7RgtCy0LXRgtGB0YLQstGD0Y7RidC40LUg0LrQvdC+0L/QutC4CnZvaWQgbWVudUl0ZW0xKCkgeyAvLyDQn9C10YDQstC+0LUg0LzQtdC90Y46INCy0YvQstC+0LQg0YLQvtC70YzQutC+INCy0YDQtdC80LXQvdC4INGBINGC0LXQvNC/0LXRgNCw0YLRg9GA0L7QuSDQuCDQstC70LDQttC90L7RgdGC0YzRjgogIGludCBhY3RpdmVCdXR0b24gPSAwOwogIGludCBpPTA7CiAgbGNkLmNsZWFyKCk7CiAgRUVQUk9NLndyaXRlKDAsIDEpOyAvL9CX0LDQv9C40YHRjCDQsiBFRVBST00g0YfRgtC+INC80Ysg0L3QsNGF0L7QtNC40LzRgdGPINCyINC/0LXRgNCy0L7QvCDQvNC10L3RjgoKICB3aGlsZSAoYWN0aXZlQnV0dG9uID09IDApIHsKICAgIGludCBidXR0b247CiAgICByZWFkS2V5ID0gYW5hbG9nUmVhZCgwKTsKICAgIGlmIChyZWFkS2V5IDwgNzkwKSB7CiAgICAgIGRlbGF5KDEwMCk7CiAgICAgIHJlYWRLZXkgPSBhbmFsb2dSZWFkKDApOwogICAgfQogICAgYnV0dG9uID0gZXZhbHVhdGVCdXR0b24ocmVhZEtleSk7CiAgICBzd2l0Y2ggKGJ1dHRvbikgewogICAgICBjYXNlIDQ6ICAvLyDQldGB0LvQuCDQvdCw0LbQsNGC0LAg0LrQvdC+0L/QutCwICJsZWZ0IgogICAgICAgIGJ1dHRvbiA9IDA7CiAgICAgICAgYWN0aXZlQnV0dG9uID0gMTsKICAgICAgICBFRVBST00ud3JpdGUoMCwgMCk7IC8v0JfQsNC/0LjRgdGMINCyIEVFUFJPTSDRh9GC0L4g0LzRiyDQstGL0YjQu9C4INCyINCz0LvQsNCy0L3QvtC1INC80LXQvdGOCiAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSA1OiAgLy8g0JXRgdC70Lgg0L3QsNC20LDRgtCwINC60L3QvtC/0LrQsCAic2V0IgogICAgICAgIGJ1dHRvbiA9IDA7CiAgICAgICAgYWN0aXZlQnV0dG9uID0gMTsKICAgICAgICBFRVBST00ud3JpdGUoMCwgMCk7IC8v0JfQsNC/0LjRgdGMINCyIEVFUFJPTSDRh9GC0L4g0LzRiyDQstGL0YjQu9C4INCyINCz0LvQsNCy0L3QvtC1INC80LXQvdGOCiAgICAgICAgYnJlYWs7CiAgICAgICAgCiAgICAgICAgZGVmYXVsdDoKICAgICAgICB0ID0gcnRjLmdldFRpbWUoKTsgLy/Qn9CV0KDQldCc0JXQndCd0JDQryDQlNCb0K8g0JLQoNCV0JzQldCd0JgKICAgICAgICAKICAgICAgICBpZiAodC5ob3VyID49IDAgJiYgdC5ob3VyIDwgMTApIHsgbGNkLnNldEN1cnNvcig2LCAwKTsgbGNkLnByaW50KCIwIik7IGxjZC5wcmludCh0LmhvdXIpO30gLy/Qp9Cw0YHRiwogICAgICAgIGVsc2UgeyBsY2Quc2V0Q3Vyc29yKDYsIDApOyBsY2QucHJpbnQodC5ob3VyKTt9CiAgICAgICAgbGNkLnByaW50KCI6Iik7CiAgICAgICAgaWYgKHQubWluID49IDAgJiYgdC5taW4gPCAxMCkgeyBsY2Quc2V0Q3Vyc29yKDksIDApOyBsY2QucHJpbnQoIjAiKTsgbGNkLnByaW50KHQubWluKTt9IC8v0JzQuNC90YPRgtGLCiAgICAgICAgZWxzZSB7IGxjZC5zZXRDdXJzb3IoOSwgMCk7IGxjZC5wcmludCh0Lm1pbik7fQogICAgICAgIC8vbGNkLnByaW50KCI6Iik7CiAgICAgICAgCiAgICAgICAgLy/QntGC0L7QsdGA0LDQttC10L3QuNC1INGB0LXQutGD0L3QtCDQv9GA0LjRiNC70L7RgdGMINC+0YLQutC70Y7Rh9C40YLRjCwg0YIu0LouINC90LAg0YHQsNC90Y/RgtC40LUg0LTQsNC90L3Ri9GFINGBIERIVCDQv9GA0L7QuNGB0YXQvtC00LjRgiDQvdC1INC80L3Qs9C90L7QstC10L3QvdC+CiAgICAgICAgLy/QuCDQuNC3LdC30LAg0Y3RgtC+0LPQviDRgdC10LrRg9C90LTRiyDRgtCw0Log0YHQutCw0LfQsNGC0Ywg0L/RgNC+0YHQutCw0LrQuNCy0LDRjtGCCiAgICAgICAgCiAgICAgICAgLy9pZiAodC5zZWMgPj0gMCAmJiB0LnNlYyA8IDEwKSB7IGxjZC5zZXRDdXJzb3IoMTAsIDApOyBsY2QucHJpbnQoIjAiKTsgbGNkLnByaW50KHQuc2VjKTt9IC8v0KHQtdC60YPQvdC00YsKICAgICAgICAvL2Vsc2UgeyBsY2Quc2V0Q3Vyc29yKDEwLCAwKTsgbGNkLnByaW50KHQuc2VjKTt9CgogICAgICAgIGZsb2F0IHRlbXAgPSBkaHQucmVhZFRlbXBlcmF0dXJlKCk7IC8v0J/QldCg0JXQnNCV0J3QndCr0JUg0JTQm9CvIERIVAogICAgICAgIGZsb2F0IGggPSBkaHQucmVhZEh1bWlkaXR5KCk7CgogICAgICAgIGxjZC5zZXRDdXJzb3IoMSwgMSk7IC8v0KLQtdC80L/QtdGA0LDRgtGD0YDQsAogICAgICAgIGxjZC5wcmludCgiXDMiKTsKICAgICAgICBsY2Quc2V0Q3Vyc29yKDMsIDEpOwogICAgICAgIGxjZC5wcmludCh0ZW1wLCAwKTsKICAgICAgICBsY2QucHJpbnQoKGNoYXIpMjIzKTsgLy/Ql9C90LDRh9C10Log0LPRgNGD0LTRg9GB0LAKICAgICAgICBsY2QucHJpbnQoIkMiKTsKCiAgICAgICAgbGNkLnNldEN1cnNvcigxMCwgMSk7IC8v0JLQu9Cw0LbQvdC+0YHRgtGMCiAgICAgICAgbGNkLnByaW50KCJcNCIpOwogICAgICAgIGxjZC5zZXRDdXJzb3IoMTIsIDEpOwogICAgICAgIGxjZC5wcmludChoLCAwKTsKICAgICAgICBsY2QucHJpbnQoIiUiKTsKCiAgICAgICAgbGNkLnNldEN1cnNvcigwLCAwKTsKICAgICAgICBpZiAoRUVQUk9NLnJlYWQoMyk9PTEpIHtsY2QucHJpbnQoIlw1Iik7fSAvL9Ce0YLQvtCx0YDQsNC20LXQvdC40LUg0YHRgtCw0YLRg9GB0LAg0LHRg9C00LjQu9GM0L3QuNC60LAKICAgICAgICBlbHNlIGlmIChFRVBST00ucmVhZCgzKT09MCkge2xjZC5wcmludCgiICIpO30KCiAgICAgICAgaWYgKEVFUFJPTS5yZWFkKDEpPT10LmhvdXIgJiYgRUVQUk9NLnJlYWQoMik9PXQubWluICYmIHQuc2VjPT0wICYmIEVFUFJPTS5yZWFkKDMpPT0xKSB7IC8v0KHQsNC8INCx0YPQtNC40LvRjNC90LjQugogICAgICAgICAgICB0b24oKTsKICAgICAgICAgIH0KICAgIH0KICB9Cn0KCnZvaWQgbWVudUl0ZW0yKCkgeyAvL9CS0YLQvtGA0L7QtSDQvNC10L3Rjjog0LLRi9Cy0L7QtCDQv9C+0LvQvdC+0Lkg0LTQsNGC0Ysg0Lgg0LLRgdC10YUg0LTQsNC90L3Ri9GFINGBINC00LDRgtGH0LjQutC+0LIKICBpbnQgYWN0aXZlQnV0dG9uID0gMDsKICBsY2QuY2xlYXIoKTsKICBFRVBST00ud3JpdGUoMCwgMik7CgogIHdoaWxlIChhY3RpdmVCdXR0b24gPT0gMCkgewogICAgaW50IGJ1dHRvbjsKICAgIHJlYWRLZXkgPSBhbmFsb2dSZWFkKDApOwogICAgaWYgKHJlYWRLZXkgPCA3OTApIHsKICAgICAgZGVsYXkoMTAwKTsKICAgICAgcmVhZEtleSA9IGFuYWxvZ1JlYWQoMCk7CiAgICB9CiAgICBidXR0b24gPSBldmFsdWF0ZUJ1dHRvbihyZWFkS2V5KTsKICAgIHN3aXRjaCAoYnV0dG9uKSB7CiAgICAgIGNhc2UgNDogIC8vINCV0YHQu9C4INC90LDQttCw0YLQsCDQutC90L7Qv9C60LAgImxlZnQiCiAgICAgICAgYnV0dG9uID0gMDsKICAgICAgICBhY3RpdmVCdXR0b24gPSAxOwogICAgICAgIEVFUFJPTS53cml0ZSgwLCAwKTsKICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDU6ICAvLyDQldGB0LvQuCDQvdCw0LbQsNGC0LAg0LrQvdC+0L/QutCwICJzZXQiCiAgICAgICAgYnV0dG9uID0gMDsKICAgICAgICBhY3RpdmVCdXR0b24gPSAxOwogICAgICAgIEVFUFJPTS53cml0ZSgwLCAwKTsKICAgICAgICBicmVhazsKICAgICAgICBkZWZhdWx0OgogICAgICAgIHQgPSBydGMuZ2V0VGltZSgpOyAvL9Cf0JXQoNCV0JzQldCd0J3QkNCvINCU0JvQryDQktCg0JXQnNCV0J3QmAogICAgICAgIAogICAgICAgIGlmICh0LmhvdXIgPj0gMCAmJiB0LmhvdXIgPCAxMCkgeyBsY2Quc2V0Q3Vyc29yKDAsIDApOyBsY2QucHJpbnQoIjAiKTsgbGNkLnByaW50KHQuaG91cik7fSAvL9Cn0LDRgdGLCiAgICAgICAgZWxzZSB7IGxjZC5zZXRDdXJzb3IoMCwgMCk7IGxjZC5wcmludCh0LmhvdXIpO30KICAgICAgICBsY2QucHJpbnQoIjoiKTsKICAgICAgICBpZiAodC5taW4gPj0gMCAmJiB0Lm1pbiA8IDEwKSB7IGxjZC5zZXRDdXJzb3IoMywgMCk7IGxjZC5wcmludCgiMCIpOyBsY2QucHJpbnQodC5taW4pO30gLy/QnNC40L3Rg9GC0YsKICAgICAgICBlbHNlIHsgbGNkLnNldEN1cnNvcigzLCAwKTsgbGNkLnByaW50KHQubWluKTt9CgogICAgICAgIGlmICh0LmRvdyA+PSAwICYmIHQuZG93IDwgMTApIHsgbGNkLnNldEN1cnNvcig4LCAwKTsgbGNkLnByaW50KCIwIik7IGxjZC5wcmludCh0LmRvdyk7fSAvL9CU0LXQvdGMCiAgICAgICAgZWxzZSB7IGxjZC5zZXRDdXJzb3IoOCwgMCk7IGxjZC5wcmludCh0LmRvdyk7fQogICAgICAgIGxjZC5wcmludCgiLyIpOwogICAgICAgIGlmICh0Lm1vbiA+PSAwICYmIHQubW9uIDwgMTApIHsgbGNkLnNldEN1cnNvcigxMSwgMCk7IGxjZC5wcmludCgiMCIpOyBsY2QucHJpbnQodC5tb24pO30gLy/QnNC10YHRj9GGCiAgICAgICAgZWxzZSB7IGxjZC5zZXRDdXJzb3IoMTEsIDApOyBsY2QucHJpbnQodC5tb24pO30KICAgICAgICBsY2QucHJpbnQoIi8iKTsKICAgICAgICBpZiAodC55ZWFyID49IDAgJiYgdC55ZWFyIDwgMTApIHsgbGNkLnNldEN1cnNvcigxNCwgMCk7IGxjZC5wcmludCgiMCIpOyBsY2QucHJpbnQodC55ZWFyLTIwMDApO30gLy/Qk9C+0LQKICAgICAgICBlbHNlIHsgbGNkLnNldEN1cnNvcigxNCwgMCk7IGxjZC5wcmludCh0LnllYXItMjAwMCk7fQogICAgICAgIAogICAgICAgIGZsb2F0IHRlbXAgPSBkaHQucmVhZFRlbXBlcmF0dXJlKCk7IC8v0J/QldCg0JXQnNCV0J3QndCr0JUg0JTQm9CvIERIVAogICAgICAgIGZsb2F0IGggPSBkaHQucmVhZEh1bWlkaXR5KCk7CiAgICAgICAgCiAgICAgICAgZHBzLmdldFByZXNzdXJlKCZQcmVzc3VyZSk7IC8v0J/QldCg0JXQnNCV0J3QndCr0JUg0JTQm9CvIEJNUAogICAgICAgIGRwcy5nZXRBbHRpdHVkZSgmQWx0aXR1ZGUpOwoKICAgICAgICBsY2Quc2V0Q3Vyc29yKDAsIDEpOyAvL9Ci0LXQvNC/0LXRgNCw0YLRg9GA0LAKICAgICAgICBsY2QucHJpbnQoIlwzIik7CiAgICAgICAgbGNkLnNldEN1cnNvcigxLCAxKTsKICAgICAgICBsY2QucHJpbnQodGVtcCwgMCk7CiAgICAgICAgbGNkLnByaW50KChjaGFyKTIyMyk7IC8vZGVncmVlIHNpZ24KICAgICAgICBsY2QucHJpbnQoIkMiKTsKCiAgICAgICAgbGNkLnNldEN1cnNvcig2LCAxKTsgLy/QlNCw0LLQu9C10L3QuNC1CiAgICAgICAgbGNkLnByaW50KFByZXNzdXJlLzEzMy4zLCAwKTsKICAgICAgICBsY2QucHJpbnQoIm1tIik7CgogICAgICAgIGxjZC5zZXRDdXJzb3IoMTIsIDEpOyAvL9CS0LvQsNC20L3QvtGB0YLRjAogICAgICAgIGxjZC5wcmludCgiXDQiKTsKICAgICAgICBsY2Quc2V0Q3Vyc29yKDEzLCAxKTsKICAgICAgICBsY2QucHJpbnQoaCwgMCk7CiAgICAgICAgbGNkLnByaW50KCIlIik7CgogICAgICAgIGxjZC5zZXRDdXJzb3IoNiwgMCk7CiAgICAgICAgaWYgKEVFUFJPTS5yZWFkKDMpPT0xKSB7bGNkLnByaW50KCJcNSIpO30gLy/QntGC0L7QsdGA0LDQttC10L3QuNC1INGB0YLQsNGC0YPRgdCwINCx0YPQtNC40LvRjNC90LjQutCwCiAgICAgICAgZWxzZSBpZiAoRUVQUk9NLnJlYWQoMyk9PTApIHtsY2QucHJpbnQoIiAiKTt9CgogICAgICAgIGlmIChFRVBST00ucmVhZCgxKT09dC5ob3VyICYmIEVFUFJPTS5yZWFkKDIpPT10Lm1pbiAmJiB0LnNlYz09MCAmJiBFRVBST00ucmVhZCgzKT09MSkgeyAvL9Ch0LDQvCDQsdGD0LTQuNC70YzQvdC40LoKICAgICAgICAgICAgdG9uKCk7CiAgICAgICAgICB9CiAgICB9CiAgfQp9Cgp2b2lkIG1lbnVJdGVtMygpIHsgLy/QotGA0LXRgtGM0LUg0LzQtdC90Y4KICBpbnQgYWN0aXZlQnV0dG9uID0gMDsKICBpbnQgYWxhcm1Ib3VyID0gRUVQUk9NLnJlYWQoMSk7IC8v0JIg0L/QtdGA0LLQvtC5INGP0YfQtdC50LrQtSDRhdGA0LDQvdC40YLRgdGPINGH0LDRgdGLINCx0YPQtNC40LvRjNC90LjQutCwCiAgaW50IGFsYXJtTWludXRlID0gRUVQUk9NLnJlYWQoMik7IC8v0JLQviDQstGC0L7RgNC+0Lkg0LzQuNC90YPRgtGLCiAgaW50IGFsYXJtU3RhdCA9IEVFUFJPTS5yZWFkKDMpOyAvL9CSINGC0YDQtdGC0LXQuSDRgdGC0LDRgtGD0YEsINCy0LrQu9GO0YfQtdC9INCx0YPQtNC40LvRjNC90LjQuiAoMSkg0LjQu9C4INC90LXRgiAoMCkKICBpbnQgYWxhcm1Qb3MgPSAxOyAvL9Cf0L7Qt9C40YbQuNGPINC60YPRgNGB0L7RgNCwLCDRgi7QtS7Rh9GC0L4g0LzQtdC90Y/RgtGMOiAxLdCc0LjQvdGD0YLRiywgMC3Qp9Cw0YHRiywgMi3QktCa0Jsg0LjQu9C4INCS0KvQmtCbINCx0YPQtNC40LvRjNC90LjQutCwCiAgCiAgbGNkLmNsZWFyKCk7CiAgRUVQUk9NLndyaXRlKDAsIDMpOwogIGxjZC5zZXRDdXJzb3IoMCwgMSk7CiAgZHJhd0luc3RydWN0aW9ucygpOwogIGxjZC5zZXRDdXJzb3IoMCwgMCk7CiAgbGNkLnByaW50KCJBTEFSTTogIik7CiAgaWYgKGFsYXJtSG91ciA+PTAgJiYgYWxhcm1Ib3VyIDwgMTApIHtsY2QucHJpbnQoIjAiKTsgbGNkLnByaW50KGFsYXJtSG91cik7fQogICAgICAgIGVsc2UgbGNkLnByaW50KGFsYXJtSG91cik7CiAgbGNkLnNldEN1cnNvcig5LCAwKTsKICBsY2QucHJpbnQoIjoiKTsKICBpZiAoYWxhcm1NaW51dGUgPj0wICYmIGFsYXJtTWludXRlIDwgMTApIHtsY2QucHJpbnQoIjAiKTsgbGNkLnByaW50KGFsYXJtTWludXRlKTt9CiAgICAgICAgZWxzZSBsY2QucHJpbnQoYWxhcm1NaW51dGUpOwoKICBsY2Quc2V0Q3Vyc29yKDEzLCAwKTsKICBpZiAoYWxhcm1TdGF0PT0xKSBsY2QucHJpbnQoIk9OIik7CiAgZWxzZSBpZiAoYWxhcm1TdGF0PT0wKSBsY2QucHJpbnQoIk9GRiIpOwogIAogIHdoaWxlIChhY3RpdmVCdXR0b24gPT0gMCkgewogICAgaW50IGJ1dHRvbjsKICAgIHJlYWRLZXkgPSBhbmFsb2dSZWFkKDApOwogICAgaWYgKHJlYWRLZXkgPCA3OTApIHsKICAgICAgZGVsYXkoMTAwKTsKICAgICAgcmVhZEtleSA9IGFuYWxvZ1JlYWQoMCk7CiAgICB9CiAgICBidXR0b24gPSBldmFsdWF0ZUJ1dHRvbihyZWFkS2V5KTsKICAgIAogICAgc3dpdGNoIChidXR0b24pIHsKICAgICAgY2FzZSAyOiAvL9Cf0YDQuNCx0LDQstC70Y/QtdC8INC30L3QsNGH0LXQvdC40Y8g0LzQuNC90YPRgiwg0YfQsNGB0L7QsiDQuNC70Lgg0JLQmtCbINCx0YPQtNC40LvRjNC90LjQutCwLCDQsiDRgdC+0L7RgtCy0LXRgtGB0YLQstC40Lgg0LPQtNC1INGB0YLQvtC40YIg0LrRg9GA0YHQvtGACiAgICAgICAgaWYgKGFsYXJtUG9zPT0xKXsKICAgICAgICBidXR0b24gPSAwOwogICAgICAgIGlmIChhbGFybU1pbnV0ZT09NTkpIGFsYXJtTWludXRlPTA7CiAgICAgICAgZWxzZSBhbGFybU1pbnV0ZSA9IGFsYXJtTWludXRlICsgMTsKICAgICAgICBhbGFybU1pbnV0ZSA9IGNvbnN0cmFpbihhbGFybU1pbnV0ZSwwLDYwKTsKICAgICAgICBsY2Quc2V0Q3Vyc29yKDEwLDApOwogICAgICAgIGxjZC5wcmludCgiICAiKTsKICAgICAgICBsY2Quc2V0Q3Vyc29yKDEwLDApOwogICAgICAgIGlmIChhbGFybU1pbnV0ZSA+PTAgJiYgYWxhcm1NaW51dGUgPCAxMCkge2xjZC5wcmludCgiMCIpOyBsY2QucHJpbnQoYWxhcm1NaW51dGUpO30KICAgICAgICBlbHNlIGxjZC5wcmludChhbGFybU1pbnV0ZSk7CiAgICAgICAgYnJlYWs7CiAgICAgICAgfSBlbHNlIGlmIChhbGFybVBvcz09MCkgewogICAgICAgIGJ1dHRvbiA9IDA7CiAgICAgICAgaWYgKGFsYXJtSG91cj09MjMpIGFsYXJtSG91cj0wOwogICAgICAgIGVsc2UgYWxhcm1Ib3VyID0gYWxhcm1Ib3VyICsgMTsKICAgICAgICBhbGFybUhvdXIgPSBjb25zdHJhaW4oYWxhcm1Ib3VyLDAsIDI0KTsKICAgICAgICBsY2Quc2V0Q3Vyc29yKDcsMCk7CiAgICAgICAgbGNkLnByaW50KCIgICIpOwogICAgICAgIGxjZC5zZXRDdXJzb3IoNywwKTsgIAogICAgICAgIGlmIChhbGFybUhvdXIgPj0wICYmIGFsYXJtSG91ciA8IDEwKSB7bGNkLnByaW50KCIwIik7IGxjZC5wcmludChhbGFybUhvdXIpO30KICAgICAgICBlbHNlIGxjZC5wcmludChhbGFybUhvdXIpOwogICAgICAgIGJyZWFrOwogICAgICAgIH0gZWxzZSBpZiAoYWxhcm1Qb3M9PTIpIHsKICAgICAgICBidXR0b24gPSAwOwogICAgICAgICAgbGNkLnNldEN1cnNvcigxMywgMCk7CiAgICAgICAgICBsY2QucHJpbnQoIk9OICIpOwogICAgICAgICAgYWxhcm1TdGF0PTE7CiAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICBjYXNlIDM6IC8v0KPQsdCw0LLQu9GP0LXQvCDQt9C90LDRh9C10L3QuNGPINC80LjQvdGD0YIsINGH0LDRgdC+0LIg0LjQu9C4INCS0KvQmtCbINCx0YPQtNC40LvRjNC90LjQutCwLCDQsiDRgdC+0L7RgtCy0LXRgtGB0YLQstC40Lgg0LPQtNC1INGB0YLQvtC40YIg0LrRg9GA0YHQvtGACiAgICAgICAgaWYgKGFsYXJtUG9zPT0xKSB7CiAgICAgICAgYnV0dG9uID0gMDsKICAgICAgICBpZiAoYWxhcm1NaW51dGU9PTApIGFsYXJtTWludXRlPTU5OwogICAgICAgIGVsc2UgYWxhcm1NaW51dGUgPSBhbGFybU1pbnV0ZSAtIDE7CiAgICAgICAgYWxhcm1NaW51dGUgPSBjb25zdHJhaW4oYWxhcm1NaW51dGUsMCw2MCk7CiAgICAgICAgbGNkLnNldEN1cnNvcigxMCwwKTsKICAgICAgICBsY2QucHJpbnQoIiAgIik7CiAgICAgICAgbGNkLnNldEN1cnNvcigxMCwwKTsKICAgICAgICBpZiAoYWxhcm1NaW51dGUgPj0wICYmIGFsYXJtTWludXRlIDwgMTApIHtsY2QucHJpbnQoIjAiKTsgbGNkLnByaW50KGFsYXJtTWludXRlKTt9CiAgICAgICAgZWxzZSBsY2QucHJpbnQoYWxhcm1NaW51dGUpOwogICAgICAgIGJyZWFrOwogICAgICAgIH0gZWxzZSBpZihhbGFybVBvcz09MCl7CiAgICAgICAgYnV0dG9uID0gMDsKICAgICAgICBpZiAoYWxhcm1Ib3VyPT0wKSBhbGFybUhvdXI9MjM7CiAgICAgICAgZWxzZSBhbGFybUhvdXIgPSBhbGFybUhvdXIgLSAxOwogICAgICAgIGFsYXJtSG91ciA9IGNvbnN0cmFpbihhbGFybUhvdXIsMCwgMjQpOwogICAgICAgIGxjZC5zZXRDdXJzb3IoNywwKTsKICAgICAgICBsY2QucHJpbnQoIiAgIik7CiAgICAgICAgbGNkLnNldEN1cnNvcig3LDApOyAgCiAgICAgICAgaWYgKGFsYXJtSG91ciA+PTAgJiYgYWxhcm1Ib3VyIDwgMTApIHtsY2QucHJpbnQoIjAiKTsgbGNkLnByaW50KGFsYXJtSG91cik7fQogICAgICAgIGVsc2UgbGNkLnByaW50KGFsYXJtSG91cik7CiAgICAgICAgYnJlYWs7CiAgICAgICAgfWVsc2UgaWYgKGFsYXJtUG9zPT0yKSB7CiAgICAgICAgYnV0dG9uID0gMDsKICAgICAgICAgIGxjZC5zZXRDdXJzb3IoMTMsIDApOwogICAgICAgICAgbGNkLnByaW50KCJPRkYiKTsKICAgICAgICAgIGFsYXJtU3RhdD0wOwogICAgICAgIGJyZWFrOwogICAgICAgIH0KCiAgICAgIGNhc2UgNDogLy8g0JXRgdC70Lgg0L3QsNC20LDRgtCwINC60L3QvtC/0LrQsCDQstC70LXQstC+LCDRgdC80L7RgtGA0LjQvCDQs9C00LUg0YHRgtC+0LjRgiDQutGD0YDRgdC+0YAg0LIg0LTQsNC90L3Ri9C5INC80L7QvNC10L3RgiDQuCDQv9C10YDQtdGB0YLQsNCy0LvRj9C10Lwg0LvQtdCy0LXQtQogICAgICAgaWYgKGFsYXJtUG9zPT0yKXsKICAgICAgIGRyYXdJbnN0cnVjdGlvbnMoKTsKICAgICAgIGFsYXJtUG9zPTE7CiAgICAgICB9IGVsc2UgaWYgKGFsYXJtUG9zPT0xKXsKICAgICAgIGRyYXdJbnN0cnVjdGlvbjIoKTsKICAgICAgIGFsYXJtUG9zPTA7CiAgICAgICB9CiAgICAgICAgYnJlYWs7CiAgICAgICAgCiAgICAgIGNhc2UgMTogLy8g0JXRgdC70Lgg0L3QsNC20LDRgtCwINC60L3QvtC/0LrQsCDQstC/0YDQsNCy0L4sINGB0LzQvtGC0YDQuNC8INCz0LTQtSDRgdGC0L7QuNGCINC60YPRgNGB0L7RgCDQsiDQtNCw0L3QvdGL0Lkg0LzQvtC80LXQvdGCINC4INC/0LXRgNC10YHRgtCw0LLQu9GP0LXQvCDQv9GA0LDQstC10LUKICAgICAgIGlmIChhbGFybVBvcz09MCl7CiAgICAgICBkcmF3SW5zdHJ1Y3Rpb25zKCk7CiAgICAgICBhbGFybVBvcz0xOwogICAgICAgfSBlbHNlIGlmIChhbGFybVBvcz09MSl7CiAgICAgICBkcmF3SW5zdHJ1Y3Rpb24zKCk7CiAgICAgICBhbGFybVBvcz0yOwogICAgICAgfQogICAgICAgIGJyZWFrOwogICAgICAgIAogICAgICBjYXNlIDU6ICAvLyDQodC+0YXRgNCw0L3QtdC90LjQtSDQstGA0LXQvNC90Lgg0LHRg9C00LjQu9GM0L3QuNC60LAg0LIg0LXQs9C+INGB0YLQsNGC0YPRgSAo0LLQutC7INC40LvQuCDQstGL0LrQuykg0LIgRUVQUk9NCiAgICAgICAgYnV0dG9uID0gMDsKICAgICAgICBsY2QuY2xlYXIoKTsKICAgICAgICBsY2Qubm9CbGluaygpOwogICAgICAgIEVFUFJPTS53cml0ZSgwLCAwKTsKICAgICAgICBsY2Quc2V0Q3Vyc29yKDIsMCk7CiAgICAgICAgbGNkLnByaW50KCItLSBBTEFSTSAtLSIpOwogICAgICAgIGxjZC5zZXRDdXJzb3IoMiwxKTsKICAgICAgICBsY2QucHJpbnQoIi0tIFNBVkVEIC0tIik7CiAgICAgICAgRUVQUk9NLndyaXRlKDEsIGFsYXJtSG91cik7CiAgICAgICAgRUVQUk9NLndyaXRlKDIsIGFsYXJtTWludXRlKTsKICAgICAgICBFRVBST00ud3JpdGUoMywgYWxhcm1TdGF0KTsKICAgICAgICBkZWxheSgxNTAwKTsKICAgICAgICBhY3RpdmVCdXR0b24gPSAxOwogICAgICAgIGJyZWFrOwogICAgfQogIH0KfQoKdm9pZCBtZW51SXRlbTQoKSB7IC8vINCn0LXRgtCy0LXRgNGC0L7QtSDQvNC10L3RjgogIGludCBhY3RpdmVCdXR0b24gPSAwOwoKICBsY2QuY2xlYXIoKTsKICBFRVBST00ud3JpdGUoMCwgNSk7CiAgbGNkLnNldEN1cnNvcigxLCAwKTsKICBsY2QucHJpbnQoIlBJS0FCVSIpOwogIGxjZC5zZXRDdXJzb3IoMTEsIDEpOwogIGxjZC5wcmludCgiMjAxNyIpOwoKICB3aGlsZSAoYWN0aXZlQnV0dG9uID09IDApIHsKICAgIGludCBidXR0b247CiAgICByZWFkS2V5ID0gYW5hbG9nUmVhZCgwKTsKICAgIGlmIChyZWFkS2V5IDwgNzkwKSB7CiAgICAgIGRlbGF5KDEwMCk7CiAgICAgIHJlYWRLZXkgPSBhbmFsb2dSZWFkKDApOwogICAgfQogICAgYnV0dG9uID0gZXZhbHVhdGVCdXR0b24ocmVhZEtleSk7CiAgICBzd2l0Y2ggKGJ1dHRvbikgewogICAgICBjYXNlIDQ6ICAvLyDQldGB0LvQuCDQvdCw0LbQsNGC0LAg0LrQvdC+0L/QutCwICJsZWZ0IgogICAgICAgIGJ1dHRvbiA9IDA7CiAgICAgICAgYWN0aXZlQnV0dG9uID0gMTsKICAgICAgICBFRVBST00ud3JpdGUoMCwgMCk7CiAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSA1OiAgLy8g0JXRgdC70Lgg0L3QsNC20LDRgtCwINC60L3QvtC/0LrQsCAic2V0IgogICAgICAgIGJ1dHRvbiA9IDA7CiAgICAgICAgYWN0aXZlQnV0dG9uID0gMTsKICAgICAgICBFRVBST00ud3JpdGUoMCwgMCk7CiAgICAgICAgYnJlYWs7CiAgICB9CiAgfQp9Cgp2b2lkIG1lbnVJdGVtNSgpIHsgLy8g0J/Rj9GC0L7QtSDQvNC10L3RjiAo0JTQu9GPINCw0LrRgtC40LLQsNGG0LjQuCDQtNC+0LHQsNCy0LjRgtGMINC90LDQt9Cy0LDQvdC40LUg0LzQtdC90Y4g0LIg0YHQsNC80L7QvCDQvdCw0YfQsNC70LUpCiAgaW50IGFjdGl2ZUJ1dHRvbiA9IDA7CgogIGxjZC5jbGVhcigpOwogIEVFUFJPTS53cml0ZSgwLCA0KTsKICBsY2Quc2V0Q3Vyc29yKDMsIDApOwogIGxjZC5wcmludCgiSGVsbG8sIFdvcmxkISIpOwoKICB3aGlsZSAoYWN0aXZlQnV0dG9uID09IDApIHsKICAgIGludCBidXR0b247CiAgICByZWFkS2V5ID0gYW5hbG9nUmVhZCgwKTsKICAgIGlmIChyZWFkS2V5IDwgNzkwKSB7CiAgICAgIGRlbGF5KDEwMCk7CiAgICAgIHJlYWRLZXkgPSBhbmFsb2dSZWFkKDApOwogICAgfQogICAgYnV0dG9uID0gZXZhbHVhdGVCdXR0b24ocmVhZEtleSk7CiAgICBzd2l0Y2ggKGJ1dHRvbikgewogICAgICBjYXNlIDQ6CiAgICAgICAgYnV0dG9uID0gMDsKICAgICAgICBhY3RpdmVCdXR0b24gPSAxOwogICAgICAgIEVFUFJPTS53cml0ZSgwLCAwKTsKICAgICAgICBicmVhazsKICAgIH0KICB9Cn0KCgp2b2lkIG1lbnVJdGVtNigpIHsgLy8g0KjQtdGB0YLQvtC1INC80LXQvdGOCiAgaW50IGFjdGl2ZUJ1dHRvbiA9IDA7CgogIGxjZC5jbGVhcigpOwogIGxjZC5zZXRDdXJzb3IoMywgMCk7CiAgbGNkLnByaW50KCJTdWIgTWVudSA2Iik7CgogIHdoaWxlIChhY3RpdmVCdXR0b24gPT0gMCkgewogICAgaW50IGJ1dHRvbjsKICAgIHJlYWRLZXkgPSBhbmFsb2dSZWFkKDApOwogICAgaWYgKHJlYWRLZXkgPCA3OTApIHsKICAgICAgZGVsYXkoMTAwKTsKICAgICAgcmVhZEtleSA9IGFuYWxvZ1JlYWQoMCk7CiAgICB9CiAgICBidXR0b24gPSBldmFsdWF0ZUJ1dHRvbihyZWFkS2V5KTsKICAgIHN3aXRjaCAoYnV0dG9uKSB7CiAgICAgIGNhc2UgNDogIC8vINCV0YHQu9C4INC90LDQttCw0YLQsCDQutC90L7Qv9C60LAgImxlZnQiCiAgICAgICAgYnV0dG9uID0gMDsKICAgICAgICBhY3RpdmVCdXR0b24gPSAxOwogICAgICAgIGJyZWFrOwogICAgfQogIH0KfQoKdm9pZCBtZW51SXRlbTcoKSB7IC8vINCh0LXQtNGM0LzQvtC1INC80LXQvdGOCiAgaW50IGFjdGl2ZUJ1dHRvbiA9IDA7CgogIGxjZC5jbGVhcigpOwogIGxjZC5zZXRDdXJzb3IoMywgMCk7CiAgbGNkLnByaW50KCJTdWIgTWVudSA3Iik7CgogIHdoaWxlIChhY3RpdmVCdXR0b24gPT0gMCkgewogICAgaW50IGJ1dHRvbjsKICAgIHJlYWRLZXkgPSBhbmFsb2dSZWFkKDApOwogICAgaWYgKHJlYWRLZXkgPCA3OTApIHsKICAgICAgZGVsYXkoMTAwKTsKICAgICAgcmVhZEtleSA9IGFuYWxvZ1JlYWQoMCk7CiAgICB9CiAgICBidXR0b24gPSBldmFsdWF0ZUJ1dHRvbihyZWFkS2V5KTsKICAgIHN3aXRjaCAoYnV0dG9uKSB7CiAgICAgIGNhc2UgNDogIC8vINCV0YHQu9C4INC90LDQttCw0YLQsCDQutC90L7Qv9C60LAgImxlZnQiCiAgICAgICAgYnV0dG9uID0gMDsKICAgICAgICBhY3RpdmVCdXR0b24gPSAxOwogICAgICAgIGJyZWFrOwogICAgfQogIH0KfQoKdm9pZCBtZW51SXRlbTgoKSB7IC8vINCS0L7RgdGM0LzQvtC1INC80LXQvdGOCiAgaW50IGFjdGl2ZUJ1dHRvbiA9IDA7CgogIGxjZC5jbGVhcigpOwogIGxjZC5zZXRDdXJzb3IoMywgMCk7CiAgbGNkLnByaW50KCJTdWIgTWVudSA4Iik7CgogIHdoaWxlIChhY3RpdmVCdXR0b24gPT0gMCkgewogICAgaW50IGJ1dHRvbjsKICAgIHJlYWRLZXkgPSBhbmFsb2dSZWFkKDApOwogICAgaWYgKHJlYWRLZXkgPCA3OTApIHsKICAgICAgZGVsYXkoMTAwKTsKICAgICAgcmVhZEtleSA9IGFuYWxvZ1JlYWQoMCk7CiAgICB9CiAgICBidXR0b24gPSBldmFsdWF0ZUJ1dHRvbihyZWFkS2V5KTsKICAgIHN3aXRjaCAoYnV0dG9uKSB7CiAgICAgIGNhc2UgNDogIC8vINCV0YHQu9C4INC90LDQttCw0YLQsCDQutC90L7Qv9C60LAgImxlZnQiCiAgICAgICAgYnV0dG9uID0gMDsKICAgICAgICBhY3RpdmVCdXR0b24gPSAxOwogICAgICAgIGJyZWFrOwogICAgfQogIH0KfQoKdm9pZCBtZW51SXRlbTkoKSB7IC8vINCU0LXQstGP0YLQvtC1INC80LXQvdGOCiAgaW50IGFjdGl2ZUJ1dHRvbiA9IDA7CgogIGxjZC5jbGVhcigpOwogIGxjZC5zZXRDdXJzb3IoMywgMCk7CiAgbGNkLnByaW50KCJTdWIgTWVudSA5Iik7CgogIHdoaWxlIChhY3RpdmVCdXR0b24gPT0gMCkgewogICAgaW50IGJ1dHRvbjsKICAgIHJlYWRLZXkgPSBhbmFsb2dSZWFkKDApOwogICAgaWYgKHJlYWRLZXkgPCA3OTApIHsKICAgICAgZGVsYXkoMTAwKTsKICAgICAgcmVhZEtleSA9IGFuYWxvZ1JlYWQoMCk7CiAgICB9CiAgICBidXR0b24gPSBldmFsdWF0ZUJ1dHRvbihyZWFkS2V5KTsKICAgIHN3aXRjaCAoYnV0dG9uKSB7CiAgICAgIGNhc2UgNDogIC8vINCV0YHQu9C4INC90LDQttCw0YLQsCDQutC90L7Qv9C60LAgImxlZnQiCiAgICAgICAgYnV0dG9uID0gMDsKICAgICAgICBhY3RpdmVCdXR0b24gPSAxOwogICAgICAgIGJyZWFrOwogICAgfQogIH0KfQoKdm9pZCBtZW51SXRlbTEwKCkgeyAvLyDQlNC10YHRj9GC0L7QtSDQvNC10L3RjgogIGludCBhY3RpdmVCdXR0b24gPSAwOwoKICBsY2QuY2xlYXIoKTsKICBsY2Quc2V0Q3Vyc29yKDMsIDApOwogIGxjZC5wcmludCgiU3ViIE1lbnUgMTAiKTsKCiAgd2hpbGUgKGFjdGl2ZUJ1dHRvbiA9PSAwKSB7CiAgICBpbnQgYnV0dG9uOwogICAgcmVhZEtleSA9IGFuYWxvZ1JlYWQoMCk7CiAgICBpZiAocmVhZEtleSA8IDc5MCkgewogICAgICBkZWxheSgxMDApOwogICAgICByZWFkS2V5ID0gYW5hbG9nUmVhZCgwKTsKICAgIH0KICAgIGJ1dHRvbiA9IGV2YWx1YXRlQnV0dG9uKHJlYWRLZXkpOwogICAgc3dpdGNoIChidXR0b24pIHsKICAgICAgY2FzZSA0OiAgLy8g0JXRgdC70Lgg0L3QsNC20LDRgtCwINC60L3QvtC/0LrQsCAibGVmdCIKICAgICAgICBidXR0b24gPSAwOwogICAgICAgIGFjdGl2ZUJ1dHRvbiA9IDE7CiAgICAgICAgYnJlYWs7CiAgICB9CiAgfQp9Cg==